From 0d324c0ff061e26e9896aa8e2866a1f12919802b Mon Sep 17 00:00:00 2001 From: Ari Vuollet Date: Sat, 21 Jun 2025 20:59:56 +0300 Subject: [PATCH] _net prog --- Content/Common/PlayerPrefab.prefab | 16 +- .../EngineSettings/BuildSettings.json | 17 +- .../EngineSettings/GraphicsSettings.json | 21 +- .../EngineSettings/NetworkSettings.json | 4 +- .../Settings/EngineSettings/TimeSettings.json | 3 +- Content/config.cfg | 5 +- GoakeFlax.code-workspace | 4 +- Source/Game/Console/ConsolePlugin.cs | 2 + Source/Game/Console/ConsoleVariable.cs | 7 +- Source/Game/GameMode/NetworkManager.cs | 6 +- Source/Game/GameMode/NetworkManager_Client.cs | 2 +- Source/Game/GameMode/NetworkManager_Demo.cs | 2 +- Source/Game/GameMode/NetworkManager_Server.cs | 11 +- Source/Game/GameMode/World.cs | 264 ++++++++++++++---- Source/Game/Player/PlayerInput2.cs | 8 +- Source/Game/Player/PlayerMovement.cs | 11 +- 16 files changed, 275 insertions(+), 108 deletions(-) diff --git a/Content/Common/PlayerPrefab.prefab b/Content/Common/PlayerPrefab.prefab index de631c2..8ec52cc 100644 --- a/Content/Common/PlayerPrefab.prefab +++ b/Content/Common/PlayerPrefab.prefab @@ -1,7 +1,7 @@ { "ID": "82e58c9d462fba5a0df1a599417ff684", "TypeName": "FlaxEngine.Prefab", - "EngineBuild": 6340, + "EngineBuild": 6704, "Data": [ { "ID": "a50f3639419a8306036ecfab7115e772", @@ -17,7 +17,11 @@ "ID": "bc518e2f40ec06a4523d78b52809c668", "TypeName": "Game.PlayerMovement", "ParentID": "a50f3639419a8306036ecfab7115e772", - "V": {}, + "V": { + "maskTest": { + "Mask": 1 + } +}, "Enabled": false }, { @@ -162,8 +166,8 @@ } }, "StaticFlags": 0, - "ContactOffset": 0.0, "Material": "d99b8b6f40198beea4703dadd642150e", + "ContactOffset": 0.0, "Radius": 16.0, "Height": 52.0 }, @@ -173,8 +177,8 @@ "ParentID": "a50f3639419a8306036ecfab7115e772", "Name": "BoxCollider", "StaticFlags": 0, - "ContactOffset": 0.0, "Material": "ffe0e84c49607480f67a3994a7fe11a8", + "ContactOffset": 0.0, "Size": { "X": 30.0, "Y": 56.0, @@ -211,9 +215,9 @@ "Name": "PlayerModel", "Transform": { "Scale": { - "X": 0.30000001192092898, + "X": 0.30000001192092896, "Y": 0.5600000023841858, - "Z": 0.30000001192092898 + "Z": 0.30000001192092896 } }, "StaticFlags": 0, diff --git a/Content/Settings/EngineSettings/BuildSettings.json b/Content/Settings/EngineSettings/BuildSettings.json index 4099356..510965e 100644 --- a/Content/Settings/EngineSettings/BuildSettings.json +++ b/Content/Settings/EngineSettings/BuildSettings.json @@ -1,7 +1,7 @@ { "ID": "af2e52554f7faed7b4937181dd22d166", "TypeName": "FlaxEditor.Content.Settings.BuildSettings", - "EngineBuild": 6605, + "EngineBuild": 6705, "Data": { "OutputName": "${PROJECT_NAME}", "MaxAssetsPerPackage": 4096, @@ -27,18 +27,9 @@ "Name": "Preset 3", "Targets": [ { - "Name": "Win64 Release", - "Output": "Output\\WindowsRelease", - "Platform": 2, - "Mode": 2, - "CustomDefines": null, - "PreBuildAction": null, - "PostBuildAction": null - }, - { - "Name": "Win64 Development", - "Output": "Output\\WindowsDevelopment", - "Platform": 2, + "Name": "Windows 64bit", + "Output": "Output\\Win64", + "Platform": 13, "Mode": 1, "CustomDefines": null, "PreBuildAction": null, diff --git a/Content/Settings/EngineSettings/GraphicsSettings.json b/Content/Settings/EngineSettings/GraphicsSettings.json index 5a9f970..2805e81 100644 --- a/Content/Settings/EngineSettings/GraphicsSettings.json +++ b/Content/Settings/EngineSettings/GraphicsSettings.json @@ -1,7 +1,7 @@ { "ID": "f94d5aae457aeba67033a8a4ca753214", "TypeName": "FlaxEditor.Content.Settings.GraphicsSettings", - "EngineBuild": 6602, + "EngineBuild": 6705, "Data": { "UseVSync": false, "AAQuality": 3, @@ -19,6 +19,7 @@ "GenerateSDFOnModelImport": false, "GIQuality": 3, "GIProbesSpacing": 100.0, + "GICascadesBlending": false, "GlobalSurfaceAtlasResolution": 4096, "PostProcessSettings": { "AO": { @@ -49,8 +50,10 @@ "Enabled": false, "Intensity": 1.0, "Threshold": 3.0, - "BlurSigma": 4.0, - "Limit": 10.0 + "ThresholdKnee": 0.5, + "Clamp": 3.0, + "BaseMix": 0.6, + "HighMix": 1.0 }, "ToneMapping": { "OverrideFlags": 4, @@ -198,7 +201,7 @@ "HistogramHighPercent": 98.0 }, "CameraArtifacts": { - "OverrideFlags": 9, + "OverrideFlags": 1, "VignetteIntensity": 0.0, "VignetteColor": { "X": 0.0, @@ -206,8 +209,8 @@ "Z": 0.001 }, "VignetteShapeFactor": 0.125, - "GrainAmount": 0.0, - "GrainParticleSize": 1.6, + "GrainAmount": 0.22999999, + "GrainParticleSize": 1.0, "GrainSpeed": 1.0, "ChromaticDistortion": 0.0, "ScreenFadeColor": { @@ -283,7 +286,11 @@ "TAA_JitterSpread": 0.75, "TAA_Sharpness": 0.0, "TAA_StationaryBlending": 0.95, - "TAA_MotionBlending": 0.4 + "TAA_MotionBlending": 0.4, + "CAS_SharpeningAmount": 0.0, + "CAS_EdgeSharpening": 0.5, + "CAS_MinEdgeThreshold": 0.03, + "CAS_OverBlurLimit": 1.0 }, "PostFxMaterials": { "Materials": null diff --git a/Content/Settings/EngineSettings/NetworkSettings.json b/Content/Settings/EngineSettings/NetworkSettings.json index 75dae0b..de1ccca 100644 --- a/Content/Settings/EngineSettings/NetworkSettings.json +++ b/Content/Settings/EngineSettings/NetworkSettings.json @@ -1,11 +1,11 @@ { "ID": "0c69a0c7471f8d0805965caf343d2f27", "TypeName": "FlaxEditor.Content.Settings.NetworkSettings", - "EngineBuild": 6340, + "EngineBuild": 6705, "Data": { "MaxClients": 100, "ProtocolVersion": 1, - "NetworkFPS": 60.0, + "NetworkFPS": 1.0, "Address": "127.0.0.1", "Port": 59183, "NetworkDriver": "FlaxEngine.Networking.ENetDriver" diff --git a/Content/Settings/EngineSettings/TimeSettings.json b/Content/Settings/EngineSettings/TimeSettings.json index d36b456..46e516c 100644 --- a/Content/Settings/EngineSettings/TimeSettings.json +++ b/Content/Settings/EngineSettings/TimeSettings.json @@ -1,9 +1,8 @@ { "ID": "a55dc3c04da4ea3744b7f1994565beac", "TypeName": "FlaxEditor.Content.Settings.TimeSettings", - "EngineBuild": 6332, + "EngineBuild": 6705, "Data": { - "UpdateMode": 1, "UpdateFPS": 120.0, "PhysicsFPS": 120.0, "DrawFPS": 120.0, diff --git a/Content/config.cfg b/Content/config.cfg index 6961891..904bbc5 100644 --- a/Content/config.cfg +++ b/Content/config.cfg @@ -1,7 +1,8 @@ // comment r_shadows 1 r_lighting 1 -cl_maxfps 240 +cl_maxfps 120 r_upscaling 0 r_gi 0 -r_staticbatch 1 \ No newline at end of file +r_staticbatch 1 +sensitivity 0.5 \ No newline at end of file diff --git a/GoakeFlax.code-workspace b/GoakeFlax.code-workspace index 4a46a8f..f7da274 100644 --- a/GoakeFlax.code-workspace +++ b/GoakeFlax.code-workspace @@ -5,8 +5,8 @@ "gulp.autoDetect": "off", "jake.autoDetect": "off", "grunt.autoDetect": "off", - "omnisharp.defaultLaunchSolution": "GoakeFlax.sln", - "omnisharp.useModernNet": true + "omnisharp.useModernNet": true, + "dotnet.defaultSolution": "GoakeFlax.sln" }, "folders": [ { diff --git a/Source/Game/Console/ConsolePlugin.cs b/Source/Game/Console/ConsolePlugin.cs index fb15577..6f2f841 100644 --- a/Source/Game/Console/ConsolePlugin.cs +++ b/Source/Game/Console/ConsolePlugin.cs @@ -2,6 +2,8 @@ using FlaxEngine; using Console = Game.Console; using System.Linq; +using System.Threading; + #if FLAX_EDITOR using FlaxEditor; #endif diff --git a/Source/Game/Console/ConsoleVariable.cs b/Source/Game/Console/ConsoleVariable.cs index 8c77fb8..74fba71 100644 --- a/Source/Game/Console/ConsoleVariable.cs +++ b/Source/Game/Console/ConsoleVariable.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Reflection; +using System.Runtime.CompilerServices; using FlaxEngine; using FlaxEngine.Assertions; @@ -71,16 +72,16 @@ internal class ConsoleVariable if (type == typeof(string)) { if (field != null) - return (string)field.GetValue(null); + return Unsafe.As(field.GetValue(null)); if (getter != null) - return ((float)getter.Invoke(null, null)).ToString(); + return Unsafe.As(getter.Invoke(null, null)); } else if (type == typeof(float)) { if (field != null) return field.GetValue(null).ToString(); if (getter != null) - return ((float)getter.Invoke(null, null)).ToString(); + return getter.Invoke(null, null).ToString(); } else throw new Exception($"ConsoleVariable: Unsupported variable type '{type.FullName}'"); diff --git a/Source/Game/GameMode/NetworkManager.cs b/Source/Game/GameMode/NetworkManager.cs index 70d6ccf..9f298df 100644 --- a/Source/Game/GameMode/NetworkManager.cs +++ b/Source/Game/GameMode/NetworkManager.cs @@ -161,10 +161,10 @@ public static partial class NetworkManager public static void Cleanup() { Scripting.Exit -= Cleanup; - Scripting.FixedUpdate -= OnDemoUpdate; - Scripting.FixedUpdate -= OnServerNetworkUpdate; + Scripting.Update -= OnDemoUpdate; + Scripting.Update -= OnServerNetworkUpdate; Level.ActorSpawned -= OnServerActorSpawned; - Scripting.FixedUpdate -= OnClientNetworkUpdate; + Scripting.Update -= OnClientNetworkUpdate; Level.ActorSpawned -= OnClientActorSpawned; if (server != null) diff --git a/Source/Game/GameMode/NetworkManager_Client.cs b/Source/Game/GameMode/NetworkManager_Client.cs index a4f30ad..e2ff3ed 100644 --- a/Source/Game/GameMode/NetworkManager_Client.cs +++ b/Source/Game/GameMode/NetworkManager_Client.cs @@ -61,7 +61,7 @@ public static partial class NetworkManager }*/ World.InitClient(); - Scripting.FixedUpdate += OnClientNetworkUpdate; + Scripting.Update += OnClientNetworkUpdate; if (!listenServer) { Scripting.Exit += Cleanup; diff --git a/Source/Game/GameMode/NetworkManager_Demo.cs b/Source/Game/GameMode/NetworkManager_Demo.cs index b434db1..39ea310 100644 --- a/Source/Game/GameMode/NetworkManager_Demo.cs +++ b/Source/Game/GameMode/NetworkManager_Demo.cs @@ -59,7 +59,7 @@ public static unsafe partial class NetworkManager return false; }*/ - Scripting.FixedUpdate += OnDemoUpdate; + Scripting.Update += OnDemoUpdate; //if (!listenServer) { Scripting.Exit += Cleanup; diff --git a/Source/Game/GameMode/NetworkManager_Server.cs b/Source/Game/GameMode/NetworkManager_Server.cs index 33514b2..85605cf 100644 --- a/Source/Game/GameMode/NetworkManager_Server.cs +++ b/Source/Game/GameMode/NetworkManager_Server.cs @@ -26,15 +26,16 @@ public static partial class NetworkManager ConnectedClients = new List(MaximumClients); - //var driver = Object.New(typeof(ENetDriver)); - //ServerNetworkDriver = null; + //INetworkDriver driver = Object.New(); NetworkLagDriver driver = Object.New(); - driver.Lag = 200f; + if (driver is NetworkLagDriver networkLagDriver) + networkLagDriver.Lag = 200f; + ServerNetworkDriver = driver; server = NetworkPeer.CreatePeer(new NetworkConfig { - NetworkDriver = driver, + NetworkDriver = (Object)driver, ConnectionsLimit = MaximumClients, MessagePoolSize = 2048, MessageSize = MTU, @@ -47,7 +48,7 @@ public static partial class NetworkManager return false; } - Scripting.FixedUpdate += OnServerNetworkUpdate; + Scripting.Update += OnServerNetworkUpdate; Scripting.Exit += Cleanup; Level.ActorSpawned += OnServerActorSpawned; diff --git a/Source/Game/GameMode/World.cs b/Source/Game/GameMode/World.cs index e92805b..cdf9281 100644 --- a/Source/Game/GameMode/World.cs +++ b/Source/Game/GameMode/World.cs @@ -22,29 +22,23 @@ public enum GameModeMessageType2 : byte LastMessageType = 128, } +public class PlayerFrame +{ + public ulong frame; + public Float3 position; + public PlayerInputState2 inputState; + public PlayerMovementState movementState; +} + +public interface IClientInfo +{ + public NetworkConnection Connection { get; set; } + public PlayerActor PlayerActor { get; set; } + public PlayerFrame[] FrameHistory { get; set; } +} + public class World { - protected class ClientInfo - { - public NetworkConnection Connection; - public PlayerActor PlayerActor; - public PlayerFrame[] FrameHistory = new PlayerFrame[120]; - - public ClientInfo() - { - for (int i = 0; i < FrameHistory.Length; i++) - FrameHistory[i] = new PlayerFrame(); - } - } - - public class PlayerFrame - { - public ulong frame; - public Float3 position; - public PlayerInputState2 inputState; - public PlayerMovementState movementState; - } - public bool IsServer => this is ServerWorld; public bool IsClient => !IsServer; public ulong Frame { get; protected set; } @@ -54,7 +48,6 @@ public class World protected Scene _scene; protected Actor _worldSpawn; - protected Dictionary _clients = new(); public static void InitClient() { @@ -65,6 +58,9 @@ public class World { WorldStore.ServerWorld = new ServerWorld(); WorldStore.ServerWorld.Init(); + Scripting.Update += WorldStore.ServerWorld.OnUpdate; + Scripting.LateUpdate += WorldStore.ServerWorld.OnUpdateLate; + Scripting.FixedUpdate += WorldStore.ServerWorld.OnFixedUpdate; } public static void CleanupClient() { @@ -79,12 +75,17 @@ public class World virtual protected void Init() { + + Scripting.LateFixedUpdate += OnLateUpdate; } virtual protected void Cleanup() { //Level.SceneLoaded -= OnLevelLoaded; //Scripting.LateUpdate -= OnLateUpdatePre; + Scripting.Update -= OnUpdate; + Scripting.LateUpdate -= OnUpdateLate; + Scripting.FixedUpdate -= OnFixedUpdate; Scripting.LateFixedUpdate -= OnLateUpdate; if (_scene) @@ -99,6 +100,21 @@ public class World } } + void OnUpdate() + { + Console.Print("server Update"); + } + + void OnUpdateLate() + { + Console.Print("server LateUpdate"); + } + + void OnFixedUpdate() + { + Console.Print("server FixedUpdate"); + } + protected void CreateScene(string sceneNamePrefix, string sceneGuid) { string physicsSceneName = $"{sceneNamePrefix}PhysicsScene"; @@ -155,7 +171,7 @@ public class World _scene.Name = $"{sceneNamePrefix}Scene"; //Level.SceneLoaded += OnLevelLoaded; - Scripting.LateFixedUpdate += OnLateUpdate; + var importer = FlaxEngine.Object.New(); importer.mapPath = @"C:\dev\GoakeFlax\Assets\Maps\aerowalk.map"; @@ -167,16 +183,12 @@ public class World Assert.IsTrue(_worldSpawn); } - public void OnLateUpdate() + virtual protected void OnLateUpdate() { Frame++; } - protected void OnClientConnected(NetworkConnection connection) - { - uint playerId = connection.ConnectionId; - _clients.Add(playerId, new ClientInfo() { Connection = connection }); - } + virtual protected IClientInfo GetClient(uint playerId) => null; virtual protected PlayerActor SpawnPlayer(uint playerId, Float3 position, Vector3 eulerAngles) { @@ -189,7 +201,8 @@ public class World playerActor.Initialize(playerId, position, eulerAngles); //playerActor.Teleport(position, eulerAngles); - _clients[playerId].PlayerActor = playerActor; + IClientInfo player = GetClient(playerId); + player.PlayerActor = playerActor; IPlayerInput playerInput = playerActor.GetScript().Input; playerInput.SetFrame(Frame); /*if (IsServer) @@ -213,7 +226,7 @@ public class World public PlayerFrame GetPlayerFrame(uint playerId, ulong frame) { - ClientInfo player = _clients[playerId]; + IClientInfo player = GetClient(playerId); PlayerFrame playerFrame = player.FrameHistory[frame % 120]; if (playerFrame.frame != frame) return null; @@ -229,10 +242,52 @@ public class World inputState = playerFrame?.inputState ?? default; return playerFrame != null; } + + virtual public void UpdatePlayerInputState(uint playerId, ulong frame, PlayerInputState2 inputState, PlayerMovementState movementState) + { + IClientInfo player = GetClient(playerId); + + PlayerFrame playerFrame = player.FrameHistory[frame % 120]; + if (playerFrame.frame == frame) + { + playerFrame.inputState = inputState with + { + ViewDelta = playerFrame.inputState.ViewDelta + inputState.ViewDelta, + MoveForward = MathF.MaxMagnitude(playerFrame.inputState.MoveForward, inputState.MoveForward), + MoveRight = MathF.MaxMagnitude(playerFrame.inputState.MoveRight, inputState.MoveRight), + Attack = playerFrame.inputState.Attack || inputState.Attack, + Jump = playerFrame.inputState.Jump || inputState.Jump, + }; + } + else + playerFrame.inputState = inputState; + playerFrame.movementState = movementState; + playerFrame.frame = frame; + } } file class ServerWorld : World { + protected class ClientInfo : IClientInfo + { + public NetworkConnection Connection { get; set; } + public PlayerActor PlayerActor { get; set; } + public PlayerFrame[] FrameHistory { get; set; } = new PlayerFrame[120]; + public ulong LastReceivedFrame = 0; + public ulong LastSentDeltaFrame = 0; // TODO: Accumulate deltas since this frame + public int SendRate = 0; // How many updates the client wants to receive per second + + public ClientInfo() + { + for (int i = 0; i < FrameHistory.Length; i++) + FrameHistory[i] = new PlayerFrame(); + } + } + + protected Dictionary _clients = new(); + + protected override IClientInfo GetClient(uint playerId) => _clients[playerId]; + protected override void Init() { NetworkManager.RegisterServerCallbacks(OnMessage, OnClientConnecting, OnClientConnected); @@ -249,6 +304,12 @@ file class ServerWorld : World base.Cleanup(); } + protected override void OnLateUpdate() + { + Console.Print("server LateFixedUpdate"); + base.OnLateUpdate(); + } + public bool OnMessage(ref NetworkEvent networkEvent) { byte messageTypeByte = networkEvent.Message.ReadByte(); @@ -266,23 +327,9 @@ file class ServerWorld : World { case GameModeMessageType2.AcceptConnection: // Client { - AcceptConnectionMessage message = AcceptConnectionMessage.Read(ref networkEvent.Message); - Frame += message.Frame; - GameTime = message.GameTime; - ServerFrame = message.Frame; - - /*foreach (var player in message.Players) - { - SpawnPlayer(player.PlayerId, player.PlayerPosition, new Float3(0)); - - var playerFrames = new PlayerFrame[120]; - for (int j = 0; j < playerFrames.Length; j++) - playerFrames[j] = new PlayerFrame(); - clientWorldState.playerFrameHistory.Add(player.PlayerId, playerFrames); - }*/ + break; } - break; - case GameModeMessageType2.PlayerPosition: + case GameModeMessageType2.PlayerPosition: // FIXME: Should be the delta frame { //uint playerId = networkEvent.Sender.ConnectionId; PlayerInputState2 inputState; //? @@ -316,8 +363,40 @@ file class ServerWorld : World inputState.Jump = networkEvent.Message.ReadBoolean(); ServerFrame = receivedFrame; + break; + } + case GameModeMessageType2.PlayerInput: + { + PlayerInputState2 inputState; //? + + ulong receivedFrame = networkEvent.Message.ReadUInt64(); + uint reportedPlayerId = networkEvent.Message.ReadUInt32(); + inputState.Frame = receivedFrame; + inputState.ViewDelta.X = networkEvent.Message.ReadSingle(); + inputState.ViewDelta.Y = networkEvent.Message.ReadSingle(); + inputState.MoveForward = networkEvent.Message.ReadSingle(); + inputState.MoveRight = networkEvent.Message.ReadSingle(); + inputState.Attack = networkEvent.Message.ReadBoolean(); + inputState.Jump = networkEvent.Message.ReadBoolean(); + + Console.Print($"server receive client frame {receivedFrame}, current server frame {Frame}"); + var asdf = receivedFrame; + receivedFrame = Frame; + + if (inputState.MoveForward != 0) + receivedFrame = receivedFrame; + + + // Sanity check + if (GetPlayerInputState(reportedPlayerId, receivedFrame, out var prevInputState)) + { + Console.PrintWarning($"Duplicate frame received from client: {asdf}"); + } + + PlayerMovementState movementState = default; + UpdatePlayerInputState(reportedPlayerId, receivedFrame, inputState, movementState); + break; } - break; default: break; } @@ -346,11 +425,10 @@ file class ServerWorld : World return true; } - public new void OnClientConnected(NetworkConnection connection) + public void OnClientConnected(NetworkConnection connection) { - base.OnClientConnected(connection); uint playerId = connection.ConnectionId; - + _clients.Add(playerId, new ClientInfo() { Connection = connection }); var spawns = _worldSpawn.GetChildren().Where(x => x.Name.StartsWith("PlayerSpawn_")).ToArray(); Console.Print($"found {spawns.Length} spawns"); @@ -375,12 +453,44 @@ file class ServerWorld : World NetworkManager.ServerEndSendMessage(ref message, connection); } } + + public override void UpdatePlayerInputState(uint playerId, ulong frame, PlayerInputState2 inputState, PlayerMovementState movementState) + { + base.UpdatePlayerInputState(playerId, frame, inputState, movementState); + + ClientInfo player = GetClient(playerId) as ClientInfo; + player.LastReceivedFrame = frame; // Dropped frames should be ignored? + } + + protected override PlayerActor SpawnPlayer(uint playerId, Float3 position, Vector3 eulerAngles) + { + var playerActor = base.SpawnPlayer(playerId, position, eulerAngles); + playerActor.Input = new PlayerInputNetwork2(playerId, this); + return playerActor; + } } file class ClientWorld : World { + protected class ClientInfo : IClientInfo + { + public NetworkConnection Connection { get; set; } + public PlayerActor PlayerActor { get; set; } + public PlayerFrame[] FrameHistory { get; set; } = new PlayerFrame[120]; + + public ClientInfo() + { + for (int i = 0; i < FrameHistory.Length; i++) + FrameHistory[i] = new PlayerFrame(); + } + } + private uint _localPlayerId; + protected Dictionary _clients = new(); + + protected override IClientInfo GetClient(uint playerId) => _clients[playerId]; + protected override void Init() { NetworkManager.RegisterClientCallbacks(OnMessage, null, OnClientConnected); @@ -396,6 +506,44 @@ file class ClientWorld : World base.Cleanup(); } + override protected void OnLateUpdate() + { + foreach (var player in _scene.GetChildren()) + { + if (player.PlayerId != _localPlayerId) + continue; + + ClientInfo playerClient = GetClient(player.PlayerId) as ClientInfo; + PlayerInputState2 inputState = player.Input.GetState(); + PlayerMovementState movementState = player.GetScript().movementState; + + if (inputState.Frame == 0) + inputState = inputState; + /*public Float2 ViewDelta; + public float MoveForward; + public float MoveRight; + public bool Attack; + public bool Jump;*/ + + + Console.Print($"client send {Frame}"); + UpdatePlayerInputState(player.PlayerId, Frame, inputState, movementState); + //Console.Print($"cframe: {Frame}"); + + NetworkMessage message = NetworkManager.ClientBeginSendMessage(); + message.WriteByte((byte)GameModeMessageType2.PlayerInput); + message.WriteUInt64(Frame); + message.WriteUInt32(player.PlayerId); + message.WriteVector2(inputState.ViewDelta); + message.WriteSingle(inputState.MoveForward); + message.WriteSingle(inputState.MoveRight); + message.WriteBoolean(inputState.Attack); + message.WriteBoolean(inputState.Jump); + NetworkManager.ClientEndSendMessage(ref message); + } + base.OnLateUpdate(); + } + public bool OnMessage(ref NetworkEvent networkEvent) { byte messageTypeByte = networkEvent.Message.ReadByte(); @@ -426,8 +574,8 @@ file class ClientWorld : World } Console.Print("received welcome: frame " + ServerFrame); + break; } - break; case GameModeMessageType2.SpawnPlayer: { uint playerId = networkEvent.Message.ReadUInt32(); @@ -447,8 +595,8 @@ file class ClientWorld : World //if (NetworkManager.IsClient) //players[playerId].GetScript().Input.SetFrame(ClientFrame); + break; } - break; #if false case GameModeMessageType2.PlayerPosition: { @@ -484,8 +632,8 @@ file class ClientWorld : World inputState.Jump = networkEvent.Message.ReadBoolean(); ServerFrame = receivedFrame; + break; } - break; #endif default: break; @@ -496,10 +644,12 @@ file class ClientWorld : World public override bool IsLocalPlayer(uint playerId) => playerId == _localPlayerId; - public new void OnClientConnected(NetworkConnection connection) + public void OnClientConnected(NetworkConnection connection) { - base.OnClientConnected(connection); - _localPlayerId = connection.ConnectionId; + uint playerId = connection.ConnectionId; + _clients.Add(playerId, new ClientInfo() { Connection = connection }); + + _localPlayerId = playerId; Console.Print($"ClientWorld: Connected, playerId: {_localPlayerId}"); } diff --git a/Source/Game/Player/PlayerInput2.cs b/Source/Game/Player/PlayerInput2.cs index 9214644..3865d15 100644 --- a/Source/Game/Player/PlayerInput2.cs +++ b/Source/Game/Player/PlayerInput2.cs @@ -11,7 +11,7 @@ namespace Game; [StructLayout(LayoutKind.Sequential)] public struct PlayerInputState2 { - //public ulong frame; + public ulong Frame; public Float2 ViewDelta; public float MoveForward; public float MoveRight; @@ -53,8 +53,13 @@ public class PlayerInput2 : IPlayerInput [ConsoleVariable("sensitivity")] private static float _sensitivity { get; set; } = 1.0f; + private ulong _frame; + public void SetFrame(ulong frame) { + if (_frame != frame) + ResetState(); + _frame = frame; } public void UpdateState() @@ -74,6 +79,7 @@ public class PlayerInput2 : IPlayerInput _recordState.MoveRight = MathF.MaxMagnitude(_recordState.MoveRight, Input.GetAxis("Horizontal")); _recordState.Attack |= Input.GetAction("Attack"); _recordState.Jump |= Input.GetAction("Jump"); + _recordState.Frame = _frame; } public PlayerInputState2 GetState() => _recordState; diff --git a/Source/Game/Player/PlayerMovement.cs b/Source/Game/Player/PlayerMovement.cs index 5885659..3e5f964 100644 --- a/Source/Game/Player/PlayerMovement.cs +++ b/Source/Game/Player/PlayerMovement.cs @@ -252,12 +252,16 @@ public class PlayerMovement : Script public override void OnUpdate() { + Console.Print("playerMovement OnUpdate"); //input.OnUpdate(); //if (Input is PlayerInputDemo /*&& currentInputFrame2 >= currentInputFrame*/) // return; + if (World.IsServer) + viewAngles = viewAngles; + Input.SetFrame(World.Frame); Input.UpdateState(); @@ -311,13 +315,14 @@ public class PlayerMovement : Script public override void OnFixedUpdate() { + Console.Print("playerMovement OnFixedUpdate"); float timeDeltaDiff = Time.DeltaTime - 1.0f / Time.PhysicsFPS; if (Time.PhysicsFPS > 0 && Math.Abs(timeDeltaDiff) > 0.0001f) Console.Print("Time.DeltaTime is not stable: " + timeDeltaDiff); //Input.OnFixedUpdate(); PlayerInputState2 inputState = Input.GetState(); - bool predict = World.IsClient; + bool predict = World.IsClient && false; if (predict) { // Get the latest frame we have predicted @@ -962,7 +967,7 @@ public class PlayerMovement : Script if (capsuleCollider && capsuleCollider.IsActive) { Quaternion rotation = capsuleCollider.LocalOrientation * Quaternion.Euler(0f, 90f, 0f); - DebugDraw.DrawWireTube(capsuleCollider.Position, rotation, capsuleCollider.Radius, + DebugDraw.DrawWireCapsule(capsuleCollider.Position, rotation, capsuleCollider.Radius, capsuleCollider.Height, Color.GreenYellow * 0.8f); } else if (meshCollider && meshCollider.IsActive) @@ -970,7 +975,7 @@ public class PlayerMovement : Script //Quaternion rotation = meshCollider.LocalOrientation * Quaternion.Euler(0f, 90f, 0f); DebugDraw.DrawWireCylinder(meshCollider.Position, meshCollider.Orientation, capsuleCollider.Radius, capsuleCollider.Height + capsuleCollider.Radius * 2, Color.GreenYellow * 0.8f); - //DebugDraw.DrawWireTube(meshCollider.Position, rotation, meshCollider.Radius, meshCollider.Height, Color.GreenYellow * 0.8f); + //DebugDraw.DrawWireCapsule(meshCollider.Position, rotation, meshCollider.Radius, meshCollider.Height, Color.GreenYellow * 0.8f); } else if (boxCollider && boxCollider.IsActive) {