using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using ExitGames.Client.Photon;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Photon.Pun;
using Photon.Realtime;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Controls;
using UnityEngine.Localization;
using UnityEngine.Localization.Settings;
using Zorro.Core;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyCompany("U-FESNOS")]
[assembly: AssemblyProduct("DealManager")]
[assembly: AssemblyTitle("DealManager")]
[assembly: AssemblyCopyright("U-FESNOS")]
[assembly: AssemblyFileVersion("1.1.1.0")]
[assembly: AssemblyVersion("1.1.1.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[Embedded]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
internal sealed class NullableAttribute : Attribute
{
public readonly byte[] NullableFlags;
public NullableAttribute(byte P_0)
{
NullableFlags = new byte[1] { P_0 };
}
public NullableAttribute(byte[] P_0)
{
NullableFlags = P_0;
}
}
[CompilerGenerated]
[Embedded]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
internal sealed class NullableContextAttribute : Attribute
{
public readonly byte Flag;
public NullableContextAttribute(byte P_0)
{
Flag = P_0;
}
}
[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 CWDealManager
{
[ContentWarningPlugin("U-FESNOS.DealManager", "1.1.1", true)]
[BepInPlugin("U-FESNOS.DealManager", "CWDealManager", "1.1.1")]
public class Plugin : BaseUnityPlugin
{
public const string Guid = "U-FESNOS.DealManager";
public const string Name = "CWDealManager";
public const string Version = "1.1.1";
internal static Plugin Instance;
internal static ManualLogSource Log;
internal static ConfigEntry<Key> PanelKey;
internal static ConfigEntry<int> MaxConcurrent;
internal static ConfigEntry<int> MaxAcceptsPerWeek;
internal static ConfigEntry<float> FeeRate;
internal static ConfigEntry<int> MinFee;
internal static ConfigEntry<bool> FreeWithFreeShop;
internal static ConfigEntry<bool> SoftwareCursor;
internal static bool PanelOpen;
private void Awake()
{
//IL_0107: Unknown result type (might be due to invalid IL or missing references)
//IL_010d: Expected O, but got Unknown
Instance = this;
Log = ((BaseUnityPlugin)this).Logger;
Lang.Bind(((BaseUnityPlugin)this).Config);
PanelKey = ((BaseUnityPlugin)this).Config.Bind<Key>("General", "PanelKey", (Key)100, "Key to open / close the quest panel / クエスト管理パネルを開閉するキー");
MaxConcurrent = ((BaseUnityPlugin)this).Config.Bind<int>("Deals", "MaxConcurrentDeals", 3, "How many quests can be active at once / 同時に受注できるクエストの数");
MaxAcceptsPerWeek = ((BaseUnityPlugin)this).Config.Bind<int>("Deals", "MaxAcceptsPerWeek", 3, "How many quests can be accepted per week. An accepted offer is replaced by a new one until this limit is reached / 1週間に受注できる数。受注した枠には新しい候補が補充され、この数に達すると候補がなくなる");
FeeRate = ((BaseUnityPlugin)this).Config.Bind<float>("Delivery", "FeeRate", 0.5f, "Redelivery fee = total shop price of the items x this rate / 再送の送料 = 物資のショップ価格の合計 × この割合");
MinFee = ((BaseUnityPlugin)this).Config.Bind<int>("Delivery", "MinFee", 20, "Minimum redelivery fee ($) / 再送の送料の最低額");
FreeWithFreeShop = ((BaseUnityPlugin)this).Config.Bind<bool>("Delivery", "FreeWithFreeShop", true, "Make redelivery free when the FreeShop mod is installed / FreeShop Mod が入っていれば送料を無料にする");
SoftwareCursor = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "SoftwareCursor", true, "Draw an arrow cursor on the panel (fallback if the system cursor is not visible) / パネル上に矢印カーソルを描画する");
Harmony val = new Harmony("U-FESNOS.DealManager");
val.PatchAll(typeof(Patches));
Log.LogInfo((object)$"CWDealManager loaded. Patched {val.GetPatchedMethods().Count()} methods.");
}
private void Start()
{
Net.Register();
}
private void OnDestroy()
{
Net.Unregister();
}
internal static void ForceCursor()
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
if ((int)Cursor.lockState != 0)
{
Cursor.lockState = (CursorLockMode)0;
}
if (!Cursor.visible)
{
Cursor.visible = true;
}
}
private void LateUpdate()
{
if (PanelOpen)
{
ForceCursor();
}
}
private void Update()
{
//IL_000e: 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)
Keyboard current = Keyboard.current;
if (current != null)
{
if ((int)PanelKey.Value != 0 && ((ButtonControl)current[PanelKey.Value]).wasPressedThisFrame)
{
PanelOpen = !PanelOpen && (Object)(object)Player.localPlayer != (Object)null;
}
else if (PanelOpen && ((ButtonControl)current[(Key)60]).wasPressedThisFrame)
{
PanelOpen = false;
}
}
if (PanelOpen && (Object)(object)Player.localPlayer == (Object)null)
{
PanelOpen = false;
}
Net.Register();
Manager.Tick();
}
private void OnGUI()
{
Ui.Draw();
}
}
internal sealed class Tracked
{
public int Id;
public NetworkDealBase Deal;
public DEAL_STATE LastState;
public float NextRedeliverTime;
}
internal static class Manager
{
internal static readonly List<Tracked> All = new List<Tracked>();
internal static int AcceptsThisWeek;
private static int nextId = 1;
private static bool dirty = true;
private static float nextBroadcast;
private static float resyncAt = -1f;
private static bool? freeShop;
private static readonly List<DIFFICULTY> AllDifficulties = new List<DIFFICULTY>
{
(DIFFICULTY)10,
(DIFFICULTY)50,
(DIFFICULTY)100,
(DIFFICULTY)150,
(DIFFICULTY)200
};
internal static bool IsHost => PhotonNetwork.IsMasterClient;
internal static NetworkDealBase? Active => NetworkDealBoss.activeDeal;
internal static bool FreeShopInstalled
{
get
{
if (!freeShop.HasValue)
{
freeShop = Chainloader.PluginInfos.ContainsKey("FreeShop") || Chainloader.PluginInfos.Values.Any((PluginInfo p) => p.Metadata.Name.Replace(" ", string.Empty).Equals("FreeShop", StringComparison.OrdinalIgnoreCase));
}
return freeShop.Value;
}
}
internal static bool DeliveryIsFree
{
get
{
if (FreeShopInstalled)
{
return Plugin.FreeWithFreeShop.Value;
}
return false;
}
}
internal static void MarkDirty()
{
dirty = true;
}
internal static Tracked? Find(int id)
{
return All.FirstOrDefault((Tracked t) => t.Id == id);
}
internal static Tracked? FindDeal(NetworkDealBase? deal)
{
if (deal != null)
{
return All.FirstOrDefault((Tracked t) => t.Deal == deal);
}
return null;
}
internal static Tracked Track(NetworkDealBase deal)
{
//IL_002d: Unknown result type (might be due to invalid IL or missing references)
//IL_0032: Unknown result type (might be due to invalid IL or missing references)
Tracked tracked = FindDeal(deal);
if (tracked != null)
{
return tracked;
}
tracked = new Tracked
{
Id = nextId++,
Deal = deal,
LastState = deal.State
};
All.Add(tracked);
dirty = true;
return tracked;
}
internal static void Clear()
{
All.Clear();
AcceptsThisWeek = 0;
dirty = true;
}
internal static void Tick()
{
//IL_005e: 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_0064: Unknown result type (might be due to invalid IL or missing references)
//IL_0066: Unknown result type (might be due to invalid IL or missing references)
//IL_0071: 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)
//IL_008a: Unknown result type (might be due to invalid IL or missing references)
//IL_008c: Invalid comparison between Unknown and I4
//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
//IL_00ce: Invalid comparison between Unknown and I4
//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
if (!PhotonNetwork.InRoom || !IsHost)
{
return;
}
NetworkDealBase active = Active;
if (active != null)
{
Track(active);
}
else if (All.Count > 0 && (Object)(object)NetworkDealBoss.me != (Object)null)
{
FocusNext();
}
foreach (Tracked item in All)
{
DEAL_STATE state = item.Deal.State;
if (state == item.LastState)
{
continue;
}
item.LastState = state;
dirty = true;
if (item.Deal != Active)
{
if ((int)state == 3)
{
Ui.Toast(Msg.Of(MsgId.DealSucceeded, Msgs.DealArg(item.Deal), ((object)Plugin.PanelKey.Value/*cast due to .constrained prefix*/).ToString()));
}
else if ((int)state == 2)
{
Ui.Toast(Msg.Of(MsgId.DealFailed, Msgs.DealArg(item.Deal)));
}
}
}
if (resyncAt > 0f && Time.unscaledTime >= resyncAt)
{
resyncAt = -1f;
if ((Object)(object)NetworkDealBoss.me != (Object)null && Active != null)
{
NetworkDealBoss.me.HardSyncDeal();
}
}
if ((dirty && Time.unscaledTime >= nextBroadcast) || Time.unscaledTime >= nextBroadcast + 5f)
{
dirty = false;
nextBroadcast = Time.unscaledTime + 0.5f;
Net.BroadcastState();
}
}
internal static IEnumerable<NetworkDealBase> Background()
{
NetworkDealBase active = Active;
return (from t in All
where t.Deal != active
select t.Deal).ToList();
}
internal static void UpdateBackground()
{
foreach (NetworkDealBase item in Background())
{
try
{
item.Update();
if (item.IsDirty)
{
item.ClearDirty();
dirty = true;
}
}
catch (Exception arg)
{
Plugin.Log.LogError((object)$"Background deal update failed: {arg}");
}
}
}
internal static void ForEachBackground(Action<NetworkDealBase> action)
{
foreach (NetworkDealBase item in Background())
{
try
{
action(item);
}
catch (Exception arg)
{
Plugin.Log.LogError((object)$"Background deal event failed: {arg}");
}
}
dirty = true;
}
internal static void Focus(Tracked t)
{
if (t.Deal != Active)
{
NetworkDealBoss.activeDeal = t.Deal;
NetworkDealBoss me = NetworkDealBoss.me;
if (me != null)
{
me.HardSyncDeal();
}
resyncAt = Time.unscaledTime + 1.5f;
dirty = true;
}
}
internal static void FocusNext()
{
if (Active == null && All.Count != 0 && !((Object)(object)NetworkDealBoss.me == (Object)null))
{
Focus(All.FirstOrDefault((Tracked t) => t.Deal.IsSuccess) ?? All[0]);
}
}
internal static Msg Accept(int offerIndex, int expectedDealIndex)
{
//IL_0153: Unknown result type (might be due to invalid IL or missing references)
RoomStatsHolder roomStats = SurfaceNetworkHandler.RoomStats;
NetworkDealBase[] array = ((roomStats != null) ? roomStats.NetworkDealsToSelect : null);
if (roomStats == null || array == null || offerIndex < 0 || offerIndex >= array.Length || array[offerIndex] == null)
{
return Msg.Of(MsgId.OfferGone);
}
NetworkDealBase offer = array[offerIndex];
if (expectedDealIndex >= 0 && offer.GetIndex() != expectedDealIndex)
{
return Msg.Of(MsgId.OffersChanged);
}
if ((Object)(object)NetworkDealBoss.me == (Object)null || (Object)(object)ShopHandler.Instance == (Object)null)
{
return Msg.Of(MsgId.AcceptOnlyAtBase);
}
if (All.Count >= Math.Max(1, Plugin.MaxConcurrent.Value))
{
return Msg.Of(MsgId.MaxConcurrent, Plugin.MaxConcurrent.Value.ToString());
}
if (AcceptsThisWeek >= Math.Max(1, Plugin.MaxAcceptsPerWeek.Value))
{
return Msg.Of(MsgId.WeekLimit);
}
if (Active == null)
{
NetworkDealBoss.me.AddDeal(offer);
return Msg.Of(MsgId.Accepted, Msgs.DealArg(offer));
}
NetworkDealBase dealFromIndex = SingletonAsset<NetworkDealDataBase>.Instance.GetDealFromIndex((int)offer.GetIndex());
DealRewardBase rewardFromIndex = SingletonAsset<DealRewardDatabase>.Instance.GetRewardFromIndex((int)offer.reward.GetIndex());
dealFromIndex.Init(rewardFromIndex, offer.difficulty);
Track(dealFromIndex);
try
{
dealFromIndex.SpawnSponsorItem();
}
catch (Exception arg)
{
Plugin.Log.LogError((object)$"SpawnSponsorItem failed: {arg}");
}
AcceptsThisWeek++;
UpdateOffersAfterAccept(array, (NetworkDealBase o) => o == offer);
dirty = true;
return Msg.Of(MsgId.Accepted, Msgs.DealArg(dealFromIndex));
}
internal static Msg Cancel(int id)
{
Tracked tracked = Find(id);
if (tracked == null)
{
return Msg.Of(MsgId.NotFound);
}
string text = Msgs.DealArg(tracked.Deal);
if (tracked.Deal == Active)
{
if ((Object)(object)NetworkDealBoss.me == (Object)null)
{
return Msg.Of(MsgId.OnlyAtBase);
}
NetworkDealBoss.me.RemoveDeal(tracked.Deal);
}
else
{
All.Remove(tracked);
}
dirty = true;
return Msg.Of(tracked.Deal.IsFailed ? MsgId.Dismissed : MsgId.Abandoned, text);
}
internal static Msg Claim(int id)
{
Tracked tracked = Find(id);
if (tracked == null)
{
return Msg.Of(MsgId.NotFound);
}
if (!tracked.Deal.IsSuccess)
{
return Msg.Of(MsgId.NotDone);
}
if ((Object)(object)NetworkDealBoss.me == (Object)null)
{
return Msg.Of(MsgId.ClaimOnlyAtBase);
}
Focus(tracked);
NetworkDealBoss.me.ClaimReward();
return Msg.Of(MsgId.Claimed, Msgs.DealArg(tracked.Deal));
}
internal static Msg Show(int id)
{
Tracked tracked = Find(id);
if (tracked == null)
{
return Msg.Of(MsgId.NotFound);
}
if ((Object)(object)NetworkDealBoss.me == (Object)null)
{
return Msg.Of(MsgId.OnlyAtBase);
}
Focus(tracked);
return Msg.Of(MsgId.Shown, Msgs.DealArg(tracked.Deal));
}
internal static Msg Redeliver(int id)
{
Tracked tracked = Find(id);
if (tracked == null)
{
return Msg.Of(MsgId.NotFound);
}
if (tracked.Deal.IsDone)
{
return Msg.Of(MsgId.DoneNoRedeliver);
}
List<Item> list = Items(tracked.Deal);
if (list.Count == 0)
{
return Msg.Of(MsgId.NoItems);
}
ShopHandler instance = ShopHandler.Instance;
RoomStatsHolder roomStats = SurfaceNetworkHandler.RoomStats;
if ((Object)(object)instance == (Object)null || roomStats == null)
{
return Msg.Of(MsgId.RedeliverOnlyAtBase);
}
if (Time.unscaledTime < tracked.NextRedeliverTime)
{
return Msg.Of(MsgId.Wait);
}
int num = Fee(list);
if (num > 0)
{
if (!roomStats.CanAfford(num))
{
return Msg.Of(MsgId.NotEnoughMoney, num.ToString());
}
roomStats.RemoveMoney(num);
}
object? value = AccessTools.Field(typeof(ShopHandler), "m_PhotonView").GetValue(instance);
PhotonView val = (PhotonView)((value is PhotonView) ? value : null);
if ((Object)(object)val == (Object)null)
{
return Msg.Of(MsgId.DroneFailed);
}
val.RPC("RPCA_SpawnDrone", (RpcTarget)0, new object[1] { list.Select((Item i) => i.id).ToArray() });
tracked.NextRedeliverTime = Time.unscaledTime + 5f;
dirty = true;
if (num <= 0)
{
return Msg.Of(MsgId.RedeliveredFree, Msgs.DealArg(tracked.Deal));
}
return Msg.Of(MsgId.Redelivered, Msgs.DealArg(tracked.Deal), num.ToString());
}
internal static List<Item> Items(NetworkDealBase deal)
{
List<Item> list = new List<Item>();
List<string> list2 = null;
try
{
list2 = deal.PersistentIdOfItem;
}
catch
{
}
if (list2 == null)
{
return list;
}
foreach (string item in list2)
{
if (!string.IsNullOrEmpty(item))
{
Item val = null;
if (ItemDatabase.TryGetItemFromPersistentID(new Guid(item), ref val) && (Object)(object)val != (Object)null)
{
list.Add(val);
}
}
}
return list;
}
internal static int Fee(List<Item> items)
{
if (DeliveryIsFree)
{
return 0;
}
int num = items.Sum((Item i) => Math.Max(0, i.price));
return Math.Max(Plugin.MinFee.Value, Mathf.CeilToInt((float)num * Plugin.FeeRate.Value));
}
internal static int FeeFor(NetworkDealBase deal)
{
List<Item> list = Items(deal);
if (list.Count != 0)
{
return Fee(list);
}
return -1;
}
internal static void UpdateOffersAfterAccept(NetworkDealBase[] before, Func<NetworkDealBase, bool> isAccepted)
{
RoomStatsHolder roomStats = SurfaceNetworkHandler.RoomStats;
if (roomStats != null && before != null && before.Length != 0)
{
List<NetworkDealBase> list = before.Where((NetworkDealBase o) => o != null).ToList();
NetworkDealBase val = list.FirstOrDefault(isAccepted);
if (val != null)
{
list.Remove(val);
}
if (AcceptsThisWeek >= Math.Max(1, Plugin.MaxAcceptsPerWeek.Value))
{
list.Clear();
}
else
{
Refill(list, before.Length);
}
roomStats.SetNetworkDealsToSelect(list.ToArray());
}
}
private static void Refill(List<NetworkDealBase> list, int target)
{
//IL_008a: Unknown result type (might be due to invalid IL or missing references)
//IL_0097: Unknown result type (might be due to invalid IL or missing references)
//IL_0085: Unknown result type (might be due to invalid IL or missing references)
NetworkDealDataBase instance = SingletonAsset<NetworkDealDataBase>.Instance;
for (int i = 0; i < 30; i++)
{
if (list.Count >= target)
{
break;
}
NetworkDealBase candidate = instance.GetWeightedRandomDeal(AllDifficulties, 1, false).FirstOrDefault();
if (candidate != null)
{
if (!list.Any((NetworkDealBase o) => o.GetIndex() == candidate.GetIndex()))
{
NetworkDealBase dealFromIndex = instance.GetDealFromIndex((int)candidate.GetIndex());
List<DIFFICULTY> allowedDifficulties = dealFromIndex.AllowedDifficulties;
DIFFICULTY val = (DIFFICULTY)((allowedDifficulties == null || allowedDifficulties.Count <= 0) ? 50 : ((int)allowedDifficulties[Random.Range(0, allowedDifficulties.Count)]));
dealFromIndex.Init(SingletonAsset<DealRewardDatabase>.Instance.GetRandom(), val);
list.Add(dealFromIndex);
}
continue;
}
break;
}
}
}
internal static class Patches
{
private static NetworkDealBase[]? offersBeforeAccept;
[HarmonyPrefix]
[HarmonyPatch(typeof(NetworkDealBoss), "RPCA_AddDeal")]
private static void AddDealPrefix()
{
if (PhotonNetwork.IsMasterClient)
{
RoomStatsHolder roomStats = SurfaceNetworkHandler.RoomStats;
offersBeforeAccept = ((roomStats == null) ? null : roomStats.NetworkDealsToSelect?.ToArray());
NetworkDealBase activeDeal = NetworkDealBoss.activeDeal;
if (activeDeal != null)
{
Manager.Track(activeDeal);
}
}
}
[HarmonyPostfix]
[HarmonyPatch(typeof(NetworkDealBoss), "RPCA_AddDeal")]
private static void AddDealPostfix(byte __0, byte __1, DIFFICULTY __2)
{
//IL_004b: Unknown result type (might be due to invalid IL or missing references)
//IL_004c: Unknown result type (might be due to invalid IL or missing references)
if (!PhotonNetwork.IsMasterClient)
{
return;
}
try
{
if (NetworkDealBoss.activeDeal != null)
{
Manager.Track(NetworkDealBoss.activeDeal);
}
Manager.AcceptsThisWeek++;
NetworkDealBase[] array = offersBeforeAccept;
offersBeforeAccept = null;
if (array != null)
{
Manager.UpdateOffersAfterAccept(array, (NetworkDealBase o) => o.GetIndex() == __0 && o.reward != null && o.reward.GetIndex() == __1 && o.difficulty == __2);
}
}
catch (Exception arg)
{
Plugin.Log.LogError((object)$"AddDealPostfix: {arg}");
}
}
[HarmonyPrefix]
[HarmonyPatch(typeof(NetworkDealBoss), "RPCA_ClaimReward")]
private static void ClaimPrefix()
{
RemoveActiveFromTracking();
}
[HarmonyPostfix]
[HarmonyPatch(typeof(NetworkDealBoss), "RPCA_ClaimReward")]
private static void ClaimPostfix()
{
Manager.FocusNext();
}
[HarmonyPrefix]
[HarmonyPatch(typeof(NetworkDealBoss), "RPCA_RemoveDeal")]
private static void RemovePrefix()
{
RemoveActiveFromTracking();
}
[HarmonyPostfix]
[HarmonyPatch(typeof(NetworkDealBoss), "RPCA_RemoveDeal")]
private static void RemovePostfix()
{
Manager.FocusNext();
}
private static void RemoveActiveFromTracking()
{
if (PhotonNetwork.IsMasterClient)
{
Tracked tracked = Manager.FindDeal(NetworkDealBoss.activeDeal);
if (tracked != null)
{
Manager.All.Remove(tracked);
Manager.MarkDirty();
}
}
}
[HarmonyPrefix]
[HarmonyPatch(typeof(NetworkDealBoss), "Cleanup")]
private static void CleanupPrefix()
{
Manager.Clear();
}
[HarmonyPostfix]
[HarmonyPatch(typeof(NetworkDealBoss), "Update")]
private static void BossUpdatePostfix()
{
if (PhotonNetwork.IsMasterClient)
{
Manager.UpdateBackground();
}
}
[HarmonyPostfix]
[HarmonyPatch(typeof(NetworkDealBoss), "ReviewUploadContent")]
private static void ReviewPostfix(ContentBuffer __0)
{
if (PhotonNetwork.IsMasterClient)
{
Manager.ForEachBackground(delegate(NetworkDealBase d)
{
d.ReviewUploadContent(__0);
});
}
}
[HarmonyPostfix]
[HarmonyPatch(typeof(NetworkDealBoss), "OnStatusUpdated")]
private static void StatusPostfix()
{
if (!PhotonNetwork.IsMasterClient || Manager.All.Count <= 1)
{
return;
}
foreach (NetworkDealBase item in Manager.Background())
{
try
{
item.OnStatusUpdated();
}
catch (Exception arg)
{
Plugin.Log.LogError((object)$"OnStatusUpdated: {arg}");
}
}
}
[HarmonyPostfix]
[HarmonyPatch(typeof(NetworkDealBoss), "OnAddQuota")]
private static void QuotaPostfix(int __0)
{
if (PhotonNetwork.IsMasterClient)
{
Manager.ForEachBackground(delegate(NetworkDealBase d)
{
d.OnAddQuota(__0);
});
}
}
[HarmonyPostfix]
[HarmonyPatch(typeof(NetworkDealBoss), "OnMoneyRemoved")]
private static void MoneyPostfix(int __0)
{
if (PhotonNetwork.IsMasterClient)
{
Manager.ForEachBackground(delegate(NetworkDealBase d)
{
d.OnRemovedMoney(__0);
});
}
}
[HarmonyPostfix]
[HarmonyPatch(typeof(NetworkDealBoss), "OnPlayerEnteredRoom")]
private static void PlayerEnteredPostfix()
{
Manager.MarkDirty();
}
[HarmonyPostfix]
[HarmonyPatch(typeof(SurfaceNetworkHandler), "NewWeek")]
private static void NewWeekPostfix()
{
if (PhotonNetwork.IsMasterClient)
{
Manager.AcceptsThisWeek = 0;
Manager.MarkDirty();
}
}
[HarmonyPostfix]
[HarmonyPatch(typeof(SaveLoadHandler), "FillSaveData")]
private static void SavePostfix(Save __0)
{
try
{
if (!PhotonNetwork.IsMasterClient || Manager.All.Count == 0)
{
return;
}
List<SerializedNetworkDeal> list = new List<SerializedNetworkDeal>();
NetworkDealBase activeDeal = NetworkDealBoss.activeDeal;
if (activeDeal != null)
{
list.Add(activeDeal.GetSerialized());
}
foreach (NetworkDealBase item in Manager.Background())
{
list.Add(item.GetSerialized());
}
if (list.Count > 1)
{
__0.SerializedNetworkDeals = list.ToArray();
Plugin.Log.LogInfo((object)$"Saved {list.Count} network deals.");
}
}
catch (Exception arg)
{
Plugin.Log.LogError((object)$"SavePostfix: {arg}");
}
}
[HarmonyPostfix]
[HarmonyPatch(typeof(SaveLoadHandler), "LoadSaveData")]
private static void LoadPostfix(Save __0)
{
try
{
Manager.Clear();
if (NetworkDealBoss.activeDeal != null)
{
Manager.Track(NetworkDealBoss.activeDeal);
}
SerializedNetworkDeal[] array = __0?.SerializedNetworkDeals;
if (array != null)
{
for (int i = 1; i < array.Length; i++)
{
SerializedNetworkDeal obj = array[i];
NetworkDealBase val = ((obj != null) ? obj.UnSerialize() : null);
if (val != null)
{
val.Refresh();
Manager.Track(val);
}
}
}
Manager.AcceptsThisWeek = Manager.All.Count;
if (Manager.All.Count > 1)
{
Plugin.Log.LogInfo((object)$"Loaded {Manager.All.Count} network deals.");
}
}
catch (Exception arg)
{
Plugin.Log.LogError((object)$"LoadPostfix: {arg}");
}
}
[HarmonyPostfix]
[HarmonyPatch(typeof(Player), "HasLockedInput")]
private static void LockInputPostfix(Player __instance, ref bool __result)
{
if (Plugin.PanelOpen && __instance == Player.localPlayer)
{
__result = true;
}
}
[HarmonyPrefix]
[HarmonyPatch(typeof(CursorHandler), "Update")]
private static bool CursorPrefix()
{
if (!Plugin.PanelOpen)
{
return true;
}
Plugin.ForceCursor();
return false;
}
}
internal sealed class MirrorDeal
{
public int Id;
public bool Focused;
public int DealIndex;
public int RewardIndex;
public int Difficulty;
public int Progress;
public DEAL_STATE State;
public int Fee;
public NetworkDealBase? Display;
}
internal static class Net
{
private const byte EvState = 179;
private const byte EvRequest = 180;
private const byte EvMessage = 181;
private const int Version = 3;
internal const int ActAccept = 1;
internal const int ActShow = 2;
internal const int ActCancel = 3;
internal const int ActClaim = 4;
internal const int ActRedeliver = 5;
internal static readonly List<MirrorDeal> Mirror = new List<MirrorDeal>();
internal static float LastStateTime = -100f;
internal static int HostMaxConcurrent;
internal static int HostAcceptsLeft;
internal static bool HostFree;
internal static int HostFeePercent = 50;
internal static int HostMinFee = 20;
private static bool registered;
internal static bool HostHasMod
{
get
{
if (!PhotonNetwork.IsMasterClient)
{
return Time.unscaledTime - LastStateTime < 12f;
}
return true;
}
}
internal static void Register()
{
if (!registered && PhotonNetwork.NetworkingClient != null)
{
PhotonNetwork.NetworkingClient.EventReceived += OnEvent;
registered = true;
}
}
internal static void Unregister()
{
if (registered && PhotonNetwork.NetworkingClient != null)
{
PhotonNetwork.NetworkingClient.EventReceived -= OnEvent;
}
registered = false;
}
internal static void BroadcastState()
{
//IL_0168: Unknown result type (might be due to invalid IL or missing references)
//IL_016d: Unknown result type (might be due to invalid IL or missing references)
//IL_016f: Unknown result type (might be due to invalid IL or missing references)
//IL_0174: Unknown result type (might be due to invalid IL or missing references)
//IL_017e: Expected O, but got Unknown
//IL_0110: Unknown result type (might be due to invalid IL or missing references)
//IL_011a: Expected I4, but got Unknown
//IL_012a: Unknown result type (might be due to invalid IL or missing references)
//IL_0134: Expected I4, but got Unknown
if (!PhotonNetwork.InRoom || PhotonNetwork.OfflineMode || PhotonNetwork.CurrentRoom == null || PhotonNetwork.CurrentRoom.PlayerCount <= 1)
{
return;
}
List<int> list = new List<int>
{
3,
Plugin.MaxConcurrent.Value,
Math.Max(0, Plugin.MaxAcceptsPerWeek.Value - Manager.AcceptsThisWeek),
Manager.DeliveryIsFree ? 1 : 0,
Mathf.RoundToInt(Plugin.FeeRate.Value * 100f),
Plugin.MinFee.Value,
Manager.All.Count
};
NetworkDealBase activeDeal = NetworkDealBoss.activeDeal;
foreach (Tracked item in Manager.All)
{
NetworkDealBase deal = item.Deal;
list.Add(item.Id);
list.Add((deal == activeDeal) ? 1 : 0);
list.Add(deal.GetIndex());
list.Add((deal.reward != null) ? deal.reward.GetIndex() : 0);
list.Add((int)deal.difficulty);
list.Add(deal.ProgressInt);
list.Add((int)deal.State);
list.Add(Manager.FeeFor(deal));
}
PhotonNetwork.RaiseEvent((byte)179, (object)list.ToArray(), new RaiseEventOptions
{
Receivers = (ReceiverGroup)0
}, SendOptions.SendReliable);
}
internal static void Request(int action, int arg, int extra = -1)
{
//IL_003d: Unknown result type (might be due to invalid IL or missing references)
//IL_0042: Unknown result type (might be due to invalid IL or missing references)
//IL_0044: Unknown result type (might be due to invalid IL or missing references)
//IL_0049: Unknown result type (might be due to invalid IL or missing references)
//IL_0053: Expected O, but got Unknown
if (PhotonNetwork.IsMasterClient)
{
Ui.Toast(Execute(action, arg, extra));
Manager.MarkDirty();
}
else if (PhotonNetwork.InRoom)
{
PhotonNetwork.RaiseEvent((byte)180, (object)new int[4] { 3, action, arg, extra }, new RaiseEventOptions
{
Receivers = (ReceiverGroup)2
}, SendOptions.SendReliable);
}
}
private static Msg Execute(int action, int arg, int extra)
{
try
{
return action switch
{
1 => Manager.Accept(arg, extra),
2 => Manager.Show(arg),
3 => Manager.Cancel(arg),
4 => Manager.Claim(arg),
5 => Manager.Redeliver(arg),
_ => Msg.Of(MsgId.None),
};
}
catch (Exception arg2)
{
Plugin.Log.LogError((object)$"Action {action} failed: {arg2}");
return Msg.Of(MsgId.ActionFailed);
}
}
private static void OnEvent(EventData ev)
{
//IL_009a: Unknown result type (might be due to invalid IL or missing references)
//IL_00a1: Expected O, but got Unknown
//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
try
{
switch (ev.Code)
{
case 179:
if (!PhotonNetwork.IsMasterClient && ev.CustomData is int[] s)
{
ReadState(s);
}
break;
case 180:
if (PhotonNetwork.IsMasterClient && ev.CustomData is int[] array && array.Length >= 4 && array[0] == 3)
{
Msg msg2 = Execute(array[1], array[2], array[3]);
Manager.MarkDirty();
if (msg2.Id != MsgId.None)
{
object[] array2 = msg2.ToNetwork();
RaiseEventOptions val = new RaiseEventOptions();
val.TargetActors = new int[1] { ev.Sender };
PhotonNetwork.RaiseEvent((byte)181, (object)array2, val, SendOptions.SendReliable);
}
}
break;
case 181:
{
Msg msg = Msg.FromNetwork(ev.CustomData);
if (msg.Id != MsgId.None)
{
Ui.Toast(msg);
}
break;
}
}
}
catch (Exception arg)
{
Plugin.Log.LogError((object)$"OnEvent: {arg}");
}
}
private static void ReadState(int[] s)
{
//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
//IL_0126: Unknown result type (might be due to invalid IL or missing references)
//IL_012d: Unknown result type (might be due to invalid IL or missing references)
//IL_0145: Unknown result type (might be due to invalid IL or missing references)
//IL_014b: Invalid comparison between Unknown and I4
//IL_0198: Unknown result type (might be due to invalid IL or missing references)
//IL_019e: Invalid comparison between Unknown and I4
//IL_0175: Unknown result type (might be due to invalid IL or missing references)
//IL_017a: Unknown result type (might be due to invalid IL or missing references)
if (s.Length < 7 || s[0] != 3)
{
return;
}
LastStateTime = Time.unscaledTime;
HostMaxConcurrent = s[1];
HostAcceptsLeft = s[2];
HostFree = s[3] == 1;
HostFeePercent = s[4];
HostMinFee = s[5];
int num = s[6];
Dictionary<int, MirrorDeal> dictionary = Mirror.ToDictionary((MirrorDeal m) => m.Id);
Mirror.Clear();
for (int num2 = 0; num2 < num; num2++)
{
int num3 = 7 + num2 * 8;
if (num3 + 8 > s.Length)
{
break;
}
MirrorDeal mirrorDeal = new MirrorDeal
{
Id = s[num3],
Focused = (s[num3 + 1] == 1),
DealIndex = s[num3 + 2],
RewardIndex = s[num3 + 3],
Difficulty = s[num3 + 4],
Progress = s[num3 + 5],
State = (DEAL_STATE)s[num3 + 6],
Fee = s[num3 + 7]
};
if (dictionary.TryGetValue(mirrorDeal.Id, out var value))
{
if (value.DealIndex == mirrorDeal.DealIndex)
{
mirrorDeal.Display = value.Display;
}
if (value.State != mirrorDeal.State && !mirrorDeal.Focused)
{
if ((int)mirrorDeal.State == 3)
{
Ui.Toast(Msg.Of(MsgId.DealSucceeded, "#" + mirrorDeal.DealIndex, ((object)Plugin.PanelKey.Value/*cast due to .constrained prefix*/).ToString()));
}
else if ((int)mirrorDeal.State == 2)
{
Ui.Toast(Msg.Of(MsgId.DealFailed, "#" + mirrorDeal.DealIndex));
}
}
}
Mirror.Add(mirrorDeal);
}
}
internal static NetworkDealBase? GetDisplay(MirrorDeal m)
{
//IL_0057: Unknown result type (might be due to invalid IL or missing references)
try
{
if (m.Display == null)
{
NetworkDealBase dealFromIndex = SingletonAsset<NetworkDealDataBase>.Instance.GetDealFromIndex(m.DealIndex);
DealRewardBase rewardFromIndex = SingletonAsset<DealRewardDatabase>.Instance.GetRewardFromIndex(m.RewardIndex);
dealFromIndex.Init(rewardFromIndex, (DIFFICULTY)(byte)m.Difficulty);
m.Display = dealFromIndex;
}
m.Display.ProgressInt = m.Progress;
m.Display.State = m.State;
m.Display.ClearDirty();
return m.Display;
}
catch
{
return null;
}
}
}
internal static class Texts
{
internal static string Name(NetworkDealBase? deal)
{
if (deal == null)
{
return "?";
}
try
{
string dealName_Localized = deal.DealName_Localized;
return string.IsNullOrEmpty(dealName_Localized) ? deal.DealName : dealName_Localized;
}
catch
{
return ((object)deal).GetType().Name;
}
}
internal static string Safe(Func<string> f)
{
try
{
return f() ?? string.Empty;
}
catch
{
return string.Empty;
}
}
internal static string StateText(DEAL_STATE s)
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_0002: Invalid comparison between Unknown and I4
//IL_0004: Unknown result type (might be due to invalid IL or missing references)
//IL_0006: Invalid comparison between Unknown and I4
if ((int)s != 2)
{
if ((int)s == 3)
{
return "<color=#7CFC8A>" + Lang.T("達成", "Completed", "已完成", "已完成", "달성") + "</color>";
}
return Lang.T("進行中", "In progress", "进行中", "進行中", "진행 중");
}
return "<color=#FF7B7B>" + Lang.T("失敗", "Failed", "失败", "失敗", "실패") + "</color>";
}
}
internal sealed class Row
{
public int Id;
public bool Focused;
public NetworkDealBase? Deal;
public DEAL_STATE State;
public int Fee;
}
internal static class Ui
{
[CompilerGenerated]
private static class <>O
{
public static WindowFunction <0>__DrawWindow;
}
private static Rect window = new Rect(0f, 0f, 640f, 520f);
private static bool positioned;
private static Vector2 scroll;
private static GUISkin? skin;
private static GUIStyle? rich;
private static GUIStyle? title;
private static GUIStyle? box;
private static string toastText = string.Empty;
private static float toastUntil;
private static int confirmCancelId = -1;
private static float confirmUntil;
private static Texture2D? arrow;
internal static void Toast(Msg msg)
{
Toast(Msgs.Text(msg));
}
internal static void Toast(string text)
{
if (!string.IsNullOrEmpty(text))
{
toastText = text;
toastUntil = Time.unscaledTime + 5f;
Plugin.Log.LogInfo((object)text);
}
}
private static void EnsureStyles()
{
//IL_0036: Unknown result type (might be due to invalid IL or missing references)
//IL_003b: Unknown result type (might be due to invalid IL or missing references)
//IL_0042: Unknown result type (might be due to invalid IL or missing references)
//IL_0049: Unknown result type (might be due to invalid IL or missing references)
//IL_0056: Expected O, but got Unknown
//IL_0060: Unknown result type (might be due to invalid IL or missing references)
//IL_0065: Unknown result type (might be due to invalid IL or missing references)
//IL_006c: Unknown result type (might be due to invalid IL or missing references)
//IL_0073: Unknown result type (might be due to invalid IL or missing references)
//IL_0080: Expected O, but got Unknown
//IL_008a: Unknown result type (might be due to invalid IL or missing references)
//IL_008f: Unknown result type (might be due to invalid IL or missing references)
//IL_0094: Unknown result type (might be due to invalid IL or missing references)
//IL_009e: Expected O, but got Unknown
//IL_00a3: Expected O, but got Unknown
if (!((Object)(object)skin != (Object)null))
{
skin = Object.Instantiate<GUISkin>(GUI.skin);
skin.font = Lang.GetFont();
rich = new GUIStyle(skin.label)
{
richText = true,
wordWrap = true,
fontSize = 14
};
title = new GUIStyle(skin.label)
{
richText = true,
fontStyle = (FontStyle)1,
fontSize = 16
};
box = new GUIStyle(skin.box)
{
padding = new RectOffset(8, 8, 6, 6)
};
}
}
internal static void Draw()
{
//IL_0075: 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_012b: Unknown result type (might be due to invalid IL or missing references)
//IL_0169: Unknown result type (might be due to invalid IL or missing references)
//IL_016e: Unknown result type (might be due to invalid IL or missing references)
//IL_0178: Unknown result type (might be due to invalid IL or missing references)
//IL_017d: Unknown result type (might be due to invalid IL or missing references)
//IL_0183: Unknown result type (might be due to invalid IL or missing references)
//IL_0140: Unknown result type (might be due to invalid IL or missing references)
//IL_0145: Unknown result type (might be due to invalid IL or missing references)
//IL_014b: Expected O, but got Unknown
//IL_018b: Unknown result type (might be due to invalid IL or missing references)
if (!Plugin.PanelOpen && Time.unscaledTime > toastUntil)
{
return;
}
EnsureStyles();
skin.font = Lang.GetFont();
GUISkin obj = GUI.skin;
GUI.skin = skin;
if (Time.unscaledTime <= toastUntil)
{
Rect val = default(Rect);
((Rect)(ref val))..ctor((float)Screen.width / 2f - 320f, (float)Screen.height - 110f, 640f, 44f);
GUI.Box(val, string.Empty);
GUI.Label(new Rect(((Rect)(ref val)).x + 10f, ((Rect)(ref val)).y + 4f, ((Rect)(ref val)).width - 20f, ((Rect)(ref val)).height - 8f), toastText, rich);
}
if (Plugin.PanelOpen)
{
if (!positioned)
{
((Rect)(ref window)).x = ((float)Screen.width - ((Rect)(ref window)).width) / 2f;
((Rect)(ref window)).y = ((float)Screen.height - ((Rect)(ref window)).height) / 2f;
positioned = true;
}
Plugin.ForceCursor();
Rect val2 = window;
object obj2 = <>O.<0>__DrawWindow;
if (obj2 == null)
{
WindowFunction val3 = DrawWindow;
<>O.<0>__DrawWindow = val3;
obj2 = (object)val3;
}
window = GUI.Window(24225, val2, (WindowFunction)obj2, Lang.T("クエスト管理", "Quest Manager", "任务管理", "任務管理", "퀘스트 관리"));
Vector2 mousePosition = Event.current.mousePosition;
if (!((Rect)(ref window)).Contains(mousePosition))
{
DrawCursorAt(mousePosition);
}
}
GUI.skin = obj;
}
private static Texture2D Arrow()
{
//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
//IL_00cd: Expected O, but got Unknown
//IL_011c: Unknown result type (might be due to invalid IL or missing references)
//IL_0115: Unknown result type (might be due to invalid IL or missing references)
//IL_010e: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)arrow != (Object)null)
{
return arrow;
}
string[] array = new string[17]
{
"X...........", "XX..........", "XOX.........", "XOOX........", "XOOOX.......", "XOOOOX......", "XOOOOOX.....", "XOOOOOOX....", "XOOOOOOOX...", "XOOOOOOOOX..",
"XOOOOOXXXXX.", "XOOXOOX.....", "XOX.XOOX....", "XX..XOOX....", "X....XOOX...", ".....XOOX...", "......XX...."
};
int length = array[0].Length;
int num = array.Length;
arrow = new Texture2D(length, num, (TextureFormat)4, false)
{
filterMode = (FilterMode)0
};
for (int i = 0; i < num; i++)
{
for (int j = 0; j < length; j++)
{
char c = array[num - 1 - i][j];
arrow.SetPixel(j, i, (Color)(c switch
{
'O' => Color.white,
'X' => Color.black,
_ => new Color(0f, 0f, 0f, 0f),
}));
}
}
arrow.Apply();
return arrow;
}
private static void DrawCursorAt(Vector2 p)
{
//IL_0011: Unknown result type (might be due to invalid IL or missing references)
//IL_0017: Invalid comparison between Unknown and I4
//IL_001a: Unknown result type (might be due to invalid IL or missing references)
//IL_0020: Unknown result type (might be due to invalid IL or missing references)
//IL_0030: Unknown result type (might be due to invalid IL or missing references)
if (Plugin.SoftwareCursor.Value && (int)Event.current.type == 7)
{
GUI.DrawTexture(new Rect(p.x, p.y, 18f, 25.5f), (Texture)(object)Arrow());
}
}
private static List<Row> Rows()
{
//IL_014b: Unknown result type (might be due to invalid IL or missing references)
//IL_0150: Unknown result type (might be due to invalid IL or missing references)
//IL_005f: 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_00e9: Unknown result type (might be due to invalid IL or missing references)
//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
List<Row> list = new List<Row>();
if (PhotonNetwork.IsMasterClient)
{
NetworkDealBase activeDeal = NetworkDealBoss.activeDeal;
foreach (Tracked item in Manager.All)
{
list.Add(new Row
{
Id = item.Id,
Focused = (item.Deal == activeDeal),
Deal = item.Deal,
State = item.Deal.State,
Fee = Manager.FeeFor(item.Deal)
});
}
}
else if (Net.HostHasMod)
{
foreach (MirrorDeal item2 in Net.Mirror)
{
list.Add(new Row
{
Id = item2.Id,
Focused = item2.Focused,
Deal = Net.GetDisplay(item2),
State = item2.State,
Fee = item2.Fee
});
}
}
else if (NetworkDealBoss.activeDeal != null)
{
NetworkDealBase activeDeal2 = NetworkDealBoss.activeDeal;
list.Add(new Row
{
Id = -1,
Focused = true,
Deal = activeDeal2,
State = activeDeal2.State,
Fee = -1
});
}
return (from r in list
orderby r.Focused descending, r.Id
select r).ToList();
}
private static void DrawWindow(int id)
{
//IL_01bc: Unknown result type (might be due to invalid IL or missing references)
//IL_01c6: Unknown result type (might be due to invalid IL or missing references)
//IL_01cb: Unknown result type (might be due to invalid IL or missing references)
//IL_0569: Unknown result type (might be due to invalid IL or missing references)
//IL_05ac: Unknown result type (might be due to invalid IL or missing references)
//IL_05ca: Unknown result type (might be due to invalid IL or missing references)
bool isMasterClient = PhotonNetwork.IsMasterClient;
bool hostHasMod = Net.HostHasMod;
RoomStatsHolder roomStats = SurfaceNetworkHandler.RoomStats;
int num = (isMasterClient ? Plugin.MaxConcurrent.Value : Net.HostMaxConcurrent);
int num2 = (isMasterClient ? Math.Max(0, Plugin.MaxAcceptsPerWeek.Value - Manager.AcceptsThisWeek) : Net.HostAcceptsLeft);
bool flag = (isMasterClient ? Manager.DeliveryIsFree : Net.HostFree);
int num3 = (isMasterClient ? Mathf.RoundToInt(Plugin.FeeRate.Value * 100f) : Net.HostFeePercent);
int num4 = (isMasterClient ? Plugin.MinFee.Value : Net.HostMinFee);
GUILayout.BeginVertical(Array.Empty<GUILayoutOption>());
GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
string text = Lang.T("所持金", "Money", "资金", "資金", "소지금");
GUILayout.Label((roomStats != null) ? $"{text}: <b>${roomStats.Money}</b>" : (text + ": -"), rich, Array.Empty<GUILayoutOption>());
GUILayout.FlexibleSpace();
GUILayout.Label(flag ? ("<color=#7CFC8A>" + Lang.T("FreeShop 導入中: 再送の送料は無料", "FreeShop installed: redelivery is free", "已安装 FreeShop:重新配送免运费", "已安裝 FreeShop:重新配送免運費", "FreeShop 사용 중: 재배송 무료") + "</color>") : string.Format(Lang.T("再送の送料: 物資の価格の{0}% (最低${1})", "Redelivery fee: {0}% of item price (min ${1})", "重新配送运费:物资价格的 {0}%(最低 ${1})", "重新配送運費:物資價格的 {0}%(最低 ${1})", "재배송 배송비: 물자 가격의 {0}% (최소 ${1})"), num3, num4), rich, Array.Empty<GUILayoutOption>());
GUILayout.EndHorizontal();
if (!hostHasMod)
{
GUILayout.Label("<color=#FFC857>" + Lang.T("ホストがこのModを入れていないため、一覧の表示と操作はできません。", "The host doesn't have this mod, so the list and actions are unavailable.", "房主未安装此模组,无法显示列表或进行操作。", "房主未安裝此模組,無法顯示列表或進行操作。", "호스트가 이 모드를 설치하지 않아 목록 표시와 조작을 할 수 없습니다.") + "</color>", rich, Array.Empty<GUILayoutOption>());
}
List<Row> list = Rows();
scroll = GUILayout.BeginScrollView(scroll, Array.Empty<GUILayoutOption>());
GUILayout.Label("<b>" + Lang.T("受注中のクエスト", "Active quests", "进行中的任务", "進行中的任務", "진행 중인 퀘스트") + $"</b> {list.Count}/{num}", title, Array.Empty<GUILayoutOption>());
if (list.Count == 0)
{
GUILayout.Label(Lang.T("受注中のクエストはありません", "No active quests", "没有进行中的任务", "沒有進行中的任務", "진행 중인 퀘스트가 없습니다"), rich, Array.Empty<GUILayoutOption>());
}
foreach (Row item in list)
{
DrawRow(item, hostHasMod && item.Id >= 0);
}
GUILayout.Space(10f);
GUILayout.Label("<b>" + Lang.T("受注できるクエスト", "Available quests", "可接受的任务", "可接受的任務", "수락 가능한 퀘스트") + "</b> " + string.Format(Lang.T("今週あと{0}件", "{0} left this week", "本周还可接受 {0} 个", "本週還可接受 {0} 個", "이번 주 {0}개 남음"), num2), title, Array.Empty<GUILayoutOption>());
NetworkDealBase[] array = ((roomStats != null) ? roomStats.NetworkDealsToSelect : null);
if (roomStats != null && !roomStats.ComputerRoomDoorUnlocked)
{
GUILayout.Label(Lang.T("PC部屋がまだ開いていません", "The computer room isn't open yet", "电脑室尚未开放", "電腦室尚未開放", "컴퓨터실이 아직 열리지 않았습니다"), rich, Array.Empty<GUILayoutOption>());
}
else if (array == null || array.Length == 0)
{
GUILayout.Label(Lang.T("今は受注できるクエストがありません (次の週に更新されます)", "No quests available right now (refreshes next week)", "目前没有可接受的任务(下周刷新)", "目前沒有可接受的任務(下週刷新)", "지금은 수락할 수 있는 퀘스트가 없습니다 (다음 주에 갱신)"), rich, Array.Empty<GUILayoutOption>());
}
else
{
for (int i = 0; i < array.Length; i++)
{
NetworkDealBase o = array[i];
if (o != null)
{
GUILayout.BeginVertical(box, Array.Empty<GUILayoutOption>());
GUILayout.Label("<b>" + Texts.Name(o) + "</b> [" + Texts.Safe((Func<string>)o.GetDifficultyText) + "]", rich, Array.Empty<GUILayoutOption>());
GUILayout.Label(Texts.Safe((Func<string>)o.DealDescription), rich, Array.Empty<GUILayoutOption>());
GUILayout.Label(Lang.T("報酬: ", "Reward: ", "奖励:", "獎勵:", "보상: ") + Texts.Safe(() => o.reward.GetRewardDescription()), rich, Array.Empty<GUILayoutOption>());
GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
GUILayout.FlexibleSpace();
GUI.enabled = hostHasMod && list.Count < Math.Max(1, num) && num2 > 0;
if (GUILayout.Button(Lang.T("受注する", "Accept", "接受", "接受", "수락"), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.MinWidth(120f) }))
{
Net.Request(1, i, o.GetIndex());
}
GUI.enabled = true;
GUILayout.EndHorizontal();
GUILayout.EndVertical();
}
}
}
GUILayout.EndScrollView();
GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
GUILayout.FlexibleSpace();
if (GUILayout.Button(Lang.T("閉じる", "Close", "关闭", "關閉", "닫기") + $" ({Plugin.PanelKey.Value})", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.MinWidth(140f) }))
{
Plugin.PanelOpen = false;
}
GUILayout.EndHorizontal();
GUILayout.EndVertical();
DrawCursorAt(Event.current.mousePosition);
GUI.DragWindow(new Rect(0f, 0f, 10000f, 24f));
}
private static void DrawRow(Row row, bool canAct)
{
//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
//IL_0155: Unknown result type (might be due to invalid IL or missing references)
//IL_015b: Invalid comparison between Unknown and I4
//IL_01ab: Unknown result type (might be due to invalid IL or missing references)
//IL_01b1: Invalid comparison between Unknown and I4
NetworkDealBase d = row.Deal;
GUILayout.BeginVertical(box, Array.Empty<GUILayoutOption>());
string text = (row.Focused ? ("<color=#8FD3FF>[" + Lang.T("PCに表示中", "On PC", "电脑显示中", "電腦顯示中", "PC 표시 중") + "]</color> ") : string.Empty);
GUILayout.Label(text + "<b>" + Texts.Name(d) + "</b> [" + Texts.Safe(() => d.GetDifficultyText()) + "] " + Texts.StateText(row.State), rich, Array.Empty<GUILayoutOption>());
if (d != null)
{
string text2 = Texts.Safe((Func<string>)d.GetProgressText);
if (!string.IsNullOrEmpty(text2))
{
GUILayout.Label(text2, rich, Array.Empty<GUILayoutOption>());
}
GUILayout.Label(Lang.T("報酬: ", "Reward: ", "奖励:", "獎勵:", "보상: ") + Texts.Safe(() => d.reward.GetRewardDescription()), rich, Array.Empty<GUILayoutOption>());
}
GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
GUILayout.FlexibleSpace();
GUI.enabled = canAct;
if ((int)row.State == 3)
{
if (GUILayout.Button(Lang.T("報酬を受け取る", "Claim reward", "领取奖励", "領取獎勵", "보상 받기"), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.MinWidth(140f) }))
{
Net.Request(4, row.Id);
}
}
else if ((int)row.State == 2)
{
if (GUILayout.Button(Lang.T("取り下げる", "Dismiss", "移除", "移除", "정리"), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.MinWidth(120f) }))
{
Net.Request(3, row.Id);
}
}
else
{
if (!row.Focused && GUILayout.Button(Lang.T("PCに表示", "Show on PC", "在电脑显示", "在電腦顯示", "PC에 표시"), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.MinWidth(100f) }))
{
Net.Request(2, row.Id);
}
GUI.enabled = canAct && row.Fee >= 0;
string text3 = Lang.T("再送", "Redeliver", "重新配送", "重新配送", "재배송");
if (GUILayout.Button((row.Fee < 0) ? (text3 + " (" + Lang.T("物資なし", "no items", "无物资", "無物資", "물자 없음") + ")") : ((row.Fee == 0) ? (text3 + " (" + Lang.T("無料", "free", "免费", "免費", "무료") + ")") : $"{text3} (${row.Fee})"), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.MinWidth(130f) }))
{
Net.Request(5, row.Id);
}
GUI.enabled = canAct;
bool flag = confirmCancelId == row.Id && Time.unscaledTime < confirmUntil;
if (GUILayout.Button(flag ? Lang.T("本当に却下する", "Really abandon?", "确定放弃?", "確定放棄?", "정말 포기?") : Lang.T("却下", "Abandon", "放弃", "放棄", "포기"), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.MinWidth((float)(flag ? 130 : 80)) }))
{
if (flag)
{
confirmCancelId = -1;
Net.Request(3, row.Id);
}
else
{
confirmCancelId = row.Id;
confirmUntil = Time.unscaledTime + 4f;
}
}
}
GUI.enabled = true;
GUILayout.EndHorizontal();
GUILayout.EndVertical();
}
}
internal enum MsgId
{
None,
OfferGone,
OffersChanged,
AcceptOnlyAtBase,
MaxConcurrent,
WeekLimit,
Accepted,
NotFound,
OnlyAtBase,
Dismissed,
Abandoned,
NotDone,
ClaimOnlyAtBase,
Claimed,
Shown,
DoneNoRedeliver,
NoItems,
RedeliverOnlyAtBase,
Wait,
NotEnoughMoney,
DroneFailed,
Redelivered,
RedeliveredFree,
ActionFailed,
DealSucceeded,
DealFailed
}
internal readonly struct Msg
{
public readonly MsgId Id;
public readonly string[] Args;
private Msg(MsgId id, string[] args)
{
Id = id;
Args = args;
}
public static Msg Of(MsgId id, params string[] args)
{
return new Msg(id, args ?? Array.Empty<string>());
}
public object[] ToNetwork()
{
return new object[2]
{
(int)Id,
Args
};
}
public static Msg FromNetwork(object data)
{
if (data is object[] array && array.Length >= 1 && array[0] is int id)
{
string[] args = ((array.Length >= 2 && array[1] is string[] array2) ? array2 : Array.Empty<string>());
return new Msg((MsgId)id, args);
}
return Of(MsgId.None);
}
}
internal static class Msgs
{
private static readonly Dictionary<string, string> NameCache = new Dictionary<string, string>();
internal static string DealArg(NetworkDealBase? deal)
{
if (deal != null)
{
return "#" + deal.GetIndex();
}
return "?";
}
private static string Arg(Msg m, int i)
{
if (m.Args == null || i >= m.Args.Length)
{
return string.Empty;
}
string text = m.Args[i] ?? string.Empty;
if (text.StartsWith("#") && int.TryParse(text.Substring(1), out var result))
{
return DealName(result);
}
return text;
}
internal static string DealName(int index)
{
string key = Lang.Current + ":" + index;
if (NameCache.TryGetValue(key, out string value))
{
return value;
}
string text;
try
{
NetworkDealBase dealFromIndex = SingletonAsset<NetworkDealDataBase>.Instance.GetDealFromIndex(index);
dealFromIndex.MakeLocalizedStrings();
text = Texts.Name(dealFromIndex);
}
catch
{
text = "#" + index;
}
NameCache[key] = text;
return text;
}
internal static string Text(Msg m)
{
string arg = Arg(m, 0);
string arg2 = Arg(m, 1);
return m.Id switch
{
MsgId.OfferGone => Lang.T("そのクエストはもう受注できません", "That quest can no longer be accepted", "该任务已无法接受", "該任務已無法接受", "이 퀘스트는 더 이상 수락할 수 없습니다"),
MsgId.OffersChanged => Lang.T("候補が更新されました。もう一度選んでください", "The offers changed. Please choose again", "任务列表已更新,请重新选择", "任務列表已更新,請重新選擇", "후보가 갱신되었습니다. 다시 선택해 주세요"),
MsgId.AcceptOnlyAtBase => Lang.T("拠点にいるときだけ受注できます", "Quests can only be accepted at the base", "只能在基地接受任务", "只能在基地接受任務", "기지에 있을 때만 수락할 수 있습니다"),
MsgId.MaxConcurrent => string.Format(Lang.T("同時に受けられるのは{0}件までです", "You can only have {0} quests at once", "最多只能同时进行 {0} 个任务", "最多只能同時進行 {0} 個任務", "동시에 진행할 수 있는 퀘스트는 {0}개까지입니다"), arg),
MsgId.WeekLimit => Lang.T("今週はこれ以上受注できません", "No more quests can be accepted this week", "本周无法再接受任务", "本週無法再接受任務", "이번 주에는 더 이상 수락할 수 없습니다"),
MsgId.Accepted => string.Format(Lang.T("「{0}」を受注しました", "Accepted \"{0}\"", "已接受「{0}」", "已接受「{0}」", "'{0}' 퀘스트를 수락했습니다"), arg),
MsgId.NotFound => Lang.T("そのクエストは見つかりません", "Quest not found", "找不到该任务", "找不到該任務", "퀘스트를 찾을 수 없습니다"),
MsgId.OnlyAtBase => Lang.T("拠点にいるときだけ操作できます", "This can only be done at the base", "只能在基地操作", "只能在基地操作", "기지에 있을 때만 할 수 있습니다"),
MsgId.Dismissed => string.Format(Lang.T("「{0}」を取り下げました", "Dismissed \"{0}\"", "已移除「{0}」", "已移除「{0}」", "'{0}' 퀘스트를 정리했습니다"), arg),
MsgId.Abandoned => string.Format(Lang.T("「{0}」を却下しました", "Abandoned \"{0}\"", "已放弃「{0}」", "已放棄「{0}」", "'{0}' 퀘스트를 포기했습니다"), arg),
MsgId.NotDone => Lang.T("まだ達成していません", "Not completed yet", "尚未完成", "尚未完成", "아직 달성하지 않았습니다"),
MsgId.ClaimOnlyAtBase => Lang.T("拠点にいるときだけ報酬を受け取れます", "Rewards can only be claimed at the base", "只能在基地领取奖励", "只能在基地領取獎勵", "기지에 있을 때만 보상을 받을 수 있습니다"),
MsgId.Claimed => string.Format(Lang.T("「{0}」の報酬を受け取りました", "Claimed the reward for \"{0}\"", "已领取「{0}」的奖励", "已領取「{0}」的獎勵", "'{0}' 보상을 받았습니다"), arg),
MsgId.Shown => string.Format(Lang.T("「{0}」をPCに表示しました", "\"{0}\" is now shown on the PC", "已在电脑上显示「{0}」", "已在電腦上顯示「{0}」", "'{0}' 퀘스트를 PC에 표시했습니다"), arg),
MsgId.DoneNoRedeliver => Lang.T("終わったクエストの物資は再送できません", "Items for finished quests can't be redelivered", "已结束的任务无法重新配送物资", "已結束的任務無法重新配送物資", "끝난 퀘스트의 물자는 재배송할 수 없습니다"),
MsgId.NoItems => Lang.T("このクエストには配送物資がありません", "This quest has no delivered items", "该任务没有配送物资", "該任務沒有配送物資", "이 퀘스트에는 배송 물자가 없습니다"),
MsgId.RedeliverOnlyAtBase => Lang.T("再送は拠点にいるときだけできます", "Redelivery is only available at the base", "只能在基地重新配送", "只能在基地重新配送", "재배송은 기지에 있을 때만 가능합니다"),
MsgId.Wait => Lang.T("少し待ってからもう一度試してください", "Please wait a moment and try again", "请稍后再试", "請稍後再試", "잠시 후 다시 시도해 주세요"),
MsgId.NotEnoughMoney => string.Format(Lang.T("所持金が足りません (送料 ${0})", "Not enough money (fee ${0})", "资金不足(运费 ${0})", "資金不足(運費 ${0})", "돈이 부족합니다 (배송비 ${0})"), arg),
MsgId.DroneFailed => Lang.T("配送ドローンを呼べませんでした", "Couldn't call the delivery drone", "无法呼叫配送无人机", "無法呼叫配送無人機", "배송 드론을 부를 수 없습니다"),
MsgId.Redelivered => string.Format(Lang.T("「{0}」の物資を再送しました (送料 ${1})", "Redelivered items for \"{0}\" (fee ${1})", "已重新配送「{0}」的物资(运费 ${1})", "已重新配送「{0}」的物資(運費 ${1})", "'{0}' 물자를 재배송했습니다 (배송비 ${1})"), arg, arg2),
MsgId.RedeliveredFree => string.Format(Lang.T("「{0}」の物資を再送しました (送料無料)", "Redelivered items for \"{0}\" (free)", "已重新配送「{0}」的物资(免运费)", "已重新配送「{0}」的物資(免運費)", "'{0}' 물자를 재배송했습니다 (무료)"), arg),
MsgId.ActionFailed => Lang.T("操作に失敗しました (LogOutput.log を確認してください)", "Action failed (see LogOutput.log)", "操作失败(请查看 LogOutput.log)", "操作失敗(請查看 LogOutput.log)", "작업에 실패했습니다 (LogOutput.log 확인)"),
MsgId.DealSucceeded => string.Format(Lang.T("クエスト「{0}」を達成しました。パネル({1})で報酬を受け取れます", "Quest \"{0}\" completed. Claim the reward in the panel ({1})", "任务「{0}」已完成,可在面板({1})中领取奖励", "任務「{0}」已完成,可在面板({1})中領取獎勵", "퀘스트 '{0}' 달성! 패널({1})에서 보상을 받으세요"), arg, arg2),
MsgId.DealFailed => string.Format(Lang.T("クエスト「{0}」に失敗しました", "Quest \"{0}\" failed", "任务「{0}」失败", "任務「{0}」失敗", "퀘스트 '{0}' 실패"), arg),
_ => string.Empty,
};
}
}
internal static class Lang
{
internal const string Ja = "ja";
internal const string En = "en";
internal const string ZhHans = "zh-Hans";
internal const string ZhHant = "zh-Hant";
internal const string Ko = "ko";
private static readonly string[] Choices = new string[6] { "Auto", "ja", "en", "zh-Hans", "zh-Hant", "ko" };
private static readonly Dictionary<string, Font> Fonts = new Dictionary<string, Font>();
private static ConfigEntry<string>? setting;
private static string current = "en";
private static float nextCheck = -1f;
internal static string Current
{
get
{
if (Time.unscaledTime >= nextCheck)
{
nextCheck = Time.unscaledTime + 1f;
current = Detect();
}
return current;
}
}
internal static void Bind(ConfigFile config)
{
//IL_0024: Unknown result type (might be due to invalid IL or missing references)
//IL_002e: Expected O, but got Unknown
setting = config.Bind<string>("General", "Language", "Auto", new ConfigDescription("Display language. Auto follows the game's language. / 表示言語。Auto はゲームの言語設定に合わせる", (AcceptableValueBase)(object)new AcceptableValueList<string>(Choices), Array.Empty<object>()));
}
internal static string T(string ja, string en, string zhHans, string zhHant, string ko)
{
return Current switch
{
"ja" => ja,
"zh-Hans" => zhHans,
"zh-Hant" => zhHant,
"ko" => ko,
_ => en,
};
}
internal static Font GetFont()
{
string text = Current;
if (!Fonts.TryGetValue(text, out Font value) || (Object)(object)value == (Object)null)
{
value = Font.CreateDynamicFontFromOSFont(FontNames(text), 16);
Fonts[text] = value;
}
return value;
}
private static string[] FontNames(string lang)
{
return lang switch
{
"ja" => new string[8] { "Yu Gothic UI", "Meiryo UI", "Meiryo", "MS UI Gothic", "Microsoft YaHei UI", "Malgun Gothic", "Segoe UI", "Arial" },
"zh-Hans" => new string[8] { "Microsoft YaHei UI", "Microsoft YaHei", "SimHei", "Microsoft JhengHei UI", "Yu Gothic UI", "Malgun Gothic", "Segoe UI", "Arial" },
"zh-Hant" => new string[8] { "Microsoft JhengHei UI", "Microsoft JhengHei", "PMingLiU", "Microsoft YaHei UI", "Yu Gothic UI", "Malgun Gothic", "Segoe UI", "Arial" },
"ko" => new string[6] { "Malgun Gothic", "Gulim", "Yu Gothic UI", "Microsoft YaHei UI", "Segoe UI", "Arial" },
_ => new string[5] { "Segoe UI", "Arial", "Yu Gothic UI", "Microsoft YaHei UI", "Malgun Gothic" },
};
}
private static string Detect()
{
//IL_0067: Unknown result type (might be due to invalid IL or missing references)
//IL_0043: Unknown result type (might be due to invalid IL or missing references)
//IL_0048: Unknown result type (might be due to invalid IL or missing references)
string text = setting?.Value ?? "Auto";
if (string.IsNullOrEmpty(text) || text.Equals("Auto", StringComparison.OrdinalIgnoreCase))
{
text = string.Empty;
try
{
Locale selectedLocale = LocalizationSettings.SelectedLocale;
object obj;
if (selectedLocale == null)
{
obj = null;
}
else
{
LocaleIdentifier identifier = selectedLocale.Identifier;
obj = ((LocaleIdentifier)(ref identifier)).Code;
}
if (obj == null)
{
obj = string.Empty;
}
text = (string)obj;
}
catch
{
}
if (string.IsNullOrEmpty(text))
{
text = FromSystem(Application.systemLanguage);
}
}
return Normalize(text);
}
private static string Normalize(string code)
{
string text = code.Trim().ToLowerInvariant();
if (text.StartsWith("ja"))
{
return "ja";
}
if (text.StartsWith("ko"))
{
return "ko";
}
if (text.StartsWith("zh"))
{
if (!text.Contains("hant") && !text.Contains("tw") && !text.Contains("hk") && !text.Contains("mo"))
{
return "zh-Hans";
}
return "zh-Hant";
}
return "en";
}
private static string FromSystem(SystemLanguage language)
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_0003: Invalid comparison between Unknown and I4
//IL_0010: Unknown result type (might be due to invalid IL or missing references)
//IL_0013: Invalid comparison between Unknown and I4
//IL_0005: Unknown result type (might be due to invalid IL or missing references)
//IL_0007: Invalid comparison between Unknown and I4
//IL_0015: Unknown result type (might be due to invalid IL or missing references)
//IL_0018: Invalid comparison between Unknown and I4
//IL_0009: Unknown result type (might be due to invalid IL or missing references)
//IL_000c: Invalid comparison between Unknown and I4
//IL_001a: Unknown result type (might be due to invalid IL or missing references)
//IL_001d: Invalid comparison between Unknown and I4
if ((int)language <= 22)
{
if ((int)language == 6)
{
goto IL_0033;
}
if ((int)language == 22)
{
return "ja";
}
}
else
{
if ((int)language == 23)
{
return "ko";
}
if ((int)language == 40)
{
goto IL_0033;
}
if ((int)language == 41)
{
return "zh-Hant";
}
}
return "en";
IL_0033:
return "zh-Hans";
}
}
}