update seamless

This commit is contained in:
Garrett
2023-09-02 00:59:34 -05:00
parent 95bb9476f1
commit 426a207e13
7 changed files with 350 additions and 64 deletions

View File

@@ -15,8 +15,8 @@ namespace SeamlessClient.OnlinePlayersWindow
public class PlayersWindowComponent : ComponentBase public class PlayersWindowComponent : ComponentBase
{ {
public static List<OnlineServer> allServers = new List<OnlineServer>(); public static List<OnlineClientServer> allServers = new List<OnlineClientServer>();
public static OnlineServer onlineServer; public static OnlineClientServer onlineServer;
public override void Patch(Harmony patcher) public override void Patch(Harmony patcher)
@@ -30,14 +30,14 @@ namespace SeamlessClient.OnlinePlayersWindow
MyPerGameSettings.GUI.PlayersScreen = typeof(OnlineNexusPlayersWindow); MyPerGameSettings.GUI.PlayersScreen = typeof(OnlineNexusPlayersWindow);
} }
public static void ApplyRecievedPlayers(List<OnlineServer> servers, int CurrentServer) public static void ApplyRecievedPlayers(List<OnlineClientServer> servers, int CurrentServer)
{ {
//Seamless.TryShow($"Recieved {CurrentServer} - {servers.Count}"); //Seamless.TryShow($"Recieved {CurrentServer} - {servers.Count}");
allServers.Clear(); allServers.Clear();
foreach (OnlineServer server in servers) foreach (OnlineClientServer server in servers)
{ {
if(server.ServerID == CurrentServer) if(server.ServerID == CurrentServer)
{ {

View File

@@ -2,14 +2,18 @@
using Sandbox; using Sandbox;
using Sandbox.Engine.Multiplayer; using Sandbox.Engine.Multiplayer;
using Sandbox.Engine.Networking; using Sandbox.Engine.Networking;
using Sandbox.Engine.Utils;
using Sandbox.Game; using Sandbox.Game;
using Sandbox.Game.Entities; using Sandbox.Game.Entities;
using Sandbox.Game.Entities.Character;
using Sandbox.Game.Gui; using Sandbox.Game.Gui;
using Sandbox.Game.GUI; using Sandbox.Game.GUI;
using Sandbox.Game.Multiplayer; using Sandbox.Game.Multiplayer;
using Sandbox.Game.Replication;
using Sandbox.Game.SessionComponents; using Sandbox.Game.SessionComponents;
using Sandbox.Game.World; using Sandbox.Game.World;
using Sandbox.Game.World.Generator; using Sandbox.Game.World.Generator;
using Sandbox.Graphics.GUI;
using Sandbox.ModAPI; using Sandbox.ModAPI;
using SeamlessClient.Components; using SeamlessClient.Components;
using SeamlessClient.OnlinePlayersWindow; using SeamlessClient.OnlinePlayersWindow;
@@ -17,11 +21,14 @@ using SeamlessClient.Utilities;
using SpaceEngineers.Game.GUI; using SpaceEngineers.Game.GUI;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics;
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using VRage;
using VRage.Game; using VRage.Game;
using VRage.Game.Entity;
using VRage.Game.ModAPI; using VRage.Game.ModAPI;
using VRage.GameServices; using VRage.GameServices;
using VRage.Network; using VRage.Network;
@@ -45,6 +52,7 @@ namespace SeamlessClient.ServerSwitching
private static MethodInfo GpsRegisterChat; private static MethodInfo GpsRegisterChat;
private static MethodInfo LoadMembersFromWorld; private static MethodInfo LoadMembersFromWorld;
private static MethodInfo InitVirtualClients; private static MethodInfo InitVirtualClients;
private static MethodInfo CreateNewPlayerInternal;
private static FieldInfo VirtualClients; private static FieldInfo VirtualClients;
@@ -59,6 +67,12 @@ namespace SeamlessClient.ServerSwitching
public static event EventHandler<JoinResultMsg> OnJoinEvent; public static event EventHandler<JoinResultMsg> OnJoinEvent;
private MyCharacter originalLocalCharacter;
private IMyControllableEntity originalControlledEntity;
private static bool isSwitch = false;
private MyObjectBuilder_Player player { get; set; }
public ServerSwitcherComponent() public ServerSwitcherComponent()
@@ -85,10 +99,35 @@ namespace SeamlessClient.ServerSwitching
LoadMembersFromWorld = PatchUtils.GetMethod(typeof(MySession), "LoadMembersFromWorld"); LoadMembersFromWorld = PatchUtils.GetMethod(typeof(MySession), "LoadMembersFromWorld");
InitVirtualClients = PatchUtils.GetMethod(PatchUtils.VirtualClientsType, "Init"); InitVirtualClients = PatchUtils.GetMethod(PatchUtils.VirtualClientsType, "Init");
CreateNewPlayerInternal = PatchUtils.GetMethod(typeof(MyPlayerCollection), "CreateNewPlayerInternal");
MethodInfo onAllmembersData = PatchUtils.ClientType.GetMethod("OnAllMembersData", BindingFlags.Instance | BindingFlags.NonPublic);
var onClientRemoved = PatchUtils.GetMethod(typeof(MyClientCollection), "RemoveClient");
var onJoin = PatchUtils.GetMethod(PatchUtils.ClientType, "OnUserJoined"); 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");
Seamless.TryShow("Patched!");
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(onJoin, postfix: new HarmonyMethod(Get(typeof(ServerSwitcherComponent), nameof(OnUserJoined))));
patcher.Patch(onAllmembersData, prefix: new HarmonyMethod(Get(typeof(ServerSwitcherComponent), nameof(OnAllMembersData))));
patcher.Patch(onClientConnected, prefix: new HarmonyMethod(Get(typeof(ServerSwitcherComponent), nameof(OnClientConnected))));
base.Patch(patcher); base.Patch(patcher);
} }
@@ -102,13 +141,44 @@ namespace SeamlessClient.ServerSwitching
Seamless.TryShow("User Joined! Result: " + msg.JoinResult.ToString()); Seamless.TryShow("User Joined! Result: " + msg.JoinResult.ToString());
//Invoke the switch event //Invoke the switch event
OnJoinEvent?.Invoke(null, msg); if (isSwitch)
Instance.StartSwitch();
} }
} }
private static bool ProcessAllMembersData(ref AllMembersDataMsg msg)
{
Sync.Players.ClearIdentities();
if (msg.Identities != null)
{
Sync.Players.LoadIdentities(msg.Identities);
}
Seamless.TryShow($"Clearing Players! \n {Environment.StackTrace.ToString()} ");
//Sync.Players.ClearPlayers();
if (msg.Players != null)
{
Sync.Players.LoadPlayers(msg.Players);
}
//MySession.Static.Factions.LoadFactions(msg.Factions);
return false;
}
private static bool RemovePlayerFromDict(MyPlayer.PlayerId playerId)
{
//Seamless.TryShow($"Removing player {playerId.SteamId} from dictionariy! \n {Environment.StackTrace.ToString()} - Sender: {MyEventContext.Current.Sender}");
return true;
}
public override void Initilized() public override void Initilized()
{ {
@@ -116,8 +186,39 @@ namespace SeamlessClient.ServerSwitching
} }
public static bool OnClientConnected(MyPacket packet)
{
Seamless.TryShow("OnClientConnected");
return true;
}
public static void RemoveClient(ulong steamId)
{
if (steamId != Sync.MyId)
return;
//Seamless.TryShow(Environment.StackTrace.ToString());
}
public static void OnAllMembersData(ref AllMembersDataMsg msg)
{
Seamless.TryShow("Recieved all members data!");
}
public static bool OnDisconnectedClient(ref MyControlDisconnectedMsg data, ulong sender)
{
Seamless.TryShow($"OnDisconnectedClient {data.Client} - Sender {sender}");
if (data.Client == Sync.MyId)
return false;
return true;
}
public void StartBackendSwitch(MyGameServerItem TargetServer, MyObjectBuilder_World TargetWorld) public void StartBackendSwitch(MyGameServerItem TargetServer, MyObjectBuilder_World TargetWorld)
{ {
@@ -125,20 +226,38 @@ namespace SeamlessClient.ServerSwitching
this.TargetWorld = TargetWorld; this.TargetWorld = TargetWorld;
OldArmorSkin = MySession.Static.LocalHumanPlayer.BuildArmorSkin; OldArmorSkin = MySession.Static.LocalHumanPlayer.BuildArmorSkin;
Seamless.TryShow($"1 NexusMajor: {Seamless.NexusVersion.Major} - ConrolledEntity {MySession.Static.ControlledEntity == null} - HumanPlayer {MySession.Static.LocalHumanPlayer == null} - Character {MySession.Static.LocalCharacter == null}");
if (Seamless.NexusVersion.Major >= 2) if (Seamless.NexusVersion.Major >= 2)
needsEntityUnload = false; needsEntityUnload = false;
isSwitch = true;
originalLocalCharacter = MySession.Static.LocalCharacter;
//originalControlledEntity = MySession.Static.ControlledEntity;
player = MySession.Static.LocalHumanPlayer.GetObjectBuilder();
player.Connected = false;
AsyncInvoke.InvokeAsync(() => AsyncInvoke.InvokeAsync(() =>
{ {
if(needsEntityUnload) Seamless.TryShow($"Needs entity Unload: {needsEntityUnload}");
MySession.Static.SetCameraController(MyCameraControllerEnum.SpectatorFixed);
//if (needsEntityUnload)
// MySession.Static.SetCameraController(MyCameraControllerEnum.SpectatorFixed);
UnloadServer(); try
SetNewMultiplayerClient(); {
UnloadServer();
SetNewMultiplayerClient();
}catch(Exception ex)
{
Seamless.TryShow(ex.ToString());
}
}); });
} }
@@ -147,6 +266,7 @@ namespace SeamlessClient.ServerSwitching
if (MyMultiplayer.Static == null) if (MyMultiplayer.Static == null)
throw new Exception("MyMultiplayer.Static is null on unloading? dafuq?"); throw new Exception("MyMultiplayer.Static is null on unloading? dafuq?");
UnloadOldEntities(); UnloadOldEntities();
//Close and Cancel any screens (Medical or QuestLog) //Close and Cancel any screens (Medical or QuestLog)
@@ -156,41 +276,99 @@ namespace SeamlessClient.ServerSwitching
//Clear all old players and clients. //Clear all old players and clients.
Sync.Clients.Clear(); //Sync.Clients.Clear();
Sync.Players.ClearPlayers(); //Sync.Players.ClearPlayers();
//Unregister Chat //Unregister Chat
MyHud.Chat.UnregisterChat(MyMultiplayer.Static); MyHud.Chat.UnregisterChat(MyMultiplayer.Static);
//Clear all local GPS Points //Clear all local GPS Points
MySession.Static.Gpss.RemovePlayerGpss(MySession.Static.LocalPlayerId); MyReplicationClient client = (MyReplicationClient)MyMultiplayer.Static.ReplicationLayer;
MyHud.GpsMarkers.Clear();
//client.Disconnect();
MyGameService.Peer2Peer.CloseSession(Sync.ServerId);
MyGameService.DisconnectFromServer();
MyControlDisconnectedMsg myControlDisconnectedMsg = default(MyControlDisconnectedMsg);
myControlDisconnectedMsg.Client = Sync.MyId;
typeof(MyMultiplayerBase).GetMethod("SendControlMessage", BindingFlags.Instance | BindingFlags.NonPublic).MakeGenericMethod(typeof(MyControlDisconnectedMsg)).Invoke(MyMultiplayer.Static, new object[] { Sync.ServerId, myControlDisconnectedMsg, true });
//DisconnectReplication //DisconnectReplication
MyMultiplayer.Static.ReplicationLayer.Disconnect(); //MyMultiplayer.Static.ReplicationLayer.Disconnect();
MyMultiplayer.Static.ReplicationLayer.Dispose(); //MyMultiplayer.Static.ReplicationLayer.Dispose();
MyMultiplayer.Static.Dispose(); //MyMultiplayer.Static.Dispose();
MyMultiplayer.Static = null; //MyMultiplayer.Static = null;
MyReplicationClient clienta = (MyReplicationClient)MyMultiplayer.Static.ReplicationLayer;
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}");
} }
private void UnloadOldEntities() private void UnloadOldEntities()
{ {
foreach (var ent in MyEntities.GetEntities()) foreach (var ent in MyEntities.GetEntities())
{ {
if (ent is MyPlanet) if (ent is MyPlanet)
continue; continue;
//ent.Close(); if (ent is MyCharacter)
continue;
ent.Close();
if (needsEntityUnload)
{
ent.Close();
}
else
{
//
}
} }
} }
private void SetNewMultiplayerClient() private void SetNewMultiplayerClient()
{ {
OnJoinEvent += ServerSwitcherComponent_OnJoinEvent;
MyReplicationClient clienta = (MyReplicationClient)MyMultiplayer.Static.ReplicationLayer;
Seamless.TryShow($"3 Streaming: {clienta.HasPendingStreamingReplicables} - LastMessage: {clienta.LastMessageFromServer}");
Seamless.TryShow($"3 NexusMajor: {Seamless.NexusVersion.Major} - ConrolledEntity {MySession.Static.ControlledEntity == null} - HumanPlayer {MySession.Static.LocalHumanPlayer == null} - Character {MySession.Static.LocalCharacter == null}");
MySandboxGame.Static.SessionCompatHelper.FixSessionComponentObjectBuilders(TargetWorld.Checkpoint, TargetWorld.Sector); MySandboxGame.Static.SessionCompatHelper.FixSessionComponentObjectBuilders(TargetWorld.Checkpoint, TargetWorld.Sector);
PatchUtils.ClientType.GetProperty("Server", BindingFlags.Public | BindingFlags.Instance).SetValue(MyMultiplayer.Static, TargetServer);
typeof(MyMultiplayerBase).GetProperty("ServerId", BindingFlags.Public | BindingFlags.Instance).SetValue(MyMultiplayer.Static, TargetServer.SteamID);
MyGameService.ConnectToServer(TargetServer, delegate (JoinResult joinResult)
{
MySandboxGame.Static.Invoke(delegate
{
Seamless.TryShow("Connected to server!");
PatchUtils.ClientType.GetMethod("OnConnectToServer", BindingFlags.Instance | BindingFlags.NonPublic).Invoke(MyMultiplayer.Static, new object[] { joinResult });
}, "OnConnectToServer");
});
Seamless.TryShow($"4 Streaming: {clienta.HasPendingStreamingReplicables} - LastMessage: {clienta.LastMessageFromServer}");
Seamless.TryShow($"4 NexusMajor: {Seamless.NexusVersion.Major} - ConrolledEntity {MySession.Static.ControlledEntity == null} - HumanPlayer {MySession.Static.LocalHumanPlayer == null} - Character {MySession.Static.LocalCharacter == null}");
return;
// Create constructors // Create constructors
var LayerInstance = TransportLayerConstructor.Invoke(new object[] { 2 }); var LayerInstance = TransportLayerConstructor.Invoke(new object[] { 2 });
var SyncInstance = SyncLayerConstructor.Invoke(new object[] { LayerInstance }); var SyncInstance = SyncLayerConstructor.Invoke(new object[] { LayerInstance });
@@ -200,27 +378,25 @@ namespace SeamlessClient.ServerSwitching
MyMultiplayer.Static = UtilExtensions.CastToReflected(instance, PatchUtils.ClientType); MyMultiplayer.Static = UtilExtensions.CastToReflected(instance, PatchUtils.ClientType);
MyMultiplayer.Static.ExperimentalMode = true; MyMultiplayer.Static.ExperimentalMode = true;
// Set the new SyncLayer to the MySession.Static.SyncLayer // Set the new SyncLayer to the MySession.Static.SyncLayer
MySessionLayer.SetValue(MySession.Static, MyMultiplayer.Static.SyncLayer); MySessionLayer.SetValue(MySession.Static, MyMultiplayer.Static.SyncLayer);
Seamless.TryShow("Successfully set MyMultiplayer.Static"); Seamless.TryShow("Successfully set MyMultiplayer.Static");
Sync.Clients.SetLocalSteamId(Sync.MyId, false, MyGameService.UserName); Sync.Clients.SetLocalSteamId(Sync.MyId, false, MyGameService.UserName);
Sync.Players.RegisterEvents(); Sync.Players.RegisterEvents();
} }
private void ServerSwitcherComponent_OnJoinEvent(object sender, JoinResultMsg e) private void StartSwitch()
{ {
OnJoinEvent -= ServerSwitcherComponent_OnJoinEvent;
if (e.JoinResult != JoinResult.OK)
{
Seamless.TryShow("Failed to join the target server!");
return;
}
MyReplicationClient clienta = (MyReplicationClient)MyMultiplayer.Static.ReplicationLayer;
Seamless.TryShow($"5 Streaming: {clienta.HasPendingStreamingReplicables} - LastMessage: {clienta.LastMessageFromServer}");
Seamless.TryShow($"5 NexusMajor: {Seamless.NexusVersion.Major} - ConrolledEntity {MySession.Static.ControlledEntity == null} - HumanPlayer {MySession.Static.LocalHumanPlayer == null} - Character {MySession.Static.LocalCharacter == null}");
Seamless.TryShow("Starting new MP Client!"); Seamless.TryShow("Starting new MP Client!");
/* On Server Successfull Join /* On Server Successfull Join
@@ -229,24 +405,69 @@ namespace SeamlessClient.ServerSwitching
*/ */
List<ulong> clients = new List<ulong>();
foreach(var client in Sync.Clients.GetClients())
{
clients.Add(client.SteamUserId);
Seamless.TryShow($"{client.SteamUserId} - {Sync.MyId}");
}
foreach(var client in clients)
{
if (client == TargetServer.SteamID || client == Sync.MyId)
continue;
Seamless.TryShow($"REMOVING {client}");
Sync.Clients.RemoveClient(client);
}
LoadConnectedClients();
//Sync.Clients.SetLocalSteamId(Sync.MyId, !Sync.Clients.HasClient(Sync.MyId), MyGameService.UserName);
SetWorldSettings(); SetWorldSettings();
InitComponents(); InitComponents();
LoadConnectedClients();
StartEntitySync(); StartEntitySync();
MyMultiplayer.Static.OnSessionReady();
typeof(MySandboxGame).GetField("m_pauseStackCount", BindingFlags.Static | BindingFlags.NonPublic).SetValue(null, 0);
MySandboxGame.IsPaused = false;
MyHud.Chat.RegisterChat(MyMultiplayer.Static); MyHud.Chat.RegisterChat(MyMultiplayer.Static);
GpsRegisterChat.Invoke(MySession.Static.Gpss, new object[] { MyMultiplayer.Static }); //GpsRegisterChat.Invoke(MySession.Static.Gpss, new object[] { MyMultiplayer.Static });
// Allow the game to start proccessing incoming messages in the buffer // Allow the game to start proccessing incoming messages in the buffer
MyMultiplayer.Static.StartProcessingClientMessages(); MyMultiplayer.Static.StartProcessingClientMessages();
//Recreate all controls... Will fix weird gui/paint/crap //Recreate all controls... Will fix weird gui/paint/crap
MyGuiScreenHudSpace.Static.RecreateControls(true); 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();
//Send Client Ready
ClientReadyDataMsg clientReadyDataMsg = default(ClientReadyDataMsg);
clientReadyDataMsg.ForcePlayoutDelayBuffer = MyFakes.ForcePlayoutDelayBuffer;
clientReadyDataMsg.UsePlayoutDelayBufferForCharacter = true;
clientReadyDataMsg.UsePlayoutDelayBufferForJetpack = true;
clientReadyDataMsg.UsePlayoutDelayBufferForGrids = true;
ClientReadyDataMsg msg = clientReadyDataMsg;
clienta.SendClientReady(ref msg);
isSwitch = false;
} }
@@ -284,7 +505,6 @@ namespace SeamlessClient.ServerSwitching
try try
{ {
MySession.Static.Gpss = new MyGpsCollection(); MySession.Static.Gpss = new MyGpsCollection();
MySession.Static.Gpss.LoadGpss(TargetWorld.Checkpoint);
} }
catch (Exception ex) catch (Exception ex)
@@ -362,13 +582,11 @@ namespace SeamlessClient.ServerSwitching
private void InitComponents() private void InitComponents()
{ {
MyModAPIHelper.Initialize();
MySession.Static.LoadDataComponents();
//MySession.Static.LoadObjectBuildersComponents(TargetWorld.Checkpoint.SessionComponents); //MySession.Static.LoadObjectBuildersComponents(TargetWorld.Checkpoint.SessionComponents);
MyModAPIHelper.Initialize(); //MyModAPIHelper.Initialize();
// MySession.Static.LoadObjectBuildersComponents(TargetWorld.Checkpoint.SessionComponents); // MySession.Static.LoadObjectBuildersComponents(TargetWorld.Checkpoint.SessionComponents);
//MySession.Static.LoadDataComponents();
UpdateWorldGenerator(); UpdateWorldGenerator();
//MethodInfo A = typeof(MySession).GetMethod("LoadGameDefinition", BindingFlags.Instance | BindingFlags.NonPublic); //MethodInfo A = typeof(MySession).GetMethod("LoadGameDefinition", BindingFlags.Instance | BindingFlags.NonPublic);
// A.Invoke(MySession.Static, new object[] { TargetWorld.Checkpoint }); // A.Invoke(MySession.Static, new object[] { TargetWorld.Checkpoint });
@@ -412,25 +630,50 @@ namespace SeamlessClient.ServerSwitching
private void StartEntitySync() private void StartEntitySync()
{ {
Seamless.TryShow("Requesting Player From Server"); Seamless.TryShow("Requesting Player From Server");
Sync.Players.RequestNewPlayer(Sync.MyId, 0, MyGameService.UserName, null, realPlayer: true, initialPlayer: true);
if (MySession.Static.ControlledEntity == null && Sync.IsServer && !Sandbox.Engine.Platform.Game.IsDedicated) Sync.Players.RequestNewPlayer(Sync.MyId, 0, MyGameService.UserName, null, true, true);
if (!Sandbox.Engine.Platform.Game.IsDedicated && MySession.Static.LocalHumanPlayer == null)
{ {
MyLog.Default.WriteLine("ControlledObject was null, respawning character"); Seamless.TryShow("RequestNewPlayer");
}
else if (MySession.Static.ControlledEntity == null && Sync.IsServer && !Sandbox.Engine.Platform.Game.IsDedicated)
{
Seamless.TryShow("ControlledObject was null, respawning character");
//m_cameraAwaitingEntity = true; //m_cameraAwaitingEntity = true;
MyPlayerCollection.RequestLocalRespawn(); MyPlayerCollection.RequestLocalRespawn();
} }
//Request client state batch //Request client state batch
(MyMultiplayer.Static as MyMultiplayerClientBase).RequestBatchConfirmation(); (MyMultiplayer.Static as MyMultiplayerClientBase).RequestBatchConfirmation();
MyMultiplayer.Static.PendingReplicablesDone += Static_PendingReplicablesDone; MyMultiplayer.Static.PendingReplicablesDone += Static_PendingReplicablesDone;
//typeof(MyGuiScreenTerminal).GetMethod("CreateTabs") //typeof(MyGuiScreenTerminal).GetMethod("CreateTabs")
MySession.Static.LoadDataComponents();
//MyGuiSandbox.LoadData(false);
//MyGuiSandbox.AddScreen(MyGuiSandbox.CreateScreen(MyPerGameSettings.GUI.HUDScreen));
//MySession.Static.LocalHumanPlayer.Controller.TakeControl(originalControlledEntity);
MyGuiSandbox.UnloadContent();
MyGuiSandbox.LoadContent();
//MyGuiSandbox.CreateScreen(MyPerGameSettings.GUI.HUDScreen);
MyRenderProxy.RebuildCullingStructure(); MyRenderProxy.RebuildCullingStructure();
MyRenderProxy.CollectGarbage(); MyRenderProxy.CollectGarbage();
Seamless.TryShow("OnlinePlayers: " + MySession.Static.Players.GetOnlinePlayers().Count); Seamless.TryShow("OnlinePlayers: " + MySession.Static.Players.GetOnlinePlayers().Count);
Seamless.TryShow("Loading Complete!"); Seamless.TryShow("Loading Complete!");
} }
@@ -442,16 +685,25 @@ namespace SeamlessClient.ServerSwitching
MySandboxGame.AreClipmapsReady = false; MySandboxGame.AreClipmapsReady = false;
} }
MyMultiplayer.Static.PendingReplicablesDone -= Static_PendingReplicablesDone; MyMultiplayer.Static.PendingReplicablesDone -= Static_PendingReplicablesDone;
} }
private void LoadConnectedClients() 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 }); LoadMembersFromWorld.Invoke(MySession.Static, new object[] { TargetWorld, MyMultiplayer.Static });
//Re-Initilize Virtual clients //Re-Initilize Virtual clients
object VirtualClientsValue = VirtualClients.GetValue(MySession.Static); //object VirtualClientsValue = VirtualClients.GetValue(MySession.Static);
InitVirtualClients.Invoke(VirtualClientsValue, null); //InitVirtualClients.Invoke(VirtualClientsValue, null);
@@ -461,10 +713,30 @@ namespace SeamlessClient.ServerSwitching
Seamless.TryShow("SavingPlayerID is null! Creating Default!"); Seamless.TryShow("SavingPlayerID is null! Creating Default!");
savingPlayerId = new MyPlayer.PlayerId(Sync.MyId); savingPlayerId = new MyPlayer.PlayerId(Sync.MyId);
} }
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()); Seamless.TryShow("Saving PlayerID: " + savingPlayerId.ToString());
Sync.Players.LoadConnectedPlayers(TargetWorld.Checkpoint, savingPlayerId); Seamless.TryShow($"AFTER {MySession.Static.LocalHumanPlayer == null} - {MySession.Static.LocalCharacter == null}");
Sync.Players.LoadControlledEntities(TargetWorld.Checkpoint.ControlledEntities, TargetWorld.Checkpoint.ControlledObject, savingPlayerId); // 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);
} }
} }
} }

