Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of Canons v1.0.1
CanonsSixVikings.dll
Decompiled a day agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Text; using BepInEx; using BepInEx.Configuration; using HarmonyLib; using Jotunn.Entities; using Jotunn.Managers; using Jotunn.Utils; using Microsoft.CodeAnalysis; using SixVikings; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyCompany("CanonsSixVikings")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.1.0")] [assembly: AssemblyInformationalVersion("1.0.1+647996836758923c0de9c8ad4e96c94fa372f426")] [assembly: AssemblyProduct("CanonsSixVikings")] [assembly: AssemblyTitle("CanonsSixVikings")] [assembly: AssemblyVersion("1.0.1.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace SixVikings { internal static class Langue { internal static bool Francais { get { try { return Localization.instance.GetSelectedLanguage() == "French"; } catch (Exception) { return false; } } } internal static string T(string francais, string anglais) { if (!Francais) { return anglais; } return francais; } internal static string Reglage(string anglais, string francais) { return anglais + "\nFR : " + francais; } } } namespace CanonsSixVikings { [BepInPlugin("sixvikings.canons", "SixVikings Canons", "1.0.1")] [BepInDependency(/*Could not decode attribute arguments.*/)] [NetworkCompatibility(/*Could not decode attribute arguments.*/)] public class Plugin : BaseUnityPlugin { [HarmonyPatch(typeof(ZNetScene), "CreateObject", new Type[] { typeof(ZDO) })] private static class CreationObjet { private static bool Prefix(ZNetScene __instance, ZDO zdo, ref GameObject __result) { //IL_0039: Unknown result type (might be due to invalid IL or missing references) try { if (!actif || zdo == null) { return true; } int prefab = zdo.GetPrefab(); bool modeleConnu = prefab == 0 || (Object)(object)__instance.GetPrefab(prefab) != (Object)null; if (suivi.LaisserFaire(actif, prefab, modeleConnu, zdo.m_uid)) { return true; } __result = null; return false; } catch (Exception ex) { if (!erreurDite) { erreurDite = true; if ((Object)(object)instance != (Object)null) { ((BaseUnityPlugin)instance).Logger.LogError((object)("Erreur dans la greffe, le jeu continue sans elle pour cet objet : " + ex)); } } return true; } } } private class CommandeCanons : ConsoleCommand { public override string Name => "canons"; public override string Help => Langue.T("canons : état du correctif. canons on / canons off : l'activer ou le couper sans relancer le jeu.", "canons: status of the fix. canons on / canons off: turn it on or off without restarting the game."); public override void Run(string[] args, Terminal context) { try { bool francais = Langue.Francais; string text = ((args.Length != 0) ? args[0].ToLowerInvariant() : ""); if (text == "on" || text == "off") { instance.reglageActif.Value = text == "on"; } else if (text != "") { instance.Repondre(context, francais ? ("canons : « " + text + " » n'existe pas. Écris canons, canons on ou canons off.") : ("canons: \"" + text + "\" does not exist. Type canons, canons on or canons off.")); return; } instance.Repondre(context, "SixVikings Canons 1.0.1" + (francais ? (" : " + (actif ? "actif" : "coupé")) : (": " + (actif ? "on" : "off"))) + ". " + EtatDeLaGreffe(out var _, francais)); instance.Repondre(context, suivi.Etat(francais)); } catch (Exception ex) { ((BaseUnityPlugin)instance).Logger.LogError((object)ex); } } } public const string ModGuid = "sixvikings.canons"; public const string ModNom = "SixVikings Canons"; public const string ModVersion = "1.0.1"; private const string MethodeDuJeu = "CreateObject"; private const string FormatDate = "yyyy-MM-dd"; private static Plugin instance; private static bool actif; private static bool erreurDite; private static bool greffeRefusee; private static readonly Suivi<ZDOID> suivi = new Suivi<ZDOID>(60.0); private ConfigEntry<bool> reglageActif; private ConfigEntry<string> premierLancement; private ConfigEntry<string> dernierSilence; private bool dateNotee; private bool retraitDit; private void Awake() { //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Expected O, but got Unknown instance = this; reglageActif = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Actif", true, Langue.Reglage("true: an unknown object is reported once, then silenced. false: the game behaves as without this mod. Can also be changed in game: canons on, canons off.", "true : un objet inconnu est signalé une fois, puis passé sous silence. false : le jeu fait comme sans ce mod. Se change aussi en jeu : canons on, canons off.")); premierLancement = ((BaseUnityPlugin)this).Config.Bind<string>("Suivi", "PremierLancement", "", Langue.Reglage("Filled in automatically: the day this mod first ran.", "Rempli tout seul : le jour où ce mod a tourné pour la première fois.")); dernierSilence = ((BaseUnityPlugin)this).Config.Bind<string>("Suivi", "DernierSilence", "", Langue.Reglage("Filled in automatically: the last day this mod had something to silence. After 30 days with nothing, it says in game that it can be removed.", "Rempli tout seul : le dernier jour où ce mod a eu quelque chose à taire. Après 30 jours sans rien, il annonce en jeu qu'il peut être retiré.")); actif = reglageActif.Value; reglageActif.SettingChanged += delegate { actif = reglageActif.Value; }; if (premierLancement.Value == "") { premierLancement.Value = Aujourdhui(); } Harmony val = new Harmony("sixvikings.canons"); try { val.PatchAll(typeof(Plugin).Assembly); } catch (Exception ex) { greffeRefusee = true; ((BaseUnityPlugin)this).Logger.LogError((object)("Harmony a refusé la greffe : " + ex.Message + ((ex.InnerException != null) ? (" — " + ex.InnerException.Message) : ""))); try { val.UnpatchSelf(); } catch (Exception ex2) { ((BaseUnityPlugin)this).Logger.LogError((object)("L'inscription de la greffe refusée n'a pas pu être retirée : " + ex2.Message)); } } bool posee; string text = EtatDeLaGreffe(out posee); if (posee) { ((BaseUnityPlugin)this).Logger.LogInfo((object)text); } else { ((BaseUnityPlugin)this).Logger.LogError((object)text); } CommandManager.Instance.AddConsoleCommand((ConsoleCommand)(object)new CommandeCanons()); } private static string EtatDeLaGreffe(out bool posee, bool francais = true) { MethodInfo methodInfo = AccessTools.Method(typeof(ZNetScene), "CreateObject", new Type[1] { typeof(ZDO) }, (Type[])null); Patches val = ((methodInfo == null) ? null : Harmony.GetPatchInfo((MethodBase)methodInfo)); posee = !greffeRefusee && val != null && val.Prefixes.Any((Patch g) => g.owner == "sixvikings.canons"); if (!posee) { if (!francais) { return "Patch NOT applied to ZNetScene.CreateObject: this mod does nothing. The game has probably changed, a new version of the mod is needed."; } return "Greffe NON posée sur ZNetScene.CreateObject : ce mod ne fait rien. Le jeu a sans doute changé, il faut une nouvelle version du mod."; } string[] array = val.Owners.Where((string o) => o != "sixvikings.canons").ToArray(); if (!francais) { return "Patch applied to ZNetScene.CreateObject. Other mods patched at the same place: " + ((array.Length == 0) ? "none" : string.Join(", ", array)) + ". Active: " + (actif ? "yes" : "no") + "."; } return "Greffe posée sur ZNetScene.CreateObject. Autres mods greffés au même endroit : " + ((array.Length == 0) ? "aucun" : string.Join(", ", array)) + ". Actif : " + (actif ? "oui" : "non") + "."; } private void OnApplicationQuit() { if (suivi.TotalIgnores > 0) { ((BaseUnityPlugin)this).Logger.LogInfo((object)("À la fermeture du jeu, " + suivi.Etat() + ".")); } } private void Update() { string text = suivi.Resume(Time.realtimeSinceStartup); if (text != null) { ((BaseUnityPlugin)this).Logger.LogInfo((object)text); } if (!dateNotee && suivi.TotalIgnores > 0) { dateNotee = true; if (dernierSilence.Value != Aujourdhui()) { dernierSilence.Value = Aujourdhui(); } } if (!retraitDit && (Object)(object)Player.m_localPlayer != (Object)null && (Object)(object)MessageHud.instance != (Object)null) { retraitDit = true; if (Regles.ARetirer(Aujourdhui(), premierLancement.Value, dernierSilence.Value)) { ((BaseUnityPlugin)this).Logger.LogWarning((object)"SixVikings Canons n'a rien eu à taire depuis 30 jours : ce mod peut être retiré."); MessageHud.instance.ShowMessage((MessageType)1, Langue.T("SixVikings Canons n'a rien eu à taire depuis 30 jours : ce mod peut être retiré.", "SixVikings Canons has had nothing to silence for 30 days: this mod can be removed."), 0, (Sprite)null, false, true); } } } private static string Aujourdhui() { return DateTime.Now.ToString("yyyy-MM-dd", CultureInfo.InvariantCulture); } private void Repondre(Terminal terminal, string texte) { if ((Object)(object)terminal != (Object)null) { terminal.AddString(texte); } ((BaseUnityPlugin)this).Logger.LogMessage((object)texte); } } public static class Regles { public const string BouletPlein = "ValheimVehicles_Cannonball_Solid_Projectile"; public const string BouletExplosif = "ValheimVehiclesCannonball_Explosive_Projectile"; private static readonly int NumeroPlein = Numero("ValheimVehicles_Cannonball_Solid_Projectile"); private static readonly int NumeroExplosif = Numero("ValheimVehiclesCannonball_Explosive_Projectile"); public static int Numero(string nom) { int num = 5381; int num2 = num; for (int i = 0; i < nom.Length && nom[i] != 0; i += 2) { num = ((num << 5) + num) ^ nom[i]; if (i == nom.Length - 1 || nom[i + 1] == '\0') { break; } num2 = ((num2 << 5) + num2) ^ nom[i + 1]; } return num + num2 * 1566083941; } public static string NomConnu(int numero, bool francais = true) { if (numero == NumeroPlein) { if (!francais) { return "ValheimRAFT solid cannonball"; } return "boulet plein de ValheimRAFT"; } if (numero == NumeroExplosif) { if (!francais) { return "ValheimRAFT explosive cannonball"; } return "boulet explosif de ValheimRAFT"; } return null; } public static bool LaisserFaire(bool actif, int numero, bool modeleConnu, bool dejaSignale) { if (!(!actif || numero == 0 || modeleConnu)) { return !dejaSignale; } return true; } public static bool ARetirer(string aujourdhui, string premierLancement, string dernierSilence, int jours = 30) { if (!Date(aujourdhui, out var date)) { return false; } if (!Date(string.IsNullOrEmpty(dernierSilence) ? premierLancement : dernierSilence, out var date2)) { return false; } return (date - date2).TotalDays >= (double)jours; } private static bool Date(string texte, out DateTime date) { return DateTime.TryParseExact(texte ?? "", "yyyy-MM-dd", CultureInfo.InvariantCulture, DateTimeStyles.None, out date); } } public sealed class Suivi<TObjet> { private sealed class Compte { public long Tentatives; public long TentativesPeriode; public readonly HashSet<TObjet> Objets = new HashSet<TObjet>(); public readonly HashSet<TObjet> ObjetsPeriode = new HashSet<TObjet>(); } private readonly double periode; private readonly int objetsMax; private readonly HashSet<int> signales = new HashSet<int>(); private readonly Dictionary<int, Compte> comptes = new Dictionary<int, Compte>(); private bool periodeOuverte; private double debutPeriode; private long ignoresPeriode; public long TotalIgnores { get; private set; } public Suivi(double periode, int objetsMax = 10000) { this.periode = periode; this.objetsMax = objetsMax; } public bool DejaSignale(int numero) { return signales.Contains(numero); } public void Signale(int numero) { signales.Add(numero); } public bool LaisserFaire(bool actif, int numero, bool modeleConnu, TObjet objet) { bool dejaSignale = !modeleConnu && DejaSignale(numero); if (Regles.LaisserFaire(actif, numero, modeleConnu, dejaSignale)) { if (actif && numero != 0 && !modeleConnu) { Signale(numero); } return true; } Ignore(numero, objet); return false; } public void Ignore(int numero, TObjet objet) { if (!comptes.TryGetValue(numero, out var value)) { value = new Compte(); comptes[numero] = value; } value.Tentatives++; value.TentativesPeriode++; if (value.Objets.Count < objetsMax) { value.Objets.Add(objet); } if (value.ObjetsPeriode.Count < objetsMax) { value.ObjetsPeriode.Add(objet); } TotalIgnores++; ignoresPeriode++; } public long Tentatives(int numero) { if (!comptes.TryGetValue(numero, out var value)) { return 0L; } return value.Tentatives; } public int Objets(int numero) { if (!comptes.TryGetValue(numero, out var value)) { return 0; } return value.Objets.Count; } public string Resume(double maintenant) { if (ignoresPeriode == 0L) { periodeOuverte = false; return null; } if (!periodeOuverte) { periodeOuverte = true; debutPeriode = maintenant; } if (maintenant - debutPeriode < periode) { return null; } StringBuilder stringBuilder = new StringBuilder(); stringBuilder.Append("objets inconnus passés sous silence en ").Append(Nombre(periode)).Append(" s : "); bool flag = true; foreach (KeyValuePair<int, Compte> compte in comptes) { Compte value = compte.Value; if (value.TentativesPeriode != 0L) { if (!flag) { stringBuilder.Append(" ; "); } flag = false; Decrire(stringBuilder, compte.Key, value.ObjetsPeriode.Count, value.TentativesPeriode); value.TentativesPeriode = 0L; value.ObjetsPeriode.Clear(); } } ignoresPeriode = 0L; periodeOuverte = false; return stringBuilder.ToString(); } public string Etat(bool francais = true) { if (comptes.Count == 0) { if (!francais) { return "no unknown object silenced since launch"; } return "aucun objet inconnu passé sous silence depuis le lancement"; } StringBuilder stringBuilder = new StringBuilder(francais ? "passés sous silence depuis le lancement : " : "silenced since launch: "); bool flag = true; foreach (KeyValuePair<int, Compte> compte in comptes) { if (!flag) { stringBuilder.Append(" ; "); } flag = false; Decrire(stringBuilder, compte.Key, compte.Value.Objets.Count, compte.Value.Tentatives, francais); } return stringBuilder.ToString(); } private void Decrire(StringBuilder texte, int numero, int objets, long tentatives, bool francais = true) { texte.Append(numero.ToString(CultureInfo.InvariantCulture)); string text = Regles.NomConnu(numero, francais); if (text != null) { texte.Append(" (").Append(text).Append(')'); } texte.Append(francais ? " : " : ": "); if (objets >= objetsMax) { texte.Append(francais ? "au moins " : "at least "); } texte.Append(objets).Append(francais ? " objet(s), " : " object(s), ").Append(tentatives) .Append(francais ? " tentative(s)" : " attempt(s)"); } private static string Nombre(double valeur) { return valeur.ToString("0.#", CultureInfo.InvariantCulture); } } }