Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of DiceCup v1.0.0
DiceCup.dll
Decompiled a day agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security.Cryptography; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Jotunn.Configs; using Jotunn.Entities; using Jotunn.Extensions; using Jotunn.Managers; using Jotunn.Utils; using Microsoft.CodeAnalysis; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyVersion("0.0.0.0")] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [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] [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; } } } namespace DiceCup { public sealed class DiceCupInteractable : MonoBehaviour, Hoverable, Interactable { private ZNetView? _nview; private void Awake() { _nview = ((Component)this).GetComponent<ZNetView>(); } public string GetHoverName() { if (Localization.instance == null) { return "$piece_dicecup"; } return Localization.instance.Localize("$piece_dicecup"); } public string GetHoverText() { if (Localization.instance == null) { return "$piece_dicecup\n[<color=yellow><b>$KEY_Use</b></color>] $dicecup_roll_action"; } return Localization.instance.Localize("$piece_dicecup\n[<color=yellow><b>$KEY_Use</b></color>] $dicecup_roll_action"); } public float GetHoverOffset() { return 0f; } public bool Interact(Humanoid user, bool hold, bool alt) { //IL_004b: Unknown result type (might be due to invalid IL or missing references) if (!(hold || alt)) { Player val = (Player)(object)((user is Player) ? user : null); if (val != null && !((Object)(object)val != (Object)(object)Player.m_localPlayer) && !((Object)(object)_nview == (Object)null) && _nview.IsValid()) { ZDO zDO = _nview.GetZDO(); if (zDO == null) { return false; } DiceCupNetwork.RequestRoll(zDO.m_uid); return true; } } return false; } public bool UseItem(Humanoid user, ItemData item) { return false; } } public enum RollMessageMode { Global, Nearby } internal static class DiceCupConfig { private const string GeneralSection = "General"; private const string MessagesSection = "Messages"; internal static ConfigEntry<float> CooldownSeconds { get; private set; } internal static ConfigEntry<RollMessageMode> MessageMode { get; private set; } internal static ConfigEntry<float> MessageRadius { get; private set; } internal static ConfigEntry<float> WorldTextDurationSeconds { get; private set; } internal static void Bind(ConfigFile config) { AcceptableValueBase val = (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 300f); CooldownSeconds = ConfigFileExtensions.BindConfig<float>(config, "General", "CooldownSeconds", 5f, "Cooldown, in seconds, applied to a player after a successful roll. The cooldown is shared across every Dice Cup and is enforced by the server.", true, (int?)null, val, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); MessageMode = ConfigFileExtensions.BindConfig<RollMessageMode>(config, "Messages", "RollMessageMode", RollMessageMode.Nearby, "Controls who receives successful roll results. Nearby sends the result only to players within RollMessageRadius of the Dice Cup; Global sends it to every connected player. The player who rolled always receives the result.", true, (int?)null, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); val = (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 200f); MessageRadius = ConfigFileExtensions.BindConfig<float>(config, "Messages", "RollMessageRadius", 20f, "Maximum distance, in metres, at which other players receive a successful roll result when RollMessageMode is Nearby. This setting is ignored in Global mode.", true, (int?)null, val, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); val = (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 30f); WorldTextDurationSeconds = ConfigFileExtensions.BindConfig<float>(config, "Messages", "WorldTextDurationSeconds", 0f, "Duration, in seconds, of the floating roll text shown above a loaded Dice Cup. Set to 0 to use Valheim's normal world-text duration.", true, (int?)null, val, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); } } internal static class DiceCupConstants { internal const string PrefabName = "DiceCup"; internal const string PieceNameToken = "$piece_dicecup"; internal const string PieceDescriptionToken = "$piece_dicecup_description"; internal const string RollActionToken = "$dicecup_roll_action"; internal const string RollFormatToken = "$dicecup_roll_format"; internal const string CooldownFormatToken = "$dicecup_cooldown_format"; internal const string RollSoundPrefabName = "sfx_bones_pick"; internal const float MaxUseDistance = 4f; internal const long LocalSenderKey = long.MinValue; } [BepInPlugin("xnolde.dicecup", "Dice Cup", "1.0.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] [NetworkCompatibility(/*Could not decode attribute arguments.*/)] public sealed class DiceCupPlugin : BaseUnityPlugin { public const string PluginGuid = "xnolde.dicecup"; public const string PluginName = "Dice Cup"; public const string PluginVersion = "1.0.0"; internal static DiceCupPlugin Instance { get; private set; } internal static ManualLogSource Log => ((BaseUnityPlugin)Instance).Logger; internal DiceCupUnlockTracker UnlockTracker { get; private set; } private void Awake() { //IL_005f: Unknown result type (might be due to invalid IL or missing references) Instance = this; DiceCupConfig.Bind(((BaseUnityPlugin)this).Config); DiceCupLocalization.Register(); UnlockTracker = ((Component)this).gameObject.AddComponent<DiceCupUnlockTracker>(); UnlockTracker.Initialize(((BaseUnityPlugin)this).Logger); DiceCupNetwork.Initialize(((BaseUnityPlugin)this).Logger); DiceCupPresentation.Initialize(this, ((BaseUnityPlugin)this).Logger); DiceCupPieceRegistry.Initialize(((BaseUnityPlugin)this).Logger); new Harmony("xnolde.dicecup").PatchAll(); PrefabManager.OnVanillaPrefabsAvailable += DiceCupPieceRegistry.Register; ((BaseUnityPlugin)this).Logger.LogInfo((object)("Dice Cup 1.0.0 loaded. " + $"Cooldown={DiceCupConfig.CooldownSeconds.Value:0.##}s, " + $"MessageMode={DiceCupConfig.MessageMode.Value}, " + $"MessageRadius={DiceCupConfig.MessageRadius.Value:0.##}m, " + $"WorldTextDuration={DiceCupConfig.WorldTextDurationSeconds.Value:0.##}s")); } private void OnDestroy() { PrefabManager.OnVanillaPrefabsAvailable -= DiceCupPieceRegistry.Register; DiceCupNetwork.Shutdown(); DiceCupPresentation.Shutdown(); if (Instance == this) { Instance = null; } } } internal static class DiceCupResources { private const string Prefix = "DiceCup.Assets."; private static readonly Assembly Assembly = typeof(DiceCupResources).Assembly; internal static string GetText(string relativeName) { using Stream stream = GetRequiredStream(relativeName); using StreamReader streamReader = new StreamReader(stream); return streamReader.ReadToEnd(); } internal static byte[] GetBytes(string relativeName) { using Stream stream = GetRequiredStream(relativeName); using MemoryStream memoryStream = new MemoryStream(); stream.CopyTo(memoryStream); return memoryStream.ToArray(); } internal static Texture2D LoadTexture(string relativeName) { Texture2D obj = AssetUtils.LoadImage(GetBytes(relativeName)); if ((Object)(object)obj == (Object)null) { throw new InvalidOperationException("Could not decode embedded DiceCup texture '" + relativeName + "'."); } ((Object)obj).name = Path.GetFileNameWithoutExtension(relativeName); ((Texture)obj).filterMode = (FilterMode)0; ((Texture)obj).wrapMode = (TextureWrapMode)0; ((Texture)obj).anisoLevel = 0; return obj; } private static Stream GetRequiredStream(string relativeName) { string text = "DiceCup.Assets." + relativeName.Replace('\\', '.').Replace('/', '.'); Stream manifestResourceStream = Assembly.GetManifestResourceStream(text); if (manifestResourceStream != null) { return manifestResourceStream; } throw new FileNotFoundException("Embedded DiceCup resource was not found: " + text); } } internal static class DiceCupUtility { internal static bool IsWithinDistance(Vector3 a, Vector3 b, float distance) { //IL_000c: 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_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) float num = Mathf.Max(0f, distance); Vector3 val = a - b; return ((Vector3)(ref val)).sqrMagnitude <= num * num; } internal static string SanitizePlayerName(string value) { if (string.IsNullOrWhiteSpace(value)) { return string.Empty; } string text = value.Replace('<', '<').Replace('>', '>').Trim(); if (text.Length > 64) { return text.Substring(0, 64); } return text; } } internal static class DiceCupLocalization { internal static void Register() { CustomLocalization localization = LocalizationManager.Instance.GetLocalization(); localization.AddJsonFile("English", DiceCupResources.GetText("Translations.English.dicecup.json")); localization.AddJsonFile("Spanish", DiceCupResources.GetText("Translations.Spanish.dicecup.json")); } } internal static class DiceCupNetwork { private const string RpcRollRequest = "xnolde.dicecup.RollRequest"; private const string RpcRollResult = "xnolde.dicecup.RollResult"; private const string RpcCooldown = "xnolde.dicecup.Cooldown"; private static readonly Dictionary<long, float> NextRollAt = new Dictionary<long, float>(); private static ManualLogSource _log = null; private static RandomNumberGenerator? _rng; private static readonly byte[] RandomByte = new byte[1]; private static ZNet? _cooldownSession; internal static void Initialize(ManualLogSource log) { _log = log; _rng = RandomNumberGenerator.Create(); } internal static void Shutdown() { NextRollAt.Clear(); _cooldownSession = null; _rng?.Dispose(); _rng = null; } internal static void RegisterPeerRpc(ZNet znet, ZNetPeer peer) { if (peer == null || peer.m_rpc == null) { return; } EnsureCooldownSession(znet); if (znet.IsServer()) { NextRollAt.Remove(peer.m_uid); peer.m_rpc.Register<ZDOID>("xnolde.dicecup.RollRequest", (Action<ZRpc, ZDOID>)delegate(ZRpc rpc, ZDOID cupId) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) ReceiveRemoteRollRequest(peer, rpc, cupId); }); } else { peer.m_rpc.Register<ZPackage>("xnolde.dicecup.RollResult", (Action<ZRpc, ZPackage>)ReceiveServerRollResult); peer.m_rpc.Register<int>("xnolde.dicecup.Cooldown", (Action<ZRpc, int>)ReceiveServerCooldown); } } internal static void RequestRoll(ZDOID cupId) { //IL_0025: 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_0076: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)ZNet.instance == (Object)null) { return; } EnsureCooldownSession(ZNet.instance); if (ZNet.instance.IsServer()) { ProcessRoll(null, cupId); return; } ZRpc serverRPC = ZNet.instance.GetServerRPC(); if (serverRPC == null || !serverRPC.IsConnected()) { _log.LogWarning((object)"DiceCup roll request aborted: direct server RPC is unavailable."); return; } serverRPC.Invoke("xnolde.dicecup.RollRequest", new object[1] { cupId }); _log.LogDebug((object)$"DiceCup roll request sent for {cupId}."); } private static void ReceiveRemoteRollRequest(ZNetPeer peer, ZRpc rpc, ZDOID cupId) { //IL_0047: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)ZNet.instance == (Object)null) && ZNet.instance.IsServer()) { if (peer == null || peer.m_rpc == null || peer.m_rpc != rpc || !peer.IsReady()) { _log.LogWarning((object)"DiceCup rejected a roll request from an invalid/unready connection."); } else { ProcessRoll(peer, cupId); } } } private static void ProcessRoll(ZNetPeer? remoteRoller, ZDOID cupId) { //IL_004c: 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_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_01c2: Unknown result type (might be due to invalid IL or missing references) //IL_01c3: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsServer() || ZDOMan.instance == null || (Object)(object)ZNetScene.instance == (Object)null) { _log.LogWarning((object)"DiceCup rejected a roll: required network state is unavailable."); return; } EnsureCooldownSession(ZNet.instance); ZDO zDO = ZDOMan.instance.GetZDO(cupId); if (!IsValidDiceCup(zDO)) { _log.LogWarning((object)$"DiceCup rejected an invalid cup ZDO: {cupId}."); return; } if (!TryResolveRoller(remoteRoller, out long cooldownKey, out string playerName, out Vector3 position, out string positionSource)) { _log.LogWarning((object)$"DiceCup could not resolve the roller for {cupId}."); return; } Vector3 position2 = zDO.GetPosition(); float num = Vector3.Distance(position, position2); if (num > 4f) { _log.LogDebug((object)("DiceCup roll rejected by distance: player=" + playerName + ", " + $"distance={num:0.000}m, source={positionSource}.")); return; } float realtimeSinceStartup = Time.realtimeSinceStartup; float num2 = Mathf.Max(0f, DiceCupConfig.CooldownSeconds.Value); if (NextRollAt.TryGetValue(cooldownKey, out var value) && value > realtimeSinceStartup) { float num3 = value - realtimeSinceStartup; _log.LogDebug((object)("DiceCup roll rejected by cooldown: player=" + playerName + ", " + $"remaining={num3:0.000}s.")); SendCooldown(remoteRoller, num3); return; } NextRollAt[cooldownKey] = realtimeSinceStartup + num2; int num4 = RollD6(); int num5 = RollD6(); _log.LogDebug((object)("DiceCup roll accepted: player=" + playerName + ", " + $"{num4},{num5}, distance={num:0.000}m, source={positionSource}.")); BroadcastRoll(cupId, position2, remoteRoller, playerName, num4, num5); } private static void EnsureCooldownSession(ZNet znet) { if (_cooldownSession != znet) { _cooldownSession = znet; NextRollAt.Clear(); } } private static bool IsValidDiceCup(ZDO? cupZdo) { if (cupZdo == null || (Object)(object)ZNetScene.instance == (Object)null) { return false; } GameObject prefab = ZNetScene.instance.GetPrefab(cupZdo.GetPrefab()); if ((Object)(object)prefab != (Object)null) { return string.Equals(((Object)prefab).name, "DiceCup", StringComparison.Ordinal); } return false; } private static bool TryResolveRoller(ZNetPeer? remoteRoller, out long cooldownKey, out string playerName, out Vector3 position, out string positionSource) { //IL_0013: 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_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) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) cooldownKey = long.MinValue; playerName = string.Empty; position = Vector3.zero; positionSource = "unresolved"; if (remoteRoller == null) { Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { return false; } playerName = DiceCupUtility.SanitizePlayerName(localPlayer.GetPlayerName()); position = ((Component)localPlayer).transform.position; positionSource = "local-player-transform"; return playerName.Length > 0; } if (!remoteRoller.IsReady() || remoteRoller.m_uid == 0L) { return false; } cooldownKey = remoteRoller.m_uid; playerName = DiceCupUtility.SanitizePlayerName(remoteRoller.m_playerName); if (playerName.Length == 0) { return false; } if (TryGetPeerCharacterPosition(remoteRoller, out position)) { positionSource = "player-zdo"; } else { position = remoteRoller.m_refPos; positionSource = "peer-refpos-fallback"; } return true; } private static bool TryGetPeerCharacterPosition(ZNetPeer peer, out Vector3 position) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001c: 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_0095: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) position = Vector3.zero; if (peer == null || !peer.IsReady() || peer.m_characterID == ZDOID.None || ZDOMan.instance == null || (Object)(object)ZNetScene.instance == (Object)null) { return false; } ZDO zDO = ZDOMan.instance.GetZDO(peer.m_characterID); if (zDO == null) { return false; } GameObject prefab = ZNetScene.instance.GetPrefab(zDO.GetPrefab()); if ((Object)(object)prefab == (Object)null || (Object)(object)prefab.GetComponent<Player>() == (Object)null) { return false; } long owner = zDO.GetOwner(); if (owner != 0L && owner != peer.m_uid) { return false; } position = zDO.GetPosition(); return true; } private static Vector3 GetPeerPositionForPresentation(ZNetPeer peer) { //IL_0011: 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) if (!TryGetPeerCharacterPosition(peer, out var position)) { return peer.m_refPos; } return position; } private static int RollD6() { if (_rng == null) { _rng = RandomNumberGenerator.Create(); } byte b; do { _rng.GetBytes(RandomByte); b = RandomByte[0]; } while (b >= 252); return b % 6 + 1; } private static void BroadcastRoll(ZDOID cupId, Vector3 cupPosition, ZNetPeer? remoteRoller, string playerName, int die1, int die2) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Expected O, but got Unknown //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Unknown result type (might be due to invalid IL or missing references) //IL_010a: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_0116: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)ZNet.instance == (Object)null) { return; } ZPackage val = new ZPackage(); val.Write(cupId); val.Write(playerName); val.Write(die1); val.Write(die2); bool flag = DiceCupConfig.MessageMode.Value == RollMessageMode.Global; float distance = Mathf.Max(1f, DiceCupConfig.MessageRadius.Value); foreach (ZNetPeer peer in ZNet.instance.GetPeers()) { if (peer != null && peer.m_rpc != null && peer.IsReady()) { bool flag2 = remoteRoller != null && peer == remoteRoller; bool flag3 = DiceCupUtility.IsWithinDistance(GetPeerPositionForPresentation(peer), cupPosition, distance); if (flag || flag2 || flag3) { peer.m_rpc.Invoke("xnolde.dicecup.RollResult", new object[1] { val }); } } } Player localPlayer = Player.m_localPlayer; if (!((Object)(object)localPlayer == (Object)null)) { bool flag4 = remoteRoller == null; if (flag || flag4 || DiceCupUtility.IsWithinDistance(((Component)localPlayer).transform.position, cupPosition, distance)) { DiceCupPresentation.ShowRollMessage(cupId, playerName, die1, die2); } } } private static void SendCooldown(ZNetPeer? remoteRoller, float remainingSeconds) { int num = Math.Max(1, (int)Math.Ceiling(remainingSeconds)); if (remoteRoller == null) { DiceCupPresentation.ShowCooldownMessage(num); } else if (remoteRoller.m_rpc != null && remoteRoller.IsReady()) { remoteRoller.m_rpc.Invoke("xnolde.dicecup.Cooldown", new object[1] { num }); } } private static void ReceiveServerRollResult(ZRpc rpc, ZPackage package) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) if (!IsCurrentServerRpc(rpc) || package == null) { return; } try { ZDOID cupId = package.ReadZDOID(); string text = DiceCupUtility.SanitizePlayerName(package.ReadString()); int num = package.ReadInt(); int num2 = package.ReadInt(); if (text.Length == 0 || num < 1 || num > 6 || num2 < 1 || num2 > 6) { _log.LogWarning((object)"DiceCup discarded a malformed roll result."); } else { DiceCupPresentation.ShowRollMessage(cupId, text, num, num2); } } catch (Exception ex) { _log.LogWarning((object)("DiceCup discarded an invalid roll result: " + ex.GetBaseException().Message)); } } private static void ReceiveServerCooldown(ZRpc rpc, int seconds) { if (IsCurrentServerRpc(rpc)) { DiceCupPresentation.ShowCooldownMessage(Math.Max(1, seconds)); } } private static bool IsCurrentServerRpc(ZRpc rpc) { if ((Object)(object)ZNet.instance == (Object)null || ZNet.instance.IsServer()) { return false; } ZRpc serverRPC = ZNet.instance.GetServerRPC(); if (serverRPC != null) { return serverRPC == rpc; } return false; } } [HarmonyPatch(typeof(Chat), "UpdateWorldTexts", new Type[] { typeof(float) })] internal static class DiceCupWorldTextPatch { [HarmonyPrefix] private static void Prefix(Chat __instance, float dt) { DiceCupWorldText.AdjustTimers(__instance, dt); } } [HarmonyPatch(typeof(ZNet), "OnNewConnection")] internal static class DiceCupNetworkConnectionPatch { [HarmonyPostfix] private static void Postfix(ZNet __instance, ZNetPeer peer) { DiceCupNetwork.RegisterPeerRpc(__instance, peer); } } internal sealed class DiceCupModel { internal GameObject Visuals { get; } internal Bounds Bounds { get; } internal DiceCupModel(GameObject visuals, Bounds bounds) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) Visuals = visuals; Bounds = bounds; } } internal static class DiceCupModelBuilder { private const float ColliderHorizontalPadding = 0.01f; private const float ColliderTopPadding = 0.005f; private const float VisualSink = 0.016f; private const float GroundTolerance = 0.001f; private const float TextureTiles = 3f; internal static DiceCupModel Build(GameObject prefab, ManualLogSource log) { //IL_002d: 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_0044: 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_0075: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Unknown result type (might be due to invalid IL or missing references) //IL_0107: Unknown result type (might be due to invalid IL or missing references) //IL_0109: Unknown result type (might be due to invalid IL or missing references) //IL_0111: Unknown result type (might be due to invalid IL or missing references) //IL_0119: Unknown result type (might be due to invalid IL or missing references) //IL_0120: Unknown result type (might be due to invalid IL or missing references) //IL_014f: Unknown result type (might be due to invalid IL or missing references) //IL_0156: Expected O, but got Unknown Material sourceMaterial = StripSourcePresentation(prefab); Texture2D texture = DiceCupResources.LoadTexture("leather.png"); Texture2D texture2 = DiceCupResources.LoadTexture("leather_band.png"); Texture2D texture3 = DiceCupResources.LoadTexture("bone.png"); GameObject val = new GameObject("DiceCupVisuals"); val.transform.SetParent(prefab.transform, false); val.layer = prefab.layer; AddVisualPart(val.transform, "cup.obj", "Cup", texture, new Color(0.86f, 0.82f, 0.78f, 1f), sourceMaterial); AddVisualPart(val.transform, "band.obj", "LeatherBand", texture2, Color.white, sourceMaterial); AddVisualPart(val.transform, "die01.obj", "Die01", texture3, new Color(0.82f, 0.78f, 0.66f, 1f), sourceMaterial); AddVisualPart(val.transform, "die02.obj", "Die02", texture3, new Color(0.82f, 0.78f, 0.66f, 1f), sourceMaterial); Bounds val2 = CalculateLocalVisualBounds(val.transform); ValidateGrounding(val2); AddGroundedCollider(prefab, val2); AddSpeechAnchor(prefab, val2); ApplyVisualSink(val.transform); log.LogDebug((object)($"DiceCup visual sink: all parts y=-{0.016f:0.000}m; " + "collider bottom remains y=0.")); return new DiceCupModel(val, val2); } private static Material? StripSourcePresentation(GameObject prefab) { Material val = null; Renderer[] componentsInChildren = prefab.GetComponentsInChildren<Renderer>(true); foreach (Renderer val2 in componentsInChildren) { if (val == null) { val = val2.sharedMaterial; } val2.enabled = false; } LODGroup[] componentsInChildren2 = prefab.GetComponentsInChildren<LODGroup>(true); for (int i = 0; i < componentsInChildren2.Length; i++) { Object.DestroyImmediate((Object)(object)componentsInChildren2[i]); } Chair[] componentsInChildren3 = prefab.GetComponentsInChildren<Chair>(true); for (int i = 0; i < componentsInChildren3.Length; i++) { Object.DestroyImmediate((Object)(object)componentsInChildren3[i]); } EffectArea[] componentsInChildren4 = prefab.GetComponentsInChildren<EffectArea>(true); for (int i = 0; i < componentsInChildren4.Length; i++) { Object.DestroyImmediate((Object)(object)componentsInChildren4[i]); } Collider[] componentsInChildren5 = prefab.GetComponentsInChildren<Collider>(true); for (int i = 0; i < componentsInChildren5.Length; i++) { Object.DestroyImmediate((Object)(object)componentsInChildren5[i]); } return val; } private static void ApplyVisualSink(Transform visualRoot) { //IL_0056: 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_006c: Unknown result type (might be due to invalid IL or missing references) string[] array = new string[4] { "Cup", "LeatherBand", "Die01", "Die02" }; foreach (string text in array) { Transform obj = visualRoot.Find(text); if ((Object)(object)obj == (Object)null) { throw new InvalidOperationException("DiceCup visual part '" + text + "' was not found."); } Vector3 localPosition = obj.localPosition; localPosition.y -= 0.016f; obj.localPosition = localPosition; } } private static void AddGroundedCollider(GameObject prefab, Bounds visualBounds) { //IL_0002: 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_0028: 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_004e: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) float num = ((Bounds)(ref visualBounds)).min.x - 0.01f; float num2 = ((Bounds)(ref visualBounds)).max.x + 0.01f; float num3 = ((Bounds)(ref visualBounds)).min.z - 0.01f; float num4 = ((Bounds)(ref visualBounds)).max.z + 0.01f; float num5 = Mathf.Max(((Bounds)(ref visualBounds)).max.y + 0.005f, 0.01f); BoxCollider obj = prefab.AddComponent<BoxCollider>(); obj.center = new Vector3((num + num2) * 0.5f, num5 * 0.5f, (num3 + num4) * 0.5f); obj.size = new Vector3(num2 - num, num5, num4 - num3); } private static void AddSpeechAnchor(GameObject prefab, Bounds visualBounds) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0023: 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_0041: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("DiceCupSpeechAnchor"); val.transform.SetParent(prefab.transform, false); val.transform.localPosition = new Vector3(((Bounds)(ref visualBounds)).center.x, ((Bounds)(ref visualBounds)).max.y + 0.1f, ((Bounds)(ref visualBounds)).center.z); } private static void ValidateGrounding(Bounds visualBounds) { //IL_0002: 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) if (Mathf.Abs(((Bounds)(ref visualBounds)).min.y) <= 0.001f) { return; } throw new InvalidOperationException("DiceCup authored geometry is not grounded at y=0. " + $"minY={((Bounds)(ref visualBounds)).min.y:0.0000}."); } private static Bounds CalculateLocalVisualBounds(Transform visualRoot) { //IL_0004: 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_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004b: 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_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) //IL_005d: 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_012b: 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_0083: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) bool flag = false; Bounds result = default(Bounds); MeshFilter[] componentsInChildren = ((Component)visualRoot).GetComponentsInChildren<MeshFilter>(true); Vector3 val3 = default(Vector3); foreach (MeshFilter val in componentsInChildren) { Mesh sharedMesh = val.sharedMesh; if ((Object)(object)sharedMesh == (Object)null) { continue; } Matrix4x4 val2 = visualRoot.worldToLocalMatrix * ((Component)val).transform.localToWorldMatrix; Bounds bounds = sharedMesh.bounds; Vector3 min = ((Bounds)(ref bounds)).min; Vector3 max = ((Bounds)(ref bounds)).max; for (int j = 0; j < 2; j++) { for (int k = 0; k < 2; k++) { for (int l = 0; l < 2; l++) { ((Vector3)(ref val3))..ctor((j == 0) ? min.x : max.x, (k == 0) ? min.y : max.y, (l == 0) ? min.z : max.z); Vector3 val4 = ((Matrix4x4)(ref val2)).MultiplyPoint3x4(val3); if (!flag) { ((Bounds)(ref result))..ctor(val4, Vector3.zero); flag = true; } else { ((Bounds)(ref result)).Encapsulate(val4); } } } } } if (!flag) { throw new InvalidOperationException("DiceCup contains no visual mesh bounds."); } return result; } private static void AddVisualPart(Transform parent, string objResource, string objectName, Texture2D texture, Color tint, Material? sourceMaterial) { //IL_0009: 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_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_0017: 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_0024: 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_0056: 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_0068: 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_0096: Unknown result type (might be due to invalid IL or missing references) Mesh val = LoadObjMeshInvariant(objResource, objectName); Bounds bounds = val.bounds; Vector3 size = ((Bounds)(ref bounds)).size; if (size.x > 2f || size.y > 2f || size.z > 2f) { throw new InvalidOperationException($"DiceCup mesh {objectName} has implausible bounds {size}."); } GameObject val2 = new GameObject(objectName); val2.transform.SetParent(parent, false); val2.layer = ((Component)parent).gameObject.layer; val2.AddComponent<MeshFilter>().sharedMesh = val; ((Renderer)val2.AddComponent<MeshRenderer>()).sharedMaterial = MakeMaterial(objectName + "_Material", texture, tint, sourceMaterial); } private static Mesh LoadObjMeshInvariant(string objResource, string meshName) { //IL_009d: Unknown result type (might be due to invalid IL or missing references) string text = DiceCupResources.GetText(objResource); List<Vector3> list = new List<Vector3>(); List<int> list2 = new List<int>(); using StringReader stringReader = new StringReader(text); string text2; while ((text2 = stringReader.ReadLine()) != null) { string text3 = text2.Trim(); if (text3.Length == 0 || text3[0] == '#') { continue; } string[] array = text3.Split((char[]?)null, StringSplitOptions.RemoveEmptyEntries); if (array.Length == 0) { continue; } if (array[0] == "v") { if (array.Length < 4) { throw new FormatException("Invalid OBJ vertex in " + objResource + ": " + text2); } list.Add(new Vector3(ParseInvariantFloat(array[1]), ParseInvariantFloat(array[2]), ParseInvariantFloat(array[3]))); } else if (array[0] == "f" && array.Length >= 4) { int item = ParseObjVertexIndex(array[1], list.Count); for (int i = 2; i < array.Length - 1; i++) { list2.Add(item); list2.Add(ParseObjVertexIndex(array[i], list.Count)); list2.Add(ParseObjVertexIndex(array[i + 1], list.Count)); } } } if (list.Count == 0 || list2.Count == 0) { throw new FormatException("OBJ contains no usable geometry: " + objResource); } return BuildFaceProjectedMesh(list, list2, meshName); } private static float ParseInvariantFloat(string value) { return float.Parse(value, NumberStyles.Float, CultureInfo.InvariantCulture); } private static int ParseObjVertexIndex(string token, int vertexCount) { int num = int.Parse(token.Split(new char[1] { '/' })[0], NumberStyles.Integer, CultureInfo.InvariantCulture); int num2 = ((num > 0) ? (num - 1) : (vertexCount + num)); if (num2 < 0 || num2 >= vertexCount) { throw new IndexOutOfRangeException($"OBJ vertex index {num} is outside 1..{vertexCount}."); } return num2; } private static Mesh BuildFaceProjectedMesh(List<Vector3> sourceVertices, List<int> sourceTriangles, string meshName) { //IL_0004: Unknown result type (might be due to invalid IL or missing references) //IL_0009: 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_0039: 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_0067: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: 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_00c6: 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_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: 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_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: 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_00ff: Unknown result type (might be due to invalid IL or missing references) //IL_010c: Unknown result type (might be due to invalid IL or missing references) //IL_0115: Unknown result type (might be due to invalid IL or missing references) //IL_011e: Unknown result type (might be due to invalid IL or missing references) //IL_0146: Unknown result type (might be due to invalid IL or missing references) //IL_0148: Unknown result type (might be due to invalid IL or missing references) //IL_014a: Unknown result type (might be due to invalid IL or missing references) //IL_014e: Unknown result type (might be due to invalid IL or missing references) //IL_015a: Unknown result type (might be due to invalid IL or missing references) //IL_015c: 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_0162: Unknown result type (might be due to invalid IL or missing references) //IL_016e: 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_0172: Unknown result type (might be due to invalid IL or missing references) //IL_0176: Unknown result type (might be due to invalid IL or missing references) //IL_0193: Unknown result type (might be due to invalid IL or missing references) //IL_0198: Unknown result type (might be due to invalid IL or missing references) //IL_019f: Unknown result type (might be due to invalid IL or missing references) //IL_01ac: Unknown result type (might be due to invalid IL or missing references) //IL_01b9: 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) //IL_01cc: Unknown result type (might be due to invalid IL or missing references) //IL_01d3: Expected O, but got Unknown Bounds bounds = default(Bounds); ((Bounds)(ref bounds))..ctor(sourceVertices[0], Vector3.zero); for (int i = 1; i < sourceVertices.Count; i++) { ((Bounds)(ref bounds)).Encapsulate(sourceVertices[i]); } float sx = Mathf.Max(((Bounds)(ref bounds)).size.x, 0.001f); float sy = Mathf.Max(((Bounds)(ref bounds)).size.y, 0.001f); float sz = Mathf.Max(((Bounds)(ref bounds)).size.z, 0.001f); List<Vector3> list = new List<Vector3>(sourceTriangles.Count); List<int> list2 = new List<int>(sourceTriangles.Count); List<Vector2> list3 = new List<Vector2>(sourceTriangles.Count); for (int j = 0; j < sourceTriangles.Count; j += 3) { Vector3 val = sourceVertices[sourceTriangles[j]]; Vector3 val2 = sourceVertices[sourceTriangles[j + 1]]; Vector3 val3 = sourceVertices[sourceTriangles[j + 2]]; Vector3 val4 = Vector3.Cross(val2 - val, val3 - val); Vector3 normalized = ((Vector3)(ref val4)).normalized; int count = list.Count; list.Add(val); list.Add(val2); list.Add(val3); list2.Add(count); list2.Add(count + 1); list2.Add(count + 2); list3.Add(ProjectFaceUv(val, normalized, bounds, sx, sy, sz)); list3.Add(ProjectFaceUv(val2, normalized, bounds, sx, sy, sz)); list3.Add(ProjectFaceUv(val3, normalized, bounds, sx, sy, sz)); } Mesh val5 = new Mesh { name = meshName, vertices = list.ToArray(), triangles = list2.ToArray(), uv = list3.ToArray() }; val5.RecalculateNormals(); val5.RecalculateBounds(); return val5; } private static Vector2 ProjectFaceUv(Vector3 point, Vector3 normal, Bounds bounds, float sx, float sy, float sz) { //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_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0028: 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_0078: Unknown result type (might be due to invalid IL or missing references) //IL_007e: 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_003c: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_0088: 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_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_0046: 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) //IL_005b: 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) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) Vector3 val = default(Vector3); ((Vector3)(ref val))..ctor(Mathf.Abs(normal.x), Mathf.Abs(normal.y), Mathf.Abs(normal.z)); Vector2 val2 = default(Vector2); if (val.y >= val.x && val.y >= val.z) { ((Vector2)(ref val2))..ctor((point.x - ((Bounds)(ref bounds)).min.x) / sx, (point.z - ((Bounds)(ref bounds)).min.z) / sz); } else if (val.x >= val.z) { ((Vector2)(ref val2))..ctor((point.z - ((Bounds)(ref bounds)).min.z) / sz, (point.y - ((Bounds)(ref bounds)).min.y) / sy); } else { ((Vector2)(ref val2))..ctor((point.x - ((Bounds)(ref bounds)).min.x) / sx, (point.y - ((Bounds)(ref bounds)).min.y) / sy); } return val2 * 3f; } private static Material MakeMaterial(string name, Texture2D texture, Color tint, Material? sourceMaterial) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Expected O, but got Unknown //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Expected O, but got Unknown //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_0097: 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_016b: Unknown result type (might be due to invalid IL or missing references) Material val; if ((Object)(object)sourceMaterial != (Object)null) { val = new Material(sourceMaterial); } else { Shader obj = Shader.Find("Custom/Piece") ?? Shader.Find("Standard"); if ((Object)(object)obj == (Object)null) { throw new InvalidOperationException("No usable shader/material found for Dice Cup."); } val = new Material(obj); } ((Object)val).name = name; if (val.HasProperty("_MainTex")) { val.SetTexture("_MainTex", (Texture)(object)texture); val.SetTextureScale("_MainTex", Vector2.one); val.SetTextureOffset("_MainTex", Vector2.zero); } if (val.HasProperty("_Color")) { val.SetColor("_Color", tint); } if (val.HasProperty("_BaseColor")) { val.SetColor("_BaseColor", tint); } if (val.HasProperty("_Metallic")) { val.SetFloat("_Metallic", 0f); } if (val.HasProperty("_Glossiness")) { val.SetFloat("_Glossiness", 0.12f); } if (val.HasProperty("_Cutoff")) { val.SetFloat("_Cutoff", 0f); } if (val.HasProperty("_BumpMap")) { val.SetTexture("_BumpMap", (Texture)null); } if (val.HasProperty("_MetallicGlossMap")) { val.SetTexture("_MetallicGlossMap", (Texture)null); } if (val.HasProperty("_EmissionMap")) { val.SetTexture("_EmissionMap", (Texture)null); } if (val.HasProperty("_EmissionColor")) { val.SetColor("_EmissionColor", Color.black); } if (val.HasProperty("_Cull")) { val.SetFloat("_Cull", 0f); } val.DisableKeyword("_ALPHATEST_ON"); val.DisableKeyword("_ALPHABLEND_ON"); val.DisableKeyword("_ALPHAPREMULTIPLY_ON"); val.DisableKeyword("_NORMALMAP"); val.DisableKeyword("_METALLICGLOSSMAP"); val.DisableKeyword("_EMISSION"); val.renderQueue = -1; return val; } } internal static class DiceCupPieceRegistry { private static ManualLogSource _log; private static bool _registered; internal static void Initialize(ManualLogSource log) { _log = log; } internal static void Register() { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Expected O, but got Unknown //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Expected O, but got Unknown PrefabManager.OnVanillaPrefabsAvailable -= Register; if (_registered) { return; } try { PieceConfig val = new PieceConfig(); val.Name = "$piece_dicecup"; val.Description = "$piece_dicecup_description"; val.PieceTable = PieceTables.Hammer; val.CraftingStation = CraftingStations.Workbench; val.Category = PieceCategories.Furniture; val.Usage = new string[2] { PieceUsages.Furniture, PieceUsages.Decor }; PieceConfig val2 = val; val2.AddRequirement("BoneFragments", 4, true); val2.AddRequirement("DeerHide", 2, true); val2.AddRequirement("Resin", 1, true); CustomPiece val3 = new CustomPiece("DiceCup", "piece_chair", val2); GameObject piecePrefab = val3.PiecePrefab; val3.Piece.m_comfort = 0; DiceCupModel diceCupModel = DiceCupModelBuilder.Build(piecePrefab, _log); RenderIcon(val3, diceCupModel.Visuals); if ((Object)(object)piecePrefab.GetComponent<DiceCupInteractable>() == (Object)null) { piecePrefab.AddComponent<DiceCupInteractable>(); } PieceManager.Instance.AddPiece(val3); _registered = true; _log.LogInfo((object)"Dice Cup piece registered."); DiceCupPlugin.Instance.UnlockTracker.RequestRefresh("piece registered"); } catch (Exception arg) { _log.LogError((object)$"Could not register Dice Cup: {arg}"); } } private static void RenderIcon(CustomPiece customPiece, GameObject visuals) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) if (GUIManager.IsHeadless()) { return; } try { Sprite val = RenderManager.Instance.Render(visuals, RenderManager.IsometricRotation); if ((Object)(object)val == (Object)null) { _log.LogWarning((object)"DiceCup icon render returned null; cloned source icon retained."); return; } customPiece.Piece.m_icon = val; _log.LogDebug((object)"DiceCup build icon rendered from the actual prefab visuals."); } catch (Exception ex) { _log.LogWarning((object)("DiceCup runtime icon render failed; cloned source icon retained: " + ex.GetBaseException().Message)); } } } internal static class DiceCupPresentation { private const string OfficialChatColor = "#E6B65A"; private static readonly BindingFlags AnyInstance = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; private static readonly MethodInfo? ChatAddStringMethod = typeof(Chat).GetMethod("AddString", AnyInstance, null, new Type[3] { typeof(string), typeof(string), typeof(Type) }, null); private static readonly MethodInfo? ChatAddStringSimpleMethod = typeof(Chat).GetMethod("AddString", AnyInstance, null, new Type[1] { typeof(string) }, null); private static readonly FieldInfo? ChatHideTimerField = typeof(Chat).GetField("m_hideTimer", AnyInstance); private static readonly FieldInfo? ChatWindowField = typeof(Chat).GetField("m_chatWindow", AnyInstance) ?? typeof(Terminal).GetField("m_chatWindow", AnyInstance); private static DiceCupPlugin _plugin = null; private static ManualLogSource _log = null; private static bool _chatFallbackLogged; private static bool _soundFallbackLogged; private static GameObject? _rollSoundPrefab; internal static void Initialize(DiceCupPlugin plugin, ManualLogSource log) { _plugin = plugin; _log = log; } internal static void Shutdown() { _rollSoundPrefab = null; _chatFallbackLogged = false; _soundFallbackLogged = false; } internal static void ShowRollMessage(ZDOID cupId, string playerName, int die1, int die2) { //IL_0044: 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) //IL_0069: Unknown result type (might be due to invalid IL or missing references) string speaker = Localize("$piece_dicecup"); string text = LocalizeFormat("$dicecup_roll_format", playerName, die1, die2, die1 + die2); ShowChatHistoryLine(speaker, text); GameObject val = FindLoadedCup(cupId); if (!((Object)(object)val == (Object)null)) { DiceCupWorldText.Show(val, speaker, text); ((MonoBehaviour)_plugin).StartCoroutine(PlayRollSoundSequence(cupId, val.transform.position)); } } internal static void ShowCooldownMessage(int seconds) { string text = LocalizeFormat("$dicecup_cooldown_format", seconds); MessageHud instance = MessageHud.instance; if (instance != null) { instance.ShowMessage((MessageType)2, text, 0, (Sprite)null, false, true); } } private static string Localize(string token) { if (Localization.instance == null) { return token; } return Localization.instance.Localize(token); } private static string LocalizeFormat(string token, params object[] values) { string text = Localize(token); try { return string.Format(CultureInfo.CurrentCulture, text, values); } catch { return text; } } private static void ShowChatHistoryLine(string speaker, string text) { string text2 = "<color=#E6B65A>" + speaker + ":</color> " + text; if ((Object)(object)Chat.instance != (Object)null && ChatAddStringSimpleMethod != null) { try { ChatAddStringSimpleMethod.Invoke(Chat.instance, new object[1] { text2 }); WakeChatPanel(); return; } catch (Exception ex) { LogChatFallbackOnce(ex); } } if ((Object)(object)Chat.instance != (Object)null && ChatAddStringMethod != null) { try { ChatAddStringMethod.Invoke(Chat.instance, new object[3] { speaker, text, (object)(Type)2 }); WakeChatPanel(); } catch (Exception ex2) { LogChatFallbackOnce(ex2); } } } private static void WakeChatPanel() { Chat instance = Chat.instance; if ((Object)(object)instance == (Object)null) { return; } try { ChatHideTimerField?.SetValue(instance, 0f); object? obj = ChatWindowField?.GetValue(instance); RectTransform val = (RectTransform)((obj is RectTransform) ? obj : null); if (val != null) { ((Component)val).gameObject.SetActive(true); } } catch { } } private static void LogChatFallbackOnce(Exception ex) { if (!_chatFallbackLogged) { _chatFallbackLogged = true; _log.LogWarning((object)("DiceCup could not add its chat-history line: " + ex.GetBaseException().Message)); } } private static IEnumerator PlayRollSoundSequence(ZDOID cupId, Vector3 initialPosition) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) PlayVanillaRollSound(initialPosition); float num = Random.Range(0.1f, 0.13f); yield return (object)new WaitForSecondsRealtime(num); GameObject val = FindLoadedCup(cupId); if ((Object)(object)val != (Object)null) { PlayVanillaRollSound(val.transform.position); } } private static GameObject? FindLoadedCup(ZDOID cupId) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)ZNetScene.instance != (Object)null)) { return null; } return ZNetScene.instance.FindInstance(cupId); } private static void PlayVanillaRollSound(Vector3 position) { //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0056: 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_0060: Unknown result type (might be due to invalid IL or missing references) try { if (_rollSoundPrefab == null) { _rollSoundPrefab = PrefabManager.Instance.GetPrefab("sfx_bones_pick"); } if ((Object)(object)_rollSoundPrefab == (Object)null) { if (!_soundFallbackLogged) { _soundFallbackLogged = true; _log.LogWarning((object)"DiceCup could not find vanilla roll sound prefab."); } } else { Object.Instantiate<GameObject>(_rollSoundPrefab, position + Vector3.up * 0.1f, Quaternion.identity); } } catch (Exception ex) { if (!_soundFallbackLogged) { _soundFallbackLogged = true; _log.LogWarning((object)("DiceCup could not play its roll sound: " + ex.GetBaseException().Message)); } } } } internal static class DiceCupWorldText { private static readonly BindingFlags AnyInstance = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; private static readonly MethodInfo? AddInworldTextMethod = typeof(Chat).GetMethod("AddInworldText", AnyInstance, null, new Type[6] { typeof(GameObject), typeof(long), typeof(Vector3), typeof(Type), typeof(UserInfo), typeof(string) }, null); private static readonly FieldInfo? WorldTextsField = typeof(Chat).GetField("m_worldTexts", AnyInstance); private static readonly FieldInfo? WorldTextTtlField = typeof(Chat).GetField("m_worldTextTTL", AnyInstance); private static readonly Dictionary<long, GameObject> Anchors = new Dictionary<long, GameObject>(); private static FieldInfo? _talkerIdField; private static FieldInfo? _timerField; private static FieldInfo? _sourceObjectField; private static bool _displayWarningLogged; private static bool _timingWarningLogged; internal static void Show(GameObject cup, string speaker, string text) { //IL_0085: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)Chat.instance == (Object)null || AddInworldTextMethod == null) { return; } Transform val = cup.transform.Find("DiceCupSpeechAnchor"); GameObject val2 = (GameObject)(((Object)(object)val != (Object)null) ? ((object)((Component)val).gameObject) : ((object)cup)); UserInfo localUser = UserInfo.GetLocalUser(); localUser.Name = speaker; long num = ((Object)val2).GetInstanceID(); Anchors[num] = val2; try { AddInworldTextMethod.Invoke(Chat.instance, new object[6] { val2, num, val2.transform.position, (object)(Type)1, localUser, text }); } catch (Exception ex) { if (!_displayWarningLogged) { _displayWarningLogged = true; DiceCupPlugin.Log.LogWarning((object)("DiceCup could not display world text: " + ex.GetBaseException().Message)); } } } internal static void AdjustTimers(Chat chat, float dt) { if (dt <= 0f || Anchors.Count == 0 || WorldTextsField == null || WorldTextTtlField == null) { return; } float num = Mathf.Max(0f, DiceCupConfig.WorldTextDurationSeconds.Value); if (num <= 0f) { Anchors.Clear(); return; } try { if (!(WorldTextTtlField.GetValue(chat) is float num2) || num2 <= 0.001f || !(WorldTextsField.GetValue(chat) is IEnumerable enumerable)) { return; } HashSet<long> hashSet = new HashSet<long>(); foreach (object item in enumerable) { if (item == null) { continue; } Type type = item.GetType(); if ((object)_talkerIdField == null) { _talkerIdField = type.GetField("m_talkerID", AnyInstance); } if ((object)_timerField == null) { _timerField = type.GetField("m_timer", AnyInstance); } if ((object)_sourceObjectField == null) { _sourceObjectField = type.GetField("m_go", AnyInstance); } if (_talkerIdField == null || _timerField == null || _sourceObjectField == null) { LogTimingWarningOnce("required WorldTextInstance fields are unavailable"); return; } if (_talkerIdField.GetValue(item) is long num3 && Anchors.TryGetValue(num3, out GameObject value)) { hashSet.Add(num3); if (!((Object)(object)value == (Object)null) && _sourceObjectField.GetValue(item) == value && _timerField.GetValue(item) is float num4) { float num5 = num2 / Mathf.Max(0.05f, num); _timerField.SetValue(item, num4 + dt * (num5 - 1f)); } } } RemoveStaleAnchors(hashSet); } catch (Exception ex) { LogTimingWarningOnce(ex.GetBaseException().Message); } } private static void RemoveStaleAnchors(HashSet<long> activeIds) { if (activeIds.Count >= Anchors.Count) { return; } List<long> list = new List<long>(); foreach (KeyValuePair<long, GameObject> anchor in Anchors) { if ((Object)(object)anchor.Value == (Object)null || !activeIds.Contains(anchor.Key)) { list.Add(anchor.Key); } } foreach (long item in list) { Anchors.Remove(item); } } private static void LogTimingWarningOnce(string reason) { if (!_timingWarningLogged) { _timingWarningLogged = true; DiceCupPlugin.Log.LogWarning((object)("DiceCup could not apply custom world-text duration; Valheim's normal duration will be used. " + reason)); } } } public sealed class DiceCupUnlockTracker : MonoBehaviour { private const float CheckInterval = 0.5f; private static readonly BindingFlags AnyInstance = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; private static readonly MethodInfo? UpdateKnownRecipesMethod = typeof(Player).GetMethod("UpdateKnownRecipesList", AnyInstance, null, Type.EmptyTypes, null); private static readonly MethodInfo? UpdateAvailablePiecesMethod = typeof(Player).GetMethod("UpdateAvailablePiecesList", AnyInstance, null, Type.EmptyTypes, null); private static readonly FieldInfo? KnownMaterialField = typeof(Player).GetField("m_knownMaterial", AnyInstance); private static readonly FieldInfo? KnownStationsField = typeof(Player).GetField("m_knownStations", AnyInstance); private ManualLogSource _log; private Player? _trackedPlayer; private int _lastMaterialCount = -1; private int _lastStationCount = -1; private float _nextCheckAt; private bool _refreshRunning; private bool _reflectionWarningLogged; internal void Initialize(ManualLogSource log) { _log = log; } internal void RequestRefresh(string reason) { Player localPlayer = Player.m_localPlayer; if (!((Object)(object)localPlayer == (Object)null) && !_refreshRunning) { ((MonoBehaviour)this).StartCoroutine(RefreshRoutine(localPlayer, reason)); } } private void Update() { if (Time.unscaledTime < _nextCheckAt) { return; } _nextCheckAt = Time.unscaledTime + 0.5f; Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { ResetTracking(); return; } int collectionCount = GetCollectionCount(KnownMaterialField, localPlayer); int collectionCount2 = GetCollectionCount(KnownStationsField, localPlayer); bool flag = localPlayer != _trackedPlayer; bool flag2 = collectionCount != _lastMaterialCount || collectionCount2 != _lastStationCount; if (flag || flag2) { _trackedPlayer = localPlayer; _lastMaterialCount = collectionCount; _lastStationCount = collectionCount2; RequestRefresh(flag ? "local player initialized" : "known materials/stations changed"); } } private IEnumerator RefreshRoutine(Player player, string reason) { _refreshRunning = true; yield return null; bool invoked = InvokeRefreshMethods(player); yield return null; invoked |= InvokeRefreshMethods(player); _log.LogDebug((object)$"DiceCup unlock refresh ({reason}): refreshInvoked={invoked}."); _refreshRunning = false; } private bool InvokeRefreshMethods(Player player) { if (player != Player.m_localPlayer) { return false; } bool flag = false; try { if (UpdateKnownRecipesMethod != null) { UpdateKnownRecipesMethod.Invoke(player, null); flag = true; } if (UpdateAvailablePiecesMethod != null) { UpdateAvailablePiecesMethod.Invoke(player, null); flag = true; } } catch (Exception ex) { LogReflectionWarningOnce("Could not refresh the local player's known/buildable piece lists: " + ex.GetBaseException().Message); } if (!flag) { LogReflectionWarningOnce("Could not find Player.UpdateKnownRecipesList() or Player.UpdateAvailablePiecesList()."); } return flag; } private void LogReflectionWarningOnce(string message) { if (!_reflectionWarningLogged) { _reflectionWarningLogged = true; _log.LogWarning((object)("DiceCup " + message)); } } private static int GetCollectionCount(FieldInfo? field, object owner) { if (field == null) { return -1; } try { object value = field.GetValue(owner); if (value == null) { return -1; } return (value.GetType().GetProperty("Count", AnyInstance)?.GetValue(value, null) is int num) ? num : (-1); } catch { return -1; } } private void ResetTracking() { _trackedPlayer = null; _lastMaterialCount = -1; _lastStationCount = -1; _refreshRunning = false; } } }