Decompiled source of New Game Plus v1.0.8
plugins/NewGamePlus.dll
Decompiled 2 weeks 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, __