Changelog
Complete version history
Full release history with all features, fixes, and technical changes. For a user-friendly overview, see the Patch Notes or the CurseForge page.
v0.8.15
Admin UI
- White-label configuration page - Server owners with the WHITE_LABEL entitlement can now edit branding settings directly from the admin UI. Access via the "White Label" button in the Actions section. Configure server name, description, branding position, accent color, and credit visibility without editing JSON files
- Entitlement-gated admin sections - Boost configuration sections (limits, stack mode, templates, award boost) are now hidden in the admin UI unless the server has the PERMISSION_BOOSTS entitlement active
Improvements
- Branding extended to all pages - Custom server branding now appears on the Quests, Boosts, Leaderboard, and Settings pages when branding position is set to "left"
- Consistent left panel styling - Settings button in Quest and Boost pages now matches the tab styling used in the main Skills Overview page
v0.8.14
New Quests
- Getting Started - New introductory quest that rewards a Skills Menu Scroll for breaking your first block. Auto-accepts and auto-claims to welcome new players. The crafting recipe for the Skills Menu Scroll has been removed in favor of this quest
Configuration
- Max active quests setting - New
maxActiveQuestsconfig option limits how many quests a player can have active at once (default: 10)
Improvements
- Quest rewards now check inventory space - Autoclaim quests will wait in "ready to claim" status if your inventory is full, and manual claims will be blocked until you free up space
- Settings moved to sidebar - The Settings button is now in the left panel navigation list instead of at the bottom
- Better reusable boosts messaging - When reusable boosts are not enabled on the server, shows a clear message instead of "No reusable boosts available"
v0.8.13
Custom Server Branding
- White-label branding support - Server owners with the WHITE_LABEL entitlement can now customize the skill menu with their own branding. Configure your server name in
mods/mmoskilltree/white-label.jsonand add your logo as an asset to replace the default header
New Quests
- Bear Bounty - New daily quest to slay 20 bears, rewarding 2 Building XP Shards. Resets every 24 hours
Bug Fixes
- Fixed Block XP from fire damage - Players no longer gain Block XP from taking fire damage
v0.8.12
New Items
- Skill Tree Reset Scroll - A consumable item that resets all skill tree reward selections. Hold for 3 seconds to reset your reward choices across all skills, allowing you to pick new rewards. XP and levels are preserved — only your reward selections are cleared. The scroll is consumed on use
Bug Fixes
- Fixed non-fatal errors on startup for invalid item qualities - Removed invalid quality JSON files that were causing errors during server startup
- Fixed combat XP exploit with invulnerable entities - Players can no longer farm combat XP by attacking invulnerable entities
Technical Details
- New
MmoSkillAllResetInteractioninteraction handler registered asmmo_skill_all_reset— extendsSimpleInstantInteraction, callsSkillTreeService.removeAllStatModifiers()thenskills.resetAllRewards()to clear all reward selections - Added
Mmo_Reset_Skills_Scroll.nameandMmo_Reset_Skills_Scroll.descriptiontranslations to all 9 language item files - Added
notify.skill_tree_resetlocalization key to all 9 language defaults files
v0.8.11
New Items
- Skills Menu Scroll - A new consumable item that opens the Skills menu when used. Left-click to instantly open your skills page without typing commands. The scroll is reusable and not consumed on use
Technical Details
- New
MmoMenuOpenInteractioninteraction handler registered asmmo_menu_open— extendsSimpleInstantInteraction, opensViewXpPagefor the player on Primary interaction - Added
Mmo_Menu_Scroll.nameandMmo_Menu_Scroll.descriptiontranslations to all 9 language files
v0.8.10
Boost Permissions Overhaul
- Boost permissions now use native permission checks - The custom
permissions.jsonfile-based boost permission system has been replaced with nativeplayer.hasPermission()checks, ensuring compatibility with any permission mod like LuckPerms or HyperPerms - 84+ built-in boost permission nodes - A comprehensive set of boost templates is now available out of the box, covering all-skills, category, per-skill, and global boosts at various multipliers and durations. Server owners grant the corresponding permission nodes through their preferred permission mod
- Removed
/mmoconfig reloadpermscommand - No longer needed since permissions are checked live through the native permission system - Boost page refresh no longer requires file reload - The Refresh button on the Boosts page now re-renders instantly, checking permissions in real time
Configurable Boost Templates
- Boost templates are now a proper override-based config - All boost permission templates are stored in
mods/mmoskilltree/boost-templates.jsonusing the same override pattern as XP tokens. Only customizations are persisted; defaults are always built in - Custom boost nodes require registration - The mod only recognizes boost nodes that are registered as templates. To create a custom boost with values not in the 124 defaults, use the "Add" button in the admin UI — simply granting an unregistered node via a permission mod will not work
- New admin UI page for boost templates - Browse, add, disable, and delete boost templates from the admin config page. Accessible via the "Boost Templates" button in the Actions section. Includes a copyable permission string field for pasting directly into permission mod commands
- Add custom templates - Create new boost templates with any multiplier, duration, and cooldown combination. Select a target and scope, enter the values, and click Add — the new permission node is generated automatically and appears in the list
- Delete custom templates - Remove custom templates you no longer need. Default templates cannot be deleted (use Disable instead)
- Disable specific boost templates - Disable any boost template to prevent players from using it, even if they have the permission node
- Trim redundant overrides - Clean up overrides that match their default values with a single button click
Offline Player Support for Bulk XP
/bulksetxpnow queues changes for offline players - When targeting*(all players) or naming specific players who aren't online, XP changes are saved and applied automatically when they next join the server- Queued resets apply on login - Pending XP changes are applied in order, rewards are validated (revoked if levels dropped), and the leaderboard is updated — all before stat effects are reapplied
- Persistent queue - Pending XP changes survive server restarts, stored in
mods/mmoskilltree/pending-xp-resets.json
Bug Fixes
- Fixed skill tree rewards showing duplicated values - Rewards on the skill tree page were displaying doubled text like "+10% +10% Mining XP" instead of "+10% Mining XP". The display text for custom reward names is now shown as-is without prepending the formatted value again
Technical Details
XpBoostService: removedbuildDefaultTemplates()method (hardcoded permission strings).initTemplates()now reads fromBoostTemplateConfig.getInstance().getAllDefinitions(), converts non-disabled definitions toBoostPermissionviatoBoostPermission(), and populatesavailableTemplates- New
BoostTemplateConfig: singleton override-based config atmods/mmoskilltree/boost-templates.json. Schema version 1. Same load/save pattern asXpTokenConfig— mergesBoostTemplateDefaultswith user overrides - New
BoostTemplateDefaults: staticgetAllDefaults()producesLinkedHashMapfrom permission node strings (previously inXpBoostService.buildDefaultTemplates()) - New
BoostTemplateDefinition: immutable value object wrappingBoostPermissionwithwithOverrides()andtoBoostPermission()methods for config round-tripping - New
BoostTemplateOverridesPage: admin UI page with Personal/Global scope tabs, category/skill target selectors, and 7-column table (DEF MULT/DUR/CD, CUR MULT/DUR/CD, STATUS). Edit section supports multiplier, duration, and cooldown fields. All changes triggerXpBoostService.initTemplates()to reload templates MMOSkillTreePlugin.setup(): addedBoostTemplateConfiginitialization beforeXpBoostService.initTemplates()AdminConfigPage: added#EditBoostTemplatesBtnbutton andeditBoostTemplatesaction handler- Added
ui.admin.edit_boost_templatesandui.boosttemplates.titlelocalization keys to all 9 language files - New
PendingXpResetStore: file-based singleton store atmods/mmoskilltree/pending-xp-resets.json, keyed by lowercase username. Each entry is a list ofPendingXpResetobjects (skill+value). Same load/save/drain pattern asPendingQuestRewardStore BulkSetXpCommand: after applying to online targets, iteratesLeaderboardDataStore.getAllPlayers()(for*) or the named target list to queue resets for any player not found online. Reports queued count separately in yellowMMOSkillTreePlugin:PendingXpResetStoreinitialized and loaded insetup(), saved in shutdown hook.PlayerReadyEventhandler drains pending resets beforereapplyStatRewards()— sets XP per operation, then runsSkillTreeService.validateAllRewards()andCommandRewardService.validateAllCommandRewards()to revoke rewards where levels dropped
v0.8.8
Quest Visibility System
- Hidden quests - Quests can now be configured to stay invisible in the UI until specific conditions are met. Hidden quests automatically appear once the player starts them (via auto-accept or admin commands)
- Permission-gated visibility - Hide quests until the player has a specific permission, useful for secret quest chains or premium content
- Prerequisite-gated visibility - Hide quests until prerequisite quests are completed, preventing players from seeing spoilers for quest chains they haven't reached yet
- Level-gated visibility - Hide quests until the player meets the level requirements, keeping the quest list focused on achievable content
Quest Page Filters
- Quest search - Filter quests by typing part of a quest name or description. Click Search to apply or the X button to clear. Case-insensitive matching against both display name and description text
- Status filter buttons - Quickly filter quests by status: All, Active, Available, or Completed. Filter state is preserved when accepting, claiming, or abandoning quests
New Default Quests
- 8 new default quests covering excavation, combat, crafting, woodcutting, harvesting, and mining progression:
- Dirt Digger (main) - Dig 200 soil blocks for Excavation XP
- First Blood (main) - Slay 5 Trorks for Defense XP
- Apprentice Crafter (main) - Craft 20 items and reach Crafting level 5
- Lumberjack's Path (main) - Chop Oak and Birch wood, reach Woodcutting level 10
- Big Game Hunter (main) - Slay Bears and Outlanders. Requires First Blood and total level 25
- Harvest Season (daily) - Harvest 40 crops on a 24-hour cooldown
- Undead Cleanup (daily) - Slay 15 Zombies on a 6-hour cooldown
- Gem Collector (misc) - Mine 10 each of Diamonds, Emeralds, and Rubies. Requires Mining level 30
Bug Fixes
- Fixed custom reward names not displaying on the skill tree page - When a skill tree reward's display name was overridden in config, the skill tree page still showed the default auto-generated name instead of the custom one
Technical Details
- New
QuestVisibilitydata class withhidden,permission,requirePrerequisites, andrequireLevelfields. Parsed from"visibility"JSON object in quest definitions QuestDefinitionnow uses a Builder pattern instead of a 17-parameter constructor. Old constructor removed; all creation goes throughQuestDefinition.builder(id, objectives).displayName(...).build()QuestService.isQuestVisible(): new method evaluating visibility conditions. Already-started quests (ACTIVE, COMPLETED_UNCLAIMED, COMPLETED, ON_COOLDOWN) always visible. Whenhidden=truewith no specific conditions, falls back tocanAcceptQuest()for backward compatibilityQuestPage: addedfilterStatusandsearchTextfields to constructor.getFilteredQuests()now applies visibility, text search, and status filter stages.QuestEventDatacodec extended withStatusandSearchInputkeyed fields. All page reopens (accept/claim/abandon/filter) preserve filter stateQuestConfig.parseQuest(): parses"visibility"JSON object intoQuestVisibility. Newmining_expertdefault quest demonstrates hidden+prerequisite visibility- Extracted
QuestDefaultsclass fromQuestConfig— default quest definitions use theQuestDefinition.builder()API instead of positional parameters.questToJson()serializes anyQuestDefinitionto JSON for file output QuestCommand.handleList(): appends[HIDDEN]tag for quests withvisibility.hidden=trueMessages.getRewardDisplayText(): added early return whenreward.getDisplayName()differs fromreward.getType().getDisplayName(), using the overridden name with formatted value instead of auto-generating from reward type and skill ID- Added 6 localization keys (
ui.quests.search_placeholder,ui.quests.search_btn,ui.quests.filter_status_all/active/available/completed) to all 9 language files
v0.8.7
New Weapon Defaults
- Added Kurabiye's Longbows mod support - All 10 weapons from the Kurabiye's Longbows mod now have default Archery XP values: 9 longbow variants matching their material tier (Adamantite, Cobalt, Thorium, Iron, Copper, Crude, Flame, Frost, Poison) and the Kurabiye bow
Bug Fixes
- Fixed skill tree rewards showing 0% instead of fractional percentages - Rewards with decimal percentage values (e.g., 0.5% Critical Chance) were displayed as 0% on the skill tree page. Fractional percentages now display correctly with one decimal place (e.g., "+0.5%"), while whole-number percentages remain unchanged (e.g., "+5%")
- Broken weapons no longer award combat XP - Attacking with a broken weapon (0 durability) was still granting XP for the weapon's skill. Broken weapons now award no combat XP
- Quest level objectives now refresh when opening the Quests page - Quests with "reach level" objectives could appear incomplete even after the player exceeded the required level, if the XP was gained through admin commands, tokens, or other means that didn't trigger a quest event. Opening the Quests page now re-evaluates all level-based objectives against current skill levels
Technical Details
Messages.getRewardFormattedValue()andSkillReward.getFormattedValue(): replaced(int)(value * 100)cast with conditional formatting — whole-number percentages useString.valueOf((int) percent), fractional percentages useString.format("%.1f", percent). Prevents truncation of values like 0.5% to 0%CombatXpEventSystem.handlePlayerDealsDamage(): added early return whenisBroken && identifier != null, preventing XP awards for broken (0 durability) weaponsBowDefaults: added 9Weapon_Longbow_*entries (Adamantite, Cobalt, Thorium, Iron, Copper, Crude, Flame, Frost, Poison) andWeapon_Kurabiye(60L)QuestService.refreshReachLevelObjectives(): new method that iterates allREACH_LEVELobjective refs, checks each active quest's objectives against the player's current skill levels, and completes any that are now satisfied. TriggerscheckQuestCompletion()for newly completed objectivesQuestPage.build(): callsrefreshReachLevelObjectives()after fetchingQuestComponent, before display logic
v0.8.6
Kill-Only Combat XP Mode
- New Kill-Only Combat XP toggle - When enabled, offensive weapon skills (Swords, Axes, Polearms, Staves, Blunt, Daggers, Archery, Unarmed) only gain XP when you kill a mob, not on every hit. Defense and Acrobatics continue gaining XP per-hit regardless of this setting. Toggle it from the admin dashboard under General Settings
- Kill XP scales with weapon and mob - Your weapon's per-hit XP value acts as a percentage bonus on the mob's base XP. A legendary sword with 70 per-hit XP grants a 70% bonus, so killing a Trork (65 base) yields 110 XP. Weapon quality matters equally whether fighting critters or bosses
- Weapon XP Scaling toggle - Control whether weapon quality applies as a percentage bonus on mob base XP. Toggle from the Mob Kill XP admin page. When disabled, kill XP equals only the mob's base value
- Comprehensive mob XP defaults - Over 100 mob types have XP values sourced from the Hytale mob database, organized into clear tiers: critters/passive (5-22 XP), minor hostile (35-45), standard enemies (65), tough enemies (85), elite (130), endgame (250), and bosses (up to 500). All values are overridable
- New Mob Kill XP config - Customize how much base XP each mob type awards on kill via the new
mods/mmoskilltree/mob-kill-xp.jsonconfig file. Uses the same override-based system as other configs — only your customizations are saved, defaults auto-update with mod versions - New Mob Kill XP admin page - Browse and edit mob kill XP values from a visual editor accessible via the "Mob Kill XP" button on the admin dashboard. Add custom patterns, disable entries, reset to defaults, trim redundant overrides, and toggle weapon XP scaling
- Pattern-based mob matching - Mob kill XP uses longest substring matching against mob type names (e.g., "Skeleton" matches "Skeleton_Fighter", "Skeleton_Archer", etc.)
Bug Fixes
- Fixed
/mmoboostnot working when executed by other plugins - Third-party plugins like Tip4Serv that execute commands through the server's command system were rejected with "Only players or console can use this command". The boost command now correctly accepts commands from any non-player sender, such as plugin-dispatched command sources - Fixed crafting XP not awarded when using workstations - Crafting at workstations (anvils, furnaces, etc.) was not awarding XP or tracking quest progress because the craft event was emitted by the workstation entity, not the player. Crafting XP and quest objectives now work correctly regardless of whether you craft from your inventory or a workstation
- Fixed quests with level requirements not completing retroactively - Quests with "reach level" objectives would stay incomplete if the player already exceeded the required level when the quest was accepted. Level-based objectives are now checked and completed immediately at accept time, so players no longer need to gain another level to unlock quest rewards
- Milestone announcement commands now use server language - The
{skill}placeholder in milestone announcement commands now resolves to the server's default language instead of the triggering player's language, so broadcast messages are consistent for all players
Technical Details
BoostCommand: changed sender validation from requiring exactlyPlayerorConsoleSenderto treating any non-Playersender as console-like. This allows third-party plugins (Tip4Serv, etc.) that dispatch commands viaCommandManagerto use/mmoboostwithout being rejectedCraftRecipeEventSystem: changed ECS query fromPlayerRef.getComponentType()toArchetype.empty()so workstation-emitted craft events are captured. AddedtryGetPlayerRefFromEvent()(reflection-based) to resolve the crafting player from the event object, with fallback to the subject entity'sPlayerRefcomponent for inventory crafting. UsesplayerRef.getReference()to get the player entity ref for XP awards when the subject is a workstationQuestService.acceptQuest(): new overload accepting@Nullable SkillComponent. After initializing objective progress, iterates allREACH_LEVELobjectives and immediately completes any where the player's current skill level (or total level) already meets the requirement. All callers (processEvent,QuestPage,PlayerQuestCommand,QuestCommand) updated to passSkillComponentCommandExecutor.processPlaceholders(): new overload accepting@Nullable SkillComponentandboolean useServerLocale. WhenuseServerLocaleis true,{skill}resolves viaMessages.getSkillNameForLang()using the server's default language. When false with a non-nullSkillComponent, resolves using the player's language. Falls back to hardcoded English display name otherwise.SkillService.checkMilestoneAnnouncement()updated to use server locale
- Added
combatXpOnKillOnlyboolean toSkillConfig(defaultfalse), with getter/setter, save/load, andreloadDefaults()reset CombatXpEventSystem: guardshandlePlayerDealsDamage()behind!SkillConfig.getInstance().isCombatXpOnKillOnly()check. Defense (TAKE_DAMAGE) and Acrobatics (FALL_DAMAGE) paths unchangedMobKillEventSystem: addedhandleKillXp()— determines weapon skill viaCombatWeaponUtil, looks up mob base XP fromMobKillXpConfig, applies weapon XP as a percentage bonus viamobBaseXp * (100 + weaponXp) / 100(whenweaponXpScalingenabled), callsSkillService.addXp()- Extracted
CombatWeaponUtil— shared weapon→skill detection utility used by bothCombatDamageEventSystemandMobKillEventSystem. Uses longest substring match against DEAL_DAMAGE_PHYSICAL skill XP maps - New
MobKillXpConfig— override-based config (schema v1) with longest substring matching for mob types,weaponXpScalingboolean (defaulttrue). Stores overrides inmods/mmoskilltree/mob-kill-xp.json, generates defaults reference file - New
MobKillXpDefaults— 100+ default XP entries sourced from hytaleitemids.com API (295 mobs). XP tiers: critters 5, small passive 8, livestock 10-22, minor hostile 35, small hostile 45, medium hostile 55, standard enemies 65, tough 85, elite 130, high elite 175, endgame 250, bosses 400-500, fallback 25. Substring collision handling (e.g., explicit "Pigeon" to avoid "Pig" match). Undead livestock variants get hostile-appropriate XP - New
MobKillXpPage— admin page modeled afterXpOverridesPagewith single scrollable pattern list, add/update/disable/reset/trim functionality AdminConfigPage: added#ToggleCombatXpKillOnlytoggle,#EditMobKillXpBtnnavigation button, and corresponding event handlersMobKillXpPage: added#ToggleWeaponScalingtoggle withweaponXpScalingaction handler, dynamic mode note text- Added 4 localization keys (
ui.admin.combat_xp_kill_only_label,ui.admin.edit_mob_kill_xp,ui.mobkillxp.title,ui.mobkillxp.weapon_scaling_label) to all 9 language files
v0.8.5
Bug Fixes
- Fixed Acrobatics skill not gaining XP - The Acrobatics skill was not awarding any XP because its default XP values were never loaded. Acrobatics now correctly awards XP when players survive fall damage
- Improved fall damage detection - Fall damage is now detected more reliably for both Acrobatics XP awards and fall damage reduction rewards, using the damage cause ID as the primary check with a fallback to the environment source type
- Improved mob identification in combat - Combat events now extract mob identities from their model asset ID (e.g., "Skeleton_Fighter", "Bear_Grizzly"), providing more reliable entity detection for combat XP, quest objectives, and entity blacklisting
Quests
- New default quest: Forest Patrol - A repeatable kill quest to slay 10 Skeletons (pattern-matched, so Skeleton_Fighter, Skeleton_Archer, etc. all count). Rewards 2 Woodcutting XP Tokens. 90-minute cooldown
Technical Details
- Uncommented
case ACROBATICSinSkillDefaultsswitch, enablingAcrobaticsDefaults.getDefaults()to be registered AcrobaticsDefaults: changed XP key from"Fall"to""(empty catch-all pattern matching all acrobatics triggers)- Extracted
DamageUtil.isCause(damage, id)— checksdamage.getCause().getId()first, falls back toEnvironmentSource.getType(). Used by bothCombatXpEventSystem(acrobatics XP) andCombatDamageEventSystem(fall damage reduction) - Extracted
EntityIdentifierUtil— consolidates mob identification fromCombatDamageEventSystem,CombatXpEventSystem, andMobKillEventSysteminto a single utility. CombinesModelComponent.getModel().modelAssetIddeep extraction (with regextoString()fallback), directModelComponentmethod probing, andDisplayNameComponentfallback. Also providesdescribeEntity()for debug logging - Replaced wildcard import in
SkillDefaultswith explicit imports
v0.8.4
Quest Config
- Default quests are now auto-generated on every server start - Default quests are written to
quests/_defaults/default-quests.jsoneach time the server loads. This file is always overwritten, so default quests stay up-to-date with new mod versions without any manual steps - User quest files fully replace defaults - Create your own
.jsonfiles anywhere in thequests/folder (or subdirectories). If any user files exist, the defaults in_defaults/are ignored entirely. The generated default file remains as a reference you can copy and customize - Legacy example-quests.json automatically migrated - Servers upgrading from older versions will have their
example-quests.jsonmoved toquests/backups/automatically. No quest data is lost - 5 new default quests - Combat Initiate (kill Trorks), Builder Basics (place planks), Crafter Apprentice (craft planks), Daily Hunt (repeatable mob bounty), and Boss Bounty (defeat Trork Chieftain with manual reward claim). Total default quests increased from 3 to 8
Balance
- Reduced Max Health rewards across all skill trees by 50% - Health bonuses from skill tree rewards were too powerful, allowing high-level players to accumulate excessive health pools. All Max Health reward values have been halved across every skill (Gathering, Combat, Crafting, and Misc). Defense remains the highest health-granting skill (up to +28 at level 100, down from +55). Server owners with custom skill tree overrides are not affected
Quest UI
- Quest requirements now shown in the UI - Locked quests now display a "Requires:" line below the description showing what's needed to unlock them: prerequisite quest names, total level gates, and skill level gates. The requirements text appears in green when all requirements are met, or gray when any are unmet. Fully localized in all 9 languages
Bug Fixes
- Quest completion notification no longer references /quest command - The "quest ready to claim" notification now directs players to the Quests page instead of the removed
/quest claimcommand
Technical Details
QuestConfigrestructured:load()now runs a 4-step pipeline —migrateLegacyExampleQuests(),writeDefaultQuestsFile(), load quests (user xor defaults),buildIndex()- New
hasUserQuestFiles()method recursively checks for.jsonfiles outside_defaults/andbackups/. If any exist,loadDefaultQuests()is skipped entirely and onlyloadUserQuests()runs (all-or-nothing) - Removed
isDirectoryEmpty(),writeDefaults(),loadDirectory(). Replaced bywriteDefaultQuestsFile()(always regenerates),loadDefaultQuests()(non-recursive_defaults/scan),loadUserQuests()(recursive, skips_defaults/andbackups/).loadFile()simplified back to no parameters (no per-ID override logic needed) _defaults/default-quests.jsonincludes_noticefield warning users the file is auto-generated- All 89
STAT_HEALTHreward values inSkillTreeDefaultsreduced by ~50% across 12 skills: Mining, Woodcutting, Excavation, Harvesting, Swords, Polearms, Staves, Axes, Blunt, Defense, Crafting, and Building notify.quest_ready_to_claimlocalization key updated in all 9 languages to reference Quests UI page; removed unused{1}(questId) parameter fromMessages.get()call inQuestServiceQuestRow.ui: added#RequirementsLabelelement (hidden by default) between#QuestDescriptionand#ObjectivesContainerQuestPage.populateQuestRow(): forNOT_STARTEDquests, calls newbuildRequirementsText()method. Reads prerequisite IDs,minLevel,minSkill/minSkillLeveldirectly fromQuestDefinitionand builds a comma-separated display string via localization keys- Added 4 localization keys (
ui.quests.requires_label,ui.quests.req_complete_quest,ui.quests.req_total_level,ui.quests.req_skill_level) to all 9 language files
v0.8.3
Improvements
- Underscore delimiter for boost commands -
/mmoboost giveand/mmoboost globalnow accept underscores as an alternative to pipes for separating arguments (e.g.,/mmoboost give Ziggfreed_mining_2_30instead of/mmoboost give Ziggfreed|mining|2|30). Pipes still work as before
v0.8.2
Admin Dashboard
- Leaderboard toggle - Server owners can now show or hide the Leaderboard tab from the admin dashboard. When disabled, the Leaderboard tab is hidden from all sidebar pages (Skill Overview, Boosts, Quests) and players cannot navigate to it. Found in General Settings alongside the existing Quests toggle
- Reset to Defaults warning - The admin dashboard now shows a prominent warning before resetting to defaults, reminding server owners to back up their overrides first
Bug Fixes
- Fixed orphaned stat bonuses persisting after skill tree changes - When an admin removed or changed a skill tree reward while players were offline, those players could retain phantom health, stamina, or mana bonuses on their next login. Offline players now receive full reward validation on reconnect regardless of whether the change was to XP config or the skill tree
- Fixed stat bonuses not updating during live skill tree edits - Editing skill tree rewards via the admin dashboard or
/mmoconfig reloadnow fully refreshes stat bonuses for all online players. Previously, changing a reward's type or removing a reward could leave stale health, stamina, or mana bonuses applied - Stat bonuses are now cleared on disconnect - Health, stamina, and mana bonuses from skill tree rewards are stripped when a player disconnects. On reconnect, only rewards that still exist in the current config are reapplied. This prevents stale stat modifiers from carrying over if the skill tree is edited between sessions
Technical Details
- Added
enableLeaderboardboolean toSkillConfig(defaulttrue), with getter/setter, save/load, andreloadDefaults()reset AdminConfigPage: new#LeaderboardRowtoggle in UI,#ToggleLeaderboardevent binding, andtoggleLeaderboardaction handlerViewXpPage,BoostPage,QuestPage:#TabLeaderboardset toVisible: falsein UI files; Java conditionally shows tab and guards action handler withisLeaderboardEnabled()check- Added
ui.admin.leaderboard_labellocalization key to all 9 language files AdminConfigPage.ui: added#WarningLabelwith red warning text above the Reset to Defaults buttonSkillService.validateOnReady()andprocessTrigger(): expandedif (configChanged)guard toif (configChanged || skillTreeConfigChanged)soSkillTreeService.validateAllRewards()→cleanupOrphanedRewards()runs for offline players after skill tree config changes (previously only ran for XP config changes)SkillTreeService.removeAllStatModifiers(): new method (two overloads —Store/RefandHolder) that iterates all claimed rewards and removes health, stamina, and mana modifiers fromEntityStatMapMMOSkillTreePlugin: registeredPlayerDisconnectEventhandler that callsremoveAllStatModifiers()on disconnect. TriesRef/Storepath first (playerRef.getReference()), falls back toHolderpath (playerRef.getHolder()) when the player is between worldsSkillTreeOverridesPage.revalidateOnlinePlayers()andMMOConfigCommand.validateAllOnlinePlayers(): addedremoveAllStatModifiers()call beforevalidateAllRewards()+reapplyStatRewards()for a clean-slate approach — strips all stat modifiers first, then only reapplies valid ones
v0.8.1
Bug Fixes
- Fixed crash when opening Quest page in a new world - Opening the Quest page before performing any quest-tracked action caused a server error. Players with no quest data (new world or first join) can now browse and accept quests immediately
- Fixed quest JSON files using unicode escapes - Generated quest files wrote
\u003dinstead of=and\u0027instead of'in reward commands, making manual editing confusing. Quest files are now written with clean, human-readable characters - Fixed boost quantity flag only awarding one token - Using
/mmoboost givewith--quantity=greater than 1 could silently discard all but one token. Multiple tokens created in rapid succession shared the same internal ID, causing each to overwrite the previous one. Token IDs are now unique regardless of creation speed - Renamed admin quest command from
/queststo/mmoquestadmin- Follows the existingmmoprefix naming convention (/mmoconfig,/mmoboost,/mmoadmin). Avoids conflicts with other mods that may register/quests - Default XP notification threshold raised to 3 - New players no longer see notifications for every 1 XP gain. The default minimum XP threshold for notifications is now 3, reducing chat spam from low-XP actions. Existing players keep their current setting
Technical Details
QuestService.canAcceptQuest(): changedquestsparameter from@Nonnullto@Nullable. When null (noQuestComponenton entity), prerequisites block acceptance, level/permission gates still apply, quest state checks are skipped (player has no quest history)QuestConfigandPendingQuestRewardStore: addeddisableHtmlEscaping()toGsonBuilderto prevent Gson's default HTML-safe encoding of=,<,>,&,'- Fixed
mining_beginnerdefault quest displayText mismatch:amount: 50but text said "Mine 150 Stone blocks" — corrected to "Mine 50 Stone blocks" BoostToken.create(): token ID generation changed fromSystem.currentTimeMillis()suffix toUUID.randomUUID()(first 8 chars). The millisecond-resolution timestamp caused ID collisions whenawardToken()was called in a tight loop, and since tokens are stored in aMapkeyed by ID, duplicates silently overwrote each otherQuestCommand: constructor changed fromsuper("quests", ...)tosuper("mmoquestadmin", ...). Updated Javadoc and all 9 language files (usage strings)MMOSkillTreePlugin: addedholder.ensureAndGetComponent(QuestComponent.TYPE)inPlayerConnectEventhandler, matching the existingSkillComponentpattern. Guarantees QuestComponent exists on every player from connect, eliminating null checks in QuestPage and QuestService for new players
v0.8.0
Data-Driven Quest System
- Fully configurable quests via JSON files - Define quests in
mods/mmoskilltree/quests/using JSON. Each quest has objectives, rewards, categories, prerequisites, and level requirements. An example file with 3 starter quests is generated on first run - 8 objective types - BREAK_BLOCK, PLACE_BLOCK, CRAFT_ITEM, KILL_ENTITY, DEAL_DAMAGE, PICKUP_ITEM, REACH_LEVEL, and TALK_TO_NPC. Each objective supports exact, contains, or prefix matching against target identifiers
- Quest categories - Organize quests into Main, Daily, Misc, or custom categories. Players can filter by category in the UI
- Repeatable quests with cooldowns - Mark any quest as repeatable with a configurable cooldown period. After completing and claiming, the quest resets once the cooldown expires
- Sequential objectives - Optionally require objectives to be completed in order. Only the next incomplete objective tracks progress when sequential mode is enabled
- Auto-accept and auto-claim - Quests can be set to automatically start tracking when a matching event occurs, or to auto-deliver rewards on completion without manual claiming
- Prerequisites and level gates - Quests can require other quests to be completed first, a minimum total level, or a minimum level in a specific skill before they become available
- Command-based rewards - Rewards execute server commands with
{player}and{quest}placeholders. Supports running as console or player, delayed execution, and offline queueing so players receive rewards on next login - Progress notifications - Players see a notification on every objective increment showing current progress (e.g., "Mine Stone Blocks (3/10)")
- Enable/disable toggle - Turn the entire quest system on or off from skill-config.json. When disabled, the Quests tab is hidden from all UI pages
Quest UI Page
- New Quests page accessible from the sidebar - Browse all available quests from a dedicated page with the same sidebar navigation as the Skill Overview. The Quests tab appears in the left panel when quests are enabled
- Category filter tabs - Filter the quest list by All, Main, Daily, or Misc categories
- State-based display - Each quest shows its current state with color-coded status labels: Available (orange), In Progress (blue), Ready to Claim (gold), Completed (green), or Cooldown with time remaining (gray)
- Objective progress tracking - Active quests display each objective with current/required progress counts. Completed objectives are highlighted in green
- Accept, Claim, and Abandon actions - State-appropriate action buttons on each quest row. Accept available quests, claim completed rewards, or abandon quests in progress
- Reward preview - Quest rows show a comma-separated list of reward display names so players know what they'll earn
- Smart sorting - Quests are sorted by relevance: active quests first, then ready-to-claim, then available, then on cooldown, then completed
Quest Commands
- Player command
/quest- Players can accept, claim, abandon, and check status of quests via commands./quest claim allclaims all pending rewards at once - Admin command
/quests- Server admins can reload quest config, list quests by category, give quests to players, reset quest progress, complete quests instantly, and view detailed player quest status. Supports targeting all players with* - Offline reward delivery - Quest rewards for offline players are queued to a persistent file and automatically delivered when the player next logs in
Boost Command
- Give multiple boost tokens at once - The
/mmoboost givecommand now accepts an optional--quantity=argument to award multiple tokens in a single command. Defaults to 1 if omitted
XP Token Overrides Editor
- New admin page for editing XP tokens and boost tokens - Browse and modify all 240 token definitions at runtime through a visual editor. Accessible from the admin dashboard via the new "Edit Tokens" button
- Three browsing modes - Switch between XP Tokens, Personal Boosts, and Global Boosts tabs. Each mode adapts the navigation and table columns to the token type
- Skill and category navigation - Browse tokens by skill (Mining, Swords, etc.) or by boost target category (All Skills, Gathering, Combat, Crafting). Personal boosts support both skill-specific and category-level targets
- Override any token value - Change XP amounts for flat tokens, or multiplier and duration for boost tokens. Only your customizations are saved; defaults auto-update with mod versions
- Disable individual tokens - Prevent specific tokens from being consumed without removing them entirely
- Reset to defaults - Restore any overridden token back to its default values with one click
- Trim redundant overrides - Remove overrides that match default values to keep your config clean
- Enable/disable toggle - Turn the entire token system on or off from the editor page
UI Improvements
- Boost page now has sidebar navigation - The Boosts page has been redesigned with the same left panel sidebar as the Skill Overview and Quest pages. Navigate between all sections without going back to the overview first
- Quests tab in sidebar - All pages with the sidebar (Skill Overview, Boosts, Quests) now include a Quests tab that links to the Quest page when quests are enabled
Skill Tree
- Admins can always reset skill trees - OPs and players with the
mmoskilltree.adminpermission can still reset skill tree rewards even when the "Allow Skill Tree Reset" toggle is disabled. This lets server owners lock respeccing for regular players while retaining the ability to fix issues
Bug Fixes
- Fixed leaderboard not updating after admin XP commands - Using
/setmmoxpor/bulksetxpnow immediately reflects changes on the leaderboard. Previously, XP changes from these commands were invisible on the leaderboard until the player next gained XP organically - Fixed ghost stat bonuses after reward revocation - Revoking skill tree rewards that had been renamed or removed from config could leave orphaned health, stamina, or mana bonuses on the player. These phantom modifiers are now properly cleaned up during revocation
- Fixed XP tokens not triggering full level-up effects - Consuming a flat XP token that caused a level-up now correctly fires milestone announcements, item reward notifications, and quest objective tracking. Previously only the level-up notification was shown
- Fixed combat damage tracking not identifying mob types - Damage dealt to regular mobs was not being identified by entity type, preventing DEAL_DAMAGE quest objectives and per-mob-type blacklisting from working. Mob types are now correctly resolved for all entities
- Entity blacklist now supports specific mob types - The combat XP entity blacklist (
/mmoconfig blacklist) can now block individual mob types (e.g., "hytale:trork") in addition to the existing Projectile and Deployable categories. Previously, only those two special categories could be blacklisted - Fixed player data not initializing until first action - Skill data is now created when a player connects to the server, not on their first block break or combat event. All UI pages, settings, and leaderboard entries work immediately on join. New players also receive the server's default language automatically
- Fixed Settings page becoming unresponsive - Clicking toggles or language buttons on the Settings page before skill data was initialized could leave the page stuck in a loading state. The page now refreshes correctly regardless of data availability
Technical Details
- New
quest/package:QuestComponent(ECS component, registered asmmoskilltree:quests),QuestDefinition,QuestObjective,QuestObjectiveProgress,QuestReward,QuestStateenum (NOT_STARTED, ACTIVE, COMPLETED, COMPLETED_UNCLAIMED, ON_COOLDOWN),ObjectiveTypeenum (8 types),PlayerQuestData(base64-encoded progress serialization) - New
QuestConfigsingleton: loads quests recursively frommods/mmoskilltree/quests/*.json, builds inverted index (ObjectiveType → quest/objective refs), generatesexample-quests.jsonon first run, supports hot-reload - New
QuestService: static event hooks (onBlockBreak,onBlockPlace,onCraftItem,onEntityKill,onPickupItem,onDealDamage,onLevelReached) called from all event systems.processEvent()routes events to active objectives withMatchMode(EXACT/CONTAINS/PREFIX) pattern matching, handles auto-accept, sequential objectives, and progress notifications - New
QuestRewardExecutor: executes command-based rewards with{player}/{quest}placeholder substitution,RunAs(CONSOLE/PLAYER),delayTickssupport (1 tick = 50ms via daemon thread), offline queueing viaPendingQuestRewardStore - New
PendingQuestRewardStore: file-based JSON queue atmods/mmoskilltree/pending-quest-rewards.json. Queues commands by UUID/username, drained onPlayerReadyEvent - New
MobKillEventSystem: detects player→mob kills viaDeathComponent/Damage.Source, resolves mob identifier viaModelComponent(reflection-based, cached) withDisplayNameComponentfallback, routes toQuestService.onEntityKill() - New
QuestPageextendsInteractiveCustomUIPage: sidebar layout matchingViewXpPage, category filter tabs (All/Main/Daily/Misc), state-based quest row display, accept/claim/abandon event handlers - New
QuestPage.ui,QuestRow.ui,QuestObjectiveRow.uitemplates - New
QuestCommand(admin,/quests): subcommandsreload,list,give,reset,complete,status - New
PlayerQuestCommand(player,/quest): subcommandsaccept,claim(supportsall),abandon,status BoostPagerestructured: standalone 860×990 layout replaced with 1100×1000 sidebar layout. AddedupdateTabStyles(),bindTabEvents(),hasPermissionForCategory(),isCategoryTab(),getCategoryFromTabId().BoostEventDataextended withcategorycodec field. Back button removed, replaced by sidebar tab navigationSkillConfig: addedenableQuestsboolean (default true),isQuestsEnabled(),setQuestsEnabled(). Config version unchanged (backward compatible)ViewXpPage: added#TabQuestsvisibility/binding when quests enabled- Quest hooks added to all event systems:
BreakBlockEventSystem,PlaceBlockEventSystem,CraftRecipeEventSystem,PickupItemEventSystem,CombatXpEventSystemeach call correspondingQuestService.on*()method MMOSkillTreePlugin: registersQuestComponentECS type, loadsQuestConfigandPendingQuestRewardStore, delivers pending rewards onPlayerReadyEvent, savesPendingQuestRewardStoreon shutdown- Added
LeaderboardDataStore.getInstance().updatePlayer()calls toSetXpCommand(both "all skills" and "single skill" paths) andBulkSetXpCommand(per-target loop) afterMMOSkillTreeAPI.setXp() SkillTreeService.validateAndRevokeRewards(): whengetChoiceById()returns null during tier revocation,removeOrphanedStatModifiers()is now called to clean up stat modifiers beforeclearClaimedRewardsForTier()wipes the component data.revokedCountnow increments regardless of whether the reward still exists in config- Extracted
SkillService.handleLevelUp()consolidatingnotifyLevelUp(),checkMilestoneAnnouncement(),checkAndNotifyItemRewards(), andQuestService.onLevelReached().addXp()refactored to call it.XpTokenConsumeInteraction.processFlatXpToken()now callshandleLevelUp()instead of onlynotifyLevelUp() SkillTreePage.build(): reset button visibility check now includesPermissionUtil.hasAdminPermission(player)bypass whenisAllowSkillReset()is falseBoostCommand: addedOptionalArgviaquantityArg withOptionalArg("quantity", ...). Parsed inexecuteAsync()with validation (>= 1, defaults to 1).handleGive()andgiveTokenToAllPlayers()loopawardToken()quantitytimes per target- New
XpTokenOverridesPageextendsInteractiveCustomUIPagewithTokenTypeTabenum (XP_TOKENS, PERSONAL_BOOSTS, GLOBAL_BOOSTS) for three-mode navigation - New
XpTokenOverridesPage.ui(950×700) andXpTokenRow.uirow template matching existing admin page styling XpTokenConfig: addedsetOverride(),setDisabled(),removeOverride(),hasOverride(),getDefaultDefinition(),setEnabled(),trimRedundantOverrides()public methodsAdminConfigPage.java+.ui: added#EditTokensBtnwith"editTokens"action binding- Added ~20
ui.quests.*localization keys, 1notify.quest_objective_progresskey,ui.admin.edit_tokens, andui.xptokenoverrides.titleto all 9 language files CombatXpEventSystem.getEntityType(): addedreadMobIdentifier()fallback after Projectile/Deployable archetype checks. UsesModelComponent(reflection-based method resolution) withDisplayNameComponentfallback — same pattern asMobKillEventSystem. Returns actual entity identifier (e.g.,"hytale:trork") instead ofnullfor regular mobs, enabling both DEAL_DAMAGE quest tracking and per-mob-type blacklistingMMOSkillTreePluginPlayerConnectEvent handler:Holder.ensureAndGetComponent(SkillComponent.TYPE)now creates the SkillComponent on connect instead of deferring toSkillService.processTrigger()on first action. Also sets default language viaSkillConfig.getDefaultLanguage()for new players with no language preferenceSettingsPage.handleDataEvent(): null SkillComponent fallback now refreshes the page viaopenCustomPage()instead of silently returning, preventing the UI from getting stuck in a loading state
v0.7.9
UI Improvements
- Item Rewards page now shows 5 cards per row - Reward cards are more compact, fitting an extra column so you can see more rewards at a glance without scrolling
Bug Fixes
- Fixed empty display names on reward cards - Rewards with localization keys that resolved to empty strings now properly fall back to the configured display name, then to auto-derived names from the item ID. Fixes blank titles on XP token and boost token reward cards
- Fixed command reward display name resolution - The fallback logic now correctly handles empty localization results instead of treating them as valid resolved names
Localization
- Boost target names are now fully localized - Boost descriptions, activation notifications, and the XP page boost summary now show skill/category names in the player's language instead of hardcoded English
- Global boost broadcast uses server default language - The server-wide boost activation announcement now uses the configured default language instead of always English
Item Reward Balance
- Added Void Leather to level 65 milestone rewards - Void Leather is now included at level 65 for Harvesting (x3), Daggers (x2), Archery (x2), Unarmed (x2), Block (x3), Acrobatics (x2), and Crafting (x2)
Technical Details
- Added
resolveDisplayName()helper toItemRewardsPage— tries localization key first, falls back todisplayName, handles empty strings fromLocalizationConfig.get() - Fixed
Messages.getCommandRewardDisplayName(): added!resolved.isEmpty()check alongside!resolved.equals(key), sinceLocalizationConfig.get()returns""for missing keys (not the key itself) - Added
XpToken_andBoostToken_prefix parsing toformatItemName()in bothItemRewardsPageandCommandRewardsDefaults - Added
Ingredient_Leather_Void→ "Void Leather" mapping toformatItemName()andgetItemColor()(COLOR_VOID) inCommandRewardsDefaults - Added
Messages.getBoostTargetName()/getBoostTargetNameForLang()— resolvesBoostTargetto localized name usingboost.target.all_skills,skill.*, orui.viewxp.category.*keys - Added
ui.boosts.desc_active,ui.boosts.desc_duration,ui.boosts.scope_globallocalization keys to all 9 language files BoostPage.java: replacedgetDisplayDescription()/getDisplayName()calls with localized equivalents usingMessagesViewXpPage.java: active boost target names now useMessages.getBoostTargetName()instead ofBoostTarget.getDisplayName()XpTokenConsumeInteraction.java: boost token consumption notification now uses localized target nameXpBoostService.broadcastGlobalBoostActivated(): now usesSkillConfig.getDefaultLanguage()instead of hardcoded"en"RewardCard.ui: card dimensions reduced from 228×110 to 186×95, padding 10→8, claim button 80×24→68×22, qty label width 40→32RewardCardRow.ui: row height reduced from 118 to 103ItemRewardsPage.java:CARDS_PER_ROWchanged from 4 to 5
v0.7.8
Bug Fixes
- Fixed combat XP exploit from non-hostile mobs - Players could farm combat XP by attacking passive creatures. Combat offense XP (Swords, Axes, Archery, etc.) is now only awarded when dealing damage to hostile entities
- Fixed XP token milestone rewards not giving items - XP tokens awarded at skill levels 25, 50, 65, 80, and 100 were using an incorrect item ID (e.g.,
XpToken_mining_Fragmentinstead ofXpToken_Mining_Fragment), causing the/givecommand to fail silently. Tokens now resolve correctly for all 16 skills - Fixed reward card display for XP tokens - XP token rewards on the Item Rewards page now show their proper display name (e.g., "Fragment XP Token") instead of raw placeholder text
- Fixed milestone announcement skill names - The
{skill}placeholder in announcement commands now uses the proper display name (e.g., "Mining") instead of the lowercased enum name ("mining") - Removed Woodcutting Fragment craft recipe - The craftable Woodcutting XP Fragment has been removed
New XP Defaults
- Added Emerald, Sapphire, Cinder, and Ruby weapon XP values - All gem-tier weapon variants now have default XP values for Swords, Daggers, Battleaxes, Axes, Maces, and Bows. Regular gem weapons match Adamantite-tier XP, Uncommon gem weapons match Iron-tier XP. Adds support for the Emerald Armor, Sapphire Armor & Weapons, and Ruby Armor & Weapons mods
Technical Details
- Added
HostilityUtilinutil/— checks NPC hostility via the BlackboardAttitudeView. Uses reflection to resolvegetAttitude*method at runtime (cached after first call) for forward-compatibility with server builds. Returnsfalse(non-hostile) if the entity has no blackboard or attitude data CombatXpEventSystem.handle(): deal-damage XP path now callsHostilityUtil.isHostileTowards(store, targetRef, attackerRef)after the blacklist check. PvP (target is a player) bypasses the hostility gateCommandExecutor.processPlaceholders():{skill}now resolves viaSkillType.fromString(skill).getDisplayName()instead ofskill.toLowerCase(). Falls back to lowercase for unrecognized stringsItemRewardsPage.parseGiveCommand(): checksreward.hasDisplayInfo()before falling back to parsing the item ID from the raw command string. AcceptsSkillComponentparameter for localized display names
v0.7.7
Consumable XP Token Items
- New item-based XP tokens - Physical items that players consume (hold-to-use) to instantly gain XP in a specific skill. Available in 8 tiers from Fragment (100 XP) to Artifact (500,000 XP), each for all 16 skills — 128 token variants total
- Boost token items - Consumable items that activate timed XP multipliers. 100 personal variants (5 tiers across 20 targets) and 12 global variants (3 tiers across 4 categories) — 112 boost token variants total
- 235 new items - Every skill × tier combination has its own item with unique name, description, and quality tier (Common, Uncommon, Rare, Epic)
- Hold-to-consume mechanic - Tokens use a charging interaction: hold right-click to consume, interrupted if you take damage
- Flat XP bypasses boosts - XP token grants are raw XP that won't be multiplied by active boosts, preserving their intended value
- Boost tokens use existing boost system - Boost items activate through the same pipeline as
/mmoboost, respecting stacking limits and expiration - XP tokens as milestone rewards - Skills now award XP tokens at levels 25, 50, 65, 80, and 100 as part of item rewards
- Craftable Woodcutting Fragment - The Woodcutting XP Fragment can be crafted at a Workbench using 200 wood, 2 light leather, and 2 iron bars
- Server-configurable - Override XP amounts, multipliers, durations, or disable specific tokens via
mods/mmoskilltree/xp-tokens.json. Only customizations are stored (override-based config)
Technical Details
- New data types:
XpTokenType(FLAT_XP, TIMED_BOOST),XpTokenTier(8 flat tiers),BoostTokenTier(5 boost tiers),XpTokenDefinition(immutable item-to-behavior mapping withwithOverrides()copy method) XpTokenDefaultsgenerates all 235 definitions via loops overIMPLEMENTED_SKILLS(16 skills) × tiers, plus category/skill boost targets × scopes. Count is 235 not 240 because "Crafting" overlaps between categories and individual skillsXpTokenConfigsingleton: override-based config atmods/mmoskilltree/xp-tokens.json(schema v1). Storesenabled,chargeDurationTicks, per-tokenOverrideEntry(nullable xpAmount, multiplier, durationMinutes, disabled). Merges defaults + overrides at load timeXpTokenConsumeInteractionextendsSimpleInstantInteraction: registered as"mmo_xp_token_consume"viagetCodecRegistry(Interaction.CODEC). OnfirstRun(): resolves held item ID →XpTokenDefinition, dispatches toprocessFlatXpToken()orprocessBoostToken(). Consumes held item viaplayer.getInventory().getHotbar().removeItemStack(held)- Flat XP path:
skills.add(skillType, xpAmount)directly (bypassesSkillService.addXp()multipliers), manual level-up detection via before/after comparison, callsSkillService.notifyLevelUp()andSkillTreeService.checkMilestones() - Boost path: creates temporary
BoostToken, stores inskills.getBoostTokens(), callsXpBoostService.activateToken(), removes token on failure (limit reached) - 235 item JSONs in
Server/Item/Items/Consumables/XpTokens/using vanilla quality strings (Common, Uncommon, Rare, Epic) and Charging → mmo_xp_token_consume interaction chain MMOSkillTreePlugin.setup(): loadsXpTokenConfigafterCommandRewardsConfig, registersXpTokenConsumeInteractioncodecCommandRewardsDefaults: addedgiveXpToken(tier, qty)andgiveBoostToken(target, scope, tier)factory methods using{skill}placeholder; added token rewards togetGlobalSkillDefaults()at levels 25/50/65/80/100- Added 6 localization keys to all 9 language files:
notify.xptoken.consumed_flat,notify.xptoken.consumed_boost,notify.xptoken.consumed_boost_global,notify.xptoken.disabled,notify.xptoken.boost_limit,notify.xptoken.not_recognized
v0.7.6
Skill Card Improvements
- Color-coded buff labels - Claimed tree buffs on each skill card now display as individually colored labels instead of plain gray text. Colors match the buff type: red for damage, blue for defense, orange for crit, green for lifesteal, purple for mana, and more
- Tier progress and metadata - Each skill card now shows a metadata line below buffs with tier progress (e.g., "Tier 4/10"), XP bonus, and luck percentage. The Total Level card aggregates tier progress across all skills
- Fixed boost button always showing active style - Skill cards with only unused boost tokens now correctly show a muted gray "Boosts" button instead of the bright yellow active style. Active boosts still display with yellow styling and the "+X%" label
Mastery Cape Updates
- Master Cape stat boost - The Master Cape now provides 20% physical and projectile damage resistance (up from 18%) and 5% damage enhancement across all attack types (up from 4%), solidifying its position as the best cape in the game
- New cape models - The Master Cape, Swords Cape, and Woodcutting Cape now have unique custom models
- Updated cosmetic slot - All mastery capes now use the "Back" cosmetic slot for proper model display
Milestone Announcement Commands
- Configurable level milestone announcements - Server owners can now run a command when players reach configurable level milestones (default: 10, 25, 50, 75, 100). Great for broadcasting achievements to the whole server via
/sayor triggering custom rewards - Admin UI controls - New section in the admin dashboard to enable/disable announcements, set milestone levels (comma-separated), and customize the command template
- Default command:
say {player} has reached level {level} in {skill}! - Supports placeholders:
{player},{level},{skill},{total_level}
Admin Dashboard Improvements
- Streamlined admin layout - The config overrides display section has been removed from the admin dashboard. Editor buttons (Edit XP Maps, Edit Rewards, Edit Skill Tree) are now in the Actions bar for quicker access
- Trim Overrides moved to editor pages - The "Trim Overrides" button now lives directly on the XP Overrides and Skill Tree Overrides pages, where it's most relevant. XP trimming also covers luck overrides
Online Status Privacy
- Players can hide their online status - New "Show Online Status" toggle in Settings lets players choose whether other players can see them as online on the leaderboard
- Admin bypass - Server admins (OP or
mmoskilltree.admin) always see true online status regardless of player privacy settings - Default: enabled (visible to all, same behavior as before)
Item Reward Balance
- Reduced ore and bar quantities across all milestone rewards - All metal bar rewards (Iron, Copper, Bronze, Cobalt, Adamantite, Thorium, Mithril, Onyxium, Prisma) have been reduced by approximately 50% across all per-skill and total level milestones. Weapons, essences, gems, capes, and boost rewards are unchanged
Technical Details
- Halved all
Ingredient_Bar_*quantities inCommandRewardsDefaults.javaacross all 16 per-skill methods andgetTotalLevelDefaults(). Non-bar rewards (essences, gems, weapons, tools, armor, capes, storm materials, voidheart, chitin, boosts) unchanged - Added
enableMilestoneAnnouncements(boolean),milestoneAnnouncementLevels(List\), milestoneAnnouncementCommand(String) toSkillConfigwith getters/setters, load/save/reloadDefaults support, andConfigDatafields (no config version bump — new fields use defaults when missing) - Added
checkMilestoneAnnouncement()inSkillService.addXp()after level-up detection; checks enabled flag, milestone list membership, processes placeholders viaCommandExecutor.processPlaceholders(), and executes viaCommandExecutor.executeAsConsole() - Added
#MilestoneAnnounceRow,#MilestoneLevelsField,#MilestoneCommandField,#ApplyMilestoneBtn,#MilestonePlaceholderstoAdminConfigPage.ui; increased#SettingsSectionheight 372 → 580 - Wired
AdminConfigPage.java:milestoneLevelsInput/milestoneCommandInputinstance vars,AdminConfigEventDatacodec fields, toggle/apply handlers, text field bindings, reload/reset sync - Added
showOnlineStatusboolean toSkillComponent(field, codec, default/full constructors, clone, getter/setter) - Added
hideOnlineStatusfield toLeaderboardDataStore.PlayerLeaderboardData, set inupdatePlayer()from!skills.getShowOnlineStatus() LeaderboardPage.gatherPlayerData()now acceptsviewerIsAdminparameter; filtersisOnlinefor cached players withhideOnlineStatus=truewhen viewer is not admin- Added
#OnlineStatusSettinggroup toSettingsPage.uiafter#CombatEffectsSetting; wired toggle inSettingsPage.javawith"toggleOnline"handler that updates SkillComponent and leaderboard cache - Added 6 localization keys to all 9 language files:
ui.admin.milestone_announce_label,ui.admin.milestone_levels_label,ui.admin.milestone_command_label,ui.admin.milestone_placeholders,ui.settings.online_status,ui.settings.online_status_desc - Removed
#OverridesSectionfromAdminConfigPage.ui(override counts display and trim/editor buttons); moved#EditXpBtn,#EditRewardsBtn,#EditSkillTreeBtninto#ActionsSectionas a second row - Moved trim functionality out of
AdminConfigPage:XpOverridesPagetrims XP + luck overrides,SkillTreeOverridesPagetrims skill tree overrides; added#TrimBtnto both.uifiles and event bindings/handlers in Java - Removed
countXpOverrides()method and unused imports (XpMapsConfig,LuckConfig,SkillTreeConfig,SkillType) fromAdminConfigPage.java - Cape_Master.json: Physical/Projectile DamageResistance 0.18 → 0.20, Light/Charged/Signature DamageClassEnhancement 0.04 → 0.05
- All 17 cape JSON files:
CosmeticsToHidechanged from["Overtop", "Cape"]to["Back"]for new model system - Fixed
card.hasActiveBoost = card.showBoostBtn→card.hasActiveBoost = hasPersonalBoostinbuildSkillCard()to match the total card's boost logic - Added
BuffEntryinner class (text + color) andgetRewardColor(RewardType)static method with per-type color mapping - Replaced
getSkillBuffsText()→getSkillBuffEntries()returningListwith color data - Changed
SkillCardData.buffsText(String) →buffEntries(List) and added metaTextfield populateSkillCard()now dynamically appendsCardBuffLabel.uitemplates into#CardBuffsRowwith per-label color viacommandBuilder.append()- New
CardBuffLabel.uitemplate: minimal colored label for dynamic buff row population - Updated
SkillCard.ui: replaced#CardBuffsTextLabel with#CardBuffsRowGroup (LayoutMode: Left), added#CardMetaTextLabel (9pt,#7a8a9e) buildSkillCard()computes metadata viaskills.getClaimedTierCount(),SkillTreeService.getActiveRewardsForSkill()for XP bonus and luckbuildTotalLevelCard()now acceptsSkillTreeConfigparameter and aggregates tier counts across all filtered skills
v0.7.5
Skill Cards Grid Layout
- Skill overview redesigned as a card grid - The skill list on the main XP page now displays as a grid of cards (3 per row) instead of flat rows. Each card shows skill name, level, progress bar, XP, claimed buffs, and next reward hint at a glance
- Total Level card in overview - A special summary card appears first when viewing all skills, showing your combined level, total XP, and aggregate buffs across all skills. Distinguished by a blue accent background
- Quick-action buttons on every card - Each card can show up to three buttons depending on context:
- Skill Tree - Opens the skill tree for that skill (shows "Reward Ready!" in orange when unclaimed rewards are available)
- Rewards - Opens the item rewards page filtered to that skill (visible when skill or global rewards are configured)
- Boost - Shows current boost percentage and opens the boost page (visible only when an active boost applies)
- Category color coding - Each card has a colored accent strip matching its category: green for Gathering, red for Combat, orange for Crafting, purple for Misc
- Total Level rewards button - The Total Level card includes a Rewards button that opens item rewards in total level mode when total level rewards are configured
Bug Fixes
- Fixed Storm Hide and Storm Leather item reward IDs - Corrected the item IDs to match the game's naming convention, so Storm materials now appear correctly when claimed
Admin Config: Skill Tree Reset Toggle
- New "Allow Skill Tree Reset" toggle in the admin dashboard - Server owners can now disable the skill tree reset button for all players. When turned off, the Reset button is completely hidden from the skill tree page, preventing players from respeccing their reward choices
- Toggle is located in the General Settings section of
/mmoadmin, between Item Rewards and Default Language - Default: enabled (players can reset as before)
- Saves automatically when toggled, like other admin settings
Technical Details
- Added
allowSkillResetboolean toSkillConfig(field,ConfigData, load/save/reloadDefaults(), getter/setter), bumpedCONFIG_VERSION10 → 11 - Added
#SkillResetRowwith#SkillResetLabeland#ToggleSkillResettoAdminConfigPage.ui, increased#SettingsSectionheight 336 → 372 - Wired toggle in
AdminConfigPage.java: label fromui.admin.skill_reset_label, event binding for"toggleSkillReset"action, handler flips config value SkillTreePage.javaenforces config: whenisAllowSkillReset()is false, sets#ResetButton.Visible = falsebefore the existing claimed-count check- Added
ui.admin.skill_reset_labellocalization key to all 9 language files - Fixed Storm material item IDs in
CommandRewardsDefaults:Ingredient_Storm_Hide→Ingredient_Hide_Storm,Ingredient_Storm_Leather→Ingredient_Leather_Storm; updatedformatItemName()andgetItemColor()matchers - Replaced
SKILL_ROW_TEMPLATE(SkillRow.ui) withSKILL_CARD_ROW_TEMPLATE(SkillCardRow.ui) andSKILL_CARD_TEMPLATE(SkillCard.ui),CARDS_PER_ROW = 3 - New
SkillCardRow.uitemplate: horizontal row container (LayoutMode: Left, Height: 210) - New
SkillCard.uitemplate: 270x200px card with#CategoryStrip,#CardSkillName,#CardLevel,#CardProgress(ProgressBar),#CardXpText,#CardBuffsText,#CardHintText, and#ButtonsRowcontaining#TreeBtn,#RewardsBtn,#BoostBtnwith spacer groups - New
SkillCardDatainner class inViewXpPageholds all display state for one card (name, level, progress, xp, buffs, hint, categoryColor, backgroundColor, button visibility flags, skill reference, isTotalCard flag) - New methods:
getCategoryColor(SkillCategory),buildTotalLevelCard(),buildSkillCard(),populateSkillCard()replace the inline skill row loop - Build method now constructs a
List, chunks into rows of 3, appends row and card templates, then populates each card - New
"skillRewards"action handler inhandleDataEvent(): routes"TOTAL"toItemRewardsPage(playerRef, MINING, true), otherwise opensItemRewardsPage(playerRef, skill)for the specific skill - Existing
ViewXpEventDatacodec reused unchanged (action/skill/category fields)
v0.7.4
Skill Tree Admin Editor
- New in-game Skill Tree editor - Server owners can now customize skill tree reward tiers directly from the admin panel. Open
/mmoadminand click "Edit Skill Tree" to browse skills by category, view all tiers, and modify individual rewards - Override-based customization - Changes are saved as overrides on top of defaults. Only your modifications are stored, so new default rewards from updates propagate automatically without losing your customizations
- Per-tier editing - Select any tier to view its rewards, edit values, add new rewards, remove rewards, or adjust level requirements and choice counts
- Disable or reset tiers - Disable entire reward tiers or reset them to defaults with one click
- Status indicators - Color-coded tier buttons (green = default, orange = overridden, red = disabled) and per-reward status labels (Default, Modified, Added) show exactly what's been customized
- Trim redundant overrides - The existing "Trim Redundant" button on the admin page now also cleans up skill tree overrides that match defaults
- Automatic migration - Existing
skill-tree.jsonfiles from previous versions are automatically detected and migrated, with a backup saved
Technical Details
- Converted
SkillTreeConfigfrom traditional full-regeneration to override-based storage pattern (dualskillTrees+skillTreeOverridesmaps) - New config format uses
schemaVersion: 1with per-skill per-tier override granularity; legacy V4 format auto-detected viaconfigVersionfield and migrated with diff comparison against code defaults - Added override query API:
isDefault(),isTierDisabled(),getOverrides(),getDefaultNode(),countTotalOverrides() - Added override mutation API:
setTierOverride(),disableTier(),removeTierOverride(),trimRedundantOverrides() - Reference file written to
_reference/defaults-skill-tree.jsonshowing all code defaults - New
SkillTreeOverridesPage.javawithSkillTreeOverridesEventDatacodec (13 fields), category/skill/tier navigation, reward list with template rows, and add/edit/remove/disable/reset actions - New UI templates:
SkillTreeOverridesPage.ui(1100x700),SkillTreeRewardRow.ui(row template) - Updated
AdminConfigPagewith#EditSkillTreeBtnbutton, skill tree override count display, and trim integration - Localization keys added to all 9 language files:
ui.admin.edit_skill_tree,ui.skilltreeoverrides.title - Internal
NodeDataandRewardDataclasses changed fromprivateto package-private forrewardsMatch()access
v0.7.3
Level 100 Mastery Boost Upgrade
- Mastering a skill now rewards a global XP boost token - Reaching level 100 in any skill now awards a 1.25x All-Skill Global XP Boost (30 min) token instead of the previous personal skill-specific boost. When activated, this boost benefits every player on the server across all skills
- Celebrating mastery is now a server-wide event - your achievement helps everyone!
Item Rewards Page Overhaul
- Fixed reward claiming not targeting the correct reward - Claim buttons now reliably trigger the correct reward. The rewards page has been rebuilt with a card grid layout where each reward has its own dedicated claim button
- Rewards are now grouped by level - Clear level separators (e.g., "Level 10", "Level 25") divide rewards into tiers, making it easier to find what you've unlocked
- Card-based layout - Rewards display as compact cards in rows of up to 4, showing item name, quantity, status, and claim button at a glance
- Reward descriptions - Server owners can now add optional description text to item rewards in
mods/mmoskilltree/command-rewards.jsonusing the"description"field. Descriptions appear below the item name on reward cards - Existing configs without descriptions continue to work unchanged
Storm Leather & Storm Hide Rewards
- New rare crafting materials added to item rewards - Storm Leather and Storm Hide now appear in milestone rewards for skills where leather and hide materials are thematically relevant
- Available at levels 80 and 100 for Defense, Daggers, Archery, Acrobatics, Unarmed, Harvesting, and Crafting
- Total Level milestones include Storm materials at levels 350, 500, 750, and 1000
- Defense gets the highest quantities as the armor skill
Item Reward Balance Adjustments
- Reduced Total Level 350 rewards - Material quantities cut roughly in half (Mithril/Onyxium 75 to 35, essences 50 to 25, etc.) and boost reduced from 2x 45m to 1.5x 30m to better match the progression stage
- Master Cape moved to Total Level 1500 - The Master Cape is now awarded at Total Level 1500 instead of 1000, making it a true long-term goal
Rewards Editor Improvements
- Click any reward to edit it - Clicking a reward entry in the admin Rewards Editor copies its command, display name, localization key, and color into the input fields for editing
- Saving updates existing rewards - If you edit a reward and save, it replaces the original entry (matched by command string) instead of adding a duplicate
Technical Details
- Replaced
boostSkill_2x_30m()(personal, single-skill, 2x, 30min) withboostGlobal_1_25x_30m()(global, all-skill, 1.25x, 30min) in all 16 skill level 100 reward defaults inCommandRewardsDefaults.java - Added
boostGlobal_1_25x_30m()factory method - Existing Global Skill milestone reward (1.25x Global 15min at level 100 in
getGlobalSkillDefaults()) remains unchanged and stacks with the per-skill reward - Added
COLOR_STORM(#5599dd) constant,formatItemName()andgetItemColor()handlers forIngredient_Storm_LeatherandIngredient_Storm_Hide - Total Level 350: reduced material quantities ~50%, removed Iron Head armor, removed Storm Hide, downgraded boost from
boostAll_2x_45m()toboostAll_1_5x_30m() - Moved
Cape_Masterfrom level 1000 tier to new level 1500 tier ingetTotalLevelDefaults()
Technical: Item Rewards Grid Layout
- Replaced
RewardTierRow.ui/RewardItem.uitemplates withRewardCard.ui,RewardCardRow.ui, andRewardTierSeparator.ui ItemRewardsPage.java: rewrotepopulateSkillRewards()andpopulateTotalRewards()to group rewards by level tier, chunk into rows of 4 cards, and populate each card individually viapopulateCard()- Added
CardDatarecord to bundle display info with claim state for grid population - Removed
populateSingleRewardItem()andgetRewardDisplayName()methods (replaced by card-based approach) CommandRewardEntry.java: addedString descriptionfield with 6-arg constructor,getDescription(),hasDescription(), builder.description()method; 5-arg constructor delegates with null descriptionCommandRewardsConfig.RewardData: addeddescriptionfield to serialization; Gson ignores missing fields on load for backwards compatibilityItemDisplayrecord: addeddescriptionas 4th field, propagated throughparseGiveCommand(),parseBoostCommand(), andparseRewardForDisplay()
Technical: Rewards Editor Click-to-Edit
CommandRewardsPage.buildRewardList(): addedActivatingevent bindings on#CommandTextand#DisplayNamelabels per row, firingselectRewardwith the row index- New
selectRewardhandler inhandleDataEvent()reads the reward at the given index and populatescommandInput,displayInput,locKeyInput,colorInput addRewardhandler now searchescurrentRewardsfor a matching command string; replaces in-place viaList.set()if found, otherwise appends- Extracted
getCurrentRewards(config)helper to reduce duplication acrossselectReward,addReward,disableReward,removeReward
v0.7.2
Bug Fixes
- Fixed skill tree stat modifiers not updating after config changes - Players who were offline during a skill tree config edit (or when the server restarted after edits) would keep outdated health, stamina, and mana bonuses from old reward values. Stat modifiers are now reconciled with current config on each player's first action after any server restart
- Fixed orphaned rewards from removed config entries - If a server owner removes or renames skill tree rewards, players who previously claimed those rewards now have the stale stat modifiers properly cleaned up on their next session
- Fixed item reward commands briefly blocking the server - Claiming item rewards with multiple items (e.g., level 100 rewards) would momentarily stall the server while commands were spaced out. Reward commands are now dispatched without blocking
Technical: Stat Modifier Reconciliation on Startup
MMOSkillTreePlugin.setup()now sets bothconfigChangedandskillTreeConfigChangedflags totrueat the end of initialization- On first skill action per player per restart,
SkillTreeService.reapplyStatRewards()removes and reapplies allSTAT_HEALTH,STAT_STAMINA,STAT_MANAEntityStatMap modifiers with current config values SkillTreeService.validateAllRewards()also runs, cleaning up orphaned rewards viacleanupOrphanedRewards()(removes modifiers for reward IDs no longer present in config)- Per-player cost is one-time iteration of claimed rewards on first action after restart; no ongoing overhead
Technical: Command Reward Execution No Longer Blocks World Thread
CommandRewardService.executeRewards()previously usedThread.sleep(25)insideworld.execute(), blocking the world thread between reward commands- Now uses
CompletableFuture.delayedExecutor()to schedule staggered commands from a background thread, dispatching each to the world thread viaworld.execute()without blocking it
v0.7.1
Mastery Cape Armor Attributes
- Skill capes now provide armor stats - Each mastery cape has unique attributes themed to its skill, making them functional gear on top of prestige cosmetics
- Damage resistance - All capes provide physical and projectile damage resistance (8-18%), surpassing Epic-tier chest armor
- Health bonuses - All capes grant bonus health (+14 to +28), scaling with the cape's combat relevance
- Combat capes include damage enhancements matching their weapon type:
- Swords: +8% Light damage | Daggers: +10% Light damage | Polearms: +10% Charged damage
- Staves: +8% Signature damage, +30 Mana | Axes: +5% Light & Charged damage
- Blunt: +8% Charged damage | Archery: +10% Charged damage | Unarmed: +10% Light damage
- Defensive capes have the highest resistance among skill capes:
- Defense: 16% Physical/Projectile, +26 Health (best pure tank)
- Acrobatics: 12% Physical, 16% Projectile, +18 Health (best projectile dodge)
- Gathering and production capes provide balanced survivability stats
- Harvesting cape also grants +30 bonus Mana
- Master Cape is the best cape - 18% Physical/Projectile resistance, +28 Health, +30 Mana, and +4% to all damage types (Light, Charged, Signature)
Technical: Cape Attribute Implementation
- Added
DamageResistance,StatModifiers, andDamageClassEnhancementblocks to all 17 cape item JSONs inServer/Item/Items/Armor/Capes/ - Stat ranges across all capes: Physical 8-18%, Projectile 8-18%, Health +14 to +28, Mana 0-30
DamageClassEnhancementused on combat capes:Light,Charged, and/orSignatureat 4-10% Multiplicative- Balance reference: base game Epic chest armor gives +24 HP / 14% resist (tank) or +17 HP / +16 Mana / 9% resist (mage); Legendary skill capes exceed both
Technical: Combat System Separation
- Split
CombatDamageEventSysteminto two separate systems for cleaner separation of concerns: -
CombatDamageEventSystem- Damage modification only (damage bonuses, defense reduction, crits, lifesteal, fall damage reduction) -
CombatXpEventSystem- XP awards only (combat XP, defense XP, acrobatics XP, entity blacklist checks) - XP system is read-only and never modifies damage amounts
- Entity blacklist logic (
getEntityType,isEntityBlacklistedForCombatXp) moved to the XP system - Both systems registered in
MMOSkillTreePluginsetup - No functional changes to combat behavior or XP awards
v0.7.0
Russian Language Support
- New language: Russian - Full Russian translation added as the 9th built-in language
- All UI text, notifications, commands, and skill tree content translated
- Select Russian in Settings like any other language
- 9 built-in languages - English, Spanish, French, Portuguese, Hungarian, Turkish, German, Italian, Russian
- Internal language system improved to make adding new languages easier in the future
- No changes to existing translations
Skill Mastery Capes
- 17 mastery capes - Cosmetic cape armor awarded for reaching level 100 in any skill (or total level 1000)
- 16 per-skill capes: Mining, Woodcutting, Excavation, Harvesting, Swords, Daggers, Polearms, Staves, Axes, Blunt, Archery, Unarmed, Block, Acrobatics, Crafting, Building
- 1 Master Cape for total level 1000
- Legendary armor stats - Each cape provides damage resistance, bonus health, and skill-themed bonuses (see v0.7.1). Equips in Chest slot, hides default cape cosmetic
- Reward-only - Not craftable; awarded automatically at level 100 through the existing command rewards system
- Custom item quality - "Mastery Cape" quality (gold text, legendary drop particles)
- Effectively indestructible - 9999 durability
- Fully localized - Cape names and descriptions in Hytale's
items.lang, reward display names in all 9 language files
Technical: Skill Capes Resource Structure
- 17 item JSON definitions in
Server/Item/Items/Armor/Capes/(shared model, per-cape textures) - Skill capes:
ItemLevel: 100, Master:ItemLevel: 200 - All use
Parent: Armor_Cloth_Wool_Head,Quality: MMO_Skill_Cape - Quality definition at
Server/Item/Qualities/MMO_Skill_Cape.json(QualityValue: 6, gold#ffaa00text) - Language files at
Server/Languages/en-US/items.langandgeneral.lang - CommandRewardsDefaults.java - Added
give()call at level 100 for each skill and total level 1000 - New
COLOR_CAPEconstant,formatItemName()andgetItemColor()handle cape IDs - 17 localization keys (
reward.cape.*) added to all 9 language default files - Art assets (model, textures, icons, quality UI) to be created separately
Technical: Localization Architecture Overhaul
- Extracted per-language defaults - Each language's default messages moved from
LocalizationConfig.javainto dedicated classes ini18n/lang/: -
LanguageDefaultsinterface (langCode(),displayName(),getDefaults()) -
EnglishDefaults,SpanishDefaults,FrenchDefaults,PortugueseDefaults,HungarianDefaults,TurkishDefaults,GermanDefaults,ItalianDefaults,RussianDefaults - Registry-based language loading -
LocalizationConfignow uses aBUILTIN_LANGUAGESregistry (LinkedHashMap) instead of hardcoded per-language methods - Reduced
LocalizationConfig.javafrom ~3,272 lines to ~377 lines - No functional changes to existing translations or file-based overrides
Default Server Language
- Server-wide default language - Server operators can now set a default language for new players
- New players inherit the server's chosen language instead of always defaulting to English
- Existing players keep their previously chosen language (only affects new players)
- CLI command -
/mmoconfig language --args=to set the default language - Validates against available (installed) languages
- Shows available language codes if invalid input is provided
- Admin UI - Language selector added to
/mmoadminGeneral Settings section - Dynamic buttons for each available language
- Current selection highlighted in green
- Config persistence - Saved in
skill-config.jsonasdefaultLanguagefield - Config version bumped to 10
- Resets to English on
reloaddefaults - Localized label - "Default Server Language" translated in all 9 language files
XP Reset Now Revokes Item Rewards
- Setting XP lower now properly resets item rewards - When using
/setmmoxpor/bulksetxpto reduce a player's XP, any claimed command rewards (items, boosts) for levels the player no longer qualifies for are now revoked - Per-skill rewards, total level rewards, and global skill rewards are all checked
- The revoked count is included in the existing "rewards revoked" message
- Previously only skill tree rewards were revoked; item milestone rewards were kept even when undeserved
Admin Rewards Editor: Custom Level Input
- Type any level number in the Command Rewards editor - A text input field with "Go" button now appears next to the level preset buttons
- Enter any level number to configure rewards at levels not in the defaults
- Selecting a preset button clears the text field for clean interaction
Bug Fixes
- Fixed Master Cape icon not loading - The Master Cape inventory icon and texture were named incorrectly (
Cape_Grandmaster) and didn't match the item definition (Cape_Master), causing missing icons in-game
Technical: Config Package Reorganization
- Moved per-skill XP defaults to
config/xpdefaults/subpackage (29 files) SkillDefaults.javaupdated with wildcard import for the new subpackage- Config managers, utilities, and top-level dispatchers remain in
config/
Technical: Command Reward Validation
- Added
validateCommandRewards()andvalidateAllCommandRewards()toCommandRewardService- parses claimed reward IDs, checks player level against each, and removes invalid claims - Added
removeCommandReward(String)toSkillComponentfor individual reward ID removal - Both
SetXpCommandandBulkSetXpCommandnow call validation after XP changes
v0.6.4
Leaderboard UX
- Hide XP column in category/total views - The "Total XP" column is now hidden when viewing Total Level, Gathering, Combat, or Production leaderboard views. XP is only shown when drilling down to a specific skill (e.g., Mining). Reduces visual clutter and keeps the focus on level rankings.
- Level breakdown in category/total views - When viewing category or total leaderboard views, each row shows a skill-level breakdown in place of the XP column (e.g., "15 Mining + 6 Woodcutting + 3 Excavation + 1 more"). Shows the top 3 skills by level with a count of remaining active skills. Applies to both leaderboard rows and the "Your Rank" section.
v0.6.3
Bug Fixes
- Fixed item reward commands not executing - Reward commands (like
/give) could fail silently when triggered from the Rewards UI. Commands now execute reliably with proper timing between multiple items. - Fixed inventory space check - Corrected the inventory storage check when claiming rewards.
Technical Details
- Reward commands dispatched via
world.execute()instead of running synchronously inside Store/UI event handlers, avoiding reentrancy issues - Multiple commands within a level staggered with 25ms delays for inventory state updates
- Fixed
getCombinedArmorHotbarStorage()→getStorage()for proper inventory space validation
v0.6.2
Inventory Space Check for Item Rewards
- Inventory space validation - Item rewards now check that you have enough inventory space before claiming
- Full inventory protection - If your inventory is full, rewards stay unclaimed so you can pick them up later
- Red notification tells you when your inventory is too full to claim
- Auto-claim respects space - Level-up auto-claim also checks inventory space, so no items are lost
- Non-item rewards unaffected - Boosts and other non-item rewards are not blocked by inventory checks
- Localized notification in all 8 languages (EN, ES, FR, PT, HU, TR, DE, IT)
Technical Details
- UI claim gating returns "inventory full" notification preserving unclaimed state
- Auto-claim paths (
checkAndExecuteRewards,checkGlobalSkillRewards,checkTotalLevelRewards,checkAllRewards) skip rewards when inventory full - Only
/givecommands are gated;/mmoboost giveand similar pass through
v0.6.1
Boost Stacking Limits
- Hard cap on total XP multiplier - New
maxBoostMultipliersetting (default: 5.0x) prevents runaway XP gains regardless of how many boosts are active - Active boost count limits - Configurable caps on simultaneous personal boosts (
maxPersonalBoosts, default: 3) and global boosts (maxGlobalBoosts, default: 3) - Stack mode selection - Choose between
"additive"(all boosts sum together) or"highest"(best global + best personal only) viaboostStackModesetting - Token preservation on limit - When a player tries to activate a boost token at the limit, the token is NOT consumed and an error message is shown
- Admin boost gating -
/mmoboost globalreturns an error when the global limit is reached instead of silently creating a boost - Boost Page UI awareness:
- Limits info line shows current state:
"Limits: 5.0x cap | additive | Personal 2/3 | Global 1/3" - Token and permission activate buttons are disabled (red "LIMIT REACHED") when the relevant limit is hit
- Admin UI section - New "Boost Stacking Limits" section in
/mmoadminwith: - Text fields for max multiplier, max personal, and max global boosts
- Toggle buttons for additive/highest stack mode
- Save button applies all changes at once
- Localized in all 8 languages (EN, ES, FR, PT, HU, TR, DE, IT)
Admin Button on XP Page
- Quick admin access - Admins now see an "Admin" tab in the
/xpsidebar, just above Settings - Opens the
/mmoadminconfiguration page directly from the skill overview - Only visible to players with
mmoskilltree.adminpermission (or OP when permissions disabled) - Server-side permission check on click prevents unauthorized access
Bug Fixes
- Fixed global boost permissions not working - Global boosts created through the Admin Award Boost UI were silently broken and never appeared. Global boost permissions now work correctly.
- Action required: Any previously awarded global boost permissions need to be re-issued. Re-award them through the Admin UI, or manually replace
.global.with.all.in existing permission entries.
Technical Details
AwardBoostPagegenerated"global"as the scope value in permission strings, butBoostScopeonly recognizes"all"for global boosts- Permissions like
mmoskilltree.xpboosts.all.global.2.30.60silently failed to parse - Now correctly generates
"all"scope (e.g.,mmoskilltree.xpboosts.all.all.2.30.60) skill-config.jsonversion 8 → 9 (auto-regenerated on first load)
v0.6.0
Command Rewards v2.0 - Schema Redesign
Major overhaul of the command rewards system with a unified schema and override-based config.
New Schema
- Unified
rewardslist - All rewards are now commands (items given via/givecommands) - Override-based config - Config stores only customizations, defaults preserved across updates
- Per-command customization:
-
localizationKey- Preferred way to set display name (supports all languages) -
displayName- Fallback literal display name -
color- Hex color for UI display (e.g.,#ffaa00) -
runAs-CONSOLE(default) orPLAYER - Display logic - Rewards without display info are executed but hidden from UI
New Config Format
{
"schemaVersion": 1,
"enabled": true,
"overrides": {
"MINING": {
"10": [
{
"command": "/give {player} Ingredient_Bar_Iron --quantity=25",
"localizationKey": "reward.item.iron_bars",
"color": "#ffaa00"
}
]
}
}
}
Override Semantics
- Missing levels use defaults automatically
- Set level to empty array
[]to disable rewards at that level - New defaults propagate without losing your customizations
- Schema version only changes for structural changes
Migration
- Automatic V4 migration - Existing configs are converted and backed up
- Claimed rewards preserved - Level-based tracking maintained across upgrade
Global Skill Rewards
- New reward category: GLOBAL_SKILL - Bonus rewards given to ALL skills at milestone levels
- Tracked per-skill: Mining 50 and Swords 50 each independently trigger level 50 global rewards
- Configurable via
GLOBAL_SKILLkey incommand-rewards.jsonoverrides - Visible in the player Rewards UI as "Lv X Bonus" rows alongside per-skill rewards
- Default: 1.25x Global XP Boost (15 min) at Level 100 for every skill mastered
XP Boost Token Rewards
- Boost tokens as milestone rewards - Level-up milestones now include XP boost tokens
- Personal skill boosts at Lv 50 (1.5x 15min) and Lv 100 (2x 30min) for each skill
- Personal all-skills boosts at Total Lv 100 (1.5x 30min) and Total Lv 350 (2x 45min)
- Global server boosts at Total Lv 500 (1.5x 30min), 750 (2x 30min), 1000 (2x 60min)
- Global boosts broadcast to all online players via
/saywhen activated
Admin Command Rewards UI
- New
CommandRewardsPage- Visual editor for command rewards, accessible from/mmoadmin - Category tabs: Gathering, Combat, Crafting, Misc, Total Level, All Skills (Global)
- Skill selector for per-skill categories, hidden for Total Level and All Skills
- Level selector showing all configured milestone levels
- Reward table with columns: Command, Display Name, Loc Key, Color, Status
- Add/Edit section with fields for Command, Display Name, Loc Key, Color
- Inline Disable button on each default reward to create override without that reward
- Remove button on overridden rewards to delete individual entries
- Disable Level to set empty override (no rewards at that level)
- Reset to Default to remove override and restore defaults
Auto-Derived Display Info
- Item rewards auto-derive display names from item IDs (e.g.,
Ingredient_Bar_Iron→ "Iron Bars") - Item rewards auto-derive tier colors from item ID patterns:
- Common materials (Iron, Copper):
#c8c8c8 - Uncommon (Cobalt, Thorium):
#4aff7f - Rare (Adamantite, Mithril):
#4a9eff - Epic (Onyxium):
#c84aff - Legendary (Prisma, Voidstone):
#ffaa4a - Gems, essences, and tools each have appropriate colors
- Rewards without explicit display info now visible in admin UI with auto-derived names
Bug Fixes
- Fixed incorrect ore XP rates - Removed explicit low-XP entries for special terrain ores (
Ore_Cobalt_Slate,Ore_Adamantite_Magma,Ore_Iron_Basalt) that overrode wildcard patterns with incorrect values (4-6 XP instead of proper ore rates) - Fixed tier label missing in player Rewards UI - localization fallback returned empty string for undefined keys, causing blank tier headers
- Fixed Visible boolean type error - Hytale CustomUI requires boolean values for Visible property, not string representations
- Fixed display name override in tier headers - Auto-derived item names no longer replace "Level X" tier labels
Technical Changes
- CommandRewardEntry.java - New unified format with command, localizationKey, displayName, color, runAs
- LevelRewards.java - New container for level -> List
mapping - CommandRewardsConfig.java - Converted to override-based pattern (like XpMapsConfig)
- Stores
userOverridesseparately from effective config - Generates
_reference/defaults-command-rewards.jsonfor server owner transparency - Changed
configVersiontoschemaVersion - Added
globalSkillRewards/globalSkillOverrideswith full getter/mutator/save/load support - CommandRewardsDefaults.java - All ItemReward definitions converted to
/givecommands - Added
formatItemName()andgetItemColor()for auto-derivation - Added
getGlobalSkillDefaults()with milestone rewards for all skills - Added boost token reward factories:
boostSkill(),boostAll(),boostGlobal() - CommandRewardService.java - Simplified to only execute commands
- Added
checkGlobalSkillRewards()for per-skill global reward tracking - Updated
checkAllRewards()to process global skill rewards - Updated
claimLevelRewards()to handleGLOBAL_SKILL_*keys - CommandRewardsPage.java (NEW) - Admin UI page for viewing/editing command rewards
- CommandRewardsPage.ui (NEW) - Admin UI template with category tabs, skill/level selectors, reward table
- CommandRewardRow.ui (NEW) - Row template with Disable/Remove inline buttons
- ItemRewardsPage.java - Shows global skill bonus rewards alongside per-skill rewards
- Added
claimGlobalaction handler for claiming global skill rewards - Fixed
getDisplayName()to not use auto-derived displayName for tier headers - Messages.java - Updated
getCommandRewardDisplayName()to take level parameter - AdminConfigPage.java - Added "Edit Rewards" button navigating to CommandRewardsPage
v0.5.11
Admin Item Rewards Toggle
- New toggle in
/mmoadmin- Enable/disable item rewards from command-rewards.json - Toggle found in the "General Settings" section
- When disabled, the Rewards tab is hidden from ViewXpPage
- Config saved immediately on toggle
UI Improvements
- Active Boosts Display - ViewXpPage now shows active XP boosts above the buffs bar
- Displays up to 3 active boosts with time remaining
- Shows scope indicator:
[G]for global boosts,[P]for personal - Global boosts shown in blue, personal in green
- Format:
[G] 2.0x Mining - 14:32(scope, multiplier, target, time)
- Skill Tree Buff Indicator - Skill tree buffs now prefixed with
[Tree] - Example:
[Tree] +15 HP +5% DMG - Helps distinguish skill tree rewards from other sources
- Improved Time Display - Boost durations and cooldowns now show human-readable formats
- Under 1 hour:
mm:ss(e.g., "45:30") - 1-24 hours:
Xh Ym(e.g., "2h 30m") - Over 24 hours:
Xd Yh(e.g., "3d 5h") - Fully localized time units for all 8 languages
Leaderboard Fix
- Total Level Calculation - Fixed leaderboard to use summed skill levels
- Previously used formula-based level from total XP (confusing)
- Now sums individual skill levels for intuitive display
- Example: Mining 50 + Woodcutting 50 = Total Level 100 (not formula result)
Technical
- AdminConfigPage.java
- Added
#ToggleItemRewardsbutton with event binding - Calls
CommandRewardsConfig.getInstance().setEnabled()on toggle
- ViewXpPage.java
- Added
populateActiveBoosts()method - Modified
getSkillBuffsText()to add[Tree]prefix - Imports:
ActiveBoost,BoostScope
- ViewXpPage.ui
- Added
#ActiveBoostsBarsection with 3 boost labels - Added
#ActiveBoostsSpacerfor spacing control
- LeaderboardDataStore.java
- Changed
data.totalLevel = skills.getTotalLevel()todata.totalLevel = skills.getSummedTotalLevel()
- LocalizationConfig.java
- Added
ui.admin.item_rewards_labelin all 8 languages - Added
time.days_short,time.hours_short,time.minutes_shortfor localized time units - Added
notify.command_reward_receivedin all 8 languages
- XpBoostService.java
- Updated
formatTimeRemaining()to showXh Ymfor hours,Xd Yhfor days - Added localized overload
formatTimeRemaining(ms, skills)using language-specific time units
- CommandExecutor.java
- Added overload
executeAsConsole(command, username)for better logging context
- CommandRewardService.java
- Now passes username to console command execution for logging
v0.5.10
New Command: `/bulksetxp`
- Bulk XP command - Set XP for one, many, or all players at once
- Usage:
/bulksetxp[targets] - Targets: Single player name, comma-separated names, or
*for all online players - Examples:
-
/bulksetxp mining 1000- Set all players to 1000 mining XP -
/bulksetxp all 0 Player1- Reset all skills to 0 for Player1 -
/bulksetxp swords 5000 A,B,C- Set swords to 5000 for specific players - Aliases:
setxpall,masssetxp - Admin permission required
Command Architecture Update
- Async command pattern -
/mmoboostand/bulksetxpnow useAbstractAsyncWorldCommand - Better console support - commands work reliably from console
- Uses
withDefaultArgfor optional parameters (cleaner syntax) - Store operations properly dispatched to world thread via
world.execute()
- Simplified
/mmoboostsyntax - Removed--args=prefix - Old:
/mmoboost give --args=Steve|mining|2|30 - New:
/mmoboost give Steve|mining|2|30 - Still uses
|(pipe) to separate values
Technical
- BulkSetXpCommand.java - New command extending
AbstractAsyncWorldCommand - Uses
withDefaultArg("targets", ...)with default*for all players - Store access via
entityRef.getStore()insideworld.execute()callback - Validates rewards after XP change (revokes if level dropped)
- Reports success count and any failures
- BoostCommand.java - Refactored to
AbstractAsyncWorldCommand - Changed from
AbstractPlayerCommandtoAbstractAsyncWorldCommand - Uses
withDefaultArginstead ofwithOptionalArg - Subcommands needing Store access (
give,clear,status) wrapped inworld.execute() - Subcommands without Store access (
global,list) run directly - Simplified message handling (direct strings instead of localization for admin commands)
- CLAUDE.md - Documented async command pattern
- Added "Command Patterns" section explaining
AbstractAsyncWorldCommandvsAbstractPlayerCommand - Critical pattern:
world.execute()required for Store operations in async context - Store thread affinity causes
IllegalStateExceptionif accessed from wrong thread
- hytale-api.md - Added "Async Commands & World Thread" section
- Documents the thread safety requirement for Store access
- Code examples showing wrong vs right approach
-
world.execute(Runnable)dispatches work to world thread
v0.5.9
Skill Permission Filtering
- Permission-based skill visibility - When skill permissions are enabled, skills are now filtered throughout the UI
- Skills without permission are hidden from the XP overview page
- Skills without permission are excluded from total/category level calculations
- Navigation in Skill Tree and Item Rewards pages skips unpermitted skills
- Leaderboard skill filters only show skills the viewer has access to
- Category tabs hidden - Category tabs (Gathering, Combat, etc.) are hidden if player has no permission for any skill in that category
- Leaderboard category filters also hidden when no skills available in that category
- Admin permission help text -
/mmoadminnow shows permission nodes when permissions are enabled - Explains
mmoskilltree.skill.*for all skills - Explains
mmoskilltree.skill.mining,.swords, etc. for individual skills - Explains
mmoskilltree.command.xpfor the/mmoxpcommand
Award Boost Admin Page
- Award Boost Page - New admin UI for granting boost permissions and tokens to players
- Access via "Award Boost" button in
/mmoadmin - Dual input fields:
- UUID field for recurring permissions (uses
/perm user add) - Username field for one-time tokens (uses XpBoostService directly)
- Dynamic skill list - Shows all skills with XP values configured
- Skill buttons wrap after 8 per row using SkillButtonRow.ui template
- Target categories: All, Gathering, Combat, Production
- Target individual skills: Mining, Woodcutting, Swords, etc. (all configured skills)
- Preset + Custom inputs - Use quick buttons or type custom values
- Multiplier: 1.5x, 2x, 3x, 5x, 10x presets + custom field
- Duration: 15m, 30m, 1h, 2h, 24h presets + custom field (minutes)
- Cooldown: None, 1h, 24h, 7d presets + custom field (minutes)
- Choose scope (Personal or Global)
- Live permission preview updates as you configure
- Rate limiting - 500ms cooldown prevents button spam
- Improved readability with lighter text colors
- Full localization in all 8 languages
Technical
- ViewXpPage.java -
getFilteredSkills()now filters byPermissionUtil.canGainSkillXp() - Total/category calculations use filtered skill list
-
hasUnclaimedItemRewards()filters by permission - Added
hasPermissionForCategory()to check if player has any permitted skills in a category - Category tabs hidden when
hasPermissionForCategory()returns false
- SkillTreePage.java - Permission check before displaying skill tree
- Shows "No permission" message if player lacks skill permission
- Navigation methods filter by permission
- LeaderboardPage.java -
getSkillsForCategoryFiltered()filters skill buttons by permission - Category filter buttons hidden when no skills available in that category
- ItemRewardsPage.java - Permission check for skill rewards (total rewards always available)
- Navigation methods filter by permission
- AdminConfigPage.ui - Added
#PermissionsHelplabel and#AwardBoostBtnbutton
- AwardBoostPage.java - New admin page for awarding boost permissions and tokens
- Dual input: UUID for recurring permissions, Username for one-time tokens
- Dynamic skill buttons from
getConfiguredSkills()using SkillButton.ui + SkillButtonRow.ui templates - Skill buttons wrap after 8 per row (SKILLS_PER_ROW constant)
- Custom text fields for multiplier, duration, cooldown (override presets)
- Recurring permissions use
CommandExecutor.executeAsConsole()with/perm user add UUID permission - Token awards call
XpBoostService.awardToken()directly (finds online player for immediate delivery) - Rate limiting with ACTION_COOLDOWN_MS (500ms) prevents spam
- Permission string format:
mmoskilltree.xpboosts.. . . .
- AwardBoostPage.ui - Improved layout and readability
- Scrollable content area (TopScrolling)
- Dynamic skill buttons container with SkillButtonRow.ui template
- Dual text fields for UUID and Username inputs
- Custom text fields for multiplier, duration, cooldown
- Lighter text colors for better readability (#b0c4d8, #8090a0)
- SkillButtonRow.ui - New template for skill button rows (LayoutMode: Left, Height: 28)
- BoostCommand.java - Added console execution support
- Checks for ConsoleSender instance to allow
/mmoboostfrom console - Console commands bypass admin permission check
- All subcommands (give, global, list, clear, status) support console execution
- LocalizationConfig.java - Added keys for all 8 languages:
-
ui.skilltree.no_permission- "No permission" -
ui.admin.permissions_help- Permission explanation text -
ui.admin.award_boost- "Award Boost" button label
Bug Fixes
- Luck loot empty values - Empty string values in luck loot tables now correctly give no bonus item
- Allows disabling luck drops for specific blocks by setting empty value
- Disabled cracked ore variants in special terrain to prevent exploits:
-
Ore_Thorium_Mud_Cracked,Ore_Cobalt_Slate_Cracked,Ore_Adamantite_Magma_Cracked,Ore_Iron_Basalt_Cracked - XP maps also updated to disable XP for these cracked ore variants
- Disabled XP patterns - Patterns with 0 or negative XP (-1) are now properly skipped for combat skill detection
- Disabled weapons don't receive skill bonuses (damage, crit, lifesteal)
- Consistent behavior: disabled pattern = no XP and no combat bonuses
- Added comment clarifying
bestXp > 0check semantics
Config Compatibility
- No config version bump required - uses existing
skillPermissionsEnabledsetting - Existing permission nodes unchanged (
mmoskilltree.skill.*,mmoskilltree.command.*)
v0.5.8
Skill Overview UX Redesign
- Compact buff bar - All active buffs shown in a single horizontal bar at the top
- Shows: XP Boost, Damage, Block, Crit, Lifesteal
- Bright color-coded values for easy reading
- Displays best values across all combat skills
- Inline skill buffs - Each skill row now shows claimed rewards inline
- Buffs appear below the progress bar:
+15 HP +5% DMG +3% LUCK - Values of same type are combined (e.g., +5 HP + +10 HP = +15 HP)
- See exactly what bonuses each skill provides at a glance
- Improved readability - Better contrast and sizing
- Lighter text colors for better visibility on dark background
- Larger font sizes for buff displays
- XP values show whole numbers for millions (1M instead of 1.2M)
- Wider skill name and XP columns
- Streamlined header - Stats moved to right side of title
- Total Level, Total XP, Skills count in compact layout
- More space for skill progress list
Permissions System
- Reload permissions command -
/mmoconfig reloadperms - Reloads boost permissions from permissions.json without restart
- Shows count of loaded boost permission templates
- Dynamic boost permissions - XpBoostService reads from permissions.json
- Boost permissions extracted from users and groups sections
- Refresh button in Boost page reloads permissions in real-time
- Supports wildcard permissions (
mmoskilltree.xpboosts.*)
Bug Fixes
- Total level calculation - Now excludes skills without XP map data
- Skills not configured in xp-maps.json don't count toward total
- More accurate representation of actual progress
- Block label - Defense renamed to "Block" in all 8 languages
- More consistent with in-game terminology
Combat Reward Targeting
- Targeted combat rewards - Combat bonuses can now apply to specific weapons/skills
- New
CombatTargetenum: ALL, MELEE, RANGED, MAGIC, and individual skills - MELEE includes: Swords, Daggers, Polearms, Staves, Axes, Blunt, Unarmed
- RANGED includes: Archery
- Rewards default to ALL (backward compatible with existing configs)
- "All Combat" rewards at high tiers - New reward options for combat skills
- Tier 8: +3% Damage (All), +3% Critical (All)
- Tier 9: +4% Damage (All), +4% Critical (All), +2% Lifesteal (All)
- Global bonuses as alternative to skill-specific bonuses
Technical
- ViewXpPage.ui - Redesigned layout with horizontal buffs bar
- SkillRow.ui - Added inline buffs display section
- ViewXpPage.java - New
populateBuffsBar()andgetSkillBuffsText()methods - XpBoostService - File-based permissions loading with reload support
- MMOConfigCommand - Added
reloadpermssubcommand - SkillComponent -
getSummedTotalLevel()now filters by XP map data
Config Compatibility
- No config version bump required -
combatTargetis optional with ALL default - Existing skill-tree.json files work unchanged
- Defense bonus remains global (applies when taking damage, not dealing)
v0.5.7
XP Boost System
- Global and personal XP boosts - Players can activate boosts that multiply XP gains
- Global boosts affect all players on the server
- Personal boosts affect only the activator
- Boosts can target all skills, specific skills, or skill categories
- Multiple boosts stack additively (1.5x + 2x = 2.5x total)
- Boost Tokens - One-time boost awards via commands
- Admins award tokens with
/mmoboost give --args=| | | |[scope] - Tokens can be personal (default) or global scope - global tokens activate server-wide when used!
- Tokens are stored until the player chooses to activate them
- Works for offline players - tokens delivered on next login
- No permission required to activate awarded tokens
- Players activate tokens from the Boost UI when ready
- Permission-based boost activation - Server owners control who can activate repeatable boosts
- Permission format:
mmoskilltree.xpboosts.. . . . - Target:
all, skill name, or category name - Scope:
self(personal) orall(global) - Multiplier uses underscore for decimal:
1_5= 1.5x - Duration and cooldown in minutes
- Example:
mmoskilltree.xpboosts.mining.self.2_0.30.60- 2x Mining, self, 30min, 1hr cooldown
- Boost UI Page - New "Boosts" tab in ViewXpPage with three sections:
- Active Boosts - Currently running boosts (global + personal) with time remaining
- Boost Tokens - One-time tokens awarded via commands, ready to activate
- Reusable Boosts - Repeatable boosts available from permissions (with cooldowns)
- Refresh button to update display
- Admin
/mmoboostcommand - OPs can manage boosts directly (uses--args=with|separator) -
/mmoboost give --args=- Award boost token| | | |[scope] -
/mmoboost global --args=- Activate global boost immediately| | -
/mmoboost list- Show active global boosts -
/mmoboost clear --args=- Clear boosts and tokens -
/mmoboost status --args=- Show boost status including tokens
- Persistence - Boosts and tokens persist across server restarts
- Global boosts saved to
mods/mmoskilltree/active-boosts.json - Pending tokens for offline players saved in the same file
- Personal boosts and tokens stored in player's SkillComponent
- Cooldowns track last activation timestamp
Other Changes
- Defense skill renamed to Block - Display name updated to "Block" across all code and UI
- Updated in all 8 languages (EN: Block, ES: Bloqueo, FR: Blocage, PT: Bloqueio, HU: Blokkolás, TR: Blok, DE: Blocken, IT: Blocco)
- Command UX improvement -
/mmoboostuses--args=with pipe-separated values - Example:
/mmoboost give --args=Steve|mining|2|30
Technical
- New data classes: BoostScope, BoostTarget, ActiveBoost, BoostPermission, BoostToken
- XpBoostService - Singleton service for boost management with token support
- SkillComponent additions: personalBoosts, boostCooldowns, boostTokens maps with codec serialization
- SkillService integration - Boost multiplier applied additively with reward bonuses, token delivery on first action
- BoostPage.java - Interactive UI page for boost management (3 sections)
- BoostCommand.java - Admin command with pipe-separated args and token scope support
- Localization - Full boost UI translations for all 8 languages (EN, ES, FR, PT, HU, TR, DE, IT)
v0.5.6
Override-Based Config System (XpMapsConfig & LuckConfig)
- Configs now store ONLY overrides - Customizations are preserved across mod updates
- File stores only values that differ from defaults
- Missing keys automatically use built-in defaults
- New defaults propagate without losing your changes
- XpMapsConfig: Use value
-1to explicitly disable a default XP pattern - LuckConfig: Use value
"__DISABLED__"to explicitly disable a default luck pattern
- Reference file generation -
mods/mmoskilltree/_reference/ -
defaults-xp-maps.json- All default XP values per skill -
defaults-luck-loot.json- All default luck loot table entries - Auto-generated read-only files for server owner reference
- Updated on every config load
- New commands:
-
/mmoconfig diff --args=- Show only overrides (XP and luck) -
/mmoconfig trim- Remove redundant overrides from both XP and luck configs -
/mmoconfig disable --args=- Explicitly disable a default pattern
- Improved
/mmoconfig list- Now shows override status for each pattern - Cyan text indicates overridden values (shows default in brackets)
- Green text indicates default values
- Header shows override count per skill
- Schema versioning -
schemaVersionreplacesconfigVersionfor override-based configs - Schema version only bumps for structural changes (new fields)
- Default value changes no longer require version bump
- Old configs with
configVersionare read for backwards compatibility
Admin UI
- New
/mmoadmincommand - Opens interactive admin configuration UI - TextField inputs for direct value entry (base XP, scale multiplier)
- Toggle settings: creative mode XP, skill permissions, leveling formula
- Real-time milestone preview updates as you type
- Formula description shows actual calculation being used
- Config override statistics and trim functionality
- Quick actions: reload configs, reload language, trim overrides, reset to defaults
- Aliases:
/mmoconfig-ui,/mmosettings
- XP Overrides Page - Visual editor for skill XP values
- Access via "Edit XP Values" button in Admin Config page
- Category tabs: Gathering, Combat, Crafting, Misc
- Dynamic skill selector buttons per category
- Pattern list showing: name, default value, current value, status
- Status indicators: Default (green), Override (orange), Disabled (red)
- Add/Update patterns with text fields for pattern name and XP value
- Disable button to set patterns to -1 (disabled)
- Reset button per row to revert overrides to defaults
- Click pattern name to copy to text field for easy editing
- Permissions toggle - Single toggle controls both skill and command permissions
- UI label simplified to "Enable Permissions"
- When enabled: skill XP gains and commands require permissions
- When disabled: all players can gain XP and use commands
- Admin permission paradigm - Flexible OP/permission-based access
- OP players always have admin access regardless of permission settings
- When permissions enabled: non-OP players can get admin via
mmoskilltree.admin - Applied to both
/mmoconfigcommand and/mmoadminUI
Localization
- Config command messages fully localized - All 8 supported languages updated
- Override system messages (diff, trim, disable, reset, reload)
- Admin page labels and buttons (20 keys per language)
- Support for: English, Spanish, French, Portuguese, Hungarian, Turkish, German, Italian
- Falls back to English for players without skill data
Technical
- XpMapsConfig.java - Complete rewrite for override-based system
-
userOverridesmap tracks only customizations -
load()now merges file overrides on top of defaults -
save()writes only overrides (smaller config files) -
DISABLED_VALUE = -1sentinel for explicit pattern removal - New methods:
getOverrides(),getAllOverrides(),isDefault(),getDefaultValue(),resetToDefault(),disablePattern(),trimRedundantOverrides()
- LuckConfig.java - Complete rewrite for override-based system
- Same override-based architecture as XpMapsConfig
-
DISABLED_VALUE = "__DISABLED__"sentinel for explicit luck pattern removal - Reference file:
_reference/defaults-luck-loot.json
- ConfigVersionUtil.java - Added
extractSchemaVersion()method - Checks for
schemaVersionfirst, falls back toconfigVersion
- MMOConfigCommand.java - Added handlers for diff, trim, disable commands
- Updated list command to show override indicators
- Updated remove command to show revert-to-default behavior
- All config messages now use localization via Messages helper
- Added
getPlayerSkills()andmsg()helper methods
- LocalizationConfig.java - Added 40+ new localization keys per language
-
cmd.config.*keys for all override system messages -
ui.admin.*keys for admin config page (20 keys per language)
- New files:
-
CommandExecutor.java- Shared utility for executing commands as console or player -
AdminConfigPage.java- Interactive admin configuration UI page -
AdminConfigUICommand.java- Command to open the admin UI -
AdminConfigPage.ui- UI layout for admin configuration page -
XpOverridesPage.java- XP pattern editor page with category/skill navigation -
XpOverridesPage.ui- UI layout for XP overrides page -
XpPatternRow.ui- Template for pattern list rows -
SkillButton.ui- Template for dynamic skill selector buttons
- PermissionUtil.java - Added admin permission support
-
ADMIN_PERMISSION = "mmoskilltree.admin"constant -
hasAdminPermission(Player)- OP always has access; checks permission when enabled -
isOp(Player)- Helper for OP status checks
- CommandRewardService.java - Refactored to use CommandExecutor utility
- Removed duplicate command execution methods (DRY)
- Uses shared
CommandExecutor.executeAsConsole()andCommandExecutor.executeAsPlayer()
- MMOConfigCommand.java - Updated permission paradigm
- Removed hardcoded
setPermissionGroups("OP") - Uses
PermissionUtil.hasAdminPermission()for flexible access control
Bug Fixes
- Fixed combat XP exploit - Players can no longer gain XP from hitting projectiles (arrows, etc.)
-
CombatDamageEventSystemnow detectsProjectilecomponent in entity archetype - Projectiles are always blocked from giving XP (hardcoded, not config-dependent)
v0.5.5
UI Improvements
- Item Rewards Fully Disabled When Config Disabled - Complete protection when item rewards are turned off
- Rewards tab hidden in ViewXpPage
- ItemRewardsPage shows "Item Rewards Disabled" if somehow accessed directly
- All navigation (tabs, arrows) hidden on disabled page
- Event handlers check
isEnabled()before opening rewards page
Upgrade Safety
- Stat Rewards Reapplied on Config Update - Existing players get correct stat values after mod updates
- When SkillTreeConfig version changes, all stat modifiers (Health, Stamina, Mana) are reapplied
- Online players: stats recalculated immediately on reload/reloaddefaults
- Offline players: stats recalculated on first XP action after login
- Prevents stale stat values from old config versions
- Orphaned Reward Cleanup - Removes stat modifiers from rewards that no longer exist
- When skill tree config changes remove tiers or reward IDs, old stat modifiers are cleaned up
-
cleanupOrphanedRewards()now callsremoveOrphanedStatModifiers()for each removed reward - Tries removing all stat types (Health, Stamina, Mana) since original reward type is unknown
Balance Changes
- Block (STAT_DEFENSE) Nerfed by 50% - Block reduction values were too powerful
- All STAT_DEFENSE skill tree rewards reduced by half
- Before: 4% → 20% range across tiers
- After: 2% → 10% range across tiers
- Maximum stacked Block from all skills now ~45% (was ~90%)
- Item Reward Tiers Expanded - Added intermediate tiers for smoother progression with hybrid OSRS formula
- New Level 65 tier for all 16 skills (Expert-level materials)
- New Level 80 tier for all 16 skills (Advanced materials)
- Rewards include mid-to-late game materials like Mithril, Adamantite, Onyxium
- Legendary materials (Prisma, Voidheart, Elemental Essences) at Level 80+
- Total: 6 milestone tiers per skill (10, 25, 50, 65, 80, 100)
Technical
- SkillTreeService.java - Added
reapplyStatRewards()andremoveOrphanedStatModifiers()methods - SkillService.java - Added
setSkillTreeConfigChanged()flag for tracking skill tree config updates - SkillTreeConfig.java - Triggers stat reapplication when config version changes on load
- MMOConfigCommand.java -
validateAllOnlinePlayers()now also reapplies stat rewards - ViewXpPage.java - Added
CommandRewardsConfig.isEnabled()checks for tab visibility and event handling - ItemRewardsPage.java - Added disabled state check in
build()method - CommandRewardsDefaults.java - Added Level 65 and 80 reward entries for all skills
- SkillTreeDefaults.java - Reduced all STAT_DEFENSE values by 50%
- SkillTreeConfig.java - CONFIG_VERSION bumped to 3
- CommandRewardsConfig.java - CONFIG_VERSION bumped to 4
v0.5.4
Improvements
- Milestone XP display - When changing
formula,basexp, orscale, shows XP required for milestone levels - Format:
XP required: Lv10=14.3k | Lv25=95.6k | Lv50=446.2k | Lv80=2.3M | Lv100=10.0M - Helps server owners understand impact of config changes instantly
Technical
- MMOConfigCommand.java - Added
showMilestoneXp()helper method with formatted output
v0.5.3
⚠️ BREAKING CHANGE: Leveling formula completely changed. XP requirements are higher at all levels, so existing players will have lower levels with the same XP. Use /mmoconfig formula --args=legacy to restore the old formula.
Hybrid OSRS Leveling Formula
- Complete formula overhaul - Combines OSRS exponential curve with quadratic floor
- Early/mid levels ~10% harder than previous quadratic formula
- Endgame scales exponentially (OSRS-style)
- Level 100 = ~10M XP (true endgame grind)
- New XP requirements (with default settings):
- Level 10: ~14,270 XP
- Level 25: ~95,573 XP
- Level 50: ~446,222 XP
- Level 80: ~2,274,045 XP
- Level 100: ~10,000,000 XP
- Config parameters:
-
baseXpPerLevel(default: 300) - Quadratic floor component -
levelScaleMultiplier(default: 200) - OSRS exponential factor - OSRS component uses
2^(level/7)- each level requires ~10% more XP than the last - Quadratic floor ensures early/mid levels aren't too easy
Improvements
/mmoconfig formula- Switch between hybrid (OSRS) and legacy (quadratic) leveling formulas-
hybrid: OSRS exponential + quadratic floor (default, ~10M XP at level 100) -
legacy: Simple quadratic (~1.5M XP at level 100 with base=150, scale=2) /mmoconfig reload- Now reloads ALL config files (was missing XpMaps, Luck, CommandRewards)/mmoconfig reloaddefaults- Now resets ALL configs to built-in defaults
Bug Fixes
- Item Rewards UI - Fixed crash when viewing Total Level rewards with more than 15 items per tier
- Now supports up to 30 items per tier (6 rows)
Technical
- SkillConfig.java - CONFIG_VERSION bumped to 8, defaults changed to hybrid values (base=300, scale=200)
- SkillComponent.java -
getXpForLevel()andcalculateLevel()use hybrid OSRS formula - ItemRewardsPage.java - Supports up to 30 items per tier (was 15)
- RewardTierRow.ui - Added ItemsRow4-6 for larger reward tiers
- CommandRewardsConfig.java - Added
reloadDefaults()method - MMOConfigCommand.java - Updated reload handlers to include all configs
v0.5.2
Bug Fixes
- Harvest Exploit Prevention - Players can no longer gain XP by placing and harvesting items
- Previously, placing a fruit/crop and then harvesting it would award XP via PickupItemEvent
- Now tracks placed item IDs in addition to block positions
- When you pick up an item you recently placed, XP is skipped
- Separate expiration timer for items:
placedItemExpireMinutes(default: 5 minutes) - Other players CAN still get XP from items you placed (fair multiplayer)
- Life Essence Crafting Exploit Prevention - Currency conversion recipes no longer give Crafting XP
-
Ingredient_Life_Essence_100_Recipe_→ 0 XP -
Ingredient_Life_Essence_Concentrated_Recipe_→ 0 XP
- No +0 XP Notifications - Actions that give 0 XP no longer show notifications
Configuration
placedItemExpireMinutes- New config option inskill-config.json- Minutes until placed items expire for harvest tracking (default: 5)
- Shorter than block expiration since items are typically harvested quickly
- Separate from
placedBlockExpireMinutes(which defaults to 0/never for blocks)
Technical
- SkillConfig.java - CONFIG_VERSION bumped to 5
- Added
placedItemExpireMinutesfield (default: 5) - Added getter/setter methods
- PlacedBlockTracker.java - Extended to track placed item IDs
- New
TrackedItemclass with atomic count and timestamp -
trackPlacedItem(playerHash, itemId)- Track when player places an item -
consumePlacedItem(playerHash, itemId)- Check and decrement on pickup (returns true if should skip XP) - Cleanup in
cleanupExpired()now uses separate expiration for blocks and items -
getTotalTrackedItems()- Stats method for debugging - PlaceBlockEventSystem.java - Now calls
trackPlacedItem()in addition to position tracking - PickupItemEventSystem.java - Checks
consumePlacedItem()before awarding XP - CraftingDefaults.java - Added 0 XP entries for Life Essence conversion recipes
- CraftRecipeEventSystem.java - Removed debug log statement
- SkillService.java - Skip XP processing when bestXp <= 0 (no notifications for 0 XP)
- MMOConfigCommand.java -
/mmoconfig reloadnow reloads ALL configs (was missing XpMaps, Luck, CommandRewards) - MMOConfigCommand.java -
/mmoconfig reloaddefaultsnow resets ALL configs to defaults - CommandRewardsConfig.java - Added
reloadDefaults()method
v0.5.1
New Features
- Target Player XP Command - OPs can now set other players' XP directly
-
/setmmoxp- Set XP for another player--target= - Requires
mmoskilltree.command.setxp.otherspermission (default: OP) - Target must be online and in the same world
- Works with all skills or "all" for bulk changes
- Example:
/setmmoxp mining 1000 --target=PlayerName
- Custom Reward Display Names - Configure display names for item rewards
- Add
displayNamefield to reward entries incommand-rewards.json - Value must be a localization key (e.g.,
"reward.mining.starter_kit") - Add the key to your
localization/messages-*.jsonfiles - Falls back to "Level X" if key not found or not configured
- Localized SetXP Command Messages - All command messages now support localization
- Error messages (permission denied, player not found, invalid XP, unknown skill)
- Success messages (skill set, all skills set, with/without target)
- Localized in all 8 supported languages
Technical
- SetXpCommand.java - Added
--targetoptional argument for targeting other players - Uses
world.getPlayers()to iterate players in the same world (deprecated but functional) -
findPlayerRefByUsername()method finds target player's entity ref - Uses
PermissionUtil.hasCommandPermission(player, "setxp.others")for permission check - Works with existing
MMOSkillTreeAPI.setXp()for data modification - All messages now localized via
Messages.get()helper
- manifest.json - Added new permission node
-
mmoskilltree.command.setxp.others- Set other players' XP with --target (default: OP)
- LocalizationConfig.java - Added setxp command message keys for all 8 languages
-
cmd.setxp.no_permission_others,cmd.setxp.player_not_found,cmd.setxp.no_skill_data -
cmd.setxp.xp_negative,cmd.setxp.unknown_skill,cmd.setxp.available_skills -
cmd.setxp.success_all,cmd.setxp.success_all_target,cmd.setxp.success_skill,cmd.setxp.success_skill_target -
cmd.setxp.rewards_revoked- Notification when rewards are revoked
- SkillTreeService.java - Added reward validation methods
-
validateAndRevokeRewards()- Revokes rewards for a skill when level drops below tier requirements -
validateAllRewards()- Validates all skills (used when setting all XP) - Uses RewardEffectRegistry to properly remove stat modifiers
- SkillComponent.java - Added helper methods for reward management
-
clearClaimedRewardsForTier()- Clears all rewards for a specific tier -
getAllClaimedRewards()- Returns map of tier -> list of reward IDs for a skill
- SetXpCommand.java - Integrated reward validation after XP changes
- Calls
SkillTreeService.validateAndRevokeRewards()for single skill changes - Calls
SkillTreeService.validateAllRewards()for "all" skill changes - Shows revoked count to admin if any rewards were revoked
- CommandRewardEntry.java - Added
displayNamefield for custom reward names - CommandRewardsConfig.java - Parses and saves displayName from JSON config
- Messages.java - Added
getCommandRewardDisplayName()helper for resolving display names - ItemRewardsPage.java - Uses custom displayName if configured
- CommandRewardService.java - Fixed ConsoleSender integration for console commands
Admin Commands
- Reset Item Rewards Command -
/mmoconfig resetrewards --args= - Resets all claimed item rewards for an online player
- Player can re-claim rewards at their current level milestones
- Example:
/mmoconfig resetrewards --args=PlayerName
Balance Changes
- Leveling Curve Rebalanced - Adjusted default leveling parameters for longer progression
-
baseXpPerLevelchanged from 100 to 150 -
levelScaleMultiplierchanged from 1.1 to 1.35 - Creates a steeper curve where high levels require significantly more XP
- Level 50 now requires ~127k XP (was ~69k), Level 100 requires ~1M XP (was ~297k)
- Existing servers can adjust via
/mmoconfig basexpand/mmoconfig scale
- Item Rewards Scaling Improved - Default item rewards scaled up to match harder leveling curve
- All skill rewards increased 3-5x at higher tiers
- Life Essence added to all skills at every tier
- Level 100 rewards now include ~100 Life Essence, ~80 rare bars, ~10-15 Voidheart
- Total Level rewards scaled up significantly (e.g., Total 1000 now gives 1000 Life Essence)
- Elemental essences (Fire, Ice, Lightning) quantities increased proportionally
Reward Validation
- Automatic Reward Revocation - Rewards are validated and revoked when player no longer qualifies
- Triggers when XP is reduced via
/setmmoxp - Triggers when leveling config changes:
/mmoconfig basexp,/mmoconfig scale,/mmoconfig reload,/mmoconfig reloaddefaults - Offline players are validated on their first skill action after logging in
- Revokes all rewards from tiers where player level is now below requirement
- Removes stat modifiers (health, stamina, mana) via RewardEffectRegistry
- Displays count of revoked rewards to admin
Config Refactoring
- Config File Split - Separated large SkillConfig into focused configs for easier management
-
skill-config.json- General settings only (leveling formula, permissions, placed blocks, entity blacklist) -
xp-maps.json(NEW) - XP values per skill (block patterns, weapon tiers, etc.) -
luck-loot.json(NEW) - Luck bonus loot tables (block pattern -> item ID) - Each config has its own version number for independent updates
- XpMapsConfig.java - New singleton config for XP values per skill
- LuckConfig.java - New singleton config for luck loot tables
- SkillConfig.java - Slimmed down, delegates XP/luck methods to new configs (marked deprecated)
- MMOSkillTreePlugin.java - Initializes all new configs on startup
v0.5.0
New Features
- Item Rewards at Skill Milestones - Receive item rewards when reaching specific skill levels
- New config file:
mods/mmoskilltree/command-rewards.json - Supports individual skill milestones (e.g., Mining level 10, 25, 50, 100)
- Supports total level milestones (50, 100, 200, 350, 500, 750, 1000)
- Comprehensive defaults included - All 16 skills have pre-configured item rewards
- Items scale with progression:
- Level 10 (Starter): 2-3 basic items (copper tools, common ingredients)
- Level 25 (Progressing): 3-4 items (iron/cobalt gear, uncommon materials)
- Level 50 (Skilled): 5-6 items (rare materials, gems, better gear)
- Level 100 (Master): 6-10 items including legendary weapons (Flame, Void, Spectral)
- Example: Mining 100 rewards include Flame Pickaxe, Mithril bars, Voidstones
- Manual claiming required - Rewards are NOT auto-claimed; use the Rewards UI
- Commands can also be executed (see Command Rewards below)
- Item Rewards UI Page - New page to view and claim your item rewards
- Access via "Rewards" tab on the Skill Overview page
- Shows all tiers with status: LOCKED (gray), READY (orange), CLAIMED (green)
- View reward contents before unlocking
- CLAIM button to receive items into your inventory
- Items wrap to new lines after 5 per row (supports up to 15 items per tier)
- Toggle between Skill Rewards and Total Level Rewards tabs
- Navigate between skills with arrow buttons
- Rewards tab highlights with orange color and
*when unclaimed rewards available
- Item Reward Notifications - Get notified when new rewards become available
- On level-up: "Mining Lv.10 item rewards available! Open /xp > Rewards"
- On total level milestone: "Total Lv.100 item rewards available! Open /xp > Rewards"
- Localized in all 8 supported languages
- Command Rewards - Server owners can also configure commands to run at milestones
- Placeholders:
{player},{level},{skill},{total_level} - RunAs modes:
CONSOLE(full permissions) orPLAYER(player's permissions) - One-time rewards - commands only execute once per milestone
- Example: Broadcast message at total level 100
Configuration
command-rewards.json- New config file for item and command rewards
`json
{
"configVersion": 3,
"enabled": true,
"rewards": {
"MINING": [
{"level": 10, "displayName": "reward.mining.starter", "giveItems": ["Item_Pickaxe_Copper:1", "Ingredient_Bar_Copper:5"], "runAs": "CONSOLE"},
{"level": 100, "displayName": "reward.mining.master", "giveItems": ["Weapon_Pickaxe_Flame:1", "Rock_Gem_Voidstone:3"], "runAs": "CONSOLE"}
],
"TOTAL": [
{"level": 100, "giveItems": ["Ingredient_Bar_Mithril:10", "Rock_Gem_Diamond:5"], "commands": ["say {player} reached total level 100!"], "runAs": "CONSOLE"}
]
}
}
`
- Per-Config Versioning - Each config file now has its own version number
- Previously: All configs shared a single
CURRENT_CONFIG_VERSION = 10 - Now:
SkillConfig.CONFIG_VERSION = 3,SkillTreeConfig.CONFIG_VERSION = 2,CommandRewardsConfig.CONFIG_VERSION = 3 - Only the changed config gets backed up when updating, not all configs
Technical
- CommandRewardEntry.java - Data class for level/commands/giveItems/runAs
-
ItemRewardinner class for item ID and quantity -
ItemReward.parse()static method to parse "ItemId:Quantity" format - CommandRewardsConfig.java - Singleton config loader following SkillConfig pattern
- CommandRewardsDefaults.java - Comprehensive item reward defaults for all 16 skills
- All item IDs verified against Hytale's item database
- Rewards use actual game items (weapons, tools, ingredients, gems)
- CommandRewardService.java - Checks milestones, gives items, executes commands
-
checkAndExecuteRewards(playerRef, skills, skillType, newLevel)- For skill level-ups -
checkTotalLevelRewards(playerRef, skills)- For total level milestones -
giveItemToPlayer()- Adds items directly to player inventory - Placeholder processing:
{player},{level},{skill},{total_level} - ItemRewardsPage.java - New UI page for viewing and claiming item rewards
-
populateSkillRewards()/populateTotalRewards()- Render reward tiers -
populateItems()- Distribute items across rows (5 per row, up to 3 rows) -
handleClaimSkillReward()/handleClaimTotalReward()- Manual claim handlers - ItemRewardsPage.ui - UI layout with skill/total tabs, tier list, navigation
- RewardTierRow.ui - Template for tier rows with claim button and 3 item rows
- RewardItem.ui - Template for individual item display (icon + quantity)
- SkillComponent.java - Added
claimedCommandRewardsfield for tracking claimed rewards - New codec entry for persistence
- New methods:
hasClaimedCommandReward(),claimCommandReward(),getClaimedCommandRewardIds(),resetCommandRewards() - New method:
getSummedTotalLevel()- Sum of individual skill levels (more intuitive than formula-based total) - ViewXpPage.java - Added "Rewards" tab navigation to ItemRewardsPage
- ViewXpPage.ui - Added
#TabRewardsbutton - ConfigVersionUtil.java - Removed shared
CURRENT_CONFIG_VERSIONconstant - Updated
checkAndBackupIfNeeded(configPath, storedVersion, expectedVersion)to take expected version parameter - SkillService.java - Integrated CommandRewardService after level-up detection
- MMOSkillTreePlugin.java - Loads CommandRewardsConfig in setup()
- LocalizationConfig.java - Added ItemRewardsPage localization keys in all 8 languages
-
ui.rewards.title,ui.rewards.total_title,ui.rewards.level,ui.rewards.claimed,ui.rewards.available,ui.rewards.locked,ui.rewards.claim, etc.
v0.4.9
New Features
- Deployable XP Exploit Fix - Totems and turrets no longer give combat XP
- Prevents XP farming by repeatedly hitting player-deployed entities
- Lays groundwork for future entity blacklist customization
- New command:
/mmoconfig blacklist- view current blacklist (expansion planned) - Config:
combatXpEntityBlacklistarray inskill-config.json
UX Improvements
- Fractional XP Accumulator - Small XP bonuses (like +5%) now properly accumulate instead of being lost to rounding
- Previously: 10 XP with 5% bonus →
10 * 1.05 = 10.5→ truncated to 10 (bonus lost!) - Now: Fractional remainder (0.5) is saved and added to next XP gain
- Example: Gain 1: 10.5 → award 10, store 0.5 | Gain 2: 10.5 + 0.5 = 11.0 → award 11
- Players see the bonus manifest every few actions (deterministic, no RNG)
- Mathematically accurate over time - no XP is ever lost
Technical
- SkillComponent.java - Added
fractionalXpMap(ConcurrentHashMap) - New codec entry
{SKILL}FracXpfor persistence - New methods:
getFractionalXp(skill),setFractionalXp(skill, amount) - SkillService.java - Updated
addXp()to use fractional accumulator pattern - Calculates exact XP with bonus multiplier
- Adds accumulated fractional remainder from previous gains
- Awards integer portion, saves decimal remainder for next time
- SkillConfig.java - Added
combatXpEntityBlacklistfield with pattern matching -
isEntityBlacklisted(entityType)- check if entity matches any blacklist pattern -
addEntityBlacklist(pattern)/removeEntityBlacklist(pattern)- manage entries - CombatDamageEventSystem.java - Added entity blacklist check before awarding combat XP
-
getEntityType()- extracts entity archetype name from chunk - Blacklisted entities still take damage/trigger effects, just no XP awarded
- MMOConfigCommand.java - Added
/mmoconfig blacklistsubcommand - ConfigVersionUtil.java - Bumped to version 10
v0.4.8
New Features
- Placed Block XP Exploit Prevention - Players can no longer gain XP by breaking blocks they placed
- Tracks block positions when players place blocks
- Breaking a self-placed block awards no XP and removes tracking
- Other players CAN still get XP from blocks you placed (fair multiplayer)
- Applies to Mining, Woodcutting, Excavation block breaks (not item pickups)
- Configurable via
trackPlacedBlocks(default: true) - Optional expiration via
placedBlockExpireMinutes(0 = never expire)
Balance Changes
- Building XP Simplified - Changed from dynamic 50% of gathering values to flat 4 XP per block
- All placed blocks now give 4 XP regardless of block type
- Previously calculated as 50% of the mining/woodcutting/excavation value
- Simpler and more predictable progression
- Mushroom XP Reduced - Reduced mushroom harvesting XP from higher values to 1 XP
-
Plant_Crop_Mushroom_andPlant_Mushroom_now give 1 XP - Prevents easy XP farming from abundant mushrooms
Localization
- Italian Language Support - Full translation of all UI, notifications, skills, and rewards
- New language file:
messages-it.json - 8 languages now supported: English, Spanish, French, Portuguese, Hungarian, Turkish, German, Italian
Configuration
trackPlacedBlocks- Enable/disable placed block tracking (default: true)- When enabled, players cannot gain XP from breaking blocks they placed
- Set to false to allow the old behavior
placedBlockExpireMinutes- Minutes until placed blocks "become natural" (default: 0)- Set to 0 for blocks to never expire (only removed when broken)
- Set to a positive value (e.g., 30) to allow XP after that many minutes
Technical
- PlacedBlockTracker.java - New singleton service for tracking player-placed blocks
- Uses
ConcurrentHashMapwith player hash -> Set of tracked blocks -
BlockPositionrecord stores x, y, z coordinates -
TrackedBlockrecord stores position and timestamp for expiration - Methods:
trackPlacement(),wasPlacedByPlayer(),removeTracking(),cleanupExpired() - PlaceBlockEventSystem.java - Now calls
PlacedBlockTracker.trackPlacement()on block place - BreakBlockEventSystem.java - Checks
PlacedBlockTracker.wasPlacedByPlayer()before awarding XP - PickupItemEventSystem.java - Same check for interactive pickups (harvesting)
- SkillConfig.java - Added
trackPlacedBlocksandplacedBlockExpireMinutesfields
v0.4.7
Bug Fixes
- Fixed leaderboard crash on multi-world servers - Leaderboard no longer crashes when players are in different world instances (e.g., dungeons, temples)
- Error was:
IllegalStateException: Assert not in thread!when accessing player data across world threads - Now uses cached leaderboard data instead of accessing live data from other world threads
- Online/offline indicator still works correctly (based on player connection status)
- Viewer's own data is still live (same thread)
Technical
- LeaderboardPage.java - Refactored
gatherPlayerData()to avoid cross-thread Store access - Only calls
playerRef.getUsername()on other players (thread-safe) - Uses
LeaderboardDataStorecache for all player XP/level data - Gets live data only for the viewer (who is on the current thread)
v0.4.6
Bug Fixes
- Fixed command permissions blocking all players - Commands like
/mmoxp,/skilltree, and/xpdisplaywere requiring permission nodes even when permission system was disabled - Added
enableCommandPermissionsconfig option (default:false) - When disabled, all players can use all commands without needing
mmoskilltree.command.*permissions - Enable via config file or future admin command to require permission nodes for commands
- Matches the existing behavior of skill permissions (
enableSkillPermissions)
Technical
- SkillConfig.java - Added
enableCommandPermissionsfield with getter/setter and JSON serialization - PermissionUtil.java - Updated
hasCommandPermission()to checkisCommandPermissionsEnabled()before requiring permissions - Added wildcard permission support (
mmoskilltree.command.*) for command permissions
v0.4.5
New Features
- Keb's Katanas Mod Support - Added default XP values for katanas from the Keb's Katanas mod
- Legendary: Keb_Katana_Prisma (55 XP)
- Epic: Keb_Katana_Mithril (48 XP), Keb_Katana_Onyxium (52 XP)
- Rare: Keb_Katana_Cobalt (23 XP), Keb_Katana_Adamantite (28 XP), Keb_Katana_Thorium (28 XP)
- Uncommon: Keb_Katana_Copper (8 XP), Keb_Katana_Steel (8 XP)
- Configurable Permission System - Opt-in permission nodes for skill XP gain and commands
- Permission checking is disabled by default for backwards compatibility
- Enable via
/mmoconfig permissions --args=true - When enabled, players need
mmoskilltree.skill.ormmoskilltree.skill.*to gain XP
- Skill Permissions - Control which players can gain XP in specific skills
-
mmoskilltree.skill.*- Wildcard for all skills (default: granted) -
mmoskilltree.skill.mining- Individual skill permissions - All 16 skills have their own permission node
- Silent deny - players without permission simply don't gain XP (no error message)
- Command Permissions - Control access to plugin commands
-
mmoskilltree.command.xp- /mmoxp command (default: granted) -
mmoskilltree.command.skilltree- /skilltree command (default: granted) -
mmoskilltree.command.xpdisplay- /xpdisplay command (default: granted) -
mmoskilltree.command.setxp- /setmmoxp command (default: op) -
mmoskilltree.command.config- /mmoconfig command (default: op)
- New Admin Command -
/mmoconfig permissions --args= - Toggle skill permission checking on/off
- Displays current state and usage help
Upgrade Notes
- Config version bumped to 8 - Existing configs will be backed up automatically
- Your old config is saved as
skill-config_backup.jsoninmods/mmoskilltree/ - Restore any custom XP values from the backup file after upgrading
Technical
- ConfigVersionUtil.java - Bumped
CURRENT_CONFIG_VERSIONto 8 - LongswordDefaults.java - Added 8 Keb's Katanas with tiered XP values
- manifest.json - Added Permissions array with all skill and command permission nodes
- SkillConfig.java - Added
enableSkillPermissionsfield with getter/setter - PermissionUtil.java - New utility class for permission checking
-
canGainSkillXp(player, skill)- Checks skill permission (respects config toggle) -
hasCommandPermission(player, command)- Checks command permission - SkillService.java - Added permission check in
processTrigger()before awarding XP - Command classes - All 5 commands now check
mmoskilltree.command.permission - GetXpCommand, SkillTreeCommand, XpDisplayCommand, SetXpCommand, MMOConfigCommand
- LocalizationConfig.java - Added
cmd.no_permissionkey to all 7 languages
v0.4.4
New Features
- Offline Player Leaderboard - Leaderboard now displays both online and offline players
- Player data is cached when XP is gained and on server shutdown
- Online players show live data; offline players show cached data
- Visual indicator distinguishes online (green dot) from offline (gray dot) players
- Player count now shows "X online / Y total" format
Technical
- LeaderboardDataStore.java - New singleton service for persistent leaderboard caching
- Stores player skill data in
mods/mmoskilltree/leaderboard-cache.json - Thread-safe with
ConcurrentHashMap - Automatically saves on JVM shutdown via shutdown hook
- SkillService.java - Added leaderboard cache update on XP gain
- LeaderboardPage.java - Merged online player data with cached offline data
- Added
isOnlinefield toPlayerLeaderboardEntry - Added
createEntryFromCache()method for offline player entries - Online/offline visual styling in leaderboard rows
- LeaderboardRow.ui - Added
#OnlineStatusindicator element - MMOSkillTreePlugin.java - Added leaderboard cache initialization and shutdown hook
- LocalizationConfig.java - Added
ui.leaderboard.player_count_onlinekey for all 7 languages
v0.4.3
New Features
- Turkish Localization - Added Turkish (Türkçe) as a supported language
- Full translation of all UI text, notifications, skill names, and reward types
- German Localization - Added German (Deutsch) as a supported language
- Full translation of all UI text, notifications, skill names, and reward types
- Expanded Language Selector - Settings page now supports up to 15 languages
- Increased from 2 rows of 3 buttons to 3 rows of 5 buttons
- Ready for community-contributed translations
Bug Fixes
- Fixed Wan's Wonder Weapons Battleaxe - Corrected typo in item ID
-
WanMine_God_Slayer_Batlleaxe→WanMine_God_Slayer_Battleaxe
Technical
- LocalizationConfig.java - Added
getTurkishDefaults()andgetGermanDefaults()with full translations - LocalizationConfig.java - Added
ensureTurkishDefaults()andensureGermanDefaults()methods - SettingsPage.java - Increased
maxLangButtonsfrom 6 to 15 - SettingsPage.ui - Added
#LangBtn3through#LangBtn14buttons in 3 rows of 5 - SettingsPage.ui - Increased
#LanguageSettingheight from 160 to 204 - SettingsPage.ui - Increased
#LanguageButtonsheight from 80 to 124
v0.4.2
Bug Fixes
- Disabled Luck for Crafting - Removed luck bonus from crafting due to critical item duplication bug
- Luck bonuses were incorrectly duplicating crafted items
- Will be re-enabled in a future update once the underlying issue is resolved
Technical
- CraftRecipeEventSystem.java - Removed
LuckUtil.tryLuckBonus()call
v0.4.1
New Features
- Mighty Staffs Mod Support - Added default XP values for staffs from the Mighty Staffs mod
- Weapon_Staff_Bo_Wood (6 XP)
- Wan's Wonder Weapons Mod Support - Added default XP values for weapons from the Wan's Wonder Weapons mod
- Swords: WanMine_Lethal_Leftovers_Sword, WanMine_Gaia's_Wrath_Sword, WanMine_Quasar_Cosmic_Sword (65-70 XP)
- Longswords: WanMine_Soulblight_Longsword, WanMine_Soulblight_Longsword_v1 (65 XP)
- Daggers: WanMine_Chromatic_Cleaver_Dagger, WanMine_Daybreak_Dagger, WanMine_Heartroot_Dagger, WanMine_Ashthorn_Dagger, WanMine_Nightshade_Dagger, WanMine_Frostburn_Dagger, WanMine_Nightfall_Dagger (58-68 XP)
- Battleaxe: WanMine_God_Slayer_Battleaxe (70 XP)
- Maces: WanMine_Helioram_Mace, WanMine_Maelstrom_Mace, WanMine_Mjollnir_Mace (65-70 XP)
Technical
- StaffDefaults.java - Added Weapon_Staff_Bo_Wood
- SwordDefaults.java - Added Legendary tier with 3 WanMine swords
- LongswordDefaults.java - Added 2 WanMine longswords to Legendary tier
- DaggerDefaults.java - Added Legendary tier with 7 WanMine daggers
- BattleaxeDefaults.java - Added Legendary tier with WanMine_God_Slayer_Battleaxe
- MaceDefaults.java - Added Legendary tier with 3 WanMine maces
v0.4.0
New Features
- Skill Tree Scrolling - Skill tree UI now scrolls when there are many tiers
- XP Progress Bar - Skill tree header shows progress bar to next level with "current / needed" XP format
- STAT_MANA Reward - New reward type for increasing maximum mana
- Complete 10-Tier Reward Redesign - All 16 skills now have 10 tiers of rewards (Lv 5, 10, 15, 20, 30, 40, 50, 65, 75, 100)
Mana System Design
Players start with 0 mana - it must be earned through skill tree choices. Each skill class has a distinct mana identity:
- Staves - THE mana class (360+ max mana potential). Bo staff masters channel mystical energy
- Archery - High mana (290+) for wand and spellbook users
- Crafting - Moderate mana (305) for enchanting and magical item creation
- Block/Harvesting - Low mana (65-180) for survivability or nature attunement
- Physical Combat (Swords, Daggers, Axes, Blunt, Polearms) - Minimal mana (15-38). Warriors rely on steel, not sorcery
- Gathering (Mining, Woodcutting, Excavation) - Minimal mana (23-38). Laborers focus on physical prowess
- Acrobatics/Building - Zero mana. Pure physical disciplines focused on stamina
Tier Structure
| Tier | Level | Choices | Required |
| ---- | ----- | ------- | -------- |
| 0-1 | 5-10 | 2 | 1 |
| 2-3 | 15-20 | 3 | 1 |
| 4-5 | 30-40 | 4 | 2 |
| 6-7 | 50-65 | 5 | 2 |
| 8 | 80 | 5 | 3 |
| 9 | 100 | 6 | 3 |
Technical
- SkillTreePage.ui:
#TiersListLayoutMode changed to TopScrolling - SkillTreePage.ui: Added
#SkillProgressProgressBar in header - SkillTreePage.java: Added progress calculation using getLevelProgress()
- SkillTreePage.java: Fixed ProgressBar.Value to use double instead of String
- SkillTreePage.java: MAX_CHOICES increased from 5 to 6 for tier 9
- RewardType.java: Added STAT_MANA enum
- StatModifierUtil.java: Added applyManaBonus/removeManaBonus methods
- StatManaEffect.java: New effect handler
- RewardEffectRegistry.java: Registered StatManaEffect
- LocalizationConfig.java: Added reward.stat_mana to all 5 languages
- SkillTreeDefaults.java: Complete rewrite with 10 tiers for all 16 skills
v0.3.5
Bug Fixes
- Leaderboard Combat Skill Filters - Fixed combat category only showing 6 of 10 skills in the filter bar
- Added SkillFilter6-9 buttons to support all combat skills
- All 10 combat skills now visible: Swords, Daggers, Polearms, Staves, Axes, Blunt, Archery, Unarmed, Block, Acrobatics
- Archery XP Defaults - Removed magic staves from Archery skill
- Staves (magic/ranged) were incorrectly included in Archery defaults
- Staves now correctly belong only to the STAVES skill (melee staves)
Technical
- LeaderboardPage.ui - Added
#SkillFilter6through#SkillFilter9buttons - LeaderboardPage.java:217 - Changed skill filter loop from
i < 6toi < 10 - ArcheryDefaults.java - Removed
StaffDefaults.getDefaults()call
v0.3.4
New Features
- Leaderboard Page - View player rankings accessible from ViewXpPage
- Shows all players ranked by total level and XP
- Sort by category: Total Level, Gathering, Combat, Production
- Drill down by individual skill within each category
- Your rank displayed at the bottom with highlighting
- Scrollable player list for large servers
Balance Changes
- Leveling Curve Rebalanced - Adjusted
baseXpPerLevelandlevelScaleMultiplierdefaults - Level 120 now requires approximately 1 million XP
- Default
levelScaleMultiplierchanged from 1.0 to 1.1 - Creates more meaningful late-game progression
- Existing servers can adjust via
/mmoconfig basexpand/mmoconfig scalecommands
Technical
- Scrollable UI Pattern -
LayoutMode: TopScrollingenables vertical scrolling in UI containers - New Files:
-
LeaderboardPage.java- Leaderboard page logic with player data gathering and sorting -
LeaderboardPage.ui- Layout with scrolling player list and filter buttons -
LeaderboardRow.ui- Template for individual player rank rows - ViewXpPage.java - Added Leaderboard tab navigation
- ViewXpPage.ui - Added Leaderboard tab button
- LocalizationConfig.java - Added leaderboard localization keys for all 5 languages
v0.3.3
New Features
- Hungarian Localization - Added Hungarian (Magyar) as a supported language
- Full translation of all UI text, notifications, skill names, and reward types
- More Crossbow Tiers Mod Support - Added default XP values for crossbows from the More Crossbow Tiers mod
Bug Fixes
- Config Reload Command - Fixed
/mmoconfig reloadoverwriting user config edits - Manual file edits are now preserved when using reload command
- Version check only runs on server startup, not manual reloads
Technical
- Config Version System - Replaced hash-based version tracking with simple version numbers
-
ConfigVersionUtil.CURRENT_CONFIG_VERSION- Bump this constant when defaults change - Configs now store
configVersionfield instead of computed hash - More reliable: user edits don't trigger false "defaults changed" detection
- SkillConfig.java / SkillTreeConfig.java -
load(false)skips version check for manual reloads
v0.3.2
New Features
- Portuguese Localization - Added Portuguese (Português) as a supported language
- Full translation of all UI text, notifications, skill names, and reward types
- Select Portuguese in Settings page
Bug Fixes
- Settings Language Selector - Fixed backup language files appearing in the language selector
- Files like
messages-en_backup.jsonno longer show as selectable languages - Only valid language files (
messages-XX.json) are displayed
Technical
- LocalizationConfig.java - Added filter to exclude
_backupfiles from language scanning - LocalizationConfig.java - Added
getPortugueseDefaults()with full Portuguese translations
v0.3.1
New Features
- Tier 7 Rewards - Added Level 65 milestone rewards for all 16 skills
- Master-tier bonuses: higher luck, health, damage, defense values
- Each skill gets 5 new reward choices at this tier
Balance Changes
- Stamina Rewards Rebalanced - Base stamina is 10, so rewards were scaled down
- Early tiers (5-15): +1 stamina
- Mid tiers (30-50): +2 stamina
- Master tier (65): +3 stamina
- Maximum stamina from all skill trees is now ~15-20 (was 100+)
Bug Fixes
- Config Backup System - Fixed bug creating nested
_backup_backup_backup...files - Backup files are now skipped when creating backups
- Added automatic cleanup of malformed backup files on startup
- Config Auto-Update - Configs now regenerate from new defaults when mod updates
- Old configs are backed up to
*_backup.jsonbefore regeneration - Ensures players get new tiers and balance changes automatically
Technical
- ConfigVersionUtil.java - Added
cleanupMalformedBackups()method - SkillConfig.java - Regenerates from defaults when hash changes instead of merging
- SkillTreeConfig.java - Same auto-regeneration behavior
- SkillTreeDefaults.java - Added tier 7 for all skills, fixed stamina values
- MMOSkillTreePlugin.java - Calls cleanup on startup for both config dirs
v0.3.0
New Features
- Luck System (renamed from Double Drop) - Complete overhaul of bonus drop mechanics
- Renamed
RewardType.DOUBLE_DROP→RewardType.LUCKthroughout codebase - New configurable
luckLootTable- maps block patterns to specific item drops - Block breaks (Mining, Excavation): Only gives luck bonus if loot table match exists
- Item pickups (Harvesting): Defaults to same item as bonus
- Default loot table includes all ore tiers (Copper → Onyxium) → raw ore items
- Default loot table includes all gems (Diamond, Emerald, Ruby, etc.) → gem items
- Creative Mode XP Disable - XP gains are now disabled by default in creative mode
- New config option
disableXpInCreative(default: true) - Toggle via
/mmoconfig creative --args= - Players in creative mode will not gain XP unless this setting is changed
UI/Text Improvements
- Luck Reward Text - Now specifies which skill the luck bonus applies to
- Before: "+5% Double Drop" (generic)
- After: "+5% Mining Luck" (skill-specific)
- Uses localization system with new
reward.luck_suffixkey - Defense renamed to Block - Clarifies that this stat is different from Hytale's built-in defense
- All reward text now shows "Block" instead of "Defense"
- Updated in all three languages (EN: "Block", ES: "Bloqueo", FR: "Blocage")
Breaking Changes
- Config field
doubleDropLootTablerenamed toluckLootTable - Existing configs will need to rename this field manually
Technical
- New Files:
-
LuckUtil.java- Luck bonus logic (renamed from DoubleDropUtil) -
LuckDefaults.java- Default loot table mappings (renamed from DoubleDropDefaults) - Renamed Methods:
-
SkillTreeService.getDoubleDropChance()→getLuckChance() -
SkillConfig.getDoubleDropLootTable()→getLuckLootTable() -
SkillConfig.getDoubleDropItem()→getLuckItem() - SkillConfig.java - Added
disableXpInCreativefield, renamed loot table fields - SkillService.java - Added creative mode check in
processTrigger() - MMOConfigCommand.java - Added
creativesubcommand for toggling the setting - Messages.java - Added LUCK handling in
getRewardDisplayText()to include skill name - LocalizationConfig.java - Added
reward.luck_suffix, renamed fromreward.double_drop_suffix - SkillTreeDefaults.java - All DOUBLE_DROP rewards renamed to LUCK
v0.2.9
Bugfixes
- Fixed critical hit notification - Now shows multiplier (x1.5) instead of total damage amount
- Fixed lifesteal notification - Removed duplicate
+sign that was appearing in heal messages
Technical
- DoubleDropUtil.java - Extracted double drop logic to shared utility class for DRY
- PickupItemEventSystem - Refactored to use
DoubleDropUtil.tryDoubleDrop()instead of inline implementation
v0.2.8
New Features
- 4 New Melee Combat Skills - Weapon types split from Swords/Axes for more focused progression:
- DAGGERS - Daggers, claws, kunai (high crit chance, fast attacks)
- POLEARMS - Spears, halberds (reach weapons, defensive bonuses)
- STAVES - Bo staffs, melee staves (disciplined, stamina-focused)
- BLUNT - Clubs, maces (heavy hitters, high damage and health)
Bugfixes
- Combat Effect Notifications - Added missing notifications for critical hits, defense blocks, and fall damage reduction (previously only lifesteal had notifications)
Combat Skill Changes
- SWORDS now covers only longswords and one-handed swords (bladed slashing weapons)
- AXES now covers only axes and battleaxes (chopping weapons)
- Daggers, spears, and melee staves moved to their own dedicated skills
- Clubs and maces moved to new BLUNT skill
Skill Tree Additions
- 4 New Skill Trees with thematic reward progressions:
- DAGGERS: High crit scaling (up to +15%), strong lifesteal
- POLEARMS: Balanced offense/defense, high defense bonuses
- STAVES: Stamina-focused, good defense and fall reduction
- BLUNT: Highest raw damage (+14%), highest health (+28%)
Technical
- Config Version Hashing - Config files now track a
defaultsHashto detect when mod defaults change - Automatically creates backup (e.g.,
skill-config_backup.json) before loading if defaults changed - Protects user customizations when updating the mod
- New config files:
DaggersDefaults.java,PolearmsDefaults.java,StavesDefaults.java,BluntDefaults.java - New utility:
ConfigVersionUtil.javafor hash generation and backup management - Updated
SkillType.javawith 4 new enum values - Updated
SkillTreeDefaults.javawith 4 new skill tree methods - Total implemented skills: 16 (was 12)
v0.2.7
Bugfixes
- Fixed Archery skill not gaining XP - Archery now correctly awards XP when dealing damage with bows, crossbows, wands, and other ranged weapons
- Changed Archery trigger type from
DEAL_DAMAGE_PROJECTILEtoDEAL_DAMAGE_PHYSICAL - Removed unused
DEAL_DAMAGE_PROJECTILEtrigger type
v0.2.6
New Features
/setmmoxpCommand - Admin command to set player XP directly-
/setmmoxp- Set XP for a specific skill -
/setmmoxp all- Set XP for all skills at once - Alias:
/setxp - Configurable permission via
setXpRequiredGameModein config
Bugfixes
- Fixed torches giving Woodcutting XP - Torches no longer incorrectly award Woodcutting experience when broken
Configuration
setXpRequiredGameMode- New config option inconfig.json- Controls who can use
/setmmoxpcommand - Values:
"OP"(default),"Adventure","Creative", etc. - Example: Set to
"Creative"to allow creative mode players to use the command
v0.2.5
Bugfixes
- Fixed BONUS_XP reward display - Now correctly shows the target skill name
- Before: "+5% Bonus XP" (generic)
- After: "+5% Mining XP" or "+5% Excavation XP" (skill-specific)
- Extracts skill from reward ID (e.g.,
excavation_xp_1→ Excavation) - Works correctly when skill trees offer XP bonuses for related skills
Technical
Messages.extractSkillFromRewardId()- Parses reward ID to determine target skill- BONUS_XP rewards now display localized skill name + "XP" suffix
v0.2.4
New Features
- Localization System - Full i18n support for all UI text
- Players can select their preferred language in Settings
- Language preference saved per-player in SkillComponent
- Auto-generated English, Spanish, and French language files
- Users can add custom
messages-{lang}.jsonfiles for additional languages
- Language Selector - New section in Settings page
- 6 language button slots in 2 rows of 3
- Currently selected language highlighted in green
- Disabled style for unavailable language slots
- Instant language switching without restart
- Auto-Generated Language Files - Located in
mods/mmoskilltree/localization/
-
messages-en.json- English (auto-generated) -
messages-es.json- Spanish (auto-generated) -
messages-fr.json- French (auto-generated) - Files auto-update with new keys on server start
- Localized Reward Text - Skill tree rewards fully localized
- Reward type names (e.g., "Max Health" → "Santé Max" in French)
- Formatted values with localized patterns (+5%, +10, +3 blocks)
- Reward claimed notifications use localized text
- Hot-Reload Support -
/mmoconfig reloadlangcommand - Reload language files without server restart
- New translations take effect immediately
Technical
- New
i18n/package:
-
LocalizationConfig.java- Singleton config manager for language files - Loads/saves JSON message files using GSON
- Scans for available
messages-*.jsonfiles - Placeholder substitution with
{0},{1}format - Merges file contents with defaults (preserves user customizations while adding new keys)
- Always falls back to English defaults (never shows raw keys)
-
Messages.java- Static helper class for message access -
get(skills, key)/get(skills, key, args...)- Get translated message -
getSkillName(skills, skillType)- Get localized skill name -
getRewardTypeName(skills, rewardType)- Get localized reward type name -
getRewardFormattedValue(skills, reward)- Get localized formatted value -
getRewardDisplayText(skills, reward)- Get full localized reward text
- SkillComponent.java - Added
languagefield (default: "en")
- Codec entry for persistence
-
getLanguage()/setLanguage()methods
- UI Localization - All UI text now uses Messages helper
- ViewXpPage - Panel titles, tabs, labels, buttons
- SkillTreePage - Tier labels, status text, buttons
- SettingsPage - All setting labels and descriptions
- SkillRow/TierRow templates - Dynamic text via indexed selectors
- SettingsPage.ui - Added element IDs for dynamic localization
-
#SettingsTitle,#XpNotificationsLabel,#XpNotificationsDesc -
#CombatEffectsLabel,#CombatEffectsDesc -
#XpThresholdLabel,#XpThresholdDesc -
#LanguageLabel,#LanguageDesc -
#LangBtn0through#LangBtn5with@DisabledButtonStyle
- ViewXpPage.ui - Added
#SkillsHeaderID for localization
- MMOConfigCommand.java - Added
reloadlangsubcommand
Message Key Structure
{
"language.name": "English",
"ui.button.close": "CLOSE",
"ui.button.back": "< BACK",
"ui.viewxp.title": "Skill Overview",
"ui.viewxp.level_prefix": "Lv. {0}",
"ui.settings.language": "Language",
"notify.xp_gain": "+{0} {1} XP",
"notify.level_up": "LEVEL UP! {0} is now Level {1}!",
"skill.mining": "Mining",
"reward.stat_health": "Max Health",
"reward.bonus_xp": "Bonus XP",
"reward.format.percent": "+{0}%",
"reward.format.flat": "+{0}"
}
Adding Custom Languages
1. Create mods/mmoskilltree/localization/messages-{code}.json
2. Copy structure from messages-en.json
3. Translate values (keys must remain the same)
4. Run /mmoconfig reloadlang or restart server
5. Language appears in Settings selector
v0.2.3
New Features
- Dynamic Skill Tree Choices - Configurable number of choices per tier (up to 5)
- New
choicesRequiredfield onSkillTreeNode- how many rewards to pick per tier - Global
defaultChoicesRequiredin config (default: 1) - UI shows "Pick X of Y" when tier has multiple selections
- Tier status shows completion progress (e.g., "1/2" when partially complete)
- Multi-Select Rewards - Players can now pick multiple rewards per tier
- Higher tiers offer more choices with multi-select (Pick 2 of 4)
- Prevents claiming same reward twice
- Tier only marked complete when all required choices made
- Dynamic UI Rendering - Choice buttons rendered dynamically
- New
ChoiceButton.uitemplate appended per choice - Buttons use FlexWeight for automatic sizing
- Supports 2-5 choices per tier
- Removed hardcoded button limits
- Expanded Reward Variety - Updated skill tree defaults
- Tiers 0-1: 2 choices, pick 1
- Tiers 2-3: 3 choices, pick 1
- Tiers 4-5: 4 choices, pick 2
- Tier 6 (Level 50): 5 choices, pick 2 - Elite rewards for all 12 skills
- More diverse reward options per tier
- Tier 6 Elite Rewards (Level 50) - All 12 skills now have elite tier rewards
- Gathering: +20% XP, +15% Double Drops, +20 Health, +15 Stamina, synergy bonuses
- Combat: +10% Damage, +12-15% Crit, +8-10% Lifesteal, +20 Health
- Defense: +12% Defense, +30 Health, -40% Fall Damage, +5% Lifesteal
- Acrobatics: -50% Fall Damage, +20 Health, +8% Defense, +20 Stamina
- Crafting/Building: +20% XP, +20 Health/Stamina, synergy bonuses
Technical
- SkillTreeNode.java - Added
choicesRequiredfield with new constructor - SkillComponent.java - Multi-claim storage using comma-separated reward IDs per tier
-
getClaimedRewardIds(skill, tier)returns list of claimed IDs -
getClaimedCount(skill, tier)returns count for tier -
hasClaimedSpecificReward(skill, tier, rewardId)checks specific claim - SkillTreeConfig.java - Added
defaultChoicesRequiredglobal setting and JSON codec - SkillTreePage.java - Dynamic button rendering with FlexWeight layout
- SkillTreeService.java - Updated claiming logic for multi-select validation
- TierRow.ui - Removed hardcoded buttons, added
#SelectionInfolabel - ChoiceButton.ui - New template for dynamic choice buttons
Config Schema Update
{
"defaultChoicesRequired": 1,
"skillTrees": {
"MINING": [{
"tier": 4,
"levelRequired": 30,
"choicesRequired": 2,
"choices": [...]
}]
}
}
Upgrade Notes
Run /mmoconfig reloaddefaults to load the new multi-choice tier defaults.
v0.2.2
Bugfixes
- Fixed double drops not working - Double drops now actually add bonus items to inventory
- Moved double drop logic from
BreakBlockEventSystemtoPickupItemEventSystem - When items are picked up, checks DOUBLE_DROP reward chance for the relevant skill
- Bonus items are added directly to inventory (hotbar prioritized) via
getCombinedHotbarFirst().addItemStack() - Notification now shows item count: "Double Drop! (+3)"
v0.2.1
Bugfixes
- Fixed duplicate component error - Resolved
IllegalArgumentException: Entity contains component typecrash when multiple XP events fired in the same tick (e.g., breaking multiple blocks rapidly or combat with multiple hits) - Added pending component cache to prevent duplicate
addComponentcalls before CommandBuffer consumption
v0.2.0
New Features
- Reward Effect Framework - Pluggable system for reward effects with handler registry
-
RewardEffectHandlerinterface for all effect types -
RewardEffectRegistrysingleton maps RewardType to handlers -
RewardEffectContextprovides store, ref, playerRef, skills to handlers
- 9 Implemented Reward Types - Beyond XP bonuses:
- STAT_HEALTH - Increases max health via Hytale's EntityStatMap
- STAT_STAMINA - Increases max stamina via EntityStatMap
- STAT_DAMAGE - Multiplies outgoing damage
- STAT_DEFENSE - Reduces incoming damage (capped at 90%)
- CRITICAL_CHANCE - Chance for 1.5x damage on attacks
- LIFESTEAL - Heals attacker for percentage of damage dealt
- DOUBLE_DROP - Chance for bonus resources when gathering
- FALL_DAMAGE_REDUCTION - Reduces fall damage (capped at 90%)
- BONUS_XP - Multiplies XP gain (existing)
- Combat Effect Notifications - New settings toggle for lifesteal/crit feedback
- Toggle via Settings > Combat Effect Notifications
- Lifesteal shows green "+X.X" heal notification
- Saved per-player in SkillComponent
- Hytale EntityStatMap Integration - Direct stat modification
-
StatModifierUtilhelper class for health/stamina modifiers - Uses
DefaultEntityStatTypes.getHealth()andgetStamina() -
StaticModifierwithModifier.ModifierTarget.MAXfor permanent bonuses -
healEntity()for lifesteal healing
- Expanded Skill Tree Defaults - 10 tiers with varied reward types
- Gathering skills: BONUS_XP, DOUBLE_DROP, STAT_STAMINA, STAT_DEFENSE, STAT_HEALTH
- Combat skills: BONUS_XP, STAT_DAMAGE, CRITICAL_CHANCE, LIFESTEAL, STAT_HEALTH
- Defense: STAT_DEFENSE, STAT_HEALTH, FALL_DAMAGE_REDUCTION
- Acrobatics: FALL_DAMAGE_REDUCTION (10%→40%), STAT_STAMINA, STAT_DEFENSE
- Debug Starting Level - Config option for testing high-level gameplay
- Set
debugStartingLevelin config.json to initialize new players at that level - Set to 0 (default) for production
Technical
- New
reward/package:
-
RewardEffectHandler.java- Interface for effect handlers -
RewardEffectRegistry.java- Singleton registry -
RewardEffectContext.java- Context holder -
StatModifierUtil.java- Hytale stat integration -
effects/PassiveEffect.java- Base for passive effects -
effects/StatHealthEffect.java- STAT_HEALTH handler -
effects/StatStaminaEffect.java- STAT_STAMINA handler -
effects/NoOpEffect.java- Placeholder for deferred types
- CombatDamageEventSystem enhancements:
- Uses
DamageModule.get().getFilterDamageGroup()to modify damage before health loss -
applyAttackerEffects()- Damage bonus + critical chance -
applyDefenseReduction()- Defense damage reduction -
applyFallDamageReduction()- Fall damage reduction -
applyLifesteal()- Heal on damage with optional notification
- BreakBlockEventSystem enhancements:
-
checkDoubleDrops()- Random check for double drops - Notification when double drop triggers
- SkillComponent additions:
-
showCombatEffectsboolean for combat notification preference - Codec entry for persistence
- SkillTreeService additions:
-
getTotalLifesteal(),getTotalHealthBonus(),getTotalStaminaBonus() - Effect application on claim/reset
Upgrade Notes
Run /mmoconfig reloaddefaults after upgrading to load the new 10-tier skill trees with varied reward types.
v0.1.1
New Features
- Settings Page - New in-game settings UI accessible via the Settings tab on ViewXpPage
- Toggle XP notifications on/off with a single click
- Choose XP gain threshold from preset values (1, 5, 10, 25, 50, 100)
- Visual feedback for current settings state
- Back button to return to skill overview
- Expanded Skill Tree Defaults - All 12 implemented skills now have 6 tiers of rewards
- Previously some skills had only 2-4 tiers
- Consistent progression across Mining, Woodcutting, Excavation, Harvesting, Swords, Axes, Archery, Unarmed, Defense, Acrobatics, Crafting, and Building
- Updated skill pairings for meaningful choices (Harvesting now pairs with Excavation/Crafting instead of unimplemented Cooking/Alchemy)
- Dynamic Skill Tree UI - Skill tree page now uses template-based dynamic rendering
- Automatically scales to display any number of tiers
- Improved visual styling with larger fonts and clearer status indicators
Upgrade Notes
Important: After upgrading to v0.1.1, run /mmoconfig reloaddefaults to load the new 6-tier defaults for all skills. This will reset your skill tree configuration to the new defaults.
v0.1.0
New Features
- Skill Tree System - Unlock XP bonus rewards at level milestones
- 6 tiers per skill, unlocked at levels 5, 10, 15, 20, 30, 40
- Each tier offers a choice between XP bonus for the main skill OR a related skill
- Example: Mining tier lets you choose +5% Mining XP OR +5% Excavation XP
- Rewards persist across sessions via ECS component
- Meaningful Reward Choices - Each skill pairs with thematically related skills:
_(TEMPORARY UNTIL MORE COMPLEX IMPLEMENTATION)_
- Mining ↔ Excavation, Smithing
- Woodcutting ↔ Building, Crafting
- Excavation ↔ Mining, Harvesting
- Harvesting ↔ Cooking, Alchemy
- Swords ↔ Defense, Axes
- Axes ↔ Swords, Woodcutting
- Archery ↔ Crafting, Acrobatics
- Unarmed ↔ Acrobatics, Defense
- Defense ↔ Acrobatics, Swords
- Acrobatics ↔ Defense, Unarmed
- Crafting ↔ Mining, Smithing
- Building ↔ Woodcutting, Crafting
- Skill Tree UI (
SkillTreePage)
- Navigate between skills with arrow buttons
- Shows tier status: LOCKED (gray), AVAILABLE (white), or CLAIMED (green)
- Color-coded buttons show selection state
- Reset button to clear all selections for current skill
- Opens via
/skilltreecommand or Tree button on ViewXpPage
- ViewXpPage Enhancement - Added "Tree" button next to each skill to jump directly to its skill tree
- Bonus XP System - Claimed BONUS_XP rewards apply multiplicatively to XP gains
- Stack bonuses from multiple tiers for compounding effect
- Milestone Notifications - Players notified when new tiers unlock
- Automatic detection when leveling up
- Prompts players to use
/skilltreeto claim
New Commands
/skilltree [skill]- Open the skill tree UI- Aliases:
/st,/rewards
Configuration
- New config file:
config/mmoskilltree/skilltree.json - Configurable level thresholds per tier
- Per-skill reward choices with custom values
- Currently supports BONUS_XP reward type (other types defined but not yet implemented)
Technical
- New data classes:
-
RewardType.java- Enum of reward types (BONUS_XP implemented, others placeholder) -
SkillReward.java- Configurable reward with id, type, value, display name -
SkillTreeNode.java- Milestone with level threshold and reward choices
- New config classes:
-
SkillTreeConfig.java- Singleton config for skill trees with JSON persistence -
SkillTreeDefaults.java- Default rewards with meaningful skill pairings
- New service:
-
SkillTreeService.java- Milestone checking, reward claiming, XP multiplier calculations
- New UI:
-
SkillTreePage.java- Interactive page with claim/reset/navigate actions -
SkillTreePage.ui- Layout with 6 tiers, 2 choices each, navigation and reset buttons
- Extended SkillComponent:
-
claimedRewards- Map of skill → claimed reward IDs per tier -
pendingRewards- Map of skill → pending milestone notifications -
resetRewards(skill)/resetAllRewards()- Clear claimed rewards - String serialization for codec compatibility
- Extended MMOSkillTreeAPI:
-
updateSkillComponent(PlayerRef, SkillComponent)- Explicit update hook
- Modified SkillService:
- Integrated milestone checks on XP gain
- Applies bonus XP multiplier from claimed rewards
v0.0.11
New Features
- Combat XP System - Full implementation of combat skills via
CombatDamageEventSystem
- SWORDS - XP for melee damage with longswords, daggers, spears, claws, staves
- AXES - XP for melee damage with axes, clubs, maces, battleaxes
- ARCHERY - XP for ranged damage with bows, crossbows, wands, spellbooks, guns, bombs
- UNARMED - XP for dealing damage without weapons
- DEFENSE - XP for taking damage from any source
- ACROBATICS - XP for surviving fall damage
- Material-Tiered XP Values - Rare weapons give more XP than common ones
- Common (Crude, Copper, Tribal): 5-6 XP
- Uncommon (Iron, Bronze, Scrap): 7-9 XP
- Rare (Cobalt, Adamantite, Thorium): 20-32 XP
- Epic (Mithril, Onyxium): 45-55 XP
- Legendary (Flame, Void, Spectral): 55-70 XP
- New Skills (in SkillType enum, not yet implemented)
- FISHING, TAMING, REPAIR, ALCHEMY, ENCHANTING, COOKING, SMITHING
Technical
- Separate defaults files for maintainability:
-
SwordsDefaults.java- Longswords, daggers, spears, staves (melee) -
AxesDefaults.java- Axes, clubs, maces (blunt weapons) -
ArcheryDefaults.java- Bows, crossbows, wands, spellbooks, guns, bombs - SkillDefaults.java now delegates to per-skill defaults files
- New TriggerTypes:
DEAL_DAMAGE_PHYSICAL,DEAL_DAMAGE_PROJECTILE(replacedDEAL_DAMAGE) - Weapon detection uses
inventory.getActiveHotbarItem().getItemId()for pattern matching - Patterns match actual item IDs (e.g.,
Weapon_Longsword_Mithril,Weapon_Axe_Iron)
v0.0.10
New Features
- Crafting XP - New
CraftRecipeEventSystemawards XP when crafting items - Building XP - New
PlaceBlockEventSystemawards XP when placing blocks - CRAFTING skill - New general crafting skill type (15 XP per craft by default)
- BUILDING skill defaults - Placing blocks now awards XP at 50% of the breaking value (e.g., placing stone = 2 XP vs mining stone = 3 XP)
Technical
- New
event/CraftRecipeEventSystem.java- HandlesCraftRecipeEventfor crafting XP - New
event/PlaceBlockEventSystem.java- HandlesPlaceBlockEventfor building XP SkillDefaults.getBuildingDefaults()dynamically computes values from mining/woodcutting/excavation at 50%
v0.0.9
New Features
- Quick threshold commands - Set XP display threshold with
/xpd 10,/xpd 20,/xpd 0, etc.
Bugfixes
- Progress bar display - Fixed progress bar rendering in skill UI
v0.0.8
Bugfixes
/mmoconfig reloaddefaults- Now properly saves config after reloading defaults (previously only applied in-memory)
Changes
- Enhanced notifications - XP gain and level up messages now use the notification system instead of chat messages for better visibility
v0.0.7
New Features
- ViewXpPage - New custom UI page for viewing skill stats
- Shows total level, total XP, and number of active skills
- Displays individual skill progress for all configured skills
- Only shows skills with XP configuration data (unconfigured skills hidden)
- Open via
player.getPageManager().setPage(ref, store, new ViewXpPage(playerRef))
Technical
- New
pages/package for custom UI pages - UI files in
src/main/resources/Common/UI/Custom/Pages/ - Updated CLAUDE.md with UI page documentation and naming conventions
v0.0.6
New Features
/mmoconfig reloaddefaults- New admin command to reset all XP values to built-in defaults fromSkillDefaults.java
v0.0.5
New Features
- Comprehensive default XP values for all Hytale blocks based on official item database
- Mining: 10+ rock types, 9 ore tiers (Copper→Onyxium), 7 gem types
- Woodcutting: 30+ tree types across 5 tiers (Common→Special)
- Excavation: All soil types including grass, sand, mud, snow, ash
- Harvesting: Grass, ferns, bushes, flowers, crops, fruits, coral, vines
- PickupItemEventSystem - Awards XP when picking up items
Changes
- Professional package structure - Reorganized codebase:
-
api/- Public API for other plugins -
command/- Command handlers -
config/- Configuration and defaults -
data/- Data models (SkillComponent, SkillType) -
event/- Event system handlers -
service/- Business logic -
util/- Utility classes - SkillDefaults.java - Centralized default XP values (separated from config)
- Updated import paths:
com.ziggfreed.mmoskilltree.api.MMOSkillTreeAPI,com.ziggfreed.mmoskilltree.data.SkillType
v0.0.4
Bugfixes
- Fixed issue with "harvesting" blocks not rewarding xp
v0.0.3
New Skills
New skills added for developers to access via API
New Features
- Public API (
MMOSkillTreeAPI) for other plugins to access player skill data -
getSkillComponent(PlayerRef)- Get full skill data -
getXp(PlayerRef, SkillType)/getLevel(PlayerRef, SkillType)- Get specific skill data -
getTotalXp(PlayerRef)/getTotalLevel(PlayerRef)- Get combined stats -
getAllXp(PlayerRef)/getAllLevels(PlayerRef)- Get all skills as maps -
addXp(PlayerRef, SkillType, long)- Add XP (silent) -
removeXp(PlayerRef, SkillType, long)/setXp(PlayerRef, SkillType, long)- Modify XP -
getLevelProgress(PlayerRef, SkillType)- Get progress to next level (0.0-1.0) -
calculateLevelFromXp(long)/getXpRequiredForLevel(int)- Utility methods -
hasSkillData(PlayerRef)/getSkillTypes()- Helper methods - New skill category: Misc (for Building and future utility skills)
- New trigger types:
PLACE_BLOCK,FALL_DAMAGE,TAME_ENTITY,CATCH_FISH
Changes
/mmoxpnow only shows skills with XP > 0 (cleaner display)- Plugin instance now accessed via
MMOSkillTreePlugin.getInstance()(singleton pattern) - Commands now extend
AbstractPlayerCommandwithPlayerRefparameter - Internal services use API for cache access (DRY principle)
- Consistent cache keying via
PlayerRef.hashCode()
v0.0.2
Changes
- Changed default XP gain threshold for message display from 0 to 10
- Fixed permission issue with
/xpdisplaycommand
v0.0.1 - Initial Release
Skills
- Mining - Gain XP from breaking stone and ores
- Woodcutting - Gain XP from chopping trees and logs
- Excavation - Gain XP from digging soil and dirt
- Harvesting - Gain XP from harvesting plants and crops
Features
- Quadratic XP scaling formula for balanced progression
- Per-player XP display preferences (toggle on/off, set minimum threshold)
- Persistent player data via ECS component codec
- JSON config file with hot-reload support
- Pattern-based block matching for flexible XP configuration
Commands
/mmoxp- View your skill levels and XP progress/xpdisplay- Configure personal XP notification settings-
on/off- Toggle XP gain messages -
threshold --value=- Only show gains >= n XP -
status- View current settings /mmoconfig(OP only) - Server configuration-
list --args=- View XP configurations -
- Set XP for block pattern--args= -
basexp --args=- Set base XP per level -
scale --args=- Set leveling speed -
remove --args=- Remove block pattern -
reload- Reload config from file
Technical
- Dynamic skill system - adding new skills only requires enum entry + defaults
- TriggerType system for future event handlers (combat, crafting, etc.)
- Thread-safe skill caching for command access
- Auto-generates config on first launch