Decompiled source of Canons v1.0.1

CanonsSixVikings.dll

Decompiled a day ago
using 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);
		}
	}
}