diff --git a/FezMultiplayerDedicatedServer/FezCompatibilityTypes.cs b/FezMultiplayerDedicatedServer/FezCompatibilityTypes.cs
new file mode 100644
index 0000000..8cb0d5e
--- /dev/null
+++ b/FezMultiplayerDedicatedServer/FezCompatibilityTypes.cs
@@ -0,0 +1,160 @@
+using System;
+
+namespace FezMultiplayerDedicatedServer
+{
+ public struct Vector3
+ {
+ public float X, Y, Z;
+ public Vector3(float x, float y, float z)
+ {
+ X = x; Y = y; Z = z;
+ }
+ public override string ToString()
+ {
+ string separator = System.Globalization.CultureInfo.CurrentCulture.NumberFormat.NumberGroupSeparator;
+ return $"<{X}{separator} {Y}{separator} {this.Z}>";
+ }
+ public Vector3 Round(int d)
+ {
+ return new Vector3((float)Math.Round(X, d), (float)Math.Round(Y, d), (float)Math.Round(Z, d));
+ }
+ }
+ public enum HorizontalDirection
+ {
+ None,
+ Left,
+ Right
+ }
+ public enum Viewpoint
+ {
+ None,
+ Front,
+ Right,
+ Back,
+ Left,
+ Up,
+ Down,
+ Perspective
+ }
+ public enum ActionType
+ {
+ None,
+ Idle,
+ LookingLeft,
+ LookingRight,
+ LookingUp,
+ LookingDown,
+ Walking,
+ Running,
+ Jumping,
+ FrontClimbingLadder,
+ BackClimbingLadder,
+ SideClimbingLadder,
+ CarryIdle,
+ CarryWalk,
+ CarryJump,
+ CarrySlide,
+ CarryEnter,
+ CarryHeavyIdle,
+ CarryHeavyWalk,
+ CarryHeavyJump,
+ CarryHeavySlide,
+ CarryHeavyEnter,
+ DropTrile,
+ DropHeavyTrile,
+ Throwing,
+ ThrowingHeavy,
+ Lifting,
+ LiftingHeavy,
+ Dying,
+ Suffering,
+ Falling,
+ Bouncing,
+ Flying,
+ Dropping,
+ Sliding,
+ Landing,
+ ReadingSign,
+ FreeFalling,
+ CollectingFez,
+ Victory,
+ EnteringDoor,
+ Grabbing,
+ Pushing,
+ SuckedIn,
+ FrontClimbingVine,
+ FrontClimbingVineSideways,
+ SideClimbingVine,
+ BackClimbingVine,
+ BackClimbingVineSideways,
+ WakingUp,
+ OpeningTreasure,
+ OpeningDoor,
+ WalkingTo,
+ Treading,
+ Swimming,
+ Sinking,
+ Teetering,
+ HurtSwim,
+ EnteringTunnel,
+ PushingPivot,
+ EnterDoorSpin,
+ EnterDoorSpinCarry,
+ EnterDoorSpinCarryHeavy,
+ EnterTunnelCarry,
+ EnterTunnelCarryHeavy,
+ RunTurnAround,
+ FindingTreasure,
+ IdlePlay,
+ IdleSleep,
+ IdleLookAround,
+ PullUpCornerLedge,
+ LowerToCornerLedge,
+ GrabCornerLedge,
+ GrabLedgeFront,
+ GrabLedgeBack,
+ PullUpFront,
+ PullUpBack,
+ LowerToLedge,
+ ShimmyFront,
+ ShimmyBack,
+ ToCornerFront,
+ ToCornerBack,
+ FromCornerBack,
+ IdleToClimb,
+ IdleToFrontClimb,
+ IdleToSideClimb,
+ JumpToClimb,
+ JumpToSideClimb,
+ ClimbOverLadder,
+ GrabTombstone,
+ PivotTombstone,
+ LetGoOfTombstone,
+ EnteringPipe,
+ ExitDoor,
+ ExitDoorCarry,
+ ExitDoorCarryHeavy,
+ LesserWarp,
+ GateWarp,
+ SleepWake,
+ ReadTurnAround,
+ EndReadTurnAround,
+ TurnToBell,
+ HitBell,
+ TurnAwayFromBell,
+ CrushHorizontal,
+ CrushVertical,
+ DrumsIdle,
+ DrumsCrash,
+ DrumsTom,
+ DrumsTom2,
+ DrumsToss,
+ DrumsTwirl,
+ DrumsHiHat,
+ VictoryForever,
+ Floating,
+ Standing,
+ StandWinking,
+ IdleYawn
+ }
+}
\ No newline at end of file
diff --git a/FezMultiplayerDedicatedServer/FezDedicatedServer.cs b/FezMultiplayerDedicatedServer/FezDedicatedServer.cs
index 69fe36e..d97d5fc 100644
--- a/FezMultiplayerDedicatedServer/FezDedicatedServer.cs
+++ b/FezMultiplayerDedicatedServer/FezDedicatedServer.cs
@@ -77,7 +77,7 @@ static void Main(string[] args)
+ $"{p.TimeSinceJoin}, "
+ $"{((p.CurrentLevelName == null || p.CurrentLevelName.Length == 0) ? "???" : p.CurrentLevelName)}, "
+ $"{p.Action}, {p.CameraViewpoint}, "
- + $"{p.Position/*.Round(3)*/}, {(DateTime.UtcNow.Ticks - p.LastUpdateTimestamp) / (double)TimeSpan.TicksPerSecond}\n";
+ + $"{p.Position.Round(3)}, {p.NetworkSpeedUp}, {(DateTime.UtcNow.Ticks - p.LastUpdateTimestamp) / (double)TimeSpan.TicksPerSecond}\n";
}
s += $"{count} players online";
Console.WriteLine(s);
diff --git a/FezMultiplayerDedicatedServer/FezMultiplayerDedicatedServer.csproj b/FezMultiplayerDedicatedServer/FezMultiplayerDedicatedServer.csproj
index 0063187..3c7646e 100644
--- a/FezMultiplayerDedicatedServer/FezMultiplayerDedicatedServer.csproj
+++ b/FezMultiplayerDedicatedServer/FezMultiplayerDedicatedServer.csproj
@@ -46,6 +46,7 @@
+
diff --git a/FezMultiplayerDedicatedServer/MultiplayerServer.cs b/FezMultiplayerDedicatedServer/MultiplayerServer.cs
index aaba58e..8b4e8bd 100644
--- a/FezMultiplayerDedicatedServer/MultiplayerServer.cs
+++ b/FezMultiplayerDedicatedServer/MultiplayerServer.cs
@@ -9,10 +9,6 @@
using System.IO;
using System.Collections.Concurrent;
using FezSharedTools;
-
-using ActionType = System.Int32;
-using HorizontalDirection = System.Int32;
-using Viewpoint = System.Int32;
using System.Threading.Tasks;
using static FezMultiplayerDedicatedServer.MultiplayerServer;
@@ -31,6 +27,7 @@ public class ServerPlayerMetadata : PlayerMetadata
public TcpClient tcpClient;
public readonly DateTime joinTime = DateTime.UtcNow;
public TimeSpan TimeSinceJoin => DateTime.UtcNow - joinTime;
+ public long NetworkSpeedUp = 0;
public ServerPlayerMetadata(TcpClient tcpClient, Guid Uuid, string CurrentLevelName, Vector3 Position, Viewpoint CameraViewpoint, ActionType Action, int AnimFrame, HorizontalDirection LookingDirection, long LastUpdateTimestamp)
: base(Uuid, CurrentLevelName, Position, CameraViewpoint, Action, AnimFrame, LookingDirection, LastUpdateTimestamp)
@@ -258,8 +255,12 @@ private void OnNewClientConnect(TcpClient tcpClient)
{
try
{
+ Queue SpeedUp = new Queue(100);
+ long SpeedDown = 0;
//send them our data and get player appearance from client
- WriteServerGameTickPacket(writer, Players.Values.Cast().ToList(), null, GetActiveLevelStates(), DisconnectedPlayers.Keys, PlayerAppearances, uuid, false, sharedSaveData);
+ SpeedUp.Enqueue(WriteServerGameTickPacket(writer, Players.Values.Cast().ToList(),
+ null, GetActiveLevelStates(), DisconnectedPlayers.Keys,
+ PlayerAppearances, uuid, false, sharedSaveData));
MiscClientData clientData = new MiscClientData(null, false, new HashSet(MiscClientData.MaxRequestedAppearancesSize));
ReadClientGameTickPacket(reader, ref clientData, uuid);
bool Disconnecting = clientData.Disconnecting;
@@ -298,11 +299,18 @@ bool PlayerAppearancesFilter(KeyValuePair p)
{
break;
}
+ if(Players.TryGetValue(uuid, out ServerPlayerMetadata serverPlayerMetadata)){
+ serverPlayerMetadata.NetworkSpeedUp = (long)Math.Round(SpeedUp.Average());//Note: does not produce a meaningful number for connections to loopback addresses
+ }
//if UnknownPlayerAppearanceGuids contains uuid, ask client to retransmit their PlayerAppearance
bool requestAppearance = UnknownPlayerAppearanceGuids.ContainsKey(uuid);
//repeat until the client disconnects or times out
- WriteServerGameTickPacket(writer, Players.Values.Cast().ToList(), GetSaveDataUpdate(), GetActiveLevelStates(), DisconnectedPlayers.Keys,
- GetPlayerAppearances(PlayerAppearancesFilter), null, requestAppearance, null);
+ if(SpeedUp.Count>=100){
+ _ = SpeedUp.Dequeue();
+ }
+ SpeedUp.Enqueue(WriteServerGameTickPacket(writer, Players.Values.Cast().ToList(),
+ GetSaveDataUpdate(), GetActiveLevelStates(), DisconnectedPlayers.Keys,
+ GetPlayerAppearances(PlayerAppearancesFilter), null, requestAppearance, null));
ReadClientGameTickPacket(reader, ref clientData, uuid);
Disconnecting = clientData.Disconnecting;
playerMetadata = clientData.Metadata;
diff --git a/FezMultiplayerMod/MultiplayerMod/FezMultiplayerMod.cs b/FezMultiplayerMod/MultiplayerMod/FezMultiplayerMod.cs
index 4120637..593a8ce 100644
--- a/FezMultiplayerMod/MultiplayerMod/FezMultiplayerMod.cs
+++ b/FezMultiplayerMod/MultiplayerMod/FezMultiplayerMod.cs
@@ -202,10 +202,10 @@ public override void Draw(GameTime gameTime)
if (p != null)
{
s += "(you): ";
- s += $"{mp.MyAppearance.PlayerName}, {mp.MyUuid}, "
+ s += $"{mp.MyAppearance.PlayerName}, "//{mp.MyUuid}, "
+ $"{((p.CurrentLevelName == null || p.CurrentLevelName.Length == 0) ? "???" : p.CurrentLevelName)}, "
+ $"{p.Action}, {p.CameraViewpoint}, "
- + $"{p.Position.Round(3)}\n";
+ + $"{p.Position.Round(3)}, {mp.ConnectionLatencyUp}\n";
}
}
if (mp.ErrorMessage != null)
@@ -246,7 +246,12 @@ public override void Draw(GameTime gameTime)
{
DrawPlayer(p, playerName, gameTime);
}
- catch { }
+ catch(Exception e)
+ {
+#if DEBUG
+ System.Diagnostics.Debugger.Launch();
+ #endif
+ }
}
}
}
@@ -273,23 +278,30 @@ public override void Draw(GameTime gameTime)
SamplerState = SamplerState.PointClamp
};
private TimeSpan sinceBackgroundChanged = TimeSpan.Zero;
+ const bool HideInFirstPerson = false;
internal void DrawPlayer(PlayerMetadata p, string playerName, GameTime gameTime, bool doDraw = true)
{
+ ActionType pAction = p.Action;
#region adapted from GomezHost.Update
if (GameState.Loading
|| GameState.InMap
|| GameState.Paused
- || (FezMath.AlmostEqual(PlayerManager.GomezOpacity, 0f) && CameraManager.Viewpoint != Viewpoint.Perspective)
- || p.Action == ActionType.None)
+ || (HideInFirstPerson
+ && ((FezMath.AlmostEqual(PlayerManager.GomezOpacity, 0f) && CameraManager.Viewpoint != Viewpoint.Perspective)
+ || pAction == ActionType.None)
+ )
+ )
{
return;
}
//TODO fix the problem with climbing in different viewpoints; see p.CameraViewpoint
- if (CameraManager.Viewpoint.GetOpposite() == p.CameraViewpoint)
+ HorizontalDirection LookingDir = p.LookingDirection;
+ Viewpoint cameraViewpoint = CameraManager.Viewpoint.IsOrthographic() ? CameraManager.Viewpoint : CameraManager.LastViewpoint;
+ if (cameraViewpoint.GetOpposite() == p.CameraViewpoint)
{
- p.LookingDirection = p.LookingDirection.GetOpposite();
+ LookingDir = LookingDir.GetOpposite();
}
- AnimatedTexture animation = PlayerManager.GetAnimation(p.Action);
+ AnimatedTexture animation = PlayerManager.GetAnimation(pAction);
if (animation.Offsets.Length < 0)
{
return;
@@ -310,7 +322,7 @@ internal void DrawPlayer(PlayerMetadata p, string playerName, GameTime gameTime,
mesh.Texture = animation.Texture;
mesh.FirstGroup.TextureMatrix.Set(new Matrix((float)rectangle.Width / (float)width, 0f, 0f, 0f, 0f, (float)rectangle.Height / (float)height, 0f, 0f, (float)rectangle.X / (float)width, (float)rectangle.Y / (float)height, 1f, 0f, 0f, 0f, 0f, 0f));
bool playerinbackground = false;// PlayerManager.Background;
- /*if (lastBackground != playerinbackground && !p.Action.NoBackgroundDarkening())
+ /*if (lastBackground != playerinbackground && !pAction.NoBackgroundDarkening())
{
sinceBackgroundChanged = TimeSpan.Zero;
lastBackground = playerinbackground;
@@ -319,9 +331,10 @@ internal void DrawPlayer(PlayerMetadata p, string playerName, GameTime gameTime,
{
sinceBackgroundChanged += gameTime.ElapsedGameTime;
}
- effect.Background = p.Action.NoBackgroundDarkening() ? 0f : FezMath.Saturate(playerinbackground ? ((float)sinceBackgroundChanged.TotalSeconds * 2f) : (1f - (float)sinceBackgroundChanged.TotalSeconds * 2f));
+ effect.Background = pAction.NoBackgroundDarkening() ? 0f : FezMath.Saturate(playerinbackground ? ((float)sinceBackgroundChanged.TotalSeconds * 2f) : (1f - (float)sinceBackgroundChanged.TotalSeconds * 2f));
mesh.Scale = new Vector3(animation.FrameWidth / 16f, animation.FrameHeight / 16f, 1f);
- mesh.Position = p.Position + GetPositionOffset(p, ref animation);
+
+ mesh.Position = p.Position + GetPositionOffset(pAction, ref animation, LookingDir, cameraViewpoint);
#endregion
#region adapted from GomezHost.DoDraw_Internal
//if (GameState.StereoMode || LevelManager.Quantum)
@@ -334,13 +347,13 @@ internal void DrawPlayer(PlayerMetadata p, string playerName, GameTime gameTime,
{
mesh.Rotation = CameraManager.Rotation;//always point the mesh at the camera so first person mode looks good
}
- if (p.LookingDirection == HorizontalDirection.Left)
+ if (LookingDir == HorizontalDirection.Left)
{
mesh.Rotation *= FezMath.QuaternionFromPhi((float)Math.PI);
}
//}
//blinking
- /*if (p.Action == ActionType.Suffering || p.Action == ActionType.Sinking)
+ /*if (pAction == ActionType.Suffering || pAction == ActionType.Sinking)
{
mesh.Material.Opacity = (float)FezMath.Saturate((Math.Sin(PlayerManager.BlinkSpeed * ((float)Math.PI * 2f) * 5f) + 0.5 - (double)(PlayerManager.BlinkSpeed * 1.25f)) * 2.0);
}
@@ -348,9 +361,10 @@ internal void DrawPlayer(PlayerMetadata p, string playerName, GameTime gameTime,
{
mesh.Material.Opacity = PlayerManager.GomezOpacity;
}*/
+ mesh.Material.Opacity = 1;
GraphicsDevice graphicsDevice = base.GraphicsDevice;
//silhouette
- if (!p.Action.SkipSilhouette())
+ if (!pAction.SkipSilhouette())
{
graphicsDevice.PrepareStencilRead(CompareFunction.Greater, StencilMask.NoSilhouette);
mesh.DepthWrites = false;
@@ -368,7 +382,7 @@ internal void DrawPlayer(PlayerMetadata p, string playerName, GameTime gameTime,
}
//finally draw the mesh
graphicsDevice.PrepareStencilWrite(StencilMask.Gomez);
- mesh.AlwaysOnTop = p.Action.NeedsAlwaysOnTop();
+ mesh.AlwaysOnTop = pAction.NeedsAlwaysOnTop();
mesh.DepthWrites = !GameState.InFpsMode;
effect.Silhouette = false;
if (doDraw) mesh.Draw();
@@ -382,15 +396,14 @@ internal void DrawPlayer(PlayerMetadata p, string playerName, GameTime gameTime,
#endregion
}
//Adapted from GomezHost.GetPositionOffset
- private Vector3 GetPositionOffset(PlayerMetadata p, ref AnimatedTexture anim)
+ private Vector3 GetPositionOffset(ActionType pAction, ref AnimatedTexture anim, HorizontalDirection LookingDir, Viewpoint view)
{
- float playerSizeY = p.Action.IsCarry() ? (Enum.GetName(typeof(ActionType), p.Action).Contains("Heavy") ? 1.75f : 1.9375f) : 0.9375f;//numbers from PlayerManager.SyncCollisionSize
- float num = playerSizeY + ((p.Action.IsCarry() || p.Action == ActionType.ThrowingHeavy) ? (-2) : 0);
+ float playerSizeY = pAction.IsCarry() ? (Enum.GetName(typeof(ActionType), pAction).Contains("Heavy") ? 1.75f : 1.9375f) : 0.9375f;//numbers from PlayerManager.SyncCollisionSize
+ float num = playerSizeY + ((pAction.IsCarry() || pAction == ActionType.ThrowingHeavy) ? (-2) : 0);
Vector3 vector = (1f - num) / 2f * Vector3.UnitY;
- Vector2 vector2 = p.Action.GetOffset() / 16f;
+ Vector2 vector2 = pAction.GetOffset() / 16f;
vector2.Y -= anim.PotOffset.Y / 64f;
- Viewpoint view = ((CameraManager.Viewpoint.IsOrthographic() || !CameraManager.ActionRunning) ? CameraManager.Viewpoint : CameraManager.LastViewpoint);
- return vector + (vector2.X * view.RightVector() * p.LookingDirection.Sign() + vector2.Y * Vector3.UnitY);
+ return vector + (vector2.X * view.RightVector() * LookingDir.Sign() + vector2.Y * Vector3.UnitY);
}
#endregion
}
diff --git a/FezMultiplayerMod/MultiplayerMod/MultiplayerClientNetcode.cs b/FezMultiplayerMod/MultiplayerMod/MultiplayerClientNetcode.cs
index 10ec575..fe0df4d 100644
--- a/FezMultiplayerMod/MultiplayerMod/MultiplayerClientNetcode.cs
+++ b/FezMultiplayerMod/MultiplayerMod/MultiplayerClientNetcode.cs
@@ -31,6 +31,7 @@ public abstract class MultiplayerClientNetcode : SharedNetcode,
public volatile bool Listening;
public PlayerAppearance MyAppearance;
private volatile bool MyAppearanceChanged = false;
+ public volatile uint ConnectionLatencyUp = 0;
public string MyPlayerName
{
get => MyAppearance.PlayerName;
@@ -71,7 +72,7 @@ internal MultiplayerClientNetcode(MultiplayerClientSettings settings)
{
bool retransmitAppearanceRequested = false;
ReadServerGameTickPacket(reader, ref retransmitAppearanceRequested);
- WriteClientGameTickPacket(writer, MyPlayerMetadata, null, null, MyAppearance, UnknownPlayerAppearanceGuids.Keys, false);
+ ConnectionLatencyUp = (uint)WriteClientGameTickPacket(writer, MyPlayerMetadata, null, null, MyAppearance, UnknownPlayerAppearanceGuids.Keys, false);
WasSucessfullyConnected = true;
while (true)
{
@@ -95,7 +96,7 @@ internal MultiplayerClientNetcode(MultiplayerClientSettings settings)
{
appearance = MyAppearance;
}
- WriteClientGameTickPacket(writer, MyPlayerMetadata, GetSaveDataUpdate(), activeLevelState, appearance, UnknownPlayerAppearanceGuids.Keys, false);
+ ConnectionLatencyUp = (uint)WriteClientGameTickPacket(writer, MyPlayerMetadata, GetSaveDataUpdate(), activeLevelState, appearance, UnknownPlayerAppearanceGuids.Keys, false);
}
else
{
diff --git a/Shared/Shared.cs b/Shared/Shared.cs
index dec2e27..c44c33e 100644
--- a/Shared/Shared.cs
+++ b/Shared/Shared.cs
@@ -7,6 +7,7 @@
using System.Net;
using System.Reflection;
using System.Text;
+using System.Diagnostics;
#if FEZCLIENT
using ActionType = FezGame.Structure.ActionType;
@@ -14,17 +15,10 @@
using Viewpoint = FezEngine.Viewpoint;
using Vector3 = Microsoft.Xna.Framework.Vector3;
#else
-using ActionType = System.Int32;
-using HorizontalDirection = System.Int32;
-using Viewpoint = System.Int32;
-public struct Vector3
-{
- public float X, Y, Z;
- public Vector3(float x, float y, float z)
- {
- X = x; Y = y; Z = z;
- }
-}
+using ActionType = FezMultiplayerDedicatedServer.ActionType;
+using HorizontalDirection = FezMultiplayerDedicatedServer.HorizontalDirection;
+using Viewpoint = FezMultiplayerDedicatedServer.Viewpoint;
+using Vector3 = FezMultiplayerDedicatedServer.Vector3;
#endif
namespace FezSharedTools
{
@@ -362,9 +356,14 @@ protected void ReadClientGameTickPacket(BinaryNetworkReader reader, ref MiscClie
retval.Metadata = playerMetadata;
retval.Disconnecting = Disconnecting;
}
- protected void WriteClientGameTickPacket(BinaryNetworkWriter writer0, PlayerMetadata playerMetadata, SaveDataUpdate? saveDataUpdate, ActiveLevelState? levelState,
+ ///
+ ///
+ /// the amount of time, in ticks, it took to write the data to the network
+ protected long WriteClientGameTickPacket(BinaryNetworkWriter writer0, PlayerMetadata playerMetadata, SaveDataUpdate? saveDataUpdate, ActiveLevelState? levelState,
PlayerAppearance? appearance, ICollection requestPlayerAppearance, bool Disconnecting)
{
+ Stopwatch sw = new Stopwatch();
+ int datalength;
//optimize network writing so it doesn't send a bazillion packets for a single tick
using (MemoryStream ms = new MemoryStream())
{
@@ -397,8 +396,14 @@ protected void WriteClientGameTickPacket(BinaryNetworkWriter writer0, PlayerMeta
writer.Write(Disconnecting);
writer.Flush();
}
- writer0.Write(ms.ToArray());
+ byte[] data = ms.ToArray();
+ datalength = data.Length;
+ sw.Start();
+ writer0.Write(data);
+ writer0.Flush();
+ sw.Stop();
}
+ return sw.ElapsedTicks / datalength;
}
protected void ReadServerGameTickPacket(BinaryNetworkReader reader, ref bool RetransmitAppearance)
{
@@ -448,10 +453,15 @@ protected void ReadServerGameTickPacket(BinaryNetworkReader reader, ref bool Ret
}
RetransmitAppearance = reader.ReadBoolean();
}
- protected void WriteServerGameTickPacket(BinaryNetworkWriter writer0, List playerMetadatas, SaveDataUpdate? saveDataUpdate, ICollection levelStates,
+ ///
+ ///
+ /// the amount of time, in ticks, it took to write the data to the network
+ protected long WriteServerGameTickPacket(BinaryNetworkWriter writer0, List playerMetadatas, SaveDataUpdate? saveDataUpdate, ICollection levelStates,
ICollection disconnectedPlayers, IDictionary appearances, Guid? NewClientGuid,
bool RequestAppearance, SharedSaveData sharedSaveData)
{
+ Stopwatch sw = new Stopwatch();
+ int datalength;
//optimize network writing so it doesn't send a bazillion packets for a single tick
using (MemoryStream ms = new MemoryStream())
{
@@ -494,8 +504,14 @@ protected void WriteServerGameTickPacket(BinaryNetworkWriter writer0, List