using System.Net.Sockets; using OpenTK.Mathematics; using OpenTK.Windowing.Common; using OpenTK.Windowing.GraphicsLibraryFramework; using Voxel.Core; using Voxel.Graphics; using Voxel.UI; namespace Voxel.Entities { public class Player : Entity { public double lastClick = 0; public readonly float mouseCooldown = 0.2f; private int _blockIndex = 0; private int _jumpTicks = 0; private Blocks _selectedBlock = Blocks.OakPlanks; private Vector3 _previousPosition; private Label _positionLabel = new Label("Position:", 16, 48, 24, Vector4.One); private Label _blockLabel = new Label("Selected Block:", 16, 80, 24, Vector4.One); public Player(Vector3 startPos, World world) : base(startPos, 0.5f, 1.8f, world) { Input.OnMouseWheel += SwitchBlock; _blockLabel.Text = $"Selected block: {_selectedBlock}"; } public void PlaceBlock() { var (success, hit, x, y, z, normal) = _world.Raycast(Camera.Position, Camera.Front.Normalized(), 8); if (!success) return; x += normal.X; y += normal.Y; z += normal.Z; _world.SetBlock(x, y, z, _selectedBlock); } public void BreakBlock() { var (success, hit, x, y, z, normal) = _world.Raycast(Camera.Position, Camera.Front.Normalized(), 8); if (!success) return; _world.SetBlock(x, y, z, Blocks.Air); } public void Tick() { if (_jumpTicks > 0) _jumpTicks--; _world.UpdateChunkLoading(Position); _previousPosition = Position; float forwards = 0; float sidewards = 0; if (Input.GetKey(Keys.W)) forwards = -1; if (Input.GetKey(Keys.S)) forwards = 1; if (Input.GetKey(Keys.A)) sidewards = -1; if (Input.GetKey(Keys.D)) sidewards = 1; if (Input.GetMouseButton(MouseButton.Right) && lastClick == 0) { lastClick = mouseCooldown; PlaceBlock(); } if (Input.GetMouseButton(MouseButton.Left) && lastClick == 0) { lastClick = mouseCooldown; BreakBlock(); } if (Position.Y < -8) { Position.Y = 64; Velocity.Y = 0; } ApplyWalkSpeed(sidewards, forwards); base.Tick(); if (Input.GetKey(Keys.Space)) { if (OnGround && _jumpTicks == 0) { Jump(); _jumpTicks = 10; } } else _jumpTicks = 0; _positionLabel.Text = $"Position: {Position.X:F2}, {Position.Y:F2}, {Position.Z:F2}"; } public void Jump() { Velocity = new Vector3(Velocity.X, 0.42f, Velocity.Z); OnGround = false; } public void Update(float deltaTime, float alpha) { Camera.Position = Vector3.Lerp(_previousPosition, Position, alpha) + Vector3.UnitY * 1.62f; Rotation = Camera.Yaw; Renderer.RenderLabel(_positionLabel); Renderer.RenderLabel(_blockLabel); if (lastClick > 0) { lastClick -= deltaTime; if (lastClick < 0) lastClick = 0; } if (!Input.GetMouseButton(MouseButton.Right) && !Input.GetMouseButton(MouseButton.Left)) { lastClick = 0; } } public void ApplyWalkSpeed(float x, float z) { Vector3 inputDir = new Vector3(x, 0, z); if (inputDir.LengthSquared > 0) inputDir = Vector3.Normalize(inputDir); float yawRad = MathHelper.DegreesToRadians(Rotation); float cos = MathF.Cos(yawRad); float sin = MathF.Sin(yawRad); Vector3 worldDir = new Vector3( inputDir.X * cos - inputDir.Z * sin, 0, inputDir.X * sin + inputDir.Z * cos ); float M_t = 1.4f; float groundMultiplier = 0.6f; if (!OnGround) { Vector3 airAccel = worldDir * 0.02f * M_t; Velocity = new Vector3(Velocity.X + airAccel.X, Velocity.Y, Velocity.Z + airAccel.Z); } else { Vector3 groundAccel = worldDir * 0.13f * M_t; Velocity = new Vector3(Velocity.X * groundMultiplier + groundAccel.X, Velocity.Y, Velocity.Z * groundMultiplier + groundAccel.Z); } } public void SwitchBlock(MouseWheelEventArgs e) { int count = BlockDefinitions.CreativeInventory.Length; int direction = e.OffsetY < 0 ? -1 : 1; _blockIndex = (_blockIndex + direction + count) % count; _selectedBlock = BlockDefinitions.CreativeInventory[_blockIndex]; _blockLabel.Text = $"Selected block: {_selectedBlock}"; Console.WriteLine(_selectedBlock); } } }