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.Threading.Tasks;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using JetBrains.Annotations;
using KillMeForMyPower.Commands;
using KillMeForMyPower.Managers;
using KillMeForMyPower.Restrictions.BossNameManagement;
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("PowersForbiddenForNewbies")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("PowersForbiddenForNewbies")]
[assembly: AssemblyCopyright("Copyright © 2024")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("e78efca2-b045-4686-8901-4fedba31614f")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace KillMeForMyPower
{
public class KillMeForMyPowerUtils
{
private static BossNameEnum parseBossName(string value)
{
Logger.Log("Parsing value: " + value);
return (BossNameEnum)Enum.Parse(typeof(BossNameEnum), value, ignoreCase: true);
}
public static BossNameEnum findBossNameByPrefabName(string value, bool logSilent = false)
{
Logger.Log("Parsing prefab bossName " + value + " into Enum");
foreach (BossNameEnum value2 in Enum.GetValues(typeof(BossNameEnum)))
{
if (value2.GetFightBossname() == value || value2.ToString() == value)
{
return value2;
}
}
if (!logSilent)
{
Logger.LogWarning(value + " not a vanilla/monstrum boss name.");
}
return BossNameEnum.None;
}
public static string getBossNameTranslation(BossNameEnum bossName)
{
return bossName.GetTranslationKey();
}
public static bool HasDefeatedBossNameStr(string bossName)
{
BossNameEnum bossNameEnum;
try
{
bossNameEnum = parseBossName(bossName);
}
catch (Exception ex)
{
Logger.LogError("Error in HasDefeatedBossName with " + bossName + " in parseBossName. " + ex);
return false;
}
return HasDefeatedBossName(bossNameEnum);
}
public static bool HasDefeatedBossName(BossNameEnum bossNameEnum)
{
bool flag = BossNameUtils.IsBossPowerGrantedForPlayer(bossNameEnum, Player.m_localPlayer);
Logger.Log($"hasDefeated(1) for player {Player.m_localPlayer.GetPlayerName()}: {flag}");
if (!flag)
{
flag = ConfigurationFile.activateMidPlayDetection.Value && ((Humanoid)Player.m_localPlayer).HaveUniqueKey(bossNameEnum.GetPowerKey());
Logger.Log($"hasDefeated(2) for player {Player.m_localPlayer.GetPlayerName()}: {flag}");
if (flag)
{
Logger.Log("Learned the power before. Granting!");
ZRoutedRpc.instance.InvokeRoutedRPC(0L, "RPC_BossPowerGrantServer", new object[2]
{
bossNameEnum.ToString(),
Player.m_localPlayer.GetPlayerName()
});
}
}
return flag;
}
public static int GetCurrentDay()
{
return (int)GameManager.GetPrivateMethod(EnvMan.instance, "GetCurrentDay");
}
public static int GetBossMinimumDayForPower(string bossName)
{
return parseBossName(bossName) switch
{
BossNameEnum.Eikthyr => ConfigurationFile.daysBossEikthyr.Value,
BossNameEnum.TheElder => ConfigurationFile.daysBossElder.Value,
BossNameEnum.Bonemass => ConfigurationFile.daysBossBonemass.Value,
BossNameEnum.Moder => ConfigurationFile.daysBossModer.Value,
BossNameEnum.Yagluth => ConfigurationFile.daysBossYagluth.Value,
BossNameEnum.Queen => ConfigurationFile.daysBossQueen.Value,
BossNameEnum.Fader => ConfigurationFile.daysBossFader.Value,
_ => ConfigurationFile.daysBossModded.Value,
};
}
public static bool bossIsKilled(string bossToCheck)
{
return bossIsKilled(parseBossName(bossToCheck));
}
public static bool bossIsKilled(BossNameEnum bossToCheck)
{
return HasDefeatedBossName(bossToCheck);
}
}
public enum Effects
{
None,
Burning,
Frost,
Lightning,
Poison
}
public enum BossDropRule
{
Default,
OnePlayer,
DropsForEachPlayerNearby
}
internal class ConfigurationFile
{
private static ConfigEntry<bool> _serverConfigLocked;
public static ConfigEntry<bool> debug;
public static ConfigEntry<bool> activateMidPlayDetection;
public static ConfigEntry<string> powerCommandsAdminPlayersList;
public static ConfigEntry<string> forbiddenMessage;
public static ConfigEntry<bool> vendorLocalRestrictions;
public static ConfigEntry<BossNameEnum> vendorHaldorBossToKill;
public static ConfigEntry<string> vendorHaldorRestrictions;
public static ConfigEntry<BossNameEnum> vendorHildirBossToKill;
public static ConfigEntry<string> vendorHildirRestrictions;
public static ConfigEntry<BossNameEnum> vendorBogWitchBossToKill;
public static ConfigEntry<string> vendorBogWitchRestrictions;
public static ConfigEntry<string> forbiddenVendorMessage;
public static ConfigEntry<Effects> scareEffect;
public static ConfigEntry<int> scareEffectDuration;
public static ConfigEntry<float> minimumPlayersAroundRange;
public static ConfigEntry<string> minimumPlayersAroundForbiddenMessage;
public static ConfigEntry<int> minimumPlayersAroundAmount;
public static ConfigEntry<bool> restrictEnteringDungeonsBeforeKillingBossesAdmins;
public static ConfigEntry<bool> restrictEnteringDungeonsBeforeKillingBosses;
public static ConfigEntry<string> restrictEnteringDungeonsBeforeKillingBossesMessage;
public static ConfigEntry<bool> restrictExitingQueenDungeonIfAliveOrAlerted;
public static ConfigEntry<bool> restrictUsingKeyItems;
public static ConfigEntry<string> restrictUsingKeyItemsMessage;
public static ConfigEntry<string> itemRestrictionAvailableTooltipMessage;
public static ConfigEntry<string> itemRestrictionAvailableTooltipYes;
public static ConfigEntry<string> itemRestrictionAvailableTooltipNo;
public static ConfigEntry<bool> grantKillToNearbyPlayers;
public static ConfigEntry<BossDropRule> dropsBossItems;
public static ConfigEntry<BossDropRule> dropsBossTrophies;
public static ConfigEntry<bool> minLevelToSpawnBoss;
public static ConfigEntry<string> minLevelToSpawnBossNotMet;
public static ConfigEntry<int> daysBossEikthyr;
public static ConfigEntry<int> daysBossElder;
public static ConfigEntry<int> daysBossBonemass;
public static ConfigEntry<int> daysBossModer;
public static ConfigEntry<int> daysBossYagluth;
public static ConfigEntry<int> daysBossQueen;
public static ConfigEntry<int> daysBossFader;
public static ConfigEntry<int> daysBossModded;
public static ConfigEntry<float> maxLevelBeforeBoss1Eikthyr;
public static ConfigEntry<float> maxLevelBeforeBoss2TheElder;
public static ConfigEntry<float> maxLevelBeforeBoss3Bonemass;
public static ConfigEntry<float> maxLevelBeforeBoss4Moder;
public static ConfigEntry<float> maxLevelBeforeBoss5Yagluth;
public static ConfigEntry<float> maxLevelBeforeBoss6Queen;
public static ConfigEntry<float> maxLevelBeforeBoss7Fader;
public static ConfigEntry<string> playerListForBoss1EikthyrPower;
public static ConfigEntry<string> playerListForBoss2TheElderPower;
public static ConfigEntry<string> playerListForBoss3BonemassPower;
public static ConfigEntry<string> playerListForBoss4ModerPower;
public static ConfigEntry<string> playerListForBoss5YagluthPower;
public static ConfigEntry<string> playerListForBoss6QueenPower;
public static ConfigEntry<string> playerListForBoss7FaderPower;
public static ConfigEntry<string> playerListForBoss8TherzieGorrPower;
public static ConfigEntry<string> playerListForBoss8TherzieBrutalisPower;
public static ConfigEntry<string> playerListForBoss8TherzieStormHeraldPower;
public static ConfigEntry<string> playerListForBoss8TherzieSythrakPower;
private static ConfigFile configFile;
private static readonly ConfigSync ConfigSync = new ConfigSync("Turbero.KillMeForMyPower")
{
DisplayName = "Kill Me For My Power",
CurrentVersion = "2.3.1",
MinimumRequiredVersion = "2.3.1"
};
internal static void LoadConfig(BaseUnityPlugin plugin)
{
//IL_011a: Unknown result type (might be due to invalid IL or missing references)
//IL_0125: Expected O, but got Unknown
//IL_0152: Unknown result type (might be due to invalid IL or missing references)
//IL_015d: Expected O, but got Unknown
configFile = plugin.Config;
_serverConfigLocked = config("1 - General", "Lock Configuration", value: true, "If on, the configuration is locked and can be changed by server admins only.");
ConfigSync.AddLockingConfigEntry<bool>(_serverConfigLocked);
debug = config("1 - General", "DebugMode", value: false, "Enabling/Disabling the debugging in the console (default = false)", synchronizedSetting: false);
activateMidPlayDetection = config("1 - General", "ActivateMidPlayDetection", value: true, "Adds boss power detection to identify if the player had used the power before installing the mod in a mid-play (default = false)");
powerCommandsAdminPlayersList = config("1 - General", "Power Commands Admin Players List", "", "List of additional player names that can help admin servers to assign powers to other players or themselves using the mod commands.");
forbiddenMessage = config("2 - Config", "ForbiddenMessage", "Kill the forsaken first!", "Message to show when you cannot obtain the forsaken power");
grantKillToNearbyPlayers = config("2 - Config", "GrantKillToNearbyPlayers", value: true, "Allows nearby players to grant the boss kill (default = true)");
scareEffect = config("2 - Config", "Scare Effect", Effects.Lightning, "Set up the effect when trying to access restricted items or dungeons (default = Lightning)");
scareEffectDuration = config("2 - Config", "Scare Effect Duration", 3, "Duration in seconds of the scare effect (default = 3)");
minimumPlayersAroundAmount = config("2 - Config", "Minimum Players Around - Amount", 1, new ConfigDescription("Minimum of players around an altar to spawn a boss, including yourself (default = 3)", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 50), Array.Empty<object>()));
minimumPlayersAroundRange = config("2 - Config", "Minimum Players Around - Range", 10f, new ConfigDescription("Range to detect minimum of players around an altar to spawn a boss, including yourself (default = 10)", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f), Array.Empty<object>()));
minimumPlayersAroundForbiddenMessage = config("2 - Config", "Minimum Players Around - Forbidden Message", "You need at least {0} people to spawn the boss!", "Message to show when you cannot spawn the boss due to insufficient people around");
vendorLocalRestrictions = config("2.1 - Vendor Restrictions", "VendorLocalRestrictions", value: true, "Vendors allow buying items based on personal progress, not global (default = true)");
vendorHaldorBossToKill = config("2.1 - Vendor Restrictions", "VendorHaldorBossToKill", BossNameEnum.Eikthyr, "Boss to be killed before being able to talk to Haldor (default = Eikthyr). Set to 'None' to remove this restriction. Possible values: Eikthyr,TheElder,Bonemass,Moder,Yagluth,Queen,Fader,None");
vendorHaldorRestrictions = config("2.1 - Vendor Restrictions", "VendorHaldorRestrictions", "BeltStrength,Eikthyr;YmirRemains,TheElder;Thunderstone,TheElder;ChickenEgg,Yagluth", "Restricted items for Haldor split by comma and semicolon. Ex: BeltStrength,Eikthyr;YmirRemains,TheElder;Thunderstone,TheElder;ChickenEgg,Yagluth. Available boss names: Eikthyr,TheElder,Bonemass,Moder,Yagluth,Queen,Fader (empty = nothing to restrict)");
vendorHildirBossToKill = config("2.1 - Vendor Restrictions", "VendorHildirBossToKill", BossNameEnum.Eikthyr, "Boss to be killed before being able to talk to Haldor (default = Eikthyr). Set to 'None' to remove this restriction. Possible values: Eikthyr,TheElder,Bonemass,Moder,Yagluth,Queen,Fader,None");
vendorHildirRestrictions = config("2.1 - Vendor Restrictions", "VendorHildirRestrictions", "", "Restricted items for Hildir split by comma and semicolon. Ex: Ironpit,Moder. Available boss names: Eikthyr,TheElder,Bonemass,Moder,Yagluth,Queen,Fader (empty = nothing to restrict)");
vendorBogWitchBossToKill = config("2.1 - Vendor Restrictions", "VendorBogWitchBossToKill", BossNameEnum.TheElder, "Boss to be killed before being able to talk to Haldor (default = TheElder). Set to 'None' to remove this restriction. Possible values: Eikthyr,TheElder,Bonemass,Moder,Yagluth,Queen,Fader,None");
vendorBogWitchRestrictions = config("2.1 - Vendor Restrictions", "VendorBogWitchRestrictions", "", "Restricted items for BogWitch split by comma. Ex: MeadTrollPheromones,TheElder;SpicePlains,Moder;SpiceAshlands,Queen. Available boss names: Eikthyr,TheElder,Bonemass,Moder,Yagluth,Queen,Fader (empty = nothing to restrict)");
forbiddenVendorMessage = config("2.1 - Vendor Restrictions", "ForbiddenVendorMessage", "You have not killed {0} yet to buy my stuff!", "Message to show when you cannot buy from a NPC");
restrictEnteringDungeonsBeforeKillingBossesAdmins = config("2.2 - Dungeon Restrictions", "Restrict Entering Dungeons Before Killing Bosses Admins", value: false, "Restricts accessing dungeons to admins as any regular player. (default = false)");
restrictEnteringDungeonsBeforeKillingBosses = config("2.2 - Dungeon Restrictions", "Restrict Entering Dungeons Before Killing Bosses", value: true, "Restricts accessing dungeons in biomes if you haven't killed the boss of the previous biome. (default = true)");
restrictEnteringDungeonsBeforeKillingBossesMessage = config("2.2 - Dungeon Restrictions", "Restrict Entering Dungeons Before Killing Bosses Message", "You must defeat {0} to access this dungeon first!", "Message to show the access restriction to dungeons if previous biome boss has not been defeated.");
restrictExitingQueenDungeonIfAliveOrAlerted = config("2.2 - Dungeon Restrictions", "Restrict Exiting Queen Dungeon If Alive or Alerted", value: true, "Blocks user the Queen room without killing her! (default = false)");
restrictUsingKeyItems = config("2.3 - Item Restrictions", "RestrictUsingKeyItems", value: true, "Restricts using pickaxe antler, crypt key, wishbone and wisplight until you kill the previous boss even if you get them from someone else. (default = true)");
restrictUsingKeyItemsMessage = config("2.3 - Item Restrictions", "RestrictUsingKeyItemsMessage", "You must kill {0} before doing that action!", "Message to show when you cannot equip or do an action with an important progression item");
itemRestrictionAvailableTooltipMessage = config("2.3 - Item Restrictions", "ItemRestrictionAvailableTooltipMessage", "Available to use", "Message to show in item descriptions to know when you can start using them");
itemRestrictionAvailableTooltipYes = config("2.3 - Item Restrictions", "ItemRestrictionAvailableTooltipMessageYes", "YES", "Message to show in item descriptions confirming when you can use them");
itemRestrictionAvailableTooltipNo = config("2.3 - Item Restrictions", "ItemRestrictionAvailableTooltipMessageNo", "NO", "Message to show in item descriptions confirming when you cannot use them");
dropsBossItems = config("2.4 - Boss drops rules", "Item drops", BossDropRule.Default, "If not default, drops a number of boss items according to the selected rule");
dropsBossTrophies = config("2.4 - Boss drops rules", "Trophy drops", BossDropRule.Default, "If not default, drops a number of trophies according to the selected rule");
minLevelToSpawnBoss = config("2.5 - EpicMMO integration", "Minimum level required", value: true, "If true and epicMMO is enabled, the player needs to have the same level as the boss as minimum to spawn it (default = true)");
minLevelToSpawnBossNotMet = config("2.5 - EpicMMO integration", "Not minimum level message", "You need at least level {0} to start this battle", "Message to indicate the player doesn't have the minimum necessary level to spawn the boss");
daysBossEikthyr = config("3 - Days", "DaysBossEikthyr", 100000, "Minimum number of days until the Eikthyr power cannot be obtained without killing him (default = 10000)");
daysBossElder = config("3 - Days", "DaysBossElder", 100000, "Minimum number of days until the Elder power cannot be obtained without killing him (default = 10000)");
daysBossBonemass = config("3 - Days", "DaysBossBonemass", 100000, "Minimum number of days until the Bonemass power cannot be obtained without killing him (default = 10000)");
daysBossModer = config("3 - Days", "DaysBossModer", 100000, "Minimum number of days until the Moder power cannot be obtained without killing him (default = 10000)");
daysBossYagluth = config("3 - Days", "DaysBossYagluth", 100000, "Minimum number of days until the Yagluth power cannot be obtained without killing him (default = 10000)");
daysBossQueen = config("3 - Days", "DaysBossQueen", 100000, "Minimum number of days until the Queen power cannot be obtained without killing him (default = 10000)");
daysBossFader = config("3 - Days", "DaysBossFader", 100000, "Minimum number of days until the Fader power cannot be obtained without killing him (default = 10000)");
daysBossModded = config("3 - Days", "DaysBossModded", 100000, "Minimum number of days until any modded boss power cannot be obtained without killing him (default = 10000)");
maxLevelBeforeBoss1Eikthyr = config("4 - Max levels", "MaxLevelBeforeBoss1Eikthyr", 100f, "Maximum skill level that player can level up skills before killing Eikthyr (default = 100)");
maxLevelBeforeBoss2TheElder = config("4 - Max levels", "MaxLevelBeforeBoss2TheElder", 100f, "Maximum skill level that player can level up skills before killing The Elder (default = 100)");
maxLevelBeforeBoss3Bonemass = config("4 - Max levels", "MaxLevelBeforeBoss3Bonemass", 100f, "Maximum skill level that player can level up skills before killing Bonemass (default = 100)");
maxLevelBeforeBoss4Moder = config("4 - Max levels", "MaxLevelBeforeBoss4Moder", 100f, "Maximum skill level that player can level up skills before killing Moder (default = 100)");
maxLevelBeforeBoss5Yagluth = config("4 - Max levels", "MaxLevelBeforeBoss5Yagluth", 100f, "Maximum skill level that player can level up skills before killing Yagluth (default = 100)");
maxLevelBeforeBoss6Queen = config("4 - Max levels", "MaxLevelBeforeBoss6Queen", 100f, "Maximum skill level that player can level up skills before killing The Queen (default = 100)");
maxLevelBeforeBoss7Fader = config("4 - Max levels", "MaxLevelBeforeBoss7Fader", 100f, "Maximum skill level that player can level up skills before killing Fader (default = 100)");
playerListForBoss1EikthyrPower = config("5 - Power Granted player lists", "Player List for Boss 1 - Eikthyr power", "", "List of player names that can use Eikthyr power after defeating him");
playerListForBoss2TheElderPower = config("5 - Power Granted player lists", "Player List for Boss 2 - The Elder power", "", "List of player names that can use The Elder power after defeating him");
playerListForBoss3BonemassPower = config("5 - Power Granted player lists", "Player List for Boss 3 - Bonemass power", "", "List of player names that can use Bonemass power after defeating him");
playerListForBoss4ModerPower = config("5 - Power Granted player lists", "Player List for Boss 4 - Moder power", "", "List of player names that can use Moder power after defeating her");
playerListForBoss5YagluthPower = config("5 - Power Granted player lists", "Player List for Boss 5 - Yagluth power", "", "List of player names that can use Yagluth power after defeating him");
playerListForBoss6QueenPower = config("5 - Power Granted player lists", "Player List for Boss 6 - Queen power", "", "List of player names that can use Queen power after defeating her");
playerListForBoss7FaderPower = config("5 - Power Granted player lists", "Player List for Boss 7 - Fader power", "", "List of player names that can use Fader power after defeating him");
playerListForBoss8TherzieGorrPower = config("5 - Power Granted player lists", "Player List for Therzie Boss - Gorr power", "", "List of player names that can use Gorr power after defeating him");
playerListForBoss8TherzieBrutalisPower = config("5 - Power Granted player lists", "Player List for Therzie Boss - Brutalis power", "", "List of player names that can use Brutalis power after defeating him");
playerListForBoss8TherzieStormHeraldPower = config("5 - Power Granted player lists", "Player List for Therzie Boss - StormHerald power", "", "List of player names that can use StormHerald power after defeating him");
playerListForBoss8TherzieSythrakPower = config("5 - Power Granted player lists", "Player List for Therzie Boss - Sythrak power", "", "List of player names that can use Sythrak power after defeating him");
}
private static ConfigEntry<T> config<T>(string group, string name, T value, string description, bool synchronizedSetting = true)
{
//IL_000b: Unknown result type (might be due to invalid IL or missing references)
//IL_0017: Expected O, but got Unknown
return config(group, name, value, new ConfigDescription(description, (AcceptableValueBase)null, Array.Empty<object>()), synchronizedSetting);
}
private static ConfigEntry<T> config<T>(string group, string name, T value, ConfigDescription description, bool synchronizedSetting = true)
{
//IL_0028: Unknown result type (might be due to invalid IL or missing references)
//IL_002e: 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 = configFile.Bind<T>(group, name, value, val);
SyncedConfigEntry<T> syncedConfigEntry = ConfigSync.AddConfigEntry<T>(val2);
syncedConfigEntry.SynchronizedConfig = synchronizedSetting;
return val2;
}
}
[BepInPlugin("Turbero.KillMeForMyPower", "Kill Me For My Power", "2.3.1")]
public class KillMeForMyPower : BaseUnityPlugin
{
[CompilerGenerated]
private sealed class <WaitForNetworking>d__6 : IEnumerator<object>, IDisposable, IEnumerator
{
private int <>1__state;
private object <>2__current;
public KillMeForMyPower <>4__this;
object IEnumerator<object>.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
object IEnumerator.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
[DebuggerHidden]
public <WaitForNetworking>d__6(int <>1__state)
{
this.<>1__state = <>1__state;
}
[DebuggerHidden]
void IDisposable.Dispose()
{
<>1__state = -2;
}
private bool MoveNext()
{
//IL_0028: Unknown result type (might be due to invalid IL or missing references)
//IL_0032: Expected O, but got Unknown
switch (<>1__state)
{
default:
return false;
case 0:
<>1__state = -1;
break;
case 1:
<>1__state = -1;
break;
}
if (ZRoutedRpc.instance == null || (Object)(object)ZNet.instance == (Object)null)
{
<>2__current = (object)new WaitForSeconds(1f);
<>1__state = 1;
return true;
}
PowerManagementCommands.RegisterConsoleCommand();
CheckBossesCommand.RegisterConsoleCommand();
((BaseUnityPlugin)<>4__this).Logger.LogInfo((object)("Console commands registered successfully. IsServer: " + ZNet.instance.IsServer().ToString().ToUpperInvariant()));
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();
}
}
public const string GUID = "Turbero.KillMeForMyPower";
public const string NAME = "Kill Me For My Power";
public const string VERSION = "2.3.1";
private readonly Harmony harmony = new Harmony("Turbero.KillMeForMyPower");
private void Awake()
{
ConfigurationFile.LoadConfig((BaseUnityPlugin)(object)this);
harmony.PatchAll();
}
private void Start()
{
((MonoBehaviour)this).StartCoroutine(WaitForNetworking());
}
[IteratorStateMachine(typeof(<WaitForNetworking>d__6))]
private IEnumerator WaitForNetworking()
{
//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
return new <WaitForNetworking>d__6(0)
{
<>4__this = this
};
}
private void onDestroy()
{
harmony.UnpatchSelf();
}
}
public static class Logger
{
public static ManualLogSource logger = Logger.CreateLogSource("Kill Me For My Power");
internal static void Log(object s)
{
if (ConfigurationFile.debug.Value)
{
logger.LogInfo((object)s?.ToString());
}
}
internal static void LogInfo(object s)
{
logger.LogInfo((object)s?.ToString());
}
internal static void LogWarning(object s)
{
logger.LogWarning((object)s?.ToString());
}
internal static void LogError(object s)
{
logger.LogError((object)s?.ToString());
}
}
}
namespace KillMeForMyPower.Restrictions
{
[HarmonyPatch(typeof(CharacterDrop), "GenerateDropList")]
public class BossDropsRules
{
public static void Postfix(ref Character ___m_character, ref List<KeyValuePair<GameObject, int>> __result)
{
if ((ConfigurationFile.dropsBossTrophies.Value == BossDropRule.Default && ConfigurationFile.dropsBossItems.Value == BossDropRule.Default) || !___m_character.IsBoss())
{
return;
}
int countPlayersNearby = GetCountPlayersNearby(___m_character);
Logger.Log("result distinct drops count: " + __result.Count);
Logger.Log("result total items count: " + __result.Select((KeyValuePair<GameObject, int> elem) => elem.Value).Sum());
Logger.Log("countPlayersNearby: " + countPlayersNearby);
List<KeyValuePair<GameObject, int>> list = new List<KeyValuePair<GameObject, int>>();
foreach (KeyValuePair<GameObject, int> item in __result)
{
GameObject key = item.Key;
int num = item.Value;
string text = ((Object)key).name.ToLowerInvariant();
Logger.Log($"Previous amount for {text}: {num}");
if (ConfigurationFile.dropsBossItems.Value != 0)
{
int num2 = ((ConfigurationFile.dropsBossItems.Value != BossDropRule.DropsForEachPlayerNearby) ? 1 : countPlayersNearby);
if (text.ToLowerInvariant().Contains("hardantler") || text.ToLowerInvariant().Contains("yagluthdrop"))
{
num = 3 * num2;
}
else if (text.ToLowerInvariant().Contains("cryptkey") || text.ToLowerInvariant().Contains("wishbone"))
{
num = num2;
}
else if (text.ToLowerInvariant().Contains("dragontear"))
{
num = 10 * num2;
}
else if (text.ToLowerInvariant().Contains("queendrop") || text.ToLowerInvariant().Contains("faderdrop"))
{
num = 5 * num2;
}
}
if (text.ToLowerInvariant().Contains("trophy"))
{
num = ((ConfigurationFile.dropsBossItems.Value == BossDropRule.OnePlayer) ? 1 : countPlayersNearby);
}
Logger.Log($"New amount for {text}: {num}");
list.Add(new KeyValuePair<GameObject, int>(key, num));
}
__result = list;
Logger.Log("__result new total items count: " + __result.Select((KeyValuePair<GameObject, int> elem) => elem.Value).Sum());
}
private static int GetCountPlayersNearby(Character boss)
{
//IL_0059: Unknown result type (might be due to invalid IL or missing references)
//IL_005e: Unknown result type (might be due to invalid IL or missing references)
//IL_005f: Unknown result type (might be due to invalid IL or missing references)
BaseAI component = ((Component)boss).GetComponent<BaseAI>();
float num = (Object.op_Implicit((Object)(object)component) ? component.m_viewRange : 0f);
Logger.Log(string.Format("Detection boss range for {0} is {1} meters", ((Object)boss).name.Replace("(Clone)", ""), num));
List<Player> list = new List<Player>();
Vector3 position = ((Component)Player.m_localPlayer).transform.position;
Player.GetPlayersInRange(position, num, list);
return list.Count;
}
}
[HarmonyPatch(typeof(Character), "OnDeath")]
public class RegisterBossDefeatPatch
{
public static void Postfix(Character __instance)
{
//IL_00c1: 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)
//IL_0116: Unknown result type (might be due to invalid IL or missing references)
//IL_011b: Unknown result type (might be due to invalid IL or missing references)
if (!((Object)(object)__instance != (Object)null) || !__instance.IsBoss())
{
return;
}
string text = ((Object)__instance).name.Replace("(Clone)", "");
Player localPlayer = Player.m_localPlayer;
List<string> list = new List<string>();
list.Add(localPlayer.GetPlayerName());
if (ConfigurationFile.grantKillToNearbyPlayers.Value)
{
Logger.LogInfo("Finding nearby players to grant the kill");
BaseAI component = ((Component)__instance).GetComponent<BaseAI>();
float num = (Object.op_Implicit((Object)(object)component) ? component.m_viewRange : 0f);
Logger.LogInfo(string.Format("Detection boss range for {0} is {1} meters", ((Object)__instance).name.Replace("(Clone)", ""), num));
Vector3 position = ((Component)__instance).transform.position;
List<Player> allPlayers = Player.GetAllPlayers();
foreach (Player item in allPlayers)
{
if (!((Object)(object)item == (Object)null) && !(item.GetPlayerName() == localPlayer.GetPlayerName()) && Vector3.Distance(((Component)item).transform.position, position) <= num)
{
list.Add(item.GetPlayerName());
}
}
}
ZRoutedRpc.instance.InvokeRoutedRPC(0L, "RPC_BossPowerGrantServer", new object[2]
{
text,
string.Join(",", list)
});
}
}
[HarmonyPatch(typeof(Player), "Save")]
public class Player_Save_Null_Key_Clean_Patch
{
[HarmonyPrefix]
public static void Prefix(Player __instance)
{
List<string> list = __instance.m_customData.Keys.Where((string k) => string.IsNullOrEmpty(k) || k == "null").ToList();
foreach (string item in list)
{
Logger.LogWarning("Removing null key from player " + __instance.GetPlayerName());
((Humanoid)__instance).RemoveUniqueKey(item);
}
}
}
public class RPC_BossPowerGrantCalls
{
public static void RPC_BossPowerGrantServer(long sender, string bossEnumStr, string playersToGrant)
{
BossNameEnum bossNameEnum = KillMeForMyPowerUtils.findBossNameByPrefabName(bossEnumStr, logSilent: true);
if (bossNameEnum != BossNameEnum.None)
{
Logger.Log($"[RPC_BossPowerGrantServer] RPC sent from sender {sender} with {bossEnumStr} ({bossNameEnum}) and {playersToGrant}");
string[] array = playersToGrant.Split(new char[1] { ',' });
string[] array2 = array;
foreach (string playerName in array2)
{
BossNameUtils.GrantBossPowerToPlayer(bossNameEnum, playerName, isAdd: true);
}
}
}
public static void RPC_BossPowerRemoveGrantServer(long sender, string bossEnumStr, string playersToRemoveGrant)
{
BossNameEnum bossNameEnum = KillMeForMyPowerUtils.findBossNameByPrefabName(bossEnumStr);
if (bossNameEnum != BossNameEnum.None)
{
Logger.Log($"[RPC_BossPowerRemoveGrantServer] RPC sent from sender {sender} with {bossEnumStr} ({bossNameEnum}) and {playersToRemoveGrant}");
string[] array = playersToRemoveGrant.Split(new char[1] { ',' });
string[] array2 = array;
foreach (string playerName in array2)
{
BossNameUtils.GrantBossPowerToPlayer(bossNameEnum, playerName, isAdd: false);
}
}
}
}
public class BossPowerRestriction
{
[HarmonyPatch(typeof(Player), "ActivateGuardianPower")]
public static class ActivateGuardianPowerPatch
{
public static bool Prefix(Player __instance, ref bool __result)
{
string guardianPowerName = __instance.GetGuardianPowerName();
if (guardianPowerName == null || guardianPowerName.Equals(""))
{
return true;
}
string text = guardianPowerName.Replace("GP_", "");
Logger.Log("ActivateGuardianPower - guardianPowerName: " + text);
if (!KillMeForMyPowerUtils.HasDefeatedBossNameStr(text) && KillMeForMyPowerUtils.GetCurrentDay() < KillMeForMyPowerUtils.GetBossMinimumDayForPower(text))
{
((Character)__instance).Message((MessageType)2, ConfigurationFile.forbiddenMessage.Value, 0, (Sprite)null);
ApplyBlockedEffect(text);
__result = false;
return false;
}
return true;
}
}
[HarmonyPatch(typeof(ItemStand), "DelayedPowerActivation")]
public static class DelayedPowerActivationPatch
{
public static bool Prefix(ItemStand __instance)
{
StatusEffect guardianPower = __instance.m_guardianPower;
string text = ((guardianPower != null) ? ((Object)guardianPower).name.Replace("GP_", "") : null);
Logger.Log("DelayedPowerActivation - ItemStand name: " + text);
if (!KillMeForMyPowerUtils.HasDefeatedBossNameStr(text) && KillMeForMyPowerUtils.GetCurrentDay() < KillMeForMyPowerUtils.GetBossMinimumDayForPower(text))
{
((Character)Player.m_localPlayer).Message((MessageType)2, ConfigurationFile.forbiddenMessage.Value, 0, (Sprite)null);
ApplyBlockedEffect(text);
return false;
}
return true;
}
}
private static void ApplyBlockedEffect(string bossName)
{
//IL_00db: Unknown result type (might be due to invalid IL or missing references)
//IL_00e2: Expected O, but got Unknown
//IL_0143: Unknown result type (might be due to invalid IL or missing references)
//IL_014a: Expected O, but got Unknown
//IL_01ab: Unknown result type (might be due to invalid IL or missing references)
//IL_01b2: Expected O, but got Unknown
//IL_01fd: Unknown result type (might be due to invalid IL or missing references)
//IL_0204: Expected O, but got Unknown
//IL_0265: Unknown result type (might be due to invalid IL or missing references)
//IL_026c: Expected O, but got Unknown
//IL_02cd: Unknown result type (might be due to invalid IL or missing references)
//IL_02d4: Expected O, but got Unknown
//IL_0335: Unknown result type (might be due to invalid IL or missing references)
//IL_033c: Expected O, but got Unknown
//IL_0388: Unknown result type (might be due to invalid IL or missing references)
//IL_038f: Expected O, but got Unknown
//IL_03f1: Unknown result type (might be due to invalid IL or missing references)
//IL_03f8: Expected O, but got Unknown
SEMan sEMan = ((Character)Player.m_localPlayer).GetSEMan();
string text = string.Join(";", from se in sEMan.GetStatusEffects()
select ((Object)se).name);
BossNameEnum bossNameEnum = (BossNameEnum)Enum.Parse(typeof(BossNameEnum), bossName, ignoreCase: true);
if (bossNameEnum == BossNameEnum.Eikthyr && !text.Contains("Lightning"))
{
StatusEffect val = ((sEMan != null) ? sEMan.AddStatusEffect("Lightning".GetHashCode(), false, 0, 0f) : null);
val.m_ttl = 5f;
}
else if (bossNameEnum == BossNameEnum.TheElder && !text.Contains("Burning"))
{
SE_Burning val2 = (SE_Burning)((sEMan != null) ? sEMan.AddStatusEffect("Burning".GetHashCode(), false, 0, 0f) : null);
val2.AddFireDamage(Math.Max(2f, ((Character)Player.m_localPlayer).GetHealth() - 10f));
}
else if (bossNameEnum == BossNameEnum.Bonemass && !text.Contains("Poison"))
{
SE_Poison val3 = (SE_Poison)((sEMan != null) ? sEMan.AddStatusEffect("Poison".GetHashCode(), false, 0, 0f) : null);
val3.AddDamage(Math.Max(1f, ((Character)Player.m_localPlayer).GetHealth() - 10f));
}
else if (bossNameEnum == BossNameEnum.Moder && !text.Contains("Frost"))
{
SE_Frost val4 = (SE_Frost)((sEMan != null) ? sEMan.AddStatusEffect("Frost".GetHashCode(), false, 0, 0f) : null);
((StatusEffect)val4).m_ttl = 5f;
}
else if (bossNameEnum == BossNameEnum.Yagluth && !text.Contains("Burning"))
{
SE_Burning val5 = (SE_Burning)((sEMan != null) ? sEMan.AddStatusEffect("Burning".GetHashCode(), false, 0, 0f) : null);
val5.AddFireDamage(Math.Max(2f, ((Character)Player.m_localPlayer).GetHealth() - 10f));
}
else if (bossNameEnum == BossNameEnum.Queen && !text.Contains("Poison"))
{
SE_Poison val6 = (SE_Poison)((sEMan != null) ? sEMan.AddStatusEffect("Poison".GetHashCode(), false, 0, 0f) : null);
val6.AddDamage(Math.Max(1f, ((Character)Player.m_localPlayer).GetHealth() - 10f));
}
else if (bossNameEnum == BossNameEnum.Fader && !text.Contains("Burning"))
{
SE_Burning val7 = (SE_Burning)((sEMan != null) ? sEMan.AddStatusEffect("Burning".GetHashCode(), false, 0, 0f) : null);
val7.AddFireDamage(Math.Max(2f, ((Character)Player.m_localPlayer).GetHealth() - 10f));
}
else if (bossNameEnum == BossNameEnum.SE_Boss_Gorr && !text.Contains("Frost"))
{
SE_Frost val8 = (SE_Frost)((sEMan != null) ? sEMan.AddStatusEffect("Frost".GetHashCode(), false, 0, 0f) : null);
((StatusEffect)val8).m_ttl = 5f;
}
else if (bossNameEnum == BossNameEnum.SE_Boss_Brutalis && !text.Contains("Burning"))
{
SE_Burning val9 = (SE_Burning)((sEMan != null) ? sEMan.AddStatusEffect("Burning".GetHashCode(), false, 0, 0f) : null);
val9.AddFireDamage(Math.Max(2f, ((Character)Player.m_localPlayer).GetHealth() - 10f));
}
else if (bossNameEnum == BossNameEnum.SE_Boss_Sythrak && !text.Contains("Burning"))
{
SE_Burning val10 = (SE_Burning)((sEMan != null) ? sEMan.AddStatusEffect("Burning".GetHashCode(), false, 0, 0f) : null);
val10.AddFireDamage(Math.Max(2f, ((Character)Player.m_localPlayer).GetHealth() - 10f));
}
else if (bossNameEnum == BossNameEnum.SE_Boss_StormHerald && !text.Contains("Lightning"))
{
StatusEffect val11 = ((sEMan != null) ? sEMan.AddStatusEffect("Lightning".GetHashCode(), false, 0, 0f) : null);
val11.m_ttl = 5f;
}
}
}
public class DungeonRestriction
{
[HarmonyPatch(typeof(Teleport), "OnTriggerEnter")]
[HarmonyPriority(700)]
public class Teleport_OnTriggerEnter_Patch
{
[HarmonyPrefix]
public static bool Prefix(Teleport __instance, Collider collider)
{
if (!ConfigurationFile.restrictEnteringDungeonsBeforeKillingBosses.Value)
{
return true;
}
Logger.Log("[Teleport - OnTriggerEnter] entered");
string text = ((Object)__instance).name.Replace("(Clone)", "").ToLower();
Logger.Log("[Teleport - OnTriggerEnter] Trying to teleport the player through " + text);
Player componentInParent = ((Component)collider).GetComponentInParent<Player>();
if ((Object)(object)componentInParent == (Object)null)
{
return true;
}
if (!ConfigurationFile.restrictEnteringDungeonsBeforeKillingBossesAdmins.Value && GameManager.IsAdmin(componentInParent))
{
Logger.Log("Player " + componentInParent.GetPlayerName() + " is admin. Skipping restriction to enter...");
return true;
}
return canCrossEntrance(text, componentInParent);
}
}
[HarmonyPatch(typeof(Player), "Interact")]
public class DetectDungeonInteractPatch
{
[HarmonyPrefix]
public static bool Prefix(GameObject go, Player __instance)
{
if ((Object)(object)go == (Object)null)
{
return true;
}
if (((Object)go).name != "Cube")
{
return true;
}
Logger.Log("[Player - Interact] Cube touched");
if (!ConfigurationFile.restrictEnteringDungeonsBeforeKillingBossesAdmins.Value && GameManager.IsAdmin(__instance))
{
Logger.Log("Player " + __instance.GetPlayerName() + " is admin. Skipping restriction to enter...");
return true;
}
return canCrossEntrance(((Character)__instance).InInterior() ? "exteriorgateway" : "gateway", __instance);
}
}
private static bool canCrossEntrance(string targetEntranceName, Player player)
{
//IL_0015: Unknown result type (might be due to invalid IL or missing references)
//IL_001b: Invalid comparison between Unknown and I4
//IL_003b: Unknown result type (might be due to invalid IL or missing references)
//IL_0041: Invalid comparison between Unknown and I4
//IL_0061: Unknown result type (might be due to invalid IL or missing references)
//IL_0067: Invalid comparison between Unknown and I4
//IL_0089: Unknown result type (might be due to invalid IL or missing references)
//IL_0093: Invalid comparison between Unknown and I4
//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
//IL_00b9: Invalid comparison between Unknown and I4
if (targetEntranceName == "gateway")
{
if ((int)player.GetCurrentBiome() == 8 && !KillMeForMyPowerUtils.HasDefeatedBossName(BossNameEnum.Eikthyr))
{
return negateAccess(player, BossNameEnum.Eikthyr);
}
if ((int)player.GetCurrentBiome() == 2 && !KillMeForMyPowerUtils.HasDefeatedBossName(BossNameEnum.TheElder))
{
return negateAccess(player, BossNameEnum.TheElder);
}
if ((int)player.GetCurrentBiome() == 4 && !KillMeForMyPowerUtils.HasDefeatedBossName(BossNameEnum.Bonemass))
{
return negateAccess(player, BossNameEnum.Bonemass);
}
if ((int)player.GetCurrentBiome() == 512 && !KillMeForMyPowerUtils.HasDefeatedBossName(BossNameEnum.Yagluth))
{
return negateAccess(player, BossNameEnum.Yagluth);
}
if ((int)player.GetCurrentBiome() == 32 && !KillMeForMyPowerUtils.HasDefeatedBossName(BossNameEnum.Queen))
{
return negateAccess(player, BossNameEnum.Queen);
}
}
if (ConfigurationFile.restrictExitingQueenDungeonIfAliveOrAlerted.Value && targetEntranceName == "exteriorgateway" && IsQueenNearbyAndAlert(player))
{
((Character)player).Message((MessageType)2, Localization.instance.Localize("$msg_blockedbyboss"), 0, (Sprite)null);
Effects.scareEffect();
return false;
}
return true;
}
private static bool negateAccess(Player player, BossNameEnum bossName)
{
((Character)player).Message((MessageType)2, ConfigurationFile.restrictEnteringDungeonsBeforeKillingBossesMessage.Value.Replace("{0}", Localization.instance.Localize(bossName.GetTranslationKey())), 0, (Sprite)null);
Effects.scareEffect();
return false;
}
public static bool IsQueenNearbyAndAlert(Player player)
{
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
//IL_000c: Unknown result type (might be due to invalid IL or missing references)
//IL_0061: Unknown result type (might be due to invalid IL or missing references)
//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
Vector3 position = ((Component)player).transform.position;
foreach (Character allCharacter in Character.GetAllCharacters())
{
if ((Object)(object)allCharacter != (Object)null && !allCharacter.IsDead() && ((Object)allCharacter).name.StartsWith("SeekerQueen", StringComparison.OrdinalIgnoreCase))
{
bool flag = ((Component)allCharacter).GetComponent<BaseAI>().IsAlerted();
bool flag2 = Location.IsInsideActiveBossDungeon(position);
Logger.Log($"isAlerted {flag}, isBossActive {flag2}");
if (!flag && !flag2)
{
Logger.LogInfo("SeekerQueen is neither close nor active. Lucky!");
return false;
}
float num = Vector3.Distance(position, ((Component)allCharacter).transform.position);
Logger.Log("SeekerQueen is " + num + " meters away!");
if (num <= 60f)
{
return true;
}
}
}
return false;
}
}
public class Effects
{
public static void scareEffect()
{
global::KillMeForMyPower.Effects value = ConfigurationFile.scareEffect.Value;
if (value != 0)
{
SEMan sEMan = ((Character)Player.m_localPlayer).GetSEMan();
if ((Object)(object)((sEMan != null) ? sEMan.GetStatusEffect(value.ToString().GetHashCode()) : null) == (Object)null)
{
StatusEffect val = ((sEMan != null) ? sEMan.AddStatusEffect(value.ToString().GetHashCode(), false, 0, 0f) : null);
val.m_ttl = ConfigurationFile.scareEffectDuration.Value;
}
}
}
}
[HarmonyPatch(typeof(Humanoid), "EquipItem")]
public class PlayerEquipItemPatch
{
[HarmonyPrefix]
public static bool EquipItemPrefix(Humanoid __instance, ItemData item, bool triggerEquipEffects, ref bool __result)
{
if (!ConfigurationFile.restrictUsingKeyItems.Value)
{
return true;
}
if (__instance is Player)
{
if (item.m_shared.m_name == "$item_pickaxe_antler" && !KillMeForMyPowerUtils.HasDefeatedBossName(BossNameEnum.Eikthyr))
{
((Character)__instance).Message((MessageType)2, ConfigurationFile.restrictUsingKeyItemsMessage.Value.Replace("{0}", BossNameEnum.Eikthyr.GetTranslationKey()), 0, (Sprite)null);
Effects.scareEffect();
__result = false;
return false;
}
if (item.m_shared.m_name == "$item_wishbone" && !KillMeForMyPowerUtils.HasDefeatedBossName(BossNameEnum.Bonemass))
{
((Character)__instance).Message((MessageType)2, ConfigurationFile.restrictUsingKeyItemsMessage.Value.Replace("{0}", BossNameEnum.Bonemass.GetTranslationKey()), 0, (Sprite)null);
Effects.scareEffect();
__result = false;
return false;
}
if (item.m_shared.m_name == "$item_demister" && !KillMeForMyPowerUtils.HasDefeatedBossName(BossNameEnum.Yagluth))
{
((Character)__instance).Message((MessageType)2, ConfigurationFile.restrictUsingKeyItemsMessage.Value.Replace("{0}", BossNameEnum.Yagluth.GetTranslationKey()), 0, (Sprite)null);
Effects.scareEffect();
__result = false;
return false;
}
}
return true;
}
}
[HarmonyPatch(typeof(Door), "Interact")]
public class SwampKeyRestrictionPatch
{
[HarmonyPrefix]
public static bool InteractPrefix(Door __instance, Humanoid character, bool hold, ref bool __result)
{
if (!ConfigurationFile.restrictUsingKeyItems.Value)
{
return true;
}
if (((Object)__instance).name.Contains("sunken_crypt_gate") && character is Player && !KillMeForMyPowerUtils.HasDefeatedBossName(BossNameEnum.TheElder))
{
((Character)character).Message((MessageType)2, ConfigurationFile.restrictUsingKeyItemsMessage.Value.Replace("{0}", BossNameEnum.TheElder.GetTranslationKey()), 0, (Sprite)null);
Effects.scareEffect();
__result = false;
return false;
}
return true;
}
}
[HarmonyPatch(typeof(UITooltip), "UpdateTextElements")]
public class UITooltipPatch
{
public static void Postfix(UITooltip __instance)
{
//IL_000e: Unknown result type (might be due to invalid IL or missing references)
//IL_0014: Expected O, but got Unknown
GameObject val = (GameObject)GameManager.GetPrivateValue(__instance, "m_tooltip", BindingFlags.Static | BindingFlags.NonPublic);
if (!((Object)(object)val != (Object)null))
{
return;
}
Transform val2 = Utils.FindChild(val.transform, "Text", (IterativeSearchType)0);
if ((Object)(object)val2 != (Object)null && __instance.m_topic != null)
{
if (__instance.m_topic == "$item_pickaxe_antler")
{
updateTooltipText(__instance, val2, BossNameEnum.Eikthyr);
}
else if (__instance.m_topic == "$item_demister")
{
updateTooltipText(__instance, val2, BossNameEnum.Yagluth);
}
else if (__instance.m_topic == "$item_wishbone")
{
updateTooltipText(__instance, val2, BossNameEnum.Bonemass);
}
else if (__instance.m_topic == "$item_cryptkey")
{
updateTooltipText(__instance, val2, BossNameEnum.TheElder);
}
}
}
private static void updateTooltipText(UITooltip __instance, Transform transform, BossNameEnum bossToCheck)
{
bool flag = KillMeForMyPowerUtils.HasDefeatedBossName(bossToCheck);
string text = (flag ? ConfigurationFile.itemRestrictionAvailableTooltipYes.Value : ConfigurationFile.itemRestrictionAvailableTooltipNo.Value);
string text2 = (flag ? "green" : "red");
string text3 = ConfigurationFile.itemRestrictionAvailableTooltipMessage.Value + ": <color=" + text2 + ">" + text + "</color>";
__instance.m_text = __instance.m_text.Replace("_description", "_description\n" + text3);
((Component)transform).GetComponent<TMP_Text>().text = Localization.instance.Localize(__instance.m_text);
string[] array = ((Component)transform).GetComponent<TMP_Text>().text.Split(new char[1] { '\n' });
((Component)transform).GetComponent<TMP_Text>().text = string.Join("\n", array, 0, array.Length - 1);
}
}
[HarmonyPatch(typeof(OfferingBowl), "InitiateSpawnBoss")]
public static class InitiateSpawnBossPatch
{
private static bool Prefix(OfferingBowl __instance, Vector3 point, bool removeItemsFromInventory)
{
//IL_0038: Unknown result type (might be due to invalid IL or missing references)
//IL_003d: Unknown result type (might be due to invalid IL or missing references)
//IL_003e: Unknown result type (might be due to invalid IL or missing references)
Logger.Log("Detecting players around " + ConfigurationFile.minimumPlayersAroundRange.Value + " meters...");
List<Player> list = new List<Player>();
Vector3 position = ((Component)Player.m_localPlayer).transform.position;
Player.GetPlayersInRange(position, ConfigurationFile.minimumPlayersAroundRange.Value, list);
if (list.Count < ConfigurationFile.minimumPlayersAroundAmount.Value)
{
Logger.Log($"{list} players detected. Minimum required: {ConfigurationFile.minimumPlayersAroundAmount.Value}. Cancelling...");
((Character)Player.m_localPlayer).Message((MessageType)2, ConfigurationFile.minimumPlayersAroundForbiddenMessage.Value.Replace("{0}", ConfigurationFile.minimumPlayersAroundAmount.Value.ToString()), 0, (Sprite)null);
return false;
}
Logger.Log("No monsters detected.");
if (ConfigurationFile.minLevelToSpawnBoss.Value && EpicMMOSystem_API.IsLoaded())
{
try
{
string name = ((Object)__instance.m_bossPrefab).name;
object obj = GetMonsters()[name + "(Clone)"];
if (obj != null)
{
int monsterLevel = GetMonsterLevel(obj);
if (EpicMMOSystem_API.GetLevel() < monsterLevel)
{
((Character)Player.m_localPlayer).Message((MessageType)2, ConfigurationFile.minLevelToSpawnBossNotMet.Value.Replace("{0}", monsterLevel.ToString()), 0, (Sprite)null);
return false;
}
Logger.Log("Level enough to spawn.");
}
}
catch (Exception ex)
{
Logger.LogWarning("Error when calculating monster level. Ignoring restriction. Error: " + ex);
}
}
return true;
}
private static IDictionary GetMonsters()
{
Type type = Type.GetType("EpicMMOSystem.DataMonsters, EpicMMOSystem");
if (type == null)
{
return new Dictionary<string, object>();
}
return type.GetField("dictionary", BindingFlags.Static | BindingFlags.NonPublic)?.GetValue(null) as IDictionary;
}
private static int GetMonsterLevel(object monster)
{
FieldInfo field = monster.GetType().GetField("level", BindingFlags.Instance | BindingFlags.Public);
if (field != null)
{
return (int)field.GetValue(monster);
}
return 0;
}
}
public class LevelCalculation
{
public static bool canSkillUp(float skillLevelValue)
{
return (KillMeForMyPowerUtils.HasDefeatedBossName(BossNameEnum.Eikthyr) || !(skillLevelValue >= ConfigurationFile.maxLevelBeforeBoss1Eikthyr.Value)) && (KillMeForMyPowerUtils.HasDefeatedBossName(BossNameEnum.TheElder) || !(skillLevelValue >= ConfigurationFile.maxLevelBeforeBoss2TheElder.Value)) && (KillMeForMyPowerUtils.HasDefeatedBossName(BossNameEnum.Bonemass) || !(skillLevelValue >= ConfigurationFile.maxLevelBeforeBoss3Bonemass.Value)) && (KillMeForMyPowerUtils.HasDefeatedBossName(BossNameEnum.Moder) || !(skillLevelValue >= ConfigurationFile.maxLevelBeforeBoss4Moder.Value)) && (KillMeForMyPowerUtils.HasDefeatedBossName(BossNameEnum.Yagluth) || !(skillLevelValue >= ConfigurationFile.maxLevelBeforeBoss5Yagluth.Value)) && (KillMeForMyPowerUtils.HasDefeatedBossName(BossNameEnum.Queen) || !(skillLevelValue >= ConfigurationFile.maxLevelBeforeBoss6Queen.Value)) && (KillMeForMyPowerUtils.HasDefeatedBossName(BossNameEnum.Fader) || !(skillLevelValue >= ConfigurationFile.maxLevelBeforeBoss7Fader.Value));
}
private static float currentMaxSkillLevel()
{
if (KillMeForMyPowerUtils.HasDefeatedBossName(BossNameEnum.Fader))
{
return float.MaxValue;
}
if (KillMeForMyPowerUtils.HasDefeatedBossName(BossNameEnum.Queen))
{
return ConfigurationFile.maxLevelBeforeBoss7Fader.Value;
}
if (KillMeForMyPowerUtils.HasDefeatedBossName(BossNameEnum.Yagluth))
{
return ConfigurationFile.maxLevelBeforeBoss6Queen.Value;
}
if (KillMeForMyPowerUtils.HasDefeatedBossName(BossNameEnum.Moder))
{
return ConfigurationFile.maxLevelBeforeBoss5Yagluth.Value;
}
if (KillMeForMyPowerUtils.HasDefeatedBossName(BossNameEnum.Bonemass))
{
return ConfigurationFile.maxLevelBeforeBoss4Moder.Value;
}
if (KillMeForMyPowerUtils.HasDefeatedBossName(BossNameEnum.TheElder))
{
return ConfigurationFile.maxLevelBeforeBoss3Bonemass.Value;
}
if (KillMeForMyPowerUtils.HasDefeatedBossName(BossNameEnum.Eikthyr))
{
return ConfigurationFile.maxLevelBeforeBoss2TheElder.Value;
}
return ConfigurationFile.maxLevelBeforeBoss1Eikthyr.Value;
}
public static bool reviewAndUpdateSkill(Player player, SkillType skillType, string buffName)
{
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
//IL_0008: Unknown result type (might be due to invalid IL or missing references)
//IL_0072: Unknown result type (might be due to invalid IL or missing references)
//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
Skill val = ((Character)player).GetSkills().GetSkillList().Find((Skill s) => s.m_info.m_skill == skillType);
if (val == null)
{
return true;
}
int num = (int)val.m_level;
float num2 = (float)num + val.GetLevelPercentage();
float num3 = currentMaxSkillLevel();
bool flag = num2 < num3;
Logger.Log($"Decision with skill {skillType}, skillLevel {num}, percentage {val.GetLevelPercentage()} and currentLevel {num2}: {flag}");
if (!flag)
{
val.m_level = Math.Min(num, num3);
val.m_accumulator = 0f;
Logger.Log($"{skillType} rounded to max allowed value: {val.m_level}");
if (GameManager.isDetailedLevelsInstalled())
{
Logger.Log("Checking DetailedLevels buff...");
List<StatusEffect> list = (List<StatusEffect>)GameManager.GetPrivateValue(((Character)Player.m_localPlayer).GetSEMan(), "m_statusEffects");
StatusEffect val2 = list.Find((StatusEffect effect) => effect.m_name.Contains(buffName));
if ((Object)(object)val2 != (Object)null)
{
Logger.Log("Fixing value in buff");
val2.m_name = $"{buffName}: {val.m_level}";
}
}
}
return flag;
}
}
[HarmonyPatch(typeof(Player), "RaiseSkill")]
public class Player_RaiseSkill_Prefix_Patch
{
private static bool Prefix(Player __instance, SkillType skill, float value)
{
//IL_0013: Unknown result type (might be due to invalid IL or missing references)
//IL_001f: Unknown result type (might be due to invalid IL or missing references)
//IL_0044: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)__instance != (Object)null)
{
float skillLevel = ((Character)__instance).GetSkills().GetSkillLevel(skill);
Logger.Log($"Checking skill level availability {skill} with {skillLevel}...");
if (skillLevel < 100f)
{
return LevelCalculation.reviewAndUpdateSkill(__instance, skill, "$skill_" + ((object)(SkillType)(ref skill)).ToString().ToLower());
}
}
return true;
}
}
[HarmonyPatch]
[HarmonyPriority(700)]
public class Dodge_ManualUpdate_Patch
{
private static MethodBase TargetMethod()
{
return AccessTools.Method(typeof(Player), "Dodge", (Type[])null, (Type[])null);
}
private static void Postfix(ref Player __instance, Vector3 dodgeDir)
{
Logger.Log("Checking dodge skill here since it doesn't seem to go through Player.RaiseSkill...");
WaitForSecondsAsync(__instance, 0.1f);
}
private static async Task WaitForSecondsAsync(Player player, float seconds)
{
await Task.Delay((int)(Math.Max(0f, seconds) * 1000f));
LevelCalculation.reviewAndUpdateSkill(player, (SkillType)108, "$skill_dodge");
}
}
[HarmonyPatch(typeof(Character), "Damage")]
public class BloodMagic_ManualUpdate_Patch
{
private static void Postfix(Character __instance, HitData hit)
{
if (!((Object)(object)__instance != (Object)null))
{
return;
}
Character attacker = hit.GetAttacker();
if (!((Object)(object)attacker != (Object)null))
{
return;
}
if (attacker.IsTamed() && __instance.IsMonsterFaction(0f))
{
WaitForSecondsAsync(null, 0.1f);
}
else if (attacker.IsMonsterFaction(0f) && ((object)__instance).GetType() == typeof(Player))
{
WaitForSecondsAsync((Player)(object)((__instance is Player) ? __instance : null), 0.1f);
}
else if (((Object)attacker).name.Contains("Troll_Summoned"))
{
if (((object)__instance).GetType() == typeof(Player))
{
WaitForSecondsAsync((Player)(object)((__instance is Player) ? __instance : null), 0.1f);
}
else if (__instance.IsTamed())
{
WaitForSecondsAsync(null, 0.1f);
}
}
}
private static async Task WaitForSecondsAsync(Player player, float seconds)
{
Logger.Log("Checking blood magic here since it doesn't seem to go through Player.RaiseSkill...");
await Task.Delay((int)(Math.Max(0f, seconds) * 1000f));
LevelCalculation.reviewAndUpdateSkill(((Object)(object)player == (Object)null) ? Player.m_localPlayer : player, (SkillType)10, "$skill_bloodmagic");
}
}
[HarmonyPatch(typeof(SkillsDialog), "Setup")]
[HarmonyPriority(100)]
public class SkillsDialogAdditions_Patch
{
private static void Postfix(SkillsDialog __instance, ref Player player, ref List<GameObject> ___m_elements)
{
//IL_003a: Unknown result type (might be due to invalid IL or missing references)
//IL_0033: Unknown result type (might be due to invalid IL or missing references)
//IL_003f: Unknown result type (might be due to invalid IL or missing references)
//IL_0057: Unknown result type (might be due to invalid IL or missing references)
List<Skill> skillList = ((Character)player).GetSkills().GetSkillList();
for (int i = 0; i < skillList.Count; i++)
{
GameObject val = ___m_elements[i];
Skill val2 = skillList[i];
Color color = (LevelCalculation.canSkillUp((int)val2.m_level) ? Color.white : Color.red);
((Component)Utils.FindChild(val.transform, "leveltext", (IterativeSearchType)0)).GetComponent<TMP_Text>().color = color;
}
}
}
public class TraderSetup
{
[HarmonyPatch(typeof(Trader), "Interact")]
public class TraderInteractPatch
{
[HarmonyPrefix]
public static bool InteractPrefix(Trader __instance, Humanoid character, bool hold, bool alt)
{
Logger.Log("**Trader.Interact called for " + ((Object)((Component)__instance).gameObject).name);
if (!ConfigurationFile.vendorLocalRestrictions.Value)
{
return true;
}
if (!grantedVendor(__instance))
{
string mandatoryBossToKill = getMandatoryBossToKill(__instance);
if (mandatoryBossToKill != null)
{
((Character)character).Message((MessageType)2, ConfigurationFile.forbiddenVendorMessage.Value.Replace("{0}", mandatoryBossToKill), 0, (Sprite)null);
return false;
}
}
return true;
}
private static string getMandatoryBossToKill(Trader trader)
{
if (((Object)((Component)trader).gameObject).name.StartsWith("Haldor") && ConfigurationFile.vendorHaldorBossToKill.Value != BossNameEnum.None)
{
return Localization.instance.Localize(KillMeForMyPowerUtils.getBossNameTranslation(ConfigurationFile.vendorHaldorBossToKill.Value));
}
if (((Object)((Component)trader).gameObject).name.StartsWith("Hildir") && ConfigurationFile.vendorHildirBossToKill.Value != BossNameEnum.None)
{
return Localization.instance.Localize(KillMeForMyPowerUtils.getBossNameTranslation(ConfigurationFile.vendorHildirBossToKill.Value));
}
if (((Object)((Component)trader).gameObject).name.StartsWith("BogWitch") && ConfigurationFile.vendorBogWitchBossToKill.Value != BossNameEnum.None)
{
return Localization.instance.Localize(KillMeForMyPowerUtils.getBossNameTranslation(ConfigurationFile.vendorBogWitchBossToKill.Value));
}
return null;
}
private static bool grantedVendor(Trader trader)
{
bool flag = ((Object)((Component)trader).gameObject).name.StartsWith("Haldor") && KillMeForMyPowerUtils.bossIsKilled(ConfigurationFile.vendorHaldorBossToKill.Value);
bool flag2 = ((Object)((Component)trader).gameObject).name.StartsWith("Hildir") && KillMeForMyPowerUtils.bossIsKilled(ConfigurationFile.vendorHildirBossToKill.Value);
bool flag3 = ((Object)((Component)trader).gameObject).name.StartsWith("BogWitch") && KillMeForMyPowerUtils.bossIsKilled(ConfigurationFile.vendorBogWitchBossToKill.Value);
return flag || flag2 || flag3;
}
}
[HarmonyPatch(typeof(Trader), "GetAvailableItems")]
public class TraderGetAvailableItemsPatch
{
[HarmonyPostfix]
public static void GetAvailableItemsPostfix(Trader __instance, ref List<TradeItem> __result)
{
Logger.Log("**Trader.GetAvailableItems called for " + ((Object)((Component)__instance).gameObject).name);
if (!ConfigurationFile.vendorLocalRestrictions.Value)
{
return;
}
List<TradeItem> list = new List<TradeItem>();
if (((Object)__instance).name.Contains("Haldor"))
{
addCustomItemsToRemove(__result, list, ConfigurationFile.vendorHaldorRestrictions.Value);
}
else if (((Object)__instance).name.Contains("Hildir"))
{
addCustomItemsToRemove(__result, list, ConfigurationFile.vendorHildirRestrictions.Value);
}
else if (((Object)__instance).name.Contains("BogWitch"))
{
addCustomItemsToRemove(__result, list, ConfigurationFile.vendorBogWitchRestrictions.Value);
}
foreach (TradeItem item in list)
{
__result.Remove(item);
}
}
private static void addCustomItemsToRemove(List<TradeItem> __result, List<TradeItem> customItemsToRemove, string vendorRestrictions)
{
if (string.IsNullOrEmpty(vendorRestrictions))
{
return;
}
string[] array = vendorRestrictions.Split(new char[1] { ';' });
string[] array2 = array;
foreach (string text in array2)
{
string[] array3 = text.Split(new char[1] { ',' });
Logger.Log("Checking vendor item " + array3[0] + " against " + array3[1]);
foreach (TradeItem item in __result)
{
Logger.Log("- Checking " + ((Object)((Component)item.m_prefab).gameObject).name + " from the vendor list...");
if (((Object)((Component)item.m_prefab).gameObject).name == array3[0])
{
if (!KillMeForMyPowerUtils.bossIsKilled(array3[1]))
{
customItemsToRemove.Add(item);
Logger.Log(array3[1] + " will be excluded.");
}
else
{
Logger.Log(array3[1] + " will NOT be excluded.");
}
break;
}
}
}
}
}
[HarmonyPatch(typeof(Vegvisir), "Interact")]
public class HildirMapTablePatch
{
public static bool Prefix(Vegvisir __instance, Humanoid character, bool hold, bool alt, ref bool __result)
{
if (character is Player && __instance.m_locations.FindAll((VegvisrLocation loc) => (int)loc.m_pinType == 14 || (int)loc.m_pinType == 15 || (int)loc.m_pinType == 16).Count > 0 && !KillMeForMyPowerUtils.HasDefeatedBossName(ConfigurationFile.vendorHildirBossToKill.Value))
{
((Character)character).Message((MessageType)2, ConfigurationFile.restrictUsingKeyItemsMessage.Value.Replace("{0}", ConfigurationFile.vendorHildirBossToKill.Value.GetTranslationKey()), 0, (Sprite)null);
Effects.scareEffect();
__result = false;
return false;
}
return true;
}
}
}
}
namespace KillMeForMyPower.Restrictions.BossNameManagement
{
public enum BossNameEnum
{
[BossNameAttr("Eikthyr", "GP_Eikthyr", "$enemy_eikthyr", "playerListForBoss1EikthyrPower")]
Eikthyr,
[BossNameAttr("gd_king", "GP_TheElder", "$enemy_gdking", "playerListForBoss2TheElderPower")]
TheElder,
[BossNameAttr("Bonemass", "GP_Bonemass", "$enemy_bonemass", "playerListForBoss3BonemassPower")]
Bonemass,
[BossNameAttr("Dragon", "GP_Moder", "$enemy_dragon", "playerListForBoss4ModerPower")]
Moder,
[BossNameAttr("GoblinKing", "GP_Yagluth", "$enemy_goblinking", "playerListForBoss5YagluthPower")]
Yagluth,
[BossNameAttr("SeekerQueen", "GP_Queen", "$enemy_seekerqueen", "playerListForBoss6QueenPower")]
Queen,
[BossNameAttr("Fader", "GP_Fader", "$enemy_fader", "playerListForBoss7FaderPower")]
Fader,
[BossNameAttr(null, null, null, null)]
None,
[BossNameAttr("BossGorr_TW", "SE_Boss_Gorr", "Gorr", "playerListForBoss8TherzieGorrPower")]
SE_Boss_Gorr,
[BossNameAttr("BossBrutalis_TW", "SE_Boss_Brutalis", "Brutalis", "playerListForBoss8TherzieBrutalisPower")]
SE_Boss_Brutalis,
[BossNameAttr("BossStormHerald_TW", "SE_Boss_StormHerald", "StormHerald", "playerListForBoss8TherzieStormHeraldPower")]
SE_Boss_StormHerald,
[BossNameAttr("BossSythrak_TW", "SE_Boss_Sythrak", "Sythrak", "playerListForBoss8TherzieSythrakPower")]
SE_Boss_Sythrak
}
internal class BossNameAttr : Attribute
{
public string prefabBossName { get; private set; }
public string translationKey { get; private set; }
public string powerKey { get; private set; }
public string configurationListName { get; private set; }
internal BossNameAttr(string prefabBossName, string powerKey, string translationKey, string configurationListName)
{
this.prefabBossName = prefabBossName;
this.powerKey = powerKey;
this.translationKey = translationKey;
this.configurationListName = configurationListName;
}
}
public static class BossNameFields
{
public static string GetGrantedPlayerNamesList(this BossNameEnum p)
{
BossNameAttr attr = GetAttr(p);
return ((ConfigEntry<string>)(typeof(ConfigurationFile).GetField(attr.configurationListName, BindingFlags.Static | BindingFlags.Public)?.GetValue(null)))?.Value;
}
public static string GetFightBossname(this BossNameEnum p)
{
BossNameAttr attr = GetAttr(p);
return attr.prefabBossName;
}
public static string GetTranslationKey(this BossNameEnum p)
{
BossNameAttr attr = GetAttr(p);
return attr.translationKey;
}
public static string GetPowerKey(this BossNameEnum p)
{
BossNameAttr attr = GetAttr(p);
return attr.powerKey;
}
public static string GetConfigurationListName(this BossNameEnum p)
{
BossNameAttr attr = GetAttr(p);
return attr.configurationListName;
}
private static BossNameAttr GetAttr(BossNameEnum p)
{
return (BossNameAttr)Attribute.GetCustomAttribute(ForValue(p), typeof(BossNameAttr));
}
private static MemberInfo ForValue(BossNameEnum p)
{
return typeof(BossNameEnum).GetField(Enum.GetName(typeof(BossNameEnum), p));
}
}
public static class BossNameUtils
{
public static void GrantBossPowerToPlayer(BossNameEnum bossNameEnum, string playerName, bool isAdd)
{
if (bossNameEnum != BossNameEnum.None)
{
UpdateConfigurationGrantedPlayersList(bossNameEnum, playerName, isAdd);
Logger.LogInfo("Player " + playerName + " " + (isAdd ? "defeated" : "removed") + $" {bossNameEnum}.");
}
}
public static bool IsBossPowerGrantedForPlayer(BossNameEnum bossNameEnum, Player player)
{
string grantedPlayerNamesList = bossNameEnum.GetGrantedPlayerNamesList();
return grantedPlayerNamesList.Contains(player.GetPlayerName());
}
[MethodImpl(MethodImplOptions.Synchronized)]
public static void UpdateConfigurationGrantedPlayersList(BossNameEnum bossNameEnum, string playerName, bool isAdd)
{
string grantedPlayerNamesList = bossNameEnum.GetGrantedPlayerNamesList();
if ((isAdd && grantedPlayerNamesList.Contains(playerName)) || (!isAdd && !grantedPlayerNamesList.Contains(playerName)))
{
return;
}
string text;
if (!string.IsNullOrEmpty(grantedPlayerNamesList))
{
string[] collection = grantedPlayerNamesList.Split(new char[1] { ',' });
List<string> list = new List<string>(collection);
if (isAdd)
{
list.Add(playerName);
}
else
{
list.Remove(playerName);
}
list.Sort();
text = string.Join(",", list.ToArray());
}
else
{
text = (isAdd ? playerName : "");
}
Logger.Log("Result to save: " + text);
switch (bossNameEnum)
{
case BossNameEnum.Eikthyr:
ConfigurationFile.playerListForBoss1EikthyrPower.Value = text;
break;
case BossNameEnum.TheElder:
ConfigurationFile.playerListForBoss2TheElderPower.Value = text;
break;
case BossNameEnum.Bonemass:
ConfigurationFile.playerListForBoss3BonemassPower.Value = text;
break;
case BossNameEnum.Moder:
ConfigurationFile.playerListForBoss4ModerPower.Value = text;
break;
case BossNameEnum.Yagluth:
ConfigurationFile.playerListForBoss5YagluthPower.Value = text;
break;
case BossNameEnum.Queen:
ConfigurationFile.playerListForBoss6QueenPower.Value = text;
break;
case BossNameEnum.Fader:
ConfigurationFile.playerListForBoss7FaderPower.Value = text;
break;
case BossNameEnum.SE_Boss_Gorr:
ConfigurationFile.playerListForBoss8TherzieGorrPower.Value = text;
break;
case BossNameEnum.SE_Boss_Brutalis:
ConfigurationFile.playerListForBoss8TherzieBrutalisPower.Value = text;
break;
case BossNameEnum.SE_Boss_StormHerald:
ConfigurationFile.playerListForBoss8TherzieStormHeraldPower.Value = text;
break;
case BossNameEnum.SE_Boss_Sythrak:
ConfigurationFile.playerListForBoss8TherzieSythrakPower.Value = text;
break;
default:
Logger.LogWarning("Not saved, boss not found!");
break;
}
}
}
[HarmonyPatch(typeof(Game), "Start")]
public class GameStartPatch
{
private static void Prefix()
{
ZRoutedRpc.instance.Register<string, string>("RPC_BossPowerGrantServer", (Action<long, string, string>)RPC_BossPowerGrantCalls.RPC_BossPowerGrantServer);
ZRoutedRpc.instance.Register<string, string>("RPC_BossPowerRemoveGrantServer", (Action<long, string, string>)RPC_BossPowerGrantCalls.RPC_BossPowerRemoveGrantServer);
}
}
}
namespace KillMeForMyPower.Managers
{
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 IsLoaded()
{
Init();
return state == API_State.Ready;
}
public static int GetLevel()
{
int result = 0;
Init();
if (eGetLevel != null)
{
result = (int)eGetLevel.Invoke(null, null);
}
return result;
}
public static int GetAttribute(Attribut attribute)
{
int result = 0;
Init();
if (eGetAttribute != null)
{
result = (int)eGetAttribute.Invoke(null, new object[1] { attribute });
}
return result;
}
public static int GetAttributeRusty(string attribute)
{
int result = 0;
Init();
if (eGetAttributeRusty != null)
{
result = (int)eGetAttributeRusty.Invoke(null, new object[1] { attribute });
}
return result;
}
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)
{
if (Type.GetType("EpicMMOSystem.EpicMMOSystem, EpicMMOSystem") == null)
{
state = API_State.NotInstalled;
return;
}
state = API_State.Ready;
Type type = Type.GetType("API.EMMOS_API, EpicMMOSystem");
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("GetAttribute", BindingFlags.Static | BindingFlags.Public);
eSetSingleRate = type?.GetMethod("SetSingleRate", BindingFlags.Static | BindingFlags.Public);
}
}
}
public class GameManager
{
public static object GetPrivateValue(object obj, string name, BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.NonPublic)
{
return obj.GetType().GetField(name, bindingAttr)?.GetValue(obj);
}
public static object GetPrivateMethod(object obj, string name, BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.NonPublic)
{
return obj.GetType().GetMethod(name, bindingAttr)?.Invoke(obj, null);
}
public static bool isDetailedLevelsInstalled()
{
return Chainloader.PluginInfos.ContainsKey("Turbero.DetailedLevels");
}
public static bool IsAdmin(Player player)
{
//IL_0080: Unknown result type (might be due to invalid IL or missing references)
//IL_0085: Unknown result type (might be due to invalid IL or missing references)
//IL_008a: Unknown result type (might be due to invalid IL or missing references)
Logger.Log("[IsAdmin] Checking powerCommandsAdminPlayersList...");
string playerName = player.GetPlayerName();
if (ConfigurationFile.powerCommandsAdminPlayersList.Value.Contains(playerName))
{
return true;
}
Logger.Log("[IsAdmin] Finding All PlayerInfo...");
List<PlayerInfo> list = ZNet.instance.GetPlayerList().FindAll((PlayerInfo p) => p.m_name == playerName);
if (list.Count == 0)
{
return false;
}
string userID = list[0].m_userInfo.m_id.m_userID;
Logger.Log("[IsAdmin] Matching steamID " + userID + " in adminList...");
return (Object)(object)ZNet.instance != (Object)null && ZNet.instance.GetAdminList() != null && ZNet.instance.GetAdminList().Contains(userID);
}
}
}
namespace KillMeForMyPower.Commands
{
public class PowerManagementCommands
{
[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 <RegisterConsoleCommand>b__0_0(ConsoleEventArgs args)
{
if (!GameManager.IsAdmin(Player.m_localPlayer))
{
args.Context.AddString("You are not an admin.");
return;
}
if (args.Args.Length < 3)
{
args.Context.AddString("Usage: add_power <name> <boss_name>");
return;
}
ZRoutedRpc.instance.InvokeRoutedRPC(0L, "RPC_BossPowerGrantServer", new object[2]
{
args.Args[2],
args.Args[1]
});
}
internal void <RegisterConsoleCommand>b__0_1(ConsoleEventArgs args)
{
if (!GameManager.IsAdmin(Player.m_localPlayer))
{
args.Context.AddString("You are not an admin.");
return;
}
if (args.Args.Length < 3)
{
args.Context.AddString("Usage: add_power <name> <boss_name>");
return;
}
ZRoutedRpc.instance.InvokeRoutedRPC(0L, "RPC_BossPowerRemoveGrantServer", new object[2]
{
args.Args[2],
args.Args[1]
});
}
}
public static void RegisterConsoleCommand()
{
//IL_0033: Unknown result type (might be due to invalid IL or missing references)
//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_002a: Expected O, but got Unknown
//IL_006b: Unknown result type (might be due to invalid IL or missing references)
//IL_0057: Unknown result type (might be due to invalid IL or missing references)
//IL_005c: Unknown result type (might be due to invalid IL or missing references)
//IL_0062: Expected O, but got Unknown
object obj = <>c.<>9__0_0;
if (obj == null)
{
ConsoleEvent val = delegate(ConsoleEventArgs args)
{
if (!GameManager.IsAdmin(Player.m_localPlayer))
{
args.Context.AddString("You are not an admin.");
}
else if (args.Args.Length < 3)
{
args.Context.AddString("Usage: add_power <name> <boss_name>");
}
else
{
ZRoutedRpc.instance.InvokeRoutedRPC(0L, "RPC_BossPowerGrantServer", new object[2]
{
args.Args[2],
args.Args[1]
});
}
};
<>c.<>9__0_0 = val;
obj = (object)val;
}
new ConsoleCommand("add_power", "[player] [boss_name]", (ConsoleEvent)obj, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false);
object obj2 = <>c.<>9__0_1;
if (obj2 == null)
{
ConsoleEvent val2 = delegate(ConsoleEventArgs args)
{
if (!GameManager.IsAdmin(Player.m_localPlayer))
{
args.Context.AddString("You are not an admin.");
}
else if (args.Args.Length < 3)
{
args.Context.AddString("Usage: add_power <name> <boss_name>");
}
else
{
ZRoutedRpc.instance.InvokeRoutedRPC(0L, "RPC_BossPowerRemoveGrantServer", new object[2]
{
args.Args[2],
args.Args[1]
});
}
};
<>c.<>9__0_1 = val2;
obj2 = (object)val2;
}
new ConsoleCommand("remove_power", "[boss_order] [player]", (ConsoleEvent)obj2, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false);
}
}
public class CheckBossesCommand
{
[Serializable]
[CompilerGenerated]
private sealed class <>c
{
public static readonly <>c <>9 = new <>c();
public static ConsoleEvent <>9__0_0;
internal void <RegisterConsoleCommand>b__0_0(ConsoleEventArgs args)
{
bool flag = false;
string playerName = Player.m_localPlayer.GetPlayerName();
args.Context.AddString("=== Bosses killed and allowed to use their powers ===");
foreach (BossNameEnum value in Enum.GetValues(typeof(BossNameEnum)))
{
if (!string.IsNullOrEmpty(value.GetConfigurationListName()))
{
string grantedPlayerNamesList = value.GetGrantedPlayerNamesList();
if ((!string.IsNullOrEmpty(grantedPlayerNamesList) && grantedPlayerNamesList.Contains(playerName)) || (ConfigurationFile.activateMidPlayDetection.Value && ((Humanoid)Player.m_localPlayer).HaveUniqueKey(value.GetPowerKey())))
{
args.Context.AddString("- " + Localization.instance.Localize(value.GetTranslationKey()));
flag = true;
}
}
}
if (!flag)
{
args.Context.AddString("NONE");
}
}
}
public static void RegisterConsoleCommand()
{
//IL_0033: Unknown result type (might be due to invalid IL or missing references)
//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_002a: Expected O, but got Unknown
object obj = <>c.<>9__0_0;
if (obj == null)
{
ConsoleEvent val = delegate(ConsoleEventArgs args)
{
bool flag = false;
string playerName = Player.m_localPlayer.GetPlayerName();
args.Context.AddString("=== Bosses killed and allowed to use their powers ===");
foreach (BossNameEnum value in Enum.GetValues(typeof(BossNameEnum)))
{
if (!string.IsNullOrEmpty(value.GetConfigurationListName()))
{
string grantedPlayerNamesList = value.GetGrantedPlayerNamesList();
if ((!string.IsNullOrEmpty(grantedPlayerNamesList) && grantedPlayerNamesList.Contains(playerName)) || (ConfigurationFile.activateMidPlayDetection.Value && ((Humanoid)Player.m_localPlayer).HaveUniqueKey(value.GetPowerKey())))
{
args.Context.AddString("- " + Localization.instance.Localize(value.GetTranslationKey()));
flag = true;
}
}
}
if (!flag)
{
args.Context.AddString("NONE");
}
};
<>c.<>9__0_0 = val;
obj = (object)val;
}
new ConsoleCommand("bosses_permissions", "", (ConsoleEvent)obj, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false);
}
}
}
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 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;
}
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 : 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;
}
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())
{
BufferingSocket value = new BufferingSocket(rpc.GetSocket());
AccessTools.DeclaredField(typeof(ZRpc), "m_socket").SetValue(rpc, value);
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)
{
AccessTools.DeclaredField(typeof(ZNetPeer), "m_socket").SetValue(val, value);
}
if (__state == null)
{
__state = new Dictionary<Assembly, BufferingSocket>();
}
__state[Assembly.GetExecutingAssembly()] = value;
}
}
[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, __instance.SettingType);
return false;
}
}
[HarmonyPatch(typeof(ConfigEntryBase), "SetSerializedValue")]
private static class PreventConfigRereadChangingValues
{
[HarmonyPrefix]
private static bool Prefix(ConfigEntryBase __instance, string value)
{
OwnConfigEntryBase ownConfigEntryBase = configData(__instance);
if (ownConfigEntryBase == null || ownConfigEntryBase.LocalBaseValue == null)
{
return true;
}
try
{
ownConfigEntryBase.LocalBaseValue = TomlTypeConverter.ConvertToValue(value, __instance.SettingType);
}
catch (Exception ex)
{
Debug.LogWarning((object)$"Config value of setting \"{__instance.Definition}\" could not be parsed and will be ignored. Reason: {ex.Message}; Value: {value}");
}
return false;
}
}
private class InvalidDeserializationTypeException : Exception
{
public string expected = null;
public string received = null;
public string field = "";
}
public static bool ProcessingServerUpdate;
public readonly string Name;
public string? DisplayName;
public string? CurrentVersion;
public string? MinimumRequiredVersion;
public bool ModRequired = false;
private bool? forceConfigLocking;
private bool isSourceOfTruth = true;
private static readonly HashSet<ConfigSync> configSyncs;
private readonly HashSet<OwnConfigEntryBase> allConfigs = new HashSet<OwnConfigEntryBase>();
private HashSet<CustomSyncedValueBase> allCustomValues = new HashSet<CustomSyncedValueBase>();
private static bool isServer;
private static bool lockExempt;
private OwnConfigEntryBase? lockedConfig = null;
private const byte PARTIAL_CONFIGS = 1;
private const byte FRAGMENTED_CONFIG = 2;
private const byte COMPRESSED_CONFIG = 4;
private readonly Dictionary<string, SortedDictionary<int, byte[]>> configValueCache = new Dictionary<string, SortedDictionary<int, byte[]>>();
private readonly List<KeyValuePair<long, string>> cacheExpirations = new List<KeyValuePair<long, string>>();
private static long packageCounter;
public bool IsLocked
{
get
{
bool? flag = forceConfigLocking;
bool num;
if (!flag.HasValue)
{
if (lockedConfig == null)
{
goto IL_0052;
}
num = ((IConvertible)lockedConfig.BaseConfig.BoxedValue).ToInt32(CultureInfo.InvariantCulture) != 0;
}
else
{
num = flag.GetValueOrDefault();
}
if (!num)
{
goto IL_0052;
}
int result = ((!lockExempt) ? 1 : 0);
goto IL_0053;
IL_0053:
return (byte)result != 0;
IL_0052:
result = 0;
goto IL_0053;
}
set
{
forceConfigLocking = value;
}
}
public bool IsAdmin => lockExempt || isSourceOfTruth;
public bool IsSourceOfTruth
{
get
{
return isSourceOfTruth;
}
private set
{
if (value != isSourceOfTruth)
{
isSourceOfTruth = value;
this.SourceOfTruthChanged?.Invoke(value);
}
}
}
public bool InitialSyncDone { get; private set; } = false;
public event Action<bool>? SourceOfTruthChanged;
private event Action? lockedConfigChanged;
static ConfigSync()
{
ProcessingServerUpdate = false;
configSyncs = new HashSet<ConfigSync>();
lockExempt = false;
packageCounter = 0L;
RuntimeHelpers.RunClassConstructor(typeof(VersionCheck).TypeHandle);
}
public ConfigSync(string name)
{
Name = name;
configSyncs.Add(this);
new VersionCheck(this);
}
public SyncedConfigEntry<T> AddConfigEntry<T>(ConfigEntry<T> configEntry)
{
ConfigEntry<T> configEntry2 = configEntry;
OwnConfigEntryBase ownConfigEntryBase = configData((ConfigEntryBase)(object)configEntry2);
SyncedConfigEntry<T> syncedEntry = ownConfigEntryBase as SyncedConfigEntry<T>;
if (syncedEntry == null)
{
syncedEntry = new SyncedConfigEntry<T>(configEntry2);
AccessTools.DeclaredField(typeof(ConfigDescription), "<Tags>k__BackingField").SetValue(((ConfigEntryBase)configEntry2).Description, new object[1]
{
new ConfigurationManagerAttributes()
}.Concat(((ConfigEntryBase)configEntry2).Description.Tags ?? Array.Empty<object>()).Concat(new SyncedConfigEntry<T>[1] { syncedEntry }).ToArray());
configEntry2.SettingChanged += delegate
{
if (!ProcessingServerUpdate && syncedEntry.SynchronizedConfig)
{
Broadcast(ZRoutedRpc.Everybody, (ConfigEntryBase)configEntry2);
}
};
allConfigs.Add(syncedEntry);
}
return syncedEntry;
}
public SyncedConfigEntry<T> AddLockingConfigEntry<T>(ConfigEntry<T> lockingConfig) where T : IConvertible
{
if (lockedConfig != null)
{
throw new Exception("Cannot initialize locking ConfigEntry twice");
}
lockedConfig = AddConfigEntry<T>(lockingConfig);
lockingConfig.SettingChanged += delegate
{
this.lockedConfigChanged?.Invoke();
};
return (SyncedConfigEntry<T>)lockedConfig;
}
internal void AddCustomValue(CustomSyncedValueBase customValue)
{
CustomSyncedValueBase customValue2 = customValue;
if (allCustomValues.Select((CustomSyncedValueBase v) => v.Identifier).Concat(new string[1] { "serverversion" }).Contains(customValue2.Identifier))
{
throw new Exception("Cannot have multiple settings with the same name or with a reserved name (serverversion)");
}
allCustomValues.Add(customValue2);
allCustomValues = new HashSet<CustomSyncedValueBase>(allCustomValues.OrderByDescending((CustomSyncedValueBase v) => v.Priority));
customValue2.ValueChanged += delegate
{
if (!ProcessingServerUpdate)
{
Broadcast(ZRoutedRpc.Everybody, customValue2);
}
};
}
private void RPC_FromServerConfigSync(ZRpc rpc, ZPackage package)
{
lockedConfigChanged += serverLockedSettingChanged;
IsSourceOfTruth = false;
if (HandleConfigSyncRPC(0L, package, clientUpdate: false))
{
InitialSyncDone = true;
}
}
private void RPC_FromOtherClientConfigSync(long sender, ZPackage package)
{
HandleConfigSyncRPC(sender, package, clientUpdate: true);
}
private bool HandleConfigSyncRPC(long sender, Z