fixes for nexus v3
This commit is contained in:
@@ -1,218 +1,203 @@
|
||||
using Sandbox.Engine.Multiplayer;
|
||||
using Sandbox.Engine.Networking;
|
||||
using Sandbox.Game;
|
||||
using Sandbox.Game.Entities;
|
||||
using Sandbox.Game.Gui;
|
||||
using Sandbox.Game.Multiplayer;
|
||||
using System.Runtime.CompilerServices;
|
||||
using CringePlugins.Ui;
|
||||
using Sandbox.Game.World;
|
||||
using Sandbox.Graphics.GUI;
|
||||
using Sandbox.ModAPI;
|
||||
using SeamlessClientPlugin.Messages;
|
||||
using SeamlessClientPlugin.SeamlessTransfer;
|
||||
using SeamlessClientPlugin.Utilities;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Timers;
|
||||
using System.Windows.Forms;
|
||||
using VRage.Game.ModAPI;
|
||||
using VRage.Input;
|
||||
using VRage.Plugins;
|
||||
using VRage.Utils;
|
||||
using VRageMath;
|
||||
using VRageRender;
|
||||
|
||||
[assembly: IgnoresAccessChecksTo("Sandbox.Game")]
|
||||
[assembly: IgnoresAccessChecksTo("Sandbox.Graphics")]
|
||||
|
||||
namespace SeamlessClientPlugin;
|
||||
|
||||
namespace SeamlessClientPlugin
|
||||
//SendAllMembersDataToClient
|
||||
|
||||
public class SeamlessClient : IPlugin
|
||||
{
|
||||
public const ushort SeamlessClientNetId = 2936;
|
||||
/* First Step. How does a player join a game?
|
||||
* First JoinGameInternal is called with the ServersLobbyID.
|
||||
* In this method, MySessionLoader.UnloadAndExitToMenu() is called. Ultimatley we want to prevent this as we dont want to unload the entire game. Just the basic neccessities.
|
||||
* Then JoinLobby is called. This looks to be simply a check to see if the client gets a result from the server. If it does, it initilizes a new STATIC/Multiplayer base by: [Static = new MyMultiplayerLobbyClient(lobby, new MySyncLayer(new MyTransportLayer(2)))));]
|
||||
* Once this above method is done and join is done, we begin the OnJoin()
|
||||
*
|
||||
* On join begins by checking join result. Success downloads world and failed sends you back to menu. (May need to use this to send players to menu)
|
||||
* Download world Requires the multiplayerbase and MyGUIScreenProgress. Which is essentially checking that the user hasnt cliecked left or closed.
|
||||
*
|
||||
* StringBuilder text = MyTexts.Get(MyCommonTexts.DialogTextJoiningWorld);
|
||||
* MyGuiScreenProgress progress = new MyGuiScreenProgress(text, MyCommonTexts.Cancel);
|
||||
*
|
||||
* This just looks to be like what happens still with the little GUI popupscreen before load starts
|
||||
*
|
||||
* DownloadWorld also contains a method to get the serversessionstate too. We will need to check this before load. Ultimatley once everything has passed join checks Downloadworld is called. (MyMultiplayerClientBase.DownloadWorld)
|
||||
*
|
||||
*
|
||||
* MyMultiplayerClientBase.DownloadWorld simply rasies a static event to the server for world request. [return MyMultiplayerServerBase.WorldRequest;]
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
* MyMultiplayerServerBase.WorldRequest (WorldRequest) This is near the start of where the magic happens. THIS IS ALL RAN SERVERSIDE
|
||||
* Checks to see if the client has been kicked or banned to prevent world requests. Not sure we really need to worry about this.
|
||||
*
|
||||
* Server gets world clears non important data such as player gps. Our player gps gets added on join so we can yeet this.
|
||||
* Also theres a sendfluch via transport layer. Might need to keep this in mind and use this for our testings
|
||||
* Theres a CleanUpData that gets called with world and playerid/identity ID. This is probably to limit things and only send whats neccessary
|
||||
* CLEANUPDATA shows me how to send allplayers data synced on the server.
|
||||
*
|
||||
*
|
||||
* Once we have everythings we use a MS to serialize everything to byte[] and via replication layer we send world to client.
|
||||
*
|
||||
*
|
||||
* BACK TO CLIENT:
|
||||
* RecieveWorld is called and packet is deserialized and then MyJoinGameHelper.WorldReceived(...,...) is called
|
||||
*
|
||||
* WorldReceived does some checks for extra version mismatches and to make sure the CheckPointObjectBuilder isnt null etc.
|
||||
* Once it passes all these checks, CheckDx11AndJoin(world, MyMutliplayerBase) is called
|
||||
*
|
||||
* CheckDx11AndJoin just checks if its a scenario world or not. Forget about this. We can figure that out all later. Then it runs: MySessionLoader.LoadMultiplayerSession(world, multiplayer);
|
||||
*
|
||||
*
|
||||
* MySessionLoader.LoadMultiplayerSession looks to be the start of the join code. It also checks for mod mismatches. (And Downloads them). However once it passes this, MySession.LoadMultiplayer is called.
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
* MySession.LoadMultiplayer (The most important step in world loading)
|
||||
* Creates new MySession.
|
||||
* Does settings stuff.
|
||||
* LoadMembersFromWorld (Loads Clients)
|
||||
* FixSessionComponentObjectBuilders
|
||||
*
|
||||
*
|
||||
*
|
||||
* PrepareBaseSession is something we need. Looks like it does some weird stuff to init fonts, Sector Enviroment settings, Loading datacomponents from world, and re-initilizes modAPI stuff
|
||||
* DeserializeClusters
|
||||
* Loads planets.
|
||||
* RegistersChat
|
||||
*
|
||||
* LOADWORLD -----------
|
||||
* Static.BeforeStartComponents
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
* -plugin "../Plugins/SeamlessClientPlugin.dll"
|
||||
*/
|
||||
|
||||
//SendAllMembersDataToClient
|
||||
|
||||
public class SeamlessClient : IPlugin
|
||||
// pretend to be the latest one
|
||||
public static string Version = "3.0.0.10";
|
||||
public static bool Debug = true;
|
||||
private static bool _initilized;
|
||||
|
||||
public static bool IsSwitching = false;
|
||||
public static bool RanJoin = false;
|
||||
|
||||
|
||||
public void Init(object gameInstance)
|
||||
{
|
||||
/* First Step. How does a player join a game?
|
||||
* First JoinGameInternal is called with the ServersLobbyID.
|
||||
* In this method, MySessionLoader.UnloadAndExitToMenu() is called. Ultimatley we want to prevent this as we dont want to unload the entire game. Just the basic neccessities.
|
||||
* Then JoinLobby is called. This looks to be simply a check to see if the client gets a result from the server. If it does, it initilizes a new STATIC/Multiplayer base by: [Static = new MyMultiplayerLobbyClient(lobby, new MySyncLayer(new MyTransportLayer(2)))));]
|
||||
* Once this above method is done and join is done, we begin the OnJoin()
|
||||
*
|
||||
* On join begins by checking join result. Success downloads world and failed sends you back to menu. (May need to use this to send players to menu)
|
||||
* Download world Requires the multiplayerbase and MyGUIScreenProgress. Which is essentially checking that the user hasnt cliecked left or closed.
|
||||
*
|
||||
* StringBuilder text = MyTexts.Get(MyCommonTexts.DialogTextJoiningWorld);
|
||||
* MyGuiScreenProgress progress = new MyGuiScreenProgress(text, MyCommonTexts.Cancel);
|
||||
*
|
||||
* This just looks to be like what happens still with the little GUI popupscreen before load starts
|
||||
*
|
||||
* DownloadWorld also contains a method to get the serversessionstate too. We will need to check this before load. Ultimatley once everything has passed join checks Downloadworld is called. (MyMultiplayerClientBase.DownloadWorld)
|
||||
*
|
||||
*
|
||||
* MyMultiplayerClientBase.DownloadWorld simply rasies a static event to the server for world request. [return MyMultiplayerServerBase.WorldRequest;]
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
* MyMultiplayerServerBase.WorldRequest (WorldRequest) This is near the start of where the magic happens. THIS IS ALL RAN SERVERSIDE
|
||||
* Checks to see if the client has been kicked or banned to prevent world requests. Not sure we really need to worry about this.
|
||||
*
|
||||
* Server gets world clears non important data such as player gps. Our player gps gets added on join so we can yeet this.
|
||||
* Also theres a sendfluch via transport layer. Might need to keep this in mind and use this for our testings
|
||||
* Theres a CleanUpData that gets called with world and playerid/identity ID. This is probably to limit things and only send whats neccessary
|
||||
* CLEANUPDATA shows me how to send allplayers data synced on the server.
|
||||
*
|
||||
*
|
||||
* Once we have everythings we use a MS to serialize everything to byte[] and via replication layer we send world to client.
|
||||
*
|
||||
*
|
||||
* BACK TO CLIENT:
|
||||
* RecieveWorld is called and packet is deserialized and then MyJoinGameHelper.WorldReceived(...,...) is called
|
||||
*
|
||||
* WorldReceived does some checks for extra version mismatches and to make sure the CheckPointObjectBuilder isnt null etc.
|
||||
* Once it passes all these checks, CheckDx11AndJoin(world, MyMutliplayerBase) is called
|
||||
*
|
||||
* CheckDx11AndJoin just checks if its a scenario world or not. Forget about this. We can figure that out all later. Then it runs: MySessionLoader.LoadMultiplayerSession(world, multiplayer);
|
||||
*
|
||||
*
|
||||
* MySessionLoader.LoadMultiplayerSession looks to be the start of the join code. It also checks for mod mismatches. (And Downloads them). However once it passes this, MySession.LoadMultiplayer is called.
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
* MySession.LoadMultiplayer (The most important step in world loading)
|
||||
* Creates new MySession.
|
||||
* Does settings stuff.
|
||||
* LoadMembersFromWorld (Loads Clients)
|
||||
* FixSessionComponentObjectBuilders
|
||||
*
|
||||
*
|
||||
*
|
||||
* PrepareBaseSession is something we need. Looks like it does some weird stuff to init fonts, Sector Enviroment settings, Loading datacomponents from world, and re-initilizes modAPI stuff
|
||||
* DeserializeClusters
|
||||
* Loads planets.
|
||||
* RegistersChat
|
||||
*
|
||||
* LOADWORLD -----------
|
||||
* Static.BeforeStartComponents
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
* -plugin "../Plugins/SeamlessClientPlugin.dll"
|
||||
*/
|
||||
TryShow($"Running Seamless Client Plugin v[{Version}]");
|
||||
MySession.LoadingStep += LoadingProgressStep;
|
||||
}
|
||||
|
||||
private static void LoadingProgressStep(LoadingProgress step)
|
||||
{
|
||||
// i copied it from the new one no guarantee it works properly
|
||||
if (step >= LoadingProgress.PROGRESS_STEP8)
|
||||
SendFirstJoin();
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static string Version = "1.4.01";
|
||||
public static bool Debug = true;
|
||||
private static bool Initilized = false;
|
||||
public void Update()
|
||||
{
|
||||
if (MyAPIGateway.Multiplayer == null)
|
||||
return;
|
||||
|
||||
|
||||
|
||||
public const ushort SeamlessClientNetID = 2936;
|
||||
|
||||
public static bool IsSwitching = false;
|
||||
public static bool RanJoin = false;
|
||||
|
||||
|
||||
|
||||
public void Init(object gameInstance)
|
||||
if (!_initilized)
|
||||
{
|
||||
|
||||
TryShow("Running Seamless Client Plugin v[" + Version + "]");
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
public void Update()
|
||||
{
|
||||
if (MyAPIGateway.Multiplayer == null)
|
||||
return;
|
||||
|
||||
|
||||
if (!Initilized)
|
||||
{
|
||||
Patches.GetPatches();
|
||||
OnlinePlayers.Patch();
|
||||
TryShow("Initilizing Communications!");
|
||||
RunInitilizations();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static void RunInitilizations()
|
||||
{
|
||||
|
||||
|
||||
MyAPIGateway.Multiplayer.RegisterSecureMessageHandler(SeamlessClientNetID, MessageHandler);
|
||||
Initilized = true;
|
||||
}
|
||||
|
||||
public static void DisposeInitilizations()
|
||||
{
|
||||
MyAPIGateway.Multiplayer?.UnregisterSecureMessageHandler(SeamlessClientNetID, MessageHandler);
|
||||
Initilized = false;
|
||||
|
||||
}
|
||||
|
||||
|
||||
private static void MessageHandler(ushort obj1, byte[] obj2, ulong obj3, bool obj4)
|
||||
{
|
||||
try
|
||||
{
|
||||
ClientMessage Recieved = Utilities.Utility.Deserialize<ClientMessage>(obj2);
|
||||
|
||||
if(Recieved.MessageType == ClientMessageType.FirstJoin)
|
||||
{
|
||||
//Server sent a first join message! Send a reply back so the server knows what version we are on
|
||||
ClientMessage PingServer = new ClientMessage(ClientMessageType.FirstJoin);
|
||||
MyAPIGateway.Multiplayer?.SendMessageToServer(SeamlessClientNetID, Utilities.Utility.Serialize(PingServer));
|
||||
}
|
||||
else if (Recieved.MessageType == ClientMessageType.TransferServer)
|
||||
{
|
||||
//Server sent a transfer message! Begin transfer via seamless
|
||||
Transfer TransferMessage = Recieved.GetTransferData();
|
||||
ServerPing.StartServerPing(TransferMessage);
|
||||
}else if(Recieved.MessageType == ClientMessageType.OnlinePlayers)
|
||||
{
|
||||
var p = Recieved.GetOnlinePlayers();
|
||||
OnlinePlayers.AllServers = p.OnlineServers;
|
||||
OnlinePlayers.currentServer = p.currentServerID;
|
||||
|
||||
//TryShow("Recieved Players! "+OnlinePlayers.AllServers.Count);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
TryShow(ex.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static void TryShow(string message)
|
||||
{
|
||||
if (MySession.Static?.LocalHumanPlayer != null && Debug)
|
||||
MyAPIGateway.Utilities?.ShowMessage("NetworkClient", message);
|
||||
|
||||
MyLog.Default?.WriteLineAndConsole($"SeamlessClient: {message}");
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
DisposeInitilizations();
|
||||
Patches.GetPatches();
|
||||
OnlinePlayers.Patch();
|
||||
TryShow("Initilizing Communications!");
|
||||
RunInitilizations();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
DisposeInitilizations();
|
||||
}
|
||||
|
||||
|
||||
public static void RunInitilizations()
|
||||
{
|
||||
MyAPIGateway.Multiplayer.RegisterSecureMessageHandler(SeamlessClientNetId, MessageHandler);
|
||||
_initilized = true;
|
||||
}
|
||||
|
||||
public static void DisposeInitilizations()
|
||||
{
|
||||
MyAPIGateway.Multiplayer?.UnregisterSecureMessageHandler(SeamlessClientNetId, MessageHandler);
|
||||
_initilized = false;
|
||||
}
|
||||
|
||||
|
||||
private static void MessageHandler(ushort obj1, byte[] obj2, ulong obj3, bool obj4)
|
||||
{
|
||||
try
|
||||
{
|
||||
var recieved = Utility.Deserialize<ClientMessage>(obj2);
|
||||
|
||||
switch (recieved.MessageType)
|
||||
{
|
||||
// was removed in newer versions, but we leave it here for backwards compatability
|
||||
case ClientMessageType.FirstJoin:
|
||||
{
|
||||
SendFirstJoin();
|
||||
break;
|
||||
}
|
||||
case ClientMessageType.TransferServer:
|
||||
{
|
||||
//Server sent a transfer message! Begin transfer via seamless
|
||||
var transferMessage = recieved.GetTransferData();
|
||||
ServerPing.StartServerPing(transferMessage);
|
||||
break;
|
||||
}
|
||||
case ClientMessageType.OnlinePlayers:
|
||||
{
|
||||
var p = recieved.GetOnlinePlayers();
|
||||
OnlinePlayers.AllServers = p.OnlineServers;
|
||||
OnlinePlayers.CurrentServer = p.CurrentServerId;
|
||||
|
||||
//TryShow("Recieved Players! "+OnlinePlayers.AllServers.Count);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
TryShow(ex.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
private static void SendFirstJoin()
|
||||
{
|
||||
var pingServer = new ClientMessage(ClientMessageType.FirstJoin);
|
||||
MyAPIGateway.Multiplayer?.SendMessageToServer(SeamlessClientNetId, Utility.Serialize(pingServer));
|
||||
}
|
||||
|
||||
|
||||
public static void TryShow(string message)
|
||||
{
|
||||
NotificationsComponent.SpawnNotification(5f, message);
|
||||
MyLog.Default?.WriteLineAndConsole($"SeamlessClient: {message}");
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user