diff --git a/Components/PlayersWindowComponent.cs b/Components/PlayersWindowComponent.cs index aae1cfb..d332a5c 100644 --- a/Components/PlayersWindowComponent.cs +++ b/Components/PlayersWindowComponent.cs @@ -16,8 +16,8 @@ namespace SeamlessClient.OnlinePlayersWindow public class PlayersWindowComponent : ComponentBase { - public static List allServers = new List(); - public static OnlineClientServer onlineServer; + //public static List allServers = new List(); + //public static OnlineClientServer onlineServer; public override void Patch(Harmony patcher) @@ -38,6 +38,7 @@ namespace SeamlessClient.OnlinePlayersWindow } } + /* public static void ApplyRecievedPlayers(List servers, int CurrentServer) { //Seamless.TryShow($"Recieved {CurrentServer} - {servers.Count}"); @@ -56,6 +57,7 @@ namespace SeamlessClient.OnlinePlayersWindow allServers.Add(server); } } + */ diff --git a/Components/SeamlessScriptManager.cs b/Components/SeamlessScriptManager.cs new file mode 100644 index 0000000..0fc594d --- /dev/null +++ b/Components/SeamlessScriptManager.cs @@ -0,0 +1,65 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using VRage.Game; +using VRage.Utils; + +namespace SeamlessClient.Components +{ + internal class SeamlessScriptManager + { + /* Sandbox.Game.World.MyScriptManager + * + * ScriptManager handles all mod script compiling and loading. Stores all compilations as various dictionaries like below: + * Looks like TryAddEntityScripts(,) can be called whenever to pass in the mod context and the compiled assembly on the fly + * + * Possibly to dynamically load/unload mods? + */ + + + /* Dictionary> ScriptsPerMod -> + * + * Use in Sandbox.Game.World.MySession.RegisterComponentsFromAssembly + * Primarily MySessionComponentDescriptor/Session Component + */ + + /* Dictionary Scripts -> + * + * Use in Sandbox.Game.World.MySession.RegisterComponentsFromAssembly + * Stores actual assemblies for all modded scripts + */ + + + /* Dictionary> EntityScripts -> + * + * Use in Sandbox.Game.Entities.MyEntityFactory.AddScriptGameLogic + * List of Type entity Scripts. Activator.CreatInstance called on entity creation + */ + + /* Dictionary, HashSet> SubEntityScripts -> + * + * Use in Sandbox.Game.Entities.MyEntityFactory.AddScriptGameLogic + * List of Type && SubType entity Scripts. Activator.CreatInstance called on entity creation + */ + + /* Dictionary StatScripts -> + * + * Use in Sandbox.Game.Components.MyEntityStatComponent + * No idea what this is but prob need to deal with it + */ + + + /* Dictionary InGameScripts -> */ + + /* Dictionary InGameScriptsCode -> */ + + /* Dictionary TypeToModMap -> + * + * Use in Sandbox.Game.Entities.MyEntityFactory.AddScriptGameLogic + * Some sort of type to mod logic component? + */ + + } +} diff --git a/Components/SeamlessSwitcher.cs b/Components/SeamlessSwitcher.cs new file mode 100644 index 0000000..30b86ea --- /dev/null +++ b/Components/SeamlessSwitcher.cs @@ -0,0 +1,446 @@ +using HarmonyLib; +using Sandbox; +using Sandbox.Engine.Multiplayer; +using Sandbox.Engine.Networking; +using Sandbox.Engine.Utils; +using Sandbox.Game.Entities.Character; +using Sandbox.Game.Entities; +using Sandbox.Game.Gui; +using Sandbox.Game.Multiplayer; +using Sandbox.Game.SessionComponents; +using Sandbox.Game.World; +using Sandbox.Graphics.GUI; +using SeamlessClient.Utilities; +using SpaceEngineers.Game.GUI; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Threading.Tasks; +using VRage.Game; +using VRage.GameServices; +using VRage.Library.Utils; +using VRage.Network; +using VRageRender; +using EmptyKeys.UserInterface.Generated.StoreBlockView_Bindings; +using System.Security.Cryptography; +using VRage.Groups; +using VRage.Game.ModAPI; +using VRage; +using static Sandbox.ModAPI.MyModAPIHelper; +using NLog.Targets; +using MyMultiplayer = Sandbox.Engine.Multiplayer.MyMultiplayer; +using static Sandbox.Engine.Networking.MyNetworkWriter; +using System.Collections.Concurrent; +using VRage.Game.Entity; +using VRageRender.Effects; +using VRage.Scripting; +using VRage.Utils; + +namespace SeamlessClient.Components +{ + public class SeamlessSwitcher : ComponentBase + { + private bool isSwitchingServer = false; + + private PropertyInfo _MyGameServerItemProperty; + private PropertyInfo _MultiplayerServerID; + private static MethodInfo PauseClient; + private MethodInfo _SendPlayerData; + private MethodInfo _SendFlush; + private MethodInfo _ClearTransportLayer; + private FieldInfo _NetworkWriteQueue; + private FieldInfo _TransportLayer; + + private MethodInfo _OnConnectToServer; + public static SeamlessSwitcher Instance; + + private static List allGrids = new List(); + + private long _OriginalCharacterEntity = -1; + private long _OriginalGridEntity = -1; + private ulong TargetServerID; + private static bool PreventRPC = false; + private static bool StartPacketCheck = false; + + public SeamlessSwitcher() + { + Instance = this; + } + + + public override void Patch(Harmony patcher) + { + _MyGameServerItemProperty = PatchUtils.GetProperty(PatchUtils.ClientType, "Server"); + _MultiplayerServerID = PatchUtils.GetProperty(typeof(MyMultiplayerBase), "ServerId"); + + _OnConnectToServer = PatchUtils.GetMethod(PatchUtils.ClientType, "OnConnectToServer"); + PauseClient = PatchUtils.GetMethod(PatchUtils.MyMultiplayerClientBase, "PauseClient"); + + _SendPlayerData = PatchUtils.GetMethod(PatchUtils.ClientType, "SendPlayerData"); + _ClearTransportLayer = PatchUtils.GetMethod(PatchUtils.MyTransportLayerType, "Clear"); + + + List st = AccessTools.GetMethodNames(PatchUtils.MyMultiplayerClientBase); + + var _SendRPC = PatchUtils.GetMethod(PatchUtils.MyMultiplayerClientBase, "VRage.Replication.IReplicationClientCallback.SendEvent"); + + var preSendRPC = PatchUtils.GetMethod(this.GetType(), "PreventEvents"); + _SendFlush = PatchUtils.GetMethod(PatchUtils.MyTransportLayerType, "SendFlush"); + _NetworkWriteQueue = PatchUtils.GetField(typeof(MyNetworkWriter), "m_packetsToSend"); + _TransportLayer = PatchUtils.GetField(typeof(MySyncLayer), "TransportLayer"); + + + var method = AccessTools.Method(PatchUtils.MyTransportLayerType, "SendMessage", new Type[] { typeof(MyMessageId), typeof(IPacketData), typeof(bool), typeof(EndpointId), typeof(byte) }); + var patchSend = PatchUtils.GetMethod(this.GetType(), "SendMessage_Patch"); + + + + + + patcher.Patch(method, prefix: patchSend); + patcher.Patch(_SendRPC, prefix: preSendRPC); + + + + base.Patch(patcher); + } + + public static void SendMessage_Patch(MyMessageId id, IPacketData data, bool reliable, EndpointId endpoint, byte index = 0) + { + if (!StartPacketCheck) + return; + + MyLog.Default?.WriteLineAndConsole($"{System.Environment.StackTrace}"); + Seamless.TryShow($"Id:{id} -> {endpoint}"); + } + + + public void StartSwitch(MyGameServerItem TargetServer, MyObjectBuilder_World TargetWorld) + { + isSwitchingServer = true; + TargetServerID = TargetServer.GameID; + MyReplicationClient localMPClient = (MyReplicationClient)MyMultiplayer.Static.ReplicationLayer; + _OriginalCharacterEntity = MySession.Static.LocalCharacter?.EntityId ?? 0; + + if (MySession.Static.LocalCharacter?.Parent != null && MySession.Static.LocalCharacter.Parent is MyCockpit cockpit) + { + _OriginalGridEntity = cockpit.CubeGrid.EntityId; + } + + + + UnloadCurrentServer(localMPClient); + + + /* Fix any weird compatibilities */ + MySandboxGame.Static.SessionCompatHelper.FixSessionComponentObjectBuilders(TargetWorld.Checkpoint, TargetWorld.Sector); + + /* Set New Multiplayer Stuff */ + _MyGameServerItemProperty.SetValue(MyMultiplayer.Static, TargetServer); + _MultiplayerServerID.SetValue(MyMultiplayer.Static, TargetServer.SteamID); + + /* Connect To Server */ + MyGameService.ConnectToServer(TargetServer, delegate (JoinResult joinResult) + { + MySandboxGame.Static.Invoke(delegate + { + Seamless.TryShow("Connected to server!"); + _OnConnectToServer.Invoke(MyMultiplayer.Static, new object[] { joinResult }); + OnUserJoined(joinResult); + + }, "OnConnectToServer"); + }); + + } + + private void UnloadCurrentServer(MyReplicationClient localMPClient) + { + + //Close and Cancel any screens (Medical or QuestLog) + MySessionComponentIngameHelp component = MySession.Static.GetComponent(); + component?.TryCancelObjective(); + MyGuiScreenMedicals.Close(); + + 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 }); + } + + + + + /* Sends disconnect message to outbound server */ + 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 }); + MyGameService.Peer2Peer.CloseSession(Sync.ServerId); + MyGameService.DisconnectFromServer(); + + + + + //Remove old signals + MyHud.GpsMarkers.Clear(); + MyHud.LocationMarkers.Clear(); + MyHud.HackingMarkers.Clear(); + + + Seamless.TryShow($"2 Streaming: {localMPClient.HasPendingStreamingReplicables} - LastMessage: {localMPClient.LastMessageFromServer}"); + Seamless.TryShow($"2 NexusMajor: {Seamless.NexusVersion.Major} - ConrolledEntity {MySession.Static.ControlledEntity == null} - HumanPlayer {MySession.Static.LocalHumanPlayer == null} - Character {MySession.Static.LocalCharacter == null}"); + + UnloadOldEntities(); + ResetReplicationTime(false); + + //MyMultiplayer.Static.ReplicationLayer.Disconnect(); + //MyMultiplayer.Static.ReplicationLayer.Dispose(); + //MyMultiplayer.Static.Dispose(); + } + + private static bool PreventEvents(IPacketData data, bool reliable) + { + return !PreventRPC; + } + + private void UnloadOldEntities() + { + + + foreach (var ent in MyEntities.GetEntities().ToList()) + { + if (ent is MyPlanet || ent is MyCubeGrid) + continue; + + if(ent.EntityId == _OriginalCharacterEntity && ent is MyCharacter character) + { + continue; + } + + ent.Close(); + } + + List grids = new List(); + + foreach (var gridgroup in MyCubeGridGroups.GetGridGroups(VRage.Game.ModAPI.GridLinkTypeEnum.Physical, grids)) + { + + List localGrids = new List(); + localGrids = gridgroup.GetGrids(localGrids); + + if (localGrids.Count == 0) + continue; + + if (localGrids.Any(x => x.EntityId == _OriginalGridEntity)) + { + + foreach(var grid in localGrids) + { + MyEntity ent = grid as MyEntity; + allGrids.Add((MyCubeGrid)grid); + grid.Synchronized = false; + + ent.SyncFlag = false; + ent.Save = false; + + + + } + + + continue; + } + + + //Delete + foreach (var grid in localGrids) + { + grid.Close(); + } + + } + + MyMultiplayer.Static.ReplicationLayer.Dispose(); + PreventRPC = true; + StartPacketCheck = true; + + //_ClearTransportLayer.Invoke(_TransportLayer.GetValue(MyMultiplayer.Static.SyncLayer), null); + + + } + + private void OnUserJoined(JoinResult joinResult) + { + isSwitchingServer = false; + + if (joinResult != JoinResult.OK) + return; + + Seamless.TryShow($"OnUserJoin! Result: {joinResult}"); + LoadDestinationServer(); + + + + _SendPlayerData.Invoke(MyMultiplayer.Static, new object[] { MyGameService.OnlineName }); + } + + private void LoadDestinationServer() + { + 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!"); + + /* On Server Successfull Join + * + * + */ + + + + List clients = new List(); + foreach (var client in Sync.Clients.GetClients()) + { + clients.Add(client.SteamUserId); + Seamless.TryShow($"ADDING {client.SteamUserId} - {Sync.MyId}"); + } + + foreach (var client in clients) + { + if (client == TargetServerID || client == Sync.MyId) + continue; + + Seamless.TryShow($"REMOVING {client}"); + Sync.Clients.RemoveClient(client); + } + + + typeof(MySandboxGame).GetField("m_pauseStackCount", BindingFlags.Static | BindingFlags.NonPublic).SetValue(null, 0); + + 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}"); + + + + + + + + ResetReplicationTime(true); + //MyPlayerCollection.ChangePlayerCharacter(MySession.Static.LocalHumanPlayer, MySession.Static.LocalCharacter, MySession.Static.LocalCharacter); + // 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; + clientReadyDataMsg.UsePlayoutDelayBufferForCharacter = true; + clientReadyDataMsg.UsePlayoutDelayBufferForJetpack = true; + clientReadyDataMsg.UsePlayoutDelayBufferForGrids = true; + ClientReadyDataMsg msg = clientReadyDataMsg; + clienta.SendClientReady(ref msg); + + PreventRPC = false; + //_ClearTransportLayer.Invoke(_TransportLayer.GetValue(MyMultiplayer.Static.SyncLayer), null); + + StartEntitySync(); + Seamless.SendSeamlessVersion(); + + + + + + + PauseClient.Invoke(MyMultiplayer.Static, new object[] { false }); + MySandboxGame.PausePop(); + + } + + private void StartEntitySync() + { + Seamless.TryShow("Requesting Player From Server"); + + Sync.Players.RequestNewPlayer(Sync.MyId, 0, MyGameService.UserName, null, true, true); + if (!Sandbox.Engine.Platform.Game.IsDedicated && MySession.Static.LocalHumanPlayer == null) + { + 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; + MyPlayerCollection.RequestLocalRespawn(); + } + + + + //Request client state batch + (MyMultiplayer.Static as MyMultiplayerClientBase).RequestBatchConfirmation(); + MyMultiplayer.Static.PendingReplicablesDone += Static_PendingReplicablesDone; + //typeof(MyGuiScreenTerminal).GetMethod("CreateTabs") + + //MySession.Static.LocalHumanPlayer.Controller.TakeControl(originalControlledEntity); + + MyGuiSandbox.UnloadContent(); + MyGuiSandbox.LoadContent(); + MyGuiScreenHudSpace.Static?.RecreateControls(true); + + + + //MyGuiSandbox.CreateScreen(MyPerGameSettings.GUI.HUDScreen); + + MyRenderProxy.RebuildCullingStructure(); + MyRenderProxy.CollectGarbage(); + + + Seamless.TryShow("OnlinePlayers: " + MySession.Static.Players.GetOnlinePlayers().Count); + Seamless.TryShow("Loading Complete!"); + } + + private void Static_PendingReplicablesDone() + { + if (MySession.Static.VoxelMaps.Instances.Count > 0) + { + MySandboxGame.AreClipmapsReady = false; + } + MyMultiplayer.Static.PendingReplicablesDone -= Static_PendingReplicablesDone; + + } + + + public void ResetReplicationTime(bool ClientReady) + { + + + + + if (!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_lastStateSyncPacketId").SetValue(MyMultiplayer.Static.ReplicationLayer,(byte)0); + PatchUtils.GetField(typeof(MyReplicationClient), "m_lastStreamingPacketId").SetValue(MyMultiplayer.Static.ReplicationLayer, (byte)0); + PatchUtils.GetField(typeof(MyReplicationClient), "m_lastStreamingPacketId").SetValue(MyMultiplayer.Static.ReplicationLayer, (byte)0); + //PatchUtils.GetField(typeof(MyReplicationClient), "m_acks").SetValue(MyMultiplayer.Static.ReplicationLayer, new List()); + } + + + + + PatchUtils.GetField(typeof(MyReplicationClient), "m_clientReady").SetValue(MyMultiplayer.Static.ReplicationLayer, ClientReady); + } + + + + } +} diff --git a/Components/ServerSwitcherComponent.cs b/Components/ServerSwitcherComponent.cs deleted file mode 100644 index 2e0a88f..0000000 --- a/Components/ServerSwitcherComponent.cs +++ /dev/null @@ -1,845 +0,0 @@ -using HarmonyLib; -using Sandbox; -using Sandbox.Engine.Multiplayer; -using Sandbox.Engine.Networking; -using Sandbox.Engine.Utils; -using Sandbox.Game; -using Sandbox.Game.Entities; -using Sandbox.Game.Entities.Character; -using Sandbox.Game.Gui; -using Sandbox.Game.GUI; -using Sandbox.Game.GUI.HudViewers; -using Sandbox.Game.Multiplayer; -using Sandbox.Game.Replication; -using Sandbox.Game.SessionComponents; -using Sandbox.Game.World; -using Sandbox.Game.World.Generator; -using Sandbox.Graphics.GUI; -using Sandbox.ModAPI; -using SeamlessClient.Components; -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 System.Timers; -using VRage; -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; -using VRageRender.Messages; - -namespace SeamlessClient.ServerSwitching -{ - public class ServerSwitcherComponent : ComponentBase - { - public static ConstructorInfo ClientConstructor; - public static ConstructorInfo SyncLayerConstructor; - public static ConstructorInfo TransportLayerConstructor; - - public static PropertyInfo MySessionLayer; - - private static FieldInfo RemoteAdminSettings; - private static FieldInfo AdminSettings; - private static MethodInfo UnloadProceduralWorldGenerator; - private static MethodInfo GpsRegisterChat; - private static MethodInfo LoadMembersFromWorld; - private static MethodInfo InitVirtualClients; - private static MethodInfo CreateNewPlayerInternal; - private static MethodInfo PauseClient; - public static MethodInfo SendPlayerData; - - private static FieldInfo VirtualClients; - - - public static ServerSwitcherComponent Instance { get; private set; } - - private MyGameServerItem TargetServer { get; set; } - private MyObjectBuilder_World TargetWorld { get; set; } - private string OldArmorSkin { get; set; } = string.Empty; - - private bool needsEntityUnload = true; - - public static event EventHandler OnJoinEvent; - - private MyCharacter originalLocalCharacter; - private IMyControllableEntity originalControlledEntity; - - private static bool isSwitch = false; - private MyObjectBuilder_Player player { get; set; } - private static Timer pauseResetTimer = new Timer(1000); - - - - public ServerSwitcherComponent() - { - pauseResetTimer.Elapsed += PauseResetTimer_Elapsed; - Instance = this; - } - - private void PauseResetTimer_Elapsed(object sender, ElapsedEventArgs e) - { - if(MySandboxGame.IsPaused) - { - Seamless.TryShow("Game is still paused... Attempting to unpause!"); - MySandboxGame.PausePop(); - } - else - { - pauseResetTimer.Stop(); - } - } - - public override void Patch(Harmony patcher) - { - 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) }); - - - RemoteAdminSettings = PatchUtils.GetField(typeof(MySession), "m_remoteAdminSettings"); - AdminSettings = PatchUtils.GetField(typeof(MySession), "m_adminSettings"); - VirtualClients = PatchUtils.GetField(typeof(MySession), "VirtualClients"); - - UnloadProceduralWorldGenerator = PatchUtils.GetMethod(typeof(MyProceduralWorldGenerator), "UnloadData"); - GpsRegisterChat = PatchUtils.GetMethod(typeof(MyGpsCollection), "RegisterChat"); - LoadMembersFromWorld = PatchUtils.GetMethod(typeof(MySession), "LoadMembersFromWorld"); - InitVirtualClients = PatchUtils.GetMethod(PatchUtils.VirtualClientsType, "Init"); - SendPlayerData = PatchUtils.GetMethod(PatchUtils.ClientType, "SendPlayerData"); - - CreateNewPlayerInternal = PatchUtils.GetMethod(typeof(MyPlayerCollection), "CreateNewPlayerInternal"); - - - MethodInfo onAllmembersData = PatchUtils.ClientType.GetMethod("OnAllMembersData", BindingFlags.Instance | BindingFlags.NonPublic); - - - var onClientRemoved = PatchUtils.GetMethod(typeof(MyClientCollection), "RemoveClient"); - 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(onAllmembersData, prefix: new HarmonyMethod(Get(typeof(ServerSwitcherComponent), nameof(OnAllMembersData)))); - - - - patcher.Patch(onClientConnected, prefix: new HarmonyMethod(Get(typeof(ServerSwitcherComponent), nameof(OnClientConnected)))); - - - base.Patch(patcher); - } - - - - public static void OnUserJoined(JoinResult msg) - { - Seamless.TryShow($"OnUserJoin! Result: {msg}"); - if (msg == JoinResult.OK) - { - - - - - //SendPlayerData - - - //Invoke the switch event - if (isSwitch) - Instance.StartSwitch(); - - if (MySandboxGame.IsPaused) - { - pauseResetTimer.Start(); - MyHud.Notifications.Remove(MyNotificationSingletons.ConnectionProblem); - MySandboxGame.PausePop(); - } - - SendPlayerData.Invoke(MyMultiplayer.Static, new object[] { MyGameService.OnlineName }); - isSwitch = false; - } - } - - public static bool LoadClientsFromWorld(ref List clients) - { - if(!isSwitch || clients == null || clients.Count == 0) - return true; - - - //Dictionary - - 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(); - - 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 false; - } - - - - private static bool ProcessAllMembersData(ref AllMembersDataMsg msg) - { - if(!isSwitch) - return true; - - - 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() - { - base.Initilized(); - } - - - 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) - { - this.TargetServer = TargetServer; - this.TargetWorld = TargetWorld; - 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) - needsEntityUnload = false; - - isSwitch = true; - - originalLocalCharacter = MySession.Static.LocalCharacter; - //originalControlledEntity = MySession.Static.ControlledEntity; - - - - - player = MySession.Static.LocalHumanPlayer.GetObjectBuilder(); - player.Connected = false; - - AsyncInvoke.InvokeAsync(() => - { - Seamless.TryShow($"Needs entity Unload: {needsEntityUnload}"); - - if (needsEntityUnload) - MySession.Static.SetCameraController(MyCameraControllerEnum.SpectatorFixed); - - try - { - - UnloadServer(); - SetNewMultiplayerClient(); - - }catch(Exception ex) - { - Seamless.TryShow(ex.ToString()); - } - }); - } - - - 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) - throw new Exception("MyMultiplayer.Static is null on unloading? dafuq?"); - - - UnloadOldEntities(); - - //Close and Cancel any screens (Medical or QuestLog) - MySessionComponentIngameHelp component = MySession.Static.GetComponent(); - component?.TryCancelObjective(); - MyGuiScreenMedicals.Close(); - - - //Clear all old players and clients. - //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(); - - - 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 - //MyMultiplayer.Static.ReplicationLayer.Disconnect(); - //MyMultiplayer.Static.ReplicationLayer.Dispose(); - //MyMultiplayer.Static.Dispose(); - //MyMultiplayer.Static = null; - - MyReplicationClient clienta = (MyReplicationClient)MyMultiplayer.Static.ReplicationLayer; - - ResetReplicationTime(false); - - //Remove old signals - MyHud.GpsMarkers.Clear(); - MyHud.LocationMarkers.Clear(); - MyHud.HackingMarkers.Clear(); - - - 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}"); - - - - - //MyMultiplayer.Static.ReplicationLayer.Disconnect(); - //MyMultiplayer.Static.ReplicationLayer.Dispose(); - //MyMultiplayer.Static.Dispose(); - } - - private void UnloadOldEntities() - { - - - foreach (var ent in MyEntities.GetEntities()) - { - if (ent is MyPlanet) - continue; - - if (ent is MyCharacter) - continue; - - - ent.Close(); - - if (needsEntityUnload) - { - ent.Close(); - } - else - { - // - } - - - } - } - - private void SetNewMultiplayerClient() - { - - 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); - - - - - 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 }); - OnUserJoined(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 - var LayerInstance = TransportLayerConstructor.Invoke(new object[] { 2 }); - var SyncInstance = SyncLayerConstructor.Invoke(new object[] { LayerInstance }); - var instance = ClientConstructor.Invoke(new object[] { TargetServer, SyncInstance }); - - - MyMultiplayer.Static = UtilExtensions.CastToReflected(instance, PatchUtils.ClientType); - MyMultiplayer.Static.ExperimentalMode = true; - - - - // Set the new SyncLayer to the MySession.Static.SyncLayer - MySessionLayer.SetValue(MySession.Static, MyMultiplayer.Static.SyncLayer); - Sync.Clients.SetLocalSteamId(Sync.MyId, false, MyGameService.UserName); - return; - Seamless.TryShow("Successfully set MyMultiplayer.Static"); - - - - Sync.Clients.SetLocalSteamId(Sync.MyId, false, MyGameService.UserName); - Sync.Players.RegisterEvents(); - - return; - } - - private void StartSwitch() - { - - 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!"); - - /* On Server Successfull Join - * - * - */ - - - - List clients = new List(); - foreach(var client in Sync.Clients.GetClients()) - { - clients.Add(client.SteamUserId); - Seamless.TryShow($"ADDING {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); - - - Seamless.TryShow("Applying World Settings..."); - SetWorldSettings(); - - Seamless.TryShow("Starting Components..."); - InitComponents(); - - Seamless.TryShow("Starting Entity Sync..."); - StartEntitySync(); - - //MyGuiSandbox.RemoveScreen(MyGuiScreenHudSpace.Static); - - - - - - typeof(MySandboxGame).GetField("m_pauseStackCount", BindingFlags.Static | BindingFlags.NonPublic).SetValue(null, 0); - - - - MyHud.Chat.RegisterChat(MyMultiplayer.Static); - //GpsRegisterChat.Invoke(MySession.Static.Gpss, new object[] { MyMultiplayer.Static }); - - - - //Recreate all controls... Will fix weird gui/paint/crap - //MyGuiScreenHudSpace.Static?.RecreateControls(true); - - - - - 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(); - 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; - clientReadyDataMsg.UsePlayoutDelayBufferForCharacter = true; - clientReadyDataMsg.UsePlayoutDelayBufferForJetpack = true; - clientReadyDataMsg.UsePlayoutDelayBufferForGrids = true; - ClientReadyDataMsg msg = clientReadyDataMsg; - clienta.SendClientReady(ref msg); - - Seamless.SendSeamlessVersion(); - - FieldInfo hudPoints = typeof(MyHudMarkerRender).GetField("m_pointsOfInterest", BindingFlags.Instance | BindingFlags.NonPublic); - IList points = (IList)hudPoints.GetValue(MyGuiScreenHudSpace.Static.MarkerRender); - - MySandboxGame.PausePop(); - //Sync.Players.RequestNewPlayer(Sync.MyId, 0, MyGameService.UserName, null, true, true); - PauseClient.Invoke(MyMultiplayer.Static, new object[] { false }); - MySandboxGame.PausePop(); - MyHud.Notifications.Remove(MyNotificationSingletons.ConnectionProblem); - } - - - - - private void SetWorldSettings() - { - //Clear old list - MySession.Static.PromotedUsers.Clear(); - MySession.Static.CreativeTools.Clear(); - Dictionary AdminSettingsList = (Dictionary)RemoteAdminSettings.GetValue(MySession.Static); - AdminSettingsList.Clear(); - - - - // Set new world settings - MySession.Static.Name = MyStatControlText.SubstituteTexts(TargetWorld.Checkpoint.SessionName); - MySession.Static.Description = TargetWorld.Checkpoint.Description; - - MySession.Static.Mods = TargetWorld.Checkpoint.Mods; - MySession.Static.Settings = TargetWorld.Checkpoint.Settings; - MySession.Static.CurrentPath = MyLocalCache.GetSessionSavesPath(MyUtils.StripInvalidChars(TargetWorld.Checkpoint.SessionName), contentFolder: false, createIfNotExists: false); - MySession.Static.WorldBoundaries = TargetWorld.Checkpoint.WorldBoundaries; - MySession.Static.InGameTime = MyObjectBuilder_Checkpoint.DEFAULT_DATE; - MySession.Static.ElapsedGameTime = new TimeSpan(TargetWorld.Checkpoint.ElapsedGameTime); - MySession.Static.Settings.EnableSpectator = false; - - MySession.Static.Password = TargetWorld.Checkpoint.Password; - MySession.Static.PreviousEnvironmentHostility = TargetWorld.Checkpoint.PreviousEnvironmentHostility; - MySession.Static.RequiresDX = TargetWorld.Checkpoint.RequiresDX; - MySession.Static.CustomLoadingScreenImage = TargetWorld.Checkpoint.CustomLoadingScreenImage; - MySession.Static.CustomLoadingScreenText = TargetWorld.Checkpoint.CustomLoadingScreenText; - MySession.Static.CustomSkybox = TargetWorld.Checkpoint.CustomSkybox; - - try - { - MySession.Static.Gpss = new MyGpsCollection(); - - } - catch (Exception ex) - { - Seamless.TryShow($"An error occured while loading GPS points! You will have an empty gps list! \n {ex.ToString()}"); - } - - - //MyRenderProxy.RebuildCullingStructure(); - //MySession.Static.Toolbars.LoadToolbars(checkpoint); - - Sync.Players.RespawnComponent.InitFromCheckpoint(TargetWorld.Checkpoint); - - - // Set new admin settings - if (TargetWorld.Checkpoint.PromotedUsers != null) - { - MySession.Static.PromotedUsers = TargetWorld.Checkpoint.PromotedUsers.Dictionary; - } - else - { - MySession.Static.PromotedUsers = new Dictionary(); - } - - - - - foreach (KeyValuePair item in TargetWorld.Checkpoint.AllPlayersData.Dictionary) - { - ulong clientId = item.Key.GetClientId(); - AdminSettingsEnum adminSettingsEnum = (AdminSettingsEnum)item.Value.RemoteAdminSettings; - if (TargetWorld.Checkpoint.RemoteAdminSettings != null && TargetWorld.Checkpoint.RemoteAdminSettings.Dictionary.TryGetValue(clientId, out var value)) - { - adminSettingsEnum = (AdminSettingsEnum)value; - } - if (!MyPlatformGameSettings.IsIgnorePcuAllowed) - { - adminSettingsEnum &= ~AdminSettingsEnum.IgnorePcu; - adminSettingsEnum &= ~AdminSettingsEnum.KeepOriginalOwnershipOnPaste; - } - - - AdminSettingsList[clientId] = adminSettingsEnum; - if (!Sync.IsDedicated && clientId == Sync.MyId) - { - AdminSettings.SetValue(MySession.Static, adminSettingsEnum); - } - - - - if (!MySession.Static.PromotedUsers.TryGetValue(clientId, out var value2)) - { - value2 = MyPromoteLevel.None; - } - if (item.Value.PromoteLevel > value2) - { - MySession.Static.PromotedUsers[clientId] = item.Value.PromoteLevel; - } - if (!MySession.Static.CreativeTools.Contains(clientId) && item.Value.CreativeToolsEnabled) - { - MySession.Static.CreativeTools.Add(clientId); - } - } - - - MySector.InitEnvironmentSettings(TargetWorld.Sector.Environment); - - string text = ((!string.IsNullOrEmpty(TargetWorld.Checkpoint.CustomSkybox)) ? TargetWorld.Checkpoint.CustomSkybox : MySector.EnvironmentDefinition.EnvironmentTexture); - MyRenderProxy.PreloadTextures(new string[1] { text }, TextureType.CubeMap); - - - - - } - - private void InitComponents() - { - UpdateWorldGenerator(); - } - private void UpdateWorldGenerator() - { - //This will re-init the MyProceduralWorldGenerator. (Not doing this will result in asteroids not rendering in properly) - - - //This shoud never be null - var Generator = MySession.Static.GetComponent(); - - //Force component to unload - UnloadProceduralWorldGenerator.Invoke(Generator, null); - - //Re-call the generator init - MyObjectBuilder_WorldGenerator GeneratorSettings = (MyObjectBuilder_WorldGenerator)TargetWorld.Checkpoint.SessionComponents.FirstOrDefault(x => x.GetType() == typeof(MyObjectBuilder_WorldGenerator)); - if (GeneratorSettings != null) - { - //Re-initilized this component (forces to update asteroid areas like not in planets etc) - Generator.Init(GeneratorSettings); - } - - //Force component to reload, re-syncing settings and seeds to the destination server - Generator.LoadData(); - - //We need to go in and force planets to be empty areas in the generator. This is originially done on planet init. - FieldInfo PlanetInitArgs = typeof(MyPlanet).GetField("m_planetInitValues", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance); - foreach (var Planet in MyEntities.GetEntities().OfType()) - { - MyPlanetInitArguments args = (MyPlanetInitArguments)PlanetInitArgs.GetValue(Planet); - - float MaxRadius = args.MaxRadius; - - Generator.MarkEmptyArea(Planet.PositionComp.GetPosition(), MaxRadius); - } - } - - private void StartEntitySync() - { - Seamless.TryShow("Requesting Player From Server"); - - Sync.Players.RequestNewPlayer(Sync.MyId, 0, MyGameService.UserName, null, true, true); - if (!Sandbox.Engine.Platform.Game.IsDedicated && MySession.Static.LocalHumanPlayer == null) - { - 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; - MyPlayerCollection.RequestLocalRespawn(); - } - - - - //Request client state batch - (MyMultiplayer.Static as MyMultiplayerClientBase).RequestBatchConfirmation(); - MyMultiplayer.Static.PendingReplicablesDone += Static_PendingReplicablesDone; - //typeof(MyGuiScreenTerminal).GetMethod("CreateTabs") - - //MySession.Static.LocalHumanPlayer.Controller.TakeControl(originalControlledEntity); - - MyGuiSandbox.UnloadContent(); - MyGuiSandbox.LoadContent(); - - //MyGuiSandbox.CreateScreen(MyPerGameSettings.GUI.HUDScreen); - - MyRenderProxy.RebuildCullingStructure(); - MyRenderProxy.CollectGarbage(); - - - Seamless.TryShow("OnlinePlayers: " + MySession.Static.Players.GetOnlinePlayers().Count); - Seamless.TryShow("Loading Complete!"); - } - - private void Static_PendingReplicablesDone() - { - if (MySession.Static.VoxelMaps.Instances.Count > 0) - { - MySandboxGame.AreClipmapsReady = false; - } - MyMultiplayer.Static.PendingReplicablesDone -= Static_PendingReplicablesDone; - - } - - private void LoadConnectedClients() - { - Seamless.TryShow($"BEFORE {MySession.Static.LocalHumanPlayer == null} - {MySession.Static.LocalCharacter == 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($"AFTER {MySession.Static.LocalHumanPlayer == null} - {MySession.Static.LocalCharacter == null}"); - } - } -} diff --git a/Components/ServerSwitcherComponentOLD.cs b/Components/ServerSwitcherComponentOLD.cs deleted file mode 100644 index 08aee58..0000000 --- a/Components/ServerSwitcherComponentOLD.cs +++ /dev/null @@ -1,494 +0,0 @@ -using HarmonyLib; -using Sandbox.Game.World; -using Sandbox; -using SeamlessClient.Utilities; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using VRage.Game; -using VRage.GameServices; -using Sandbox.Game.Gui; -using Sandbox.Game.SessionComponents; -using SpaceEngineers.Game.GUI; -using Sandbox.Engine.Multiplayer; -using Sandbox.Game.Multiplayer; -using Sandbox.Game.Entities; -using Sandbox.Engine.Networking; -using System.Reflection; -using VRage.Network; -using Sandbox.ModAPI; -using VRageRender.Messages; -using VRageRender; -using Sandbox.Game.GUI; -using Sandbox.Game.World.Generator; -using Sandbox.Game; -using VRage.Game.ModAPI; -using VRage.Utils; -using SeamlessClient.ServerSwitching; - -namespace SeamlessClient.Components -{ - public class ServerSwitcherComponentOLD : ComponentBase - { - private static bool isSeamlessSwitching = false; - private static ConstructorInfo TransportLayerConstructor; - private static ConstructorInfo SyncLayerConstructor; - private static ConstructorInfo ClientConstructor; - - private static MethodInfo UnloadProceduralWorldGenerator; - private static MethodInfo GpsRegisterChat; - private static MethodInfo LoadMembersFromWorld; - private static MethodInfo InitVirtualClients; - private static FieldInfo AdminSettings; - private static FieldInfo RemoteAdminSettings; - private static FieldInfo VirtualClients; - private static PropertyInfo MySessionLayer; - - public static MyGameServerItem TargetServer { get; private set; } - public static MyObjectBuilder_World TargetWorld { get; private set; } - - public static ServerSwitcherComponentOLD Instance { get; private set; } - private string OldArmorSkin { get; set; } = string.Empty; - - public ServerSwitcherComponentOLD() { Instance = this; } - - - - - - public override void Patch(Harmony patcher) - { - TransportLayerConstructor = PatchUtils.GetConstructor(PatchUtils.MyTransportLayerType, new[] { typeof(int) }); - SyncLayerConstructor = PatchUtils.GetConstructor(PatchUtils.SyncLayerType, new[] { PatchUtils.MyTransportLayerType }); - ClientConstructor = PatchUtils.GetConstructor(PatchUtils.ClientType, new[] { typeof(MyGameServerItem), PatchUtils.SyncLayerType }); - MySessionLayer = PatchUtils.GetProperty(typeof(MySession), "SyncLayer"); - - var onJoin = PatchUtils.GetMethod(PatchUtils.ClientType, "OnUserJoined"); - UnloadProceduralWorldGenerator = PatchUtils.GetMethod(typeof(MyProceduralWorldGenerator), "UnloadData"); - GpsRegisterChat = PatchUtils.GetMethod(typeof(MyGpsCollection), "RegisterChat"); - AdminSettings = PatchUtils.GetField(typeof(MySession), "m_adminSettings"); - RemoteAdminSettings = PatchUtils.GetField(typeof(MySession), "m_remoteAdminSettings"); - LoadMembersFromWorld = PatchUtils.GetMethod(typeof(MySession), "LoadMembersFromWorld"); - InitVirtualClients = PatchUtils.GetMethod(PatchUtils.VirtualClientsType, "Init"); - VirtualClients = PatchUtils.GetField(typeof(MySession), "VirtualClients"); - - patcher.Patch(onJoin, postfix: new HarmonyMethod(Get(typeof(ServerSwitcherComponentOLD), nameof(OnUserJoined)))); - base.Patch(patcher); - } - - private static void OnUserJoined(ref JoinResultMsg msg) - { - if (msg.JoinResult == JoinResult.OK && isSeamlessSwitching) - { - //SeamlessClient.TryShow("User Joined! Result: " + msg.JoinResult.ToString()); - - //Invoke the switch event - ForceClientConnection(); - isSeamlessSwitching = false; - } - } - - public void StartBackendSwitch(MyGameServerItem _TargetServer, MyObjectBuilder_World _TargetWorld) - { - isSeamlessSwitching = true; - OldArmorSkin = MySession.Static.LocalHumanPlayer.BuildArmorSkin; - TargetServer = _TargetServer; - TargetWorld = _TargetWorld; - - MySandboxGame.Static.Invoke(delegate - { - //Set camera controller to fixed spectator - MySession.Static.SetCameraController(MyCameraControllerEnum.SpectatorFixed); - UnloadCurrentServer(); - SetNewMultiplayerClient(); - //SeamlessClient.IsSwitching = false; - - - }, "SeamlessClient"); - - } - - private void SetNewMultiplayerClient() - { - // Following is called when the multiplayer is set successfully to target server - MySandboxGame.Static.SessionCompatHelper.FixSessionComponentObjectBuilders(TargetWorld.Checkpoint, TargetWorld.Sector); - - // Create constructors - var LayerInstance = TransportLayerConstructor.Invoke(new object[] { 2 }); - var SyncInstance = SyncLayerConstructor.Invoke(new object[] { LayerInstance }); - var instance = ClientConstructor.Invoke(new object[] { TargetServer, SyncInstance }); - - - MyMultiplayer.Static = UtilExtensions.CastToReflected(instance, PatchUtils.ClientType); - MyMultiplayer.Static.ExperimentalMode = true; - - - - // Set the new SyncLayer to the MySession.Static.SyncLayer - MySessionLayer.SetValue(MySession.Static, MyMultiplayer.Static.SyncLayer); - - Seamless.TryShow("Successfully set MyMultiplayer.Static"); - - - Sync.Clients.SetLocalSteamId(Sync.MyId, false, MyGameService.UserName); - Sync.Players.RegisterEvents(); - - } - - - - private static void ForceClientConnection() - { - - //Set World Settings - SetWorldSettings(); - - //Load force load any connected players - LoadConnectedClients(); - - - - MySector.InitEnvironmentSettings(TargetWorld.Sector.Environment); - - - - string text = ((!string.IsNullOrEmpty(TargetWorld.Checkpoint.CustomSkybox)) ? TargetWorld.Checkpoint.CustomSkybox : MySector.EnvironmentDefinition.EnvironmentTexture); - MyRenderProxy.PreloadTextures(new string[1] { text }, TextureType.CubeMap); - - MyModAPIHelper.Initialize(); - MySession.Static.LoadDataComponents(); - - //MySession.Static.LoadObjectBuildersComponents(TargetWorld.Checkpoint.SessionComponents); - MyModAPIHelper.Initialize(); - // MySession.Static.LoadObjectBuildersComponents(TargetWorld.Checkpoint.SessionComponents); - - - //MethodInfo A = typeof(MySession).GetMethod("LoadGameDefinition", BindingFlags.Instance | BindingFlags.NonPublic); - // A.Invoke(MySession.Static, new object[] { TargetWorld.Checkpoint }); - - - - MyMultiplayer.Static.OnSessionReady(); - - - UpdateWorldGenerator(); - - StartEntitySync(); - - - 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 - if(MyGuiScreenHudSpace.Static != null) - MyGuiScreenHudSpace.Static.RecreateControls(true); - //MySession.Static.LocalHumanPlayer.BuildArmorSkin = OldArmorSkin; - } - - private static void LoadOnlinePlayers() - { - //Get This players ID - - MyPlayer.PlayerId? savingPlayerId = new MyPlayer.PlayerId(Sync.MyId); - if (!savingPlayerId.HasValue) - { - Seamless.TryShow("SavingPlayerID is null! Creating Default!"); - savingPlayerId = new MyPlayer.PlayerId(Sync.MyId); - } - Seamless.TryShow("Saving PlayerID: " + savingPlayerId.ToString()); - - Sync.Players.LoadConnectedPlayers(TargetWorld.Checkpoint, savingPlayerId); - Sync.Players.LoadControlledEntities(TargetWorld.Checkpoint.ControlledEntities, TargetWorld.Checkpoint.ControlledObject, savingPlayerId); - /* - - - SeamlessClient.TryShow("Saving PlayerID: " + savingPlayerId.ToString()); - - - - foreach (KeyValuePair item3 in TargetWorld.Checkpoint.AllPlayersData.Dictionary) - { - MyPlayer.PlayerId playerId5 = new MyPlayer.PlayerId(item3.Key.GetClientId(), item3.Key.SerialId); - - SeamlessClient.TryShow($"ConnectedPlayer: {playerId5.ToString()}"); - if (savingPlayerId.HasValue && playerId5.SteamId == savingPlayerId.Value.SteamId) - { - playerId5 = new MyPlayer.PlayerId(Sync.MyId, playerId5.SerialId); - } - - Patches.LoadPlayerInternal.Invoke(MySession.Static.Players, new object[] { playerId5, item3.Value, false }); - ConcurrentDictionary Players = (ConcurrentDictionary)Patches.MPlayerGPSCollection.GetValue(MySession.Static.Players); - //LoadPlayerInternal(ref playerId5, item3.Value); - if (Players.TryGetValue(playerId5, out MyPlayer myPlayer)) - { - List value2 = null; - if (TargetWorld.Checkpoint.AllPlayersColors != null && TargetWorld.Checkpoint.AllPlayersColors.Dictionary.TryGetValue(item3.Key, out value2)) - { - myPlayer.SetBuildColorSlots(value2); - } - else if (TargetWorld.Checkpoint.CharacterToolbar != null && TargetWorld.Checkpoint.CharacterToolbar.ColorMaskHSVList != null && TargetWorld.Checkpoint.CharacterToolbar.ColorMaskHSVList.Count > 0) - { - myPlayer.SetBuildColorSlots(TargetWorld.Checkpoint.CharacterToolbar.ColorMaskHSVList); - } - } - } - - */ - - } - - private static void SetWorldSettings() - { - //MyEntities.MemoryLimitAddFailureReset(); - - //Clear old list - MySession.Static.PromotedUsers.Clear(); - MySession.Static.CreativeTools.Clear(); - Dictionary AdminSettingsList = (Dictionary)RemoteAdminSettings.GetValue(MySession.Static); - AdminSettingsList.Clear(); - - - - // Set new world settings - MySession.Static.Name = MyStatControlText.SubstituteTexts(TargetWorld.Checkpoint.SessionName); - MySession.Static.Description = TargetWorld.Checkpoint.Description; - - MySession.Static.Mods = TargetWorld.Checkpoint.Mods; - MySession.Static.Settings = TargetWorld.Checkpoint.Settings; - MySession.Static.CurrentPath = MyLocalCache.GetSessionSavesPath(MyUtils.StripInvalidChars(TargetWorld.Checkpoint.SessionName), contentFolder: false, createIfNotExists: false); - MySession.Static.WorldBoundaries = TargetWorld.Checkpoint.WorldBoundaries; - MySession.Static.InGameTime = MyObjectBuilder_Checkpoint.DEFAULT_DATE; - MySession.Static.ElapsedGameTime = new TimeSpan(TargetWorld.Checkpoint.ElapsedGameTime); - MySession.Static.Settings.EnableSpectator = false; - - MySession.Static.Password = TargetWorld.Checkpoint.Password; - MySession.Static.PreviousEnvironmentHostility = TargetWorld.Checkpoint.PreviousEnvironmentHostility; - MySession.Static.RequiresDX = TargetWorld.Checkpoint.RequiresDX; - MySession.Static.CustomLoadingScreenImage = TargetWorld.Checkpoint.CustomLoadingScreenImage; - MySession.Static.CustomLoadingScreenText = TargetWorld.Checkpoint.CustomLoadingScreenText; - MySession.Static.CustomSkybox = TargetWorld.Checkpoint.CustomSkybox; - - try - { - MySession.Static.Gpss = new MyGpsCollection(); - MySession.Static.Gpss.LoadGpss(TargetWorld.Checkpoint); - - } - catch (Exception ex) - { - Seamless.TryShow($"An error occured while loading GPS points! You will have an empty gps list! \n {ex.ToString()}"); - } - - - MyRenderProxy.RebuildCullingStructure(); - //MySession.Static.Toolbars.LoadToolbars(checkpoint); - - Sync.Players.RespawnComponent.InitFromCheckpoint(TargetWorld.Checkpoint); - - - // Set new admin settings - if (TargetWorld.Checkpoint.PromotedUsers != null) - { - MySession.Static.PromotedUsers = TargetWorld.Checkpoint.PromotedUsers.Dictionary; - } - else - { - MySession.Static.PromotedUsers = new Dictionary(); - } - - - - - foreach (KeyValuePair item in TargetWorld.Checkpoint.AllPlayersData.Dictionary) - { - ulong clientId = item.Key.GetClientId(); - AdminSettingsEnum adminSettingsEnum = (AdminSettingsEnum)item.Value.RemoteAdminSettings; - if (TargetWorld.Checkpoint.RemoteAdminSettings != null && TargetWorld.Checkpoint.RemoteAdminSettings.Dictionary.TryGetValue(clientId, out var value)) - { - adminSettingsEnum = (AdminSettingsEnum)value; - } - if (!MyPlatformGameSettings.IsIgnorePcuAllowed) - { - adminSettingsEnum &= ~AdminSettingsEnum.IgnorePcu; - adminSettingsEnum &= ~AdminSettingsEnum.KeepOriginalOwnershipOnPaste; - } - - - AdminSettingsList[clientId] = adminSettingsEnum; - if (!Sync.IsDedicated && clientId == Sync.MyId) - { - AdminSettings.SetValue(MySession.Static, adminSettingsEnum); - - //m_adminSettings = adminSettingsEnum; - } - - - - if (!MySession.Static.PromotedUsers.TryGetValue(clientId, out var value2)) - { - value2 = MyPromoteLevel.None; - } - if (item.Value.PromoteLevel > value2) - { - MySession.Static.PromotedUsers[clientId] = item.Value.PromoteLevel; - } - if (!MySession.Static.CreativeTools.Contains(clientId) && item.Value.CreativeToolsEnabled) - { - MySession.Static.CreativeTools.Add(clientId); - } - } - - - - - } - - private static void LoadConnectedClients() - { - - LoadMembersFromWorld.Invoke(MySession.Static, new object[] { TargetWorld, MyMultiplayer.Static }); - - - //Re-Initilize Virtual clients - object VirtualClientsValue = VirtualClients.GetValue(MySession.Static); - InitVirtualClients.Invoke(VirtualClientsValue, null); - - - //load online players - LoadOnlinePlayers(); - - } - - private static void StartEntitySync() - { - 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) - { - MyLog.Default.WriteLine("ControlledObject was null, respawning character"); - //m_cameraAwaitingEntity = true; - MyPlayerCollection.RequestLocalRespawn(); - } - - //Request client state batch - (MyMultiplayer.Static as MyMultiplayerClientBase).RequestBatchConfirmation(); - MyMultiplayer.Static.PendingReplicablesDone += MyMultiplayer_PendingReplicablesDone; - //typeof(MyGuiScreenTerminal).GetMethod("CreateTabs") - - MySession.Static.LoadDataComponents(); - //MyGuiSandbox.LoadData(false); - //MyGuiSandbox.AddScreen(MyGuiSandbox.CreateScreen(MyPerGameSettings.GUI.HUDScreen)); - MyRenderProxy.RebuildCullingStructure(); - MyRenderProxy.CollectGarbage(); - - Seamless.TryShow("OnlinePlayers: " + MySession.Static.Players.GetOnlinePlayers().Count); - Seamless.TryShow("Loading Complete!"); - } - - private static void MyMultiplayer_PendingReplicablesDone() - { - if (MySession.Static.VoxelMaps.Instances.Count > 0) - { - MySandboxGame.AreClipmapsReady = false; - } - MyMultiplayer.Static.PendingReplicablesDone -= MyMultiplayer_PendingReplicablesDone; - } - - - private static void UpdateWorldGenerator() - { - //This will re-init the MyProceduralWorldGenerator. (Not doing this will result in asteroids not rendering in properly) - - - //This shoud never be null - var Generator = MySession.Static.GetComponent(); - - //Force component to unload - UnloadProceduralWorldGenerator.Invoke(Generator, null); - - //Re-call the generator init - MyObjectBuilder_WorldGenerator GeneratorSettings = (MyObjectBuilder_WorldGenerator)TargetWorld.Checkpoint.SessionComponents.FirstOrDefault(x => x.GetType() == typeof(MyObjectBuilder_WorldGenerator)); - if (GeneratorSettings != null) - { - //Re-initilized this component (forces to update asteroid areas like not in planets etc) - Generator.Init(GeneratorSettings); - } - - //Force component to reload, re-syncing settings and seeds to the destination server - Generator.LoadData(); - - //We need to go in and force planets to be empty areas in the generator. This is originially done on planet init. - FieldInfo PlanetInitArgs = typeof(MyPlanet).GetField("m_planetInitValues", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance); - foreach (var Planet in MyEntities.GetEntities().OfType()) - { - MyPlanetInitArguments args = (MyPlanetInitArguments)PlanetInitArgs.GetValue(Planet); - - float MaxRadius = args.MaxRadius; - - Generator.MarkEmptyArea(Planet.PositionComp.GetPosition(), MaxRadius); - } - } - - private void UnloadCurrentServer() - { - //Unload current session on game thread - if (MyMultiplayer.Static == null) - throw new Exception("MyMultiplayer.Static is null on unloading? dafuq?"); - - - RemoveOldEntities(); - - //Try and close the quest log - MySessionComponentIngameHelp component = MySession.Static.GetComponent(); - component?.TryCancelObjective(); - - //Clear all old players and clients. - Sync.Clients.Clear(); - Sync.Players.ClearPlayers(); - - - MyHud.Chat.UnregisterChat(MyMultiplayer.Static); - - - - - MySession.Static.Gpss.RemovePlayerGpss(MySession.Static.LocalPlayerId); - MyHud.GpsMarkers.Clear(); - MyMultiplayer.Static.ReplicationLayer.Disconnect(); - MyMultiplayer.Static.ReplicationLayer.Dispose(); - MyMultiplayer.Static.Dispose(); - MyMultiplayer.Static = null; - - //Close any respawn screens that are open - MyGuiScreenMedicals.Close(); - - //MySession.Static.UnloadDataComponents(); - - } - - private void RemoveOldEntities() - { - foreach (var ent in MyEntities.GetEntities()) - { - if (ent is MyPlanet) - continue; - - ent.Close(); - } - } - - - - - - - - - } -} diff --git a/Messages/OnlinePlayerData.cs b/Messages/OnlinePlayerData.cs index f3e581c..bc810d8 100644 --- a/Messages/OnlinePlayerData.cs +++ b/Messages/OnlinePlayerData.cs @@ -10,26 +10,11 @@ namespace SeamlessClient.Messages [ProtoContract] public class OnlinePlayerData { - [ProtoMember(10)] public List OnlineServers = new List(); + [ProtoMember(10)] public List OnlinePlayers = new List(); [ProtoMember(12)] public int currentServerID; } - [ProtoContract] - public class OnlineClientServer - { - [ProtoMember(2)] public List Players = new List(); - - [ProtoMember(3)] public bool ServerRunning = false; - - [ProtoMember(10)] public int ServerID; - - [ProtoMember(11)] public string ServerName; - - public OnlineClientServer() - { - } - } [ProtoContract] public class OnlinePlayer @@ -42,9 +27,6 @@ namespace SeamlessClient.Messages [ProtoMember(4)] public int OnServer; - - public string ServerName; - public OnlinePlayer(string PlayerName, ulong SteamID, long IdentityID, int OnServer) { this.PlayerName = PlayerName; diff --git a/OnlinePlayersWindow/OnlineNexusPlayersWindow.cs b/OnlinePlayersWindow/OnlineNexusPlayersWindow.cs index 4f304dc..cdceb1f 100644 --- a/OnlinePlayersWindow/OnlineNexusPlayersWindow.cs +++ b/OnlinePlayersWindow/OnlineNexusPlayersWindow.cs @@ -385,7 +385,8 @@ namespace SeamlessClient.OnlinePlayersWindow Controls.Add(m_playersTable); - string servername = PlayersWindowComponent.onlineServer?.ServerName ?? "thisServer"; + //string servername = PlayersWindowComponent.onlineServer?.ServerName ?? "thisServer"; + string servername = "thisserver"; foreach (MyPlayer onlinePlayer in Sync.Players.GetOnlinePlayers()) { @@ -408,13 +409,14 @@ namespace SeamlessClient.OnlinePlayersWindow AddPlayer(onlinePlayer.Id.SteamId, servername); } - + /* foreach(var server in PlayersWindowComponent.allServers) { foreach(var player in server.Players) AddPlayerFromOtherServer(player, server.ServerName); } + */ m_lobbyTypeCombo.ItemSelected += lobbyTypeCombo_OnSelect; @@ -796,7 +798,7 @@ namespace SeamlessClient.OnlinePlayersWindow protected void Multiplayer_PlayerJoined(ulong userId, string userName) { - AddPlayer(userId, PlayersWindowComponent.onlineServer.ServerName); + //AddPlayer(userId, PlayersWindowComponent.onlineServer.ServerName); } protected void Multiplayer_PlayerLeft(ulong userId, MyChatMemberStateChangeEnum arg2) diff --git a/Seamless.cs b/Seamless.cs index 0014fa2..39333a7 100644 --- a/Seamless.cs +++ b/Seamless.cs @@ -1,13 +1,13 @@ using HarmonyLib; using NLog.Fluent; using Sandbox; +using Sandbox.Game.Entities; using Sandbox.Game.Localization; using Sandbox.Game.World; using Sandbox.ModAPI; using SeamlessClient.Components; using SeamlessClient.Messages; using SeamlessClient.OnlinePlayersWindow; -using SeamlessClient.ServerSwitching; using SeamlessClient.Utilities; using System; using System.Collections.Generic; @@ -33,6 +33,7 @@ namespace SeamlessClient public static ushort SeamlessClientNetId = 2936; private List allComps = new List(); + private Assembly thisAssembly => typeof(Seamless).Assembly; private bool Initilized = false; public static bool isSeamlessServer { get; private set; } = false; @@ -141,7 +142,7 @@ namespace SeamlessClient case ClientMessageType.OnlinePlayers: //Not implemented yet var playerData = msg.GetOnlinePlayers(); - PlayersWindowComponent.ApplyRecievedPlayers(playerData.OnlineServers, playerData.currentServerID); + //PlayersWindowComponent.ApplyRecievedPlayers(playerData.OnlineServers, playerData.currentServerID); break; } } @@ -204,11 +205,11 @@ namespace SeamlessClient Seamless.TryShow($"Beginning Redirect to server: {targetServer.TargetServerId}"); var world = targetServer.WorldRequest.DeserializeWorldData(); + + SeamlessSwitcher.Instance.StartSwitch(server, world); //Temp fix till im not lazy enough to fix new version - if (UseNewVersion) - ServerSwitcherComponent.Instance.StartBackendSwitch(server, world); - else - ServerSwitcherComponentOLD.Instance.StartBackendSwitch(server, world); + + } diff --git a/SeamlessClient.csproj b/SeamlessClient.csproj index 42355dd..d3d72dd 100644 --- a/SeamlessClient.csproj +++ b/SeamlessClient.csproj @@ -105,9 +105,11 @@ - + + + @@ -117,7 +119,6 @@ - diff --git a/Utilities/GameEvents.cs b/Utilities/GameEvents.cs new file mode 100644 index 0000000..3337293 --- /dev/null +++ b/Utilities/GameEvents.cs @@ -0,0 +1,34 @@ +using Sandbox.Engine.Multiplayer; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Threading.Tasks; +using VRage.Network; +using VRageMath; + +namespace SeamlessClient.Utilities +{ + public class GameEvents + { + private static Dictionary _delegateCache = new Dictionary(); + + private static Func GetDelegate(MethodInfo method) where TA : class + { + if (!_delegateCache.TryGetValue(method, out var del)) + { + del = (Func)(x => Delegate.CreateDelegate(typeof(TA), x, method) as TA); + _delegateCache[method] = del; + } + + return (Func)del; + } + + public static void RaiseStaticEvent(MethodInfo method, T1 arg1, EndpointId target = default, Vector3D? position = null) + { + var del = GetDelegate>(method); + MyMultiplayer.RaiseStaticEvent(del, arg1, target, position); + } + } +}