This commit is contained in:
2025-03-28 15:24:44 +02:00
parent cc9eacca8d
commit 6783efdb6a
25 changed files with 1077 additions and 364 deletions

View File

@@ -4616,301 +4616,209 @@
}
// entity 10
{
"origin" "612 -512 72"
"classname" "ammo_shells"
}
// entity 11
{
"origin" "668 -512 72"
"classname" "ammo_bullets"
}
// entity 12
{
"origin" "128 -464 72"
"classname" "item_health_mega"
}
// entity 13
// entity 11
{
"classname" "weapon_rocketlauncher"
"origin" "-384 -448 144"
}
// entity 14
// entity 12
{
"classname" "item_armor_green"
"origin" "-544 -304 144"
}
// entity 15
// entity 13
{
"classname" "item_ammo_lightning"
"origin" "-192 32 144"
}
// entity 16
{
"classname" "ammo_shells"
"origin" "492 -128 376"
}
// entity 17
// entity 14
{
"classname" "item_ammo_lightning"
"origin" "436 -128 376"
}
// entity 18
{
"classname" "weapon_shotgun"
"origin" "128 0 -48"
}
// entity 19
// entity 15
{
"classname" "item_ammo_rockets"
"origin" "56 -352 -48"
}
// entity 20
// entity 16
{
"classname" "info_player_deathmatch"
"origin" "-608 -304 152"
}
// entity 21
// entity 17
{
"origin" "928 -552 144"
"classname" "item_health_5"
}
// entity 22
// entity 18
{
"origin" "144 -352 -40"
"angle" "90"
"classname" "info_player_deathmatch"
}
// entity 23
// entity 19
{
"classname" "item_health_25"
"origin" "784 -224 144"
}
// entity 24
// entity 20
{
"classname" "item_health_25"
"origin" "-32 -96 -48"
}
// entity 25
// entity 21
{
"classname" "info_player_deathmatch"
"angle" "225"
"origin" "776 12 384"
}
// entity 26
// entity 22
{
"angle" "315"
"classname" "info_player_deathmatch"
"origin" "-116 356 152"
}
// entity 27
// entity 23
{
"classname" "weapon_grenadelauncher"
"origin" "928 -448 144"
}
// entity 28
// entity 24
{
"classname" "item_ammo_rockets"
"origin" "776 -520 376"
}
// entity 29
// entity 25
{
"classname" "weapon_lightning"
"origin" "-228 288 320"
}
// entity 30
// entity 26
{
"origin" "368 120 152"
"angle" "270"
"targetname" "upper_sg"
"classname" "info_teleport_destination"
}
// entity 31
// entity 27
{
"origin" "160 -464 376"
"classname" "weapon_stake"
}
// entity 32
// entity 28
{
"origin" "448 32 376"
"classname" "weapon_rocketlauncher"
}
// entity 33
// entity 29
{
"origin" "148 312 448"
"targetname" "jump1"
"classname" "target_position"
}
// entity 34
// entity 30
{
"origin" "980 -160 152"
"angle" "180"
"classname" "info_player_deathmatch"
}
// entity 35
// entity 31
{
"origin" "-144 -184 144"
"classname" "item_health_25"
}
// entity 36
// entity 32
{
"spawnflags" "0"
"classname" "item_health_25"
"origin" "320 -464 376"
}
// entity 37
// entity 33
{
"classname" "item_health_5"
"origin" "928 -504 144"
}
// entity 38
// entity 34
{
"classname" "item_health_5"
"origin" "928 -344 144"
}
// entity 39
// entity 35
{
"classname" "info_player_deathmatch"
"angle" "90"
"origin" "-384 -130 368"
}
// entity 40
// entity 36
{
"origin" "928 -392 144"
"classname" "item_health_5"
}
// entity 41
// entity 37
{
"origin" "-324 -304 152"
"targetname" "25armour"
"classname" "info_teleport_destination"
"angle" "180"
}
// entity 42
// entity 38
{
"classname" "info_teleport_destination"
"targetname" "rg"
"origin" "16 -464 384"
}
// entity 43
// entity 39
{
"classname" "item_ammo_stakes"
"origin" "400 -128 144"
}
// entity 44
{
"classname" "light"
"origin" "224 -464 220"
}
// entity 45
{
"classname" "light"
"origin" "32 -464 220"
}
// entity 46
{
"classname" "light"
"origin" "432 -464 196"
}
// entity 47
{
"classname" "light"
"origin" "816 -656 272"
}
// entity 48
{
"classname" "light"
"origin" "624 -48 288"
}
// entity 49
{
"classname" "light"
"origin" "656 -464 280"
}
// entity 50
{
"classname" "light"
"origin" "-560 -304 284"
}
// entity 51
{
"classname" "light"
"origin" "-160 304 388"
}
// entity 52
{
"classname" "light"
"origin" "96 312 492"
}
// entity 53
{
"classname" "light"
"origin" "448 0 492"
}
// entity 54
{
"classname" "light"
"origin" "712 -120 492"
}
// entity 55
{
"classname" "light"
"origin" "432 -464 486"
}
// entity 56
{
"classname" "light"
"origin" "256 -464 532"
}
// entity 57
{
"classname" "light"
"origin" "-384 -104 416"
}
// entity 58
{
"classname" "light"
"origin" "-384 -96 384"
"_color" "0.85 0.2 0.2"
"light" "200"
"radius" "32"
}
// entity 59
// entity 40
{
"classname" "light"
"origin" "120 536 496"
}
// entity 60
// entity 41
{
"classname" "item_armor_green"
"origin" "944 0 144"
}
// entity 42
{
"classname" "item_health_50"
"origin" "128 544 376"
}
// entity 43
{
"classname" "target_position"
"origin" "160 40 504"
"targetname" "light_target1"
}
// entity 44
{
"classname" "info_player_deathmatch"
"origin" "-496 -304 152"
"angle" "180"
}
// entity 45
{
"classname" "light"
"origin" "704 -448 492"
"origin" "-136 0 284"
}
// entity 61
// entity 46
{
"classname" "light"
"origin" "64 -464 532"
"origin" "-384 -104 416"
}
// entity 62
// entity 47
{
"classname" "light"
"origin" "-384 -304 284"
"origin" "-560 -304 284"
}
// entity 63
{
"classname" "light"
"origin" "432 -464 96"
"_color" "0.752941 0.752941 0"
"light" "200"
"radius" "32"
}
// entity 64
{
"classname" "light"
"origin" "944 0 168"
"_color" "0 0.752941 0"
"light" "200"
"radius" "32"
}
// entity 65
// entity 48
{
"classname" "light"
"origin" "-544 -304 168"
@@ -4918,40 +4826,25 @@
"light" "200"
"radius" "32"
}
// entity 66
// entity 49
{
"classname" "light"
"origin" "424 0 252"
"origin" "-384 -304 284"
}
// entity 67
// entity 50
{
"classname" "light"
"origin" "-136 0 284"
}
// entity 68
{
"classname" "light"
"origin" "64 -348 24"
}
// entity 69
{
"classname" "item_armor_green"
"origin" "944 0 144"
}
// entity 70
{
"classname" "light"
"origin" "128 -464 96"
"_color" "0 0 0.752941"
"origin" "-384 -96 384"
"_color" "0.85 0.2 0.2"
"light" "200"
"radius" "32"
}
// entity 71
// entity 51
{
"classname" "item_health_50"
"origin" "128 544 376"
"classname" "light"
"origin" "96 312 492"
}
// entity 72
// entity 52
{
"classname" "light"
"origin" "160 144 592"
@@ -4959,15 +4852,122 @@
"radius" "0"
"light" "600"
}
// entity 53
{
"classname" "light"
"origin" "-160 304 388"
}
// entity 54
{
"origin" "612 -512 72"
"classname" "ammo_shells"
}
// entity 55
{
"origin" "668 -512 72"
"classname" "ammo_bullets"
}
// entity 56
{
"classname" "ammo_shells"
"origin" "492 -128 376"
}
// entity 57
{
"classname" "weapon_shotgun"
"origin" "128 0 -48"
}
// entity 58
{
"classname" "light"
"origin" "224 -464 220"
}
// entity 59
{
"classname" "light"
"origin" "32 -464 220"
}
// entity 60
{
"classname" "light"
"origin" "432 -464 196"
}
// entity 61
{
"classname" "light"
"origin" "816 -656 272"
}
// entity 62
{
"classname" "light"
"origin" "624 -48 288"
}
// entity 63
{
"classname" "light"
"origin" "656 -464 280"
}
// entity 64
{
"classname" "light"
"origin" "448 0 492"
}
// entity 65
{
"classname" "light"
"origin" "712 -120 492"
}
// entity 66
{
"classname" "light"
"origin" "432 -464 486"
}
// entity 67
{
"classname" "light"
"origin" "256 -464 532"
}
// entity 68
{
"classname" "light"
"origin" "704 -448 492"
}
// entity 69
{
"classname" "light"
"origin" "64 -464 532"
}
// entity 70
{
"classname" "light"
"origin" "432 -464 96"
"_color" "0.752941 0.752941 0"
"light" "200"
"radius" "32"
}
// entity 71
{
"classname" "light"
"origin" "944 0 168"
"_color" "0 0.752941 0"
"light" "200"
"radius" "32"
}
// entity 72
{
"classname" "light"
"origin" "424 0 252"
}
// entity 73
{
"classname" "target_position"
"origin" "160 40 504"
"targetname" "light_target1"
"classname" "light"
"origin" "64 -348 24"
}
// entity 74
{
"classname" "info_player_deathmatch"
"origin" "-496 -304 152"
"angle" "180"
"classname" "light"
"origin" "128 -464 96"
"_color" "0 0 0.752941"
"light" "200"
"radius" "32"
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -1,7 +1,7 @@
{
"ID": "194e05f445ece24ec5448d886e1334df",
"TypeName": "FlaxEngine.SceneAsset",
"EngineBuild": 6601,
"EngineBuild": 6605,
"Data": [
{
"ID": "194e05f445ece24ec5448d886e1334df",
@@ -27,6 +27,12 @@
"X": 3.0,
"Y": 0.0,
"Z": 0.0
},
"Orientation": {
"X": 0.13052625954151154,
"Y": -1.6762705001838186e-7,
"Z": -1.6762705001838186e-7,
"W": 0.9914449453353882
}
},
"V": {}
@@ -51,7 +57,7 @@
}
},
"Data": {
"Text": "0 tris\n 0 drawcalls\r\n262fps2\r\n285fps"
"Text": "0 tris\n 0 drawcalls\r\n10fps2\r\n10fps"
}
},
{
@@ -68,6 +74,13 @@
"TypeName": "FlaxEngine.UIControl",
"ParentID": "ff6b6db54b5aa08e7286ef86246149ef",
"Name": "CrosshairWidget",
"Transform": {
"Translation": {
"X": 11.0,
"Y": 8.0,
"Z": 0.0
}
},
"Control": "FlaxEngine.GUI.Image",
"Data": {
"Brush": {
@@ -110,10 +123,10 @@
"Y": 1.0
},
"Offsets": {
"Left": 0.0,
"Right": 0.0,
"Top": 0.0,
"Bottom": 0.0
"Left": 11.0,
"Right": -11.0,
"Top": 8.0,
"Bottom": -8.0
},
"Scale": {
"X": 1.0,
@@ -134,6 +147,7 @@
"B": 0.0,
"A": 0.0
},
"BackgroundBrush": null,
"Enabled": true,
"Visible": true,
"AutoFocus": false

View File

@@ -1,8 +1,9 @@
{
"ID": "af2e52554f7faed7b4937181dd22d166",
"TypeName": "FlaxEditor.Content.Settings.BuildSettings",
"EngineBuild": 6340,
"EngineBuild": 6605,
"Data": {
"OutputName": "${PROJECT_NAME}",
"MaxAssetsPerPackage": 4096,
"MaxPackageSizeMB": 1024,
"ContentKey": 0,
@@ -18,7 +19,9 @@
],
"ShadersNoOptimize": false,
"ShadersGenerateDebugData": false,
"SkipDotnetPackaging": true,
"SkipDefaultFonts": false,
"SkipDotnetPackaging": false,
"SkipUnusedDotnetLibsPackaging": true,
"Presets": [
{
"Name": "Preset 3",

Binary file not shown.

View File

@@ -1,7 +1,7 @@
// comment
r_shadows 1
r_lighting 1
cl_maxfps 0
cl_maxfps 240
r_upscaling 0
r_gi 0
r_staticbatch 1

View File

@@ -145,11 +145,18 @@ public class ConsoleInputTextBox : ConsoleTextBoxBase
public override void OnLostFocus()
{
// Prevent caret location getting reset back to beginning
// Prevent caret location getting reset back to beginning,
// and submitting the value when focus is lost.
bool oldEditing = _isEditing;
_isEditing = false;
base.OnLostFocus();
_isEditing = oldEditing;
try
{
base.OnLostFocus();
}
finally
{
_isEditing = oldEditing;
}
}
public override bool OnMouseDown(Float2 location, MouseButton button)

View File

@@ -0,0 +1,54 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using FlaxEngine.Networking;
using FlaxEngine;
namespace Game;
public struct AcceptConnectionMessage
{
public struct PlayerInfo
{
public uint PlayerId;
public Float3 PlayerPosition;
}
public ulong Frame;
public float GameTime;
public PlayerInfo[] Players;
public static AcceptConnectionMessage Read(ref NetworkMessage networkMessage)
{
AcceptConnectionMessage packet = new AcceptConnectionMessage();
packet.Frame = networkMessage.ReadUInt64();
packet.GameTime = networkMessage.ReadSingle();
int numActors = (int)networkMessage.ReadUInt32();
packet.Players = new PlayerInfo[numActors];
for (int i = 0; i < numActors; i++)
{
packet.Players[i].PlayerId = networkMessage.ReadUInt32();
packet.Players[i].PlayerPosition.X = networkMessage.ReadSingle();
packet.Players[i].PlayerPosition.Y = networkMessage.ReadSingle();
packet.Players[i].PlayerPosition.Z = networkMessage.ReadSingle();
}
return packet;
}
public void Write(ref NetworkMessage networkMessage)
{
networkMessage.WriteByte((byte)GameModeMessageType2.AcceptConnection);
networkMessage.WriteUInt64(Frame);
networkMessage.WriteSingle(GameTime);
networkMessage.WriteUInt32((uint)Players.Length);
foreach (PlayerInfo player in Players)
{
networkMessage.WriteUInt32(player.PlayerId);
networkMessage.WriteSingle(player.PlayerPosition.X);
networkMessage.WriteSingle(player.PlayerPosition.Y);
networkMessage.WriteSingle(player.PlayerPosition.Z);
}
}
}

View File

@@ -1,54 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using FlaxEngine.Networking;
using FlaxEngine;
namespace Game;
public struct WelcomePlayerMessage
{
public struct PlayerInfo
{
public uint playerId;
public Float3 playerPosition;
}
public ulong frame;
public float time;
public PlayerInfo[] players;
public static WelcomePlayerMessage Read(ref NetworkMessage networkMessage)
{
WelcomePlayerMessage packet = new WelcomePlayerMessage();
packet.frame = networkMessage.ReadUInt64();
packet.time = networkMessage.ReadSingle();
int numActors = (int)networkMessage.ReadUInt32();
packet.players = new PlayerInfo[numActors];
for (int i = 0; i < numActors; i++)
{
packet.players[i].playerId = networkMessage.ReadUInt32();
packet.players[i].playerPosition.X = networkMessage.ReadSingle();
packet.players[i].playerPosition.Y = networkMessage.ReadSingle();
packet.players[i].playerPosition.Z = networkMessage.ReadSingle();
}
return packet;
}
public void Write(ref NetworkMessage networkMessage)
{
networkMessage.WriteByte((byte)GameModeMessageType.WelcomePlayer);
networkMessage.WriteUInt64(frame);
networkMessage.WriteSingle(time);
networkMessage.WriteUInt32((uint)players.Length);
foreach (PlayerInfo player in players)
{
networkMessage.WriteUInt32(player.playerId);
networkMessage.WriteSingle(player.playerPosition.X);
networkMessage.WriteSingle(player.playerPosition.Y);
networkMessage.WriteSingle(player.playerPosition.Z);
}
}
}

View File

@@ -33,6 +33,8 @@ public enum NetworkMessageType : byte
public static partial class NetworkManager
{
public delegate bool OnMessageDecl(ref NetworkEvent networkEvent);
public delegate bool OnClientConnectingDecl(NetworkConnection sender);
public delegate void OnClientConnectedDecl(NetworkConnection sender);
private static bool initialized;
@@ -45,28 +47,76 @@ public static partial class NetworkManager
private static readonly ushort MaximumClients = 32;
private static List<OnMessageDecl> OnClientMessageDelegates = new(3);
private static List<OnClientConnectingDecl> OnClientConnectingDelegates = new(3);
private static List<OnClientConnectedDecl> OnClientConnectedDelegates = new(3);
private static List<OnMessageDecl> OnServerMessageDelegates = new(3);
private static List<OnClientConnectingDecl> OnServerConnectingDelegates = new(3);
private static List<OnClientConnectedDecl> OnServerConnectedDelegates = new(3);
public static void RegisterClientMessageCallback(OnMessageDecl deleg)
public static void RegisterClientCallbacks(OnMessageDecl onMessage, OnClientConnectingDecl onClientConnecting, OnClientConnectedDecl onClientConnected)
{
Assert.IsTrue(!OnClientMessageDelegates.Contains(deleg));
OnClientMessageDelegates.Add(deleg);
Assert.IsTrue(!OnClientMessageDelegates.Contains(onMessage));
OnClientMessageDelegates.Add(onMessage);
if (onClientConnecting != null)
{
Assert.IsTrue(!OnClientConnectingDelegates.Contains(onClientConnecting));
OnClientConnectingDelegates.Add(onClientConnecting);
}
if (onClientConnected != null)
{
Assert.IsTrue(!OnClientConnectedDelegates.Contains(onClientConnected));
OnClientConnectedDelegates.Add(onClientConnected);
}
}
public static void UnregisterClientMessageCallback(OnMessageDecl deleg)
public static void UnregisterClientCallbacks(OnMessageDecl onMessage, OnClientConnectingDecl onClientConnecting, OnClientConnectedDecl onClientConnected)
{
Assert.IsTrue(OnClientMessageDelegates.Contains(deleg));
OnClientMessageDelegates.Remove(deleg);
Assert.IsTrue(OnClientMessageDelegates.Contains(onMessage));
OnClientMessageDelegates.Remove(onMessage);
if (onClientConnecting != null)
{
Assert.IsTrue(OnClientConnectingDelegates.Contains(onClientConnecting));
OnClientConnectingDelegates.Remove(onClientConnecting);
}
if (onClientConnected != null)
{
Assert.IsTrue(OnClientConnectedDelegates.Contains(onClientConnected));
OnClientConnectedDelegates.Remove(onClientConnected);
}
}
public static void RegisterServerMessageCallback(OnMessageDecl deleg)
public static void RegisterServerCallbacks(OnMessageDecl onMessage, OnClientConnectingDecl onClientConnecting, OnClientConnectedDecl onClientConnected)
{
Assert.IsTrue(!OnServerMessageDelegates.Contains(deleg));
OnServerMessageDelegates.Add(deleg);
Assert.IsTrue(!OnServerMessageDelegates.Contains(onMessage));
OnServerMessageDelegates.Add(onMessage);
if (onClientConnecting != null)
{
Assert.IsTrue(!OnServerConnectingDelegates.Contains(onClientConnecting));
OnServerConnectingDelegates.Add(onClientConnecting);
}
if (onClientConnected != null)
{
Assert.IsTrue(!OnServerConnectedDelegates.Contains(onClientConnected));
OnServerConnectedDelegates.Add(onClientConnected);
}
}
public static void UnregisterServerMessageCallback(OnMessageDecl deleg)
public static void UnregisterServerCallbacks(OnMessageDecl onMessage, OnClientConnectingDecl onClientConnecting, OnClientConnectedDecl onClientConnected)
{
Assert.IsTrue(OnServerMessageDelegates.Contains(deleg));
OnServerMessageDelegates.Remove(deleg);
Assert.IsTrue(OnServerMessageDelegates.Contains(onMessage));
OnServerMessageDelegates.Remove(onMessage);
if (onClientConnecting != null)
{
Assert.IsTrue(OnServerConnectingDelegates.Contains(onClientConnecting));
OnServerConnectingDelegates.Remove(onClientConnecting);
}
if (onClientConnected != null)
{
Assert.IsTrue(OnServerConnectedDelegates.Contains(onClientConnected));
OnServerConnectedDelegates.Remove(onClientConnected);
}
}
public static string DebugLastHandledMessage = "";
@@ -129,22 +179,14 @@ public static partial class NetworkManager
client = null;
}
LocalPlayerClientId = 0;
//LocalPlayerClientId = 0;
#if FLAX_EDITOR
Editor.Instance.PlayModeEnd -= Cleanup;
//GameModeManager.Cleanup(); // FIXME
#endif
if (clientWorldStateManager != null)
{
clientWorldStateManager.Cleanup();
clientWorldStateManager = null;
}
if (serverWorldStateManager != null)
{
serverWorldStateManager.Cleanup();
serverWorldStateManager = null;
}
World.CleanupClient();
World.CleanupServer();
StopRecording();

View File

@@ -14,7 +14,7 @@ public static partial class NetworkManager
public static INetworkDriver ClientNetworkDriver { get; set; }
public static WorldStateManager clientWorldStateManager = null;
//public static WorldStateManager clientWorldStateManager = null;
public static bool ConnectServer(string serverAddress = "localhost", bool listenServer = false)
{
@@ -50,7 +50,7 @@ public static partial class NetworkManager
}
Debug.Log("Connected...");
if (!listenServer)
/*if (!listenServer)
{
//WorldStateManager.Init();
clientWorldStateManager = new WorldStateManager(isClient: true);
@@ -58,7 +58,8 @@ public static partial class NetworkManager
else
{
clientWorldStateManager = new WorldStateManager(isLocalClient: true);
}
}*/
World.InitClient();
Scripting.FixedUpdate += OnClientNetworkUpdate;
if (!listenServer)
@@ -106,20 +107,20 @@ public static partial class NetworkManager
{
case NetworkEventType.Connected:
{
LocalPlayerClientId = networkEvent.Sender.ConnectionId;
Console.Print("Connected to server, ConnectionId: " + networkEvent.Sender.ConnectionId);
foreach (var func in OnClientConnectedDelegates)
func(networkEvent.Sender);
break;
}
case NetworkEventType.Disconnected:
{
Console.Print("Disconnected from server, timeout.");
LocalPlayerClientId = 0;
//LocalPlayerClientId = 0;
break;
}
case NetworkEventType.Timeout:
{
Console.Print("Disconnected from server, connection closed.");
LocalPlayerClientId = 0;
//LocalPlayerClientId = 0;
break;
}
case NetworkEventType.Message:

View File

@@ -38,7 +38,8 @@ public static unsafe partial class NetworkManager
{
{
Cleanup();
clientWorldStateManager = new WorldStateManager(isServer: true);
//clientWorldStateManager = new WorldStateManager(isServer: true);
World.InitServer();
}
if (!ReadDemo(demoName))

View File

@@ -18,7 +18,7 @@ public static partial class NetworkManager
public static INetworkDriver ServerNetworkDriver { get; set; }
public static WorldStateManager serverWorldStateManager = null;
//public static WorldStateManager serverWorldStateManager = null;
public static bool StartServer(bool listenServer = true)
{
@@ -82,8 +82,9 @@ public static partial class NetworkManager
foreach (Type type in NetworkedTypes)
Console.Print("tracking networked type: " + type.Name);
#endif
serverWorldStateManager = new WorldStateManager(isServer: true);
//serverWorldStateManager = new WorldStateManager(isServer: true);
//WorldStateManager.Init();
World.InitServer();
if (listenServer)
return ConnectServer(listenServer: true);
@@ -139,13 +140,21 @@ public static partial class NetworkManager
try
{
//IsServer = true;
if (serverWorldStateManager.OnClientConnecting(networkEvent.Sender))
bool handled = false;
foreach (var func in OnServerConnectingDelegates)
{
handled = func(networkEvent.Sender);
if (handled)
break;
}
if (handled)
{
ConnectedClients.Add(networkEvent.Sender);
Console.Print(
$"Client({networkEvent.Sender.ConnectionId}) connected. Total clients: {ConnectedClients.Count}");
serverWorldStateManager.OnClientConnected(networkEvent.Sender);
foreach (var func in OnServerConnectedDelegates)
func(networkEvent.Sender);
}
else
Console.Print($"Client({networkEvent.Sender.ConnectionId}) connection refused");

View File

@@ -0,0 +1,549 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using FlaxEngine;
using FlaxEngine.Assertions;
using FlaxEngine.Json;
using FlaxEngine.Networking;
namespace Game;
public enum GameModeMessageType2 : byte
{
AcceptConnection, // AcceptConnectionMessage
SpawnPlayer,
PlayerInput,
PlayerPosition, // world update
PlayerSnapshot, // send world state delta to client since last client's acknowledged frame
LastMessageType = 128,
}
public class World
{
protected class ClientInfo
{
public NetworkConnection Connection;
public PlayerActor PlayerActor;
public PlayerFrame[] FrameHistory = new PlayerFrame[120];
public ClientInfo()
{
for (int i = 0; i < FrameHistory.Length; i++)
FrameHistory[i] = new PlayerFrame();
}
}
public class PlayerFrame
{
public ulong frame;
public Float3 position;
public PlayerInputState2 inputState;
public PlayerMovementState movementState;
}
public bool IsServer => this is ServerWorld;
public bool IsClient => !IsServer;
public ulong Frame { get; protected set; }
public ulong ServerFrame { get; protected set; } // Last received frame from server
public float GameTime { get; protected set; } // The join time
public float GetFrameTime(ulong frame) => GameTime + (frame * (1.0f / Time.PhysicsFPS));
protected Scene _scene;
protected Actor _worldSpawn;
protected Dictionary<uint, ClientInfo> _clients = new();
public static void InitClient()
{
WorldStore.ClientWorld = new ClientWorld();
WorldStore.ClientWorld.Init();
}
public static void InitServer()
{
WorldStore.ServerWorld = new ServerWorld();
WorldStore.ServerWorld.Init();
}
public static void CleanupClient()
{
WorldStore.ClientWorld?.Cleanup();
WorldStore.ClientWorld = null;
}
public static void CleanupServer()
{
WorldStore.ServerWorld?.Cleanup();
WorldStore.ServerWorld = null;
}
virtual protected void Init()
{
}
virtual protected void Cleanup()
{
//Level.SceneLoaded -= OnLevelLoaded;
//Scripting.LateUpdate -= OnLateUpdatePre;
Scripting.LateFixedUpdate -= OnLateUpdate;
if (_scene)
{
foreach (var player in _scene.GetChildren<PlayerActor>())
{
FlaxEngine.Object.Destroy(player);
}
if (Level.UnloadScene(_scene))
throw new Exception("Failed to unload scene");
_scene = null;
}
}
protected void CreateScene(string sceneNamePrefix, string sceneGuid)
{
string physicsSceneName = $"{sceneNamePrefix}PhysicsScene";
PhysicsScene localPhysicsScene = Physics.FindOrCreateScene(physicsSceneName);
Guid guid = JsonSerializer.ParseID(sceneGuid);
string guidStr = JsonSerializer.GetStringID(guid);
string sceneData = $@"
{{
""ID"": ""{guidStr}"",
""TypeName"": ""FlaxEngine.SceneAsset"",
""EngineBuild"": 65046,
""Data"": [
{{
""ID"": ""{guidStr}"",
""TypeName"": ""FlaxEngine.Scene"",
""LightmapSettings"": {{
""IndirectLightingIntensity"": 1.0,
""GlobalObjectsScale"": 1.0,
""ChartsPadding"": 3,
""AtlasSize"": 1024,
""BounceCount"": 1,
""CompressLightmaps"": true,
""UseGeometryWithNoMaterials"": true,
""Quality"": 10
}}
}}
]
}}";
{
var onSceneLoaded = (Scene loadedScene, Guid id) =>
{
if (guid == id)
{
loadedScene.PhysicsScene = localPhysicsScene;
//scene = loadedScene;
}
};
try
{
Level.SceneLoaded += onSceneLoaded;
//Level.LoadScene(new SceneReference(guid));
_scene = Level.LoadSceneFromBytes(Encoding.ASCII.GetBytes(sceneData));
}
finally
{
Level.SceneLoaded -= onSceneLoaded;
}
}
Assert.IsTrue(_scene);
_scene.Name = $"{sceneNamePrefix}Scene";
//Level.SceneLoaded += OnLevelLoaded;
Scripting.LateFixedUpdate += OnLateUpdate;
var importer = FlaxEngine.Object.New<Q3MapImporter>();
importer.mapPath = @"C:\dev\GoakeFlax\Assets\Maps\aerowalk.map";
importer.LoadCollidersOnly = sceneNamePrefix != "Client"; // FIXME
importer.Parent = _scene;
//importer.Enabled = true;
_worldSpawn = _scene.FindActor("WorldSpawn");// ?? Level.FindActor("WorldSpawn");
Assert.IsTrue(_worldSpawn);
}
public void OnLateUpdate()
{
Frame++;
}
protected void OnClientConnected(NetworkConnection connection)
{
uint playerId = connection.ConnectionId;
_clients.Add(playerId, new ClientInfo() { Connection = connection });
}
virtual protected PlayerActor SpawnPlayer(uint playerId, Float3 position, Vector3 eulerAngles)
{
string prefabPath = Path.Combine(AssetManager.ContentPath, "Common");
var playerPrefab = Content.Load<Prefab>(Path.Combine(prefabPath, "PlayerPrefab.prefab"));
if (playerPrefab == null)
Console.PrintError("GameModeManager: Failed to find PlayerPrefab");
PlayerActor playerActor = SpawnActor<PlayerActor>(playerPrefab);
playerActor.Initialize(playerId, position, eulerAngles);
//playerActor.Teleport(position, eulerAngles);
_clients[playerId].PlayerActor = playerActor;
IPlayerInput playerInput = playerActor.GetScript<PlayerMovement>().Input;
playerInput.SetFrame(Frame);
/*if (IsServer)
{
serverWorldState.actors.Add(playerActor);
if (!playerLastReceivedFrames.ContainsKey(playerId))
playerLastReceivedFrames.Add(playerId, 0);
}*/
return playerActor;
}
protected T SpawnActor<T>(Prefab prefab) where T : Actor
{
T actor = PrefabManager.SpawnPrefab(prefab, _scene).As<T>();
actor.PhysicsScene = _scene.PhysicsScene;
return actor;
}
virtual public bool IsLocalPlayer(uint playerId) => false;
public PlayerFrame GetPlayerFrame(uint playerId, ulong frame)
{
ClientInfo player = _clients[playerId];
PlayerFrame playerFrame = player.FrameHistory[frame % 120];
if (playerFrame.frame != frame)
return null;
return playerFrame;
}
public bool HasPlayerFrame(uint playerId, ulong frame) => GetPlayerFrame(playerId, frame) != null;
public bool GetPlayerInputState(uint playerId, ulong frame, out PlayerInputState2 inputState)
{
PlayerFrame playerFrame = GetPlayerFrame(playerId, frame);
inputState = playerFrame?.inputState ?? default;
return playerFrame != null;
}
}
file class ServerWorld : World
{
protected override void Init()
{
NetworkManager.RegisterServerCallbacks(OnMessage, OnClientConnecting, OnClientConnected);
GameTime = Time.GameTime;
CreateScene("Server", "59dd37cc444d5d7015759389c6153c4c");
base.Init();
}
protected override void Cleanup()
{
NetworkManager.UnregisterServerCallbacks(OnMessage, OnClientConnecting, OnClientConnected);
base.Cleanup();
}
public bool OnMessage(ref NetworkEvent networkEvent)
{
byte messageTypeByte = networkEvent.Message.ReadByte();
if (!Enum.IsDefined(typeof(GameModeMessageType2), messageTypeByte))
{
//Console.PrintError($"GameModeManager: Unsupported message type received from client: {messageTypeByte}");
return false;
}
GameModeMessageType2 messageType = (GameModeMessageType2)messageTypeByte;
NetworkManager.DebugLastHandledMessage = messageType.ToString();
//Console.Print($"GameModeManager: {messageType}");
switch (messageType)
{
case GameModeMessageType2.AcceptConnection: // Client
{
AcceptConnectionMessage message = AcceptConnectionMessage.Read(ref networkEvent.Message);
Frame += message.Frame;
GameTime = message.GameTime;
ServerFrame = message.Frame;
/*foreach (var player in message.Players)
{
SpawnPlayer(player.PlayerId, player.PlayerPosition, new Float3(0));
var playerFrames = new PlayerFrame[120];
for (int j = 0; j < playerFrames.Length; j++)
playerFrames[j] = new PlayerFrame();
clientWorldState.playerFrameHistory.Add(player.PlayerId, playerFrames);
}*/
}
break;
case GameModeMessageType2.PlayerPosition:
{
//uint playerId = networkEvent.Sender.ConnectionId;
PlayerInputState2 inputState; //?
PlayerActorState actorState;
ulong receivedFrame = networkEvent.Message.ReadUInt64();
uint reportedPlayerId = networkEvent.Message.ReadUInt32();
actorState.position.X = networkEvent.Message.ReadSingle();
actorState.position.Y = 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();
actorState.lastJumpTime = networkEvent.Message.ReadSingle();
actorState.numJumps = networkEvent.Message.ReadInt32();
actorState.jumped = networkEvent.Message.ReadBoolean();
//inputState.frame = receivedFrame;
inputState.ViewDelta.X = networkEvent.Message.ReadSingle();
inputState.ViewDelta.Y = networkEvent.Message.ReadSingle();
inputState.MoveForward = networkEvent.Message.ReadSingle();
inputState.MoveRight = networkEvent.Message.ReadSingle();
inputState.Attack = networkEvent.Message.ReadBoolean();
inputState.Jump = networkEvent.Message.ReadBoolean();
ServerFrame = receivedFrame;
}
break;
default:
break;
}
return true;
}
public bool OnClientConnecting(NetworkConnection connection)
{
AcceptConnectionMessage message = new AcceptConnectionMessage();
message.Frame = Frame;
message.GameTime = GameTime;
message.Players = new AcceptConnectionMessage.PlayerInfo[_clients.Count];
int playerIndex = 0;
foreach (var player in _clients.Values)
{
ref AcceptConnectionMessage.PlayerInfo playerInfo = ref message.Players[playerIndex];
playerInfo.PlayerId = player.PlayerActor.GetScript<PlayerMovement>().PlayerId;
playerInfo.PlayerPosition = player.PlayerActor.Position;
playerIndex++;
}
NetworkMessage networkMessage = NetworkManager.ServerBeginSendMessage();
message.Write(ref networkMessage);
NetworkManager.ServerEndSendMessage(ref networkMessage, connection);
return true;
}
public new void OnClientConnected(NetworkConnection connection)
{
base.OnClientConnected(connection);
uint playerId = connection.ConnectionId;
var spawns = _worldSpawn.GetChildren<Actor>().Where(x => x.Name.StartsWith("PlayerSpawn_")).ToArray();
Console.Print($"found {spawns.Length} spawns");
var randomSpawn = spawns.First();
Float3 position = randomSpawn.Position + new Float3(0f, 4.1f, 0f);
Float3 eulerAngles = randomSpawn.Orientation.EulerAngles;
SpawnPlayer(playerId, position, eulerAngles);
{
NetworkMessage message = NetworkManager.ServerBeginSendMessage();
message.WriteByte((byte)GameModeMessageType.SpawnPlayer);
message.WriteUInt32(playerId);
message.WriteUInt64(Frame);
message.WriteSingle(position.X);
message.WriteSingle(position.Y);
message.WriteSingle(position.Z);
message.WriteSingle(eulerAngles.X);
message.WriteSingle(eulerAngles.Y);
message.WriteSingle(eulerAngles.Z);
NetworkManager.ServerEndSendMessage(ref message, connection);
}
}
}
file class ClientWorld : World
{
private uint _localPlayerId;
protected override void Init()
{
NetworkManager.RegisterClientCallbacks(OnMessage, null, OnClientConnected);
CreateScene("Client", "c095f9ac4989a46afd7fe3821f086e2e");
base.Init();
}
protected override void Cleanup()
{
NetworkManager.UnregisterClientCallbacks(OnMessage, null, OnClientConnected);
base.Cleanup();
}
public bool OnMessage(ref NetworkEvent networkEvent)
{
byte messageTypeByte = networkEvent.Message.ReadByte();
if (!Enum.IsDefined(typeof(GameModeMessageType2), messageTypeByte))
{
//Console.PrintError($"GameModeManager: Unsupported message type received from client: {messageTypeByte}");
return false;
}
GameModeMessageType2 messageType = (GameModeMessageType2)messageTypeByte;
NetworkManager.DebugLastHandledMessage = messageType.ToString();
//Console.Print($"GameModeManager: {messageType}");
switch (messageType)
{
case GameModeMessageType2.AcceptConnection:
{
// Setup some initial state for newly connected client
AcceptConnectionMessage welcomePlayer = AcceptConnectionMessage.Read(ref networkEvent.Message);
ServerFrame = welcomePlayer.Frame;
Frame += welcomePlayer.Frame;
GameTime = welcomePlayer.GameTime;
foreach (var playerInfo in welcomePlayer.Players)
{
_clients.Add(playerInfo.PlayerId, new ClientInfo());
SpawnPlayer(playerInfo.PlayerId, playerInfo.PlayerPosition, new Float3(0));
}
Console.Print("received welcome: frame " + ServerFrame);
}
break;
case GameModeMessageType2.SpawnPlayer:
{
uint playerId = networkEvent.Message.ReadUInt32();
ulong playerFrameIndex = networkEvent.Message.ReadUInt64();
Float3 position = new Float3(networkEvent.Message.ReadSingle(), networkEvent.Message.ReadSingle(), networkEvent.Message.ReadSingle());
Vector3 eulerAngles = new Float3(networkEvent.Message.ReadSingle(), networkEvent.Message.ReadSingle(), networkEvent.Message.ReadSingle());
/*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, position, eulerAngles);
//if (NetworkManager.IsClient)
//players[playerId].GetScript<PlayerMovement>().Input.SetFrame(ClientFrame);
}
break;
#if false
case GameModeMessageType2.PlayerPosition:
{
//uint playerId = networkEvent.Sender.ConnectionId;
PlayerInputState2 inputState; //?
PlayerActorState actorState;
ulong receivedFrame = networkEvent.Message.ReadUInt64();
uint reportedPlayerId = networkEvent.Message.ReadUInt32();
actorState.position.X = networkEvent.Message.ReadSingle();
actorState.position.Y = 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();
actorState.lastJumpTime = networkEvent.Message.ReadSingle();
actorState.numJumps = networkEvent.Message.ReadInt32();
actorState.jumped = networkEvent.Message.ReadBoolean();
//inputState.frame = receivedFrame;
inputState.ViewDelta.X = networkEvent.Message.ReadSingle();
inputState.ViewDelta.Y = networkEvent.Message.ReadSingle();
inputState.MoveForward = networkEvent.Message.ReadSingle();
inputState.MoveRight = networkEvent.Message.ReadSingle();
inputState.Attack = networkEvent.Message.ReadBoolean();
inputState.Jump = networkEvent.Message.ReadBoolean();
ServerFrame = receivedFrame;
}
break;
#endif
default:
break;
}
return true;
}
public override bool IsLocalPlayer(uint playerId) => playerId == _localPlayerId;
public new void OnClientConnected(NetworkConnection connection)
{
base.OnClientConnected(connection);
_localPlayerId = connection.ConnectionId;
Console.Print($"ClientWorld: Connected, playerId: {_localPlayerId}");
}
protected override PlayerActor SpawnPlayer(uint playerId, Float3 position, Vector3 eulerAngles)
{
var playerActor = base.SpawnPlayer(playerId, position, eulerAngles);
if (playerId == _localPlayerId)
playerActor.Input = new PlayerInput2();
else
playerActor.Input = new PlayerInputNetwork2(playerId, this);
return playerActor;
}
}
public static class WorldExtensions
{
public static World GetWorld(this Script script) => IsServerScene(script.Scene) ? WorldStore.ServerWorld : WorldStore.ClientWorld;
public static World GetWorld(this Actor actor) => IsServerScene(actor.Scene) ? WorldStore.ServerWorld : WorldStore.ClientWorld;
private static bool IsServerScene(Scene scene) => scene.Name == "ServerScene";
}
file static class WorldStore
{
public static ServerWorld ServerWorld;
public static ClientWorld ClientWorld;
}
/*file class WorldPlugin : GamePlugin
{
public WorldPlugin()
{
}
public override void Initialize()
{
WorldStore.ClientWorld = new World(isServer: false);
}
public override void Deinitialize()
{
WorldStore.ServerWorld = null;
WorldStore.ClientWorld = null;
}
}*/

View File

@@ -14,7 +14,7 @@ namespace Game;
public enum GameModeMessageType : byte
{
WelcomePlayer, // WelcomePlayerMessage
AcceptConnection, // WelcomePlayerMessage
SpawnPlayer,
PlayerInput,
PlayerPosition, // world update
@@ -97,10 +97,10 @@ public class WorldStateManager
clientWorldState = new WorldState();
gameMode = new GameMode();
if (IsServer)
NetworkManager.RegisterServerMessageCallback(OnMessage);
/*if (IsServer)
NetworkManager.RegisterServerCallbacks(OnMessage);
else
NetworkManager.RegisterClientMessageCallback(OnMessage);
NetworkManager.RegisterClientCallbacks(OnMessage);*/
Debug.Log($"WorldStateManager Init is server: {IsServer}");
Debug.Log($"WorldStateManager Init is local client: {IsLocalClient}");
@@ -173,10 +173,10 @@ public class WorldStateManager
public void Cleanup()
{
if (IsServer)
NetworkManager.UnregisterServerMessageCallback(OnMessage);
/*if (IsServer)
NetworkManager.UnregisterServerCallbacks(OnMessage);
else
NetworkManager.UnregisterClientMessageCallback(OnMessage);
NetworkManager.UnregisterClientCallbacks(OnMessage);*/
Level.SceneLoaded -= OnLevelLoaded;
//Scripting.LateUpdate -= OnLateUpdatePre;
@@ -454,26 +454,26 @@ public class WorldStateManager
//Console.Print($"GameModeManager: {messageType}");
switch (messageType)
{
case GameModeMessageType.WelcomePlayer:
case GameModeMessageType.AcceptConnection:
{
welcomed = true;
if (IsClient || IsLocalClient)
{
WelcomePlayerMessage welcomePlayer = WelcomePlayerMessage.Read(ref networkEvent.Message);
AcceptConnectionMessage welcomePlayer = AcceptConnectionMessage.Read(ref networkEvent.Message);
if (!IsLocalClient)
serverWorldState.frame = welcomePlayer.frame;
serverWorldState.frame = welcomePlayer.Frame;
//lastReceivedServerFrame = welcomePlayer.frame;
clientWorldState.frame += welcomePlayer.frame;
clientWorldState.frame += welcomePlayer.Frame;
ClientTime = welcomePlayer.time;
foreach (var playerInfo in welcomePlayer.players)
ClientTime = welcomePlayer.GameTime;
foreach (var playerInfo in welcomePlayer.Players)
{
SpawnPlayer(playerInfo.playerId, playerInfo.playerPosition, new Float3(0));
SpawnPlayer(playerInfo.PlayerId, playerInfo.PlayerPosition, new Float3(0));
var playerFrames = new PlayerFrame[120];
for (int j = 0; j < playerFrames.Length; j++)
playerFrames[j] = new PlayerFrame();
clientWorldState.playerFrameHistory.Add(playerInfo.playerId, playerFrames);
clientWorldState.playerFrameHistory.Add(playerInfo.PlayerId, playerFrames);
}
Console.Print("received welcome: frame " + serverWorldState.frame);
@@ -614,17 +614,17 @@ public class WorldStateManager
//if (connection.ConnectionId != NetworkManager.LocalPlayerClientId)
{
Console.Print("sending welcome: frame " + serverWorldState.frame);
WelcomePlayerMessage welcomeMessage = new WelcomePlayerMessage();
welcomeMessage.frame = serverWorldState.frame;
welcomeMessage.time = ServerTime;
welcomeMessage.players = new WelcomePlayerMessage.PlayerInfo[serverWorldState.actors.Count];
AcceptConnectionMessage welcomeMessage = new AcceptConnectionMessage();
welcomeMessage.Frame = serverWorldState.frame;
welcomeMessage.GameTime = ServerTime;
welcomeMessage.Players = new AcceptConnectionMessage.PlayerInfo[serverWorldState.actors.Count];
for (int i = 0; i < serverWorldState.actors.Count; i++)
{
PlayerActor playerActor = serverWorldState.actors[i];
ref WelcomePlayerMessage.PlayerInfo playerInfo = ref welcomeMessage.players[i];
playerInfo.playerId = playerActor.GetScript<PlayerMovement>().PlayerId;
playerInfo.playerPosition = playerActor.Position;
ref AcceptConnectionMessage.PlayerInfo playerInfo = ref welcomeMessage.Players[i];
playerInfo.PlayerId = playerActor.GetScript<PlayerMovement>().PlayerId;
playerInfo.PlayerPosition = playerActor.Position;
/*playerActor.GetScript<PlayerMovement>().Input.SetState(serverWorldState.frame, new PlayerInputState(), new PlayerActorState()
{

View File

@@ -43,7 +43,12 @@ public class PlayerActor : RigidBody//, INetworkSerializable
public MeshCollider meshCollider;
//[NetworkReplicated]
public uint PlayerId = uint.MaxValue;
public uint PlayerId { get; private set; } = uint.MaxValue;
public IPlayerInput Input { get; set; } = PlayerInputNone.Instance;
private World _world;
private World World => _world ??= this.GetWorld();
/*public PlayerActor()
{
@@ -103,9 +108,9 @@ public class PlayerActor : RigidBody//, INetworkSerializable
IsActive = true;
PlayerId = playerId;
playerMovement.SetInput(playerId);
//playerMovement.SetInput(playerId);
bool isServerScene = Scene.Name == "ServerScene";
if (playerId == NetworkManager.LocalPlayerClientId && !isServerScene)
if (World.IsLocalPlayer(PlayerId))
{
FindActor("CameraHolder").IsActive = true;
//FindActor("ViewModelHolder").IsActive = true;

View File

@@ -84,21 +84,21 @@ public class PlayerInput2 : IPlayerInput
public class PlayerInputNetwork2 : IPlayerInput
{
private uint _playerId;
private WorldStateManager _worldStateManager;
private World _world;
private ulong _frame;
private PlayerInputState2 _state;
public PlayerInputNetwork2(uint playerId, WorldStateManager worldStateManager)
public PlayerInputNetwork2(uint playerId, World world)
{
_playerId = playerId;
_worldStateManager = worldStateManager;
_world = world;
}
public void SetFrame(ulong frame) => _frame = frame;
public void UpdateState()
{
_worldStateManager.GetPlayerInputState(_playerId, _frame, out _state);
_world.GetPlayerInputState(_playerId, _frame, out _state);
}
public PlayerInputState2 GetState() => _state;
@@ -107,4 +107,15 @@ public class PlayerInputNetwork2 : IPlayerInput
{
_state = new PlayerInputState2();
}
}
public class PlayerInputNone : IPlayerInput
{
public static PlayerInputNone Instance { get; } = new PlayerInputNone();
private PlayerInputNone() { }
public PlayerInputState2 GetState() => default;
public void ResetState() { }
public void SetFrame(ulong frame) { }
public void UpdateState() { }
}

View File

@@ -107,7 +107,10 @@ public class PlayerMovement : Script
private readonly bool demoDeltasVerify = true;
private WorldStateManager worldStateManager;
//private WorldStateManager worldStateManager;
private World _world;
private World World => _world ??= this.GetWorld();
private bool predicting = false;
@@ -115,8 +118,8 @@ public class PlayerMovement : Script
//public int currentInputFrame;
//private int currentInputFrame2;
public IPlayerInput Input;
[NoSerialize, HideInEditor]
public IPlayerInput Input => playerActor?.Input ?? PlayerInputNone.Instance;
//private bool physicsInteractions = false;
@@ -136,7 +139,7 @@ public class PlayerMovement : Script
public Float3 viewAngles;
private Float3 viewAnglesLastFrame;
public uint PlayerId = 0;
public uint PlayerId => playerActor ? playerActor.PlayerId : 0;
[ReadOnly]
public float CurrentVelocity
@@ -161,7 +164,6 @@ public class PlayerMovement : Script
{
base.OnAwake();
Console.Print("player awake, playerid: " + PlayerId);
rootActor = Actor.GetChild("RootActor");
rigidBody = Actor.As<RigidBody>();
playerActor = Actor.As<PlayerActor>();
@@ -176,36 +178,6 @@ public class PlayerMovement : Script
//rigidBody.TriggerExit += OnTriggerExit;
}
public void SetInput(uint playerId)
{
//if (playerId == 0)
// input = new PlayerInput();
Assert.IsTrue(playerId != uint.MaxValue);
PlayerId = playerId;
bool isServerScene = Scene.Name == "ServerScene";
if (isServerScene)
worldStateManager = NetworkManager.serverWorldStateManager;
else
worldStateManager = NetworkManager.clientWorldStateManager;
if (PlayerId == NetworkManager.LocalPlayerClientId && !isServerScene)//if (NetworkReplicator.GetObjectRole(this.Parent) == NetworkObjectRole.OwnedAuthoritative)// if (playerId == NetworkManager.LocalPlayerClientId)
{
Console.Print("local player?: " + playerId.ToString());
//string demoPath = System.IO.Path.Combine(AssetManager.DemoPath, $"{DateTimeOffset.Now.UtcTicks}.gdem");
//input = new PlayerInputLocal(playerActor, demoPath); // TODO: support recording
Input = new PlayerInput2();//new PlayerInputLocal(playerActor);
}
else
{
Console.Print("network player: " + playerId.ToString());
Input = new PlayerInputNetwork2(playerId, worldStateManager);
}
Assert.IsTrue(worldStateManager != null);
}
#if false
public void SetInput(string demoFile)
{
@@ -286,7 +258,7 @@ public class PlayerMovement : Script
//if (Input is PlayerInputDemo /*&& currentInputFrame2 >= currentInputFrame*/)
// return;
Input.SetFrame(worldStateManager.Frame);
Input.SetFrame(World.Frame);
Input.UpdateState();
/*if (input.frame > 0)
@@ -345,7 +317,107 @@ public class PlayerMovement : Script
//Input.OnFixedUpdate();
PlayerInputState2 inputState = Input.GetState();
bool predict = World.IsClient;
if (predict)
{
// Get the latest frame we have predicted
ulong lastFrame = World.ServerFrame;
for (; lastFrame < World.Frame; lastFrame++)
{
if (!World.HasPlayerFrame(PlayerId, lastFrame))
//if (!Input.GetState(currentFrame, out var pastInputState, out var pastActorState))
{
//Console.Print($"not predicting");
predict = false;
break;
}
}
if (predict)
{
var oldAngles = viewAngles;
var oldPos = movementState.position;
var oldVel = movementState.currentVelocity;
ulong currentFrame = World.ServerFrame;
if (currentFrame == World.ServerFrame)
{
// Reset all state to latest confirmed state from server
var frameInfo = World.GetPlayerFrame(PlayerId, currentFrame);
movementState.position = frameInfo.movementState.position;
movementState.currentVelocity = frameInfo.movementState.currentVelocity;
movementState.lastJumped = frameInfo.movementState.lastJumped;
movementState.numJumps = frameInfo.movementState.numJumps;
movementState.jumped = frameInfo.movementState.jumped;
Actor.Position = movementState.position;
SetCameraEulerAngles(frameInfo.movementState.viewAngles, true);
//cameraHolder.Orientation = Quaternion.Euler(pastActorState.viewAngles.Y, pastActorState.viewAngles.X, pastActorState.viewAngles.Z);
//ApplyInputToCamera(pastInputState, true);
//if (pastActorState.viewAngles != new Float3(90f, 0f, 0f))
// Console.Print($"moved server frame: {currentFrame}, {pastActorState.viewAngles}");
currentFrame++;
//rootActor.Orientation = pastActorState.orientation;
//viewAngles = pastActorState.viewAngles;
//viewAngles = new Float3(pastActorState.viewAngles.Y, pastActorState.viewAngles.X, pastActorState.viewAngles.Z);
}
// Predict the frames since last received frame from server up to latest client frame
predicting = true;
for (; currentFrame < lastFrame; currentFrame++)
{
var frameInfo = World.GetPlayerFrame(PlayerId, currentFrame);
if (frameInfo == null)
{
Console.Print($"unexpected predict failure: {currentFrame}");
break;
}
ApplyInputToCamera(frameInfo.inputState, true);
SimulatePlayerMovement(frameInfo.inputState, frameInfo.frame);
}
predicting = false;
var posDelta = (movementState.position - oldPos);
var velDelta = (movementState.currentVelocity - oldVel);
if (posDelta.Length > 0.001)
Console.Print($"mispredicted final position");
if (velDelta.Length > 0.001)
Console.Print($"mispredicted final velocity");
// Run simulation for the upcoming frame
//if (input is not PlayerInputNetwork)
{
/*if ((movementState.position - oldPos).Length > 0.001)
Console.Print($"mispredicted final position");
if ((currentVelocity - oldVel).Length > 0.001)
Console.Print($"mispredicted final velocity");*/
ApplyInputToCamera(inputState, true);
// Ensure orientation is always up-to-date after predicting
//rootActor.Orientation = Quaternion.Euler(0, viewAngles.X, 0);
cameraHolder.Orientation = Quaternion.Euler(viewAngles.Y, viewAngles.X, viewAngles.Z);
SimulatePlayerMovement(inputState, World.Frame); // MAYBE?
}
var viewDelta = (viewAngles - oldAngles);
if (viewDelta.Length > 0.001)
Console.Print($"mispredicted final viewangles: {viewAngles} <- {oldAngles}");
}
}
if (!predict)
{
SetCameraEulerAngles(viewAnglesLastFrame, true);
ApplyInputToCamera(inputState, true);
SimulatePlayerMovement(inputState, World.Frame); // MAYBE?
}
viewAnglesLastFrame = viewAngles;
#if false
if (false && Input is PlayerInputNetwork2)
{
#if false
@@ -456,12 +528,13 @@ public class PlayerMovement : Script
//viewAngles = viewAnglesLastFrame;
bool canpredict = true;
if (true /*&& Input.Predict*/ /*&& !NetworkManager.IsDemoPlaying*/ && worldStateManager.ClientFrame > 0 && worldStateManager.ServerFrame > 0)
if (true /*&& Input.Predict*/ /*&& !NetworkManager.IsDemoPlaying*/ && World.Frame > 0 && World.ServerFrame > 0)
{
ulong currentFrame = worldStateManager.ServerFrame;
for (; currentFrame < worldStateManager.ClientFrame; currentFrame++)
// Get the latest frame we have predicted
ulong currentFrame = World.ServerFrame;
for (; currentFrame < World.Frame; currentFrame++)
{
if (!worldStateManager.HasPlayerFrame(PlayerId, currentFrame))
if (!World.HasPlayerFrame(PlayerId, currentFrame))
//if (!Input.GetState(currentFrame, out var pastInputState, out var pastActorState))
{
//Console.Print($"not predicting");
@@ -471,22 +544,19 @@ public class PlayerMovement : Script
}
ulong lastFrame = currentFrame;
if (canpredict)
{
var oldAngles = viewAngles;
var oldPos = movementState.position;
var oldVel = movementState.currentVelocity;
// Predict the frames since last received frame from server up to latest client frame
predicting = true;
currentFrame = worldStateManager.ServerFrame;
currentFrame = World.ServerFrame;
for (; currentFrame < lastFrame; currentFrame++)
{
//if (!Input.GetState(currentFrame, out var pastInputState, out var pastActorState))
var frameInfo = worldStateManager.GetPlayerFrame(PlayerId, currentFrame);
var frameInfo = World.GetPlayerFrame(PlayerId, currentFrame);
if (frameInfo == null)
{
Console.Print($"unexpected predict failure: {currentFrame}");
@@ -496,7 +566,7 @@ public class PlayerMovement : Script
//if (currentFrame == inputState.frame)
// movementState.jumped = movementState.jumped;
if (currentFrame == worldStateManager.ServerFrame)
if (currentFrame == World.ServerFrame)
{
movementState.position = frameInfo.movementState.position;
movementState.currentVelocity = frameInfo.movementState.currentVelocity;
@@ -563,7 +633,7 @@ public class PlayerMovement : Script
//rootActor.Orientation = Quaternion.Euler(0, viewAngles.X, 0);
cameraHolder.Orientation = Quaternion.Euler(viewAngles.Y, viewAngles.X, viewAngles.Z);
SimulatePlayerMovement(inputState, worldStateManager.Frame); // MAYBE?
SimulatePlayerMovement(inputState, World.Frame); // MAYBE?
}
var viewDelta = (viewAngles - oldAngles);
@@ -585,7 +655,7 @@ public class PlayerMovement : Script
{
SetCameraEulerAngles(viewAnglesLastFrame, true);
ApplyInputToCamera(inputState, true);
SimulatePlayerMovement(inputState, worldStateManager.Frame); // MAYBE?
SimulatePlayerMovement(inputState, World.Frame); // MAYBE?
}
if (movementState.position.Length < 0.1)
@@ -625,7 +695,7 @@ public class PlayerMovement : Script
});*/
//Console.Print($"recording frame {input.frame}, client: {GameModeManager.ClientFrame}, server: {GameModeManager.ServerFrame}");
worldStateManager.RecordPlayerInput(PlayerId, worldStateManager.Frame, inputState, movementState); // MAYBE?
World.RecordPlayerInput(PlayerId, World.Frame, inputState, movementState); // MAYBE?
Input.ResetState();
}
@@ -649,6 +719,7 @@ public class PlayerMovement : Script
currentVelocity = pastActorState2.velocity;
SetCameraEulerAngles(pastActorState2.viewAngles, true);
}*/
#endif
}
public void ApplyInputToCamera(PlayerInputState2 inputState, bool wrapAround = true)
@@ -925,10 +996,10 @@ public class PlayerMovement : Script
}
#endif
}
else if (worldStateManager.IsClient)
else if (World.IsClient)
{
var serverBbox = boxCollider.OrientedBox.GetBoundingBox();
var frameInfo = worldStateManager.GetPlayerFrame(PlayerId, worldStateManager.ServerFrame);
var frameInfo = World.GetPlayerFrame(PlayerId, World.ServerFrame);
if (frameInfo != null)
serverBbox.Center = frameInfo.movementState.position;
@@ -1178,7 +1249,7 @@ public class PlayerMovement : Script
public void SimulatePlayerMovement(PlayerInputState2 inputState, ulong frame)
{
simulationTime = worldStateManager.ClientTime + (frame * (1.0f / Time.PhysicsFPS));
simulationTime = World.GetFrameTime(frame);
Vector3 inputDirection =
new Float3(inputState.MoveRight, 0.0f, inputState.MoveForward);