diff --git a/GuiModifications.cs b/GuiModifications.cs
index 1ada39c..1a94908 100644
--- a/GuiModifications.cs
+++ b/GuiModifications.cs
@@ -49,7 +49,7 @@ internal static void RunMainMenuModifications()
textComponent.font = LocalizedText.localizationTable.GetFont(Settings.Get().Language, false);
textComponent.color = Color.Lerp(Color.blue, Color.black, 0.6f);
- // not sure what this is I stole it from WackyModer lol
+ // not sure what this is I stole it from WackyModer lol -- Melon, It stops the text from being clickced and blocking the buttons I think
textComponent.raycastTarget = false;
textComponent.fontSize = 13;
@@ -91,4 +91,4 @@ internal static string GetBepInExInfo()
return text;
}
}
-}
\ No newline at end of file
+}
diff --git a/HarmonyLoader.cs b/HarmonyLoader.cs
index 64f635b..aefb6a1 100644
--- a/HarmonyLoader.cs
+++ b/HarmonyLoader.cs
@@ -7,7 +7,70 @@ namespace Splotch.Loader
///
internal static class Patcher
{
- public static Harmony harmony = new Harmony("com.codemob.splotch");
+ public static Harmony harmony = new Harmony("com.splotch.splotchfixes");
+ ///
+ /// Runs all of Splotch's patches.
+ ///
+ public static void DoPatching()
+ {
+ harmony.PatchAll(typeof(Patches));
+ }
+
+ [HarmonyPatch]
+ internal static class Patches
+ {
+ /* im not done with this yet
+ [HarmonyPatch(typeof(Client)]
+ public static bool UpdateInputHistoryReplacement(Client __instance, InputPacketUpdate update)
+ {
+ uint num = this.inputHistoryHeadSeqNum;
+ int num2 = (int)(update.seqNumber - num);
+ if (num2 > 32)
+ {
+ Debug.LogError("Discarded a packet because it was too new");
+ return true;
+ }
+ for (int i = num2 - 1; i >= 0; i--)
+ {
+ uint num = this.inputHistoryHeadSeqNum;
+ int num2 = (int)(update.seqNumber - num);
+ if (num2 > 32)
+ {
+ Debug.LogError("Discarded a packet because it was too new");
+ return true;
+ }
+ for (int i = num2 - 1; i >= 0; i--)
+ {
+ uint num3 = 1U << i;
+ InputPacket inputPacket = default(InputPacket);
+ inputPacket.jump = ((update.jump & num3) > 0U);
+ inputPacket.ab1 = ((update.ab1 & num3) > 0U);
+ inputPacket.ab2 = ((update.ab2 & num3) > 0U);
+ inputPacket.ab3 = ((update.ab3 & num3) > 0U);
+ inputPacket.select = ((update.select & num3) > 0U);
+ inputPacket.start = ((update.start & num3) > 0U);
+ inputPacket.w = ((update.w & num3) > 0U);
+ inputPacket.a = ((update.a & num3) > 0U);
+ inputPacket.s = ((update.s & num3) > 0U);
+ inputPacket.d = ((update.d & num3) > 0U);
+ inputPacket.joystickAngle = update.joystickAngle[i];
+ inputPacket.targetDelayBufferSize = update.targetDelayBufferSize;
+ inputPacket.seqNumber = num + 1U;
+ num += 1U;
+ this.inputHistory.Enqueue(inputPacket);
+ this.inputHistoryHeadSeqNum = inputPacket.seqNumber;
+ }
+ return false;
+ }
+ */
+ // put your patch here
+ }
+
+ [HarmonyPatch]
+ internal static class Patches
+ {
+ // second one for ease
+ }
}
}
diff --git a/LICENSE b/LICENSE
index 785366c..5c93f45 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,21 +1,13 @@
-MIT License
+ DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
+ Version 2, December 2004
-Copyright (c) 2024 codemob
+ Copyright (C) 2004 Sam Hocevar
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
+ Everyone is permitted to copy and distribute verbatim or modified
+ copies of this license document, and changing it is allowed as long
+ as the name is changed.
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
+ DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
+ 0. You just DO WHAT THE FUCK YOU WANT TO.
diff --git a/Loader.cs b/Loader.cs
index ae73960..179906f 100644
--- a/Loader.cs
+++ b/Loader.cs
@@ -10,8 +10,6 @@
using System.Collections;
using HarmonyLib;
using MonoMod.Utils;
-using Splotch.Network;
-using Splotch.UserInterface;
namespace Splotch.Loader
{
@@ -21,6 +19,7 @@ namespace Splotch.Loader
public static class Loader
{
public static bool BepInExPresent { get { return Directory.Exists(@"BepInEx\core\"); } }
+ public static string ModPath = null;
struct SplotchConfigContainer
{
@@ -42,11 +41,17 @@ public static void OnEnterScene(Scene scene, LoadSceneMode loadSceneMode)
Logger.Log($"Entering main menu on version {VersionChecker.currentVersionString}");
+ string[] commandLineArgs = Environment.GetCommandLineArgs();
+
+ foreach (string arg in commandLineArgs)
+ {
+ Console.WriteLine(arg);
+ }
+
enteredScene = true;
+ Patcher.DoPatching();
ModLoader.ModLoader.LoadMods();
EventManager.Load();
- Networker.Load();
- UserInterface.SplotchGUI.Load();
GameObject obj = new GameObject("Unloader", new Type[] { typeof(UnLoader) });
Logger.Debug("Finished main menu loading!");
@@ -80,6 +85,31 @@ public static void LoadBepInEx()
///
public static void Main()
{
+ // Test for the "--begone-splotch" command line arg so we can run vanilla
+
+ string[] commandLineArgs = Environment.GetCommandLineArgs();
+
+ bool CustomPath = false;
+ foreach (string arg in commandLineArgs)
+ {
+ if (CustomPath)
+ {
+ ModPath = arg;
+ }
+
+ CustomPath = false;
+
+ // I have no clue why, it just breaks randomly and inoften when this is not .Contains()
+ if (arg.Contains("--begone-splotch"))
+ {
+ return;
+ }
+
+ if (arg.Contains("--splotch-mods-dir"))
+ {
+ CustomPath = true;
+ }
+ }
if (BepInExPresent)
LoadBepInEx();
@@ -144,4 +174,4 @@ public static void LoadBepInExUnstable()
SceneManager.sceneLoaded += Loader.SceneLoaded;
}
}
-}
\ No newline at end of file
+}
diff --git a/Logger.cs b/Logger.cs
index 451564a..30b4bec 100644
--- a/Logger.cs
+++ b/Logger.cs
@@ -1,4 +1,4 @@
-using Splotch.Loader;
+using Splotch.Loader;
using System;
using System.Diagnostics;
using System.IO;
@@ -6,8 +6,6 @@
using System.Runtime.InteropServices;
using System.Threading;
using UnityEngine;
-
-
public static class Logger
{
///
@@ -33,8 +31,6 @@ private static string GetCallingClass()
//Console.WriteLine("Unable to determine calling class.");
}
}
-
-
///
/// Initializes the console.
///
@@ -43,7 +39,6 @@ private static string GetCallingClass()
internal static void InitLogger()
{
VersionChecker.RunVersionChecker();
-
// Create a new process
Process process = new Process();
process.StartInfo.FileName = "cmd.exe";
@@ -51,39 +46,29 @@ internal static void InitLogger()
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.UseShellExecute = false;
process.StartInfo.CreateNoWindow = !Splotch.Config.LoadedSplotchConfig.consoleEnabled && !VersionChecker.updateNeeded; // Set this to true if you want to hide the window (Might be how we disable the window)
-
// Start the process
process.Start();
-
// It breaks if this isn't here
Thread.Sleep(1000);
-
// Connects the console window to bopl
- AttachConsole((uint) process.Id);
-
+ AttachConsole((uint)process.Id);
// Sets the output to the console window thing
StreamWriter sw = new StreamWriter(Console.OpenStandardOutput()) { AutoFlush = true };
Console.SetOut(sw);
-
// Set the title of the window
Console.Title = $"Splotch Log version {VersionChecker.currentVersionString}";
-
Application.logMessageReceived += HandleUnityLogs;
-
if (VersionChecker.updateNeeded)
{
Console.WriteLine($"Update {VersionChecker.targetVersionString} needed! The current installed version is {VersionChecker.currentVersionString} Press [P] to open the download page or any other key to continue");
-
ConsoleKeyInfo key = Console.ReadKey();
if (key.KeyChar == 'p')
{
Process.Start("https://github.com/commandblox/Splotch/releases");
}
-
if (!Splotch.Config.LoadedSplotchConfig.consoleEnabled)
process.Close();
}
-
Logger.Log("Log test");
Logger.Warning("Warn test");
Logger.Error("Error test");
@@ -92,6 +77,7 @@ internal static void InitLogger()
Logger.Log("Logging initialized.");
+ Logger.Log("Starting Mod logging!");
}
private static string PrevMSG = "";
private static void HandleUnityLogs(string condition, string stackTrace, LogType type)
@@ -104,26 +90,24 @@ private static void HandleUnityLogs(string condition, string stackTrace, LogType
{
case LogType.Error:
Logger.Error(condition, true);
- Logger.Error(stackTrace, true);
+ Logger.Error(stackTrace, true);
break;
case LogType.Warning:
- Logger.Warning(condition, true);
+ Logger.Warning(condition, true);
break;
case LogType.Log:
- Logger.Log(condition, true);
+ Logger.Log(condition, true);
break;
case LogType.Exception:
Logger.Error(condition, true);
- Logger.Error(stackTrace, true);
+ Logger.Error(stackTrace, true);
break;
case LogType.Assert:
Logger.Error(condition, true);
- Logger.Error(stackTrace, true);
+ Logger.Error(stackTrace, true);
break;
}
}
-
-
///
/// Logs into console and output_log.txt
///
@@ -132,7 +116,6 @@ public static void Log(string message, bool doublestack = false)
string formattedString;
if (doublestack)
{
-
formattedString = $"[INFO : Unity] {message}";
}
else
@@ -140,15 +123,11 @@ public static void Log(string message, bool doublestack = false)
formattedString = $"[INFO : {GetCallingClass()}] {message}";
}
//string formattedString = $"[INFO : {GetCallingClass()}] {message}";
-
PrevMSG = formattedString;
-
Console.ForegroundColor = ConsoleColor.Gray;
-
Console.WriteLine(formattedString);
UnityEngine.Debug.Log(formattedString);
}
-
///
/// Logs a warning into console and logs to output_log.txt
///
@@ -157,24 +136,18 @@ public static void Warning(string message, bool doublestack = false)
string formattedString;
if (doublestack)
{
-
formattedString = $"[WARNING : Unity] {message}";
}
else
{
formattedString = $"[WARNING : {GetCallingClass()}] {message}";
}
-
PrevMSG = formattedString;
-
Console.ForegroundColor = ConsoleColor.Yellow;
-
Console.WriteLine(formattedString);
UnityEngine.Debug.LogWarning(formattedString);
-
Console.ForegroundColor = ConsoleColor.Gray;
}
-
///
/// Logs an error into console and logs to output_log.txt
///
@@ -183,7 +156,6 @@ public static void Error(string message, bool doublestack = false)
string formattedString;
if (doublestack)
{
-
formattedString = $"[ERROR : Unity] {message}";
}
else
@@ -191,17 +163,12 @@ public static void Error(string message, bool doublestack = false)
formattedString = $"[ERROR : {GetCallingClass()}] {message}";
}
//string formattedString = $"[ERROR : {GetCallingClass()}] {message}";
-
PrevMSG = formattedString;
-
Console.ForegroundColor = ConsoleColor.Red;
-
Console.WriteLine(formattedString);
UnityEngine.Debug.LogError(formattedString);
-
Console.ForegroundColor = ConsoleColor.Gray;
}
-
///
/// Logs an debug message into console and logs to output_log.txt.
///
@@ -213,28 +180,21 @@ public static void Debug(string message, bool doublestack = false)
{
return;
}
-
string formattedString;
if (doublestack)
{
-
formattedString = $"[DEBUG : Unity] {message}";
}
else
{
formattedString = $"[DEBUG : {GetCallingClass()}] {message}";
}
-
PrevMSG = formattedString;
-
Console.ForegroundColor = ConsoleColor.White;
-
Console.WriteLine(formattedString);
- UnityEngine.Debug.Log(formattedString);
-
+ UnityEngine.Debug.LogError(formattedString);
Console.ForegroundColor = ConsoleColor.Gray;
}
-
// AttachConsole lets me "hook" the logger into the thing
[DllImport("kernel32.dll")]
private static extern bool AttachConsole(uint dwProcessId);
diff --git a/ModLoader.cs b/ModLoader.cs
index d17680f..3ee2282 100644
--- a/ModLoader.cs
+++ b/ModLoader.cs
@@ -1,4 +1,4 @@
-using System.IO;
+using System.IO;
using YamlDotNet.Serialization;
using YamlDotNet.Serialization.NamingConventions;
using System.Reflection;
@@ -15,9 +15,9 @@ namespace Splotch.Loader.ModLoader
///
internal static class ModLoader
{
- static readonly string MOD_FOLDER_PATH = "splotch_mods";
- static readonly string MOD_INFO_FILE_NAME = "modinfo.yaml";
- static readonly string UNZIPPED_MOD_TEMP_FOLDER = @"splotch_mods\temp";
+ static string MOD_FOLDER_PATH = "splotch_mods";
+ static readonly string MOD_INFO_FILE_NAME = "modinfo.yaml";
+ static string UNZIPPED_MOD_TEMP_FOLDER = @"splotch_mods\temp"; // Can't have as readonly because thunderstore
public static DirectoryInfo modFolderDirectory;
public static DirectoryInfo modFolderTempDirectory;
@@ -27,6 +27,12 @@ internal static class ModLoader
internal static void LoadMods()
{
Logger.Log("Starting to load mods...");
+ if (Loader.ModPath != null)
+ {
+ Logger.Log($"Loading mods from Thunderstore mod manager path {Loader.ModPath}");
+ MOD_FOLDER_PATH = Loader.ModPath;
+ UNZIPPED_MOD_TEMP_FOLDER = Loader.ModPath + "\\temp";
+ }
int modCountLoaded = 0;
int modCountTot = 0;
modFolderDirectory = Directory.CreateDirectory(MOD_FOLDER_PATH);
@@ -46,9 +52,12 @@ internal static void LoadMods()
}
}
+ Dictionary loadedMods = new Dictionary();
- foreach (DirectoryInfo modFolder in modFolderDirectory.GetDirectories().AddRangeToArray(modFolderTempDirectory.GetDirectories()))
+ foreach (DirectoryInfo modFolder in modFolderDirectory.GetDirectories().AddRangeToArray(modFolderTempDirectory.GetDirectories()))
{
+ if (modFolder.FullName == modFolderTempDirectory.FullName) continue;
+
modCountTot++;
string modFolderPath = modFolder.FullName;
string modInfoPath = Path.Combine(modFolderPath, MOD_INFO_FILE_NAME);
@@ -60,22 +69,15 @@ internal static void LoadMods()
using (StreamReader reader = new StreamReader(modInfoPath))
{
IDeserializer deserializer = new DeserializerBuilder()
- .IgnoreUnmatchedProperties()
.WithNamingConvention(CamelCaseNamingConvention.Instance).Build();
DeserializedModInfo deserializedData = deserializer.Deserialize(reader);
data = deserializedData.ToModInfo();
-
- if (data.dll == null) throw new KeyNotFoundException("modinfo.yaml must contain the key dll!");
- if (data.className == null) throw new KeyNotFoundException("modinfo.yaml must contain the key className!");
- if (data.id == null) throw new KeyNotFoundException("modinfo.yaml must contain the key id!");
- if (data.name == null) throw new KeyNotFoundException("modinfo.yaml must contain the key name!");
}
bool loadSuccess = data.LoadMod(modFolderPath);
if (loadSuccess)
{
- Logger.Log($"{data} loaded");
- modCountLoaded++;
+ loadedMods.Add(data.id, data);
//Debug.Log($"{data} loaded");
}
else
@@ -93,13 +95,48 @@ internal static void LoadMods()
}
else
{
- if (modFolder.Name == "temp") continue;
Logger.Warning($"Invalid mod folder {modFolder.Name}!");
//Debug.LogWarning($"Invalid mod folder {modFolder.Name}!");
}
}
+ void LoadWithDependencies(ModInfo mod)
+ {
+ bool modHasAllDep = true;
+
+ foreach (string depId in mod.dependencies)
+ {
+ if (loadedMods.TryGetValue(depId, out ModInfo depMod))
+ {
+ if (depMod.initalized) continue;
+ LoadWithDependencies(depMod);
+ }
+ else
+ {
+ modHasAllDep = false;
+ Logger.Warning($"{mod.name} is missing dependency '{depId}'");
+ }
+ }
+
+ if (!modHasAllDep) return;
+
+ Logger.Log($"{mod} loaded");
+ modCountLoaded++;
+
+ mod.FinishInit();
+ }
+
+ foreach (KeyValuePair pair in loadedMods)
+ {
+ ModInfo mod = pair.Value;
+ if (mod.initalized) continue;
+ LoadWithDependencies(mod);
+ }
+
Logger.Log($"Loaded {modCountLoaded}/{modCountTot} mods successfully!");
+
+ // load patches
+ // Splotch.Patches.SplotchPatches.ApplyPatches(); // someone please fix my code bad please im beg of you!
}
public static void RecursiveDelete(DirectoryInfo baseDir)
@@ -161,9 +198,8 @@ public class ModAttributesData
public string Description { get; set; } = "";
public string Version { get; set; } = "1.0";
public string[] Authors { get; set; } = { };
-
- public bool RequiredOnOtherClients { get; set; } = true;
- }
+ public string[] Dependencies { get; set; } = { };
+ }
///
/// Converts the class into the final ModInfo format.
@@ -171,7 +207,7 @@ public class ModAttributesData
/// The ModInfo representation of the class
internal ModInfo ToModInfo()
{
- return new ModInfo(Entrypoint.Dll, Entrypoint.ClassName, Attributes.Id, Attributes.Name, Attributes.Description, Attributes.Version, Attributes.Authors, Attributes.RequiredOnOtherClients);
+ return new ModInfo(Entrypoint.Dll, Entrypoint.ClassName, Attributes.Id, Attributes.Name, Attributes.Description, Attributes.Version, Attributes.Authors, Attributes.Dependencies);
}
}
@@ -186,12 +222,14 @@ public class ModInfo
public string name;
public string description;
public string version;
- public bool requiredOnOtherClients;
public string[] authors;
+ public string[] dependencies;
- public SplotchMod splotchMod;
+ public SplotchMod splotchMod;
public Assembly assembly;
- internal ModInfo(string dll, string className, string id, string name, string description, string version, string[] authors, bool requiredOnOtherClients)
+ internal bool initalized = false;
+
+ internal ModInfo(string dll, string className, string id, string name, string description, string version, string[] authors, string[] dependencies)
{
this.dll = dll;
this.className = className;
@@ -200,8 +238,18 @@ internal ModInfo(string dll, string className, string id, string name, string de
this.description = description;
this.version = version;
this.authors = authors;
- this.requiredOnOtherClients = requiredOnOtherClients;
- }
+ this.dependencies = dependencies;
+ }
+
+ ///
+ /// Called after every dependency loaded and there was no error.
+ ///
+ internal void FinishInit()
+ {
+ initalized = true;
+ splotchMod.OnLoad();
+ ModManager.loadedMods.Add(this);
+ }
///
/// Attempts to load the mod from the metadata using the dll and className fields to determine the entrypoint.
@@ -215,7 +263,7 @@ internal bool LoadMod(string modFolder)
string dllAbsolutePath = Path.Combine(modFolder, dll);
Logger.Debug($"Loading {dllAbsolutePath}");
- assembly = Assembly.Load(File.ReadAllBytes(dllAbsolutePath));
+ assembly = Assembly.LoadFrom(dllAbsolutePath);
Logger.Debug($"Loaded {assembly}");
Type assemblyEntrypoint = assembly.GetType(className);
@@ -229,9 +277,6 @@ internal bool LoadMod(string modFolder)
{
splotchMod = (SplotchMod)Activator.CreateInstance(assemblyEntrypoint);
splotchMod.Setup(this);
- splotchMod.OnLoad();
-
- ModManager.loadedMods.Add(this);
return true;
}
@@ -243,7 +288,7 @@ internal bool LoadMod(string modFolder)
}
catch (Exception ex)
{
- Logger.Error($"An error occurred while loading the mod {name}: \n{ex.Message}\n{ex.StackTrace}");
+ Logger.Error($"An error occurred while loading the mod {name}: \n{ex.Message}\n{ex.StackTrace}\n{ex.GetType()}");
//Debug.LogError($"An error occurred while loading the mod {name}: \n{ex.Message}\n{ex.StackTrace}");
}
return false;
@@ -258,4 +303,4 @@ public override string ToString()
return $"{name} by {string.Join(", ", authors)} version {version}";
}
}
-}
\ No newline at end of file
+}
diff --git a/ModManager.cs b/ModManager.cs
index 9d0411a..87aa055 100644
--- a/ModManager.cs
+++ b/ModManager.cs
@@ -1,4 +1,4 @@
-using Splotch.Loader.ModLoader;
+using Splotch.Loader.ModLoader;
using System.Collections.Generic;
namespace Splotch
@@ -45,6 +45,7 @@ public static string GetLoadedModsInfoText()
}
i++;
}
+ Logger.Log(modInfoString);
return modInfoString;
}
}
diff --git a/Networker.cs b/Networker.cs
deleted file mode 100644
index 3cfda50..0000000
--- a/Networker.cs
+++ /dev/null
@@ -1,329 +0,0 @@
-using HarmonyLib;
-using Splotch.Loader;
-using Splotch.Loader.ModLoader;
-using Splotch.UserInterface;
-using Steamworks;
-using Steamworks.Data;
-using System;
-using System.Collections.Generic;
-using System.IO.Ports;
-using System.Linq;
-using System.Net.Configuration;
-using System.Reflection;
-using System.Runtime.InteropServices;
-using System.Security.Principal;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace Splotch.Network
-{
- public abstract class Packet
- {
- public static Packet instance;
- public Packet(ushort id)
- {
- instance = this;
- this.id = id;
- }
-
- public static void Send(byte[] data, Connection connection)
- {
- Networker.SendMessageBypass(connection, SplotchUtils.CombineArrays(BitConverter.GetBytes(instance.id + 1), data));
- Logger.Debug($"Sent {SplotchUtils.FormattedList(data)}");
- }
-
- public readonly ushort id;
- public abstract void OnMessage(byte[] data, Connection connection, NetIdentity netIdentity);
- }
-
- public class TestPacket : Packet
- {
- public TestPacket(ushort id) : base(id)
- {
- }
-
- public override void OnMessage(byte[] data, Connection connection, NetIdentity netIdentity)
- {
- SplotchGUI.ShowPopup(Encoding.ASCII.GetString(data));
- }
- }
-
- public class PacketArrangementPacket : Packet
- {
- public PacketArrangementPacket(ushort id) : base(id)
- {
- }
-
- public static void SendPacket(Connection connection)
- {
- var data = Encoding.ASCII.GetBytes(string.Join("%", Networker.registeredPackets.Keys.ToArray()));
- Send(data, connection);
- }
-
- public override void OnMessage(byte[] data, Connection connection, NetIdentity netIdentity)
- {
- if (SteamManager.instance.currentLobby.IsOwnedBy(netIdentity.SteamId))
- {
- string[] ids = Encoding.ASCII.GetString(data).Split('%');
- Networker.packetTypes = new Packet[ids.Length];
- ushort i = 0;
- foreach (var id in ids)
- {
- Networker.packetTypes[i] = (Packet)AccessTools.Constructor(Networker.registeredPackets[id]).Invoke(new object[] { i });
- i++;
- }
- }
- }
- }
-
- public static class Networker
- {
- internal static Dictionary registeredPackets = new Dictionary();
- public static Packet[] packetTypes;
-
- private static Dictionary steamIdFriendPairs = new Dictionary();
- private static Dictionary SplotchPresent = new Dictionary();
- private static Dictionary SplotchInfoPerFriend = new Dictionary();
- private static NetworkedSplotchInfo? LobbySplotchInfo = null;
- internal static void Load()
- {
- Patcher.harmony.PatchAll(typeof(Networker));
- SteamMatchmaking.OnLobbyEntered += OnLobbyEnteredCallback;
- SteamMatchmaking.OnLobbyCreated += OnLobbyCreatedCallback;
-
- MethodInfo baseMethod = AccessTools.Method(typeof(SteamManager), "AddMember");
- HarmonyMethod patchMethod = new HarmonyMethod(typeof(Networker), nameof(Networker.OnConnection));
- Patcher.harmony.Patch(baseMethod, postfix: patchMethod);
-
- Logger.Log($"Networker loaded!");
- }
-
- public static void OnConnection(Lobby lobby, Friend newPlayer)
- {
- steamIdFriendPairs[newPlayer.Id] = newPlayer;
- Logger.Log($"Found lobby connection {newPlayer.Name} with steam id {newPlayer.Id}");
- if (lobby.IsOwnedBy(SteamClient.SteamId))
- {
- Logger.Log($"You own this lobby");
- var connection = SteamManager.instance.connectedPlayers.Last();
- if (connection.id == SteamClient.SteamId)
- {
- Logger.Log($"Connection is you");
- Networker.packetTypes = new Packet[Networker.registeredPackets.Count];
- ushort i = 0;
- foreach (var registeredPacket in registeredPackets.Values)
- {
- Networker.packetTypes[i] = (Packet)AccessTools.Constructor(registeredPacket).Invoke(new object[] { i });
- i++;
- }
- }
- else
- {
- Logger.Log($"Connection is not you");
- PacketArrangementPacket.SendPacket(connection.Connection);
-
- TestPacket.Send(Encoding.ASCII.GetBytes("Hello world!"), connection.Connection);
- }
- }
- }
-
- public static bool GetSplotchPresent(SteamId steamId)
- {
- if (SplotchPresent.ContainsKey(steamId)) return SplotchPresent[steamId];
- if (!steamIdFriendPairs.ContainsKey(steamId)) Logger.Warning($"{steamId} is not present in the steamIdFriendPairs! Only {SplotchUtils.FormattedList(steamIdFriendPairs.Keys)} is present");
- var splotchPresent = SteamManager.instance.currentLobby.GetMemberData(steamIdFriendPairs[steamId], "splotchPresent") == "true";
- SplotchPresent[steamId] = splotchPresent;
- return splotchPresent;
- }
-
-
- public static SteamConnection GetSteamConnectionFromConnection(Connection connection)
- {
- foreach (var steamConnection in SteamManager.instance.connectedPlayers)
- {
- if (steamConnection.Connection.Id == connection.Id) return steamConnection;
- }
- return null;
- }
-
- public static NetworkedSplotchInfo GetSplotchInfo(SteamId steamId)
- {
- if (SplotchInfoPerFriend.ContainsKey(steamId)) return SplotchInfoPerFriend[steamId];
- var splotchInfo = NetworkedSplotchInfo.FromString(SteamManager.instance.currentLobby.GetMemberData(steamIdFriendPairs[steamId], "splotchInfo"));
- SplotchInfoPerFriend[steamId] = splotchInfo;
- return splotchInfo;
- }
-
- public static NetworkedSplotchInfo GetLobbySplotchInfo()
- {
- if (LobbySplotchInfo.HasValue) return LobbySplotchInfo.Value;
- var splotchInfo = NetworkedSplotchInfo.FromString(SteamManager.instance.currentLobby.GetData("splotchInfo"));
- LobbySplotchInfo = splotchInfo;
- return splotchInfo;
- }
-
- private static void OnLobbyCreatedCallback(Result result, Lobby lobby)
- {
- if (result == Result.OK)
- {
- lobby.SetData("splotchPresent", "true");
- lobby.SetData("splotchInfo", NetworkedSplotchInfo.FromCurrent().ToString());
- }
- }
-
- private static void OnLobbyEnteredCallback(Lobby lobby)
- {
- lobby.SetMemberData("splotchPresent", "true");
- lobby.SetMemberData("splotchInfo", NetworkedSplotchInfo.FromCurrent().ToString());
-
- var data = GetLobbySplotchInfo();
- NetworkedSplotchInfo.ModNameCheck(data, NetworkedSplotchInfo.FromCurrent());
- }
-
- [HarmonyReversePatch]
- [HarmonyPatch(typeof(Connection), nameof(Connection.SendMessage), new[] { typeof(byte[]), typeof(SendType) })]
- public static Result SendMessageBypass(object instance, byte[] data, SendType sendType = SendType.Reliable)
- {
- // its a stub so it has no initial content
- throw new NotImplementedException("It's a stub");
- }
-
- [HarmonyPatch(typeof(Connection), nameof(Connection.SendMessage), new[] { typeof(byte[]), typeof(SendType) })]
- [HarmonyPrefix]
- public static void SendMessage(ref Connection __instance, ref byte[] data, ref SendType sendType)
- {
- SteamConnection steamConnection = GetSteamConnectionFromConnection(__instance);
- if (GetSplotchPresent(steamConnection.id))
- {
- data = SplotchUtils.CombineArrays(BitConverter.GetBytes((ushort)0), data);
- Logger.Debug($"Sent {SplotchUtils.FormattedList(data)}");
- }
- }
-
- [HarmonyPatch(typeof(SteamSocket), nameof(SteamSocket.OnMessage))]
- [HarmonyPrefix]
- public static bool OnMessage(ref Connection connection, ref NetIdentity identity, ref IntPtr data, ref int size, ref long messageNum, ref long recvTime, ref int channel)
- {
- if (GetSplotchPresent(identity.SteamId))
- {
- byte[] specialData = new byte[2];
- Marshal.Copy(data, specialData, 0, 2);
-
- ushort messageType = BitConverter.ToUInt16(specialData, 0);
-
- Logger.Debug($"received {SplotchUtils.FormattedList(specialData)}");
-
- size -= 2;
- data = IntPtr.Add(data, 2);
- if (messageType == 0) return true;
- else
- {
- byte[] buffer = new byte[size];
- Marshal.Copy(data, buffer, 0, size);
- packetTypes[messageType - 1].OnMessage(buffer, connection, identity);
- }
- return messageType == 0;
- } else
- Logger.Debug($"splotch is not present on {connection.ConnectionName}");
- return true;
- }
- }
- public struct NetworkedModInfo
- {
- public string id;
- public string version;
-
- public override string ToString()
- {
- return id + "%" + version;
- }
-
- public static NetworkedModInfo FromString(string str)
- {
- var values = str.Split('%');
- return new NetworkedModInfo
- {
- id = values[0],
- version = values[1]
- };
- }
-
- public static NetworkedModInfo FromModInfo(ModInfo mod)
- {
- return new NetworkedModInfo
- {
- id = mod.id,
- version = mod.version
- };
- }
- }
-
- public struct NetworkedSplotchInfo
- {
- public List modInfos;
- public string version;
- public static NetworkedSplotchInfo FromCurrent()
- {
- return new NetworkedSplotchInfo
- {
- version = VersionChecker.currentVersionString,
-
- modInfos = ModManager.loadedMods
- .Where(modinfo => modinfo.requiredOnOtherClients).ToList()
- .ConvertAll(new Converter(NetworkedModInfo.FromModInfo))
- };
- }
-
- public override string ToString()
- {
- return version + "\n" + string.Join("\n", modInfos);
- }
-
- public static NetworkedSplotchInfo FromString(string str)
- {
- NetworkedSplotchInfo networkedSplotchInfo = new NetworkedSplotchInfo();
- List data = new List(str.Split('\n'));
- networkedSplotchInfo.version = data[0];
- data.RemoveAt(0);
- networkedSplotchInfo.modInfos = data.ConvertAll(
- new Converter(NetworkedModInfo.FromString)
- );
- return networkedSplotchInfo;
- }
-
- public bool HasMod(NetworkedModInfo targetModInfo)
- {
- return modInfos.Any(modinfo => targetModInfo.id == modinfo.id);
- }
-
- public static void ModNameCheck(NetworkedSplotchInfo targetMods, NetworkedSplotchInfo currentMods)
- {
- List modsToAdd = new List();
- List modsToRemove = new List();
- foreach (var targetModInfo in targetMods.modInfos)
- {
- if (!currentMods.HasMod(targetModInfo))
- modsToAdd.Add(targetModInfo.id);
- }
-
- foreach (var currentModInfo in currentMods.modInfos)
- {
- if (!targetMods.HasMod(currentModInfo))
- modsToRemove.Add(currentModInfo.id);
- }
-
- if (modsToAdd.Any() || modsToRemove.Any())
- {
- string popuptext = "Your mods do not match the host!";
- if (modsToAdd.Any())
- popuptext += "\nInstall the following mods: " + string.Join(", ", modsToAdd);
- if (modsToRemove.Any())
- popuptext += "\nUninstall the following mods: " + string.Join(", ", modsToRemove);
-
- SplotchGUI.ShowPopup(popuptext.Split(new[] { '\n' }, 2)[0], popuptext.Split(new[] { '\n' }, 2)[1]);
-
- Logger.Warning(popuptext);
- }
- }
- }
-}
diff --git a/Properties/AssemblyInfo.cs b/Properties/AssemblyInfo.cs
index 047ccf4..5d12dfe 100644
--- a/Properties/AssemblyInfo.cs
+++ b/Properties/AssemblyInfo.cs
@@ -36,4 +36,4 @@
// X: major versions
// Y: feature addition/ removal
// Z: small patch/ bugfix
-[assembly: AssemblyVersion("0.5.0")]
+[assembly: AssemblyVersion("0.5.1")]
diff --git a/README.md b/README.md
index 1d7beb7..f7ae172 100644
--- a/README.md
+++ b/README.md
@@ -1,11 +1,67 @@
+
+
+
+# WARNING!
+### Splotch is going to be turned into a BepInEx library. DO NOT make any new mods for this and DO NOT install it to run any mods.
+
# Splotch
-
+[](https://github.com/commandblox/Splotch)
+[](https://github.com/commandblox/Splotch)
+[](https://github.com/commandblox/Splotch/releases)
+[](#)
+[](https://github.com/commandblox/Splotch/issues)
+[](#)
-Splotch is a mod loader for the game Bopl Battle. It runs on [Doorstop](https://github.com/NeighTools/UnityDoorstop) and [HarmonyX](https://github.com/BepInEx/HarmonyX).
+Splotch is a mod loader for the game [Bopl Battle](https://zapraygames.com/), running on [Doorstop](https://github.com/NeighTools/UnityDoorstop) and [HarmonyX](https://github.com/BepInEx/HarmonyX).
+
+## Table of Contents
+1. [Installation](#installation)
+2. [Mod Creation](#mod-creation)
+3. [Roadmap](#roadmap)
+4. [Contributing](#contributing)
+5. [Credits](#credits)
+6. [License](#license)
+7. [Help](#help)
+8. [Statistics](#statistics)
## Installation
-Extract the [latest release](https://github.com/commandblox/Splotch/releases/latest) into the game files of Bopl Battle and start the game. The folder `bopl_mods` should be generated. Put the folder of any mods you want to install and start the game and you should see the names of the mods you installed appear in the bottom right.
+To install Splotch, follow these steps:
+- Extract the [latest release](https://github.com/commandblox/Splotch/releases/latest) into the game files of Bopl Battle.
+- Start the game. A folder named `splotch_mods` should be generated.
+- Place any mods you want to install into this folder.
+- Start the game again, and you should see the names of the installed mods appear in the bottom right corner.
+- The same procedure can be followed to update the game. If using BepInEx, ensure the `doorstop_config.ini` file is from Splotch.
+
+## Mod Creation
+To create mods for Splotch, clone the [template mod](https://github.com/commandblox/Splotch-Mod-Template) and refer to the [wiki](https://github.com/commandblox/Splotch/wiki/Mod-Development) for more information.
+
+## Roadmap
+### Mod Loading
+- [x] Basic functionality
+- [x] Loading from zip files
+- [ ] Mod dependencies
+### APIs
+- [x] Event API (More events needed)
+- [ ] BGL (Bopl Graphics Lib) (in progress)
+- [ ] Ability API (in progress)
+- [ ] Networking Lib (in progress)
+### Other Features
+- [x] General utility class
+- [x] BepInEx compatibility
+- [ ] Built-in mod manager
+
+## Contributing
+Contributions to Splotch are welcome! Feel free to check out the [issues](https://github.com/commandblox/Splotch/issues) and contribute in any way you can.
+
+## Credits
+- **Developer**: Codemob
+- **Developer**: WackyModder
+- **Contributer**: Almafa64
+- **Wiki, Docs & Contributer**: Melon
+
+## License
+This project is licensed under the [WPFTL License](LICENSE).
-## Mod creation
-Clone my [template mod](https://github.com/commandblox/Splotch-Mod-Template) to get started. More info on the [wiki](https://github.com/commandblox/Splotch/wiki/Mod-Development).
+## Help
+If you need assistance, join our [Discord server](https://discord.gg/official-bopl-battle-modding-comunity-1175164882388275310). You can ask for help or discuss anything related to Splotch and modding for Bopl Battle.
diff --git a/Splotch.csproj b/Splotch.csproj
index dd9c7e4..412732e 100644
--- a/Splotch.csproj
+++ b/Splotch.csproj
@@ -42,14 +42,12 @@
-
-
diff --git a/SplotchGUI.cs b/SplotchGUI.cs
deleted file mode 100644
index f3e0537..0000000
--- a/SplotchGUI.cs
+++ /dev/null
@@ -1,81 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using UnityEngine;
-
-namespace Splotch.UserInterface
-{
- public class SplotchGUI : MonoBehaviour
- {
- public static void Load()
- {
- GameObject gameObject = new GameObject("splotch-gui", typeof(SplotchGUI));
- DontDestroyOnLoad(gameObject);
- }
-
- void OnGUI()
- {
-
- }
-
- public static Popup ShowPopup(string title, string text)
- {
- GameObject gameObject = new GameObject($"popup {title}", typeof(Popup));
- DontDestroyOnLoad(gameObject);
- Popup popup = gameObject.GetComponent();
-
- popup.title = title;
- popup.text = text;
- return popup;
- }
-
- public static Popup ShowPopup(string text)
- {
- return ShowPopup(text, "");
- }
- }
-
- public class Popup : MonoBehaviour
- {
- public string title;
- public string text;
- public int width = 300;
- public int textOffset = 20;
- public Rect okbutton = new Rect(0, 0, 75, 20);
-
- void OnGUI()
- {
- var textStyle = new GUIStyle();
- textStyle.alignment = TextAnchor.MiddleLeft;
-
- var height = (int)textStyle.CalcHeight(new GUIContent(text), width);
- var box = new Rect(Screen.width / 2 - width / 2, Screen.height / 2 - height / 2, width, height + textOffset + okbutton.height);
- var infotext = box;
- infotext.y += textOffset;
- infotext.height -= textOffset + okbutton.height;
-
- box.width += 40;
- box.x -= 20;
-
- okbutton.x = box.x + box.width - okbutton.width - 10;
- okbutton.y = box.y + box.height - okbutton.height - 10;
-
- var bgcolor = Color.gray;
- bgcolor.a = 0.7F;
- GUI.backgroundColor = bgcolor;
-
- GUI.Box(box, title);
-
-
-
- GUI.color = Color.white;
- GUI.TextField(infotext, text, textStyle);
- if (GUI.Button(okbutton, "ok"))
- {
- Destroy(gameObject);
- }
- }
- }
-}
diff --git a/SplotchPatches.cs b/SplotchPatches.cs
new file mode 100644
index 0000000..77eb8fe
--- /dev/null
+++ b/SplotchPatches.cs
@@ -0,0 +1,68 @@
+using HarmonyLib;
+using BoplFixedMath
+
+namespace Splotch.Patches
+{
+ public static class SplotchPatches
+ {
+ public static void ApplyPatches()
+ {
+
+ // Harmony Harmony = new Harmony("Harmony") - Melon, 2024
+ Harmony harmony = new Harmony("com.Splotch.splotchpatches");
+
+
+ // epic patching
+ MethodInfo originalfix = AccessTools.Method(typeof(Client), "Awake");
+ MethodInfo splotchfix = AccessTools.Method(typeof(SplotchFixes), "BugFixPatch");
+ harmony.Patch(originalfix, new HarmonyMethod(splotchfix));
+
+ }
+ public class SplotchFixes
+ {
+ // Code from Client - 306-334 - Need to patch this but eh, will do that later.
+ public static bool UpdateInputHistoryReplacement(Client __instance, InputPacketUpdate update)
+ {
+ uint num = this.inputHistoryHeadSeqNum;
+ int num2 = (int)(update.seqNumber - num);
+ if (num2 > 32)
+ {
+ Debug.LogError("Discarded a packet because it was too new");
+ return true;
+ }
+ for (int i = num2 - 1; i >= 0; i--)
+ {
+ uint num = this.inputHistoryHeadSeqNum;
+ int num2 = (int)(update.seqNumber - num);
+ if (num2 > 32)
+ {
+ Debug.LogError("Discarded a packet because it was too new");
+ return true;
+ }
+ for (int i = num2 - 1; i >= 0; i--)
+ {
+ uint num3 = 1U << i;
+ InputPacket inputPacket = default(InputPacket);
+ inputPacket.jump = ((update.jump & num3) > 0U);
+ inputPacket.ab1 = ((update.ab1 & num3) > 0U);
+ inputPacket.ab2 = ((update.ab2 & num3) > 0U);
+ inputPacket.ab3 = ((update.ab3 & num3) > 0U);
+ inputPacket.select = ((update.select & num3) > 0U);
+ inputPacket.start = ((update.start & num3) > 0U);
+ inputPacket.w = ((update.w & num3) > 0U);
+ inputPacket.a = ((update.a & num3) > 0U);
+ inputPacket.s = ((update.s & num3) > 0U);
+ inputPacket.d = ((update.d & num3) > 0U);
+ inputPacket.joystickAngle = update.joystickAngle[i];
+ inputPacket.targetDelayBufferSize = update.targetDelayBufferSize;
+ inputPacket.seqNumber = num + 1U;
+ num += 1U;
+ this.inputHistory.Enqueue(inputPacket);
+ this.inputHistoryHeadSeqNum = inputPacket.seqNumber;
+ }
+ return false;
+ }
+ }
+ }
+
+}
diff --git a/SplotchUtils.cs b/SplotchUtils.cs
index 113cb57..22cecd1 100644
--- a/SplotchUtils.cs
+++ b/SplotchUtils.cs
@@ -22,20 +22,6 @@ public static GameSessionHandler GetGameSessionHandler()
return selfRefField.GetValue(null) as GameSessionHandler;
}
- public static string FormattedList(IEnumerable list)
- {
- return $"{{ {string.Join(", ", list)} }}";
- }
-
- public static T[] CombineArrays(T[] first, T[] second)
- {
- T[] ret = new T[first.Length + second.Length];
- Buffer.BlockCopy(first, 0, ret, 0, first.Length);
- Buffer.BlockCopy(second, 0, ret, first.Length, second.Length);
- return ret;
- }
-
-
///
/// Gets the slime controllers
///
diff --git a/VersionChecker.cs b/VersionChecker.cs
index 3de3bb7..67e98ec 100644
--- a/VersionChecker.cs
+++ b/VersionChecker.cs
@@ -39,6 +39,7 @@ public static void RetrieveVersionInfo()
string[] lines = result.Replace("\n\r", "\n").Replace("\r\n", "\n").Split('\n');
version = lines[0].Split('=')[1];
nightly = lines[1].Split('=')[1];
+ Logger.log(version)
}
}
}
diff --git a/githublogo.png b/githublogo.png
new file mode 100644
index 0000000..d68464c
Binary files /dev/null and b/githublogo.png differ
diff --git a/run.bat b/run.bat
index c7385f8..c000016 100644
--- a/run.bat
+++ b/run.bat
@@ -1,3 +1,3 @@
dotnet build -c release
-xcopy /s .\bin\Release "C:\Program Files (x86)\Steam\steamapps\common\Bopl Battle\Splotch" /Y
-"C:\Program Files (x86)\Steam\steamapps\common\Bopl Battle\BoplBattle.exe"
\ No newline at end of file
+xcopy /s .\bin\Debug "C:\Program Files (x86)\Steam\steamapps\common\Bopl Battle\Splotch" /Y
+"C:\Program Files (x86)\Steam\steamapps\common\Bopl Battle\BoplBattle.exe"
diff --git a/version b/version
index c1a57b3..ae82110 100644
--- a/version
+++ b/version
@@ -1,2 +1,2 @@
-latest=0.4.0
-latestNightly=0.4.0
\ No newline at end of file
+latest=0.5.1
+latestNightly=0.5.1