View File

@@ -36,6 +36,13 @@ namespace SeamlessClient.Messages
this.PluginVersion = PluginVersion; this.PluginVersion = PluginVersion;
} }
public ClientMessage(ClientMessageType messageType, string NexusVersion)
{
this.MessageType = messageType;
this.NexusVersion = NexusVersion;
}
public ClientMessage() { } public ClientMessage() { }
@@ -53,5 +60,10 @@ namespace SeamlessClient.Messages
return msg; return msg;
} }
public void SerializeData<T>(T Data)
{
MessageData = MessageUtils.Serialize(Data);
}
} }
} }

View File

@@ -10,13 +10,13 @@ namespace SeamlessClient.Messages
[ProtoContract] [ProtoContract]
public class OnlinePlayerData public class OnlinePlayerData
{ {
[ProtoMember(10)] public List<OnlineServer> OnlineServers = new List<OnlineServer>(); [ProtoMember(10)] public List<OnlineClientServer> OnlineServers = new List<OnlineClientServer>();
[ProtoMember(12)] public int currentServerID; [ProtoMember(12)] public int currentServerID;
} }
[ProtoContract] [ProtoContract]
public class OnlineServer public class OnlineClientServer
{ {
[ProtoMember(2)] public List<OnlinePlayer> Players = new List<OnlinePlayer>(); [ProtoMember(2)] public List<OnlinePlayer> Players = new List<OnlinePlayer>();
@@ -26,7 +26,7 @@ namespace SeamlessClient.Messages
[ProtoMember(11)] public string ServerName; [ProtoMember(11)] public string ServerName;
public OnlineServer() public OnlineClientServer()
{ {
} }
} }

