From d37ad9c619ac9d0332c911bf284b080b5e9fae48 Mon Sep 17 00:00:00 2001 From: DragonFire47 <46509577+DragonFire47@users.noreply.github.com> Date: Fri, 19 Aug 2022 16:27:00 -0700 Subject: [PATCH 01/12] -Changed Patch location for sending Ping --- PulsarModLoader/MPModChecks.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/PulsarModLoader/MPModChecks.cs b/PulsarModLoader/MPModChecks.cs index 167eda2..43aa541 100644 --- a/PulsarModLoader/MPModChecks.cs +++ b/PulsarModLoader/MPModChecks.cs @@ -106,15 +106,15 @@ static bool Prefix(ref RoomInfo room) return true; } } - [HarmonyPatch(typeof(PLServer), "OnPhotonPlayerConnected")] + [HarmonyPatch(typeof(PLServer), "AttemptGetVerified")] class PrefixServerOnClientJoin { - static void Prefix(PhotonPlayer connected) + static void Prefix(PhotonMessageInfo pmi) { if (PhotonNetwork.isMasterClient) { Logger.Info("Sending Ping (asking for mod list/Pong)"); - ModMessageHelper.Instance.photonView.RPC("SendConnectionMessage", connected, new object[0]); + ModMessageHelper.Instance.photonView.RPC("SendConnectionMessage", pmi.sender, new object[0]); } } } From c335397f2d1d5f611442abcd4119758d156d3f9c Mon Sep 17 00:00:00 2001 From: DragonFire47 <46509577+DragonFire47@users.noreply.github.com> Date: Sun, 21 Aug 2022 13:49:09 -0700 Subject: [PATCH 02/12] -Moved MPModCheck files to new Location --- PulsarModLoader/MPFunction.cs | 22 --------- PulsarModLoader/MPModChecks/MPFunction.cs | 47 +++++++++++++++++++ .../{ => MPModChecks}/MPModChecks.cs | 4 +- PulsarModLoader/PulsarModLoader.csproj | 4 +- 4 files changed, 51 insertions(+), 26 deletions(-) delete mode 100644 PulsarModLoader/MPFunction.cs create mode 100644 PulsarModLoader/MPModChecks/MPFunction.cs rename PulsarModLoader/{ => MPModChecks}/MPModChecks.cs (98%) diff --git a/PulsarModLoader/MPFunction.cs b/PulsarModLoader/MPFunction.cs deleted file mode 100644 index d3c50ea..0000000 --- a/PulsarModLoader/MPFunction.cs +++ /dev/null @@ -1,22 +0,0 @@ -namespace PulsarModLoader -{ - public enum MPFunction - { - /// - /// No MP Requirements - /// - None, //0 No mp requirements - /// - /// Only the host is required to have it installed - /// - HostOnly, //1 Only the host is required to have it installed - /// - /// Host must have installed for clients to use - /// - HostRequired, //2 Host must have installed for clients to use - /// - /// All clients must have installed - /// - All //3 All clients must have installed - } -} diff --git a/PulsarModLoader/MPModChecks/MPFunction.cs b/PulsarModLoader/MPModChecks/MPFunction.cs new file mode 100644 index 0000000..7916887 --- /dev/null +++ b/PulsarModLoader/MPModChecks/MPFunction.cs @@ -0,0 +1,47 @@ +using System; + +namespace PulsarModLoader +{ + [Obsolete] + public enum MPFunction + { + /// + /// No MP Requirements + /// + None, //0 No mp requirements + /// + /// Only the host is required to have it installed + /// + HostOnly, //1 Only the host is required to have it installed + /// + /// Host must have installed for clients to use + /// + HostRequired, //2 Host must have installed for clients to use + /// + /// All clients must have installed + /// + All //3 All clients must have installed + } +} +namespace PulsarModLoader.MPModChecks +{ + public enum MPFunction + { + /// + /// No MP Requirements + /// + None, //0 No mp requirements + /// + /// Only the host is required to have it installed + /// + HostOnly, //1 Only the host is required to have it installed + /// + /// Host must have installed for clients to use + /// + HostRequired, //2 Host must have installed for clients to use + /// + /// All clients must have installed + /// + All //3 All clients must have installed + } +} diff --git a/PulsarModLoader/MPModChecks.cs b/PulsarModLoader/MPModChecks/MPModChecks.cs similarity index 98% rename from PulsarModLoader/MPModChecks.cs rename to PulsarModLoader/MPModChecks/MPModChecks.cs index 43aa541..b7560ce 100644 --- a/PulsarModLoader/MPModChecks.cs +++ b/PulsarModLoader/MPModChecks/MPModChecks.cs @@ -3,7 +3,7 @@ using Steamworks; using System.Collections.Generic; -namespace PulsarModLoader +namespace PulsarModLoader.MPModChecks { class MPModChecks { @@ -187,7 +187,7 @@ static bool Prefix(ref PhotonMessageInfo pmi) } } - Logger.Info("Modcheck passed, proceding ondwards"); + Logger.Info("Modcheck passed, proceding onwards"); } else //client wasn't found in mod list { diff --git a/PulsarModLoader/PulsarModLoader.csproj b/PulsarModLoader/PulsarModLoader.csproj index 55c4956..86a0459 100644 --- a/PulsarModLoader/PulsarModLoader.csproj +++ b/PulsarModLoader/PulsarModLoader.csproj @@ -192,8 +192,8 @@ - - + + From f1f91178ffc1cef2de4c367cca6e3c1f1feaae6e Mon Sep 17 00:00:00 2001 From: DragonFire47 <46509577+DragonFire47@users.noreply.github.com> Date: Thu, 1 Sep 2022 16:14:53 -0700 Subject: [PATCH 03/12] -Moved chat extensions patch to PLGlobalStart -Marked old Mod Check variables as obsolete -Moved MPFunction enum location -Renamed MPFunction.HostOnly to HideFromServerList -Rebuilt ModChecks -Added Hashing --- .../Chat/Extensions/HarmonyServerStart.cs | 14 - PulsarModLoader/MPModChecks/MPFunction.cs | 12 +- .../MPModChecks/MPModCheckManager.cs | 460 ++++++++++++++++++ PulsarModLoader/MPModChecks/MPModChecks.cs | 211 -------- PulsarModLoader/MPModChecks/MPModDataBlock.cs | 32 ++ .../MPModChecks/MPUserDataBlock.cs | 26 + .../ModMessage/ModMessageHelper.cs | 50 +- PulsarModLoader/Patches/GameVersion.cs | 5 +- PulsarModLoader/Patches/PLGlobalStart.cs | 4 + PulsarModLoader/Patches/PLServerStart.cs | 21 + PulsarModLoader/Patches/PhotonProperties.cs | 3 +- PulsarModLoader/PulsarMod.cs | 7 +- PulsarModLoader/PulsarModLoader.csproj | 6 +- 13 files changed, 578 insertions(+), 273 deletions(-) delete mode 100644 PulsarModLoader/Chat/Extensions/HarmonyServerStart.cs create mode 100644 PulsarModLoader/MPModChecks/MPModCheckManager.cs delete mode 100644 PulsarModLoader/MPModChecks/MPModChecks.cs create mode 100644 PulsarModLoader/MPModChecks/MPModDataBlock.cs create mode 100644 PulsarModLoader/MPModChecks/MPUserDataBlock.cs create mode 100644 PulsarModLoader/Patches/PLServerStart.cs diff --git a/PulsarModLoader/Chat/Extensions/HarmonyServerStart.cs b/PulsarModLoader/Chat/Extensions/HarmonyServerStart.cs deleted file mode 100644 index 504d528..0000000 --- a/PulsarModLoader/Chat/Extensions/HarmonyServerStart.cs +++ /dev/null @@ -1,14 +0,0 @@ -using HarmonyLib; - -namespace PulsarModLoader.Chat.Extensions -{ - [HarmonyPatch(typeof(PLServer), "Start")] - class HarmonyServerStart - { - static void Postfix() - { - ChatHelper.publicCached = false; - HandlePublicCommands.RequestPublicCommands(); - } - } -} diff --git a/PulsarModLoader/MPModChecks/MPFunction.cs b/PulsarModLoader/MPModChecks/MPFunction.cs index 7916887..702d096 100644 --- a/PulsarModLoader/MPModChecks/MPFunction.cs +++ b/PulsarModLoader/MPModChecks/MPFunction.cs @@ -30,18 +30,18 @@ public enum MPFunction /// /// No MP Requirements /// - None, //0 No mp requirements + None, //0 No mp requirements/Clientside or Hostside /// - /// Only the host is required to have it installed + /// No MP Requirements, is hidden from server listings. /// - HostOnly, //1 Only the host is required to have it installed + HideFromServerList, //1 Hidden from server listings /// - /// Host must have installed for clients to use + /// Host must have installed for clients to join /// - HostRequired, //2 Host must have installed for clients to use + HostRequired, //2 Host must have installed for clients to join /// /// All clients must have installed /// - All //3 All clients must have installed + All //3 All clients must have installed } } diff --git a/PulsarModLoader/MPModChecks/MPModCheckManager.cs b/PulsarModLoader/MPModChecks/MPModCheckManager.cs new file mode 100644 index 0000000..6649ced --- /dev/null +++ b/PulsarModLoader/MPModChecks/MPModCheckManager.cs @@ -0,0 +1,460 @@ +using ExitGames.Client.Photon; +using HarmonyLib; +using PulsarModLoader.Utilities; +using Steamworks; +using System; +using System.Collections; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Security.Cryptography; +using UnityEngine; +using Hashtable = ExitGames.Client.Photon.Hashtable; +using Logger = PulsarModLoader.Utilities.Logger; + +namespace PulsarModLoader.MPModChecks +{ + public class MPModCheckManager + { + public MPModCheckManager() + { + Instance = this; + RefreshData(); + } + + public void RefreshData() + { + UpdateMyModList(); + UpdateLobbyModList(); + } + + private void UpdateLobbyModList() //Update Photon Lobby Listing with mod list + { + if (PhotonNetwork.isMasterClient && PhotonNetwork.inRoom) + { + Room room = PhotonNetwork.room; + Hashtable customProperties = room.CustomProperties; + customProperties["modList"] = GetModListForLobbyListing(); + room.SetCustomProperties(customProperties); + } + } + + public static MPModCheckManager Instance = null; + + private MPModDataBlock[] MyModList = null; + + private Dictionary NetworkedPeersModLists = new Dictionary(); + + private bool ServerHasMPMods = false; + + public MPModDataBlock[] getNetworkedPeerMods(PhotonPlayer Photonplayer) + { + return NetworkedPeersModLists[Photonplayer]; + } + + public void AddNetworkedPeerMods(PhotonPlayer Photonplayer, MPModDataBlock[] modList) + { + if (NetworkedPeersModLists.ContainsKey(Photonplayer)) + { + NetworkedPeersModLists[Photonplayer] = modList; + return; + } + NetworkedPeersModLists.Add(Photonplayer, modList); + } + + public void RemoveNetworkedPeerMods(PhotonPlayer Photonplayer) + { + NetworkedPeersModLists.Remove(Photonplayer); + } + + private List GetMPModList() + { + List modList = new List(); + foreach (PulsarMod mod in ModManager.Instance.GetAllMods()) + { + if (mod.MPFunctionality != (int)MPFunction.HideFromServerList) + { + if (mod.MPFunctionality > (int)MPFunction.HostRequired) + { + ServerHasMPMods = true; + } + modList.Add(mod); + } + } + return modList; + } + + private void UpdateMyModList() + { + Logger.Info("Building MyModList"); + Stopwatch stopwatch = new Stopwatch(); + stopwatch.Start(); + List UnprocessedMods = GetMPModList(); + MPModDataBlock[] ProcessedMods = new MPModDataBlock[UnprocessedMods.Count]; + using (SHA256 MyHasher = SHA256.Create()) + { + for (int i = 0; i < UnprocessedMods.Count; i++) + { + PulsarMod currentMod = UnprocessedMods[i]; + using (FileStream MyStream = File.OpenRead(currentMod.GetType().Assembly.Location)) + { + MyStream.Position = 0; + byte[] Hash = MyHasher.ComputeHash(MyStream); + ProcessedMods[i] = new MPModDataBlock(currentMod.HarmonyIdentifier(), currentMod.Name, currentMod.Version, (MPFunction)currentMod.MPFunctionality, currentMod.ModID, Hash); + } + } + } + MyModList = ProcessedMods; + stopwatch.Stop(); + Logger.Info("Finished Building MyModList, time elapsted: " + stopwatch.ElapsedMilliseconds.ToString()); + } + + private MemoryStream GetModListForLobbyListing() + { + MemoryStream dataStream = new MemoryStream(); + using (BinaryWriter writer = new BinaryWriter(dataStream)) + { + //Datastream storage structure: + writer.Write(Patches.GameVersion.PMLVersion); //--Header-- + writer.Write(MyModList.Length); //string PMLVersion + for (int i = 0; i < MyModList.Length; i++) //int modcount + { // + MPModDataBlock dataBlock = MyModList[i]; //--ModData-- + writer.Write(dataBlock.ModName); //string mod name + writer.Write(dataBlock.HarmonyIdentifier); //string harmony ident + writer.Write(dataBlock.Version); //string mod version + writer.Write((byte)dataBlock.MPFunction); //byte MPFunction + writer.Write(dataBlock.ModID); //string ModID + } + } + return dataStream; + } + + public MPUserDataBlock GetModListFromLobbyListingData(MemoryStream memoryStream) + { + memoryStream.Position = 0; + MPUserDataBlock UserData = null; + using (BinaryReader reader = new BinaryReader(memoryStream)) + { + try + { + string PMLVersion = reader.ReadString(); + int ModCount = reader.ReadInt32(); + MPModDataBlock[] ModList = new MPModDataBlock[ModCount]; + for (int i = 0; i < ModCount; i++) + { + string modname = reader.ReadString(); + string HarmonyIdent = reader.ReadString(); + string ModVersion = reader.ReadString(); + MPFunction MPFunction = (MPFunction)reader.ReadByte(); + string ModID = reader.ReadString(); + ModList[i] = new MPModDataBlock(HarmonyIdent, modname, ModVersion, MPFunction, ModID); + } + UserData = new MPUserDataBlock(PMLVersion, ModList); + } + catch (Exception ex) + { + Logger.Info($"Failed to read mod list from lobby listing data.\n{ex.Message}"); + } + } + Logger.Info("Failed to read mod list from lobby listing data, returning null."); + return UserData; + } + + public static string GetModListAsString(MPModDataBlock[] ModDatas) + { + string ModList = string.Empty; + foreach (MPModDataBlock DataBlock in ModDatas) + { + ModList += $"\n{DataBlock.ModName}"; + } + return ModList; + } + + private MPUserDataBlock GetHostModList(RoomInfo room) + { + if (room.CustomProperties.ContainsKey("modList")) + { + return GetModListFromLobbyListingData((MemoryStream)room.CustomProperties["modList"]); + } + return new MPUserDataBlock(); + } + + public void KickClient(PhotonPlayer client) + { + if (SteamManager.Initialized && client.SteamID != CSteamID.Nil) + { + SteamUser.EndAuthSession(client.SteamID); + } + PhotonNetwork.CloseConnection(client); + } + + /// + /// overall basic description: checks if it is possible to join room based on mods installed locally and on the server + /// + /// + /// + public bool ClientClickJoinRoom(RoomInfo room) + { + MPUserDataBlock HostModData = GetHostModList(room); + MPModDataBlock[] HostModList = HostModData.ModData; + + string HostModListString = GetModListAsString(HostModList); + string LocalModListString = GetModListAsString(MyModList); + Logger.Info($"Joining room: {room.Name} ServerPMLVersion: {HostModData.PMLVersion}\n--Hostmodlist: {HostModListString}\n--Localmodlist: {LocalModListString}"); + + string missingMods = string.Empty; + string localMPLimitedMods = string.Empty; + string outdatedMods = string.Empty; + int MyModListLength = MyModList.Length; + int HostModListLength = HostModList.Length; + for (int a = 0; a < MyModListLength; a++) + { + bool found = false; + int b = 0; + for (; b < HostModListLength; b++) + { + if (HostModList[b].HarmonyIdentifier == MyModList[a].HarmonyIdentifier) + { + found = true; + break; + } + } + if (!found) + { //didn't find mod in host list, checking if mod function mandates host installation + if (MyModList[a].MPFunction >= MPFunction.HostRequired) + { + localMPLimitedMods += $"\n{MyModList[a].ModName}"; + } + } + else + { //found mod in host list, checking if mod versions match. + if (MyModList[a].Version != HostModList[b].Version) + { + outdatedMods += $"\nLocal: {MyModList[a].ModName} {MyModList[a].Version} Host: {HostModList[b].ModName} {HostModList[b].Version}"; + } + } + } + for (int a = 0; a < HostModListLength; a++) + { + bool found = false; + for (int b = 0; b < MyModListLength; b++) + { + if (HostModList[a].HarmonyIdentifier == MyModList[b].HarmonyIdentifier) + { + found = true; + break; + } + } + if (!found) + { + if (HostModList[a].MPFunction == MPFunction.All) + { //Host MP mod not found locally + missingMods += $"\n{HostModList[a].ModName}"; + } + } + } + string message = string.Empty; + if (missingMods != string.Empty) + { + message += $"\nYOU ARE MISSING THE FOLLOWING REQUIRED MODS{missingMods}"; + } + if (localMPLimitedMods != string.Empty) + { + message += $"\nYOU CANNOT JOIN WITH THE FOLLOWING MODS INSTALLED{localMPLimitedMods}"; + } + if (outdatedMods != string.Empty) + { + message += $"\nTHE FOLLOWING MOD VERSIONS DO NOT MATCH{outdatedMods}"; + } + if (message != string.Empty) + { + PLNetworkManager.Instance.MainMenu.AddActiveMenu(new PLErrorMessageMenu($"Failed to join crew!{message}")); + + Logger.Info("Local mod list is not equal to Server mod list"); + return false; + } + else + { + Logger.Info("Modcheck passed, proceding ondwards"); + return true; + } + } + + public void HostOnClientJoined(PhotonPlayer Player) + { + MPModDataBlock[] ClientMods = null; + bool foundplayer = false; + if (NetworkedPeersModLists.ContainsKey(Player)) //checks if server has received mod list from client. + { + ClientMods = NetworkedPeersModLists[Player]; + foundplayer = true; + } + Logger.Info("HostOnClientJoined checking for player mods, returned " + foundplayer.ToString()); + + + //Checks mod list + if (foundplayer) //If server received mod list from client + { + string missingMods = string.Empty; + string clientMPLimitedMods = string.Empty; + string outdatedMods = string.Empty; + string incorrectHashMods = string.Empty; + Logger.Info($"Starting Serverside Mod check"); + Logger.Info($"Checking if client is missing required mods"); + + int localLength = MyModList.Length; + int clientLength = ClientMods.Length; + + //Check mods installed locally against client + for (int a = 0; a < localLength; a++) + { + bool found = false; + int b = 0; + for (; b < clientLength; b++) + { + if (MyModList[a].HarmonyIdentifier == ClientMods[b].HarmonyIdentifier) + { + found = true; + break; + } + } + + if (found) + { + if (MyModList[a].MPFunction >= MPFunction.HostRequired) //limit these types of kicking to MPLimited mods. + { + if (MyModList[a].Version != ClientMods[b].Version) //if mod versions don't match, add as kick reason + { + outdatedMods += $"\nLocal: {MyModList[a].ModName} {MyModList[a].Version} Client: {ClientMods[b].ModName} {ClientMods[b].Version}"; + } + else if (MyModList[a].Hash != ClientMods[b].Hash) //if mod versions match but hash doesn't, add as kick reason + { + incorrectHashMods += $"\n{ClientMods[b].ModName}"; + missingMods += $"\n{ClientMods[b].ModName}"; + Logger.Info("Client has bad hash for " + MyModList[a].ModName); + } + } + } + else + { + if (MyModList[a].MPFunction == MPFunction.All) //if client needs mod installed + { + missingMods += $"\n{MyModList[a].ModName}"; + } + } + } + + //Check mods installed on client against local + for (int b = 0; b < clientLength; b++) + { + bool found = false; + for(int a = 0; a < localLength; a++) + { + if (MyModList[a].HarmonyIdentifier == ClientMods[b].HarmonyIdentifier) + { + found = true; + break; + } + } + if(!found) //if client mod not installed locally requires host to have installed. + { + if(ClientMods[b].MPFunction >= MPFunction.HostRequired) + { + clientMPLimitedMods += $"\n{ClientMods[b].ModName}"; + } + } + } + + string message = string.Empty; + if (missingMods != string.Empty) + { + message += $"\nYOU ARE MISSING THE FOLLOWING REQUIRED MODS{missingMods}"; + } + if (clientMPLimitedMods != string.Empty) + { + message += $"\nYOU CANNOT JOIN WITH THE FOLLOWING MODS INSTALLED{clientMPLimitedMods}"; + } + if (outdatedMods != string.Empty) + { + message += $"\nTHE FOLLOWING MOD VERSIONS DO NOT MATCH{outdatedMods}"; + } + if (message != string.Empty) + { + PLNetworkManager.Instance.MainMenu.AddActiveMenu(new PLErrorMessageMenu($"Failed to join crew!{message}")); + + Logger.Info("Local mod list is not equal to Server mod list"); + } + else + { + Logger.Info("Modcheck passed, proceding onwards"); + } + } + else //client wasn't found in mod list + { + if (ServerHasMPMods) + { + Utilities.Logger.Info("Didn't receive message or proper modlist. proceeding to kick PhotonPlayer"); + string message = $"You have been disconnected for not having the mod loader installed"; + ModMessageHelper.Instance.photonView.RPC("RecieveErrorMessage", Player, new object[] { message }); + KickClient(Player); + } + Utilities.Logger.Info("Didn't receive message or proper modlist, but the server doesn't have multiplayer explicit mods. Proceeding onwards"); + } + } + + public IEnumerator ServerVerifyClient(PhotonPlayer player) + { + int loops = 0; + WaitForSeconds cachedWaitTime = new WaitForSeconds(0.25f); + while (loops < 40) + { + loops++; + if (NetworkedPeersModLists.ContainsKey(player)) + { + break; + } + yield return cachedWaitTime; + } + HostOnClientJoined(player); + } + + [HarmonyPatch(typeof(PLUIPlayMenu), "ActuallyJoinRoom")] //allow/disallow local client to join server. + class JoinRoomPatch + { + static bool Prefix(RoomInfo room) + { + return Instance.ClientClickJoinRoom(room); + } + } + + [HarmonyPatch(typeof(PLServer), "ServerOnClientVerified")] //Starts host mod verification coroutine + class ServerOnClientVerifiedPatch + { + static void Postfix(PhotonPlayer client) + { + PLServer.Instance.StartCoroutine(Instance.ServerVerifyClient(client)); + } + } + + [HarmonyPatch(typeof(PLServer), "VerifyClient")] //Client sends mod info as early as possible during connection, + class ClientJoinPatch + { + static void Postfix(PhotonPlayer player, PhotonMessageInfo pmi) + { + if (pmi.sender != null && pmi.sender.IsMasterClient && player != null) + { + if (player == PhotonNetwork.player) + { + ModMessageHelper.Instance.photonView.RPC("ReceiveConnectionMessage", pmi.sender, new object[] + { + MPModCheckManager.Instance.MyModList, + Patches.GameVersion.PMLVersion + }); + } + player.Verified = true; + } + } + } + } +} diff --git a/PulsarModLoader/MPModChecks/MPModChecks.cs b/PulsarModLoader/MPModChecks/MPModChecks.cs deleted file mode 100644 index b7560ce..0000000 --- a/PulsarModLoader/MPModChecks/MPModChecks.cs +++ /dev/null @@ -1,211 +0,0 @@ -using HarmonyLib; -using PulsarModLoader.Utilities; -using Steamworks; -using System.Collections.Generic; - -namespace PulsarModLoader.MPModChecks -{ - class MPModChecks - { - public static string ConvertModlist(List Missinglist) - { - string Missing = string.Empty; - for (int i = 0; i < Missinglist.Count; i++) - { - if (i < Missinglist.Count - 1) - { - Missing += $"{Missinglist[i]},\n"; - } - else - { - Missing += Missinglist[i]; - } - } - return Missing; - } - public static string GetMPModList() - { - string modlist = string.Empty; - foreach (PulsarMod mod in ModManager.Instance.GetAllMods()) - { - if (mod.MPFunctionality == (int)MPFunction.All || mod.MPFunctionality == (int)MPFunction.HostRequired) - { - modlist += $"{mod.Name} {mod.Version} MPF{mod.MPFunctionality}\n"; - } - } - return modlist; - } - public static string GetModList() - { - string modlist = string.Empty; - foreach (PulsarMod mod in ModManager.Instance.GetAllMods()) - { - modlist += $"{mod.Name} {mod.Version} MPF{mod.MPFunctionality}\n"; - } - return modlist; - } - public static string GetHostModList(RoomInfo room) - { - if (room.CustomProperties.ContainsKey("modList")) - { - return room.CustomProperties["modList"].ToString(); - } - return string.Empty; - } - } - [HarmonyPatch(typeof(PLUIPlayMenu), "ActuallyJoinRoom")] - class JoinRoomPatch - { - static bool Prefix(ref RoomInfo room) - { - //overall basic description: checks if it is possible to join room based on mods installed locally and on the server - string LocalMods = MPModChecks.GetMPModList(); - string MPMods = MPModChecks.GetHostModList(room); - Logger.Info($"Joining room: {room.Name} MPmodlist: {room.CustomProperties["modList"]} Localmodlist: {LocalMods}"); - if (!string.IsNullOrEmpty(LocalMods)) - { - Logger.Info("Modlist != NullOrEmpty"); - if (MPMods != LocalMods) - { - List missingmods = new List(); - string[] localmodlist = LocalMods.Split('\n'); - foreach (string mod in localmodlist) - { - //Logger.Info("Checking client mod " + mod); - if (!string.IsNullOrEmpty(mod) && !MPMods.Contains(mod)) - { - missingmods.Add(mod); - } - } - string[] MPmodlist = MPMods.Split('\n'); - if (missingmods.Count > 0) - { - Logger.Info("Client mods good, checking server mods"); - foreach (string mod in MPmodlist) - { - //Logger.Info("Checking Server mod " + mod); - if (!string.IsNullOrEmpty(mod) && !LocalMods.Contains(mod) && mod.Contains("MPF3")) - { - missingmods.Add(mod); - } - } - if (missingmods.Count > 0) - { - Logger.Info("Server mod list is not equal to local mod list"); - PLNetworkManager.Instance.MainMenu.AddActiveMenu(new PLErrorMessageMenu($"Failed to join crew! The Server is missing the following mods or is not up to date (try uninstalling/updating):\n{MPModChecks.ConvertModlist(missingmods)}")); - return false; - } - } - PLNetworkManager.Instance.MainMenu.AddActiveMenu(new PLErrorMessageMenu($"Failed to join crew! You are missing the following mods or the mods are not up to date:\n{MPModChecks.ConvertModlist(missingmods)}")); - - Logger.Info("Local mod list is not equal to Server mod list"); - return false; - } - } - Logger.Info("Modcheck passed, proceding ondwards"); - return true; - } - } - [HarmonyPatch(typeof(PLServer), "AttemptGetVerified")] - class PrefixServerOnClientJoin - { - static void Prefix(PhotonMessageInfo pmi) - { - if (PhotonNetwork.isMasterClient) - { - Logger.Info("Sending Ping (asking for mod list/Pong)"); - ModMessageHelper.Instance.photonView.RPC("SendConnectionMessage", pmi.sender, new object[0]); - } - } - } - - [HarmonyPatch(typeof(PLServer), "AttemptGetVerified")] - class VerifyModlistBeforeConnection - { - static bool Prefix(ref PhotonMessageInfo pmi) - { - //Utilities.Logger.Info("About to check if containskey. isMasterClient: " + PhotonNetwork.isMasterClient.ToString()); - bool foundplayer = false; - if (ModMessageHelper.Instance.GetPlayerMods(pmi.sender) != "NoPlayer") - { //checks if server has received mod list from client. request for mod list is sent in the class 'PrefixServerOnClientJoin' - foundplayer = true; - } - Utilities.Logger.Info("tried finding player, returned " + foundplayer.ToString()); - //Checks mod list - if (foundplayer) //If server received mod list from client - { - List missingmods = new List(); - string LocalMods = MPModChecks.GetMPModList(); - string clientmods = ModMessageHelper.Instance.GetPlayerMods(pmi.sender); - Logger.Info($"Starting Serverside Mod check"); - if (clientmods != LocalMods) //if the client's modlist isn't equal to the local mod list - { - Logger.Info($"Checking if client is missing required mods"); - string[] localmodlist = LocalMods.Split('\n'); - foreach (string mod in localmodlist) //check local multiplayer mods to see if the client has required mods - { - if (!string.IsNullOrWhiteSpace(mod) && !clientmods.Contains(mod) && mod.Contains("MPF3")) - { - missingmods.Add(mod); - } - } - if (missingmods.Count == 0) //if nothing was added to the missing mod list check if the client needs something the server doesn't. - { - Logger.Info($"Client isn't missing mods, checking if client has mods that require server installation"); - string[] clientmodlist = clientmods.Split('\n'); - foreach (string mod in clientmodlist) - { - if (!string.IsNullOrWhiteSpace(mod) && !LocalMods.Contains(mod) && (mod.Contains("MPF2") || mod.Contains("MPF3"))) - { - missingmods.Add(mod); - } - } - if (missingmods.Count > 0) //Client has non-server mods - { - Logger.Info("Client has non-server multiplayer mods"); - string message = $"You have been disconnected for having the following mods (try removing them):\n{MPModChecks.ConvertModlist(missingmods)}"; - ModMessageHelper.Instance.photonView.RPC("RecieveErrorMessage", pmi.sender, new object[] { message }); - if (SteamManager.Initialized && pmi.sender.SteamID != CSteamID.Nil) - { - SteamUser.EndAuthSession(pmi.sender.SteamID); - } - PhotonNetwork.CloseConnection(pmi.sender); - return false; - } - } - else //client is missing server mods - { - Logger.Info("client is missing server mods"); - string message = $"You have been disconnected for not having the following mods (try installing them):\n{MPModChecks.ConvertModlist(missingmods)}"; - ModMessageHelper.Instance.photonView.RPC("RecieveErrorMessage", pmi.sender, new object[] { message }); - if (SteamManager.Initialized && pmi.sender.SteamID != CSteamID.Nil) - { - SteamUser.EndAuthSession(pmi.sender.SteamID); - } - PhotonNetwork.CloseConnection(pmi.sender); - return false; - } - - } - Logger.Info("Modcheck passed, proceding onwards"); - } - else //client wasn't found in mod list - { - if (ModMessageHelper.ServerHasMPMods) //small vulnerability: if a client with mods disables the pong message, they can still connect with their multiplayer mods - { - Utilities.Logger.Info("Didn't receive message or proper modlist. proceeding to kick PhotonPlayer"); - string message = $"You have been disconnected for not having the mod loader installed"; - ModMessageHelper.Instance.photonView.RPC("RecieveErrorMessage", pmi.sender, new object[] { message }); - if (SteamManager.Initialized && pmi.sender.SteamID != CSteamID.Nil) - { - SteamUser.EndAuthSession(pmi.sender.SteamID); - } - PhotonNetwork.CloseConnection(pmi.sender); - return false; - } - Utilities.Logger.Info("Didn't receive message or proper modlist, but the server doesn't have multiplayer explicit mods. Proceeding onwards"); - } - return true; - } - } -} diff --git a/PulsarModLoader/MPModChecks/MPModDataBlock.cs b/PulsarModLoader/MPModChecks/MPModDataBlock.cs new file mode 100644 index 0000000..fc0e373 --- /dev/null +++ b/PulsarModLoader/MPModChecks/MPModDataBlock.cs @@ -0,0 +1,32 @@ +namespace PulsarModLoader.MPModChecks +{ + public class MPModDataBlock + { + public MPModDataBlock(string HarmonyIdentifier, string ModName, string Version, MPFunction MPFunction, string ModID, byte[] Hash) + { + this.HarmonyIdentifier = HarmonyIdentifier; + this.ModName = ModName; + this.Version = Version; + this.MPFunction = MPFunction; + this.Hash = Hash; + this.ModID = ModID; + } + + public MPModDataBlock(string HarmonyIdentifier, string ModName, string Version, MPFunction MPFunction, string ModID) + { + this.HarmonyIdentifier = HarmonyIdentifier; + this.ModName = ModName; + this.Version = Version; + this.MPFunction = MPFunction; + this.Hash = new byte[32]; + this.ModID = ModID; + } + + public string HarmonyIdentifier { get; } + public string ModName { get; } + public string Version { get; } + public MPFunction MPFunction { get; } + public byte[] Hash { get; } + public string ModID { get; } + } +} diff --git a/PulsarModLoader/MPModChecks/MPUserDataBlock.cs b/PulsarModLoader/MPModChecks/MPUserDataBlock.cs new file mode 100644 index 0000000..147c58f --- /dev/null +++ b/PulsarModLoader/MPModChecks/MPUserDataBlock.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace PulsarModLoader.MPModChecks +{ + public class MPUserDataBlock + { + public MPUserDataBlock(string PMLVersion, MPModDataBlock[] ModData) + { + this.PMLVersion = PMLVersion; + this.ModData = ModData; + } + + public MPUserDataBlock() + { + this.PMLVersion = ""; + this.ModData = null; + } + + public string PMLVersion { get; } + public MPModDataBlock[] ModData { get; } + } +} diff --git a/PulsarModLoader/ModMessage/ModMessageHelper.cs b/PulsarModLoader/ModMessage/ModMessageHelper.cs index 0c50592..b208ded 100644 --- a/PulsarModLoader/ModMessage/ModMessageHelper.cs +++ b/PulsarModLoader/ModMessage/ModMessageHelper.cs @@ -1,4 +1,5 @@ using HarmonyLib; +using PulsarModLoader.MPModChecks; using PulsarModLoader.Utilities; using System; using System.Collections.Generic; @@ -17,16 +18,19 @@ static void Prefix(PLServer __instance) } public class ModMessageHelper : PLMonoBehaviour { - public static bool ServerHasMPMods = false; public static ModMessageHelper Instance; - public Dictionary PlayersWithMods; + + [Obsolete] + public Dictionary PlayersWithMods = new Dictionary(); + private static Dictionary modMessageHandlers = new Dictionary(); + [Obsolete] public string GetPlayerMods(PhotonPlayer inPlayer) //if the player exists, return the modlist, otherwise return the string 'NoPlayer' { if (PlayersWithMods.ContainsKey(inPlayer)) { - return PlayersWithMods[inPlayer]; + return "NoPlayer"; } else { @@ -42,10 +46,6 @@ public class ModMessageHelper : PLMonoBehaviour { Assembly asm = mod.GetType().Assembly; Type modMessage = typeof(ModMessage); - if(mod.MPFunctionality > 2) - { - ServerHasMPMods = true; - } foreach (Type t in asm.GetTypes()) { if (modMessage.IsAssignableFrom(t) && !t.IsAbstract && !t.IsInterface) @@ -62,13 +62,15 @@ protected override void Awake() //gameobject startup script { base.Awake(); Instance = this; - PlayersWithMods = new Dictionary(); } + + [Obsolete] public string GetModName(string modName) { PulsarMod mod = ModManager.Instance.GetMod(modName); return $"{mod.Name} {mod.Version} MPF{mod.MPFunctionality}"; } + [PunRPC] public void ReceiveMessage(string modID, object[] arguments, PhotonMessageInfo pmi) { @@ -82,36 +84,18 @@ public void ReceiveMessage(string modID, object[] arguments, PhotonMessageInfo p Utilities.Logger.Info($"ModMessage for {modID} doesn't exist"); } } + [PunRPC] - public void ReceiveConnectionMessage(string modList, string PMLVersion, PhotonMessageInfo pmi) //Pong - { - PhotonPlayer sender = pmi.sender; - Utilities.Logger.Info($"ConnectionMessage received message from a sender with the following PML Version and modlist:\nPMLVersion: {PMLVersion}\nModlist:\n{modList}"); - - if (!PlayersWithMods.ContainsKey(sender)) - { - PlayersWithMods.Add(sender, modList); - Utilities.Logger.Info("Added Sender to PlayersWithMods list"); - } - else - { - Utilities.Logger.Info("Couldn't find sender"); - } - } - [PunRPC] - public void SendConnectionMessage(PhotonMessageInfo pmi) //Ping + public void RecieveErrorMessage(string message) { - Logger.Info("Received ping, Sending pong"); - ModMessageHelper.Instance.photonView.RPC("ReceiveConnectionMessage", pmi.sender, new object[] - { - MPModChecks.GetModList(), - FileVersionInfo.GetVersionInfo(Assembly.GetExecutingAssembly().Location).FileVersion - }); + PLNetworkManager.Instance.MainMenu.AddActiveMenu(new PLErrorMessageMenu(message)); } + [PunRPC] - public void RecieveErrorMessage(string message) + public void ReceiveConnectionMessage(MPModDataBlock[] modList, string PMLVersion, PhotonMessageInfo pmi) //Pong { - PLNetworkManager.Instance.MainMenu.AddActiveMenu(new PLErrorMessageMenu(message)); + Logger.Info($"recieved modlist and connection info from user with the following info:\nPMLVersion: {PMLVersion}\nModlist:{MPModCheckManager.GetModListAsString(modList)}"); + MPModCheckManager.Instance.AddNetworkedPeerMods(pmi.sender, modList); } } } diff --git a/PulsarModLoader/Patches/GameVersion.cs b/PulsarModLoader/Patches/GameVersion.cs index 0cbd9be..ba62e80 100644 --- a/PulsarModLoader/Patches/GameVersion.cs +++ b/PulsarModLoader/Patches/GameVersion.cs @@ -1,9 +1,6 @@ using HarmonyLib; -using PulsarModLoader.Chat.Commands; using System.Diagnostics; using System.Reflection; -using UnityEngine; -using UnityEngine.UI; namespace PulsarModLoader.Patches { @@ -12,7 +9,7 @@ namespace PulsarModLoader.Patches internal class GameVersion { internal static string Version = string.Empty; - static readonly string PMLVersion = FileVersionInfo.GetVersionInfo(Assembly.GetExecutingAssembly().Location).FileVersion; + public static readonly string PMLVersion = FileVersionInfo.GetVersionInfo(Assembly.GetExecutingAssembly().Location).FileVersion; static void Prefix(ref string Obj3) { diff --git a/PulsarModLoader/Patches/PLGlobalStart.cs b/PulsarModLoader/Patches/PLGlobalStart.cs index 9d1d974..3a90568 100644 --- a/PulsarModLoader/Patches/PLGlobalStart.cs +++ b/PulsarModLoader/Patches/PLGlobalStart.cs @@ -33,6 +33,10 @@ static void Prefix() //ModLoading string modsDir = Path.Combine(Directory.GetCurrentDirectory(), "Mods"); ModManager.Instance.LoadModsDirectory(modsDir); + + //MP Mod Checks + new MPModChecks.MPModCheckManager(); + modsLoaded = true; } } diff --git a/PulsarModLoader/Patches/PLServerStart.cs b/PulsarModLoader/Patches/PLServerStart.cs new file mode 100644 index 0000000..724feda --- /dev/null +++ b/PulsarModLoader/Patches/PLServerStart.cs @@ -0,0 +1,21 @@ +using HarmonyLib; +using PulsarModLoader.Chat.Extensions; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace PulsarModLoader.Patches +{ + [HarmonyPatch(typeof(PLServer), "Start")] + class PLServerStart + { + static void Postfix() + { + //Chat Extensions + ChatHelper.publicCached = false; + HandlePublicCommands.RequestPublicCommands(); + } + } +} diff --git a/PulsarModLoader/Patches/PhotonProperties.cs b/PulsarModLoader/Patches/PhotonProperties.cs index 91b827c..2813cac 100644 --- a/PulsarModLoader/Patches/PhotonProperties.cs +++ b/PulsarModLoader/Patches/PhotonProperties.cs @@ -1,5 +1,6 @@ using ExitGames.Client.Photon; using HarmonyLib; +using PulsarModLoader.MPModChecks; using System; using System.Collections.Generic; using System.Linq; @@ -24,8 +25,6 @@ private static void Prefix(RoomOptions roomOptions) "playerList", "modList", }); - //Add multiplayer mods to modList - roomOptions.CustomRoomProperties["modList"] = MPModChecks.GetMPModList(); } public static void UpdatePlayerList() diff --git a/PulsarModLoader/PulsarMod.cs b/PulsarModLoader/PulsarMod.cs index d77c5f8..29f168c 100644 --- a/PulsarModLoader/PulsarMod.cs +++ b/PulsarModLoader/PulsarMod.cs @@ -103,7 +103,7 @@ public virtual int MPFunctionality { get { - return (int)MPFunction.None; + return (int)MPModChecks.MPFunction.None; } } @@ -142,5 +142,10 @@ public virtual void Enable() { enabled = true; } + + /// + /// Mod ID for future feature involving download IDs for a public webserver + /// + public virtual string ModID => ""; } } diff --git a/PulsarModLoader/PulsarModLoader.csproj b/PulsarModLoader/PulsarModLoader.csproj index 86a0459..b34df8d 100644 --- a/PulsarModLoader/PulsarModLoader.csproj +++ b/PulsarModLoader/PulsarModLoader.csproj @@ -139,7 +139,6 @@ - @@ -192,7 +191,7 @@ - + @@ -205,11 +204,14 @@ + + + From 2ebd25f2dbd860c8228e4cce568170d86da10bde Mon Sep 17 00:00:00 2001 From: DragonFire47 <46509577+DragonFire47@users.noreply.github.com> Date: Thu, 1 Sep 2022 22:05:29 -0700 Subject: [PATCH 04/12] -Set several methods as static and private. --- PulsarModLoader/MPModChecks/MPModCheckManager.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/PulsarModLoader/MPModChecks/MPModCheckManager.cs b/PulsarModLoader/MPModChecks/MPModCheckManager.cs index 6649ced..152aaad 100644 --- a/PulsarModLoader/MPModChecks/MPModCheckManager.cs +++ b/PulsarModLoader/MPModChecks/MPModCheckManager.cs @@ -47,7 +47,7 @@ private void UpdateLobbyModList() //Update Photon Lobby Listing with mod list private bool ServerHasMPMods = false; - public MPModDataBlock[] getNetworkedPeerMods(PhotonPlayer Photonplayer) + public MPModDataBlock[] GetNetworkedPeerMods(PhotonPlayer Photonplayer) { return NetworkedPeersModLists[Photonplayer]; } @@ -130,7 +130,7 @@ private MemoryStream GetModListForLobbyListing() return dataStream; } - public MPUserDataBlock GetModListFromLobbyListingData(MemoryStream memoryStream) + public static MPUserDataBlock GetModListFromLobbyListingData(MemoryStream memoryStream) { memoryStream.Position = 0; MPUserDataBlock UserData = null; @@ -161,7 +161,7 @@ public MPUserDataBlock GetModListFromLobbyListingData(MemoryStream memoryStream) return UserData; } - public static string GetModListAsString(MPModDataBlock[] ModDatas) + private static string GetModListAsString(MPModDataBlock[] ModDatas) { string ModList = string.Empty; foreach (MPModDataBlock DataBlock in ModDatas) @@ -171,7 +171,7 @@ public static string GetModListAsString(MPModDataBlock[] ModDatas) return ModList; } - private MPUserDataBlock GetHostModList(RoomInfo room) + private static MPUserDataBlock GetHostModList(RoomInfo room) { if (room.CustomProperties.ContainsKey("modList")) { @@ -180,7 +180,7 @@ private MPUserDataBlock GetHostModList(RoomInfo room) return new MPUserDataBlock(); } - public void KickClient(PhotonPlayer client) + private static void KickClient(PhotonPlayer client) { if (SteamManager.Initialized && client.SteamID != CSteamID.Nil) { From 73c17e9ac7ad55d6b51a61441327e12630ac0fda Mon Sep 17 00:00:00 2001 From: DragonFire47 <46509577+DragonFire47@users.noreply.github.com> Date: Fri, 2 Sep 2022 13:52:31 -0700 Subject: [PATCH 05/12] -Fixed usage of old enum in GUIMain -Changed sent datatype for RPCs -Changed NetworkedPeersModLists dictionary and all ussages of it to store userdata. -Changed multiple method data inputs and outputs. -Added setting of modList value in CustomRoomProperties during lobby reaction. --- PulsarModLoader/CustomGUI/GUIMain.cs | 2 +- .../MPModChecks/MPModCheckManager.cs | 24 ++++++++++--------- .../ModMessage/ModMessageHelper.cs | 7 +++--- PulsarModLoader/Patches/PhotonProperties.cs | 3 +++ 4 files changed, 21 insertions(+), 15 deletions(-) diff --git a/PulsarModLoader/CustomGUI/GUIMain.cs b/PulsarModLoader/CustomGUI/GUIMain.cs index 35da7bf..17f2a41 100644 --- a/PulsarModLoader/CustomGUI/GUIMain.cs +++ b/PulsarModLoader/CustomGUI/GUIMain.cs @@ -120,7 +120,7 @@ void WindowFunction(int WindowID) Label($"Short Description: {mod.ShortDescription}"); if (mod.LongDescription != string.Empty) Label($"Long Description: {mod.LongDescription}"); - Label($"MPFunctionality: {((MPFunction)mod.MPFunctionality).ToString()}"); + Label($"MPFunctionality: {((MPModChecks.MPFunction)mod.MPFunctionality).ToString()}"); } EndScrollView(); } diff --git a/PulsarModLoader/MPModChecks/MPModCheckManager.cs b/PulsarModLoader/MPModChecks/MPModCheckManager.cs index 152aaad..426028c 100644 --- a/PulsarModLoader/MPModChecks/MPModCheckManager.cs +++ b/PulsarModLoader/MPModChecks/MPModCheckManager.cs @@ -43,16 +43,16 @@ private void UpdateLobbyModList() //Update Photon Lobby Listing with mod list private MPModDataBlock[] MyModList = null; - private Dictionary NetworkedPeersModLists = new Dictionary(); + private Dictionary NetworkedPeersModLists = new Dictionary(); private bool ServerHasMPMods = false; - public MPModDataBlock[] GetNetworkedPeerMods(PhotonPlayer Photonplayer) + public MPUserDataBlock GetNetworkedPeerMods(PhotonPlayer Photonplayer) { return NetworkedPeersModLists[Photonplayer]; } - public void AddNetworkedPeerMods(PhotonPlayer Photonplayer, MPModDataBlock[] modList) + public void AddNetworkedPeerMods(PhotonPlayer Photonplayer, MPUserDataBlock modList) { if (NetworkedPeersModLists.ContainsKey(Photonplayer)) { @@ -109,7 +109,7 @@ private void UpdateMyModList() Logger.Info("Finished Building MyModList, time elapsted: " + stopwatch.ElapsedMilliseconds.ToString()); } - private MemoryStream GetModListForLobbyListing() + public byte[] GetModListForLobbyListing() { MemoryStream dataStream = new MemoryStream(); using (BinaryWriter writer = new BinaryWriter(dataStream)) @@ -127,11 +127,12 @@ private MemoryStream GetModListForLobbyListing() writer.Write(dataBlock.ModID); //string ModID } } - return dataStream; + return dataStream.ToArray(); } - public static MPUserDataBlock GetModListFromLobbyListingData(MemoryStream memoryStream) + public static MPUserDataBlock GetModListFromLobbyListingData(byte[] byteData) { + MemoryStream memoryStream = new MemoryStream(byteData); memoryStream.Position = 0; MPUserDataBlock UserData = null; using (BinaryReader reader = new BinaryReader(memoryStream)) @@ -161,7 +162,7 @@ public static MPUserDataBlock GetModListFromLobbyListingData(MemoryStream memory return UserData; } - private static string GetModListAsString(MPModDataBlock[] ModDatas) + public static string GetModListAsString(MPModDataBlock[] ModDatas) { string ModList = string.Empty; foreach (MPModDataBlock DataBlock in ModDatas) @@ -175,7 +176,7 @@ private static MPUserDataBlock GetHostModList(RoomInfo room) { if (room.CustomProperties.ContainsKey("modList")) { - return GetModListFromLobbyListingData((MemoryStream)room.CustomProperties["modList"]); + return GetModListFromLobbyListingData((byte[])room.CustomProperties["modList"]); } return new MPUserDataBlock(); } @@ -287,7 +288,7 @@ public void HostOnClientJoined(PhotonPlayer Player) bool foundplayer = false; if (NetworkedPeersModLists.ContainsKey(Player)) //checks if server has received mod list from client. { - ClientMods = NetworkedPeersModLists[Player]; + ClientMods = NetworkedPeersModLists[Player].ModData; foundplayer = true; } Logger.Info("HostOnClientJoined checking for player mods, returned " + foundplayer.ToString()); @@ -398,6 +399,7 @@ public void HostOnClientJoined(PhotonPlayer Player) string message = $"You have been disconnected for not having the mod loader installed"; ModMessageHelper.Instance.photonView.RPC("RecieveErrorMessage", Player, new object[] { message }); KickClient(Player); + return; } Utilities.Logger.Info("Didn't receive message or proper modlist, but the server doesn't have multiplayer explicit mods. Proceeding onwards"); } @@ -446,10 +448,10 @@ static void Postfix(PhotonPlayer player, PhotonMessageInfo pmi) { if (player == PhotonNetwork.player) { + Logger.Info("Sending 'RecieveConnectionMessage' RPC"); ModMessageHelper.Instance.photonView.RPC("ReceiveConnectionMessage", pmi.sender, new object[] { - MPModCheckManager.Instance.MyModList, - Patches.GameVersion.PMLVersion + MPModCheckManager.Instance.GetModListForLobbyListing() }); } player.Verified = true; diff --git a/PulsarModLoader/ModMessage/ModMessageHelper.cs b/PulsarModLoader/ModMessage/ModMessageHelper.cs index b208ded..70e2ec9 100644 --- a/PulsarModLoader/ModMessage/ModMessageHelper.cs +++ b/PulsarModLoader/ModMessage/ModMessageHelper.cs @@ -92,10 +92,11 @@ public void RecieveErrorMessage(string message) } [PunRPC] - public void ReceiveConnectionMessage(MPModDataBlock[] modList, string PMLVersion, PhotonMessageInfo pmi) //Pong + public void ReceiveConnectionMessage(byte[] recievedData, PhotonMessageInfo pmi) //Pong { - Logger.Info($"recieved modlist and connection info from user with the following info:\nPMLVersion: {PMLVersion}\nModlist:{MPModCheckManager.GetModListAsString(modList)}"); - MPModCheckManager.Instance.AddNetworkedPeerMods(pmi.sender, modList); + MPUserDataBlock userDataBlock = MPModCheckManager.GetModListFromLobbyListingData(recievedData); + Logger.Info($"recieved modlist and connection info from user with the following info:\nPMLVersion: {userDataBlock.PMLVersion}\nModlist:{MPModCheckManager.GetModListAsString(userDataBlock.ModData)}"); + MPModCheckManager.Instance.AddNetworkedPeerMods(pmi.sender, userDataBlock); } } } diff --git a/PulsarModLoader/Patches/PhotonProperties.cs b/PulsarModLoader/Patches/PhotonProperties.cs index 2813cac..814bcb1 100644 --- a/PulsarModLoader/Patches/PhotonProperties.cs +++ b/PulsarModLoader/Patches/PhotonProperties.cs @@ -25,6 +25,9 @@ private static void Prefix(RoomOptions roomOptions) "playerList", "modList", }); + + //MPModCheck + roomOptions.CustomRoomProperties["modList"] = MPModChecks.MPModCheckManager.Instance.GetModListForLobbyListing(); } public static void UpdatePlayerList() From 300311e1029aa94e9abaa123b33b81757389d811 Mon Sep 17 00:00:00 2001 From: DragonFire47 <46509577+DragonFire47@users.noreply.github.com> Date: Sat, 3 Sep 2022 16:02:04 -0700 Subject: [PATCH 06/12] -Renamed Serialization and Deserialization methods -Changed MPUserDataBlock constructor to use string.empty -Fixed Hashchecks to use strings, byte arrays were failing even when they were the same. -Changed HasMPMods to HighestLevelOfMPMods, and added checks to client for when joining a vanilla host. -Changes to kicked Error Messages --- .../MPModChecks/MPModCheckManager.cs | 120 +++++++++++++++--- .../MPModChecks/MPUserDataBlock.cs | 2 +- .../ModMessage/ModMessageHelper.cs | 2 +- PulsarModLoader/Patches/PhotonProperties.cs | 2 +- 4 files changed, 104 insertions(+), 22 deletions(-) diff --git a/PulsarModLoader/MPModChecks/MPModCheckManager.cs b/PulsarModLoader/MPModChecks/MPModCheckManager.cs index 426028c..9c3610f 100644 --- a/PulsarModLoader/MPModChecks/MPModCheckManager.cs +++ b/PulsarModLoader/MPModChecks/MPModCheckManager.cs @@ -1,5 +1,6 @@ using ExitGames.Client.Photon; using HarmonyLib; +using PulsarModLoader.Patches; using PulsarModLoader.Utilities; using Steamworks; using System; @@ -7,7 +8,9 @@ using System.Collections.Generic; using System.Diagnostics; using System.IO; +using System.Reflection.Emit; using System.Security.Cryptography; +using System.Text; using UnityEngine; using Hashtable = ExitGames.Client.Photon.Hashtable; using Logger = PulsarModLoader.Utilities.Logger; @@ -30,11 +33,11 @@ public void RefreshData() private void UpdateLobbyModList() //Update Photon Lobby Listing with mod list { - if (PhotonNetwork.isMasterClient && PhotonNetwork.inRoom) + if (PhotonNetwork.isMasterClient && PhotonNetwork.inRoom && PLNetworkManager.Instance != null) { Room room = PhotonNetwork.room; Hashtable customProperties = room.CustomProperties; - customProperties["modList"] = GetModListForLobbyListing(); + customProperties["modList"] = SerializeHashlessUserData(); room.SetCustomProperties(customProperties); } } @@ -45,7 +48,7 @@ private void UpdateLobbyModList() //Update Photon Lobby Listing with mod list private Dictionary NetworkedPeersModLists = new Dictionary(); - private bool ServerHasMPMods = false; + private int HighestLevelOfMPMods = 0; public MPUserDataBlock GetNetworkedPeerMods(PhotonPlayer Photonplayer) { @@ -69,14 +72,15 @@ public void RemoveNetworkedPeerMods(PhotonPlayer Photonplayer) private List GetMPModList() { + HighestLevelOfMPMods = 0; List modList = new List(); foreach (PulsarMod mod in ModManager.Instance.GetAllMods()) { if (mod.MPFunctionality != (int)MPFunction.HideFromServerList) { - if (mod.MPFunctionality > (int)MPFunction.HostRequired) + if (mod.MPFunctionality >= (int)MPFunction.HostRequired && mod.MPFunctionality > HighestLevelOfMPMods) { - ServerHasMPMods = true; + HighestLevelOfMPMods = (mod.MPFunctionality); } modList.Add(mod); } @@ -109,7 +113,7 @@ private void UpdateMyModList() Logger.Info("Finished Building MyModList, time elapsted: " + stopwatch.ElapsedMilliseconds.ToString()); } - public byte[] GetModListForLobbyListing() + public byte[] SerializeHashlessUserData() { MemoryStream dataStream = new MemoryStream(); using (BinaryWriter writer = new BinaryWriter(dataStream)) @@ -130,7 +134,29 @@ public byte[] GetModListForLobbyListing() return dataStream.ToArray(); } - public static MPUserDataBlock GetModListFromLobbyListingData(byte[] byteData) + public byte[] SerializeHashfullUserData() + { + MemoryStream dataStream = new MemoryStream(); + using (BinaryWriter writer = new BinaryWriter(dataStream)) + { + //Datastream storage structure: + writer.Write(Patches.GameVersion.PMLVersion); //--Header-- + writer.Write(MyModList.Length); //string PMLVersion + for (int i = 0; i < MyModList.Length; i++) //int modcount + { // + MPModDataBlock dataBlock = MyModList[i]; //--ModData-- + writer.Write(dataBlock.ModName); //string mod name + writer.Write(dataBlock.HarmonyIdentifier); //string harmony ident + writer.Write(dataBlock.Version); //string mod version + writer.Write((byte)dataBlock.MPFunction); //byte MPFunction + writer.Write(dataBlock.ModID); //string ModID + writer.Write(dataBlock.Hash); //byte[] Hash + } + } + return dataStream.ToArray(); + } + + public static MPUserDataBlock DeserializeHashlessMPUserData(byte[] byteData) { MemoryStream memoryStream = new MemoryStream(byteData); memoryStream.Position = 0; @@ -158,6 +184,39 @@ public static MPUserDataBlock GetModListFromLobbyListingData(byte[] byteData) Logger.Info($"Failed to read mod list from lobby listing data.\n{ex.Message}"); } } + Logger.Info("Failed to read mod list from hashless data, returning null."); + return UserData; + } + + public static MPUserDataBlock DeserializeHashfullMPUserData(byte[] byteData) + { + MemoryStream memoryStream = new MemoryStream(byteData); + memoryStream.Position = 0; + MPUserDataBlock UserData = null; + using (BinaryReader reader = new BinaryReader(memoryStream)) + { + try + { + string PMLVersion = reader.ReadString(); + int ModCount = reader.ReadInt32(); + MPModDataBlock[] ModList = new MPModDataBlock[ModCount]; + for (int i = 0; i < ModCount; i++) + { + string modname = reader.ReadString(); + string HarmonyIdent = reader.ReadString(); + string ModVersion = reader.ReadString(); + MPFunction MPFunction = (MPFunction)reader.ReadByte(); + string ModID = reader.ReadString(); + byte[] Hash = reader.ReadBytes(32); + ModList[i] = new MPModDataBlock(HarmonyIdent, modname, ModVersion, MPFunction, ModID, Hash); + } + UserData = new MPUserDataBlock(PMLVersion, ModList); + } + catch (Exception ex) + { + Logger.Info($"Failed to read mod list from lobby listing data.\n{ex.Message}"); + } + } Logger.Info("Failed to read mod list from lobby listing data, returning null."); return UserData; } @@ -176,7 +235,7 @@ private static MPUserDataBlock GetHostModList(RoomInfo room) { if (room.CustomProperties.ContainsKey("modList")) { - return GetModListFromLobbyListingData((byte[])room.CustomProperties["modList"]); + return DeserializeHashlessMPUserData((byte[])room.CustomProperties["modList"]); } return new MPUserDataBlock(); } @@ -198,6 +257,20 @@ private static void KickClient(PhotonPlayer client) public bool ClientClickJoinRoom(RoomInfo room) { MPUserDataBlock HostModData = GetHostModList(room); + if(HostModData.PMLVersion == string.Empty) + { + if(HighestLevelOfMPMods >= (int)MPFunction.HostRequired) + { + PLNetworkManager.Instance.MainMenu.AddActiveMenu(new PLErrorMessageMenu($"FAILED TO JOIN CREW!\nMods requiring host installation or higher have been installed locally")); + + Logger.Info("Mods requiring host installation or higher have been installed locally"); + return false; + } + else + { + return true; + } + } MPModDataBlock[] HostModList = HostModData.ModData; string HostModListString = GetModListAsString(HostModList); @@ -302,7 +375,6 @@ public void HostOnClientJoined(PhotonPlayer Player) string outdatedMods = string.Empty; string incorrectHashMods = string.Empty; Logger.Info($"Starting Serverside Mod check"); - Logger.Info($"Checking if client is missing required mods"); int localLength = MyModList.Length; int clientLength = ClientMods.Length; @@ -329,11 +401,11 @@ public void HostOnClientJoined(PhotonPlayer Player) { outdatedMods += $"\nLocal: {MyModList[a].ModName} {MyModList[a].Version} Client: {ClientMods[b].ModName} {ClientMods[b].Version}"; } - else if (MyModList[a].Hash != ClientMods[b].Hash) //if mod versions match but hash doesn't, add as kick reason + else if (Encoding.ASCII.GetString(MyModList[a].Hash) != Encoding.ASCII.GetString(ClientMods[b].Hash)) //if mod versions match but hash doesn't, add as kick reason { incorrectHashMods += $"\n{ClientMods[b].ModName}"; missingMods += $"\n{ClientMods[b].ModName}"; - Logger.Info("Client has bad hash for " + MyModList[a].ModName); + Logger.Info($"Client has bad hash for {MyModList[a].ModName}. Local: {Encoding.ASCII.GetString(MyModList[a].Hash)} Client: {Encoding.ASCII.GetString(ClientMods[b].Hash)}"); } } } @@ -370,21 +442,22 @@ public void HostOnClientJoined(PhotonPlayer Player) string message = string.Empty; if (missingMods != string.Empty) { - message += $"\nYOU ARE MISSING THE FOLLOWING REQUIRED MODS{missingMods}"; + message += $"\nYou are missing the following required mods{missingMods}"; } if (clientMPLimitedMods != string.Empty) { - message += $"\nYOU CANNOT JOIN WITH THE FOLLOWING MODS INSTALLED{clientMPLimitedMods}"; + message += $"\nYou cannot join without the following mods installed{clientMPLimitedMods}"; } if (outdatedMods != string.Empty) { - message += $"\nTHE FOLLOWING MOD VERSIONS DO NOT MATCH{outdatedMods}"; + message += $"\nThe following mod versions do not match{outdatedMods}"; } if (message != string.Empty) { - PLNetworkManager.Instance.MainMenu.AddActiveMenu(new PLErrorMessageMenu($"Failed to join crew!{message}")); + ModMessageHelper.Instance.photonView.RPC("RecieveErrorMessage", Player, new object[] {$"Failed to join crew!{message}"}); + KickClient(Player); - Logger.Info("Local mod list is not equal to Server mod list"); + Logger.Info("Kicked client for failing mod check with the following message:" + message); } else { @@ -393,7 +466,7 @@ public void HostOnClientJoined(PhotonPlayer Player) } else //client wasn't found in mod list { - if (ServerHasMPMods) + if (HighestLevelOfMPMods >= (int)MPFunction.All) { Utilities.Logger.Info("Didn't receive message or proper modlist. proceeding to kick PhotonPlayer"); string message = $"You have been disconnected for not having the mod loader installed"; @@ -439,7 +512,7 @@ static void Postfix(PhotonPlayer client) } } - [HarmonyPatch(typeof(PLServer), "VerifyClient")] //Client sends mod info as early as possible during connection, + [HarmonyPatch(typeof(PLServer), "VerifyClient")] //Client sends mod info as early as possible during connection class ClientJoinPatch { static void Postfix(PhotonPlayer player, PhotonMessageInfo pmi) @@ -451,12 +524,21 @@ static void Postfix(PhotonPlayer player, PhotonMessageInfo pmi) Logger.Info("Sending 'RecieveConnectionMessage' RPC"); ModMessageHelper.Instance.photonView.RPC("ReceiveConnectionMessage", pmi.sender, new object[] { - MPModCheckManager.Instance.GetModListForLobbyListing() + MPModCheckManager.Instance.SerializeHashfullUserData() }); } player.Verified = true; } } } + + [HarmonyPatch(typeof(PLServer), "RemovePlayer")] + class RemovePlayerPatch + { + static void Postfix(PhotonPlayer inPlayer) + { + Instance.RemoveNetworkedPeerMods(inPlayer); + } + } } } diff --git a/PulsarModLoader/MPModChecks/MPUserDataBlock.cs b/PulsarModLoader/MPModChecks/MPUserDataBlock.cs index 147c58f..ee66b5f 100644 --- a/PulsarModLoader/MPModChecks/MPUserDataBlock.cs +++ b/PulsarModLoader/MPModChecks/MPUserDataBlock.cs @@ -16,7 +16,7 @@ public MPUserDataBlock(string PMLVersion, MPModDataBlock[] ModData) public MPUserDataBlock() { - this.PMLVersion = ""; + this.PMLVersion = string.Empty; this.ModData = null; } diff --git a/PulsarModLoader/ModMessage/ModMessageHelper.cs b/PulsarModLoader/ModMessage/ModMessageHelper.cs index 70e2ec9..ac3c35a 100644 --- a/PulsarModLoader/ModMessage/ModMessageHelper.cs +++ b/PulsarModLoader/ModMessage/ModMessageHelper.cs @@ -94,7 +94,7 @@ public void RecieveErrorMessage(string message) [PunRPC] public void ReceiveConnectionMessage(byte[] recievedData, PhotonMessageInfo pmi) //Pong { - MPUserDataBlock userDataBlock = MPModCheckManager.GetModListFromLobbyListingData(recievedData); + MPUserDataBlock userDataBlock = MPModCheckManager.DeserializeHashfullMPUserData(recievedData); Logger.Info($"recieved modlist and connection info from user with the following info:\nPMLVersion: {userDataBlock.PMLVersion}\nModlist:{MPModCheckManager.GetModListAsString(userDataBlock.ModData)}"); MPModCheckManager.Instance.AddNetworkedPeerMods(pmi.sender, userDataBlock); } diff --git a/PulsarModLoader/Patches/PhotonProperties.cs b/PulsarModLoader/Patches/PhotonProperties.cs index 814bcb1..ed4679a 100644 --- a/PulsarModLoader/Patches/PhotonProperties.cs +++ b/PulsarModLoader/Patches/PhotonProperties.cs @@ -27,7 +27,7 @@ private static void Prefix(RoomOptions roomOptions) }); //MPModCheck - roomOptions.CustomRoomProperties["modList"] = MPModChecks.MPModCheckManager.Instance.GetModListForLobbyListing(); + roomOptions.CustomRoomProperties["modList"] = MPModChecks.MPModCheckManager.Instance.SerializeHashlessUserData(); } public static void UpdatePlayerList() From 4114f27456bba748b1811efaa1c09dbb3c067a49 Mon Sep 17 00:00:00 2001 From: DragonFire47 <46509577+DragonFire47@users.noreply.github.com> Date: Sat, 3 Sep 2022 23:52:19 -0700 Subject: [PATCH 07/12] -Patched RPC Execution, allowing PML RPCs to run earlier. -Changed Patch locations to send mod info and verify clients earlier. --- .../MPModChecks/MPModCheckManager.cs | 47 ++++++++++++++++--- .../ModMessage/AllowPMLRPCPatch.cs | 38 +++++++++++++++ PulsarModLoader/PulsarModLoader.csproj | 1 + 3 files changed, 80 insertions(+), 6 deletions(-) create mode 100644 PulsarModLoader/ModMessage/AllowPMLRPCPatch.cs diff --git a/PulsarModLoader/MPModChecks/MPModCheckManager.cs b/PulsarModLoader/MPModChecks/MPModCheckManager.cs index 9c3610f..6ae86ab 100644 --- a/PulsarModLoader/MPModChecks/MPModCheckManager.cs +++ b/PulsarModLoader/MPModChecks/MPModCheckManager.cs @@ -355,7 +355,7 @@ public bool ClientClickJoinRoom(RoomInfo room) } } - public void HostOnClientJoined(PhotonPlayer Player) + public bool HostOnClientJoined(PhotonPlayer Player) { MPModDataBlock[] ClientMods = null; bool foundplayer = false; @@ -458,6 +458,7 @@ public void HostOnClientJoined(PhotonPlayer Player) KickClient(Player); Logger.Info("Kicked client for failing mod check with the following message:" + message); + return false; } else { @@ -472,13 +473,14 @@ public void HostOnClientJoined(PhotonPlayer Player) string message = $"You have been disconnected for not having the mod loader installed"; ModMessageHelper.Instance.photonView.RPC("RecieveErrorMessage", Player, new object[] { message }); KickClient(Player); - return; + return false; } Utilities.Logger.Info("Didn't receive message or proper modlist, but the server doesn't have multiplayer explicit mods. Proceeding onwards"); } + return true; } - public IEnumerator ServerVerifyClient(PhotonPlayer player) + /*public IEnumerator ServerVerifyClient(PhotonPlayer player) { int loops = 0; WaitForSeconds cachedWaitTime = new WaitForSeconds(0.25f); @@ -492,7 +494,7 @@ public IEnumerator ServerVerifyClient(PhotonPlayer player) yield return cachedWaitTime; } HostOnClientJoined(player); - } + }*/ [HarmonyPatch(typeof(PLUIPlayMenu), "ActuallyJoinRoom")] //allow/disallow local client to join server. class JoinRoomPatch @@ -503,16 +505,24 @@ static bool Prefix(RoomInfo room) } } - [HarmonyPatch(typeof(PLServer), "ServerOnClientVerified")] //Starts host mod verification coroutine + /*[HarmonyPatch(typeof(PLServer), "ServerOnClientVerified")] //Starts host mod verification coroutine class ServerOnClientVerifiedPatch { static void Postfix(PhotonPlayer client) { PLServer.Instance.StartCoroutine(Instance.ServerVerifyClient(client)); } + }*/ + [HarmonyPatch(typeof(PLServer), "AttemptGetVerified")] + class AttemptGetVerifiedRecievePatch + { + static bool Prefix(PhotonMessageInfo pmi) + { + return Instance.HostOnClientJoined(pmi.sender); + } } - [HarmonyPatch(typeof(PLServer), "VerifyClient")] //Client sends mod info as early as possible during connection + /*[HarmonyPatch(typeof(PLServer), "VerifyClient")] //Client sends mod info as early as possible during connection class ClientJoinPatch { static void Postfix(PhotonPlayer player, PhotonMessageInfo pmi) @@ -530,6 +540,31 @@ static void Postfix(PhotonPlayer player, PhotonMessageInfo pmi) player.Verified = true; } } + }*/ + + [HarmonyPatch(typeof(PLServer), "Update")] + class AttemptGetVerifiedSendPatch + { + static void PatchMethod() //Client sends mod info just before requesting verification + { + Logger.Info("Sending 'RecieveConnectionMessage' RPC"); + ModMessageHelper.Instance.photonView.RPC("ReceiveConnectionMessage", PhotonTargets.MasterClient, new object[] + { + Instance.SerializeHashfullUserData() + }); + } + static IEnumerable Transpiler(IEnumerable instructions) + { + List targetSequence = new List() + { + new CodeInstruction(OpCodes.Ldstr, "Attempting to get verified") + }; + List injectedSequence = new List() + { + new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof(AttemptGetVerifiedSendPatch), "PatchMethod")) + }; + return HarmonyHelpers.PatchBySequence(instructions, targetSequence, injectedSequence); + } } [HarmonyPatch(typeof(PLServer), "RemovePlayer")] diff --git a/PulsarModLoader/ModMessage/AllowPMLRPCPatch.cs b/PulsarModLoader/ModMessage/AllowPMLRPCPatch.cs new file mode 100644 index 0000000..4d14291 --- /dev/null +++ b/PulsarModLoader/ModMessage/AllowPMLRPCPatch.cs @@ -0,0 +1,38 @@ +using HarmonyLib; +using PulsarModLoader.Patches; +using System.Collections.Generic; +using System.Reflection.Emit; + +namespace PulsarModLoader.ModMessages +{ + [HarmonyPatch(typeof(NetworkingPeer), "ExecuteRpc")] + class AllowPMLRPCPatch + { + static bool PatchMethod(bool ShouldContinue, string MethodName) + { + if (MethodName == "ReceiveConnectionMessage" || MethodName == "ReceiveMessage") + { + return true; + } + else + { + return ShouldContinue; + } + } + static IEnumerable Transpiler(IEnumerable instructions) + { + List targetSequence = new List() + { + new CodeInstruction(OpCodes.Stloc_S, (byte)10), + new CodeInstruction(OpCodes.Ldloc_S, (byte)10), + }; + + List injectedSequence = new List() + { + new CodeInstruction(OpCodes.Ldloc_2), + new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof(AllowPMLRPCPatch), "PatchMethod")), + }; + return HarmonyHelpers.PatchBySequence(instructions, targetSequence, injectedSequence, patchMode: HarmonyHelpers.PatchMode.AFTER); + } + } +} diff --git a/PulsarModLoader/PulsarModLoader.csproj b/PulsarModLoader/PulsarModLoader.csproj index b34df8d..c4f1a35 100644 --- a/PulsarModLoader/PulsarModLoader.csproj +++ b/PulsarModLoader/PulsarModLoader.csproj @@ -189,6 +189,7 @@ + From ee9a2e717715e0fc3cc65ea948b063e28c194630 Mon Sep 17 00:00:00 2001 From: DragonFire47 <46509577+DragonFire47@users.noreply.github.com> Date: Mon, 5 Sep 2022 08:07:05 -0700 Subject: [PATCH 08/12] -Fixed AllowPMLRPCPatch -Added RPCs for client-mod synchronization -Added Framework for client-mod synchronization, might still need some work --- .../MPModChecks/MPModCheckManager.cs | 113 ++++++++++-------- .../ModMessage/AllowPMLRPCPatch.cs | 22 ++-- .../ModMessage/ModMessageHelper.cs | 36 +++++- 3 files changed, 110 insertions(+), 61 deletions(-) diff --git a/PulsarModLoader/MPModChecks/MPModCheckManager.cs b/PulsarModLoader/MPModChecks/MPModCheckManager.cs index 6ae86ab..59d563b 100644 --- a/PulsarModLoader/MPModChecks/MPModCheckManager.cs +++ b/PulsarModLoader/MPModChecks/MPModCheckManager.cs @@ -1,7 +1,5 @@ -using ExitGames.Client.Photon; -using HarmonyLib; +using HarmonyLib; using PulsarModLoader.Patches; -using PulsarModLoader.Utilities; using Steamworks; using System; using System.Collections; @@ -11,7 +9,6 @@ using System.Reflection.Emit; using System.Security.Cryptography; using System.Text; -using UnityEngine; using Hashtable = ExitGames.Client.Photon.Hashtable; using Logger = PulsarModLoader.Utilities.Logger; @@ -23,9 +20,10 @@ public MPModCheckManager() { Instance = this; RefreshData(); + ModManager.Instance.OnModUnloaded += RefreshData; } - public void RefreshData() + public void RefreshData(PulsarMod mod = null) { UpdateMyModList(); UpdateLobbyModList(); @@ -46,13 +44,22 @@ private void UpdateLobbyModList() //Update Photon Lobby Listing with mod list private MPModDataBlock[] MyModList = null; + public List RequestedModLists = new List(); + private Dictionary NetworkedPeersModLists = new Dictionary(); private int HighestLevelOfMPMods = 0; public MPUserDataBlock GetNetworkedPeerMods(PhotonPlayer Photonplayer) { - return NetworkedPeersModLists[Photonplayer]; + if (NetworkedPeersModLists.TryGetValue(Photonplayer, out MPUserDataBlock value)) + { + return value; + } + else + { + return null; + } } public void AddNetworkedPeerMods(PhotonPlayer Photonplayer, MPUserDataBlock modList) @@ -160,11 +167,11 @@ public static MPUserDataBlock DeserializeHashlessMPUserData(byte[] byteData) { MemoryStream memoryStream = new MemoryStream(byteData); memoryStream.Position = 0; - MPUserDataBlock UserData = null; - using (BinaryReader reader = new BinaryReader(memoryStream)) + try { - try + using (BinaryReader reader = new BinaryReader(memoryStream)) { + string PMLVersion = reader.ReadString(); int ModCount = reader.ReadInt32(); MPModDataBlock[] ModList = new MPModDataBlock[ModCount]; @@ -177,26 +184,26 @@ public static MPUserDataBlock DeserializeHashlessMPUserData(byte[] byteData) string ModID = reader.ReadString(); ModList[i] = new MPModDataBlock(HarmonyIdent, modname, ModVersion, MPFunction, ModID); } - UserData = new MPUserDataBlock(PMLVersion, ModList); - } - catch (Exception ex) - { - Logger.Info($"Failed to read mod list from lobby listing data.\n{ex.Message}"); + return new MPUserDataBlock(PMLVersion, ModList); + } } - Logger.Info("Failed to read mod list from hashless data, returning null."); - return UserData; + catch (Exception ex) + { + Logger.Info($"Failed to read mod list from Hashless MPUserData, returning null.\n{ex.Message}"); + return null; + } } public static MPUserDataBlock DeserializeHashfullMPUserData(byte[] byteData) { MemoryStream memoryStream = new MemoryStream(byteData); memoryStream.Position = 0; - MPUserDataBlock UserData = null; - using (BinaryReader reader = new BinaryReader(memoryStream)) + try { - try + using (BinaryReader reader = new BinaryReader(memoryStream)) { + string PMLVersion = reader.ReadString(); int ModCount = reader.ReadInt32(); MPModDataBlock[] ModList = new MPModDataBlock[ModCount]; @@ -210,15 +217,15 @@ public static MPUserDataBlock DeserializeHashfullMPUserData(byte[] byteData) byte[] Hash = reader.ReadBytes(32); ModList[i] = new MPModDataBlock(HarmonyIdent, modname, ModVersion, MPFunction, ModID, Hash); } - UserData = new MPUserDataBlock(PMLVersion, ModList); - } - catch (Exception ex) - { - Logger.Info($"Failed to read mod list from lobby listing data.\n{ex.Message}"); + return new MPUserDataBlock(PMLVersion, ModList); } } - Logger.Info("Failed to read mod list from lobby listing data, returning null."); - return UserData; + catch (Exception ex) + { + Logger.Info($"Failed to read mod list from Hashfull MPUserData, returning null.\n{ex.Message}"); + return null; + } + } public static string GetModListAsString(MPModDataBlock[] ModDatas) @@ -257,9 +264,9 @@ private static void KickClient(PhotonPlayer client) public bool ClientClickJoinRoom(RoomInfo room) { MPUserDataBlock HostModData = GetHostModList(room); - if(HostModData.PMLVersion == string.Empty) + if (HostModData.PMLVersion == string.Empty) { - if(HighestLevelOfMPMods >= (int)MPFunction.HostRequired) + if (HighestLevelOfMPMods >= (int)MPFunction.HostRequired) { PLNetworkManager.Instance.MainMenu.AddActiveMenu(new PLErrorMessageMenu($"FAILED TO JOIN CREW!\nMods requiring host installation or higher have been installed locally")); @@ -384,7 +391,7 @@ public bool HostOnClientJoined(PhotonPlayer Player) { bool found = false; int b = 0; - for (; b < clientLength; b++) + for (; b < clientLength; b++) { if (MyModList[a].HarmonyIdentifier == ClientMods[b].HarmonyIdentifier) { @@ -422,7 +429,7 @@ public bool HostOnClientJoined(PhotonPlayer Player) for (int b = 0; b < clientLength; b++) { bool found = false; - for(int a = 0; a < localLength; a++) + for (int a = 0; a < localLength; a++) { if (MyModList[a].HarmonyIdentifier == ClientMods[b].HarmonyIdentifier) { @@ -430,9 +437,9 @@ public bool HostOnClientJoined(PhotonPlayer Player) break; } } - if(!found) //if client mod not installed locally requires host to have installed. + if (!found) //if client mod not installed locally requires host to have installed. { - if(ClientMods[b].MPFunction >= MPFunction.HostRequired) + if (ClientMods[b].MPFunction >= MPFunction.HostRequired) { clientMPLimitedMods += $"\n{ClientMods[b].ModName}"; } @@ -454,7 +461,7 @@ public bool HostOnClientJoined(PhotonPlayer Player) } if (message != string.Empty) { - ModMessageHelper.Instance.photonView.RPC("RecieveErrorMessage", Player, new object[] {$"Failed to join crew!{message}"}); + ModMessageHelper.Instance.photonView.RPC("RecieveErrorMessage", Player, new object[] { $"Failed to join crew!{message}" }); KickClient(Player); Logger.Info("Kicked client for failing mod check with the following message:" + message); @@ -480,20 +487,16 @@ public bool HostOnClientJoined(PhotonPlayer Player) return true; } - /*public IEnumerator ServerVerifyClient(PhotonPlayer player) + /*public IEnumerator ServerSendModsToClient(PhotonPlayer client) { - int loops = 0; - WaitForSeconds cachedWaitTime = new WaitForSeconds(0.25f); - while (loops < 40) + foreach (PhotonPlayer player in NetworkedPeersModLists.Keys) { - loops++; - if (NetworkedPeersModLists.ContainsKey(player)) + ModMessageHelper.Instance.photonView.RPC("ClientRecieveModList", client, new object[] { - break; - } - yield return cachedWaitTime; + Instance.SerializeHashlessUserData() + }); + yield return null; } - HostOnClientJoined(player); }*/ [HarmonyPatch(typeof(PLUIPlayMenu), "ActuallyJoinRoom")] //allow/disallow local client to join server. @@ -510,7 +513,7 @@ class ServerOnClientVerifiedPatch { static void Postfix(PhotonPlayer client) { - PLServer.Instance.StartCoroutine(Instance.ServerVerifyClient(client)); + PLServer.Instance.StartCoroutine(Instance.ServerSendModsToClient(client)); } }*/ [HarmonyPatch(typeof(PLServer), "AttemptGetVerified")] @@ -548,7 +551,7 @@ class AttemptGetVerifiedSendPatch static void PatchMethod() //Client sends mod info just before requesting verification { Logger.Info("Sending 'RecieveConnectionMessage' RPC"); - ModMessageHelper.Instance.photonView.RPC("ReceiveConnectionMessage", PhotonTargets.MasterClient, new object[] + ModMessageHelper.Instance.photonView.RPC("ServerRecieveModList", PhotonTargets.MasterClient, new object[] { Instance.SerializeHashfullUserData() }); @@ -567,12 +570,26 @@ static IEnumerable Transpiler(IEnumerable inst } } - [HarmonyPatch(typeof(PLServer), "RemovePlayer")] + [HarmonyPatch(typeof(PLNetworkManager), "OnPhotonPlayerDisconnected")] class RemovePlayerPatch { - static void Postfix(PhotonPlayer inPlayer) + static void Postfix(PhotonPlayer photonPlayer) { - Instance.RemoveNetworkedPeerMods(inPlayer); + Instance.RemoveNetworkedPeerMods(photonPlayer); + } + } + + [HarmonyPatch(typeof(PLNetworkManager), "OnPhotonPlayerConnected")] + class AddPlayerPatch + { + static void Postfix(PhotonPlayer photonPlayer) + { + if(PhotonNetwork.isMasterClient) + { + return; + } + Instance.RequestedModLists.Add(photonPlayer); + ModMessageHelper.Instance.photonView.RPC("ClientRequestModList", photonPlayer, new object[] { }); } } } diff --git a/PulsarModLoader/ModMessage/AllowPMLRPCPatch.cs b/PulsarModLoader/ModMessage/AllowPMLRPCPatch.cs index 4d14291..8f65961 100644 --- a/PulsarModLoader/ModMessage/AllowPMLRPCPatch.cs +++ b/PulsarModLoader/ModMessage/AllowPMLRPCPatch.cs @@ -10,7 +10,7 @@ class AllowPMLRPCPatch { static bool PatchMethod(bool ShouldContinue, string MethodName) { - if (MethodName == "ReceiveConnectionMessage" || MethodName == "ReceiveMessage") + if (MethodName == "ReceiveMessage" || MethodName == "ClientRecieveModList" || MethodName == "ServerRecieveModList" || MethodName == "ClientRequestModList") { return true; } @@ -22,17 +22,19 @@ static bool PatchMethod(bool ShouldContinue, string MethodName) static IEnumerable Transpiler(IEnumerable instructions) { List targetSequence = new List() - { - new CodeInstruction(OpCodes.Stloc_S, (byte)10), - new CodeInstruction(OpCodes.Ldloc_S, (byte)10), - }; + { + new CodeInstruction(OpCodes.Brfalse_S), + new CodeInstruction(OpCodes.Ldc_I4_1), + new CodeInstruction(OpCodes.Stloc_S), + new CodeInstruction(OpCodes.Ldloc_S), + }; List injectedSequence = new List() - { - new CodeInstruction(OpCodes.Ldloc_2), - new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof(AllowPMLRPCPatch), "PatchMethod")), - }; - return HarmonyHelpers.PatchBySequence(instructions, targetSequence, injectedSequence, patchMode: HarmonyHelpers.PatchMode.AFTER); + { + new CodeInstruction(OpCodes.Ldloc_2), + new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof(AllowPMLRPCPatch), "PatchMethod")), + }; + return HarmonyHelpers.PatchBySequence(instructions, targetSequence, injectedSequence, checkMode: HarmonyHelpers.CheckMode.NEVER); } } } diff --git a/PulsarModLoader/ModMessage/ModMessageHelper.cs b/PulsarModLoader/ModMessage/ModMessageHelper.cs index ac3c35a..fc15398 100644 --- a/PulsarModLoader/ModMessage/ModMessageHelper.cs +++ b/PulsarModLoader/ModMessage/ModMessageHelper.cs @@ -3,7 +3,6 @@ using PulsarModLoader.Utilities; using System; using System.Collections.Generic; -using System.Diagnostics; using System.Reflection; namespace PulsarModLoader @@ -92,11 +91,42 @@ public void RecieveErrorMessage(string message) } [PunRPC] - public void ReceiveConnectionMessage(byte[] recievedData, PhotonMessageInfo pmi) //Pong + public void ServerRecieveModList(byte[] recievedData, PhotonMessageInfo pmi) { MPUserDataBlock userDataBlock = MPModCheckManager.DeserializeHashfullMPUserData(recievedData); - Logger.Info($"recieved modlist and connection info from user with the following info:\nPMLVersion: {userDataBlock.PMLVersion}\nModlist:{MPModCheckManager.GetModListAsString(userDataBlock.ModData)}"); + Logger.Info($"recieved modlist from user with the following info:\nPMLVersion: {userDataBlock.PMLVersion}\nModlist:{MPModCheckManager.GetModListAsString(userDataBlock.ModData)}"); MPModCheckManager.Instance.AddNetworkedPeerMods(pmi.sender, userDataBlock); } + + /*[PunRPC] + public void ClientRecieveModListFromServer(PhotonPlayer player, byte[] recievedData, PhotonMessageInfo pmi) + { + MPUserDataBlock userDataBlock = MPModCheckManager.DeserializeHashfullMPUserData(recievedData); + MPModCheckManager.Instance.AddNetworkedPeerMods(player, userDataBlock); + }*/ + + [PunRPC] + public void ClientRecieveModList(byte[] recievedData, PhotonMessageInfo pmi) + { + MPUserDataBlock userDataBlock = MPModCheckManager.DeserializeHashlessMPUserData(recievedData); + Logger.Info($"recieved modlist from user with the following info:\nPMLVersion: {userDataBlock.PMLVersion}\nModlist:{MPModCheckManager.GetModListAsString(userDataBlock.ModData)}"); + MPModCheckManager.Instance.AddNetworkedPeerMods(pmi.sender, userDataBlock); + } + + [PunRPC] + public void ClientRequestModList(PhotonMessageInfo pmi) + { + PhotonPlayer sender = pmi.sender; + photonView.RPC("ClientRecieveModList", sender, new object[] + { + MPModCheckManager.Instance.SerializeHashlessUserData() + }); + + if (MPModCheckManager.Instance.GetNetworkedPeerMods(sender) == null && !MPModCheckManager.Instance.RequestedModLists.Contains(sender)) + { + MPModCheckManager.Instance.RequestedModLists.Add(sender); + photonView.RPC("ClientRequestModList", sender, new object[] {}); + } + } } } From 5d479e1a6924b0ea251e838ddb06c57b39e07881 Mon Sep 17 00:00:00 2001 From: DragonFire47 <46509577+DragonFire47@users.noreply.github.com> Date: Mon, 5 Sep 2022 14:36:21 -0700 Subject: [PATCH 09/12] -Added HelperMethods for detecting client mods. --- .../MPModChecks/MPModCheckManager.cs | 53 +++++++++++++------ 1 file changed, 38 insertions(+), 15 deletions(-) diff --git a/PulsarModLoader/MPModChecks/MPModCheckManager.cs b/PulsarModLoader/MPModChecks/MPModCheckManager.cs index 59d563b..44916ac 100644 --- a/PulsarModLoader/MPModChecks/MPModCheckManager.cs +++ b/PulsarModLoader/MPModChecks/MPModCheckManager.cs @@ -61,6 +61,38 @@ public MPUserDataBlock GetNetworkedPeerMods(PhotonPlayer Photonplayer) return null; } } + + public bool NetworkedPeerHasMod(PhotonPlayer player, string HarmonyIdentifier) + { + MPUserDataBlock userData = GetNetworkedPeerMods(player); + if(userData != null) + { + foreach(MPModDataBlock modData in userData.ModData) + { + if(modData.HarmonyIdentifier == HarmonyIdentifier) + { + return true; + } + } + } + return false; + } + + public List NetworkedPeersWithMod(string HarmonyIdentifier) + { + List playerList = new List(); + foreach(KeyValuePair userEntry in NetworkedPeersModLists) + { + foreach(MPModDataBlock modData in userEntry.Value.ModData) + { + if(modData.HarmonyIdentifier == HarmonyIdentifier) + { + playerList.Add(userEntry.Key); + } + } + } + return playerList; + } public void AddNetworkedPeerMods(PhotonPlayer Photonplayer, MPUserDataBlock modList) { @@ -487,18 +519,6 @@ public bool HostOnClientJoined(PhotonPlayer Player) return true; } - /*public IEnumerator ServerSendModsToClient(PhotonPlayer client) - { - foreach (PhotonPlayer player in NetworkedPeersModLists.Keys) - { - ModMessageHelper.Instance.photonView.RPC("ClientRecieveModList", client, new object[] - { - Instance.SerializeHashlessUserData() - }); - yield return null; - } - }*/ - [HarmonyPatch(typeof(PLUIPlayMenu), "ActuallyJoinRoom")] //allow/disallow local client to join server. class JoinRoomPatch { @@ -508,14 +528,17 @@ static bool Prefix(RoomInfo room) } } - /*[HarmonyPatch(typeof(PLServer), "ServerOnClientVerified")] //Starts host mod verification coroutine + [HarmonyPatch(typeof(PLServer), "ServerOnClientVerified")] //Starts host mod verification coroutine class ServerOnClientVerifiedPatch { static void Postfix(PhotonPlayer client) { - PLServer.Instance.StartCoroutine(Instance.ServerSendModsToClient(client)); + ModMessageHelper.Instance.photonView.RPC("ClientRecieveModList", client, new object[] + { + Instance.SerializeHashlessUserData() + }); } - }*/ + } [HarmonyPatch(typeof(PLServer), "AttemptGetVerified")] class AttemptGetVerifiedRecievePatch { From 5ffe0a9f79b29e5bacee6c022ff9f2c582a95b81 Mon Sep 17 00:00:00 2001 From: DragonFire47 <46509577+DragonFire47@users.noreply.github.com> Date: Mon, 5 Sep 2022 15:11:04 -0700 Subject: [PATCH 10/12] -Host mods now synced to client. --- .../MPModChecks/MPModCheckManager.cs | 35 +++---------------- 1 file changed, 4 insertions(+), 31 deletions(-) diff --git a/PulsarModLoader/MPModChecks/MPModCheckManager.cs b/PulsarModLoader/MPModChecks/MPModCheckManager.cs index 44916ac..b218091 100644 --- a/PulsarModLoader/MPModChecks/MPModCheckManager.cs +++ b/PulsarModLoader/MPModChecks/MPModCheckManager.cs @@ -528,17 +528,6 @@ static bool Prefix(RoomInfo room) } } - [HarmonyPatch(typeof(PLServer), "ServerOnClientVerified")] //Starts host mod verification coroutine - class ServerOnClientVerifiedPatch - { - static void Postfix(PhotonPlayer client) - { - ModMessageHelper.Instance.photonView.RPC("ClientRecieveModList", client, new object[] - { - Instance.SerializeHashlessUserData() - }); - } - } [HarmonyPatch(typeof(PLServer), "AttemptGetVerified")] class AttemptGetVerifiedRecievePatch { @@ -548,26 +537,6 @@ static bool Prefix(PhotonMessageInfo pmi) } } - /*[HarmonyPatch(typeof(PLServer), "VerifyClient")] //Client sends mod info as early as possible during connection - class ClientJoinPatch - { - static void Postfix(PhotonPlayer player, PhotonMessageInfo pmi) - { - if (pmi.sender != null && pmi.sender.IsMasterClient && player != null) - { - if (player == PhotonNetwork.player) - { - Logger.Info("Sending 'RecieveConnectionMessage' RPC"); - ModMessageHelper.Instance.photonView.RPC("ReceiveConnectionMessage", pmi.sender, new object[] - { - MPModCheckManager.Instance.SerializeHashfullUserData() - }); - } - player.Verified = true; - } - } - }*/ - [HarmonyPatch(typeof(PLServer), "Update")] class AttemptGetVerifiedSendPatch { @@ -609,6 +578,10 @@ static void Postfix(PhotonPlayer photonPlayer) { if(PhotonNetwork.isMasterClient) { + ModMessageHelper.Instance.photonView.RPC("ClientRecieveModList", photonPlayer, new object[] + { + Instance.SerializeHashlessUserData() + }); return; } Instance.RequestedModLists.Add(photonPlayer); From 7337dc5543b344bf7b751d2c975bbe3d3f357bde Mon Sep 17 00:00:00 2001 From: DragonFire47 <46509577+DragonFire47@users.noreply.github.com> Date: Mon, 5 Sep 2022 15:22:14 -0700 Subject: [PATCH 11/12] Renamed MPFunction to MPRequirement --- PulsarModLoader/CustomGUI/GUIMain.cs | 2 +- .../MPModChecks/MPModCheckManager.cs | 34 +++++++++---------- PulsarModLoader/MPModChecks/MPModDataBlock.cs | 10 +++--- .../{MPFunction.cs => MPRequirement.cs} | 4 +-- .../ModMessage/ModMessageHelper.cs | 2 +- PulsarModLoader/PulsarMod.cs | 20 +++++++---- PulsarModLoader/PulsarModLoader.csproj | 2 +- 7 files changed, 41 insertions(+), 33 deletions(-) rename PulsarModLoader/MPModChecks/{MPFunction.cs => MPRequirement.cs} (93%) diff --git a/PulsarModLoader/CustomGUI/GUIMain.cs b/PulsarModLoader/CustomGUI/GUIMain.cs index 17f2a41..cc9d9f1 100644 --- a/PulsarModLoader/CustomGUI/GUIMain.cs +++ b/PulsarModLoader/CustomGUI/GUIMain.cs @@ -120,7 +120,7 @@ void WindowFunction(int WindowID) Label($"Short Description: {mod.ShortDescription}"); if (mod.LongDescription != string.Empty) Label($"Long Description: {mod.LongDescription}"); - Label($"MPFunctionality: {((MPModChecks.MPFunction)mod.MPFunctionality).ToString()}"); + Label($"MPRequirement: {((MPModChecks.MPRequirement)mod.MPRequirements).ToString()}"); } EndScrollView(); } diff --git a/PulsarModLoader/MPModChecks/MPModCheckManager.cs b/PulsarModLoader/MPModChecks/MPModCheckManager.cs index b218091..69f33b2 100644 --- a/PulsarModLoader/MPModChecks/MPModCheckManager.cs +++ b/PulsarModLoader/MPModChecks/MPModCheckManager.cs @@ -115,11 +115,11 @@ private List GetMPModList() List modList = new List(); foreach (PulsarMod mod in ModManager.Instance.GetAllMods()) { - if (mod.MPFunctionality != (int)MPFunction.HideFromServerList) + if (mod.MPRequirements != (int)MPRequirement.HideFromServerList) { - if (mod.MPFunctionality >= (int)MPFunction.HostRequired && mod.MPFunctionality > HighestLevelOfMPMods) + if (mod.MPRequirements >= (int)MPRequirement.Host && mod.MPRequirements > HighestLevelOfMPMods) { - HighestLevelOfMPMods = (mod.MPFunctionality); + HighestLevelOfMPMods = (mod.MPRequirements); } modList.Add(mod); } @@ -143,7 +143,7 @@ private void UpdateMyModList() { MyStream.Position = 0; byte[] Hash = MyHasher.ComputeHash(MyStream); - ProcessedMods[i] = new MPModDataBlock(currentMod.HarmonyIdentifier(), currentMod.Name, currentMod.Version, (MPFunction)currentMod.MPFunctionality, currentMod.ModID, Hash); + ProcessedMods[i] = new MPModDataBlock(currentMod.HarmonyIdentifier(), currentMod.Name, currentMod.Version, (MPRequirement)currentMod.MPRequirements, currentMod.ModID, Hash); } } } @@ -166,7 +166,7 @@ public byte[] SerializeHashlessUserData() writer.Write(dataBlock.ModName); //string mod name writer.Write(dataBlock.HarmonyIdentifier); //string harmony ident writer.Write(dataBlock.Version); //string mod version - writer.Write((byte)dataBlock.MPFunction); //byte MPFunction + writer.Write((byte)dataBlock.MPRequirement);//byte MPRequirement writer.Write(dataBlock.ModID); //string ModID } } @@ -187,7 +187,7 @@ public byte[] SerializeHashfullUserData() writer.Write(dataBlock.ModName); //string mod name writer.Write(dataBlock.HarmonyIdentifier); //string harmony ident writer.Write(dataBlock.Version); //string mod version - writer.Write((byte)dataBlock.MPFunction); //byte MPFunction + writer.Write((byte)dataBlock.MPRequirement);//byte MPRequirements writer.Write(dataBlock.ModID); //string ModID writer.Write(dataBlock.Hash); //byte[] Hash } @@ -212,9 +212,9 @@ public static MPUserDataBlock DeserializeHashlessMPUserData(byte[] byteData) string modname = reader.ReadString(); string HarmonyIdent = reader.ReadString(); string ModVersion = reader.ReadString(); - MPFunction MPFunction = (MPFunction)reader.ReadByte(); + MPRequirement MPRequirements = (MPRequirement)reader.ReadByte(); string ModID = reader.ReadString(); - ModList[i] = new MPModDataBlock(HarmonyIdent, modname, ModVersion, MPFunction, ModID); + ModList[i] = new MPModDataBlock(HarmonyIdent, modname, ModVersion, MPRequirements, ModID); } return new MPUserDataBlock(PMLVersion, ModList); @@ -244,10 +244,10 @@ public static MPUserDataBlock DeserializeHashfullMPUserData(byte[] byteData) string modname = reader.ReadString(); string HarmonyIdent = reader.ReadString(); string ModVersion = reader.ReadString(); - MPFunction MPFunction = (MPFunction)reader.ReadByte(); + MPRequirement MPRequirements = (MPRequirement)reader.ReadByte(); string ModID = reader.ReadString(); byte[] Hash = reader.ReadBytes(32); - ModList[i] = new MPModDataBlock(HarmonyIdent, modname, ModVersion, MPFunction, ModID, Hash); + ModList[i] = new MPModDataBlock(HarmonyIdent, modname, ModVersion, MPRequirements, ModID, Hash); } return new MPUserDataBlock(PMLVersion, ModList); } @@ -298,7 +298,7 @@ public bool ClientClickJoinRoom(RoomInfo room) MPUserDataBlock HostModData = GetHostModList(room); if (HostModData.PMLVersion == string.Empty) { - if (HighestLevelOfMPMods >= (int)MPFunction.HostRequired) + if (HighestLevelOfMPMods >= (int)MPRequirement.Host) { PLNetworkManager.Instance.MainMenu.AddActiveMenu(new PLErrorMessageMenu($"FAILED TO JOIN CREW!\nMods requiring host installation or higher have been installed locally")); @@ -335,7 +335,7 @@ public bool ClientClickJoinRoom(RoomInfo room) } if (!found) { //didn't find mod in host list, checking if mod function mandates host installation - if (MyModList[a].MPFunction >= MPFunction.HostRequired) + if (MyModList[a].MPRequirement >= MPRequirement.Host) { localMPLimitedMods += $"\n{MyModList[a].ModName}"; } @@ -361,7 +361,7 @@ public bool ClientClickJoinRoom(RoomInfo room) } if (!found) { - if (HostModList[a].MPFunction == MPFunction.All) + if (HostModList[a].MPRequirement == MPRequirement.All) { //Host MP mod not found locally missingMods += $"\n{HostModList[a].ModName}"; } @@ -434,7 +434,7 @@ public bool HostOnClientJoined(PhotonPlayer Player) if (found) { - if (MyModList[a].MPFunction >= MPFunction.HostRequired) //limit these types of kicking to MPLimited mods. + if (MyModList[a].MPRequirement >= MPRequirement.Host) //limit these types of kicking to MPLimited mods. { if (MyModList[a].Version != ClientMods[b].Version) //if mod versions don't match, add as kick reason { @@ -450,7 +450,7 @@ public bool HostOnClientJoined(PhotonPlayer Player) } else { - if (MyModList[a].MPFunction == MPFunction.All) //if client needs mod installed + if (MyModList[a].MPRequirement == MPRequirement.All) //if client needs mod installed { missingMods += $"\n{MyModList[a].ModName}"; } @@ -471,7 +471,7 @@ public bool HostOnClientJoined(PhotonPlayer Player) } if (!found) //if client mod not installed locally requires host to have installed. { - if (ClientMods[b].MPFunction >= MPFunction.HostRequired) + if (ClientMods[b].MPRequirement >= MPRequirement.Host) { clientMPLimitedMods += $"\n{ClientMods[b].ModName}"; } @@ -506,7 +506,7 @@ public bool HostOnClientJoined(PhotonPlayer Player) } else //client wasn't found in mod list { - if (HighestLevelOfMPMods >= (int)MPFunction.All) + if (HighestLevelOfMPMods >= (int)MPRequirement.All) { Utilities.Logger.Info("Didn't receive message or proper modlist. proceeding to kick PhotonPlayer"); string message = $"You have been disconnected for not having the mod loader installed"; diff --git a/PulsarModLoader/MPModChecks/MPModDataBlock.cs b/PulsarModLoader/MPModChecks/MPModDataBlock.cs index fc0e373..7954355 100644 --- a/PulsarModLoader/MPModChecks/MPModDataBlock.cs +++ b/PulsarModLoader/MPModChecks/MPModDataBlock.cs @@ -2,22 +2,22 @@ { public class MPModDataBlock { - public MPModDataBlock(string HarmonyIdentifier, string ModName, string Version, MPFunction MPFunction, string ModID, byte[] Hash) + public MPModDataBlock(string HarmonyIdentifier, string ModName, string Version, MPRequirement MPRequirement, string ModID, byte[] Hash) { this.HarmonyIdentifier = HarmonyIdentifier; this.ModName = ModName; this.Version = Version; - this.MPFunction = MPFunction; + this.MPRequirement = MPRequirement; this.Hash = Hash; this.ModID = ModID; } - public MPModDataBlock(string HarmonyIdentifier, string ModName, string Version, MPFunction MPFunction, string ModID) + public MPModDataBlock(string HarmonyIdentifier, string ModName, string Version, MPRequirement MPRequirement, string ModID) { this.HarmonyIdentifier = HarmonyIdentifier; this.ModName = ModName; this.Version = Version; - this.MPFunction = MPFunction; + this.MPRequirement = MPRequirement; this.Hash = new byte[32]; this.ModID = ModID; } @@ -25,7 +25,7 @@ public MPModDataBlock(string HarmonyIdentifier, string ModName, string Version, public string HarmonyIdentifier { get; } public string ModName { get; } public string Version { get; } - public MPFunction MPFunction { get; } + public MPRequirement MPRequirement { get; } public byte[] Hash { get; } public string ModID { get; } } diff --git a/PulsarModLoader/MPModChecks/MPFunction.cs b/PulsarModLoader/MPModChecks/MPRequirement.cs similarity index 93% rename from PulsarModLoader/MPModChecks/MPFunction.cs rename to PulsarModLoader/MPModChecks/MPRequirement.cs index 702d096..21a1e8f 100644 --- a/PulsarModLoader/MPModChecks/MPFunction.cs +++ b/PulsarModLoader/MPModChecks/MPRequirement.cs @@ -25,7 +25,7 @@ public enum MPFunction } namespace PulsarModLoader.MPModChecks { - public enum MPFunction + public enum MPRequirement { /// /// No MP Requirements @@ -38,7 +38,7 @@ public enum MPFunction /// /// Host must have installed for clients to join /// - HostRequired, //2 Host must have installed for clients to join + Host, //2 Host must have installed for clients to join /// /// All clients must have installed /// diff --git a/PulsarModLoader/ModMessage/ModMessageHelper.cs b/PulsarModLoader/ModMessage/ModMessageHelper.cs index fc15398..fdfce6f 100644 --- a/PulsarModLoader/ModMessage/ModMessageHelper.cs +++ b/PulsarModLoader/ModMessage/ModMessageHelper.cs @@ -67,7 +67,7 @@ protected override void Awake() //gameobject startup script public string GetModName(string modName) { PulsarMod mod = ModManager.Instance.GetMod(modName); - return $"{mod.Name} {mod.Version} MPF{mod.MPFunctionality}"; + return $"{mod.Name} {mod.Version} MPF{mod.MPRequirements}"; } [PunRPC] diff --git a/PulsarModLoader/PulsarMod.cs b/PulsarModLoader/PulsarMod.cs index 29f168c..b176ab4 100644 --- a/PulsarModLoader/PulsarMod.cs +++ b/PulsarModLoader/PulsarMod.cs @@ -92,18 +92,26 @@ public virtual string Name } } + [Obsolete] + public virtual int MPFunctionality + { + get + { + return MPRequirements; + } + } /// - /// Mod's multiplayer requirements. use MPFunction.
- /// None: No Functionality
- /// HostOnly: Only the host is required to have it installed
- /// HostApproved: Host must have the mod installed, works better when client has it installed.
+ /// Mod's multiplayer requirements. use MPModChecks.MPRequirement.
+ /// None: No requirement
+ /// Hidden: Hidden from mod lists
+ /// Host: Host must have the mod installed, works better when client has it installed.
/// All: All players must have the mod installed ///
- public virtual int MPFunctionality + public virtual int MPRequirements { get { - return (int)MPModChecks.MPFunction.None; + return (int)MPModChecks.MPRequirement.None; } } diff --git a/PulsarModLoader/PulsarModLoader.csproj b/PulsarModLoader/PulsarModLoader.csproj index c4f1a35..8912e9d 100644 --- a/PulsarModLoader/PulsarModLoader.csproj +++ b/PulsarModLoader/PulsarModLoader.csproj @@ -193,7 +193,7 @@ - + From b5e4e693795754d0b113b174fc69f619d1bcec19 Mon Sep 17 00:00:00 2001 From: DragonFire47 <46509577+DragonFire47@users.noreply.github.com> Date: Mon, 5 Sep 2022 15:27:51 -0700 Subject: [PATCH 12/12] Changed MPRequirements to grab from MPFunctionality if set to host or all, preserving MPRequirements for old mods. --- PulsarModLoader/PulsarMod.cs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/PulsarModLoader/PulsarMod.cs b/PulsarModLoader/PulsarMod.cs index b176ab4..0893e04 100644 --- a/PulsarModLoader/PulsarMod.cs +++ b/PulsarModLoader/PulsarMod.cs @@ -1,4 +1,5 @@ using HarmonyLib; +using PulsarModLoader.MPModChecks; using System; using System.Diagnostics; using System.Reflection; @@ -111,7 +112,14 @@ public virtual int MPRequirements { get { - return (int)MPModChecks.MPRequirement.None; + if (MPFunctionality >= (int)MPRequirement.Host) + { + return MPFunctionality; + } + else + { + return (int)MPRequirement.None; + } } }