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<ValuableObject, float, float> 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<PriceEntry> prices = new List<PriceEntry>();
}
[Serializable]
public class PriceEntry
{
public int viewId;
public float price;
}
public class RandomValueRpcRelay : MonoBehaviourPunCallbacks
{
[CompilerGenerated]
private sealed class <PublishConfigDelayed>d__4 : IEnumerator<object>, IDisposable, IEnumerator
{
private int <>1__state;
private object <>2__current;
public RandomValueRpcRelay <>4__this;
object IEnumerator<object>.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
object IEnumerator.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
[DebuggerHidden]
public <PublishConfigDelayed>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<PunManager>();
if ((Object)(object)val != (Object)null)
{
_instance = ((Component)val).GetComponent<RandomValueRpcRelay>();
if ((Object)(object)_instance == (Object)null)
{
_instance = ((Component)val).gameObject.AddComponent<RandomValueRpcRelay>();
}
}
}
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<PhotonView>() == (Object)null)
{
((Component)this).gameObject.AddComponent<PhotonView>();
}
}
[IteratorStateMachine(typeof(<PublishConfigDelayed>d__4))]
private IEnumerator PublishConfigDelayed()
{
//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
return new <PublishConfigDelayed>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<PriceSyncData>(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<int, float> 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, object>)(object)propertiesThatChanged).ContainsKey((object)"rv_config"))
{
return;
}
string text = propertiesThatChanged[(object)"rv_config"] as string;
if (!string.IsNullOrEmpty(text))
{
RandomValueConfigSnapshot randomValueConfigSnapshot = JsonUtility.FromJson<RandomValueConfigSnapshot>(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<ValuableObject>() : 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<bool> EnableValueRandomization;
public static ConfigEntry<float> MinValueMultiplier;
public static ConfigEntry<float> MaxValueMultiplier;
public static ConfigEntry<bool> EnableVerboseLogging;
public static ConfigEntry<string> BlacklistKeywords;
public static ConfigEntry<string> WhitelistKeywords;
public static ConfigEntry<bool> EnableBlacklistMode;
public static ConfigEntry<bool> EnableWhitelistMode;
public static ConfigEntry<bool> ExcludeHighValueItems;
public static ConfigEntry<float> HighValueThreshold;
public static ConfigEntry<bool> CashBagRandomizationToggle;
public static HashSet<int> modifiedItemIds = new HashSet<int>();
public static Dictionary<int, float> priceCache = new Dictionary<int, float>();
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<bool>("基础设置", "随机化物品价格", true, (ConfigDescription)null);
MinValueMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("价格设置", "最小价格倍率", 0.5f, new ConfigDescription("最小倍率", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 5f), Array.Empty<object>()));
MaxValueMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("价格设置", "最大价格倍率", 2f, new ConfigDescription("最大倍率", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 10f), Array.Empty<object>()));
EnableBlacklistMode = ((BaseUnityPlugin)this).Config.Bind<bool>("黑白名单", "启用黑名单模式", true, (ConfigDescription)null);
BlacklistKeywords = ((BaseUnityPlugin)this).Config.Bind<string>("黑白名单", "黑名单关键词", "", (ConfigDescription)null);
EnableWhitelistMode = ((BaseUnityPlugin)this).Config.Bind<bool>("黑白名单", "启用白名单模式", false, (ConfigDescription)null);
WhitelistKeywords = ((BaseUnityPlugin)this).Config.Bind<string>("黑白名单", "白名单关键词", "", (ConfigDescription)null);
ExcludeHighValueItems = ((BaseUnityPlugin)this).Config.Bind<bool>("特殊排除规则", "排除高价物品", false, (ConfigDescription)null);
HighValueThreshold = ((BaseUnityPlugin)this).Config.Bind<float>("特殊排除规则", "高价阈值", 50000f, new ConfigDescription("阈值", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1000f, 1000000f), Array.Empty<object>()));
CashBagRandomizationToggle = ((BaseUnityPlugin)this).Config.Bind<bool>("特殊排除规则", "现金袋随机化", false, (ConfigDescription)null);
EnableVerboseLogging = ((BaseUnityPlugin)this).Config.Bind<bool>("调试", "详细日志", 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<ValuableObject>();
if ((Object)(object)component == (Object)null)
{
return;
}
bool isConnected = PhotonNetwork.IsConnected;
int num;
if (isConnected)
{
PhotonView component2 = ((Component)component).GetComponent<PhotonView>();
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();
}
}