Split GameServer into Core (engine) + Content (scripts), static reference #17
Labels
No labels
alpha:wave-0
alpha:wave-1
alpha:wave-2
alpha:wave-3
area:assets
area:combat
area:ecology
area:infra
area:render
area:scripting
area:ui
area:world
enhancement
epic
migration
post-alpha
roadmap
tech-debt
type:bug
type:chore
type:design
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
marco/IsoMmo#17
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Split
IsoMmo.GameServerinto an engine core and a content/scripts project, mirroring ModernUO's Server/UOContent separation organizationally (not its runtime script compiler).Decision (agreed 2026-07-17)
Contentis a normal .NET project that references the Core and registers content at compile time. Reloading content = restart the server. No ModernUO-style runtime Roslyn recompilation / hot-reload (a heavy subsystem, overkill for a small friends server).Scope
IsoMmo.GameServerkeeps: networking,World/tick, AoI, persistence, protocol handling, and the base types/hooks content extends.IsoMmo.GameServer.Contentholds: item kinds/definitions (today'sItemCatalog), mobile types, spawners, gameplay rules, GM commands.IContentModule/DI registration) so content registers itself without the core knowing concrete types.Definition of Done
Base DoD applies on top.
ModernUO study (informs the seam design)
Projects/splits intoServer(engine:Item,Mobile,Serial,World, networking, serialization infra) andUOContent(all gameplay content:BaseWeapon,BaseCreature, spells).UOContentdepends onServer; the engine knows no concrete content types.Content loading — key finding: NO runtime script compilation. RunUO compiled a
Scripts/folder at startup; ModernUO abandoned that. Content is plain C# AOT-compiled intoUOContent.dll; at runtime the server uses reflection + attributes ([Constructible],[SerializationGenerator]) to discover types. So the engine/content boundary is a compile-time assembly boundary — exactly the static split we chose. Good confirmation.Data model worth borrowing:
Serial— a strongly-typed unique id per networked entity.Itemwith a polymorphicParent(IEntity) — one reference models "in world / in a container / equipped" (Parent = Mobile, Item, or null). Their single best idea. Our current M5 model uses an explicitItemPlaceenum (Ground/Backpack/Equipped) — fine for now; we can evolve towardParentwhen containers land.Layerenum +FindItemOnLayer— equipment stored as a flatList<Item>filtered by aLayerfield, rather than a fixed slot struct. Simpler; scales fine.Mobile: raw vs effective stats (RawStr/Str…), derived pools (Hits/Stam/Mana),Skills. Good shape for M6/M8.Skip as overkill: runtime script compilation (they dropped it); their source-generated custom serialization + parallel/incremental saves + JSON migration snapshots (engineering for hundreds of players/years) — we already use EF Core + SQLite/Postgres, keep that.
Takeaway for #17 (M7 refactor): copy the engine/content assembly boundary and the data-model shapes (Serial / Item+Parent / Mobile / Layer); keep our EF-based persistence; register content via a simple DI/reflection seam, no runtime compiler.