using System.Runtime.InteropServices; using FlaxEngine; using FlaxEngine.Networking; namespace Game; [StructLayout(LayoutKind.Sequential)] public struct PlayerInputState { /*static PlayerInputState() { NetworkReplicator.AddSerializer(typeof(PlayerInputState), (ptr, streamPtr) => { }, (ptr, streamPtr) => { }); }*/ #if false public PlayerInputState(ulong frame, float viewDeltaX, float viewDeltaY, float moveForward, float moveRight, bool attacking, bool jumping) { this.frame = frame; this.viewDeltaX = viewDeltaX; this.viewDeltaY = viewDeltaY; this.moveForward = moveForward; this.moveRight = moveRight; this.attacking = attacking; this.jumping = jumping; /*this.verificationPosition = verificationPosition; this.verificationVelocity = verificationVelocity; this.verificationViewAngles = verificationViewAngles; this.verificationOrientation = verificationOrientation;*/ } public PlayerInputState(ulong frame, float viewDeltaX, float viewDeltaY, float moveForward, float moveRight, bool attacking, bool jumping, Float3 verificationPosition, Float3 verificationVelocity, Float3 verificationViewAngles, Quaternion verificationOrientation) { this.frame = frame; this.viewDeltaX = viewDeltaX; this.viewDeltaY = viewDeltaY; this.moveForward = moveForward; this.moveRight = moveRight; this.attacking = attacking; this.jumping = jumping; this.verificationPosition = verificationPosition; this.verificationVelocity = verificationVelocity; this.verificationViewAngles = verificationViewAngles; this.verificationOrientation = verificationOrientation; } #endif public ulong frame; public float viewDeltaX, viewDeltaY; public float moveForward; public float moveRight; public bool attacking; public bool jumping; public Float3 verificationPosition; public Float3 verificationVelocity; public Float3 verificationViewAngles; public Quaternion verificationOrientation; } [StructLayout(LayoutKind.Sequential)] public struct PlayerActorState { public Float3 position; public Float3 velocity; public Quaternion orientation; public Float3 viewAngles; // yaw, pitch, roll public float lastJumpTime; public int numJumps; public bool jumped; } [StructLayout(LayoutKind.Sequential)] public struct PlayerState { public PlayerInputState input; public PlayerActorState actor; } public class PlayerInput { public const byte DemoVer = 1; public const int MaxPlayerStates = 120; public PlayerState currentState; public ulong frame; //public ulong oldestFrame; private PlayerState[] states = new PlayerState[MaxPlayerStates]; public virtual bool Predict => false; public virtual void OnUpdate() { } public virtual void OnFixedUpdate() { } public virtual void OnEndFrame() { //Console.Print("recorded frame " + frame); states[frame % MaxPlayerStates] = currentState; /*ulong oldest = ulong.MaxValue; for (int i = 0; i < 120; i++) oldest = states[i].input.frame < oldest ? states[i].input.frame : oldest; oldestFrame = oldest;*/ frame++; currentState.input.frame = frame; } public virtual void RecordCurrentActorState(PlayerActorState actorState) { if (actorState.position.Length <= 0.01) Console.Print("wrong recorded position?"); currentState.actor = actorState; } public bool GetState(ulong frame, out PlayerInputState inputState, out PlayerActorState actorState) { int frameIndex = (int)frame % MaxPlayerStates; if (states[frameIndex].input.frame != frame) { inputState = default; actorState = default; return false; } inputState = states[frameIndex].input; actorState = states[frameIndex].actor; return true; } public void SetState(ulong frame, PlayerInputState inputState) { int frameIndex = (int)frame % MaxPlayerStates; states[frameIndex].input = inputState; states[frameIndex].input.frame = frame; states[frameIndex].actor = new PlayerActorState(); } public void SetState(ulong frame, PlayerInputState inputState, PlayerActorState actorState) { int frameIndex = (int)frame % MaxPlayerStates; states[frameIndex].input = inputState; states[frameIndex].input.frame = frame; states[frameIndex].actor = actorState; } public PlayerInputState GetCurrentInputState() { return currentState.input; } public PlayerActorState GetCurrentActorState() { return currentState.actor; } }