From a95579b301a2a5e7d975f17e4ab4225d416e50b4 Mon Sep 17 00:00:00 2001 From: Cassunshine Date: Fri, 8 Dec 2023 12:45:09 -0500 Subject: [PATCH] -Player moving around on server -Basics of debug renderer -kill me please --- Client/Client.csproj | 2 +- Client/Content/shaders/debug.frag.glsl | 9 ++ Client/Content/shaders/debug.vert.glsl | 19 ++++ Client/Keybinding/Button.cs | 2 +- Client/Keybinding/Keybinds.cs | 4 +- Client/Network/ClientConnectionContext.cs | 8 ++ Client/Rendering/CameraStateManager.cs | 2 +- Client/Rendering/Debug/DebugRenderer.cs | 97 +++++++++++++++++++ Client/Rendering/GameRenderer.cs | 12 +++ Client/Rendering/Models/BlockModelManager.cs | 2 +- Client/Rendering/Renderer.cs | 2 +- Client/Rendering/Texture/Atlas.cs | 2 +- Client/Rendering/Texture/AtlasLoader.cs | 4 +- .../Rendering/Utils/ArrayTypedDeviceBuffer.cs | 2 +- Client/Rendering/Utils/TypedDeviceBuffer.cs | 2 +- Client/Rendering/VertexTypes/DebugVertex.cs | 17 ++++ Client/Rendering/World/ChunkMeshBuilder.cs | 3 +- Client/Rendering/World/ChunkRenderSlot.cs | 2 +- Client/Rendering/World/ChunkRenderer.cs | 4 +- Client/VoxelClient.cs | 10 +- Client/World/ClientChunk.cs | 19 ++++ Client/World/ClientWorld.cs | 5 + Client/World/Entity/ClientPlayerEntity.cs | 7 ++ .../Entity/ControlledClientPlayerEntity.cs | 36 +++++++ Common/Common.csproj | 5 +- Common/Entity/PlayerEntity.cs | 13 --- Common/Network/ConnectionBase.cs | 1 + .../Packets/C2S/Gameplay/PlayerUpdated.cs | 19 ++++ Common/Network/Packets/PacketHandler.cs | 6 +- .../S2C/Gameplay/Entity/EntityPacket.cs | 23 +++++ .../Gameplay/Entity/EntityTransformUpdate.cs | 30 ++++++ .../Networking/ServerConnectionContext.cs | 26 ++++- Common/Server/Components/PlayerManager.cs | 4 +- Common/Util/Serialization/VDataReader.cs | 2 +- Common/World/Chunk.cs | 15 ++- Common/{ => World}/Entity/Entity.cs | 19 ++-- Common/World/Entity/PlayerEntity.cs | 8 ++ Common/World/LoadedChunkSection.cs | 17 +++- Common/World/Tickable.cs | 5 + Common/World/VoxelWorld.cs | 14 ++- Core/Assets/AssetReader.cs | 2 +- Core/Core.csproj | 2 +- Core/Game.cs | 10 +- Core/Input/Gamepad/Buttons.cs | 2 +- Core/Input/Gamepad/SdlGamepad.cs | 2 +- Core/Input/InputAction.cs | 2 +- Core/Input/InputManager.cs | 4 +- Core/Rendering/RenderSystem.cs | 4 +- Core/Rendering/ShaderManager.cs | 4 +- Core/Rendering/TextureManager.cs | 4 +- Test/Test.csproj | 2 +- 51 files changed, 444 insertions(+), 73 deletions(-) create mode 100644 Client/Content/shaders/debug.frag.glsl create mode 100644 Client/Content/shaders/debug.vert.glsl create mode 100644 Client/Rendering/Debug/DebugRenderer.cs create mode 100644 Client/Rendering/VertexTypes/DebugVertex.cs create mode 100644 Client/World/ClientChunk.cs create mode 100644 Client/World/Entity/ClientPlayerEntity.cs create mode 100644 Client/World/Entity/ControlledClientPlayerEntity.cs delete mode 100644 Common/Entity/PlayerEntity.cs create mode 100644 Common/Network/Packets/C2S/Gameplay/PlayerUpdated.cs create mode 100644 Common/Network/Packets/S2C/Gameplay/Entity/EntityPacket.cs create mode 100644 Common/Network/Packets/S2C/Gameplay/Entity/EntityTransformUpdate.cs rename Common/{ => World}/Entity/Entity.cs (79%) create mode 100644 Common/World/Entity/PlayerEntity.cs create mode 100644 Common/World/Tickable.cs diff --git a/Client/Client.csproj b/Client/Client.csproj index d19ef23..f07a8b8 100644 --- a/Client/Client.csproj +++ b/Client/Client.csproj @@ -4,7 +4,7 @@ net7.0 Major false - Voxel + Voxel.Client disable enable true diff --git a/Client/Content/shaders/debug.frag.glsl b/Client/Content/shaders/debug.frag.glsl new file mode 100644 index 0000000..da179d3 --- /dev/null +++ b/Client/Content/shaders/debug.frag.glsl @@ -0,0 +1,9 @@ +#version 450 + +layout(location = 1) in vec4 fsin_Color; + +layout(location = 0) out vec4 fsout_Color; + +void main() { + fsout_Color = fsin_Color; +} diff --git a/Client/Content/shaders/debug.vert.glsl b/Client/Content/shaders/debug.vert.glsl new file mode 100644 index 0000000..4f35f24 --- /dev/null +++ b/Client/Content/shaders/debug.vert.glsl @@ -0,0 +1,19 @@ +#version 450 + +layout(location = 0) in vec3 Position; +layout(location = 1) in vec4 Color; +layout(location = 2) in vec2 UV; + + +layout(location = 1) out vec4 fsin_Color; + +layout (set = 0, binding = 0) uniform CameraData { + mat4 VPMatrix; +}; + +void main() { + vec4 pos = vec4(Position, 1) * VPMatrix; + gl_Position = pos; + + fsin_Color = Color; +} diff --git a/Client/Keybinding/Button.cs b/Client/Keybinding/Button.cs index 408ffc7..f4e98b1 100644 --- a/Client/Keybinding/Button.cs +++ b/Client/Keybinding/Button.cs @@ -5,8 +5,8 @@ using System; using System.Collections.Generic; using GlmSharp; -using RenderSurface.Input.Gamepad; using Veldrid; +using Voxel.Core.Input.Gamepad; using VMouseButton = Veldrid.MouseButton; namespace Voxel.Client.Keybinding; diff --git a/Client/Keybinding/Keybinds.cs b/Client/Keybinding/Keybinds.cs index 38c0454..83bf4fa 100644 --- a/Client/Keybinding/Keybinds.cs +++ b/Client/Keybinding/Keybinds.cs @@ -1,6 +1,6 @@ using System.Collections.Generic; -using RenderSurface.Input.Gamepad; using Veldrid; +using Voxel.Core.Input.Gamepad; using VMouseButton = Veldrid.MouseButton; namespace Voxel.Client.Keybinding; @@ -50,7 +50,7 @@ public static class Keybinds { KeyButton.Get(Key.ShiftLeft), ControllerButton.Get(GamepadButton.RightStick) ); - + public static readonly Keybind Look = new( "camera.full", ControllerJoystickButton.Get(ControllerJoystickButton.GamepadJoystick.Right) diff --git a/Client/Network/ClientConnectionContext.cs b/Client/Network/ClientConnectionContext.cs index 97dcf81..5fa6d28 100644 --- a/Client/Network/ClientConnectionContext.cs +++ b/Client/Network/ClientConnectionContext.cs @@ -1,10 +1,13 @@ using System; using Common.Network.Packets; +using Common.Network.Packets.C2S; using Common.Network.Packets.C2S.Handshake; using Common.Network.Packets.S2C; using Common.Network.Packets.S2C.Gameplay; using Common.Network.Packets.S2C.Handshake; +using Common.Network.Packets.Utils; using Voxel.Client.World; +using Voxel.Common.Network.Packets; namespace Voxel.Client.Network; @@ -59,5 +62,10 @@ private void HandleChunkData(ChunkData packet) { packet.Apply(chunk); } + public void SendPacket(C2SPacket packet) { + Connection.DeliverPacket(packet); + PacketPool.Return(packet); + } + public void Close() => Connection.Close(); } diff --git a/Client/Rendering/CameraStateManager.cs b/Client/Rendering/CameraStateManager.cs index 6e33b14..3dc005c 100644 --- a/Client/Rendering/CameraStateManager.cs +++ b/Client/Rendering/CameraStateManager.cs @@ -1,9 +1,9 @@ using System; using GlmSharp; -using RenderSurface.Rendering; using Veldrid; using Voxel.Client.Rendering.Utils; using Voxel.Common.Util; +using Voxel.Core.Rendering; namespace Voxel.Client.Rendering; diff --git a/Client/Rendering/Debug/DebugRenderer.cs b/Client/Rendering/Debug/DebugRenderer.cs new file mode 100644 index 0000000..ee45df5 --- /dev/null +++ b/Client/Rendering/Debug/DebugRenderer.cs @@ -0,0 +1,97 @@ +using System; +using System.Runtime.InteropServices; +using GlmSharp; +using Veldrid; +using Voxel.Client.Rendering.VertexTypes; + +namespace Voxel.Client.Rendering.Debug; + +public class DebugRenderer : Renderer { + private const int BatchSize = 2048; + private static DebugRenderer Instance; + + public readonly Pipeline DebugPipeline; + private readonly DeviceBuffer vertexBuffer; + + private readonly DebugVertex[] DebugVertices = new DebugVertex[BatchSize]; + private int vertexIndex = 0; + + public DebugRenderer(VoxelClient client) : base(client) { + Instance = this; + + if (!client.RenderSystem.ShaderManager.GetShaders("shaders/debug", out var shaders)) + throw new("Shaders not present."); + + DebugPipeline = ResourceFactory.CreateGraphicsPipeline(new() { + BlendState = BlendStateDescription.SingleOverrideBlend, + DepthStencilState = new() { + DepthComparison = ComparisonKind.LessEqual, DepthTestEnabled = true, DepthWriteEnabled = true, + }, + Outputs = RenderSystem.GraphicsDevice.SwapchainFramebuffer.OutputDescription, + PrimitiveTopology = PrimitiveTopology.LineList, + RasterizerState = new() { + CullMode = FaceCullMode.None, DepthClipEnabled = false, FillMode = PolygonFillMode.Wireframe, ScissorTestEnabled = false, + }, + ResourceLayouts = new[] { + Client.GameRenderer.CameraStateManager.CameraResourceLayout, + }, + ShaderSet = new() { + VertexLayouts = new[] { + DebugVertex.Layout + }, + Shaders = shaders + } + }); + + + vertexBuffer = ResourceFactory.CreateBuffer(new BufferDescription { + Usage = BufferUsage.Dynamic | BufferUsage.VertexBuffer, SizeInBytes = (uint)Marshal.SizeOf() * BatchSize + }); + } + public override void Render(double delta) { + + DrawLine(new() { + position = new vec3(0, 0, 0) - (vec3)Client.GameRenderer.MainCamera.position, color = new vec4(1, 1, 1, 1) + }, + new() { + position = new vec3(0, 1000, 0) - (vec3)Client.GameRenderer.MainCamera.position, color = new vec4(1, 1, 1, 1) + } + ); + + Flush(); + } + + private void Flush() { + if (vertexIndex == 0) + return; + + CommandList.UpdateBuffer(vertexBuffer, 0, DebugVertices.AsSpan(0, vertexIndex)); + CommandList.SetPipeline(DebugPipeline); + + CommandList.SetGraphicsResourceSet(0, Client.GameRenderer.CameraStateManager.CameraResourceSet); + + CommandList.SetVertexBuffer(0, vertexBuffer); + CommandList.Draw((uint)vertexIndex); + + vertexIndex = 0; + } + + public override void Dispose() { + DebugPipeline.Dispose(); + } + + + public static void DrawLine(DebugVertex a, DebugVertex b) { + Instance.DebugVertices[Instance.vertexIndex++] = a; + Instance.DebugVertices[Instance.vertexIndex++] = b; + + if (Instance.vertexIndex >= BatchSize) { + Instance.Flush(); + } + } + + /*public static void DrawCube(DebugVertex min, DebugVertex max) { + DebugVertices.Add(a); + DebugVertices.Add(b); + }*/ +} diff --git a/Client/Rendering/GameRenderer.cs b/Client/Rendering/GameRenderer.cs index 3b352da..22f0f88 100644 --- a/Client/Rendering/GameRenderer.cs +++ b/Client/Rendering/GameRenderer.cs @@ -1,6 +1,7 @@ using System; using GlmSharp; using Voxel.Client.Keybinding; +using Voxel.Client.Rendering.Debug; using Voxel.Client.Rendering.GUI; using Voxel.Client.Rendering.World; using Voxel.Common.Collision; @@ -18,6 +19,7 @@ public class GameRenderer : Renderer { public readonly WorldRenderer WorldRenderer; public readonly GuiRenderer GuiRenderer; public readonly CameraStateManager CameraStateManager; + public readonly DebugRenderer DebugRenderer; public GameRenderer(VoxelClient client) : base(client) { //Jank but OK @@ -28,17 +30,27 @@ public GameRenderer(VoxelClient client) : base(client) { WorldRenderer = new(client); GuiRenderer = new(client); + + + DebugRenderer = new DebugRenderer(client); } public override void Render(double delta) { CameraStateManager.SetToCamera(MainCamera, Client.timeSinceLastTick); + MainCamera.position = Client.PlayerEntity?.position ?? dvec3.Zero; + MainCamera.oldPosition = MainCamera.position; + WorldRenderer.Render(delta); GuiRenderer.Render(delta); + + DebugRenderer.Render(delta); } public override void Dispose() { WorldRenderer.Dispose(); GuiRenderer.Dispose(); + + DebugRenderer.Dispose(); } } diff --git a/Client/Rendering/Models/BlockModelManager.cs b/Client/Rendering/Models/BlockModelManager.cs index 6098e69..1e41bf2 100644 --- a/Client/Rendering/Models/BlockModelManager.cs +++ b/Client/Rendering/Models/BlockModelManager.cs @@ -3,9 +3,9 @@ using System.IO; using GlmSharp; using Newtonsoft.Json; -using RenderSurface.Assets; using Voxel.Client.Rendering.Texture; using Voxel.Common.Tile; +using Voxel.Core.Assets; using Voxel.Rendering.Utils; namespace Voxel.Client.Rendering.Models; diff --git a/Client/Rendering/Renderer.cs b/Client/Rendering/Renderer.cs index 7db53a8..a89b52e 100644 --- a/Client/Rendering/Renderer.cs +++ b/Client/Rendering/Renderer.cs @@ -1,6 +1,6 @@ using System; -using RenderSurface.Rendering; using Veldrid; +using Voxel.Core.Rendering; namespace Voxel.Client.Rendering; diff --git a/Client/Rendering/Texture/Atlas.cs b/Client/Rendering/Texture/Atlas.cs index ec14ac2..daedb3c 100644 --- a/Client/Rendering/Texture/Atlas.cs +++ b/Client/Rendering/Texture/Atlas.cs @@ -5,11 +5,11 @@ using System.Drawing; using System.Runtime.InteropServices; using GlmSharp; -using RenderSurface.Rendering; using Veldrid; using Veldrid.OpenGLBinding; using Voxel.Client.Rendering.Utils; using Voxel.Client.Rendering.VertexTypes; +using Voxel.Core.Rendering; namespace Voxel.Client.Rendering.Texture; diff --git a/Client/Rendering/Texture/AtlasLoader.cs b/Client/Rendering/Texture/AtlasLoader.cs index d93c53b..4b765a8 100644 --- a/Client/Rendering/Texture/AtlasLoader.cs +++ b/Client/Rendering/Texture/AtlasLoader.cs @@ -2,8 +2,8 @@ using System.IO; using GlmSharp; using Newtonsoft.Json; -using RenderSurface.Assets; -using RenderSurface.Rendering; +using Voxel.Core.Assets; +using Voxel.Core.Rendering; namespace Voxel.Client.Rendering.Texture; diff --git a/Client/Rendering/Utils/ArrayTypedDeviceBuffer.cs b/Client/Rendering/Utils/ArrayTypedDeviceBuffer.cs index f9e1e33..583d032 100644 --- a/Client/Rendering/Utils/ArrayTypedDeviceBuffer.cs +++ b/Client/Rendering/Utils/ArrayTypedDeviceBuffer.cs @@ -1,7 +1,7 @@ using System; using System.Runtime.InteropServices; -using RenderSurface.Rendering; using Veldrid; +using Voxel.Core.Rendering; namespace Voxel.Client.Rendering.Utils; diff --git a/Client/Rendering/Utils/TypedDeviceBuffer.cs b/Client/Rendering/Utils/TypedDeviceBuffer.cs index 5986df4..2d3652e 100644 --- a/Client/Rendering/Utils/TypedDeviceBuffer.cs +++ b/Client/Rendering/Utils/TypedDeviceBuffer.cs @@ -1,7 +1,7 @@ using System; using System.Runtime.InteropServices; -using RenderSurface.Rendering; using Veldrid; +using Voxel.Core.Rendering; namespace Voxel.Client.Rendering.Utils; diff --git a/Client/Rendering/VertexTypes/DebugVertex.cs b/Client/Rendering/VertexTypes/DebugVertex.cs new file mode 100644 index 0000000..114c516 --- /dev/null +++ b/Client/Rendering/VertexTypes/DebugVertex.cs @@ -0,0 +1,17 @@ +using GlmSharp; +using Veldrid; + +namespace Voxel.Client.Rendering.VertexTypes; + +public struct DebugVertex { + + public static readonly VertexLayoutDescription Layout = new( + new VertexElementDescription("Position", VertexElementFormat.Float3, VertexElementSemantic.Position), + new VertexElementDescription("Color", VertexElementFormat.Float4, VertexElementSemantic.Color), + new VertexElementDescription("UV", VertexElementFormat.Float2, VertexElementSemantic.TextureCoordinate) + ); + + public vec3 position; + public vec4 color; + public vec2 uv; +} diff --git a/Client/Rendering/World/ChunkMeshBuilder.cs b/Client/Rendering/World/ChunkMeshBuilder.cs index 2f7142b..a58b0cb 100644 --- a/Client/Rendering/World/ChunkMeshBuilder.cs +++ b/Client/Rendering/World/ChunkMeshBuilder.cs @@ -6,6 +6,7 @@ using Newtonsoft.Json.Serialization; using Voxel.Client.Rendering.Models; using Voxel.Client.Rendering.VertexTypes; +using Voxel.Client.World; using Voxel.Common.Tile; using Voxel.Common.Util; using Voxel.Common.World.Storage; @@ -220,7 +221,7 @@ public bool Build(ChunkRenderSlot target, ivec3 worldPosition) { for (int i = 0; i < DiagonalSelfNeighborPositions.Length; i++) { var pos = DiagonalSelfNeighborPositions[i] + target.targetChunk!.ChunkPosition; - if (!target.targetChunk!.World.IsChunkLoadedRaw(pos)) + if (!target.targetChunk!.World.TryGetChunkRaw(pos, out var c) || c is not ClientChunk clientChunk || !clientChunk.isFilled) return false; } diff --git a/Client/Rendering/World/ChunkRenderSlot.cs b/Client/Rendering/World/ChunkRenderSlot.cs index fe4ed30..63959d3 100644 --- a/Client/Rendering/World/ChunkRenderSlot.cs +++ b/Client/Rendering/World/ChunkRenderSlot.cs @@ -1,12 +1,12 @@ using System; using System.Runtime.InteropServices; using GlmSharp; -using RenderSurface.Rendering; using Veldrid; using Voxel.Client.Rendering.Utils; using Voxel.Client.Rendering.VertexTypes; using Voxel.Common.Util; using Voxel.Common.World; +using Voxel.Core.Rendering; namespace Voxel.Client.Rendering.World; diff --git a/Client/Rendering/World/ChunkRenderer.cs b/Client/Rendering/World/ChunkRenderer.cs index 0722b87..debbd6d 100644 --- a/Client/Rendering/World/ChunkRenderer.cs +++ b/Client/Rendering/World/ChunkRenderer.cs @@ -104,6 +104,8 @@ public void Reload() { public override void Render(double delta) { if (renderSlots == null) return; + + SetRenderPosition(Client.GameRenderer.MainCamera.position); CommandList.SetPipeline(ChunkPipeline); @@ -160,7 +162,7 @@ public void SetRenderPosition(dvec3 worldPosition) { } //Sort by distance so that closer chunks are rebuilt first. - createdRenderSlots.Sort((a, b) => (a.RealPosition - renderPosition).LengthSqr.CompareTo((b.RealPosition - renderPosition).LengthSqr)); + //createdRenderSlots.Sort((a, b) => (a.RealPosition - renderPosition).LengthSqr.CompareTo((b.RealPosition - renderPosition).LengthSqr)); } diff --git a/Client/VoxelClient.cs b/Client/VoxelClient.cs index 71d4802..e556426 100644 --- a/Client/VoxelClient.cs +++ b/Client/VoxelClient.cs @@ -1,13 +1,14 @@ using System; using GlmSharp; -using RenderSurface; using Voxel.Client.Keybinding; using Voxel.Client.Network; using Voxel.Client.Rendering; using Voxel.Client.Server; using Voxel.Client.World; -using Voxel.Common.Entity; +using Voxel.Client.World.Entity; using Voxel.Common.World; +using Voxel.Common.World.Entity; +using Voxel.Core; namespace Voxel.Client; @@ -60,7 +61,7 @@ public void SetupWorld() { world?.Dispose(); world = new ClientWorld(); - PlayerEntity = new PlayerEntity(); + PlayerEntity = new ControlledClientPlayerEntity(); world.AddEntity(PlayerEntity, dvec3.Zero, 0); } @@ -76,8 +77,9 @@ public override void OnTick() { if (Keybinds.Pause.justPressed) GameRenderer.WorldRenderer.ChunkRenderer.Reload(); - + connection?.Tick(); + world?.Tick(); } public override void OnWindowResize() { diff --git a/Client/World/ClientChunk.cs b/Client/World/ClientChunk.cs new file mode 100644 index 0000000..e3d0d31 --- /dev/null +++ b/Client/World/ClientChunk.cs @@ -0,0 +1,19 @@ +using GlmSharp; +using Voxel.Common.World; +using Voxel.Common.World.Storage; + +namespace Voxel.Client.World; + +public class ClientChunk : Chunk { + + public bool isFilled; + + public ClientChunk(ivec3 chunkPosition, VoxelWorld world, ChunkStorage? storage = null) : base(chunkPosition, world, storage) { + + } + + public override void SetStorage(ChunkStorage newStorage) { + isFilled = true; + base.SetStorage(newStorage); + } +} diff --git a/Client/World/ClientWorld.cs b/Client/World/ClientWorld.cs index 27e8700..f24f279 100644 --- a/Client/World/ClientWorld.cs +++ b/Client/World/ClientWorld.cs @@ -1,7 +1,12 @@ +using GlmSharp; using Voxel.Common.World; namespace Voxel.Client.World; public class ClientWorld : VoxelWorld { + protected override Chunk CreateChunk(ivec3 pos) { + var c = new ClientChunk(pos, this); + return c; + } } diff --git a/Client/World/Entity/ClientPlayerEntity.cs b/Client/World/Entity/ClientPlayerEntity.cs new file mode 100644 index 0000000..9f31868 --- /dev/null +++ b/Client/World/Entity/ClientPlayerEntity.cs @@ -0,0 +1,7 @@ +using Voxel.Common.World.Entity; + +namespace Voxel.Client.World.Entity; + +public class ClientPlayerEntity : PlayerEntity { + +} diff --git a/Client/World/Entity/ControlledClientPlayerEntity.cs b/Client/World/Entity/ControlledClientPlayerEntity.cs new file mode 100644 index 0000000..da74ebe --- /dev/null +++ b/Client/World/Entity/ControlledClientPlayerEntity.cs @@ -0,0 +1,36 @@ +using Common.Network.Packets.Utils; +using GlmSharp; +using SharpGen.Runtime; +using Voxel.Client.Keybinding; +using Voxel.Common.Network.Packets.C2S.Gameplay; + +namespace Voxel.Client.World.Entity; + +public class ControlledClientPlayerEntity : ClientPlayerEntity { + + public override void Tick() { + var movement = Keybinds.Move.axis; + var looking = Keybinds.Look.axis; + + movement += new dvec2(0, -1) * Keybinds.Forward.strength; + movement += new dvec2(0, 1) * Keybinds.Backward.strength; + movement += new dvec2(-1, 0) * Keybinds.StrafeLeft.strength; + movement += new dvec2(1, 0) * Keybinds.StrafeRight.strength; + + if (movement.LengthSqr > 1) + movement = movement.Normalized; + + var movement3d = new dvec3(movement.x, 0, movement.y); + + movement3d += new dvec3(0, 1, 0) * Keybinds.Jump.strength; + movement3d += new dvec3(0, -1, 0) * Keybinds.Crouch.strength; + + position += movement3d; + rotation += (float)looking.x; + + var transformUpdate = PacketPool.GetPacket(); + transformUpdate.Position = position; + transformUpdate.Rotation = rotation; + VoxelClient.Instance.connection!.SendPacket(transformUpdate); + } +} diff --git a/Common/Common.csproj b/Common/Common.csproj index ba70678..22a8ffc 100644 --- a/Common/Common.csproj +++ b/Common/Common.csproj @@ -4,6 +4,7 @@ net7.0 enable enable + Voxel.Common @@ -21,8 +22,4 @@ - - - - diff --git a/Common/Entity/PlayerEntity.cs b/Common/Entity/PlayerEntity.cs deleted file mode 100644 index 7567925..0000000 --- a/Common/Entity/PlayerEntity.cs +++ /dev/null @@ -1,13 +0,0 @@ -using Voxel.Common.Collision; -using Voxel.Common.World; - -namespace Voxel.Common.Entity; - -public class PlayerEntity : Entity { - public override float eyeHeight { get; } = 1.62f; - public override AABB boundingBox { get; } = new(new(0,0,0), new(0,0,0)); - - public override void Tick() { - //TODO! - } -} diff --git a/Common/Network/ConnectionBase.cs b/Common/Network/ConnectionBase.cs index 94863d1..257b497 100644 --- a/Common/Network/ConnectionBase.cs +++ b/Common/Network/ConnectionBase.cs @@ -1,5 +1,6 @@ using Common.Network.Packets; using NLog.Targets; +using Voxel.Common.Network.Packets; namespace Common.Network; diff --git a/Common/Network/Packets/C2S/Gameplay/PlayerUpdated.cs b/Common/Network/Packets/C2S/Gameplay/PlayerUpdated.cs new file mode 100644 index 0000000..fa8cd59 --- /dev/null +++ b/Common/Network/Packets/C2S/Gameplay/PlayerUpdated.cs @@ -0,0 +1,19 @@ +using Common.Network.Packets.C2S; +using Common.Util.Serialization; +using GlmSharp; + +namespace Voxel.Common.Network.Packets.C2S.Gameplay; + +public class PlayerUpdated : C2SPacket { + public dvec3 Position; + public float Rotation; + + public override void Write(VDataWriter writer) { + writer.Write(Position); + writer.Write(Rotation); + } + public override void Read(VDataReader reader) { + Position = reader.ReadDVec3(); + Rotation = reader.ReadFloat(); + } +} diff --git a/Common/Network/Packets/PacketHandler.cs b/Common/Network/Packets/PacketHandler.cs index cf3a294..559e59e 100644 --- a/Common/Network/Packets/PacketHandler.cs +++ b/Common/Network/Packets/PacketHandler.cs @@ -1,4 +1,7 @@ -namespace Common.Network.Packets; +using Common.Network.Packets; +using Common.Network.Packets.Utils; + +namespace Voxel.Common.Network.Packets; /// /// Clean way of handling multiple packets by type. @@ -17,6 +20,7 @@ public bool HandlePacket(T packet) { handler(packet); + PacketPool.Return(packet); return true; } } diff --git a/Common/Network/Packets/S2C/Gameplay/Entity/EntityPacket.cs b/Common/Network/Packets/S2C/Gameplay/Entity/EntityPacket.cs new file mode 100644 index 0000000..568fba4 --- /dev/null +++ b/Common/Network/Packets/S2C/Gameplay/Entity/EntityPacket.cs @@ -0,0 +1,23 @@ +using Common.Network.Packets.S2C; +using Common.Util.Serialization; + +namespace Voxel.Common.Network.Packets.S2C.Gameplay.Entity; + +public class EntityPacket : S2CPacket { + public Guid ID; + + public virtual void Init(World.Entity.Entity entity) { + ID = entity.ID; + } + + public virtual void Apply(World.Entity.Entity entity) { + + } + + public override void Write(VDataWriter writer) { + writer.Write(ID); + } + public override void Read(VDataReader reader) { + ID = reader.ReadGuid(); + } +} diff --git a/Common/Network/Packets/S2C/Gameplay/Entity/EntityTransformUpdate.cs b/Common/Network/Packets/S2C/Gameplay/Entity/EntityTransformUpdate.cs new file mode 100644 index 0000000..83c99a2 --- /dev/null +++ b/Common/Network/Packets/S2C/Gameplay/Entity/EntityTransformUpdate.cs @@ -0,0 +1,30 @@ +using Common.Util.Serialization; +using GlmSharp; +using Voxel.Common.Network.Packets.S2C.Gameplay.Entity; +using Voxel.Common.World.Entity; + +namespace Common.Network.Packets.S2C.Gameplay; + +public class EntityTransformUpdate : EntityPacket { + public dvec3 Position; + public float Rotation; + + public override void Init(Entity entity) { + Position = entity.position; + Rotation = entity.rotation; + } + + public override void Apply(Entity entity) { + entity.position = Position; + entity.rotation = Rotation; + } + + public override void Write(VDataWriter writer) { + writer.Write(Position); + writer.Write(Rotation); + } + public override void Read(VDataReader reader) { + Position = reader.ReadDVec3(); + Rotation = reader.ReadFloat(); + } +} diff --git a/Common/Server/Components/Networking/ServerConnectionContext.cs b/Common/Server/Components/Networking/ServerConnectionContext.cs index 34fa6a3..d1b921e 100644 --- a/Common/Server/Components/Networking/ServerConnectionContext.cs +++ b/Common/Server/Components/Networking/ServerConnectionContext.cs @@ -6,8 +6,10 @@ using Common.Network.Packets.S2C.Gameplay; using Common.Network.Packets.S2C.Handshake; using Common.Network.Packets.Utils; -using Voxel.Common.Entity; +using Voxel.Common.Network.Packets; +using Voxel.Common.Network.Packets.C2S.Gameplay; using Voxel.Common.World; +using Voxel.Common.World.Entity; namespace Common.Server.Components.Networking; @@ -36,11 +38,12 @@ public ServerConnectionContext(S2CConnection connection) { HandshakeHandler.RegisterHandler(OnHandshakeDone); GameplayHandler = new PacketHandler(); + GameplayHandler.RegisterHandler(OnPlayerUpdated); Connection.packetHandler = HandshakeHandler; } - private void OnHandshakeDone(C2SHandshakeDone obj) { + private void OnHandshakeDone(C2SHandshakeDone pkt) { Connection.packetHandler = GameplayHandler; //Notify client that server has finished handshake. @@ -50,6 +53,18 @@ private void OnHandshakeDone(C2SHandshakeDone obj) { GameplayStart(); } + private void OnPlayerUpdated(PlayerUpdated pkt) { + if (entity == null) + return; + + entity.position = pkt.Position; + entity.rotation = pkt.Rotation; + + loadedChunks?.Move(entity.chunkPosition); + + //Console.WriteLine(entity.position + "|" + entity.chunkPosition); + } + public void Close() => Connection.Close(); @@ -74,5 +89,12 @@ public void SetupViewArea(int range) { SendPacket(pkt); } + + loadedChunks.OnChunkAddedToView += c => { + var pkt = PacketPool.GetPacket(); + pkt.Init(c); + + SendPacket(pkt); + }; } } diff --git a/Common/Server/Components/PlayerManager.cs b/Common/Server/Components/PlayerManager.cs index 7aeed6e..7e30d99 100644 --- a/Common/Server/Components/PlayerManager.cs +++ b/Common/Server/Components/PlayerManager.cs @@ -2,7 +2,7 @@ using Common.Server.Components.Networking; using GlmSharp; using Voxel.Common.Config; -using Voxel.Common.Entity; +using Voxel.Common.World.Entity; namespace Common.Server.Components; @@ -42,7 +42,7 @@ private void OnConnectionMade(ServerConnectionContext context) { Console.WriteLine("Server:Sending player to world..."); context.SendPacket(new SetupWorld()); - context.SetupViewArea(3); + context.SetupViewArea(5); }; } } diff --git a/Common/Util/Serialization/VDataReader.cs b/Common/Util/Serialization/VDataReader.cs index 5bf3f39..e7209cd 100644 --- a/Common/Util/Serialization/VDataReader.cs +++ b/Common/Util/Serialization/VDataReader.cs @@ -77,7 +77,7 @@ private Span GetBytes(int length) { public float ReadFloat() => BitConverter.ToSingle(GetBytes(sizeof(float))); public double ReadDouble() => BitConverter.ToDouble(GetBytes(sizeof(double))); - public Guid ReadGuid(Guid data) => new Guid(GetBytes(16)); + public Guid ReadGuid() => new Guid(GetBytes(16)); public string ReadString() => ReadString(Encoding.UTF8); public string ReadString(Encoding encoding) { diff --git a/Common/World/Chunk.cs b/Common/World/Chunk.cs index 9b71447..d8eb428 100644 --- a/Common/World/Chunk.cs +++ b/Common/World/Chunk.cs @@ -7,12 +7,14 @@ namespace Voxel.Common.World; -public class Chunk : IDisposable { +public class Chunk : Tickable, IDisposable { public readonly ivec3 ChunkPosition; public readonly ivec3 WorldPosition; public readonly VoxelWorld World; + private readonly List Tickables = new(); + public ChunkStorage storage { get; private set; } private uint viewCount; @@ -35,7 +37,7 @@ public Chunk(ivec3 chunkPosition, VoxelWorld world, ChunkStorage? storage = null public ChunkStorage CopyStorage() => storage.GenerateCopy(); - public void SetStorage(ChunkStorage newStorage) { + public virtual void SetStorage(ChunkStorage newStorage) { storage.Dispose(); storage = newStorage; IncrementVersion(); @@ -67,6 +69,15 @@ internal void DecrementViewCount() { World.UnloadChunk(ChunkPosition); } + + public void Tick() { + foreach (var tickable in Tickables) + tickable.Tick(); + } + + public void AddTickable(Tickable tickable) => Tickables.Add(tickable); + public void RemoveTickable(Tickable tickable) => Tickables.Remove(tickable); + public void Dispose() { storage.Dispose(); } diff --git a/Common/Entity/Entity.cs b/Common/World/Entity/Entity.cs similarity index 79% rename from Common/Entity/Entity.cs rename to Common/World/Entity/Entity.cs index b97c1c6..12a4389 100644 --- a/Common/Entity/Entity.cs +++ b/Common/World/Entity/Entity.cs @@ -1,11 +1,13 @@ +using Common.Network.Packets; +using Common.Network.Packets.S2C.Gameplay; +using Common.Network.Packets.Utils; using GlmSharp; using Voxel.Common.Collision; using Voxel.Common.Util; -using Voxel.Common.World; -namespace Voxel.Common.Entity; +namespace Voxel.Common.World.Entity; -public abstract class Entity { +public abstract class Entity : Tickable { public VoxelWorld world { get; private set; } public Chunk chunk { get; private set; } @@ -19,15 +21,18 @@ public abstract class Entity { /// World-space rotation of entity around the y axis. /// public float rotation = 0; - + /// - /// World-space 3d block position + /// World-space 3d block position of the entity. /// public ivec3 blockPosition { get => (ivec3)dvec3.Floor(position); set => position = value; } + /// + /// The chunk-space 3d position of the entity. + /// public ivec3 chunkPosition => blockPosition.BlockToChunkPosition(); public bool destroyed { get; private set; } = false; @@ -44,7 +49,9 @@ public void AddToWorld(VoxelWorld newWorld, dvec3 pos, float rot) { public virtual void OnAddedToWorld() {} - public abstract void Tick(); + public virtual void Tick() { + + } /// /// Queues an entity to be destroyed at the end of the tick. diff --git a/Common/World/Entity/PlayerEntity.cs b/Common/World/Entity/PlayerEntity.cs new file mode 100644 index 0000000..3b3b9ba --- /dev/null +++ b/Common/World/Entity/PlayerEntity.cs @@ -0,0 +1,8 @@ +using Voxel.Common.Collision; + +namespace Voxel.Common.World.Entity; + +public class PlayerEntity : Entity { + public override float eyeHeight { get; } = 1.62f; + public override AABB boundingBox { get; } = new(new(0, 0, 0), new(0, 0, 0)); +} diff --git a/Common/World/LoadedChunkSection.cs b/Common/World/LoadedChunkSection.cs index ebcbcb1..3b12236 100644 --- a/Common/World/LoadedChunkSection.cs +++ b/Common/World/LoadedChunkSection.cs @@ -16,6 +16,9 @@ public class LoadedChunkSection { private Dictionary views = new(); + + public event Action OnChunkAddedToView = _ => {}; + public LoadedChunkSection(VoxelWorld world, ivec3 centerPos, int halfWidth, int halfHeight) { World = world; this.centerPos = centerPos; @@ -48,9 +51,19 @@ public void Resize(int halfWidth, int halfHeight) { private void Update() { var map = new Dictionary(); foreach (var pos in Iteration.Cubic(min, max)) { - map[pos] = World.GetOrCreateChunkView(centerPos + pos); - } + bool hadAlready = views.ContainsKey(centerPos + pos); + var view = World.GetOrCreateChunkView(centerPos + pos); + map[pos] = view; + + if (!hadAlready) { + OnChunkAddedToView(view.Chunk); + } + } + + foreach (var view in views.Values) + view.Dispose(); + views = map; } diff --git a/Common/World/Tickable.cs b/Common/World/Tickable.cs new file mode 100644 index 0000000..818597b --- /dev/null +++ b/Common/World/Tickable.cs @@ -0,0 +1,5 @@ +namespace Voxel.Common.World; + +public interface Tickable { + public void Tick(); +} diff --git a/Common/World/VoxelWorld.cs b/Common/World/VoxelWorld.cs index d4208fd..002a33e 100644 --- a/Common/World/VoxelWorld.cs +++ b/Common/World/VoxelWorld.cs @@ -10,6 +10,8 @@ public abstract class VoxelWorld : BlockView { private readonly Dictionary Chunks = new(); + public List GlobalTickables = new(); + public bool TryGetChunkRaw(ivec3 chunkPos, [NotNullWhen(true)] out Chunk? chunk) => Chunks.TryGetValue(chunkPos, out chunk); public bool TryGetChunk(dvec3 worldPosition, [NotNullWhen(true)] out Chunk? chunk) => TryGetChunkRaw(worldPosition.WorldToChunkPosition(), out chunk); public bool TryGetChunk(ivec3 blockPosition, [NotNullWhen(true)] out Chunk? chunk) => TryGetChunkRaw(blockPosition.BlockToChunkPosition(), out chunk); @@ -33,13 +35,17 @@ public Chunk GetOrCreateChunk(ivec3 chunkPosition) { chunk = CreateChunk(chunkPosition); Chunks[chunkPosition] = chunk; + GlobalTickables.Add(chunk); return chunk; } protected virtual Chunk CreateChunk(ivec3 pos) => new(pos, this); internal void UnloadChunk(ivec3 chunkPosition) { - Chunks.Remove(chunkPosition); + Chunks.Remove(chunkPosition, out var c); + + if (c != null) + GlobalTickables.Remove(c); } internal ChunkView GetOrCreateChunkView(ivec3 chunkPosition) { @@ -67,10 +73,14 @@ public Block GetBlock(ivec3 position) { public virtual void AddEntity(Entity.Entity entity, dvec3 position, float rotation) { entity.AddToWorld(this, position, rotation); + + var chunk = GetOrCreateChunk(entity.chunkPosition); + chunk.AddTickable(entity); } public void Tick() { - + foreach (var tickable in GlobalTickables) + tickable.Tick(); } public void Dispose() { diff --git a/Core/Assets/AssetReader.cs b/Core/Assets/AssetReader.cs index 7b7a754..46893fe 100644 --- a/Core/Assets/AssetReader.cs +++ b/Core/Assets/AssetReader.cs @@ -1,7 +1,7 @@ using System.Diagnostics.CodeAnalysis; using System.IO.Compression; -namespace RenderSurface.Assets; +namespace Voxel.Core.Assets; public sealed class AssetReader : IDisposable { public delegate bool ConditionDelegate(string path); diff --git a/Core/Core.csproj b/Core/Core.csproj index 6afe679..a2c8413 100644 --- a/Core/Core.csproj +++ b/Core/Core.csproj @@ -4,8 +4,8 @@ net7.0 enable enable - RenderSurface true + Voxel.Core diff --git a/Core/Game.cs b/Core/Game.cs index 2e32301..187b189 100644 --- a/Core/Game.cs +++ b/Core/Game.cs @@ -1,11 +1,11 @@ -using RenderSurface.Assets; -using RenderSurface.Input; -using RenderSurface.Rendering; using Veldrid; using Veldrid.Sdl2; using Veldrid.StartupUtilities; +using Voxel.Core.Assets; +using Voxel.Core.Input; +using Voxel.Core.Rendering; -namespace RenderSurface; +namespace Voxel.Core; public abstract class Game : IDisposable { public Sdl2Window NativeWindow { get; private set; } @@ -34,7 +34,7 @@ public void Run(int tps = 20, string windowTitle = "Game") { var gdo = new GraphicsDeviceOptions { PreferDepthRangeZeroToOne = true, PreferStandardClipSpaceYDirection = true, - SyncToVerticalBlank = false, + SyncToVerticalBlank = true, SwapchainDepthFormat = PixelFormat.R32_Float, }; diff --git a/Core/Input/Gamepad/Buttons.cs b/Core/Input/Gamepad/Buttons.cs index c1e444b..7f30cae 100644 --- a/Core/Input/Gamepad/Buttons.cs +++ b/Core/Input/Gamepad/Buttons.cs @@ -1,7 +1,7 @@ using System.Runtime.CompilerServices; using Veldrid.Sdl2; -namespace RenderSurface.Input.Gamepad; +namespace Voxel.Core.Input.Gamepad; public enum GamepadButton : byte { Invalid = unchecked((byte)-1), diff --git a/Core/Input/Gamepad/SdlGamepad.cs b/Core/Input/Gamepad/SdlGamepad.cs index b7cfc88..8bf142a 100644 --- a/Core/Input/Gamepad/SdlGamepad.cs +++ b/Core/Input/Gamepad/SdlGamepad.cs @@ -2,7 +2,7 @@ using System.Runtime.InteropServices; using Veldrid.Sdl2; -namespace RenderSurface.Input.Gamepad; +namespace Voxel.Core.Input.Gamepad; public sealed class SdlGamepad { public readonly int Index; diff --git a/Core/Input/InputAction.cs b/Core/Input/InputAction.cs index 638bc20..e6c2189 100644 --- a/Core/Input/InputAction.cs +++ b/Core/Input/InputAction.cs @@ -1,6 +1,6 @@ using Veldrid; -namespace RenderSurface.Input; +namespace Voxel.Core.Input; public class InputAction { internal readonly InputManager Manager; diff --git a/Core/Input/InputManager.cs b/Core/Input/InputManager.cs index f5dfa48..b8912df 100644 --- a/Core/Input/InputManager.cs +++ b/Core/Input/InputManager.cs @@ -1,10 +1,10 @@ using System.Runtime.CompilerServices; using GlmSharp; -using RenderSurface.Input.Gamepad; using Veldrid; using Veldrid.Sdl2; +using Voxel.Core.Input.Gamepad; -namespace RenderSurface.Input; +namespace Voxel.Core.Input; public sealed class InputManager : IDisposable { public readonly Game Game; diff --git a/Core/Rendering/RenderSystem.cs b/Core/Rendering/RenderSystem.cs index 4de88a9..fce987a 100644 --- a/Core/Rendering/RenderSystem.cs +++ b/Core/Rendering/RenderSystem.cs @@ -1,8 +1,8 @@ using System.Collections.Concurrent; -using RenderSurface.Assets; using Veldrid; +using Voxel.Core.Assets; -namespace RenderSurface.Rendering; +namespace Voxel.Core.Rendering; public class RenderSystem { public const uint QuadCount = 196608; diff --git a/Core/Rendering/ShaderManager.cs b/Core/Rendering/ShaderManager.cs index 760171c..000d5cb 100644 --- a/Core/Rendering/ShaderManager.cs +++ b/Core/Rendering/ShaderManager.cs @@ -1,10 +1,10 @@ using System.Diagnostics.CodeAnalysis; using System.Text; -using RenderSurface.Assets; using Veldrid; using Veldrid.SPIRV; +using Voxel.Core.Assets; -namespace RenderSurface.Rendering; +namespace Voxel.Core.Rendering; public class ShaderManager { diff --git a/Core/Rendering/TextureManager.cs b/Core/Rendering/TextureManager.cs index f704892..a5b1edd 100644 --- a/Core/Rendering/TextureManager.cs +++ b/Core/Rendering/TextureManager.cs @@ -1,9 +1,9 @@ using System.Diagnostics.CodeAnalysis; -using RenderSurface.Assets; using Veldrid; using Veldrid.ImageSharp; +using Voxel.Core.Assets; -namespace RenderSurface.Rendering; +namespace Voxel.Core.Rendering; public class TextureManager { diff --git a/Test/Test.csproj b/Test/Test.csproj index b8597ac..0f8e262 100644 --- a/Test/Test.csproj +++ b/Test/Test.csproj @@ -5,7 +5,7 @@ net7.0 Major false - Voxel + Voxel.Test disable enable true