Update with old version
This commit is contained in:
@@ -29,6 +29,7 @@ using System.Reflection;
|
|||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using System.Timers;
|
||||||
using VRage;
|
using VRage;
|
||||||
using VRage.Game;
|
using VRage.Game;
|
||||||
using VRage.Game.Entity;
|
using VRage.Game.Entity;
|
||||||
@@ -58,6 +59,7 @@ namespace SeamlessClient.ServerSwitching
|
|||||||
private static MethodInfo InitVirtualClients;
|
private static MethodInfo InitVirtualClients;
|
||||||
private static MethodInfo CreateNewPlayerInternal;
|
private static MethodInfo CreateNewPlayerInternal;
|
||||||
private static MethodInfo PauseClient;
|
private static MethodInfo PauseClient;
|
||||||
|
public static MethodInfo SendPlayerData;
|
||||||
|
|
||||||
private static FieldInfo VirtualClients;
|
private static FieldInfo VirtualClients;
|
||||||
|
|
||||||
@@ -77,14 +79,28 @@ namespace SeamlessClient.ServerSwitching
|
|||||||
|
|
||||||
private static bool isSwitch = false;
|
private static bool isSwitch = false;
|
||||||
private MyObjectBuilder_Player player { get; set; }
|
private MyObjectBuilder_Player player { get; set; }
|
||||||
|
private static Timer pauseResetTimer = new Timer(1000);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public ServerSwitcherComponent()
|
public ServerSwitcherComponent()
|
||||||
{
|
{
|
||||||
|
pauseResetTimer.Elapsed += PauseResetTimer_Elapsed;
|
||||||
Instance = this;
|
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)
|
public override void Patch(Harmony patcher)
|
||||||
{
|
{
|
||||||
@@ -104,6 +120,7 @@ namespace SeamlessClient.ServerSwitching
|
|||||||
GpsRegisterChat = PatchUtils.GetMethod(typeof(MyGpsCollection), "RegisterChat");
|
GpsRegisterChat = PatchUtils.GetMethod(typeof(MyGpsCollection), "RegisterChat");
|
||||||
LoadMembersFromWorld = PatchUtils.GetMethod(typeof(MySession), "LoadMembersFromWorld");
|
LoadMembersFromWorld = PatchUtils.GetMethod(typeof(MySession), "LoadMembersFromWorld");
|
||||||
InitVirtualClients = PatchUtils.GetMethod(PatchUtils.VirtualClientsType, "Init");
|
InitVirtualClients = PatchUtils.GetMethod(PatchUtils.VirtualClientsType, "Init");
|
||||||
|
SendPlayerData = PatchUtils.GetMethod(PatchUtils.ClientType, "SendPlayerData");
|
||||||
|
|
||||||
CreateNewPlayerInternal = PatchUtils.GetMethod(typeof(MyPlayerCollection), "CreateNewPlayerInternal");
|
CreateNewPlayerInternal = PatchUtils.GetMethod(typeof(MyPlayerCollection), "CreateNewPlayerInternal");
|
||||||
|
|
||||||
@@ -118,6 +135,7 @@ namespace SeamlessClient.ServerSwitching
|
|||||||
var RemovePlayer = PatchUtils.GetMethod(typeof(MyPlayerCollection), "RemovePlayerFromDictionary");
|
var RemovePlayer = PatchUtils.GetMethod(typeof(MyPlayerCollection), "RemovePlayerFromDictionary");
|
||||||
var LoadClient = PatchUtils.GetMethod(PatchUtils.ClientType, "LoadMembersFromWorld");
|
var LoadClient = PatchUtils.GetMethod(PatchUtils.ClientType, "LoadMembersFromWorld");
|
||||||
|
|
||||||
|
|
||||||
Seamless.TryShow("Patched!");
|
Seamless.TryShow("Patched!");
|
||||||
|
|
||||||
|
|
||||||
@@ -145,9 +163,23 @@ namespace SeamlessClient.ServerSwitching
|
|||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//SendPlayerData
|
||||||
|
|
||||||
|
|
||||||
//Invoke the switch event
|
//Invoke the switch event
|
||||||
if (isSwitch)
|
if (isSwitch)
|
||||||
Instance.StartSwitch();
|
Instance.StartSwitch();
|
||||||
|
|
||||||
|
if (MySandboxGame.IsPaused)
|
||||||
|
{
|
||||||
|
pauseResetTimer.Start();
|
||||||
|
MyHud.Notifications.Remove(MyNotificationSingletons.ConnectionProblem);
|
||||||
|
MySandboxGame.PausePop();
|
||||||
|
}
|
||||||
|
|
||||||
|
SendPlayerData.Invoke(MyMultiplayer.Static, new object[] { MyGameService.OnlineName });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -281,8 +313,8 @@ namespace SeamlessClient.ServerSwitching
|
|||||||
{
|
{
|
||||||
Seamless.TryShow($"Needs entity Unload: {needsEntityUnload}");
|
Seamless.TryShow($"Needs entity Unload: {needsEntityUnload}");
|
||||||
|
|
||||||
//if (needsEntityUnload)
|
if (needsEntityUnload)
|
||||||
// MySession.Static.SetCameraController(MyCameraControllerEnum.SpectatorFixed);
|
MySession.Static.SetCameraController(MyCameraControllerEnum.SpectatorFixed);
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -384,6 +416,13 @@ namespace SeamlessClient.ServerSwitching
|
|||||||
|
|
||||||
Seamless.TryShow($"2 Streaming: {clienta.HasPendingStreamingReplicables} - LastMessage: {clienta.LastMessageFromServer}");
|
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}");
|
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()
|
private void UnloadOldEntities()
|
||||||
@@ -449,6 +488,7 @@ namespace SeamlessClient.ServerSwitching
|
|||||||
Seamless.TryShow($"4 Streaming: {clienta.HasPendingStreamingReplicables} - LastMessage: {clienta.LastMessageFromServer}");
|
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}");
|
Seamless.TryShow($"4 NexusMajor: {Seamless.NexusVersion.Major} - ConrolledEntity {MySession.Static.ControlledEntity == null} - HumanPlayer {MySession.Static.LocalHumanPlayer == null} - Character {MySession.Static.LocalCharacter == null}");
|
||||||
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
// Create constructors
|
// Create constructors
|
||||||
var LayerInstance = TransportLayerConstructor.Invoke(new object[] { 2 });
|
var LayerInstance = TransportLayerConstructor.Invoke(new object[] { 2 });
|
||||||
@@ -463,13 +503,16 @@ namespace SeamlessClient.ServerSwitching
|
|||||||
|
|
||||||
// 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);
|
||||||
|
Sync.Clients.SetLocalSteamId(Sync.MyId, false, MyGameService.UserName);
|
||||||
|
return;
|
||||||
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();
|
||||||
|
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void StartSwitch()
|
private void StartSwitch()
|
||||||
@@ -562,9 +605,13 @@ namespace SeamlessClient.ServerSwitching
|
|||||||
FieldInfo hudPoints = typeof(MyHudMarkerRender).GetField("m_pointsOfInterest", BindingFlags.Instance | BindingFlags.NonPublic);
|
FieldInfo hudPoints = typeof(MyHudMarkerRender).GetField("m_pointsOfInterest", BindingFlags.Instance | BindingFlags.NonPublic);
|
||||||
IList points = (IList)hudPoints.GetValue(MyGuiScreenHudSpace.Static.MarkerRender);
|
IList points = (IList)hudPoints.GetValue(MyGuiScreenHudSpace.Static.MarkerRender);
|
||||||
|
|
||||||
|
MySandboxGame.PausePop();
|
||||||
//Sync.Players.RequestNewPlayer(Sync.MyId, 0, MyGameService.UserName, null, true, true);
|
//Sync.Players.RequestNewPlayer(Sync.MyId, 0, MyGameService.UserName, null, true, true);
|
||||||
PauseClient.Invoke(MyMultiplayer.Static, new object[] { false });
|
PauseClient.Invoke(MyMultiplayer.Static, new object[] { false });
|
||||||
|
MySandboxGame.PausePop();
|
||||||
|
MyHud.Notifications.Remove(MyNotificationSingletons.ConnectionProblem);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
isSwitch = false;
|
isSwitch = false;
|
||||||
@@ -743,28 +790,17 @@ namespace SeamlessClient.ServerSwitching
|
|||||||
MyMultiplayer.Static.PendingReplicablesDone += Static_PendingReplicablesDone;
|
MyMultiplayer.Static.PendingReplicablesDone += Static_PendingReplicablesDone;
|
||||||
//typeof(MyGuiScreenTerminal).GetMethod("CreateTabs")
|
//typeof(MyGuiScreenTerminal).GetMethod("CreateTabs")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//MySession.Static.LocalHumanPlayer.Controller.TakeControl(originalControlledEntity);
|
//MySession.Static.LocalHumanPlayer.Controller.TakeControl(originalControlledEntity);
|
||||||
|
|
||||||
MyGuiSandbox.UnloadContent();
|
MyGuiSandbox.UnloadContent();
|
||||||
MyGuiSandbox.LoadContent();
|
MyGuiSandbox.LoadContent();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//MyGuiSandbox.CreateScreen(MyPerGameSettings.GUI.HUDScreen);
|
//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!");
|
||||||
}
|
}
|
||||||
@@ -804,10 +840,6 @@ namespace SeamlessClient.ServerSwitching
|
|||||||
Sync.Players.LoadConnectedPlayers(TargetWorld.Checkpoint, savingPlayerId);
|
Sync.Players.LoadConnectedPlayers(TargetWorld.Checkpoint, savingPlayerId);
|
||||||
Sync.Players.LoadControlledEntities(TargetWorld.Checkpoint.ControlledEntities, TargetWorld.Checkpoint.ControlledObject, savingPlayerId);
|
Sync.Players.LoadControlledEntities(TargetWorld.Checkpoint.ControlledEntities, TargetWorld.Checkpoint.ControlledObject, savingPlayerId);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Seamless.TryShow("Saving PlayerID: " + savingPlayerId.ToString());
|
|
||||||
Seamless.TryShow($"AFTER {MySession.Static.LocalHumanPlayer == null} - {MySession.Static.LocalCharacter == null}");
|
Seamless.TryShow($"AFTER {MySession.Static.LocalHumanPlayer == null} - {MySession.Static.LocalCharacter == null}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
493
Components/ServerSwitcherComponentOLD.cs
Normal file
493
Components/ServerSwitcherComponentOLD.cs
Normal file
@@ -0,0 +1,493 @@
|
|||||||
|
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
|
||||||
|
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<MyObjectBuilder_Checkpoint.PlayerId, MyObjectBuilder_Player> 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<MyPlayer.PlayerId, MyPlayer> Players = (ConcurrentDictionary<MyPlayer.PlayerId, MyPlayer>)Patches.MPlayerGPSCollection.GetValue(MySession.Static.Players);
|
||||||
|
//LoadPlayerInternal(ref playerId5, item3.Value);
|
||||||
|
if (Players.TryGetValue(playerId5, out MyPlayer myPlayer))
|
||||||
|
{
|
||||||
|
List<Vector3> 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<ulong, AdminSettingsEnum> AdminSettingsList = (Dictionary<ulong, AdminSettingsEnum>)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<ulong, MyPromoteLevel>();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
foreach (KeyValuePair<MyObjectBuilder_Checkpoint.PlayerId, MyObjectBuilder_Player> 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<MyProceduralWorldGenerator>();
|
||||||
|
|
||||||
|
//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<MyPlanet>())
|
||||||
|
{
|
||||||
|
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<MySessionComponentIngameHelp>();
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@@ -33,5 +33,5 @@ using System.Runtime.InteropServices;
|
|||||||
// by using the '*' as shown below:
|
// by using the '*' as shown below:
|
||||||
// [assembly: AssemblyVersion("1.0.*")]
|
// [assembly: AssemblyVersion("1.0.*")]
|
||||||
|
|
||||||
[assembly: AssemblyVersion("2.0.0.4")] //Set these both to the same
|
[assembly: AssemblyVersion("2.0.0.6")] //Set these both to the same
|
||||||
[assembly: AssemblyFileVersion("2.0.0.4")]
|
[assembly: AssemblyFileVersion("2.0.0.6")]
|
||||||
|
14
Seamless.cs
14
Seamless.cs
@@ -1,8 +1,10 @@
|
|||||||
using HarmonyLib;
|
using HarmonyLib;
|
||||||
using NLog.Fluent;
|
using NLog.Fluent;
|
||||||
|
using Sandbox;
|
||||||
using Sandbox.Game.Localization;
|
using Sandbox.Game.Localization;
|
||||||
using Sandbox.Game.World;
|
using Sandbox.Game.World;
|
||||||
using Sandbox.ModAPI;
|
using Sandbox.ModAPI;
|
||||||
|
using SeamlessClient.Components;
|
||||||
using SeamlessClient.Messages;
|
using SeamlessClient.Messages;
|
||||||
using SeamlessClient.OnlinePlayersWindow;
|
using SeamlessClient.OnlinePlayersWindow;
|
||||||
using SeamlessClient.ServerSwitching;
|
using SeamlessClient.ServerSwitching;
|
||||||
@@ -15,6 +17,7 @@ using System.Net.NetworkInformation;
|
|||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using VRage;
|
||||||
using VRage.GameServices;
|
using VRage.GameServices;
|
||||||
using VRage.Plugins;
|
using VRage.Plugins;
|
||||||
using VRage.Sync;
|
using VRage.Sync;
|
||||||
@@ -34,6 +37,7 @@ namespace SeamlessClient
|
|||||||
private bool Initilized = false;
|
private bool Initilized = false;
|
||||||
public static bool isSeamlessServer { get; private set; } = false;
|
public static bool isSeamlessServer { get; private set; } = false;
|
||||||
public static bool isDebug = false;
|
public static bool isDebug = false;
|
||||||
|
public static bool UseNewVersion = false;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -173,6 +177,9 @@ namespace SeamlessClient
|
|||||||
Initilized = true;
|
Initilized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IMyGameServer server = MyServiceManager.Instance.GetService<IMyGameServer>();
|
||||||
|
MySandboxGame.PausePop();
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -196,7 +203,12 @@ namespace SeamlessClient
|
|||||||
|
|
||||||
Seamless.TryShow($"Beginning Redirect to server: {targetServer.TargetServerId}");
|
Seamless.TryShow($"Beginning Redirect to server: {targetServer.TargetServerId}");
|
||||||
var world = targetServer.WorldRequest.DeserializeWorldData();
|
var world = targetServer.WorldRequest.DeserializeWorldData();
|
||||||
ServerSwitcherComponent.Instance.StartBackendSwitch(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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -99,6 +99,7 @@
|
|||||||
<Compile Include="Components\LoadingScreenComponent.cs" />
|
<Compile Include="Components\LoadingScreenComponent.cs" />
|
||||||
<Compile Include="Components\MyGUIScreenMedicalsPatch.cs" />
|
<Compile Include="Components\MyGUIScreenMedicalsPatch.cs" />
|
||||||
<Compile Include="Components\MyHudTimeTracker.cs" />
|
<Compile Include="Components\MyHudTimeTracker.cs" />
|
||||||
|
<Compile Include="Components\ServerSwitcherComponentOLD.cs" />
|
||||||
<Compile Include="GUI\Screens\GUILoadingScreen.cs" />
|
<Compile Include="GUI\Screens\GUILoadingScreen.cs" />
|
||||||
<Compile Include="Messages\OnlinePlayerData.cs" />
|
<Compile Include="Messages\OnlinePlayerData.cs" />
|
||||||
<Compile Include="Utilities\UtilExtensions.cs" />
|
<Compile Include="Utilities\UtilExtensions.cs" />
|
||||||
|
@@ -72,7 +72,7 @@ Type.GetType("Sandbox.Game.Screens.Helpers.MyLoadingScreenText, Sandbox.Game");
|
|||||||
public static MethodInfo LoadPlayerInternal { get; private set; }
|
public static MethodInfo LoadPlayerInternal { get; private set; }
|
||||||
|
|
||||||
|
|
||||||
public static MethodInfo SendPlayerData;
|
|
||||||
|
|
||||||
|
|
||||||
public static event EventHandler<JoinResultMsg> OnJoinEvent;
|
public static event EventHandler<JoinResultMsg> OnJoinEvent;
|
||||||
@@ -92,7 +92,7 @@ Type.GetType("Sandbox.Game.Screens.Helpers.MyLoadingScreenText, Sandbox.Game");
|
|||||||
|
|
||||||
/* Get Methods */
|
/* Get Methods */
|
||||||
LoadPlayerInternal = GetMethod(typeof(MyPlayerCollection), "LoadPlayerInternal");
|
LoadPlayerInternal = GetMethod(typeof(MyPlayerCollection), "LoadPlayerInternal");
|
||||||
SendPlayerData = GetMethod(ClientType, "SendPlayerData");
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user