View File

@@ -10,6 +10,7 @@ using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using VRage.Game; using VRage.Game;
using VRage.ObjectBuilders; using VRage.ObjectBuilders;
using VRage.ObjectBuilders.Private;
namespace SeamlessClient.Messages namespace SeamlessClient.Messages
{ {
@@ -52,8 +53,8 @@ namespace SeamlessClient.Messages
WorldData = (MyObjectBuilder_World)data[0]; WorldData = (MyObjectBuilder_World)data[0];
using (var memoryStream = new MemoryStream()) using (var memoryStream = new MemoryStream())
{ {
MyObjectBuilderSerializer.SerializeXML(memoryStream, WorldData, MyObjectBuilderSerializerKeen.SerializeXML(memoryStream, WorldData,
MyObjectBuilderSerializer.XmlCompression.Gzip); MyObjectBuilderSerializerKeen.XmlCompression.Gzip);
this.WorldData = memoryStream.ToArray(); this.WorldData = memoryStream.ToArray();
Log.Warn("Successfully Converted World"); Log.Warn("Successfully Converted World");
} }
@@ -61,7 +62,7 @@ namespace SeamlessClient.Messages
public MyObjectBuilder_World DeserializeWorldData() public MyObjectBuilder_World DeserializeWorldData()
{ {
MyObjectBuilderSerializer.DeserializeGZippedXML<MyObjectBuilder_World>(new MemoryStream(WorldData), MyObjectBuilderSerializerKeen.DeserializeGZippedXML<MyObjectBuilder_World>(new MemoryStream(WorldData),
out var objectBuilder); out var objectBuilder);
objectBuilder.Checkpoint.Gps.Dictionary.Add(IdentityID, GpsCollection); objectBuilder.Checkpoint.Gps.Dictionary.Add(IdentityID, GpsCollection);

View File

@@ -23,13 +23,13 @@ namespace SeamlessClient
{ {
public class Seamless : IPlugin public class Seamless : IPlugin
{ {
public static Version SeamlessVersion; public static Version SeamlessVersion => typeof(Seamless).Assembly.GetName().Version;
public static Version NexusVersion = new Version(1, 0, 0); public static Version NexusVersion = new Version(1, 0, 0);
private static Harmony SeamlessPatcher; private static Harmony SeamlessPatcher;
public const ushort SeamlessClientNetId = 2936; public static ushort SeamlessClientNetId = 2936;
private List<ComponentBase> allComps = new List<ComponentBase>(); private List<ComponentBase> allComps = new List<ComponentBase>();
private Assembly thisAssembly; private Assembly thisAssembly => typeof(Seamless).Assembly;
private bool Initilized = false; private bool Initilized = false;
public static bool isSeamlessServer = false; public static bool isSeamlessServer = false;
@@ -39,8 +39,6 @@ namespace SeamlessClient
public void Init(object gameInstance) public void Init(object gameInstance)
{ {
thisAssembly = typeof(Seamless).Assembly;
SeamlessVersion = thisAssembly.GetName().Version;
TryShow($"Running Seamless Client Plugin v[{SeamlessVersion}]"); TryShow($"Running Seamless Client Plugin v[{SeamlessVersion}]");
SeamlessPatcher = new Harmony("SeamlessClientPatcher"); SeamlessPatcher = new Harmony("SeamlessClientPatcher");
GetComponents(); GetComponents();
@@ -112,18 +110,22 @@ namespace SeamlessClient
private static void MessageHandler(ushort packetID, byte[] data, ulong sender, bool fromServer) private static void MessageHandler(ushort packetID, byte[] data, ulong sender, bool fromServer)
{ {
//Ignore anything except dedicated server //Ignore anything except dedicated server
Seamless.TryShow("1!");
if (!fromServer || sender == 0) if (!fromServer || sender == 0)
return; return;
Seamless.TryShow("2!");
ClientMessage msg = MessageUtils.Deserialize<ClientMessage>(data); ClientMessage msg = MessageUtils.Deserialize<ClientMessage>(data);
if (msg == null) if (msg == null)
return; return;
Seamless.TryShow("3!");
//Get Nexus Version //Get Nexus Version
if (!string.IsNullOrEmpty(msg.NexusVersion)) if (!string.IsNullOrEmpty(msg.NexusVersion))
NexusVersion = Version.Parse(msg.NexusVersion); NexusVersion = Version.Parse(msg.NexusVersion);
Seamless.TryShow("4!");
switch (msg.MessageType) switch (msg.MessageType)
{ {
case ClientMessageType.FirstJoin: case ClientMessageType.FirstJoin:

View File

@@ -78,7 +78,6 @@ namespace SeamlessClient.Components
/* Get Methods */ /* Get Methods */
LoadPlayerInternal = GetMethod(typeof(MyPlayerCollection), "LoadPlayerInternal"); LoadPlayerInternal = GetMethod(typeof(MyPlayerCollection), "LoadPlayerInternal");
SendPlayerData = GetMethod(ClientType, "SendPlayerData"); SendPlayerData = GetMethod(ClientType, "SendPlayerData");