using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using ExitGames.Client.Photon;
using Peak.Afflictions;
using Photon.Pun;
using Photon.Realtime;
using UnityEngine;
using Zorro.Core;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("CampfireHaven")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.1.0.0")]
[assembly: AssemblyInformationalVersion("1.1.0+0383e9a2e04a5d5d8423b5aa94390544ff83e9a2")]
[assembly: AssemblyProduct("CampfireHaven")]
[assembly: AssemblyTitle("CampfireHaven")]
[assembly: AssemblyVersion("1.1.0.0")]
namespace CampfireHaven;
internal static class CampfireAura
{
private const float RescanInterval = 120f;
private static readonly List<Campfire> s_Tracked = new List<Campfire>();
private static object s_SeenMapHandler;
private static bool s_Seeded;
private static float s_NextRescan;
internal static List<Campfire> Tracked => s_Tracked;
internal static void Refresh()
{
Prune();
if (EnsureMapHandler())
{
SeedOnce();
TrackSegmentCampfires();
RescanIfDue();
}
}
private static bool EnsureMapHandler()
{
MapHandler instance = Singleton<MapHandler>.Instance;
if ((Object)(object)instance == (Object)null)
{
return false;
}
if (instance == s_SeenMapHandler)
{
return true;
}
s_SeenMapHandler = instance;
s_Tracked.Clear();
s_Seeded = false;
s_NextRescan = 0f;
return true;
}
private static void SeedOnce()
{
if (!s_Seeded)
{
try
{
ScanScene();
}
catch (Exception ex)
{
Diagnostics.Warn("[篝火] 开局扫描异常,下一 tick 重试:" + ex.GetType().Name + ": " + ex.Message);
return;
}
s_Seeded = true;
s_NextRescan = Time.time + 120f;
Diagnostics.Trace($"[篝火] 开局扫描完成,共 {s_Tracked.Count} 个");
}
}
private static void TrackSegmentCampfires()
{
try
{
TryTrack(MapHandler.CurrentCampfire);
}
catch
{
}
try
{
TryTrack(MapHandler.PreviousCampfire);
}
catch
{
}
}
private static void RescanIfDue()
{
if (Time.time < s_NextRescan)
{
return;
}
s_NextRescan = Time.time + 120f;
try
{
ScanScene();
}
catch (Exception ex)
{
Diagnostics.Warn("[篝火] 定期扫描异常:" + ex.GetType().Name + ": " + ex.Message);
}
}
private static void ScanScene()
{
Campfire[] array = Object.FindObjectsByType<Campfire>((FindObjectsInactive)1, (FindObjectsSortMode)0);
for (int i = 0; i < array.Length; i++)
{
TryTrack(array[i]);
}
}
private static void TryTrack(Campfire campfire)
{
if (!((Object)(object)campfire == (Object)null) && !s_Tracked.Contains(campfire) && !(campfire.moraleBoostRadius <= 0f))
{
try
{
CampfireContext.Install(campfire);
}
catch (Exception ex)
{
Diagnostics.Warn("[篝火] 登记失败 " + ((Object)campfire).name + ",该篝火本次不生效:" + ex.GetType().Name + ": " + ex.Message);
return;
}
s_Tracked.Add(campfire);
}
}
private static void Prune()
{
for (int num = s_Tracked.Count - 1; num >= 0; num--)
{
if ((Object)(object)s_Tracked[num] == (Object)null)
{
s_Tracked.RemoveAt(num);
}
}
}
}
internal sealed class CampfireContext : MonoBehaviour
{
private const float BuffRefreshInterval = 1.5f;
private StatusEmitter _emitter;
private float _lastBuffApplied;
private bool _resolved;
internal bool LocalInProtectionAura;
internal bool LocalInWarmthAura;
internal bool HasWarmth => (Object)(object)_emitter != (Object)null;
internal Vector3 WarmthOrigin
{
get
{
//IL_0025: Unknown result type (might be due to invalid IL or missing references)
//IL_0019: Unknown result type (might be due to invalid IL or missing references)
if (!((Object)(object)_emitter == (Object)null))
{
return _emitter.transform.position;
}
return ((Component)this).transform.position;
}
}
internal float WarmthRadius
{
get
{
if (!((Object)(object)_emitter == (Object)null))
{
return _emitter.radius + _emitter.outerFade;
}
return 0f;
}
}
internal float WarmthPerSecond
{
get
{
if (!((Object)(object)_emitter == (Object)null))
{
return _emitter.amount;
}
return 0f;
}
}
internal bool TryRefreshBuff(CharacterAfflictions afflictions)
{
if (!afflictions.canGetHungry && Time.time - _lastBuffApplied <= 1.5f)
{
return false;
}
_lastBuffApplied = Time.time;
return true;
}
internal static CampfireContext Install(Campfire campfire)
{
if ((Object)(object)campfire == (Object)null)
{
return null;
}
CampfireContext campfireContext = default(CampfireContext);
if (((Component)campfire).TryGetComponent<CampfireContext>(ref campfireContext))
{
if (!campfireContext._resolved)
{
campfireContext.Resolve(campfire);
}
return campfireContext;
}
CampfireContext campfireContext2 = ((Component)campfire).gameObject.AddComponent<CampfireContext>();
campfireContext2.Resolve(campfire);
return campfireContext2;
}
private void Resolve(Campfire campfire)
{
try
{
_emitter = FindWarmthEmitter(campfire);
}
catch (Exception ex)
{
Diagnostics.Warn("[篝火] 取暖组件解析失败 " + ((Object)campfire).name + ":" + ex.GetType().Name + ": " + ex.Message);
}
_resolved = true;
Diagnostics.Trace($"[篝火] 已登记 {((Object)campfire).name}:防饥饿半径 {campfire.moraleBoostRadius:F1} 世界单位," + (HasWarmth ? $"取暖 {WarmthPerSecond:F3}/s 半径 {WarmthRadius:F1} 世界单位" : "未找到取暖组件"));
}
private static StatusEmitter FindWarmthEmitter(Campfire campfire)
{
if ((Object)(object)campfire.enableWhenLit != (Object)null)
{
StatusEmitter val = PickColdEmitter(campfire.enableWhenLit.GetComponentsInChildren<StatusEmitter>(true));
if ((Object)(object)val != (Object)null)
{
return val;
}
}
return PickColdEmitter(((Component)campfire).GetComponentsInChildren<StatusEmitter>(true));
}
private static StatusEmitter PickColdEmitter(StatusEmitter[] emitters)
{
//IL_000b: Unknown result type (might be due to invalid IL or missing references)
//IL_0011: Invalid comparison between Unknown and I4
foreach (StatusEmitter val in emitters)
{
if ((int)val.statusType == 2 && val.amount < 0f)
{
return val;
}
}
return null;
}
}
[BepInPlugin("campfirehaven.host", "Campfire Haven", "1.1.0")]
public sealed class CampfireHavenPlugin : BaseUnityPlugin
{
public const string Guid = "campfirehaven.host";
public const string Name = "Campfire Haven";
public const string Version = "1.1.0";
private void Awake()
{
//IL_002a: Unknown result type (might be due to invalid IL or missing references)
//IL_002f: Unknown result type (might be due to invalid IL or missing references)
//IL_0035: Expected O, but got Unknown
Diagnostics.Sink = ((BaseUnityPlugin)this).Logger;
PluginConfig.Bind(((BaseUnityPlugin)this).Config);
Diagnostics.Verbose = PluginConfig.DebugLog.Value;
GameObject val = new GameObject("Campfire Haven");
Object.DontDestroyOnLoad((Object)val);
val.AddComponent<HostLoop>();
Diagnostics.Info(string.Format("{0} {1} 已加载:防饥饿={2} ", "Campfire Haven", "1.1.0", PluginConfig.ProtectFromHunger.Value) + $"取暖={PluginConfig.ProtectFromCold.Value} 驱逐领队={PluginConfig.EvictScoutmaster.Value} " + $"半径(防饥饿/取暖/驱逐)={PluginConfig.ProtectionRadius.Value}/{PluginConfig.WarmthRadius.Value}/{PluginConfig.EvictionRadius.Value} 米 " + $"调试日志={Diagnostics.Verbose}");
}
}
internal static class CampfireProtection
{
private struct HungerHold
{
internal float Anchor;
internal float Mirror;
}
private const float ColdQuantum = 0.025f;
private const float EmitterTick = 0.5f;
private static readonly Affliction_NoHunger s_Buff = new Affliction_NoHunger
{
totalTime = 3f
};
private static readonly Dictionary<Character, HungerHold> s_Holds = new Dictionary<Character, HungerHold>();
private static readonly List<Character> s_Stale = new List<Character>();
internal static void ApplyLocalHunger(CampfireContext context, Character local)
{
if (!((Object)(object)context == (Object)null) && context.TryRefreshBuff(local.refs.afflictions))
{
local.refs.afflictions.AddAffliction((Affliction)(object)s_Buff, false);
}
}
internal static void ApplyLocalWarmth(Character local, float warmthPerSecond, float deltaTime)
{
float num = WarmthStep(warmthPerSecond, deltaTime);
if (!(num <= 0f))
{
local.refs.afflictions.SubtractStatus((STATUSTYPE)2, num, false, false);
}
}
internal static void WarmRemote(Character character, float warmthPerSecond, float deltaTime)
{
float num = WarmthStep(warmthPerSecond, deltaTime);
if (!(num <= 0f))
{
StatusRelay.PushCold(character, 0f - num);
}
}
private static float WarmthStep(float warmthPerSecond, float deltaTime)
{
int num = Mathf.Max(1, Mathf.RoundToInt(deltaTime / 0.5f));
return Mathf.Abs(warmthPerSecond) * 0.5f * (float)num;
}
internal static void HoldRemoteHunger(Character character, bool insideAura)
{
if (!insideAura)
{
s_Holds.Remove(character);
return;
}
float currentStatus = character.refs.afflictions.GetCurrentStatus((STATUSTYPE)1);
if (!s_Holds.TryGetValue(character, out var value))
{
s_Holds[character] = new HungerHold
{
Anchor = currentStatus,
Mirror = currentStatus
};
Diagnostics.Trace($"[篝火] 开始压制 {((Object)character).name} 的饥饿,基线 {currentStatus:F3}");
}
else if (currentStatus <= value.Anchor)
{
value.Anchor = currentStatus;
value.Mirror = currentStatus;
s_Holds[character] = value;
}
else if (currentStatus == value.Mirror)
{
s_Holds[character] = value;
}
else
{
value.Mirror = currentStatus;
s_Holds[character] = value;
StatusRelay.PushHunger(character, value.Anchor - currentStatus);
}
}
internal static void ForgetAllHolds()
{
s_Holds.Clear();
}
internal static void DropDestroyedHolds()
{
if (s_Holds.Count == 0)
{
return;
}
s_Stale.Clear();
foreach (KeyValuePair<Character, HungerHold> s_Hold in s_Holds)
{
if ((Object)(object)s_Hold.Key == (Object)null)
{
s_Stale.Add(s_Hold.Key);
}
}
foreach (Character item in s_Stale)
{
s_Holds.Remove(item);
}
}
}
internal static class Diagnostics
{
internal static ManualLogSource Sink;
internal static bool Verbose;
internal static void Trace(string message)
{
if (Verbose)
{
ManualLogSource sink = Sink;
if (sink != null)
{
sink.LogInfo((object)message);
}
}
}
internal static void Info(string message)
{
ManualLogSource sink = Sink;
if (sink != null)
{
sink.LogInfo((object)message);
}
}
internal static void Warn(string message)
{
ManualLogSource sink = Sink;
if (sink != null)
{
sink.LogWarning((object)message);
}
}
}
internal sealed class HostLoop : MonoBehaviour
{
private const float TickInterval = 0.5f;
private const float ReportInterval = 30f;
private readonly List<Character> _characters = new List<Character>();
private readonly HashSet<Character> _hungerCovered = new HashSet<Character>();
private readonly HashSet<Character> _warmthCovered = new HashSet<Character>();
private float _warmthPerSecond;
private float _nextTick;
private float _nextReport;
private float _lastTickTime;
private bool _reportedStartup;
private bool _reportedActivation;
private bool _reportedStandDown;
private bool _reportedStandDownReasonIsHost;
private bool _localInProtection;
private bool _localInWarmth;
private float _localWarmthPerSecond;
private float _nearestDistance;
private float _nearestRadius;
private bool _nearestHasWarmth;
private bool _hasNearest;
private void Update()
{
if (Time.time < _nextTick)
{
return;
}
float deltaTime = Mathf.Clamp(Time.time - _lastTickTime, 0.1f, 1f);
_lastTickTime = Time.time;
_nextTick = Time.time + 0.5f;
bool inRoom = PhotonNetwork.InRoom;
bool flag = !inRoom || PhotonNetwork.IsMasterClient;
try
{
ModPresence.Sync(inRoom, PluginConfig.Active);
}
catch (Exception ex)
{
Diagnostics.Warn("[篝火] 宣告状态同步异常:" + ex.GetType().Name + ": " + ex.Message);
}
if (!PluginConfig.Active)
{
return;
}
Diagnostics.Verbose = PluginConfig.DebugLog.Value;
ReportStartup();
bool flag2 = inRoom && ModPresence.HostHasMod;
if (inRoom && !flag && (!PluginConfig.ClientFallback.Value || flag2))
{
CampfireProtection.ForgetAllHolds();
ReportStandDown(flag2);
return;
}
_reportedStandDown = false;
try
{
CampfireAura.Refresh();
}
catch (Exception ex2)
{
Diagnostics.Warn("[篝火] 注册表刷新异常:" + ex2.GetType().Name + ": " + ex2.Message);
}
CollectCharacters();
try
{
ApplyCampfireAuras(deltaTime, flag);
}
catch (Exception ex3)
{
Diagnostics.Warn("[篝火] 光环应用异常:" + ex3.GetType().Name + ": " + ex3.Message);
}
try
{
CampfireProtection.DropDestroyedHolds();
}
catch (Exception ex4)
{
Diagnostics.Warn("[篝火] 清理饥饿压制表异常:" + ex4.GetType().Name + ": " + ex4.Message);
}
if (PluginConfig.EvictScoutmaster.Value && inRoom && flag)
{
try
{
EvictScoutmasters();
}
catch (Exception ex5)
{
Diagnostics.Warn("[篝火] 驱逐领队异常:" + ex5.GetType().Name + ": " + ex5.Message);
}
}
try
{
ReportPeriodic(flag, flag2);
}
catch (Exception ex6)
{
Diagnostics.Warn("[篝火] 状态汇总异常:" + ex6.GetType().Name);
}
}
private void ReportStartup()
{
if (!_reportedStartup)
{
_reportedStartup = true;
string text = $"[状态] HostLoop 已挂载 InRoom={PhotonNetwork.InRoom} ";
object arg = PhotonNetwork.IsMasterClient;
Player localPlayer = PhotonNetwork.LocalPlayer;
Diagnostics.Trace(text + $"IsMaster={arg} Actor={((localPlayer != null) ? new int?(localPlayer.ActorNumber) : ((int?)null))} " + "游戏版本=" + Application.version);
}
}
private void ReportStandDown(bool hostHasMod)
{
if (!_reportedStandDown || _reportedStandDownReasonIsHost != hostHasMod)
{
_reportedStandDown = true;
_reportedStandDownReasonIsHost = hostHasMod;
Diagnostics.Info(hostHasMod ? "[篝火] 主机已安装本模组,本客户端自动让位,不会重复生效" : "[篝火] 客户端回退已关闭,本客户端不工作");
}
}
private void ReportPeriodic(bool isMaster, bool hostOwnsAuthority)
{
if (!(Time.time < _nextReport))
{
_nextReport = Time.time + 30f;
string arg = ((!PhotonNetwork.InRoom) ? "单机" : (isMaster ? "主机" : (hostOwnsAuthority ? "客户端(让位)" : "客户端(自保)")));
Character localCharacter = Character.localCharacter;
string arg2 = (((Object)(object)localCharacter == (Object)null) ? "本地角色未就绪" : ($"饥饿={localCharacter.refs.afflictions.GetCurrentStatus((STATUSTYPE)1):F3} " + $"寒冷={localCharacter.refs.afflictions.GetCurrentStatus((STATUSTYPE)2):F3} " + $"离受冻={localCharacter.data.sinceAddedCold:F1}s " + $"饥饿速率={localCharacter.refs.afflictions.hungerPerSecond:F4}/s " + $"免饥饿={!localCharacter.refs.afflictions.canGetHungry} " + $"在防饥饿圈={_localInProtection} " + (_hasNearest ? $"最近篝火={_nearestDistance * CharacterStats.unitsToMeters:F1}m/{_nearestRadius * CharacterStats.unitsToMeters:F1}m " : "最近篝火=附近无未点燃篝火 ") + $"取暖组件={_nearestHasWarmth} " + $"在取暖圈={_localInWarmth}({Mathf.Abs(_localWarmthPerSecond):F3}/s)"));
Diagnostics.Trace($"[状态] 角色={arg} 篝火={CampfireAura.Tracked.Count} 角色数={_characters.Count} " + $"远程饥饿={_hungerCovered.Count} 远程取暖={_warmthCovered.Count} | 本地 {arg2}");
}
}
private void CollectCharacters()
{
_characters.Clear();
_characters.AddRange(Character.AllCharacters);
_characters.AddRange(Character.AllBotCharacters);
}
private void ApplyCampfireAuras(float deltaTime, bool isMaster)
{
//IL_018e: 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_01b9: Unknown result type (might be due to invalid IL or missing references)
//IL_01bb: 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_0130: Unknown result type (might be due to invalid IL or missing references)
//IL_0135: Unknown result type (might be due to invalid IL or missing references)
//IL_01d9: 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)
Character localCharacter = Character.localCharacter;
bool value = PluginConfig.ProtectFromHunger.Value;
bool value2 = PluginConfig.ProtectFromCold.Value;
_hungerCovered.Clear();
_warmthCovered.Clear();
_warmthPerSecond = 0f;
CampfireContext campfireContext = null;
_localInProtection = false;
_localInWarmth = false;
_localWarmthPerSecond = 0f;
_nearestDistance = float.MaxValue;
_nearestRadius = 0f;
_nearestHasWarmth = false;
_hasNearest = false;
foreach (Campfire item in CampfireAura.Tracked)
{
if ((Object)(object)item == (Object)null || !((Component)item).gameObject.activeInHierarchy || item.Lit)
{
continue;
}
CampfireContext campfireContext2 = CampfireContext.Install(item);
if ((Object)(object)campfireContext2 == (Object)null)
{
continue;
}
float num = PluginConfig.ToWorldUnits(PluginConfig.ProtectionRadius.Value, item.moraleBoostRadius);
bool flag = value2 && campfireContext2.HasWarmth;
float num2 = (flag ? PluginConfig.ToWorldUnits(PluginConfig.WarmthRadius.Value, campfireContext2.WarmthRadius) : 0f);
Vector3 position = ((Component)item).transform.position;
Vector3 warmthOrigin = campfireContext2.WarmthOrigin;
foreach (Character character in _characters)
{
if ((Object)(object)character == (Object)null || character.isBot || character.data.dead || (!character.IsLocal && !isMaster))
{
continue;
}
Vector3 center;
try
{
center = character.Center;
}
catch (Exception ex)
{
Diagnostics.Warn("[篝火] 取角色坐标失败,已跳过:" + ex.GetType().Name);
continue;
}
float num3 = Vector3.Distance(position, center);
bool flag2 = value && num3 <= num;
bool flag3 = flag && Vector3.Distance(warmthOrigin, center) <= num2;
if (character.IsLocal)
{
if (num3 < _nearestDistance)
{
_nearestDistance = num3;
_nearestRadius = num;
_nearestHasWarmth = campfireContext2.HasWarmth;
_hasNearest = true;
}
if (flag2)
{
_localInProtection = true;
if ((Object)(object)campfireContext == (Object)null)
{
campfireContext = campfireContext2;
}
}
if (flag3)
{
_localInWarmth = true;
_localWarmthPerSecond = campfireContext2.WarmthPerSecond;
}
LogLocalTransition(item, campfireContext2, flag2, flag3, num3, num);
}
else
{
if (flag2)
{
_hungerCovered.Add(character);
}
if (flag3)
{
_warmthCovered.Add(character);
_warmthPerSecond = campfireContext2.WarmthPerSecond;
}
}
}
}
ApplyLocal(localCharacter, campfireContext, deltaTime);
if (isMaster)
{
ApplyRemote(deltaTime);
}
else
{
_hungerCovered.Clear();
_warmthCovered.Clear();
}
ReportFirstActivation();
}
private void ApplyLocal(Character local, CampfireContext protector, float deltaTime)
{
if (!((Object)(object)local == (Object)null) && !local.data.dead)
{
if ((Object)(object)protector != (Object)null)
{
CampfireProtection.ApplyLocalHunger(protector, local);
}
if (_localInWarmth)
{
CampfireProtection.ApplyLocalWarmth(local, _localWarmthPerSecond, deltaTime);
}
}
}
private void ApplyRemote(float deltaTime)
{
foreach (Character character in _characters)
{
if (!((Object)(object)character == (Object)null) && !character.isBot && !character.IsLocal)
{
CampfireProtection.HoldRemoteHunger(character, _hungerCovered.Contains(character));
if (_warmthCovered.Contains(character))
{
CampfireProtection.WarmRemote(character, _warmthPerSecond, deltaTime);
}
}
}
}
private void EvictScoutmasters()
{
foreach (Character character in _characters)
{
if (!((Object)(object)character == (Object)null) && character.data.isScoutmaster)
{
ScoutmasterEviction.EvictInsideCampfires(character);
}
}
}
private void ReportFirstActivation()
{
if (!_reportedActivation && (_localInProtection || _localInWarmth))
{
_reportedActivation = true;
Diagnostics.Info("[篝火] 本地玩家已进入未点燃篝火的保护范围," + $"防饥饿={_localInProtection} 取暖={_localInWarmth}");
}
}
private static void LogLocalTransition(Campfire campfire, CampfireContext context, bool inProtection, bool inWarmth, float distance, float radius)
{
if (Diagnostics.Verbose)
{
if (inProtection != context.LocalInProtectionAura)
{
context.LocalInProtectionAura = inProtection;
Diagnostics.Trace(inProtection ? $"[篝火] 进入 {((Object)campfire).name} 防饥饿范围,距离 {distance * CharacterStats.unitsToMeters:F1} 米 / {radius * CharacterStats.unitsToMeters:F1} 米" : ("[篝火] 离开 " + ((Object)campfire).name + " 防饥饿范围"));
}
if (inWarmth != context.LocalInWarmthAura)
{
context.LocalInWarmthAura = inWarmth;
Diagnostics.Trace(inWarmth ? $"[篝火] 开始取暖 {((Object)campfire).name},{context.WarmthPerSecond:F3}/s" : ("[篝火] 结束取暖 " + ((Object)campfire).name));
}
}
}
}
internal static class ModPresence
{
private const string PropertyKey = "campfirehaven.host";
private static int s_AnnouncedActor = -1;
internal static bool HostHasMod
{
get
{
Player masterClient = PhotonNetwork.MasterClient;
if (masterClient == null)
{
return false;
}
return ((Dictionary<object, object>)(object)masterClient.CustomProperties)?.ContainsKey((object)"campfirehaven.host") ?? false;
}
}
internal static void Sync(bool inRoom, bool active)
{
//IL_0076: Unknown result type (might be due to invalid IL or missing references)
//IL_007b: Unknown result type (might be due to invalid IL or missing references)
//IL_008b: Expected O, but got Unknown
//IL_0092: Expected O, but got Unknown
//IL_0037: Unknown result type (might be due to invalid IL or missing references)
//IL_003c: Unknown result type (might be due to invalid IL or missing references)
//IL_0048: Expected O, but got Unknown
//IL_004f: Expected O, but got Unknown
Player localPlayer = PhotonNetwork.LocalPlayer;
if (localPlayer == null)
{
s_AnnouncedActor = -1;
return;
}
Hashtable customProperties = localPlayer.CustomProperties;
if (!(inRoom && active))
{
((Dictionary<object, object>)(object)customProperties)?.Remove((object)"campfirehaven.host");
if (inRoom && s_AnnouncedActor != -1)
{
Hashtable val = new Hashtable();
((Dictionary<object, object>)val).Add((object)"campfirehaven.host", (object)null);
localPlayer.SetCustomProperties(val, (Hashtable)null, (WebFlags)null);
}
s_AnnouncedActor = -1;
}
else if (s_AnnouncedActor != localPlayer.ActorNumber || customProperties == null || !((Dictionary<object, object>)(object)customProperties).ContainsKey((object)"campfirehaven.host"))
{
Hashtable val2 = new Hashtable();
((Dictionary<object, object>)val2).Add((object)"campfirehaven.host", (object)"1.1.0");
if (!localPlayer.SetCustomProperties(val2, (Hashtable)null, (WebFlags)null))
{
s_AnnouncedActor = -1;
}
else
{
s_AnnouncedActor = localPlayer.ActorNumber;
}
}
}
}
internal static class PluginConfig
{
internal static ConfigEntry<bool> Enabled;
internal static ConfigEntry<bool> DebugLog;
internal static ConfigEntry<bool> ClientFallback;
internal static ConfigEntry<bool> ProtectFromHunger;
internal static ConfigEntry<bool> ProtectFromCold;
internal static ConfigEntry<float> ProtectionRadius;
internal static ConfigEntry<float> WarmthRadius;
internal static ConfigEntry<bool> EvictScoutmaster;
internal static ConfigEntry<float> EvictionRadius;
internal static bool Active
{
get
{
if (Enabled != null)
{
return Enabled.Value;
}
return true;
}
}
internal static void Bind(ConfigFile config)
{
Enabled = config.Bind<bool>("General", "Enabled", true, "总开关,关闭后插件不产生任何效果");
DebugLog = config.Bind<bool>("General", "DebugLog", false, "输出详细诊断日志。仅在排查问题时打开,正常游玩建议关闭");
ClientFallback = config.Bind<bool>("General", "ClientFallback", true, "主机已经装了本模组时,非主机客户端自动让位。主机没装时,非主机是否只保护自己(关闭则非主机完全不工作)");
ProtectFromHunger = config.Bind<bool>("Campfire", "ProtectFromHunger", true, "未点燃的篝火是否阻止饥饿");
ProtectFromCold = config.Bind<bool>("Campfire", "ProtectFromCold", true, "未点燃的篝火是否消除寒冷");
ProtectionRadius = config.Bind<float>("Campfire", "ProtectionRadius", 19.2f, "防饥饿半径,单位是游戏内提示显示的米。19.2 米等于原版篝火的 12 世界单位。填 0 表示沿用每座篝火自己的数值");
WarmthRadius = config.Bind<float>("Campfire", "WarmthRadius", 6.4f, "取暖半径,单位是游戏内提示显示的米。6.4 米等于原版篝火点燃时的 4 世界单位。填 0 表示沿用每座篝火自己的数值");
EvictScoutmaster = config.Bind<bool>("Scoutmaster", "Enabled", true, "童子军领队进入篝火范围时是否让其消失");
EvictionRadius = config.Bind<float>("Scoutmaster", "EvictionRadius", 19.2f, "驱逐半径,单位是游戏内提示显示的米。19.2 米等于原版篝火的 12 世界单位。填 0 表示沿用每座篝火自己的数值");
}
internal static float ToWorldUnits(float meters, float fallbackUnits)
{
if (meters <= 0f)
{
return fallbackUnits;
}
float unitsToMeters = CharacterStats.unitsToMeters;
if (!(unitsToMeters > 0f))
{
return meters;
}
return meters / unitsToMeters;
}
}
internal static class ScoutmasterEviction
{
internal static void EvictInsideCampfires(Character scoutmaster)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
//IL_000c: Unknown result type (might be due to invalid IL or missing references)
Vector3 center;
try
{
center = scoutmaster.Center;
}
catch
{
return;
}
if (TryFindContainingCampfire(center, out var nearestDistance))
{
Evict(scoutmaster, nearestDistance);
}
}
private static bool TryFindContainingCampfire(Vector3 point, out float nearestDistance)
{
//IL_0050: Unknown result type (might be due to invalid IL or missing references)
//IL_0055: Unknown result type (might be due to invalid IL or missing references)
nearestDistance = float.MaxValue;
bool result = false;
foreach (Campfire item in CampfireAura.Tracked)
{
if ((Object)(object)item == (Object)null || !((Component)item).gameObject.activeInHierarchy)
{
continue;
}
float num = PluginConfig.ToWorldUnits(PluginConfig.EvictionRadius.Value, item.moraleBoostRadius);
float num2 = Vector3.Distance(((Component)item).transform.position, point);
if (!(num2 > num))
{
result = true;
if (num2 < nearestDistance)
{
nearestDistance = num2;
}
}
}
return result;
}
private static void Evict(Character scoutmaster, float distance)
{
if (PhotonNetwork.InRoom && PhotonNetwork.IsMasterClient && !((Object)(object)((MonoBehaviourPun)scoutmaster).photonView == (Object)null) && ((MonoBehaviourPun)scoutmaster).photonView.IsMine)
{
if ((Object)(object)scoutmaster.data.grabJoint != (Object)null)
{
scoutmaster.refs.view.RPC("RPCA_GrabUnattach", (RpcTarget)0, Array.Empty<object>());
}
Diagnostics.Info($"[篝火] 童子军领队进入保护范围({distance * CharacterStats.unitsToMeters:F1} 米),已移除");
PhotonNetwork.Destroy(((MonoBehaviourPun)scoutmaster).photonView);
}
}
}
internal static class StatusRelay
{
internal static void PushHunger(Character character, float delta)
{
Push(character, 1, delta);
}
internal static void PushCold(Character character, float delta)
{
Push(character, 2, delta);
}
private static void Push(Character character, int statusIndex, float delta)
{
if (!(delta >= 0f) && PhotonNetwork.InRoom && PhotonNetwork.IsMasterClient)
{
float[] array = new float[character.refs.afflictions.currentStatuses.Length];
array[statusIndex] = delta;
((MonoBehaviourPun)character).photonView.RPC("RPC_ApplyStatusesFromFloatArray", (RpcTarget)0, new object[1] { array });
}
}
}