Working Version
This commit is contained in:
@@ -20,10 +20,12 @@ using SeamlessClient.OnlinePlayersWindow;
|
||||
using SeamlessClient.Utilities;
|
||||
using SpaceEngineers.Game.GUI;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using VRage;
|
||||
@@ -31,6 +33,7 @@ using VRage.Game;
|
||||
using VRage.Game.Entity;
|
||||
using VRage.Game.ModAPI;
|
||||
using VRage.GameServices;
|
||||
using VRage.Library.Utils;
|
||||
using VRage.Network;
|
||||
using VRage.Utils;
|
||||
using VRageRender;
|
||||
@@ -53,6 +56,7 @@ namespace SeamlessClient.ServerSwitching
|
||||
private static MethodInfo LoadMembersFromWorld;
|
||||
private static MethodInfo InitVirtualClients;
|
||||
private static MethodInfo CreateNewPlayerInternal;
|
||||
private static MethodInfo PauseClient;
|
||||
|
||||
private static FieldInfo VirtualClients;
|
||||
|
||||
@@ -85,6 +89,7 @@ namespace SeamlessClient.ServerSwitching
|
||||
{
|
||||
MySessionLayer = PatchUtils.GetProperty(typeof(MySession), "SyncLayer");
|
||||
|
||||
PauseClient = PatchUtils.GetMethod(PatchUtils.MyMultiplayerClientBase, "PauseClient");
|
||||
ClientConstructor = PatchUtils.GetConstructor(PatchUtils.ClientType, new[] { typeof(MyGameServerItem), PatchUtils.SyncLayerType });
|
||||
SyncLayerConstructor = PatchUtils.GetConstructor(PatchUtils.SyncLayerType, new[] { PatchUtils.MyTransportLayerType });
|
||||
TransportLayerConstructor = PatchUtils.GetConstructor(PatchUtils.MyTransportLayerType, new[] { typeof(int) });
|
||||
@@ -106,22 +111,20 @@ namespace SeamlessClient.ServerSwitching
|
||||
|
||||
|
||||
var onClientRemoved = PatchUtils.GetMethod(typeof(MyClientCollection), "RemoveClient");
|
||||
var onJoin = PatchUtils.GetMethod(PatchUtils.ClientType, "OnUserJoined");
|
||||
var onDisconnectedClient = PatchUtils.GetMethod(typeof(MyMultiplayerBase), "OnDisconnectedClient");
|
||||
var onClientConnected = PatchUtils.GetMethod(PatchUtils.ClientType, "OnClientConnected");
|
||||
var processAllMembersData = PatchUtils.GetMethod(typeof(MyMultiplayerBase), "ProcessAllMembersData");
|
||||
var RemovePlayer = PatchUtils.GetMethod(typeof(MyPlayerCollection), "RemovePlayerFromDictionary");
|
||||
|
||||
|
||||
var LoadClient = PatchUtils.GetMethod(PatchUtils.ClientType, "LoadMembersFromWorld");
|
||||
|
||||
Seamless.TryShow("Patched!");
|
||||
|
||||
|
||||
patcher.Patch(LoadClient, prefix: new HarmonyMethod(Get(typeof(ServerSwitcherComponent), nameof(LoadClientsFromWorld))));
|
||||
patcher.Patch(RemovePlayer, prefix: new HarmonyMethod(Get(typeof(ServerSwitcherComponent), nameof(RemovePlayerFromDict))));
|
||||
patcher.Patch(processAllMembersData, prefix: new HarmonyMethod(Get(typeof(ServerSwitcherComponent), nameof(ProcessAllMembersData))));
|
||||
patcher.Patch(onDisconnectedClient, prefix: new HarmonyMethod(Get(typeof(ServerSwitcherComponent), nameof(OnDisconnectedClient))));
|
||||
patcher.Patch(onClientRemoved, prefix: new HarmonyMethod(Get(typeof(ServerSwitcherComponent), nameof(RemoveClient))));
|
||||
patcher.Patch(onJoin, postfix: new HarmonyMethod(Get(typeof(ServerSwitcherComponent), nameof(OnUserJoined))));
|
||||
patcher.Patch(onAllmembersData, prefix: new HarmonyMethod(Get(typeof(ServerSwitcherComponent), nameof(OnAllMembersData))));
|
||||
|
||||
|
||||
@@ -134,11 +137,12 @@ namespace SeamlessClient.ServerSwitching
|
||||
|
||||
|
||||
|
||||
private static void OnUserJoined(ref JoinResultMsg msg)
|
||||
public static void OnUserJoined(JoinResult msg)
|
||||
{
|
||||
if (msg.JoinResult == JoinResult.OK)
|
||||
Seamless.TryShow($"OnUserJoin! Result: {msg}");
|
||||
if (msg == JoinResult.OK)
|
||||
{
|
||||
Seamless.TryShow("User Joined! Result: " + msg.JoinResult.ToString());
|
||||
|
||||
|
||||
//Invoke the switch event
|
||||
if (isSwitch)
|
||||
@@ -146,6 +150,39 @@ namespace SeamlessClient.ServerSwitching
|
||||
}
|
||||
}
|
||||
|
||||
public static bool LoadClientsFromWorld(ref List<MyObjectBuilder_Client> clients)
|
||||
{
|
||||
if(clients == null || clients.Count == 0)
|
||||
return false;
|
||||
|
||||
|
||||
//Dictionary<ulong, MyConnectedClientData>
|
||||
|
||||
IDictionary m_memberData = (IDictionary)PatchUtils.GetField(PatchUtils.ClientType, "m_memberData").GetValue(MyMultiplayer.Static);
|
||||
|
||||
Seamless.TryShow($"{m_memberData.Count} members from clients");
|
||||
|
||||
var keys = m_memberData.Keys.Cast<ulong>();
|
||||
|
||||
|
||||
|
||||
for(int i = clients.Count - 1; i >= 0; i-- )
|
||||
{
|
||||
Seamless.TryShow($"Client {clients[i].SteamId}");
|
||||
if (keys.Contains(clients[i].SteamId))
|
||||
{
|
||||
Seamless.TryShow($"Remove {clients[i].SteamId}");
|
||||
clients.RemoveAt(i);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
private static bool ProcessAllMembersData(ref AllMembersDataMsg msg)
|
||||
{
|
||||
|
||||
@@ -261,6 +298,22 @@ namespace SeamlessClient.ServerSwitching
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
public void ResetReplicationTime(bool ClientReady)
|
||||
{
|
||||
PatchUtils.GetField(typeof(MyReplicationClient), "m_lastServerTimestamp").SetValue(MyMultiplayer.Static.ReplicationLayer, MyTimeSpan.Zero);
|
||||
PatchUtils.GetField(typeof(MyReplicationClient), "m_lastServerTimeStampReceivedTime").SetValue(MyMultiplayer.Static.ReplicationLayer, MyTimeSpan.Zero);
|
||||
PatchUtils.GetField(typeof(MyReplicationClient), "m_clientStartTimeStamp").SetValue(MyMultiplayer.Static.ReplicationLayer, MyTimeSpan.Zero);
|
||||
PatchUtils.GetField(typeof(MyReplicationClient), "m_lastTime").SetValue(MyMultiplayer.Static.ReplicationLayer, MyTimeSpan.Zero);
|
||||
PatchUtils.GetField(typeof(MyReplicationClient), "m_lastClientTime").SetValue(MyMultiplayer.Static.ReplicationLayer, MyTimeSpan.Zero);
|
||||
PatchUtils.GetField(typeof(MyReplicationClient), "m_lastServerTime").SetValue(MyMultiplayer.Static.ReplicationLayer, MyTimeSpan.Zero);
|
||||
PatchUtils.GetField(typeof(MyReplicationClient), "m_lastClientTimestamp").SetValue(MyMultiplayer.Static.ReplicationLayer, MyTimeSpan.Zero);
|
||||
|
||||
|
||||
PatchUtils.GetField(typeof(MyReplicationClient), "m_clientReady").SetValue(MyMultiplayer.Static.ReplicationLayer, ClientReady);
|
||||
}
|
||||
|
||||
|
||||
private void UnloadServer()
|
||||
{
|
||||
if (MyMultiplayer.Static == null)
|
||||
@@ -279,15 +332,32 @@ namespace SeamlessClient.ServerSwitching
|
||||
//Sync.Clients.Clear();
|
||||
//Sync.Players.ClearPlayers();
|
||||
|
||||
|
||||
//Unregister Chat
|
||||
MyHud.Chat.UnregisterChat(MyMultiplayer.Static);
|
||||
|
||||
MethodInfo removeClient = PatchUtils.GetMethod(PatchUtils.ClientType, "MyMultiplayerClient_ClientLeft");
|
||||
foreach (var connectedClient in Sync.Clients.GetClients())
|
||||
{
|
||||
if (connectedClient.SteamUserId == Sync.MyId || connectedClient.SteamUserId == Sync.ServerId)
|
||||
continue;
|
||||
|
||||
removeClient.Invoke(MyMultiplayer.Static, new object[] { connectedClient.SteamUserId, MyChatMemberStateChangeEnum.Left });
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//Clear all local GPS Points
|
||||
MyReplicationClient client = (MyReplicationClient)MyMultiplayer.Static.ReplicationLayer;
|
||||
|
||||
client.Dispose();
|
||||
//client.Disconnect();
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
MyGameService.Peer2Peer.CloseSession(Sync.ServerId);
|
||||
MyGameService.DisconnectFromServer();
|
||||
|
||||
@@ -304,6 +374,9 @@ namespace SeamlessClient.ServerSwitching
|
||||
//MyMultiplayer.Static = null;
|
||||
|
||||
MyReplicationClient clienta = (MyReplicationClient)MyMultiplayer.Static.ReplicationLayer;
|
||||
|
||||
ResetReplicationTime(false);
|
||||
|
||||
Seamless.TryShow($"2 Streaming: {clienta.HasPendingStreamingReplicables} - LastMessage: {clienta.LastMessageFromServer}");
|
||||
Seamless.TryShow($"2 NexusMajor: {Seamless.NexusVersion.Major} - ConrolledEntity {MySession.Static.ControlledEntity == null} - HumanPlayer {MySession.Static.LocalHumanPlayer == null} - Character {MySession.Static.LocalCharacter == null}");
|
||||
}
|
||||
@@ -360,6 +433,9 @@ namespace SeamlessClient.ServerSwitching
|
||||
{
|
||||
Seamless.TryShow("Connected to server!");
|
||||
PatchUtils.ClientType.GetMethod("OnConnectToServer", BindingFlags.Instance | BindingFlags.NonPublic).Invoke(MyMultiplayer.Static, new object[] { joinResult });
|
||||
OnUserJoined(joinResult);
|
||||
|
||||
|
||||
}, "OnConnectToServer");
|
||||
});
|
||||
|
||||
@@ -424,8 +500,6 @@ namespace SeamlessClient.ServerSwitching
|
||||
|
||||
LoadConnectedClients();
|
||||
|
||||
|
||||
|
||||
//Sync.Clients.SetLocalSteamId(Sync.MyId, !Sync.Clients.HasClient(Sync.MyId), MyGameService.UserName);
|
||||
|
||||
|
||||
@@ -441,23 +515,24 @@ namespace SeamlessClient.ServerSwitching
|
||||
typeof(MySandboxGame).GetField("m_pauseStackCount", BindingFlags.Static | BindingFlags.NonPublic).SetValue(null, 0);
|
||||
|
||||
|
||||
MySandboxGame.IsPaused = false;
|
||||
|
||||
MyHud.Chat.RegisterChat(MyMultiplayer.Static);
|
||||
//GpsRegisterChat.Invoke(MySession.Static.Gpss, new object[] { MyMultiplayer.Static });
|
||||
|
||||
|
||||
// Allow the game to start proccessing incoming messages in the buffer
|
||||
MyMultiplayer.Static.StartProcessingClientMessages();
|
||||
|
||||
//Recreate all controls... Will fix weird gui/paint/crap
|
||||
MyGuiScreenHudSpace.Static?.RecreateControls(false);
|
||||
|
||||
Seamless.TryShow($"6 NexusMajor: {Seamless.NexusVersion.Major} - ConrolledEntity {MySession.Static.ControlledEntity == null} - HumanPlayer {MySession.Static.LocalHumanPlayer == null} - Character {MySession.Static.LocalCharacter == null}");
|
||||
Seamless.TryShow($"6 Streaming: {clienta.HasPendingStreamingReplicables} - LastMessage: {clienta.LastMessageFromServer}");
|
||||
|
||||
originalLocalCharacter.Close();
|
||||
originalLocalCharacter?.Close();
|
||||
ResetReplicationTime(true);
|
||||
|
||||
|
||||
|
||||
// Allow the game to start proccessing incoming messages in the buffer
|
||||
MyMultiplayer.Static.StartProcessingClientMessages();
|
||||
|
||||
//Send Client Ready
|
||||
ClientReadyDataMsg clientReadyDataMsg = default(ClientReadyDataMsg);
|
||||
clientReadyDataMsg.ForcePlayoutDelayBuffer = MyFakes.ForcePlayoutDelayBuffer;
|
||||
@@ -467,6 +542,8 @@ namespace SeamlessClient.ServerSwitching
|
||||
ClientReadyDataMsg msg = clientReadyDataMsg;
|
||||
clienta.SendClientReady(ref msg);
|
||||
|
||||
PauseClient.Invoke(MyMultiplayer.Static, new object[] { false });
|
||||
|
||||
isSwitch = false;
|
||||
}
|
||||
|
||||
@@ -582,14 +659,7 @@ namespace SeamlessClient.ServerSwitching
|
||||
|
||||
private void InitComponents()
|
||||
{
|
||||
//MySession.Static.LoadObjectBuildersComponents(TargetWorld.Checkpoint.SessionComponents);
|
||||
//MyModAPIHelper.Initialize();
|
||||
// MySession.Static.LoadObjectBuildersComponents(TargetWorld.Checkpoint.SessionComponents);
|
||||
|
||||
//MySession.Static.LoadDataComponents();
|
||||
UpdateWorldGenerator();
|
||||
//MethodInfo A = typeof(MySession).GetMethod("LoadGameDefinition", BindingFlags.Instance | BindingFlags.NonPublic);
|
||||
// A.Invoke(MySession.Static, new object[] { TargetWorld.Checkpoint });
|
||||
}
|
||||
|
||||
|
||||
@@ -690,53 +760,34 @@ namespace SeamlessClient.ServerSwitching
|
||||
|
||||
private void LoadConnectedClients()
|
||||
{
|
||||
|
||||
//Sync.Clients.SetLocalSteamId(Sync.MyId, !Sync.Clients.HasClient(Sync.MyId), MyGameService.UserName);
|
||||
|
||||
|
||||
Seamless.TryShow($"BEFORE {MySession.Static.LocalHumanPlayer == null} - {MySession.Static.LocalCharacter == null}");
|
||||
|
||||
|
||||
|
||||
LoadMembersFromWorld.Invoke(MySession.Static, new object[] { TargetWorld, MyMultiplayer.Static });
|
||||
|
||||
|
||||
//Re-Initilize Virtual clients
|
||||
//object VirtualClientsValue = VirtualClients.GetValue(MySession.Static);
|
||||
//InitVirtualClients.Invoke(VirtualClientsValue, null);
|
||||
|
||||
|
||||
|
||||
MyPlayer.PlayerId? savingPlayerId = new MyPlayer.PlayerId(Sync.MyId);
|
||||
if (!savingPlayerId.HasValue)
|
||||
{
|
||||
Seamless.TryShow("SavingPlayerID is null! Creating Default!");
|
||||
savingPlayerId = new MyPlayer.PlayerId(Sync.MyId);
|
||||
}
|
||||
|
||||
|
||||
|
||||
LoadMembersFromWorld.Invoke(MySession.Static, new object[] { TargetWorld, MyMultiplayer.Static });
|
||||
|
||||
|
||||
|
||||
|
||||
player.IsWildlifeAgent = true;
|
||||
CreateNewPlayerInternal.Invoke(MySession.Static.Players, new object[] { Sync.Clients.LocalClient, savingPlayerId.Value, player });
|
||||
typeof(MyPlayerCollection).GetMethod("LoadPlayerInternal", BindingFlags.Instance | BindingFlags.NonPublic).Invoke(MySession.Static.Players, new object[] { savingPlayerId.Value, player, false });
|
||||
|
||||
Seamless.TryShow("Saving PlayerID: " + savingPlayerId.ToString());
|
||||
|
||||
Sync.Players.LoadConnectedPlayers(TargetWorld.Checkpoint, savingPlayerId);
|
||||
Sync.Players.LoadControlledEntities(TargetWorld.Checkpoint.ControlledEntities, TargetWorld.Checkpoint.ControlledObject, savingPlayerId);
|
||||
|
||||
|
||||
|
||||
|
||||
Seamless.TryShow("Saving PlayerID: " + savingPlayerId.ToString());
|
||||
|
||||
Seamless.TryShow($"AFTER {MySession.Static.LocalHumanPlayer == null} - {MySession.Static.LocalCharacter == null}");
|
||||
// MySession.Static.Players.OnInitialPlayerCreated(Sync.MyId, 0, false, playerDataMsg.PlayerBuilder);
|
||||
|
||||
|
||||
// if (TargetWorld.Checkpoint.ConnectedPlayers.Dictionary.Any(x => x.Key.ClientId == savingPlayerId.Value.SteamId))
|
||||
// Seamless.TryShow("Checkpoint already has player!");
|
||||
|
||||
|
||||
|
||||
//Sync.Players.LoadConnectedPlayers(TargetWorld.Checkpoint, savingPlayerId);
|
||||
//Sync.Players.LoadControlledEntities(TargetWorld.Checkpoint.ControlledEntities, TargetWorld.Checkpoint.ControlledObject, savingPlayerId);
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -110,21 +110,17 @@ namespace SeamlessClient
|
||||
private static void MessageHandler(ushort packetID, byte[] data, ulong sender, bool fromServer)
|
||||
{
|
||||
//Ignore anything except dedicated server
|
||||
Seamless.TryShow("1!");
|
||||
if (!fromServer || sender == 0)
|
||||
return;
|
||||
|
||||
Seamless.TryShow("2!");
|
||||
ClientMessage msg = MessageUtils.Deserialize<ClientMessage>(data);
|
||||
if (msg == null)
|
||||
return;
|
||||
|
||||
Seamless.TryShow("3!");
|
||||
//Get Nexus Version
|
||||
if (!string.IsNullOrEmpty(msg.NexusVersion))
|
||||
NexusVersion = Version.Parse(msg.NexusVersion);
|
||||
|
||||
Seamless.TryShow("4!");
|
||||
|
||||
switch (msg.MessageType)
|
||||
{
|
||||
|
Reference in New Issue
Block a user