using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Jotunn.Configs;
using Jotunn.Entities;
using Jotunn.Managers;
using TMPro;
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("RavenwoodRandomRelics")]
[assembly: AssemblyDescription("A Valheim mod that adds custom relics, statues, and decor.")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("James Jones TV")]
[assembly: AssemblyProduct("Ravenwood Random Relics Mod")]
[assembly: AssemblyCopyright("")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("e3243d22-4307-4008-ba36-9f326008cde5")]
[assembly: AssemblyFileVersion("2.2.2")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("2.2.2.0")]
namespace ImperiumEvents;
public class FinishRuneInteract : MonoBehaviour, Hoverable, Interactable
{
private Piece m_piece;
private void Awake()
{
m_piece = ((Component)this).GetComponent<Piece>();
}
public bool Interact(Humanoid user, bool hold, bool alt)
{
if (hold)
{
return false;
}
Player val = (Player)(object)((user is Player) ? user : null);
if ((Object)(object)val == (Object)null || (Object)(object)ImperiumTriathlonManager.Instance == (Object)null)
{
return false;
}
ImperiumTriathlonManager.Instance.RequestFinish(val);
return true;
}
public bool UseItem(Humanoid user, ItemData item)
{
return false;
}
public string GetHoverText()
{
string text = (((Object)(object)m_piece != (Object)null) ? m_piece.m_name : "Finish Rune");
return text + "\n[<color=yellow><b>E</b></color>] Finish Race";
}
public string GetHoverName()
{
return ((Object)(object)m_piece != (Object)null) ? m_piece.m_name : "Finish Rune";
}
}
public class HornInteract : MonoBehaviour, Hoverable, Interactable
{
private ZSFX m_sfx;
private Piece m_piece;
private ZNetView m_nview;
private void Awake()
{
m_sfx = ((Component)this).GetComponent<ZSFX>();
m_piece = ((Component)this).GetComponent<Piece>();
m_nview = ((Component)this).GetComponent<ZNetView>();
if ((Object)(object)m_nview != (Object)null)
{
m_nview.Register("ImperiumHornSound", (Action<long>)RPC_PlayHorn);
}
}
public bool Interact(Humanoid user, bool hold, bool alt)
{
if (hold)
{
return false;
}
Player val = (Player)(object)((user is Player) ? user : null);
if ((Object)(object)val == (Object)null || (Object)(object)ImperiumTriathlonManager.Instance == (Object)null)
{
return false;
}
if (!ImperiumTriathlonManager.Instance.IsConfiguredAdmin(val))
{
if ((Object)(object)MessageHud.instance != (Object)null)
{
MessageHud.instance.ShowMessage((MessageType)2, "Only configured admin can start the race.", 0, (Sprite)null, false);
}
return false;
}
if ((Object)(object)m_nview != (Object)null)
{
m_nview.InvokeRPC(ZNetView.Everybody, "ImperiumHornSound", Array.Empty<object>());
}
ImperiumTriathlonManager.Instance.RequestStartRace(val);
return true;
}
private void RPC_PlayHorn(long sender)
{
if ((Object)(object)m_sfx != (Object)null)
{
m_sfx.Play();
}
}
public bool UseItem(Humanoid user, ItemData item)
{
return false;
}
public string GetHoverText()
{
string text = (((Object)(object)m_piece != (Object)null) ? m_piece.m_name : "Horn");
return text + "\n[<color=yellow><b>E</b></color>] Start Imperium Triathlon";
}
public string GetHoverName()
{
return ((Object)(object)m_piece != (Object)null) ? m_piece.m_name : "Horn";
}
}
[BepInPlugin("Imperium.Events", "Imperium Events", "1.0.0")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public class ImperiumEvents : BaseUnityPlugin
{
public const string PluginGUID = "Imperium.Events";
public const string PluginName = "Imperium Events";
public const string PluginVersion = "1.0.0";
private AssetBundle relicsBundle;
public static ConfigEntry<string> PlayerPreferredCategory;
public static ManualLogSource ModLogger;
private void Awake()
{
//IL_0011: Unknown result type (might be due to invalid IL or missing references)
ModLogger = ((BaseUnityPlugin)this).Logger;
new Harmony("imperium.events.harmony").PatchAll();
PlayerPreferredCategory = ((BaseUnityPlugin)this).Config.Bind<string>("General", "CustomHammerTab", "ImperiumEvents", "Custom hammer tab category name");
ImperiumTriathlonManager.Initialize(((BaseUnityPlugin)this).Config);
((Component)this).gameObject.AddComponent<ImperiumTriathlonManager>();
Assembly executingAssembly = Assembly.GetExecutingAssembly();
string text = executingAssembly.GetManifestResourceNames().FirstOrDefault((string r) => r.ToLower().Contains("imperium"));
if (string.IsNullOrEmpty(text))
{
((BaseUnityPlugin)this).Logger.LogError((object)"Could not find embedded asset bundle resource containing 'imperium'.");
return;
}
using (Stream stream = executingAssembly.GetManifestResourceStream(text))
{
if (stream == null)
{
((BaseUnityPlugin)this).Logger.LogError((object)("Embedded asset bundle stream was null for '" + text + "'."));
return;
}
using MemoryStream memoryStream = new MemoryStream();
stream.CopyTo(memoryStream);
relicsBundle = AssetBundle.LoadFromMemory(memoryStream.ToArray());
}
if ((Object)(object)relicsBundle == (Object)null)
{
((BaseUnityPlugin)this).Logger.LogError((object)"Failed to load AssetBundle from embedded resource!");
return;
}
PrefabManager.OnPrefabsRegistered -= RegisterNow;
PrefabManager.OnPrefabsRegistered += RegisterNow;
}
private void RegisterNow()
{
if (!((Object)(object)relicsBundle == (Object)null))
{
RelicRegistrar.RegisterAllRelics(relicsBundle);
ImperiumTriathlonBootstrap.AttachTriathlonComponents(((BaseUnityPlugin)this).Logger);
((BaseUnityPlugin)this).Logger.LogInfo((object)("[ImperiumEvents] Registration complete. Hammer tab: '" + PlayerPreferredCategory.Value + "'."));
}
}
}
public static class ImperiumTriathlonBootstrap
{
public static void AttachTriathlonComponents(ManualLogSource logger)
{
AttachIfFound("Imperium_Horn", typeof(HornInteract), logger);
AttachIfFound("Start_Rune", typeof(StartRuneInteract), logger);
AttachIfFound("Finish_Rune", typeof(FinishRuneInteract), logger);
AttachIfFound("Imperium_Scoreboard", typeof(RaceScoreboard), logger);
AttachNightLight(logger);
}
private static void AttachIfFound(string prefabName, Type componentType, ManualLogSource logger)
{
GameObject prefab = PrefabManager.Instance.GetPrefab(prefabName);
if ((Object)(object)prefab == (Object)null)
{
if (logger != null)
{
logger.LogWarning((object)("[ImperiumEvents] Prefab not found for triathlon hookup: " + prefabName));
}
}
else if ((Object)(object)prefab.GetComponent(componentType) == (Object)null)
{
prefab.AddComponent(componentType);
if (logger != null)
{
logger.LogInfo((object)("[ImperiumEvents] Attached " + componentType.Name + " to " + prefabName + "."));
}
}
}
private static void AttachNightLight(ManualLogSource logger)
{
GameObject prefab = PrefabManager.Instance.GetPrefab("Imperium_Scoreboard");
if ((Object)(object)prefab == (Object)null)
{
if (logger != null)
{
logger.LogWarning((object)"[ImperiumEvents] Imperium_Scoreboard prefab not found.");
}
return;
}
Transform val = prefab.transform.Find("NightLight");
if ((Object)(object)val == (Object)null)
{
if (logger != null)
{
logger.LogWarning((object)"[ImperiumEvents] NightLight child not found on Imperium_Scoreboard.");
}
}
else if ((Object)(object)((Component)val).GetComponent<ScoreboardEmissionNight>() == (Object)null)
{
((Component)val).gameObject.AddComponent<ScoreboardEmissionNight>();
if (logger != null)
{
logger.LogInfo((object)"[ImperiumEvents] Attached ScoreboardEmissionNight to NightLight.");
}
}
}
}
public class ImperiumTriathlonManager : MonoBehaviour
{
[Serializable]
private struct EntrantState
{
public string PlayerName;
public bool Registered;
public bool Finished;
public double StartTime;
public double FinishTime;
}
[Serializable]
private class RaceResultsFile
{
public string EventName;
public string SavedAt;
public List<RaceResultEntry> Results = new List<RaceResultEntry>();
}
[Serializable]
private class RaceResultEntry
{
public string PlayerName;
public float TimeSeconds;
public string TimeFormatted;
}
private static class MiniJson
{
public static string Serialize(RaceResultsFile file)
{
if (file == null)
{
return "{}";
}
string text = "{\n";
text = text + " \"EventName\": " + Quote(file.EventName) + ",\n";
text = text + " \"SavedAt\": " + Quote(file.SavedAt) + ",\n";
text += " \"Results\": [\n";
for (int i = 0; i < file.Results.Count; i++)
{
RaceResultEntry raceResultEntry = file.Results[i];
text += " {\n";
text = text + " \"PlayerName\": " + Quote(raceResultEntry.PlayerName) + ",\n";
text = text + " \"TimeSeconds\": " + raceResultEntry.TimeSeconds.ToString(CultureInfo.InvariantCulture) + ",\n";
text = text + " \"TimeFormatted\": " + Quote(raceResultEntry.TimeFormatted) + "\n";
text += " }";
if (i < file.Results.Count - 1)
{
text += ",";
}
text += "\n";
}
text += " ]\n";
return text + "}";
}
private static string Quote(string value)
{
if (value == null)
{
return "\"\"";
}
return "\"" + value.Replace("\\", "\\\\").Replace("\"", "\\\"").Replace("\n", "\\n")
.Replace("\r", "\\r")
.Replace("\t", "\\t") + "\"";
}
}
[CompilerGenerated]
private sealed class <RegisterRpcsWhenReady>d__21 : IEnumerator<object>, IDisposable, IEnumerator
{
private int <>1__state;
private object <>2__current;
public ImperiumTriathlonManager <>4__this;
object IEnumerator<object>.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
object IEnumerator.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
[DebuggerHidden]
public <RegisterRpcsWhenReady>d__21(int <>1__state)
{
this.<>1__state = <>1__state;
}
[DebuggerHidden]
void IDisposable.Dispose()
{
<>1__state = -2;
}
private bool MoveNext()
{
switch (<>1__state)
{
default:
return false;
case 0:
<>1__state = -1;
break;
case 1:
<>1__state = -1;
break;
}
if (ZRoutedRpc.instance == null || (Object)(object)ZNet.instance == (Object)null)
{
<>2__current = null;
<>1__state = 1;
return true;
}
if (!<>4__this.rpcsRegistered)
{
ZRoutedRpc.instance.Register<string>("ImperiumTriathlon_Register", (Action<long, string>)<>4__this.RPC_Register);
ZRoutedRpc.instance.Register<string>("ImperiumTriathlon_Finish", (Action<long, string>)<>4__this.RPC_Finish);
ZRoutedRpc.instance.Register<string>("ImperiumTriathlon_StartRace", (Action<long, string>)<>4__this.RPC_StartRace);
ZRoutedRpc.instance.Register<string>("ImperiumTriathlon_AdminReset", (Action<long, string>)<>4__this.RPC_AdminReset);
ZRoutedRpc.instance.Register<string>("ImperiumTriathlon_BoardText", (Action<long, string>)<>4__this.RPC_BoardText);
ZRoutedRpc.instance.Register<string>("ImperiumTriathlon_CenterMessage", (Action<long, string>)<>4__this.RPC_CenterMessage);
ZRoutedRpc.instance.Register<string>("ImperiumTriathlon_ResultsPopup", (Action<long, string>)<>4__this.RPC_ResultsPopup);
<>4__this.rpcsRegistered = true;
}
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();
}
}
[CompilerGenerated]
private sealed class <ServerStartRaceCountdown>d__38 : IEnumerator<object>, IDisposable, IEnumerator
{
private int <>1__state;
private object <>2__current;
public ImperiumTriathlonManager <>4__this;
private int <seconds>5__1;
private List<string> <keys>5__2;
private int <i>5__3;
private List<string>.Enumerator <>s__4;
private string <key>5__5;
private EntrantState <state>5__6;
object IEnumerator<object>.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
object IEnumerator.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
[DebuggerHidden]
public <ServerStartRaceCountdown>d__38(int <>1__state)
{
this.<>1__state = <>1__state;
}
[DebuggerHidden]
void IDisposable.Dispose()
{
<keys>5__2 = null;
<>s__4 = default(List<string>.Enumerator);
<key>5__5 = null;
<state>5__6 = default(EntrantState);
<>1__state = -2;
}
private bool MoveNext()
{
//IL_0097: Unknown result type (might be due to invalid IL or missing references)
//IL_00a1: Expected O, but got Unknown
switch (<>1__state)
{
default:
return false;
case 0:
<>1__state = -1;
<>4__this.registrationOpen = false;
<>4__this.BroadcastBoardText(<>4__this.BuildBoardText());
<seconds>5__1 = Mathf.Max(1, Mathf.RoundToInt(CountdownSeconds.Value));
<i>5__3 = <seconds>5__1;
break;
case 1:
<>1__state = -1;
<i>5__3--;
break;
}
if (<i>5__3 >= 1)
{
<>4__this.BroadcastCenterMessage("Imperium Triathlon starts in " + <i>5__3);
<>2__current = (object)new WaitForSeconds(1f);
<>1__state = 1;
return true;
}
<>4__this.raceStarted = true;
<>4__this.raceEnded = false;
<>4__this.raceStartServerTime = Time.realtimeSinceStartupAsDouble;
<keys>5__2 = <>4__this.entrants.Keys.ToList();
<>s__4 = <keys>5__2.GetEnumerator();
try
{
while (<>s__4.MoveNext())
{
<key>5__5 = <>s__4.Current;
<state>5__6 = <>4__this.entrants[<key>5__5];
<state>5__6.StartTime = <>4__this.raceStartServerTime;
<state>5__6.FinishTime = 0.0;
<state>5__6.Finished = false;
<>4__this.entrants[<key>5__5] = <state>5__6;
<state>5__6 = default(EntrantState);
<key>5__5 = null;
}
}
finally
{
((IDisposable)<>s__4).Dispose();
}
<>s__4 = default(List<string>.Enumerator);
<>4__this.BroadcastCenterMessage("GO!");
<>4__this.BroadcastBoardText(<>4__this.BuildBoardText());
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();
}
}
public static ImperiumTriathlonManager Instance;
private const string RpcRegister = "ImperiumTriathlon_Register";
private const string RpcFinish = "ImperiumTriathlon_Finish";
private const string RpcStartRace = "ImperiumTriathlon_StartRace";
private const string RpcAdminReset = "ImperiumTriathlon_AdminReset";
private const string RpcBoardText = "ImperiumTriathlon_BoardText";
private const string RpcCenterMessage = "ImperiumTriathlon_CenterMessage";
private const string RpcResultsPopup = "ImperiumTriathlon_ResultsPopup";
private static ConfigEntry<string> AdminPlayerNames;
private static ConfigEntry<string> ResultsFileName;
private static ConfigEntry<float> CountdownSeconds;
private static ConfigEntry<bool> RequireConfiguredAdminForStartAndReset;
private readonly Dictionary<string, EntrantState> entrants = new Dictionary<string, EntrantState>(StringComparer.OrdinalIgnoreCase);
private readonly List<RaceScoreboard> localBoards = new List<RaceScoreboard>();
private bool registrationOpen = true;
private bool raceStarted = false;
private bool raceEnded = false;
private double raceStartServerTime = 0.0;
private bool rpcsRegistered = false;
public static void Initialize(ConfigFile config)
{
AdminPlayerNames = config.Bind<string>("Imperium Triathlon", "AdminPlayerNames", "Caenos", "Comma separated player names allowed to start/reset the event. Example: Caenos,James");
ResultsFileName = config.Bind<string>("Imperium Triathlon", "ResultsFileName", "ImperiumTriathlonResults.json", "JSON file written into BepInEx/config.");
CountdownSeconds = config.Bind<float>("Imperium Triathlon", "CountdownSeconds", 5f, "Countdown before the race starts.");
RequireConfiguredAdminForStartAndReset = config.Bind<bool>("Imperium Triathlon", "RequireConfiguredAdminForStartAndReset", true, "If true, only names in AdminPlayerNames can start/reset the race.");
}
private void Awake()
{
if ((Object)(object)Instance != (Object)null && (Object)(object)Instance != (Object)(object)this)
{
Object.Destroy((Object)(object)this);
return;
}
Instance = this;
Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject);
((MonoBehaviour)this).StartCoroutine(RegisterRpcsWhenReady());
}
[IteratorStateMachine(typeof(<RegisterRpcsWhenReady>d__21))]
private IEnumerator RegisterRpcsWhenReady()
{
//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
return new <RegisterRpcsWhenReady>d__21(0)
{
<>4__this = this
};
}
public void ForceEndRace()
{
if (ZNet.instance.IsServer())
{
EndRace();
}
}
public void RegisterLocalBoard(RaceScoreboard board)
{
if (!((Object)(object)board == (Object)null) && !localBoards.Contains(board))
{
localBoards.Add(board);
board.SetBoardText(BuildBoardText());
}
}
public void UnregisterLocalBoard(RaceScoreboard board)
{
if (!((Object)(object)board == (Object)null))
{
localBoards.Remove(board);
}
}
public bool IsRaceStarted()
{
return raceStarted;
}
public bool IsRaceEnded()
{
return raceEnded;
}
public bool IsRegistrationOpen()
{
return registrationOpen && !raceStarted && !raceEnded;
}
public bool IsConfiguredAdmin(Player player)
{
return (Object)(object)player != (Object)null && IsConfiguredAdmin(player.GetPlayerName());
}
public bool IsConfiguredAdmin(string playerName)
{
if (!RequireConfiguredAdminForStartAndReset.Value)
{
return true;
}
if (string.IsNullOrWhiteSpace(playerName))
{
return false;
}
string[] source = (from x in AdminPlayerNames.Value.Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries)
select x.Trim() into x
where !string.IsNullOrWhiteSpace(x)
select x).ToArray();
return source.Any((string x) => string.Equals(x, playerName, StringComparison.OrdinalIgnoreCase));
}
public void RequestRegister(Player player)
{
if (!((Object)(object)player == (Object)null) && ZRoutedRpc.instance != null && !((Object)(object)ZNet.instance == (Object)null))
{
ZRoutedRpc.instance.InvokeRoutedRPC(ZRoutedRpc.Everybody, "ImperiumTriathlon_Register", new object[1] { player.GetPlayerName() });
}
}
public void RequestFinish(Player player)
{
if (!((Object)(object)player == (Object)null) && ZRoutedRpc.instance != null && !((Object)(object)ZNet.instance == (Object)null))
{
ZRoutedRpc.instance.InvokeRoutedRPC(ZRoutedRpc.Everybody, "ImperiumTriathlon_Finish", new object[1] { player.GetPlayerName() });
}
}
public void RequestStartRace(Player player)
{
if (!((Object)(object)player == (Object)null) && ZRoutedRpc.instance != null && !((Object)(object)ZNet.instance == (Object)null))
{
ZRoutedRpc.instance.InvokeRoutedRPC(ZRoutedRpc.Everybody, "ImperiumTriathlon_StartRace", new object[1] { player.GetPlayerName() });
}
}
public void RequestAdminReset(Player player)
{
if (!((Object)(object)player == (Object)null) && ZRoutedRpc.instance != null && !((Object)(object)ZNet.instance == (Object)null))
{
ZRoutedRpc.instance.InvokeRoutedRPC(ZRoutedRpc.Everybody, "ImperiumTriathlon_AdminReset", new object[1] { player.GetPlayerName() });
}
}
private void RPC_Register(long sender, string playerName)
{
if (!ZNet.instance.IsServer())
{
return;
}
if (raceStarted)
{
BroadcastCenterMessage("Race already started.");
}
else if (raceEnded)
{
BroadcastCenterMessage("Race ended. Admin must reset the event.");
}
else if (!string.IsNullOrWhiteSpace(playerName))
{
if (!entrants.ContainsKey(playerName))
{
entrants.Add(playerName, new EntrantState
{
PlayerName = playerName,
Registered = true,
Finished = false,
StartTime = 0.0,
FinishTime = 0.0
});
BroadcastCenterMessage(playerName + " joined the Imperium Triathlon.");
}
else
{
BroadcastCenterMessage(playerName + " is already registered.");
}
BroadcastBoardText(BuildBoardText());
}
}
private void RPC_Finish(long sender, string playerName)
{
if (!ZNet.instance.IsServer() || !raceStarted || raceEnded || string.IsNullOrWhiteSpace(playerName))
{
return;
}
if (!entrants.TryGetValue(playerName, out var value))
{
BroadcastCenterMessage(playerName + " is not registered.");
return;
}
if (value.Finished)
{
BroadcastCenterMessage(playerName + " already finished.");
return;
}
value.Finished = true;
value.FinishTime = Time.realtimeSinceStartupAsDouble - raceStartServerTime;
entrants[playerName] = value;
BroadcastCenterMessage(playerName + " finished in " + FormatTime(value.FinishTime));
BroadcastBoardText(BuildBoardText());
if (entrants.Count > 0 && entrants.Values.All((EntrantState x) => x.Finished))
{
EndRace();
}
}
private void RPC_StartRace(long sender, string playerName)
{
if (ZNet.instance.IsServer())
{
if (raceStarted)
{
BroadcastCenterMessage("Race already started.");
}
else if (raceEnded)
{
BroadcastCenterMessage("Race ended. Admin must reset the event.");
}
else if (entrants.Count == 0)
{
BroadcastCenterMessage("No registered players.");
}
else if (!IsConfiguredAdmin(playerName))
{
BroadcastCenterMessage("Only configured admin players can start the race.");
}
else
{
((MonoBehaviour)this).StartCoroutine(ServerStartRaceCountdown());
}
}
}
private void RPC_AdminReset(long sender, string playerName)
{
if (ZNet.instance.IsServer())
{
if (!raceEnded)
{
BroadcastCenterMessage("Race is not in ended state.");
return;
}
if (!IsConfiguredAdmin(playerName))
{
BroadcastCenterMessage("Only configured admin players can reset the race.");
return;
}
ResetRaceServer();
BroadcastCenterMessage("Imperium Triathlon reset. Registration is open.");
BroadcastBoardText(BuildBoardText());
}
}
[IteratorStateMachine(typeof(<ServerStartRaceCountdown>d__38))]
private IEnumerator ServerStartRaceCountdown()
{
//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
return new <ServerStartRaceCountdown>d__38(0)
{
<>4__this = this
};
}
private void EndRace()
{
raceStarted = false;
raceEnded = true;
registrationOpen = false;
string text = BuildResultsPopupText();
BroadcastBoardText(BuildBoardText());
BroadcastResultsPopup(text);
SaveResultsJson();
}
private void ResetRaceServer()
{
entrants.Clear();
registrationOpen = true;
raceStarted = false;
raceEnded = false;
raceStartServerTime = 0.0;
}
private void BroadcastBoardText(string text)
{
if (ZRoutedRpc.instance != null)
{
ZRoutedRpc.instance.InvokeRoutedRPC(ZRoutedRpc.Everybody, "ImperiumTriathlon_BoardText", new object[1] { text ?? string.Empty });
}
}
private void BroadcastCenterMessage(string text)
{
if (ZRoutedRpc.instance != null)
{
ZRoutedRpc.instance.InvokeRoutedRPC(ZRoutedRpc.Everybody, "ImperiumTriathlon_CenterMessage", new object[1] { text ?? string.Empty });
}
}
private void BroadcastResultsPopup(string text)
{
if (ZRoutedRpc.instance != null)
{
ZRoutedRpc.instance.InvokeRoutedRPC(ZRoutedRpc.Everybody, "ImperiumTriathlon_ResultsPopup", new object[1] { text ?? string.Empty });
}
}
private void RPC_BoardText(long sender, string text)
{
for (int num = localBoards.Count - 1; num >= 0; num--)
{
if ((Object)(object)localBoards[num] == (Object)null)
{
localBoards.RemoveAt(num);
}
else
{
localBoards[num].SetBoardText(text);
}
}
}
private void RPC_CenterMessage(long sender, string text)
{
if ((Object)(object)MessageHud.instance != (Object)null && !string.IsNullOrWhiteSpace(text))
{
MessageHud.instance.ShowMessage((MessageType)2, text, 0, (Sprite)null, false);
}
}
private void RPC_ResultsPopup(long sender, string text)
{
if ((Object)(object)MessageHud.instance != (Object)null && !string.IsNullOrWhiteSpace(text))
{
MessageHud.instance.ShowMessage((MessageType)2, text, 0, (Sprite)null, false);
}
}
private string BuildBoardText()
{
if (raceEnded)
{
List<EntrantState> list = entrants.Values.OrderBy((EntrantState x) => x.FinishTime).ToList();
string text = "IMPERIUM TRIATHLON\n\nRESULTS";
for (int i = 0; i < list.Count; i++)
{
text = text + "\n" + (i + 1) + ". " + list[i].PlayerName + " " + FormatTime(list[i].FinishTime);
}
return text + "\n\nAdmin touch Start Rune to reset";
}
if (raceStarted)
{
List<EntrantState> list2 = (from x in entrants.Values
where x.Finished
orderby x.FinishTime
select x).ToList();
List<EntrantState> list3 = (from x in entrants.Values
where !x.Finished
orderby x.PlayerName
select x).ToList();
string text2 = "IMPERIUM TRIATHLON\n\nRACE LIVE";
if (list2.Count > 0)
{
text2 += "\n\nFINISHED";
for (int j = 0; j < list2.Count; j++)
{
text2 = text2 + "\n" + (j + 1) + ". " + list2[j].PlayerName + " " + FormatTime(list2[j].FinishTime);
}
}
if (list3.Count > 0)
{
text2 += "\n\nRACING";
for (int k = 0; k < list3.Count; k++)
{
text2 = text2 + "\n- " + list3[k].PlayerName;
}
}
return text2;
}
string text3 = "IMPERIUM TRIATHLON\n\nREGISTERED PLAYERS";
if (entrants.Count == 0)
{
text3 += "\n\nWaiting for racers...";
}
else
{
int num = 1;
foreach (EntrantState item in entrants.Values.OrderBy((EntrantState x) => x.PlayerName))
{
text3 = text3 + "\n" + num + ". " + item.PlayerName;
num++;
}
}
text3 += "\n\nUse Start Rune to register";
return text3 + "\nUse Horn to start";
}
private string BuildResultsPopupText()
{
List<EntrantState> list = entrants.Values.OrderBy((EntrantState x) => x.FinishTime).ToList();
string text = "IMPERIUM TRIATHLON RESULTS";
for (int i = 0; i < list.Count; i++)
{
text = text + "\n" + (i + 1) + ". " + list[i].PlayerName + " " + FormatTime(list[i].FinishTime);
}
return text;
}
private void SaveResultsJson()
{
try
{
RaceResultsFile file = new RaceResultsFile
{
EventName = "Imperium Triathlon",
SavedAt = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
Results = (from x in entrants.Values
orderby x.FinishTime
select new RaceResultEntry
{
PlayerName = x.PlayerName,
TimeSeconds = (float)x.FinishTime,
TimeFormatted = FormatTime(x.FinishTime)
}).ToList()
};
string path = Path.Combine(Paths.ConfigPath, ResultsFileName.Value);
string contents = MiniJson.Serialize(file);
File.WriteAllText(path, contents);
}
catch (Exception ex)
{
Debug.LogError((object)("[Imperium Triathlon] Failed to save results JSON: " + ex));
}
}
private string FormatTime(double seconds)
{
return TimeSpan.FromSeconds(seconds).ToString("mm\\:ss\\.ff");
}
}
public class PlacementWatcher : MonoBehaviour
{
public List<GameObject> RegisterList;
private void Start()
{
if (RegisterList != null && !RegisterList.Contains(((Component)this).gameObject))
{
RegisterList.Add(((Component)this).gameObject);
}
}
private void OnDestroy()
{
if (RegisterList != null)
{
RegisterList.Remove(((Component)this).gameObject);
}
}
}
public class RaceScoreboard : MonoBehaviour
{
private TMP_Text scoreText;
private void Awake()
{
Transform val = ((Component)this).transform.Find("ScoreText");
if ((Object)(object)val != (Object)null)
{
scoreText = ((Component)val).GetComponent<TMP_Text>();
}
if ((Object)(object)scoreText == (Object)null)
{
scoreText = ((Component)this).GetComponentInChildren<TMP_Text>(true);
}
if ((Object)(object)scoreText != (Object)null && string.IsNullOrWhiteSpace(scoreText.text))
{
scoreText.text = "IMPERIUM TRIATHLON\n\nWaiting for race...";
}
}
private void OnEnable()
{
if ((Object)(object)ImperiumTriathlonManager.Instance != (Object)null)
{
ImperiumTriathlonManager.Instance.RegisterLocalBoard(this);
}
}
private void Start()
{
if ((Object)(object)ImperiumTriathlonManager.Instance != (Object)null)
{
ImperiumTriathlonManager.Instance.RegisterLocalBoard(this);
}
}
private void OnDisable()
{
if ((Object)(object)ImperiumTriathlonManager.Instance != (Object)null)
{
ImperiumTriathlonManager.Instance.UnregisterLocalBoard(this);
}
}
public void SetBoardText(string text)
{
if ((Object)(object)scoreText != (Object)null)
{
scoreText.text = text;
}
}
}
public static class RelicConfigManager
{
private static string configPath = Path.Combine(Paths.ConfigPath, "ImperiumEvents.cfg");
public static void SaveConfig(string key, string value)
{
File.AppendAllText(configPath, key + "=" + value + "\n");
}
public static string LoadConfig(string key)
{
if (!File.Exists(configPath))
{
return null;
}
string[] array = File.ReadAllLines(configPath);
foreach (string text in array)
{
if (text.StartsWith(key + "="))
{
return text.Substring(key.Length + 1);
}
}
return null;
}
}
public class RelicRegistration
{
public string PrefabName;
public string DisplayName;
public RequirementConfig[] Requirements;
public string Description;
public int Comfort;
public bool IsWerewolf;
public bool IsHorn;
public RelicRegistration(string prefab, string display, RequirementConfig[] reqs, string desc, int comfort = 0, bool isWerewolf = false, bool isHorn = false)
{
PrefabName = prefab;
DisplayName = display;
Requirements = reqs;
Description = desc;
Comfort = comfort;
IsWerewolf = isWerewolf;
IsHorn = isHorn;
}
}
public static class RelicRegistrar
{
private static readonly List<GameObject> placedWerewolves = new List<GameObject>();
private static bool wasAlreadyRegistered = false;
public static readonly List<RelicRegistration> AllRegistrations = new List<RelicRegistration>
{
new RelicRegistration("Start_Gate", "Start Gate", (RequirementConfig[])(object)new RequirementConfig[2]
{
new RequirementConfig("RoundLog", 10, 0, true),
new RequirementConfig("FineWood", 5, 0, true)
}, "Imperium event Start Gate."),
new RelicRegistration("Finish_Gate", "Finish Gate", (RequirementConfig[])(object)new RequirementConfig[2]
{
new RequirementConfig("RoundLog", 10, 0, true),
new RequirementConfig("FineWood", 5, 0, true)
}, "Imperium event Start Gate."),
new RelicRegistration("Welcome_Banner", "Welcome Banner", (RequirementConfig[])(object)new RequirementConfig[2]
{
new RequirementConfig("Wood", 5, 0, true),
new RequirementConfig("FineWood", 2, 0, true)
}, "Imperium event banner."),
new RelicRegistration("Imperium_Standing_Banner", "Imperium Standing Banner", (RequirementConfig[])(object)new RequirementConfig[2]
{
new RequirementConfig("Wood", 5, 0, true),
new RequirementConfig("FineWood", 2, 0, true)
}, "Imperium event banner."),
new RelicRegistration("Imperium_Hanging_Banner", "Imperium Hanging Banner", (RequirementConfig[])(object)new RequirementConfig[2]
{
new RequirementConfig("Wood", 5, 0, true),
new RequirementConfig("FineWood", 3, 0, true)
}, "Imperium event banner."),
new RelicRegistration("Arrow_Left", "Left Arrow Banner", (RequirementConfig[])(object)new RequirementConfig[2]
{
new RequirementConfig("Wood", 5, 0, true),
new RequirementConfig("FineWood", 3, 0, true)
}, "Imperium event banner."),
new RelicRegistration("Arrow_Right", "Right Arrow Banner", (RequirementConfig[])(object)new RequirementConfig[2]
{
new RequirementConfig("Wood", 5, 0, true),
new RequirementConfig("FineWood", 3, 0, true)
}, "Imperium event banner."),
new RelicRegistration("Arrow_Straight", "Straight Arrow Banner", (RequirementConfig[])(object)new RequirementConfig[2]
{
new RequirementConfig("Wood", 5, 0, true),
new RequirementConfig("FineWood", 2, 0, true)
}, "Imperium event banner."),
new RelicRegistration("Safe_Zone", "Safe Zone Banner", (RequirementConfig[])(object)new RequirementConfig[2]
{
new RequirementConfig("Wood", 5, 0, true),
new RequirementConfig("FineWood", 2, 0, true)
}, "Imperium event banner."),
new RelicRegistration("Danger_Other", "Other kind of danger Banner", (RequirementConfig[])(object)new RequirementConfig[2]
{
new RequirementConfig("Wood", 5, 0, true),
new RequirementConfig("FineWood", 2, 0, true)
}, "Imperium event banner."),
new RelicRegistration("Danger_Troll", "Danger of Troll Banner", (RequirementConfig[])(object)new RequirementConfig[2]
{
new RequirementConfig("Wood", 5, 0, true),
new RequirementConfig("FineWood", 2, 0, true)
}, "Imperium event banner."),
new RelicRegistration("Imperium_Horn", "Horn of Farting", (RequirementConfig[])(object)new RequirementConfig[2]
{
new RequirementConfig("Wood", 5, 0, true),
new RequirementConfig("FineWood", 2, 0, true)
}, "Imperium event banner."),
new RelicRegistration("Start_Rune", "Start Registration", (RequirementConfig[])(object)new RequirementConfig[2]
{
new RequirementConfig("Wood", 5, 0, true),
new RequirementConfig("FineWood", 2, 0, true)
}, "For player registration to the event."),
new RelicRegistration("Finish_Rune", "Finish line", (RequirementConfig[])(object)new RequirementConfig[2]
{
new RequirementConfig("Wood", 5, 0, true),
new RequirementConfig("FineWood", 2, 0, true)
}, "To stop timers."),
new RelicRegistration("Imperium_Scoreboard", "Scoreboard", (RequirementConfig[])(object)new RequirementConfig[2]
{
new RequirementConfig("Wood", 5, 0, true),
new RequirementConfig("FineWood", 2, 0, true)
}, "Timers.")
};
public static void RegisterAllRelics(AssetBundle bundle)
{
if (wasAlreadyRegistered || (Object)(object)bundle == (Object)null)
{
return;
}
int num = 0;
int num2 = 0;
foreach (RelicRegistration allRegistration in AllRegistrations)
{
if (RegisterRelic(bundle, allRegistration))
{
num++;
}
else
{
num2++;
}
}
wasAlreadyRegistered = true;
}
private static bool RegisterRelic(AssetBundle bundle, RelicRegistration reg)
{
//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
//IL_00d5: Expected O, but got Unknown
//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
//IL_0103: Expected O, but got Unknown
//IL_0114: Unknown result type (might be due to invalid IL or missing references)
//IL_0119: Unknown result type (might be due to invalid IL or missing references)
//IL_0121: Unknown result type (might be due to invalid IL or missing references)
//IL_012d: Expected O, but got Unknown
//IL_016a: Unknown result type (might be due to invalid IL or missing references)
//IL_0171: Expected O, but got Unknown
//IL_0188: Unknown result type (might be due to invalid IL or missing references)
//IL_018d: 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)
//IL_01a1: Expected O, but got Unknown
//IL_01b2: Unknown result type (might be due to invalid IL or missing references)
//IL_01b7: 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_01cb: Expected O, but got Unknown
//IL_0229: Unknown result type (might be due to invalid IL or missing references)
//IL_022e: Unknown result type (might be due to invalid IL or missing references)
//IL_023a: Unknown result type (might be due to invalid IL or missing references)
//IL_024b: Unknown result type (might be due to invalid IL or missing references)
//IL_0254: Unknown result type (might be due to invalid IL or missing references)
//IL_0263: Expected O, but got Unknown
//IL_026c: Unknown result type (might be due to invalid IL or missing references)
//IL_0276: Expected O, but got Unknown
if ((Object)(object)bundle == (Object)null)
{
return false;
}
GameObject val = bundle.LoadAsset<GameObject>(reg.PrefabName);
if ((Object)(object)val == (Object)null)
{
return false;
}
((Object)val).name = reg.PrefabName;
ZNetView val2 = val.GetComponent<ZNetView>();
if ((Object)(object)val2 == (Object)null)
{
val2 = val.AddComponent<ZNetView>();
}
val2.m_persistent = true;
val2.m_syncInitialScale = true;
if (!Object.op_Implicit((Object)(object)val.GetComponent<ZSyncTransform>()))
{
val.AddComponent<ZSyncTransform>();
}
Piece val3 = val.GetComponent<Piece>() ?? val.AddComponent<Piece>();
val3.m_name = reg.DisplayName;
val3.m_description = reg.Description;
val3.m_groundOnly = false;
SFX_VFX_Registry.GetEffects(reg.PrefabName, out var vfxPlace, out var sfxPlace, out var destroyVFX, out var destroySFX);
EffectList val4 = new EffectList();
List<EffectData> list = new List<EffectData>();
if ((Object)(object)vfxPlace != (Object)null)
{
list.Add(new EffectData
{
m_prefab = vfxPlace,
m_enabled = true
});
}
if ((Object)(object)sfxPlace != (Object)null)
{
list.Add(new EffectData
{
m_prefab = sfxPlace,
m_enabled = true
});
}
val4.m_effectPrefabs = list.ToArray();
val3.m_placeEffect = val4;
WearNTear val5 = val.GetComponent<WearNTear>() ?? val.AddComponent<WearNTear>();
val5.m_health = 10000f;
val5.m_noRoofWear = true;
EffectList val6 = new EffectList();
List<EffectData> list2 = new List<EffectData>();
if ((Object)(object)destroyVFX != (Object)null)
{
list2.Add(new EffectData
{
m_prefab = destroyVFX,
m_enabled = true
});
}
if ((Object)(object)destroySFX != (Object)null)
{
list2.Add(new EffectData
{
m_prefab = destroySFX,
m_enabled = true
});
}
val6.m_effectPrefabs = list2.ToArray();
val5.m_destroyedEffect = val6;
if (reg.Comfort > 0)
{
val3.m_comfort = reg.Comfort;
}
Sprite val7 = bundle.LoadAsset<Sprite>(reg.PrefabName);
if ((Object)(object)val7 != (Object)null)
{
val3.m_icon = val7;
}
string craftingStation = "piece_workbench";
PieceConfig val8 = new PieceConfig
{
PieceTable = "Hammer",
Category = ImperiumEvents.PlayerPreferredCategory.Value,
CraftingStation = craftingStation,
Requirements = reg.Requirements
};
PieceManager.Instance.AddPiece(new CustomPiece(val, true, val8));
if (reg.IsWerewolf && (Object)(object)val.GetComponent<PlacementWatcher>() == (Object)null)
{
val.AddComponent<PlacementWatcher>().RegisterList = placedWerewolves;
}
return true;
}
}
public class ScoreboardEmissionNight : MonoBehaviour
{
private Renderer rend;
private Material mat;
private Color originalEmission;
private float nextCheckTime;
private bool lastNightState;
private void Awake()
{
//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)
rend = ((Component)this).GetComponent<Renderer>();
if ((Object)(object)rend != (Object)null)
{
mat = rend.material;
if (mat.HasProperty("_EmissionColor"))
{
originalEmission = mat.GetColor("_EmissionColor");
}
}
}
private void Update()
{
//IL_00a8: 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)
if ((Object)(object)mat == (Object)null || (Object)(object)EnvMan.instance == (Object)null || Time.time < nextCheckTime)
{
return;
}
nextCheckTime = Time.time + 2f;
bool flag = EnvMan.IsNight();
if (flag != lastNightState)
{
lastNightState = flag;
if (flag)
{
mat.SetColor("_EmissionColor", originalEmission);
mat.EnableKeyword("_EMISSION");
}
else
{
mat.SetColor("_EmissionColor", Color.black);
mat.DisableKeyword("_EMISSION");
}
}
}
}
public static class SFX_VFX_Registry
{
private static readonly HashSet<string> MetalObjects = new HashSet<string>();
private static readonly HashSet<string> WoodObjects = new HashSet<string>
{
"Imperium_Standing_Banner", "Imperium_Hanging_Banner", "Start_Gate", "Finish_Gate", "Arrow_Left", "Arrow_Right", "Arrow_Straight", "Welcome_Banner", "Danger_Troll", "Danger_Other",
"Safe_Zone", "Imperium_Horn", "Start_Rune", "Finish_Rune", "Imperium_Scoreboard"
};
public static void GetEffects(string prefabName, out GameObject vfxPlace, out GameObject sfxPlace, out GameObject destroyVFX, out GameObject destroySFX)
{
if (MetalObjects.Contains(prefabName))
{
ZNetScene instance = ZNetScene.instance;
vfxPlace = ((instance != null) ? instance.GetPrefab("vfx_Place_stone") : null);
ZNetScene instance2 = ZNetScene.instance;
sfxPlace = ((instance2 != null) ? instance2.GetPrefab("sfx_build_hammer_metal") : null);
ZNetScene instance3 = ZNetScene.instance;
destroyVFX = ((instance3 != null) ? instance3.GetPrefab("vfx_destroyed") : null);
ZNetScene instance4 = ZNetScene.instance;
destroySFX = ((instance4 != null) ? instance4.GetPrefab("sfx_metal_blocked") : null);
}
else if (WoodObjects.Contains(prefabName))
{
ZNetScene instance5 = ZNetScene.instance;
vfxPlace = ((instance5 != null) ? instance5.GetPrefab("vfx_Place_wood") : null);
ZNetScene instance6 = ZNetScene.instance;
sfxPlace = ((instance6 != null) ? instance6.GetPrefab("sfx_build_hammer_wood") : null);
ZNetScene instance7 = ZNetScene.instance;
destroyVFX = ((instance7 != null) ? instance7.GetPrefab("vfx_destroyed") : null);
ZNetScene instance8 = ZNetScene.instance;
destroySFX = ((instance8 != null) ? instance8.GetPrefab("sfx_wood_break") : null);
}
else
{
ZNetScene instance9 = ZNetScene.instance;
vfxPlace = ((instance9 != null) ? instance9.GetPrefab("vfx_Place_stone") : null);
ZNetScene instance10 = ZNetScene.instance;
sfxPlace = ((instance10 != null) ? instance10.GetPrefab("sfx_build_hammer_stone") : null);
ZNetScene instance11 = ZNetScene.instance;
destroyVFX = ((instance11 != null) ? instance11.GetPrefab("vfx_destroyed") : null);
ZNetScene instance12 = ZNetScene.instance;
destroySFX = ((instance12 != null) ? instance12.GetPrefab("sfx_rock_destroyed") : null);
}
}
}
public class StartRuneInteract : MonoBehaviour, Hoverable, Interactable
{
private Piece m_piece;
private void Awake()
{
m_piece = ((Component)this).GetComponent<Piece>();
}
public bool Interact(Humanoid user, bool hold, bool alt)
{
if (hold)
{
return false;
}
Player val = (Player)(object)((user is Player) ? user : null);
if ((Object)(object)val == (Object)null || (Object)(object)ImperiumTriathlonManager.Instance == (Object)null)
{
return false;
}
if (ImperiumTriathlonManager.Instance.IsRaceEnded())
{
if (!ImperiumTriathlonManager.Instance.IsConfiguredAdmin(val))
{
if ((Object)(object)MessageHud.instance != (Object)null)
{
MessageHud.instance.ShowMessage((MessageType)2, "Only configured admin can reset the event.", 0, (Sprite)null, false);
}
return false;
}
ImperiumTriathlonManager.Instance.RequestAdminReset(val);
return true;
}
if (!ImperiumTriathlonManager.Instance.IsRegistrationOpen())
{
if ((Object)(object)MessageHud.instance != (Object)null)
{
MessageHud.instance.ShowMessage((MessageType)2, "Registration is closed.", 0, (Sprite)null, false);
}
return false;
}
ImperiumTriathlonManager.Instance.RequestRegister(val);
return true;
}
public bool UseItem(Humanoid user, ItemData item)
{
return false;
}
public string GetHoverText()
{
string text = (((Object)(object)m_piece != (Object)null) ? m_piece.m_name : "Start Rune");
if ((Object)(object)ImperiumTriathlonManager.Instance != (Object)null && ImperiumTriathlonManager.Instance.IsRaceEnded())
{
return text + "\n[<color=yellow><b>E</b></color>] Admin Reset Event";
}
return text + "\n[<color=yellow><b>E</b></color>] Register for Imperium Triathlon";
}
public string GetHoverName()
{
return ((Object)(object)m_piece != (Object)null) ? m_piece.m_name : "Start Rune";
}
}