using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security.Cryptography;
using System.Text;
using BepInEx;
using BepInEx.Logging;
using GameNetcodeStuff;
using HarmonyLib;
using LethalNetworkAPI;
using TMPro;
using TerminalApi;
using TerminalApi.Classes;
using TerminalSeedPicker.Patches;
using Unity.Netcode;
using UnityEngine;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("TerminalSeedPicker")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("TerminalSeedPicker")]
[assembly: AssemblyCopyright("Copyright © 2024")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("febf3383-12d4-4c26-b500-9fec6b0f6c7f")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace TerminalSeedPicker
{
public class Logger
{
public enum LogLevelConfig
{
None,
Important,
Everything
}
internal ManualLogSource MLS;
public string modName = "No-Name";
public string modVersion = "No-Ver";
public void Init(string modGUID = "")
{
MLS = Logger.CreateLogSource(modGUID);
}
public bool LogLevelAllow(LogLevelConfig severity = LogLevelConfig.Important, LogLevelConfig severity2 = LogLevelConfig.Everything)
{
if (severity2 == LogLevelConfig.None)
{
return false;
}
if (severity == LogLevelConfig.Everything)
{
return severity2 == LogLevelConfig.Everything;
}
return true;
}
public void Log(string text = "", LogLevel level = 16, LogLevelConfig severity = LogLevelConfig.Important)
{
//IL_0027: Unknown result type (might be due to invalid IL or missing references)
if (true)
{
string text2 = $"[{modName} v{modVersion}] - {text}";
MLS.Log(level, (object)text2);
}
}
}
[BepInPlugin("thej01.lc.TerminalSeedPicker", "TerminalSeedPicker", "1.0.0")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public class TerminalSeedPickerMod : BaseUnityPlugin
{
public class SeedNetworkData
{
public int? seedToForce = null;
public string seedWordToForce = null;
public bool seedWasString = false;
}
public static class TerminalKeywords
{
public static TerminalKeyword set;
public static TerminalKeyword s;
public static TerminalKeyword seed;
public static TerminalKeyword get;
public static TerminalKeyword check;
public static TerminalKeyword g;
public static TerminalKeyword c;
}
public static class TerminalNodes
{
public static TerminalNode setSeed;
public static TerminalNode getSeed;
}
private const string modGUID = "thej01.lc.TerminalSeedPicker";
private const string modName = "TerminalSeedPicker";
private const string modVersion = "1.0.0";
private readonly Harmony harmony = new Harmony("thej01.lc.TerminalSeedPicker");
private static TerminalSeedPickerMod Instance;
public static Logger seedLogger = new Logger();
public static LethalClientMessage<SeedNetworkData> sendSeedClientMessage = new LethalClientMessage<SeedNetworkData>("thej01.lc.TerminalSeedPicker.sendSeedClientMessage", (Action<SeedNetworkData>)null, (Action<SeedNetworkData, ulong>)null);
public static LethalClientMessage<string> askSeedClientMessage = new LethalClientMessage<string>("thej01.lc.TerminalSeedPicker.askSeedClientMessage", (Action<string>)null, (Action<string, ulong>)null);
public static LethalClientEvent replaceRandomSeedText = new LethalClientEvent("thej01.lc.TerminalSeedPicker.replaceRandomSeedText", (Action)null, (Action<ulong>)null);
public static int maxSeed = 100000000;
public static List<TerminalKeyword> seedCommandGet = new List<TerminalKeyword>();
public static List<TerminalKeyword> seedCommandSet = new List<TerminalKeyword>();
public static SeedNetworkData seedNetworkData = new SeedNetworkData();
public static int? lastSeedToForce = null;
public static string lastSeedWordToForce = null;
public static bool lastSeedWasString = false;
public static string terminalMsg = "";
public void InitConfigValues(Logger seedLogger)
{
seedLogger.Log("Initialising config values...", (LogLevel)16);
seedLogger.Log("Config values initialised.", (LogLevel)16);
}
public void InitAllConfigBinds(Logger seedLogger)
{
}
public void InitConfig(Logger seedLogger)
{
seedLogger.Log("Initialising config...", (LogLevel)8);
InitAllConfigBinds(seedLogger);
InitConfigValues(seedLogger);
seedLogger.Log("Config initialised.", (LogLevel)8);
}
public static string GetNumWord(string text = "", int targetWordNum = 1)
{
int num = 1;
int num2 = 0;
StringBuilder stringBuilder = new StringBuilder();
foreach (char c in text)
{
num2++;
if (char.IsWhiteSpace(c))
{
if (num >= targetWordNum)
{
return stringBuilder.ToString();
}
num++;
stringBuilder.Clear();
}
else
{
stringBuilder.Append(c);
}
if (num2 >= text.Length && num < targetWordNum)
{
seedLogger.Log("Reached the end of word before reaching targetWordNum, returning blank.", (LogLevel)4);
return "";
}
}
return stringBuilder.ToString();
}
public static string StartStringAtWord(string text = "", string targetWordCut = "")
{
int num = 0;
int startIndex = 0;
StringBuilder stringBuilder = new StringBuilder();
foreach (char c in text)
{
num++;
if (char.IsWhiteSpace(c))
{
if (targetWordCut == stringBuilder.ToString())
{
return text.Substring(startIndex);
}
stringBuilder.Clear();
startIndex = num;
}
else
{
stringBuilder.Append(c);
}
if (num >= text.Length)
{
seedLogger.Log("Reached the end of word before reaching targetWordCut, returning blank.", (LogLevel)4);
return "";
}
}
return stringBuilder.ToString();
}
public static bool IsStringOnlyNumbers(string text = "")
{
foreach (char c in text)
{
if (!char.IsNumber(c))
{
return false;
}
}
return true;
}
public static void LogTerminalAudioClips()
{
Terminal val = Object.FindObjectOfType<Terminal>();
int num = 0;
AudioClip[] syncedAudios = val.syncedAudios;
foreach (AudioClip val2 in syncedAudios)
{
string text = $"TERMINAL AUDIO CLIP {num}: {((Object)val2).name}";
seedLogger.Log(text, (LogLevel)8, Logger.LogLevelConfig.Everything);
num++;
}
}
public static void PlayTerminalAudio(int audioIndex)
{
Terminal val = Object.FindObjectOfType<Terminal>();
val.PlayTerminalAudioClientRpc(audioIndex);
}
public static string RunSeedCommand()
{
string numWord = GetNumWord(terminalMsg);
seedLogger.Log("Trying get keywords...", (LogLevel)8);
foreach (TerminalKeyword item in seedCommandGet)
{
seedLogger.Log("CUR GET KEYWORD: " + item.word, (LogLevel)8);
if (item.word == numWord)
{
return RunGetSeedCommand();
}
}
seedLogger.Log("Didn't find a get keyword! Trying set...", (LogLevel)8);
foreach (TerminalKeyword item2 in seedCommandSet)
{
seedLogger.Log("CUR SET KEYWORD: " + item2.word, (LogLevel)8);
if (item2.word == numWord)
{
return RunSetSeedCommand();
}
}
PlayTerminalAudio(1);
return "['" + numWord + "' cannot be applied to seed.]\n\n";
}
public static string RunSetSeedCommand()
{
StartMatchLever val = Object.FindObjectOfType<StartMatchLever>();
LogTerminalAudioClips();
int audioIndex = 1;
if (GameNetworkManager.Instance.currentSaveFileName == "LCChallengeFile")
{
PlayTerminalAudio(audioIndex);
return "[Seed cannot be changed on a Challenge Moon.]\n\n";
}
if (!val.triggerScript.interactable && GameNetworkManager.Instance.gameHasStarted)
{
PlayTerminalAudio(audioIndex);
return "[Ship cannot be leaving or landing!]\n\n";
}
if (!val.playersManager.inShipPhase)
{
PlayTerminalAudio(audioIndex);
return "[Seed can only be changed while in orbit.]\n\n";
}
string text = StartStringAtWord(terminalMsg, "seed");
seedLogger.Log("Parsed Command: " + text, (LogLevel)8);
string numWord = GetNumWord(text, 2);
seedLogger.Log("Seed word: " + numWord, (LogLevel)8);
if (numWord == "" || numWord == " ")
{
seedLogger.Log("Seed word was invalid! Denying.", (LogLevel)8);
PlayTerminalAudio(audioIndex);
return "[Please input a valid seed.]\n\n";
}
if (IsStringOnlyNumbers(numWord))
{
seedNetworkData.seedWasString = false;
seedNetworkData.seedWordToForce = null;
string result = "[Failed to set seed!]\n[Please try again.]\n\n";
try
{
bool flag = false;
seedNetworkData.seedToForce = int.Parse(numWord);
if (seedNetworkData.seedToForce > maxSeed)
{
seedNetworkData.seedToForce = null;
result = "[Seed cannot be greater than 100,000,000!]\n\n";
flag = true;
}
if (seedNetworkData.seedToForce < 0)
{
seedNetworkData.seedToForce = null;
result = "[Seed cannot be less than 0!]\n\n";
flag = true;
}
if (!flag)
{
seedNetworkData.seedWordToForce = "Raw Number";
audioIndex = 2;
result = $"[Moon seed has been set to {seedNetworkData.seedToForce}]\n[Raw number.]\n\n";
sendSeedClientMessage.SendAllClients(seedNetworkData, true, false);
}
}
catch (Exception ex)
{
seedLogger.Log("Unable to parse '" + numWord + "', err: " + ex.Message, (LogLevel)2);
}
PlayTerminalAudio(audioIndex);
return result;
}
seedNetworkData.seedToForce = GenerateSeedFromString(numWord);
seedNetworkData.seedToForce = (seedNetworkData.seedToForce % maxSeed + maxSeed) % maxSeed;
seedNetworkData.seedWordToForce = numWord;
seedNetworkData.seedWasString = true;
audioIndex = 2;
PlayTerminalAudio(audioIndex);
sendSeedClientMessage.SendAllClients(seedNetworkData, true, false);
return $"[Moon seed has been set to {seedNetworkData.seedToForce}]\n[Generated from '{numWord}'.]\n\n";
}
public static string RunGetSeedCommand()
{
StartMatchLever val = Object.FindObjectOfType<StartMatchLever>();
int audioIndex = 1;
if (val.playersManager.inShipPhase)
{
PlayTerminalAudio(audioIndex);
return "[Must land on a planet first!]\n\n";
}
string text = $"[Random Seed: {StartOfRound.Instance.randomMapSeed}]";
string text2 = "\n\n";
string text3 = $"lastSeedToForce: {lastSeedToForce}, lastSeedWasString: {lastSeedWasString}, lastSeedWordToForce: {lastSeedWordToForce}";
seedLogger.Log(text3, (LogLevel)8);
if (lastSeedToForce.HasValue || GameNetworkManager.Instance.currentSaveFileName == "LCChallengeFile")
{
text = $"[Set Seed: {StartOfRound.Instance.randomMapSeed}]";
text2 = ((!lastSeedWasString) ? "\n[Raw Number]\n\n" : ("\n[Generated from: '" + lastSeedWordToForce + "']\n\n"));
if (GameNetworkManager.Instance.currentSaveFileName == "LCChallengeFile")
{
text2 = "\n[Challenge Moon]\n\n";
}
}
return text + text2;
}
private static int GenerateSeedFromString(string input)
{
byte[] bytes = Encoding.UTF8.GetBytes(input);
using SHA256 sHA = SHA256.Create();
byte[] value = sHA.ComputeHash(bytes);
return BitConverter.ToInt32(value, 0);
}
private void Awake()
{
//IL_02f2: Unknown result type (might be due to invalid IL or missing references)
//IL_02f8: Expected O, but got Unknown
if ((Object)(object)Instance == (Object)null)
{
Instance = this;
}
seedLogger.Init("thej01.lc.TerminalSeedPicker");
seedLogger.modName = "TerminalSeedPicker";
seedLogger.modVersion = "1.0.0";
seedLogger.Log("seedLogger Initialised!", (LogLevel)16, Logger.LogLevelConfig.Everything);
InitConfig(seedLogger);
seedLogger.Log("Patching TerminalSeedPickerMod...", (LogLevel)16, Logger.LogLevelConfig.Everything);
harmony.PatchAll(typeof(TerminalSeedPickerMod));
seedLogger.Log("Patched TerminalSeedPickerMod.", (LogLevel)16, Logger.LogLevelConfig.Everything);
seedLogger.Log("Patching TerminalPatch...", (LogLevel)16, Logger.LogLevelConfig.Everything);
harmony.PatchAll(typeof(TerminalPatch));
seedLogger.Log("Patched TerminalPatch.", (LogLevel)16, Logger.LogLevelConfig.Everything);
seedLogger.Log("Patching StartOfRoundPatch...", (LogLevel)16, Logger.LogLevelConfig.Everything);
harmony.PatchAll(typeof(StartOfRoundPatch));
seedLogger.Log("Patched StartOfRoundPatch.", (LogLevel)16, Logger.LogLevelConfig.Everything);
seedLogger.Log("Patching RoundManagerPatch...", (LogLevel)16, Logger.LogLevelConfig.Everything);
harmony.PatchAll(typeof(RoundManagerPatch));
seedLogger.Log("Patched RoundManagerPatch.", (LogLevel)16, Logger.LogLevelConfig.Everything);
seedLogger.Log("Patching PlayerControllerBPatch...", (LogLevel)16, Logger.LogLevelConfig.Everything);
harmony.PatchAll(typeof(PlayerControllerBPatch));
seedLogger.Log("Patched PlayerControllerBPatch.", (LogLevel)16, Logger.LogLevelConfig.Everything);
seedLogger.Log("Initialising terminal commands...", (LogLevel)8);
TerminalNodes.setSeed = TerminalApi.CreateTerminalNode("Hello world!!!\n", true, "");
TerminalNodes.getSeed = TerminalApi.CreateTerminalNode("Hello world 2!!!\n", true, "");
TerminalKeywords.set = TerminalApi.CreateTerminalKeyword("set", true, (TerminalNode)null);
TerminalKeywords.s = TerminalApi.CreateTerminalKeyword("s", true, (TerminalNode)null);
TerminalKeywords.seed = TerminalApi.CreateTerminalKeyword("seed", false, TerminalNodes.setSeed);
TerminalKeywords.get = TerminalApi.CreateTerminalKeyword("get", true, (TerminalNode)null);
TerminalKeywords.g = TerminalApi.CreateTerminalKeyword("g", true, (TerminalNode)null);
TerminalKeywords.check = TerminalApi.CreateTerminalKeyword("check", true, (TerminalNode)null);
TerminalKeywords.c = TerminalApi.CreateTerminalKeyword("c", true, (TerminalNode)null);
TerminalKeywords.set = TerminalExtenstionMethods.AddCompatibleNoun(TerminalKeywords.set, TerminalKeywords.seed, TerminalNodes.setSeed);
TerminalKeywords.s = TerminalExtenstionMethods.AddCompatibleNoun(TerminalKeywords.s, TerminalKeywords.seed, TerminalNodes.setSeed);
TerminalKeywords.get = TerminalExtenstionMethods.AddCompatibleNoun(TerminalKeywords.get, TerminalKeywords.seed, TerminalNodes.getSeed);
TerminalKeywords.g = TerminalExtenstionMethods.AddCompatibleNoun(TerminalKeywords.g, TerminalKeywords.seed, TerminalNodes.getSeed);
TerminalKeywords.check = TerminalExtenstionMethods.AddCompatibleNoun(TerminalKeywords.check, TerminalKeywords.seed, TerminalNodes.getSeed);
TerminalKeywords.c = TerminalExtenstionMethods.AddCompatibleNoun(TerminalKeywords.c, TerminalKeywords.seed, TerminalNodes.getSeed);
TerminalKeywords.seed.defaultVerb = TerminalKeywords.set;
TerminalKeyword seed = TerminalKeywords.seed;
CommandInfo val = new CommandInfo();
val.Title = "[Set/Get] SEED [Seed]";
val.TriggerNode = TerminalNodes.setSeed;
val.DisplayTextSupplier = RunSeedCommand;
val.Category = "Other";
val.Description = "Type set to set seed, Text or numbers allowed.\nType get to get info on the current seed.";
TerminalApi.AddTerminalKeyword(seed, val);
seedCommandSet.Add(TerminalKeywords.set);
seedCommandSet.Add(TerminalKeywords.s);
seedCommandGet.Add(TerminalKeywords.get);
seedCommandGet.Add(TerminalKeywords.g);
seedCommandGet.Add(TerminalKeywords.check);
seedCommandGet.Add(TerminalKeywords.c);
seedLogger.Log("Initialised terminal commands!", (LogLevel)8);
sendSeedClientMessage.OnReceivedFromClient += ReceiveFromClient;
askSeedClientMessage.OnReceivedFromClient += ReceiveAskSeed;
replaceRandomSeedText.OnReceivedFromClient += ReceiveRandomSeedEvent;
}
private void ReceiveFromClient(SeedNetworkData data, ulong clientId)
{
seedNetworkData = data;
seedLogger.Log($"Recieved seedNetworkData Client MSG from {clientId}", (LogLevel)8);
}
private void ReceiveAskSeed(string data, ulong clientId)
{
if (data == "sendSeed" && ((NetworkBehaviour)GameNetworkManager.Instance.localPlayerController).IsServer)
{
sendSeedClientMessage.SendAllClients(seedNetworkData, true, false);
}
}
private void ReceiveRandomSeedEvent(ulong clientId)
{
seedLogger.Log($"Replacing random seed text! Sent from {clientId}", (LogLevel)8);
seedLogger.Log("Level loaded, initialising variables.", (LogLevel)8);
RoundManagerPatch.newLoadingText = "";
if (seedNetworkData.seedToForce.HasValue || GameNetworkManager.Instance.currentSaveFileName == "LCChallengeFile")
{
RoundManagerPatch.newLoadingText = RoundManagerPatch.GetText();
}
else
{
seedLogger.Log("seedNetworkData.seedToForce was null or not on a challenge moon! Not changing text.", (LogLevel)8);
}
lastSeedWordToForce = seedNetworkData.seedWordToForce;
lastSeedToForce = seedNetworkData.seedToForce;
lastSeedWasString = seedNetworkData.seedWasString;
seedNetworkData.seedWordToForce = null;
seedNetworkData.seedToForce = null;
seedNetworkData.seedWasString = false;
}
}
}
namespace TerminalSeedPicker.Patches
{
[HarmonyPatch(typeof(PlayerControllerB))]
internal class PlayerControllerBPatch
{
[HarmonyPatch("SpawnPlayerAnimation")]
[HarmonyPostfix]
private static void PostSpawnIn()
{
TerminalSeedPickerMod.seedLogger.Log("Spawned in! Initialising, then asking for seed data!", (LogLevel)8);
TerminalSeedPickerMod.seedNetworkData.seedToForce = null;
TerminalSeedPickerMod.lastSeedToForce = null;
TerminalSeedPickerMod.seedNetworkData.seedWasString = false;
TerminalSeedPickerMod.lastSeedWasString = false;
TerminalSeedPickerMod.seedNetworkData.seedWordToForce = null;
TerminalSeedPickerMod.lastSeedWordToForce = null;
StartOfRound.Instance.overrideRandomSeed = false;
TerminalSeedPickerMod.seedLogger.Log("Asking now...", (LogLevel)8);
TerminalSeedPickerMod.askSeedClientMessage.SendAllClients("sendSeed", true, false);
}
}
[HarmonyPatch(typeof(RoundManager))]
internal class RoundManagerPatch
{
public static string newLoadingText = "";
[HarmonyPatch("GenerateNewLevelClientRpc")]
[HarmonyPostfix]
public static void PostGenerateNewLevel()
{
if (newLoadingText != "" && ((TMP_Text)HUDManager.Instance.loadingText).text.Contains("Random"))
{
((TMP_Text)HUDManager.Instance.loadingText).text = newLoadingText;
TerminalSeedPickerMod.seedLogger.Log("Random Seed text succesfully replaced with: '" + newLoadingText + "'!", (LogLevel)8);
}
}
[HarmonyPatch("LoadNewLevel")]
[HarmonyPostfix]
public static void PostLoadLevel()
{
TerminalSeedPickerMod.replaceRandomSeedText.InvokeAllClients(true, false);
StartOfRound.Instance.overrideRandomSeed = false;
}
public static string GetText()
{
string text = $"Set Seed: {TerminalSeedPickerMod.seedNetworkData.seedToForce}";
string text2 = "";
text2 = ((!TerminalSeedPickerMod.seedNetworkData.seedWasString) ? ("\n" + TerminalSeedPickerMod.seedNetworkData.seedWordToForce) : ("\n(Generated from: " + TerminalSeedPickerMod.seedNetworkData.seedWordToForce + ")"));
if (GameNetworkManager.Instance.currentSaveFileName == "LCChallengeFile")
{
text2 = "\n(Challenge Moon)";
}
text += text2;
TerminalSeedPickerMod.seedLogger.Log("Intended seed text: " + text, (LogLevel)8);
return text;
}
}
[HarmonyPatch(typeof(StartOfRound))]
internal class StartOfRoundPatch
{
[HarmonyPatch(typeof(StartOfRound), "StartGame")]
[HarmonyPrefix]
public static void PreStartGame(ref StartOfRound __instance)
{
if (TerminalSeedPickerMod.seedNetworkData.seedToForce.HasValue)
{
string arg = (TerminalSeedPickerMod.seedNetworkData.seedWasString ? ("Generated from: " + TerminalSeedPickerMod.seedNetworkData.seedWordToForce) : TerminalSeedPickerMod.seedNetworkData.seedWordToForce);
string text = $"Seed **should** be overridden by {TerminalSeedPickerMod.seedNetworkData.seedToForce} ({arg})";
TerminalSeedPickerMod.seedLogger.Log(text, (LogLevel)8);
__instance.overrideRandomSeed = true;
__instance.overrideSeedNumber = TerminalSeedPickerMod.seedNetworkData.seedToForce.Value;
}
}
}
[HarmonyPatch(typeof(Terminal))]
internal class TerminalPatch
{
[HarmonyPatch(typeof(Terminal), "ParsePlayerSentence")]
[HarmonyPrefix]
public static void PreParsePlayerSentence(ref Terminal __instance)
{
string s = __instance.screenText.text.Substring(__instance.screenText.text.Length - __instance.textAdded);
s = RemovePunctuationWhyCantIUseItFromInstance(s);
TerminalSeedPickerMod.terminalMsg = s;
string text = $"Terminal String: {TerminalSeedPickerMod.terminalMsg}";
TerminalSeedPickerMod.seedLogger.Log(text, (LogLevel)8);
}
public static string RemovePunctuationWhyCantIUseItFromInstance(string s)
{
StringBuilder stringBuilder = new StringBuilder();
foreach (char c in s)
{
if (!char.IsPunctuation(c))
{
stringBuilder.Append(c);
}
}
return stringBuilder.ToString().ToLower();
}
}
}