Decompiled source of PeakCustomItemMod v1.10.30
BepInEx/plugins/createitem/PeakCustomItemMod.dll
Decompiled a week ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security.Cryptography; using System.Text; using BepInEx; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using Newtonsoft.Json; using PEAKLib.Core; using PEAKLib.Items; using Peak.Afflictions; using PeakCustomItemMod.Items; using Photon.Pun; using UnityEngine; using UnityEngine.InputSystem; using UnityEngine.Rendering; using Zorro.Core; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("PeakCustomItemMod")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("PeakCustomItemMod")] [assembly: AssemblyTitle("PeakCustomItemMod")] [assembly: AssemblyVersion("1.0.0.0")] [module: RefSafetyRules(11)] 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; } } [CompilerGenerated] [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 PeakCustomItemMod { internal static class ChineseDisplayNameIntegration { private static bool _patched; public static void Apply(ManualLogSource log) { try { if (!TryApply(log)) { StartRetryer(log); log.LogInfo((object)"[中文物品名] PEAK_MENU_CN 尚未就绪,已启动延时重试挂载"); } } catch (Exception ex) { log.LogWarning((object)("[中文物品名] 挂载流程异常(不影响其它功能): " + ex.Message)); } } internal static bool TryApply(ManualLogSource log) { //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Expected O, but got Unknown //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Expected O, but got Unknown if (_patched) { return true; } try { Type type = AccessTools.TypeByName("P.E.A.K_MENU.Features.ItemSpawn.ItemCatalogService"); if (type == null) { return false; } MethodInfo methodInfo = AccessTools.Method(type, "ResolveDisplayName", new Type[1] { typeof(Item) }, (Type[])null); if (methodInfo == null) { log.LogWarning((object)"[中文物品名] 未找到 ResolveDisplayName(Item),跳过"); return false; } Harmony val = new Harmony("Mr.PeakCustomItems.ChineseDisplayName"); HarmonyMethod val2 = new HarmonyMethod(typeof(ResolveDisplayNamePatch).GetMethod("Prefix")); val.Patch((MethodBase)methodInfo, val2, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); _patched = true; ForceRefreshCatalog(log); log.LogInfo((object)"[中文物品名] 已挂载:PEAK_MENU_CN 物品列表将优先显示中文"); return true; } catch (Exception ex) { log.LogWarning((object)("[中文物品名] 单次挂载尝试失败(将重试): " + ex.Message)); return false; } } private static void StartRetryer(ManualLogSource log) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Expected O, but got Unknown try { GameObject val = new GameObject("ChinesePatchRetryer"); Object.DontDestroyOnLoad((Object)(object)val); ChinesePatchRetryer chinesePatchRetryer = val.AddComponent<ChinesePatchRetryer>(); chinesePatchRetryer.Init(log); } catch (Exception ex) { log.LogWarning((object)("[中文物品名] 启动重试器失败(将放弃中文补丁): " + ex.Message)); } } private static void ForceRefreshCatalog(ManualLogSource log) { try { Type type = AccessTools.TypeByName("P.E.A.K_MENU.Features.ItemSpawn.ItemSpawnRuntime"); if (type == null) { return; } PropertyInfo propertyInfo = AccessTools.Property(type, "Catalog"); if (propertyInfo == null || propertyInfo.GetGetMethod(nonPublic: true) == null) { return; } object value = propertyInfo.GetValue(null); if (value != null) { MethodInfo methodInfo = AccessTools.Method(value.GetType(), "ForceRefresh", (Type[])null, (Type[])null); if (!(methodInfo == null)) { methodInfo.Invoke(value, null); log.LogInfo((object)"[中文物品名] 已强制刷新物品目录"); } } } catch (Exception ex) { log.LogWarning((object)("[中文物品名] 强制刷新目录失败(可忽略): " + ex.Message)); } } internal static void ForceRefreshOnce(ManualLogSource log) { ForceRefreshCatalog(log); } } internal class ChinesePatchRetryer : MonoBehaviour { private ManualLogSource _log; private int _attempts; private const int MaxAttempts = 60; public void Init(ManualLogSource log) { _log = log; } private IEnumerator Start() { while (_attempts < 60) { _attempts++; if (ChineseDisplayNameIntegration.TryApply(_log)) { for (int i = 0; i < 10; i++) { ChineseDisplayNameIntegration.ForceRefreshOnce(_log); yield return (object)new WaitForSeconds(0.5f); } Object.Destroy((Object)(object)((Component)this).gameObject); yield break; } yield return (object)new WaitForSeconds(0.5f); } _log.LogWarning((object)"[中文物品名] 多次重试仍未找到 PEAK_MENU_CN,放弃中文补丁(不影响其它功能)"); Object.Destroy((Object)(object)((Component)this).gameObject); } } internal static class ResolveDisplayNamePatch { public static bool Prefix(Item item, ref string __result) { try { if ((Object)(object)item != (Object)null) { string name = ((Object)item).name; if (!string.IsNullOrEmpty(name) && ChineseNameMap.Map.TryGetValue(name, out string value)) { __result = value; return false; } string name2 = item.GetName(); if (!string.IsNullOrEmpty(name2) && !name2.StartsWith("LOC:", StringComparison.OrdinalIgnoreCase)) { __result = name2; return false; } } } catch (Exception ex) { ManualLogSource log = CustomItemsPlugin.Log; if (log != null) { log.LogWarning((object)("[中文物品名] 解析物品名异常: " + ex.Message)); } } return true; } } internal static class ChineseNameMap { public static readonly Dictionary<string, string> Map = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase) { { "AK", "AK 突击步枪" }, { "Apple Berry Weird", "怪味苹果莓" }, { "ClimbingChalk", "攀岩粉" }, { "Cure-Some", "缓和药剂" }, { "Darkberry", "暗莓" }, { "Energy Elixir", "能量精油" }, { "Lollipop_Evil", "邪糖果" }, { "Matchbook", "火柴盒" }, { "Painkillers", "止痛药" }, { "Skyberry", "天空莓" }, { "Wand of Wind", "风之杖" }, { "Warpsketball", "传送篮球" }, { "Wonderberry", "奇幻莓" }, { "WildDogMilk", "野生狗奶" } }; } [BepInPlugin("Mr.PeakCustomItems", "刘泽铭的奇思妙想", "1.10.30")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] public class CustomItemsPlugin : BaseUnityPlugin { private ItemConfig _config = new ItemConfig(); private bool _registered; private bool _spawned; private float _nextCheck = 2f; internal static ManualLogSource Log { get; private set; } = null; public static ModDefinition Definition { get; private set; } = null; public static string PluginDirectory { get; private set; } = ""; private void Awake() { //IL_012c: Unknown result type (might be due to invalid IL or missing references) //IL_0132: Expected O, but got Unknown //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; Definition = ModDefinition.GetOrCreate(((BaseUnityPlugin)this).Info.Metadata); PluginDirectory = Path.GetDirectoryName(typeof(CustomItemsPlugin).Assembly.Location) ?? Paths.PluginPath; _config = ItemConfigLoader.LoadAll(PluginDirectory); if (_config.items.Length == 0) { Log.LogWarning((object)"没有找到任何物品配置,已生成示例物品(野生狗奶)"); ItemConfigLoader.WriteExampleFolder(Path.Combine(PluginDirectory, "WildDogMilk")); _config = ItemConfigLoader.LoadAll(PluginDirectory); } ManualLogSource log = Log; string pluginDirectory = PluginDirectory; ItemConfigEntry[] items = _config.items; log.LogInfo((object)$"刘泽铭的奇思妙想 已加载(DLL: {pluginDirectory},配置条目数: {((items != null) ? items.Length : 0)})"); try { GameObject val = new GameObject("PeakCustomItemEditor"); val.AddComponent<ItemEditorUI>(); Object.DontDestroyOnLoad((Object)(object)val); Log.LogInfo((object)"已加载游戏内物品编辑器(按 F11 开关)"); } catch (Exception ex) { Log.LogWarning((object)("游戏内编辑器初始化失败(不影响其他功能): " + ex.Message)); } try { GameObject val2 = new GameObject("PetrifyBombManager"); val2.AddComponent<PetrifyBombManager>(); Object.DontDestroyOnLoad((Object)(object)val2); } catch (Exception ex2) { Log.LogWarning((object)("石化炸弹管理器初始化失败: " + ex2.Message)); } try { ChineseDisplayNameIntegration.Apply(Log); } catch (Exception ex3) { Log.LogWarning((object)("中文物品名显示集成失败(不影响其它功能): " + ex3.Message)); } } private void Update() { if (Time.unscaledTime < _nextCheck) { return; } _nextCheck = Time.unscaledTime + 2f; if (!_registered) { try { TryRegisterItems(); return; } catch (Exception arg) { Log.LogError((object)$"注册物品失败: {arg}"); return; } } if (!_spawned) { TrySpawnCustomItems(); } } private void TryRegisterItems() { if (_registered) { return; } ItemDatabase instance = SingletonAsset<ItemDatabase>.Instance; if ((Object)(object)instance == (Object)null || ((DatabaseAsset<ItemDatabase, Item>)(object)instance).Objects == null || ((DatabaseAsset<ItemDatabase, Item>)(object)instance).Objects.Count == 0) { Log.LogInfo((object)"ItemDatabase 尚未就绪,等待..."); return; } int num = ConfigItemRegistry.RegisterFromConfig(_config, Definition); _registered = num > 0; Log.LogInfo((object)$"配置驱动注册完成:成功 {num} 个道具"); if (num <= 0) { return; } foreach (ItemConfigEntry registeredEntry in ConfigItemRegistry.RegisteredEntries) { bool flag = string.IsNullOrWhiteSpace(registeredEntry.texture) && string.IsNullOrWhiteSpace(registeredEntry.icon); if (registeredEntry.dumpTemplateTexture || flag) { ((MonoBehaviour)this).StartCoroutine(DumpTemplateDelayed(registeredEntry)); } } } private void TrySpawnCustomItems() { if (PhotonNetwork.IsConnected && !PhotonNetwork.IsMasterClient) { Log.LogInfo((object)"联机且非房主,不生成(等房主同步)"); _spawned = true; return; } Character localCharacter = Character.localCharacter; if ((Object)(object)localCharacter == (Object)null) { Log.LogInfo((object)"本地角色尚未出生,等待..."); } else { SpawnCustomItems(localCharacter); } } private void SpawnCustomItems(Character player) { //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_008a: 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_0094: 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_00a3: 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_01bf: 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_01d1: Unknown result type (might be due to invalid IL or missing references) //IL_01d6: Unknown result type (might be due to invalid IL or missing references) List<ItemConfigEntry> registeredEntries = ConfigItemRegistry.RegisteredEntries; int num = 0; foreach (ItemConfigEntry item in registeredEntries) { if (item.spawn) { num++; } } if (num == 0) { Log.LogInfo((object)"配置中没有需要生成的道具"); _spawned = true; return; } Vector3 val = ((Component)player).transform.position + ((Component)player).transform.forward * 2f + Vector3.up * 0.5f; int num2 = 0; foreach (ItemConfigEntry item2 in registeredEntries) { if (!item2.spawn) { continue; } float num3 = item2.spawnChance ?? 100f; if (num3 <= 0f) { continue; } if (num3 < 100f && Random.Range(0f, 100f) > num3) { Log.LogInfo((object)$"{item2.name}: 未触发生成(概率 {num3:0.#}%)"); continue; } string text = item2.runtimePrefabId; if (string.IsNullOrEmpty(text)) { text = "0_Items/" + item2.name; } if (!NetworkPrefabManager.HasNetworkPrefab(text)) { Log.LogWarning((object)("网络预制体不存在: " + text + ",跳过生成")); continue; } float num4 = ((float)num2 - (float)(num - 1) / 2f) * 1.1f; NetworkPrefabManager.SpawnNetworkPrefab(text, val + new Vector3(num4, 0f, 0f), Quaternion.identity, (byte)0, (object[])null); num2++; } _spawned = true; Log.LogInfo((object)$"已在玩家面前生成 {num2} 个自定义道具"); } private IEnumerator DumpTemplateDelayed(ItemConfigEntry entry) { if ((Object)(object)entry.templateGo == (Object)null) { Log.LogWarning((object)(entry.name + ": dumpTemplateTexture 模板引用为空,跳过")); yield break; } Texture2D src = null; Texture2D iconSrc = null; GameObject go = Object.Instantiate<GameObject>(entry.templateGo); if ((Object)(object)go != (Object)null) { go.SetActive(true); Log.LogInfo((object)(entry.name + ": dumpTemplateTexture 已实例化模板(" + entry.templateValue + "),轮询等待流式贴图加载...")); Item tmplItem = go.GetComponent<Item>(); for (int i = 0; i < 10; i++) { if (!((Object)(object)src == (Object)null) && !((Object)(object)iconSrc == (Object)null)) { break; } yield return (object)new WaitForSeconds(1f); if ((Object)(object)src == (Object)null) { src = ConfigItemRegistry.GrabTemplateTexture(tmplItem); } if ((Object)(object)iconSrc == (Object)null) { iconSrc = ConfigItemRegistry.GrabTemplateIcon(tmplItem); } } if ((Object)(object)src == (Object)null) { Log.LogWarning((object)(entry.name + ": dumpTemplateTexture 实例化克隆未抓到 3D 贴图")); ConfigItemRegistry.LogTextureDiag(tmplItem, entry.name); } else { Log.LogInfo((object)$"{entry.name}: dumpTemplateTexture 从实例化克隆抓到 3D 贴图 {((Texture)src).width}x{((Texture)src).height}"); } if ((Object)(object)iconSrc != (Object)null) { Log.LogInfo((object)$"{entry.name}: dumpTemplateTexture 从实例化克隆抓到物品栏图标 {((Texture)iconSrc).width}x{((Texture)iconSrc).height}"); } else { Log.LogWarning((object)(entry.name + ": dumpTemplateTexture 实例化克隆未抓到物品栏图标(UIData.icon 为空或尚未加载)")); } Object.Destroy((Object)(object)go); } if ((Object)(object)src == (Object)null || (Object)(object)iconSrc == (Object)null) { Log.LogInfo((object)(entry.name + ": dumpTemplateTexture 改从世界里的真实" + entry.templateValue + "抓取(请用菜单生成一个" + entry.templateValue + ",或等待其自然生成)")); for (int j = 0; j < 8; j++) { Item live = FindLiveTemplateItem(entry); if ((Object)(object)live != (Object)null) { if ((Object)(object)src == (Object)null) { src = ConfigItemRegistry.GrabTemplateTexture(live); if ((Object)(object)src != (Object)null) { Log.LogInfo((object)$"{entry.name}: dumpTemplateTexture 从世界生成物抓到 3D 贴图 {((Texture)src).width}x{((Texture)src).height}"); } } if ((Object)(object)iconSrc == (Object)null) { iconSrc = ConfigItemRegistry.GrabTemplateIcon(live); if ((Object)(object)iconSrc != (Object)null) { Log.LogInfo((object)$"{entry.name}: dumpTemplateTexture 从世界生成物抓到物品栏图标 {((Texture)iconSrc).width}x{((Texture)iconSrc).height}"); } } if ((Object)(object)src != (Object)null && (Object)(object)iconSrc != (Object)null) { break; } } yield return (object)new WaitForSeconds(1f); } if ((Object)(object)src == (Object)null) { ConfigItemRegistry.LogTextureDiag(FindLiveTemplateItem(entry), entry.name); } } entry.templateTexture = src; entry.templateIconTex = iconSrc; if (entry.dumpTemplateTexture && (Object)(object)src == (Object)null && (Object)(object)iconSrc != (Object)null) { Log.LogInfo((object)(entry.name + ": 3D 贴图抓取失败(模板可能是纯色/程序化材质),用物品栏图标代替导出为模板源")); src = iconSrc; entry.templateTexture = iconSrc; } if (entry.dumpTemplateTexture) { if ((Object)(object)src != (Object)null) { ConfigItemRegistry.DumpTemplateTexture(src, entry, entry.configDir ?? PluginDirectory); } if ((Object)(object)iconSrc != (Object)null) { ConfigItemRegistry.DumpTemplateIcon(iconSrc, entry, entry.configDir ?? PluginDirectory); } } if ((Object)(object)src != (Object)null) { if ((Object)(object)entry.runtimeItem != (Object)null) { ConfigItemRegistry.ApplyTemplateTextureToItem(entry.runtimeItem, entry); } ApplyTemplateTextureToLiveInstances(entry); } if ((Object)(object)src == (Object)null && (Object)(object)iconSrc == (Object)null) { Log.LogWarning((object)(entry.name + ": 模板贴图抓取两种来源都没抓到" + entry.templateValue + "的原生贴图/图标(继承模式将缺 3D 贴图)")); } } private void ApplyTemplateTextureToLiveInstances(ItemConfigEntry entry) { if ((Object)(object)entry.templateTexture == (Object)null) { return; } try { Item[] array = Object.FindObjectsOfType<Item>(); Item[] array2 = array; foreach (Item val in array2) { if (!((Object)(object)val == (Object)null)) { GameObject gameObject = ((Component)val).gameObject; string text = ((gameObject != null) ? ((Object)gameObject).name : null) ?? ""; if (text.IndexOf(entry.name, StringComparison.OrdinalIgnoreCase) >= 0) { ConfigItemRegistry.ApplyTemplateTextureToItem(val, entry); } } } } catch (Exception ex) { Log.LogWarning((object)(entry.name + ": 套用模板贴图到场上实例失败: " + ex.Message)); } } private Item? FindLiveTemplateItem(ItemConfigEntry entry) { try { Item[] array = Object.FindObjectsOfType<Item>(); string text = (entry.templateValue ?? "").Trim(); string text2 = text.ToLowerInvariant(); Item[] array2 = array; foreach (Item val in array2) { if (!((Object)(object)val == (Object)null)) { string a = val.UIData?.itemName ?? ""; GameObject gameObject = ((Component)val).gameObject; string text3 = ((gameObject != null) ? ((Object)gameObject).name : null) ?? ""; if (string.Equals(a, text, StringComparison.OrdinalIgnoreCase) || string.Equals(text3, text, StringComparison.OrdinalIgnoreCase) || (text2.Contains("sports") && text3.IndexOf("sports", StringComparison.OrdinalIgnoreCase) >= 0)) { return val; } } } } catch (Exception ex) { Log.LogWarning((object)(entry.name + ": 查找世界里的" + entry.templateValue + "失败: " + ex.Message)); } return null; } } } namespace PeakCustomItemMod.Items { public class AllyBuffRpc : MonoBehaviour { private static readonly HashSet<int> _explodedViewIds = new HashSet<int>(); private const float ExplosionKnockbackMultiplier = 2f; private const float ExplosionVertKnockbackAdd = 18f; [PunRPC] public void ApplyAllyBuffs(Vector3 origin, float radius, string buffsJoined, float time) { //IL_002e: 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_0087: Unknown result type (might be due to invalid IL or missing references) try { Character localCharacter = Character.localCharacter; if ((Object)(object)localCharacter == (Object)null || localCharacter.data.dead || !(Vector3.Distance(((Component)localCharacter).transform.position, origin) <= radius)) { return; } string[] array = buffsJoined.Split(','); foreach (string text in array) { if (!string.IsNullOrWhiteSpace(text) && Enum.TryParse<AfflictionType>(text.Trim(), ignoreCase: true, out AfflictionType result)) { Affliction val = Affliction.CreateBlankAffliction(result); if (val != null) { val.totalTime = Mathf.Max(0.1f, time); localCharacter.refs.afflictions.AddAffliction(val, false); } } } } catch (Exception ex) { Debug.LogWarning((object)("[PeakCustomItem] AllyBuff RPC 处理失败: " + ex.Message)); } } public static void BroadcastExplode(Vector3 pos, int itemViewId) { //IL_0070: 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) try { GameUtils instance = GameUtils.instance; if (!((Object)(object)instance == (Object)null)) { AllyBuffRpc allyBuffRpc = ((Component)instance).gameObject.GetComponent<AllyBuffRpc>() ?? ((Component)instance).gameObject.AddComponent<AllyBuffRpc>(); if ((Object)(object)((MonoBehaviourPun)instance).photonView != (Object)null) { ((MonoBehaviourPun)instance).photonView.RPC("WildDogMilkExplode", (RpcTarget)0, new object[2] { pos, itemViewId }); } else { allyBuffRpc.ExplodeLocal(pos, itemViewId); } } } catch (Exception ex) { Debug.LogWarning((object)("[PeakCustomItem] 野生狗奶爆炸广播失败: " + ex.Message)); } } [PunRPC] public void WildDogMilkExplode(Vector3 pos, int itemViewId) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) if (itemViewId < 0 || _explodedViewIds.Add(itemViewId)) { SpawnExplosion(pos); ConsumeItem(itemViewId); } } public void ExplodeLocal(Vector3 pos, int itemViewId) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) SpawnExplosion(pos); ConsumeItem(itemViewId); } private void ConsumeItem(int itemViewId) { //IL_0074: Unknown result type (might be due to invalid IL or missing references) if (itemViewId < 0) { return; } try { PhotonView val = PhotonView.Find(itemViewId); Item val2 = ((val != null) ? ((Component)val).GetComponent<Item>() : null); if (!((Object)(object)val2 == (Object)null)) { if ((Object)(object)Character.localCharacter != (Object)null && (Object)(object)Character.localCharacter.data.currentItem == (Object)(object)val2) { Player.localPlayer.EmptySlot(Character.localCharacter.refs.items.currentSelectedSlot); } val2.ClearDataFromBackpack(); if ((Object)(object)((MonoBehaviourPun)val2).photonView != (Object)null && (((MonoBehaviourPun)val2).photonView.IsMine || PhotonNetwork.IsMasterClient)) { PhotonNetwork.Destroy(((Component)val2).gameObject); } } } catch (Exception ex) { Debug.LogWarning((object)("[PeakCustomItem] 野生狗奶消耗失败: " + ex.Message)); } } private void SpawnExplosion(Vector3 pos) { //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_004d: 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) try { GameObject nativeExplosionPrefab = ConfigItemRegistry.GetNativeExplosionPrefab(); if ((Object)(object)nativeExplosionPrefab != (Object)null) { GameObject val = Object.Instantiate<GameObject>(nativeExplosionPrefab, pos, Quaternion.identity); AmplifyAoeKnockback(val); Object.Destroy((Object)(object)val, 4f); return; } GameObject orBuildAoeExplosionPrefab = ConfigItemRegistry.GetOrBuildAoeExplosionPrefab(); if ((Object)(object)orBuildAoeExplosionPrefab != (Object)null) { GameObject val2 = Object.Instantiate<GameObject>(orBuildAoeExplosionPrefab, pos, Quaternion.identity); AmplifyAoeKnockback(val2); Object.Destroy((Object)(object)val2, 2f); } } catch (Exception ex) { Debug.LogWarning((object)("[PeakCustomItem] 爆炸实例化失败: " + ex.Message)); } } private static void AmplifyAoeKnockback(GameObject go) { if (!((Object)(object)go == (Object)null)) { AOE[] componentsInChildren = go.GetComponentsInChildren<AOE>(); foreach (AOE val in componentsInChildren) { val.knockback *= 2f; val.additionalVerticalKnockback += 18f; } } } } public static class ConfigItemRegistry { private static readonly HashSet<string> _dumpedTemplates = new HashSet<string>(); private static readonly HashSet<string> _dumpedIcons = new HashSet<string>(); private static GameObject _nativeExplosionPrefab; private static GameObject _dynamiteExplosionPrefab; private static bool _dbSearched; private static GameObject _aoeExplosionPrefab; public static List<ItemConfigEntry> RegisteredEntries { get; } = new List<ItemConfigEntry>(); public static int RegisterFromConfig(ItemConfig config, ModDefinition definition) { RegisteredEntries.Clear(); int num = 0; ItemConfigEntry[] items = config.items; foreach (ItemConfigEntry itemConfigEntry in items) { if (string.IsNullOrWhiteSpace(itemConfigEntry.name)) { CustomItemsPlugin.Log.LogWarning((object)"配置里有个条目的 name 为空,已跳过"); continue; } if (string.IsNullOrWhiteSpace(itemConfigEntry.displayName)) { itemConfigEntry.displayName = itemConfigEntry.name; } try { Item val = FindTemplate(itemConfigEntry); if ((Object)(object)val == (Object)null) { CustomItemsPlugin.Log.LogWarning((object)(itemConfigEntry.name + ": 没有找到模板 (match=" + itemConfigEntry.templateMatch + ", value=" + itemConfigEntry.templateValue + "),已跳过")); } else { RegisterClone(val, itemConfigEntry, definition); RegisteredEntries.Add(itemConfigEntry); num++; } } catch (Exception arg) { CustomItemsPlugin.Log.LogError((object)$"{itemConfigEntry.name}: 注册失败: {arg}"); } } if (num > 0 && LootData.AllSpawnWeightData != null) { LootData.PopulateLootData(); CustomItemsPlugin.Log.LogInfo((object)"已重建 LootData 世界生成概率表,自定义物品按模板稀有度/生成池参与自然生成"); VerifyNaturalSpawn(); } if (num > 0) { EnsurePeakLibPrefabPool(); } return num; } private static void EnsurePeakLibPrefabPool() { try { MethodInfo method = typeof(NetworkPrefabManager).GetMethod("Initialize", BindingFlags.Static | BindingFlags.NonPublic); if (method == null) { CustomItemsPlugin.Log.LogWarning((object)"未找到 NetworkPrefabManager.Initialize(PEAKLib 版本不兼容?),跳过网络生成池初始化"); return; } method.Invoke(null, null); CustomItemsPlugin.Log.LogInfo((object)"Photon 网络生成池已切换为 PEAKLib CustomPrefabPool,自定义物品可正常网络生成"); } catch (Exception ex) { CustomItemsPlugin.Log.LogWarning((object)("初始化 PEAKLib 网络生成池失败(不影响注册/注入/自然生成): " + ex.Message)); } } private static Item? FindTemplate(ItemConfigEntry entry) { //IL_0188: Unknown result type (might be due to invalid IL or missing references) //IL_018b: Invalid comparison between Unknown and I4 //IL_01ad: Unknown result type (might be due to invalid IL or missing references) //IL_01b2: 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_01b6: Invalid comparison between Unknown and I4 ItemDatabase instance = SingletonAsset<ItemDatabase>.Instance; if ((Object)(object)instance == (Object)null) { return null; } List<Item> list = new List<Item>(); if (instance.itemLookup != null) { list.AddRange(instance.itemLookup.Values); } if (((DatabaseAsset<ItemDatabase, Item>)(object)instance).Objects != null) { list.AddRange(((DatabaseAsset<ItemDatabase, Item>)(object)instance).Objects); } list = list.Where((Item i) => (Object)(object)i != (Object)null).Distinct().ToList(); string value = entry.templateValue?.Trim() ?? ""; switch ((entry.templateMatch ?? "").Trim().ToLowerInvariant()) { case "exact": foreach (Item item in list) { if (ItemName(item).Equals(value, StringComparison.OrdinalIgnoreCase) || ((Object)(object)((Component)item).gameObject != (Object)null && ((Object)((Component)item).gameObject).name.Equals(value, StringComparison.OrdinalIgnoreCase))) { return item; } } break; case "tag": { if (!Enum.TryParse<ItemTags>(value, ignoreCase: true, out ItemTags result) || (int)result <= 0) { break; } foreach (Item item2 in list) { if ((item2.itemTags & result) > 0) { return item2; } } break; } default: foreach (Item item3 in list) { string text = ItemName(item3); if (text.Contains(value, StringComparison.OrdinalIgnoreCase) || ((Object)(object)((Component)item3).gameObject != (Object)null && ((Object)((Component)item3).gameObject).name.Contains(value, StringComparison.OrdinalIgnoreCase))) { return item3; } } break; } return null; } private static string ItemName(Item item) { try { if (item.UIData != null && !string.IsNullOrEmpty(item.UIData.itemName)) { return item.UIData.itemName; } } catch { } return ((Object)(object)((Component)item).gameObject != (Object)null) ? ((Object)((Component)item).gameObject).name : ""; } public static Item RegisterClone(Item template, ItemConfigEntry entry, ModDefinition definition) { //IL_0175: Unknown result type (might be due to invalid IL or missing references) //IL_020c: 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_006e: Expected O, but got Unknown //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Invalid comparison between Unknown and I4 //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Invalid comparison between Unknown and I4 //IL_00f7: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: 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) GameObject val = Object.Instantiate<GameObject>(((Component)template).gameObject); ((Object)val).name = entry.name; Object.DontDestroyOnLoad((Object)(object)val); Item component = val.GetComponent<Item>(); if ((Object)(object)component == (Object)null) { Object.Destroy((Object)(object)val); throw new InvalidOperationException("模板 " + ((Object)template).name + " 上没有 Item 组件"); } if (component.UIData == null) { component.UIData = new ItemUIData(); } component.UIData.itemName = entry.displayName; RegisterNameLocalization(entry); if (entry.tags != null && entry.tags.Length != 0) { ItemTags val2 = (ItemTags)0; string[] tags = entry.tags; foreach (string value in tags) { if (Enum.TryParse<ItemTags>(value, ignoreCase: true, out ItemTags result) && (int)result > 0) { val2 |= result; } } if ((int)val2 > 0) { component.itemTags = val2; } } ApplyLook(component, template, entry); try { if ((Object)(object)((Component)component).gameObject.GetComponent<RuntimeLookApplier>() == (Object)null) { ((Component)component).gameObject.AddComponent<RuntimeLookApplier>().entry = entry; } } catch (Exception ex) { CustomItemsPlugin.Log.LogWarning((object)(entry.name + ": 运行时贴图组件挂载失败: " + ex.Message)); } ApplyActionsAndCooking(component, entry); ApplyUses(component, entry); ApplyPetrifyBomb(component, entry); new ItemContent(component).Register(definition); ApplySpawnChance(component, template, entry); entry.runtimePrefabId = "0_Items/" + ((Object)((Component)component).gameObject).name; CustomItemsPlugin.Log.LogInfo((object)(entry.name + ": 网络预制体 = " + entry.runtimePrefabId)); InjectToItemDatabase(SingletonAsset<ItemDatabase>.Instance, component, definition, entry.name); PeakMenuIntegrator.AddToVisibleItems(entry); entry.runtimeItem = component; CustomItemsPlugin.Log.LogInfo((object)$"已注册新道具: {entry.name} (显示名: {entry.displayName}, 标签: {component.itemTags}, 模板: {((Object)template).name})"); return component; } private static void InjectToItemDatabase(ItemDatabase? db, Item item, ModDefinition definition, string entryName) { if ((Object)(object)db == (Object)null || db.itemLookup == null || ((DatabaseAsset<ItemDatabase, Item>)(object)db).Objects == null) { CustomItemsPlugin.Log.LogWarning((object)(entryName + ": ItemDatabase 未就绪,跳过注入")); return; } if (db.itemLookup.ContainsValue(item) || ((DatabaseAsset<ItemDatabase, Item>)(object)db).Objects.Contains(item)) { CustomItemsPlugin.Log.LogInfo((object)(entryName + ": 已在 ItemDatabase 中,跳过注入")); return; } byte[] value = MD5.Create().ComputeHash(Encoding.UTF8.GetBytes(definition.Id + ((Object)((Component)item).gameObject).name)); ushort num = BitConverter.ToUInt16(value, 0); bool flag = db.itemLookup.ContainsKey(num); while (db.itemLookup.ContainsKey(num)) { num++; } item.itemID = num; ((DatabaseAsset<ItemDatabase, Item>)(object)db).Objects.Add(item); db.itemLookup.Add(num, item); CustomItemsPlugin.Log.LogInfo((object)(flag ? $"{entryName}: 已注入 ItemDatabase(itemID={num},与原物品冲突已顺延,当前共 {((DatabaseAsset<ItemDatabase, Item>)(object)db).Objects.Count} 个物品)" : $"{entryName}: 已注入 ItemDatabase(itemID={num},当前共 {((DatabaseAsset<ItemDatabase, Item>)(object)db).Objects.Count} 个物品)")); } private static void VerifyNaturalSpawn() { //IL_00d1: 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_01b0: 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_016b: Unknown result type (might be due to invalid IL or missing references) if (LootData.AllSpawnWeightData == null) { CustomItemsPlugin.Log.LogWarning((object)"自然生成验证:概率表尚未构建(进入一局后首次抽物品时才构建),跳过"); return; } foreach (ItemConfigEntry registeredEntry in RegisteredEntries) { Item runtimeItem = registeredEntry.runtimeItem; if ((Object)(object)runtimeItem == (Object)null) { continue; } LootData component = ((Component)runtimeItem).GetComponent<LootData>(); if ((Object)(object)component == (Object)null) { CustomItemsPlugin.Log.LogWarning((object)(registeredEntry.name + ": 无 LootData 组件 → 不参与世界自然生成(模板本身可能不进世界生成,属正常)")); continue; } List<string> list = new List<string>(); foreach (KeyValuePair<SpawnPool, Dictionary<ushort, int>> allSpawnWeightDatum in LootData.AllSpawnWeightData) { if (allSpawnWeightDatum.Value.TryGetValue(runtimeItem.itemID, out var value)) { list.Add($"{allSpawnWeightDatum.Key}(权重{value},占该池 {LootData.GetPercentageOdds(runtimeItem.itemID, allSpawnWeightDatum.Key):0.##}%)"); } } if (list.Count == 0) { CustomItemsPlugin.Log.LogWarning((object)$"{registeredEntry.name}: ❌ 未出现在任何生成池!(itemID={runtimeItem.itemID},稀有度={component.Rarity},spawnLocations={component.spawnLocations})——模板可能本身不参与世界生成"); } else { CustomItemsPlugin.Log.LogInfo((object)string.Format("{0}: ✅ 已确认进入世界生成表 (itemID={1},稀有度={2}) → {3}", registeredEntry.name, runtimeItem.itemID, component.Rarity, string.Join(";", list))); } try { bool flag = runtimeItem.IsValidToSpawn(); CustomItemsPlugin.Log.LogInfo((object)(flag ? (registeredEntry.name + ": IsValidToSpawn(当前环境)=True,可被世界生成器抽取") : (registeredEntry.name + ": IsValidToSpawn(当前环境)=False(如 banInSolo 单人局或运行设置禁用),进局后视设置而定"))); } catch (Exception ex) { CustomItemsPlugin.Log.LogWarning((object)(registeredEntry.name + ": IsValidToSpawn 判定失败(环境未就绪): " + ex.Message)); } } } private static void ApplySpawnChance(Item item, Item template, ItemConfigEntry entry) { //IL_005b: 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) if (entry.spawnChance.HasValue) { entry.spawnChance = Mathf.Clamp(entry.spawnChance.Value, 0f, 100f); return; } LootData val = ((Component)item).GetComponent<LootData>() ?? ((Component)template).GetComponent<LootData>(); if ((Object)(object)val != (Object)null && LootData.RarityWeights.TryGetValue(val.Rarity, out var value)) { entry.spawnChance = value; CustomItemsPlugin.Log.LogInfo((object)$"{entry.name}: spawnChance 未配置,沿用模板({((Object)template).name})生成概率 = {value}(稀有度 {val.Rarity})"); } else { entry.spawnChance = 100f; CustomItemsPlugin.Log.LogInfo((object)(entry.name + ": spawnChance 未配置且模板(" + ((Object)template).name + ")无 LootData,默认 100(必出)")); } } internal static void ApplyLook(Item item, Item template, ItemConfigEntry entry) { string text = (string.IsNullOrEmpty(entry.configDir) ? CustomItemsPlugin.PluginDirectory : entry.configDir); try { entry.templateGo = ((Component)template).gameObject; } catch { } if (!string.IsNullOrWhiteSpace(entry.texture) || !string.IsNullOrWhiteSpace(entry.icon)) { ApplyLookTextures(item, entry); return; } if (item.UIData != null && template.UIData != null && (Object)(object)template.UIData.icon != (Object)null) { item.UIData.icon = template.UIData.icon; } CustomItemsPlugin.Log.LogInfo((object)(entry.name + ": 贴图 = 继承模板材质 (" + ((Object)template).name + ")")); } internal static void ApplyLookTextures(Item item, ItemConfigEntry entry) { //IL_0351: Unknown result type (might be due to invalid IL or missing references) //IL_038c: Unknown result type (might be due to invalid IL or missing references) string path = (string.IsNullOrEmpty(entry.configDir) ? CustomItemsPlugin.PluginDirectory : entry.configDir); if (!string.IsNullOrWhiteSpace(entry.icon)) { string pngPath = Path.Combine(path, entry.icon); Texture2D val = TextureTools.LoadFromPng(pngPath); if ((Object)(object)val != (Object)null && item.UIData != null) { Texture2D icon = item.UIData.icon; if ((Object)(object)icon != (Object)null && ((Object)icon).name == Path.GetFileNameWithoutExtension(entry.icon)) { Object.DestroyImmediate((Object)(object)icon); } item.UIData.icon = val; } } else if (!string.IsNullOrWhiteSpace(entry.texture)) { string pngPath2 = Path.Combine(path, entry.texture); Texture2D val2 = TextureTools.LoadFromPng(pngPath2); if ((Object)(object)val2 != (Object)null && item.UIData != null) { item.UIData.icon = val2; } } if (string.IsNullOrWhiteSpace(entry.texture)) { return; } string text = Path.Combine(path, entry.texture); Texture2D val3 = TextureTools.LoadFromPng(text); if ((Object)(object)val3 == (Object)null) { CustomItemsPlugin.Log.LogWarning((object)(entry.name + ": 贴图文件不存在或无法解析 " + text + ",无法应用")); return; } Renderer[] componentsInChildren = ((Component)item).GetComponentsInChildren<Renderer>(true); string[] source = new string[10] { "_MainTex", "_BaseMap", "_BaseTexture", "_MainTexture", "MAINTEX", "ALBEDO", "_Texture1", "_Texture2", "_BaseColorMap", "_Albedo" }; int num = 0; string text2 = null; Renderer[] array = componentsInChildren; foreach (Renderer val4 in array) { if ((Object)(object)val4 == (Object)null) { continue; } Material material = val4.material; List<string> list = new List<string>(); string[] texturePropertyNames = material.GetTexturePropertyNames(); string[] array2 = texturePropertyNames; foreach (string text3 in array2) { if (source.Contains<string>(text3, StringComparer.OrdinalIgnoreCase) || (Object)(object)material.GetTexture(text3) != (Object)null) { list.Add(text3); } } if (list.Count == 0) { continue; } Texture texture = material.GetTexture(list[0]); Texture2D val5 = (Texture2D)(object)((texture is Texture2D) ? texture : null); foreach (string item2 in list) { material.SetTexture(item2, (Texture)(object)val3); } if ((Object)(object)val5 != (Object)null && (Object)(object)val5 != (Object)(object)val3 && ((Object)val5).name == Path.GetFileNameWithoutExtension(entry.texture)) { Object.DestroyImmediate((Object)(object)val5); } foreach (string item3 in list) { if (entry.textureOffset != null && entry.textureOffset.Length == 2) { material.SetTextureOffset(item3, new Vector2(entry.textureOffset[0], entry.textureOffset[1])); } if (entry.textureScale != null && entry.textureScale.Length == 2) { material.SetTextureScale(item3, new Vector2(entry.textureScale[0], entry.textureScale[1])); } } text2 = string.Join(",", list); num++; } if (num > 0) { CustomItemsPlugin.Log.LogInfo((object)$"{entry.name}: 贴图 = {text},已替换 {num} 个渲染器的 {text2}"); } else { CustomItemsPlugin.Log.LogWarning((object)$"{entry.name}: 贴图 = {text} 已加载,但没有渲染器可替换(共 {componentsInChildren.Length} 个渲染器均未命中主纹理属性)"); } } internal static Texture2D? GrabTemplateTexture(Item? item) { if ((Object)(object)item == (Object)null) { return null; } Renderer[] componentsInChildren = ((Component)item).GetComponentsInChildren<Renderer>(true); string[] array = new string[16] { "_MainTex", "_BaseMap", "_BaseTexture", "_MainTexture", "MAINTEX", "ALBEDO", "_BaseColorMap", "_AlbedoMap", "_Diffuse", "_DiffuseMap", "_ColorMap", "_MainTex_ST", "_MaskMap", "_BaseMap_ST", "_MainTex2", "_MainTex3" }; Renderer[] array2 = componentsInChildren; foreach (Renderer val in array2) { if ((Object)(object)val == (Object)null) { continue; } Material material = val.material; string[] array3 = array; foreach (string text in array3) { if (material.HasProperty(text)) { Texture texture = material.GetTexture(text); Texture2D val2 = (Texture2D)(object)((texture is Texture2D) ? texture : null); if (val2 != null && ((Texture)val2).width > 0 && ((Texture)val2).height > 0) { return val2; } } } } return null; } internal static Texture2D? GrabTemplateIcon(Item? item) { if ((Object)(object)item == (Object)null || item.UIData == null) { return null; } Texture2D icon = item.UIData.icon; if (icon != null && ((Texture)icon).width > 0 && ((Texture)icon).height > 0) { return icon; } return null; } internal static void ApplyTemplateTextureToItem(Item item, ItemConfigEntry entry) { if ((Object)(object)item == (Object)null || entry == null || (Object)(object)entry.templateTexture == (Object)null) { return; } Renderer[] componentsInChildren = ((Component)item).GetComponentsInChildren<Renderer>(true); string[] array = new string[6] { "_MainTex", "_BaseMap", "_BaseTexture", "_MainTexture", "MAINTEX", "ALBEDO" }; int num = 0; Renderer[] array2 = componentsInChildren; foreach (Renderer val in array2) { if ((Object)(object)val == (Object)null) { continue; } Material material = val.material; string text = null; string[] array3 = array; foreach (string text2 in array3) { if (material.HasProperty(text2)) { text = text2; break; } } if (text != null) { material.SetTexture(text, (Texture)(object)entry.templateTexture); num++; } } if (num > 0) { CustomItemsPlugin.Log.LogInfo((object)$"{entry.name}: 继承模式已把模板 3D 贴图套到 {num} 个渲染器"); } } internal static void LogTextureDiag(Item? item, string entryName) { if ((Object)(object)item == (Object)null) { CustomItemsPlugin.Log.LogWarning((object)(entryName + ": dumpTemplateTexture 诊断——物品为 null")); return; } Renderer[] componentsInChildren = ((Component)item).GetComponentsInChildren<Renderer>(true); string[] array = new string[6] { "_MainTex", "_BaseMap", "_BaseTexture", "_MainTexture", "MAINTEX", "ALBEDO" }; StringBuilder stringBuilder = new StringBuilder(); stringBuilder.Append($"{entryName}: dumpTemplateTexture 诊断——共 {componentsInChildren.Length} 个渲染器:"); Renderer[] array2 = componentsInChildren; foreach (Renderer val in array2) { if ((Object)(object)val == (Object)null) { continue; } Material material = val.material; List<string> list = new List<string>(); string[] array3 = array; foreach (string text in array3) { if (material.HasProperty(text)) { Texture texture = material.GetTexture(text); object obj; if (!((Object)(object)texture == (Object)null)) { Texture2D val2 = (Texture2D)(object)((texture is Texture2D) ? texture : null); obj = ((val2 != null) ? $"{((Texture)val2).width}x{((Texture)val2).height}" : ((object)texture).GetType().Name); } else { obj = "null"; } string text2 = (string)obj; list.Add(text + "=" + text2); } } string[] obj2 = new string[7] { " [", ((Object)val).name, "/", null, null, null, null }; Shader shader = material.shader; obj2[3] = ((shader != null) ? ((Object)shader).name : null); obj2[4] = ":"; obj2[5] = ((list.Count == 0) ? "无主纹理属性" : string.Join(",", list)); obj2[6] = "]"; stringBuilder.Append(string.Concat(obj2)); } CustomItemsPlugin.Log.LogWarning((object)stringBuilder.ToString()); } private static bool ReadbackToPng(Texture2D src, string outPath) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Expected O, but got Unknown //IL_0049: Unknown result type (might be due to invalid IL or missing references) int width = ((Texture)src).width; int height = ((Texture)src).height; RenderTexture temporary = RenderTexture.GetTemporary(width, height, 0, (RenderTextureFormat)0, (RenderTextureReadWrite)2); Graphics.Blit((Texture)(object)src, temporary); Texture2D val = new Texture2D(width, height, (TextureFormat)5, false); RenderTexture active = RenderTexture.active; RenderTexture.active = temporary; val.ReadPixels(new Rect(0f, 0f, (float)width, (float)height), 0, 0); val.Apply(); RenderTexture.active = active; RenderTexture.ReleaseTemporary(temporary); File.WriteAllBytes(outPath, ImageConversion.EncodeToPNG(val)); Object.Destroy((Object)(object)val); return true; } internal static void DumpTemplateTexture(Texture2D src, ItemConfigEntry entry, string dir) { if ((Object)(object)src == (Object)null || string.IsNullOrWhiteSpace(dir) || _dumpedTemplates.Contains(entry.name)) { return; } try { string text = Path.Combine(dir, entry.name + "_template_source.png"); ReadbackToPng(src, text); _dumpedTemplates.Add(entry.name); CustomItemsPlugin.Log.LogInfo((object)$"{entry.name}: 已导出模板原生贴图 -> {text} ({((Texture)src).width}x{((Texture)src).height})"); } catch (Exception ex) { CustomItemsPlugin.Log.LogWarning((object)(entry.name + ": 导出模板贴图失败: " + ex.Message)); } } internal static void DumpTemplateIcon(Texture2D src, ItemConfigEntry entry, string dir) { if ((Object)(object)src == (Object)null || string.IsNullOrWhiteSpace(dir) || _dumpedIcons.Contains(entry.name)) { return; } try { string text = Path.Combine(dir, entry.name + "_template_icon_source.png"); ReadbackToPng(src, text); _dumpedIcons.Add(entry.name); CustomItemsPlugin.Log.LogInfo((object)$"{entry.name}: 已导出模板物品栏图标 -> {text} ({((Texture)src).width}x{((Texture)src).height})"); } catch (Exception ex) { CustomItemsPlugin.Log.LogWarning((object)(entry.name + ": 导出模板物品栏图标失败: " + ex.Message)); } } public static void ApplyUvToItem(Item item, ItemConfigEntry entry) { //IL_0036: 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_004d: 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_0082: Unknown result type (might be due to invalid IL or missing references) //IL_007d: 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_011c: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)item == (Object)null || string.IsNullOrWhiteSpace(entry.texture)) { return; } Vector2 val = (Vector2)((entry.textureOffset != null && entry.textureOffset.Length == 2) ? new Vector2(entry.textureOffset[0], entry.textureOffset[1]) : Vector2.zero); Vector2 val2 = (Vector2)((entry.textureScale != null && entry.textureScale.Length == 2) ? new Vector2(entry.textureScale[0], entry.textureScale[1]) : Vector2.one); string[] array = new string[6] { "_MainTex", "_BaseMap", "_BaseTexture", "_MainTexture", "MAINTEX", "ALBEDO" }; Renderer[] componentsInChildren = ((Component)item).GetComponentsInChildren<Renderer>(true); Renderer[] array2 = componentsInChildren; foreach (Renderer val3 in array2) { if ((Object)(object)val3 == (Object)null) { continue; } Material material = val3.material; string[] array3 = array; foreach (string text in array3) { if (material.HasProperty(text)) { material.SetTextureOffset(text, val); material.SetTextureScale(text, val2); break; } } } } private static void RegisterNameLocalization(ItemConfigEntry entry) { try { string text = (string.IsNullOrEmpty(entry.displayName) ? entry.name : entry.displayName); if (string.IsNullOrEmpty(text)) { return; } Dictionary<string, List<string>> mainTable = LocalizedText.mainTable; string key = "NAME_" + text.ToUpperInvariant(); if (!mainTable.ContainsKey(key)) { int num = 15; List<string> list = new List<string>(num); for (int i = 0; i < num; i++) { list.Add(text); } mainTable[key] = list; mainTable["DESC_" + text.ToUpperInvariant()] = list; CustomItemsPlugin.Log.LogInfo((object)(entry.name + ": 已注册名称本地化 '" + text + "'(NAME_/DESC_ key),UI 不再显示 LOC: 前缀")); } } catch (Exception ex) { CustomItemsPlugin.Log.LogWarning((object)(entry.name + ": 名称本地化注入失败(不影响注册): " + ex.Message)); } } public static void ApplyActionsAndCooking(Item item, ItemConfigEntry entry) { try { ItemCooking val = ((Component)item).GetComponent<ItemCooking>(); List<string> removeBeh = new List<string>(); if (entry.removeCookingBehaviors != null) { removeBeh.AddRange(entry.removeCookingBehaviors); } if (entry.cooking?.removeBehaviors != null) { removeBeh.AddRange(entry.cooking.removeBehaviors); } removeBeh = removeBeh.Where((string s) => !string.IsNullOrWhiteSpace(s)).ToList(); if (removeBeh.Count > 0) { if ((Object)(object)val == (Object)null) { CustomItemsPlugin.Log.LogWarning((object)(entry.name + ": 配置要移除烹饪行为,但模板没有 ItemCooking 组件,跳过")); } else { AdditionalCookingBehavior[] array = val.additionalCookingBehaviors.Where((AdditionalCookingBehavior b) => b != null && !removeBeh.Contains<string>(((object)b).GetType().Name, StringComparer.OrdinalIgnoreCase)).ToArray(); int num = val.additionalCookingBehaviors.Length - array.Length; if (num > 0) { val.additionalCookingBehaviors = array; CustomItemsPlugin.Log.LogInfo((object)string.Format("{0}: 已移除 {1} 个烹饪行为: {2}", entry.name, num, string.Join(",", removeBeh))); } } } if (entry.removeActions != null && entry.removeActions.Length != 0) { List<string> want = entry.removeActions.Where((string s) => !string.IsNullOrWhiteSpace(s)).ToList(); if (want.Count > 0) { List<ItemAction> list = (from a in ((Component)item).GetComponents<ItemAction>() where (Object)(object)a != (Object)null && want.Contains<string>(((object)a).GetType().Name, StringComparer.OrdinalIgnoreCase) select a).ToList(); foreach (ItemAction item3 in list) { Object.Destroy((Object)(object)item3); } if (list.Count > 0) { CustomItemsPlugin.Log.LogInfo((object)string.Format("{0}: 已移除 {1} 个食用动作: {2}", entry.name, list.Count, string.Join(",", list.Select((ItemAction d) => ((object)d).GetType().Name)))); } } } if (entry.addActions != null && entry.addActions.Length != 0) { int num2 = 0; HashSet<string> hashSet = (from a in ((Component)item).GetComponents<ItemAction>() where (Object)(object)a != (Object)null select a).Select(ActionKey).ToHashSet<string>(StringComparer.OrdinalIgnoreCase); ActionSpec[] addActions = entry.addActions; foreach (ActionSpec actionSpec in addActions) { if (actionSpec != null && !string.IsNullOrWhiteSpace(actionSpec.type)) { string item2 = ActionKeyFor(actionSpec); if (!hashSet.Contains(item2) && TryAddAction(((Component)item).gameObject, actionSpec)) { num2++; hashSet.Add(item2); } } } if (num2 > 0) { CustomItemsPlugin.Log.LogInfo((object)$"{entry.name}: 已添加 {num2} 个食用动作"); } } if (entry.cooking == null) { return; } if ((Object)(object)val == (Object)null) { val = ((Component)item).gameObject.AddComponent<ItemCooking>(); CustomItemsPlugin.Log.LogInfo((object)(entry.name + ": 模板无 ItemCooking,已自动补加并启用烹饪")); } try { FieldInfo field = ((object)val).GetType().GetField("disableCooking", BindingFlags.Instance | BindingFlags.NonPublic); if (field != null && field.FieldType == typeof(bool) && (bool)field.GetValue(val)) { field.SetValue(val, false); } } catch { } if (entry.cooking.ignoreDefaultCook) { val.ignoreDefaultCookBehavior = true; CustomItemsPlugin.Log.LogInfo((object)(entry.name + ": 已关闭默认烹饪逻辑(只保留配置的行为)")); } if (entry.cooking.wreckWhenCooked) { val.wreckWhenCooked = true; CustomItemsPlugin.Log.LogInfo((object)(entry.name + ": 烹饪即毁坏物品(wreckWhenCooked)")); } if (entry.cooking.addBehaviors == null || entry.cooking.addBehaviors.Length == 0) { return; } List<AdditionalCookingBehavior> list2 = new List<AdditionalCookingBehavior>(); CookingBehaviorSpec[] addBehaviors = entry.cooking.addBehaviors; foreach (CookingBehaviorSpec cookingBehaviorSpec in addBehaviors) { if (cookingBehaviorSpec != null && !string.IsNullOrWhiteSpace(cookingBehaviorSpec.type)) { AdditionalCookingBehavior val2 = BuildCookingBehavior(item, cookingBehaviorSpec); if (val2 != null) { val2.cookedAmountToTrigger = cookingBehaviorSpec.cookedAmountToTrigger; val2.onlyOnce = cookingBehaviorSpec.onlyOnce; list2.Add(val2); CustomItemsPlugin.Log.LogInfo((object)$"{entry.name}: 已添加烹饪行为 {cookingBehaviorSpec.type}(cookedAmountToTrigger={cookingBehaviorSpec.cookedAmountToTrigger}, onlyOnce={cookingBehaviorSpec.onlyOnce})"); } } } val.additionalCookingBehaviors = list2.ToArray(); } catch (Exception arg) { CustomItemsPlugin.Log.LogError((object)$"{entry.name}: 应用属性配置失败: {arg}"); } } public static void ReapplyLive(ItemConfigEntry entry) { //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Expected O, but got Unknown //IL_0083: 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_00cc: Invalid comparison between Unknown and I4 //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Invalid comparison between Unknown and I4 //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: 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_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: 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) Item runtimeItem = entry.runtimeItem; if ((Object)(object)runtimeItem == (Object)null) { CustomItemsPlugin.Log.LogWarning((object)(entry.name + ": 克隆体尚未就绪,无法实时应用(等注册完成或重启)")); return; } try { if (runtimeItem.UIData == null) { runtimeItem.UIData = new ItemUIData(); } runtimeItem.UIData.itemName = entry.displayName; RegisterNameLocalization(entry); if (entry.tags != null && entry.tags.Length != 0) { ItemTags val = (ItemTags)0; string[] tags = entry.tags; foreach (string value in tags) { if (Enum.TryParse<ItemTags>(value, ignoreCase: true, out ItemTags result) && (int)result > 0) { val |= result; } } if ((int)val > 0) { runtimeItem.itemTags = val; } } Item val2 = FindTemplate(entry); if ((Object)(object)val2 != (Object)null) { ApplyLook(runtimeItem, val2, entry); } else { CustomItemsPlugin.Log.LogWarning((object)(entry.name + ": 找不到模板,跳过贴图实时应用")); } ApplyActionsAndCooking(runtimeItem, entry); ApplyPetrifyBomb(runtimeItem, entry); CustomItemsPlugin.Log.LogInfo((object)(entry.name + ": 已实时应用配置(贴图/名称/标签/属性)")); } catch (Exception arg) { CustomItemsPlugin.Log.LogError((object)$"{entry.name}: 实时应用失败: {arg}"); } } private static bool TryAddAction(GameObject go, ActionSpec spec) { //IL_0149: 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_01cf: Unknown result type (might be due to invalid IL or missing references) try { string text = spec.type.Trim().ToLowerInvariant(); switch (text.StartsWith("action_") ? text.Substring("action_".Length) : text) { case "modifystatus": { Action_ModifyStatus val4 = go.AddComponent<Action_ModifyStatus>(); val4.statusType = ParseEnum<STATUSTYPE>(spec.statusType, (STATUSTYPE)8); val4.changeAmount = spec.changeAmount; val4.ifSkeleton = spec.ifSkeleton; SetTrigger((ItemAction)(object)val4, spec.on); return true; } case "restorehunger": { Action_RestoreHunger val5 = go.AddComponent<Action_RestoreHunger>(); val5.restorationAmount = spec.restorationAmount; SetTrigger((ItemAction)(object)val5, spec.on); return true; } case "applyaffliction": { Action_ApplyAffliction val3 = go.AddComponent<Action_ApplyAffliction>(); if (Enum.TryParse<AfflictionType>(spec.affliction, ignoreCase: true, out AfflictionType result)) { val3.affliction = Affliction.CreateBlankAffliction(result); if (val3.affliction != null && spec.totalTime > 0f) { val3.affliction.totalTime = spec.totalTime; } } SetTrigger((ItemAction)(object)val3, spec.on); return true; } case "giveextrastamina": { Action_GiveExtraStamina val2 = go.AddComponent<Action_GiveExtraStamina>(); val2.amount = spec.amount; SetTrigger((ItemAction)(object)val2, spec.on); return true; } case "consume": { Action_Consume action2 = go.AddComponent<Action_Consume>(); SetTrigger((ItemAction)(object)action2, spec.on); return true; } case "playanimation": { Action_PlayAnimation val = go.AddComponent<Action_PlayAnimation>(); val.animationName = spec.animationName; SetTrigger((ItemAction)(object)val, spec.on); return true; } case "die": { Action_Die action = go.AddComponent<Action_Die>(); SetTrigger((ItemAction)(object)action, spec.on); return true; } default: CustomItemsPlugin.Log.LogWarning((object)("未知食用动作类型: " + spec.type + "(可选 ModifyStatus/RestoreHunger/ApplyAffliction/GiveExtraStamina/Consume/PlayAnimation/Die)")); return false; } } catch (Exception ex) { CustomItemsPlugin.Log.LogWarning((object)("添加食用动作 " + spec.type + " 失败: " + ex.Message)); return false; } } private static void SetTrigger(ItemAction action, string on) { switch ((on ?? "").Trim().ToLowerInvariant()) { case "": break; case "pressed": action.OnPressed = true; break; case "held": action.OnHeld = true; break; case "released": action.OnReleased = true; break; case "cancelled": action.OnCancelled = true; break; case "consumed": action.OnConsumed = true; break; case "secondarypressed": action.OnSecondaryPressed = true; break; case "secondaryheld": action.OnSecondaryHeld = true; break; case "secondarycastfinished": action.OnSecondaryCastFinished = true; break; case "secondarycancelled": action.OnSecondaryCancelled = true; break; default: action.OnCastFinished = true; break; } } private static string ActionKey(ItemAction a) { //IL_0016: 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) Action_ModifyStatus val = (Action_ModifyStatus)(object)((a is Action_ModifyStatus) ? a : null); if (val != null) { return $"modifystatus|{val.statusType}"; } Action_ApplyAffliction val2 = (Action_ApplyAffliction)(object)((a is Action_ApplyAffliction) ? a : null); if (val2 != null) { Affliction affliction = val2.affliction; return $"applyaffliction|{((affliction != null) ? new AfflictionType?(affliction.GetAfflictionType()) : ((AfflictionType?)null))}"; } return ((object)a).GetType().Name; } private static string ActionKeyFor(ActionSpec s) { string text = s.type.Trim(); text = (text.StartsWith("action_", StringComparison.OrdinalIgnoreCase) ? text.Substring("action_".Length) : text); if (text.Equals("modifystatus", StringComparison.OrdinalIgnoreCase)) { return "modifystatus|" + s.statusType; } if (text.Equals("applyaffliction", StringComparison.OrdinalIgnoreCase)) { return "applyaffliction|" + s.affliction; } return "Action_" + text; } private static AdditionalCookingBehavior? BuildCookingBehavior(Item item, CookingBehaviorSpec spec) { //IL_00c7: 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_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Expected O, but got Unknown //IL_012e: Unknown result type (might be due to invalid IL or missing references) //IL_0130: 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_0195: Unknown result type (might be due to invalid IL or missing references) switch (spec.type.Trim().ToLowerInvariant()) { case "explode": { CookingBehavior_WildDogMilkExplode cookingBehavior_WildDogMilkExplode = new CookingBehavior_WildDogMilkExplode(); ((AdditionalCookingBehavior)cookingBehavior_WildDogMilkExplode).onlyOnce = true; EnsureExplosionPrefab(item, (AdditionalCookingBehavior)(object)cookingBehavior_WildDogMilkExplode); return (AdditionalCookingBehavior?)(object)cookingBehavior_WildDogMilkExplode; } case "changeafflictiontime": { Action_ApplyAffliction val = ((IEnumerable<Action_ApplyAffliction>)((Component)item).GetComponents<Action_ApplyAffliction>()).FirstOrDefault((Func<Action_ApplyAffliction, bool>)((Action_ApplyAffliction a) => (Object)(object)a != (Object)null)); if ((Object)(object)val == (Object)null) { CustomItemsPlugin.Log.LogWarning((object)"烹饪行为 ChangeAfflictionTime 需要物品上有 Action_ApplyAffliction,但当前没有,已跳过"); return null; } return (AdditionalCookingBehavior?)new CookingBehavior_ChangeAfflictionTime { action = val, change = spec.change }; } case "afflictall": { if (!Enum.TryParse<AfflictionType>(spec.affliction, ignoreCase: true, out AfflictionType result2)) { CustomItemsPlugin.Log.LogWarning((object)("烹饪行为 AfflictAll 需要合法的 affliction(如 Invincibility),当前为 '" + spec.affliction + "',已跳过")); return null; } return (AdditionalCookingBehavior?)(object)new CookingBehavior_AfflictAll { afflictionType = result2, totalTime = spec.totalTime, alsoExplode = false }; } case "afflictallandexplode": { if (!Enum.TryParse<AfflictionType>(spec.affliction, ignoreCase: true, out AfflictionType result)) { CustomItemsPlugin.Log.LogWarning((object)("烹饪行为 AfflictAllAndExplode 需要合法的 affliction,当前为 '" + spec.affliction + "',已跳过")); return null; } CookingBehavior_AfflictAll cookingBehavior_AfflictAll = new CookingBehavior_AfflictAll { afflictionType = result, totalTime = spec.totalTime, alsoExplode = true }; EnsureExplosionPrefab(item, (AdditionalCookingBehavior)(object)cookingBehavior_AfflictAll); return (AdditionalCookingBehavior?)(object)cookingBehavior_AfflictAll; } default: CustomItemsPlugin.Log.LogWarning((object)("未知烹饪行为类型: " + spec.type + "(可选 Explode/ChangeAfflictionTime/AfflictAll/AfflictAllAndExplode)")); return null; } } private static void EnsureExplosionPrefab(Item item, AdditionalCookingBehavior behavior) { try { ItemCooking component = ((Component)item).GetComponent<ItemCooking>(); if (!((Object)(object)component == (Object)null)) { component.explosionPrefab = GetOrBuildAoeExplosionPrefab(); CustomItemsPlugin.Log.LogInfo((object)(((Object)item).name + ": 已挂载自定义范围爆炸体(Injury 致死+击退+击飞,range=5)")); } } catch (Exception ex) { CustomItemsPlugin.Log.LogWarning((object)(((Object)item).name + ": 挂载爆炸体失败: " + ex.Message)); } } public static GameObject GetNativeExplosionPrefab() { if ((Object)(object)_dynamiteExplosionPrefab == (Object)null && !_dbSearched) { ItemDatabase instance = SingletonAsset<ItemDatabase>.Instance; if ((Object)(object)instance != (Object)null && instance.itemLookup != null) { _dbSearched = true; _dynamiteExplosionPrefab = ResolveDynamiteExplosionPrefab(instance); if ((Object)(object)_dynamiteExplosionPrefab != (Object)null) { CustomItemsPlugin.Log.LogInfo((object)"[爆炸] 已从 ItemDatabase 锁定 Dynamite.explosionPrefab(炸药同款)"); } else { CustomItemsPlugin.Log.LogWarning((object)"[爆炸] ItemDatabase 中未找到带 Dynamite 组件的条目,回退场景扫描"); } } } if ((Object)(object)_dynamiteExplosionPrefab != (Object)null) { _nativeExplosionPrefab = _dynamiteExplosionPrefab; return _nativeExplosionPrefab; } if ((Object)(object)_nativeExplosionPrefab != (Object)null) { return _nativeExplosionPrefab; } GameObject val = null; GameObject val2 = null; GameObject val3 = null; try { Character localCharacter = Character.localCharacter; if ((Object)(object)localCharacter?.refs?.movement?.explosionPrefab != (Object)null) { val2 = localCharacter.refs.movement.explosionPrefab; } } catch (Exception ex) { CustomItemsPlugin.Log.LogWarning((object)("[爆炸] 读本地角色 explosionPrefab 失败: " + ex.Message)); } if ((Object)(object)val2 == (Object)null) { try { if (Character.AllCharacters != null) { foreach (Character allCharacter in Character.AllCharacters) { if ((Object)(object)allCharacter?.refs?.movement?.explosionPrefab != (Object)null) { val2 = allCharacter.refs.movement.explosionPrefab; break; } } } } catch (Exception ex2) { CustomItemsPlugin.Log.LogWarning((object)("[爆炸] 扫描角色 explosionPrefab 失败: " + ex2.Message)); } } try { MonoBehaviour[] array = Object.FindObjectsOfType<MonoBehaviour>(); MonoBehaviour[] array2 = array; foreach (MonoBehaviour val4 in array2) { if ((Object)(object)val4 == (Object)null) { continue; } Type type = ((object)val4).GetType(); FieldInfo field = type.GetField("explosionPrefab", BindingFlags.Instance | BindingFlags.Public); if (!(field != null) || !(field.FieldType == typeof(GameObject))) { continue; } object? value = field.GetValue(val4); GameObject val5 = (GameObject)((value is GameObject) ? value : null); if (!((Object)(object)val5 == (Object)null)) { if ((Object)(object)val3 == (Object)null) { val3 = val5; } if ((Object)(object)val == (Object)null && (type.Name == "Dynamite" || type.FullName.EndsWith(".Dynamite", StringComparison.Ordinal))) { val = val5; } } } } catch (Exception ex3) { CustomItemsPlugin.Log.LogWarning((object)("[爆炸] 扫描场景 explosionPrefab 失败: " + ex3.Message)); } if ((Object)(object)val != (Object)null) { _nativeExplosionPrefab = val; CustomItemsPlugin.Log.LogInfo((object)"[爆炸] 已采用场上 Dynamite.explosionPrefab(炸药同款)作为原生爆炸视觉"); } else if ((Object)(object)val2 != (Object)null) { _nativeExplosionPrefab = val2; CustomItemsPlugin.Log.LogWarning((object)"[爆炸] 场上无 Dynamite,回退用 CharacterMovement.explosionPrefab(火箭引爆款)作为爆炸视觉"); } else { if (!((Object)(object)val3 != (Object)null)) { CustomItemsPlugin.Log.LogWarning((object)"[爆炸] 未取得原生 explosionPrefab,将回退到自建爆炸体"); return null; } _nativeExplosionPrefab = val3; CustomItemsPlugin.Log.LogWarning((object)"[爆炸] 场上无 Dynamite/角色移动,回退用场景任意 explosionPrefab 作为爆炸视觉"); } return _nativeExplosionPrefab; } private static GameObject ResolveDynamiteExplosionPrefab(ItemDatabase db) { try { foreach (KeyValuePair<ushort, Item> item in db.itemLookup) { Item value = item.Value; if (!((Object)(object)value == (Object)null)) { Dynamite component = ((Component)value).GetComponent<Dynamite>(); if ((Object)(object)component != (Object)null && (Object)(object)component.explosionPrefab != (Object)null) { return component.explosionPrefab; } } } } catch (Exception ex) { CustomItemsPlugin.Log.LogWarning((object)("[爆炸] 从 ItemDatabase 解析 Dynamite 失败: " + ex.Message)); } return null; } public static GameObject GetOrBuildAoeExplosionPrefab() { if ((Object)(object)_aoeExplosionPrefab == (Object)null) { _aoeExplosionPrefab = BuildAoePrefab(); } return _aoeExplosionPrefab; } private static GameObject BuildAoePrefab() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown //IL_0015: 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) GameObject val = new GameObject("WildDogMilkExplosionAOE_Fallback"); AOE val2 = val.AddComponent<AOE>(); val2.mask = (LayerType)0; val2.auto = true; val2.onEnable = false; val2.range = 5f; val2.knockback = 25f; val2.additionalVerticalKnockback = 8f; val2.fallTime = 0.5f; val2.statusType = (STATUSTYPE)0; val2.statusAmount = 1.5f; val2.minFactor = 0.2f; val2.factorPow = 1f; val2.ignoreFactor = false; val2.requireLineOfSigh = false; val2.capFallDamage = true; val2.fallDamageCap = 1f; val2.fallDamageCapTime = 5f; val2.canLaunchItems = true; val2.itemKnockbackMultiplier = 1f; val2.worksOnCarriedScout = true; val2.useSingleDirection = false; val2.addtlStatus = (STATUSTYPE[])(object)new STATUSTYPE[0]; val2.addlStatusAmountOverrides = new List<float>(); val2.illegalStatus = ""; val2.hasAffliction = false; val2.affliction = null; val.AddComponent<ExplosionFlash>(); return val; } private static T ParseEnum<T>(string? value, T fallback) where T : struct { if (!string.IsNullOrWhiteSpace(value) && Enum.TryParse<T>(value.Replace("-", "").Replace(" ", ""), ignoreCase: true, out var result)) { return result; } return fallback; } private static void ApplyPetrifyBomb(Item item, ItemConfigEntry entry) { if (entry.petrifyBomb == null) { return; } GameObject gameObject = ((Component)item).gameObject; PetrifyBombBehavior component = gameObject.GetComponent<PetrifyBombBehavior>(); PetrifyBombBehavior petrifyBombBehavior = component ?? gameObject.AddComponent<PetrifyBombBehavior>(); petrifyBombBehavior.spec = entry.petrifyBomb; petrifyBombBehavior.duration = entry.petrifyBomb.baseDuration; PetrifyBombBehavior.RegisterSpec(item, entry); if (entry.petrifyBomb.cookDurations != null && entry.petrifyBomb.cookDurations.Length != 0) { ItemCooking component2 = ((Component)item).GetComponent<ItemCooking>(); if ((Object)(object)component2 != (Object)null) { List<AdditionalCookingBehavior> list = new List<AdditionalCookingBehavior>(); if (component2.additionalCookingBehaviors != null) { list.AddRange(component2.additionalCookingBehaviors); } bool flag = false; foreach (AdditionalCookingBehavior item2 in list) { if (item2 is CookingBehavior_PetrifyBombDuration) { flag = true; break; } } if (!flag) { list.Add((AdditionalCookingBehavior)(object)new CookingBehavior_PetrifyBombDuration { sourceItem = item, baseDuration = entry.petrifyBomb.baseDuration, cookDurations = entry.petrifyBomb.cookDurations }); component2.additionalCookingBehaviors = list.ToArray(); } } else { CustomItemsPlugin.Log.LogWarning((object)(entry.name + ": 模板没有 ItemCooking,烹饪升级将不生效(但基础石化炸弹仍可用)")); } } CustomItemsPlugin.Log.LogInfo((object)string.Format("{0}: 已挂载石化炸弹(基础时长 {1}s,烹饪升级 {2})", entry.name, entry.petrifyBomb.baseDuration, string.Join("/", entry.petrifyBomb.cookDurations))); } private static void ApplyUses(Item item, ItemConfigEntry entry) { if (!entry.uses.HasValue || (Object)(object)item == (Object)null) { return; } try { OptionableIntItemData data = item.GetData<OptionableIntItemData>((DataEntryKey)2); data.HasData = true; data.Value = entry.uses.Value; if (entry.uses.Value > 0) { item.SetUseRemainingPercentage(1f); } CustomItemsPlugin.Log.LogInfo((object)$"{entry.name}: 可用次数已设为 {entry.uses.Value}"); } catch (Exception ex) { CustomItemsPlugin.Log.LogWarning((object)(entry.name + ": 设置可用次数失败: " + ex.Message)); } } } [Serializable] public class CookingBehavior_AfflictAll : AdditionalCookingBehavior { public AfflictionType afflictionType; public float totalTime; public bool alsoExplode; public bool includeBots = false; private static readonly FieldInfo? ItemCookingField = typeof(AdditionalCookingBehavior).GetField("itemCooking", BindingFlags.Instance | BindingFlags.NonPublic); protected override void TriggerBehaviour(int cookedAmount) { //IL_0139: 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_00d4: Unknown result type (might be due to invalid IL or missing references) object? obj = ItemCookingField?.GetValue(this); ItemCooking val = (ItemCooking)((obj is ItemCooking) ? obj : null); if (alsoExplode) { try { if (val != null) { val.Explode(); } } catch (Exception ex) { Debug.LogWarning((object)("[PeakCustomItem] 烹饪爆炸失败: " + ex.Message)); } } int num = 0; List<Character> allCharacters = Character.AllCharacters; if (allCharacters == null) { return; } foreach (Character item in allCharacters) { if ((Object)(object)item == (Object)null || item.refs == null || (Object)(object)item.refs.afflictions == (Object)null || (!includeBots && item.isBot)) { continue; } try { Affliction val2 = Affliction.CreateBlankAffliction(afflictionType); if (val2 != null) { if (totalTime > 0f) { val2.totalTime = totalTime; } item.refs.afflictions.AddAffliction(val2, false); num++; } } catch (Exception ex2) { Debug.LogWarning((object)$"[PeakCustomItem] 给 {((Object)item).name} 添加 {afflictionType} 失败: {ex2.Message}"); } } Debug.Log((object)($"[PeakCustomItem] 烹饪全员效果: {afflictionType}({totalTime}s) 已添加给 {num} 名角色" + (alsoExplode ? "(并已爆炸)" : ""))); } } [Serializable] public class CookingBehavior_PetrifyBombDuration : AdditionalCookingBehavior { public Item? sourceItem; public float baseDuration = 10f; public float[] cookDurations = new float[3] { 20f, 30f, 35f }; private static FieldInfo? _itemCookingField; protected override void TriggerBehaviour(int cookedAmount) { Item val = ResolveItem(); if ((Object)(object)val == (Object)null) { return; } PetrifyBombBehavior component = ((Component)val).GetComponent<PetrifyBombBehavior>(); if (!((Object)(object)component == (Object)null)) { float num = baseDuration; int num2 = cookedAmount - 1; if (num2 >= 0 && num2 < cookDurations.Length) { num = cookDurations[num2]; } else if (cookDurations.Length != 0) { num = cookDurations[cookDurations.Length - 1]; } component.duration = num; CustomItemsPlugin.Log.LogInfo((object)$"[PeakCustomItem] 石化炸弹烹饪升级:cookedAmount={cookedAmount} → 时长 {num}s"); } } private Item? ResolveItem() { if ((Object)(object)sourceItem != (Object)null) { return sourceItem; } try { if ((object)_itemCookingField == null) { _itemCookingField = typeof(AdditionalCookingBehavior).GetField("itemCooking", BindingFlags.Instance | BindingFlags.NonPublic); } object? obj = _itemCookingField?.GetValue(this); return ((ItemComponent)(((obj is ItemCooking) ? obj : null)?)).item; } catch { return null; } } } public class CookingBehavior_WildDogMilkExplode : AdditionalCookingBehavior { protected override void TriggerBehaviour(int cookedAmount) { //IL_005c: 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_00d0: Unknown result type (might be due to invalid IL or missing references) try { object? obj = typeof(AdditionalCookingBehavior).GetField("itemCooking", BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(this); ItemCooking val = (ItemCooking)((obj is ItemCooking) ? obj : null); if (!((Object)(object)val == (Object)null) && !((Object)(object)((ItemComponent)val).item == (Object)null)) { Item item = ((ItemComponent)val).item; Vector3 position = ((Component)val).transform.position; int itemViewId = (((Object)(object)((MonoBehaviourPun)item).photonView != (Object)null) ? ((MonoBehaviourPun)item).photonView.ViewID : (-1)); bool flag = (Object)(object)Character.localCharacter != (Object)null && (Object)(object)Character.localCharacter.data.currentItem == (Object)(object)item; bool flag2 = (Object)(object)((MonoBehaviourPun)item).photonView != (Object)null && ((MonoBehaviourPun)item).photonView.AmController; if (flag || flag2) { AllyBuffRpc.BroadcastExplode(position, itemViewId); } } } catch (Exception ex) { Debug.LogWarning((object)("[PeakCustomItem] 野生狗奶爆炸触发失败: " + ex.Message)); } } } public class ExplosionFlash : MonoBehaviour { public float duration = 0.55f; public float maxRadius = 5f; public Color color = new Color(1f, 0.55f, 0.15f, 0.7f); private float _t; private Transform _sphere; private MeshRenderer _r; private Light _light; private void Start() { //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Expected O, but got Unknown //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) GameObject val = GameObject.CreatePrimitive((PrimitiveType)0); Object.Destroy((Object)(object)val.GetComponent<Collider>()); val.transform.SetParent(((Component)this).transform, false); _sphere = val.transform; _r = val.GetComponent<MeshRenderer>(); try { Material val2 = new Material(Shader.Find("Sprites/Default")); val2.color = color; val2.SetInt("_Cull", 0); ((Renderer)_r).material = val2; } catch { } _light = val.AddComponent<Light>(); _light.type = (LightType)2; _light.color = new Color(1f, 0.6f, 0.3f); _light.range = maxRadius * 1.6f; _light.intensity = 7f; } private void Update() { //IL_0066: 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_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) _t += Time.deltaTime; float num = Mathf.Clamp01(_t / duration); if ((Object)(object)_r != (Object)null && (Object)(object)_sphere != (Object)null) { float num2 = Mathf.Lerp(0.6f, maxRadius * 2f, num); _sphere.localScale = Vector3.one * num2; Color val = ((Renderer)_r).material.color; val.a = color.a * (1f - num); ((Renderer)_r).material.color = val; } if ((Object)(object)_light != (Object)null) { _light.intensity = 7f * (1f - num); } if (_t >= duration) { Object.Destroy((Object)(object)((Component)this).gameObject); } } } [Serializable] public class ItemConfigEntry { public string name = ""; public string displayName = ""; public string templateMatch = "contains"; public string templateValue = "milk"; public string[] tags = Array.Empty<string>(); public string texture = ""; public string icon = ""; public float[]? textureOffset = null; public float[]? textureScale = null; public string behavior = ""; public string[] removeActions = Array.Empty<string>(); public ActionSpec[] addActions = Array.Empty<ActionSpec>(); public string[] removeCookingBehaviors = Array.Empty<string>(); public CookingSpec? cooking = null; public bool spawn = true; public int? uses = null; public float? spawnChance = null; public bool dumpTemplateTexture = false; [JsonIgnore] internal GameObject? templateGo = null; [JsonIgnore] internal Texture2D? templateTexture = null; [JsonIgnore] internal Texture2D? templateIconTex = null; public PetrifyBombSpec? petrifyBomb = null; [JsonIgnore] public string configDir = ""; [JsonIgnore] public string runtimePrefabId = ""; [JsonIgnore] public Item runtimeItem = null; } [Serializable] public class PetrifyBombSpec { public float baseDuration = 10f; public string[]? buffAfflictions = null; public float[] cookDurations = new float[3] { 20f, 30f, 35f }; public float rampCapDuringCountdown = 95f; public bool petrifyAtEnd = true; public float allyRadius = 0f; } [Serializable] public class ItemConfig { public ItemConfigEntry[] items = Array.Empty<ItemConfigEntry>(); public bool liveReloadTexture = true; } [Serializable] public class ActionSpec { public string type = ""; public string on = "CastFinished"; public string statusType = ""; public float changeAmount = 0f; public bool ifSkeleton = false; public float restorationAmount = 0f; public string affliction = ""; public float totalTime = 0f; public float amount = 0f; public string animationName = ""; } [Serializable] public class CookingBehaviorSpec { public string type = ""; public int cookedAmountToTrigger = 1; public bool onlyOnce = true; public bool dontRunIfOutOfFuel = false; public string actionType = "Action_ApplyAffliction"; public float change = 0f; public string affliction = ""; public float totalTime = 0f; } [Serializable] public class CookingSpec { public bool ignoreDefaultCook = false; public bool wreckWhenCooked = false; public string[] removeBehaviors = Array.Empty<string>(); public CookingBehaviorSpec[] addBehaviors = Array.Empty<CookingBehaviorSpec>(); } public static class ItemConfigLoader { public static ItemConfig? Load(string path) { try { if (!File.Exists(path)) { return null; } string text = File.ReadAllText(path); if (string.IsNullOrWhiteSpace(text)) { return null; } ItemConfig itemConfig = JsonConvert.DeserializeObject<ItemConfig>(text); if (itemConfig == null || itemConfig.items == null) { return null; } return itemConfig; } catch (Exception arg) { CustomItemsPlugin.Log.LogError((object)$"读取物品配置失败 {path}: {arg}"); return null; } } public static ItemConfig LoadAll(string rootDir) { List<ItemConfigEntry> list = new List<ItemConfigEntry>(); string path = Path.Combine(rootDir, "itemconfig.json"); if (File.Exists(path)) { ItemConfig itemConfig = Load(path); if (itemConfig != null) { list.AddRange(itemConfig.items); } } try { string[] directories = Directory.GetDirectories(rootDir); foreach (string text in directories) { string path2 = Path.Combine(text, "itemconfig.json"); if (!File.Exists(path2)) { continue; } ItemConfig itemConfig2 = Load(path2); if (itemConfig2 == null || itemConfig2.items == null || itemConfig2.items.Length == 0) { continue; } ItemConfigEntry[] items = itemConfig2.items; foreach (ItemConfigEntry itemConfigEntry in items) { itemConfigEntry.configDir = text; if (string.IsNullOrWhiteSpace(itemConfigEntry.name)) { itemConfigEntry.name = Path.GetFileName(text); } } list.AddRange(itemConfig2.items); } } catch (Exception arg) { CustomItemsPlugin.Log.LogError((object)$"扫描物品文件夹失败 {rootDir}: {arg}"); } return new ItemConfig { items = list.ToArray() }; } public static void WriteEntryToFolder(string dir, ItemConfigEntry entry) { try { Directory.CreateDirectory(dir); ItemConfig itemConfig = new ItemConfig(); itemConfig.items = new ItemConfigEntry[1] { entry }; ItemConfig itemConfig2 = itemConfig; string text = JsonConvert.SerializeObject((object)itemConfig2, (Formatting)1); string text2 = "// ============================================================\n// 新物品配置(由游戏内 F10 物品编辑器生成)\n" + $"// 模板: {entry.templateValue} 生成时间: {DateTime.Now:yyyy-MM-dd HH:mm:ss}\n" + "// 修改后重启游戏生效;贴图 PNG 放到本文件夹\n// ============================================================\n"; File.WriteAllText(Path.Combine(dir, "itemconfig.json"), text2 + text); CustomItemsPlugin.Log.LogInfo((object)("已写入配置: " + Path.Combine(dir, "itemconfig.json"))); } catch (Exception arg) { CustomItemsPlugin.Log.LogError((object)$"写入配置失败 {dir}: {arg}"); } } public static void WriteExampleFolder(string dir) { try { Directory.CreateDirectory(dir); File.WriteAllText(Path.Combine(dir, "itemconfig.json"), "{\n // ============================================================\n // 示例物品:野生狗奶(以游戏内\"奶白金\"为模板)\n // 用法:改 name/displayName → 重启游戏 → 进一局看到道具\n // texture/icon 留空 = 完全继承模板外观\n // spawnChance 留空(null) = 沿用模板生成概率;写 0~100 可覆盖\n // 属性(v1.4.6 全部可选,不写 = 继承模板):\n // removeActions: 移除模板继承的食用动作,如 [\"Action_ApplyAffliction\"]\n // addActions: 添加食用动作,如 [{ \"type\": \"ModifyStatus\", \"on\": \"CastFinished\",\n // \"statusType\": \"Hot\", \"changeAmount\": -0.5 }]\n // type 可选 ModifyStatus/RestoreHunger/ApplyAffliction/\n // GiveExtraStamina/Consume/PlayAnimation\n // on 可选 Pressed/Held/Released/CastFinished/Cancelled/Consumed/Secondary*\n // removeCookingBehaviors: 移除烹饪行为,如 [\"CookingBehavior_ChangeAfflictionTime\"]\n // cooking: 烹饪配置,如 { \"ignoreDefaultCook\": true, \"addBehaviors\": [\n // { \"type\": \"Explode\" },\n // { \"type\": \"AfflictAllAndExplode\", \"affliction\": \"Invincibility\", \"totalTime\": 10 } ] }\n // addBehaviors type 可选 Explode/ChangeAfflictionTime/AfflictAll/AfflictAllAndExplode\n // 石化炸弹(v1.6.0):加 \"petrifyBomb\": { \"baseDuration\": 10, \"cookDurations\": [20,30,35],\n // \"petrifyAtEnd\": true, \"explodeAtEnd\": true, \"splashRadius\": 6, \"splashPetrify\": 50 }\n // → 食用 10s 无敌+逐渐石化,结束满石化(变石头)+爆炸波及附近;烹饪逐次升级时长\n // ItemInfoDisplay 兼容(v1.6.3):addActions 挂标准动作即可显示属性(像官方物品):\n // ApplyAffliction→获得无敌 / RestoreHunger→恢复饱食 / ModifyStatus→状态增减\n // 技巧:on 留空 \"\" = 纯装饰组件(不触发不生效,仅让属性面板显示,如石化)\n // ============================================================\n \"items\": [\n {\n \"name\": \"WildDogMilk\",\n \"displayName\": \"野生狗奶\",\n \"templateMatch\": \"contains\",\n \"templateValue\": \"milk\",\n \"tags\": [],\n \"texture\": \"\",\n \"icon\": \"\",\n \"behavior\": \"\",\n \"spawn\": true,\n \"spawnChance\": null\n }\n ]\n}"); CustomItemsPlugin.Log.LogInfo((object)("已生成示例物品文件夹: " + dir)); } catch (Exception arg) { CustomItemsPlugin.Log.LogError((object)$"生成示例配置失败 {dir}: {arg}"); } } } public class ItemEditorUI : MonoBehaviour { private static class PreviewRig { private const int Layer = 30; private static GameObject? _root; private static Camera? _cam; private static RenderTexture? _rt; private static int _lastItemId = -1; private static GameObject? _clone; private static Vector3 _center = Vector3.zero; private static float _radius = 2f; private static float _yaw = 0f; private static float _pitch = 12f; public static RenderTexture? RT => _rt; public static bool HasModel => (Object)(object)_clone != (Object)null; private static void EnsureBuilt() { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Expected O, but got Unknown //IL_004c: 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_006d: Expected O, but got Unknown //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_011c: Unknown result type (might be due to invalid IL or missing references) //IL_0122: Expected O, but got Unknown //IL_0155: Unknown result type (might be due to invalid IL or missing references) //IL_0175: Unknown result type (might be due to invalid IL or missing references) //IL_0185: Unknown result type (might be due to invalid IL or missing references) //IL_018b: Expected O, but got Unknown //IL_01c2: Unknown result type (might be due to invalid IL or missing references) //IL_01e2: Unknown result type (might be due to invalid IL or missing references) //IL_01fa: Unknown result type (might be due to invalid IL or missing references) //IL_0204: Expected O, but got Unknown if (!((Object)(object)_root != (Object)null)) { _root = new GameObject("PeakPreviewStage"); _root.layer = 30; _root.transform.position = new Vector3(0f, -10000f, 0f); Object.DontDestroyOnLoad((Object)(object)_root); GameObject val = new GameObject("PeakPreviewCam"); val.transform.SetParent(_root.transform, false); _cam = val.AddComponent<Camera>(); _cam.clearFlags = (CameraClearFlags)2; _cam.backgroundColor = new Color(0.14f, 0.14f, 0.17f, 1f); _cam.cullingMask = 1073741824; _cam.orthographic = false; _cam.nearClipPlane = 0.01f; _cam.farClipPlane = 100f; _cam.fieldOfView = 35f; ((Behaviour)_cam).enabled = false; GameObject val2 = new GameObject("PeakPreviewKey"); val2.transform.SetParent(_root.transform, false); Light val3 = val2.AddComponent<Light>(); val3.type = (LightType)1; val3.intensity = 1.3f; val3.color = Color.white; val2.transform.rotation = Quaternion.Euler(40f, 35f, 0f); GameObject val4 = new GameObject("PeakPreviewFill"); val4.transform.SetParent(_root.transform, false); Light val5 = val4.AddComponent<Light>(); val5.type = (LightType)1; val5.intensity = 0.55f; val5.color = Color.white; val4.transform.rotation = Quaternion.Euler(-25f, -130f, 0f); _rt = new RenderTexture(512, 512, 24, (RenderTextureFormat)0); _rt.Create(); _cam.targetTexture = _rt; } } public static void SetItem(Item item) { //IL_00f7: Unknown result type (might be due to invalid IL or missing references) //IL_0136: Unknown result type (might be due to invalid IL or missing references) //IL_0127: Unknown result type (might be due to invalid IL or missing references) //IL_012c: Unknown result type (might be due to invalid IL or missing references) //IL_0155: 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_01db: Unknown result type (might be due to invalid IL or missing references) //IL_01e0: 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_017b: 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_0199: 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) EnsureBuilt(); int num = (((Object)(object)item != (Object)null) ? ((Object)item).GetInstanceID() : (-1)); if (num == _lastItemId) { return; } _lastItemId = num; for (int num2 = _root.transform.childCount - 1; num2 >= 0; num2--) { Transform child = _root.transform.GetChild(num2); bool flag; switch (((Object)child).name) { case "PeakPreviewCam": case "PeakPreviewKey": case "PeakPreviewFill": flag = true; break; default: flag = false; break; } if (!flag) { Object.Destroy((Object)(object)((Component)child).gameObject); } } _clone = null;