552 lines
21 KiB
C#
552 lines
21 KiB
C#
using HarmonyLib;
|
|
using Sandbox;
|
|
using Sandbox.Definitions;
|
|
using Sandbox.Engine;
|
|
using Sandbox.Engine.Multiplayer;
|
|
using Sandbox.Engine.Networking;
|
|
using Sandbox.Engine.Physics;
|
|
using Sandbox.Engine.Utils;
|
|
using Sandbox.Engine.Voxels;
|
|
using Sandbox.Game;
|
|
using Sandbox.Game.Entities;
|
|
using Sandbox.Game.Gui;
|
|
using Sandbox.Game.GUI;
|
|
using Sandbox.Game.Multiplayer;
|
|
using Sandbox.Game.Screens.Helpers;
|
|
using Sandbox.Game.SessionComponents;
|
|
using Sandbox.Game.World;
|
|
using Sandbox.Graphics.GUI;
|
|
using Sandbox.ModAPI;
|
|
using SeamlessClientPlugin.Utilities;
|
|
using System;
|
|
using System.Collections.Concurrent;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Reflection;
|
|
using System.Reflection.Emit;
|
|
using System.Text;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
using VRage;
|
|
using VRage.Game;
|
|
using VRage.Game.ModAPI;
|
|
using VRage.Game.SessionComponents;
|
|
using VRage.Game.Voxels;
|
|
using VRage.GameServices;
|
|
using VRage.Network;
|
|
using VRage.Serialization;
|
|
using VRage.Utils;
|
|
using VRageMath;
|
|
using VRageRender;
|
|
using VRageRender.Messages;
|
|
|
|
namespace SeamlessClientPlugin.SeamlessTransfer
|
|
{
|
|
public class LoadServer
|
|
{
|
|
//Protected or internal class types
|
|
private static readonly Type ClientType = Type.GetType("Sandbox.Engine.Multiplayer.MyMultiplayerClient, Sandbox.Game");
|
|
private static readonly Type SyncLayerType = Type.GetType("Sandbox.Game.Multiplayer.MySyncLayer, Sandbox.Game");
|
|
private static readonly Type MyTransportLayerType = Type.GetType("Sandbox.Engine.Multiplayer.MyTransportLayer, Sandbox.Game");
|
|
private static readonly Type MySessionType = Type.GetType("Sandbox.Game.World.MySession, Sandbox.Game");
|
|
private static readonly Type VirtualClientsType = Type.GetType("Sandbox.Engine.Multiplayer.MyVirtualClients, Sandbox.Game");
|
|
private static readonly Type GUIScreenChat = Type.GetType("Sandbox.Game.Gui.MyGuiScreenChat, Sandbox.Game");
|
|
|
|
private static Harmony Patcher = new Harmony("SeamlessClientReUnload");
|
|
private static MyGameServerItem Server;
|
|
private static MyObjectBuilder_World World;
|
|
|
|
public static object MyMulitplayerClient;
|
|
|
|
|
|
|
|
public static ConstructorInfo ClientConstructor;
|
|
public static ConstructorInfo SyncLayerConstructor;
|
|
public static ConstructorInfo TransportLayerConstructor;
|
|
public static ConstructorInfo MySessionConstructor;
|
|
|
|
//Reflected Methods
|
|
public static FieldInfo VirtualClients;
|
|
public static FieldInfo AdminSettings;
|
|
public static FieldInfo RemoteAdminSettings;
|
|
public static FieldInfo MPlayerGPSCollection;
|
|
public static MethodInfo RemovePlayerFromDictionary;
|
|
public static MethodInfo InitVirtualClients;
|
|
public static MethodInfo LoadPlayerInternal;
|
|
public static MethodInfo LoadMembersFromWorld;
|
|
|
|
|
|
public LoadServer()
|
|
{
|
|
InitiatePatches();
|
|
|
|
|
|
|
|
|
|
//TargetWorld = World;
|
|
//Server = e;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
public void InitiatePatches()
|
|
{
|
|
//Patch the on connection event
|
|
MethodInfo OnJoin = ClientType.GetMethod("OnUserJoined", BindingFlags.NonPublic | BindingFlags.Instance);
|
|
Patcher.Patch(OnJoin, postfix: new HarmonyMethod(GetPatchMethod(nameof(OnUserJoined))));
|
|
|
|
|
|
ClientConstructor = ClientType?.GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic, null, new Type[2] { typeof(MyGameServerItem), SyncLayerType }, null);
|
|
SyncLayerConstructor = SyncLayerType?.GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic, null, new Type[1] { MyTransportLayerType }, null);
|
|
TransportLayerConstructor = MyTransportLayerType?.GetConstructor(BindingFlags.Instance | BindingFlags.Public, null, new Type[1] { typeof(int) }, null);
|
|
MySessionConstructor = MySessionType?.GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic, null, new Type[2] { typeof(MySyncLayer), typeof(bool) }, null);
|
|
|
|
if (ClientConstructor == null)
|
|
{
|
|
throw new InvalidOperationException("Couldn't find ClientConstructor");
|
|
}
|
|
|
|
if (SyncLayerConstructor == null)
|
|
{
|
|
throw new InvalidOperationException("Couldn't find SyncLayerConstructor");
|
|
}
|
|
|
|
if (TransportLayerConstructor == null)
|
|
{
|
|
throw new InvalidOperationException("Couldn't find TransportLayerConstructor");
|
|
}
|
|
|
|
if (MySessionConstructor == null)
|
|
{
|
|
throw new InvalidOperationException("Couldn't find MySessionConstructor");
|
|
}
|
|
|
|
RemovePlayerFromDictionary = typeof(MyPlayerCollection).GetMethod("RemovePlayerFromDictionary", BindingFlags.Instance | BindingFlags.NonPublic);
|
|
VirtualClients = typeof(MySession).GetField("VirtualClients", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
|
|
InitVirtualClients = VirtualClientsType.GetMethod("Init", BindingFlags.Instance | BindingFlags.Public);
|
|
LoadPlayerInternal = typeof(MyPlayerCollection).GetMethod("LoadPlayerInternal", BindingFlags.Instance | BindingFlags.NonPublic);
|
|
LoadMembersFromWorld = typeof(MySession).GetMethod("LoadMembersFromWorld", BindingFlags.NonPublic | BindingFlags.Instance);
|
|
AdminSettings = typeof(MySession).GetField("m_adminSettings", BindingFlags.Instance | BindingFlags.NonPublic);
|
|
RemoteAdminSettings = typeof(MySession).GetField("m_remoteAdminSettings", BindingFlags.Instance | BindingFlags.NonPublic);
|
|
MPlayerGPSCollection = typeof(MyPlayerCollection).GetField("m_players", BindingFlags.Instance | BindingFlags.NonPublic);
|
|
}
|
|
|
|
|
|
private static MethodInfo GetPatchMethod(string v)
|
|
{
|
|
return typeof(LoadServer).GetMethod(v, BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
|
|
}
|
|
|
|
|
|
private static void OnUserJoined(ref JoinResultMsg msg)
|
|
{
|
|
if (SeamlessClient.IsSwitching && msg.JoinResult == JoinResult.OK)
|
|
{
|
|
SeamlessClient.TryShow("User Joined! Result: "+msg.JoinResult.ToString());
|
|
ForceClientConnection();
|
|
}else if (SeamlessClient.IsSwitching && msg.JoinResult != JoinResult.OK)
|
|
{
|
|
SeamlessClient.TryShow("Failed to join server! Reason: " + msg.JoinResult.ToString());
|
|
MySession.Static.Unload();
|
|
}
|
|
}
|
|
|
|
|
|
|
|
public static void LoadWorldData(MyGameServerItem TargetServer, MyObjectBuilder_World TargetWorld)
|
|
{
|
|
Server = TargetServer;
|
|
World = TargetWorld;
|
|
}
|
|
|
|
|
|
public static void ResetMPClient()
|
|
{
|
|
try
|
|
{
|
|
|
|
|
|
MySandboxGame.Static.SessionCompatHelper.FixSessionComponentObjectBuilders(World.Checkpoint, World.Sector);
|
|
|
|
|
|
var LayerInstance = TransportLayerConstructor.Invoke(new object[] { 2 });
|
|
var SyncInstance = SyncLayerConstructor.Invoke(new object[] { LayerInstance });
|
|
var instance = ClientConstructor.Invoke(new object[] { Server, SyncInstance });
|
|
MyMulitplayerClient = instance;
|
|
|
|
|
|
|
|
|
|
MyMultiplayer.Static = (MyMultiplayerBase)instance;
|
|
MyMultiplayer.Static.ExperimentalMode = MySandboxGame.Config.ExperimentalMode;
|
|
SeamlessClient.TryShow("Successfully set MyMultiplayer.Static");
|
|
//var m = ClientType.GetMethod("SendPlayerData", BindingFlags.Public | BindingFlags.Instance);
|
|
//m.Invoke(MyMultiplayer.Static, new object[] { MyGameService.UserName });
|
|
Server.GetGameTagByPrefix("gamemode");
|
|
//typeof(MySession).GetMethod("LoadMembersFromWorld", BindingFlags.NonPublic | BindingFlags.Instance).Invoke(MySession.Static, new object[] { LoadServer.TargetWorld, MyMultiplayer.Static });
|
|
|
|
|
|
//MyScreenManager.CloseScreen(GUIScreenChat);
|
|
MyHud.Chat.RegisterChat(MyMultiplayer.Static);
|
|
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
SeamlessClient.TryShow("Error! " + ex.ToString());
|
|
}
|
|
}
|
|
|
|
public static void LoadMP(MyObjectBuilder_World world, MyMultiplayerBase multiplayerSession)
|
|
{
|
|
SeamlessClient.TryShow("Starting LoadMP!");
|
|
|
|
|
|
//var MySessionConstructor = MySessionType.GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic, null, new Type[2] { typeof(MySyncLayer), typeof(bool) }, null);
|
|
//MySession.Static = (MySession)MySessionConstructor.Invoke(new object[] { MyMultiplayer.Static.SyncLayer, true });
|
|
MySession.Static.Mods = World.Checkpoint.Mods;
|
|
MySession.Static.Settings = World.Checkpoint.Settings;
|
|
MySession.Static.CurrentPath = MyLocalCache.GetSessionSavesPath(MyUtils.StripInvalidChars(world.Checkpoint.SessionName), contentFolder: false, createIfNotExists: false);
|
|
MySession.Static.WorldBoundaries = world.Checkpoint.WorldBoundaries;
|
|
MySession.Static.InGameTime = MyObjectBuilder_Checkpoint.DEFAULT_DATE;
|
|
|
|
|
|
|
|
// MySession.Static.Players.LoadConnectedPlayers(world.Checkpoint);
|
|
|
|
//typeof(MySession).GetMethod("PrepareBaseSession", BindingFlags.NonPublic | BindingFlags.Instance, null, new Type[] { typeof(MyObjectBuilder_Checkpoint), typeof(MyObjectBuilder_Sector) }, null).Invoke(MySession.Static, new object[] { world.Checkpoint, world.Sector });
|
|
|
|
if (MyFakes.MP_SYNC_CLUSTERTREE)
|
|
{
|
|
SeamlessClient.TryShow("Deserializing Clusters!");
|
|
//MyPhysics.DeserializeClusters(world.Clusters);
|
|
}
|
|
|
|
|
|
|
|
//_ = world.Checkpoint.ControlledObject;
|
|
//world.Checkpoint.ControlledObject = -1L;
|
|
LoadOnlinePlayers(world.Checkpoint);
|
|
LoadWorld(world.Checkpoint, world.Sector);
|
|
SeamlessClient.TryShow("Loading World Complete!");
|
|
}
|
|
|
|
|
|
|
|
private static void LoadWorld(MyObjectBuilder_Checkpoint checkpoint, MyObjectBuilder_Sector sector)
|
|
{
|
|
|
|
Dictionary<ulong, AdminSettingsEnum> AdminSettingsList = (Dictionary<ulong, AdminSettingsEnum>)RemoteAdminSettings.GetValue(MySession.Static);
|
|
AdminSettingsList.Clear();
|
|
|
|
MySession.Static.PromotedUsers.Clear();
|
|
MySession.Static.CreativeTools.Clear();
|
|
|
|
MyEntities.MemoryLimitAddFailureReset();
|
|
MySession.Static.ElapsedGameTime = new TimeSpan(checkpoint.ElapsedGameTime);
|
|
MySession.Static.InGameTime = checkpoint.InGameTime;
|
|
MySession.Static.Name = MyStatControlText.SubstituteTexts(checkpoint.SessionName);
|
|
MySession.Static.Description = checkpoint.Description;
|
|
|
|
|
|
if (checkpoint.PromotedUsers != null)
|
|
{
|
|
MySession.Static.PromotedUsers = checkpoint.PromotedUsers.Dictionary;
|
|
}
|
|
else
|
|
{
|
|
MySession.Static.PromotedUsers = new Dictionary<ulong, MyPromoteLevel>();
|
|
}
|
|
|
|
|
|
|
|
|
|
foreach (KeyValuePair<MyObjectBuilder_Checkpoint.PlayerId, MyObjectBuilder_Player> item in checkpoint.AllPlayersData.Dictionary)
|
|
{
|
|
ulong clientId = item.Key.GetClientId();
|
|
AdminSettingsEnum adminSettingsEnum = (AdminSettingsEnum)item.Value.RemoteAdminSettings;
|
|
if (checkpoint.RemoteAdminSettings != null && 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);
|
|
}
|
|
}
|
|
|
|
|
|
//MySession.Static.WorkshopId = checkpoint.WorkshopId;
|
|
MySession.Static.Password = checkpoint.Password;
|
|
MySession.Static.PreviousEnvironmentHostility = checkpoint.PreviousEnvironmentHostility;
|
|
MySession.Static.RequiresDX = checkpoint.RequiresDX;
|
|
MySession.Static.CustomLoadingScreenImage = checkpoint.CustomLoadingScreenImage;
|
|
MySession.Static.CustomLoadingScreenText = checkpoint.CustomLoadingScreenText;
|
|
MySession.Static.CustomSkybox = checkpoint.CustomSkybox;
|
|
//FixIncorrectSettings(Settings);
|
|
// MySession.Static.AppVersionFromSave = checkpoint.AppVersion;
|
|
//MyToolbarComponent.InitCharacterToolbar(checkpoint.CharacterToolbar);
|
|
//LoadCameraControllerSettings(checkpoint);
|
|
|
|
|
|
|
|
|
|
foreach(var GPS in checkpoint.Gps.Dictionary)
|
|
{
|
|
if (GPS.Key != MySession.Static.LocalPlayerId)
|
|
continue;
|
|
|
|
SeamlessClient.TryShow(GPS.Key + ":" + GPS.Value.Entries.Count);
|
|
|
|
|
|
}
|
|
|
|
|
|
SeamlessClient.TryShow("LocalPlayerID: " + MySession.Static.LocalPlayerId);
|
|
checkpoint.Gps.Dictionary.TryGetValue(MySession.Static.LocalPlayerId, out MyObjectBuilder_Gps GPSCollection);
|
|
SeamlessClient.TryShow("You have " + GPSCollection.Entries.Count + " gps points!");
|
|
|
|
|
|
Dictionary<long, Dictionary<int, MyGps>> m_playerGpss = (Dictionary<long, Dictionary<int, MyGps>>)typeof(MyGpsCollection).GetField("m_playerGpss", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(MySession.Static.Gpss);
|
|
m_playerGpss.Clear();
|
|
|
|
|
|
foreach (var GPS in GPSCollection.Entries)
|
|
{
|
|
MyGps myGps = new MyGps(GPS);
|
|
|
|
if(MySession.Static.Gpss.AddPlayerGps(MySession.Static.LocalPlayerId, ref myGps))
|
|
{
|
|
MyHud.GpsMarkers.RegisterMarker(myGps);
|
|
}
|
|
else
|
|
{
|
|
SeamlessClient.TryShow("Failed to registered Marker! It already exsists!");
|
|
}
|
|
}
|
|
|
|
|
|
|
|
MySession.Static.Gpss.LoadGpss(checkpoint);
|
|
MySession.Static.Toolbars.LoadToolbars(checkpoint);
|
|
|
|
Sync.Players.RespawnComponent.InitFromCheckpoint(checkpoint);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private static void ForceClientConnection()
|
|
{
|
|
SeamlessClient.IsSwitching = false;
|
|
|
|
try
|
|
{
|
|
|
|
try
|
|
{
|
|
if (MyMultiplayer.Static == null)
|
|
SeamlessClient.TryShow("MyMultiplayer.Static is null");
|
|
|
|
if (World == null)
|
|
SeamlessClient.TryShow("TargetWorld is null");
|
|
|
|
LoadClients();
|
|
|
|
LoadMP(World, MyMultiplayer.Static);
|
|
|
|
|
|
}catch(Exception ex)
|
|
{
|
|
SeamlessClient.TryShow(ex.ToString());
|
|
|
|
}
|
|
|
|
|
|
SeamlessClient.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)
|
|
{
|
|
SeamlessClient.TryShow("C");
|
|
MyLog.Default.WriteLine("ControlledObject was null, respawning character");
|
|
//m_cameraAwaitingEntity = true;
|
|
MyPlayerCollection.RequestLocalRespawn();
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//typeof(MyGuiScreenTerminal).GetMethod("CreateTabs")
|
|
MyMultiplayer.Static.OnSessionReady();
|
|
MySession.Static.LoadDataComponents();
|
|
//MyGuiSandbox.LoadData(false);
|
|
//MyGuiSandbox.AddScreen(MyGuiSandbox.CreateScreen(MyPerGameSettings.GUI.HUDScreen));
|
|
MyRenderProxy.RebuildCullingStructure();
|
|
MyRenderProxy.CollectGarbage();
|
|
|
|
SeamlessClient.TryShow("OnlinePlayers: " + MySession.Static.Players.GetOnlinePlayers().Count);
|
|
SeamlessClient.TryShow("Loading Complete!");
|
|
|
|
}
|
|
catch (Exception Ex)
|
|
{
|
|
SeamlessClient.TryShow(Ex.ToString());
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
private static void LoadClients()
|
|
{
|
|
|
|
|
|
try
|
|
{
|
|
//Remove all old players
|
|
foreach (var Client in MySession.Static.Players.GetOnlinePlayers())
|
|
{
|
|
if (Client.Id.SteamId == Sync.MyId)
|
|
continue;
|
|
|
|
SeamlessClient.TryShow("Disconnecting: " + Client.DisplayName);
|
|
RemovePlayerFromDictionary.Invoke(MySession.Static.Players, new object[] { Client.Id });
|
|
}
|
|
|
|
//Clear all exsisting clients
|
|
foreach (var Client in Sync.Clients.GetClients().ToList())
|
|
{
|
|
if (Client.SteamUserId == Sync.MyId)
|
|
continue;
|
|
|
|
Sync.Clients.RemoveClient(Client.SteamUserId);
|
|
}
|
|
|
|
|
|
object VirtualClientsValue = VirtualClients.GetValue(MySession.Static);
|
|
|
|
//Re-Initilize Virtual clients
|
|
SeamlessClient.TryShow("Initilizing Virtual Clients!");
|
|
InitVirtualClients.Invoke(VirtualClientsValue, null);
|
|
|
|
|
|
//Load Members from world
|
|
SeamlessClient.TryShow("Loading Members From World!");
|
|
LoadMembersFromWorld.Invoke(MySession.Static, new object[] { World, MyMulitplayerClient });
|
|
foreach (var Client in World.Checkpoint.Clients)
|
|
{
|
|
SeamlessClient.TryShow("Adding New Client: " + Client.Name);
|
|
Sync.Clients.AddClient(Client.SteamId, Client.Name);
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
SeamlessClient.TryShow(ex.ToString());
|
|
}
|
|
|
|
|
|
}
|
|
|
|
private static void LoadOnlinePlayers(MyObjectBuilder_Checkpoint checkpoint)
|
|
{
|
|
//Get This players ID
|
|
MyPlayer.PlayerId? savingPlayerId = new MyPlayer.PlayerId(Sync.MyId);
|
|
if (!savingPlayerId.HasValue)
|
|
{
|
|
SeamlessClient.TryShow("SavingPlayerID is null! Creating Default!");
|
|
savingPlayerId = new MyPlayer.PlayerId(Sync.MyId);
|
|
}
|
|
|
|
SeamlessClient.TryShow("Saving PlayerID: "+savingPlayerId.ToString());
|
|
|
|
|
|
SeamlessClient.TryShow("Checkpoint.AllPlayers: " + checkpoint.AllPlayers.Count);
|
|
//These both are null/empty. Server doesnt need to send them to the client
|
|
//SeamlessClient.TryShow("Checkpoint.ConnectedPlayers: " + checkpoint.ConnectedPlayers.Dictionary.Count);
|
|
//SeamlessClient.TryShow("Checkpoint.DisconnectedPlayers: " + checkpoint.DisconnectedPlayers.Dictionary.Count);
|
|
SeamlessClient.TryShow("Checkpoint.AllPlayersData: " + checkpoint.AllPlayersData.Dictionary.Count);
|
|
|
|
|
|
foreach (KeyValuePair<MyObjectBuilder_Checkpoint.PlayerId, MyObjectBuilder_Player> item3 in checkpoint.AllPlayersData.Dictionary)
|
|
{
|
|
MyPlayer.PlayerId playerId5 = new MyPlayer.PlayerId(item3.Key.GetClientId(), item3.Key.SerialId);
|
|
if (savingPlayerId.HasValue && playerId5.SteamId == savingPlayerId.Value.SteamId)
|
|
{
|
|
playerId5 = new MyPlayer.PlayerId(Sync.MyId, playerId5.SerialId);
|
|
|
|
}
|
|
|
|
LoadPlayerInternal.Invoke(MySession.Static.Players, new object[] { playerId5, item3.Value, false });
|
|
ConcurrentDictionary<MyPlayer.PlayerId, MyPlayer> Players = (ConcurrentDictionary<MyPlayer.PlayerId, MyPlayer>)MPlayerGPSCollection.GetValue(MySession.Static.Players);
|
|
//LoadPlayerInternal(ref playerId5, item3.Value);
|
|
if (Players.TryGetValue(playerId5, out MyPlayer myPlayer))
|
|
{
|
|
List<Vector3> value2 = null;
|
|
if (checkpoint.AllPlayersColors != null && checkpoint.AllPlayersColors.Dictionary.TryGetValue(item3.Key, out value2))
|
|
{
|
|
myPlayer.SetBuildColorSlots(value2);
|
|
}
|
|
else if (checkpoint.CharacterToolbar != null && checkpoint.CharacterToolbar.ColorMaskHSVList != null && checkpoint.CharacterToolbar.ColorMaskHSVList.Count > 0)
|
|
{
|
|
myPlayer.SetBuildColorSlots(checkpoint.CharacterToolbar.ColorMaskHSVList);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
private static void UpdatePlayerData()
|
|
{
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|