networking progress
This commit is contained in:
@@ -4965,3 +4965,9 @@
|
|||||||
"origin" "160 40 504"
|
"origin" "160 40 504"
|
||||||
"targetname" "light_target1"
|
"targetname" "light_target1"
|
||||||
}
|
}
|
||||||
|
// entity 74
|
||||||
|
{
|
||||||
|
"classname" "info_player_deathmatch"
|
||||||
|
"origin" "-496 -304 152"
|
||||||
|
"angle" "180"
|
||||||
|
}
|
||||||
|
|||||||
@@ -9,19 +9,6 @@
|
|||||||
"V": {},
|
"V": {},
|
||||||
"IsActive": false,
|
"IsActive": false,
|
||||||
"Name": "PlayerPrefab",
|
"Name": "PlayerPrefab",
|
||||||
"Transform": {
|
|
||||||
"Translation": {
|
|
||||||
"X": 73.19660949707031,
|
|
||||||
"Y": -33.01502227783203,
|
|
||||||
"Z": -139.43125915527345
|
|
||||||
},
|
|
||||||
"Orientation": {
|
|
||||||
"X": 0.0,
|
|
||||||
"Y": 1.0,
|
|
||||||
"Z": 0.0,
|
|
||||||
"W": -4.371138828673793e-8
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"StaticFlags": 0,
|
"StaticFlags": 0,
|
||||||
"OverrideMass": true,
|
"OverrideMass": true,
|
||||||
"Mass": 10.0
|
"Mass": 10.0
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"ID": "3c7bc3854d42f9b1b0fea9ba0d7fa8e9",
|
"ID": "3c7bc3854d42f9b1b0fea9ba0d7fa8e9",
|
||||||
"TypeName": "FlaxEditor.Content.Settings.GameSettings",
|
"TypeName": "FlaxEditor.Content.Settings.GameSettings",
|
||||||
"EngineBuild": 6335,
|
"EngineBuild": 6340,
|
||||||
"Data": {
|
"Data": {
|
||||||
"ProductName": "Goake",
|
"ProductName": "Goake",
|
||||||
"CompanyName": "GoaLitiuM",
|
"CompanyName": "GoaLitiuM",
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
@@ -49,13 +49,13 @@
|
|||||||
"ParentID": "ff6b6db54b5aa08e7286ef86246149ef",
|
"ParentID": "ff6b6db54b5aa08e7286ef86246149ef",
|
||||||
"Transform": {
|
"Transform": {
|
||||||
"Translation": {
|
"Translation": {
|
||||||
"X": 1841.0,
|
"X": 1355.0,
|
||||||
"Y": 972.0,
|
"Y": 791.0,
|
||||||
"Z": 0.0
|
"Z": 0.0
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"Data": {
|
"Data": {
|
||||||
"Text": "1302 tris\n 131 drawcalls\n434fps2\n1921fps"
|
"Text": "13022 tris\n 102 drawcalls\n238fps2\n240fps"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"ID": "af2e52554f7faed7b4937181dd22d166",
|
"ID": "af2e52554f7faed7b4937181dd22d166",
|
||||||
"TypeName": "FlaxEditor.Content.Settings.BuildSettings",
|
"TypeName": "FlaxEditor.Content.Settings.BuildSettings",
|
||||||
"EngineBuild": 6332,
|
"EngineBuild": 6340,
|
||||||
"Data": {
|
"Data": {
|
||||||
"MaxAssetsPerPackage": 4096,
|
"MaxAssetsPerPackage": 4096,
|
||||||
"MaxPackageSizeMB": 1024,
|
"MaxPackageSizeMB": 1024,
|
||||||
@@ -9,6 +9,7 @@
|
|||||||
"ForDistribution": false,
|
"ForDistribution": false,
|
||||||
"SkipPackaging": false,
|
"SkipPackaging": false,
|
||||||
"AdditionalAssets": [],
|
"AdditionalAssets": [],
|
||||||
|
"AdditionalScenes": null,
|
||||||
"AdditionalAssetFolders": [
|
"AdditionalAssetFolders": [
|
||||||
"Content/Materials",
|
"Content/Materials",
|
||||||
"Content/Textures",
|
"Content/Textures",
|
||||||
@@ -17,6 +18,7 @@
|
|||||||
],
|
],
|
||||||
"ShadersNoOptimize": false,
|
"ShadersNoOptimize": false,
|
||||||
"ShadersGenerateDebugData": false,
|
"ShadersGenerateDebugData": false,
|
||||||
|
"SkipDotnetPackaging": true,
|
||||||
"Presets": [
|
"Presets": [
|
||||||
{
|
{
|
||||||
"Name": "Preset 3",
|
"Name": "Preset 3",
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -7,6 +7,6 @@ StaticallyLinkedBinaryModuleInitializer StaticallyLinkedBinaryModuleGame(GetBina
|
|||||||
|
|
||||||
extern "C" BinaryModule* GetBinaryModuleGame()
|
extern "C" BinaryModule* GetBinaryModuleGame()
|
||||||
{
|
{
|
||||||
static NativeBinaryModule module("Game", MAssemblyOptions());
|
static NativeBinaryModule module("Game");
|
||||||
return &module;
|
return &module;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,12 +3,13 @@ using System.Collections.Generic;
|
|||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
using FlaxEditor;
|
using FlaxEditor;
|
||||||
using FlaxEngine;
|
using FlaxEngine;
|
||||||
|
|
||||||
namespace Game
|
namespace Game
|
||||||
{
|
{
|
||||||
public class ConsoleLine
|
public struct ConsoleLine
|
||||||
{
|
{
|
||||||
public string content;
|
public string content;
|
||||||
|
|
||||||
@@ -75,7 +76,7 @@ namespace Game
|
|||||||
|
|
||||||
public static string LinePrefix => instance.LinePrefix;
|
public static string LinePrefix => instance.LinePrefix;
|
||||||
|
|
||||||
public static IReadOnlyCollection<ConsoleLine> Lines => instance.Lines;
|
public static ReadOnlySpan<ConsoleLine> Lines => instance.Lines;
|
||||||
|
|
||||||
public static void Init()
|
public static void Init()
|
||||||
{
|
{
|
||||||
@@ -220,7 +221,7 @@ namespace Game
|
|||||||
public int DebugVerbosity { get; set; } = 1;
|
public int DebugVerbosity { get; set; } = 1;
|
||||||
public string LinePrefix { get; internal set; } = "]";
|
public string LinePrefix { get; internal set; } = "]";
|
||||||
|
|
||||||
public IReadOnlyCollection<ConsoleLine> Lines => consoleLines.AsReadOnly();
|
public ReadOnlySpan<ConsoleLine> Lines => CollectionsMarshal.AsSpan(consoleLines);
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
@@ -380,23 +381,14 @@ namespace Game
|
|||||||
{
|
{
|
||||||
debugLastLine = text;
|
debugLastLine = text;
|
||||||
|
|
||||||
foreach (string line in text.Split('\n'))
|
PrintLine(text);
|
||||||
{
|
|
||||||
ConsoleLine lineEntry = new ConsoleLine(line);
|
|
||||||
consoleLines.Add(lineEntry);
|
|
||||||
OnPrint?.Invoke(text);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Echoes warning text to Console
|
// Echoes warning text to Console
|
||||||
public void PrintWarning(string text)
|
public void PrintWarning(string text)
|
||||||
{
|
{
|
||||||
foreach (string line in text.Split('\n'))
|
PrintLine(text);
|
||||||
{
|
|
||||||
ConsoleLine lineEntry = new ConsoleLine(line);
|
|
||||||
consoleLines.Add(lineEntry);
|
|
||||||
OnPrint?.Invoke(text);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Echoes error text to Console
|
// Echoes error text to Console
|
||||||
@@ -404,17 +396,32 @@ namespace Game
|
|||||||
[DebuggerHidden]
|
[DebuggerHidden]
|
||||||
public void PrintError(string text)
|
public void PrintError(string text)
|
||||||
{
|
{
|
||||||
|
PrintLine(text);
|
||||||
|
|
||||||
|
/*if (Debugger.IsAttached)
|
||||||
|
Debugger.Break();
|
||||||
|
else*/
|
||||||
|
throw new Exception(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void PrintLine(string text)
|
||||||
|
{
|
||||||
|
if (text.IndexOf('\n') != -1)
|
||||||
|
{
|
||||||
|
// Avoid generating extra garbage in single-line cases
|
||||||
foreach (string line in text.Split('\n'))
|
foreach (string line in text.Split('\n'))
|
||||||
{
|
{
|
||||||
ConsoleLine lineEntry = new ConsoleLine(line);
|
ConsoleLine lineEntry = new ConsoleLine(line);
|
||||||
consoleLines.Add(lineEntry);
|
consoleLines.Add(lineEntry);
|
||||||
OnPrint?.Invoke(text);
|
OnPrint?.Invoke(text);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
/*if (Debugger.IsAttached)
|
else
|
||||||
Debugger.Break();
|
{
|
||||||
else*/
|
ConsoleLine lineEntry = new ConsoleLine(text);
|
||||||
throw new Exception(text);
|
consoleLines.Add(lineEntry);
|
||||||
|
OnPrint?.Invoke(text);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void PrintDebug(int verbosity, bool noRepeat, string text)
|
public void PrintDebug(int verbosity, bool noRepeat, string text)
|
||||||
@@ -428,12 +435,7 @@ namespace Game
|
|||||||
|
|
||||||
debugLastLine = text;
|
debugLastLine = text;
|
||||||
|
|
||||||
foreach (string line in text.Split('\n'))
|
PrintLine(text);
|
||||||
{
|
|
||||||
ConsoleLine lineEntry = new ConsoleLine(line);
|
|
||||||
consoleLines.Add(lineEntry);
|
|
||||||
OnPrint?.Invoke(text);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Opens the Console
|
// Opens the Console
|
||||||
|
|||||||
@@ -127,7 +127,7 @@ namespace Game
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void CalculateVisibleLines(IReadOnlyCollection<ConsoleLine> lines, out int firstVisibleLine,
|
private void CalculateVisibleLines(ReadOnlySpan<ConsoleLine> lines, out int firstVisibleLine,
|
||||||
out int lastVisibleLine, out LineInfo[] wrappedLines)
|
out int lastVisibleLine, out LineInfo[] wrappedLines)
|
||||||
{
|
{
|
||||||
wrappedLines = null;
|
wrappedLines = null;
|
||||||
@@ -142,18 +142,21 @@ namespace Game
|
|||||||
int lineMaxChars = (int)(Width / fontWidth);
|
int lineMaxChars = (int)(Width / fontWidth);
|
||||||
int lineMaxLines = GetHeightInLines();
|
int lineMaxLines = GetHeightInLines();
|
||||||
int numLines = 0;
|
int numLines = 0;
|
||||||
int lineIndex = lines.Count;
|
|
||||||
var lineInfos = new List<LineInfo>(lineMaxLines + 1);
|
var lineInfos = new List<LineInfo>(lineMaxLines + 1);
|
||||||
int linesSkipped = 0;
|
int linesSkipped = 0;
|
||||||
foreach (string line in lines.Reverse())
|
//foreach (string line in lines.Reverse())
|
||||||
|
int lineIndex = lines.Length - 1;
|
||||||
|
for (; lineIndex >= 0; lineIndex--)
|
||||||
{
|
{
|
||||||
lineIndex--;
|
//lineIndex--;
|
||||||
if (linesSkipped < ScrollOffset)
|
if (linesSkipped < ScrollOffset)
|
||||||
{
|
{
|
||||||
linesSkipped++;
|
linesSkipped++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
string line = lines[lineIndex];
|
||||||
|
|
||||||
int numChars = 0;
|
int numChars = 0;
|
||||||
int startIndex = lineInfos.Count;
|
int startIndex = lineInfos.Count;
|
||||||
while (numChars < line.Length)
|
while (numChars < line.Length)
|
||||||
@@ -207,7 +210,7 @@ namespace Game
|
|||||||
Profiler.BeginEvent("ConsoleContentTextBoxDraw_FetchLines");
|
Profiler.BeginEvent("ConsoleContentTextBoxDraw_FetchLines");
|
||||||
var lines = Console.Lines;
|
var lines = Console.Lines;
|
||||||
Profiler.EndEvent();
|
Profiler.EndEvent();
|
||||||
if (lines.Count > 0)
|
if (lines.Length > 0)
|
||||||
{
|
{
|
||||||
Profiler.BeginEvent("ConsoleContentTextBoxDraw_Lines");
|
Profiler.BeginEvent("ConsoleContentTextBoxDraw_Lines");
|
||||||
|
|
||||||
@@ -253,7 +256,7 @@ namespace Game
|
|||||||
foreach (LineInfo li in wrappedLines)
|
foreach (LineInfo li in wrappedLines)
|
||||||
{
|
{
|
||||||
int lineIndex = li.lineIndex;
|
int lineIndex = li.lineIndex;
|
||||||
string fullLine = lines.ElementAt(lineIndex);
|
string fullLine = lines[lineIndex];
|
||||||
string line = fullLine.Substring(li.lineOffset, li.lineLength);
|
string line = fullLine.Substring(li.lineOffset, li.lineLength);
|
||||||
|
|
||||||
int leftChar = selectionLeftChar;
|
int leftChar = selectionLeftChar;
|
||||||
@@ -330,7 +333,7 @@ namespace Game
|
|||||||
foreach (LineInfo li in wrappedLines)
|
foreach (LineInfo li in wrappedLines)
|
||||||
{
|
{
|
||||||
int lineIndex = li.lineIndex;
|
int lineIndex = li.lineIndex;
|
||||||
string line = lines.ElementAt(lineIndex).content.Substring(li.lineOffset, li.lineLength);
|
string line = lines[lineIndex].content.Substring(li.lineOffset, li.lineLength);
|
||||||
Render2D.DrawText(font, line, TextColor, ref layout);
|
Render2D.DrawText(font, line, TextColor, ref layout);
|
||||||
layout.Bounds.Y += lineHeight;
|
layout.Bounds.Y += lineHeight;
|
||||||
}
|
}
|
||||||
@@ -405,7 +408,7 @@ namespace Game
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
hitLine = wrappedLines[hitWrappedLine].lineIndex;
|
hitLine = wrappedLines[hitWrappedLine].lineIndex;
|
||||||
string line = lines.ElementAt(hitLine).content.Substring(wrappedLines[hitWrappedLine].lineOffset,
|
string line = lines[hitLine].content.Substring(wrappedLines[hitWrappedLine].lineOffset,
|
||||||
wrappedLines[hitWrappedLine].lineLength);
|
wrappedLines[hitWrappedLine].lineLength);
|
||||||
|
|
||||||
layout.Bounds.Y = top + hitWrappedLine * lineHeight;
|
layout.Bounds.Y = top + hitWrappedLine * lineHeight;
|
||||||
@@ -447,7 +450,7 @@ namespace Game
|
|||||||
ScrollOffset += GetHeightInLines() / 2;
|
ScrollOffset += GetHeightInLines() / 2;
|
||||||
// should count the wrapped line count here over Console.Lines.Count
|
// should count the wrapped line count here over Console.Lines.Count
|
||||||
//var maxOffset = Console.Lines.Count - GetHeightInLines();
|
//var maxOffset = Console.Lines.Count - GetHeightInLines();
|
||||||
int maxOffset = Console.Lines.Count - 1;
|
int maxOffset = Console.Lines.Length - 1;
|
||||||
if (ScrollOffset > maxOffset)
|
if (ScrollOffset > maxOffset)
|
||||||
ScrollOffset = maxOffset;
|
ScrollOffset = maxOffset;
|
||||||
}
|
}
|
||||||
@@ -477,7 +480,7 @@ namespace Game
|
|||||||
else if (delta > 0)
|
else if (delta > 0)
|
||||||
{
|
{
|
||||||
ScrollOffset += ScrollMouseLines;
|
ScrollOffset += ScrollMouseLines;
|
||||||
int maxOffset = Console.Lines.Count - GetHeightInLines();
|
int maxOffset = Console.Lines.Length - GetHeightInLines();
|
||||||
if (ScrollOffset > maxOffset)
|
if (ScrollOffset > maxOffset)
|
||||||
ScrollOffset = maxOffset;
|
ScrollOffset = maxOffset;
|
||||||
}
|
}
|
||||||
@@ -497,7 +500,7 @@ namespace Game
|
|||||||
ret = true;
|
ret = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (button == MouseButton.Left && Console.Lines.Count > 0)
|
if (button == MouseButton.Left && Console.Lines.Length > 0)
|
||||||
{
|
{
|
||||||
bool selectionStarted = !selectionActive;
|
bool selectionStarted = !selectionActive;
|
||||||
Focus();
|
Focus();
|
||||||
@@ -614,7 +617,7 @@ namespace Game
|
|||||||
selectedText.AppendLine();
|
selectedText.AppendLine();
|
||||||
lastLineIndex = lineIndex;
|
lastLineIndex = lineIndex;
|
||||||
|
|
||||||
string fullLine = lines.ElementAt(lineIndex);
|
string fullLine = lines[lineIndex];
|
||||||
string line = fullLine.Substring(li.lineOffset, li.lineLength);
|
string line = fullLine.Substring(li.lineOffset, li.lineLength);
|
||||||
|
|
||||||
int leftChar = selectionLeftChar;
|
int leftChar = selectionLeftChar;
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ namespace Game
|
|||||||
//AssetManager.Init(); // TODO: move these elsewhere
|
//AssetManager.Init(); // TODO: move these elsewhere
|
||||||
#if !FLAX_EDITOR
|
#if !FLAX_EDITOR
|
||||||
Level.SceneLoading += OnSceneLoading;
|
Level.SceneLoading += OnSceneLoading;
|
||||||
|
Level.SceneLoaded += OnSceneLoaded;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -32,6 +33,7 @@ namespace Game
|
|||||||
{
|
{
|
||||||
#if !FLAX_EDITOR
|
#if !FLAX_EDITOR
|
||||||
Level.SceneLoading -= OnSceneLoading;
|
Level.SceneLoading -= OnSceneLoading;
|
||||||
|
Level.SceneLoaded -= OnSceneLoaded;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -41,6 +43,19 @@ namespace Game
|
|||||||
LoadConfig();
|
LoadConfig();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void OnSceneLoaded(Scene scene, Guid guid)
|
||||||
|
{
|
||||||
|
Level.SceneLoaded -= OnSceneLoaded;
|
||||||
|
#if !FLAX_EDITOR
|
||||||
|
|
||||||
|
//GameMode.Connect();
|
||||||
|
//GameMode.StartServer(true);
|
||||||
|
//NetworkManager.StartServer();
|
||||||
|
GameModeManager.Init();
|
||||||
|
NetworkManager.ConnectServer();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
private void LoadConfig()
|
private void LoadConfig()
|
||||||
{
|
{
|
||||||
Console.Print("Loading config file (GamePlugin)");
|
Console.Print("Loading config file (GamePlugin)");
|
||||||
@@ -101,12 +116,16 @@ namespace Game
|
|||||||
{
|
{
|
||||||
//FlaxEditor.Editor.Instance.PlayModeBegin -= Instance_PlayModeBegin;
|
//FlaxEditor.Editor.Instance.PlayModeBegin -= Instance_PlayModeBegin;
|
||||||
LoadConfig();
|
LoadConfig();
|
||||||
GameMode.StartServer(true);
|
//GameMode.Connect();
|
||||||
|
GameModeManager.Init();
|
||||||
|
NetworkManager.StartServer();
|
||||||
|
//GameMode.StartServer(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnPlayModeEnd()
|
private void OnPlayModeEnd()
|
||||||
{
|
{
|
||||||
GameMode.StopServer();
|
//GameMode.StopServer();
|
||||||
|
NetworkManager.Cleanup();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Deinitialize()
|
public override void Deinitialize()
|
||||||
|
|||||||
@@ -30,6 +30,8 @@ namespace Game
|
|||||||
|
|
||||||
private UIControl rootControl;
|
private UIControl rootControl;
|
||||||
|
|
||||||
|
private int fontHeight;
|
||||||
|
|
||||||
public override void OnStart()
|
public override void OnStart()
|
||||||
{
|
{
|
||||||
consoleInputEvent = new InputEvent("Console");
|
consoleInputEvent = new InputEvent("Console");
|
||||||
@@ -37,8 +39,7 @@ namespace Game
|
|||||||
|
|
||||||
FontReference fontReference = new FontReference(ConsoleFont, ConsoleFontSize);
|
FontReference fontReference = new FontReference(ConsoleFont, ConsoleFontSize);
|
||||||
Font fontRaw = fontReference.GetFont();
|
Font fontRaw = fontReference.GetFont();
|
||||||
int fontHeight = (int)(fontRaw.Height / Platform.DpiScale);
|
fontHeight = (int)(fontRaw.Height / Platform.DpiScale);
|
||||||
|
|
||||||
// root actor which holds all the elements
|
// root actor which holds all the elements
|
||||||
//var rootContainerControl = new ContainerControl(new Rectangle(0, 0, screenSize.X, screenSize.Y));
|
//var rootContainerControl = new ContainerControl(new Rectangle(0, 0, screenSize.X, screenSize.Y));
|
||||||
ContainerControl rootContainerControl = new ContainerControl(new Rectangle());
|
ContainerControl rootContainerControl = new ContainerControl(new Rectangle());
|
||||||
@@ -222,6 +223,7 @@ namespace Game
|
|||||||
Debug.Logger.LogHandler.SendLog += OnSendLog;
|
Debug.Logger.LogHandler.SendLog += OnSendLog;
|
||||||
Debug.Logger.LogHandler.SendExceptionLog += OnSendExceptionLog;
|
Debug.Logger.LogHandler.SendExceptionLog += OnSendExceptionLog;
|
||||||
|
|
||||||
|
|
||||||
Console.OnOpen += OnConsoleOpen;
|
Console.OnOpen += OnConsoleOpen;
|
||||||
Console.OnClose += OnConsoleClose;
|
Console.OnClose += OnConsoleClose;
|
||||||
Console.OnPrint += OnPrint;
|
Console.OnPrint += OnPrint;
|
||||||
@@ -254,7 +256,7 @@ namespace Game
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Console.Print("[EXCEP] " + exception.Message);
|
Console.Print("[EXCEP] " + exception.ToString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -374,7 +376,6 @@ namespace Game
|
|||||||
}
|
}
|
||||||
else if (!Console.IsOpen)
|
else if (!Console.IsOpen)
|
||||||
{
|
{
|
||||||
int fontHeight = (int)(consoleNotifyBox.FontHeight / Platform.DpiScale);
|
|
||||||
if (location.Y < -conHeight * ConsoleHeight + fontHeight)
|
if (location.Y < -conHeight * ConsoleHeight + fontHeight)
|
||||||
{
|
{
|
||||||
consoleNotifyBox.Visible = true;
|
consoleNotifyBox.Visible = true;
|
||||||
@@ -386,8 +387,7 @@ namespace Game
|
|||||||
|
|
||||||
public void OnPrint(string text)
|
public void OnPrint(string text)
|
||||||
{
|
{
|
||||||
int fontHeight = (int)(consoleNotifyBox.FontHeight / Platform.DpiScale);
|
consoleNotifyBox.Height = Math.Min(ConsoleNotifyLines, Console.Lines.Length) * fontHeight;
|
||||||
consoleNotifyBox.Height = Math.Min(ConsoleNotifyLines, Console.Lines.Count) * fontHeight;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetInput(string text)
|
public void SetInput(string text)
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ using NVIDIA;
|
|||||||
#endif
|
#endif
|
||||||
using FlaxEditor.Content.Settings;
|
using FlaxEditor.Content.Settings;
|
||||||
using FlaxEngine;
|
using FlaxEngine;
|
||||||
|
using FlaxEngine.Networking;
|
||||||
|
|
||||||
namespace Game
|
namespace Game
|
||||||
{
|
{
|
||||||
@@ -353,11 +354,12 @@ namespace Game
|
|||||||
/*aoSettings.OverrideFlags = (aoSettings.OverrideFlags & ~AmbientOcclusionSettingsOverride.Enabled) |
|
/*aoSettings.OverrideFlags = (aoSettings.OverrideFlags & ~AmbientOcclusionSettingsOverride.Enabled) |
|
||||||
(boolValue
|
(boolValue
|
||||||
? AmbientOcclusionSettingsOverride.Enabled
|
? AmbientOcclusionSettingsOverride.Enabled
|
||||||
: 0 & AmbientOcclusionSettingsOverride.Enabled);
|
: 0 & AmbientOcclusionSettingsOverride.Enabled);*/
|
||||||
*/
|
|
||||||
|
|
||||||
aoSettings.Enabled = boolValue;
|
aoSettings.Enabled = boolValue;
|
||||||
postProcessSettings.AmbientOcclusion = aoSettings;
|
postProcessSettings.AmbientOcclusion = aoSettings;
|
||||||
|
Graphics.PostProcessSettings = postProcessSettings;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -608,17 +610,45 @@ namespace Game
|
|||||||
Scripting.Update += TimeDemoOnUpdate;
|
Scripting.Update += TimeDemoOnUpdate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[ConsoleVariable("net_fakelag")]
|
||||||
|
public static string NetFakeLag
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
var driver = NetworkManager.server != null ? (NetworkManager.ServerNetworkDriver as NetworkLagDriver) : (NetworkManager.ClientNetworkDriver as NetworkLagDriver);
|
||||||
|
if (driver == null)
|
||||||
|
return 0.ToString();
|
||||||
|
return ((int)driver.Lag).ToString();
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
var driver = NetworkManager.server != null ? (NetworkManager.ServerNetworkDriver as NetworkLagDriver) : (NetworkManager.ClientNetworkDriver as NetworkLagDriver);
|
||||||
|
if (driver == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
int intValue = 0;
|
||||||
|
if (int.TryParse(value, out intValue))
|
||||||
|
{ }
|
||||||
|
else if (float.TryParse(value, out float valueFloat))
|
||||||
|
intValue = (int)valueFloat;
|
||||||
|
intValue = Math.Clamp(intValue, 0, 2000);
|
||||||
|
|
||||||
|
driver.Lag = intValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
[ConsoleCommand("map")]
|
[ConsoleCommand("map")]
|
||||||
public static void MapCommand()
|
public static void MapCommand()
|
||||||
{
|
{
|
||||||
//NetworkManager.StartServer(true);
|
//NetworkManager.StartServer(true);
|
||||||
GameMode.StartServer(true);
|
NetworkManager.StartServer();
|
||||||
}
|
}
|
||||||
|
|
||||||
[ConsoleCommand("connect")]
|
[ConsoleCommand("connect")]
|
||||||
public static void ConnectCommand()
|
public static void ConnectCommand()
|
||||||
{
|
{
|
||||||
GameMode.Connect();
|
//GameMode.Connect();
|
||||||
|
NetworkManager.ConnectServer();
|
||||||
}
|
}
|
||||||
|
|
||||||
[ConsoleSubsystemInitializer]
|
[ConsoleSubsystemInitializer]
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
#if false
|
#if true
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using FlaxEngine;
|
using FlaxEngine;
|
||||||
|
using FlaxEngine.Assertions;
|
||||||
using FlaxEngine.Networking;
|
using FlaxEngine.Networking;
|
||||||
using Console = Game.Console;
|
using Console = Game.Console;
|
||||||
|
|
||||||
@@ -14,7 +15,8 @@ namespace Game
|
|||||||
WelcomePlayer,
|
WelcomePlayer,
|
||||||
SpawnPlayer,
|
SpawnPlayer,
|
||||||
PlayerInput,
|
PlayerInput,
|
||||||
PlayerPosition, // debug
|
PlayerPosition, // world update
|
||||||
|
PlayerSnapshot, // send world state delta to client since last client's acknowledged frame
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -43,32 +45,42 @@ namespace Game
|
|||||||
|
|
||||||
private static Dictionary<uint, PlayerActor> players;
|
private static Dictionary<uint, PlayerActor> players;
|
||||||
private static Dictionary<uint, NetworkConnection> playerConnections;
|
private static Dictionary<uint, NetworkConnection> playerConnections;
|
||||||
private static bool spawned = false;
|
private static bool welcomed = false;
|
||||||
|
|
||||||
private static WorldState worldState;
|
private static WorldState serverWorldState;
|
||||||
private static PlayerFrame[] localPlayerFrameHistory;
|
private static WorldState clientWorldState;
|
||||||
|
|
||||||
|
private static ulong lastReceivedServerFrame = 0;
|
||||||
|
public static ulong ServerFrame => /*NetworkManager.server != null ? serverWorldState.frame :*/ lastReceivedServerFrame;
|
||||||
|
public static ulong ClientFrame => clientWorldState.frame;
|
||||||
|
|
||||||
public static void Init()
|
public static void Init()
|
||||||
{
|
{
|
||||||
|
welcomed = false;
|
||||||
|
lastReceivedServerFrame = 0;
|
||||||
|
|
||||||
players = new Dictionary<uint, PlayerActor>();
|
players = new Dictionary<uint, PlayerActor>();
|
||||||
playerConnections = new Dictionary<uint, NetworkConnection>();
|
playerConnections = new Dictionary<uint, NetworkConnection>();
|
||||||
localPlayerFrameHistory = new PlayerFrame[120];
|
serverWorldState = new WorldState();
|
||||||
worldState = new WorldState();
|
clientWorldState = new WorldState();
|
||||||
|
|
||||||
NetworkManager.OnMessage += OnMessage;
|
NetworkManager.OnMessage += OnMessage;
|
||||||
Level.SceneLoaded += OnLevelLoaded;
|
Level.SceneLoaded += OnLevelLoaded;
|
||||||
Scripting.LateUpdate += OnLateUpdatePre;
|
//Scripting.LateUpdate += OnLateUpdatePre;
|
||||||
|
Scripting.LateFixedUpdate += OnLateUpdatePre;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Cleanup()
|
public static void Cleanup()
|
||||||
{
|
{
|
||||||
NetworkManager.OnMessage -= OnMessage;
|
NetworkManager.OnMessage -= OnMessage;
|
||||||
Level.SceneLoaded -= OnLevelLoaded;
|
Level.SceneLoaded -= OnLevelLoaded;
|
||||||
Scripting.LateUpdate -= OnLateUpdatePre;
|
//Scripting.LateUpdate -= OnLateUpdatePre;
|
||||||
|
Scripting.LateFixedUpdate -= OnLateUpdatePre;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static PlayerFrame GetPlayerFrame(uint playerIndex, ulong playerFrameIndex)
|
private static PlayerFrame GetPlayerFrame(uint playerIndex, ulong playerFrameIndex)
|
||||||
{
|
{
|
||||||
|
WorldState worldState = NetworkManager.server != null ? serverWorldState : clientWorldState;
|
||||||
PlayerFrame[] playerFrames = worldState.playerFrameHistory[playerIndex];
|
PlayerFrame[] playerFrames = worldState.playerFrameHistory[playerIndex];
|
||||||
PlayerFrame playerFrame = playerFrames[playerFrameIndex % 120];
|
PlayerFrame playerFrame = playerFrames[playerFrameIndex % 120];
|
||||||
|
|
||||||
@@ -80,7 +92,7 @@ namespace Game
|
|||||||
|
|
||||||
public static void OnLevelLoaded(Scene scene, Guid assetGuid)
|
public static void OnLevelLoaded(Scene scene, Guid assetGuid)
|
||||||
{
|
{
|
||||||
worldState.frame = 0;
|
serverWorldState.frame = 0;
|
||||||
Console.Print("level loaded");
|
Console.Print("level loaded");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -90,12 +102,14 @@ namespace Game
|
|||||||
{
|
{
|
||||||
NetworkManager.IsServer = NetworkManager.server != null;
|
NetworkManager.IsServer = NetworkManager.server != null;
|
||||||
NetworkManager.IsClient = NetworkManager.client != null && NetworkManager.server == null;
|
NetworkManager.IsClient = NetworkManager.client != null && NetworkManager.server == null;
|
||||||
|
NetworkManager.IsLocalClient = NetworkManager.client != null && NetworkManager.server != null;
|
||||||
OnLateUpdate();
|
OnLateUpdate();
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
NetworkManager.IsServer = false;
|
NetworkManager.IsServer = false;
|
||||||
NetworkManager.IsClient = false;
|
NetworkManager.IsClient = false;
|
||||||
|
NetworkManager.IsLocalClient = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -108,10 +122,10 @@ namespace Game
|
|||||||
var playerId = kv.Key;
|
var playerId = kv.Key;
|
||||||
var playerActor = kv.Value;
|
var playerActor = kv.Value;
|
||||||
|
|
||||||
var playerFrames = worldState.playerFrameHistory[playerId];
|
var playerFrames = serverWorldState.playerFrameHistory[playerId];
|
||||||
var playerFrame = playerFrames[worldState.frame % 120];
|
var playerFrame = playerFrames[serverWorldState.frame % 120];
|
||||||
|
|
||||||
playerFrame.frame = worldState.frame;
|
playerFrame.frame = serverWorldState.frame;
|
||||||
playerFrame.position = playerActor.Position;
|
playerFrame.position = playerActor.Position;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -120,41 +134,79 @@ namespace Game
|
|||||||
var playerId = kv.Key;
|
var playerId = kv.Key;
|
||||||
foreach (KeyValuePair<uint, PlayerActor> kv2 in players)
|
foreach (KeyValuePair<uint, PlayerActor> kv2 in players)
|
||||||
{
|
{
|
||||||
if (kv2.Key == playerId)
|
//if (kv2.Key == playerId)
|
||||||
continue;
|
// continue;
|
||||||
|
|
||||||
var otherPlayerActor = kv2.Value;
|
var otherPlayerActor = kv2.Value;
|
||||||
|
|
||||||
// TODO: relevancy checks here etc.
|
// TODO: relevancy checks here etc.
|
||||||
|
|
||||||
|
PlayerMovement playerMovement = otherPlayerActor.GetScript<PlayerMovement>();
|
||||||
|
PlayerActorState actorState = playerMovement.input.GetCurrentActorState();
|
||||||
|
PlayerInputState inputState = playerMovement.input.GetCurrentInputState();
|
||||||
{
|
{
|
||||||
NetworkMessage message = NetworkManager.ServerBeginSendMessage();
|
NetworkMessage message = NetworkManager.ServerBeginSendMessage();
|
||||||
message.WriteByte((byte)GameModeMessageType.PlayerPosition);
|
message.WriteByte((byte)GameModeMessageType.PlayerPosition);
|
||||||
message.WriteUInt64(worldState.frame);
|
message.WriteUInt64(serverWorldState.frame);
|
||||||
message.WriteUInt32(kv2.Key);
|
message.WriteUInt32(kv2.Key);
|
||||||
message.WriteSingle(otherPlayerActor.Position.X);
|
message.WriteSingle(actorState.position.X);
|
||||||
message.WriteSingle(otherPlayerActor.Position.Y);
|
message.WriteSingle(actorState.position.Y);
|
||||||
message.WriteSingle(otherPlayerActor.Position.Z);
|
message.WriteSingle(actorState.position.Z);
|
||||||
|
message.WriteSingle(actorState.velocity.X);
|
||||||
|
message.WriteSingle(actorState.velocity.Y);
|
||||||
|
message.WriteSingle(actorState.velocity.Z);
|
||||||
|
message.WriteSingle(actorState.orientation.X);
|
||||||
|
message.WriteSingle(actorState.orientation.Y);
|
||||||
|
message.WriteSingle(actorState.orientation.Z);
|
||||||
|
message.WriteSingle(actorState.orientation.W);
|
||||||
|
message.WriteSingle(actorState.viewAngles.X);
|
||||||
|
message.WriteSingle(actorState.viewAngles.Y);
|
||||||
|
message.WriteSingle(actorState.viewAngles.Z);
|
||||||
|
|
||||||
|
//inputState.frame
|
||||||
|
message.WriteSingle(inputState.viewDeltaX);
|
||||||
|
message.WriteSingle(inputState.viewDeltaY);
|
||||||
|
message.WriteSingle(inputState.moveForward);
|
||||||
|
message.WriteSingle(inputState.moveRight);
|
||||||
|
message.WriteBoolean(inputState.attacking);
|
||||||
|
message.WriteBoolean(inputState.jumping);
|
||||||
|
|
||||||
NetworkManager.ServerEndSendMessage(ref message, playerConnections[playerId]);
|
NetworkManager.ServerEndSendMessage(ref message, playerConnections[playerId]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (NetworkManager.IsClient)
|
if (NetworkManager.IsClient || NetworkManager.IsLocalClient)
|
||||||
{
|
{
|
||||||
if (!spawned)
|
//if (!welcomed)
|
||||||
return;
|
// return;
|
||||||
|
|
||||||
PlayerActor playerActor = Level.GetActors<PlayerActor>().First(x =>
|
if (welcomed)
|
||||||
|
foreach (PlayerActor playerActor in Level.GetActors<PlayerActor>())
|
||||||
|
{
|
||||||
|
var playerId = playerActor.PlayerId;
|
||||||
|
var playerFrameHistory = clientWorldState.playerFrameHistory[playerId];
|
||||||
|
var playerFrame = playerFrameHistory[clientWorldState.frame % 120];
|
||||||
|
|
||||||
|
playerFrame.frame = clientWorldState.frame;
|
||||||
|
playerFrame.position = playerActor.Position;
|
||||||
|
}
|
||||||
|
|
||||||
|
clientWorldState.frame++;
|
||||||
|
|
||||||
|
/*PlayerActor playerActor = Level.GetActors<PlayerActor>().FirstOrDefault(x =>
|
||||||
x.GetScript<PlayerMovement>().PlayerId == NetworkManager.LocalPlayerClientId);
|
x.GetScript<PlayerMovement>().PlayerId == NetworkManager.LocalPlayerClientId);
|
||||||
|
|
||||||
var playerFrame = localPlayerFrameHistory[worldState.frame % 120];
|
if (playerActor == null)
|
||||||
|
return;*/
|
||||||
|
|
||||||
playerFrame.frame = worldState.frame;
|
//var playerFrame = localPlayerFrameHistory[serverWorldState.frame % 120];
|
||||||
playerFrame.position = playerActor.Position;
|
|
||||||
|
|
||||||
{
|
//playerFrame.frame = serverWorldState.frame;
|
||||||
|
//playerFrame.position = playerActor.Position;
|
||||||
|
|
||||||
|
/*{
|
||||||
NetworkMessage message = NetworkManager.ClientBeginSendMessage();
|
NetworkMessage message = NetworkManager.ClientBeginSendMessage();
|
||||||
message.WriteByte((byte)GameModeMessageType.PlayerPosition);
|
message.WriteByte((byte)GameModeMessageType.PlayerPosition);
|
||||||
message.WriteUInt64(worldState.frame);
|
message.WriteUInt64(worldState.frame);
|
||||||
@@ -163,10 +215,14 @@ namespace Game
|
|||||||
message.WriteSingle(playerActor.Position.Y);
|
message.WriteSingle(playerActor.Position.Y);
|
||||||
message.WriteSingle(playerActor.Position.Z);
|
message.WriteSingle(playerActor.Position.Z);
|
||||||
NetworkManager.ClientEndSendMessage(ref message);
|
NetworkManager.ClientEndSendMessage(ref message);
|
||||||
|
}*/
|
||||||
}
|
}
|
||||||
|
else if (NetworkManager.IsLocalClient)
|
||||||
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
worldState.frame++;
|
serverWorldState.frame++;
|
||||||
|
|
||||||
/*foreach (KeyValuePair<uint,PlayerActor> kv in players)
|
/*foreach (KeyValuePair<uint,PlayerActor> kv in players)
|
||||||
{
|
{
|
||||||
@@ -205,11 +261,12 @@ namespace Game
|
|||||||
{
|
{
|
||||||
case GameModeMessageType.WelcomePlayer:
|
case GameModeMessageType.WelcomePlayer:
|
||||||
{
|
{
|
||||||
if (NetworkManager.IsClient)
|
welcomed = true;
|
||||||
|
if (NetworkManager.IsClient || NetworkManager.IsLocalClient)
|
||||||
{
|
{
|
||||||
worldState.frame = networkEvent.Message.ReadUInt64();
|
var serverFrame = networkEvent.Message.ReadUInt64();
|
||||||
int numActors = (int)networkEvent.Message.ReadUInt32();
|
int numActors = (int)networkEvent.Message.ReadUInt32();
|
||||||
for (int i=0; i<numActors; i++)
|
for (int i = 0; i < numActors; i++)
|
||||||
{
|
{
|
||||||
uint playerId = networkEvent.Message.ReadUInt32();
|
uint playerId = networkEvent.Message.ReadUInt32();
|
||||||
Float3 playerPosition;
|
Float3 playerPosition;
|
||||||
@@ -218,15 +275,24 @@ namespace Game
|
|||||||
playerPosition.Z = networkEvent.Message.ReadSingle();
|
playerPosition.Z = networkEvent.Message.ReadSingle();
|
||||||
|
|
||||||
SpawnPlayer(playerId, playerPosition, new Float3(0));
|
SpawnPlayer(playerId, playerPosition, new Float3(0));
|
||||||
|
|
||||||
|
var playerFrames = new PlayerFrame[120];
|
||||||
|
for (int j = 0; j < playerFrames.Length; j++)
|
||||||
|
playerFrames[j] = new PlayerFrame();
|
||||||
|
clientWorldState.playerFrameHistory.Add(playerId, playerFrames);
|
||||||
}
|
}
|
||||||
|
|
||||||
Console.Print("received welcome: frame " + worldState.frame);
|
Console.Print("received welcome: frame " + serverWorldState.frame);
|
||||||
|
|
||||||
|
if (!NetworkManager.IsLocalClient)
|
||||||
|
serverWorldState.frame = serverFrame;
|
||||||
|
//lastReceivedServerFrame = serverFrame;
|
||||||
|
clientWorldState.frame += serverFrame;
|
||||||
|
|
||||||
|
if (!players.ContainsKey(NetworkManager.LocalPlayerClientId)) // listen server
|
||||||
players.Add(NetworkManager.LocalPlayerClientId, null);
|
players.Add(NetworkManager.LocalPlayerClientId, null);
|
||||||
//playerConnections.Add(NetworkManager.LocalPlayerClientId, connection);
|
//playerConnections.Add(NetworkManager.LocalPlayerClientId, connection);
|
||||||
localPlayerFrameHistory = new PlayerFrame[120];
|
|
||||||
for (int i = 0; i < localPlayerFrameHistory.Length; i++)
|
|
||||||
localPlayerFrameHistory[i] = new PlayerFrame();
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -234,9 +300,21 @@ namespace Game
|
|||||||
{
|
{
|
||||||
uint playerId = networkEvent.Message.ReadUInt32();
|
uint playerId = networkEvent.Message.ReadUInt32();
|
||||||
ulong playerFrameIndex = networkEvent.Message.ReadUInt64();
|
ulong playerFrameIndex = networkEvent.Message.ReadUInt64();
|
||||||
|
|
||||||
|
if (!clientWorldState.playerFrameHistory.ContainsKey(playerId))
|
||||||
|
{
|
||||||
|
var playerFrames = new PlayerFrame[120];
|
||||||
|
for (int j = 0; j < playerFrames.Length; j++)
|
||||||
|
playerFrames[j] = new PlayerFrame();
|
||||||
|
clientWorldState.playerFrameHistory.Add(playerId, playerFrames);
|
||||||
|
}
|
||||||
|
|
||||||
SpawnPlayer(playerId,
|
SpawnPlayer(playerId,
|
||||||
new Float3(networkEvent.Message.ReadSingle(), networkEvent.Message.ReadSingle(), networkEvent.Message.ReadSingle()),
|
new Float3(networkEvent.Message.ReadSingle(), networkEvent.Message.ReadSingle(), networkEvent.Message.ReadSingle()),
|
||||||
new Float3(networkEvent.Message.ReadSingle(), networkEvent.Message.ReadSingle(), networkEvent.Message.ReadSingle()));
|
new Float3(networkEvent.Message.ReadSingle(), networkEvent.Message.ReadSingle(), networkEvent.Message.ReadSingle()));
|
||||||
|
|
||||||
|
//if (NetworkManager.IsClient)
|
||||||
|
players[playerId].GetScript<PlayerMovement>().input.frame = clientWorldState.frame;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case GameModeMessageType.PlayerInput:
|
case GameModeMessageType.PlayerInput:
|
||||||
@@ -257,21 +335,49 @@ namespace Game
|
|||||||
case GameModeMessageType.PlayerPosition:
|
case GameModeMessageType.PlayerPosition:
|
||||||
{
|
{
|
||||||
uint playerId = networkEvent.Sender.ConnectionId;
|
uint playerId = networkEvent.Sender.ConnectionId;
|
||||||
Float3 reportedPosition;
|
PlayerInputState inputState = default; //?
|
||||||
|
PlayerActorState actorState;
|
||||||
|
|
||||||
ulong reportedFrame = networkEvent.Message.ReadUInt64();
|
ulong reportedFrame = networkEvent.Message.ReadUInt64();
|
||||||
uint reportedPlayerId = networkEvent.Message.ReadUInt32();
|
uint reportedPlayerId = networkEvent.Message.ReadUInt32();
|
||||||
reportedPosition.X = networkEvent.Message.ReadSingle();
|
actorState.position.X = networkEvent.Message.ReadSingle();
|
||||||
reportedPosition.Y = networkEvent.Message.ReadSingle();
|
actorState.position.Y = networkEvent.Message.ReadSingle();
|
||||||
reportedPosition.Z = networkEvent.Message.ReadSingle();
|
actorState.position.Z = networkEvent.Message.ReadSingle();
|
||||||
|
actorState.velocity.X = networkEvent.Message.ReadSingle();
|
||||||
|
actorState.velocity.Y = networkEvent.Message.ReadSingle();
|
||||||
|
actorState.velocity.Z = networkEvent.Message.ReadSingle();
|
||||||
|
actorState.orientation.X = networkEvent.Message.ReadSingle();
|
||||||
|
actorState.orientation.Y = networkEvent.Message.ReadSingle();
|
||||||
|
actorState.orientation.Z = networkEvent.Message.ReadSingle();
|
||||||
|
actorState.orientation.W = networkEvent.Message.ReadSingle();
|
||||||
|
actorState.viewAngles.X = networkEvent.Message.ReadSingle();
|
||||||
|
actorState.viewAngles.Y = networkEvent.Message.ReadSingle();
|
||||||
|
actorState.viewAngles.Z = networkEvent.Message.ReadSingle();
|
||||||
|
|
||||||
if (NetworkManager.IsLocalClient && !NetworkManager.IsServer)
|
inputState.frame = reportedFrame;
|
||||||
|
inputState.viewDeltaX = networkEvent.Message.ReadSingle();
|
||||||
|
inputState.viewDeltaY = networkEvent.Message.ReadSingle();
|
||||||
|
inputState.moveForward = networkEvent.Message.ReadSingle();
|
||||||
|
inputState.moveRight = networkEvent.Message.ReadSingle();
|
||||||
|
inputState.attacking = networkEvent.Message.ReadBoolean();
|
||||||
|
inputState.jumping = networkEvent.Message.ReadBoolean();
|
||||||
|
|
||||||
|
//Assert.IsTrue(reportedFrame >= lastReceivedServerFrame);
|
||||||
|
if (reportedFrame < lastReceivedServerFrame)
|
||||||
|
{
|
||||||
|
Console.Print($"packet wrong order, received {lastReceivedServerFrame}, new {reportedFrame}");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*if (NetworkManager.IsLocalClient && !NetworkManager.IsServer)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
else if (NetworkManager.IsServer)
|
else*/ if (NetworkManager.IsServer)
|
||||||
{
|
{
|
||||||
PlayerFrame playerFrame = GetPlayerFrame(playerId, reportedFrame);
|
Assert.Fail();
|
||||||
|
/*PlayerFrame playerFrame = GetPlayerFrame(playerId, reportedFrame);
|
||||||
PlayerActor playerActor = players[playerId];
|
PlayerActor playerActor = players[playerId];
|
||||||
if (playerFrame == null)
|
if (playerFrame == null)
|
||||||
Console.Print("frame is in the past, unable to verify frame");
|
Console.Print("frame is in the past, unable to verify frame");
|
||||||
@@ -285,12 +391,8 @@ namespace Game
|
|||||||
{
|
{
|
||||||
NetworkMessage message = NetworkManager.ServerBeginSendMessage();
|
NetworkMessage message = NetworkManager.ServerBeginSendMessage();
|
||||||
message.WriteByte((byte)GameModeMessageType.PlayerPosition);
|
message.WriteByte((byte)GameModeMessageType.PlayerPosition);
|
||||||
/*message.WriteUInt64(reportedFrame);
|
|
||||||
message.WriteUInt32(playerId);
|
message.WriteUInt64(serverWorldState.frame);
|
||||||
message.WriteSingle(playerFramePosition.X);
|
|
||||||
message.WriteSingle(playerFramePosition.Y);
|
|
||||||
message.WriteSingle(playerFramePosition.Z);*/
|
|
||||||
message.WriteUInt64(worldState.frame);
|
|
||||||
message.WriteUInt32(playerId);
|
message.WriteUInt32(playerId);
|
||||||
message.WriteSingle(playerActor.Position.X);
|
message.WriteSingle(playerActor.Position.X);
|
||||||
message.WriteSingle(playerActor.Position.Y);
|
message.WriteSingle(playerActor.Position.Y);
|
||||||
@@ -298,16 +400,26 @@ namespace Game
|
|||||||
NetworkManager.ServerEndSendMessage(ref message, playerConnections[playerId]);
|
NetworkManager.ServerEndSendMessage(ref message, playerConnections[playerId]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}*/
|
||||||
}
|
}
|
||||||
else if (NetworkManager.IsClient)
|
else if (NetworkManager.IsClient)
|
||||||
{
|
{
|
||||||
Console.Print($"we drifted, corrected. client frame: {worldState.frame}, server frame: {reportedFrame}");
|
lastReceivedServerFrame = reportedFrame;
|
||||||
|
//Console.Print($"we drifted, corrected. client frame: {serverWorldState.frame}, server frame: {reportedFrame}");
|
||||||
PlayerActor playerActor = Level.GetActors<PlayerActor>().FirstOrDefault(x =>
|
PlayerActor playerActor = Level.GetActors<PlayerActor>().FirstOrDefault(x =>
|
||||||
x.GetScript<PlayerMovement>().PlayerId == reportedPlayerId);
|
x.GetScript<PlayerMovement>().PlayerId == reportedPlayerId);
|
||||||
|
|
||||||
|
|
||||||
if (playerActor != null)
|
if (playerActor != null)
|
||||||
playerActor.SetPosition(reportedPosition);
|
{
|
||||||
|
PlayerInput playerInput = playerActor.GetScript<PlayerMovement>().input;
|
||||||
|
|
||||||
|
playerInput.SetState(reportedFrame, ref inputState, ref actorState);
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
//playerActor.SetPosition(reportedPosition);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@@ -322,14 +434,14 @@ namespace Game
|
|||||||
|
|
||||||
public static bool OnClientConnecting(NetworkConnection connection)
|
public static bool OnClientConnecting(NetworkConnection connection)
|
||||||
{
|
{
|
||||||
if (connection.ConnectionId != NetworkManager.LocalPlayerClientId)
|
//if (connection.ConnectionId != NetworkManager.LocalPlayerClientId)
|
||||||
{
|
{
|
||||||
Console.Print("sending welcome: frame " + worldState.frame);
|
Console.Print("sending welcome: frame " + serverWorldState.frame);
|
||||||
NetworkMessage message = NetworkManager.ServerBeginSendMessage();
|
NetworkMessage message = NetworkManager.ServerBeginSendMessage();
|
||||||
message.WriteByte((byte)GameModeMessageType.WelcomePlayer);
|
message.WriteByte((byte)GameModeMessageType.WelcomePlayer);
|
||||||
message.WriteUInt64(worldState.frame);
|
message.WriteUInt64(serverWorldState.frame);
|
||||||
message.WriteUInt32((uint)worldState.actors.Count);
|
message.WriteUInt32((uint)serverWorldState.actors.Count);
|
||||||
foreach (PlayerActor playerActor in worldState.actors)
|
foreach (PlayerActor playerActor in serverWorldState.actors)
|
||||||
{
|
{
|
||||||
message.WriteUInt32(playerActor.GetScript<PlayerMovement>().PlayerId);
|
message.WriteUInt32(playerActor.GetScript<PlayerMovement>().PlayerId);
|
||||||
message.WriteSingle(playerActor.Position.X);
|
message.WriteSingle(playerActor.Position.X);
|
||||||
@@ -343,12 +455,16 @@ namespace Game
|
|||||||
|
|
||||||
public static bool OnClientConnected(NetworkConnection connection)
|
public static bool OnClientConnected(NetworkConnection connection)
|
||||||
{
|
{
|
||||||
|
uint playerId = connection.ConnectionId;
|
||||||
|
if (NetworkManager.LocalPlayerClientId == 0)
|
||||||
|
NetworkManager.LocalPlayerClientId = playerId;
|
||||||
|
|
||||||
var spawns = Level.GetActors<Actor>().Where(x => x.Name.StartsWith("PlayerSpawn_")).ToArray();
|
var spawns = Level.GetActors<Actor>().Where(x => x.Name.StartsWith("PlayerSpawn_")).ToArray();
|
||||||
Console.Print($"found {spawns.Length} spawns");
|
Console.Print($"found {spawns.Length} spawns");
|
||||||
|
|
||||||
var randomSpawn = spawns.First();
|
var randomSpawn = spawns.First();
|
||||||
|
|
||||||
uint playerId = connection.ConnectionId;
|
|
||||||
Float3 position = randomSpawn.Position + new Float3(0f, 4.1f, 0f);
|
Float3 position = randomSpawn.Position + new Float3(0f, 4.1f, 0f);
|
||||||
Float3 eulerAngles = randomSpawn.Orientation.EulerAngles;
|
Float3 eulerAngles = randomSpawn.Orientation.EulerAngles;
|
||||||
|
|
||||||
@@ -357,7 +473,7 @@ namespace Game
|
|||||||
var playerFrames = new PlayerFrame[120];
|
var playerFrames = new PlayerFrame[120];
|
||||||
for (int i = 0; i < playerFrames.Length; i++)
|
for (int i = 0; i < playerFrames.Length; i++)
|
||||||
playerFrames[i] = new PlayerFrame();
|
playerFrames[i] = new PlayerFrame();
|
||||||
worldState.playerFrameHistory.Add(playerId, playerFrames);
|
serverWorldState.playerFrameHistory.Add(playerId, playerFrames);
|
||||||
|
|
||||||
|
|
||||||
SpawnPlayer(playerId, position, eulerAngles);
|
SpawnPlayer(playerId, position, eulerAngles);
|
||||||
@@ -365,7 +481,7 @@ namespace Game
|
|||||||
NetworkMessage message = NetworkManager.ServerBeginSendMessage();
|
NetworkMessage message = NetworkManager.ServerBeginSendMessage();
|
||||||
message.WriteByte((byte)GameModeMessageType.SpawnPlayer);
|
message.WriteByte((byte)GameModeMessageType.SpawnPlayer);
|
||||||
message.WriteUInt32(playerId);
|
message.WriteUInt32(playerId);
|
||||||
message.WriteUInt64(worldState.frame);
|
message.WriteUInt64(serverWorldState.frame);
|
||||||
message.WriteSingle(position.X);
|
message.WriteSingle(position.X);
|
||||||
message.WriteSingle(position.Y);
|
message.WriteSingle(position.Y);
|
||||||
message.WriteSingle(position.Z);
|
message.WriteSingle(position.Z);
|
||||||
@@ -383,7 +499,7 @@ namespace Game
|
|||||||
if (NetworkManager.IsLocalClient)
|
if (NetworkManager.IsLocalClient)
|
||||||
return; // Handled by listenserver
|
return; // Handled by listenserver
|
||||||
|
|
||||||
spawned = true;
|
//spawned = true;
|
||||||
|
|
||||||
string prefabPath = Path.Combine(AssetManager.ContentPath, "Common");
|
string prefabPath = Path.Combine(AssetManager.ContentPath, "Common");
|
||||||
var playerPrefab = Content.Load<Prefab>(Path.Combine(prefabPath, "PlayerPrefab.prefab"));
|
var playerPrefab = Content.Load<Prefab>(Path.Combine(prefabPath, "PlayerPrefab.prefab"));
|
||||||
@@ -391,15 +507,16 @@ namespace Game
|
|||||||
Console.PrintError("GameModeManager: Failed to find PlayerPrefab");
|
Console.PrintError("GameModeManager: Failed to find PlayerPrefab");
|
||||||
|
|
||||||
PlayerActor playerActor = PrefabManager.SpawnPrefab(playerPrefab).As<PlayerActor>();
|
PlayerActor playerActor = PrefabManager.SpawnPrefab(playerPrefab).As<PlayerActor>();
|
||||||
playerActor.Initialize(playerId);
|
playerActor.Initialize(playerId, position, eulerAngles);
|
||||||
playerActor.Teleport(position, eulerAngles);
|
//playerActor.Teleport(position, eulerAngles);
|
||||||
|
|
||||||
if (!players.ContainsKey(playerId))
|
if (!players.ContainsKey(playerId))
|
||||||
players.Add(playerId, null);
|
players.Add(playerId, null);
|
||||||
players[playerId] = playerActor;
|
players[playerId] = playerActor;
|
||||||
|
PlayerInput playerInput = playerActor.GetScript<PlayerMovement>().input;
|
||||||
|
|
||||||
if (NetworkManager.IsServer)
|
if (NetworkManager.IsServer)
|
||||||
worldState.actors.Add(playerActor);
|
serverWorldState.actors.Add(playerActor);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void UpdatePlayerInput(uint playerId, PlayerInputState inputState)
|
private static void UpdatePlayerInput(uint playerId, PlayerInputState inputState)
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using FlaxEditor.Content.Settings;
|
#if false
|
||||||
|
using FlaxEditor.Content.Settings;
|
||||||
using FlaxEngine;
|
using FlaxEngine;
|
||||||
using FlaxEngine.Networking;
|
using FlaxEngine.Networking;
|
||||||
using System;
|
using System;
|
||||||
@@ -88,6 +89,8 @@ namespace Game
|
|||||||
|
|
||||||
currentGameMode.Start();
|
currentGameMode.Start();
|
||||||
|
|
||||||
|
Console.Open();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -121,11 +124,25 @@ namespace Game
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static void NetworkManager_ClientConnected(NetworkClient networkClient)
|
private static void NetworkManager_ClientConnected(NetworkClient networkClient)
|
||||||
|
{
|
||||||
|
try
|
||||||
{
|
{
|
||||||
Console.Print("new client connected");
|
Console.Print("new client connected");
|
||||||
|
|
||||||
|
foreach (var (playerId, playerActor) in currentGameMode.players)
|
||||||
|
{
|
||||||
|
NetworkReplicator.SpawnObject(playerActor, new[] { networkClient.ClientId });
|
||||||
|
playerActor.Initialize(playerId, playerActor.Position, playerActor.GetRotation());
|
||||||
|
}
|
||||||
|
|
||||||
currentGameMode.OnPlayerSpawn(networkClient.ClientId);
|
currentGameMode.OnPlayerSpawn(networkClient.ClientId);
|
||||||
}
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Console.Print(e.ToString());
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static void NetworkManager_ClientConnecting(ref NetworkClientConnectionData arg0)
|
private static void NetworkManager_ClientConnecting(ref NetworkClientConnectionData arg0)
|
||||||
{
|
{
|
||||||
@@ -184,11 +201,18 @@ namespace Game
|
|||||||
|
|
||||||
public void OnPlayerSpawn(uint clientId)
|
public void OnPlayerSpawn(uint clientId)
|
||||||
{
|
{
|
||||||
// Get random spawn
|
// Get a random spawn
|
||||||
var spawns = Level.GetActors<Actor>().Where(x => x.Name.StartsWith("PlayerSpawn_")).ToArray();
|
var spawns = Level.GetActors<Actor>().Where(x => x.Name.StartsWith("PlayerSpawn_")).ToArray();
|
||||||
Console.Print($"found {spawns.Length} spawns");
|
|
||||||
|
|
||||||
var randomSpawn = spawns.First();
|
var randomSpawn = spawns.FirstOrDefault();
|
||||||
|
if (players.Count > 0)
|
||||||
|
randomSpawn = spawns.LastOrDefault();
|
||||||
|
if (randomSpawn == null)
|
||||||
|
{
|
||||||
|
Console.Print("No spawns found for player");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Console.Print($"found {spawns.Length} spawns");
|
||||||
|
|
||||||
Float3 spawnPosition = randomSpawn.Position + new Float3(0f, 4.1f, 0f);
|
Float3 spawnPosition = randomSpawn.Position + new Float3(0f, 4.1f, 0f);
|
||||||
Float3 spawnAngles = randomSpawn.Orientation.EulerAngles;
|
Float3 spawnAngles = randomSpawn.Orientation.EulerAngles;
|
||||||
@@ -201,12 +225,13 @@ namespace Game
|
|||||||
|
|
||||||
PlayerActor playerActor = PrefabManager.SpawnPrefab(playerPrefab).As<PlayerActor>();
|
PlayerActor playerActor = PrefabManager.SpawnPrefab(playerPrefab).As<PlayerActor>();
|
||||||
NetworkReplicator.AddObject(playerActor);
|
NetworkReplicator.AddObject(playerActor);
|
||||||
playerActor.Initialize(clientId);
|
playerActor.Initialize(clientId, spawnPosition, spawnAngles);
|
||||||
|
|
||||||
playerActor.Teleport(spawnPosition, spawnAngles);
|
//playerActor.Teleport(spawnPosition, spawnAngles);
|
||||||
//NetworkReplicator.SetObjectOwnership(playerActor, clientId);
|
//NetworkReplicator.SetObjectOwnership(playerActor, clientId);
|
||||||
|
|
||||||
NetworkReplicator.SpawnObject(playerActor);
|
NetworkReplicator.SpawnObject(playerActor);
|
||||||
|
players.Add(clientId, playerActor);
|
||||||
//playerActor.Initialize(clientId);
|
//playerActor.Initialize(clientId);
|
||||||
//playerActor.hai = 345;
|
//playerActor.hai = 345;
|
||||||
|
|
||||||
@@ -233,3 +258,4 @@ namespace Game
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
150
Source/Game/GameMode/NetworkManager.cs
Normal file
150
Source/Game/GameMode/NetworkManager.cs
Normal file
@@ -0,0 +1,150 @@
|
|||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using FlaxEditor;
|
||||||
|
using FlaxEngine;
|
||||||
|
using FlaxEngine.Networking;
|
||||||
|
using Console = Game.Console;
|
||||||
|
|
||||||
|
namespace Game
|
||||||
|
{
|
||||||
|
[AttributeUsage(AttributeTargets.Class)]
|
||||||
|
public class NetworkPredictedAttribute : Attribute
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: insert code to update variables with this attribute?
|
||||||
|
// rename to NetworkReplicatedAttribute?
|
||||||
|
[AttributeUsage(AttributeTargets.Class)]
|
||||||
|
public class NetworkedAttribute : Attribute
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// NetworkMulticastAttribute: calls methods marked with this in all clients
|
||||||
|
|
||||||
|
public enum NetworkMessageType : byte
|
||||||
|
{
|
||||||
|
Handshake = 1,
|
||||||
|
Message
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static partial class NetworkManager
|
||||||
|
{
|
||||||
|
public delegate bool OnMessageDecl(ref NetworkEvent networkEvent);
|
||||||
|
|
||||||
|
private static bool initialized;
|
||||||
|
|
||||||
|
public static NetworkPeer server;
|
||||||
|
public static NetworkPeer client;
|
||||||
|
|
||||||
|
private static readonly ushort ServerPort = 59183;
|
||||||
|
private static string ServerAddress;
|
||||||
|
private static readonly ushort MTU = 1500;
|
||||||
|
private static readonly ushort MaximumClients = 32;
|
||||||
|
public static OnMessageDecl OnMessage;
|
||||||
|
|
||||||
|
public static bool IsServer = false;
|
||||||
|
public static bool IsClient = false;
|
||||||
|
public static bool IsLocalClient = false; // Context dependant, true when message is handled by local client
|
||||||
|
|
||||||
|
public static void Init()
|
||||||
|
{
|
||||||
|
if (initialized)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/*if (Engine.CommandLine.Contains("-server"))
|
||||||
|
{
|
||||||
|
StartServer();
|
||||||
|
ServerAddress = "localhost";
|
||||||
|
ConnectServer();
|
||||||
|
}
|
||||||
|
else if (Engine.CommandLine.Contains("-client"))
|
||||||
|
{
|
||||||
|
ServerAddress = "localhost";
|
||||||
|
ConnectServer();
|
||||||
|
}
|
||||||
|
//#if FLAX_EDITOR
|
||||||
|
else
|
||||||
|
{
|
||||||
|
StartServer();
|
||||||
|
ServerAddress = "localhost";
|
||||||
|
ConnectServer();
|
||||||
|
}*/
|
||||||
|
//#endif
|
||||||
|
|
||||||
|
initialized = true;
|
||||||
|
#if FLAX_EDITOR
|
||||||
|
Editor.Instance.PlayModeEnd += Cleanup;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
GameModeManager.Init(); // FIXME
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Cleanup()
|
||||||
|
{
|
||||||
|
if (server != null)
|
||||||
|
{
|
||||||
|
Scripting.FixedUpdate -= OnServerUpdate;
|
||||||
|
Scripting.Exit -= Cleanup;
|
||||||
|
Level.ActorSpawned -= OnServerActorSpawned;
|
||||||
|
NetworkPeer.ShutdownPeer(server);
|
||||||
|
server = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (client != null)
|
||||||
|
{
|
||||||
|
Scripting.FixedUpdate -= OnClientUpdate;
|
||||||
|
Scripting.Exit -= Cleanup;
|
||||||
|
Level.ActorSpawned -= OnClientActorSpawned;
|
||||||
|
NetworkPeer.ShutdownPeer(client);
|
||||||
|
client = null;
|
||||||
|
}
|
||||||
|
LocalPlayerClientId = 0;
|
||||||
|
|
||||||
|
#if FLAX_EDITOR
|
||||||
|
Editor.Instance.PlayModeEnd -= Cleanup;
|
||||||
|
GameModeManager.Cleanup(); // FIXME
|
||||||
|
#endif
|
||||||
|
|
||||||
|
initialized = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void OnNetworkMessage(ref NetworkEvent networkEvent)
|
||||||
|
{
|
||||||
|
byte messageTypeByte = networkEvent.Message.ReadByte();
|
||||||
|
if (!Enum.IsDefined(typeof(NetworkMessageType), messageTypeByte))
|
||||||
|
{
|
||||||
|
Console.PrintError($"Unsupported message type received from client: {messageTypeByte}");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
NetworkMessageType messageType = (NetworkMessageType)messageTypeByte;
|
||||||
|
|
||||||
|
switch (messageType)
|
||||||
|
{
|
||||||
|
case NetworkMessageType.Handshake:
|
||||||
|
{
|
||||||
|
string message = networkEvent.Message.ReadString();
|
||||||
|
Console.Print($"Received handshake from {networkEvent.Sender.ConnectionId}, msg: " + message);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case NetworkMessageType.Message:
|
||||||
|
{
|
||||||
|
if (OnMessage != null)
|
||||||
|
foreach (OnMessageDecl func in OnMessage.GetInvocationList()
|
||||||
|
.Cast<OnMessageDecl>().ToArray())
|
||||||
|
{
|
||||||
|
bool ret = func.Invoke(ref networkEvent);
|
||||||
|
if (ret)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
Console.PrintError($"Unsupported message type received from client: {messageTypeByte}");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
128
Source/Game/GameMode/NetworkManager_Client.cs
Normal file
128
Source/Game/GameMode/NetworkManager_Client.cs
Normal file
@@ -0,0 +1,128 @@
|
|||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using FlaxEngine;
|
||||||
|
using FlaxEngine.Networking;
|
||||||
|
using Console = Game.Console;
|
||||||
|
using Object = FlaxEngine.Object;
|
||||||
|
|
||||||
|
namespace Game
|
||||||
|
{
|
||||||
|
public static partial class NetworkManager
|
||||||
|
{
|
||||||
|
public static uint LocalPlayerClientId { get; /*private*/ set; }
|
||||||
|
|
||||||
|
public static INetworkDriver ClientNetworkDriver { get; set; }
|
||||||
|
|
||||||
|
public static bool ConnectServer(string serverAddress = "localhost", bool listenServer = false)
|
||||||
|
{
|
||||||
|
if (!listenServer)
|
||||||
|
Cleanup();
|
||||||
|
ServerAddress = serverAddress;
|
||||||
|
|
||||||
|
//var driver = Object.New(typeof(ENetDriver));
|
||||||
|
//ClientNetworkDriver = null;
|
||||||
|
NetworkLagDriver driver = Object.New<NetworkLagDriver>();
|
||||||
|
driver.Lag = 0f;
|
||||||
|
ClientNetworkDriver = driver;
|
||||||
|
|
||||||
|
|
||||||
|
client = NetworkPeer.CreatePeer(new NetworkConfig
|
||||||
|
{
|
||||||
|
NetworkDriver = driver,
|
||||||
|
ConnectionsLimit = MaximumClients,
|
||||||
|
MessagePoolSize = 2048,
|
||||||
|
MessageSize = MTU,
|
||||||
|
Address = ServerAddress == "localhost" ? "127.0.0.1" : ServerAddress,
|
||||||
|
Port = ServerPort
|
||||||
|
});
|
||||||
|
if (client == null)
|
||||||
|
{
|
||||||
|
Console.Print("Failed to create NetworkPeer.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!client.Connect())
|
||||||
|
{
|
||||||
|
Console.Print("Failed to connect to the server.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Scripting.FixedUpdate += OnClientUpdate;
|
||||||
|
if (!listenServer)
|
||||||
|
{
|
||||||
|
Scripting.Exit += Cleanup;
|
||||||
|
Level.ActorSpawned += OnClientActorSpawned;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void OnClientUpdate()
|
||||||
|
{
|
||||||
|
using Utilities.ScopeProfiler _ = Utilities.ProfileScope("NetworkManager_OnClientUpdate");
|
||||||
|
|
||||||
|
while (client.PopEvent(out NetworkEvent networkEvent))
|
||||||
|
switch (networkEvent.EventType)
|
||||||
|
{
|
||||||
|
case NetworkEventType.Connected:
|
||||||
|
{
|
||||||
|
LocalPlayerClientId = networkEvent.Sender.ConnectionId;
|
||||||
|
Console.Print("Connected to server, ConnectionId: " + networkEvent.Sender.ConnectionId);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case NetworkEventType.Disconnected:
|
||||||
|
{
|
||||||
|
Console.Print("Disconnected from server, timeout.");
|
||||||
|
LocalPlayerClientId = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case NetworkEventType.Timeout:
|
||||||
|
{
|
||||||
|
Console.Print("Disconnected from server, connection closed.");
|
||||||
|
LocalPlayerClientId = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case NetworkEventType.Message:
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
IsLocalClient = server != null;
|
||||||
|
IsClient = true;
|
||||||
|
OnNetworkMessage(ref networkEvent);
|
||||||
|
|
||||||
|
if (networkEvent.Message.Position > 0 &&
|
||||||
|
networkEvent.Message.Position < networkEvent.Message.Length)
|
||||||
|
{
|
||||||
|
string err =
|
||||||
|
$"Network message was not fully read: {networkEvent.Message.Position} / {networkEvent.Message.Length}.";
|
||||||
|
|
||||||
|
networkEvent.Message.Position = 0;
|
||||||
|
byte[] messageBytes = new byte[networkEvent.Message.Length];
|
||||||
|
unsafe
|
||||||
|
{
|
||||||
|
fixed (byte* messageBytePtr = &messageBytes[0])
|
||||||
|
networkEvent.Message.ReadBytes(messageBytePtr, (int)networkEvent.Message.Length);
|
||||||
|
}
|
||||||
|
|
||||||
|
string messageBytesStr = string.Join(", ",
|
||||||
|
messageBytes.Select(x => "0x" + ((int)x).ToString("X2")));
|
||||||
|
|
||||||
|
Console.PrintError(err + $"Message dump: {messageBytesStr}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
IsLocalClient = false;
|
||||||
|
IsClient = false;
|
||||||
|
client.RecycleMessage(networkEvent.Message);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
throw new ArgumentOutOfRangeException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void OnClientActorSpawned(Actor actor)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
196
Source/Game/GameMode/NetworkManager_Server.cs
Normal file
196
Source/Game/GameMode/NetworkManager_Server.cs
Normal file
@@ -0,0 +1,196 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
|
using FlaxEngine;
|
||||||
|
using FlaxEngine.Networking;
|
||||||
|
using Console = Game.Console;
|
||||||
|
using Object = FlaxEngine.Object;
|
||||||
|
|
||||||
|
namespace Game
|
||||||
|
{
|
||||||
|
public static partial class NetworkManager
|
||||||
|
{
|
||||||
|
private static List<NetworkConnection> ConnectedClients;
|
||||||
|
|
||||||
|
private static List<Type> NetworkedTypes;
|
||||||
|
|
||||||
|
public static INetworkDriver ServerNetworkDriver { get; set; }
|
||||||
|
|
||||||
|
public static bool StartServer(bool listenServer = true)
|
||||||
|
{
|
||||||
|
ConnectedClients = new List<NetworkConnection>(MaximumClients);
|
||||||
|
|
||||||
|
|
||||||
|
//var driver = Object.New(typeof(ENetDriver));
|
||||||
|
//ServerNetworkDriver = null;
|
||||||
|
NetworkLagDriver driver = Object.New<NetworkLagDriver>();
|
||||||
|
driver.Lag = 200f;
|
||||||
|
ServerNetworkDriver = driver;
|
||||||
|
|
||||||
|
server = NetworkPeer.CreatePeer(new NetworkConfig
|
||||||
|
{
|
||||||
|
NetworkDriver = driver,
|
||||||
|
ConnectionsLimit = MaximumClients,
|
||||||
|
MessagePoolSize = 2048,
|
||||||
|
MessageSize = MTU,
|
||||||
|
Address = "any",
|
||||||
|
Port = ServerPort
|
||||||
|
});
|
||||||
|
if (!server.Listen())
|
||||||
|
{
|
||||||
|
Console.PrintError("Failed to start the server.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Scripting.FixedUpdate += OnServerUpdate;
|
||||||
|
Scripting.Exit += Cleanup;
|
||||||
|
Level.ActorSpawned += OnServerActorSpawned;
|
||||||
|
|
||||||
|
NetworkedTypes = new List<Type>();
|
||||||
|
|
||||||
|
#if false
|
||||||
|
var assemblies = Utils.GetAssemblies();
|
||||||
|
|
||||||
|
foreach (Assembly assembly in assemblies)
|
||||||
|
{
|
||||||
|
// Skip common assemblies
|
||||||
|
string assemblyName = assembly.GetName().Name;
|
||||||
|
if (assemblyName == "System" ||
|
||||||
|
assemblyName.StartsWith("System.") ||
|
||||||
|
assemblyName.StartsWith("Mono.") ||
|
||||||
|
assemblyName == "mscorlib" ||
|
||||||
|
assemblyName == "Newtonsoft.Json" ||
|
||||||
|
assemblyName == "Snippets" ||
|
||||||
|
assemblyName == "netstandard" ||
|
||||||
|
assemblyName == "Anonymously Hosted DynamicMethods Assembly" ||
|
||||||
|
assemblyName.StartsWith("FlaxEngine.") ||
|
||||||
|
assemblyName.StartsWith("JetBrains.") ||
|
||||||
|
assemblyName.StartsWith("Microsoft.") ||
|
||||||
|
assemblyName.StartsWith("nunit."))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
foreach (Type type in assembly.GetTypes())
|
||||||
|
if (type.GetCustomAttributes().Any(x => x is NetworkedAttribute))
|
||||||
|
NetworkedTypes.Add(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (Type type in NetworkedTypes)
|
||||||
|
Console.Print("tracking networked type: " + type.Name);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (listenServer)
|
||||||
|
return ConnectServer(listenServer: true);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static NetworkMessage ServerBeginSendMessage()
|
||||||
|
{
|
||||||
|
NetworkMessage message = server.BeginSendMessage();
|
||||||
|
message.WriteByte((byte)NetworkMessageType.Message);
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void ServerEndSendMessage(ref NetworkMessage message, NetworkConnection connection, NetworkChannelType channelType = NetworkChannelType.Reliable)
|
||||||
|
{
|
||||||
|
server.EndSendMessage(channelType, message, connection);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static NetworkMessage ClientBeginSendMessage()
|
||||||
|
{
|
||||||
|
NetworkMessage message = client.BeginSendMessage();
|
||||||
|
message.WriteByte((byte)NetworkMessageType.Message);
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void ClientEndSendMessage(ref NetworkMessage message, NetworkChannelType channelType = NetworkChannelType.Reliable)
|
||||||
|
{
|
||||||
|
client.EndSendMessage(channelType, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void OnServerUpdate()
|
||||||
|
{
|
||||||
|
using Utilities.ScopeProfiler _ = Utilities.ProfileScope("NetworkManager_OnServerUpdate");
|
||||||
|
|
||||||
|
while (server.PopEvent(out NetworkEvent networkEvent))
|
||||||
|
switch (networkEvent.EventType)
|
||||||
|
{
|
||||||
|
case NetworkEventType.Connected:
|
||||||
|
{
|
||||||
|
Console.Print($"Client({networkEvent.Sender.ConnectionId}) is trying to connect");
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
IsServer = true;
|
||||||
|
if (GameModeManager.OnClientConnecting(networkEvent.Sender))
|
||||||
|
{
|
||||||
|
ConnectedClients.Add(networkEvent.Sender);
|
||||||
|
Console.Print(
|
||||||
|
$"Client({networkEvent.Sender.ConnectionId}) connected. Total clients: {ConnectedClients.Count}");
|
||||||
|
|
||||||
|
GameModeManager.OnClientConnected(networkEvent.Sender);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
Console.Print($"Client({networkEvent.Sender.ConnectionId}) connection refused");
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
IsServer = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case NetworkEventType.Disconnected:
|
||||||
|
case NetworkEventType.Timeout:
|
||||||
|
{
|
||||||
|
Console.Print($"Client({networkEvent.Sender.ConnectionId}) disconnected!");
|
||||||
|
|
||||||
|
ConnectedClients.Remove(networkEvent.Sender);
|
||||||
|
Console.Print("Connected clients: " + ConnectedClients.Count);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case NetworkEventType.Message:
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
IsServer = true;
|
||||||
|
OnNetworkMessage(ref networkEvent);
|
||||||
|
|
||||||
|
if (networkEvent.Message.Position > 0 &&
|
||||||
|
networkEvent.Message.Position < networkEvent.Message.Length)
|
||||||
|
{
|
||||||
|
string err =
|
||||||
|
$"Network message was not fully read: {networkEvent.Message.Position} / {networkEvent.Message.Length}.";
|
||||||
|
|
||||||
|
networkEvent.Message.Position = 0;
|
||||||
|
byte[] messageBytes = new byte[networkEvent.Message.Length];
|
||||||
|
unsafe
|
||||||
|
{
|
||||||
|
fixed (byte* messageBytePtr = &messageBytes[0])
|
||||||
|
networkEvent.Message.ReadBytes(messageBytePtr, (int)networkEvent.Message.Length);
|
||||||
|
}
|
||||||
|
|
||||||
|
string messageBytesStr = string.Join(", ",
|
||||||
|
messageBytes.Select(x => "0x" + ((int)x).ToString("X2")));
|
||||||
|
|
||||||
|
Console.PrintError(err + $"Message dump: {messageBytesStr}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
IsServer = false;
|
||||||
|
server.RecycleMessage(networkEvent.Message);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
throw new ArgumentOutOfRangeException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void OnServerActorSpawned(Actor actor)
|
||||||
|
{
|
||||||
|
//Console.Print($"actor spawned: {actor.Name} ({actor.TypeName})");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
50
Source/Game/GameMode/NetworkWorld.cs
Normal file
50
Source/Game/GameMode/NetworkWorld.cs
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using FlaxEngine;
|
||||||
|
using FlaxEngine.Assertions;
|
||||||
|
|
||||||
|
namespace Game;
|
||||||
|
|
||||||
|
public static class NetworkWorld
|
||||||
|
{
|
||||||
|
private class WorldState
|
||||||
|
{
|
||||||
|
public ulong frame;
|
||||||
|
public List<PlayerActor> actors;
|
||||||
|
public Dictionary<PlayerActor, PlayerLagCompStates> playerFrameHistory;
|
||||||
|
|
||||||
|
public WorldState()
|
||||||
|
{
|
||||||
|
actors = new List<PlayerActor>();
|
||||||
|
playerFrameHistory = new Dictionary<PlayerActor, PlayerLagCompStates>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private struct PlayerLagCompState
|
||||||
|
{
|
||||||
|
public Float3 position;
|
||||||
|
}
|
||||||
|
|
||||||
|
private class PlayerLagCompStates
|
||||||
|
{
|
||||||
|
public ulong oldestFrame;
|
||||||
|
private PlayerLagCompState[] states;
|
||||||
|
|
||||||
|
public PlayerLagCompStates(int frames)
|
||||||
|
{
|
||||||
|
states = new PlayerLagCompState[frames];
|
||||||
|
}
|
||||||
|
|
||||||
|
public PlayerLagCompState GetState(ulong frame)
|
||||||
|
{
|
||||||
|
Assert.IsTrue(frame >= oldestFrame);
|
||||||
|
ulong index = frame % (ulong)states.Length;
|
||||||
|
return states[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetState(PlayerLagCompState state, ulong frame)
|
||||||
|
{
|
||||||
|
ulong index = frame % (ulong)states.Length;
|
||||||
|
states[index] = state;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -135,7 +135,7 @@ namespace Game
|
|||||||
outVertices = finalPoints.ToArray();
|
outVertices = finalPoints.ToArray();
|
||||||
|
|
||||||
//verts = new QuickHull().QuickHull2(points);
|
//verts = new QuickHull().QuickHull2(points);
|
||||||
//outVertices = verts.ToArray();
|
//outVertices = verts.ToArray(); frf f
|
||||||
}
|
}
|
||||||
|
|
||||||
private MapEntity root;
|
private MapEntity root;
|
||||||
|
|||||||
@@ -35,12 +35,16 @@ namespace Game
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
public class PlayerActor : RigidBody
|
public class SomeActor : EmptyActor
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public class PlayerActor : RigidBody//, INetworkSerializable
|
||||||
{
|
{
|
||||||
private PlayerMovement playerMovement;
|
private PlayerMovement playerMovement;
|
||||||
private RigidBody playerRigidBody;
|
|
||||||
|
|
||||||
[NetworkReplicated]
|
//[NetworkReplicated]
|
||||||
public uint PlayerId = uint.MaxValue;
|
public uint PlayerId = uint.MaxValue;
|
||||||
|
|
||||||
/*public PlayerActor()
|
/*public PlayerActor()
|
||||||
@@ -65,12 +69,17 @@ namespace Game
|
|||||||
base.OnBeginPlay();
|
base.OnBeginPlay();
|
||||||
|
|
||||||
playerMovement = FindScript<PlayerMovement>();
|
playerMovement = FindScript<PlayerMovement>();
|
||||||
playerRigidBody = FindActor<RigidBody>();
|
//playerRigidBody = FindActor<RigidBody>();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//Console.Print("OnBeginPlay playerid: " + PlayerId.ToString());
|
||||||
|
//playerMovement.input = new PlayerInputNetwork();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void OnEnable()
|
public override void OnEnable()
|
||||||
{
|
{
|
||||||
// Trigger OnEnable manually, does not seem 8to propagate when parent gets enabled/disabled
|
// Trigger OnEnable manually, does not seem to propagate when parent gets enabled/disabled
|
||||||
playerMovement.Enabled = true;
|
playerMovement.Enabled = true;
|
||||||
//NetworkReplicator.AddObject(this);
|
//NetworkReplicator.AddObject(this);
|
||||||
}
|
}
|
||||||
@@ -81,29 +90,37 @@ namespace Game
|
|||||||
//NetworkReplicator.RemoveObject(this);
|
//NetworkReplicator.RemoveObject(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
[NetworkRpc(client: true)]
|
//[NetworkRpc(client: true)]
|
||||||
public void Initialize(uint playerId)
|
public void Initialize(uint playerId, Float3 newPosition, Float3 eulerAngles)
|
||||||
{
|
{
|
||||||
|
if (PlayerId == playerId) // FIXME
|
||||||
|
return;
|
||||||
|
|
||||||
|
FindActor("PlayerModel").IsActive = true;
|
||||||
|
IsActive = true;
|
||||||
|
|
||||||
PlayerId = playerId;
|
PlayerId = playerId;
|
||||||
playerMovement.SetInput(playerId);
|
playerMovement.SetInput(playerId);
|
||||||
if (playerId == NetworkManager.LocalClientId)
|
if (playerId == NetworkManager.LocalPlayerClientId)
|
||||||
{
|
{
|
||||||
FindActor("CameraHolder").IsActive = true;
|
FindActor("CameraHolder").IsActive = true;
|
||||||
//FindActor("ViewModelHolder").IsActive = true;
|
//FindActor("ViewModelHolder").IsActive = true;
|
||||||
FindActor("PlayerModel").IsActive = false;
|
FindActor("PlayerModel").IsActive = false;
|
||||||
}
|
}
|
||||||
else
|
SetPosition(newPosition);
|
||||||
FindActor("PlayerModel").IsActive = true;
|
SetRotation(eulerAngles);
|
||||||
IsActive = true;
|
//else
|
||||||
|
// FindActor("PlayerModel").IsActive = true;
|
||||||
|
//IsActive = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
[NetworkRpc(server: true)]
|
//[NetworkRpc(server: true)]
|
||||||
public void UpdateNetworkInput(ulong frame, Float4 viewDeltaXYMoveForwardRight, bool attacking, bool jumping)
|
public void UpdateNetworkInput(PlayerInputState inputState/*, Float4 viewDeltaXYMoveForwardRight, bool attacking, bool jumping*/)
|
||||||
{
|
{
|
||||||
if (playerMovement.input is not PlayerInputNetwork playerInputNetwork)
|
if (playerMovement.input is not PlayerInputNetwork playerInputNetwork)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
PlayerInputState inputState = new PlayerInputState(frame, viewDeltaXYMoveForwardRight.X, viewDeltaXYMoveForwardRight.Y, viewDeltaXYMoveForwardRight.Z, viewDeltaXYMoveForwardRight.W, attacking, jumping);
|
//PlayerInputState inputState = new PlayerInputState(frame, viewDeltaXYMoveForwardRight.X, viewDeltaXYMoveForwardRight.Y, viewDeltaXYMoveForwardRight.Z, viewDeltaXYMoveForwardRight.W, attacking, jumping);
|
||||||
playerInputNetwork.currentState.input = inputState;
|
playerInputNetwork.currentState.input = inputState;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -117,7 +134,12 @@ namespace Game
|
|||||||
playerMovement.ResetRotation(eulerAngles);
|
playerMovement.ResetRotation(eulerAngles);
|
||||||
}
|
}
|
||||||
|
|
||||||
[NetworkRpc(client: true)]
|
public Float3 GetRotation()
|
||||||
|
{
|
||||||
|
return playerMovement.viewAngles;
|
||||||
|
}
|
||||||
|
|
||||||
|
//[NetworkRpc(client: true)]
|
||||||
public void Teleport(Float3 newPosition, Float3 eulerAngles)
|
public void Teleport(Float3 newPosition, Float3 eulerAngles)
|
||||||
{
|
{
|
||||||
SetPosition(newPosition);
|
SetPosition(newPosition);
|
||||||
|
|||||||
@@ -87,6 +87,11 @@ namespace Game
|
|||||||
public const byte DemoVer = 1;
|
public const byte DemoVer = 1;
|
||||||
public PlayerState currentState;
|
public PlayerState currentState;
|
||||||
public ulong frame;
|
public ulong frame;
|
||||||
|
//public ulong oldestFrame;
|
||||||
|
|
||||||
|
private PlayerState[] states = new PlayerState[120];
|
||||||
|
|
||||||
|
public virtual bool Predict => false;
|
||||||
|
|
||||||
public virtual void OnUpdate()
|
public virtual void OnUpdate()
|
||||||
{
|
{
|
||||||
@@ -98,12 +103,43 @@ namespace Game
|
|||||||
|
|
||||||
public virtual void OnEndFrame()
|
public virtual void OnEndFrame()
|
||||||
{
|
{
|
||||||
|
states[frame % 120] = 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++;
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual void RecordCurrentActorState(PlayerActorState actorState)
|
public virtual void RecordCurrentActorState(PlayerActorState actorState)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool GetState(ulong frame, out PlayerInputState inputState, out PlayerActorState actorState)
|
||||||
|
{
|
||||||
|
int frameIndex = (int)frame % 120;
|
||||||
|
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, ref PlayerInputState inputState, ref PlayerActorState actorState)
|
||||||
|
{
|
||||||
|
int frameIndex = (int)frame % 120;
|
||||||
|
states[frameIndex].input = inputState;
|
||||||
|
states[frameIndex].input.frame = frame;
|
||||||
|
states[frameIndex].actor = actorState;
|
||||||
|
}
|
||||||
|
|
||||||
public PlayerInputState GetCurrentInputState()
|
public PlayerInputState GetCurrentInputState()
|
||||||
{
|
{
|
||||||
return currentState.input;
|
return currentState.input;
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.IO.Compression;
|
using System.IO.Compression;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using Console = Game.Console;
|
using Console = Game.Console;
|
||||||
|
|
||||||
@@ -26,49 +28,46 @@ namespace Game
|
|||||||
if (!File.Exists(demoPath))
|
if (!File.Exists(demoPath))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
int expectedPlayerInputStateSize = Marshal.SizeOf(typeof(PlayerInputState));
|
int expectedPlayerInputStateSize = Unsafe.SizeOf<PlayerInputState>();
|
||||||
|
|
||||||
FileStream fileStream = File.OpenRead(demoPath);
|
Stopwatch sw = Stopwatch.StartNew();
|
||||||
GZipStream stream = new GZipStream(fileStream, CompressionMode.Decompress);
|
|
||||||
|
using FileStream fileStream = File.OpenRead(demoPath);
|
||||||
|
using GZipStream stream = new GZipStream(fileStream, CompressionMode.Decompress);
|
||||||
|
|
||||||
int ver = stream.ReadByte();
|
int ver = stream.ReadByte();
|
||||||
int inputStateSize = stream.ReadByte();
|
int inputStateSize = stream.ReadByte();
|
||||||
if (ver != DemoVer && inputStateSize != expectedPlayerInputStateSize)
|
if (ver != DemoVer || inputStateSize != expectedPlayerInputStateSize)
|
||||||
{
|
{
|
||||||
Console.Print("demover mismatch: version " + ver + " != " + DemoVer + ", inputStateSize " +
|
Console.Print("demover mismatch: version " + ver + " != " + DemoVer + ", inputStateSize " +
|
||||||
inputStateSize + " != " + Marshal.SizeOf(typeof(PlayerInputState)));
|
inputStateSize + " != " + Unsafe.SizeOf<PlayerInputState>());
|
||||||
stream.Close();
|
stream.Close();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: bench and compare to unsafe ptr version of this:
|
Span<byte> b = stackalloc byte[expectedPlayerInputStateSize];
|
||||||
// https://stackoverflow.com/questions/17549123/c-sharp-performance-using-unsafe-pointers-instead-of-intptr-and-marshal/29836312#29836312
|
|
||||||
T RawDeserialize<T>(byte[] rawData, int position)
|
|
||||||
{
|
|
||||||
int rawsize = Marshal.SizeOf(typeof(T));
|
|
||||||
if (rawsize > rawData.Length - position)
|
|
||||||
throw new ArgumentException("Not enough data to fill struct. Array length from position: " +
|
|
||||||
(rawData.Length - position) + ", Struct length: " + rawsize);
|
|
||||||
IntPtr buffer = Marshal.AllocHGlobal(rawsize);
|
|
||||||
Marshal.Copy(rawData, position, buffer, rawsize);
|
|
||||||
T retobj = (T)Marshal.PtrToStructure(buffer, typeof(T));
|
|
||||||
Marshal.FreeHGlobal(buffer);
|
|
||||||
return retobj;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
byte[] b = new byte[expectedPlayerInputStateSize];
|
int bytesLeftInBuffer = expectedPlayerInputStateSize;
|
||||||
int readBytes = stream.Read(b, 0, b.Length);
|
do
|
||||||
if (readBytes < expectedPlayerInputStateSize)
|
{
|
||||||
|
int readBytes = stream.Read(b.Slice(expectedPlayerInputStateSize - bytesLeftInBuffer, bytesLeftInBuffer));
|
||||||
|
if (readBytes == 0)
|
||||||
break;
|
break;
|
||||||
|
bytesLeftInBuffer -= readBytes;
|
||||||
|
} while (bytesLeftInBuffer > 0);
|
||||||
|
|
||||||
buffer.Add(RawDeserialize<PlayerInputState>(b, 0));
|
if (bytesLeftInBuffer > 0)
|
||||||
|
break; // EOF;
|
||||||
|
|
||||||
|
buffer.Add(MemoryMarshal.Read<PlayerInputState>(b));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sw.Stop();
|
||||||
|
|
||||||
bufferEnumerable = buffer.GetEnumerator();
|
bufferEnumerable = buffer.GetEnumerator();
|
||||||
|
|
||||||
Console.Print("demo numstates: " + buffer.Count);
|
Console.Print($"Demo parse time {sw.Elapsed.TotalMilliseconds}ms, frames: {buffer.Count} ");
|
||||||
|
|
||||||
OnEndFrame(); // advances to first frame
|
OnEndFrame(); // advances to first frame
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.IO.Compression;
|
using System.IO.Compression;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using FlaxEngine;
|
using FlaxEngine;
|
||||||
using FlaxEngine.Networking;
|
using FlaxEngine.Networking;
|
||||||
@@ -12,16 +14,19 @@ namespace Game
|
|||||||
public class PlayerInputLocal : PlayerInput
|
public class PlayerInputLocal : PlayerInput
|
||||||
{
|
{
|
||||||
protected List<PlayerInputState> buffer = new List<PlayerInputState>();
|
protected List<PlayerInputState> buffer = new List<PlayerInputState>();
|
||||||
protected GZipStream demoFileStream;
|
protected GZipStream demoStream;
|
||||||
protected FileStream demoFileStream2;
|
protected FileStream demoFileStream;
|
||||||
|
|
||||||
private PlayerActor playerActor;
|
private PlayerActor playerActor;
|
||||||
//public bool IsNetworked => NetworkManager.client != null;
|
public bool IsNetworked => NetworkManager.client != null;
|
||||||
|
private long flushedFrames = 0;
|
||||||
|
|
||||||
/*public PlayerInputLocal()
|
/*public PlayerInputLocal()
|
||||||
{
|
{
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
|
public override bool Predict => true;
|
||||||
|
|
||||||
public PlayerInputLocal(PlayerActor playerActor, string demoPath)
|
public PlayerInputLocal(PlayerActor playerActor, string demoPath)
|
||||||
{
|
{
|
||||||
this.playerActor = playerActor;
|
this.playerActor = playerActor;
|
||||||
@@ -29,15 +34,13 @@ namespace Game
|
|||||||
if (!demoFolder.Exists)
|
if (!demoFolder.Exists)
|
||||||
Directory.CreateDirectory(demoFolder.FullName);
|
Directory.CreateDirectory(demoFolder.FullName);
|
||||||
|
|
||||||
demoFileStream2 = File.Open(demoPath, FileMode.Create, FileAccess.Write);
|
demoFileStream = File.Open(demoPath, FileMode.Create, FileAccess.Write);
|
||||||
demoFileStream = new GZipStream(demoFileStream2, CompressionMode.Compress);
|
demoStream = new GZipStream(demoFileStream, CompressionMode.Compress);
|
||||||
//stream.Position = 0;
|
demoStream.WriteByte(DemoVer);
|
||||||
//stream.SetLength(0);
|
demoStream.WriteByte((byte)Unsafe.SizeOf<PlayerInputState>());
|
||||||
demoFileStream.WriteByte(DemoVer);
|
|
||||||
demoFileStream.WriteByte((byte)Marshal.SizeOf(typeof(PlayerInputState)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsRecording => demoFileStream != null;
|
public bool IsRecording => demoStream != null;
|
||||||
|
|
||||||
public override void OnUpdate()
|
public override void OnUpdate()
|
||||||
{
|
{
|
||||||
@@ -82,11 +85,12 @@ namespace Game
|
|||||||
|
|
||||||
if (playerActor != null)
|
if (playerActor != null)
|
||||||
{
|
{
|
||||||
playerActor.UpdateNetworkInput(currentState.input.frame, new Float4(currentState.input.viewDeltaX, currentState.input.viewDeltaY, currentState.input.moveForward, currentState.input.moveRight), currentState.input.attacking, currentState.input.jumping);
|
//playerActor.UpdateNetworkInput(currentState.input.frame, new Float4(currentState.input.viewDeltaX, currentState.input.viewDeltaY, currentState.input.moveForward, currentState.input.moveRight), currentState.input.attacking, currentState.input.jumping);
|
||||||
|
|
||||||
}
|
}
|
||||||
//playerActor.UpdateNetworkInput(currentState.input.frame, currentState.input.viewDeltaX, currentState.input.viewDeltaY, currentState.input.moveForward, currentState.input.moveRight, currentState.input.attacking, currentState.input.jumping, currentState.input.verificationPosition, currentState.input.verificationVelocity, currentState.input.verificationViewAngles, currentState.input.verificationOrientation);
|
//playerActor.UpdateNetworkInput(currentState.input.frame, currentState.input.viewDeltaX, currentState.input.viewDeltaY, currentState.input.moveForward, currentState.input.moveRight, currentState.input.attacking, currentState.input.jumping, currentState.input.verificationPosition, currentState.input.verificationVelocity, currentState.input.verificationViewAngles, currentState.input.verificationOrientation);
|
||||||
|
|
||||||
/*if (IsNetworked)
|
if (IsNetworked)
|
||||||
{
|
{
|
||||||
var message = NetworkManager.ClientBeginSendMessage();
|
var message = NetworkManager.ClientBeginSendMessage();
|
||||||
message.WriteByte((byte)GameModeMessageType.PlayerInput);
|
message.WriteByte((byte)GameModeMessageType.PlayerInput);
|
||||||
@@ -98,13 +102,13 @@ namespace Game
|
|||||||
message.WriteBoolean(currentState.input.attacking);
|
message.WriteBoolean(currentState.input.attacking);
|
||||||
message.WriteBoolean(currentState.input.jumping);
|
message.WriteBoolean(currentState.input.jumping);
|
||||||
NetworkManager.ClientEndSendMessage(ref message);
|
NetworkManager.ClientEndSendMessage(ref message);
|
||||||
}*/
|
}
|
||||||
|
|
||||||
// Reset anything accumulatable here
|
// Reset anything accumulatable here
|
||||||
currentState.input.viewDeltaX = 0;
|
currentState.input.viewDeltaX = 0;
|
||||||
currentState.input.viewDeltaY = 0;
|
currentState.input.viewDeltaY = 0;
|
||||||
|
|
||||||
frame++;
|
base.OnEndFrame();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void RecordCurrentActorState(PlayerActorState actorState)
|
public override void RecordCurrentActorState(PlayerActorState actorState)
|
||||||
@@ -122,24 +126,21 @@ namespace Game
|
|||||||
if (!IsRecording)
|
if (!IsRecording)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
byte[] RawSerialize(object anything)
|
Stopwatch sw = Stopwatch.StartNew();
|
||||||
|
|
||||||
|
Span<byte> bytes = stackalloc byte[Unsafe.SizeOf<PlayerInputState>()];
|
||||||
|
foreach (ref PlayerInputState state in CollectionsMarshal.AsSpan(buffer))
|
||||||
{
|
{
|
||||||
int rawSize = Marshal.SizeOf(anything);
|
MemoryMarshal.Write(bytes, ref state);
|
||||||
IntPtr buffer = Marshal.AllocHGlobal(rawSize);
|
demoStream.Write(bytes);
|
||||||
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)
|
sw.Stop();
|
||||||
{
|
|
||||||
byte[] bytes = RawSerialize(state);
|
|
||||||
demoFileStream.Write(bytes, 0, bytes.Length * sizeof(byte));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
flushedFrames += buffer.Count;
|
||||||
buffer.Clear();
|
buffer.Clear();
|
||||||
|
|
||||||
|
FlaxEngine.Debug.Write(LogType.Info, $"Wrote demo in {sw.Elapsed.TotalMilliseconds}ms, frames: {flushedFrames}");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void StopRecording()
|
public void StopRecording()
|
||||||
@@ -148,10 +149,10 @@ namespace Game
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
FlushDemo();
|
FlushDemo();
|
||||||
|
demoStream.Close();
|
||||||
|
demoStream = null;
|
||||||
demoFileStream.Close();
|
demoFileStream.Close();
|
||||||
demoFileStream = null;
|
demoFileStream = null;
|
||||||
|
|
||||||
Debug.Write(LogType.Info, "demo, wrote states: " + buffer.Count);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2,5 +2,12 @@
|
|||||||
{
|
{
|
||||||
public class PlayerInputNetwork : PlayerInput
|
public class PlayerInputNetwork : PlayerInput
|
||||||
{
|
{
|
||||||
|
public override bool Predict => true;
|
||||||
|
|
||||||
|
public override void OnEndFrame()
|
||||||
|
{
|
||||||
|
currentState.input.frame = frame;
|
||||||
|
base.OnEndFrame();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
using FlaxEngine;
|
using FlaxEngine;
|
||||||
using FlaxEngine.Assertions;
|
using FlaxEngine.Assertions;
|
||||||
using FlaxEngine.Networking;
|
using FlaxEngine.Networking;
|
||||||
@@ -79,11 +80,11 @@ namespace Game
|
|||||||
|
|
||||||
private readonly InputEvent onExit = new InputEvent("Exit");
|
private readonly InputEvent onExit = new InputEvent("Exit");
|
||||||
|
|
||||||
private readonly bool predicting = false;
|
private bool predicting = false;
|
||||||
|
|
||||||
private readonly List<PhysicsColliderActor> touchingActors = new List<PhysicsColliderActor>();
|
private readonly List<PhysicsColliderActor> touchingActors = new List<PhysicsColliderActor>();
|
||||||
public int currentInputFrame;
|
//public int currentInputFrame;
|
||||||
private int currentInputFrame2;
|
//private int currentInputFrame2;
|
||||||
|
|
||||||
private Float3 currentVelocity;
|
private Float3 currentVelocity;
|
||||||
public PlayerInput input;
|
public PlayerInput input;
|
||||||
@@ -92,7 +93,7 @@ namespace Game
|
|||||||
|
|
||||||
private bool jumped;
|
private bool jumped;
|
||||||
|
|
||||||
private int lastInputFrame;
|
//private int lastInputFrame;
|
||||||
private float lastJumped = -1f;
|
private float lastJumped = -1f;
|
||||||
private float lastLanded = -1f;
|
private float lastLanded = -1f;
|
||||||
private int numJumps;
|
private int numJumps;
|
||||||
@@ -105,7 +106,7 @@ namespace Game
|
|||||||
private Actor rootActor;
|
private Actor rootActor;
|
||||||
private float startupTime;
|
private float startupTime;
|
||||||
|
|
||||||
private Float3 viewAngles;
|
public Float3 viewAngles;
|
||||||
private Float3 viewAnglesLastFrame;
|
private Float3 viewAnglesLastFrame;
|
||||||
|
|
||||||
[Limit(0, 9000)]
|
[Limit(0, 9000)]
|
||||||
@@ -114,7 +115,7 @@ namespace Game
|
|||||||
|
|
||||||
private static Float3 Gravity { get; } = new Float3(0, -800.0f, 0f);
|
private static Float3 Gravity { get; } = new Float3(0, -800.0f, 0f);
|
||||||
|
|
||||||
//private Float3 safePosition;
|
//private Float3 safePosition;444 rg
|
||||||
|
|
||||||
[NetworkReplicated]
|
[NetworkReplicated]
|
||||||
public uint PlayerId = 0;
|
public uint PlayerId = 0;
|
||||||
@@ -173,7 +174,7 @@ namespace Game
|
|||||||
Assert.IsTrue(playerId != uint.MaxValue);
|
Assert.IsTrue(playerId != uint.MaxValue);
|
||||||
|
|
||||||
PlayerId = playerId;
|
PlayerId = playerId;
|
||||||
if (PlayerId == NetworkManager.LocalClientId)//if (NetworkReplicator.GetObjectRole(this.Parent) == NetworkObjectRole.OwnedAuthoritative)// if (playerId == NetworkManager.LocalPlayerClientId)
|
if (PlayerId == NetworkManager.LocalPlayerClientId)//if (NetworkReplicator.GetObjectRole(this.Parent) == NetworkObjectRole.OwnedAuthoritative)// if (playerId == NetworkManager.LocalPlayerClientId)
|
||||||
{
|
{
|
||||||
Console.Print("local player?: " + playerId.ToString());
|
Console.Print("local player?: " + playerId.ToString());
|
||||||
string demoPath = System.IO.Path.Combine(AssetManager.DemoPath, $"{DateTimeOffset.Now.UtcTicks}.gdem");
|
string demoPath = System.IO.Path.Combine(AssetManager.DemoPath, $"{DateTimeOffset.Now.UtcTicks}.gdem");
|
||||||
@@ -290,24 +291,26 @@ namespace Game
|
|||||||
viewPitch = viewPitch,
|
viewPitch = viewPitch,
|
||||||
viewRoll = viewRoll
|
viewRoll = viewRoll
|
||||||
});*/
|
});*/
|
||||||
currentInputFrame2++;
|
//currentInputFrame2++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private ulong lastPredictedFrame = 0;
|
||||||
public override void OnFixedUpdate()
|
public override void OnFixedUpdate()
|
||||||
{
|
{
|
||||||
if (input is PlayerInputDemo)
|
PlayerInputDemo demoInput = input as PlayerInputDemo;
|
||||||
input.OnUpdate();
|
if (demoInput != null)
|
||||||
|
demoInput.OnUpdate();
|
||||||
|
|
||||||
float deltadif = Time.DeltaTime - 1.0f / Time.PhysicsFPS;
|
float timeDeltaDiff = Time.DeltaTime - 1.0f / Time.PhysicsFPS;
|
||||||
//if (Math.Abs(deltadif) > 0.0001f)
|
if (Math.Abs(timeDeltaDiff) > 0.0001f)
|
||||||
// Console.Print("drift: " + deltadif);
|
Console.Print("Time.DeltaTime is not stable: " + timeDeltaDiff);
|
||||||
|
|
||||||
input.OnFixedUpdate();
|
input.OnFixedUpdate();
|
||||||
PlayerInputState inputState = input.GetCurrentInputState();
|
PlayerInputState inputState = input.GetCurrentInputState();
|
||||||
|
|
||||||
if (input is PlayerInputDemo)
|
if (demoInput != null && demoInput.IsPlaying)
|
||||||
{
|
{
|
||||||
ApplyInputToCamera(inputState, false);
|
ApplyInputToCamera(inputState, true);
|
||||||
|
|
||||||
// Verify view angles first
|
// Verify view angles first
|
||||||
if (demoDeltasVerify)
|
if (demoDeltasVerify)
|
||||||
@@ -316,30 +319,29 @@ namespace Game
|
|||||||
float viewAnglesDelta = (viewAngles - verifAngles).Length;
|
float viewAnglesDelta = (viewAngles - verifAngles).Length;
|
||||||
if (viewAnglesDelta > 0.00001)
|
if (viewAnglesDelta > 0.00001)
|
||||||
{
|
{
|
||||||
Console.PrintError($"Demo verification failed, view angles delta: {viewAnglesDelta}, viewAngles:{viewAngles}, verif:{verifAngles}");
|
Console.Print($"Demo verification failed, view angles delta: {viewAnglesDelta}, viewAngles:{viewAngles}, verif:{verifAngles}");
|
||||||
if (demoDeltasCorrect)
|
if (demoDeltasCorrect)
|
||||||
SetCameraEulerAngles(verifAngles, false);
|
SetCameraEulerAngles(verifAngles, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
SimulatePlayerMovement(inputState);
|
SimulatePlayerMovement(inputState);
|
||||||
|
|
||||||
if (input is PlayerInputDemo && demoDeltasVerify)
|
if (demoDeltasVerify)
|
||||||
{
|
{
|
||||||
// verify
|
// verify
|
||||||
float positionDelta = (Actor.Position - inputState.verificationPosition).Length;
|
float positionDelta = (Actor.Position - inputState.verificationPosition).Length;
|
||||||
if (positionDelta > 0.00001)
|
if (positionDelta > 0.00001)
|
||||||
Console.PrintError("Demo verification failed, position delta: " + positionDelta);
|
Console.Print("Demo verification failed, position delta: " + positionDelta);
|
||||||
|
|
||||||
float velocityDelta = (currentVelocity - inputState.verificationVelocity).Length;
|
float velocityDelta = (currentVelocity - inputState.verificationVelocity).Length;
|
||||||
if (velocityDelta > 0.00001)
|
if (velocityDelta > 0.00001)
|
||||||
Console.PrintError("Demo verification failed, velocity delta: " + velocityDelta);
|
Console.Print("Demo verification failed, velocity delta: " + velocityDelta);
|
||||||
|
|
||||||
float orientationDelta = (rootActor.Orientation - inputState.verificationOrientation).Length;
|
float orientationDelta = (rootActor.Orientation - inputState.verificationOrientation).Length;
|
||||||
if (orientationDelta > 0.00001)
|
if (orientationDelta > 0.00001)
|
||||||
{
|
{
|
||||||
Console.PrintError("Demo verification failed, orientation delta: " + orientationDelta);
|
Console.Print("Demo verification failed, orientation delta: " + orientationDelta);
|
||||||
if (demoDeltasCorrect)
|
if (demoDeltasCorrect)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@@ -354,6 +356,39 @@ namespace Game
|
|||||||
rootActor.Orientation = inputState.verificationOrientation;
|
rootActor.Orientation = inputState.verificationOrientation;
|
||||||
}*/
|
}*/
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (input.Predict && GameModeManager.ClientFrame > 0 && GameModeManager.ServerFrame > 0)
|
||||||
|
{
|
||||||
|
predicting = true;
|
||||||
|
for (ulong currentFrame = GameModeManager.ServerFrame; currentFrame < GameModeManager.ClientFrame - 1; currentFrame++)
|
||||||
|
{
|
||||||
|
if (!input.GetState(currentFrame, out var pastInputState, out var pastActorState))
|
||||||
|
{
|
||||||
|
Console.Print($"predict failure: {currentFrame}");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentFrame == GameModeManager.ServerFrame)
|
||||||
|
{
|
||||||
|
Actor.Position = pastActorState.position;
|
||||||
|
currentVelocity = pastActorState.velocity;
|
||||||
|
rootActor.Orientation = pastActorState.orientation;
|
||||||
|
viewAngles = new Float3(pastActorState.viewAngles.Y, pastActorState.viewAngles.X, pastActorState.viewAngles.Z);
|
||||||
|
}
|
||||||
|
SimulatePlayerMovement(pastInputState);
|
||||||
|
|
||||||
|
//Console.Print($"predicted: {currentFrame}");
|
||||||
|
}
|
||||||
|
predicting = false;
|
||||||
|
//Console.Print($"current: {inputState.frame}");
|
||||||
|
//if (GameModeManager.ClientFrame - GameModeManager.ServerFrame > 0)
|
||||||
|
// Console.Print($"current diff: {GameModeManager.ClientFrame - GameModeManager.ServerFrame}");
|
||||||
|
}
|
||||||
|
|
||||||
|
SimulatePlayerMovement(inputState);
|
||||||
|
}
|
||||||
|
|
||||||
input.RecordCurrentActorState(new PlayerActorState
|
input.RecordCurrentActorState(new PlayerActorState
|
||||||
{
|
{
|
||||||
@@ -365,8 +400,8 @@ namespace Game
|
|||||||
input.OnEndFrame();
|
input.OnEndFrame();
|
||||||
|
|
||||||
|
|
||||||
lastInputFrame = currentInputFrame;
|
//lastInputFrame = currentInputFrame;
|
||||||
currentInputFrame++;
|
//currentInputFrame++;
|
||||||
|
|
||||||
viewAnglesLastFrame = viewAngles;
|
viewAnglesLastFrame = viewAngles;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,6 +28,13 @@ public class GameTarget : GameProjectTarget
|
|||||||
Modules.Add("Game");
|
Modules.Add("Game");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override void SetupTargetEnvironment(BuildOptions options)
|
||||||
|
{
|
||||||
|
base.SetupTargetEnvironment(options);
|
||||||
|
|
||||||
|
options.LinkEnv.UseFastPDBLinking = true;
|
||||||
|
}
|
||||||
|
|
||||||
public override string GetOutputFilePath(BuildOptions options, TargetOutputType? outputType = null)
|
public override string GetOutputFilePath(BuildOptions options, TargetOutputType? outputType = null)
|
||||||
{
|
{
|
||||||
if (!Environment.CommandLine.Contains("Cooker")) // Hacky way to detect if this is run during cooking
|
if (!Environment.CommandLine.Contains("Cooker")) // Hacky way to detect if this is run during cooking
|
||||||
|
|||||||
Reference in New Issue
Block a user