diff --git a/StardewArchipelago/Archipelago/ModsManager.cs b/StardewArchipelago/Archipelago/ModsManager.cs index 52072bc44..1acdd0b6b 100644 --- a/StardewArchipelago/Archipelago/ModsManager.cs +++ b/StardewArchipelago/Archipelago/ModsManager.cs @@ -3,6 +3,7 @@ using System.Linq; using KaitoKid.ArchipelagoUtilities.Net.Interfaces; using StardewArchipelago.Constants.Modded; +using StardewArchipelago.GameModifications.Testing; using StardewModdingAPI; namespace StardewArchipelago.Archipelago @@ -11,12 +12,14 @@ namespace StardewArchipelago.Archipelago public class ModsManager { private readonly ILogger _logger; + private readonly TesterFeatures _testerFeatures; private readonly List _activeMods; private readonly VersionValidator _versionValidator; - public ModsManager(ILogger logger, List activeMods) + public ModsManager(ILogger logger, TesterFeatures testerFeatures, List activeMods) { _logger = logger; + _testerFeatures = testerFeatures; _activeMods = activeMods; _versionValidator = new VersionValidator(); } @@ -117,10 +120,18 @@ private bool IsModActiveAndCorrectVersion(List loadedModData, string d } existingVersion = modInfo.Manifest.Version.ToString(); + if (_testerFeatures.UnstableMods.Value != VerifyMods.MODS_AND_VERSIONS) + { + return true; + } return _versionValidator.IsVersionCorrect(existingVersion, desiredVersion); } existingVersion = "[NOT FOUND]"; + if (_testerFeatures.UnstableMods.Value == VerifyMods.NOTHING) + { + return true; + } return false; } diff --git a/StardewArchipelago/Archipelago/SlotData.cs b/StardewArchipelago/Archipelago/SlotData.cs index b1a722a16..cb1d445e7 100644 --- a/StardewArchipelago/Archipelago/SlotData.cs +++ b/StardewArchipelago/Archipelago/SlotData.cs @@ -3,6 +3,7 @@ using System.Linq; using KaitoKid.ArchipelagoUtilities.Net.Interfaces; using Newtonsoft.Json; +using StardewArchipelago.GameModifications.Testing; using StardewValley; using StardewValley.GameData; @@ -109,7 +110,7 @@ public class SlotData : ISlotData public bool AppearanceRandomizationDaily { get; set; } public ModsManager Mods { get; set; } - public SlotData(string slotName, Dictionary slotDataFields, ILogger logger) + public SlotData(string slotName, Dictionary slotDataFields, ILogger logger, TesterFeatures testerFeatures) { SlotName = slotName; _slotDataFields = slotDataFields; @@ -164,7 +165,7 @@ public SlotData(string slotName, Dictionary slotDataFields, ILog AppearanceRandomizationDaily = false; // GetSlotSetting(RANDOMIZE_NPC_APPEARANCES_DAILY_KEY, false); var modsString = GetSlotSetting(MOD_LIST_KEY, ""); var mods = JsonConvert.DeserializeObject>(modsString); - Mods = new ModsManager(_logger, mods); + Mods = new ModsManager(_logger, testerFeatures, mods); } private Walnutsanity GetSlotWalnutsanitySetting() diff --git a/StardewArchipelago/Archipelago/StardewArchipelagoClient.cs b/StardewArchipelago/Archipelago/StardewArchipelagoClient.cs index e8a1c2119..84ec0f2c7 100644 --- a/StardewArchipelago/Archipelago/StardewArchipelagoClient.cs +++ b/StardewArchipelago/Archipelago/StardewArchipelagoClient.cs @@ -11,6 +11,7 @@ using KaitoKid.ArchipelagoUtilities.Net.Interfaces; using Microsoft.Xna.Framework; using StardewArchipelago.Extensions; +using StardewArchipelago.GameModifications.Testing; using StardewModdingAPI; using StardewValley; @@ -21,6 +22,7 @@ public class StardewArchipelagoClient : ArchipelagoClient private readonly IModHelper _modHelper; private readonly IManifest _manifest; private readonly Harmony _harmony; + private readonly TesterFeatures _testerFeatures; private IDataStorageWrapper _bigIntegerDataStorage; private DeathManager _deathManager; @@ -30,17 +32,18 @@ public class StardewArchipelagoClient : ArchipelagoClient public SlotData SlotData => (SlotData)_slotData; - public StardewArchipelagoClient(ILogger logger, IModHelper modHelper, IManifest manifest, Harmony harmony, Action itemReceivedFunction, IJsonLoader jsonLoader) : + public StardewArchipelagoClient(ILogger logger, IModHelper modHelper, IManifest manifest, Harmony harmony, Action itemReceivedFunction, IJsonLoader jsonLoader, TesterFeatures testerFeatures) : base(logger, new DataPackageCache(new ArchipelagoItemLoader(jsonLoader), new StardewArchipelagoLocationLoader(jsonLoader), "stardew_valley", "IdTables"), itemReceivedFunction) { _modHelper = modHelper; _manifest = manifest; _harmony = harmony; + _testerFeatures = testerFeatures; } protected override void InitializeSlotData(string slotName, Dictionary slotDataFields) { - _slotData = new SlotData(slotName, slotDataFields, Logger); + _slotData = new SlotData(slotName, slotDataFields, Logger, _testerFeatures); } public override bool ConnectToMultiworld(ArchipelagoConnectionInfo connectionInfo, out string errorMessage) @@ -49,8 +52,7 @@ public override bool ConnectToMultiworld(ArchipelagoConnectionInfo connectionInf { return false; } - -#if RELEASE + if (!SlotData.Mods.IsModStateCorrect(_modHelper, out errorMessage)) { DisconnectPermanently(); @@ -62,7 +64,7 @@ public override bool ConnectToMultiworld(ArchipelagoConnectionInfo connectionInf DisconnectPermanently(); return false; } -#endif + return true; } diff --git a/StardewArchipelago/GameModifications/AdvancedOptionsManager.cs b/StardewArchipelago/GameModifications/AdvancedOptionsManager.cs index d053a797c..afe9b5ed2 100644 --- a/StardewArchipelago/GameModifications/AdvancedOptionsManager.cs +++ b/StardewArchipelago/GameModifications/AdvancedOptionsManager.cs @@ -3,6 +3,7 @@ using KaitoKid.ArchipelagoUtilities.Net.Interfaces; using Microsoft.Xna.Framework; using StardewArchipelago.Archipelago; +using StardewArchipelago.GameModifications.Testing; using StardewModdingAPI; using StardewValley; using StardewValley.Menus; @@ -16,14 +17,16 @@ public class AdvancedOptionsManager private static IModHelper _modHelper; private readonly Harmony _harmony; private static StardewArchipelagoClient _archipelago; + private static TesterFeatures _testerFeatures; - public AdvancedOptionsManager(ModEntry modEntry, ILogger logger, IModHelper modHelper, Harmony harmony, StardewArchipelagoClient archipelago) + public AdvancedOptionsManager(ModEntry modEntry, ILogger logger, IModHelper modHelper, Harmony harmony, StardewArchipelagoClient archipelago, TesterFeatures testerFeatures) { _modEntry = modEntry; _logger = logger; _modHelper = modHelper; _harmony = harmony; _archipelago = archipelago; + _testerFeatures = testerFeatures; } public void InjectArchipelagoAdvancedOptions() @@ -99,6 +102,8 @@ public static bool LoadForNewGame_ForceSettings_Prefix(bool loadedGame = false) ForceFarmTypeToArchipelagoProvidedFarm(); Game1.bundleType = Game1.BundleType.Default; Game1.game1.SetNewGameOption("YearOneCompletable", false); + Game1.startingCabins = _testerFeatures.Multiplayer.Value; + Game1.cabinsSeparate = false; return true; // run original logic } diff --git a/StardewArchipelago/GameModifications/Testing/Constants.cs b/StardewArchipelago/GameModifications/Testing/Constants.cs new file mode 100644 index 000000000..7d3aaa773 --- /dev/null +++ b/StardewArchipelago/GameModifications/Testing/Constants.cs @@ -0,0 +1,9 @@ +namespace StardewArchipelago.GameModifications.Testing +{ + public static class VerifyMods + { + public const int MODS_AND_VERSIONS = 0; + public const int MODS_ONLY = 1; + public const int NOTHING = 2; + } +} diff --git a/StardewArchipelago/GameModifications/Testing/TesterFeature.cs b/StardewArchipelago/GameModifications/Testing/TesterFeature.cs new file mode 100644 index 000000000..78a146fd9 --- /dev/null +++ b/StardewArchipelago/GameModifications/Testing/TesterFeature.cs @@ -0,0 +1,14 @@ +namespace StardewArchipelago.GameModifications.Testing +{ + public class TesterFeature + { + public string Name { get; set; } + public int Value { get; set; } + + public TesterFeature(string name, int defaultValue) + { + Name = name; + Value = defaultValue; + } + } +} diff --git a/StardewArchipelago/GameModifications/Testing/TesterFeatureNames.cs b/StardewArchipelago/GameModifications/Testing/TesterFeatureNames.cs new file mode 100644 index 000000000..89bad347b --- /dev/null +++ b/StardewArchipelago/GameModifications/Testing/TesterFeatureNames.cs @@ -0,0 +1,8 @@ +namespace StardewArchipelago.GameModifications.Testing +{ + public class TesterFeatureNames + { + public const string UNSTABLE_MODS = "VerifyMods"; + public const string MULTIPLAYER = "Multiplayer"; + } +} diff --git a/StardewArchipelago/GameModifications/Testing/TesterFeatures.cs b/StardewArchipelago/GameModifications/Testing/TesterFeatures.cs new file mode 100644 index 000000000..b39a99435 --- /dev/null +++ b/StardewArchipelago/GameModifications/Testing/TesterFeatures.cs @@ -0,0 +1,49 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using KaitoKid.ArchipelagoUtilities.Net.Interfaces; +using StardewModdingAPI; + +namespace StardewArchipelago.GameModifications.Testing +{ + public class TesterFeatures + { + private const string TESTER_FEATURES_FILE = "tester.json"; + public readonly TesterFeature Multiplayer = new(TesterFeatureNames.MULTIPLAYER, 0); + public readonly TesterFeature UnstableMods = new(TesterFeatureNames.UNSTABLE_MODS, VerifyMods.MODS_AND_VERSIONS); + private readonly Dictionary _featuresByName = new(); + + public TesterFeatures(ILogger logger, IModHelper modHelper) + { + _featuresByName.Add(Multiplayer.Name, Multiplayer); + _featuresByName.Add(UnstableMods.Name, UnstableMods); + +#if DEBUG + UnstableMods.Value = VerifyMods.NOTHING; +#endif + + try + { + var entries = modHelper.Data.ReadJsonFile>(TESTER_FEATURES_FILE); + if (entries == null || !entries.Any()) + { + return; + } + + foreach (var (name, value) in entries) + { + if (!_featuresByName.ContainsKey(name)) + { + continue; + } + + _featuresByName[name].Value = value; + } + } + catch (Exception ex) + { + logger.LogError($"Failed at reading the TesterFeatures file. The file is probably corrupted and should be deleted to start fresh, or fixed manually"); + } + } + } +} diff --git a/StardewArchipelago/Locations/Patcher/ModLocationPatcher.cs b/StardewArchipelago/Locations/Patcher/ModLocationPatcher.cs index 067a55c90..582a7ebdd 100644 --- a/StardewArchipelago/Locations/Patcher/ModLocationPatcher.cs +++ b/StardewArchipelago/Locations/Patcher/ModLocationPatcher.cs @@ -1,4 +1,5 @@ -using HarmonyLib; +using System; +using HarmonyLib; using KaitoKid.ArchipelagoUtilities.Net.Interfaces; using StardewArchipelago.Archipelago; using StardewArchipelago.Constants.Modded; @@ -38,14 +39,20 @@ public ModLocationPatcher(Harmony harmony, ILogger logger, IModHelper modHelper, public void ReplaceAllLocationsRewardsWithChecks() { - AddModSkillInjections(); - AddDeepWoodsModInjections(); - AddMagicModInjections(); - AddSkullCavernElevatorModInjections(); - AddSVEModInjections(); - AddBoardingHouseInjections(); - PatchSVEShops(); - + try + { + AddModSkillInjections(); + AddDeepWoodsModInjections(); + AddMagicModInjections(); + AddSkullCavernElevatorModInjections(); + AddSVEModInjections(); + AddBoardingHouseInjections(); + PatchSVEShops(); + } + catch (Exception ex) + { + _logger.LogError($"Failed at Initializing mod content. Message: {ex.Message}"); + } } public void CleanEvents() diff --git a/StardewArchipelago/ModEntry.cs b/StardewArchipelago/ModEntry.cs index ee638cd89..517c820dc 100644 --- a/StardewArchipelago/ModEntry.cs +++ b/StardewArchipelago/ModEntry.cs @@ -17,6 +17,7 @@ using StardewArchipelago.GameModifications.EntranceRandomizer; using StardewArchipelago.GameModifications.Modded; using StardewArchipelago.GameModifications.Seasons; +using StardewArchipelago.GameModifications.Testing; using StardewArchipelago.Goals; using StardewArchipelago.Integrations.GenericModConfigMenu; using StardewArchipelago.Items; @@ -57,6 +58,7 @@ public class ModEntry : Mod private LogHandler _logger; private IModHelper _helper; private Harmony _harmony; + private TesterFeatures _testerFeatures; private StardewArchipelagoClient _archipelago; private AdvancedOptionsManager _advancedOptionsManager; private Mailman _mail; @@ -108,8 +110,9 @@ public override void Entry(IModHelper helper) _logger = new LogHandler(Monitor); _helper = helper; _harmony = new Harmony(ModManifest.UniqueID); + _testerFeatures = new TesterFeatures(_logger, _helper); - _archipelago = new StardewArchipelagoClient(_logger, _helper, ModManifest, _harmony, OnItemReceived, new SmapiJsonLoader(_helper)); + _archipelago = new StardewArchipelagoClient(_logger, _helper, ModManifest, _harmony, OnItemReceived, new SmapiJsonLoader(_helper), _testerFeatures); _helper.Events.GameLoop.GameLaunched += OnGameLaunched; _helper.Events.GameLoop.SaveCreating += OnSaveCreating; @@ -224,7 +227,7 @@ private void ResetArchipelago() _bundlesManager = null; SeasonsRandomizer.ResetMailKeys(); _multiSleep = new MultiSleep(_logger, _helper, _harmony); - _advancedOptionsManager = new AdvancedOptionsManager(this, _logger, _helper, _harmony, _archipelago); + _advancedOptionsManager = new AdvancedOptionsManager(this, _logger, _helper, _harmony, _archipelago, _testerFeatures); _advancedOptionsManager.InjectArchipelagoAdvancedOptions(); _giftHandler = new CrossGiftHandler(); _villagerEvents = new ModifiedVillagerEventChecker();