using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Mirror;
using QuickBoxRecycle.Configuration;
using QuickBoxRecycle.Features;
using QuickBoxRecycle.Localization;
using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("QuickBoxRecycle")]
[assembly: AssemblyDescription("Quick Box Recycle mod for Supermarket Together by Ice Box Studio")]
[assembly: AssemblyCompany("Ice Box Studio")]
[assembly: AssemblyProduct("QuickBoxRecycle")]
[assembly: AssemblyCopyright("Copyright © 2026 Ice Box Studio All rights reserved.")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("9ac2c2e4-0d2a-42f8-95ef-f3ebbb7e9cf8")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace QuickBoxRecycle
{
public static class PluginInfo
{
public const string PLUGIN_GUID = "IceBoxStudio.SupermarketTogether.QuickBoxRecycle";
public const string PLUGIN_NAME = "QuickBoxRecycle";
public const string PLUGIN_VERSION = "1.0.0";
}
[BepInPlugin("IceBoxStudio.SupermarketTogether.QuickBoxRecycle", "QuickBoxRecycle", "1.0.0")]
public class QuickBoxRecycle : BaseUnityPlugin
{
public static QuickBoxRecycle _Instance;
private Harmony _harmony;
private bool patchesApplied;
public static QuickBoxRecycle Instance => _Instance;
internal static ManualLogSource Logger { get; private set; }
private void Awake()
{
_Instance = this;
Logger = ((BaseUnityPlugin)this).Logger;
try
{
Logger.LogInfo((object)"=============================================");
Logger.LogInfo((object)("QuickBoxRecycle " + ModLocalizationManager.Instance.GetLocalizedText("plugin.initializing")));
Logger.LogInfo((object)(ModLocalizationManager.Instance.GetLocalizedText("plugin.author_prefix") + "Ice Box Studio(https://steamcommunity.com/id/ibox666/)"));
ConfigManager.Initialize(((BaseUnityPlugin)this).Config);
ApplyPatches();
Logger.LogInfo((object)("QuickBoxRecycle " + ModLocalizationManager.Instance.GetLocalizedText("plugin.initialized")));
Logger.LogInfo((object)"=============================================");
}
catch (Exception ex)
{
Logger.LogError((object)("QuickBoxRecycle 初始化错误: " + ex.Message + "\n" + ex.StackTrace));
}
}
private void Update()
{
QuickRecycleController.Tick();
}
private void ApplyPatches()
{
//IL_000e: Unknown result type (might be due to invalid IL or missing references)
//IL_0018: Expected O, but got Unknown
if (!patchesApplied)
{
try
{
_harmony = new Harmony("IceBoxStudio.SupermarketTogether.QuickBoxRecycle");
_harmony.PatchAll();
patchesApplied = true;
return;
}
catch (Exception ex)
{
Logger.LogError((object)("QuickBoxRecycle 应用补丁错误: " + ex.Message + "\n" + ex.StackTrace));
return;
}
}
Logger.LogInfo((object)ModLocalizationManager.Instance.GetLocalizedText("plugin.patches_skipped"));
}
}
}
namespace QuickBoxRecycle.Localization
{
public static class LocalizationHelper
{
public static Dictionary<string, string> GetDefaultTranslations(string language)
{
Dictionary<string, string> dictionary = new Dictionary<string, string>();
switch (language)
{
case "Localization_CH1":
dictionary.Add("plugin.initializing", "开始初始化...");
dictionary.Add("plugin.author_prefix", "作者:");
dictionary.Add("plugin.initialized", "初始化成功!");
dictionary.Add("plugin.patches_skipped", "补丁已应用,跳过...");
dictionary.Add("config.recycle_shortcut", "一键回收空箱的快捷键");
dictionary.Add("config.show_notifications", "显示回收提示");
dictionary.Add("recycle.success", "已快速回收空箱,获得 {0}");
dictionary.Add("recycle.no_box", "当前没有抱着可回收的普通箱子。");
dictionary.Add("recycle.not_empty", "当前箱子不是空箱,无法快速回收。");
break;
case "Localization_CH2":
dictionary.Add("plugin.initializing", "開始初始化...");
dictionary.Add("plugin.author_prefix", "作者:");
dictionary.Add("plugin.initialized", "初始化成功!");
dictionary.Add("plugin.patches_skipped", "補丁已套用,跳過...");
dictionary.Add("config.recycle_shortcut", "一鍵回收空箱的快捷鍵");
dictionary.Add("config.show_notifications", "顯示回收提示");
dictionary.Add("recycle.success", "已快速回收空箱,獲得 {0}");
dictionary.Add("recycle.no_box", "目前沒有抱著可回收的普通箱子。");
dictionary.Add("recycle.not_empty", "目前箱子不是空箱,無法快速回收。");
break;
default:
dictionary.Add("plugin.initializing", "Initializing...");
dictionary.Add("plugin.author_prefix", "Author: ");
dictionary.Add("plugin.initialized", "Initialized successfully!");
dictionary.Add("plugin.patches_skipped", "Patches already applied, skipping...");
dictionary.Add("config.recycle_shortcut", "Hotkey for quick empty box recycling");
dictionary.Add("config.show_notifications", "Show recycle notifications");
dictionary.Add("recycle.success", "Empty box recycled, earned {0}");
dictionary.Add("recycle.no_box", "You are not holding a recyclable regular box.");
dictionary.Add("recycle.not_empty", "The current box is not empty and cannot be recycled.");
break;
case "Localization_JP":
dictionary.Add("plugin.initializing", "初期化中...");
dictionary.Add("plugin.author_prefix", "作者:");
dictionary.Add("plugin.initialized", "初期化に成功しました!");
dictionary.Add("plugin.patches_skipped", "パッチは既に適用されているため、スキップします...");
dictionary.Add("config.recycle_shortcut", "空箱を即時回収するホットキー");
dictionary.Add("config.show_notifications", "回収通知を表示");
dictionary.Add("recycle.success", "空箱を即時回収し、{0} を獲得しました");
dictionary.Add("recycle.no_box", "回収可能な通常の箱を持っていません。");
dictionary.Add("recycle.not_empty", "現在の箱は空ではないため、即時回収できません。");
break;
}
return dictionary;
}
}
public class ModLocalizationManager
{
private const string ChineseSimplifiedLocale = "Localization_CH1";
private const string ChineseTraditionalLocale = "Localization_CH2";
private const string EnglishLocale = "Localization_EN";
private const string JapaneseLocale = "Localization_JP";
private static ModLocalizationManager _instance;
private readonly Dictionary<string, Dictionary<string, string>> _localizations = new Dictionary<string, Dictionary<string, string>>();
private string _currentLocale = "Localization_CH1";
public static readonly string[] SupportedLanguages = new string[4] { "Localization_CH1", "Localization_CH2", "Localization_EN", "Localization_JP" };
public static ModLocalizationManager Instance => _instance ?? (_instance = new ModLocalizationManager());
private ModLocalizationManager()
{
Initialize();
}
public void Initialize()
{
string[] supportedLanguages = SupportedLanguages;
foreach (string text in supportedLanguages)
{
Dictionary<string, string> defaultTranslations = LocalizationHelper.GetDefaultTranslations(text);
if (defaultTranslations != null && defaultTranslations.Count != 0)
{
_localizations[text] = defaultTranslations;
}
}
RefreshCurrentLocale();
}
public string GetLocalizedText(string key, params object[] args)
{
RefreshCurrentLocale();
string text = ResolveCurrentLocale();
if (TryGetLocalizedText(text, key, out var text2) || (text != "Localization_EN" && TryGetLocalizedText("Localization_EN", key, out text2)))
{
return FormatLocalizedText(text2, args);
}
return key;
}
private string ResolveCurrentLocale()
{
if (string.IsNullOrEmpty(_currentLocale) || !_localizations.ContainsKey(_currentLocale))
{
_currentLocale = "Localization_EN";
}
return _currentLocale;
}
private bool TryGetLocalizedText(string locale, string key, out string text)
{
text = null;
if (!string.IsNullOrEmpty(locale) && _localizations.TryGetValue(locale, out var value))
{
return value.TryGetValue(key, out text);
}
return false;
}
private static string FormatLocalizedText(string text, object[] args)
{
if (args == null || args.Length == 0)
{
return text;
}
return string.Format(text, args);
}
private void RefreshCurrentLocale()
{
string currentGameLocale = GetCurrentGameLocale();
if (!string.IsNullOrEmpty(currentGameLocale))
{
_currentLocale = MapGameLocaleToModLocale(currentGameLocale);
}
}
private string GetCurrentGameLocale()
{
string text = Application.persistentDataPath + "/Settings/GameOptions.es3";
if (!ES3.KeyExists("GameLanguage", text))
{
return null;
}
return ES3.Load<string>("GameLanguage", text);
}
private static string MapGameLocaleToModLocale(string gameLocale)
{
switch (gameLocale)
{
case "Localization_CH1":
case "Localization_CH2":
case "Localization_JP":
case "Localization_EN":
return gameLocale;
default:
return "Localization_EN";
}
}
}
}
namespace QuickBoxRecycle.Features
{
internal static class QuickRecycleController
{
private const float BoxReward = 1.5f;
private const float Cooldown = 0.25f;
private static float _nextRecycleTime;
public static void Tick()
{
//IL_0012: Unknown result type (might be due to invalid IL or missing references)
if (ConfigManager.Instance != null && Input.GetKeyDown(ConfigManager.Instance.RecycleShortcut.Value) && !IsUiBlocked())
{
TryRecycle();
}
}
private static void TryRecycle()
{
if (Time.unscaledTime < _nextRecycleTime)
{
return;
}
PlayerNetwork localPlayer = GetLocalPlayer();
if ((Object)(object)localPlayer == (Object)null)
{
return;
}
if (!HasBox(localPlayer))
{
Notify("recycle.no_box");
return;
}
if (!IsEmptyBox(localPlayer))
{
Notify("recycle.not_empty");
return;
}
GameData instance = GameData.Instance;
UpgradesManager val = (((Object)(object)instance != (Object)null) ? ((Component)instance).GetComponent<UpgradesManager>() : null);
if (!((Object)(object)instance == (Object)null) && !((Object)(object)val == (Object)null))
{
float num = Mathf.Round(1.5f * (float)val.boxRecycleFactor * 100f) / 100f;
localPlayer.CmdChangeEquippedItem(0);
instance.CmdAlterFunds(num);
if ((Object)(object)AchievementsManager.Instance != (Object)null)
{
AchievementsManager.Instance.CmdAddAchievementPoint(2, 1);
}
if ((Object)(object)StatisticsManager.Instance != (Object)null && NetworkServer.active)
{
StatisticsManager.Instance.AddDataFromFSMOrScript(0, 1);
}
_nextRecycleTime = Time.unscaledTime + 0.25f;
string text = (((Object)(object)ProductListing.Instance != (Object)null) ? ProductListing.Instance.ConvertFloatToTextPrice(num) : ("$" + num.ToString("0.00")));
Notify("recycle.success", text);
}
}
private static PlayerNetwork GetLocalPlayer()
{
PlayerNetwork[] array = Object.FindObjectsByType<PlayerNetwork>((FindObjectsSortMode)0);
for (int i = 0; i < array.Length; i++)
{
if ((Object)(object)array[i] != (Object)null && ((NetworkBehaviour)array[i]).isLocalPlayer)
{
return array[i];
}
}
return null;
}
private static bool HasBox(PlayerNetwork player)
{
if (player.equippedItem == 1)
{
return player.extraParameter1 >= 0;
}
return false;
}
private static bool IsEmptyBox(PlayerNetwork player)
{
return player.extraParameter2 <= 0;
}
private static bool IsUiBlocked()
{
//IL_0028: Unknown result type (might be due to invalid IL or missing references)
//IL_002e: Invalid comparison between Unknown and I4
if ((Object)(object)EventSystem.current != (Object)null && (Object)(object)EventSystem.current.currentSelectedGameObject != (Object)null)
{
return true;
}
if (Cursor.visible || (int)Cursor.lockState != 1)
{
return true;
}
if ((Object)(object)GameCanvas.Instance == (Object)null)
{
return false;
}
if (!IsPanelOpen("Builder") && !IsPanelOpen("SurveillanceContainer") && !IsPanelOpen("EndDayStats") && !IsPanelOpen("SavingContainer"))
{
return IsPanelOpen("HostDisconnect");
}
return true;
}
private static bool IsPanelOpen(string path)
{
Transform val = ((Component)GameCanvas.Instance).transform.Find(path);
if ((Object)(object)val != (Object)null)
{
return ((Component)val).gameObject.activeInHierarchy;
}
return false;
}
private static void Notify(string localizationKey, params object[] args)
{
if (ConfigManager.Instance != null && ConfigManager.Instance.ShowNotifications.Value)
{
ShowNotice(ModLocalizationManager.Instance.GetLocalizedText(localizationKey, args));
}
}
private static void ShowNotice(string message)
{
if (!((Object)(object)GameCanvas.Instance == (Object)null) && !((Object)(object)GameCanvas.Instance.notificationPrefab == (Object)null) && !((Object)(object)GameCanvas.Instance.notificationParentTransform == (Object)null))
{
GameObject obj = Object.Instantiate<GameObject>(GameCanvas.Instance.notificationPrefab, GameCanvas.Instance.notificationParentTransform);
TextMeshProUGUI component = obj.GetComponent<TextMeshProUGUI>();
if ((Object)(object)component != (Object)null)
{
((TMP_Text)component).text = message;
}
obj.SetActive(true);
}
}
}
}
namespace QuickBoxRecycle.Configuration
{
public class ConfigManager
{
private static ConfigManager _instance;
private readonly ConfigFile _configFile;
private readonly Dictionary<string, ConfigEntry<bool>> _boolConfigs = new Dictionary<string, ConfigEntry<bool>>();
private readonly Dictionary<string, ConfigEntry<string>> _stringConfigs = new Dictionary<string, ConfigEntry<string>>();
private readonly Dictionary<string, ConfigEntry<int>> _intConfigs = new Dictionary<string, ConfigEntry<int>>();
private readonly Dictionary<string, ConfigEntry<float>> _floatConfigs = new Dictionary<string, ConfigEntry<float>>();
private readonly Dictionary<string, ConfigEntry<KeyCode>> _keyCodeConfigs = new Dictionary<string, ConfigEntry<KeyCode>>();
public static ConfigManager Instance => _instance;
public ConfigEntry<KeyCode> RecycleShortcut { get; private set; }
public ConfigEntry<bool> ShowNotifications { get; private set; }
private ConfigManager(ConfigFile configFile)
{
_configFile = configFile;
InitializeDefaultConfigs();
}
public static void Initialize(ConfigFile configFile)
{
if (_instance == null)
{
_instance = new ConfigManager(configFile);
}
}
private void InitializeDefaultConfigs()
{
RecycleShortcut = RegisterKeyCode("QuickRecycle", "RecycleShortcut", GetLocalizedDescription("config.recycle_shortcut"), (KeyCode)120);
ShowNotifications = RegisterBool("QuickRecycle", "ShowNotifications", GetLocalizedDescription("config.show_notifications"), defaultValue: true);
}
private string GetLocalizedDescription(string key)
{
return ModLocalizationManager.Instance?.GetLocalizedText(key) ?? key;
}
public ConfigEntry<bool> RegisterBool(string section, string key, string description, bool defaultValue)
{
ConfigEntry<bool> val = _configFile.Bind<bool>(section, key, defaultValue, description);
_boolConfigs[key] = val;
return val;
}
public ConfigEntry<string> RegisterString(string section, string key, string description, string defaultValue)
{
ConfigEntry<string> val = _configFile.Bind<string>(section, key, defaultValue, description);
_stringConfigs[key] = val;
return val;
}
public ConfigEntry<KeyCode> RegisterKeyCode(string section, string key, string description, KeyCode defaultValue)
{
//IL_0008: Unknown result type (might be due to invalid IL or missing references)
ConfigEntry<KeyCode> val = _configFile.Bind<KeyCode>(section, key, defaultValue, description);
_keyCodeConfigs[key] = val;
return val;
}
public ConfigEntry<int> RegisterInt(string section, string key, string description, int defaultValue)
{
ConfigEntry<int> val = _configFile.Bind<int>(section, key, defaultValue, description);
_intConfigs[key] = val;
return val;
}
public ConfigEntry<int> RegisterIntRange(string section, string key, string description, int defaultValue, int minValue, int maxValue)
{
//IL_0019: Unknown result type (might be due to invalid IL or missing references)
//IL_0023: Expected O, but got Unknown
ConfigEntry<int> val = _configFile.Bind<int>(section, key, defaultValue, new ConfigDescription(description, (AcceptableValueBase)(object)new AcceptableValueRange<int>(minValue, maxValue), Array.Empty<object>()));
_intConfigs[key] = val;
return val;
}
public ConfigEntry<float> RegisterFloat(string section, string key, string description, float defaultValue)
{
ConfigEntry<float> val = _configFile.Bind<float>(section, key, defaultValue, description);
_floatConfigs[key] = val;
return val;
}
public ConfigEntry<float> RegisterFloatRange(string section, string key, string description, float defaultValue, float minValue, float maxValue)
{
//IL_0019: Unknown result type (might be due to invalid IL or missing references)
//IL_0023: Expected O, but got Unknown
ConfigEntry<float> val = _configFile.Bind<float>(section, key, defaultValue, new ConfigDescription(description, (AcceptableValueBase)(object)new AcceptableValueRange<float>(minValue, maxValue), Array.Empty<object>()));
_floatConfigs[key] = val;
return val;
}
}
}