using System; using System.Collections.Generic; using System.IO; using System.Runtime.InteropServices; using FlaxEngine; using Console = Game.Console; namespace Game { public class PlayerInputLocal : PlayerInput { protected List buffer = new List(); protected FileStream demoFileStream; public bool IsNetworked => NetworkManager.client != null; public PlayerInputLocal() { } public PlayerInputLocal(string demoPath) { demoFileStream = File.Open(demoPath, FileMode.Create, FileAccess.Write); //stream.Position = 0; //stream.SetLength(0); demoFileStream.WriteByte(DemoVer); demoFileStream.WriteByte((byte)Marshal.SizeOf(typeof(PlayerInputState))); } public bool IsRecording => demoFileStream != null; public override void OnUpdate() { // Collect all input here // All axis values here should be accumulated float sensitivity = 1.0f / 8.0f; sensitivity = 1.0f; //var asf = InputManager.GetAxisRaw("Mouse X"); //if (asf != 0.0f) // Console.Print(InputManager.GetAxisRaw("Mouse X").ToString("G9", System.Globalization.CultureInfo.InvariantCulture)); currentState.input.viewDeltaX += InputManager.GetAxisRaw("Mouse X") * sensitivity; currentState.input.viewDeltaY += InputManager.GetAxisRaw("Mouse Y") * sensitivity; currentState.input.viewDeltaX += InputManager.GetAxisRaw("LookRight") * Time.DeltaTime * 100; currentState.input.viewDeltaY += -InputManager.GetAxisRaw("LookUp") * Time.DeltaTime * 100; currentState.input.moveForward = InputManager.GetAxis("Vertical"); currentState.input.moveRight = InputManager.GetAxis("Horizontal"); currentState.input.attacking = InputManager.GetAction("Attack"); currentState.input.jumping = InputManager.GetAction("Jump"); } public override void OnFixedUpdate() { } public override void OnEndFrame() { if (IsRecording) { currentState.input.verificationPosition = currentState.actor.position; currentState.input.verificationVelocity = currentState.actor.velocity; currentState.input.verificationViewAngles = currentState.actor.viewAngles; currentState.input.verificationOrientation = currentState.actor.orientation; currentState.input.frame = frame; buffer.Add(currentState.input); } if (IsNetworked) { var message = NetworkManager.ClientBeginSendMessage(); message.WriteByte((byte)GameModeMessageType.PlayerInput); message.WriteUInt64(currentState.input.frame); message.WriteSingle(currentState.input.viewDeltaX); message.WriteSingle(currentState.input.viewDeltaY); message.WriteSingle(currentState.input.moveForward); message.WriteSingle(currentState.input.moveRight); message.WriteBoolean(currentState.input.attacking); message.WriteBoolean(currentState.input.jumping); NetworkManager.ClientEndSendMessage(ref message); } // Reset anything accumulatable here currentState.input.viewDeltaX = 0; currentState.input.viewDeltaY = 0; frame++; } public override void RecordCurrentActorState(PlayerActorState actorState) { if (!IsRecording) return; if (actorState.position.Length <= 0.01) Console.Print("wrong recorded position?"); currentState.actor = actorState; } public void FlushDemo() { if (!IsRecording) return; byte[] RawSerialize(object anything) { int rawSize = Marshal.SizeOf(anything); IntPtr buffer = Marshal.AllocHGlobal(rawSize); Marshal.StructureToPtr(anything, buffer, false); byte[] rawDatas = new byte[rawSize]; Marshal.Copy(buffer, rawDatas, 0, rawSize); Marshal.FreeHGlobal(buffer); return rawDatas; } foreach (PlayerInputState state in buffer) { byte[] bytes = RawSerialize(state); demoFileStream.Write(bytes, 0, bytes.Length * sizeof(byte)); } buffer.Clear(); } public void StopRecording() { if (!IsRecording) return; FlushDemo(); demoFileStream.Close(); demoFileStream = null; Debug.Write(LogType.Info, "demo, wrote states: " + buffer.Count); } } }