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 New Game Plus v1.0.8
plugins/NewGamePlus.dll
Decompiled 2 months ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.IO.Compression; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Serialization; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using API; using BepInEx; using BepInEx.Configuration; using HarmonyLib; using JetBrains.Annotations; using Microsoft.CodeAnalysis; using ServerSync; using TMPro; 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("NewGamePlus")] [assembly: AssemblyDescription("NewGamePlus")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("NewGamePlus")] [assembly: AssemblyCopyright("Copyright © 2025")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("b8f1a3c4-5dcf-4df6-899e-73f354a55c84")] [assembly: AssemblyFileVersion("1.2.0")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.2.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.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 radamanto.NG { [HarmonyPatch] internal static class NGPlus_DamagePatch { [HarmonyPatch(typeof(Character), "Damage", new Type[] { typeof(HitData) })] [HarmonyPrefix] private static void Prefix(Character __instance, ref HitData hit) { if (!NewGamePlusPlugin.CE_Enable.Value) { return; } Player val = (Player)(object)((__instance is Player) ? __instance : null); if (val != null) { SEMan sEMan = ((Character)val).GetSEMan(); if (sEMan != null && sEMan.HaveStatusEffect(NGPlus_StatusEffect.SE_Hash)) { float value = NewGamePlusPlugin.CE_DamageTakenPercent.Value; if (Mathf.Abs(value) > 0.001f) { float multiplier = 1f + value / 100f; ScaleDamage(ref hit, multiplier); } } } Character attacker = hit.GetAttacker(); Player val2 = (Player)(object)((attacker is Player) ? attacker : null); if (!((Object)(object)val2 != (Object)null)) { return; } SEMan sEMan2 = ((Character)val2).GetSEMan(); if (sEMan2 != null && sEMan2.HaveStatusEffect(NGPlus_StatusEffect.SE_Hash)) { float value2 = NewGamePlusPlugin.CE_DamageDonePercent.Value; if (Mathf.Abs(value2) > 0.001f) { float multiplier2 = 1f + value2 / 100f; ScaleDamage(ref hit, multiplier2); } } } private static void ScaleDamage(ref HitData hit, float multiplier) { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) if (!(Mathf.Abs(multiplier - 1f) < 0.001f)) { DamageTypes damage = hit.m_damage; damage.m_blunt *= multiplier; damage.m_slash *= multiplier; damage.m_pierce *= multiplier; damage.m_chop *= multiplier; damage.m_pickaxe *= multiplier; damage.m_fire *= multiplier; damage.m_frost *= multiplier; damage.m_lightning *= multiplier; damage.m_poison *= multiplier; damage.m_spirit *= multiplier; hit.m_damage = damage; } } } [HarmonyPatch(typeof(SE_Stats), "Setup")] internal static class NGPlus_RegenerationPatch { private static void Postfix(SE_Stats __instance) { if (((StatusEffect)__instance).m_nameHash == NGPlus_StatusEffect.SE_Hash) { float value = NewGamePlusPlugin.CE_RegenHealthPercent.Value; if (Mathf.Abs(value) > 0.001f) { float num = 1f + value / 100f; __instance.m_healthRegenMultiplier *= num; } float value2 = NewGamePlusPlugin.CE_RegenStaminaPercent.Value; if (Mathf.Abs(value2) > 0.001f) { float num2 = 1f + value2 / 100f; __instance.m_staminaRegenMultiplier *= num2; } float value3 = NewGamePlusPlugin.CE_RegenEitrPercent.Value; if (Mathf.Abs(value3) > 0.001f) { float num3 = 1f + value3 / 100f; __instance.m_eitrRegenMultiplier *= num3; } } } } [HarmonyPatch(typeof(SE_Stats), "ModifyMaxCarryWeight")] internal static class NGPlus_CarryWeightPatch { private static void Postfix(SE_Stats __instance, float baseLimit, ref float limit) { if (((StatusEffect)__instance).m_nameHash == NGPlus_StatusEffect.SE_Hash) { float value = NewGamePlusPlugin.CE_CarryWeightAdd.Value; if (value != 0f) { limit += value; } } } } [HarmonyPatch(typeof(Inventory), "IsTeleportable")] internal static class NGPlus_PortalBypass { private static void Postfix(Inventory __instance, ref bool __result) { try { if (__result || !NewGamePlusPlugin.CE_IgnorePortalRestrictionsWithNGPlus.Value) { return; } Player localPlayer = Player.m_localPlayer; if (!((Object)(object)localPlayer == (Object)null) && ((Humanoid)localPlayer).GetInventory() == __instance) { SEMan sEMan = ((Character)localPlayer).GetSEMan(); if (sEMan != null && sEMan.HaveStatusEffect(NGPlus_StatusEffect.SE_Hash)) { __result = true; } } } catch { } } } internal static class NGPlus_SkillReset { internal static void ResetIfEnabled(Player player) { //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Invalid comparison between Unknown and I4 //IL_006e: Unknown result type (might be due to invalid IL or missing references) if (!NewGamePlusPlugin.CE_ResetSkillsOnNGPlus.Value || (Object)(object)player == (Object)null) { return; } Skills skills = player.m_skills; if ((Object)(object)skills == (Object)null) { return; } foreach (SkillType value in Enum.GetValues(typeof(SkillType))) { if ((int)value != 0) { skills.ResetSkill(value); } } } } internal static class NGPlus_EpicMMO { internal const string RPC_EpicMMO_ResetTotalPoints = "NGP_EpicMMO_ResetTotalPoints"; private static bool IsEpicMmoInstalled() { return Type.GetType("EpicMMOSystem.EpicMMOSystem, EpicMMOSystem") != null; } internal static void OnNgPlusActivated(Player player) { //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Expected O, but got Unknown if ((Object)(object)player == (Object)null) { return; } if (!IsEpicMmoInstalled()) { ApplyXpRate(player, isNgPlusActive: false); return; } if (NewGamePlusPlugin.CE_EpicMMO_ResetOnNGPlus.Value && ZRoutedRpc.instance != null) { string text = player.GetPlayerName() ?? ""; if (!string.IsNullOrWhiteSpace(text)) { ZPackage val = new ZPackage(); val.Write(text); long serverPeerID = ZRoutedRpc.instance.GetServerPeerID(); if (serverPeerID != 0) { ZRoutedRpc.instance.InvokeRoutedRPC(serverPeerID, "NGP_EpicMMO_ResetTotalPoints", new object[1] { val }); } } } ApplyXpRate(player, isNgPlusActive: true); } internal static void OnNgPlusDeactivated(Player player) { if (IsEpicMmoInstalled()) { ApplyXpRate(player, isNgPlusActive: false); } } private static void ApplyXpRate(Player player, bool isNgPlusActive) { if (!((Object)(object)player == (Object)null) && !((Object)(object)player != (Object)(object)Player.m_localPlayer)) { float singleRate = (isNgPlusActive ? Mathf.Max(0f, NewGamePlusPlugin.CE_EpicMMO_XpMultiplierNGPlus.Value) : 1f); EpicMMOSystem_API.SetSingleRate(singleRate); } } } [BepInPlugin("radamanto.NewGamePlus", "NewGamePlus", "1.0.8")] [BepInDependency(/*Could not decode attribute arguments.*/)] public class NewGamePlusPlugin : BaseUnityPlugin { private class ConfigurationManagerAttributes { public bool? Browsable = false; } [CompilerGenerated] private sealed class <NGP_EarlyXp_WatcherLoop>d__38 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public NewGamePlusPlugin <>4__this; private WaitForSeconds <wait>5__1; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <NGP_EarlyXp_WatcherLoop>d__38(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <wait>5__1 = null; <>1__state = -2; } private bool MoveNext() { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; <wait>5__1 = new WaitForSeconds(2f); break; case 1: <>1__state = -1; break; } try { NGPlus_EarlyGameXp.ReevaluateForLocalPlayer(); } catch { } <>2__current = <wait>5__1; <>1__state = 1; return true; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class <NGP_Reset_RPCRegisterLoop>d__37 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public NewGamePlusPlugin <>4__this; private WaitForSeconds <wait>5__1; private ZNet <znet>5__2; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <NGP_Reset_RPCRegisterLoop>d__37(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <wait>5__1 = null; <znet>5__2 = null; <>1__state = -2; } private bool MoveNext() { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; <wait>5__1 = new WaitForSeconds(2f); break; case 1: <>1__state = -1; break; } try { <>4__this.NGP_TryRegisterResetRPC_Server(); <>4__this.NGP_TryRegisterApplyRPC_Client(); <>4__this.NGP_TryRegisterEpicResetRPC_Server(); <znet>5__2 = ZNet.instance; if ((Object)(object)<znet>5__2 != (Object)null) { if (<znet>5__2.IsServer()) { if (<>4__this._ngpResetRegistered && <>4__this._ngpClientApplyRegistered && <>4__this._epicResetRegistered) { return false; } } else if (<>4__this._ngpClientApplyRegistered) { return false; } } <znet>5__2 = null; } catch { } <>2__current = <wait>5__1; <>1__state = 1; return true; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class <ReloadConfigAfterQuietPeriod>d__57 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public float quietSeconds; public NewGamePlusPlugin <>4__this; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <ReloadConfigAfterQuietPeriod>d__57(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { switch (<>1__state) { default: return false; case 0: <>1__state = -1; break; case 1: <>1__state = -1; break; } if ((DateTime.UtcNow - <>4__this._lastCfgWriteUtc).TotalSeconds < (double)quietSeconds) { <>2__current = null; <>1__state = 1; return true; } try { if (<>4__this._configWatcher == null || !<>4__this._watcherReady) { return false; } <>4__this._configWatcher.EnableRaisingEvents = false; if ((Object)(object)ZNet.instance != (Object)null && ZNet.instance.IsServer()) { ((BaseUnityPlugin)<>4__this).Config.Reload(); <>4__this._ignoreEventsUntilUtc = DateTime.UtcNow.AddSeconds(1.0); ((BaseUnityPlugin)<>4__this).Config.Save(); } } catch { } finally { if (<>4__this._configWatcher != null) { <>4__this._configWatcher.EnableRaisingEvents = true; } <>4__this._reloadScheduled = false; } return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } internal const string ModName = "NewGamePlus"; internal const string ModVersion = "1.0.8"; internal const string Author = "radamanto"; private const string ModGUID = "radamanto.NewGamePlus"; internal const string NGPlusCustomKey = "radamanto.ngplus.active"; internal static ConfigEntry<bool> CE_EarlyXp_Enable; internal static ConfigEntry<string> CE_EarlyXp_RequiredKeys; internal static ConfigEntry<int> CE_EarlyXp_MinWorldDay; internal static ConfigEntry<float> CE_EarlyXp_EpicXpMultiplier; internal static ConfigEntry<bool> CE_Enable; internal static ConfigEntry<string> CE_RequiredPrivateKeys; internal static ConfigEntry<bool> CE_ResetSkillsOnNGPlus; internal static ConfigEntry<float> CE_DamageDonePercent; internal static ConfigEntry<float> CE_DamageTakenPercent; internal static ConfigEntry<float> CE_RegenHealthPercent; internal static ConfigEntry<float> CE_RegenStaminaPercent; internal static ConfigEntry<float> CE_RegenEitrPercent; internal static ConfigEntry<float> CE_CarryWeightAdd; internal static ConfigEntry<bool> CE_ShowOverheadIcon; internal static ConfigEntry<float> CE_OverheadIconHeight; internal static ConfigEntry<float> CE_OverheadIconScale; internal static ConfigEntry<bool> CE_IgnorePortalRestrictionsWithNGPlus; internal static ConfigEntry<bool> CE_EpicMMO_ResetOnNGPlus; internal static ConfigEntry<float> CE_EpicMMO_XpMultiplierNGPlus; internal const string RPC_NGPlusResetRequest = "NGP_ResetRequest"; internal const string RPC_NGPlusResetApply = "NGP_ResetApply"; private readonly Harmony _harmony = new Harmony("radamanto.NewGamePlus"); private bool _epicResetRegistered; private bool _ngpResetRegistered; private bool _ngpClientApplyRegistered; internal static ConfigSync? ConfigSync; private static ConfigEntry<bool>? _serverConfigLocked; private FileSystemWatcher? _configWatcher; private DateTime _lastCfgWriteUtc = DateTime.MinValue; private bool _reloadScheduled; private bool _watcherReady; private DateTime _ignoreEventsUntilUtc = DateTime.MinValue; internal static NewGamePlusPlugin Instance { get; private set; } private void Awake() { Instance = this; SetupServerSyncAndWatcher(); BindConfigs(); _harmony.PatchAll(Assembly.GetExecutingAssembly()); NGPlus_AssetLoader.Init(); NGPlus_StatusEffect.EnsureRegistered(); NGPlus_EarlyGameXp.EnsureRegistered(); NGPlus_EarlyGameXp.ReevaluateForLocalPlayer(); ((MonoBehaviour)this).StartCoroutine(NGP_Reset_RPCRegisterLoop()); ((MonoBehaviour)this).StartCoroutine(NGP_EarlyXp_WatcherLoop()); } private void OnDestroy() { _configWatcher?.Dispose(); _configWatcher = null; } private void BindConfigs() { CE_Enable = config("01 - General", "Enable", value: true, "Enable or disable the NG+ system."); CE_EarlyXp_Enable = config("EarlyGameXP", "EnableEarlyGameXp", value: true, "Enable or disable the Early Game XP bonus buff."); CE_EarlyXp_RequiredKeys = config("EarlyGameXP", "RequiredKeysToDisableBuff", "defeated_eikthyr", "Keys that remove the Early Game XP buff (comma-separated). The buff is removed only when ALL keys are present."); CE_EarlyXp_MinWorldDay = config("EarlyGameXP", "MinWorldDay", 300, "Minimum world day required to enable the Early Game XP buff."); CE_EarlyXp_EpicXpMultiplier = config("EarlyGameXP", "EpicMMO_XpMultiplier", 2f, "EpicMMO XP multiplier while the Early Game XP buff is active. (1.0 = normal)"); CE_RequiredPrivateKeys = config("NG Plus", "RequiredKeys", "defeated_eikthyr, defeated_gdking, defeated_bonemass, defeated_dragon, defeated_goblinking, defeated_queen, defeated_fader", "Keys required to activate NG+. Player must have ALL listed keys (comma-separated)."); CE_ResetSkillsOnNGPlus = config("NG Plus", "ResetSkillsOnNGPlus", value: false, "If enabled, activating NG+ resets all skills to level 0."); CE_IgnorePortalRestrictionsWithNGPlus = config("NG Plus", "IgnorePortalRestrictionsWithNGPlus", value: false, "If enabled, players with NG+ can use portals with any items."); CE_DamageDonePercent = config("NG Plus", "DamageDonePercent", 0f, "Damage dealt adjustment in percent. (0 = no change)"); CE_DamageTakenPercent = config("NG Plus", "DamageTakenPercent", 0f, "Damage taken adjustment in percent. (0 = no change)"); CE_RegenHealthPercent = config("NG Plus", "RegenHealthPercent", 0f, "Health regeneration adjustment in percent. (0 = no change)"); CE_RegenStaminaPercent = config("NG Plus", "RegenStaminaPercent", 0f, "Stamina regeneration adjustment in percent. (0 = no change)"); CE_RegenEitrPercent = config("NG Plus", "RegenEitrPercent", 0f, "Eitr regeneration adjustment in percent. (0 = no change)"); CE_CarryWeightAdd = config("NG Plus", "CarryWeightAdd", 0f, "Flat carry weight bonus. (0 = no change)"); CE_EpicMMO_ResetOnNGPlus = config("NG Plus", "ResetOnNGPlus", value: true, "If EpicMMO is installed, activating NG+ resets EpicMMO points/level/XP for this character."); CE_EpicMMO_XpMultiplierNGPlus = config("NG Plus", "XpMultiplierNGPlus", 1f, "EpicMMO XP multiplier while NG+ is active. (1.0 = normal)"); CE_ShowOverheadIcon = config("Visual", "ShowOverheadIcon", value: true, "Show an icon above players with NG+ active."); CE_OverheadIconHeight = config("Visual", "OverheadIconHeight", 2.4f, "Icon height above the player."); CE_OverheadIconScale = config("Visual", "OverheadIconScale", 0.08f, "Icon size scale."); } [IteratorStateMachine(typeof(<NGP_Reset_RPCRegisterLoop>d__37))] private IEnumerator NGP_Reset_RPCRegisterLoop() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <NGP_Reset_RPCRegisterLoop>d__37(0) { <>4__this = this }; } [IteratorStateMachine(typeof(<NGP_EarlyXp_WatcherLoop>d__38))] private IEnumerator NGP_EarlyXp_WatcherLoop() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <NGP_EarlyXp_WatcherLoop>d__38(0) { <>4__this = this }; } private void NGP_TryRegisterResetRPC_Server() { if (_ngpResetRegistered) { return; } ZRoutedRpc instance = ZRoutedRpc.instance; ZNet instance2 = ZNet.instance; if (instance == null || (Object)(object)instance2 == (Object)null || !instance2.IsServer()) { return; } try { instance.Register<ZPackage>("NGP_ResetRequest", (Action<long, ZPackage>)NGP_OnResetRequest_Server); _ngpResetRegistered = true; } catch (ArgumentException) { _ngpResetRegistered = true; } catch { } } private void NGP_TryRegisterApplyRPC_Client() { if (_ngpClientApplyRegistered) { return; } ZRoutedRpc instance = ZRoutedRpc.instance; if (instance == null) { return; } try { instance.Register<ZPackage>("NGP_ResetApply", (Action<long, ZPackage>)NGP_OnResetApply_Client); _ngpClientApplyRegistered = true; } catch (ArgumentException) { _ngpClientApplyRegistered = true; } catch { } } private void NGP_TryRegisterEpicResetRPC_Server() { if (_epicResetRegistered) { return; } ZRoutedRpc instance = ZRoutedRpc.instance; ZNet instance2 = ZNet.instance; if (instance == null || (Object)(object)instance2 == (Object)null || !instance2.IsServer()) { return; } try { instance.Register<ZPackage>("NGP_EpicMMO_ResetTotalPoints", (Action<long, ZPackage>)NGP_OnEpicReset_Server); _epicResetRegistered = true; } catch (ArgumentException) { _epicResetRegistered = true; } catch { } } private void NGP_OnEpicReset_Server(long sender, ZPackage pkg) { try { if (pkg != null) { string a = ""; ZNet instance = ZNet.instance; ZNetPeer val = ((instance != null) ? instance.GetPeer(sender) : null); if (val != null) { a = val.m_playerName ?? ""; } string text = pkg.ReadString(); if (string.Equals(a, text, StringComparison.OrdinalIgnoreCase) && (Object)(object)Console.instance != (Object)null) { string text2 = "\"" + text + "\""; ((Terminal)Console.instance).TryRunCommand("epicmmosystem reset_points " + text2, false, false); ((Terminal)Console.instance).TryRunCommand("epicmmosystem reset_totalpoints " + text2, false, false); ((Terminal)Console.instance).TryRunCommand("epicmmosystem recalc " + text2, false, false); } } } catch { } } private void NGP_OnResetRequest_Server(long senderPeerId, ZPackage pkg) { //IL_0124: Unknown result type (might be due to invalid IL or missing references) //IL_012b: Expected O, but got Unknown try { if ((Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsServer()) { return; } string targetName = (pkg.ReadString() ?? string.Empty).Trim(); if (string.IsNullOrWhiteSpace(targetName)) { return; } ZNetPeer peer = ZNet.instance.GetPeer(senderPeerId); if (peer == null) { return; } ISocket socket = peer.m_rpc.GetSocket(); string text = ((socket != null) ? socket.GetHostName() : null) ?? ""; string text2 = peer.m_playerName ?? ""; string text3 = peer.m_uid.ToString(); if (ZNet.instance.IsAdmin(text) || ZNet.instance.IsAdmin(text2) || ZNet.instance.IsAdmin(text3)) { ZNetPeer val = ZNet.instance.GetPeers()?.FirstOrDefault((Func<ZNetPeer, bool>)((ZNetPeer p) => string.Equals(p.m_playerName, targetName, StringComparison.OrdinalIgnoreCase))); if (val != null) { ZPackage val2 = new ZPackage(); val2.Write(targetName); ZRoutedRpc.instance.InvokeRoutedRPC(val.m_uid, "NGP_ResetApply", new object[1] { val2 }); } } } catch { } } private void NGP_OnResetApply_Client(long _sender, ZPackage pkg) { try { string text = (pkg.ReadString() ?? string.Empty).Trim(); Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null || !localPlayer.GetPlayerName().Equals(text, StringComparison.OrdinalIgnoreCase)) { return; } SEMan sEMan = ((Character)localPlayer).GetSEMan(); if (sEMan != null && sEMan.HaveStatusEffect(NGPlus_StatusEffect.SE_Hash)) { sEMan.RemoveStatusEffect(NGPlus_StatusEffect.SE_Hash, false); } localPlayer.m_customData?.Remove("radamanto.ngplus.active"); ZNetView nview = ((Character)localPlayer).m_nview; if (nview != null) { ZDO zDO = nview.GetZDO(); if (zDO != null) { zDO.Set("radamanto.ngplus.active", 0); } } NGPlus_EpicMMO.OnNgPlusDeactivated(localPlayer); string text2 = Localization.instance.Localize("$ngplus_removed_center"); string text3 = Localization.instance.Localize("$ngplus_chat_reset_done"); string text4 = text3.Replace("{0}", text); ((Character)localPlayer).Message((MessageType)2, text2, 0, (Sprite)null); Chat instance = Chat.instance; if (instance != null) { ((Terminal)instance).AddString(text4); } } catch { } } public void SetupServerSyncAndWatcher() { //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Expected O, but got Unknown bool flag = false; try { ((BaseUnityPlugin)this).Config.SaveOnConfigSet = false; ConfigSync = new ConfigSync(((BaseUnityPlugin)this).Info.Metadata.GUID) { DisplayName = ((BaseUnityPlugin)this).Info.Metadata.Name, CurrentVersion = ((BaseUnityPlugin)this).Info.Metadata.Version.ToString(), MinimumRequiredVersion = ((BaseUnityPlugin)this).Info.Metadata.Version.ToString() }; _serverConfigLocked = ((BaseUnityPlugin)this).Config.Bind<bool>("01 - General", "LockConfiguration", true, new ConfigDescription("If true, the server locks synchronized configs.", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Browsable = false } })); ConfigSync.AddLockingConfigEntry<bool>(_serverConfigLocked); SetupConfigWatcher(); flag = true; } catch { } finally { ((BaseUnityPlugin)this).Config.SaveOnConfigSet = true; if (flag && (Object)(object)ZNet.instance != (Object)null && ZNet.instance.IsServer()) { ((BaseUnityPlugin)this).Config.Save(); } } } private ConfigEntry<T> config<T>(string group, string name, T value, ConfigDescription description, bool synchronizedSetting = true) { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Expected O, but got Unknown ConfigDescription val = new ConfigDescription(description.Description + (synchronizedSetting ? " [Synced with Server]" : " [Not Synced with Server]"), description.AcceptableValues, description.Tags); ConfigEntry<T> val2 = ((BaseUnityPlugin)this).Config.Bind<T>(group, name, value, val); try { SyncedConfigEntry<T> syncedConfigEntry = ConfigSync?.AddConfigEntry<T>(val2); if (syncedConfigEntry != null) { syncedConfigEntry.SynchronizedConfig = synchronizedSetting; } } catch { } return val2; } private ConfigEntry<T> config<T>(string group, string name, T value, string description, bool synchronizedSetting = true) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Expected O, but got Unknown return config(group, name, value, new ConfigDescription(description, (AcceptableValueBase)null, Array.Empty<object>()), synchronizedSetting); } private void SetupConfigWatcher() { try { _configWatcher?.Dispose(); string configPath = Paths.ConfigPath; string fileName = Path.GetFileName(((BaseUnityPlugin)this).Config.ConfigFilePath); _configWatcher = new FileSystemWatcher(configPath, fileName) { IncludeSubdirectories = false, NotifyFilter = (NotifyFilters.FileName | NotifyFilters.Size | NotifyFilters.LastWrite | NotifyFilters.CreationTime) }; FileSystemEventHandler onChanged = delegate { if (!(DateTime.UtcNow < _ignoreEventsUntilUtc)) { _lastCfgWriteUtc = DateTime.UtcNow; if (!_reloadScheduled) { _reloadScheduled = true; ((MonoBehaviour)this).StartCoroutine(ReloadConfigAfterQuietPeriod(0.75f)); } } }; _configWatcher.Changed += onChanged; _configWatcher.Created += onChanged; _configWatcher.Renamed += delegate(object _, RenamedEventArgs __) { onChanged(_, __); }; _configWatcher.EnableRaisingEvents = true; _watcherReady = true; } catch { } } [IteratorStateMachine(typeof(<ReloadConfigAfterQuietPeriod>d__57))] private IEnumerator ReloadConfigAfterQuietPeriod(float quietSeconds) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <ReloadConfigAfterQuietPeriod>d__57(0) { <>4__this = this, quietSeconds = quietSeconds }; } } internal static class NGPlus_AssetLoader { private static AssetBundle? _bundle; private const string ResourceName = "NewGamePlus.assets.new_game"; internal static void Init() { LoadBundle(); } private static void LoadBundle() { if ((Object)(object)_bundle != (Object)null) { return; } try { Assembly executingAssembly = Assembly.GetExecutingAssembly(); using Stream stream = executingAssembly.GetManifestResourceStream("NewGamePlus.assets.new_game"); if (stream != null) { byte[] array = new byte[stream.Length]; stream.Read(array, 0, array.Length); _bundle = AssetBundle.LoadFromMemory(array); } } catch { } } internal static Sprite? GetSprite(string name) { LoadBundle(); if ((Object)(object)_bundle == (Object)null) { return null; } try { if (name == "ng_plus_icon") { name = "ngplus_ico"; } return _bundle.LoadAsset<Sprite>(name); } catch { return null; } } } [HarmonyPatch(typeof(Terminal), "InitTerminal")] internal static class NGPlus_Commands { [Serializable] [CompilerGenerated] private sealed class <>c { public static readonly <>c <>9 = new <>c(); public static ConsoleEvent <>9__0_0; public static ConsoleEvent <>9__0_1; internal void <Postfix>b__0_0(ConsoleEventArgs args) { if (!Object.op_Implicit((Object)(object)Player.m_localPlayer)) { return; } Player localPlayer = Player.m_localPlayer; SEMan sEMan = ((Character)localPlayer).GetSEMan(); if (sEMan != null && sEMan.HaveStatusEffect(NGPlus_EarlyGameXpStatusEffect.SE_Hash)) { sEMan.RemoveStatusEffect(NGPlus_EarlyGameXpStatusEffect.SE_Hash, false); } if (!NewGamePlusPlugin.CE_Enable.Value) { string text = Localization.instance.Localize("$ngplus_disabled"); string text2 = Localization.instance.Localize("$ngplus_chat_disabled"); ((Character)localPlayer).Message((MessageType)2, text, 0, (Sprite)null); PrintChat(text2); return; } if (!NGPlus_KeyChecker.HasAllRequiredKeys(NewGamePlusPlugin.CE_RequiredPrivateKeys.Value)) { string text3 = Localization.instance.Localize("$ngplus_missing_keys"); string text4 = Localization.instance.Localize("$ngplus_chat_missing_keys"); ((Character)localPlayer).Message((MessageType)2, text3, 0, (Sprite)null); PrintChat(text4); return; } if (localPlayer.m_customData != null && localPlayer.m_customData.TryGetValue("radamanto.ngplus.active", out var value) && value == "1") { string text5 = Localization.instance.Localize("$ngplus_already_active"); string text6 = Localization.instance.Localize("$ngplus_chat_already_active"); ((Character)localPlayer).Message((MessageType)2, text5, 0, (Sprite)null); PrintChat(text6); return; } if (NewGamePlusPlugin.CE_ResetSkillsOnNGPlus.Value && HasAnyEquippedItem(localPlayer)) { string text7 = Localization.instance.Localize("$ngplus_remove_equipped_center"); string text8 = Localization.instance.Localize("$ngplus_chat_remove_equipped"); ((Character)localPlayer).Message((MessageType)2, text7, 0, (Sprite)null); PrintChat(text8); return; } NGPlus_SkillReset.ResetIfEnabled(localPlayer); SEMan sEMan2 = ((Character)localPlayer).GetSEMan(); if (sEMan2 != null && !sEMan2.HaveStatusEffect(NGPlus_StatusEffect.SE_Hash)) { sEMan2.AddStatusEffect(NGPlus_StatusEffect.SE_Hash, false, 0, 0f); } NGPlus_EpicMMO.OnNgPlusActivated(localPlayer); if (localPlayer.m_customData != null) { localPlayer.m_customData["radamanto.ngplus.active"] = "1"; } ZNetView nview = ((Character)localPlayer).m_nview; ZDO val = ((nview != null) ? nview.GetZDO() : null); if (val != null) { val.Set("radamanto.ngplus.active", 1); } bool value2 = NewGamePlusPlugin.CE_ResetSkillsOnNGPlus.Value; string text9 = (value2 ? "$ngplus_activated_center" : "$ngplus_activated_center_noskillreset"); string text10 = (value2 ? "$ngplus_chat_activated" : "$ngplus_chat_activated_noskillreset"); string text11 = Localization.instance.Localize(text9); string text12 = Localization.instance.Localize(text10); ((Character)localPlayer).Message((MessageType)2, text11, 0, (Sprite)null); PrintChat(text12); } internal void <Postfix>b__0_1(ConsoleEventArgs args) { //IL_01cd: Unknown result type (might be due to invalid IL or missing references) //IL_01d3: Expected O, but got Unknown //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: Expected O, but got Unknown <>c__DisplayClass0_0 CS$<>8__locals0 = new <>c__DisplayClass0_0(); if (args == null || args.Args.Length < 2) { string text = Localization.instance.Localize("$ngplus_chat_remove_usage"); Chat instance = Chat.instance; if (instance != null) { ((Terminal)instance).AddString(text); } return; } CS$<>8__locals0.target = string.Join(" ", args.Args.Skip(1)).Trim(); if ((Object)(object)ZNet.instance == (Object)null) { return; } if (ZNet.instance.IsServer()) { ZNet instance2 = ZNet.instance; bool flag; if (instance2.IsDedicated()) { string text2 = (Object.op_Implicit((Object)(object)Player.m_localPlayer) ? Player.m_localPlayer.GetPlayerName() : ""); flag = instance2.IsAdmin(text2); } else { flag = true; } if (flag) { ZPackage val = new ZPackage(); val.Write(CS$<>8__locals0.target); ZNetPeer val2 = instance2.GetPeers()?.FirstOrDefault((Func<ZNetPeer, bool>)((ZNetPeer p) => string.Equals(p.m_playerName, CS$<>8__locals0.target, StringComparison.OrdinalIgnoreCase))); if (val2 != null) { ZRoutedRpc.instance.InvokeRoutedRPC(val2.m_uid, "NGP_ResetApply", new object[1] { val }); } else if (Object.op_Implicit((Object)(object)Player.m_localPlayer) && Player.m_localPlayer.GetPlayerName().Equals(CS$<>8__locals0.target, StringComparison.OrdinalIgnoreCase)) { ZRoutedRpc.instance.InvokeRoutedRPC(ZRoutedRpc.Everybody, "NGP_ResetApply", new object[1] { val }); } } } else { ZRoutedRpc instance3 = ZRoutedRpc.instance; ZNetPeer serverPeer = ZNet.instance.GetServerPeer(); if (instance3 != null && serverPeer != null) { ZPackage val3 = new ZPackage(); val3.Write(CS$<>8__locals0.target); instance3.InvokeRoutedRPC(serverPeer.m_uid, "NGP_ResetRequest", new object[1] { val3 }); } } } } [CompilerGenerated] private sealed class <>c__DisplayClass0_0 { public string target; internal bool <Postfix>b__2(ZNetPeer p) { return string.Equals(p.m_playerName, target, StringComparison.OrdinalIgnoreCase); } } private static void Postfix(Terminal __instance) { //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Expected O, but got Unknown //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Expected O, but got Unknown if (!Terminal.commands.ContainsKey("ngplus.start")) { object obj = <>c.<>9__0_0; if (obj == null) { ConsoleEvent val = delegate { if (Object.op_Implicit((Object)(object)Player.m_localPlayer)) { Player localPlayer = Player.m_localPlayer; SEMan sEMan = ((Character)localPlayer).GetSEMan(); if (sEMan != null && sEMan.HaveStatusEffect(NGPlus_EarlyGameXpStatusEffect.SE_Hash)) { sEMan.RemoveStatusEffect(NGPlus_EarlyGameXpStatusEffect.SE_Hash, false); } string value; if (!NewGamePlusPlugin.CE_Enable.Value) { string text3 = Localization.instance.Localize("$ngplus_disabled"); string text4 = Localization.instance.Localize("$ngplus_chat_disabled"); ((Character)localPlayer).Message((MessageType)2, text3, 0, (Sprite)null); PrintChat(text4); } else if (!NGPlus_KeyChecker.HasAllRequiredKeys(NewGamePlusPlugin.CE_RequiredPrivateKeys.Value)) { string text5 = Localization.instance.Localize("$ngplus_missing_keys"); string text6 = Localization.instance.Localize("$ngplus_chat_missing_keys"); ((Character)localPlayer).Message((MessageType)2, text5, 0, (Sprite)null); PrintChat(text6); } else if (localPlayer.m_customData != null && localPlayer.m_customData.TryGetValue("radamanto.ngplus.active", out value) && value == "1") { string text7 = Localization.instance.Localize("$ngplus_already_active"); string text8 = Localization.instance.Localize("$ngplus_chat_already_active"); ((Character)localPlayer).Message((MessageType)2, text7, 0, (Sprite)null); PrintChat(text8); } else if (NewGamePlusPlugin.CE_ResetSkillsOnNGPlus.Value && HasAnyEquippedItem(localPlayer)) { string text9 = Localization.instance.Localize("$ngplus_remove_equipped_center"); string text10 = Localization.instance.Localize("$ngplus_chat_remove_equipped"); ((Character)localPlayer).Message((MessageType)2, text9, 0, (Sprite)null); PrintChat(text10); } else { NGPlus_SkillReset.ResetIfEnabled(localPlayer); SEMan sEMan2 = ((Character)localPlayer).GetSEMan(); if (sEMan2 != null && !sEMan2.HaveStatusEffect(NGPlus_StatusEffect.SE_Hash)) { sEMan2.AddStatusEffect(NGPlus_StatusEffect.SE_Hash, false, 0, 0f); } NGPlus_EpicMMO.OnNgPlusActivated(localPlayer); if (localPlayer.m_customData != null) { localPlayer.m_customData["radamanto.ngplus.active"] = "1"; } ZNetView nview = ((Character)localPlayer).m_nview; ZDO val6 = ((nview != null) ? nview.GetZDO() : null); if (val6 != null) { val6.Set("radamanto.ngplus.active", 1); } bool value2 = NewGamePlusPlugin.CE_ResetSkillsOnNGPlus.Value; string text11 = (value2 ? "$ngplus_activated_center" : "$ngplus_activated_center_noskillreset"); string text12 = (value2 ? "$ngplus_chat_activated" : "$ngplus_chat_activated_noskillreset"); string text13 = Localization.instance.Localize(text11); string text14 = Localization.instance.Localize(text12); ((Character)localPlayer).Message((MessageType)2, text13, 0, (Sprite)null); PrintChat(text14); } } }; <>c.<>9__0_0 = val; obj = (object)val; } new ConsoleCommand("ngplus.start", "ngplus.start - Activates New Game Plus (NG+).", (ConsoleEvent)obj, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); } if (Terminal.commands.ContainsKey("ngplus.remove")) { return; } object obj2 = <>c.<>9__0_1; if (obj2 == null) { ConsoleEvent val2 = delegate(ConsoleEventArgs args) { //IL_01cd: Unknown result type (might be due to invalid IL or missing references) //IL_01d3: Expected O, but got Unknown //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: Expected O, but got Unknown if (args == null || args.Args.Length < 2) { string text = Localization.instance.Localize("$ngplus_chat_remove_usage"); Chat instance = Chat.instance; if (instance != null) { ((Terminal)instance).AddString(text); } } else { string target = string.Join(" ", args.Args.Skip(1)).Trim(); if (!((Object)(object)ZNet.instance == (Object)null)) { if (ZNet.instance.IsServer()) { ZNet instance2 = ZNet.instance; bool flag; if (instance2.IsDedicated()) { string text2 = (Object.op_Implicit((Object)(object)Player.m_localPlayer) ? Player.m_localPlayer.GetPlayerName() : ""); flag = instance2.IsAdmin(text2); } else { flag = true; } if (flag) { ZPackage val3 = new ZPackage(); val3.Write(target); ZNetPeer val4 = instance2.GetPeers()?.FirstOrDefault((Func<ZNetPeer, bool>)((ZNetPeer p) => string.Equals(p.m_playerName, target, StringComparison.OrdinalIgnoreCase))); if (val4 != null) { ZRoutedRpc.instance.InvokeRoutedRPC(val4.m_uid, "NGP_ResetApply", new object[1] { val3 }); } else if (Object.op_Implicit((Object)(object)Player.m_localPlayer) && Player.m_localPlayer.GetPlayerName().Equals(target, StringComparison.OrdinalIgnoreCase)) { ZRoutedRpc.instance.InvokeRoutedRPC(ZRoutedRpc.Everybody, "NGP_ResetApply", new object[1] { val3 }); } } } else { ZRoutedRpc instance3 = ZRoutedRpc.instance; ZNetPeer serverPeer = ZNet.instance.GetServerPeer(); if (instance3 != null && serverPeer != null) { ZPackage val5 = new ZPackage(); val5.Write(target); instance3.InvokeRoutedRPC(serverPeer.m_uid, "NGP_ResetRequest", new object[1] { val5 }); } } } } }; <>c.<>9__0_1 = val2; obj2 = (object)val2; } new ConsoleCommand("ngplus.remove", "ngplus.remove <NAME> - Removes NG+ from the player (admin only).", (ConsoleEvent)obj2, false, true, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); } private static void PrintChat(string text) { if ((Object)(object)Chat.instance != (Object)null) { ((Terminal)Chat.instance).AddString(text); return; } Console instance = Console.instance; if (instance != null) { ((Terminal)instance).AddString(text); } } private static bool HasAnyEquippedItem(Player player) { if ((Object)(object)player == (Object)null) { return false; } Type typeFromHandle = typeof(Humanoid); string[] array = new string[9] { "m_rightItem", "m_leftItem", "m_chestItem", "m_legItem", "m_helmetItem", "m_shoulderItem", "m_utilityItem", "m_trinketItem", "m_ammoItem" }; for (int i = 0; i < array.Length; i++) { FieldInfo field = typeFromHandle.GetField(array[i], BindingFlags.Instance | BindingFlags.NonPublic); if (!(field == null) && field.GetValue(player) != null) { return true; } } return false; } } [HarmonyPatch(typeof(Player), "OnSpawned")] internal static class NGPlus_PlayerOnSpawnedPatch { private static void Postfix(Player __instance) { if ((Object)(object)__instance != (Object)(object)Player.m_localPlayer) { return; } Dictionary<string, string> customData = __instance.m_customData; if (customData != null && customData.TryGetValue("radamanto.ngplus.active", out var value) && !(value != "1")) { SEMan sEMan = ((Character)__instance).GetSEMan(); if (sEMan != null && !sEMan.HaveStatusEffect(NGPlus_StatusEffect.SE_Hash)) { sEMan.AddStatusEffect(NGPlus_StatusEffect.SE_Hash, false, 0, 0f); } } } } internal static class NGPlus_KeyChecker { private static bool _resolved; private static MethodInfo? _miHasPrivateKey; public static bool IsUsingPrivateKeys { get { ResolveOnce(); return _miHasPrivateKey != null && CanUsePrivateKeys(); } } private static void ResolveOnce() { if (_resolved) { return; } _resolved = true; try { Type type = Type.GetType("BiomeLock.BiomeLockAPI, BiomeLock", throwOnError: false); if (type == null) { Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); foreach (Assembly assembly in assemblies) { type = assembly.GetType("BiomeLock.BiomeLockAPI", throwOnError: false); if (type != null) { break; } } } if (!(type == null)) { _miHasPrivateKey = type.GetMethod("HasPrivateKey", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[1] { typeof(string) }, null); } } catch { } } private static bool CanUsePrivateKeys() { try { return (Object)(object)ZNetScene.instance != (Object)null && (Object)(object)Player.m_localPlayer != (Object)null; } catch { return false; } } private static bool HasPrivateKey(string key) { ResolveOnce(); if (_miHasPrivateKey == null) { return false; } if (!CanUsePrivateKeys()) { return false; } try { object obj = _miHasPrivateKey.Invoke(null, new object[1] { key }); bool flag = default(bool); int num; if (obj is bool) { flag = (bool)obj; num = 1; } else { num = 0; } return (byte)((uint)num & (flag ? 1u : 0u)) != 0; } catch { return false; } } private static bool HasGlobalKey(string key) { try { ZoneSystem instance = ZoneSystem.instance; if ((Object)(object)instance == (Object)null) { return false; } return instance.GetGlobalKey(key); } catch { return false; } } private static bool HasKey(string key) { if (IsUsingPrivateKeys) { return HasPrivateKey(key); } return HasGlobalKey(key); } public static bool HasAllRequiredKeys(string csv) { if (string.IsNullOrWhiteSpace(csv)) { return false; } string[] array = csv.Split(new char[2] { ',', ';' }, StringSplitOptions.RemoveEmptyEntries); bool result = false; string[] array2 = array; foreach (string text in array2) { string text2 = text.Trim(); if (text2.Length != 0) { result = true; if (!HasKey(text2)) { return false; } } } return result; } } public class NGPlus_EarlyGameXpStatusEffect : SE_Stats { public const string SE_Name = "NG_EarlyGameXP"; public static readonly int SE_Hash = StringExtensionMethods.GetStableHashCode("NG_EarlyGameXP"); public override string GetTooltipString() { try { float num = Mathf.Max(0f, NewGamePlusPlugin.CE_EarlyXp_EpicXpMultiplier.Value); float num2 = (num - 1f) * 100f; Localization instance = Localization.instance; if (instance == null) { return "$ngplus_earlyxp_fallback"; } string text; if (Mathf.Abs(num2) < 0.01f) { text = instance.Localize("$ngplus_se_line_epicxp_nochange"); } else { string text2 = Mathf.Abs(num2).ToString("0.#") + "%"; if (num2 > 0f) { text2 = "+" + text2; } else if (num2 < 0f) { text2 = "-" + text2; } string newValue = ((num2 > 0f) ? ("<color=orange>" + text2 + "</color>") : ("<color=red>" + text2 + "</color>")); string text3 = instance.Localize("$ngplus_se_line_epicxp"); text = text3.Replace("{0}", newValue); } string text4 = instance.Localize("$ngplus_earlyxp_hint"); return text + "\n" + text4; } catch { return "$ngplus_earlyxp_fallback"; } } public override void Setup(Character character) { ((SE_Stats)this).Setup(character); try { if (!EpicMMOSystem_API.IsInstalled) { return; } Player val = (Player)(object)((character is Player) ? character : null); if (!((Object)(object)val == (Object)null) && !((Object)(object)val != (Object)(object)Player.m_localPlayer)) { SEMan sEMan = ((Character)val).GetSEMan(); if (sEMan == null || !sEMan.HaveStatusEffect(NGPlus_StatusEffect.SE_Hash)) { float singleRate = Mathf.Max(0f, NewGamePlusPlugin.CE_EarlyXp_EpicXpMultiplier.Value); EpicMMOSystem_API.SetSingleRate(singleRate); } } } catch { } } public override void Stop() { ((StatusEffect)this).Stop(); try { if (!EpicMMOSystem_API.IsInstalled) { return; } Player localPlayer = Player.m_localPlayer; if (!((Object)(object)localPlayer == (Object)null)) { SEMan sEMan = ((Character)localPlayer).GetSEMan(); if (sEMan == null || !sEMan.HaveStatusEffect(NGPlus_StatusEffect.SE_Hash)) { EpicMMOSystem_API.SetSingleRate(1f); } } } catch { } } } internal static class NGPlus_EarlyGameXp { internal const string EarlySeName = "NG_EarlyGameXP"; internal static readonly int EarlySeHash = NGPlus_EarlyGameXpStatusEffect.SE_Hash; internal static void EnsureRegistered() { try { ObjectDB instance = ObjectDB.instance; if (!((Object)(object)instance == (Object)null) && instance.m_StatusEffects != null && !instance.m_StatusEffects.Any((StatusEffect se) => Object.op_Implicit((Object)(object)se) && ((Object)se).name == "NG_EarlyGameXP")) { NGPlus_EarlyGameXpStatusEffect nGPlus_EarlyGameXpStatusEffect = ScriptableObject.CreateInstance<NGPlus_EarlyGameXpStatusEffect>(); ((Object)nGPlus_EarlyGameXpStatusEffect).name = "NG_EarlyGameXP"; ((StatusEffect)nGPlus_EarlyGameXpStatusEffect).m_nameHash = EarlySeHash; ((StatusEffect)nGPlus_EarlyGameXpStatusEffect).m_name = "$ngplus_earlyxp_name"; ((StatusEffect)nGPlus_EarlyGameXpStatusEffect).m_icon = NGPlus_AssetLoader.GetSprite("xp"); instance.m_StatusEffects.Add((StatusEffect)(object)nGPlus_EarlyGameXpStatusEffect); } } catch { } } private static bool ShouldHaveBuff(Player player) { if ((Object)(object)player == (Object)null) { return false; } if (!NewGamePlusPlugin.CE_EarlyXp_Enable.Value) { return false; } SEMan sEMan = ((Character)player).GetSEMan(); if (sEMan != null && sEMan.HaveStatusEffect(NGPlus_StatusEffect.SE_Hash)) { return false; } EnvMan instance = EnvMan.instance; ZNet instance2 = ZNet.instance; if ((Object)(object)instance == (Object)null || (Object)(object)instance2 == (Object)null) { return false; } int num; try { num = instance.GetDay(instance2.GetTimeSeconds()); } catch { num = 0; } if (num < NewGamePlusPlugin.CE_EarlyXp_MinWorldDay.Value) { return false; } string value = NewGamePlusPlugin.CE_EarlyXp_RequiredKeys.Value; if (string.IsNullOrWhiteSpace(value)) { return false; } if (NGPlus_KeyChecker.HasAllRequiredKeys(value)) { return false; } if (!EpicMMOSystem_API.IsInstalled) { return false; } return true; } private static void AddTo(Player player) { SEMan sEMan = ((Character)player).GetSEMan(); if (sEMan != null && !sEMan.HaveStatusEffect(EarlySeHash)) { sEMan.AddStatusEffect(EarlySeHash, false, 0, 0f); } } private static void RemoveFrom(Player player) { SEMan sEMan = ((Character)player).GetSEMan(); if (sEMan != null && sEMan.HaveStatusEffect(EarlySeHash)) { sEMan.RemoveStatusEffect(EarlySeHash, false); } } internal static void ReevaluateForLocalPlayer() { try { Player localPlayer = Player.m_localPlayer; if (!((Object)(object)localPlayer == (Object)null)) { if (ShouldHaveBuff(localPlayer)) { AddTo(localPlayer); } else { RemoveFrom(localPlayer); } } } catch { } } internal static void OnGlobalKeyChanged(string _) { try { ReevaluateForLocalPlayer(); } catch { } } } [HarmonyPatch(typeof(ObjectDB), "Awake")] internal static class NGPlus_EarlyGameXp_ObjectDB_Awake_Patch { private static void Postfix(ObjectDB __instance) { NGPlus_EarlyGameXp.EnsureRegistered(); } } [HarmonyPatch(typeof(ObjectDB), "CopyOtherDB")] internal static class NGPlus_EarlyGameXp_ObjectDB_CopyOtherDB_Patch { private static void Postfix(ObjectDB __instance) { NGPlus_EarlyGameXp.EnsureRegistered(); } } [HarmonyPatch(typeof(Player), "OnSpawned")] internal static class NGPlus_EarlyGameXp_PlayerOnSpawnedPatch { private static void Postfix(Player __instance) { try { if (!((Object)(object)__instance != (Object)(object)Player.m_localPlayer)) { NGPlus_EarlyGameXp.ReevaluateForLocalPlayer(); } } catch { } } } [HarmonyPatch(typeof(ZoneSystem), "RPC_SetGlobalKey")] internal static class NGPlus_EarlyGameXp_ZoneSystem_GlobalKeyPatch { private static void Postfix(long sender, string name) { try { NGPlus_EarlyGameXp.OnGlobalKeyChanged(name); } catch { } } } public class NGPlus_StatusEffect : SE_Stats { [HarmonyPatch(typeof(ObjectDB), "Awake")] private class Patch_ObjectDB_Awake { private static void Postfix(ObjectDB __instance) { EnsureRegistered(); } } [HarmonyPatch(typeof(ObjectDB), "CopyOtherDB")] private class Patch_ObjectDB_CopyOtherDB { private static void Postfix(ObjectDB __instance) { EnsureRegistered(); } } public const string SE_Name = "NG_BossDifficulty"; public static readonly int SE_Hash = StringExtensionMethods.GetStableHashCode("NG_BossDifficulty"); private const string ZDO_HasNgBuff = "NGPlus_HasNgBuff"; public override string GetIconText() { return ""; } public override string GetTooltipString() { Localization instance = Localization.instance; string text = instance.Localize("$ngplus_se_header"); float value = NewGamePlusPlugin.CE_DamageDonePercent.Value; float value2 = NewGamePlusPlugin.CE_DamageTakenPercent.Value; float value3 = NewGamePlusPlugin.CE_RegenHealthPercent.Value; float value4 = NewGamePlusPlugin.CE_RegenStaminaPercent.Value; float value5 = NewGamePlusPlugin.CE_RegenEitrPercent.Value; float value6 = NewGamePlusPlugin.CE_CarryWeightAdd.Value; string text2 = BuildPercentLine(value, "$ngplus_se_line_dealt_nochange", "$ngplus_se_line_dealt"); string text3 = BuildPercentLine(value2, "$ngplus_se_line_taken_nochange", "$ngplus_se_line_taken"); string text4 = BuildWeightLine(value6, "$ngplus_se_line_weight_nochange", "$ngplus_se_line_weight"); string text5 = BuildPercentLine(value3, "$ngplus_se_line_regen_hp_nochange", "$ngplus_se_line_regen_hp"); string text6 = BuildPercentLine(value4, "$ngplus_se_line_regen_stamina_nochange", "$ngplus_se_line_regen_stamina"); string text7 = BuildPercentLine(value5, "$ngplus_se_line_regen_eitr_nochange", "$ngplus_se_line_regen_eitr"); string text8 = string.Empty; if (EpicMMOSystem_API.IsInstalled) { float num = Mathf.Max(0f, NewGamePlusPlugin.CE_EpicMMO_XpMultiplierNGPlus.Value); float delta = (num - 1f) * 100f; text8 = BuildPercentLine(delta, "$ngplus_se_line_epicxp_nochange", "$ngplus_se_line_epicxp"); } string text9 = BuildPortalLine(); string text10 = text + "\n\n" + text2 + "\n" + text3 + "\n" + text4 + "\n" + text5 + "\n" + text6 + "\n" + text7; if (!string.IsNullOrEmpty(text8)) { text10 = text10 + "\n" + text8; } if (!string.IsNullOrEmpty(text9)) { text10 = text10 + "\n" + text9; } return text10; } public override void Setup(Character character) { ((SE_Stats)this).Setup(character); try { Player val = (Player)(object)((character is Player) ? character : null); if (val != null) { ZNetView nview = ((Character)val).m_nview; if ((Object)(object)nview != (Object)null && nview.IsValid() && (nview.IsOwner() || ((Object)(object)ZNet.instance != (Object)null && ZNet.instance.IsServer()))) { ZDO zDO = nview.GetZDO(); if (zDO != null) { zDO.Set("NGPlus_HasNgBuff", true); } } } } catch { } try { Player val2 = (Player)(object)((character is Player) ? character : null); if (val2 != null && (Object)(object)val2 == (Object)(object)Player.m_localPlayer && Type.GetType("EpicMMOSystem.EpicMMOSystem, EpicMMOSystem") != null) { float singleRate = Mathf.Max(0f, NewGamePlusPlugin.CE_EpicMMO_XpMultiplierNGPlus.Value); EpicMMOSystem_API.SetSingleRate(singleRate); } } catch { } } public override void Stop() { try { Character character = ((StatusEffect)this).m_character; Player val = (Player)(object)((character is Player) ? character : null); if ((Object)(object)val != (Object)null) { ZNetView nview = ((Character)val).m_nview; if ((Object)(object)nview != (Object)null && nview.IsValid() && (nview.IsOwner() || ((Object)(object)ZNet.instance != (Object)null && ZNet.instance.IsServer()))) { ZDO zDO = nview.GetZDO(); if (zDO != null) { zDO.Set("NGPlus_HasNgBuff", false); } } } } catch { } try { Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer != (Object)null && Type.GetType("EpicMMOSystem.EpicMMOSystem, EpicMMOSystem") != null) { EpicMMOSystem_API.SetSingleRate(1f); } } catch { } ((StatusEffect)this).Stop(); } private static string BuildPercentLine(float delta, string noChangeKey, string lineKey) { Localization instance = Localization.instance; if (Mathf.Abs(delta) < 0.001f) { return instance.Localize(noChangeKey); } string text = Mathf.Abs(delta).ToString("0.#") + "%"; if (delta > 0f) { text = "+" + text; } else if (delta < 0f) { text = "-" + text; } string arg = ((delta > 0f) ? ("<color=orange>" + text + "</color>") : ("<color=red>" + text + "</color>")); string format = instance.Localize(lineKey); return string.Format(format, arg); } private static string BuildWeightLine(float add, string noChangeKey, string lineKey) { Localization instance = Localization.instance; if (Mathf.Abs(add) < 0.001f) { return instance.Localize(noChangeKey); } string text = Mathf.Abs(add).ToString("0"); if (add > 0f) { text = "+" + text; } else if (add < 0f) { text = "-" + text; } string arg = ((add > 0f) ? ("<color=orange>" + text + "</color>") : ("<color=red>" + text + "</color>")); string format = instance.Localize(lineKey); return string.Format(format, arg); } private static string BuildPortalLine() { if (!NewGamePlusPlugin.CE_IgnorePortalRestrictionsWithNGPlus.Value) { return string.Empty; } return Localization.instance.Localize("$ngplus_se_line_portal"); } public static void EnsureRegistered() { if (Object.op_Implicit((Object)(object)ObjectDB.instance) && ObjectDB.instance.m_StatusEffects != null && !ObjectDB.instance.m_StatusEffects.Any((StatusEffect se) => Object.op_Implicit((Object)(object)se) && ((Object)se).name == "NG_BossDifficulty")) { AddSE(ObjectDB.instance); } } private static void AddSE(ObjectDB odb) { NGPlus_StatusEffect nGPlus_StatusEffect = ScriptableObject.CreateInstance<NGPlus_StatusEffect>(); ((Object)nGPlus_StatusEffect).name = "NG_BossDifficulty"; ((StatusEffect)nGPlus_StatusEffect).m_nameHash = SE_Hash; ((StatusEffect)nGPlus_StatusEffect).m_icon = NGPlus_AssetLoader.GetSprite("ng_plus_icon"); ((StatusEffect)nGPlus_StatusEffect).m_name = "$ngplus_se_name"; odb.m_StatusEffects.Add((StatusEffect)(object)nGPlus_StatusEffect); } } internal static class NGPlus_Translations { private enum Lang { English, Portuguese_Brazilian, Spanish, German, Korean, Chinese } internal static void Apply(Localization loc) { Lang lang; if (loc != null) { lang = GetLang(loc); loc.AddWord("ngplus_disabled", T("O sistema NG+ está desativado na configuração do servidor.", "The NG+ system is disabled in the server configuration.", "El sistema NG+ está desactivado en la configuración del servidor.", "Das NG+-System ist in der Serverkonfiguration deaktiviert.", "NG+ 시스템이 서버 설정에서 비활성화되어 있습니다.", "NG+ 系统已在服务器配置中禁用。")); loc.AddWord("ngplus_missing_keys", T("Você ainda não completou todos os chefes necessários para o NG+.", "You have not defeated all required bosses for NG+.", "Aún no has derrotado a todos los jefes necesarios para NG+.", "Du hast noch nicht alle erforderlichen Bosse für NG+ besiegt.", "NG+에 필요한 모든 보스를 아직 처치하지 않았습니다.", "你尚未击败 NG+ 所需的全部首领。")); loc.AddWord("ngplus_already_active", T("New Game Plus (NG+) já está ativo neste personagem.", "New Game Plus (NG+) is already active on this character.", "New Game Plus (NG+) ya está activo en este personaje.", "New Game Plus (NG+) ist für diesen Charakter bereits aktiv.", "이 캐릭터에 New Game Plus (NG+)가 이미 활성화되어 있습니다.", "该角色的 New Game Plus (NG+) 已经处于激活状态。")); loc.AddWord("ngplus_activated_center", T("New Game Plus (NG+) ativado! Todas as suas skills foram resetadas.", "New Game Plus (NG+) activated! All your skills were reset.", "¡New Game Plus (NG+) activado! Todas tus habilidades se han reiniciado.", "New Game Plus (NG+) aktiviert! Alle deine Fähigkeiten wurden zurückgesetzt.", "New Game Plus (NG+) 활성화! 모든 스킬이 초기화되었습니다.", "New Game Plus (NG+) 已激活!你的所有技能已重置。")); loc.AddWord("ngplus_removed_center", T("Seu NG+ foi removido por um administrador.", "Your NG+ has been removed by an administrator.", "Un administrador ha eliminado tu NG+.", "Dein NG+ wurde von einem Administrator entfernt.", "관리자가 당신의 NG+를 제거했습니다.", "管理员已移除你的 NG+。")); loc.AddWord("ngplus_chat_disabled", T("<color=yellow>[NG+]</color> O sistema NG+ está desativado na configuração do servidor.", "<color=yellow>[NG+]</color> The NG+ system is disabled in the server configuration.", "<color=yellow>[NG+]</color> El sistema NG+ está desactivado en la configuración del servidor.", "<color=yellow>[NG+]</color> Das NG+-System ist in der Serverkonfiguration deaktiviert.", "<color=yellow>[NG+]</color> NG+ 시스템이 서버 설정에서 비활성화되어 있습니다.", "<color=yellow>[NG+]</color> NG+ 系统已在服务器配置中禁用。")); loc.AddWord("ngplus_chat_missing_keys", T("<color=yellow>[NG+]</color> Você ainda não completou todos os chefes necessários para o NG+.", "<color=yellow>[NG+]</color> You have not defeated all required bosses for NG+.", "<color=yellow>[NG+]</color> Aún no has derrotado a todos los jefes necesarios para NG+.", "<color=yellow>[NG+]</color> Du hast noch nicht alle erforderlichen Bosse für NG+ besiegt.", "<color=yellow>[NG+]</color> NG+에 필요한 모든 보스를 아직 처치하지 않았습니다.", "<color=yellow>[NG+]</color> 你尚未击败 NG+ 所需的全部首领。")); loc.AddWord("ngplus_chat_already_active", T("<color=yellow>[NG+]</color> NG+ já está ativo neste personagem.", "<color=yellow>[NG+]</color> NG+ is already active on this character.", "<color=yellow>[NG+]</color> NG+ ya está activo en este personaje.", "<color=yellow>[NG+]</color> NG+ ist für diesen Charakter bereits aktiv.", "<color=yellow>[NG+]</color> 이 캐릭터에 NG+가 이미 활성화되어 있습니다.", "<color=yellow>[NG+]</color> 该角色的 NG+ 已经处于激活状态。")); loc.AddWord("ngplus_chat_activated", T("<color=orange>[NG+]</color> New Game Plus (NG+) ativado! Todas as suas skills foram resetadas.", "<color=orange>[NG+]</color> New Game Plus (NG+) activated! All your skills were reset.", "<color=orange>[NG+]</color> ¡New Game Plus (NG+) activado! Todas tus habilidades se han reiniciado.", "<color=orange>[NG+]</color> New Game Plus (NG+) aktiviert! Alle deine Fähigkeiten wurden zurückgesetzt.", "<color=orange>[NG+]</color> New Game Plus (NG+) 활성화! 모든 스킬이 초기화되었습니다.", "<color=orange>[NG+]</color> New Game Plus (NG+) 已激活!你的所有技能已重置。")); loc.AddWord("ngplus_activated_center_noskillreset", T("New Game Plus (NG+) ativado!", "New Game Plus (NG+) activated!", "¡New Game Plus (NG+) activado!", "New Game Plus (NG+) aktiviert!", "New Game Plus (NG+) 활성화!", "New Game Plus (NG+) 已激活!")); loc.AddWord("ngplus_chat_activated_noskillreset", T("<color=orange>[NG+]</color> New Game Plus (NG+) ativado.", "<color=orange>[NG+]</color> New Game Plus (NG+) activated.", "<color=orange>[NG+]</color> New Game Plus (NG+) activado.", "<color=orange>[NG+]</color> New Game Plus (NG+) aktiviert.", "<color=orange>[NG+]</color> New Game Plus (NG+) 활성화.", "<color=orange>[NG+]</color> New Game Plus (NG+) 已激活。")); loc.AddWord("ngplus_chat_reset_usage", T("<color=yellow>[NG+]</color> Uso correto: <color=white>/ngplus_reset <nome do jogador></color>", "<color=yellow>[NG+]</color> Correct usage: <color=white>/ngplus_reset <player name></color>", "<color=yellow>[NG+]</color> Uso correcto: <color=white>/ngplus_reset <nombre del jugador></color>", "<color=yellow>[NG+]</color> Richtige Verwendung: <color=white>/ngplus_reset <Spielername></color>", "<color=yellow>[NG+]</color> 올바른 사용법: <color=white>/ngplus_reset <플레이어 이름></color>", "<color=yellow>[NG+]</color> 正确用法:<color=white>/ngplus_reset <玩家名字></color>")); loc.AddWord("ngplus_chat_player_not_found", T("<color=red>[NG+]</color> Jogador <b>{0}</b> não encontrado.", "<color=red>[NG+]</color> Player <b>{0}</b> not found.", "<color=red>[NG+]</color> Jugador <b>{0}</b> no encontrado.", "<color=red>[NG+]</color> Spieler <b>{0}</b> nicht gefunden.", "<color=red>[NG+]</color> 플레이어 <b>{0}</b>를 찾을 수 없습니다.", "<color=red>[NG+]</color> 未找到玩家 <b>{0}</b>。")); loc.AddWord("ngplus_chat_reset_done", T("<color=orange>[NG+]</color> NG+ removido do jogador <b>{0}</b>.", "<color=orange>[NG+]</color> NG+ removed from player <b>{0}</b>.", "<color=orange>[NG+]</color> NG+ eliminado del jugador <b>{0}</b>.", "<color=orange>[NG+]</color> NG+ wurde von Spieler <b>{0}</b> entfernt.", "<color=orange>[NG+]</color> 플레이어 <b>{0}</b>의 NG+가 제거되었습니다.", "<color=orange>[NG+]</color> 已从玩家 <b>{0}</b> 移除 NG+。")); loc.AddWord("ngplus_se_name", T("New Game Plus (NG+)", "New Game Plus (NG+)", "New Game Plus (NG+)", "New Game Plus (NG+)", "New Game Plus (NG+)", "New Game Plus (NG+)")); loc.AddWord("ngplus_se_tooltip", T("Ajusta a dificuldade do personagem conforme as configurações do NG+.", "Adjusts character difficulty based on NG+ settings.", "Ajusta la dificultad del personaje según la configuración de NG+.", "Passt die Schwierigkeit des Charakters basierend auf den NG+-Einstellungen an.", "NG+ 설정에 따라 캐릭터 난이도를 조정합니다.", "根据 NG+ 设置调整角色难度。")); loc.AddWord("ngplus_se_header", T("Concedido após derrotar os chefes configurados.", "Granted after defeating the configured bosses.", "Se otorga tras derrotar a los jefes configurados.", "Wird nach dem Besiegen der konfigurierten Bosse gewährt.", "설정된 보스를 처치한 후 부여됩니다.", "在击败配置的首领后获得。")); loc.AddWord("ngplus_se_line_dealt_nochange", T("Dano causado: sem alteração", "Damage dealt: no change", "Daño infligido: sin cambios", "Verursachter Schaden: keine Änderung", "가한 피해: 변경 없음", "造成伤害:无变化")); loc.AddWord("ngplus_se_line_dealt", T("Dano causado: {0}", "Damage dealt: {0}", "Daño infligido: {0}", "Verursachter Schaden: {0}", "가한 피해: {0}", "造成伤害:{0}")); loc.AddWord("ngplus_se_line_taken_nochange", T("Dano recebido: sem alteração", "Damage taken: no change", "Daño recibido: sin cambios", "Erlittener Schaden: keine Änderung", "받는 피해: 변경 없음", "受到伤害:无变化")); loc.AddWord("ngplus_se_line_taken", T("Dano recebido: {0}", "Damage taken: {0}", "Daño recibido: {0}", "Erlittener Schaden: {0}", "받는 피해: {0}", "受到伤害:{0}")); loc.AddWord("ngplus_se_line_done_nochange", T("Dano causado: sem mudança", "Damage dealt: no change", "Daño infligido: sin cambios", "Verursachter Schaden: keine Änderung", "가한 피해: 변경 없음", "造成伤害:无变化")); loc.AddWord("ngplus_se_line_done", T("Dano causado: {0}", "Damage dealt: {0}", "Daño infligido: {0}", "Verursachter Schaden: {0}", "가한 피해: {0}", "造成伤害:{0}")); loc.AddWord("ngplus_se_line_taken_nochange_alt", T("Dano recebido: sem mudança", "Damage taken: no change", "Daño recibido: sin cambios", "Erlittener Schaden: keine Änderung", "받는 피해: 변경 없음", "受到伤害:无变化")); loc.AddWord("ngplus_se_line_taken_alt", T("Dano recebido: {0}", "Damage taken: {0}", "Daño recibido: {0}", "Erlittener Schaden: {0}", "받는 피해: {0}", "受到伤害:{0}")); loc.AddWord("ngplus_se_line_weight_nochange", T("Incremento de capacidade de carga: sem alteração", "Carry weight bonus: no change", "Bonificación de carga: sin cambios", "Traglast-Bonus: keine Änderung", "휴대 무게 보너스: 변경 없음", "负重加成:无变化")); loc.AddWord("ngplus_se_line_weight", T("Incremento de capacidade de carga: {0}", "Carry weight bonus: {0}", "Bonificación de carga: {0}", "Traglast-Bonus: {0}", "휴대 무게 보너스: {0}", "负重加成:{0}")); loc.AddWord("ngplus_se_line_regen_hp_nochange", T("Regeneração de vida: sem alteração", "Health regeneration: no change", "Regeneración de vida: sin cambios", "Lebensregeneration: keine Änderung", "체력 재생: 변경 없음", "生命回复:无变化")); loc.AddWord("ngplus_se_line_regen_hp", T("Regeneração de vida: {0}", "Health regeneration: {0}", "Regeneración de vida: {0}", "Lebensregeneration: {0}", "체력 재생: {0}", "生命回复:{0}")); loc.AddWord("ngplus_se_line_regen_stamina_nochange", T("Regeneração de vigor: sem alteração", "Stamina regeneration: no change", "Regeneración de aguante: sin cambios", "Ausdauerregeneration: keine Änderung", "스태미나 재생: 변경 없음", "耐力回复:无变化")); loc.AddWord("ngplus_se_line_regen_stamina", T("Regeneração de vigor: {0}", "Stamina regeneration: {0}", "Regeneración de aguante: {0}", "Ausdauerregeneration: {0}", "스태미나 재생: {0}", "耐力回复:{0}")); loc.AddWord("ngplus_se_line_regen_eitr_nochange", T("Regeneração de éter: sem alteração", "Eitr regeneration: no change", "Regeneración de éter: sin cambios", "Eitr-Regeneration: keine Änderung", "에이트르 재생: 변경 없음", "法力(Eitr)回复:无变化")); loc.AddWord("ngplus_se_line_regen_eitr", T("Regeneração de éter: {0}", "Eitr regeneration: {0}", "Regeneración de éter: {0}", "Eitr-Regeneration: {0}", "에이트르 재생: {0}", "法力(Eitr)回复:{0}")); loc.AddWord("ngplus_se_line_portal", T("Pode usar portais com qualquer item.", "Can use portals with any item.", "Puede usar portales con cualquier objeto.", "Kann Portale mit beliebigen Gegenständen benutzen.", "어떤 아이템을 들고 있어도 포탈을 사용할 수 있습니다.", "可携带任意物品使用传送门。")); loc.AddWord("ngplus_se_line_portal_bypass", T("Portais: restrições ignoradas", "Portals: restrictions ignored", "Portales: restricciones ignoradas", "Portale: Einschränkungen ignoriert", "포탈: 제한 무시", "传送门:忽略限制")); loc.AddWord("ngplus_se_line_epicxp_nochange", T("XP (EpicMMO): sem mudança", "EpicMMO XP: no change", "XP (EpicMMO): sin cambios", "XP (EpicMMO): keine Änderung", "XP (EpicMMO): 변경 없음", "经验(EpicMMO):无变化")); loc.AddWord("ngplus_se_line_epicxp", T("XP (EpicMMO): {0}", "EpicMMO XP: {0}", "XP (EpicMMO): {0}", "XP (EpicMMO): {0}", "XP (EpicMMO): {0}", "经验(EpicMMO):{0}")); loc.AddWord("ngplus_earlyxp_name", T("Bônus de XP Inicial", "Early Game XP", "XP de inicio", "Frühes Spiel-XP", "초반 XP 보너스", "前期经验加成")); loc.AddWord("ngplus_earlyxp_hint", T("Bônus inicial e temporário de XP.", "Initial and temporary XP bonus.", "Bonificación de XP inicial y temporal.", "Anfänglicher und vorübergehender XP-Bonus.", "초반에 적용되는 일시적인 XP 보너스입니다.", "初期的临时经验加成。")); loc.AddWord("ngplus_remove_equipped_center", T("Remova todos os itens equipados antes de ativar o NG+.", "Unequip all items before activating NG+.", "Desequipa todos los objetos antes de activar NG+.", "Lege alle ausgerüsteten Gegenstände ab, bevor du NG+ aktivierst.", "NG+를 활성화하기 전에 모든 장비를 해제하세요.", "在激活 NG+ 之前请先卸下所有已装备物品。")); loc.AddWord("ngplus_chat_remove_equipped", T("<color=yellow>[NG+]</color> Remova todos os itens equipados (armas/armaduras/acessórios/utilitários) antes de ativar o NG+.", "<color=yellow>[NG+]</color> Unequip all items (weapons/armor/accessories/utility) before activating NG+.", "<color=yellow>[NG+]</color> Desequipa todos los objetos (armas/armadura/accesorios/utilidad) antes de activar NG+.", "<color=yellow>[NG+]</color> Lege alle ausgerüsteten Gegenstände (Waffen/Rüstung/Zubehör/Nutzen) ab, bevor du NG+ aktivierst.", "<color=yellow>[NG+]</color> NG+를 활성화하기 전에 모든 장비(무기/방어구/액세서리/유틸리티)를 해제하세요.", "<color=yellow>[NG+]</color> 激活 NG+ 前请先卸下所有装备(武器/护甲/饰品/工具)。")); loc.AddWord("ngplus_chat_remove_usage", T("<color=yellow>[NG+]</color> Uso: <color=white>/ngplus.remove <nome></color>", "<color=yellow>[NG+]</color> Usage: <color=white>/ngplus.remove <name></color>", "<color=yellow>[NG+]</color> Uso: <color=white>/ngplus.remove <nombre></color>", "<color=yellow>[NG+]</color> Verwendung: <color=white>/ngplus.remove <Name></color>", "<color=yellow>[NG+]</color> 사용법: <color=white>/ngplus.remove <이름></color>", "<color=yellow>[NG+]</color> 用法:<color=white>/ngplus.remove <名字></color>")); loc.AddWord("ngplus_earlyxp_fallback", T("Bônus temporário de XP (EpicMMO).", "Temporary XP bonus (EpicMMO).", "Bonificación temporal de XP (EpicMMO).", "Temporärer XP-Bonus (EpicMMO).", "임시 XP 보너스 (EpicMMO).", "临时经验加成(EpicMMO)。")); loc.AddWord("ngplus_remove_equipped_center", T("Remova todos os itens equipados antes de ativar o NG+.", "Remove all equipped items before activating NG+.", "Quita todos los objetos equipados antes de activar NG+.", "Lege alle ausgerüsteten Gegenstände ab, bevor du NG+ aktivierst.", "NG+를 활성화하기 전에 장착한 모든 아이템을 제거하세요.", "在激活 NG+ 之前,请移除所有已装备的物品。")); loc.AddWord("ngplus_chat_remove_equipped", T("<color=yellow>[NG+]</color> Remova todos os itens equipados (armas/armaduras/acessórios/utilitários) antes de ativar o NG+.", "<color=yellow>[NG+]</color> Remove all equipped items (weapons/armor/accessories/utility) before activating NG+.", "<color=yellow>[NG+]</color> Quita todos los objetos equipados (armas/armaduras/accesorios/utilidad) antes de activar NG+.", "<color=yellow>[NG+]</color> Entferne alle ausgerüsteten Gegenstände (Waffen/Rüstung/Zubehör/Nützliches), bevor du NG+ aktivierst.", "<color=yellow>[NG+]</color> NG+를 활성화하기 전에 모든 장비(무기/방어구/장신구/유틸리티)를 제거하세요.", "<color=yellow>[NG+]</color> 在激活 NG+ 之前,请移除所有已装备的物品(武器/护甲/饰品/工具)。")); loc.AddWord("ngplus_chat_remove_usage", T("<color=yellow>[NG+]</color> Uso correto: <color=white>/ngplus.remove <nome do jogador></color>", "<color=yellow>[NG+]</color> Correct usage: <color=white>/ngplus.remove <player name></color>", "<color=yellow>[NG+]</color> Uso correcto: <color=white>/ngplus.remove <nombre del jugador></color>", "<color=yellow>[NG+]</color> Richtige Verwendung: <color=white>/ngplus.remove <Spielername></color>", "<color=yellow>[NG+]</color> 올바른 사용법: <color=white>/ngplus.remove <플레이어 이름></color>", "<color=yellow>[NG+]</color> 正确用法:<color=white>/ngplus.remove <玩家名称></color>")); } string T(string ptbr, string en, string es, string de, string ko, string zh) { return (lang == Lang.Portuguese_Brazilian) ? ptbr : ((lang == Lang.Spanish) ? es : ((lang == Lang.German) ? de : ((lang == Lang.Korean) ? ko : ((lang == Lang.Chinese) ? zh : en)))); } } private static Lang GetLang(Localization loc) { return (TryGetLanguage(loc) ?? "English") switch { "Portuguese_Brazilian" => Lang.Portuguese_Brazilian, "Spanish" => Lang.Spanish, "German" => Lang.German, "Korean" => Lang.Korean, "Chinese" => Lang.Chinese, _ => Lang.English, }; } private static string? TryGetLanguage(Localization loc) { Type type = ((object)loc).GetType(); string[] array = new string[2] { "GetSelectedLanguage", "GetLanguage" }; for (int i = 0; i < array.Length; i++) { try { MethodInfo method = type.GetMethod(array[i], BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (method == null) { continue; } object obj = method.Invoke(loc, null); return obj as string; } catch { } } return null; } } [HarmonyPatch] internal static class NGPlus_Translations_Patch { [HarmonyPatch(typeof(Localization), "LoadCSV", new Type[] { typeof(TextAsset), typeof(string) })] [HarmonyPostfix] private static void LoadCSV_Postfix(Localization __instance) { try { NGPlus_Translations.Apply(__instance); } catch { } } [HarmonyPatch(typeof(Localization), "SetupLanguage", new Type[] { typeof(string) })] [HarmonyPostfix] private static void SetupLanguage_Postfix(Localization __instance) { try { NGPlus_Translations.Apply(__instance); } catch { } try { NGPlus_StatusEffect.EnsureRegistered(); } catch { } } } internal static class NGPlus_OverheadIcon { private const string IconObjectName = "NGPlus_OverheadIcon"; private const float FadeNearDistance = 1f; private const float FadeFarDistance = 15f; private const string ZDO_HasNgBuff = "NGPlus_HasNgBuff"; internal static void UpdateForPlayer(Player player, bool hasBuff) { if (!Object.op_Implicit((Object)(object)player)) { return; } Transform val = ((Component)player).transform.Find("NGPlus_OverheadIcon"); if (!hasBuff || !NewGamePlusPlugin.CE_ShowOverheadIcon.Value) { if (Object.op_Implicit((Object)(object)val)) { Object.Destroy((Object)(object)((Component)val).gameObject); } } else if (!Object.op_Implicit((Object)(object)val)) { CreateIcon(player); } } private static void CreateIcon(Player player) { //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Expected O, but got Unknown //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) Sprite sprite = NGPlus_AssetLoader.GetSprite("star_ico"); if (Object.op_Implicit((Object)(object)sprite)) { float num = Mathf.Max(0.1f, NewGamePlusPlugin.CE_OverheadIconHeight.Value); float num2 = Mathf.Max(0.01f, NewGamePlusPlugin.CE_OverheadIconScale.Value); GameObject val = new GameObject("NGPlus_OverheadIcon"); val.transform.SetParent(((Component)player).transform, false); val.transform.localPosition = new Vector3(0f, num, 0f); Vector3 val2 = default(Vector3); ((Vector3)(ref val2))..ctor(num2, num2, num2); val.transform.localScale = val2; SpriteRenderer val3 = val.AddComponent<SpriteRenderer>(); val3.sprite = sprite; ((Renderer)val3).sortingOrder = 5000; NGPlus_OverheadBillboard nGPlus_OverheadBillboard = val.AddComponent<NGPlus_OverheadBillboard>(); nGPlus_OverheadBillboard.Init(val3, val2, 1f, 15f); } } } internal sealed class NGPlus_OverheadBillboard : MonoBehaviour { private SpriteRenderer? _renderer; private Vector3 _baseScale; private float _fadeNear; private float _fadeFar; public void Init(SpriteRenderer renderer, Vector3 baseScale, float fadeNear, float fadeFar) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) _renderer = renderer; _baseScale = baseScale; _fadeNear = fadeNear; _fadeFar = fadeFar; } private void LateUpdate() { //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0103: Unknown result type (might be due to invalid IL or missing references) //IL_0108: Unknown result type (might be due to invalid IL or missing references) //IL_0118: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_renderer == (Object)null) { return; } Camera main = Camera.main; if (Object.op_Implicit((Object)(object)main)) { Vector3 val = ((Component)main).transform.position - ((Component)this).transform.position; if (((Vector3)(ref val)).sqrMagnitude > 0.001f) { ((Component)this).transform.rotation = Quaternion.LookRotation(-val); } ((Component)this).transform.localScale = _baseScale; float num = Vector3.Distance(((Component)this).transform.position, ((Component)main).transform.position); float a; if (num <= _fadeNear) { a = 0f; } else if (num >= _fadeFar) { a = 1f; } else { float num2 = (num - _fadeNear) / (_fadeFar - _fadeNear); a = Mathf.Clamp01(num2); } Color color = _renderer.color; color.a = a; _renderer.color = color; } } } [HarmonyPatch(typeof(Player), "Update")] internal static class NGPlus_Player_Update_OverheadIcon { private const string ZDO_HasNgBuff = "NGPlus_HasNgBuff"; private static void Postfix(Player __instance) { if (Object.op_Implicit((Object)(object)__instance) && !((Character)__instance).IsDead()) { ZNetView nview = ((Character)__instance).m_nview; ZDO val = ((nview != null) ? nview.GetZDO() : null); bool hasBuff = val != null && val.GetBool("NGPlus_HasNgBuff", false); NGPlus_OverheadIcon.UpdateForPlayer(__instance, hasBuff); } } } } namespace API { public static class EpicMMOSystem_API { private enum API_State { NotReady, NotInstalled, Ready } public enum Attribut { Strength, Agility, Intellect, Body, Vigour, Special } private static API_State state; private static MethodInfo? eGetLevel; private static MethodInfo? eAddExp; private static MethodInfo? eGetAttribute; private static MethodInfo? eGetAttributeRusty; private static MethodInfo? eSetSingleRate; public static bool IsInstalled { get { Init(); return state == API_State.Ready; } } public static int GetLevel() { Init(); return (eGetLevel != null) ? ((int)eGetLevel.Invoke(null, null)) : 0; } public static int GetAttribute(Attribut attribute) { Init(); return (eGetAttribute != null) ? ((int)eGetAttribute.Invoke(null, new object[1] { attribute })) : 0; } public static int GetAttributeRusty(string attribute) { Init(); return (eGetAttributeRusty != null) ? ((int)eGetAttributeRusty.Invoke(null, new object[1] { attribute })) : 0; } public static void AddExp(int value) { Init(); eAddExp?.Invoke(null, new object[1] { value }); } public static void SetSingleRate(float rate) { Init(); eSetSingleRate?.Invoke(null, new object[1] { rate }); } private static void Init() { API_State aPI_State = state; if ((uint)(aPI_State - 1) <= 1u) { return; } if (Type.GetType("EpicMMOSystem.EpicMMOSystem, EpicMMOSystem") == null) { state = API_State.NotInstalled; return; } Type type = Type.GetType("API.EMMOS_API, EpicMMOSystem"); if (type == null) { state = API_State.NotInstalled; return; } eGetLevel = type.GetMethod("GetLevel", BindingFlags.Static | BindingFlags.Public); eAddExp = type.GetMethod("AddExp", BindingFlags.Static | BindingFlags.Public); eGetAttribute = type.GetMethod("GetAttribute", BindingFlags.Static | BindingFlags.Public); eGetAttributeRusty = type.GetMethod("GetAttributeRusty", BindingFlags.Static | BindingFlags.Public); eSetSingleRate = type.GetMethod("SetSingleRate", BindingFlags.Static | BindingFlags.Public); state = API_State.Ready; } } } namespace ServerSync { [PublicAPI] internal abstract class OwnConfigEntryBase { public object? LocalBaseValue; public bool SynchronizedConfig = true; public abstract ConfigEntryBase BaseConfig { get; } } [PublicAPI] internal class SyncedConfigEntry<T> : OwnConfigEntryBase { public readonly ConfigEntry<T> SourceConfig; public override ConfigEntryBase BaseConfig => (ConfigEntryBase)(object)SourceConfig; public T Value { get { return SourceConfig.Value; } set { SourceConfig.Value = value; } } public SyncedConfigEntry(ConfigEntry<T> sourceConfig) { SourceConfig = sourceConfig; base..ctor(); } public void AssignLocalValue(T value) { if (LocalBaseValue == null) { Value = value; } else { LocalBaseValue = value; } } } internal abstract class CustomSyncedValueBase { public object? LocalBaseValue; public readonly string Identifier; public readonly Type Type; private object? boxedValue; protected bool localIsOwner; public readonly int Priority; public object? BoxedValue { get { return boxedValue; } set { boxedValue = value; this.ValueChanged?.Invoke(); } } public event Action? ValueChanged; protected CustomSyncedValueBase(ConfigSync configSync, string identifier, Type type, int priority) { Priority = priority; Identifier = identifier; Type = type; configSync.AddCustomValue(this); localIsOwner = configSync.IsSourceOfTruth; configSync.SourceOfTruthChanged += delegate(bool truth) { localIsOwner = truth; }; } } [PublicAPI] internal sealed class CustomSyncedValue<T> : CustomSyncedValueBase { public T Value { get { return (T)base.BoxedValue; } set { base.BoxedValue = value; } } public CustomSyncedValue(ConfigSync configSync, string identifier, T value = default(T), int priority = 0) : base(configSync, identifier, typeof(T), priority) { Value = value; } public void AssignLocalValue(T value) { if (localIsOwner) { Value = value; } else { LocalBaseValue = value; } } } internal class ConfigurationManagerAttributes { [UsedImplicitly] public bool? ReadOnly = false; } [PublicAPI] internal class ConfigSync { [HarmonyPatch(typeof(ZRpc), "HandlePackage")] private static class SnatchCurrentlyHandlingRPC { public static ZRpc? currentRpc; [HarmonyPrefix] private static void Prefix(ZRpc __instance) { currentRpc = __instance; } } [HarmonyPatch(typeof(ZNet), "Awake")] internal static class RegisterRPCPatch { [HarmonyPostfix] private static void Postfix(ZNet __instance) { isServer = __instance.IsServer(); foreach (ConfigSync configSync2 in configSyncs) { ZRoutedRpc.instance.Register<ZPackage>(configSync2.Name + " ConfigSync", (Action<long, ZPackage>)configSync2.RPC_FromOtherClientConfigSync); if (isServer) { configSync2.InitialSyncDone = true; Debug.Log((object)("Registered '" + configSync2.Name + " ConfigSync' RPC - waiting for incoming connections")); } } if (isServer) { ((MonoBehaviour)__instance).StartCoroutine(WatchAdminListChanges()); } static void SendAdmin(List<ZNetPeer> peers, bool isAdmin) { ZPackage package = ConfigsToPackage(null, null, new PackageEntry[1] { new PackageEntry { section = "Internal", key = "lockexempt", type = typeof(bool), value = isAdmin } }); ConfigSync configSync = configSyncs.First(); if (configSync != null) { ((MonoBehaviour)ZNet.instance).StartCoroutine(configSync.sendZPackage(peers, package)); } } static IEnumerator WatchAdminListChanges() { MethodInfo listContainsId = AccessTools.DeclaredMethod(typeof(ZNet), "ListContainsId", (Type[])null, (Type[])null); SyncedList adminList = (SyncedList)AccessTools.DeclaredField(typeof(ZNet), "m_adminList").GetValue(ZNet.instance); List<string> CurrentList = new List<string>(adminList.GetList()); while (true) { yield return (object)new WaitForSeconds(30f); if (!adminList.GetList().SequenceEqual(CurrentList)) { CurrentList = new List<string>(adminList.GetList()); List<ZNetPeer> adminPeer = ZNet.instance.GetPeers().Where(delegate(ZNetPeer p) { string hostName = p.m_rpc.GetSocket().GetHostName(); return ((object)listContainsId == null) ? adminList.Contains(hostName) : ((bool)listContainsId.Invoke(ZNet.instance, new object[2] { adminList, hostName })); }).ToList(); List<ZNetPeer> nonAdminPeer = ZNet.instance.GetPeers().Except(adminPeer).ToList(); SendAdmin(nonAdminPeer, isAdmin: false); SendAdmin(adminPeer, isAdmin: true); } } } } } [HarmonyPatch(typeof(ZNet), "OnNewConnection")] private static class RegisterClientRPCPatch { [HarmonyPostfix] private static void Postfix(ZNet __instance, ZNetPeer peer) { if (__instance.IsServer()) { return; } foreach (ConfigSync configSync in configSyncs) { peer.m_rpc.Register<ZPackage>(configSync.Name + " ConfigSync", (Action<ZRpc, ZPackage>)configSync.RPC_FromServerConfigSync); } } } private class ParsedConfigs { public readonly Dictionary<OwnConfigEntryBase, object?> configValues = new Dictionary<OwnConfigEntryBase, object>(); public readonly Dictionary<CustomSyncedValueBase, object?> customValues = new Dictionary<CustomSyncedValueBase, object>(); } [HarmonyPatch(typeof(ZNet), "Shutdown")] private class ResetConfigsOnShutdown { [HarmonyPostfix] private static void Postfix() { ProcessingServerUpdate = true; foreach (ConfigSync configSync in configSyncs) { configSync.resetConfigsFromServer(); configSync.IsSourceOfTruth = true; configSync.InitialSyncDone = false; } ProcessingServerUpdate = false; } } [HarmonyPatch(typeof(ZNet), "RPC_PeerInfo")] private class SendConfigsAfterLogin { private class BufferingSocket : ZPlayFabSocket, ISocket { public volatile bool finished = false; public volatile int versionMatchQueued = -1; public readonly List<ZPackage> Package = new List<ZPackage>(); public readonly ISocket Original; public BufferingSocket(ISocket original) { Original = original; ((ZPlayFabSocket)this)..ctor(); } public bool IsConnected() { return Original.IsConnected(); } public ZPackage Recv() { return Original.Recv(); } public int GetSendQueueSize() { return Original.GetSendQueueSize(); } public int GetCurrentSendRate() { return Original.GetCurrentSendRate(); } public bool IsHost() { return Original.IsHost(); } public void Dispose() { Original.Dispose(); } public bool GotNewData() { return Original.GotNewData(); } public void Close() { Original.Close(); } public string GetEndPointString() { return Original.GetEndPointString(); } public void GetAndResetStats(out int totalSent, out int totalRecv) { Original.GetAndResetStats(ref totalSent, ref totalRecv); } public void GetConnectionQuality(out float localQuality, out float remoteQuality, out int ping, out float outByteSec, out float inByteSec) { Original.GetConnectionQuality(ref localQuality, ref remoteQuality, ref ping, ref outByteSec, ref inByteSec); } public ISocket Accept() { return Original.Accept(); } public int GetHostPort() { return Original.GetHostPort(); } public bool Flush() { return Original.Flush(); } public string GetHostName() { return Original.GetHostName(); } public void VersionMatch() { if (finished) { Original.VersionMatch(); } else { versionMatchQueued = Package.Count; } } public void Send(ZPackage pkg) { //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Expected O, but got Unknown int pos = pkg.GetPos(); pkg.SetPos(0); int num = pkg.ReadInt(); if ((num == StringExtensionMethods.GetStableHashCode("PeerInfo") || num == StringExtensionMethods.GetStableHashCode("RoutedRPC") || num == StringExtensionMethods.GetStableHashCode("ZDOData")) && !finished) { ZPackage val = new ZPackage(pkg.GetArray()); val.SetPos(pos); Package.Add(val); } else { pkg.SetPos(pos); Original.Send(pkg); } } } [HarmonyPriority(800)] [HarmonyPrefix] private static void Prefix(ref Dictionary<Assembly, BufferingSocket>? __state, ZNet __instance, ZRpc rpc) { //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Invalid comparison between Unknown and I4 if (!__instance.IsServer()) { return; } BufferingSocket bufferingSocket = new BufferingSocket(rpc.GetSocket()); AccessTools.DeclaredField(typeof(ZRpc), "m_socket").SetValue(rpc, bufferingSocket); object? obj = AccessTools.DeclaredMethod(typeof(ZNet), "GetPeer", new Type[1] { typeof(ZRpc) }, (Type[])null).Invoke(__instance, new object[1] { rpc }); ZNetPeer val = (ZNetPeer)((obj is ZNetPeer) ? obj : null); if (val != null && (int)ZNet.m_onlineBackend > 0) { FieldInfo fieldInfo = AccessTools.DeclaredField(typeof(ZNetPeer), "m_socket"); object? value = fieldInfo.GetValue(val); ZPlayFabSocket val2 = (ZPlayFabSocket)((value is ZPlayFabSocket) ? value : null); if (val2 != null) { typeof(ZPlayFabSocket).GetField("m_remotePlayerId").SetValue(bufferingSocket, val2.m_remotePlayerId); } fieldInfo.SetValue(val, bufferingSocket); } if (__state == null) { __state = new Dictionary<Assembly, BufferingSocket>(); } __state[Assembly.GetExecutingAssembly()] = bufferingSocket; } [HarmonyPostfix] private static void Postfix(Dictionary<Assembly, BufferingSocket> __state, ZNet __instance, ZRpc rpc) { ZRpc rpc2 = rpc; ZNet __instance2 = __instance; Dictionary<Assembly, BufferingSocket> __state2 = __state; ZNetPeer peer; if (__instance2.IsServer()) { object obj = AccessTools.DeclaredMethod(typeof(ZNet), "GetPeer", new Type[1] { typeof(ZRpc) }, (Type[])null).Invoke(__instance2, new object[1] { rpc2 }); peer = (ZNetPeer)((obj is ZNetPeer) ? obj : null); if (peer == null) { SendBufferedData(); } else { ((MonoBehaviour)__instance2).StartCoroutine(sendAsync()); } } void SendBufferedData() { if (rpc2.GetSocket() is BufferingSocket bufferingSocket) { AccessTools.DeclaredField(typeof(ZRpc), "m_socket").SetValue(rpc2, bufferingSocket.Original); object? obj2 = AccessTools.DeclaredMethod(typeof(ZNet), "GetPeer", new Type[1] { typeof(ZRpc) }, (Type[])null).Invoke(__instance2, new object[1] { rpc2 }); ZNetPeer val = (ZNetPeer)((obj2 is ZNetPeer) ? obj2 : null); if (val != null) { AccessTools.DeclaredField(typeof(ZNetPeer), "m_socket").SetValue(val, bufferingSocket.Original); } } BufferingSocket bufferingSocket2 = __state2[Assembly.GetExecutingAssembly()]; bufferingSocket2.finished = true; for (int i = 0; i < bufferingSocket2.Package.Count; i++) { if (i == bufferingSocket2.versionMatchQueued) { bufferingSocket2.Original.VersionMatch(); } bufferingSocket2.Original.Send(bufferingSocket2.Package[i]); } if (bufferingSocket2.Package.Count == bufferingSocket2.versionMatchQueued) { bufferingSocket2.Original.VersionMatch(); } } IEnumerator sendAsync() { foreach (ConfigSync configSync in configSyncs) { List<PackageEntry> entries = new List<PackageEntry>(); if (configSync.CurrentVersion != null) { entries.Add(new PackageEntry { section = "Internal", key = "serverversion", type = typeof(string), value = configSync.CurrentVersion }); } MethodInfo listContainsId = AccessTools.DeclaredMethod(typeof(ZNet), "ListContainsId", (Type[])null, (Type[])null); SyncedList adminList = (SyncedList)AccessTools.DeclaredField(typeof(ZNet), "m_adminList").GetValue(ZNet.instance); entries.Add(new PackageEntry { section = "Internal", key = "lockexempt", type = typeof(bool), value = (((object)listContainsId == null) ? ((object)adminList.Contains(rpc2.GetSocket().GetHostName())) : listContainsId.Invoke(ZNet.instance, new object[2] { adminList, rpc2.GetSocket().GetHostName() })) }); ZPackage package = ConfigsToPackage(configSync.allConfigs.Select((OwnConfigEntryBase c) => c.BaseConfig), configSync.allCustomValues, entries, partial: false); yield return ((MonoBehaviour)__instance2).StartCoroutine(configSync.sendZPackage(new List<ZNetPeer> { peer }, package)); } SendBufferedData(); } } } private class PackageEntry { public string section = null; public string key = null; public Type type = null; public object? value; } [HarmonyPatch(typeof(ConfigEntryBase), "GetSerializedValue")] private static class PreventSavingServerInfo { [HarmonyPrefix] private static bool Prefix(ConfigEntryBase __instance, ref string __result) { OwnConfigEntryBase ownConfigEntryBase = configData(__instance); if (ownConfigEntryBase == null || isWritableConfig(ownConfigEntryBase)) { return true; } __result = TomlTypeConverter.ConvertToString(ownConfigEntryBase.LocalBaseValue, __