Service Architecture (Drop Service)
🎯 Goal
Item Drops follows the same core services + engine adapters approach used across the rest of the game. The core exposes a Drop Service abstraction, while Godot/Unity provide adapter layers for scene integration.
1. Core Service: IDropService
Namespace: ItemDrops.Core.Services
public interface IDropService
{
IReadOnlyList<DropResult> GenerateDrops(string tableId, LootContext context);
DropStatistics GetStatistics(string tableId, LootContext? context = null, int simulations = 1000);
void RegisterDropTable(string id, IDropTable dropTable);
}
Key points:
- Operates on core types only (
DropResult,LootContext,IDropTable). - Knows nothing about Godot or Unity.
- Encapsulates use of
DropTableRegistryandDropCalculator.
2. Default Implementation: DropService
Namespace: ItemDrops.Core.Services
var registry = new DropTableRegistry();
var service = new DropService(registry);
service.RegisterDropTable("default_enemy", enemyTable);
var drops = service.GenerateDrops("default_enemy", new LootContext { LuckModifier = 1.0f });
- Uses
DropTableRegistryto resolve tables by ID. - Uses
DropCalculatorinternally to produceDropResultcollections. - Reuses
DropTableRegistry.GetStatisticsfor analysis.- Hosts are responsible for computing a luck scalar from game state and passing it via
LootContext.LuckModifier;DropCalculatormultiplies the table’sDropChanceby this value (clamped to[0,1]) and does not apply anyGlobalConditionsorGlobalModifiersat runtime.
- Hosts are responsible for computing a luck scalar from game state and passing it via
3. Engine Adapters
Godot: ItemDropsBus and EnemyDrops
ItemDropsBus(ItemDrops.Godot.Resources) is the Godot adapter:- Owns
DropTableRegistry,LootGeneratorRegistry, and aDropCalculator. - Provides methods like
GenerateDropsandGenerateLootthat return GodotNodeinstances. - Spawns scenes using
GodotDropSpawner.
- Owns
EnemyDropsis a scene-level component:- Resolves defaults via
ItemDropsBus(currently through a legacy singleton, see below). - Builds
LootContextfrom enemy state and calls into drop tables.
- Resolves defaults via
Unity: ItemDropsManager
ItemDropsManager(ItemDrops.Unity.Managers) is the Unity adapter:- Manages Unity
DropTableAssetresources. - Uses
LootGeneratorandDropCalculatorto produceDropResultcollections. - Spawns
GameObjectinstances into the scene.
- Manages Unity
In both cases, the core drop logic remains in ItemDrops.Core (tables, generators, calculators). Engine layers deal only with scenes, nodes, and prefabs.
4. Legacy DI / Singleton Patterns
Some older access patterns remain for backward compatibility and are now explicitly marked as obsolete:
Godot: ItemDropsBus.Instance
[Tool]
public partial class ItemDropsBus : Resource
{
private static ItemDropsBus? _instance;
[System.Obsolete("Use scene- or resource-local ItemDropsBus instances wired via dependency injection instead of the global singleton. This property will be removed in a future version.")]
public static ItemDropsBus Instance { get; }
}
- Existing code like
ItemDropsBus.Instance.GetDropTable("default_enemy")will continue to work. - New code should instead:
- Expose an
ItemDropsBusresource via scene or DI container. - Inject it into systems that need drop management.
- Expose an
Unity: ItemDropsManager.Instance
public class ItemDropsManager : MonoBehaviour
{
private static ItemDropsManager instance;
[System.Obsolete("Use explicitly injected ItemDropsManager instances or services instead of the global singleton. This property will be removed in a future version.")]
public static ItemDropsManager Instance { get; }
}
- Existing uses of
ItemDropsManager.Instanceare still supported. - New code should obtain managers or services via explicit references (scene wiring, DI, or a shared service registry) instead of relying on global static state.
5. Recommended Usage Going Forward
-
Core / shared code
- Depend on
IDropServicerather than concrete registries. - Configure a
DropServiceinstance in your composition root and pass it to systems that need to generate or analyze drops.
- Depend on
-
Godot
- Treat
ItemDropsBusas the primary adapter for scene integration. - Prefer scene- or resource-local instances over the static
Instancewhen writing new code.
- Treat
-
Unity
- Treat
ItemDropsManageras an adapter for prefabs andGameObjectspawning. - Prefer explicit references in scenes/MonoBehaviours instead of the global singleton instance for new systems.
- Treat
This keeps Item Drops aligned with the broader service + adapter architecture used across the game while clearly marking legacy global DI patterns as obsolete.