feat(app): wire IGameState+IEvents into Program and SmokePlugin

Pass WorldGameState and WorldEvents into GameWindow so OnLoad fires
FireEntitySpawned and Add for each hydrated entity. SmokePlugin now
subscribes to EntitySpawned in Enable(), unsubscribes in Disable(),
and logs the replay count at subscribe time and total seen at disable.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Erik 2026-04-10 20:31:50 +02:00
parent 0c0c042dca
commit 08097b6c7e
3 changed files with 40 additions and 6 deletions

View file

@ -50,7 +50,7 @@ try
catch (Exception ex) { Log.Error(ex, "plugin enable failed: {Id}", plugin.Manifest.Id); }
}
using var window = new GameWindow(datDir);
using var window = new GameWindow(datDir, worldGameState, worldEvents);
window.Run();
}
finally

View file

@ -1,3 +1,4 @@
using AcDream.Core.Plugins;
using DatReaderWriter;
using DatReaderWriter.Options;
using Silk.NET.Input;
@ -10,6 +11,8 @@ namespace AcDream.App.Rendering;
public sealed class GameWindow : IDisposable
{
private readonly string _datDir;
private readonly WorldGameState _worldGameState;
private readonly WorldEvents _worldEvents;
private IWindow? _window;
private GL? _gl;
private IInputContext? _input;
@ -25,7 +28,12 @@ public sealed class GameWindow : IDisposable
private TextureCache? _textureCache;
private IReadOnlyList<AcDream.Core.World.WorldEntity> _entities = Array.Empty<AcDream.Core.World.WorldEntity>();
public GameWindow(string datDir) => _datDir = datDir;
public GameWindow(string datDir, WorldGameState worldGameState, WorldEvents worldEvents)
{
_datDir = datDir;
_worldGameState = worldGameState;
_worldEvents = worldEvents;
}
public void Run()
{
@ -209,14 +217,23 @@ public sealed class GameWindow : IDisposable
(lbY - centerY) * 192f,
0f);
hydratedEntities.Add(new AcDream.Core.World.WorldEntity
var hydrated = new AcDream.Core.World.WorldEntity
{
Id = e.Id,
SourceGfxObjOrSetupId = e.SourceGfxObjOrSetupId,
Position = e.Position + worldOffset,
Rotation = e.Rotation,
MeshRefs = meshRefs,
});
};
hydratedEntities.Add(hydrated);
var snapshot = new AcDream.Plugin.Abstractions.WorldEntitySnapshot(
Id: hydrated.Id,
SourceId: hydrated.SourceGfxObjOrSetupId,
Position: hydrated.Position,
Rotation: hydrated.Rotation);
_worldGameState.Add(snapshot);
_worldEvents.FireEntitySpawned(snapshot);
}
}

View file

@ -5,6 +5,7 @@ namespace AcDream.Plugins.Smoke;
public sealed class SmokePlugin : IAcDreamPlugin
{
private IPluginHost? _host;
private int _entitiesSeen;
public void Initialize(IPluginHost host)
{
@ -12,6 +13,22 @@ public sealed class SmokePlugin : IAcDreamPlugin
_host.Log.Info("smoke plugin initialized");
}
public void Enable() => _host?.Log.Info("smoke plugin enabled");
public void Disable() => _host?.Log.Info("smoke plugin disabled");
public void Enable()
{
_host?.Log.Info("smoke plugin enabled");
if (_host is not null)
{
_host.Events.EntitySpawned += OnEntitySpawned;
_host.Log.Info($"smoke plugin sees {_entitiesSeen} entities (replay count at subscribe)");
}
}
public void Disable()
{
if (_host is not null)
_host.Events.EntitySpawned -= OnEntitySpawned;
_host?.Log.Info($"smoke plugin disabled (saw {_entitiesSeen} entities total)");
}
private void OnEntitySpawned(WorldEntitySnapshot snapshot) => _entitiesSeen++;
}