using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using Jotunn.Configs;
using Jotunn.Entities;
using Jotunn.Managers;
using Jotunn.Utils;
using Microsoft.CodeAnalysis;
using Splatform;
using UnityEngine;
using UnityEngine.PostProcessing;
using Zen;
using Zen.Interop;
using Zen.Lib;
using Zen.Lib.Config;
using ZenPortal.StatusEffects;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("ZenPortal")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("ZenPortal")]
[assembly: AssemblyCopyright("Copyright \ufffd 2021")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("e3243d22-4307-4008-ba36-9f326008cde5")]
[assembly: AssemblyFileVersion("0.0.1.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.0.1.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
internal sealed class NullableAttribute : Attribute
{
public readonly byte[] NullableFlags;
public NullableAttribute(byte P_0)
{
NullableFlags = new byte[1] { P_0 };
}
public NullableAttribute(byte[] P_0)
{
NullableFlags = P_0;
}
}
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
internal sealed class NullableContextAttribute : Attribute
{
public readonly byte Flag;
public NullableContextAttribute(byte P_0)
{
Flag = P_0;
}
}
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
internal sealed class RefSafetyRulesAttribute : Attribute
{
public readonly int Version;
public RefSafetyRulesAttribute(int P_0)
{
Version = P_0;
}
}
}
namespace ZenPortal
{
internal static class Animations
{
private static PostProcessingBehaviour? _cameraPost;
private static Incinerator IncineratorPrefab => GlobalStatic.GetPrefab<Incinerator>("incinerator", true);
private static PostProcessingBehaviour CameraPost
{
get
{
if (!Object.op_Implicit((Object)(object)_cameraPost))
{
return _cameraPost = ((Component)GameCamera.instance.m_camera).GetComponent<PostProcessingBehaviour>();
}
return _cameraPost;
}
}
public static void Eat(Humanoid human, ItemData item)
{
//IL_000c: Unknown result type (might be due to invalid IL or missing references)
//IL_0011: Unknown result type (might be due to invalid IL or missing references)
human.m_consumeItemEffects.Create(((Component)human).transform.position, Quaternion.identity, (Transform)null, 1f, -1);
((Character)human).m_zanim.SetTrigger("eat");
GameObject val = default(GameObject);
if (ObjectDB.instance.TryGetItemPrefab(item.m_shared, ref val))
{
human.SetUseHandVisual(val, item.m_shared.m_foodEatAnimTime);
}
}
public static void Kneel(this Player player, float seconds, Action? onFinished = null, bool autoStand = true)
{
Player player2 = player;
Action onFinished2 = onFinished;
player2.StartEmote("Kneel".ToLowerInvariant(), true);
PlayerController.SetTakeInputDelay(seconds);
Timing.Delay((MonoBehaviour)(object)player2, seconds, (Action)delegate
{
if (Object.op_Implicit((Object)(object)player2) && autoStand)
{
((Character)player2).StopEmote();
}
onFinished2?.Invoke();
});
}
public static void DistantThunder(this Character character)
{
DistantThunder(((Component)character).transform);
}
public static void DistantThunder(this RuneStone runestone)
{
DistantThunder(((Component)runestone).transform);
}
private static void DistantThunder(Transform transform)
{
//IL_000b: Unknown result type (might be due to invalid IL or missing references)
//IL_0011: Unknown result type (might be due to invalid IL or missing references)
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
//IL_001b: Unknown result type (might be due to invalid IL or missing references)
//IL_004a: Unknown result type (might be due to invalid IL or missing references)
//IL_0050: Expected O, but got Unknown
GameObject[] array = IncineratorPrefab.m_leverEffects.Create(transform.position - transform.forward, Quaternion.identity, (Transform)null, 1f, -1);
for (int i = 0; i < array.Length; i++)
{
foreach (Transform item in array[i].transform)
{
Transform val = item;
string name = ((Object)val).name;
if ((name == "Sparks" || name == "sfx_lever") ? true : false)
{
((Component)val).gameObject.SetActive(false);
}
else if (((Object)val).name.StartsWith("Point light"))
{
((Component)val).gameObject.SetActive(true);
}
}
}
}
public static void LightningStrike(this Character character, bool knockback = false)
{
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
//IL_000b: Unknown result type (might be due to invalid IL or missing references)
LightningStrike(((Component)character).transform.position, Quaternion.identity, knockback);
}
public static void LightningStrike(this RuneStone runestone, bool knockback = true)
{
//IL_0008: Unknown result type (might be due to invalid IL or missing references)
//IL_000e: Unknown result type (might be due to invalid IL or missing references)
//IL_0018: Unknown result type (might be due to invalid IL or missing references)
//IL_001d: Unknown result type (might be due to invalid IL or missing references)
//IL_0022: Unknown result type (might be due to invalid IL or missing references)
Transform transform = ((Component)runestone).transform;
LightningStrike(transform.position - transform.forward * 0.5f, Quaternion.identity, knockback);
}
private static void LightningStrike(Vector3 position, Quaternion rotation, bool knockback)
{
//IL_000a: Unknown result type (might be due to invalid IL or missing references)
//IL_000b: 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
foreach (Transform item in Object.Instantiate<GameObject>(IncineratorPrefab.m_lightingAOEs, position, rotation).transform)
{
Transform val = item;
if (((Object)val).name.StartsWith("vfx_RockHit"))
{
((Component)val).gameObject.SetActive(true);
}
else if (((Object)val).name == "AOE_ROD")
{
((Component)val).gameObject.SetActive(false);
}
else if (((Object)val).name == "AOE_AREA")
{
((Component)val).gameObject.SetActive(knockback);
}
}
}
public static void SetCameraState(bool inverted)
{
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
//IL_002c: Unknown result type (might be due to invalid IL or missing references)
//IL_002e: Unknown result type (might be due to invalid IL or missing references)
//IL_0031: Unknown result type (might be due to invalid IL or missing references)
//IL_005b: Unknown result type (might be due to invalid IL or missing references)
//IL_005d: Unknown result type (might be due to invalid IL or missing references)
//IL_0060: Unknown result type (might be due to invalid IL or missing references)
//IL_008a: Unknown result type (might be due to invalid IL or missing references)
//IL_008c: Unknown result type (might be due to invalid IL or missing references)
//IL_008f: Unknown result type (might be due to invalid IL or missing references)
//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
//IL_00be: Unknown result type (might be due to invalid IL or missing references)
//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
//IL_0118: Unknown result type (might be due to invalid IL or missing references)
//IL_011a: Unknown result type (might be due to invalid IL or missing references)
//IL_0134: Unknown result type (might be due to invalid IL or missing references)
//IL_0139: Unknown result type (might be due to invalid IL or missing references)
//IL_015e: Unknown result type (might be due to invalid IL or missing references)
//IL_0163: Unknown result type (might be due to invalid IL or missing references)
//IL_019a: Unknown result type (might be due to invalid IL or missing references)
//IL_019b: Unknown result type (might be due to invalid IL or missing references)
//IL_01a7: Unknown result type (might be due to invalid IL or missing references)
//IL_01a8: Unknown result type (might be due to invalid IL or missing references)
//IL_01b4: Unknown result type (might be due to invalid IL or missing references)
//IL_01b5: Unknown result type (might be due to invalid IL or missing references)
//IL_016f: Unknown result type (might be due to invalid IL or missing references)
//IL_0170: Unknown result type (might be due to invalid IL or missing references)
//IL_017c: Unknown result type (might be due to invalid IL or missing references)
//IL_017e: Unknown result type (might be due to invalid IL or missing references)
//IL_018a: Unknown result type (might be due to invalid IL or missing references)
//IL_018c: Unknown result type (might be due to invalid IL or missing references)
//IL_01c6: Unknown result type (might be due to invalid IL or missing references)
Vector3 val = default(Vector3);
val.x = 1f;
val.y = 0f;
val.z = 0f;
Vector3 red = val;
val = default(Vector3);
val.x = 0f;
val.y = 1f;
val.z = 0f;
Vector3 green = val;
val = default(Vector3);
val.x = 0f;
val.y = 0f;
val.z = 1f;
Vector3 blue = val;
val = default(Vector3);
val.x = 0f;
val.y = 1f;
val.z = 1f;
Vector3 red2 = val;
val = default(Vector3);
val.x = 1f;
val.y = 0f;
val.z = 1f;
Vector3 green2 = val;
val = default(Vector3);
val.x = 1f;
val.y = 1f;
val.z = 0f;
Vector3 blue2 = val;
PostProcessingBehaviour cameraPost = CameraPost;
Logging<Plugin>.Info((object)("frameBlending: " + cameraPost.profile.motionBlur.settings.frameBlending), 0);
Settings settings = cameraPost.profile.colorGrading.settings;
if (inverted)
{
settings.channelMixer.red = red2;
settings.channelMixer.green = green2;
settings.channelMixer.blue = blue2;
}
else
{
settings.channelMixer.red = red;
settings.channelMixer.green = green;
settings.channelMixer.blue = blue;
}
cameraPost.profile.colorGrading.settings = settings;
}
}
[HarmonyPatch]
internal static class BiomeTeleport
{
private static readonly Dictionary<Biome, List<Vector2i>> SafeBiomeTeleportPositions = new Dictionary<Biome, List<Vector2i>>();
private static string? _tombstoneText;
public static bool IsTeleportBiome(this Biome biome)
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_0006: Invalid comparison between Unknown and I4
//IL_0008: Unknown result type (might be due to invalid IL or missing references)
//IL_000b: Unknown result type (might be due to invalid IL or missing references)
//IL_0011: Invalid comparison between Unknown and I4
if ((int)biome != 256 && (int)biome != 0)
{
return (int)biome != 895;
}
return false;
}
private static List<Vector2i> GetZones(Biome biome)
{
//IL_0005: Unknown result type (might be due to invalid IL or missing references)
//IL_0011: Unknown result type (might be due to invalid IL or missing references)
//IL_0036: Unknown result type (might be due to invalid IL or missing references)
//IL_0026: Unknown result type (might be due to invalid IL or missing references)
if (SafeBiomeTeleportPositions.TryGetValue(biome, out List<Vector2i> value))
{
return value;
}
if ((int)biome == 0)
{
Logging<Plugin>.Info((object)"Biome: None, returning location 0,0 (start temple)", 0);
return new List<Vector2i>(1) { Vector2i.zero };
}
Logging<Plugin>.Info((object)$"Biome {biome}, returning all possible locations", 0);
return SafeBiomeTeleportPositions.Values.SelectMany((List<Vector2i> z) => z).ToList();
}
public static void InitTeleportZoneCache()
{
//IL_005f: 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_0066: Unknown result type (might be due to invalid IL or missing references)
//IL_0068: Unknown result type (might be due to invalid IL or missing references)
//IL_0076: Unknown result type (might be due to invalid IL or missing references)
//IL_008c: Unknown result type (might be due to invalid IL or missing references)
//IL_009f: Unknown result type (might be due to invalid IL or missing references)
//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
//IL_00af: Unknown result type (might be due to invalid IL or missing references)
Logging<Plugin>.Info((object)"Building biome zone cache...", 0);
int num = Mathf.CeilToInt((float)Configs.CompatibilityWorldSize.Value);
int num2 = Mathf.CeilToInt(ZoneSystem.instance.m_zoneSize);
SafeBiomeTeleportPositions.Clear();
int num3 = 0;
Vector3 val = default(Vector3);
Color val2 = default(Color);
for (int i = -num; i <= num; i += num2)
{
for (int j = -num; j <= num; j += num2)
{
((Vector3)(ref val))..ctor((float)i, 0f, (float)j);
Biome biome = WorldGenerator.instance.GetBiome(val);
if (biome.IsTeleportBiome() && !(WorldGenerator.instance.GetBiomeHeight(biome, (float)i, (float)j, ref val2, false) <= 30f) && !ZoneSystem.IsLavaPreHeightmap(val, 0.6f))
{
if (!SafeBiomeTeleportPositions.TryGetValue(biome, out List<Vector2i> value))
{
value = (SafeBiomeTeleportPositions[biome] = new List<Vector2i>());
}
value.Add(new Vector2i(i, j));
num3++;
}
}
}
Logging<Plugin>.Info((object)$"Zones added to cache: {num3}", 0);
}
public static void DropAllNoTeleport(this Player player)
{
Logging<Plugin>.Info((object)"Drop all no teleport items", 0);
Inventory inventory = ((Humanoid)player).GetInventory();
ItemData[] array = (from item in inventory.GetAllItems()
where !item.m_shared.m_teleportable
select item).ToArray();
foreach (ItemData val in array)
{
((Humanoid)player).DropItem(inventory, val, val.m_stack);
}
}
public static Vector3 GetRandomTeleportPosition(Biome biome, float yOffset = 0f)
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_0014: Unknown result type (might be due to invalid IL or missing references)
//IL_0019: 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_0026: 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_003d: 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)
List<Vector2i> zones = GetZones(biome);
Vector2i val = zones[Random.Range(0, zones.Count)];
float height = WorldGenerator.instance.GetHeight((float)val.x, (float)val.y);
return new Vector3((float)val.x, height + yOffset, (float)val.y);
}
private static Vector3 GetRuneTeleportPosition(RuneID runeID, float yOffset = 0f)
{
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
//IL_000d: Unknown result type (might be due to invalid IL or missing references)
//IL_0032: Unknown result type (might be due to invalid IL or missing references)
//IL_0037: 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_0044: Unknown result type (might be due to invalid IL or missing references)
//IL_0051: Unknown result type (might be due to invalid IL or missing references)
//IL_005b: Unknown result type (might be due to invalid IL or missing references)
//IL_0062: Unknown result type (might be due to invalid IL or missing references)
List<Vector2i> zones = GetZones(runeID.Biome);
State state = Random.state;
Random.InitState(runeID.Identity);
int index = Random.Range(0, zones.Count);
Random.state = state;
Vector2i val = zones[index];
float height = WorldGenerator.instance.GetHeight((float)val.x, (float)val.y);
return new Vector3((float)val.x, height + yOffset, (float)val.y);
}
public static void TeleportToRuneAddress(this Player? player, RuneID runeID)
{
//IL_0028: 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_0042: Unknown result type (might be due to invalid IL or missing references)
//IL_004f: Unknown result type (might be due to invalid IL or missing references)
//IL_0050: Unknown result type (might be due to invalid IL or missing references)
//IL_0053: Unknown result type (might be due to invalid IL or missing references)
//IL_006c: Unknown result type (might be due to invalid IL or missing references)
//IL_006d: Unknown result type (might be due to invalid IL or missing references)
//IL_0060: Unknown result type (might be due to invalid IL or missing references)
//IL_0065: Unknown result type (might be due to invalid IL or missing references)
Player player2 = player;
if (Object.op_Implicit((Object)(object)player2))
{
Logging<Plugin>.Info((object)$"Teleport to {runeID} biome {runeID.Biome}", 0);
Vector3 zero = Vector3.zero;
zero.y = 50f;
Vector3 val = zero;
if ((int)runeID.Biome != 0)
{
val = GetRuneTeleportPosition(runeID, 30f);
}
((Character)player2).TeleportTo(val, Quaternion.identity, true);
Timing.Delay((MonoBehaviour)(object)player2, 4f, (Action)delegate
{
SlowFallUngrounded.ApplyTo(player2);
});
}
}
public static void LightningTeleport(this Player? player, Vector3 position, string? tombstoneText)
{
//IL_0015: Unknown result type (might be due to invalid IL or missing references)
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
//IL_002f: Unknown result type (might be due to invalid IL or missing references)
Player player2 = player;
string tombstoneText2 = tombstoneText;
if (!Object.op_Implicit((Object)(object)player2))
{
return;
}
Logging<Plugin>.Info((object)$"Lightning teleport to: {position}", 0);
player2.Kneel(8f);
((Character)(object)player2).DistantThunder();
Timing.Delay((MonoBehaviour)(object)player2, 4.5f, (Action)delegate
{
if (Object.op_Implicit((Object)(object)player2))
{
if (tombstoneText2 != null)
{
player2.DropTombstone(tombstoneText2);
}
((Character)(object)player2).LightningStrike();
((Character)player2).m_visual.SetActive(false);
Timing.Delay((MonoBehaviour)(object)player2, 0.5f, (Action)delegate
{
//IL_0015: Unknown result type (might be due to invalid IL or missing references)
//IL_001a: Unknown result type (might be due to invalid IL or missing references)
if (Object.op_Implicit((Object)(object)player2))
{
((Character)player2).TeleportTo(position, Quaternion.identity, true);
Timing.Delay((MonoBehaviour)(object)player2, 4f, (Action)delegate
{
SlowFallUngrounded.ApplyTo(player2);
if (Object.op_Implicit((Object)(object)player2))
{
((Character)player2).m_visual.SetActive(true);
}
});
}
});
}
});
}
private static void DropTombstone(this Player player, string? text)
{
//IL_0014: Unknown result type (might be due to invalid IL or missing references)
//IL_0019: Unknown result type (might be due to invalid IL or missing references)
//IL_0052: Unknown result type (might be due to invalid IL or missing references)
//IL_0064: Unknown result type (might be due to invalid IL or missing references)
//IL_006a: Unknown result type (might be due to invalid IL or missing references)
if (((Humanoid)player).GetInventory().NrOfItems() != 0)
{
Vector3 position = ((Component)player).transform.position;
((Humanoid)player).UnequipAllItems();
((Humanoid)player).m_hiddenLeftItem = null;
((Humanoid)player).m_hiddenRightItem = null;
((Humanoid)player).SetupVisEquipment(((Humanoid)player).m_visEquipment, false);
_tombstoneText = text;
player.CreateTombStone();
_tombstoneText = null;
Minimap.instance.AddPin(position, (PinType)4, ItemDataExt.GetName(ItemRuneShard.Prefab), true, false, 0L, default(PlatformUserID));
}
}
[HarmonyPostfix]
[HarmonyPatch(typeof(TombStone), "Setup")]
[HarmonyPriority(200)]
private static void TombStone_Setup(TombStone __instance)
{
if (_tombstoneText != null)
{
__instance.m_nview.GetZDO().Set(ZDOVars.s_text, _tombstoneText);
}
}
}
internal static class BitUtils
{
private static class BitPermuter
{
public static uint Mix(uint value, uint seed, int bits)
{
if ((bits < 2 || bits > 32) ? true : false)
{
throw new ArgumentOutOfRangeException("bits");
}
uint num = Mask(bits);
value &= num;
seed &= num;
int num2 = bits / 2;
int rightBits = bits - num2;
(int, int)[] array = BuildWidths(num2, rightBits);
uint num3 = value;
for (int i = 0; i < 4; i++)
{
num3 = MixRound(num3, seed, i, array[i].Item1, array[i].Item2);
}
return num3 & num;
}
public static uint Unmix(uint value, uint seed, int bits)
{
if ((bits < 2 || bits > 32) ? true : false)
{
throw new ArgumentOutOfRangeException("bits");
}
uint num = Mask(bits);
value &= num;
seed &= num;
int num2 = bits / 2;
int rightBits = bits - num2;
(int, int)[] array = BuildWidths(num2, rightBits);
uint num3 = value;
for (int num4 = 3; num4 >= 0; num4--)
{
num3 = UnmixRound(num3, seed, num4, array[num4].Item1, array[num4].Item2);
}
return num3 & num;
}
private static (int leftBits, int rightBits)[] BuildWidths(int leftBits0, int rightBits0)
{
(int, int)[] array = new(int, int)[4];
int num = leftBits0;
int num2 = rightBits0;
for (int i = 0; i < 4; i++)
{
array[i] = (num, num2);
int num3 = num2;
num2 = num;
num = num3;
}
return array;
}
private static uint MixRound(uint value, uint seed, int round, int leftBits, int rightBits)
{
uint num = Mask(leftBits);
uint num2 = Mask(rightBits);
uint num3 = (value >> rightBits) & num;
uint num4 = value & num2;
uint key = RoundKey(seed, round, rightBits);
uint num5 = RoundFunction(num4, key, leftBits);
uint num6 = num4 & num2;
uint num7 = (num3 ^ num5) & num;
return (num6 << leftBits) | num7;
}
private static uint UnmixRound(uint value, uint seed, int round, int leftBits, int rightBits)
{
uint num = Mask(leftBits);
uint num2 = Mask(rightBits);
uint num3 = (value >> leftBits) & num2;
uint num4 = value & num;
uint key = RoundKey(seed, round, rightBits);
uint num5 = num3;
return (((num4 ^ RoundFunction(num5, key, leftBits)) & num) << rightBits) | num5;
}
private static uint RoundFunction(uint x, uint key, int outBits)
{
uint num = Mask(outBits);
x ^= key;
x = (x * 17881) & 0xFFFFFFFFu;
x ^= x >> 7;
x = (x * 668265261) & 0xFFFFFFFFu;
x ^= x >> 9;
return x & num;
}
private static uint RoundKey(uint seed, int round, int bits)
{
int num = (int)seed + -1640531527 + (int)(round * 2246822507u);
int num2 = (num ^ (num >>> 16)) * 2146121005;
return ((uint)num2 ^ ((uint)num2 >> 15)) & Mask(bits);
}
public static uint Mask(int bits)
{
if (bits == 32)
{
return uint.MaxValue;
}
return (uint)((1 << bits) - 1);
}
}
public static uint GetMask(int bits)
{
return BitPermuter.Mask(bits);
}
public static uint Mix10(uint value, uint salt)
{
return BitPermuter.Mix(value, salt, 10);
}
public static uint Unmix10(uint value, uint salt)
{
return BitPermuter.Unmix(value, salt, 10);
}
public static uint Mix15(uint value, uint salt)
{
return BitPermuter.Mix(value, salt, 15);
}
public static uint Unmix15(uint value, uint salt)
{
return BitPermuter.Unmix(value, salt, 15);
}
public static uint Mix12(uint value, uint salt)
{
return BitPermuter.Mix(value, salt, 12);
}
public static uint Unmix12(uint value, uint salt)
{
return BitPermuter.Unmix(value, salt, 12);
}
public static uint Mix32(uint value, uint salt)
{
return BitPermuter.Mix(value, salt, 32);
}
public static uint Unmix32(uint value, uint salt)
{
return BitPermuter.Unmix(value, salt, 32);
}
public static bool VerifyMixer()
{
for (int i = 4; i <= 16; i++)
{
if (!VerifyMixer(i))
{
Logging<Plugin>.Error((object)$"Failed to verify {i} bits", (ushort)0);
return false;
}
}
return true;
}
private static bool VerifyMixer(int bits)
{
if (bits > 20)
{
Logging<Plugin>.Error((object)$"Max test range 2-{20}, aborting", (ushort)0);
return false;
}
uint mask = GetMask(bits);
Logging<Plugin>.Message((object)$"Verify mixer for {bits} bits", 0);
return VerifyMixer("BitPermuter", WrapMix, WrapUnmix, mask);
uint WrapMix(uint x, uint seed)
{
return BitPermuter.Mix(x, seed, bits);
}
uint WrapUnmix(uint x, uint seed)
{
return BitPermuter.Unmix(x, seed, bits);
}
}
private static bool VerifyMixer(string label, Func<uint, uint, uint> mix, Func<uint, uint, uint> unmix, uint mask)
{
Logging<Plugin>.Message((object)$"Testing {label} for mask: {mask:X}", 0);
HashSet<uint> hashSet = new HashSet<uint>();
uint num = mask + 1;
Logging<Plugin>.Message((object)$"Test 1: Verify bijection (one-to-one mapping) using salt: {1234567890u}", 0);
for (uint num2 = 0u; num2 < num; num2++)
{
uint num3 = mix(num2, 1234567890u);
uint num4 = unmix(num3, 1234567890u);
if (num3 > mask)
{
Logging<Plugin>.Error((object)$"FAIL: permuted value {num3:X8} is outside the mask range: {mask:X8}", (ushort)0);
return false;
}
if (num2 != num4)
{
Logging<Plugin>.Error((object)$"FAIL: The inverse {num4} does not equal the original value: {num2}, permuted: {num3}", (ushort)0);
return false;
}
if (!hashSet.Add(num3))
{
Logging<Plugin>.Error((object)$"FAIL: collision detected at input {num2}, output {num3}", (ushort)0);
return false;
}
if (num2 < 10 || num2 == mask || num3 == mask)
{
Logging<Plugin>.Message((object)$"Data - Original: {num2:X8}, Permuted: {num3:X8}, Inverse: {num4:X8}", 0);
}
}
Logging<Plugin>.Message((object)"Test 2: Verify all values are covered", 0);
if (hashSet.Count != num)
{
Logging<Plugin>.Error((object)$"FAIL: only {hashSet.Count} unique values out of {num}", (ushort)0);
return false;
}
Logging<Plugin>.Message((object)"Test 3: Verify distribution (check that sequential inputs produce non-sequential outputs)", 0);
int num5 = 0;
for (uint num6 = 0u; num6 < 1000; num6++)
{
uint num7 = mix(num6, 1234567890u);
uint num8 = mix(num6 + 1, 1234567890u);
if (Math.Abs(num7 - num8) <= 1)
{
num5++;
}
}
Logging<Plugin>.Message((object)"Test 4: Less than 5% of sequential pairs should be adjacent", 0);
if (num5 > 50)
{
Logging<Plugin>.Warning((object)$"Permute: {num5} adjacent outputs detected (distribution may be poor)", 0);
}
Logging<Plugin>.Message((object)$"PASSED: bijection verified, all values covered [0000-{mask:X8}]", 0);
return true;
}
}
internal static class Commands
{
private sealed class MakeRuneCmd : TerminalCommand
{
public override string Name => "portalrune";
public override string Syntax => "Syntax: " + ((TerminalCommand)this).SyntaxName + " -random [biome] [channel] [group] | [hexID]";
public override string Description => "Create new runestones with a given ID and optional biome, or random ID if random is specified.";
public override bool IsCheat => true;
public override void Exec(string[] args)
{
//IL_01e7: Unknown result type (might be due to invalid IL or missing references)
//IL_01ed: Unknown result type (might be due to invalid IL or missing references)
//IL_01f2: Unknown result type (might be due to invalid IL or missing references)
//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
//IL_01ad: Unknown result type (might be due to invalid IL or missing references)
if (!PlayerExt.IsReady(Player.m_localPlayer))
{
Console.instance.Print("Player not ready");
return;
}
RuneID runeID;
switch (args.Length)
{
case 1:
Console.instance.Print(((TerminalCommand)this).Syntax);
return;
case 2:
{
string text = args[1];
if (text.ToLowerInvariant().StartsWith("-rand"))
{
Biome[] array = (from Biome b in Enum.GetValues(typeof(Biome))
where b.IsTeleportBiome()
select b).ToArray();
Biome biome2 = array[Random.Range(0, array.Length)];
int channel = Random.Range(0, 32);
int group = Random.Range(0, PortalGroup.Max);
runeID = new RuneID(biome2, channel, group);
}
else if (!RuneID.TryParse(text, out runeID, logError: false))
{
Console.instance.Print("Invalid argument: " + text);
Console.instance.Print(((TerminalCommand)this).Syntax);
return;
}
break;
}
case 4:
{
if (!TryParseBiomeName(args[1], out var biome))
{
Console.instance.Print("Invalid biome: " + args[2]);
Console.instance.Print(((TerminalCommand)this).Syntax);
return;
}
if (!byte.TryParse(args[2], out var result))
{
Console.instance.Print("Invalid chan: " + args[1]);
Console.instance.Print(((TerminalCommand)this).Syntax);
return;
}
if (!byte.TryParse(args[3], out var result2))
{
Console.instance.Print("Invalid group: " + args[3]);
Console.instance.Print(((TerminalCommand)this).Syntax);
return;
}
runeID = new RuneID(biome, result, result2);
break;
}
default:
Console.instance.Print("Invalid number of arguments");
Console.instance.Print(((TerminalCommand)this).Syntax);
return;
}
Transform transform = ((Component)Player.m_localPlayer).transform;
ItemRuneShard.Spawn(runeID, transform.position + transform.forward, 2);
}
}
private sealed class CureSicknessCmd : TerminalCommand
{
public override string Name => "portalcure";
public override string Syntax => "Syntax: " + ((TerminalCommand)this).SyntaxName;
public override string Description => "Cure the player of portal sickness " + ((TerminalCommand)this).Syntax;
public override bool IsCheat => true;
public override void Exec(string[] args)
{
if (!PlayerExt.IsReady(Player.m_localPlayer))
{
Console.instance.Print("Player not ready");
}
else
{
PortalSickness.Cure(Player.m_localPlayer);
}
}
}
private sealed class RuneDebugCmd : TerminalCommand
{
public override string Name => "portalrunedebug";
public override string Syntax => "Syntax: " + ((TerminalCommand)this).SyntaxName;
public override string Description => "Print the raw data of every rune in your inventory to the console.";
public override bool IsCheat => true;
public override void Exec(string[] args)
{
//IL_0128: Unknown result type (might be due to invalid IL or missing references)
if (!PlayerExt.IsReady(Player.m_localPlayer))
{
Console.instance.Print("Player not ready");
return;
}
string[] symbols = RuneID.Symbols;
HashSet<string> unique = new HashSet<string>();
foreach (string item in symbols.Where((string s) => !unique.Add(s)))
{
string text = "Symbol duplicate: " + item;
Console.instance.Print("ERROR: " + text);
Logging<Plugin>.Error((object)text, (ushort)0);
}
Console.instance.Print(string.Format("{0} Glyphs: {1}", symbols.Length, GeneralExtensions.Join<string>((IEnumerable<string>)symbols, (Func<string, string>)null, "")));
foreach (ItemData allItem in ((Humanoid)Player.m_localPlayer).GetInventory().GetAllItems())
{
string prefabName = ItemDataExt.GetPrefabName(allItem);
if (!(prefabName != ((Object)ItemRuneShard.Prefab).name))
{
string arg = allItem.GetRuneDataInternal() ?? "(null)";
string text2 = $"{prefabName} ({allItem.m_gridPos}) Data: {arg}";
Console.instance.Print(text2);
}
}
}
}
public sealed class PortalGroupCmd : TerminalCommand
{
public const string CmdName = "portalgroup";
public override string Name => "portalgroup";
public override string Description => "Assign a portal group to the current player.";
public override string Syntax => $"Syntax: {((TerminalCommand)this).SyntaxName} [0-{PortalGroup.Max - 1}]";
public override bool IsCheat => true;
public override void Exec(string[] args)
{
int num = -1;
if (args.Length > 1 && int.TryParse(args[1], out var result))
{
num = result;
}
if (num < 0 || num > PortalGroup.Max - 1)
{
Console.instance.Print(((TerminalCommand)this).Syntax);
return;
}
Player.m_localPlayer.SetPortalGroup(num);
Console.instance.Print($"Assigned to group: {num}");
}
}
public static void Init()
{
ZenMod<Plugin>.Terminal.CreateCommand((TerminalCommand)(object)new MakeRuneCmd());
ZenMod<Plugin>.Terminal.CreateCommand((TerminalCommand)(object)new CureSicknessCmd());
ZenMod<Plugin>.Terminal.CreateCommand((TerminalCommand)(object)new RuneDebugCmd());
ZenMod<Plugin>.Terminal.CreateCommand((TerminalCommand)(object)new PortalGroupCmd());
}
private static bool TryParseBiomeName(string name, out Biome biome)
{
biome = (Biome)0;
if (!Enum.TryParse<Biome>(name, ignoreCase: true, out biome))
{
return false;
}
if ((int)biome == 895)
{
biome = (Biome)0;
}
return true;
}
}
internal static class Configs
{
public static readonly ConfigEntry<int> CompatibilityWorldSize;
public static readonly ConfigEntry<Color> ColorPortalHoverTextLinkConnected;
public static readonly ConfigEntry<Color> ColorRuneHoverTextLinkPending;
public static readonly ConfigEntry<Color> ColorRuneHoverTextLinkAvailable;
public static readonly ConfigEntry<Color> ColorRuneHoverTextLinkUnavailable;
public static readonly ConfigEntry<Color> ColorRuneInventoryLinkAvailable;
public static readonly ConfigEntry<Color> ColorRuneInventoryLinkPending;
public static readonly ConfigEntry<Color> ColorRuneInventoryLinkUnavailable;
public static readonly ConfigEntry<int> PortalSicknessDuration;
public static readonly ConfigEntry<float> PortalSicknessSpeedAdj;
public static readonly ConfigEntry<float> PortalSicknessStaminaRegen;
public static readonly ConfigEntry<float> PortalSicknessHealthRegen;
public static readonly ConfigEntry<float> PortalSicknessHealthPerTick;
public static readonly ConfigEntry<bool> PortalSicknessPukeOnUse;
public static readonly ConfigEntry<bool> PortalSicknessPukeOnEat;
public static readonly ConfigEntry<bool> PortalSicknessPreventTeleport;
public static readonly ConfigEntry<Portal.PortalType> TravelRequireRoof;
public static readonly ConfigEntry<Portal.PortalType> TravelRequireWalls;
public static readonly ConfigEntry<Portal.PortalType> TravelKnownBiome;
public static readonly ConfigEntry<bool> LinkSameTypeOnly;
public static readonly ConfigEntry<int> PreventNearDungeonRange;
public static readonly ConfigEntry<Biome> AllowBiomesPortalWood;
public static readonly ConfigEntry<Biome> AllowBiomesPortalStone;
public static readonly ConfigEntry<int> AllowBiomesMargin;
private static readonly Dictionary<Biome, ConfigEntry<int>> AllowBiomeMinAltitude;
public static readonly ConfigEntry<StringList> CraftPortalWoodResources;
public static readonly ConfigEntry<string> CraftPortalWoodStation;
public static readonly ConfigEntry<StringList> CraftPortalStoneResources;
public static readonly ConfigEntry<string> CraftPortalStoneStation;
public static readonly ConfigEntry<Portal.PortalType> CraftRequiresHeavySupport;
public static readonly ConfigEntry<string> FractureItem;
public static readonly ConfigEntry<int> FractureItemAmount;
public static readonly ConfigEntry<bool> RuneShardConsumable;
public static readonly ConfigEntry<bool> RuneShardMageTable;
public static readonly ConfigEntry<bool> RuneShardDisplayBiome;
public static readonly ConfigEntry<float> RuneShardWeight;
public static readonly ConfigEntry<int> RuneStonePortalGroups;
public static readonly ConfigEntry<int> RuneStoneChannelsPerBiome;
public static readonly ConfigEntry<string> FuelItemPortalWood;
public static readonly ConfigEntry<string> FuelItemPortalStone;
public static readonly ConfigEntry<int> FuelMax;
public static int GetBiomeMinAltitude(Vector3 position)
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
return GetBiomeMinAltitude(Heightmap.FindBiome(position));
}
public static int GetBiomeMinAltitude(Biome biome)
{
//IL_0005: Unknown result type (might be due to invalid IL or missing references)
if (!AllowBiomeMinAltitude.TryGetValue(biome, out ConfigEntry<int> value))
{
return 0;
}
return value.Value;
}
static Configs()
{
//IL_0057: Unknown result type (might be due to invalid IL or missing references)
//IL_007b: Unknown result type (might be due to invalid IL or missing references)
//IL_009f: Unknown result type (might be due to invalid IL or missing references)
//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
//IL_010b: Unknown result type (might be due to invalid IL or missing references)
//IL_012f: Unknown result type (might be due to invalid IL or missing references)
//IL_03c9: Unknown result type (might be due to invalid IL or missing references)
//IL_03ce: Unknown result type (might be due to invalid IL or missing references)
//IL_03d4: Unknown result type (might be due to invalid IL or missing references)
//IL_03e0: Unknown result type (might be due to invalid IL or missing references)
//IL_03ec: Unknown result type (might be due to invalid IL or missing references)
//IL_0402: Unknown result type (might be due to invalid IL or missing references)
//IL_047a: Unknown result type (might be due to invalid IL or missing references)
//IL_047f: Unknown result type (might be due to invalid IL or missing references)
//IL_048a: Expected O, but got Unknown
//IL_048a: Unknown result type (might be due to invalid IL or missing references)
//IL_0495: Expected O, but got Unknown
//IL_0495: Unknown result type (might be due to invalid IL or missing references)
//IL_04a0: Expected O, but got Unknown
//IL_04aa: Expected O, but got Unknown
//IL_04de: Unknown result type (might be due to invalid IL or missing references)
//IL_04e3: Unknown result type (might be due to invalid IL or missing references)
//IL_04ee: Expected O, but got Unknown
//IL_04ee: Unknown result type (might be due to invalid IL or missing references)
//IL_04f9: Expected O, but got Unknown
//IL_04f9: Unknown result type (might be due to invalid IL or missing references)
//IL_0504: Expected O, but got Unknown
//IL_050e: Expected O, but got Unknown
AllowBiomeMinAltitude = new Dictionary<Biome, ConfigEntry<int>>();
CompatibilityWorldSize = Config.Define<int>(true, "Compatibility", "World Size", 10000, Config.AcceptRange<int>(5000, 50000), $"Size of the world if modded from default. Vanilla: {10000f}");
ColorPortalHoverTextLinkConnected = Config.Define<Color>(false, "Rune - Colors", "Portal HoverText - Link Connected", UIColor.ValheimYellow.Color, "Portal rune's text color when connected to another portal.");
ColorRuneHoverTextLinkPending = Config.Define<Color>(false, "Rune - Colors", "Rune HoverText - Link Pending", UIColor.Clear.Color, "Text color when pending a connection to another portal.\r\nNOTE: Clear means that it will fallback to the default color (white)");
ColorRuneHoverTextLinkAvailable = Config.Define<Color>(false, "Rune - Colors", "Rune HoverText - Link Available", UIColor.ValheimYellow.Color, "Text color when not in use in any portals.");
ColorRuneHoverTextLinkUnavailable = Config.Define<Color>(false, "Rune - Colors", "Rune HoverText - Link Unavailable", UIColor.Gray.Color, "Rune text color when they are already connected to another portal somewhere in the world.");
ColorRuneInventoryLinkAvailable = Config.Define<Color>(false, "Rune - Colors", "Rune Inventory - Link Available", UIColor.ValheimYellow.Color, "Inventory item rune text color when not in use in any portals");
ColorRuneInventoryLinkUnavailable = Config.Define<Color>(false, "Rune - Colors", "Rune Inventory - Link Unavailable", UIColor.Gray.Color, "Inventory item rune text color when in use by connected portals somewhere in the world");
ColorRuneInventoryLinkPending = Config.Define<Color>(false, "Rune - Colors", "Rune Inventory - Link Pending", UIColor.Clear.Color, "Inventory item rune text color when the rune is in only one portal somewhere in the world");
PortalSicknessPukeOnUse = Config.Define<bool>(true, "Portal - Sickness", "Puke On Use", true, "Vomit and lose all food after using a portal.");
PortalSicknessPukeOnEat = Config.Define<bool>(true, "Portal - Sickness", "Puke On Eat", false, "If true then the player is unable to eat until portal sickness wears off.\r\nHowever, they can still drink meads and potions.");
PortalSicknessPreventTeleport = Config.Define<bool>(true, "Portal - Sickness", "Prevent Teleport", false, "Can not teleport while portal sickness is in effect. \r\nIf false the portal sickness timer will be reset after each portal jump.");
PortalSicknessDuration = Config.Define<int>(true, "Portal - Sickness", "Duration (Minutes)", 5, Config.AcceptRange<int>(0, 120), "Number of minutes that players will be sick after using a portal.\r\nSleep will remove the sickness instantly.\r\nSet to 0 to disable portal sickness.");
PortalSicknessSpeedAdj = Config.Define<float>(true, "Portal - Sickness", "Debuff - Movement Speed", 0.8f, Config.AcceptRange<float>(0f, 1f), "Movement speed adjustment when portal sickness is in effect.\r\nSet to 1 to for normal movement speed.");
PortalSicknessStaminaRegen = Config.Define<float>(true, "Portal - Sickness", "Debuff - Stamina Regen", 0.5f, Config.AcceptRange<float>(0f, 1f), "Stamina regen multiplier when portal sickness is in effect.\r\nSet to 1 for normal regen rate.");
PortalSicknessHealthRegen = Config.Define<float>(true, "Portal - Sickness", "Debuff - Health Regen", 0.5f, Config.AcceptRange<float>(0f, 1f), "Health regen multiplier when portal sickness is in effect.\r\nSet to 1 to for normal regen rate.");
PortalSicknessHealthPerTick = Config.Define<float>(true, "Portal - Sickness", "Debuff - Health Per Second", 0f, Config.AcceptRange<float>(-2f, 2f), "Health regen amount per tick when portal sickness is in effect. \r\nNegative numbers do harm, positive numbers heal.\r\nThis will run for aproximately 10s whenever the player walks through a portal.\r\nSet to 0 to disable.");
TravelKnownBiome = Config.Define<Portal.PortalType>(true, "Portal - Travel", "Require Known Destination Biome", Portal.PortalType.PortalWood | Portal.PortalType.PortalStone, "Restrict travel so that you can only enter a portal if the destination biome is already discovered.\r\nThis is helpful to require the first voyage into a new biome to always be done manually once.\r\nFor example: Ashlands");
TravelRequireRoof = Config.Define<Portal.PortalType>(true, "Portal - Travel", "Require Roof", Portal.PortalType.None, "Restrict travel so that you can only enter a portal if there is a roof over it.");
TravelRequireWalls = Config.Define<Portal.PortalType>(true, "Portal - Travel", "Require Walls", Portal.PortalType.PortalWood, "Restrict travel so that you can only enter a portal if it has walls around it.");
LinkSameTypeOnly = Config.Define<bool>(true, "Portal - Travel", "Connection - Same Type Only", true, "Wood portals can only link to other wood portals, stone to stone. (Vanilla: false)\r\nThis has no effect on admin created \"locked!\" tags, they can always link to any type of portal.");
PreventNearDungeonRange = Config.Define<int>(true, "Build - Restrictions", "Prevent Near Dungeon - Range", 10, Config.AcceptRange<int>(0, 30), "Anti-cheese to prevent portals from being built near dungeon entrances.\r\nSet to 0 to disable this feature and allow building near the entrances.");
AllowBiomesPortalWood = Config.Define<Biome>(true, "Build - Restrictions", "Allow Biomes - Wood", (Biome)6, "Biomes which allow wooden portals to be built. (Vanilla: All)");
AllowBiomesPortalStone = Config.Define<Biome>(true, "Build - Restrictions", "Allow Biomes - Stone", (Biome)36, "Biomes which allow stone portals to be built. (Vanilla: All)");
AllowBiomesMargin = Config.Define<int>(true, "Build - Restrictions", "Allow Biomes - Margin", 25, Config.AcceptRange<int>(0, 100), "Minimum distance from any disallowed biome before a portal can be built.\r\nThis prevents placing a portal just inside the edge of an allowed biome.");
Dictionary<Biome, int> dictionary = new Dictionary<Biome, int>
{
[(Biome)1] = 0,
[(Biome)8] = 0,
[(Biome)2] = 45,
[(Biome)4] = 150,
[(Biome)16] = 0,
[(Biome)512] = 0,
[(Biome)32] = 80,
[(Biome)64] = 0,
[(Biome)256] = 0
};
foreach (Biome key in dictionary.Keys)
{
AllowBiomeMinAltitude[key] = Config.Define<int>(true, "Build - Restrictions", $"Min Altitude - {key}", dictionary[key], Config.AcceptRange<int>(0, 500), $"Only allow portals to be built above this altitude in the {key}.");
}
CraftRequiresHeavySupport = Config.Define<Portal.PortalType>(true, "Build - Cost", "Requires Heavy Support", Portal.PortalType.PortalStone, "For new games it is recommended to enable this for Wood and Stone portals. It is disabled by default for Wood portals so as not to break existing worlds.\r\nRequire portals of the selected type to have heavy support.\r\nIf checked then the portal type requires heavy building materials for support.\r\nIf unchecked then light materials can be used to support the portal.\r\nHeavy mats are ground/stone/iron/etc. Light mats are woods.\r\nIncrease or decrease portal tower construction challenge.\r\nWARNING: Turning this on for wood portals on existing worlds will cause any wood portals with weak support to collapse.");
CraftPortalWoodStation = Config.Define<string>(true, "Build - Cost", "Portal Wood - Station", "Workbench", CraftingStations.GetAcceptableValueList(), "Crafting station required to build the wood portal");
StringList val = new StringList();
((List<string>)val).Add("GreydwarfEye:10");
((List<string>)val).Add("ElderBark:20");
((List<string>)val).Add("SurtlingCore:2");
CraftPortalWoodResources = Config.Define<StringList>(true, "Build - Cost", "Portal Wood - Resources", val, "List of resources required to build a Wood Portal (Vanilla: GreydwarfEye:10, FineWood:20, SurtlingCore:2)");
CraftPortalStoneStation = Config.Define<string>(true, "Build - Cost", "Portal Stone - Station", "Stonecutter", CraftingStations.GetAcceptableValueList(), "Crafting station required to build the stone portal");
StringList val2 = new StringList();
((List<string>)val2).Add("GreydwarfEye:10");
((List<string>)val2).Add("Grausten:30");
((List<string>)val2).Add("MoltenCore:2");
CraftPortalStoneResources = Config.Define<StringList>(true, "Build - Cost", "Portal Stone - Resources", val2, "List of resources required to build a Stone Portal (Vanilla: GreydwarfEye:10, Grausten:30, MoltenCore:2)");
FractureItem = Config.Define<string>(true, "Portal - Rune", "Fracture Item", "Obsidian", "Prefab name of the item that is required to fracture Runestones.");
FractureItemAmount = Config.Define<int>(true, "Portal - Rune", "Fracture Item - Amount", 2, Config.AcceptRange<int>(1, 50), "The amount of \"" + ((ConfigEntryBase)FractureItem).Definition.Key + "\" required.");
RuneShardConsumable = Config.Define<bool>(true, "Portal - Rune", "Rune Shard - Consumable", true, "Do you want to eat this rock?\r\n[logout required for changes to take effect]");
RuneShardMageTable = Config.Define<bool>(true, "Portal - Rune", "Rune Shard - Mage Table", true, "Can the shard be used on mage tables?\r\n[logout required for changes to take effect]");
RuneShardDisplayBiome = Config.Define<bool>(true, "Portal - Rune", "Rune Shard - Display Biome", false, "Display the biome that the rune shard represents on the tooltip?\r\nNOTE: Admin can always see this by being in god mode and holding the Alt key.");
RuneShardWeight = Config.Define<float>(true, "Portal - Rune", "Rune Shard - Weight", 2f, Config.AcceptRange<float>(0.1f, 300f), "The weight of a rune shard.\r\n[logout required for changes to take effect]");
RuneStonePortalGroups = Config.Define<int>(true, "Portal - Rune", "Rune Shard - Portal Groups", 1, Config.AcceptRange<int>(1, 32), "Total number of portal groups available. Each group is a slightly diff version of reality.\r\nLarger servers with many players can have the players in diff groups so they don't all see the same symbols.\r\nSmall friends may want to all share the same reality, in which case one shared group is enough.\r\nEach Runestone will look the same to all players who are part of the same group.\r\nIf two players are in different groups and stand at the same Runestone they will see diff symbols.\r\nIf they are in the same group they will see the same symbols at that Runestone.\r\nGroups are controlled via the player key: portalgroup\r\nNote, group 0 is the default group if no group is assigned.\r\nTo have all players see the same symbols set this to 1 to force all players into the same group.\r\nIf this config is greater than 1 then players are assigned to a random group if they do not have one when they next login.\r\nAdmin command syntax:\r\n- zen_portalgroup N\r\nSet another player's group who is logged on:\r\n- Turn on command relay in Zen.ModLib configs:\r\n- relay playername zen_portalgroup N\r\nRemove a player from all groups and let the system assign them a random one on next login:\r\n- first, figure out what group they are in using listkeys, then remove their key:\r\n- relay playername removekeyplayer portalgroup N\r\n- ask the player to logout/login to allow the system to assign a new group, or kick them to force it.");
RuneStoneChannelsPerBiome = Config.Define<int>(true, "Portal - Rune", "Rune Shard - Channels Per Biome", 4, Config.AcceptRange<int>(1, 32), "Total number of unique channels available per biome.\r\nHigher numbers make it easier to find open channels on Runestone.\r\nLower numbers make it harder and requires venturing into different biomes to find open channels.\r\nNOTE: Changing this on existing worlds may cause existing Runestones to be assigned different symbols.");
FuelItemPortalWood = Config.Define<string>(true, "Portal - Fuel", "Wood Portal Fuel Item", "BoneFragments", "Prefab name of the fuel item for wood portals, leave blank for no fuel requirement");
FuelItemPortalStone = Config.Define<string>(true, "Portal - Fuel", "Stone Portal Fuel Item", "CharredBone", "Prefab name of the fuel item for stone portals, leave blank for no fuel requirement");
FuelMax = Config.Define<int>(true, "Portal - Fuel", "Max Fuel (Minutes)", 10, Config.AcceptRange<int>(1, 60), "Max amount of units of fuel a portal can hold.");
}
public static T GetConfigValue<T>(Portal.PortalType portalType, ConfigEntry<T> configWood, ConfigEntry<T> configStone)
{
return portalType switch
{
Portal.PortalType.PortalWood => configWood.Value,
Portal.PortalType.PortalStone => configStone.Value,
_ => throw new ArgumentOutOfRangeException("portalType"),
};
}
}
[HarmonyPatch]
internal static class ItemRuneShard
{
private const string DataRuneID = "ZenRuneID";
public const string PrefabName = "ZenRuneShard";
public static ItemDrop Prefab => GlobalStatic.GetPrefab<ItemDrop>("ZenRuneShard", true);
public static bool HaveRuneShard(this Inventory inventory)
{
return InventoryExt.ContainsItemByPrefab(inventory, "ZenRuneShard");
}
public static Action AddCraftingItem()
{
//IL_0025: Unknown result type (might be due to invalid IL or missing references)
//IL_002b: Expected O, but got Unknown
//IL_0081: Unknown result type (might be due to invalid IL or missing references)
//IL_0087: Expected O, but got Unknown
//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
Logging<Plugin>.Info((object)"Add crafting item: ZenRuneShard, based on Thunderstone", 0);
Sprite val = AssetIO.LoadSpriteFromResource((BaseUnityPlugin)(object)ZenMod<Plugin>.Instance, "rune_shard.png");
ItemConfig val2 = new ItemConfig();
val2.Name = "$item_rune_shard";
val2.Description = "$item_rune_shard_description";
val2.CraftingStation = CraftingStations.None;
val2.MinStationLevel = 1;
val2.Requirements = Array.Empty<RequirementConfig>();
val2.Icons = (Sprite[])(object)((!Object.op_Implicit((Object)(object)val)) ? null : new Sprite[1] { val });
val2.StackSize = 1;
CustomItem val3 = new CustomItem("ZenRuneShard", "Thunderstone", val2);
ItemManager.Instance.AddItem(val3);
Transform obj = ((Component)Prefab).transform.Find("model");
((Renderer)((Component)obj).GetComponent<MeshRenderer>()).material.SetColor("_EmissionColor", Color.red * 2f);
Object.Destroy((Object)(object)((Component)obj).GetComponent<ParticleSystemRenderer>());
Object.Destroy((Object)(object)((Component)obj).GetComponent<ParticleSystem>());
Object.Destroy((Object)(object)((Component)obj.parent.GetChild(1)).gameObject);
return ConfigSync;
static void ConfigSync()
{
//IL_002f: Unknown result type (might be due to invalid IL or missing references)
Prefab.m_itemData.m_shared.m_weight = Configs.RuneShardWeight.Value;
Prefab.m_itemData.m_shared.m_itemType = (ItemType)16;
}
}
internal static string? GetRuneDataInternal(this ItemData itemData)
{
if (!itemData.m_customData.TryGetValue("ZenRuneID", out var value))
{
return null;
}
return value;
}
public static bool TryGetRuneID(this ItemData? itemData, out RuneID runeID)
{
runeID = default(RuneID);
string text = itemData?.GetRuneDataInternal();
if (text != null)
{
return RuneID.TryParse(text, out runeID);
}
return false;
}
public static bool HasRuneID(this ItemData? itemData)
{
return itemData?.GetRuneDataInternal() != null;
}
public static void SetRuneID(this ItemData itemData, RuneID runeID)
{
itemData.m_customData["ZenRuneID"] = runeID.ToString();
}
public static void Spawn(RuneID runeID, Vector3 origin, int amount, bool autoPickup = false)
{
//IL_001a: Unknown result type (might be due to invalid IL or missing references)
//IL_001b: Unknown result type (might be due to invalid IL or missing references)
//IL_0020: Unknown result type (might be due to invalid IL or missing references)
//IL_0025: Unknown result type (might be due to invalid IL or missing references)
//IL_002f: Unknown result type (might be due to invalid IL or missing references)
//IL_0034: Unknown result type (might be due to invalid IL or missing references)
//IL_0039: Unknown result type (might be due to invalid IL or missing references)
//IL_003b: Unknown result type (might be due to invalid IL or missing references)
//IL_003c: Unknown result type (might be due to invalid IL or missing references)
for (int i = 0; i < amount; i++)
{
ItemData obj = Prefab.m_itemData.Clone();
obj.SetRuneID(runeID);
Vector3 val = origin + Vector3.up + Random.insideUnitSphere * 0.3f;
ItemDrop.DropItem(obj, 1, val, Random.rotation).m_autoPickup = autoPickup;
}
}
[HarmonyPostfix]
[HarmonyPatch(typeof(ItemDrop), "GetHoverText")]
[HarmonyPriority(0)]
private static void ItemDrop_GetHoverText(ItemDrop __instance, ref string __result)
{
if (__instance.m_itemData.TryGetRuneID(out var runeID))
{
UIColor linkStatusColorHoverText = runeID.GetLinkStatusColorHoverText();
string hoverTextMysticSymbols = runeID.GetHoverTextMysticSymbols(linkStatusColorHoverText);
if (HoverItem.IsLoaded)
{
HoverItem.UpdateIcons(ItemDataExt.GetIcon(__instance), hoverTextMysticSymbols);
}
else
{
__result += hoverTextMysticSymbols;
}
}
}
[HarmonyPrefix]
[HarmonyPatch(typeof(Humanoid), "UseItem")]
private static void Humanoid_UseItem(Humanoid __instance, Inventory inventory, ItemData item, bool fromInventoryGui, ref bool __runOriginal)
{
//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
//IL_00c4: Expected O, but got Unknown
//IL_00c4: Expected O, but got Unknown
//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
//IL_00c9: Expected O, but got Unknown
Humanoid __instance2 = __instance;
ItemData item2 = item;
if (Configs.RuneShardConsumable.Value && fromInventoryGui && item2.TryGetRuneID(out var runeID))
{
__runOriginal = false;
if (PortalSickness.IsSick((Character?)(object)__instance2))
{
((Character)__instance2).Message((MessageType)2, "$se_puke_start", 0, (Sprite)null);
return;
}
Logging<Plugin>.Warning((object)((object)UIColor.ValheimYellow).ToString(), 0);
string text = StringExt.Localize("$item_rune_shard_consume_warning", new string[2]
{
((object)UIColor.ValheimYellow).ToString(),
ItemDataExt.GetName(item2)
});
UnifiedPopup.Push((PopupBase)new YesNoPopup(runeID.ToMysticSymbols(), text, new PopupButtonCallback(Accept), new PopupButtonCallback(Reject), true));
}
void Accept()
{
//IL_008b: Unknown result type (might be due to invalid IL or missing references)
//IL_0090: Unknown result type (might be due to invalid IL or missing references)
//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
//IL_00fb: Expected O, but got Unknown
UnifiedPopup.Pop();
InventoryGui.instance.Hide();
((Character)__instance2).Message((MessageType)2, "$msg_consumed " + ItemDataExt.GetName(item2), 1, item2.GetIcon());
__instance2.GetInventory().RemoveOneItem(item2);
Animations.Eat(__instance2, item2);
Stack<Vector3> stack = new Stack<Vector3>();
string tombstoneText = "$tombstone_text " + runeID.ToMysticSymbols();
Vector3 position = ((Component)__instance2).transform.position;
position.y += 30f;
stack.Push(position);
Biome biome = (Biome)(((int)runeID.Biome == 0) ? 895 : ((int)runeID.Biome));
for (int i = 0; i < 2; i++)
{
stack.Push(BiomeTeleport.GetRandomTeleportPosition(biome, 30f));
}
PortalDrift.ApplyTo((Player)__instance2, stack, tombstoneText);
}
static void Reject()
{
UnifiedPopup.Pop();
}
}
}
[HarmonyPatch]
internal static class ItemRuneShardInventoryGrid
{
[HarmonyTranspiler]
[HarmonyPatch(typeof(InventoryGrid), "UpdateGui")]
private static IEnumerable<CodeInstruction> InventoryGrid_UpdateGui(IEnumerable<CodeInstruction> codes, ILGenerator gen)
{
//IL_0014: Unknown result type (might be due to invalid IL or missing references)
//IL_001a: Expected O, but got Unknown
//IL_003b: Unknown result type (might be due to invalid IL or missing references)
//IL_0041: Expected O, but got Unknown
//IL_0062: Unknown result type (might be due to invalid IL or missing references)
//IL_0068: Expected O, but got Unknown
//IL_0076: Unknown result type (might be due to invalid IL or missing references)
//IL_007c: Expected O, but got Unknown
//IL_008a: Unknown result type (might be due to invalid IL or missing references)
//IL_0090: Expected O, but got Unknown
//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
//IL_00c2: Expected O, but got Unknown
//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
//IL_00db: Expected O, but got Unknown
//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
//IL_00ef: Expected O, but got Unknown
//IL_0120: Unknown result type (might be due to invalid IL or missing references)
//IL_0126: Expected O, but got Unknown
//IL_0134: Unknown result type (might be due to invalid IL or missing references)
//IL_013a: Expected O, but got Unknown
//IL_0147: Unknown result type (might be due to invalid IL or missing references)
//IL_014d: Expected O, but got Unknown
//IL_0151: Unknown result type (might be due to invalid IL or missing references)
CodeMatch[] array = (CodeMatch[])(object)new CodeMatch[5]
{
new CodeMatch((OpCode?)OpCodes.Ldloc_S, (object)null, (string)null),
new CodeMatch((OpCode?)OpCodes.Ldfld, (object)AccessTools.DeclaredField(typeof(ItemData), "m_shared"), (string)null),
new CodeMatch((OpCode?)OpCodes.Ldfld, (object)AccessTools.DeclaredField(typeof(SharedData), "m_maxStackSize"), (string)null),
new CodeMatch((OpCode?)OpCodes.Ldc_I4_1, (object)null, (string)null),
new CodeMatch((OpCode?)OpCodes.Ble, (object)null, (string)null)
};
MethodInfo methodInfo = AccessTools.DeclaredMethod(typeof(List<ItemData>), "GetEnumerator", (Type[])null, (Type[])null);
CodeMatch[] array2 = (CodeMatch[])(object)new CodeMatch[3]
{
new CodeMatch((OpCode?)OpCodes.Ldloca_S, (object)null, (string)null),
new CodeMatch((OpCode?)OpCodes.Call, (object)AccessTools.EnumeratorMoveNext((MethodBase)methodInfo), (string)null),
new CodeMatch((OpCode?)OpCodes.Brtrue, (object)null, (string)null)
};
Action<ItemData, Element> action = HandleRuneShard;
CodeInstruction[] array3 = (CodeInstruction[])(object)new CodeInstruction[3]
{
new CodeInstruction(OpCodes.Ldloc_S, (object)(byte)18),
new CodeInstruction(OpCodes.Ldloc_S, (object)(byte)19),
new CodeInstruction(OpCodes.Call, (object)action.Method)
};
Label label = default(Label);
return new CodeMatcher(codes, gen).MatchStartForward(array2).ThrowIfInvalid("Unable to match IL sequence: end of loop").Insert(array3)
.CreateLabel(ref label)
.MatchEndBackwards(array)
.ThrowIfInvalid("Unable to match IL sequence: branch correction")
.SetOperandAndAdvance((object)label)
.InstructionEnumeration();
static void HandleRuneShard(ItemData item, Element element)
{
//IL_0034: Unknown result type (might be due to invalid IL or missing references)
//IL_0039: Unknown result type (might be due to invalid IL or missing references)
if (!(ItemDataExt.GetPrefabName(item) != "ZenRuneShard"))
{
string text = "<color=red>INVALID</color>";
if (item.TryGetRuneID(out var runeID))
{
UIColor linkStatusColorInventory = runeID.GetLinkStatusColorInventory();
string text2 = runeID.ToMysticSymbols();
text = ((UIColor.op_Implicit(linkStatusColorInventory) != Color.clear) ? $"<color={linkStatusColorInventory}>{text2}</color>" : text2);
}
((Behaviour)element.m_amount).enabled = true;
element.m_amount.text = text;
}
}
}
[HarmonyPostfix]
[HarmonyPatch(typeof(ItemData), "GetTooltip", new Type[] { typeof(int) })]
[HarmonyPriority(100)]
private static void ItemData_GetTooltip(ItemData __instance, ref string __result)
{
//IL_001f: Unknown result type (might be due to invalid IL or missing references)
//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
//IL_0032: Unknown result type (might be due to invalid IL or missing references)
if (__instance.TryGetRuneID(out var runeID))
{
string text = string.Empty;
if (Configs.RuneShardDisplayBiome.Value && runeID.Biome.IsTeleportBiome())
{
text = "\n" + BiomeExt.Localize(runeID.Biome);
}
string text2 = "<size=200%>" + runeID.ToMysticSymbols() + "</size>" + text;
ItemDataExt.SetTooltipExtra(__instance, text2);
string description = __instance.m_shared.m_description;
__result = __result.Replace(description, $"{description}\n\n<color={UIColor.Orange}><align=center>{text2}</align></color>");
if (PlayerExt.IsGodMode(Player.m_localPlayer))
{
__result += $"\n\n<color={UIColor.MinorInfo}>Rune ID: {runeID}\nBiome: {runeID.Biome}\nGroup: {runeID.Group}\nChan: {runeID.Channel}</color>";
}
}
}
}
[HarmonyPatch]
internal static class MageTable
{
private const float EitrUseAmount = 20f;
private static bool IsMageTable(this CraftingStation station)
{
return Utils.GetPrefabName(((Object)station).name) == CraftingStations.GaldrTable;
}
[HarmonyPostfix]
[HarmonyPatch(typeof(CraftingStation), "GetHoverText")]
private static void CraftingStation_GetHoverText(CraftingStation __instance, ref string __result)
{
if (__instance.IsMageTable() && __instance.InUseDistance((Humanoid)(object)Player.m_localPlayer) && __instance.CheckUsable(Player.m_localPlayer, false) && ((Humanoid)Player.m_localPlayer).GetInventory().HaveRuneShard())
{
__result += StringExt.Localize("\n" + UI.PromptUseItem + " $piece_use " + ItemDataExt.GetName(ItemRuneShard.Prefab));
}
}
[HarmonyPostfix]
[HarmonyPatch(typeof(CraftingStation), "UseItem")]
private static void CraftingStation_UseItem(CraftingStation __instance, Humanoid user, ItemData item, ref bool __result, ref bool __runOriginal)
{
//IL_009b: Unknown result type (might be due to invalid IL or missing references)
//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
//IL_0105: Expected O, but got Unknown
//IL_0105: Expected O, but got Unknown
//IL_0100: Unknown result type (might be due to invalid IL or missing references)
//IL_010a: Expected O, but got Unknown
ItemData item2 = item;
if (!Configs.RuneShardMageTable.Value || !__instance.IsMageTable() || !item2.TryGetRuneID(out var runeID))
{
return;
}
Player player = (Player)(object)((user is Player) ? user : null);
if (player != null && __instance.CheckUsable(player, true))
{
__runOriginal = false;
__result = true;
if (!((Character)player).TryUseEitr(20f))
{
((Character)player).Message((MessageType)2, "$hud_eitrrequired", 0, (Sprite)null);
return;
}
string text = runeID.ToMysticSymbols();
string text2 = (((int)runeID.Biome == 0) ? "$location_start_temple" : BiomeExt.Localize(runeID.Biome));
string text3 = StringExt.Localize("$item_rune_shard_magetable_warning", new string[3]
{
__instance.GetHoverName(),
ItemDataExt.GetName(ItemRuneShard.Prefab),
text2
});
UnifiedPopup.Push((PopupBase)new YesNoPopup(text, text3, new PopupButtonCallback(Accept), new PopupButtonCallback(Reject), true));
}
void Accept()
{
InventoryGui.instance.Hide();
UnifiedPopup.Pop();
if (Object.op_Implicit((Object)(object)player))
{
if (!((Humanoid)player).IsTeleportable())
{
((Character)player).Message((MessageType)2, "$msg_noteleport", 0, (Sprite)null);
}
else
{
((Character)player).UseEitr(20f);
((Humanoid)player).GetInventory().RemoveItem(item2);
player.TeleportToRuneAddress(runeID);
}
}
}
static void Reject()
{
UnifiedPopup.Pop();
}
}
}
[BepInPlugin("ZenDragon.ZenPortal", "ZenPortal", "0.5.7")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
internal class Plugin : ZenMod<Plugin>, IMessageListener
{
public const string PluginName = "ZenPortal";
public const string PluginVersion = "0.5.7";
public const string PluginGUID = "ZenDragon.ZenPortal";
public static bool IsAdminKeyPressed
{
get
{
if (PlayerExt.IsGodMode(Player.m_localPlayer))
{
return ZInput.GetKey((KeyCode)308, true);
}
return false;
}
}
protected override void Setup()
{
((ZenMod)this).RunOnServer = true;
base.RegisterCraftingItems += ItemRuneShard.AddCraftingItem;
base.ConfigSync += Portal.InitPrefabs;
Commands.Init();
if (Logging<Plugin>.IsEnabled && !BitUtils.VerifyMixer())
{
throw new Exception("Permutation function failed to pass all tests.");
}
}
protected override void TitleScene(bool isFirstBoot)
{
}
protected override void WorldStart()
{
PortalFuel.Init();
PortalConnect.Init();
BiomeTeleport.InitTeleportZoneCache();
PortalSickness.Init();
PortalDrift.Init();
SlowFallUngrounded.Init();
}
protected override void Shutdown()
{
PortalFuel.Shutdown();
PortalConnect.Shutdown();
PortalSickness.Shutdown();
PortalDrift.Shutdown();
SlowFallUngrounded.Shutdown();
}
protected override void HotRestore()
{
if (Object.op_Implicit((Object)(object)ZNetScene.instance))
{
Portal.InitPrefabs();
PortalSickness.HotRestore();
PortalFuel.HotRestore();
}
}
public void ReceiveMessage(string message, object? arg)
{
//IL_001a: Unknown result type (might be due to invalid IL or missing references)
//IL_0020: Expected O, but got Unknown
if (!(message != Portal.Message_PortalSymbols) && arg != null)
{
object[] obj = (object[])arg;
ZDO portalZDO = (ZDO)obj[0];
obj[1] = (Portal.TryGetRuneID(portalZDO, out var runeID) ? runeID.ToMysticSymbols() : null);
}
}
}
[HarmonyPatch]
internal static class Portal
{
[Flags]
public enum PortalType : byte
{
None = 0,
PortalWood = 1,
PortalStone = 2
}
private enum LinkStatus : byte
{
Pending,
Connected,
AlreadyInUse
}
private static class PrefabName
{
public const string Wood = "portal_wood";
public const string Stone = "portal_stone";
}
private const string RuneTagPrefix = "ZEN:";
public static bool IsRuneTag(this string tag)
{
return tag.StartsWith("ZEN:");
}
public static bool IsPortal(this Component component)
{
PortalType portalType;
return component.IsPortal(out portalType);
}
public static bool IsPortal(this Component component, out PortalType portalType)
{
return component.gameObject.IsPortal(out portalType);
}
public static bool IsPortal(this GameObject g)
{
PortalType portalType;
return g.IsPortal(out portalType);
}
public static bool IsPortal(this GameObject g, out PortalType portalType)
{
return (portalType = GetPortalType(GameObjectExt.GetPrefabName(g))) != PortalType.None;
}
public static bool HaveRune(this TeleportWorld teleport)
{
RuneID runeID;
return teleport.TryGetRuneID(out runeID);
}
public static Biome GetAllowedBiomes(Component portal)
{
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
return GetAllowedBiomes(portal.gameObject);
}
public static Biome GetAllowedBiomes(GameObject portal)
{
//IL_0015: Unknown result type (might be due to invalid IL or missing references)
return Configs.GetConfigValue<Biome>(GetPortalType(((Object)portal).name), Configs.AllowBiomesPortalWood, Configs.AllowBiomesPortalStone);
}
private static LinkStatus GetLinkStatus(this TeleportWorld teleport)
{
if (!teleport.HaveTarget())
{
if (!PortalConnect.IsTagConnected(teleport.GetPortalTag(includeRunes: true)))
{
return LinkStatus.Pending;
}
return LinkStatus.AlreadyInUse;
}
return LinkStatus.Connected;
}
public static UIColor GetLinkStatusColor(this TeleportWorld teleport)
{
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
//IL_0015: 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)
return teleport.GetLinkStatusColor(UIColor.op_Implicit(Configs.ColorPortalHoverTextLinkConnected.Value), UIColor.op_Implicit(Configs.ColorRuneHoverTextLinkPending.Value), UIColor.op_Implicit(Configs.ColorRuneHoverTextLinkUnavailable.Value));
}
public static UIColor GetLinkStatusColor(this TeleportWorld teleport, UIColor connected, UIColor pending, UIColor alreadyInUse)
{
return (UIColor)(teleport.GetLinkStatus() switch
{
LinkStatus.Connected => connected,
LinkStatus.Pending => pending,
LinkStatus.AlreadyInUse => alreadyInUse,
_ => throw new ArgumentOutOfRangeException(),
});
}
public static bool TryGetRuneID(ZDO portalZDO, out RuneID runeID)
{
if (portalZDO.IsValid())
{
string @string = portalZDO.GetString(ZDOVars.s_tag, "");
if ([email protected]())
{
runeID = default(RuneID);
return false;
}
return RuneID.TryParse(@string.Substring("ZEN:".Length, 4), out runeID);
}
runeID = default(RuneID);
return false;
}
public static bool TryGetRuneID(this TeleportWorld teleport, out RuneID runeID)
{
if (Object.op_Implicit((Object)(object)teleport.m_nview) && teleport.m_nview.IsValid())
{
return TryGetRuneID(teleport.m_nview.GetZDO(), out runeID);
}
runeID = default(RuneID);
return false;
}
public static bool TryTakeRune(this TeleportWorld teleport, Humanoid human)
{
ItemData rune;
return teleport.TryTakeRune(human, out rune);
}
public static bool TryTakeRune(this TeleportWorld teleport, Humanoid human, out ItemData rune)
{
rune = null;
if (!teleport.TryGetRuneID(out var runeID))
{
return false;
}
GameObject gameObject = ((Component)ItemRuneShard.Prefab).gameObject;
if (!InventoryExt.TryAddItem(human.GetInventory(), gameObject, 1, ref rune))
{
((Character)human).Message((MessageType)2, "$inventory_full", 0, (Sprite)null);
return false;
}
rune.SetRuneID(runeID);
((Character)human).ShowRemovedMessage(rune, 1);
PlayInventoryFX();
teleport.SetText(string.Empty);
PortalFuel portalFuel = default(PortalFuel);
if (((Component)teleport).TryGetComponent<PortalFuel>(ref portalFuel))
{
portalFuel.SetExpireTime(0.0);
}
return true;
}
public static string CreatePortalTag(RuneID runeID)
{
return "ZEN:" + runeID;
}
public static string GetPortalTag(this TeleportWorld teleport, bool includeRunes = false)
{
string text = default(string);
string text2 = default(string);
teleport.GetTagSignature(ref text, ref text2);
if (!includeRunes && text.IsRuneTag())
{
return string.Empty;
}
return text;
}
internal static void AssignRune(this TeleportWorld teleport, RuneID runeID)
{
teleport.SetText(CreatePortalTag(runeID));
teleport.PlayInteractFX();
PlayInventoryFX();
}
public static bool IsFuelEmpty(this TeleportWorld teleport)
{
PortalFuel portalFuel = default(PortalFuel);
if (((Component)teleport).TryGetComponent<PortalFuel>(ref portalFuel))
{
return portalFuel.IsFuelEmpty();
}
return false;
}
public static bool AddFuel(this TeleportWorld teleport, Humanoid human)
{
PortalFuel portalFuel = default(PortalFuel);
if (!((Component)teleport).TryGetComponent<PortalFuel>(ref portalFuel))
{
return false;
}
ItemDrop fuelItem = portalFuel.FuelItem;
if (!Object.op_Implicit((Object)(object)fuelItem))
{
return false;
}
Inventory inventory = human.GetInventory();
string name = ItemDataExt.GetName(fuelItem);
if (!inventory.HaveItem(name, true))
{
((Character)human).Message((MessageType)2, "$msg_donthaveany " + name, 0, (Sprite)null);
return false;
}
if (!teleport.HaveTarget())
{
((Character)human).Message((MessageType)2, "$error_disconnected", 0, (Sprite)null);
((Character)human).Message((MessageType)1, StringExt.Localize("$portal_need", new string[1] { ItemDataExt.GetName(ItemRuneShard.Prefab) }), 0, ItemDataExt.GetIcon(ItemRuneShard.Prefab));
return false;
}
if (portalFuel.GetFuelUnits() >= PortalFuel.MaxUnits)
{
((Character)human).Message((MessageType)2, StringExt.Localize("$msg_cantaddmore", new string[1] { string.Empty }), 0, (Sprite)null);
return false;
}
portalFuel.AddFuelUnits(1);
inventory.RemoveItem(ItemDataExt.GetName(fuelItem), 1, -1, true);
((Character)human).Message((MessageType)2, StringExt.Localize("$portal_add_fuel_use", new string[1] { ItemDataExt.GetName(fuelItem) }), 0, (Sprite)null);
return true;
}
private static void PlayInventoryFX()
{
FX.PlayFX((MonoBehaviour)(object)Player.m_localPlayer, "sfx_equip");
}
private static bool IsCovered(this TeleportWorld teleport, bool showMessage)
{
//IL_005f: Unknown result type (might be due to invalid IL or missing references)
//IL_0066: Unknown result type (might be due to invalid IL or missing references)
//IL_0070: Unknown result type (might be due to invalid IL or missing references)
//IL_0075: Unknown result type (might be due to invalid IL or missing references)
Player localPlayer = Player.m_localPlayer;
if (!PlayerExt.IsReady(localPlayer))
{
return false;
}
PortalType portalType = teleport.GetPortalType();
bool flag = Configs.TravelRequireRoof.Value.HasFlag(portalType);
bool flag2 = Configs.TravelRequireWalls.Value.HasFlag(portalType);
if (!flag && !flag2)
{
return true;
}
Transform transform = ((Component)teleport).transform;
float num = default(float);
bool flag3 = default(bool);
Cover.GetCoverForPoint(transform.position + transform.up * 0.25f, ref num, ref flag3, 0.5f);
if (flag && !flag3)
{
if (showMessage)
{
((Character)localPlayer).Message((MessageType)2, "$portal_need_roof", 0, (Sprite)null);
}
return false;
}
if (flag2 && num < 0.8f)
{
if (showMessage)
{
((Character)localPlayer).Message((MessageType)2, "$portal_need_walls", 0, (Sprite)null);
}
return false;
}
return true;
}
public static Biome GetConnectedBiome(this TeleportWorld teleport)
{
//IL_0030: Unknown result type (might be due to invalid IL or missing references)
//IL_0035: Unknown result type (might be due to invalid IL or missing references)
//IL_003b: Unknown result type (might be due to invalid IL or missing references)
//IL_004d: Unknown result type (might be due to invalid IL or missing references)
//IL_0052: Unknown result type (might be due to invalid IL or missing references)
if (!((Component)(object)teleport).IsPortal() || !Object.op_Implicit((Object)(object)teleport.m_nview) || !teleport.m_nview.IsValid())
{
return (Biome)0;
}
ZDOID connectionZDOID = teleport.m_nview.GetZDO().GetConnectionZDOID((ConnectionType)1);
ZDO zDO = ZDOMan.instance.GetZDO(connectionZDOID);
if (zDO == null)
{
return (Biome)0;
}
return WorldGenerator.instance.GetBiome(zDO.GetPosition());
}
public static void PlayInteractFX(this TeleportWorld teleport)
{
//IL_0028: 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_003d: Unknown result type (might be due to invalid IL or missing references)
//IL_0042: Unknown result type (might be due to invalid IL or missing references)
//IL_0047: Unknown result type (might be due to invalid IL or missing references)
//IL_0064: Unknown result type (might be due to invalid IL or missing references)
//IL_0065: 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_0079: Unknown result type (might be due to invalid IL or missing references)
//IL_0050: Unknown result type (might be due to invalid IL or missing references)
//IL_0055: 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_0063: Unknown result type (might be due to invalid IL or missing references)
EffectList removedPermittedEffect = GlobalStatic.GetPrefab<PrivateArea>("guard_stone", true).m_removedPermittedEffect;
Vector3 val = (Vector3)(teleport.GetPortalType() switch
{
PortalType.PortalWood => ((Component)teleport).transform.position + ((Component)teleport).transform.up * 0.35f,
PortalType.PortalStone => ((StaticTarget)((Component)teleport).GetComponent<Piece>()).GetCenter(),
_ => ((Component)teleport).transform.position,
});
Logging<Plugin>.Info((object)"Applying client-side portal effects", 0);
removedPermittedEffect.Create(val, ((Component)teleport).transform.rotation, (Transform)null, 1f, -1);
}
[HarmonyPostfix]
[HarmonyPatch(typeof(Piece), "DropResources")]
private static void Piece_DropResources(Piece __instance)
{
//IL_0026: Unknown result type (might be due to invalid IL or missing references)
TeleportWorld val = default(TeleportWorld);
if (((Component)(object)__instance).IsPortal() && ((Component)__instance).TryGetComponent<TeleportWorld>(ref val) && val.TryGetRuneID(out var runeID))
{
ItemRuneShard.Spawn(runeID, ((Component)val).transform.position, 1, autoPickup: true);
}
}
[HarmonyPrefix]
[HarmonyPatch(typeof(TeleportWorld), "Teleport")]
private static void TeleportWorld_Teleport(TeleportWorld __instance, Player player, ref bool __runOriginal)
{
if (!__instance.IsFuelEmpty() && !__instance.CanTeleport(player, showMessage: true))
{
__runOriginal = false;
}
}
[HarmonyPostfix]
[HarmonyPatch(typeof(TeleportWorld), "TargetFound")]
private static void TeleportWorld_TargetFound(TeleportWorld __instance, ref bool __result)
{
__result = __result && !__instance.IsFuelEmpty() && __instance.CanTeleport(Player.m_localPlayer, showMessage: false);
}
private static bool CanTeleport(this TeleportWorld teleport, Player? player, bool showMessage)
{
//IL_004e: Unknown result type (might be due to invalid IL or missing references)
//IL_0053: Unknown result type (might be due to invalid IL or missing references)
//IL_0054: Unknown result type (might be due to invalid IL or missing references)
//IL_0058: Unknown result type (might be due to invalid IL or missing references)
if (!Configs.TravelKnownBiome.Value.HasFlag(teleport.GetPortalType()))
{
return true;
}
if (!Object.op_Implicit((Object)(object)player))
{
return false;
}
if (PlayerExt.IsGodMode(player))
{
Logging<Plugin>.Info((object)"Admin god mode always allowed", 0);
return true;
}
if (!teleport.IsCovered(showMessage))
{
return false;
}
Biome connectedBiome = teleport.GetConnectedBiome();
if ((int)connectedBiome == 0 || !player.IsBiomeKnown(connectedBiome))
{
if (showMessage)
{
((Character)player).Message((MessageType)2, "$portal_travel_unknown", 0, (Sprite)null);
}
return false;
}
return true;
}
[HarmonyTranspiler]
[HarmonyPatch(typeof(WearNTear), "HaveSupport")]
[HarmonyPriority(100)]
private static IEnumerable<CodeInstruction> WearNTear_HaveSupport_Transpiler(IEnumerable<CodeInstruction> codes)
{
MethodInfo methodInfo = AccessTools.DeclaredMethod(typeof(WearNTear), "GetMinSupport", (Type[])null, (Type[])null);
Func<WearNTear, float> func = GetMinSupportIntercept;
return Transpilers.MethodReplacer(codes, (MethodBase)methodInfo, (MethodBase)func.Method);
static float GetMinSupportIntercept(WearNTear wnt)
{
if (!((Component)(object)wnt).IsPortal(out var portalType))
{
return wnt.GetMinSupport();
}
if (Configs.CraftRequiresHeavySupport.Value == PortalType.PortalStone)
{
return wnt.GetMinSupport();
}
return Configs.CraftRequiresHeavySupport.Value.HasFlag(portalType) ? 100 : 10;
}
}
public static PortalType GetPortalType(this TeleportWorld teleport)
{
return GetPortalType(((Object)teleport).name);
}
public static PortalType GetPortalType(string name)
{
string prefabName = Utils.GetPrefabName(name);
if (!(prefabName == "portal_wood"))
{
if (prefabName == "portal_stone")
{
return PortalType.PortalStone;
}
return PortalType.None;
}
return PortalType.PortalWood;
}
public static void InitPrefabs()
{
InitPortalPrefab("portal_wood");
InitPortalPrefab("portal_stone");
}
private static void InitPortalPrefab(string prefabName)
{
Logging<Plugin>.Info((object)("Init portal: " + prefabName), 0);
TeleportWorld prefab = GlobalStatic.GetPrefab<TeleportWorld>(prefabName, false);
PortalType portalType = GetPortalType(prefabName);
((Component)prefab).gameObject.AddComponent<PortalFuel>();
string configValue = Configs.GetConfigValue<string>(portalType, Configs.CraftPortalWoodStation, Configs.CraftPortalStoneStation);
Requirement[] array = Configs.GetConfigValue<StringList>(portalType, Configs.CraftPortalWoodResources, Configs.CraftPortalStoneResources).ToRequirements(':');
Piece component = ((Component)prefab).GetComponent<Piece>();
if (array.Length != 0)
{
component.m_resources = array;
}
if (!Utility.IsNullOrWhiteSpace(configValue))
{
component.m_craftingStation = PrefabManagerExt.GetCraftingStation(PrefabManager.Instance, configValue);
}
}
}
[HarmonyPatch]
internal static class PortalConnect
{
public enum TagStatus : byte
{
Pending,
Connected,
Unconnected
}
private static readonly Dictionary<int, TagStatus> PortalTagStatus = new Dictionary<int, TagStatus>();
public static TagStatus GetTagStatus(string tag)
{
return GetTagStatus(StringExtensionMethods.GetStableHashCode(tag));
}
public static TagStatus GetTagStatus(int tagHash)
{
if (!PortalTagStatus.TryGetValue(tagHash, out var value))
{
return TagStatus.Unconnected;
}
return value;
}
public static bool IsTagConnected(int tagHash)
{
return GetTagStatus(tagHash) == TagStatus.Connected;
}
public static bool IsTagConnected(string tag)
{
return IsTagConnected(StringExtensionMethods.GetStableHashCode(tag));
}
public static bool IsLockedTag(this string tag)
{
return tag.EndsWith("!");
}
public static bool IsLockedTag(this string tag, out string text)
{
return (tag.IsLockedTag() ? (text = tag.Remove(tag.Length - 1)) : (text = null)) != null;
}
public static void Init()
{
PortalTagStatus.Clear();
ZRoutedRpc.instance.Register<ZPackage>("RPC_UpdatePortalTagStatus", (Action<long, ZPackage>)RPC_UpdatePortalTagStatus);
}
public static void Shutdown()
{
ZRoutedRpcExt.Unregister(ZRoutedRpc.instance, "RPC_UpdatePortalTagStatus");
}
private static void SendPortalTagStatusUpdate(long target)
{
//IL_0018: Unknown result type (might be due to invalid IL or missing references)
//IL_001e: Expected O, but got Unknown
if (ZNet.instance.GetPeerConnections() == 0)
{
Logging<Plugin>.Debug((object)"No clients connected, aborting send", 0);
return;
}
ZPackage val = new ZPackage();
foreach (KeyValuePair<int, TagStatus> item in PortalTagStatus)
{
val.Write(item.Key);
val.Write((byte)item.Value);
}
Logging<Plugin>.Info((object)$"Sending connected portal tag satus to client: {target}", 0);
ZRoutedRpc.instance.InvokeRoutedRPC(target, "RPC_UpdatePortalTagStatus", new object[1] { val });
}
private static void RPC_UpdatePortalTagStatus(long sender, ZPackage pkg)
{
if (!ZNet.instance.IsServer())
{
Logging<Plugin>.Info((object)"Receive portal tag status update from server", 0);
PortalTagStatus.Clear();
while (pkg.GetPos() < pkg.Size())
{
PortalTagStatus.Add(pkg.ReadInt(), (TagStatus)pkg.ReadByte());
}
}
}
[HarmonyPrefix]
[HarmonyPatch(typeof(Game), "ConnectPortals")]
private static void Game_ConnectPortals_Prefix(Game __instance)
{
//IL_0044: Unknown result type (might be due to invalid IL or missing references)
//IL_0049: Unknown result type (might be due to invalid IL or missing references)
PortalTagStatus.Clear();
foreach (ZDO portal in ZDOMan.instance.GetPortals())
{
int stableHashCode = StringExtensionMethods.GetStableHashCode(portal.GetString(ZDOVars.s_tag, ""));
if (!IsTagConnected(stableHashCode))
{
ZDOID connectionZDOID = portal.GetConnectionZDOID((ConnectionType)1);
TagStatus value = ((!((ZDOID)(ref connectionZDOID)).IsNone()) ? TagStatus.Connected : TagStatus.Pending);
PortalTagStatus[stableHashCode] = value;
}
}
if (ZNet.instance.IsServer())
{
SendPortalTagStatusUpdate(ZRoutedRpc.Everybody);
}
}
[HarmonyTranspiler]
[HarmonyPatch(typeof(Game), "ConnectPortals")]
private static IEnumerable<CodeInstruction> Game_ConnectPortals_Transpiler(IEnumerable<CodeInstruction> codes)
{
//IL_0054: Unknown result type (might be due to invalid IL or missing references)
//IL_006d: Unknown result type (might be due to invalid IL or missing references)
//IL_0073: Expected O, but got Unknown
MethodInfo methodInfo = AccessTools.DeclaredMethod(typeof(ZDO), "GetString", new Type[2]
{
typeof(int),
typeof(string)
}, (Type[])null);
Func<ZDO, int, string, string> func = GetStringIntercept;
return new CodeMatcher(codes, (ILGenerator)null).MatchStartForward((CodeMatch[])(object)new CodeMatch[1]
{
new CodeMatch((OpCode?)OpCodes.Callvirt, (object)methodInfo, (string)null)
}).ThrowIfInvalid("Unable to match IL").Set(OpCodes.Call, (object)func.Method)
.InstructionEnumeration();
static string? GetStringIntercept(ZDO zdo, int hash, string defaultValue)
{
bool num = hash == ZDOVars.s_tag;
string @string = zdo.GetString(hash, defaultValue);
if (num && Utility.IsNullOrWhiteSpace(@string))
{
return null;
}
return @string;
}
}
[HarmonyPrefix]
[HarmonyPatch(typeof(Game), "FindRandomUnconnectedPortal")]
[HarmonyPriority(800)]
private static bool Prefix_Game_FindRandomUnconnectedPortal(string tag)
{
if (Utility.IsNullOrWhiteSpace(tag))
{
return false;
}
return !IsTagConnected(tag);
}
[HarmonyTranspiler]
[HarmonyPatch(typeof(Game), "FindRandomUnconnectedPortal")]
private static IEnumerable<CodeInstruction> Transpiler_Game_FindRandomUnconnectedPortal(IEnumerable<CodeInstruction> codes)
{
//IL_0054: Unknown result type (might be due to invalid IL or missing references)
//IL_006d: Unknown result type (might be due to invalid IL or missing references)
//IL_0073: Expected O, but got Unknown
//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
//IL_00a6: Expected O, but got Unknown
MethodInfo methodInfo = AccessTools.DeclaredMethod(typeof(ZDO), "GetString", new Type[2]
{
typeof(int),
typeof(string)
}, (Type[])null);
Func<ZDO, int, string, ZDO, string> func = GetStringIntercept;
return new CodeMatcher(codes, (ILGenerator)null).MatchStartForward((CodeMatch[])(object)new CodeMatch[1]
{
new CodeMatch((OpCode?)OpCodes.Callvirt, (object)methodInfo, (string)null)
}).ThrowIfInvalid("Unable to match IL").Set(OpCodes.Call, (object)func.Method)
.Insert((CodeInstruction[])(object)new CodeInstruction[1]
{
new CodeInstruction(OpCodes.Ldarg_2, (object)null)
})
.InstructionEnumeration();
static string? GetStringIntercept(ZDO dest, int hash, string defaultValue, ZDO source)
{
string @string = dest.GetString(hash, defaultValue);
if (Configs.LinkSameTypeOnly.Value && [email protected]() && dest.GetPrefab() != source.GetPrefab())
{
return null;
}
return @string;
}
}
}
internal class PortalFuel : MonoBehaviour
{
public const float SecPerFuelUnit = 60f;
private ZNetView _nview;
private Portal.PortalType _portalType;
public ItemDrop? FuelItem => (ItemDrop?)(_portalType switch
{
Portal.PortalType.PortalWood => GlobalStatic.GetPrefab<ItemDrop>(Configs.FuelItemPortalWood.Value, true),
Portal.PortalType.PortalStone => GlobalStatic.GetPrefab<ItemDrop>(Configs.FuelItemPortalStone.Value, true),
_ => null,
});
public static int MaxUnits => Configs.FuelMax.Value;
public double FuelTimeRemaining => Math.Max(0.0, ExpireTime - ZNet.instance.GetTimeSeconds());
private double ExpireTime => ZdoExt.GetDouble(_nview.GetZDO(), ZDOVar.ExpireTime, 0.0);
private void Awake()
{
_nview = ((Component)this).GetComponent<ZNetView>();
_portalType = Portal.GetPortalType(((Object)this).name);
}
public static void Init()
{
RegisterGlobalRPC();
}
private static void RegisterGlobalRPC()
{
ZRoutedRpc.instance.Register<ZDOID, double>("RPC_SetRemotePortalExpireTime", (Action<long, ZDOID, double>)RPC_SetRemotePortalExpireTime);
}
private static void UnregisterGlobalRPC()
{
ZRoutedRpcExt.Unregister(ZRoutedRpc.instance, "RPC_SetRemotePortalExpireTime");
}
public static void HotRestore()
{
TeleportWorld[] array = Object.FindObjectsByType<TeleportWorld>((FindObjectsSortMode)0);
for (int i = 0; i < array.Length; i++)
{
((Component)array[i]).gameObject.AddComponent<PortalFuel>();
}
}
public static void Shutdown()
{
TeleportWorld[] array = Object.FindObjectsByType<TeleportWorld>((FindObjectsSortMode)0);
PortalFuel portalFuel = default(PortalFuel);
for (int i = 0; i < array.Length; i++)
{
if (((Component)array[i]).TryGetComponent<PortalFuel>(ref portalFuel))
{
Object.Destroy((Object)(object)portalFuel);
}
}
UnregisterGlobalRPC();
}
public void AddFuelUnits(int units)
{
double timeSeconds = ZNet.instance.GetTimeSeconds();
float num = (float)units * 60f;
double num2 = Math.Max(0.0, ExpireTime - timeSeconds) + (double)num;
SetExpireTime(timeSeconds + num2);
}
public int GetFuelUnits()
{
double fuelTimeRemaining = FuelTimeRemaining;
if (!(fuelTimeRemaining <= 0.0))
{
return Mathf.CeilToInt((float)(fuelTimeRemaining / 60.0));
}
return 0;
}
public void SetExpireTime(double expireTime)
{
UpdateConnectedPortalFuel(expireTime);
SetZDOExpireTime(_nview.GetZDO(), expireTime);
PlayFuelAddFX();
}
private static void SetZDOExpireTime(ZDO zdo, double expireTime)
{
//IL_0043: Unknown result type (might be due to invalid IL or missing references)
Logging<Plugin>.Info((object)$"Set ZDO fuel expire time {expireTime}", 0);
if (!zdo.IsOwner())
{
zdo.SetOwner(ZDOMan.GetSessionID());
}
ZdoExt.Set(zdo, ZDOVar.ExpireTime, expireTime);
if (expireTime <= 0.0)
{
zdo.SetConnection((ConnectionType)1, ZDOID.None);
}
}
public bool IsFuelEmpty()
{
if (Object.op_Implicit((Object)(object)FuelItem))
{
return ZNet.instance.GetTimeSeconds() >= ExpireTime;
}
return false;
}
private void PlayFuelAddFX()
{
((Component)this).GetComponent<TeleportWorld>().PlayInteractFX();
}
private void UpdateConnectedPortalFuel(double expireTime)
{
//IL_000c: Unknown result type (might be due to invalid IL or missing references)
//IL_0011: 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)
ZDOID connectionZDOID = _nview.GetZDO().GetConnectionZDOID((ConnectionType)1);
if (!((ZDOID)(ref connectionZDOID)).IsNone())
{
Logging<Plugin>.Info((object)"Update connected portal fuel levels to match this portal.", 0);
ZRoutedRpc.instance.InvokeRoutedRPC(ZRoutedRpc.Everybody, "RPC_SetRemotePortalExpireTime", new object[2] { connectionZDOID, expireTime });
}
}
private static void RPC_SetRemotePortalExpireTime(long sender, ZDOID portalID, double expireTime)
{
//IL_0005: Unknown result type (might be due to invalid IL or missing references)
//IL_001b: Unknown result type (might be due to invalid IL or missing references)
//IL_004e: Unknown result type (might be due to invalid IL or missing references)
ZDO zDO = ZDOMan.instance.GetZDO(portalID);
if (!zDO.IsOwner())
{
return;
}
Logging<Plugin>.Info((object)$"Set expire time on remote portal at {zDO.GetPosition()}: {expireTime:N}", 0);
SetZDOExpireTime(zDO, expireTime);
if (!ZNet.instance.IsDedicated())
{
GameObject val = ZNetScene.instance.FindInstance(portalID);
PortalFuel portalFuel = default(PortalFuel);
if (Object.op_Implicit((Object)(object)val) && val.TryGetComponent<PortalFuel>(ref portalFuel))
{
portalFuel.PlayFuelAddFX();
}
}
}
}
[HarmonyPatch]
internal static class PortalGroup
{
public const string PlayerKey = "portalgroup";
public static int Max => Configs.RuneStonePortalGroups.Value;
public static int GetPortalGroup(this Player player)
{
string s = default(string);
if (!player.TryGetUniqueKeyValue("portalgroup", ref s))
{
return 0;
}
if (!int.TryParse(s, out var result))
{
return 0;
}
return result % Max;
}
public static void SetPortalGroup(this Player player, int group)
{
player.RemoveUniqueKeyValue("portalgroup");
player.AddUniqueKeyValue("portalgroup", group.ToString());
}
public static bool HasPortalGroup(this Player player)
{
return player.m_uniques.Any((string k) => k.StartsWith("portalgroup"));
}
[HarmonyPostfix]
[HarmonyPatch(typeof(Player), "OnSpawned")]
private static void Player_OnSpawned(Player __instance)
{
if (__instance.HasPortalGroup())
{
int portalGroup = __instance.GetPortalGroup();
Logging<Plugin>.Message((object)$"Player is using portal group {portalGroup}", 0);
}
else if (Max > 1)
{
int group = Random.Range(0, Max);
__instance.SetPortalGroup(group);
}
}
}
[HarmonyPatch]
internal static class PortalPlacement
{
private static readonly List<Heightmap> BiomeEdgesCache = new List<Heightmap>();
private static Biome _invalidEdgeBiome;
private static int _altitudeDelta;
private static void ResetState()
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
_invalidEdgeBiome = (Biome)0;
_altitudeDelta = 0;
}
private static bool IsNearDungeonEntrance(Vector3 position)
{
//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)
int range = Configs.PreventNearDungeonRange.Value;
if (range > 0)
{
return Object.op_Implicit((Object)(object)((IEnumerable<Location>)Location.s_allLocations).FirstOrDefault((Func<Location, bool>)((Location loc) => loc.m_hasInterior && MathExt.InRange((MonoBehaviour)(object)loc, position, (float)range))));
}
return false;
}
[HarmonyPrefix]
[HarmonyPatch(typeof(Player), "SetPlacementGhostValid")]
private static void Player_SetPlacementGhostValid(Player __instance,