achievements service - UQcsse3200/2026-studio-4 GitHub Wiki
AchievementService holds every achievement for the current run and passes game events to them. It is registered once in ServiceLocator, so any system can report an event without holding a reference to a manager, and nothing needs to re-subscribe when rooms change.
MainGameScreen builds it from configs/achievements.json and registers it:
ServiceLocator.registerAchievementService(createAchievementService());Fetch it anywhere with:
ServiceLocator.getAchievementService()It is created before RoomManager, because RoomManager's constructor subscribes to its events. Don't construct your own.
Fields you don't set stay null or false, and every achievement ignores fields it doesn't use. Report one kind of event per context.
For each achievement, the service calls achievement.update(ctx). That returns true only on the call that unlocks it. Achievements that are already unlocked return false without evaluating their condition, so an unlock is announced exactly once. The service then:
- Logs
Achievement unlocked: <name>. - Triggers
"achievementUnlocked"with the achievement's name as aString.
ServiceLocator.getAchievementService()
.getEvents()
.addListener("achievementUnlocked", this::onUnlocked);RoomManager is the existing listener. It passes the name to the current room's GameAreaDisplay.showAchievement(name), which queues the toast.
-
Achievement logic: test through
AchievementsFactory.build(config)andachievement.update(ctx)with no service involved (seeAchievementsFactoryTest). -
Code that reports events: the code calls
ServiceLocator.getAchievementService(), so tests that build players, enemies or inventories need a service available. Register one insetUp(), or makeServiceLocatordefault to an empty service.