using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Newtonsoft.Json;
using UnityEngine;
using UnityEngine.Localization;
using UnityEngine.Localization.Settings;
using UnityEngine.Localization.Tables;
[assembly: CompilationRelaxations(8)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: AssemblyVersion("0.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[Embedded]
[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
internal sealed class RefSafetyRulesAttribute : Attribute
{
public readonly int Version;
public RefSafetyRulesAttribute(int P_0)
{
Version = P_0;
}
}
}
namespace ServiceTracker
{
public class ServiceRecord
{
public string StartedAt;
public string EndedAt;
public string TavernName;
public int GameDay;
public float OpenSeconds;
public float DrainSeconds;
public string EndReason;
public bool JoinedMidService;
public int CustomersArrived;
public int CustomersServed;
public int VipsServed;
public int WalkoutsAfterSeating;
public int FledDanger;
public int TurnedAwayFull;
public int TurnedAwayReputation;
public int TurnedAwayCleanliness;
public int TurnedAwayCantReach;
public int GotDrunk;
public int DrunksBanished;
public int RoomGuests;
public int DishesServed;
public int JustInTime;
public Dictionary<string, int> Dishes = new Dictionary<string, int>();
public long Income;
public long Spent;
public float AvgWaitSeconds;
public float MaxWaitSeconds;
[JsonIgnore]
public int TurnedAway => TurnedAwayFull + TurnedAwayReputation + TurnedAwayCleanliness + TurnedAwayCantReach;
[JsonIgnore]
public int Lost => WalkoutsAfterSeating + FledDanger + TurnedAway;
[JsonIgnore]
public long Net => Income - Spent;
[JsonIgnore]
public float ServedPct
{
get
{
int num = CustomersServed + Lost;
if (num == 0)
{
return 0f;
}
return 100f * (float)CustomersServed / (float)num;
}
}
[JsonIgnore]
public string TopDish
{
get
{
if (Dishes.Count == 0)
{
return "-";
}
return Dishes.OrderByDescending((KeyValuePair<string, int> k) => k.Value).First().Key;
}
}
}
public class History
{
public List<ServiceRecord> Records = new List<ServiceRecord>();
private readonly string _path;
private readonly int _max;
public History(string path, int max)
{
_path = path;
_max = Math.Max(1, max);
}
public void Load()
{
try
{
if (File.Exists(_path))
{
Records = JsonConvert.DeserializeObject<List<ServiceRecord>>(File.ReadAllText(_path)) ?? new List<ServiceRecord>();
}
}
catch (Exception ex)
{
Plugin.Log.LogError((object)("Could not read history, starting fresh (old file kept as .bak): " + ex.Message));
try
{
File.Copy(_path, _path + ".bak", overwrite: true);
}
catch
{
}
Records = new List<ServiceRecord>();
}
}
public void Add(ServiceRecord r)
{
Records.Insert(0, r);
while (Records.Count > _max)
{
Records.RemoveAt(Records.Count - 1);
}
Save();
}
public void Remove(ServiceRecord r)
{
Records.Remove(r);
Save();
}
public void Clear()
{
Records.Clear();
Save();
}
public void Save()
{
try
{
string text = _path + ".tmp";
File.WriteAllText(text, JsonConvert.SerializeObject((object)Records, (Formatting)1));
if (File.Exists(_path))
{
File.Delete(_path);
}
File.Move(text, _path);
}
catch (Exception ex)
{
Plugin.Log.LogError((object)("Could not save history: " + ex.Message));
}
}
}
[BepInPlugin("aletale.servicetracker", "Service Tracker", "1.2.1")]
public class Plugin : BaseUnityPlugin
{
public const string Guid = "aletale.servicetracker";
public const string Name = "Service Tracker";
public const string Version = "1.2.1";
internal static Plugin Inst;
internal static ManualLogSource Log;
internal ConfigEntry<KeyboardShortcut> ToggleKey;
internal ConfigEntry<KeyboardShortcut> EndNowKey;
internal ConfigEntry<bool> ShowLiveHud;
internal ConfigEntry<bool> ShowSummaryPopup;
internal ConfigEntry<float> DrainTimeout;
internal ConfigEntry<int> MaxHistory;
internal Tracker Tracker;
internal History History;
private TrackerUI _ui;
private void Awake()
{
//IL_002c: Unknown result type (might be due to invalid IL or missing references)
//IL_0064: Unknown result type (might be due to invalid IL or missing references)
//IL_0153: Unknown result type (might be due to invalid IL or missing references)
Inst = this;
Log = ((BaseUnityPlugin)this).Logger;
ToggleKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Keys", "ToggleHistoryWindow", new KeyboardShortcut((KeyCode)289, Array.Empty<KeyCode>()), "Open or close the service history window.");
EndNowKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Keys", "EndServiceNow", new KeyboardShortcut((KeyCode)289, (KeyCode[])(object)new KeyCode[1] { (KeyCode)304 }), "Finalize the current service report immediately (use if a customer is stuck).");
ShowLiveHud = ((BaseUnityPlugin)this).Config.Bind<bool>("Display", "ShowLiveHud", true, "Show a small live counter while a service is running.");
ShowSummaryPopup = ((BaseUnityPlugin)this).Config.Bind<bool>("Display", "ShowSummaryPopup", true, "Show a summary popup when a service ends.");
DrainTimeout = ((BaseUnityPlugin)this).Config.Bind<float>("Tracking", "DrainTimeoutSeconds", 240f, "After closing, finalize the report anyway if customers are still inside after this many seconds.");
MaxHistory = ((BaseUnityPlugin)this).Config.Bind<int>("Tracking", "MaxHistory", 200, "How many past services to keep.");
string text = Path.Combine(Paths.ConfigPath, "ServiceTracker_history.json");
History = new History(text, MaxHistory.Value);
History.Load();
Tracker = new Tracker(this);
_ui = new TrackerUI(this);
new Harmony("aletale.servicetracker").PatchAll(typeof(Plugin).Assembly);
Log.LogInfo((object)("Service Tracker 1.2.1 loaded. History file: " + text));
}
private void Update()
{
//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_006d: Unknown result type (might be due to invalid IL or missing references)
//IL_0072: Unknown result type (might be due to invalid IL or missing references)
try
{
Tracker.Tick();
}
catch (Exception ex)
{
Log.LogError((object)("Tracker tick failed: " + ex));
}
KeyboardShortcut value = ToggleKey.Value;
if (((KeyboardShortcut)(ref value)).IsDown() || (_ui.IsOpen && Input.GetKeyDown((KeyCode)27)))
{
_ui.Toggle();
}
value = EndNowKey.Value;
if (((KeyboardShortcut)(ref value)).IsDown())
{
Tracker.ForceEnd();
}
}
private void LateUpdate()
{
_ui.LateUpdate();
}
private void OnGUI()
{
_ui.Draw();
}
private void OnDestroy()
{
Tracker.OnShutdown();
}
}
[HarmonyPatch(typeof(Customer), "OnNetworkSpawn")]
internal static class CustomerSpawnPatch
{
private static void Postfix(Customer __instance)
{
try
{
Plugin.Inst.Tracker.OnCustomerSpawn(__instance);
}
catch (Exception ex)
{
Plugin.Log.LogError((object)ex);
}
}
}
[HarmonyPatch(typeof(Customer), "OnNetworkDespawn")]
internal static class CustomerDespawnPatch
{
private static void Prefix(Customer __instance)
{
try
{
Plugin.Inst.Tracker.OnCustomerDespawn(__instance);
}
catch (Exception ex)
{
Plugin.Log.LogError((object)ex);
}
}
}
public enum Phase
{
Idle,
Open,
Draining
}
internal class CustInfo
{
public ushort Id;
public bool CountedThisSession;
public float SatAt = -1f;
public bool Served;
public bool Guest;
public bool Fled;
public bool Banished;
public bool Vip;
}
internal class Tracker
{
private readonly Plugin _p;
private readonly Dictionary<Customer, CustInfo> _live = new Dictionary<Customer, CustInfo>();
private readonly List<float> _waits = new List<float>();
public Phase Phase;
public ServiceRecord Current;
public ServiceRecord LastFinished;
public float LastFinishedAt = -999f;
private float _openedAt;
private float _closedAt;
private bool? _lastOpen;
private Game _subscribedGame;
private Action<GameEvent, uint, int> _handler;
private float _nextPoll;
private readonly Dictionary<uint, string> _dishNames = new Dictionary<uint, string>();
public int CustomersInside => _live.Where((KeyValuePair<Customer, CustInfo> kv) => (Object)(object)kv.Key != (Object)null && !kv.Value.Guest).Count();
public float PhaseSeconds
{
get
{
if (Phase == Phase.Open)
{
return Time.time - _openedAt;
}
if (Phase == Phase.Draining)
{
return Time.time - _closedAt;
}
return 0f;
}
}
public Tracker(Plugin p)
{
_p = p;
_handler = OnGameEvent;
}
public void Tick()
{
EnsureSubscribed();
GameStatus instance = GameStatus.Instance;
if ((Object)(object)instance == (Object)null || instance.isTavernOpen == null)
{
if (Phase != Phase.Idle)
{
Finish("Left game");
}
_lastOpen = null;
_live.Clear();
return;
}
bool value = instance.isTavernOpen.Value;
bool? lastOpen = _lastOpen;
if (!lastOpen.HasValue)
{
if (value)
{
Start(midService: true);
}
}
else if (value != _lastOpen.Value)
{
if (value)
{
if (Phase == Phase.Draining)
{
Phase = Phase.Open;
}
else
{
Start(midService: false);
}
}
else if (Phase == Phase.Open)
{
Phase = Phase.Draining;
_closedAt = Time.time;
Current.OpenSeconds += _closedAt - _openedAt;
}
}
_lastOpen = value;
if (Time.time >= _nextPoll)
{
_nextPoll = Time.time + 0.25f;
PollCustomers();
}
if (Phase == Phase.Draining)
{
if (CustomersInside == 0)
{
Finish("Emptied");
}
else if (Time.time - _closedAt > _p.DrainTimeout.Value)
{
Finish("Timed out");
}
}
}
private void EnsureSubscribed()
{
Game instance = Game.Instance;
if ((Object)(object)instance == (Object)(object)_subscribedGame)
{
return;
}
if ((Object)(object)_subscribedGame != (Object)null)
{
try
{
Game subscribedGame = _subscribedGame;
subscribedGame.onGameEvent = (Action<GameEvent, uint, int>)Delegate.Remove(subscribedGame.onGameEvent, _handler);
}
catch
{
}
}
_subscribedGame = instance;
if ((Object)(object)instance != (Object)null)
{
instance.onGameEvent = (Action<GameEvent, uint, int>)Delegate.Combine(instance.onGameEvent, _handler);
}
}
private void Start(bool midService)
{
Current = new ServiceRecord
{
StartedAt = DateTime.Now.ToString("yyyy-MM-dd HH:mm"),
TavernName = ReadTavernName(),
GameDay = ReadDay(),
JoinedMidService = midService
};
_waits.Clear();
_openedAt = Time.time;
Phase = Phase.Open;
foreach (CustInfo value in _live.Values)
{
value.CountedThisSession = false;
}
if (!midService)
{
return;
}
foreach (CustInfo value2 in _live.Values)
{
value2.CountedThisSession = true;
Current.CustomersArrived++;
}
}
public void ForceEnd()
{
if (Phase != Phase.Idle)
{
bool num = Phase == Phase.Open;
if (num)
{
Current.OpenSeconds += Time.time - _openedAt;
}
Finish("Ended manually", alreadyClosedOpenTime: true);
if (num)
{
Start(midService: false);
}
}
}
public void OnShutdown()
{
if (Phase != Phase.Idle)
{
Finish("Left game");
}
}
private void Finish(string reason, bool alreadyClosedOpenTime = false)
{
if (Current == null)
{
Phase = Phase.Idle;
return;
}
if (Phase == Phase.Open && !alreadyClosedOpenTime)
{
Current.OpenSeconds += Time.time - _openedAt;
}
if (Phase == Phase.Draining)
{
Current.DrainSeconds = Time.time - _closedAt;
}
Current.EndedAt = DateTime.Now.ToString("yyyy-MM-dd HH:mm");
Current.EndReason = reason;
if (_waits.Count > 0)
{
Current.AvgWaitSeconds = _waits.Average();
Current.MaxWaitSeconds = _waits.Max();
}
if (Current.CustomersArrived > 0 || Current.DishesServed > 0 || Current.Income > 0)
{
_p.History.Add(Current);
LastFinished = Current;
LastFinishedAt = Time.unscaledTime;
}
Current = null;
Phase = Phase.Idle;
foreach (CustInfo value in _live.Values)
{
value.CountedThisSession = false;
}
}
public void OnCustomerSpawn(Customer c)
{
CustInfo custInfo = new CustInfo();
try
{
custInfo.Id = c.id.Value;
}
catch
{
}
_live[c] = custInfo;
if (Phase != Phase.Idle && Current != null)
{
custInfo.CountedThisSession = true;
Current.CustomersArrived++;
}
}
public void OnCustomerDespawn(Customer c)
{
if (!_live.TryGetValue(c, out var value))
{
return;
}
_live.Remove(c);
if (Current != null && value.CountedThisSession && !value.Served && !value.Guest && !value.Banished)
{
if (value.Fled)
{
Current.FledDanger++;
}
else if (value.SatAt >= 0f)
{
Current.WalkoutsAfterSeating++;
}
}
}
private void PollCustomers()
{
//IL_0096: Unknown result type (might be due to invalid IL or missing references)
//IL_009b: Unknown result type (might be due to invalid IL or missing references)
//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
//IL_00cf: Expected I4, but got Unknown
List<Customer> list = null;
foreach (KeyValuePair<Customer, CustInfo> item in _live)
{
Customer key = item.Key;
if ((Object)(object)key == (Object)null)
{
(list ?? (list = new List<Customer>())).Add(key);
continue;
}
CustInfo value = item.Value;
if (value.Id == 0)
{
try
{
value.Id = key.id.Value;
}
catch
{
}
}
try
{
if (key.isVip != null && key.isVip.Value)
{
value.Vip = true;
}
}
catch
{
}
CustomerState value2;
try
{
value2 = key.CurrentState.Value;
}
catch
{
continue;
}
switch (value2 - 2)
{
case 0:
case 1:
if (value.SatAt < 0f)
{
value.SatAt = Time.time;
}
break;
case 5:
if (!value.Served)
{
value.Fled = true;
}
break;
case 7:
case 8:
value.Guest = true;
break;
}
}
if (list == null)
{
return;
}
foreach (Customer item2 in list)
{
_live.Remove(item2);
}
}
private CustInfo FindById(uint id)
{
foreach (CustInfo value in _live.Values)
{
if (value.Id == id)
{
return value;
}
}
return null;
}
private void OnGameEvent(GameEvent e, uint obj, int value)
{
//IL_0010: Unknown result type (might be due to invalid IL or missing references)
//IL_0013: Invalid comparison between Unknown and I4
//IL_0026: Unknown result type (might be due to invalid IL or missing references)
//IL_0029: Unknown result type (might be due to invalid IL or missing references)
//IL_004f: Expected I4, but got Unknown
//IL_0015: Unknown result type (might be due to invalid IL or missing references)
//IL_0018: Invalid comparison between Unknown and I4
//IL_004f: Unknown result type (might be due to invalid IL or missing references)
//IL_0055: Invalid comparison between Unknown and I4
//IL_001d: Unknown result type (might be due to invalid IL or missing references)
//IL_0020: Invalid comparison between Unknown and I4
//IL_005a: Unknown result type (might be due to invalid IL or missing references)
//IL_0060: Unknown result type (might be due to invalid IL or missing references)
//IL_0076: Expected I4, but got Unknown
if (Current == null)
{
return;
}
ServiceRecord current = Current;
if ((int)e <= 11)
{
if ((int)e != 10)
{
if ((int)e == 11 && value > 0)
{
current.Spent += value;
}
}
else if (value > 0)
{
current.Income += value;
}
return;
}
switch (e - 34)
{
case 0:
{
CustInfo custInfo2 = FindById(obj);
if (custInfo2 != null && !custInfo2.Served)
{
custInfo2.Served = true;
current.CustomersServed++;
if (custInfo2.Vip)
{
current.VipsServed++;
}
if (custInfo2.SatAt >= 0f)
{
_waits.Add(Time.time - custInfo2.SatAt);
}
}
else if (custInfo2 == null)
{
current.CustomersServed++;
}
return;
}
case 1:
{
current.DishesServed++;
string key = DishName(obj);
current.Dishes.TryGetValue(key, out var value2);
current.Dishes[key] = value2 + 1;
return;
}
case 4:
current.GotDrunk++;
return;
case 5:
{
current.DrunksBanished++;
CustInfo custInfo = FindById(obj);
if (custInfo != null)
{
custInfo.Banished = true;
}
return;
}
case 7:
current.RoomGuests++;
return;
case 2:
case 3:
case 6:
return;
}
if ((int)e != 154)
{
switch (e - 220)
{
case 0:
current.TurnedAwayFull++;
break;
case 1:
current.TurnedAwayReputation++;
break;
case 2:
current.TurnedAwayCleanliness++;
break;
case 3:
current.TurnedAwayCantReach++;
break;
}
}
else
{
current.JustInTime++;
}
}
private string DishName(uint id)
{
if (_dishNames.TryGetValue(id, out var value))
{
return value;
}
value = "Item #" + id;
try
{
ItemData val = default(ItemData);
if ((Object)(object)ItemManager.Instance != (Object)null && ItemManager.Instance.GetItemData(id, ref val) && (Object)(object)val != (Object)null)
{
string name = val.name;
if (string.IsNullOrEmpty(name))
{
name = ((Object)val).name;
}
if (!string.IsNullOrEmpty(name))
{
value = name;
}
}
}
catch
{
}
_dishNames[id] = value;
return value;
}
private static int ReadDay()
{
try
{
return (int)(((Object)(object)DayNight.Instance != (Object)null) ? DayNight.Instance.day.Value : 0);
}
catch
{
return 0;
}
}
private static string ReadTavernName()
{
try
{
GameStatus instance = GameStatus.Instance;
FieldInfo field = typeof(GameStatus).GetField("tavernName", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
object obj = ((!(field != null)) ? null : field.GetValue(instance));
if (obj == null)
{
return string.Empty;
}
PropertyInfo property = obj.GetType().GetProperty("Value");
object obj2 = ((!(property != null)) ? obj : property.GetValue(obj, null));
return (obj2 == null) ? string.Empty : obj2.ToString();
}
catch
{
return string.Empty;
}
}
}
internal static class DishNames
{
private const string Prefix = "ItemDataName";
private static readonly Dictionary<string, string> _cache = new Dictionary<string, string>();
public static string Display(string key)
{
if (string.IsNullOrEmpty(key) || key == "-")
{
return key;
}
if (_cache.TryGetValue(key, out var value))
{
return value;
}
string text = Localized(key);
if (text == null)
{
return Fallback(key);
}
_cache[key] = text;
return text;
}
private static string Localized(string key)
{
//IL_001b: Unknown result type (might be due to invalid IL or missing references)
//IL_0021: Unknown result type (might be due to invalid IL or missing references)
try
{
if ((Object)(object)LocalizationSettings.SelectedLocale == (Object)null)
{
return null;
}
string localizedString = LocalizationSettings.StringDatabase.GetLocalizedString(TableReference.op_Implicit("ItemData"), TableEntryReference.op_Implicit(key), (Locale)null, (FallbackBehavior)0, Array.Empty<object>());
if (string.IsNullOrEmpty(localizedString) || localizedString == key || localizedString.StartsWith("No translation found"))
{
return Fallback(key);
}
return localizedString;
}
catch
{
return null;
}
}
private static string Fallback(string key)
{
string text = (key.StartsWith("ItemDataName") ? key.Substring("ItemDataName".Length) : key);
StringBuilder stringBuilder = new StringBuilder(text.Length + 8);
for (int i = 0; i < text.Length; i++)
{
char c = text[i];
if (i > 0 && char.IsUpper(c) && !char.IsUpper(text[i - 1]))
{
stringBuilder.Append(' ');
}
stringBuilder.Append(c);
}
return stringBuilder.ToString();
}
}
internal class TrackerUI
{
private readonly Plugin _p;
private bool _open;
private Rect _win = new Rect(80f, 80f, 760f, 520f);
private Vector2 _listScroll;
private Vector2 _detailScroll;
private int _sel;
private bool _confirmClear;
private CursorLockMode _prevLock;
private bool _prevVisible;
private bool _blocking;
private bool _restorePending;
private GUIStyle _h;
private GUIStyle _small;
private GUIStyle _rowSel;
private GUIStyle _row;
private GUIStyle _good;
private GUIStyle _bad;
public bool IsOpen => _open;
public TrackerUI(Plugin p)
{
//IL_0015: Unknown result type (might be due to invalid IL or missing references)
//IL_001a: Unknown result type (might be due to invalid IL or missing references)
_p = p;
}
internal static bool PlayerIsFree()
{
//IL_0010: Unknown result type (might be due to invalid IL or missing references)
//IL_0016: Invalid comparison between Unknown and I4
PlayerInventory instance = PlayerInventory.Instance;
if (!((Object)(object)instance == (Object)null))
{
return (int)instance.state == 0;
}
return true;
}
public void Toggle()
{
//IL_0080: 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_0034: Unknown result type (might be due to invalid IL or missing references)
//IL_0069: Unknown result type (might be due to invalid IL or missing references)
if (!_open && !PlayerIsFree())
{
return;
}
_open = !_open;
_confirmClear = false;
if (_open)
{
_prevLock = Cursor.lockState;
_prevVisible = Cursor.visible;
_sel = 0;
_restorePending = false;
_blocking = false;
PlayerInventory instance = PlayerInventory.Instance;
if ((Object)(object)instance != (Object)null && (int)instance.state == 0)
{
instance.SetState((State)1);
_blocking = true;
}
}
else
{
Cursor.lockState = _prevLock;
Cursor.visible = _prevVisible;
if (_blocking)
{
_restorePending = true;
}
_blocking = false;
}
}
public void LateUpdate()
{
//IL_001f: Unknown result type (might be due to invalid IL or missing references)
//IL_0025: Invalid comparison between Unknown and I4
//IL_004e: Unknown result type (might be due to invalid IL or missing references)
//IL_0054: Invalid comparison between Unknown and I4
if (_restorePending)
{
_restorePending = false;
PlayerInventory instance = PlayerInventory.Instance;
if ((Object)(object)instance != (Object)null && (int)instance.state == 1)
{
instance.SetState((State)0);
}
}
if (!_open)
{
return;
}
if (_blocking)
{
PlayerInventory instance2 = PlayerInventory.Instance;
if ((Object)(object)instance2 == (Object)null || (int)instance2.state != 1)
{
Toggle();
return;
}
}
Cursor.lockState = (CursorLockMode)0;
Cursor.visible = true;
}
private void Styles()
{
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
//IL_001b: Unknown result type (might be due to invalid IL or missing references)
//IL_0023: Unknown result type (might be due to invalid IL or missing references)
//IL_002f: Expected O, but got Unknown
//IL_003a: Unknown result type (might be due to invalid IL or missing references)
//IL_003f: Unknown result type (might be due to invalid IL or missing references)
//IL_004c: Expected O, but got Unknown
//IL_0057: Unknown result type (might be due to invalid IL or missing references)
//IL_005c: Unknown result type (might be due to invalid IL or missing references)
//IL_0063: Unknown result type (might be due to invalid IL or missing references)
//IL_0070: Expected O, but got Unknown
//IL_0077: Unknown result type (might be due to invalid IL or missing references)
//IL_007c: Unknown result type (might be due to invalid IL or missing references)
//IL_0088: Expected O, but got Unknown
//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
//IL_00c1: Expected O, but got Unknown
//IL_00db: 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_00fa: Expected O, but got Unknown
//IL_0114: Unknown result type (might be due to invalid IL or missing references)
if (_h == null)
{
_h = new GUIStyle(GUI.skin.label)
{
fontSize = 15,
fontStyle = (FontStyle)1
};
_small = new GUIStyle(GUI.skin.label)
{
fontSize = 12
};
_row = new GUIStyle(GUI.skin.button)
{
alignment = (TextAnchor)3,
fontSize = 12
};
_rowSel = new GUIStyle(_row)
{
fontStyle = (FontStyle)1
};
_rowSel.normal.textColor = new Color(1f, 0.85f, 0.4f);
_good = new GUIStyle(GUI.skin.label);
_good.normal.textColor = new Color(0.55f, 0.9f, 0.55f);
_bad = new GUIStyle(GUI.skin.label);
_bad.normal.textColor = new Color(1f, 0.55f, 0.5f);
}
}
public void Draw()
{
//IL_0093: Unknown result type (might be due to invalid IL or missing references)
//IL_009f: Unknown result type (might be due to invalid IL or missing references)
//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
//IL_00d2: Expected O, but got Unknown
//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
Styles();
Tracker tracker = _p.Tracker;
if (_p.ShowLiveHud.Value && tracker.Phase != Phase.Idle && tracker.Current != null && !_open)
{
DrawLiveHud(tracker);
}
if (_p.ShowSummaryPopup.Value && tracker.LastFinished != null && !_open && Time.unscaledTime - tracker.LastFinishedAt < 20f)
{
DrawPopup(tracker.LastFinished);
}
if (_open)
{
_win = GUILayout.Window(6177219, _win, new WindowFunction(Window), string.Concat("Service History (", _p.ToggleKey.Value, " to close)"), Array.Empty<GUILayoutOption>());
}
}
private void DrawLiveHud(Tracker t)
{
//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
//IL_0116: Unknown result type (might be due to invalid IL or missing references)
ServiceRecord current = t.Current;
string text = ((t.Phase != Phase.Open) ? ("CLOSING, " + t.CustomersInside + " still inside (" + Clock(t.PhaseSeconds) + ")") : ("OPEN " + Clock(t.PhaseSeconds)));
string text2 = text + " Served " + current.CustomersServed + " Lost " + current.Lost + " Dishes " + current.DishesServed + " +" + current.Income + "g";
GUI.Box(new Rect(10f, 10f, 560f, 26f), string.Empty);
GUI.Label(new Rect(18f, 13f, 550f, 22f), text2, _small);
}
private void DrawPopup(ServiceRecord r)
{
//IL_0028: Unknown result type (might be due to invalid IL or missing references)
//IL_005b: Unknown result type (might be due to invalid IL or missing references)
//IL_01ff: Unknown result type (might be due to invalid IL or missing references)
float num = 300f;
float num2 = 168f;
Rect val = default(Rect);
((Rect)(ref val))..ctor((float)Screen.width - num - 16f, 16f, num, num2);
GUI.Box(val, "Service complete");
GUILayout.BeginArea(new Rect(((Rect)(ref val)).x + 12f, ((Rect)(ref val)).y + 24f, num - 24f, num2 - 30f));
GUILayout.Label("Served " + r.CustomersServed + " of " + (r.CustomersServed + r.Lost) + " (" + r.ServedPct.ToString("0") + "%)", _small, Array.Empty<GUILayoutOption>());
GUILayout.Label("Income +" + r.Income + "g Spent -" + r.Spent + "g", _small, Array.Empty<GUILayoutOption>());
GUILayout.Label("Dishes " + r.DishesServed + " Top: " + DishNames.Display(r.TopDish), _small, Array.Empty<GUILayoutOption>());
GUILayout.Label("Avg wait " + r.AvgWaitSeconds.ToString("0") + "s Longest " + r.MaxWaitSeconds.ToString("0") + "s", _small, Array.Empty<GUILayoutOption>());
GUILayout.Label("Open " + Clock(r.OpenSeconds) + " Wind-down " + Clock(r.DrainSeconds), _small, Array.Empty<GUILayoutOption>());
GUILayout.Label(string.Concat("Press ", _p.ToggleKey.Value, " for full history"), _small, Array.Empty<GUILayoutOption>());
GUILayout.EndArea();
}
private void Window(int id)
{
//IL_01ef: Unknown result type (might be due to invalid IL or missing references)
//IL_0203: Unknown result type (might be due to invalid IL or missing references)
//IL_0208: Unknown result type (might be due to invalid IL or missing references)
//IL_03b2: Unknown result type (might be due to invalid IL or missing references)
//IL_03c6: Unknown result type (might be due to invalid IL or missing references)
//IL_03cb: Unknown result type (might be due to invalid IL or missing references)
//IL_046e: Unknown result type (might be due to invalid IL or missing references)
List<ServiceRecord> records = _p.History.Records;
Tracker tracker = _p.Tracker;
GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
GUILayout.Label((tracker.Phase == Phase.Idle) ? "No service running" : ((tracker.Phase != Phase.Open) ? ("Closing: " + tracker.CustomersInside + " customers still inside") : ("Service running: " + Clock(tracker.PhaseSeconds))), _h, Array.Empty<GUILayoutOption>());
GUILayout.FlexibleSpace();
if (tracker.Phase != Phase.Idle && GUILayout.Button("End report now", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(130f) }))
{
tracker.ForceEnd();
}
GUILayout.EndHorizontal();
if (records.Count > 0)
{
List<ServiceRecord> list = records.Take(10).ToList();
GUILayout.Label("Last " + list.Count + " services: avg served " + list.Average((ServiceRecord x) => x.ServedPct).ToString("0") + "%, avg income " + ((IEnumerable<ServiceRecord>)list).Average((Func<ServiceRecord, double>)((ServiceRecord x) => x.Income)).ToString("0") + "g, avg wait " + list.Average((ServiceRecord x) => x.AvgWaitSeconds).ToString("0") + "s", _small, Array.Empty<GUILayoutOption>());
}
GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
GUILayout.BeginVertical((GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(300f) });
_listScroll = GUILayout.BeginScrollView(_listScroll, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandHeight(true) });
if (records.Count == 0)
{
GUILayout.Label("No services recorded yet. Open the tavern to start one.", _small, Array.Empty<GUILayoutOption>());
}
for (int num = 0; num < records.Count; num++)
{
ServiceRecord serviceRecord = records[num];
if (GUILayout.Button("Day " + serviceRecord.GameDay + " " + serviceRecord.StartedAt.Substring(Math.Max(0, serviceRecord.StartedAt.Length - 5)) + " " + serviceRecord.CustomersServed + " served +" + serviceRecord.Income + "g", (num != _sel) ? _row : _rowSel, Array.Empty<GUILayoutOption>()))
{
_sel = num;
_confirmClear = false;
}
}
GUILayout.EndScrollView();
GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
if (!_confirmClear)
{
if (records.Count > 0 && GUILayout.Button("Clear all", Array.Empty<GUILayoutOption>()))
{
_confirmClear = true;
}
}
else
{
GUILayout.Label("Delete all history?", _bad, Array.Empty<GUILayoutOption>());
if (GUILayout.Button("Yes", Array.Empty<GUILayoutOption>()))
{
_p.History.Clear();
_confirmClear = false;
_sel = 0;
}
if (GUILayout.Button("No", Array.Empty<GUILayoutOption>()))
{
_confirmClear = false;
}
}
GUILayout.EndHorizontal();
GUILayout.EndVertical();
GUILayout.BeginVertical(Array.Empty<GUILayoutOption>());
_detailScroll = GUILayout.BeginScrollView(_detailScroll, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandHeight(true) });
if (records.Count > 0)
{
if (_sel >= records.Count)
{
_sel = records.Count - 1;
}
Details(records[_sel]);
}
GUILayout.EndScrollView();
if (records.Count > 0 && GUILayout.Button("Delete this service", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(160f) }))
{
_p.History.Remove(records[_sel]);
}
GUILayout.EndVertical();
GUILayout.EndHorizontal();
GUI.DragWindow(new Rect(0f, 0f, 10000f, 22f));
}
private void Details(ServiceRecord r)
{
GUILayout.Label(((!string.IsNullOrEmpty(r.TavernName)) ? (r.TavernName + ", ") : string.Empty) + "Day " + r.GameDay, _h, Array.Empty<GUILayoutOption>());
GUILayout.Label(r.StartedAt + " to " + (r.EndedAt ?? "?") + " (" + r.EndReason + ")", _small, Array.Empty<GUILayoutOption>());
if (r.JoinedMidService)
{
GUILayout.Label("Joined partway through, so this service is incomplete.", _bad, Array.Empty<GUILayoutOption>());
}
GUILayout.Space(6f);
Section("Time");
Row("Open", Clock(r.OpenSeconds));
Row("Wind-down after closing", Clock(r.DrainSeconds));
Row("Average wait for first dish", r.AvgWaitSeconds.ToString("0") + "s");
Row("Longest wait", r.MaxWaitSeconds.ToString("0") + "s");
Section("Customers");
Row("Arrived", r.CustomersArrived.ToString());
Row("Served", r.CustomersServed + " (" + r.ServedPct.ToString("0") + "%)", _good);
if (r.VipsServed > 0)
{
Row("VIPs served", r.VipsServed.ToString());
}
Row("Walked out after sitting", r.WalkoutsAfterSeating.ToString(), (r.WalkoutsAfterSeating <= 0) ? null : _bad);
if (r.TurnedAwayFull > 0)
{
Row("Turned away: no seats", r.TurnedAwayFull.ToString(), _bad);
}
if (r.TurnedAwayReputation > 0)
{
Row("Turned away: reputation", r.TurnedAwayReputation.ToString(), _bad);
}
if (r.TurnedAwayCleanliness > 0)
{
Row("Turned away: dirty tavern", r.TurnedAwayCleanliness.ToString(), _bad);
}
if (r.TurnedAwayCantReach > 0)
{
Row("Turned away: couldn't reach seat", r.TurnedAwayCantReach.ToString(), _bad);
}
if (r.FledDanger > 0)
{
Row("Fled danger", r.FledDanger.ToString(), _bad);
}
if (r.GotDrunk > 0)
{
Row("Got drunk", r.GotDrunk.ToString());
}
if (r.DrunksBanished > 0)
{
Row("Drunks thrown out", r.DrunksBanished.ToString());
}
if (r.RoomGuests > 0)
{
Row("Room guests checked in", r.RoomGuests.ToString());
}
Section("Money");
Row("Income", "+" + r.Income + "g", _good);
Row("Spent during service", "-" + r.Spent + "g");
Row("Net", r.Net + "g", (r.Net < 0) ? _bad : _good);
Section("Dishes (" + r.DishesServed + " served, " + r.JustInTime + " just in time)");
foreach (KeyValuePair<string, int> item in r.Dishes.OrderByDescending((KeyValuePair<string, int> k) => k.Value))
{
Row(DishNames.Display(item.Key), item.Value.ToString());
}
}
private void Section(string s)
{
GUILayout.Space(6f);
GUILayout.Label(s, _h, Array.Empty<GUILayoutOption>());
}
private void Row(string k, string v, GUIStyle vs = null)
{
GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
GUILayout.Label(k, _small, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(230f) });
GUILayout.Label(v, vs ?? _small, Array.Empty<GUILayoutOption>());
GUILayout.EndHorizontal();
}
private static string Clock(float s)
{
if (s < 0f)
{
s = 0f;
}
int num = (int)(s / 60f);
int num2 = (int)(s % 60f);
return num + ":" + num2.ToString("00");
}
}
}