using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Text.Json;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Core.Logging.Interpolation;
using BepInEx.Logging;
using BepInEx.NET.Common;
using Candide;
using Candide.GameModels.Helpers;
using CandideServer;
using CandideServer.Game;
using CandideServer.Helpers;
using CandideServer.Models;
using CandideServer.Models.Buildings;
using CandideServer.Models.Citizen;
using CandideServer.Server;
using CandideServer.ServerControllers;
using CandideServer.ServerManagers;
using CandideServer.ServerServices;
using CandideServer.ServerSystems;
using CandideServer.SimulationModels;
using CandideServer.SyncStrategies;
using HarmonyLib;
using Microsoft.Xna.Framework;
using ModSettingsMenu.Api;
using ProsperityTweaks.Configuration;
using ProsperityTweaks.Localizations;
using Shared.Models;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("Prosperity Tweaks")]
[assembly: AssemblyDescription("Prosperity Tweaks for Romestead by Ice Box Studio")]
[assembly: AssemblyCompany("Ice Box Studio")]
[assembly: AssemblyProduct("Prosperity Tweaks")]
[assembly: AssemblyCopyright("Copyright © 2026 Ice Box Studio All rights reserved.")]
[assembly: ComVisible(false)]
[assembly: Guid("8e19e628-4eff-442f-9b7f-f4b975d0b306")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETCoreApp,Version=v8.0", FrameworkDisplayName = ".NET 8.0")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace ProsperityTweaks
{
public static class PluginInfo
{
public const string PLUGIN_GUID = "IceBoxStudio.Romestead.ProsperityTweaks";
public const string PLUGIN_NAME = "Prosperity Tweaks";
public const string PLUGIN_VERSION = "1.0.0";
public const string PLUGIN_AUTHOR = "Ice Box Studio";
public const string PLUGIN_AUTHOR_URL = "https://steamcommunity.com/id/ibox666/";
}
[BepInPlugin("IceBoxStudio.Romestead.ProsperityTweaks", "Prosperity Tweaks", "1.0.0")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public class ProsperityTweaks : BasePlugin
{
public static ProsperityTweaks _Instance;
private Harmony _harmony;
public static ProsperityTweaks Instance => _Instance;
internal static ManualLogSource Logger { get; private set; }
public override void Load()
{
//IL_0141: Unknown result type (might be due to invalid IL or missing references)
//IL_0148: Expected O, but got Unknown
//IL_002f: Unknown result type (might be due to invalid IL or missing references)
//IL_0035: Expected O, but got Unknown
//IL_0063: Unknown result type (might be due to invalid IL or missing references)
//IL_0069: Expected O, but got Unknown
//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
//IL_00d8: Expected O, but got Unknown
//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
//IL_00fb: Expected O, but got Unknown
_Instance = this;
Logger = ((BasePlugin)this).Log;
bool flag = default(bool);
try
{
Logger.LogInfo((object)"=============================================");
ManualLogSource logger = Logger;
BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(16, 1, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>("Prosperity Tweaks");
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" initializing...");
}
logger.LogInfo(val);
ManualLogSource logger2 = Logger;
val = new BepInExInfoLogInterpolatedStringHandler(10, 2, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Author: ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>("Ice Box Studio");
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("(");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>("https://steamcommunity.com/id/ibox666/");
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(")");
}
logger2.LogInfo(val);
ConfigManager.Init(((BasePlugin)this).Config);
ModSettingsMenuRegistration.Register(((BasePlugin)this).Config);
_harmony = new Harmony("IceBoxStudio.Romestead.ProsperityTweaks");
_harmony.PatchAll(Assembly.GetExecutingAssembly());
ManualLogSource logger3 = Logger;
val = new BepInExInfoLogInterpolatedStringHandler(13, 1, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>("Prosperity Tweaks");
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" initialized.");
}
logger3.LogInfo(val);
Logger.LogInfo((object)"=============================================");
}
catch (Exception ex)
{
ManualLogSource logger4 = Logger;
BepInExErrorLogInterpolatedStringHandler val2 = new BepInExErrorLogInterpolatedStringHandler(24, 3, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>("Prosperity Tweaks");
((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" initialization error: ");
((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(ex.Message);
((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("\n");
((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(ex.StackTrace);
}
logger4.LogError(val2);
}
}
}
}
namespace ProsperityTweaks.Patches
{
internal static class AlwaysWetFarmland
{
private static readonly List<Point> ChangedTiles = new List<Point>();
private static bool _wasEnabled;
private static bool _needsCatchUp = true;
private static int _lastCropCount = -1;
public static bool Enabled => PatchHelper.ShouldApply && ConfigManager.KeepFarmlandWet;
public static void Tick()
{
if (!Enabled)
{
_wasEnabled = false;
_needsCatchUp = true;
_lastCropCount = -1;
return;
}
if (!CanUseWorldState())
{
_needsCatchUp = true;
return;
}
int count = ServerGameState.Crops.Count;
if (!_wasEnabled || _needsCatchUp || count != _lastCropCount)
{
WetAllCropTiles();
_lastCropCount = ServerGameState.Crops.Count;
_needsCatchUp = false;
}
_wasEnabled = true;
}
public static void MarkDirty()
{
_needsCatchUp = true;
}
public static void WetCropTile(CropServerModel crop, bool notify)
{
//IL_003c: Unknown result type (might be due to invalid IL or missing references)
if (!Enabled || crop == null)
{
return;
}
if (!CanUseWorldState())
{
MarkDirty();
return;
}
ChangedTiles.Clear();
WetCropTile(crop, new FarmlandStatusModel(ServerGameState.Time), ChangedTiles);
if (notify)
{
SendChangedTiles();
}
if (!_needsCatchUp)
{
_lastCropCount = ServerGameState.Crops.Count;
}
}
private static void WetAllCropTiles()
{
//IL_0035: Unknown result type (might be due to invalid IL or missing references)
ChangedTiles.Clear();
FarmlandStatusModel status = default(FarmlandStatusModel);
((FarmlandStatusModel)(ref status))..ctor(ServerGameState.Time);
foreach (CropServerModel value in ServerGameState.Crops.Values)
{
WetCropTile(value, status, ChangedTiles);
}
SendChangedTiles();
}
private static void WetCropTile(CropServerModel crop, FarmlandStatusModel status, List<Point> changedTiles)
{
//IL_0002: 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_0020: 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)
//IL_0023: Invalid comparison between Unknown and I4
//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)
//IL_002c: Unknown result type (might be due to invalid IL or missing references)
//IL_0076: Unknown result type (might be due to invalid IL or missing references)
if (TryGetFarmTile(crop.TilePosition, out var ground))
{
bool flag = false;
Point tilePosition = crop.TilePosition;
if ((int)ground == 3)
{
WorldTilesServerController.SetTile(tilePosition, (GroundType?)(GroundType)4, (StructureType?)null);
flag = true;
}
ServerGameState.WetFarmlands[tilePosition] = status;
if (!crop.IsWatered)
{
CropServerController.WaterCrop(crop);
flag = true;
}
if (flag)
{
changedTiles.Add(tilePosition);
}
}
}
private static bool TryGetFarmTile(Point point, out GroundType ground)
{
//IL_000d: Unknown result type (might be due to invalid IL or missing references)
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
//IL_004e: Unknown result type (might be due to invalid IL or missing references)
//IL_0054: 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_0065: Expected I4, but got Unknown
//IL_001f: Unknown result type (might be due to invalid IL or missing references)
//IL_002e: Unknown result type (might be due to invalid IL or missing references)
ground = (GroundType)0;
WorldTile[,] worldTiles = ServerGameState.WorldTiles;
if (worldTiles == null || point.X < 0 || point.Y < 0 || point.X >= worldTiles.GetLength(0) || point.Y >= worldTiles.GetLength(1))
{
return false;
}
ground = (GroundType)(int)worldTiles[point.X, point.Y].Ground;
return (int)ground == 3 || (int)ground == 4;
}
private static void SendChangedTiles()
{
//IL_001b: Unknown result type (might be due to invalid IL or missing references)
if (ChangedTiles.Count > 0 && CanNotifyClients())
{
CropServerService.SendWaterCrops(Vector2.Zero, ChangedTiles);
}
}
private static bool CanUseWorldState()
{
return ServerGameState.WorldTiles != null && ServerGameState.Crops != null && ServerGameState.WetFarmlands != null;
}
private static bool CanNotifyClients()
{
return ServerRunState.OutsideWorld != null;
}
}
[HarmonyPatch(typeof(CropServerSystem), "UpdateWetFarmlandCheck", new Type[] { typeof(float) })]
internal static class WetFarmlandDryPatch
{
private static bool Prefix()
{
return !AlwaysWetFarmland.Enabled;
}
}
[HarmonyPatch(typeof(CropServerSystem), "Update", new Type[] { typeof(GameTime) })]
internal static class AlwaysWetFarmlandUpdatePatch
{
private static void Postfix()
{
AlwaysWetFarmland.Tick();
}
}
[HarmonyPatch(typeof(CropServerManager), "SpawnCrop", new Type[]
{
typeof(string),
typeof(Point),
typeof(bool),
typeof(SyncStrategy)
})]
internal static class SpawnCropWaterSyncPatch
{
private static void Postfix(CropServerModel __result)
{
AlwaysWetFarmland.WetCropTile(__result, notify: true);
}
}
[HarmonyPatch(typeof(CropServerController), "AfterWorldGameStateLoaded")]
internal static class LoadedCropsWetFarmlandPatch
{
private static void Postfix()
{
AlwaysWetFarmland.MarkDirty();
}
}
[HarmonyPatch(typeof(BuildingSimulationModel), "Update", new Type[] { typeof(float) })]
internal static class BuildingTickPatch
{
private static void Prefix(ref float dt)
{
if (PatchHelper.ShouldApply)
{
dt *= ConfigManager.BuildingTick;
}
}
}
[HarmonyPatch(typeof(CropServerSystem), "Update", new Type[] { typeof(GameTime) })]
internal static class CropServerSystemPatch
{
private static void Prefix(out ConfigScaleState __state)
{
float original;
bool changed = PatchHelper.TryScaleConfig(ConfigManager.CropGrowth, ConfigField.CropGrowthSpeedMultiplier, out original);
__state = new ConfigScaleState(changed, original);
}
private static void Postfix(ConfigScaleState __state)
{
PatchHelper.RestoreConfig(ConfigField.CropGrowthSpeedMultiplier, __state.Original, __state.Changed);
}
private static Exception Finalizer(Exception __exception, ConfigScaleState __state)
{
PatchHelper.RestoreConfig(ConfigField.CropGrowthSpeedMultiplier, __state.Original, __state.Changed);
return __exception;
}
}
[HarmonyPatch(typeof(BuildingFurnaceHelper), "Tick", new Type[]
{
typeof(BuildingSimulationModel),
typeof(SourceModel),
typeof(bool)
})]
internal static class FuelPatch
{
private static void Prefix(out ConfigScaleState __state)
{
float original;
bool changed = PatchHelper.TryScaleConfig(ConfigManager.FuelDrain, ConfigField.FuelDrainMultiplier, out original);
__state = new ConfigScaleState(changed, original);
}
private static void Postfix(ConfigScaleState __state)
{
PatchHelper.RestoreConfig(ConfigField.FuelDrainMultiplier, __state.Original, __state.Changed);
}
private static Exception Finalizer(Exception __exception, ConfigScaleState __state)
{
PatchHelper.RestoreConfig(ConfigField.FuelDrainMultiplier, __state.Original, __state.Changed);
return __exception;
}
}
[HarmonyPatch(typeof(JobHelper), "GetJobTickForCurrentJob", new Type[]
{
typeof(CitizenModel),
typeof(float)
})]
internal static class JobHelperPatch
{
private static void Postfix(ref float __result)
{
if (PatchHelper.ShouldApply)
{
__result *= ConfigManager.JobProgress;
}
}
}
internal static class PatchHelper
{
public static bool ShouldApply => ConfigManager.Active && IsServerRunning;
private static bool IsServerRunning
{
get
{
BaseServer instance = BaseServer.Instance;
return instance.Running || instance.Updating || ServerGlobals.StandAlone;
}
}
public static bool TryScaleConfig(float multiplier, ConfigField field, out float original)
{
original = 1f;
if (!ShouldApply || multiplier == 1f || ServerGameState.Config == null)
{
return false;
}
GameConfig config = ServerGameState.Config;
original = Get(config, field);
Set(config, field, original * multiplier);
return true;
}
public static void RestoreConfig(ConfigField field, float original, bool changed)
{
if (changed && ServerGameState.Config != null)
{
Set(ServerGameState.Config, field, original);
}
}
private static float Get(GameConfig config, ConfigField field)
{
return field switch
{
ConfigField.CropGrowthSpeedMultiplier => config.CropGrowthSpeedMultiplier,
ConfigField.FuelDrainMultiplier => config.FuelDrainMultiplier,
_ => 1f,
};
}
private static void Set(GameConfig config, ConfigField field, float value)
{
switch (field)
{
case ConfigField.CropGrowthSpeedMultiplier:
config.CropGrowthSpeedMultiplier = value;
break;
case ConfigField.FuelDrainMultiplier:
config.FuelDrainMultiplier = value;
break;
}
}
}
internal enum ConfigField
{
CropGrowthSpeedMultiplier,
FuelDrainMultiplier
}
internal readonly struct ConfigScaleState
{
public bool Changed { get; }
public float Original { get; }
public ConfigScaleState(bool changed, float original)
{
Changed = changed;
Original = original;
}
}
[HarmonyPatch(typeof(TradeRoutesHelper), "Server_GetRouteTime", new Type[]
{
typeof(BuildingInstanceModel),
typeof(BuildingInstanceModel),
typeof(CitizenModel),
typeof(GameConfig),
typeof(float)
})]
internal static class TradeRoutesPatch
{
private static void Postfix(ref float __result)
{
if (PatchHelper.ShouldApply)
{
__result /= ConfigManager.TradeRouteSpeed;
}
}
}
}
namespace ProsperityTweaks.Localizations
{
internal static class LocalizationHelper
{
public static readonly string[] SupportedLanguages = new string[4] { "zh_CN", "zh_TW", "en", "ja_JP" };
public static Dictionary<string, string> GetDefaultTranslations(string language)
{
Dictionary<string, string> dictionary = new Dictionary<string, string>();
switch (language)
{
case "zh_CN":
dictionary.Add("mod.name", "繁荣调整");
dictionary.Add("mod.description", "调整农业、农田湿润、生产、燃料和贸易路线速度,让定居点发展更轻松。");
dictionary.Add("section.general", "通用");
dictionary.Add("section.production", "生产");
dictionary.Add("section.resources", "资源");
dictionary.Add("section.trade", "贸易");
dictionary.Add("entry.enabled", "启用模组");
dictionary.Add("entry.crop_growth", "作物成长倍率");
dictionary.Add("entry.always_wet_farmland", "永湿农田");
dictionary.Add("entry.building_tick", "建筑生产倍率");
dictionary.Add("entry.job_progress", "工作进度倍率");
dictionary.Add("entry.fuel_drain", "燃料消耗倍率");
dictionary.Add("entry.trade_route_speed", "贸易路线速度倍率");
dictionary.Add("config.enabled.description", "繁荣调整总开关。");
dictionary.Add("config.crop_growth.description", "额外作用于作物成长速度的倍率。");
dictionary.Add("config.always_wet_farmland.description", "作物所在的农田会自动保持湿润,并阻止湿农田自然变干。");
dictionary.Add("config.building_tick.description", "额外作用于建筑生产速度的倍率。");
dictionary.Add("config.job_progress.description", "额外作用于村民单次工作进度的倍率,会和建筑生产倍率叠加。");
dictionary.Add("config.fuel_drain.description", "额外作用于炉子燃料消耗的倍率。数值越低,燃料越耐烧。");
dictionary.Add("config.trade_route_speed.description", "额外作用于贸易路线速度的倍率。");
break;
case "zh_TW":
dictionary.Add("mod.name", "繁榮調整");
dictionary.Add("mod.description", "調整農業、農田濕潤、生產、燃料和貿易路線速度,讓聚落發展更輕鬆。");
dictionary.Add("section.general", "通用");
dictionary.Add("section.production", "生產");
dictionary.Add("section.resources", "資源");
dictionary.Add("section.trade", "貿易");
dictionary.Add("entry.enabled", "啟用模組");
dictionary.Add("entry.crop_growth", "作物成長倍率");
dictionary.Add("entry.always_wet_farmland", "永濕農田");
dictionary.Add("entry.building_tick", "建築生產倍率");
dictionary.Add("entry.job_progress", "工作進度倍率");
dictionary.Add("entry.fuel_drain", "燃料消耗倍率");
dictionary.Add("entry.trade_route_speed", "貿易路線速度倍率");
dictionary.Add("config.enabled.description", "繁榮調整總開關。");
dictionary.Add("config.crop_growth.description", "額外作用於作物成長速度的倍率。");
dictionary.Add("config.always_wet_farmland.description", "作物所在的農田會自動保持濕潤,並阻止濕農田自然變乾。");
dictionary.Add("config.building_tick.description", "額外作用於建築生產速度的倍率。");
dictionary.Add("config.job_progress.description", "額外作用於村民單次工作進度的倍率,會和建築生產倍率疊加。");
dictionary.Add("config.fuel_drain.description", "額外作用於爐子燃料消耗的倍率。數值越低,燃料越耐燒。");
dictionary.Add("config.trade_route_speed.description", "額外作用於貿易路線速度的倍率。");
break;
case "ja_JP":
dictionary.Add("mod.name", "Prosperity Tweaks");
dictionary.Add("mod.description", "農業、畑の湿り具合、生産、燃料、交易ルートの速度を調整し、集落の発展を楽にします。");
dictionary.Add("section.general", "全般");
dictionary.Add("section.production", "生産");
dictionary.Add("section.resources", "資源");
dictionary.Add("section.trade", "交易");
dictionary.Add("entry.enabled", "MODを有効化");
dictionary.Add("entry.crop_growth", "作物成長倍率");
dictionary.Add("entry.always_wet_farmland", "畑を常に湿らせる");
dictionary.Add("entry.building_tick", "建物生産倍率");
dictionary.Add("entry.job_progress", "作業進行倍率");
dictionary.Add("entry.fuel_drain", "燃料消費倍率");
dictionary.Add("entry.trade_route_speed", "交易ルート速度倍率");
dictionary.Add("config.enabled.description", "Prosperity Tweaks のマスタースイッチ。");
dictionary.Add("config.crop_growth.description", "作物の成長速度に追加で適用される倍率。");
dictionary.Add("config.always_wet_farmland.description", "作物が植えられている畑を自動的に湿らせ、湿った畑が自然に乾かないようにします。");
dictionary.Add("config.building_tick.description", "建物の作業速度に追加で適用される倍率。");
dictionary.Add("config.job_progress.description", "住民の 1 tick あたりの作業進行量に追加で適用される倍率。建物生産倍率と重なります。");
dictionary.Add("config.fuel_drain.description", "炉の燃料消費に追加で適用される倍率。低いほど燃料が長持ちします。");
dictionary.Add("config.trade_route_speed.description", "交易ルート速度に追加で適用される倍率。");
break;
case "en":
dictionary.Add("mod.name", "Prosperity Tweaks");
dictionary.Add("mod.description", "Tune farming, farmland wetness, production, fuel, and trade route speed to make settlement growth smoother.");
dictionary.Add("section.general", "General");
dictionary.Add("section.production", "Production");
dictionary.Add("section.resources", "Resources");
dictionary.Add("section.trade", "Trade");
dictionary.Add("entry.enabled", "Enable Mod");
dictionary.Add("entry.crop_growth", "Crop Growth Multiplier");
dictionary.Add("entry.always_wet_farmland", "Always Wet Farmland");
dictionary.Add("entry.building_tick", "Building Production Multiplier");
dictionary.Add("entry.job_progress", "Job Progress Multiplier");
dictionary.Add("entry.fuel_drain", "Fuel Drain Multiplier");
dictionary.Add("entry.trade_route_speed", "Trade Route Speed Multiplier");
dictionary.Add("config.enabled.description", "Master switch for Prosperity Tweaks.");
dictionary.Add("config.crop_growth.description", "Extra multiplier applied to crop growth speed.");
dictionary.Add("config.always_wet_farmland.description", "Automatically keeps farmland with crops wet and prevents wet farmland from drying naturally.");
dictionary.Add("config.building_tick.description", "Extra multiplier applied to building work speed.");
dictionary.Add("config.job_progress.description", "Extra multiplier applied to citizen work progress per tick. This stacks with Building Production Multiplier.");
dictionary.Add("config.fuel_drain.description", "Extra multiplier applied to furnace fuel drain. Lower values make fuel last longer.");
dictionary.Add("config.trade_route_speed.description", "Extra multiplier applied to trade route speed.");
break;
}
return dictionary;
}
}
internal sealed class LocalizationManager
{
private static LocalizationManager _instance;
private readonly Dictionary<string, Dictionary<string, string>> _localizations = new Dictionary<string, Dictionary<string, string>>(StringComparer.OrdinalIgnoreCase);
private string _currentLocale = "en";
public static LocalizationManager Instance => _instance ?? (_instance = new LocalizationManager());
public string CurrentLocale => _currentLocale;
public event Action LanguageChanged;
private LocalizationManager()
{
Initialize();
}
public void Initialize()
{
_localizations.Clear();
string[] supportedLanguages = LocalizationHelper.SupportedLanguages;
foreach (string text in supportedLanguages)
{
Dictionary<string, string> defaultTranslations = LocalizationHelper.GetDefaultTranslations(text);
if (defaultTranslations.Count > 0)
{
_localizations[text] = defaultTranslations;
}
}
RefreshLanguage(forceNotify: false);
}
public void RefreshLanguage(bool forceNotify = true)
{
string text = DetectLocale();
if (!_localizations.ContainsKey(text))
{
text = "en";
}
bool flag = !string.Equals(_currentLocale, text, StringComparison.OrdinalIgnoreCase);
_currentLocale = text;
if (flag || forceNotify)
{
this.LanguageChanged?.Invoke();
}
}
public string GetText(string key, params object[] args)
{
RefreshLanguage(forceNotify: false);
string text = TryGetText(_currentLocale, key) ?? TryGetText("en", key) ?? TryGetText("zh_CN", key) ?? key;
return (args != null && args.Length != 0) ? string.Format(text, args) : text;
}
private string TryGetText(string locale, string key)
{
Dictionary<string, string> value;
string value2;
return (_localizations.TryGetValue(locale, out value) && value.TryGetValue(key, out value2)) ? value2 : null;
}
private static string DetectLocale()
{
if (!string.IsNullOrWhiteSpace(Globals.LanguageCode))
{
return NormalizeLocale(Globals.LanguageCode);
}
string text = ReadSavedLocale();
if (!string.IsNullOrWhiteSpace(text))
{
return NormalizeLocale(text);
}
return NormalizeLocale(CultureInfo.CurrentCulture.Name);
}
private static string ReadSavedLocale()
{
try
{
string path = Path.Combine(GamePathHelper.GetFolderPath((GameFolder)1, false), "localization.json");
if (!File.Exists(path))
{
return null;
}
using FileStream utf8Json = File.OpenRead(path);
using JsonDocument jsonDocument = JsonDocument.Parse((Stream)utf8Json, new JsonDocumentOptions
{
AllowTrailingCommas = true,
CommentHandling = JsonCommentHandling.Skip
});
JsonElement value;
return (jsonDocument.RootElement.TryGetProperty("LanguageCode", out value) && value.ValueKind == JsonValueKind.String) ? value.GetString() : null;
}
catch
{
return null;
}
}
private static string NormalizeLocale(string languageCode)
{
switch ((languageCode ?? string.Empty).Replace('-', '_'))
{
case "zh_CN":
case "zh_Hans":
return "zh_CN";
case "zh_TW":
case "zh_HK":
case "zh_MO":
case "zh_Hant":
return "zh_TW";
case "ja_JP":
case "ja":
return "ja_JP";
case "en":
case "en_US":
case "en_GB":
return "en";
default:
return "en";
}
}
}
}
namespace ProsperityTweaks.Configuration
{
internal static class ConfigManager
{
public const string GeneralSection = "General";
public const string ProductionSection = "Production";
public const string ResourcesSection = "Resources";
public const string TradeSection = "Trade";
public static ConfigEntry<bool> Enabled { get; private set; }
public static ConfigEntry<float> CropGrowthMultiplier { get; private set; }
public static ConfigEntry<bool> AlwaysWetFarmland { get; private set; }
public static ConfigEntry<float> BuildingTickMultiplier { get; private set; }
public static ConfigEntry<float> JobProgressMultiplier { get; private set; }
public static ConfigEntry<float> FuelDrainMultiplier { get; private set; }
public static ConfigEntry<float> TradeRouteSpeedMultiplier { get; private set; }
public static float CropGrowth => GetMultiplier(CropGrowthMultiplier);
public static bool KeepFarmlandWet => AlwaysWetFarmland?.Value ?? false;
public static float BuildingTick => GetMultiplier(BuildingTickMultiplier);
public static float JobProgress => GetMultiplier(JobProgressMultiplier);
public static float FuelDrain => GetMultiplier(FuelDrainMultiplier);
public static float TradeRouteSpeed => GetMultiplier(TradeRouteSpeedMultiplier);
public static bool Active => Enabled?.Value ?? false;
public static void Init(ConfigFile config)
{
Enabled = config.Bind<bool>("General", "Enabled", true, Text("config.enabled.description"));
CropGrowthMultiplier = config.Bind<float>("Production", "CropGrowthMultiplier", 1f, Range("config.crop_growth.description", 0.1f, 50f));
AlwaysWetFarmland = config.Bind<bool>("Production", "AlwaysWetFarmland", false, Text("config.always_wet_farmland.description"));
BuildingTickMultiplier = config.Bind<float>("Production", "BuildingTickMultiplier", 1f, Range("config.building_tick.description", 0.1f, 50f));
JobProgressMultiplier = config.Bind<float>("Production", "JobProgressMultiplier", 1f, Range("config.job_progress.description", 0.1f, 50f));
FuelDrainMultiplier = config.Bind<float>("Resources", "FuelDrainMultiplier", 1f, Range("config.fuel_drain.description", 0f, 1f));
TradeRouteSpeedMultiplier = config.Bind<float>("Trade", "TradeRouteSpeedMultiplier", 1f, Range("config.trade_route_speed.description", 0.1f, 50f));
}
private static ConfigDescription Range(string descriptionKey, float min, float max)
{
//IL_0013: Unknown result type (might be due to invalid IL or missing references)
//IL_0019: Expected O, but got Unknown
return new ConfigDescription(Text(descriptionKey), (AcceptableValueBase)(object)new AcceptableValueRange<float>(min, max), Array.Empty<object>());
}
private static float GetMultiplier(ConfigEntry<float> entry)
{
return entry?.Value ?? 1f;
}
private static string Text(string key)
{
return LocalizationManager.Instance.GetText(key);
}
}
internal static class ModSettingsMenuRegistration
{
private static ConfigFile _config;
private static string _locale;
private static bool _subscribed;
public static void Register(ConfigFile config)
{
_config = config;
if (!_subscribed)
{
ModSettingsRegistry.RefreshRequested += Refresh;
_subscribed = true;
}
RegisterCurrent(config);
}
public static void Refresh()
{
if (_config != null)
{
LocalizationManager.Instance.RefreshLanguage(forceNotify: false);
string currentLocale = LocalizationManager.Instance.CurrentLocale;
ModSettingsRegistration val = default(ModSettingsRegistration);
if (!(_locale == currentLocale) || !ModSettingsRegistry.TryGet("IceBoxStudio.Romestead.ProsperityTweaks", ref val))
{
RegisterCurrent(_config);
}
}
}
private static void RegisterCurrent(ConfigFile config)
{
ModSettingsRegistry.Register("IceBoxStudio.Romestead.ProsperityTweaks", Text("mod.name"), config, (Action<ModSettingsRegistration>)delegate(ModSettingsRegistration registration)
{
registration.Icon = "cog";
registration.Version = "1.0.0";
registration.Author = "Ice Box Studio";
registration.Description = Text("mod.description");
registration.NexusModsId = 22;
registration.UpdateManifestUrl = "https://fastly.jsdelivr.net/gh/ibox233/MyMod_Version@main/ProsperityTweaks.json";
registration.Order = -80;
registration.ConfigureSection("General", (Action<ModSettingsSectionOptions>)delegate(ModSettingsSectionOptions section)
{
section.DisplayName = Text("section.general");
section.Order = 10;
});
registration.ConfigureSection("Production", (Action<ModSettingsSectionOptions>)delegate(ModSettingsSectionOptions section)
{
section.DisplayName = Text("section.production");
section.Order = 20;
});
registration.ConfigureSection("Resources", (Action<ModSettingsSectionOptions>)delegate(ModSettingsSectionOptions section)
{
section.DisplayName = Text("section.resources");
section.Order = 30;
});
registration.ConfigureSection("Trade", (Action<ModSettingsSectionOptions>)delegate(ModSettingsSectionOptions section)
{
section.DisplayName = Text("section.trade");
section.Order = 40;
});
registration.ConfigureEntry("General", "Enabled", (Action<ModSettingsEntryOptions>)delegate(ModSettingsEntryOptions entry)
{
entry.DisplayName = Text("entry.enabled");
entry.Description = Text("config.enabled.description");
entry.Order = 1;
});
registration.ConfigureEntry("Production", "CropGrowthMultiplier", (Action<ModSettingsEntryOptions>)delegate(ModSettingsEntryOptions entry)
{
entry.DisplayName = Text("entry.crop_growth");
entry.Description = Text("config.crop_growth.description");
entry.SliderStep = 0.1;
entry.Order = 1;
});
registration.ConfigureEntry("Production", "AlwaysWetFarmland", (Action<ModSettingsEntryOptions>)delegate(ModSettingsEntryOptions entry)
{
entry.DisplayName = Text("entry.always_wet_farmland");
entry.Description = Text("config.always_wet_farmland.description");
entry.Order = 2;
});
registration.ConfigureEntry("Production", "BuildingTickMultiplier", (Action<ModSettingsEntryOptions>)delegate(ModSettingsEntryOptions entry)
{
entry.DisplayName = Text("entry.building_tick");
entry.Description = Text("config.building_tick.description");
entry.SliderStep = 0.1;
entry.Order = 3;
});
registration.ConfigureEntry("Production", "JobProgressMultiplier", (Action<ModSettingsEntryOptions>)delegate(ModSettingsEntryOptions entry)
{
entry.DisplayName = Text("entry.job_progress");
entry.Description = Text("config.job_progress.description");
entry.SliderStep = 0.1;
entry.Order = 4;
});
registration.ConfigureEntry("Resources", "FuelDrainMultiplier", (Action<ModSettingsEntryOptions>)delegate(ModSettingsEntryOptions entry)
{
entry.DisplayName = Text("entry.fuel_drain");
entry.Description = Text("config.fuel_drain.description");
entry.SliderStep = 0.1;
entry.Order = 1;
});
registration.ConfigureEntry("Trade", "TradeRouteSpeedMultiplier", (Action<ModSettingsEntryOptions>)delegate(ModSettingsEntryOptions entry)
{
entry.DisplayName = Text("entry.trade_route_speed");
entry.Description = Text("config.trade_route_speed.description");
entry.SliderStep = 0.1;
entry.Order = 1;
});
});
_locale = LocalizationManager.Instance.CurrentLocale;
}
private static string Text(string key)
{
return LocalizationManager.Instance.GetText(key);
}
}
}