promotional bannermobile promotional banner

MMO Skill Tree & Abilities

(Multiple Languages) MMO Skill Tree adds an RPG-style progression system where every action you take helps you grow stronger.

File Details

MMOSkillTree-0.6.0.jar

  • R
  • Jan 28, 2026
  • 466.87 KB
  • 2.3K
  • Early Access

File Name

MMOSkillTree-0.6.0.jar

Supported Versions

  • Early Access

Changelog

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 rewards list - All rewards are now commands (items given via /give commands)
  • 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) or PLAYER
  • 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
    • Levels 10, 25, 50, 65, 80, 100 each grant bonus items when ANY skill reaches that level
    • Tracked per-skill: Mining 50 and Swords 50 each independently trigger level 50 global rewards
    • Configurable via GLOBAL_SKILL key in command-rewards.json overrides
    • Visible in the player Rewards UI as "Lv X Bonus" rows alongside per-skill rewards
    • Default rewards scale from Life Essence + Iron Bars (Lv 10) to Prisma + Voidstone (Lv 100)

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 /say when 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 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<CommandRewardEntry> mapping
  • CommandRewardsConfig.java - Converted to override-based pattern (like XpMapsConfig)
    • Stores userOverrides separately from effective config
    • Generates _reference/defaults-command-rewards.json for server owner transparency
    • Changed configVersion to schemaVersion
    • Added globalSkillRewards / globalSkillOverrides with full getter/mutator/save/load support
  • CommandRewardsDefaults.java - All ItemReward definitions converted to /give commands
    • Added formatItemName() and getItemColor() 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 handle GLOBAL_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 claimGlobal action 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 #ToggleItemRewards button 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 #ActiveBoostsBar section with 3 boost labels
    • Added #ActiveBoostsSpacer for spacing control
  • LeaderboardDataStore.java

    • Changed data.totalLevel = skills.getTotalLevel() to data.totalLevel = skills.getSummedTotalLevel()
  • LocalizationConfig.java

    • Added ui.admin.item_rewards_label in all 8 languages
    • Added time.days_short, time.hours_short, time.minutes_short for localized time units
    • Added notify.command_reward_received in all 8 languages
  • XpBoostService.java

    • Updated formatTimeRemaining() to show Xh Ym for hours, Xd Yh for 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 <skill|all> <value> [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 - /mmoboost and /bulksetxp now use AbstractAsyncWorldCommand

    • Better console support - commands work reliably from console
    • Uses withDefaultArg for optional parameters (cleaner syntax)
    • Store operations properly dispatched to world thread via world.execute()
  • Simplified /mmoboost syntax - 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() inside world.execute() callback
    • Validates rewards after XP change (revokes if level dropped)
    • Reports success count and any failures
  • BoostCommand.java - Refactored to AbstractAsyncWorldCommand

    • Changed from AbstractPlayerCommand to AbstractAsyncWorldCommand
    • Uses withDefaultArg instead of withOptionalArg
    • Subcommands needing Store access (give, clear, status) wrapped in world.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 AbstractAsyncWorldCommand vs AbstractPlayerCommand
    • Critical pattern: world.execute() required for Store operations in async context
    • Store thread affinity causes IllegalStateException if 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 - /mmoadmin now 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.xp for the /mmoxp command

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 by PermissionUtil.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 #PermissionsHelp label and #AwardBoostBtn button

  • 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.<target>.<scope>.<mult>.<dur>.<cooldown>
  • 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 /mmoboost from 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 > 0 check semantics

Config Compatibility

  • No config version bump required - uses existing skillPermissionsEnabled setting
  • 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 CombatTarget enum: 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() and getSkillBuffsText() methods
  • XpBoostService - File-based permissions loading with reload support
  • MMOConfigCommand - Added reloadperms subcommand
  • SkillComponent - getSummedTotalLevel() now filters by XP map data

Config Compatibility

  • No config version bump required - combatTarget is 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=<player>|<target>|<multiplier>|<duration>|[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>.<scope>.<multiplier>.<duration>.<cooldown>
    • Target: all, skill name, or category name
    • Scope: self (personal) or all (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 /mmoboost command - OPs can manage boosts directly (uses --args= with | separator)

    • /mmoboost give --args=<player|*>|<target>|<mult>|<mins>|[scope] - Award boost token
    • /mmoboost global --args=<target>|<multiplier>|<minutes> - Activate global boost immediately
    • /mmoboost list - Show active global boosts
    • /mmoboost clear --args=<player> - Clear boosts and tokens
    • /mmoboost status --args=<player> - 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 - /mmoboost uses --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 -1 to 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=<skill|all|luck> - Show only overrides (XP and luck)
    • /mmoconfig trim - Remove redundant overrides from both XP and luck configs
    • /mmoconfig disable --args=<skill|pattern> - 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 - schemaVersion replaces configVersion for override-based configs

    • Schema version only bumps for structural changes (new fields)
    • Default value changes no longer require version bump
    • Old configs with configVersion are read for backwards compatibility

Admin UI

  • New /mmoadmin command - 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 /mmoconfig command and /mmoadmin UI

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

    • userOverrides map tracks only customizations
    • load() now merges file overrides on top of defaults
    • save() writes only overrides (smaller config files)
    • DISABLED_VALUE = -1 sentinel 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 schemaVersion first, falls back to configVersion
  • 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() and msg() 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() and CommandExecutor.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.)
    • CombatDamageEventSystem now detects Projectile component 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 calls removeOrphanedStatModifiers() 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() and removeOrphanedStatModifiers() 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, or scale, 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() and calculateLevel() 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 in skill-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 placedItemExpireMinutes field (default: 5)
    • Added getter/setter methods
  • PlacedBlockTracker.java - Extended to track placed item IDs
    • New TrackedItem class 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 reload now reloads ALL configs (was missing XpMaps, Luck, CommandRewards)
  • MMOConfigCommand.java - /mmoconfig reloaddefaults now 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 <skill> <value> --target=<player> - Set XP for another player
    • Requires mmoskilltree.command.setxp.others permission (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 displayName field to reward entries in command-rewards.json
    • Value must be a localization key (e.g., "reward.mining.starter_kit")
    • Add the key to your localization/messages-*.json files
    • 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 --target optional 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 displayName field 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=<player>
    • 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

    • baseXpPerLevel changed from 100 to 150
    • levelScaleMultiplier changed 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 basexp and /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) or PLAYER (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

    {
      "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
    • ItemReward inner 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 claimedCommandRewards field 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 #TabRewards button
  • ConfigVersionUtil.java - Removed shared CURRENT_CONFIG_VERSION constant
    • 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: combatXpEntityBlacklist array in skill-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<SkillType, Double>)
    • New codec entry {SKILL}FracXp for 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 combatXpEntityBlacklist field 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 blacklist subcommand
  • 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_ and Plant_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 ConcurrentHashMap with player hash -> Set of tracked blocks
    • BlockPosition record stores x, y, z coordinates
    • TrackedBlock record 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 trackPlacedBlocks and placedBlockExpireMinutes fields

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 LeaderboardDataStore cache 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 /xpdisplay were requiring permission nodes even when permission system was disabled
    • Added enableCommandPermissions config 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 enableCommandPermissions field with getter/setter and JSON serialization
  • PermissionUtil.java - Updated hasCommandPermission() to check isCommandPermissionsEnabled() 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.<skillname> or mmoskilltree.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=<true|false>

    • 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.json in mods/mmoskilltree/
  • Restore any custom XP values from the backup file after upgrading

Technical

  • ConfigVersionUtil.java - Bumped CURRENT_CONFIG_VERSION to 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 enableSkillPermissions field 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.<name> permission
    • GetXpCommand, SkillTreeCommand, XpDisplayCommand, SetXpCommand, MMOConfigCommand
  • LocalizationConfig.java - Added cmd.no_permission key 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 isOnline field to PlayerLeaderboardEntry
    • Added createEntryFromCache() method for offline player entries
    • Online/offline visual styling in leaderboard rows
  • LeaderboardRow.ui - Added #OnlineStatus indicator element
  • MMOSkillTreePlugin.java - Added leaderboard cache initialization and shutdown hook
  • LocalizationConfig.java - Added ui.leaderboard.player_count_online key 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_BatlleaxeWanMine_God_Slayer_Battleaxe

Technical

  • LocalizationConfig.java - Added getTurkishDefaults() and getGermanDefaults() with full translations
  • LocalizationConfig.java - Added ensureTurkishDefaults() and ensureGermanDefaults() methods
  • SettingsPage.java - Increased maxLangButtons from 6 to 15
  • SettingsPage.ui - Added #LangBtn3 through #LangBtn14 buttons in 3 rows of 5
  • SettingsPage.ui - Increased #LanguageSetting height from 160 to 204
  • SettingsPage.ui - Increased #LanguageButtons height 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: #TiersList LayoutMode changed to TopScrolling
  • SkillTreePage.ui: Added #SkillProgress ProgressBar 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 #SkillFilter6 through #SkillFilter9 buttons
  • LeaderboardPage.java:217 - Changed skill filter loop from i < 6 to i < 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 baseXpPerLevel and levelScaleMultiplier defaults
    • Level 120 now requires approximately 1 million XP
    • Default levelScaleMultiplier changed from 1.0 to 1.1
    • Creates more meaningful late-game progression
    • Existing servers can adjust via /mmoconfig basexp and /mmoconfig scale commands

Technical

  • Scrollable UI Pattern - LayoutMode: TopScrolling enables 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 reload overwriting 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 configVersion field 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.json no longer show as selectable languages
    • Only valid language files (messages-XX.json) are displayed

Technical

  • LocalizationConfig.java - Added filter to exclude _backup files 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.json before 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_DROPRewardType.LUCK throughout 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=<true|false>
    • 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_suffix key
  • 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 doubleDropLootTable renamed to luckLootTable
  • 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 disableXpInCreative field, renamed loot table fields
  • SkillService.java - Added creative mode check in processTrigger()
  • MMOConfigCommand.java - Added creative subcommand for toggling the setting
  • Messages.java - Added LUCK handling in getRewardDisplayText() to include skill name
  • LocalizationConfig.java - Added reward.luck_suffix, renamed from reward.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 defaultsHash to 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.java for hash generation and backup management
  • Updated SkillType.java with 4 new enum values
  • Updated SkillTreeDefaults.java with 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_PROJECTILE to DEAL_DAMAGE_PHYSICAL
    • Removed unused DEAL_DAMAGE_PROJECTILE trigger type

... https://mmo-skill-tree-docs.vercel.app/docs/changelog/