feat(mosstank): add VTank-style automation PoC

This commit is contained in:
Erik 2026-08-27 18:57:21 +02:00
parent f6fe0f2a4f
commit 4e6e9bc9d9
212 changed files with 49462 additions and 416 deletions

View file

@ -715,6 +715,7 @@ public sealed class GameWindow :
// reset across generations. Re-binding per session would be re-binding
// the same two references.
_automation?.Bind(_runtime, _runtime.CharacterOwner, _runtime.ActionOwner.SpellCast);
_automation?.BindProjectileCollision(_physicsEngine);
_localPlayerIdentity = new AcDream.App.Input.LocalPlayerIdentityState(
_runtime.PlayerIdentity);
_updateFrameClock = new AcDream.App.Update.UpdateFrameClock(
@ -960,6 +961,10 @@ public sealed class GameWindow :
// zero skills with no error to explain it.
if (_automation is null)
return;
_automation.BindSpeciesNameResolver(
AcDream.App.UI.Layout.CreatureDisplayNameResolver.Load(value).Resolve);
_automation.BindPaletteColorResolver(
new AcDream.Content.CharGen.ChargenAppearanceCatalog(value));
if (!value.TryGet<DatReaderWriter.DBObjs.SkillTable>(0x0E000004u, out var skillTable)
|| skillTable is null)
{
@ -983,8 +988,11 @@ public sealed class GameWindow :
"prepared asset source");
void IGameWindowContentEffectsAudioPublication.PublishMagicCatalog(
MagicCatalog value) =>
MagicCatalog value)
{
PublishCompositionOwner(ref _magicCatalog, value, "magic catalog");
_automation?.BindMagicCatalog(value);
}
void IGameWindowContentEffectsAudioPublication.PublishAnimationLoader(
AcDream.Core.Physics.IAnimationLoader value) =>
@ -1144,6 +1152,25 @@ public sealed class GameWindow :
_combatAttackController = result.CombatAttack;
_externalContainerLifecycle = result.ExternalContainerLifecycle;
_itemInteractionController = result.ItemInteraction;
_automation?.BindEquipment(
(itemId, requestedLocation) =>
result.ItemInteraction.TryWieldItem(
itemId,
(AcDream.Core.Items.EquipMask)requestedLocation),
() => result.ItemInteraction.IsAutoWieldBusy);
_automation?.BindItems(
result.ItemInteraction.TryUseItemForAutomation,
result.ItemInteraction.TryApplyItem,
result.ItemInteraction.TryMoveItemForAutomation,
result.ItemInteraction.TryMergeItemsForAutomation,
result.ItemInteraction.TryDropItemForAutomation,
result.ItemInteraction.TryGiveItemForAutomation,
result.ItemInteraction.PlaceWorldItemInBackpack,
result.ItemInteraction.TryAppraiseForAutomation,
result.ItemInteraction.TrySalvageItemsForAutomation,
(vendorId, itemId, amount) => result.ItemInteraction.TrySell(
vendorId,
[(amount, itemId)]));
_interactionUiLateBindings = result.LateBindings;
_magicRuntime = result.Magic;
if (result.RetainedUi is { } retained)
@ -1219,6 +1246,17 @@ public sealed class GameWindow :
_retailSelectionScene = result.SelectionScene;
_worldSelectionQuery = result.SelectionQuery;
_selectionInteractions = result.SelectionInteractions;
_automation?.BindSelectionActions(action =>
result.SelectionInteractions.HandleInputAction(action switch
{
AcDream.Plugin.Abstractions.PluginSelectionAction.PreviousSelection =>
InputAction.SelectionPreviousSelection,
AcDream.Plugin.Abstractions.PluginSelectionAction.PreviousPlayer =>
InputAction.SelectionPreviousPlayer,
AcDream.Plugin.Abstractions.PluginSelectionAction.NextPlayer =>
InputAction.SelectionNextPlayer,
_ => InputAction.None,
}));
_retainedUiGameplayBinding = result.RetainedGameplay;
_paperdollViewportRenderer = result.PaperdollRenderer;
_paperdollFramePresenter = result.PaperdollPresenter;
@ -1272,6 +1310,7 @@ public sealed class GameWindow :
_worldReveal = result.WorldReveal;
_spawnClaimHydration = result.SpawnClaimHydration;
_liveEntityHydration = result.Hydration;
_automation?.BindGhostDeletion(result.Deletion.DeleteClientGhost);
_liveEntityNetworkUpdates = result.NetworkUpdates;
_liveEntityLiveness = result.Liveness;
_liveEntitySessionEvents = result.SessionEvents;
@ -1282,6 +1321,7 @@ public sealed class GameWindow :
_playerModeAutoEntry = result.PlayerModeAutoEntry;
_localPlayerTeleport = result.LocalTeleport;
_liveSessionHost = result.SessionHost;
_automation?.BindSessionCommands(result.GameRuntime);
_gameplayInputActions = result.GameplayActions;
_sessionPlayerBindings = result.RuntimeBindings;
}
@ -1529,7 +1569,8 @@ public sealed class GameWindow :
() => WorldTime.CurrentCalendar,
settingsDevTools.RenderPacks,
_renderPackDiagnostics.CaptureDiagnostics,
_applicationPaths.ScreenshotsDirectory),
_applicationPaths.ScreenshotsDirectory,
_automation),
_retailUiLease,
this).Compose(
platformResult,
@ -1653,6 +1694,9 @@ public sealed class GameWindow :
_combatFeedback,
_portalTunnelFallback,
Console.WriteLine,
_automation is null
? null
: _automation.TryHandlePluginCommand,
_statusWriter),
this).Compose(
hostInputCamera,