diff --git a/Source/Game/Console/EngineSubsystem.cs b/Source/Game/Console/EngineSubsystem.cs index 8419109..3ca2b1c 100644 --- a/Source/Game/Console/EngineSubsystem.cs +++ b/Source/Game/Console/EngineSubsystem.cs @@ -1,5 +1,6 @@ using System; using System.IO; +using System.Linq; using FidelityFX; using FlaxEngine; @@ -239,6 +240,73 @@ namespace Game } } + [ConsoleCommand("playdemo")] + public static void PlayDemoCommand(string[] text) + { + if (text.Length < 1) + return; + string demoName = text[0]; + + if (!demoName.EndsWith(".gdem")) + demoName += ".gdem"; + + PlayerActor playerActor = Level.GetActors().First(x => + x.GetScript().PlayerId == NetworkManager.LocalPlayerClientId); + + string demoPath = Path.Combine(AssetManager.DemoPath, demoName); + if (File.Exists(demoPath)) + playerActor.GetScript().SetInput(demoPath); + } + + [ConsoleCommand("timedemo")] + public static void TimeDemoCommand(string[] text) + { + if (text.Length < 1) + return; + string demoName = text[0]; + + if (!demoName.EndsWith(".gdem")) + demoName += ".gdem"; + + PlayerActor playerActor = Level.GetActors().First(x => + x.GetScript().PlayerId == NetworkManager.LocalPlayerClientId); + + var playerMovement = playerActor.GetScript(); + string demoPath = Path.Combine(AssetManager.DemoPath, demoName); + if (File.Exists(demoPath)) + playerMovement.SetInput(demoPath); + + Action onUpdate = () => {}; + //bool lastPlaying = true; + float accumTime = 0f; + int accumTimes = 0; + onUpdate = () => + { + if (playerMovement) + { + var input = playerMovement.input as PlayerInputDemo; + if (input != null) + { + if (!input.IsPlaying) + { + Console.Print($"demo ended, time: {accumTimes} frames, avg: {(accumTime/(float)accumTimes)*1000.0f}"); + Scripting.Update -= onUpdate; + return; + } + + if (accumTimes == 0) + Console.Print($"timedemo started"); + + accumTime += Time.DeltaTime; + accumTimes++; + //input.IsPlaying + } + } + }; + + Scripting.Update += onUpdate; + } + [ConsoleSubsystemInitializer] public static void Initialize() { diff --git a/Source/Game/Player/PlayerInputDemo.cs b/Source/Game/Player/PlayerInputDemo.cs index 8db8e32..2f95433 100644 --- a/Source/Game/Player/PlayerInputDemo.cs +++ b/Source/Game/Player/PlayerInputDemo.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.IO; +using System.IO.Compression; using System.Linq; using System.Runtime.InteropServices; using Console = Game.Console; @@ -12,6 +13,14 @@ namespace Game protected List buffer = new List(); protected IEnumerator bufferEnumerable; + public bool IsPlaying + { + get + { + return bufferEnumerable != null; + } + } + public PlayerInputDemo(string demoPath) { if (!File.Exists(demoPath)) @@ -19,7 +28,9 @@ namespace Game int expectedPlayerInputStateSize = Marshal.SizeOf(typeof(PlayerInputState)); - FileStream stream = File.OpenRead(demoPath); + FileStream fileStream = File.OpenRead(demoPath); + GZipStream stream = new GZipStream(fileStream, CompressionMode.Decompress); + int ver = stream.ReadByte(); int inputStateSize = stream.ReadByte(); if (ver != DemoVer && inputStateSize != expectedPlayerInputStateSize) @@ -30,6 +41,8 @@ namespace Game return; } + // TODO: bench and compare to unsafe ptr version of this: + // https://stackoverflow.com/questions/17549123/c-sharp-performance-using-unsafe-pointers-instead-of-intptr-and-marshal/29836312#29836312 T RawDeserialize(byte[] rawData, int position) { int rawsize = Marshal.SizeOf(typeof(T)); diff --git a/Source/Game/Player/PlayerInputLocal.cs b/Source/Game/Player/PlayerInputLocal.cs index 0572f77..3405181 100644 --- a/Source/Game/Player/PlayerInputLocal.cs +++ b/Source/Game/Player/PlayerInputLocal.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.IO; +using System.IO.Compression; using System.Runtime.InteropServices; using FlaxEngine; using Console = Game.Console; @@ -10,7 +11,8 @@ namespace Game public class PlayerInputLocal : PlayerInput { protected List buffer = new List(); - protected FileStream demoFileStream; + protected GZipStream demoFileStream; + protected FileStream demoFileStream2; public bool IsNetworked => NetworkManager.client != null; @@ -20,7 +22,12 @@ namespace Game public PlayerInputLocal(string demoPath) { - demoFileStream = File.Open(demoPath, FileMode.Create, FileAccess.Write); + var demoFolder = Directory.GetParent(demoPath); + if (!demoFolder.Exists) + Directory.CreateDirectory(demoFolder.FullName); + + demoFileStream2 = File.Open(demoPath, FileMode.Create, FileAccess.Write); + demoFileStream = new GZipStream(demoFileStream2, CompressionMode.Compress); //stream.Position = 0; //stream.SetLength(0); demoFileStream.WriteByte(DemoVer);