main
12 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
6648b3b375 |
docs: rename GEMINI.md → CLAUDE.md and update content
Renamed with git mv to preserve history. Refreshed the content to match the current state of the project: - Java 11 build target (was 16) — explicit warning not to reintroduce records / pattern matching / switch expressions. - New three-layer architecture: util/ (always on) + features/ (opt-in via setupX()) + builtin/ (top-level commands). - New features documented: messages, broadcasts, GUI framework, team settings, moderation skeleton. - Diagrams layout: util/ + features/<feature>/ + cross-cutting at root. - File generation pattern documented: <plugin>-messages.yml, <plugin>-broadcasts.yml, <plugin>-team-config.yml in dataFolder. - Maven build + deploy commands and Gitea Packages publishing URL. - Git workflow conventions: HTTPS URL with token, co-author trailer. setup.md tree updated (GEMINI.md → CLAUDE.md reference). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> |
||
|
|
4efaa5bbde |
feat: moderation feature skeleton (/core admin + mod mode + tools)
New feature fr.luc.crcore.features.moderation, opt-in via CRCoreConfig.setupModeration() (also enabled by setupAll()). Core abstractions: - ModerationState: full player snapshot (inv + armor + offhand, XP, health, food, location, gamemode, allowFlight/flying, walk/fly speed). Immutable, restoreTo(player) restores everything. - ModerationService interface + ModerationServiceImpl (with protected onAfterEnter/onAfterExit hooks) + BukkitEventFiringModerationServiceImpl (fires ModerationEnterEvent / ModerationExitEvent). - ModerationRepository interface + InMemoryModerationRepository (skeleton — SQLite impl with BukkitObjectOutputStream serialization planned). - ModeratorTool interface: getKey/getSlot(0..8)/buildIcon + onLeftClick/onRightClick/onInteractEntity. ModeratorToolRegistry preserves registration order, slot collision = replace. - Exceptions: ModerationException base + AlreadyActive + NotActive. - Events: ModerationEvent base + Enter + Exit. 5 skeleton tools in the hotbar: - slot 0: TeleportRandomPlayerTool (compass, right-click → tp random) - slot 1: InventorySpyTool (chest, right-click on player → open inv) - slot 2: FreezeTool (ice, right-click on player → toggle freeze) - slot 7: VanishToggleTool (ender eye, click → toggle vanish) - slot 8: ExitTool (barrier, click → exit mod mode) Slots 3-6 free for custom tools. ModerationListener routes interactions and locks hotbar: - PlayerInteractEvent → tool.onLeftClick / onRightClick (with cancel). - PlayerInteractEntityEvent → tool.onInteractEntity (with cancel). - PlayerDropItemEvent / PlayerSwapHandItemsEvent: cancel for mods. - InventoryClickEvent: cancel only when top inv is the mod's own inv (preserves InventorySpyTool's ability to manipulate target's inv). - PlayerJoinEvent: re-applies vanish for already-vanished mods. - PlayerQuitEvent: cleanup freeze state. - PlayerMoveEvent: cancel block-position changes for frozen players, keeping head rotation free. Mod mode lifecycle: - enter: snapshot + clear inv + populate hotbar + CREATIVE + allowFlight + vanish + ModerationEnterEvent. - exit: state.restoreTo(player) + unvanish + unfreeze + repo delete + ModerationExitEvent. /core admin (perm crcore.admin, player-only): toggle on/off. Messages moderation.enter.success / moderation.exit.success added to crcore-messages.yml. CRCoreConfig.setupModeration() + isModerationEnabled() flag. CRCore: buildModerationService() and registerDefaultModeratorTools() override points, moderation() / getModerationService() getters with IllegalStateException guard. Builds + registers ModerationListener at enable() when feature on. CoreCommand extended to take ModerationService; registers AdminToggleSubCommand only when service non-null. Skeleton limitations documented in features.md: - In-memory repo only (server crash = lost inv) — SQLite planned. - InventorySpyTool opens real inv (no read-only wrapping yet). - TeleportRandomPlayerTool is a placeholder for a future player-picker GUI. - No moderation.*.broadcast keys yet. - No /core admin <player> (self-toggle only). Docs: section 11 in features.md, decision logged in decisions.md (skeleton scope + rationale), setup.md snippet updated, new moderation-class-diagram.puml, README.md updated. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> |
||
|
|
84735221f1 |
refactor: split util/ vs features/ + modular opt-in setupX() config
Package restructure to prepare future modularization. Three layers now:
1. fr.luc.crcore.util.* (always active)
- common, command framework, database, message, broadcast, gui,
placeholder
2. fr.luc.crcore.features.* (opt-in)
- team (entities, services, repos, events, exceptions, config + GUI,
command/Team*SubCommand)
- player (profile, ranking, services, repos, events, exceptions)
3. fr.luc.crcore.builtin.*
- CoreCommand + CoreReloadSubCommand (top-level routing — not a
feature, not an util)
FQN moves (game plugins importing these need their imports updated):
- fr.luc.crcore.common.* → fr.luc.crcore.util.common.*
- fr.luc.crcore.command.* → fr.luc.crcore.util.command.*
- fr.luc.crcore.command.builtin.team.*
→ fr.luc.crcore.features.team.command.*
- fr.luc.crcore.command.builtin.CoreCommand / CoreReloadSubCommand
→ fr.luc.crcore.builtin.*
- fr.luc.crcore.database.* → fr.luc.crcore.util.database.*
- fr.luc.crcore.message.* → fr.luc.crcore.util.message.*
- fr.luc.crcore.broadcast.* → fr.luc.crcore.util.broadcast.*
- fr.luc.crcore.gui.* → fr.luc.crcore.util.gui.*
- fr.luc.crcore.placeholder.* → fr.luc.crcore.util.placeholder.*
- fr.luc.crcore.team.* → fr.luc.crcore.features.team.*
- fr.luc.crcore.player.* → fr.luc.crcore.features.player.*
CRCoreConfig — features opt-in via fluent setup:
- setupTeams() enables team feature
- setupPlayers() enables player feature
- setupPlaceholders() enables PAPI integration
- setupAll() shortcut
By default no feature is active. Game plugin must opt-in.
CRCore.enable() now conditional:
- Util services always built (messages, broadcasts, gui listener).
- Team services + repos + config built only if setupTeams().
- Player services + repos built only if setupPlayers().
- Placeholder hook registered only if setupPlaceholders() (and PAPI
installed at runtime).
- Getters of disabled features throw IllegalStateException with a clear
message pointing to the missing setupX() call.
- CoreCommand only registers TeamGroupSubCommand if teamService and
teamConfig are non-null. CoreReloadSubCommand handles teamConfig=null
(just skips that reload). /core reload always available.
Docs:
- setup.md tree fully rewritten to reflect util/+features/+builtin
layout (~70 lines of arborescence).
- setup.md code snippet shows the three opt-in patterns (setupAll /
granular / with options).
- decisions.md logs both decisions (restructure + modular setup).
- All .puml diagrams auto-updated to new FQNs.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
|
||
|
|
75d2fa866d |
feat: typed team settings (cascade per-team → global → default) + in-game GUI
New fr.luc.crcore.team.config module: - TeamSetting<T> (typed, with key/type/default/parser/serializer; factories ofBoolean/ofInt/ofString/ofEnum). - TeamSettings registry: 8 standard settings (FRIENDLY_FIRE, PVP_PROTECTION_SECONDS, MAX_SIZE, MIN_SIZE, RESPAWN_AT_TEAM_SPAWN, TEAM_CHAT_ENABLED, SHOW_TAG_ABOVE_HEAD, TEAM_COLOR_IN_NAME), extensible via register() for game plugins. - TeamConfigService interface with cascade get(team, setting) → per-team override (SQLite) → global YAML → hard default. Persists per- team via TeamRepository.save(), global via YamlConfiguration.save(). - YamlTeamConfigService default impl with bundled crcore-team-config.yml. Storage: - Team.getSettings() Map<String, Object> for per-team overrides. - New SQLite table crcore_team_settings (team_id, key, value, type) with load + write-through persist in SqliteTeamRepository. - Global YAML <plugin>-team-config.yml in dataFolder, auto-created at first boot (template from game plugin's resource of the same name takes priority). New reusable GUI framework fr.luc.crcore.gui: - AbstractInventoryGui (implements InventoryHolder, rebuild() abstract, setButton/setDecoration/clearSlot helpers, onClose hook, openTo()). - GuiClickHandler FunctionalInterface. - GuiListener (single Bukkit listener, detects via getHolder(), ALWAYS cancels clicks even on slots without handlers). - GuiItems builder (named/of/filler + lore/amount/build, '&' color codes translated). Concrete settings GUIs (fr.luc.crcore.team.config.gui): - AbstractSettingsGui base renderer: 27 slots, settings in row 2, booleans = LIME_DYE / GRAY_DYE toggle, integers = BOOK with left +1 / right -1 (shift × 10), strings/enums display-only. - GlobalSettingsGui: writes to YAML on each change. - TeamSettingsGui: writes to per-team overrides, "override active" flag in lore when value differs from global, "Reset all overrides" footer button. New /core team settings [team] subcommand: - No arg → GlobalSettingsGui (perm crcore.team.settings.global). - With arg → TeamSettingsGui (perm crcore.team.settings). - Player-only (Bukkit needs HumanEntity to open inventory). - Lives under /core team to stay modular (objective: split into modules later; everything team-related under /core team). CRCore: buildTeamConfigService() override point, teamConfig()/getTeamConfig() getters, GuiListener.registerOn(plugin) at enable(). CoreCommand, TeamGroupSubCommand and CoreReloadSubCommand extended to receive TeamConfigService. /core reload now reloads messages + broadcasts + team-config. Docs: new section 10 "Paramètres d'équipe", new decisions logged, setup.md tree updated, two new diagrams (team-config + gui). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> |
||
|
|
a94bc56a5b |
feat: configurable broadcasts + /core reload
New fr.luc.crcore.broadcast module: - BroadcastAudience enum (NONE, LEADER, TEAM, ADMIN, ALL). - BroadcastContext (fluent: team + involvedPlayerId + placeholders). - BroadcastService interface + YamlBroadcastService impl. - CRCoreBroadcastListener (Bukkit listener) wires the 12 native events (9 team + 3 player) to broadcasts.broadcast(eventKey, ctx). Same single-per-plugin file pattern as messages: <plugin-dataFolder>/<plugin-name-lowercase>-broadcasts.yml. Defaults bundled at resources/crcore-broadcasts.yml, copied on first boot (game plugin's own resource of the same name takes priority as the template). In-memory fallback so new CR-Core keys work without admin edit. Routes (who) vs templates (what) are separated: broadcasts.yml lists audiences per eventKey, messages.yml contains the templates under keys <eventKey>.broadcast. Admin can change either independently. 12 new *.broadcast keys added to crcore-messages.yml with sensible French defaults and color codes. Listener injects standard placeholders (name, team_name, tag, color, visibility, player, new_leader, old/new_value, etc.). ADMIN audience resolved via crcore.broadcast.admin permission. Multi- audiences via YAML list (e.g., [TEAM, ADMIN]); union of resolved players, no duplicate. New /core reload subcommand (permission crcore.reload) hot-reloads both messages and broadcasts from disk without restart. CRCore: protected buildBroadcastService() override point, getter broadcasts(), wire of CRCoreBroadcastListener at enable(). CoreCommand constructor extended to take BroadcastService, registers the reload subcommand. Docs/features.md: new section 9 "Service de broadcasts". docs/setup.md: updated to mention both YAML files. decisions.md logs the routes-vs- templates split, the audience model, and the reload semantics. New diagram broadcasts-class-diagram.puml. README updated. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> |
||
|
|
923f48ffc7 |
refactor: split team/player/message into impl/ and exception/ subpackages
Each domain now has:
- Top-level package: contracts (interfaces, entities, enums, values, events).
- exception/ subpackage: exception hierarchy.
- impl/ subpackage: implementations CR-Core ships by default, swappable by
a game plugin if needed.
Moved (FQN changes for consumers):
- fr.luc.crcore.team.TeamException (+ AlreadyExists, NotFound, Access)
→ fr.luc.crcore.team.exception.*
- fr.luc.crcore.team.TeamServiceImpl, BukkitEventFiringTeamServiceImpl,
InMemoryTeamRepository, SqliteTeamRepository
→ fr.luc.crcore.team.impl.*
- fr.luc.crcore.player.PlayerException, PlayerProfileNotFoundException
→ fr.luc.crcore.player.exception.*
- fr.luc.crcore.player.PlayerProfileServiceImpl,
BukkitEventFiringPlayerProfileServiceImpl,
InMemoryPlayerProfileRepository, SqlitePlayerProfileRepository
→ fr.luc.crcore.player.impl.*
- fr.luc.crcore.message.YamlMessagesService
→ fr.luc.crcore.message.impl.YamlMessagesService
Unchanged top-level packages: database/, command/, common/ (already small
and well-organized). Events stay where they were (already in event/
subpackages).
setup.md tree updated to reflect the new layout. decisions.md logs the
rationale (consumer-facing FQNs, separation between contract and impl).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
|
||
|
|
4651ccbe69 |
docs: document MessagesService — single per-plugin YAML, defaults in jar
features.md: new section 8 "Service de messages" with the single-file model, two-layer in-memory (jar defaults + user file), API examples, template-override mechanism, and override-the-impl extension point. Bootstrap section renumbered to 9. decisions.md: new decision logging the choice of MessagesService design (YAML, single per-plugin file, in-jar fallback for new keys, template priority from the game plugin's own resource, programmatic set() for dynamic cases). README.md: feature list mentions externalized messages; diagrams index adds messages-class-diagram.puml. setup.md: new "Fichier messages" section explaining the file location, how to seed it from a game plugin's bundled template, and the API for hot reload / extras / programmatic set(). New diagram: docs/diagrams/messages-class-diagram.puml — MessagesService interface, YamlMessagesService impl, link to CRCore, with explanatory note on the two-source merge and template fallback at first boot. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> |
||
|
|
8b7cad3fce |
feat: chef commands moved to admin + PlaceholderAPI integration
Chef → admin: the chef role no longer grants any command privilege. All team-management subcommands now take <team> as an argument and are gated by their crcore.team.<action> permission only: - add <team> <player> - remove <team> <player> - transfer <team> <player> - visibility <team> <PUBLIC|PRIVATE> - setspawn <team> (still player-only — needs admin's location) The LEADER role is kept in the data model (Team / TeamMember) and remains usable by game plugins via the API, but does not unlock any default command. Future work can re-introduce chef-specific commands if needed. PlaceholderAPI: auto-detected at CRCore.enable(). If the PAPI plugin is present on the server, CRCorePlaceholderExpansion registers automatically; otherwise the lib runs without it (no NoClassDefFoundError thanks to the indirection through doRegisterPlaceholderHook). Placeholders exposed: - Team: %crcore_team%, %crcore_team_name/tag/color/color_chat/size/ visibility/leader_name/total_score%, %crcore_team_score_<name>% - Player: %crcore_player_score_<name>%, %crcore_player_score_total% Dependency: me.clip:placeholderapi:2.11.6, scope provided. New repo: https://repo.extendedclip.com/content/repositories/placeholderapi/. docs/features.md, decisions.md and the builtin-commands diagram updated to reflect the simpler admin/player two-tier model and the PAPI section. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> |
||
|
|
5bd6e227d3 |
chore: downgrade compile target to Java 11
Uses <release>11</release> in maven-compiler-plugin (recommended over source/target to guarantee bytecode and API surface match Java 11). Code changes to drop Java 12-16 features: - records (TeamRanking, PlayerRanking, internal tuples in SqliteTeamRepository) become hand-written immutable classes; same accessor names (rank()/team()/score()/...) so call sites are unchanged. - instanceof X x pattern matching becomes classic instanceof + cast in CommandContext.requirePlayer and Database.normalize. - switch expressions with -> arrows become classic switch + break, or if/else chains, in BaseCommand.handleResult, ArgumentTypes.BOOLEAN and TeamScoreSubCommand.execute. docs/setup.md, features.md and decisions.md updated to reflect Java 11. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> |
||
|
|
7ee349f206 |
feat: dynamic command registration + Maven publication setup
CRCore.registerCommand() now falls back to dynamic registration via the server's internal CommandMap (reflection on CraftServer.commandMap) when the command is absent from the host plugin's plugin.yml. Game plugins can now use CR-Core with zero plugin.yml changes — just instantiate CRCore. If the command IS declared in plugin.yml, CR-Core detects it and uses setExecutor/setTabCompleter as before. pom.xml: distributionManagement targeting Gitea Packages (https://gitea.luc-rival.fr/api/packages/admin/maven), plus maven-source-plugin (3.3.0) and maven-javadoc-plugin (3.6.3) so each mvn deploy publishes the main jar, a -sources.jar and a -javadoc.jar. doclint=none on javadoc to tolerate partial doc. docs/setup.md: clarifies that the commands: entry in plugin.yml is now optional. docs/decisions.md: new decision logged for the dynamic registration approach. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> |
||
|
|
c1b414f400 |
feat: SQLite persistence, default /core commands, Bukkit events, bootstrap
CRCore bootstrap class: one-line setup for game plugins (new CRCore(this).enable()).
Wires SQLite, services with event firing, and the /core command tree.
SQLite layer (fr.luc.crcore.database): Database wrapper exposing execute/update/
queryOne/query plus a fluent TableBuilder. ColumnType enum, RowMapper interface,
DatabaseException. Game plugins create their own tables in 2 lines via
db.table("foo").ifNotExists().column(...).create().
Repositories: SqliteTeamRepository and SqlitePlayerProfileRepository extend their
InMemory counterparts (write-through cache). 5 internal tables prefixed crcore_.
Command framework refactored for nested sub-commands: subcommand storage moved
from BaseCommand to AbstractCommand, recursive dispatch() and tabComplete(),
replaceSubCommand() for plugin overrides.
Default /core team commands (13 leaf sub-commands): create, delete, add, remove,
join, leave, info, list, transfer, visibility, score, top, setspawn. Each in its
own class under fr.luc.crcore.command.builtin.team, fully substitutable.
Bukkit events: 9 team events (Create/Dissolve/MemberAdd/MemberRemove/PlayerJoin/
LeadershipTransfer/VisibilityChange/ScoreChange/SpawnPointChange) + 3 player
events (ProfileCreate/Delete/ScoreChange). All post-only, non-cancellable.
BukkitEventFiringTeamServiceImpl and BukkitEventFiringPlayerProfileServiceImpl
override the on* hooks to call Bukkit.getPluginManager().callEvent.
JavaDoc on all new public classes and key existing ones. docs/, GEMINI.md and
PUML diagrams synced: new sections (built-in commands, events, database,
bootstrap), 4 new diagrams (builtin-commands, events, database, bootstrap-
sequence), and 7 new architecture decisions logged.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
|
||
|
|
ffc77c4213 |
feat: initial CR-Core library (team + player + command framework)
Pure Maven library for CR Minecraft game plugins, targeting Paper 1.16.5. Common abstractions (fr.luc.crcore.common): Identifiable, Named, ScoreHolder, AbstractEntity, Repository<T>. Team domain (fr.luc.crcore.team): Team entity with name/tag/color/leader/ visibility (PUBLIC|PRIVATE)/members/scores/spawn point, TeamMember, TeamRole/TeamColor/TeamVisibility enums, TeamRanking record, TeamService with overridable hooks (factories, validations, lifecycle events), in-memory repository, dedicated exception hierarchy. Player domain (fr.luc.crcore.player): PlayerProfile with named scores per player, PlayerProfileService with auto-creation, individual rankings, exception hierarchy. Both Team and PlayerProfile implement ScoreHolder. Command framework (fr.luc.crcore.command): Command interface, AbstractCommand base, BaseCommand (CommandExecutor + TabCompleter), SubCommand, CommandContext, CommandResult, ArgumentType<T> + ArgumentTypes catalogue (STRING, INTEGER, DOUBLE, BOOLEAN, ONLINE_PLAYER, enumOf, choice). Docs (docs/) is the single source of truth: README, setup, features, decisions log, and 6 PlantUML diagrams (team class/sequence/activity/join, player class, command class). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> |