Compare commits
3
Commits
75cc3c1279
...
b8fb306a57
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b8fb306a57 | ||
|
|
04c334c36a | ||
|
|
07d7d10fc5 |
No files matched your search
+37
-37
@@ -1,37 +1,37 @@
|
|||||||
# Godot 4.x
|
# Godot 4.x
|
||||||
.godot/
|
.godot/
|
||||||
.idea/
|
.idea/
|
||||||
sdk/
|
sdk/
|
||||||
bin/
|
bin/
|
||||||
obj/
|
obj/
|
||||||
|
|
||||||
#ai
|
#ai
|
||||||
.omo/
|
.omo/
|
||||||
.opencode/
|
.opencode/
|
||||||
|
|
||||||
gen/
|
gen/
|
||||||
obj/
|
obj/
|
||||||
bin/
|
bin/
|
||||||
|
|
||||||
*.tres~
|
*.tres~
|
||||||
*.tscn~
|
*.tscn~
|
||||||
|
|
||||||
# GDScript LSP
|
# GDScript LSP
|
||||||
.godot/
|
.godot/
|
||||||
|
|
||||||
# Export
|
# Export
|
||||||
*.exe
|
*.exe
|
||||||
*.dmg
|
*.dmg
|
||||||
*.apk
|
*.apk
|
||||||
*.aab
|
*.aab
|
||||||
*.pck
|
*.pck
|
||||||
*.zip
|
*.zip
|
||||||
*.log
|
*.log
|
||||||
|
|
||||||
# OS
|
# OS
|
||||||
.DS_Store
|
.DS_Store
|
||||||
Thumbs.db
|
Thumbs.db
|
||||||
|
|
||||||
# Editor
|
# Editor
|
||||||
*.import
|
*.import
|
||||||
*.godot.uid
|
*.godot.uid
|
||||||
+169
-169
@@ -1,169 +1,169 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using Cthangover.Core.Scenes;
|
using Cthangover.Core.Scenes;
|
||||||
using Cthangover.Core.Settings;
|
using Cthangover.Core.Settings;
|
||||||
using Cthangover.Core.UI.Menu;
|
using Cthangover.Core.UI.Menu;
|
||||||
using Cthangover.Core.UI.Theming;
|
using Cthangover.Core.UI.Theming;
|
||||||
using Cthangover.Core.UI.Tool;
|
using Cthangover.Core.UI.Tool;
|
||||||
using Cthangover.Core.Utils;
|
using Cthangover.Core.Utils;
|
||||||
using Godot;
|
using Godot;
|
||||||
|
|
||||||
using Cthangover.Mods.Interface.Menu;
|
using Cthangover.Mods.Interface.Menu;
|
||||||
namespace Cthangover.BaseMenu
|
namespace Cthangover.BaseMenu
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Title screen main menu, fully driven by <see cref="MenuRegistry"/>. The scene
|
/// Title screen main menu, fully driven by <see cref="MenuRegistry"/>. The scene
|
||||||
/// only defines named section containers (game, mods, exit, tools); every button —
|
/// only defines named section containers (game, mods, exit, tools); every button —
|
||||||
/// built-in or mod-provided — is created from registry entries, so mods can add,
|
/// built-in or mod-provided — is created from registry entries, so mods can add,
|
||||||
/// replace or re-order entries without touching this scene. Below the sections,
|
/// replace or re-order entries without touching this scene. Below the sections,
|
||||||
/// every registered tool appends its own launcher button via
|
/// every registered tool appends its own launcher button via
|
||||||
/// <see cref="IToolProvider.AddMenuButton"/>, so no tool list is hardcoded here.
|
/// <see cref="IToolProvider.AddMenuButton"/>, so no tool list is hardcoded here.
|
||||||
/// If GameLogger reports mod compilation errors, a popup lists them. The
|
/// If GameLogger reports mod compilation errors, a popup lists them. The
|
||||||
/// SettingsMenu and SaveLoadMenu panels are instantiated at ready time but stay
|
/// SettingsMenu and SaveLoadMenu panels are instantiated at ready time but stay
|
||||||
/// hidden; they are registered in <see cref="MenuRegistry"/> as panels "settings"
|
/// hidden; they are registered in <see cref="MenuRegistry"/> as panels "settings"
|
||||||
/// and "save_load", so other mods can open them by id.
|
/// and "save_load", so other mods can open them by id.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public partial class MainMenu : Control
|
public partial class MainMenu : Control
|
||||||
{
|
{
|
||||||
private SettingsMenu _settingsMenu;
|
private SettingsMenu _settingsMenu;
|
||||||
private SaveLoadMenu _saveLoadMenu;
|
private SaveLoadMenu _saveLoadMenu;
|
||||||
private GamePickerPanel _gamePicker;
|
private GamePickerPanel _gamePicker;
|
||||||
private readonly Dictionary<Button, string> _btnKeys = new();
|
private readonly Dictionary<Button, string> _btnKeys = new();
|
||||||
|
|
||||||
public override void _Ready()
|
public override void _Ready()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
BuildUi();
|
BuildUi();
|
||||||
}
|
}
|
||||||
catch (System.Exception ex)
|
catch (System.Exception ex)
|
||||||
{
|
{
|
||||||
GameLogger.Log("MAIN_MENU",
|
GameLogger.Log("MAIN_MENU",
|
||||||
$"_Ready failed: {ex.GetType().Name}: {ex.Message}{System.Environment.NewLine}{ex.StackTrace}",
|
$"_Ready failed: {ex.GetType().Name}: {ex.Message}{System.Environment.NewLine}{ex.StackTrace}",
|
||||||
LogLevel.Error);
|
LogLevel.Error);
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Assembles the runtime UI: theme, hidden settings and save/load panels,
|
/// Assembles the runtime UI: theme, hidden settings and save/load panels,
|
||||||
/// telegram link wiring, scene manager initialization and registry/tool
|
/// telegram link wiring, scene manager initialization and registry/tool
|
||||||
/// driven buttons.
|
/// driven buttons.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private void BuildUi()
|
private void BuildUi()
|
||||||
{
|
{
|
||||||
CthangoverTheme.Apply(this);
|
CthangoverTheme.Apply(this);
|
||||||
|
|
||||||
_settingsMenu = new ModScenePrefab("scenes/menu/settings_menu.tscn").Instantiate<SettingsMenu>();
|
_settingsMenu = new ModScenePrefab("scenes/menu/settings_menu.tscn").Instantiate<SettingsMenu>();
|
||||||
_settingsMenu.Name = "SettingsPanel";
|
_settingsMenu.Name = "SettingsPanel";
|
||||||
_settingsMenu.Visible = false;
|
_settingsMenu.Visible = false;
|
||||||
_settingsMenu.LanguageChanged += RefreshButtons;
|
_settingsMenu.LanguageChanged += RefreshButtons;
|
||||||
AddChild(_settingsMenu);
|
AddChild(_settingsMenu);
|
||||||
|
|
||||||
_saveLoadMenu = new ModScenePrefab("scenes/menu/save_load_menu.tscn").Instantiate<SaveLoadMenu>();
|
_saveLoadMenu = new ModScenePrefab("scenes/menu/save_load_menu.tscn").Instantiate<SaveLoadMenu>();
|
||||||
_saveLoadMenu.Name = "SaveLoadPanel";
|
_saveLoadMenu.Name = "SaveLoadPanel";
|
||||||
_saveLoadMenu.Visible = false;
|
_saveLoadMenu.Visible = false;
|
||||||
AddChild(_saveLoadMenu);
|
AddChild(_saveLoadMenu);
|
||||||
|
|
||||||
_gamePicker = new GamePickerPanel { Name = "GamePickerPanel" };
|
_gamePicker = new GamePickerPanel { Name = "GamePickerPanel" };
|
||||||
AddChild(_gamePicker);
|
AddChild(_gamePicker);
|
||||||
_gamePicker.SavesRequested += gameId =>
|
_gamePicker.SavesRequested += gameId =>
|
||||||
{
|
{
|
||||||
_gamePicker.Visible = false;
|
_gamePicker.Visible = false;
|
||||||
_saveLoadMenu.OpenForGame(gameId);
|
_saveLoadMenu.OpenForGame(gameId);
|
||||||
};
|
};
|
||||||
|
|
||||||
var telegramLink = GetNode<RichTextLabel>("TelegramLink");
|
var telegramLink = GetNode<RichTextLabel>("TelegramLink");
|
||||||
telegramLink.MetaClicked += OnTelegramLinkClicked;
|
telegramLink.MetaClicked += OnTelegramLinkClicked;
|
||||||
|
|
||||||
var sceneManager = GetNode<SceneManager>("/root/SceneManager");
|
var sceneManager = GetNode<SceneManager>("/root/SceneManager");
|
||||||
sceneManager.Initialize();
|
sceneManager.Initialize();
|
||||||
|
|
||||||
BuildRegistryButtons();
|
BuildRegistryButtons();
|
||||||
BuildToolButtons();
|
BuildToolButtons();
|
||||||
CheckModCompilationErrors();
|
CheckModCompilationErrors();
|
||||||
|
|
||||||
RefreshButtons();
|
RefreshButtons();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates one button per <see cref="MenuRegistry"/> entry, routed to the
|
/// Creates one button per <see cref="MenuRegistry"/> entry, routed to the
|
||||||
/// section container matching its <c>Section</c> ("game", "mods", "exit",
|
/// section container matching its <c>Section</c> ("game", "mods", "exit",
|
||||||
/// "tools"). Runs after <see cref="SceneManager.Initialize"/> because the
|
/// "tools"). Runs after <see cref="SceneManager.Initialize"/> because the
|
||||||
/// registry is built during boot and filled by mod initializers; the
|
/// registry is built during boot and filled by mod initializers; the
|
||||||
/// defensive Initialize call keeps direct scene launches working. Each
|
/// defensive Initialize call keeps direct scene launches working. Each
|
||||||
/// button's translation key is registered so <see cref="RefreshButtons"/>
|
/// button's translation key is registered so <see cref="RefreshButtons"/>
|
||||||
/// keeps it localized.
|
/// keeps it localized.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private void BuildRegistryButtons()
|
private void BuildRegistryButtons()
|
||||||
{
|
{
|
||||||
var sections = new Dictionary<string, Container>
|
var sections = new Dictionary<string, Container>
|
||||||
{
|
{
|
||||||
{ "game", GetNode<Container>("MenuContainer/GameButtons") },
|
{ "game", GetNode<Container>("MenuContainer/GameButtons") },
|
||||||
{ MenuButtonEntry.SectionMods, GetNode<Container>("MenuContainer/ModMenuButtons") },
|
{ MenuButtonEntry.SectionMods, GetNode<Container>("MenuContainer/ModMenuButtons") },
|
||||||
{ "exit", GetNode<Container>("MenuContainer/ExitButtons") },
|
{ "exit", GetNode<Container>("MenuContainer/ExitButtons") },
|
||||||
{ "tools", GetNode<Container>("MenuContainer/ToolMenuButtons") },
|
{ "tools", GetNode<Container>("MenuContainer/ToolMenuButtons") },
|
||||||
};
|
};
|
||||||
MenuBuilder.Build(this, sections);
|
MenuBuilder.Build(this, sections);
|
||||||
|
|
||||||
foreach (var container in sections.Values)
|
foreach (var container in sections.Values)
|
||||||
MenuBuilder.CollectLocaleKeys(container, _btnKeys);
|
MenuBuilder.CollectLocaleKeys(container, _btnKeys);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Lets every registered tool append its launcher button to the tool block
|
/// Lets every registered tool append its launcher button to the tool block
|
||||||
/// below Exit (<c>MenuContainer/ToolMenuButtons</c>). Tools register
|
/// below Exit (<c>MenuContainer/ToolMenuButtons</c>). Tools register
|
||||||
/// themselves in <see cref="ToolFactory"/>, so the block stays empty when no
|
/// themselves in <see cref="ToolFactory"/>, so the block stays empty when no
|
||||||
/// tools are installed and needs no changes when a mod introduces a new tool.
|
/// tools are installed and needs no changes when a mod introduces a new tool.
|
||||||
/// Each button carries its translation key in metadata, keeping
|
/// Each button carries its translation key in metadata, keeping
|
||||||
/// <see cref="RefreshButtons"/> aware of it.
|
/// <see cref="RefreshButtons"/> aware of it.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private void BuildToolButtons()
|
private void BuildToolButtons()
|
||||||
{
|
{
|
||||||
var container = GetNodeOrNull<VBoxContainer>("MenuContainer/ToolMenuButtons");
|
var container = GetNodeOrNull<VBoxContainer>("MenuContainer/ToolMenuButtons");
|
||||||
if (container == null)
|
if (container == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
foreach (var tool in ToolFactory.Instance.GetAll())
|
foreach (var tool in ToolFactory.Instance.GetAll())
|
||||||
tool.AddMenuButton(container);
|
tool.AddMenuButton(container);
|
||||||
|
|
||||||
MenuBuilder.CollectLocaleKeys(container, _btnKeys);
|
MenuBuilder.CollectLocaleKeys(container, _btnKeys);
|
||||||
|
|
||||||
GameLogger.Log("MAIN_MENU", $"Built {container.GetChildCount()} tool button(s)");
|
GameLogger.Log("MAIN_MENU", $"Built {container.GetChildCount()} tool button(s)");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void CheckModCompilationErrors()
|
private void CheckModCompilationErrors()
|
||||||
{
|
{
|
||||||
if (GameLogger.CompilationErrors.Count == 0)
|
if (GameLogger.CompilationErrors.Count == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var errorText = string.Join("\r\n", GameLogger.CompilationErrors);
|
var errorText = string.Join("\r\n", GameLogger.CompilationErrors);
|
||||||
ShowModErrorPopup(errorText);
|
ShowModErrorPopup(errorText);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void RefreshButtons()
|
private void RefreshButtons()
|
||||||
{
|
{
|
||||||
foreach (var kv in _btnKeys)
|
foreach (var kv in _btnKeys)
|
||||||
kv.Key.Text = TranslationServer.Translate(kv.Value);
|
kv.Key.Text = TranslationServer.Translate(kv.Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ShowModErrorPopup(string errorText)
|
private void ShowModErrorPopup(string errorText)
|
||||||
{
|
{
|
||||||
var dialog = new AcceptDialog();
|
var dialog = new AcceptDialog();
|
||||||
dialog.Title = "Mod Compilation Error";
|
dialog.Title = "Mod Compilation Error";
|
||||||
dialog.DialogText = errorText;
|
dialog.DialogText = errorText;
|
||||||
dialog.OkButtonText = "OK";
|
dialog.OkButtonText = "OK";
|
||||||
dialog.Exclusive = true;
|
dialog.Exclusive = true;
|
||||||
AddChild(dialog);
|
AddChild(dialog);
|
||||||
dialog.PopupCentered();
|
dialog.PopupCentered();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnTelegramLinkClicked(Variant meta)
|
private void OnTelegramLinkClicked(Variant meta)
|
||||||
{
|
{
|
||||||
OS.ShellOpen($"https://{meta.AsString()}");
|
OS.ShellOpen($"https://{meta.AsString()}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -9,6 +9,7 @@ using Cthangover.Core.Games;
|
|||||||
using Cthangover.Core.Mods;
|
using Cthangover.Core.Mods;
|
||||||
using Cthangover.Core.Mods.HotReload;
|
using Cthangover.Core.Mods.HotReload;
|
||||||
using Cthangover.Core.Scenes;
|
using Cthangover.Core.Scenes;
|
||||||
|
using Cthangover.Core.UI;
|
||||||
using Cthangover.Core.Utils;
|
using Cthangover.Core.Utils;
|
||||||
using Godot;
|
using Godot;
|
||||||
|
|
||||||
@@ -136,7 +137,7 @@ namespace Mods.CollectionEditTest
|
|||||||
Check("New game after the edit switched the mod set", reload?.Applied == true && reload.Plan?.Load.Contains(AddedMod) == true);
|
Check("New game after the edit switched the mod set", reload?.Applied == true && reload.Plan?.Load.Contains(AddedMod) == true);
|
||||||
Check($"'{AddedMod}' is loaded after the edit", EditorsLoaded);
|
Check($"'{AddedMod}' is loaded after the edit", EditorsLoaded);
|
||||||
Check($"'{StudioMod}' is loaded after the edit", ModRegistry.Instance.Mods.ContainsKey(StudioMod));
|
Check($"'{StudioMod}' is loaded after the edit", ModRegistry.Instance.Mods.ContainsKey(StudioMod));
|
||||||
Check("the studio's button is on the game's toolbar", HasToolbarButton(TranslationServer.Translate("studio/title").ToString()));
|
Check("the studio's button is on the game's toolbar", HasToolbarButton(StudioButtonTooltip()));
|
||||||
Check("the game matches its edited collection", !GameCatalog.IsActiveOutdated());
|
Check("the game matches its edited collection", !GameCatalog.IsActiveOutdated());
|
||||||
Check($"entered a scene of '{GameId}' ('{enteredScenes[0]}')", true);
|
Check($"entered a scene of '{GameId}' ('{enteredScenes[0]}')", true);
|
||||||
Finish();
|
Finish();
|
||||||
@@ -193,6 +194,17 @@ namespace Mods.CollectionEditTest
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Tooltip of the studio's toolbar button, read from the panel entry the studio
|
||||||
|
/// registered: the suite does not depend on the studio (it is added by the edit),
|
||||||
|
/// so its locale key must not be hard-coded here.
|
||||||
|
/// </summary>
|
||||||
|
private static string StudioButtonTooltip()
|
||||||
|
{
|
||||||
|
var locale = UiRegistry.PanelEntries.FirstOrDefault(e => e.ModId == StudioMod && e.Button != null)?.Button.Locale;
|
||||||
|
return locale == null ? null : TranslationServer.Translate(locale).ToString();
|
||||||
|
}
|
||||||
|
|
||||||
private bool HasToolbarButton(string tooltip)
|
private bool HasToolbarButton(string tooltip)
|
||||||
=> GetTree().Root.FindChildren("*", "Button", true, false).OfType<Button>().Any(b => b.TooltipText == tooltip && b.IsVisibleInTree());
|
=> GetTree().Root.FindChildren("*", "Button", true, false).OfType<Button>().Any(b => b.TooltipText == tooltip && b.IsVisibleInTree());
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ using Cthangover.Core.Bootstrap;
|
|||||||
using Cthangover.Core.Events;
|
using Cthangover.Core.Events;
|
||||||
using Cthangover.Core.Games;
|
using Cthangover.Core.Games;
|
||||||
using Cthangover.Core.Mods;
|
using Cthangover.Core.Mods;
|
||||||
|
using Cthangover.Core.Characters;
|
||||||
using Cthangover.Core.Mods.HotReload;
|
using Cthangover.Core.Mods.HotReload;
|
||||||
using Cthangover.Core.Utils;
|
using Cthangover.Core.Utils;
|
||||||
using Godot;
|
using Godot;
|
||||||
@@ -23,6 +24,8 @@ namespace Mods.HotReloadTest
|
|||||||
/// cascades), the old contexts are collected, the front-end stays.</item>
|
/// cascades), the old contexts are collected, the front-end stays.</item>
|
||||||
/// <item>A compile error in the library is rejected: v2 keeps running.</item>
|
/// <item>A compile error in the library is rejected: v2 keeps running.</item>
|
||||||
/// <item>Fixing it (v3) reloads again.</item>
|
/// <item>Fixing it (v3) reloads again.</item>
|
||||||
|
/// <item>Editing a character of a data-only probe (no code) is picked up by
|
||||||
|
/// the kept characters engine mod: its factory serves the new template.</item>
|
||||||
/// <item>Dropping the probes from the selection unloads them and their node.</item>
|
/// <item>Dropping the probes from the selection unloads them and their node.</item>
|
||||||
/// </list>
|
/// </list>
|
||||||
/// Reload outcomes are read from <see cref="ModSetReloadedEvent"/>s, since
|
/// Reload outcomes are read from <see cref="ModSetReloadedEvent"/>s, since
|
||||||
@@ -35,6 +38,8 @@ namespace Mods.HotReloadTest
|
|||||||
|
|
||||||
private const string LibId = "hot_reload_probe_lib";
|
private const string LibId = "hot_reload_probe_lib";
|
||||||
private const string AppId = "hot_reload_probe_app";
|
private const string AppId = "hot_reload_probe_app";
|
||||||
|
private const string DataId = "hot_reload_probe_data";
|
||||||
|
private const string ProbeCharacterId = "hot_reload_probe_character";
|
||||||
private const string ProbeNodeName = "HotReloadProbeNode";
|
private const string ProbeNodeName = "HotReloadProbeNode";
|
||||||
private const float TimeoutSeconds = 300f;
|
private const float TimeoutSeconds = 300f;
|
||||||
|
|
||||||
@@ -109,8 +114,9 @@ namespace Mods.HotReloadTest
|
|||||||
return;
|
return;
|
||||||
Check("hot reload watcher is installed", ModHotReloadService.Instance != null);
|
Check("hot reload watcher is installed", ModHotReloadService.Instance != null);
|
||||||
startSelection = GameLaunchArgs.Current;
|
startSelection = GameLaunchArgs.Current;
|
||||||
GameLaunchArgs.SetCurrent(GameLaunchArgs.Parse(startSelection.UserArgs.Concat(new[] { GameLaunchArgs.WithModsPrefix + AppId })));
|
GameLaunchArgs.SetCurrent(GameLaunchArgs.Parse(startSelection.UserArgs.Concat(new[] { GameLaunchArgs.WithModsPrefix + AppId + "," + DataId })));
|
||||||
reloads.Clear();
|
reloads.Clear();
|
||||||
|
WriteData("probe_v1");
|
||||||
WriteProbes("v1");
|
WriteProbes("v1");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -118,6 +124,7 @@ namespace Mods.HotReloadTest
|
|||||||
if (Busy || ProbeValue() != "v1")
|
if (Busy || ProbeValue() != "v1")
|
||||||
return;
|
return;
|
||||||
Check("probes loaded by the watcher", AnyApplied(LoadedBoth));
|
Check("probes loaded by the watcher", AnyApplied(LoadedBoth));
|
||||||
|
Check("data probe's character is served", ProbeCharacterName() == "probe_v1");
|
||||||
CheckNoLeaks("v1");
|
CheckNoLeaks("v1");
|
||||||
reloads.Clear();
|
reloads.Clear();
|
||||||
WriteLib("v2", compiles: true);
|
WriteLib("v2", compiles: true);
|
||||||
@@ -148,11 +155,19 @@ namespace Mods.HotReloadTest
|
|||||||
Check("fixing the error reloads again", AnyApplied(LoadedBoth));
|
Check("fixing the error reloads again", AnyApplied(LoadedBoth));
|
||||||
CheckNoLeaks("v3");
|
CheckNoLeaks("v3");
|
||||||
reloads.Clear();
|
reloads.Clear();
|
||||||
|
WriteData("probe_v2");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 5:
|
||||||
|
if (Busy || !reloads.Any(r => r.Applied))
|
||||||
|
return;
|
||||||
|
Check("editing a data-only mod reaches the kept character factory", ProbeCharacterName() == "probe_v2");
|
||||||
|
reloads.Clear();
|
||||||
GameLaunchArgs.SetCurrent(startSelection);
|
GameLaunchArgs.SetCurrent(startSelection);
|
||||||
StartManualReload();
|
StartManualReload();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 5:
|
case 6:
|
||||||
if (Busy || ProbeValue() != null || !AnyApplied(UnloadedBoth))
|
if (Busy || ProbeValue() != null || !AnyApplied(UnloadedBoth))
|
||||||
return;
|
return;
|
||||||
Check("dropping the probes unloads them and their node", true);
|
Check("dropping the probes unloads them and their node", true);
|
||||||
@@ -205,6 +220,19 @@ namespace Mods.HotReloadTest
|
|||||||
GameLogger.Log("TEST", $"HotReloadTest: leaked: {string.Join(", ", leaked)}", LogLevel.Error);
|
GameLogger.Log("TEST", $"HotReloadTest: leaked: {string.Join(", ", leaked)}", LogLevel.Error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static string ProbeCharacterName() => CharacterTemplateRegistry.Get(ProbeCharacterId)?.Name;
|
||||||
|
|
||||||
|
private void WriteData(string name)
|
||||||
|
{
|
||||||
|
var data = Path.Combine(modsRoot, DataId);
|
||||||
|
Directory.CreateDirectory(Path.Combine(data, "characters"));
|
||||||
|
File.WriteAllText(Path.Combine(data, "manifest.json"),
|
||||||
|
"{ \"id\": \"" + DataId + "\", \"name\": \"Hot reload probe data\", \"version\": \"1.0.0\", \"author\": \"test\", " +
|
||||||
|
"\"depends\": [\"characters_base>=1\"] }");
|
||||||
|
File.WriteAllText(Path.Combine(data, "characters", "probe.json"),
|
||||||
|
"{ \"Kind\": \"character\", \"Items\": [ { \"Id\": \"" + ProbeCharacterId + "\", \"Name\": \"" + name + "\", \"Health\": 1 } ] }");
|
||||||
|
}
|
||||||
|
|
||||||
private void WriteProbes(string version)
|
private void WriteProbes(string version)
|
||||||
{
|
{
|
||||||
var app = Path.Combine(modsRoot, AppId);
|
var app = Path.Combine(modsRoot, AppId);
|
||||||
@@ -229,7 +257,7 @@ namespace Mods.HotReloadTest
|
|||||||
|
|
||||||
private void DeleteProbes()
|
private void DeleteProbes()
|
||||||
{
|
{
|
||||||
foreach (var id in new[] { LibId, AppId })
|
foreach (var id in new[] { LibId, AppId, DataId })
|
||||||
{
|
{
|
||||||
var dir = Path.Combine(modsRoot, id);
|
var dir = Path.Combine(modsRoot, id);
|
||||||
if (Directory.Exists(dir))
|
if (Directory.Exists(dir))
|
||||||
|
|||||||
Reference in new issue
Block a user