Files
Antone Barbaud b02e532563 docs: organize diagrams to mirror code layout (util/ + features/)
Move flat docs/diagrams/*.puml into a hierarchy matching the source
package structure:

  docs/diagrams/
  ├── bootstrap-sequence.puml         (cross-cutting)
  ├── events-diagram.puml             (cross-feature)
  ├── util/
  │   ├── command-class-diagram.puml
  │   ├── database-diagram.puml
  │   ├── messages-class-diagram.puml
  │   ├── broadcasts-class-diagram.puml
  │   └── gui-class-diagram.puml
  └── features/
      ├── team/
      │   ├── team-class-diagram.puml
      │   ├── team-config-class-diagram.puml
      │   ├── builtin-commands-diagram.puml
      │   ├── team-create-sequence.puml
      │   ├── team-create-activity.puml
      │   └── team-join-sequence.puml
      ├── player/
      │   └── player-class-diagram.puml
      └── moderation/
          └── moderation-class-diagram.puml

README.md diagram index split into 4 sections (overview, util,
features/team, features/player, features/moderation) for readability;
all links updated. features.md auto-updated by sed for the new paths.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-10 13:58:48 +02:00

177 lines
5.3 KiB
Plaintext

@startuml moderation-class-diagram
title CR-Core — Moderation feature (class diagram, skeleton)
skinparam classAttributeIconSize 0
hide empty members
package "fr.luc.crcore.features.moderation" {
class ModerationState <<final>> {
- playerId: UUID
- enteredAt: Instant
- inventoryContents: ItemStack[]
- armorContents: ItemStack[]
- offhandItem: ItemStack
- xpLevel: int
- xpProgress: float
- health: double
- foodLevel: int
- saturation: float
- location: Location
- gameMode: GameMode
- allowFlight / flying / walkSpeed / flySpeed
--
+ ModerationState(player)
+ restoreTo(player): void
}
interface ModerationRepository {
+ findByPlayer(uuid): Optional<ModerationState>
+ exists(uuid): boolean
+ save(state): void
+ delete(uuid): boolean
+ findAll(): Collection<ModerationState>
}
interface ModeratorTool {
+ getKey(): String
+ getSlot(): int ' 0..8
+ buildIcon(): ItemStack
+ onLeftClick(player): void
+ onRightClick(player): void
+ onInteractEntity(player, target): void
}
class ModeratorToolRegistry {
- bySlot: Map<Integer, ModeratorTool>
- byKey: Map<String, ModeratorTool>
+ register(tool): void
+ unregister(key): boolean
+ get(key): Optional<ModeratorTool>
+ getBySlot(slot): Optional<ModeratorTool>
+ all(): Collection<ModeratorTool>
}
interface ModerationService {
+ enter(player): void
+ exit(player): void
+ isInModeration(uuid): boolean
+ getState(uuid): Optional<ModerationState>
+ getActiveModerators(): Set<UUID>
--
+ vanish(player) / unvanish / isVanished / getVanishedPlayers
+ freeze(uuid) / unfreeze / isFrozen / getFrozenPlayers
+ getToolRegistry(): ModeratorToolRegistry
}
package "fr.luc.crcore.features.moderation.impl" {
class InMemoryModerationRepository
InMemoryModerationRepository ..|> ModerationRepository
class ModerationServiceImpl {
# plugin: Plugin
# repository: ModerationRepository
# toolRegistry: ModeratorToolRegistry
# vanished: Set<UUID>
# frozen: Set<UUID>
--
# onAfterEnter(player) ' hook
# onAfterExit(player)
}
ModerationServiceImpl ..|> ModerationService
class BukkitEventFiringModerationServiceImpl
BukkitEventFiringModerationServiceImpl --|> ModerationServiceImpl
class ModerationListener {
+ registerOn(plugin): void
--
@ onInteract ' route → tool.onLeftClick / onRightClick
@ onInteractEntity ' route → tool.onInteractEntity
@ onDrop / onSwap ' lock hotbar
@ onInventoryClick ' cancel sur self-inv
@ onJoin ' re-hide vanished players
@ onQuit ' unfreeze
@ onMove ' cancel si frozen
}
ModerationListener ..|> "org.bukkit.event.Listener"
ModerationListener --> ModerationService
}
package "fr.luc.crcore.features.moderation.tool" {
class ExitTool ' slot 8
class VanishToggleTool ' slot 7
class FreezeTool ' slot 2 (entity right-click)
class InventorySpyTool ' slot 1 (entity right-click)
class TeleportRandomPlayerTool ' slot 0
ExitTool ..|> ModeratorTool
VanishToggleTool ..|> ModeratorTool
FreezeTool ..|> ModeratorTool
InventorySpyTool ..|> ModeratorTool
TeleportRandomPlayerTool ..|> ModeratorTool
}
package "fr.luc.crcore.features.moderation.event" {
abstract class ModerationEvent {
- moderator: Player
+ getModerator(): Player
}
ModerationEvent --|> "org.bukkit.event.Event"
class ModerationEnterEvent
class ModerationExitEvent
ModerationEnterEvent --|> ModerationEvent
ModerationExitEvent --|> ModerationEvent
}
package "fr.luc.crcore.features.moderation.exception" {
class ModerationException
class ModerationAlreadyActiveException
class ModerationNotActiveException
ModerationException --|> RuntimeException
ModerationAlreadyActiveException --|> ModerationException
ModerationNotActiveException --|> ModerationException
}
package "fr.luc.crcore.features.moderation.command" {
class AdminToggleSubCommand {
+ execute(ctx): CommandResult
}
AdminToggleSubCommand ..> ModerationService
}
ModerationService ..> ModerationState : reads/writes
ModerationService o--> ModerationRepository
ModerationService o--> ModeratorToolRegistry
ModeratorToolRegistry o--> "*" ModeratorTool
}
package "fr.luc.crcore" {
class CRCore {
+ moderation(): ModerationService
# buildModerationService(repo, registry): ModerationService
# registerDefaultModeratorTools(registry, mod): void
}
CRCore "1" *-- "0..1" ModerationService : owns (if setupModeration)
CRCore ..> ModerationListener : registers
}
note bottom of ModerationServiceImpl
enter(player) :
1. ModerationState snapshot → repo.save
2. clear inventory, set tools in hotbar
3. gamemode CREATIVE + allowFlight
4. vanish(player)
5. onAfterEnter() → event fired
exit(player) :
1. state.restoreTo(player) ' inv + xp + loc + gm + flight
2. unvanish(player)
3. unfreeze + repo.delete
4. onAfterExit() → event fired
Skeleton : in-memory repository only.
Persistance SQLite à venir.
end note
@enduml