
Team-HomeGUI Plugin
A lightweight team system with team homes, private team chat, personal homes, and a clean home GUI
Список изменений
[1.3.0] — Bug-fix & Feature Release
New Feature
- Confirm-Delete Home GUI — clicking the red dye (delete) button in the Home GUI now
opens a 27-slot confirmation dialog instead of deleting instantly.
- Slot 11 (user-facing 12) → 🔴 Red glass pane "No" — cancel
- Slot 13 (user-facing 14) → 🛏 Red bed "Delete Home?" — centre icon
- Slot 15 (user-facing 16) → 🟢 Lime glass pane "Yes" — confirm permanent deletion
Critical Bug Fixes
- NPE crash when opening Home GUI —
loc.getWorld().getName()was called without a null check; if a world was deleted or unloaded after a home was saved, opening the GUI caused aNullPointerExceptionand crashed the inventory for that player. Now shows"World no longer exists"gracefully for both personal homes and team home. - Race condition in HomeManager — inner
HashMap<String, Location>was not thread-safe; the async save thread iterating it while the main thread wrote to it could causeConcurrentModificationExceptionand silent data loss. Changed toConcurrentHashMapfor inner maps.
Bug Fixes — Logic
- Mass message-key mismatch — dozens of
plugin.msg(key)calls used keys that did not exist inteam-config.yml, causing players to see raw"Message not found: <key>"strings. All handlers now reference the correct existing keys or new keys added in this release:TeamHandler:invite-no-permission,invite-already-in-team,leave-success,player-left-team,player-not-in-team,kick-no-permission,cannot-kick-owner,kick-broadcast(updated placeholders{kicker}/{kicked})ChatHandler:chat-already-enabled,chat-already-disabled; team-message format now readssettings.chat-format(was hardcoded missing key"team-chat-format") and correctly replaces{team}and callsTeamPlugin.color()SettingsHandler: all promote / demote / transfer / name / invite messages now match config keys;"settings-name-success","settings-invite-changed","settings-transfer-success/received/broadcast"and"settings-promote-self-error"addedAdminHandler:"wrong-password","admin-team-already-exists","admin-ban-success","admin-unban-success","admin-add-success/target","admin-already-banned","admin-not-banned","admin-disbanned-target","admin-remove-team-success"alignedListHandler:"list-entry"and"list-footer"added to config
SettingsHandler.handleAdminSettings()always returned "team not found" — the handler was readingargs[1](which contains the literal string"settings") instead ofargs[2]as the team ID. Fixed all admin-settings argument indices accordingly.- Admin
/team admin settingssub-command was unreachable —AdminHandler.handleAdmin()had no"settings"case in its switch statement. Added routing toSettingsHandler. Team.canInvite()ignored Admin role — the public method only checked Owner andmembersCanInvite, making the Admin role unable to invite whenmembersCanInvite=false. Now consistent withTeamHandler.canInvite().- No max-members enforcement on invite —
TeamHandler.handleInvite()never checked the configuredsettings.max-memberslimit. Teams could grow without bound. Fixed. - Self-invite not caught — a player could invite themselves; added explicit check using
existing
"invite-self-error"config key. - Pending-invite not checked — a target with a pending invite from any team could receive
multiple invites. Now uses the existing
"invite-already-pending"key. GUISlotsenum had duplicate slot values —DELETE_DYE_*andSET_DYE_*both pointed to slots 29–33 (which were never used; real action slots are 20–24). Replaced withACTION_1..5+ newCONFIRM_NO / CONFIRM_BED / CONFIRM_YESslots.ListHandlerreturned teams in random order —ConcurrentHashMap.values()has no guaranteed iteration order; added alphabetical sort.
Bug Fixes — Performance / Safety
Team.getOwnerName()could block the main thread —Bukkit.getOfflinePlayer(UUID)may perform disk I/O to read playerdata files. Now checks the online-player cache first, thengetOfflinePlayerIfCached()(no I/O), and only falls back to the disk call for completely unknown players.- WarmupListener did not restore custom walk/fly speed — after a warmup the speed was always reset to Bukkit defaults (0.2 / 0.1), overriding server-rank speed multipliers. The actual speeds are now saved before freezing and restored on cancel or completion.
HomeManager.getHomeNames()returned a mutable live view — callers iterating the result while a concurrent modification occurred could getConcurrentModificationException. Now returnsSet.copyOf().- Home name validation inconsistency —
HomeServiceallowed-and had no length cap, whileHomeHandlerdid not allow-and enforced 16 chars. Unified to the stricter^[a-zA-Z0-9_]{1,16}$pattern across both paths. gui.show-coordinatesdefault mismatch — Java fallback wastruewhile the config file default isfalse. Changed Java fallback tofalse.
Config Changes (team-config.yml)
Added keys:
cannot-kick-owner, team-full, chat-already-enabled, chat-already-disabled,
list-entry, list-footer, admin-target-is-banned, admin-add-success,
admin-add-target-msg, admin-already-banned, admin-not-banned,
admin-removed-from-team, admin-cannot-remove-admin-team, admin-disbanned-target,
admin-remove-team-success, settings-name-success, settings-name-changed-broadcast,
settings-name-failed, settings-invite-changed, settings-invite-changed-broadcast,
settings-transfer-success, settings-transfer-received, settings-transfer-broadcast,
settings-help, admin-settings-help, settings-promote-self-error,
usage-settings-name/color/invite/promote/demote/transfer, usage-admin-settings
Updated keys:
kick-broadcast→ now uses{kicker}and{kicked}placeholderssettings-name-broadcast→ now uses{name}and{player}placeholders

