using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using ExitGames.Client.Photon; using HarmonyLib; using Photon.Pun; using Photon.Realtime; using RandomValueLib; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: AssemblyTitle("RandomValueMod")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("RandomValueMod")] [assembly: AssemblyCopyright("Copyright © 2026")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("94f4834c-4276-4ed1-92e7-92a919ab9c3b")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyVersion("1.0.0.0")] namespace RandomValuablePrice; public static class RandomValueAPI { public static event Action OnItemRandomized; internal static void TriggerItemRandomized(ValuableObject vo, float oldPrice, float newPrice) { RandomValueAPI.OnItemRandomized?.Invoke(vo, oldPrice, newPrice); } } [Serializable] public class RandomValueConfigSnapshot { public float minMultiplier; public float maxMultiplier; public bool enableBlacklist; public bool enableWhitelist; public bool excludeHigh; public bool cashBag; public string blacklist; public string whitelist; public float highThreshold; public int levelSeed; public long revision; } [Serializable] public class PriceSyncData { public List prices = new List(); } [Serializable] public class PriceEntry { public int viewId; public float price; } public class RandomValueRpcRelay : MonoBehaviourPunCallbacks { [CompilerGenerated] private sealed class d__4 : IEnumerator, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public RandomValueRpcRelay <>4__this; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__4(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>2__current = (object)new WaitForSeconds(1f); <>1__state = 1; return true; case 1: <>1__state = -1; if (PhotonNetwork.IsMasterClient && PhotonNetwork.InRoom) { RandomValueMod.CurrentLevelSeed = <>4__this.GetLevelSeed(); <>4__this.PublishConfigSnapshot(RandomValueMod.CurrentConfig, RandomValueMod.CurrentLevelSeed); RandomValueMod.StaticLogger.LogInfo((object)"[Config] 延迟发布配置快照完成"); } return false; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } private static RandomValueRpcRelay _instance; public static RandomValueRpcRelay Instance { get { if ((Object)(object)_instance == (Object)null) { PunManager val = Object.FindObjectOfType(); if ((Object)(object)val != (Object)null) { _instance = ((Component)val).GetComponent(); if ((Object)(object)_instance == (Object)null) { _instance = ((Component)val).gameObject.AddComponent(); } } } return _instance; } } private void Awake() { if ((Object)(object)_instance != (Object)null && (Object)(object)_instance != (Object)(object)this) { Object.Destroy((Object)(object)this); return; } _instance = this; if ((Object)(object)((Component)this).GetComponent() == (Object)null) { ((Component)this).gameObject.AddComponent(); } } [IteratorStateMachine(typeof(d__4))] private IEnumerator PublishConfigDelayed() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__4(0) { <>4__this = this }; } [PunRPC] public void RequestItemPriceRPC(int viewId, int requesterActorNumber) { if (!PhotonNetwork.IsMasterClient) { return; } ValuableObject val = FindValuableByViewId(viewId); if (!((Object)(object)val == (Object)null)) { float itemPrice = RandomValueService.GetItemPrice(val); float num = RandomValueService.ApplyRandomPrice(val, RandomValueMod.CurrentConfig, (int?)RandomValueMod.CurrentLevelSeed); if (RandomValueMod.EnableVerboseLogging.Value) { string playerNameByActorNumber = GetPlayerNameByActorNumber(requesterActorNumber); string text = CleanItemName(((Object)val).name); float num2 = ((itemPrice > 0f) ? (num / itemPrice) : 0f); RandomValueMod.StaticLogger.LogInfo((object)$"[Host] {playerNameByActorNumber} 抓取 {text} | {itemPrice:F0} → {num:F0} | 倍率: {num2:F2}x"); } if (Math.Abs(num - itemPrice) > 0.01f) { RandomValueMod.priceCache[viewId] = num; ((MonoBehaviourPun)this).photonView.RPC("SetItemPriceRPC", (RpcTarget)0, new object[3] { viewId, num, itemPrice }); } } } [PunRPC] public void SetItemPriceRPC(int viewId, float newPrice, float oldPrice) { ValuableObject val = FindValuableByViewId(viewId); if (!((Object)(object)val == (Object)null)) { RandomValueService.SetItemPrice(val, newPrice); RandomValueAPI.TriggerItemRandomized(val, oldPrice, newPrice); RandomValueMod.modifiedItemIds.Add(viewId); RandomValueMod.priceCache[viewId] = newPrice; if (RandomValueMod.EnableVerboseLogging.Value) { string text = CleanItemName(((Object)val).name); float num = ((oldPrice > 0f) ? (newPrice / oldPrice) : 0f); RandomValueMod.StaticLogger.LogInfo((object)$"[Sync] {text} | {oldPrice:F0} → {newPrice:F0} | 倍率: {num:F2}x"); } } } [PunRPC] public void SyncAllPricesRPC(int targetActor, string priceDataJson) { if (PhotonNetwork.LocalPlayer.ActorNumber != targetActor) { return; } PriceSyncData priceSyncData = JsonUtility.FromJson(priceDataJson); if (priceSyncData == null) { return; } foreach (PriceEntry price in priceSyncData.prices) { ValuableObject val = FindValuableByViewId(price.viewId); if ((Object)(object)val != (Object)null) { RandomValueService.SetItemPrice(val, price.price); RandomValueMod.modifiedItemIds.Add(price.viewId); RandomValueMod.priceCache[price.viewId] = price.price; } } if (RandomValueMod.EnableVerboseLogging.Value) { RandomValueMod.StaticLogger.LogInfo((object)$"[Sync] 新玩家补发 {priceSyncData.prices.Count} 个物品价格"); } } public override void OnPlayerEnteredRoom(Player newPlayer) { if (!PhotonNetwork.IsMasterClient) { return; } PriceSyncData priceSyncData = new PriceSyncData(); foreach (KeyValuePair item in RandomValueMod.priceCache) { priceSyncData.prices.Add(new PriceEntry { viewId = item.Key, price = item.Value }); } string text = JsonUtility.ToJson((object)priceSyncData); ((MonoBehaviourPun)this).photonView.RPC("SyncAllPricesRPC", newPlayer, new object[2] { newPlayer.ActorNumber, text }); } public void PublishConfigSnapshot(RandomizationConfig config, int levelSeed) { //IL_00c4: 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_00db: Expected O, but got Unknown if (PhotonNetwork.IsMasterClient && PhotonNetwork.InRoom) { RandomValueConfigSnapshot randomValueConfigSnapshot = new RandomValueConfigSnapshot { minMultiplier = config.MinMultiplier, maxMultiplier = config.MaxMultiplier, enableBlacklist = config.EnableBlacklist, blacklist = string.Join(",", config.BlacklistKeywords), enableWhitelist = config.EnableWhitelist, whitelist = string.Join(",", config.WhitelistKeywords), excludeHigh = config.ExcludeHighValueItems, highThreshold = config.HighValueThreshold, cashBag = config.RandomizeCashBags, levelSeed = levelSeed, revision = DateTime.UtcNow.Ticks }; string text = JsonUtility.ToJson((object)randomValueConfigSnapshot); Hashtable val = new Hashtable { [(object)"rv_config"] = text }; PhotonNetwork.CurrentRoom.SetCustomProperties(val, (Hashtable)null, (WebFlags)null); } } public override void OnRoomPropertiesUpdate(Hashtable propertiesThatChanged) { if (!((Dictionary)(object)propertiesThatChanged).ContainsKey((object)"rv_config")) { return; } string text = propertiesThatChanged[(object)"rv_config"] as string; if (!string.IsNullOrEmpty(text)) { RandomValueConfigSnapshot randomValueConfigSnapshot = JsonUtility.FromJson(text); if (randomValueConfigSnapshot != null) { ApplySnapshot(randomValueConfigSnapshot); } } } public override void OnJoinedRoom() { RandomValueMod.ClearCache(); ((MonoBehaviour)this).StartCoroutine(PublishConfigDelayed()); } private void ApplySnapshot(RandomValueConfigSnapshot snapshot) { RandomValueMod.MinValueMultiplier.Value = snapshot.minMultiplier; RandomValueMod.MaxValueMultiplier.Value = snapshot.maxMultiplier; RandomValueMod.EnableBlacklistMode.Value = snapshot.enableBlacklist; RandomValueMod.BlacklistKeywords.Value = snapshot.blacklist; RandomValueMod.EnableWhitelistMode.Value = snapshot.enableWhitelist; RandomValueMod.WhitelistKeywords.Value = snapshot.whitelist; RandomValueMod.ExcludeHighValueItems.Value = snapshot.excludeHigh; RandomValueMod.HighValueThreshold.Value = snapshot.highThreshold; RandomValueMod.CashBagRandomizationToggle.Value = snapshot.cashBag; RandomValueMod.CurrentLevelSeed = snapshot.levelSeed; RandomValueMod.StaticLogger.LogInfo((object)$"[Config] 快照已应用 (rev {snapshot.revision})"); } public int GetLevelSeed() { if (PhotonNetwork.InRoom) { int serverTimestamp = PhotonNetwork.ServerTimestamp; RunManager instance = RunManager.instance; object obj; if (instance == null) { obj = null; } else { Level levelCurrent = instance.levelCurrent; obj = ((levelCurrent != null) ? ((Object)levelCurrent).name : null); } if (obj == null) { obj = "default"; } string text = (string)obj; return serverTimestamp ^ text.GetHashCode(); } return Random.Range(1, int.MaxValue); } private ValuableObject FindValuableByViewId(int viewId) { PhotonView val = PhotonView.Find(viewId); return (val != null) ? ((Component)val).GetComponent() : null; } private static string GetPlayerNameByActorNumber(int actorNumber) { if (PhotonNetwork.CurrentRoom != null) { Player player = PhotonNetwork.CurrentRoom.GetPlayer(actorNumber, false); if (player != null && !string.IsNullOrEmpty(player.NickName)) { return player.NickName; } } return $"Player {actorNumber}"; } private static string CleanItemName(string rawName) { if (string.IsNullOrEmpty(rawName)) { return rawName; } return rawName.Replace("Valuable ", "").Replace("(Clone)", "").Trim(); } } [BepInPlugin("dyxc666.RandomValuablePrice", "随机贵重物品价格", "2.0.5")] [BepInProcess("REPO.exe")] public class RandomValueMod : BaseUnityPlugin { private readonly Harmony harmony = new Harmony("dyxc666.RandomValuablePrice"); public static ConfigEntry EnableValueRandomization; public static ConfigEntry MinValueMultiplier; public static ConfigEntry MaxValueMultiplier; public static ConfigEntry EnableVerboseLogging; public static ConfigEntry BlacklistKeywords; public static ConfigEntry WhitelistKeywords; public static ConfigEntry EnableBlacklistMode; public static ConfigEntry EnableWhitelistMode; public static ConfigEntry ExcludeHighValueItems; public static ConfigEntry HighValueThreshold; public static ConfigEntry CashBagRandomizationToggle; public static HashSet modifiedItemIds = new HashSet(); public static Dictionary priceCache = new Dictionary(); public static RandomizationConfig CurrentConfig { get; private set; } public static int CurrentLevelSeed { get; set; } public static ManualLogSource StaticLogger { get; private set; } private void Awake() { StaticLogger = ((BaseUnityPlugin)this).Logger; StaticLogger.LogInfo((object)"随机贵重物品价格 v2.0.5"); CreateConfigEntries(); UpdateConfig(); MinValueMultiplier.SettingChanged += delegate { UpdateConfig(); PublishConfigIfMaster(); }; MaxValueMultiplier.SettingChanged += delegate { UpdateConfig(); PublishConfigIfMaster(); }; EnableBlacklistMode.SettingChanged += delegate { UpdateConfig(); PublishConfigIfMaster(); }; BlacklistKeywords.SettingChanged += delegate { UpdateConfig(); PublishConfigIfMaster(); }; EnableWhitelistMode.SettingChanged += delegate { UpdateConfig(); PublishConfigIfMaster(); }; WhitelistKeywords.SettingChanged += delegate { UpdateConfig(); PublishConfigIfMaster(); }; ExcludeHighValueItems.SettingChanged += delegate { UpdateConfig(); PublishConfigIfMaster(); }; HighValueThreshold.SettingChanged += delegate { UpdateConfig(); PublishConfigIfMaster(); }; CashBagRandomizationToggle.SettingChanged += delegate { UpdateConfig(); PublishConfigIfMaster(); }; ApplyHarmonyPatches(); } private void PublishConfigIfMaster() { if (PhotonNetwork.IsMasterClient && PhotonNetwork.InRoom) { RandomValueRpcRelay instance = RandomValueRpcRelay.Instance; if (!((Object)(object)instance == (Object)null)) { CurrentLevelSeed = instance.GetLevelSeed(); instance.PublishConfigSnapshot(CurrentConfig, CurrentLevelSeed); } } } private void UpdateConfig() { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Expected O, but got Unknown RandomizationConfig val = new RandomizationConfig(); val.MinMultiplier = MinValueMultiplier.Value; val.MaxMultiplier = MaxValueMultiplier.Value; val.EnableBlacklist = EnableBlacklistMode.Value; val.BlacklistKeywords = (from k in BlacklistKeywords.Value.Split(new char[3] { ',', ';', '|' }, StringSplitOptions.RemoveEmptyEntries) select k.Trim().ToLower() into k where !string.IsNullOrEmpty(k) select k).ToList(); val.EnableWhitelist = EnableWhitelistMode.Value; val.WhitelistKeywords = (from k in WhitelistKeywords.Value.Split(new char[3] { ',', ';', '|' }, StringSplitOptions.RemoveEmptyEntries) select k.Trim().ToLower() into k where !string.IsNullOrEmpty(k) select k).ToList(); val.ExcludeHighValueItems = ExcludeHighValueItems.Value; val.HighValueThreshold = HighValueThreshold.Value; val.RandomizeCashBags = CashBagRandomizationToggle.Value; CurrentConfig = val; } private void CreateConfigEntries() { //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Expected O, but got Unknown //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Expected O, but got Unknown //IL_0159: Unknown result type (might be due to invalid IL or missing references) //IL_0163: Expected O, but got Unknown EnableValueRandomization = ((BaseUnityPlugin)this).Config.Bind("基础设置", "随机化物品价格", true, (ConfigDescription)null); MinValueMultiplier = ((BaseUnityPlugin)this).Config.Bind("价格设置", "最小价格倍率", 0.5f, new ConfigDescription("最小倍率", (AcceptableValueBase)(object)new AcceptableValueRange(0.1f, 5f), Array.Empty())); MaxValueMultiplier = ((BaseUnityPlugin)this).Config.Bind("价格设置", "最大价格倍率", 2f, new ConfigDescription("最大倍率", (AcceptableValueBase)(object)new AcceptableValueRange(0.5f, 10f), Array.Empty())); EnableBlacklistMode = ((BaseUnityPlugin)this).Config.Bind("黑白名单", "启用黑名单模式", true, (ConfigDescription)null); BlacklistKeywords = ((BaseUnityPlugin)this).Config.Bind("黑白名单", "黑名单关键词", "", (ConfigDescription)null); EnableWhitelistMode = ((BaseUnityPlugin)this).Config.Bind("黑白名单", "启用白名单模式", false, (ConfigDescription)null); WhitelistKeywords = ((BaseUnityPlugin)this).Config.Bind("黑白名单", "白名单关键词", "", (ConfigDescription)null); ExcludeHighValueItems = ((BaseUnityPlugin)this).Config.Bind("特殊排除规则", "排除高价物品", false, (ConfigDescription)null); HighValueThreshold = ((BaseUnityPlugin)this).Config.Bind("特殊排除规则", "高价阈值", 50000f, new ConfigDescription("阈值", (AcceptableValueBase)(object)new AcceptableValueRange(1000f, 1000000f), Array.Empty())); CashBagRandomizationToggle = ((BaseUnityPlugin)this).Config.Bind("特殊排除规则", "现金袋随机化", false, (ConfigDescription)null); EnableVerboseLogging = ((BaseUnityPlugin)this).Config.Bind("调试", "详细日志", true, (ConfigDescription)null); } private void ApplyHarmonyPatches() { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Expected O, but got Unknown //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Expected O, but got Unknown harmony.Patch((MethodBase)AccessTools.Method(typeof(PhysGrabObject), "GrabStarted", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(PhysGrabObjectPatch), "Postfix_GrabStarted", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null); harmony.Patch((MethodBase)AccessTools.Method(typeof(PhysGrabObject), "GrabEnded", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(PhysGrabObjectPatch), "Postfix_GrabEnded", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null); } public static void ClearCache() { modifiedItemIds.Clear(); priceCache.Clear(); if (EnableVerboseLogging.Value) { StaticLogger.LogInfo((object)"[Cache] 已清空缓存"); } } } [HarmonyPatch(typeof(PhysGrabObject))] public static class PhysGrabObjectPatch { [HarmonyPostfix] [HarmonyPatch("GrabStarted")] public static void Postfix_GrabStarted(PhysGrabObject __instance, PhysGrabber player) { if (!RandomValueMod.EnableValueRandomization.Value) { return; } ValuableObject component = ((Component)__instance).GetComponent(); if ((Object)(object)component == (Object)null) { return; } bool isConnected = PhotonNetwork.IsConnected; int num; if (isConnected) { PhotonView component2 = ((Component)component).GetComponent(); if ((Object)(object)component2 == (Object)null) { return; } num = component2.ViewID; } else { num = ((Object)component).GetInstanceID(); } if (RandomValueMod.modifiedItemIds.Contains(num)) { return; } RandomValueMod.modifiedItemIds.Add(num); if (!isConnected || PhotonNetwork.IsMasterClient) { float itemPrice = RandomValueService.GetItemPrice(component); float num2 = RandomValueService.ApplyRandomPrice(component, RandomValueMod.CurrentConfig, (int?)RandomValueMod.CurrentLevelSeed); if (RandomValueMod.EnableVerboseLogging.Value) { string text = CleanItemName(((Object)component).name); float num3 = ((itemPrice > 0f) ? (num2 / itemPrice) : 0f); if (isConnected) { string playerNameByActorNumber = GetPlayerNameByActorNumber(PhotonNetwork.LocalPlayer.ActorNumber); RandomValueMod.StaticLogger.LogInfo((object)$"[Host Grab] {playerNameByActorNumber} 抓取 {text} | {itemPrice:F0} → {num2:F0} | 倍率: {num3:F2}x"); } else { string nickName = PhotonNetwork.LocalPlayer.NickName; RandomValueMod.StaticLogger.LogInfo((object)$"[Single] {nickName} 抓取 {text} | {itemPrice:F0} → {num2:F0} | 倍率: {num3:F2}x"); } } if (Math.Abs(num2 - itemPrice) > 0.01f && isConnected) { RandomValueMod.priceCache[num] = num2; RandomValueRpcRelay instance = RandomValueRpcRelay.Instance; if (instance != null) { ((MonoBehaviourPun)instance).photonView.RPC("SetItemPriceRPC", (RpcTarget)0, new object[3] { num, num2, itemPrice }); } } } else { RandomValueRpcRelay instance2 = RandomValueRpcRelay.Instance; if (instance2 != null) { ((MonoBehaviourPun)instance2).photonView.RPC("RequestItemPriceRPC", (RpcTarget)2, new object[2] { num, PhotonNetwork.LocalPlayer.ActorNumber }); } } } [HarmonyPostfix] [HarmonyPatch("GrabEnded")] public static void Postfix_GrabEnded(PhysGrabObject __instance, PhysGrabber player) { } private static string GetPlayerNameByActorNumber(int actorNumber) { if (PhotonNetwork.CurrentRoom != null) { Player player = PhotonNetwork.CurrentRoom.GetPlayer(actorNumber, false); if (player != null && !string.IsNullOrEmpty(player.NickName)) { return player.NickName; } } return $"Player {actorNumber}"; } private static string CleanItemName(string rawName) { if (string.IsNullOrEmpty(rawName)) { return rawName; } return rawName.Replace("Valuable ", "").Replace("(Clone)", "").Trim(); } }