Releases: HyperSystems-Development/HyperPerms

2.10.0 — Command tab-completion, QoL fixes & QuestLines Claims compatibility

Choose a tag to compare

@nmang004nmang004 released this 24 Jun 00:52

Server Version:0.5.6 (release) · 0.6.0-pre.4 (pre-release)

Quality-of-life release: tab-completion for /hp, instant command-tree refresh, and fixes for several silently-broken integration paths — including a QuestLines Claims compatibility fix that was handing out double (or triple) the claims a permission allowed. The same codebase now runs on both the Hytale release (0.5.x) and pre-release (0.6.0-pre.x) channels.

Added

  • Tab-completion for /hp commands. Group, track, permission-node and online-player arguments now suggest as you type (case-insensitive prefix match). Previously every argument was a plain string with no completion.
  • Instant command-tree refresh. When a player's groups or permissions change, the affected online player gets a fresh command tree immediately — newly-granted commands appear without a relog.
  • Clickable download link in the "update available" notification (alongside /hp update).
  • Startup self-check that verifies the Hytale-core reflection targets used by optional integrations resolve on the running build, logging a clear warning if any are missing.

Fixed

  • QuestLines Claims granted double (or triple) the claims/rent a permission allowed. QuestLines computes claim/rent limits by summing the numeric suffix of questlinesclaims.claim.chunks.<n> / questlinesclaims.rent.limit.<n> nodes across every provider, and across both a user's permissions and each of their groups' permissions. HyperPerms exposed the same fully-resolved set through several of those surfaces (getUserPermissions, the virtual user:<uuid> group, and the native-provider sync), so each node was counted 2–3×. When QuestLines is detected, HyperPerms now collapses those to a single summable source — boolean checks are unaffected, and servers without QuestLines see no change. (LuckPerms was already special-cased by QuestLines, which is why it behaved correctly.)
  • PlaceholderAPI offline-player fallback never worked — it referenced a non-existent class (…server.HytaleServer, missing .core) and a dead getPlayerManager() chain, silently returning null. Now uses Universe.get().getPlayer(uuid).
  • MysticNameTags nameplate refresh never worked — the World class literal omitted its .world sub-package.
  • Event listener leaks across /reload — chat, tab-list and update-notification listeners stored their registration handles but never called unregister() (a stale comment claimed no such API existed). They now unregister properly instead of leaving duplicate handlers.
  • Stale "ghost" entries in the player/tab list — HyperPerms only ever added player-list entries; quitting players are now removed via RemoveFromServerPlayerList instead of lingering.

Changed

  • Centralized the Hytale-core reflection string literals (Universe, PlayerRef, World) into ReflectionUtil so a future Hytale package move is a one-line fix and the optional integrations can't drift independently.

Upgrade

Drop-in replacement for 2.9.x — no config changes. Replace the jar in mods/ and restart, using the build that matches your server channel:

  • HyperPerms-2.10.0.jar — Hytale release servers (0.5.x, manifest ^0.5.6)
  • HyperPerms-2.10.0-prerelease.jar — Hytale pre-release servers (0.6.0-pre.x, manifest ^0.6.0-pre.4)

If you run QuestLines Claims, HyperPerms prunes any duplicate questlinesclaims.* entries a previous version wrote into the native provider the first time each player connects after updating.


Requirements: Hytale 0.5.6+ (release) or 0.6.0-pre.x (pre-release), Java 25
Full Changelog:2.9.6...2.10.0
Discord:https://discord.gg/SNPjyfkYPc

2.9.6 — Hytale 0.5.2 OP recognition hotfix

Choose a tag to compare

@nmang004nmang004 released this 29 May 13:36

Server Version:0.5.2

Hotfix for operator (OP) recognition on Hytale 0.5.2. If you're on 2.9.5 and your HyperPerms admins are showing as "not OP" in-game, update to 2.9.6.

Fixed

  • HyperPerms admins were not recognized as OP on 0.5.2. Hytale 0.5.2 determines operator status by group membership — it checks whether a player is in the hytale:Admin group (getGroupsForUser(uuid).contains("hytale:Admin")), and FlyCameraModule/WorldMapTracker key off group names too. HyperPerms funnels all resolution through a single user:<uuid> virtual group, so admins were never seen in hytale:Admin and showed as "not OP" even though their permission checks passed.
  • getGroupsForUser now also advertises hytale:Admin for any user who effectively resolves the * permission (superuser). Granting a HyperPerms group the * node makes its members OP, recognized by Hytale and OP-gated features. Permission resolution itself is unchanged (still funneled through user:<uuid>).

Changed

  • Reverted the authoritative-provider mode added in 2.9.5. HyperPerms no longer removes Hytale's built-in provider; it registers itself first and keeps the built-in provider registered (its removal aggravated the OP break, because Hytale's getGroupsForUser aggregates across all providers).

Upgrade

Drop-in replacement for 2.9.5/2.9.4. No config changes. Replace the jar in mods/ and restart.


Requirements: Hytale 0.5.2+, Java 25
Full Changelog:2.9.5...2.9.6
Discord:https://discord.gg/SNPjyfkYPc

2.9.5 — Hytale 0.5.2 Support

Choose a tag to compare

@nmang004nmang004 released this 29 May 12:34

Server Version:0.5.2 ("Update 5", rev 8b2f3de, Java 25)

Compatibility release for Hytale 0.5.2. Verified by booting the local 0.5.2 server: HyperPerms loads, enables, and registers as the authoritative permission provider with no errors.

Fixed

  • Plugin failed to load on 0.5.2 (manifest). 0.5.2 added a strict SemverRange codec that rejected the manifest's bare ServerVersion (0.5.2) and the spaced >= 1.0.2 optional-dependency range. Now uses ^0.5.2 and >=1.0.2. Without this the plugin did not load at all.
  • PermissionProvider interface conformance. 0.5.2 expanded the interface from 10 to 14 methods. Implemented the four new ones (setUserGroup, getGroupParent, getAllRegisteredGroups, getEffectiveGroupPermissions).
  • Deny-by-default permission model. A group using -* (deny-all) plus specific grants previously had every granted permission silently denied on native command checks. HyperPerms now resolves these correctly — standard "deny-all, then grant" setups work, and native checks agree with /hp check.

Changed

  • Authoritative permission provider. HyperPerms now removes Hytale's built-in provider while enabled (and restores it on disable), so it is the single source of permission decisions. Manage everything via /hp — vanilla /perm, /setgroup and /op operate on data HyperPerms no longer consults, and /op self is advisory-disabled while HyperPerms is active (grant admin via a group with the * node).
  • Default build channel is now release (targets 0.5.2). Use -Phytale_channel=pre-release for pre-release builds.

Added

  • Registered the 0.5.2 built-in nodes so they surface in the web editor and wildcard expansion: hytale.world_map.teleport.coordinate, hytale.world_map.teleport.marker, hytale.system.update.notify (+ matching wildcards).

Removed

  • Obsolete warnAboutVanillaGroupOverwrite startup check (tested the legacy OP/Default group keys that no longer exist in 0.5.2).

Requirements: Hytale 0.5.2+, Java 25
Full Changelog:2.9.4...2.9.5
Discord:https://discord.gg/SNPjyfkYPc

HyperPerms v2.9.4

Choose a tag to compare

@derrickmehaffyderrickmehaffy released this 02 Apr 08:39

Fixed

  • TabListListener runtime crashUniverse.getPlayers() return type differs between Maven artifact (Collection) and runtime server (List), causing NoSuchMethodError. Fixed by copying into new ArrayList<>() to decouple from the return type descriptor

Server Version:2026.03.26-89796e57b

Full Changelog:https://github.com/HyperSystems-Development/HyperPerms/blob/main/CHANGELOG.md

HyperPerms v2.9.3

Choose a tag to compare

@nmang004nmang004 released this 28 Mar 12:37

v2.9.3 — March 26 Server Support

Server Version:2026.03.26 (release & pre-release)

What's New (since 2.9.1)

Added

  • Per-world permissionssetperm and unsetperm commands (group and user) now accept an optional world argument to restrict permissions to a specific world
  • Context display in info commands — Group and user info now shows context restrictions (e.g. [world=Survival]) on permission nodes

Fixed

  • API compatibility — Updated TabListListener to handle Universe.get().getPlayers() returning Collection<PlayerRef> instead of List<PlayerRef>, fixing compilation against the March 26 server update
  • Group inheritance priority — Child group permissions now always take precedence over inherited parent group permissions, regardless of weight values
  • LuckPerms H2 migration version mismatch — Use isolated classloader when loading H2 driver from LuckPerms libs
  • H2 driver selection — Prefer modern H2 driver over legacy to match current LuckPerms database format
  • H2 migration column access — Use unquoted column name for ResultSet access
  • Analytics flush data loss — Prevent race condition where permission check counters could be lost during flush
  • ImportCommand silent failures — Await all group save futures before reporting success
  • Non-atomic node mutations — Synchronize compound removeIf+add operations in setNode and addGroup
  • SQL serialization — Use Gson instead of hand-rolled JSON parser for correct escaping of special characters
  • Cycle detection case sensitivity — Normalize group names to lowercase in inheritance cycle detection
  • Template loader race condition — Prevent concurrent template loading from clearing the map mid-load
  • Confirmation memory leak — Clean up expired pending confirmations to prevent unbounded map growth
  • Migration thread starvation — Use dedicated executor instead of common ForkJoinPool for LuckPerms migration
  • SQLite nested ResultSet — Collect all rows before loading nodes to avoid driver conflicts on single connection
  • SQLite backup consistency — Checkpoint WAL before copying database file to capture all committed writes
  • SQLite restore PRAGMAs — Re-enable WAL and foreign_keys after restoring a backup
  • Clone command data loss — Await save future in clone command before reporting success
  • Group rename atomicity — Create new group before deleting old to prevent data loss on crash; await all save futures
  • JSON storage path traversal — Validate names on load/delete paths to prevent directory traversal
  • WildcardMatcher trace inconsistency — Add stripped-prefix matching to checkWithTrace() to match check() behavior

Full Changelog: v2.9.1...v2.9.3

HyperPerms v2.9.1

Choose a tag to compare

@nmang004nmang004 released this 09 Mar 00:31

v2.9.1 — Permission Resolution, Templates & PermissionsPlus Migration

Added

PermissionsPlus Migration Tool

Full migration support for servers transitioning from PermissionsPlus to HyperPerms.

  • /hp migrate permissionsplus — Preview migration (dry-run)
  • /hp migrate permissionsplus --confirm — Execute migration
  • Reads PermissionsPlus JSON data files and transforms groups, users, and permissions into HyperPerms format
  • Automatic permission cleaning and validation for PermissionsPlus-specific formats
  • Comprehensive test coverage for data models, permission cleaning, and validation

SSP Auto-Owner Assignment

First player to join a single-player (SSP) world is automatically assigned the owner group, removing the need for manual /hp user addgroup setup on fresh worlds.


Fixed

Permission Resolution Order

The resolver now evaluates permissions in most-specific-first order:

a.b.c → a.b.* → a.* → *

Previously, a broad wildcard like a.* could override a more specific grant or denial on a.b.c. This is now resolved — specific permissions always take priority.

Template Application with Existing Groups

/hp template apply no longer fails when groups from the template already exist on the server. Existing groups are gracefully skipped or merged instead of throwing an error.

Template Clearing Nodes and Tracks

Fixed UnsupportedOperationException when applying templates that clear existing nodes and tracks. Template application now uses proper mutable collection methods instead of operating on immutable list views.

SSP Owner Assignment Race Condition

Added synchronization guard to prevent duplicate owner group assignments when multiple players connect simultaneously during first server start.


Chore

  • Bumped version to 2.9.1
  • Updated CHANGELOG.md

Full Commit Log

TypeScopeDescription
featmigrationAdd PermissionsPlus data models
featmigrationAdd PermissionsPlus migrator with JSON reading and transformation
featmigrationRegister PermissionsPlus migrator in /hp migrate command
testmigrationAdd PermissionsPlus data model tests
testmigrationAdd PermissionsPlus permission cleaning and validation tests
refactormigrationApply code review fixes to PermissionsPlus migrator
fixresolverChange to most-specific-first permission resolution order
fixtemplateGracefully handle existing groups during template application
featsspAuto-assign owner group to first player
fixsspPrevent race condition in first-player owner assignment
fixtemplateUse proper mutable methods for clearing nodes and tracks
choreBump version to 2.9.1 and update changelog

v2.9.0-rc1: Permission Resolution, Template & SSP Fixes

Choose a tag to compare

@nmang004nmang004 released this 08 Mar 15:40

Fixes

  • Permission Resolution: Specific grants (e.g. + simpleclaims.edit-party) now correctly override global denies (- *). Resolution order changed to most-specific-first.
  • Template Application: Fixed "Failed to apply template: null" error when applying templates to servers with existing groups. Template applier now uses proper mutable methods for updating groups and tracks.
  • SSP Auto-Owner: First player on an empty server is automatically assigned the configured owner group.

Testing

Download HyperPerms-2.9.0.jar and replace your existing plugin JAR. Please report any issues.

HyperPerms v2.9.0

Choose a tag to compare

@derrickmehaffyderrickmehaffy released this 05 Mar 23:10

Hotfix: Web Editor Session Create

Fixed

  • Web editor returning 500 on /hp editor — The gzip compression introduced in 2.8.9 was applied to all session create requests, but the Cloudflare Worker API does not support Content-Encoding: gzip on incoming request bodies. This caused every /hp editor command to fail with "Server returned status 500". Compression is now only applied to payloads exceeding 500KB, keeping normal requests uncompressed while still protecting very large servers from HTTP 413 errors.

If you are on 2.8.9, update immediately.

HyperPerms v2.8.9

Choose a tag to compare

@derrickmehaffyderrickmehaffy released this 05 Mar 23:10

Architecture Rehaul & MMOSkillTree Integration

First-Class MMOSkillTree Support

HyperPerms now has full, first-class integration with MMOSkillTree — one of the biggest plugins on Hytale.

  • 200+ permission nodes registered across admin, command, skill, boost, and alternate prefix categories
  • All 23 skill nodesmmoskilltree.skill.mining, .woodcutting, .excavation, .harvesting, .fishing, .swords, .daggers, .polearms, .staves, .axes, .blunt, .archery, .unarmed, .defense, .taming, .acrobatics, .crafting, .repair, .alchemy, .enchanting, .cooking, .smithing, .building
  • All 140 XP boost permission nodes covering personal and global boosts for all skills, skill categories, and all-skills targets with varying multipliers, durations, and cooldowns
  • ziggfreed.* alternate prefix support — MMOSkillTree checks permissions through both mmoskilltree.* and ziggfreed.mmoskilltree.* prefixes. HyperPerms now correctly resolves both via bidirectional aliases
  • Hytale command path aliasescom.ziggfreed.mmoskilltree.command.* paths resolve to their mmoskilltree.command.* equivalents
  • Wildcard expansion for all MMST permission categories
  • Tab completion & web editor now show all MMST permission nodes
  • Updated RPG & Survival templates with appropriate MMST permissions at each rank tier (XP boosts scale with rank progression)

Staged Plugin Lifecycle

The plugin initialization system has been completely rewritten with a clean, modular architecture:

  • 11 ordered stages: Config → Storage → CoreManager → Resolver → Registry → Chat → Integration → Web → Scheduler → Analytics → DefaultGroups
  • PluginLifecycle orchestrator initializes stages in order and shuts them down in reverse — if any stage fails, previously initialized stages are safely torn down
  • ServiceContainer provides typed dependency injection across all stages
  • HyperPerms.java reduced from ~400 lines of monolithic init to ~25 lines — all setup logic now lives in dedicated Stage implementations

Annotation-Based Command Framework

The entire command system has been rebuilt using a declarative annotation-driven approach:

  • New annotations: @CommandGroup, @Command, @Arg, @OptionalArg, @Permission, @Confirm
  • CommandScanner automatically discovers and registers annotated command methods at startup
  • CommandDispatcher handles argument parsing, permission checks, and confirmation flows
  • 5 annotated command groups replace 42 individual command classes: GroupCommands, UserCommands, DebugCommands, RootCommands, PermsCommands, BackupCommands
  • Net reduction of ~1,500 lines with significantly better maintainability

Web Editor Improvements

  • Gzip compressed session requests — Session create payloads are now gzip compressed before sending to the API, preventing HTTP 413 errors on servers with many groups and permissions

Bug Fixes

  • Fixed config being null during early stage initialization
  • Fixed default groups being created before storage was fully ready
  • Integrated 2.8.8's centralized sync and diff-based permission logic into the new lifecycle system

HyperPerms v2.8.8

Choose a tag to compare

@derrickmehaffyderrickmehaffy released this 05 Mar 23:10

[2.8.8] - 2026-02-23

Server Version:2026.02.19-1a311a592

Fixed

  • Permission pollution in Hytale's permissions.json - syncPermissionsToHytale() previously pushed all resolved permissions on every change, causing hundreds of permissions to accumulate. Now uses diff-based sync that computes the delta between Hytale's current state and HyperPerms' resolved set, only adding missing and removing stale permissions
  • Race condition in concurrent permission syncs - Multiple threads (command thread, scheduler, CF pool, web editor) could call syncPermissionsToHytale() simultaneously for the same user, racing on Hytale's non-thread-safe HashSet view from getUserPermissions(). Added per-UUID synchronization locks and defensive copying of the live view
  • Scattered manual sync calls - Six user commands and HyperPermsPermissionProvider each had their own inline syncPermissionsToHytale() call via bootstrap reflection. Centralized all sync logic into a CacheInvalidator.setSyncListener() hook — every cache invalidation now automatically triggers Hytale sync for affected online users
  • Group commands invalidated entire cache - Group permission/property changes (setperm, unsetperm, setprefix, setsuffix, setweight, setexpiry, parent add/remove) called invalidateAll() instead of targeted invalidateGroup(), causing unnecessary cache churn for unrelated users
  • Expired permissions not synced to Hytale - ExpiryCleanupTask removed expired nodes but didn't invalidate the cache or trigger Hytale sync, so expired permissions remained active until the player reconnected
  • Inconsistent cache invalidation API - Some commands used getCache().invalidate() (bypassing sync) while others used getCacheInvalidator().invalidate() (with sync). Unified all commands to use getCacheInvalidator()
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Releases: HyperSystems-Development/HyperPerms

2.10.0 — Command tab-completion, QoL fixes & QuestLines Claims compatibility

Choose a tag to compare

@nmang004nmang004 released this 24 Jun 00:52

Server Version:0.5.6 (release) · 0.6.0-pre.4 (pre-release)

Quality-of-life release: tab-completion for /hp, instant command-tree refresh, and fixes for several silently-broken integration paths — including a QuestLines Claims compatibility fix that was handing out double (or triple) the claims a permission allowed. The same codebase now runs on both the Hytale release (0.5.x) and pre-release (0.6.0-pre.x) channels.

Added

  • Tab-completion for /hp commands. Group, track, permission-node and online-player arguments now suggest as you type (case-insensitive prefix match). Previously every argument was a plain string with no completion.
  • Instant command-tree refresh. When a player's groups or permissions change, the affected online player gets a fresh command tree immediately — newly-granted commands appear without a relog.
  • Clickable download link in the "update available" notification (alongside /hp update).
  • Startup self-check that verifies the Hytale-core reflection targets used by optional integrations resolve on the running build, logging a clear warning if any are missing.

Fixed

  • QuestLines Claims granted double (or triple) the claims/rent a permission allowed. QuestLines computes claim/rent limits by summing the numeric suffix of questlinesclaims.claim.chunks.<n> / questlinesclaims.rent.limit.<n> nodes across every provider, and across both a user's permissions and each of their groups' permissions. HyperPerms exposed the same fully-resolved set through several of those surfaces (getUserPermissions, the virtual user:<uuid> group, and the native-provider sync), so each node was counted 2–3×. When QuestLines is detected, HyperPerms now collapses those to a single summable source — boolean checks are unaffected, and servers without QuestLines see no change. (LuckPerms was already special-cased by QuestLines, which is why it behaved correctly.)
  • PlaceholderAPI offline-player fallback never worked — it referenced a non-existent class (…server.HytaleServer, missing .core) and a dead getPlayerManager() chain, silently returning null. Now uses Universe.get().getPlayer(uuid).
  • MysticNameTags nameplate refresh never worked — the World class literal omitted its .world sub-package.
  • Event listener leaks across /reload — chat, tab-list and update-notification listeners stored their registration handles but never called unregister() (a stale comment claimed no such API existed). They now unregister properly instead of leaving duplicate handlers.
  • Stale "ghost" entries in the player/tab list — HyperPerms only ever added player-list entries; quitting players are now removed via RemoveFromServerPlayerList instead of lingering.

Changed

  • Centralized the Hytale-core reflection string literals (Universe, PlayerRef, World) into ReflectionUtil so a future Hytale package move is a one-line fix and the optional integrations can't drift independently.

Upgrade

Drop-in replacement for 2.9.x — no config changes. Replace the jar in mods/ and restart, using the build that matches your server channel:

  • HyperPerms-2.10.0.jar — Hytale release servers (0.5.x, manifest ^0.5.6)
  • HyperPerms-2.10.0-prerelease.jar — Hytale pre-release servers (0.6.0-pre.x, manifest ^0.6.0-pre.4)

If you run QuestLines Claims, HyperPerms prunes any duplicate questlinesclaims.* entries a previous version wrote into the native provider the first time each player connects after updating.


Requirements: Hytale 0.5.6+ (release) or 0.6.0-pre.x (pre-release), Java 25
Full Changelog:2.9.6...2.10.0
Discord:https://discord.gg/SNPjyfkYPc

2.9.6 — Hytale 0.5.2 OP recognition hotfix

Choose a tag to compare

@nmang004nmang004 released this 29 May 13:36

Server Version:0.5.2

Hotfix for operator (OP) recognition on Hytale 0.5.2. If you're on 2.9.5 and your HyperPerms admins are showing as "not OP" in-game, update to 2.9.6.

Fixed

  • HyperPerms admins were not recognized as OP on 0.5.2. Hytale 0.5.2 determines operator status by group membership — it checks whether a player is in the hytale:Admin group (getGroupsForUser(uuid).contains("hytale:Admin")), and FlyCameraModule/WorldMapTracker key off group names too. HyperPerms funnels all resolution through a single user:<uuid> virtual group, so admins were never seen in hytale:Admin and showed as "not OP" even though their permission checks passed.
  • getGroupsForUser now also advertises hytale:Admin for any user who effectively resolves the * permission (superuser). Granting a HyperPerms group the * node makes its members OP, recognized by Hytale and OP-gated features. Permission resolution itself is unchanged (still funneled through user:<uuid>).

Changed

  • Reverted the authoritative-provider mode added in 2.9.5. HyperPerms no longer removes Hytale's built-in provider; it registers itself first and keeps the built-in provider registered (its removal aggravated the OP break, because Hytale's getGroupsForUser aggregates across all providers).

Upgrade

Drop-in replacement for 2.9.5/2.9.4. No config changes. Replace the jar in mods/ and restart.


Requirements: Hytale 0.5.2+, Java 25
Full Changelog:2.9.5...2.9.6
Discord:https://discord.gg/SNPjyfkYPc

2.9.5 — Hytale 0.5.2 Support

Choose a tag to compare

@nmang004nmang004 released this 29 May 12:34

Server Version:0.5.2 ("Update 5", rev 8b2f3de, Java 25)

Compatibility release for Hytale 0.5.2. Verified by booting the local 0.5.2 server: HyperPerms loads, enables, and registers as the authoritative permission provider with no errors.

Fixed

  • Plugin failed to load on 0.5.2 (manifest). 0.5.2 added a strict SemverRange codec that rejected the manifest's bare ServerVersion (0.5.2) and the spaced >= 1.0.2 optional-dependency range. Now uses ^0.5.2 and >=1.0.2. Without this the plugin did not load at all.
  • PermissionProvider interface conformance. 0.5.2 expanded the interface from 10 to 14 methods. Implemented the four new ones (setUserGroup, getGroupParent, getAllRegisteredGroups, getEffectiveGroupPermissions).
  • Deny-by-default permission model. A group using -* (deny-all) plus specific grants previously had every granted permission silently denied on native command checks. HyperPerms now resolves these correctly — standard "deny-all, then grant" setups work, and native checks agree with /hp check.

Changed

  • Authoritative permission provider. HyperPerms now removes Hytale's built-in provider while enabled (and restores it on disable), so it is the single source of permission decisions. Manage everything via /hp — vanilla /perm, /setgroup and /op operate on data HyperPerms no longer consults, and /op self is advisory-disabled while HyperPerms is active (grant admin via a group with the * node).
  • Default build channel is now release (targets 0.5.2). Use -Phytale_channel=pre-release for pre-release builds.

Added

  • Registered the 0.5.2 built-in nodes so they surface in the web editor and wildcard expansion: hytale.world_map.teleport.coordinate, hytale.world_map.teleport.marker, hytale.system.update.notify (+ matching wildcards).

Removed

  • Obsolete warnAboutVanillaGroupOverwrite startup check (tested the legacy OP/Default group keys that no longer exist in 0.5.2).

Requirements: Hytale 0.5.2+, Java 25
Full Changelog:2.9.4...2.9.5
Discord:https://discord.gg/SNPjyfkYPc

HyperPerms v2.9.4

Choose a tag to compare

@derrickmehaffyderrickmehaffy released this 02 Apr 08:39

Fixed

  • TabListListener runtime crashUniverse.getPlayers() return type differs between Maven artifact (Collection) and runtime server (List), causing NoSuchMethodError. Fixed by copying into new ArrayList<>() to decouple from the return type descriptor

Server Version:2026.03.26-89796e57b

Full Changelog:https://github.com/HyperSystems-Development/HyperPerms/blob/main/CHANGELOG.md

HyperPerms v2.9.3

Choose a tag to compare

@nmang004nmang004 released this 28 Mar 12:37

v2.9.3 — March 26 Server Support

Server Version:2026.03.26 (release & pre-release)

What's New (since 2.9.1)

Added

  • Per-world permissionssetperm and unsetperm commands (group and user) now accept an optional world argument to restrict permissions to a specific world
  • Context display in info commands — Group and user info now shows context restrictions (e.g. [world=Survival]) on permission nodes

Fixed

  • API compatibility — Updated TabListListener to handle Universe.get().getPlayers() returning Collection<PlayerRef> instead of List<PlayerRef>, fixing compilation against the March 26 server update
  • Group inheritance priority — Child group permissions now always take precedence over inherited parent group permissions, regardless of weight values
  • LuckPerms H2 migration version mismatch — Use isolated classloader when loading H2 driver from LuckPerms libs
  • H2 driver selection — Prefer modern H2 driver over legacy to match current LuckPerms database format
  • H2 migration column access — Use unquoted column name for ResultSet access
  • Analytics flush data loss — Prevent race condition where permission check counters could be lost during flush
  • ImportCommand silent failures — Await all group save futures before reporting success
  • Non-atomic node mutations — Synchronize compound removeIf+add operations in setNode and addGroup
  • SQL serialization — Use Gson instead of hand-rolled JSON parser for correct escaping of special characters
  • Cycle detection case sensitivity — Normalize group names to lowercase in inheritance cycle detection
  • Template loader race condition — Prevent concurrent template loading from clearing the map mid-load
  • Confirmation memory leak — Clean up expired pending confirmations to prevent unbounded map growth
  • Migration thread starvation — Use dedicated executor instead of common ForkJoinPool for LuckPerms migration
  • SQLite nested ResultSet — Collect all rows before loading nodes to avoid driver conflicts on single connection
  • SQLite backup consistency — Checkpoint WAL before copying database file to capture all committed writes
  • SQLite restore PRAGMAs — Re-enable WAL and foreign_keys after restoring a backup
  • Clone command data loss — Await save future in clone command before reporting success
  • Group rename atomicity — Create new group before deleting old to prevent data loss on crash; await all save futures
  • JSON storage path traversal — Validate names on load/delete paths to prevent directory traversal
  • WildcardMatcher trace inconsistency — Add stripped-prefix matching to checkWithTrace() to match check() behavior

Full Changelog: v2.9.1...v2.9.3

HyperPerms v2.9.1

Choose a tag to compare

@nmang004nmang004 released this 09 Mar 00:31

v2.9.1 — Permission Resolution, Templates & PermissionsPlus Migration

Added

PermissionsPlus Migration Tool

Full migration support for servers transitioning from PermissionsPlus to HyperPerms.

  • /hp migrate permissionsplus — Preview migration (dry-run)
  • /hp migrate permissionsplus --confirm — Execute migration
  • Reads PermissionsPlus JSON data files and transforms groups, users, and permissions into HyperPerms format
  • Automatic permission cleaning and validation for PermissionsPlus-specific formats
  • Comprehensive test coverage for data models, permission cleaning, and validation

SSP Auto-Owner Assignment

First player to join a single-player (SSP) world is automatically assigned the owner group, removing the need for manual /hp user addgroup setup on fresh worlds.


Fixed

Permission Resolution Order

The resolver now evaluates permissions in most-specific-first order:

a.b.c → a.b.* → a.* → *

Previously, a broad wildcard like a.* could override a more specific grant or denial on a.b.c. This is now resolved — specific permissions always take priority.

Template Application with Existing Groups

/hp template apply no longer fails when groups from the template already exist on the server. Existing groups are gracefully skipped or merged instead of throwing an error.

Template Clearing Nodes and Tracks

Fixed UnsupportedOperationException when applying templates that clear existing nodes and tracks. Template application now uses proper mutable collection methods instead of operating on immutable list views.

SSP Owner Assignment Race Condition

Added synchronization guard to prevent duplicate owner group assignments when multiple players connect simultaneously during first server start.


Chore

  • Bumped version to 2.9.1
  • Updated CHANGELOG.md

Full Commit Log

TypeScopeDescription
featmigrationAdd PermissionsPlus data models
featmigrationAdd PermissionsPlus migrator with JSON reading and transformation
featmigrationRegister PermissionsPlus migrator in /hp migrate command
testmigrationAdd PermissionsPlus data model tests
testmigrationAdd PermissionsPlus permission cleaning and validation tests
refactormigrationApply code review fixes to PermissionsPlus migrator
fixresolverChange to most-specific-first permission resolution order
fixtemplateGracefully handle existing groups during template application
featsspAuto-assign owner group to first player
fixsspPrevent race condition in first-player owner assignment
fixtemplateUse proper mutable methods for clearing nodes and tracks
choreBump version to 2.9.1 and update changelog

v2.9.0-rc1: Permission Resolution, Template & SSP Fixes

Choose a tag to compare

@nmang004nmang004 released this 08 Mar 15:40

Fixes

  • Permission Resolution: Specific grants (e.g. + simpleclaims.edit-party) now correctly override global denies (- *). Resolution order changed to most-specific-first.
  • Template Application: Fixed "Failed to apply template: null" error when applying templates to servers with existing groups. Template applier now uses proper mutable methods for updating groups and tracks.
  • SSP Auto-Owner: First player on an empty server is automatically assigned the configured owner group.

Testing

Download HyperPerms-2.9.0.jar and replace your existing plugin JAR. Please report any issues.

HyperPerms v2.9.0

Choose a tag to compare

@derrickmehaffyderrickmehaffy released this 05 Mar 23:10

Hotfix: Web Editor Session Create

Fixed

  • Web editor returning 500 on /hp editor — The gzip compression introduced in 2.8.9 was applied to all session create requests, but the Cloudflare Worker API does not support Content-Encoding: gzip on incoming request bodies. This caused every /hp editor command to fail with "Server returned status 500". Compression is now only applied to payloads exceeding 500KB, keeping normal requests uncompressed while still protecting very large servers from HTTP 413 errors.

If you are on 2.8.9, update immediately.

HyperPerms v2.8.9

Choose a tag to compare

@derrickmehaffyderrickmehaffy released this 05 Mar 23:10

Architecture Rehaul & MMOSkillTree Integration

First-Class MMOSkillTree Support

HyperPerms now has full, first-class integration with MMOSkillTree — one of the biggest plugins on Hytale.

  • 200+ permission nodes registered across admin, command, skill, boost, and alternate prefix categories
  • All 23 skill nodesmmoskilltree.skill.mining, .woodcutting, .excavation, .harvesting, .fishing, .swords, .daggers, .polearms, .staves, .axes, .blunt, .archery, .unarmed, .defense, .taming, .acrobatics, .crafting, .repair, .alchemy, .enchanting, .cooking, .smithing, .building
  • All 140 XP boost permission nodes covering personal and global boosts for all skills, skill categories, and all-skills targets with varying multipliers, durations, and cooldowns
  • ziggfreed.* alternate prefix support — MMOSkillTree checks permissions through both mmoskilltree.* and ziggfreed.mmoskilltree.* prefixes. HyperPerms now correctly resolves both via bidirectional aliases
  • Hytale command path aliasescom.ziggfreed.mmoskilltree.command.* paths resolve to their mmoskilltree.command.* equivalents
  • Wildcard expansion for all MMST permission categories
  • Tab completion & web editor now show all MMST permission nodes
  • Updated RPG & Survival templates with appropriate MMST permissions at each rank tier (XP boosts scale with rank progression)

Staged Plugin Lifecycle

The plugin initialization system has been completely rewritten with a clean, modular architecture:

  • 11 ordered stages: Config → Storage → CoreManager → Resolver → Registry → Chat → Integration → Web → Scheduler → Analytics → DefaultGroups
  • PluginLifecycle orchestrator initializes stages in order and shuts them down in reverse — if any stage fails, previously initialized stages are safely torn down
  • ServiceContainer provides typed dependency injection across all stages
  • HyperPerms.java reduced from ~400 lines of monolithic init to ~25 lines — all setup logic now lives in dedicated Stage implementations

Annotation-Based Command Framework

The entire command system has been rebuilt using a declarative annotation-driven approach:

  • New annotations: @CommandGroup, @Command, @Arg, @OptionalArg, @Permission, @Confirm
  • CommandScanner automatically discovers and registers annotated command methods at startup
  • CommandDispatcher handles argument parsing, permission checks, and confirmation flows
  • 5 annotated command groups replace 42 individual command classes: GroupCommands, UserCommands, DebugCommands, RootCommands, PermsCommands, BackupCommands
  • Net reduction of ~1,500 lines with significantly better maintainability

Web Editor Improvements

  • Gzip compressed session requests — Session create payloads are now gzip compressed before sending to the API, preventing HTTP 413 errors on servers with many groups and permissions

Bug Fixes

  • Fixed config being null during early stage initialization
  • Fixed default groups being created before storage was fully ready
  • Integrated 2.8.8's centralized sync and diff-based permission logic into the new lifecycle system

HyperPerms v2.8.8

Choose a tag to compare

@derrickmehaffyderrickmehaffy released this 05 Mar 23:10

[2.8.8] - 2026-02-23

Server Version:2026.02.19-1a311a592

Fixed

  • Permission pollution in Hytale's permissions.json - syncPermissionsToHytale() previously pushed all resolved permissions on every change, causing hundreds of permissions to accumulate. Now uses diff-based sync that computes the delta between Hytale's current state and HyperPerms' resolved set, only adding missing and removing stale permissions
  • Race condition in concurrent permission syncs - Multiple threads (command thread, scheduler, CF pool, web editor) could call syncPermissionsToHytale() simultaneously for the same user, racing on Hytale's non-thread-safe HashSet view from getUserPermissions(). Added per-UUID synchronization locks and defensive copying of the live view
  • Scattered manual sync calls - Six user commands and HyperPermsPermissionProvider each had their own inline syncPermissionsToHytale() call via bootstrap reflection. Centralized all sync logic into a CacheInvalidator.setSyncListener() hook — every cache invalidation now automatically triggers Hytale sync for affected online users
  • Group commands invalidated entire cache - Group permission/property changes (setperm, unsetperm, setprefix, setsuffix, setweight, setexpiry, parent add/remove) called invalidateAll() instead of targeted invalidateGroup(), causing unnecessary cache churn for unrelated users
  • Expired permissions not synced to Hytale - ExpiryCleanupTask removed expired nodes but didn't invalidate the cache or trigger Hytale sync, so expired permissions remained active until the player reconnected
  • Inconsistent cache invalidation API - Some commands used getCache().invalidate() (bypassing sync) while others used getCacheInvalidator().invalidate() (with sync). Unified all commands to use getCacheInvalidator()
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Releases: HyperSystems-Development/HyperPerms

2.10.0 — Command tab-completion, QoL fixes & QuestLines Claims compatibility

Choose a tag to compare

@nmang004nmang004 released this 24 Jun 00:52

Server Version:0.5.6 (release) · 0.6.0-pre.4 (pre-release)

Quality-of-life release: tab-completion for /hp, instant command-tree refresh, and fixes for several silently-broken integration paths — including a QuestLines Claims compatibility fix that was handing out double (or triple) the claims a permission allowed. The same codebase now runs on both the Hytale release (0.5.x) and pre-release (0.6.0-pre.x) channels.

Added

  • Tab-completion for /hp commands. Group, track, permission-node and online-player arguments now suggest as you type (case-insensitive prefix match). Previously every argument was a plain string with no completion.
  • Instant command-tree refresh. When a player's groups or permissions change, the affected online player gets a fresh command tree immediately — newly-granted commands appear without a relog.
  • Clickable download link in the "update available" notification (alongside /hp update).
  • Startup self-check that verifies the Hytale-core reflection targets used by optional integrations resolve on the running build, logging a clear warning if any are missing.

Fixed

  • QuestLines Claims granted double (or triple) the claims/rent a permission allowed. QuestLines computes claim/rent limits by summing the numeric suffix of questlinesclaims.claim.chunks.<n> / questlinesclaims.rent.limit.<n> nodes across every provider, and across both a user's permissions and each of their groups' permissions. HyperPerms exposed the same fully-resolved set through several of those surfaces (getUserPermissions, the virtual user:<uuid> group, and the native-provider sync), so each node was counted 2–3×. When QuestLines is detected, HyperPerms now collapses those to a single summable source — boolean checks are unaffected, and servers without QuestLines see no change. (LuckPerms was already special-cased by QuestLines, which is why it behaved correctly.)
  • PlaceholderAPI offline-player fallback never worked — it referenced a non-existent class (…server.HytaleServer, missing .core) and a dead getPlayerManager() chain, silently returning null. Now uses Universe.get().getPlayer(uuid).
  • MysticNameTags nameplate refresh never worked — the World class literal omitted its .world sub-package.
  • Event listener leaks across /reload — chat, tab-list and update-notification listeners stored their registration handles but never called unregister() (a stale comment claimed no such API existed). They now unregister properly instead of leaving duplicate handlers.
  • Stale "ghost" entries in the player/tab list — HyperPerms only ever added player-list entries; quitting players are now removed via RemoveFromServerPlayerList instead of lingering.

Changed

  • Centralized the Hytale-core reflection string literals (Universe, PlayerRef, World) into ReflectionUtil so a future Hytale package move is a one-line fix and the optional integrations can't drift independently.

Upgrade

Drop-in replacement for 2.9.x — no config changes. Replace the jar in mods/ and restart, using the build that matches your server channel:

  • HyperPerms-2.10.0.jar — Hytale release servers (0.5.x, manifest ^0.5.6)
  • HyperPerms-2.10.0-prerelease.jar — Hytale pre-release servers (0.6.0-pre.x, manifest ^0.6.0-pre.4)

If you run QuestLines Claims, HyperPerms prunes any duplicate questlinesclaims.* entries a previous version wrote into the native provider the first time each player connects after updating.


Requirements: Hytale 0.5.6+ (release) or 0.6.0-pre.x (pre-release), Java 25
Full Changelog:2.9.6...2.10.0
Discord:https://discord.gg/SNPjyfkYPc

2.9.6 — Hytale 0.5.2 OP recognition hotfix

Choose a tag to compare

@nmang004nmang004 released this 29 May 13:36

Server Version:0.5.2

Hotfix for operator (OP) recognition on Hytale 0.5.2. If you're on 2.9.5 and your HyperPerms admins are showing as "not OP" in-game, update to 2.9.6.

Fixed

  • HyperPerms admins were not recognized as OP on 0.5.2. Hytale 0.5.2 determines operator status by group membership — it checks whether a player is in the hytale:Admin group (getGroupsForUser(uuid).contains("hytale:Admin")), and FlyCameraModule/WorldMapTracker key off group names too. HyperPerms funnels all resolution through a single user:<uuid> virtual group, so admins were never seen in hytale:Admin and showed as "not OP" even though their permission checks passed.
  • getGroupsForUser now also advertises hytale:Admin for any user who effectively resolves the * permission (superuser). Granting a HyperPerms group the * node makes its members OP, recognized by Hytale and OP-gated features. Permission resolution itself is unchanged (still funneled through user:<uuid>).

Changed

  • Reverted the authoritative-provider mode added in 2.9.5. HyperPerms no longer removes Hytale's built-in provider; it registers itself first and keeps the built-in provider registered (its removal aggravated the OP break, because Hytale's getGroupsForUser aggregates across all providers).

Upgrade

Drop-in replacement for 2.9.5/2.9.4. No config changes. Replace the jar in mods/ and restart.


Requirements: Hytale 0.5.2+, Java 25
Full Changelog:2.9.5...2.9.6
Discord:https://discord.gg/SNPjyfkYPc

2.9.5 — Hytale 0.5.2 Support

Choose a tag to compare

@nmang004nmang004 released this 29 May 12:34

Server Version:0.5.2 ("Update 5", rev 8b2f3de, Java 25)

Compatibility release for Hytale 0.5.2. Verified by booting the local 0.5.2 server: HyperPerms loads, enables, and registers as the authoritative permission provider with no errors.

Fixed

  • Plugin failed to load on 0.5.2 (manifest). 0.5.2 added a strict SemverRange codec that rejected the manifest's bare ServerVersion (0.5.2) and the spaced >= 1.0.2 optional-dependency range. Now uses ^0.5.2 and >=1.0.2. Without this the plugin did not load at all.
  • PermissionProvider interface conformance. 0.5.2 expanded the interface from 10 to 14 methods. Implemented the four new ones (setUserGroup, getGroupParent, getAllRegisteredGroups, getEffectiveGroupPermissions).
  • Deny-by-default permission model. A group using -* (deny-all) plus specific grants previously had every granted permission silently denied on native command checks. HyperPerms now resolves these correctly — standard "deny-all, then grant" setups work, and native checks agree with /hp check.

Changed

  • Authoritative permission provider. HyperPerms now removes Hytale's built-in provider while enabled (and restores it on disable), so it is the single source of permission decisions. Manage everything via /hp — vanilla /perm, /setgroup and /op operate on data HyperPerms no longer consults, and /op self is advisory-disabled while HyperPerms is active (grant admin via a group with the * node).
  • Default build channel is now release (targets 0.5.2). Use -Phytale_channel=pre-release for pre-release builds.

Added

  • Registered the 0.5.2 built-in nodes so they surface in the web editor and wildcard expansion: hytale.world_map.teleport.coordinate, hytale.world_map.teleport.marker, hytale.system.update.notify (+ matching wildcards).

Removed

  • Obsolete warnAboutVanillaGroupOverwrite startup check (tested the legacy OP/Default group keys that no longer exist in 0.5.2).

Requirements: Hytale 0.5.2+, Java 25
Full Changelog:2.9.4...2.9.5
Discord:https://discord.gg/SNPjyfkYPc

HyperPerms v2.9.4

Choose a tag to compare

@derrickmehaffyderrickmehaffy released this 02 Apr 08:39

Fixed

  • TabListListener runtime crashUniverse.getPlayers() return type differs between Maven artifact (Collection) and runtime server (List), causing NoSuchMethodError. Fixed by copying into new ArrayList<>() to decouple from the return type descriptor

Server Version:2026.03.26-89796e57b

Full Changelog:https://github.com/HyperSystems-Development/HyperPerms/blob/main/CHANGELOG.md

HyperPerms v2.9.3

Choose a tag to compare

@nmang004nmang004 released this 28 Mar 12:37

v2.9.3 — March 26 Server Support

Server Version:2026.03.26 (release & pre-release)

What's New (since 2.9.1)

Added

  • Per-world permissionssetperm and unsetperm commands (group and user) now accept an optional world argument to restrict permissions to a specific world
  • Context display in info commands — Group and user info now shows context restrictions (e.g. [world=Survival]) on permission nodes

Fixed

  • API compatibility — Updated TabListListener to handle Universe.get().getPlayers() returning Collection<PlayerRef> instead of List<PlayerRef>, fixing compilation against the March 26 server update
  • Group inheritance priority — Child group permissions now always take precedence over inherited parent group permissions, regardless of weight values
  • LuckPerms H2 migration version mismatch — Use isolated classloader when loading H2 driver from LuckPerms libs
  • H2 driver selection — Prefer modern H2 driver over legacy to match current LuckPerms database format
  • H2 migration column access — Use unquoted column name for ResultSet access
  • Analytics flush data loss — Prevent race condition where permission check counters could be lost during flush
  • ImportCommand silent failures — Await all group save futures before reporting success
  • Non-atomic node mutations — Synchronize compound removeIf+add operations in setNode and addGroup
  • SQL serialization — Use Gson instead of hand-rolled JSON parser for correct escaping of special characters
  • Cycle detection case sensitivity — Normalize group names to lowercase in inheritance cycle detection
  • Template loader race condition — Prevent concurrent template loading from clearing the map mid-load
  • Confirmation memory leak — Clean up expired pending confirmations to prevent unbounded map growth
  • Migration thread starvation — Use dedicated executor instead of common ForkJoinPool for LuckPerms migration
  • SQLite nested ResultSet — Collect all rows before loading nodes to avoid driver conflicts on single connection
  • SQLite backup consistency — Checkpoint WAL before copying database file to capture all committed writes
  • SQLite restore PRAGMAs — Re-enable WAL and foreign_keys after restoring a backup
  • Clone command data loss — Await save future in clone command before reporting success
  • Group rename atomicity — Create new group before deleting old to prevent data loss on crash; await all save futures
  • JSON storage path traversal — Validate names on load/delete paths to prevent directory traversal
  • WildcardMatcher trace inconsistency — Add stripped-prefix matching to checkWithTrace() to match check() behavior

Full Changelog: v2.9.1...v2.9.3

HyperPerms v2.9.1

Choose a tag to compare

@nmang004nmang004 released this 09 Mar 00:31

v2.9.1 — Permission Resolution, Templates & PermissionsPlus Migration

Added

PermissionsPlus Migration Tool

Full migration support for servers transitioning from PermissionsPlus to HyperPerms.

  • /hp migrate permissionsplus — Preview migration (dry-run)
  • /hp migrate permissionsplus --confirm — Execute migration
  • Reads PermissionsPlus JSON data files and transforms groups, users, and permissions into HyperPerms format
  • Automatic permission cleaning and validation for PermissionsPlus-specific formats
  • Comprehensive test coverage for data models, permission cleaning, and validation

SSP Auto-Owner Assignment

First player to join a single-player (SSP) world is automatically assigned the owner group, removing the need for manual /hp user addgroup setup on fresh worlds.


Fixed

Permission Resolution Order

The resolver now evaluates permissions in most-specific-first order:

a.b.c → a.b.* → a.* → *

Previously, a broad wildcard like a.* could override a more specific grant or denial on a.b.c. This is now resolved — specific permissions always take priority.

Template Application with Existing Groups

/hp template apply no longer fails when groups from the template already exist on the server. Existing groups are gracefully skipped or merged instead of throwing an error.

Template Clearing Nodes and Tracks

Fixed UnsupportedOperationException when applying templates that clear existing nodes and tracks. Template application now uses proper mutable collection methods instead of operating on immutable list views.

SSP Owner Assignment Race Condition

Added synchronization guard to prevent duplicate owner group assignments when multiple players connect simultaneously during first server start.


Chore

  • Bumped version to 2.9.1
  • Updated CHANGELOG.md

Full Commit Log

TypeScopeDescription
featmigrationAdd PermissionsPlus data models
featmigrationAdd PermissionsPlus migrator with JSON reading and transformation
featmigrationRegister PermissionsPlus migrator in /hp migrate command
testmigrationAdd PermissionsPlus data model tests
testmigrationAdd PermissionsPlus permission cleaning and validation tests
refactormigrationApply code review fixes to PermissionsPlus migrator
fixresolverChange to most-specific-first permission resolution order
fixtemplateGracefully handle existing groups during template application
featsspAuto-assign owner group to first player
fixsspPrevent race condition in first-player owner assignment
fixtemplateUse proper mutable methods for clearing nodes and tracks
choreBump version to 2.9.1 and update changelog

v2.9.0-rc1: Permission Resolution, Template & SSP Fixes

Choose a tag to compare

@nmang004nmang004 released this 08 Mar 15:40

Fixes

  • Permission Resolution: Specific grants (e.g. + simpleclaims.edit-party) now correctly override global denies (- *). Resolution order changed to most-specific-first.
  • Template Application: Fixed "Failed to apply template: null" error when applying templates to servers with existing groups. Template applier now uses proper mutable methods for updating groups and tracks.
  • SSP Auto-Owner: First player on an empty server is automatically assigned the configured owner group.

Testing

Download HyperPerms-2.9.0.jar and replace your existing plugin JAR. Please report any issues.

HyperPerms v2.9.0

Choose a tag to compare

@derrickmehaffyderrickmehaffy released this 05 Mar 23:10

Hotfix: Web Editor Session Create

Fixed

  • Web editor returning 500 on /hp editor — The gzip compression introduced in 2.8.9 was applied to all session create requests, but the Cloudflare Worker API does not support Content-Encoding: gzip on incoming request bodies. This caused every /hp editor command to fail with "Server returned status 500". Compression is now only applied to payloads exceeding 500KB, keeping normal requests uncompressed while still protecting very large servers from HTTP 413 errors.

If you are on 2.8.9, update immediately.

HyperPerms v2.8.9

Choose a tag to compare

@derrickmehaffyderrickmehaffy released this 05 Mar 23:10

Architecture Rehaul & MMOSkillTree Integration

First-Class MMOSkillTree Support

HyperPerms now has full, first-class integration with MMOSkillTree — one of the biggest plugins on Hytale.

  • 200+ permission nodes registered across admin, command, skill, boost, and alternate prefix categories
  • All 23 skill nodesmmoskilltree.skill.mining, .woodcutting, .excavation, .harvesting, .fishing, .swords, .daggers, .polearms, .staves, .axes, .blunt, .archery, .unarmed, .defense, .taming, .acrobatics, .crafting, .repair, .alchemy, .enchanting, .cooking, .smithing, .building
  • All 140 XP boost permission nodes covering personal and global boosts for all skills, skill categories, and all-skills targets with varying multipliers, durations, and cooldowns
  • ziggfreed.* alternate prefix support — MMOSkillTree checks permissions through both mmoskilltree.* and ziggfreed.mmoskilltree.* prefixes. HyperPerms now correctly resolves both via bidirectional aliases
  • Hytale command path aliasescom.ziggfreed.mmoskilltree.command.* paths resolve to their mmoskilltree.command.* equivalents
  • Wildcard expansion for all MMST permission categories
  • Tab completion & web editor now show all MMST permission nodes
  • Updated RPG & Survival templates with appropriate MMST permissions at each rank tier (XP boosts scale with rank progression)

Staged Plugin Lifecycle

The plugin initialization system has been completely rewritten with a clean, modular architecture:

  • 11 ordered stages: Config → Storage → CoreManager → Resolver → Registry → Chat → Integration → Web → Scheduler → Analytics → DefaultGroups
  • PluginLifecycle orchestrator initializes stages in order and shuts them down in reverse — if any stage fails, previously initialized stages are safely torn down
  • ServiceContainer provides typed dependency injection across all stages
  • HyperPerms.java reduced from ~400 lines of monolithic init to ~25 lines — all setup logic now lives in dedicated Stage implementations

Annotation-Based Command Framework

The entire command system has been rebuilt using a declarative annotation-driven approach:

  • New annotations: @CommandGroup, @Command, @Arg, @OptionalArg, @Permission, @Confirm
  • CommandScanner automatically discovers and registers annotated command methods at startup
  • CommandDispatcher handles argument parsing, permission checks, and confirmation flows
  • 5 annotated command groups replace 42 individual command classes: GroupCommands, UserCommands, DebugCommands, RootCommands, PermsCommands, BackupCommands
  • Net reduction of ~1,500 lines with significantly better maintainability

Web Editor Improvements

  • Gzip compressed session requests — Session create payloads are now gzip compressed before sending to the API, preventing HTTP 413 errors on servers with many groups and permissions

Bug Fixes

  • Fixed config being null during early stage initialization
  • Fixed default groups being created before storage was fully ready
  • Integrated 2.8.8's centralized sync and diff-based permission logic into the new lifecycle system

HyperPerms v2.8.8

Choose a tag to compare

@derrickmehaffyderrickmehaffy released this 05 Mar 23:10

[2.8.8] - 2026-02-23

Server Version:2026.02.19-1a311a592

Fixed

  • Permission pollution in Hytale's permissions.json - syncPermissionsToHytale() previously pushed all resolved permissions on every change, causing hundreds of permissions to accumulate. Now uses diff-based sync that computes the delta between Hytale's current state and HyperPerms' resolved set, only adding missing and removing stale permissions
  • Race condition in concurrent permission syncs - Multiple threads (command thread, scheduler, CF pool, web editor) could call syncPermissionsToHytale() simultaneously for the same user, racing on Hytale's non-thread-safe HashSet view from getUserPermissions(). Added per-UUID synchronization locks and defensive copying of the live view
  • Scattered manual sync calls - Six user commands and HyperPermsPermissionProvider each had their own inline syncPermissionsToHytale() call via bootstrap reflection. Centralized all sync logic into a CacheInvalidator.setSyncListener() hook — every cache invalidation now automatically triggers Hytale sync for affected online users
  • Group commands invalidated entire cache - Group permission/property changes (setperm, unsetperm, setprefix, setsuffix, setweight, setexpiry, parent add/remove) called invalidateAll() instead of targeted invalidateGroup(), causing unnecessary cache churn for unrelated users
  • Expired permissions not synced to Hytale - ExpiryCleanupTask removed expired nodes but didn't invalidate the cache or trigger Hytale sync, so expired permissions remained active until the player reconnected
  • Inconsistent cache invalidation API - Some commands used getCache().invalidate() (bypassing sync) while others used getCacheInvalidator().invalidate() (with sync). Unified all commands to use getCacheInvalidator()
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Releases: HyperSystems-Development/HyperPerms

2.10.0 — Command tab-completion, QoL fixes & QuestLines Claims compatibility

Choose a tag to compare

@nmang004nmang004 released this 24 Jun 00:52

Server Version:0.5.6 (release) · 0.6.0-pre.4 (pre-release)

Quality-of-life release: tab-completion for /hp, instant command-tree refresh, and fixes for several silently-broken integration paths — including a QuestLines Claims compatibility fix that was handing out double (or triple) the claims a permission allowed. The same codebase now runs on both the Hytale release (0.5.x) and pre-release (0.6.0-pre.x) channels.

Added

  • Tab-completion for /hp commands. Group, track, permission-node and online-player arguments now suggest as you type (case-insensitive prefix match). Previously every argument was a plain string with no completion.
  • Instant command-tree refresh. When a player's groups or permissions change, the affected online player gets a fresh command tree immediately — newly-granted commands appear without a relog.
  • Clickable download link in the "update available" notification (alongside /hp update).
  • Startup self-check that verifies the Hytale-core reflection targets used by optional integrations resolve on the running build, logging a clear warning if any are missing.

Fixed

  • QuestLines Claims granted double (or triple) the claims/rent a permission allowed. QuestLines computes claim/rent limits by summing the numeric suffix of questlinesclaims.claim.chunks.<n> / questlinesclaims.rent.limit.<n> nodes across every provider, and across both a user's permissions and each of their groups' permissions. HyperPerms exposed the same fully-resolved set through several of those surfaces (getUserPermissions, the virtual user:<uuid> group, and the native-provider sync), so each node was counted 2–3×. When QuestLines is detected, HyperPerms now collapses those to a single summable source — boolean checks are unaffected, and servers without QuestLines see no change. (LuckPerms was already special-cased by QuestLines, which is why it behaved correctly.)
  • PlaceholderAPI offline-player fallback never worked — it referenced a non-existent class (…server.HytaleServer, missing .core) and a dead getPlayerManager() chain, silently returning null. Now uses Universe.get().getPlayer(uuid).
  • MysticNameTags nameplate refresh never worked — the World class literal omitted its .world sub-package.
  • Event listener leaks across /reload — chat, tab-list and update-notification listeners stored their registration handles but never called unregister() (a stale comment claimed no such API existed). They now unregister properly instead of leaving duplicate handlers.
  • Stale "ghost" entries in the player/tab list — HyperPerms only ever added player-list entries; quitting players are now removed via RemoveFromServerPlayerList instead of lingering.

Changed

  • Centralized the Hytale-core reflection string literals (Universe, PlayerRef, World) into ReflectionUtil so a future Hytale package move is a one-line fix and the optional integrations can't drift independently.

Upgrade

Drop-in replacement for 2.9.x — no config changes. Replace the jar in mods/ and restart, using the build that matches your server channel:

  • HyperPerms-2.10.0.jar — Hytale release servers (0.5.x, manifest ^0.5.6)
  • HyperPerms-2.10.0-prerelease.jar — Hytale pre-release servers (0.6.0-pre.x, manifest ^0.6.0-pre.4)

If you run QuestLines Claims, HyperPerms prunes any duplicate questlinesclaims.* entries a previous version wrote into the native provider the first time each player connects after updating.


Requirements: Hytale 0.5.6+ (release) or 0.6.0-pre.x (pre-release), Java 25
Full Changelog:2.9.6...2.10.0
Discord:https://discord.gg/SNPjyfkYPc

2.9.6 — Hytale 0.5.2 OP recognition hotfix

Choose a tag to compare

@nmang004nmang004 released this 29 May 13:36

Server Version:0.5.2

Hotfix for operator (OP) recognition on Hytale 0.5.2. If you're on 2.9.5 and your HyperPerms admins are showing as "not OP" in-game, update to 2.9.6.

Fixed

  • HyperPerms admins were not recognized as OP on 0.5.2. Hytale 0.5.2 determines operator status by group membership — it checks whether a player is in the hytale:Admin group (getGroupsForUser(uuid).contains("hytale:Admin")), and FlyCameraModule/WorldMapTracker key off group names too. HyperPerms funnels all resolution through a single user:<uuid> virtual group, so admins were never seen in hytale:Admin and showed as "not OP" even though their permission checks passed.
  • getGroupsForUser now also advertises hytale:Admin for any user who effectively resolves the * permission (superuser). Granting a HyperPerms group the * node makes its members OP, recognized by Hytale and OP-gated features. Permission resolution itself is unchanged (still funneled through user:<uuid>).

Changed

  • Reverted the authoritative-provider mode added in 2.9.5. HyperPerms no longer removes Hytale's built-in provider; it registers itself first and keeps the built-in provider registered (its removal aggravated the OP break, because Hytale's getGroupsForUser aggregates across all providers).

Upgrade

Drop-in replacement for 2.9.5/2.9.4. No config changes. Replace the jar in mods/ and restart.


Requirements: Hytale 0.5.2+, Java 25
Full Changelog:2.9.5...2.9.6
Discord:https://discord.gg/SNPjyfkYPc

2.9.5 — Hytale 0.5.2 Support

Choose a tag to compare

@nmang004nmang004 released this 29 May 12:34

Server Version:0.5.2 ("Update 5", rev 8b2f3de, Java 25)

Compatibility release for Hytale 0.5.2. Verified by booting the local 0.5.2 server: HyperPerms loads, enables, and registers as the authoritative permission provider with no errors.

Fixed

  • Plugin failed to load on 0.5.2 (manifest). 0.5.2 added a strict SemverRange codec that rejected the manifest's bare ServerVersion (0.5.2) and the spaced >= 1.0.2 optional-dependency range. Now uses ^0.5.2 and >=1.0.2. Without this the plugin did not load at all.
  • PermissionProvider interface conformance. 0.5.2 expanded the interface from 10 to 14 methods. Implemented the four new ones (setUserGroup, getGroupParent, getAllRegisteredGroups, getEffectiveGroupPermissions).
  • Deny-by-default permission model. A group using -* (deny-all) plus specific grants previously had every granted permission silently denied on native command checks. HyperPerms now resolves these correctly — standard "deny-all, then grant" setups work, and native checks agree with /hp check.

Changed

  • Authoritative permission provider. HyperPerms now removes Hytale's built-in provider while enabled (and restores it on disable), so it is the single source of permission decisions. Manage everything via /hp — vanilla /perm, /setgroup and /op operate on data HyperPerms no longer consults, and /op self is advisory-disabled while HyperPerms is active (grant admin via a group with the * node).
  • Default build channel is now release (targets 0.5.2). Use -Phytale_channel=pre-release for pre-release builds.

Added

  • Registered the 0.5.2 built-in nodes so they surface in the web editor and wildcard expansion: hytale.world_map.teleport.coordinate, hytale.world_map.teleport.marker, hytale.system.update.notify (+ matching wildcards).

Removed

  • Obsolete warnAboutVanillaGroupOverwrite startup check (tested the legacy OP/Default group keys that no longer exist in 0.5.2).

Requirements: Hytale 0.5.2+, Java 25
Full Changelog:2.9.4...2.9.5
Discord:https://discord.gg/SNPjyfkYPc

HyperPerms v2.9.4

Choose a tag to compare

@derrickmehaffyderrickmehaffy released this 02 Apr 08:39

Fixed

  • TabListListener runtime crashUniverse.getPlayers() return type differs between Maven artifact (Collection) and runtime server (List), causing NoSuchMethodError. Fixed by copying into new ArrayList<>() to decouple from the return type descriptor

Server Version:2026.03.26-89796e57b

Full Changelog:https://github.com/HyperSystems-Development/HyperPerms/blob/main/CHANGELOG.md

HyperPerms v2.9.3

Choose a tag to compare

@nmang004nmang004 released this 28 Mar 12:37

v2.9.3 — March 26 Server Support

Server Version:2026.03.26 (release & pre-release)

What's New (since 2.9.1)

Added

  • Per-world permissionssetperm and unsetperm commands (group and user) now accept an optional world argument to restrict permissions to a specific world
  • Context display in info commands — Group and user info now shows context restrictions (e.g. [world=Survival]) on permission nodes

Fixed

  • API compatibility — Updated TabListListener to handle Universe.get().getPlayers() returning Collection<PlayerRef> instead of List<PlayerRef>, fixing compilation against the March 26 server update
  • Group inheritance priority — Child group permissions now always take precedence over inherited parent group permissions, regardless of weight values
  • LuckPerms H2 migration version mismatch — Use isolated classloader when loading H2 driver from LuckPerms libs
  • H2 driver selection — Prefer modern H2 driver over legacy to match current LuckPerms database format
  • H2 migration column access — Use unquoted column name for ResultSet access
  • Analytics flush data loss — Prevent race condition where permission check counters could be lost during flush
  • ImportCommand silent failures — Await all group save futures before reporting success
  • Non-atomic node mutations — Synchronize compound removeIf+add operations in setNode and addGroup
  • SQL serialization — Use Gson instead of hand-rolled JSON parser for correct escaping of special characters
  • Cycle detection case sensitivity — Normalize group names to lowercase in inheritance cycle detection
  • Template loader race condition — Prevent concurrent template loading from clearing the map mid-load
  • Confirmation memory leak — Clean up expired pending confirmations to prevent unbounded map growth
  • Migration thread starvation — Use dedicated executor instead of common ForkJoinPool for LuckPerms migration
  • SQLite nested ResultSet — Collect all rows before loading nodes to avoid driver conflicts on single connection
  • SQLite backup consistency — Checkpoint WAL before copying database file to capture all committed writes
  • SQLite restore PRAGMAs — Re-enable WAL and foreign_keys after restoring a backup
  • Clone command data loss — Await save future in clone command before reporting success
  • Group rename atomicity — Create new group before deleting old to prevent data loss on crash; await all save futures
  • JSON storage path traversal — Validate names on load/delete paths to prevent directory traversal
  • WildcardMatcher trace inconsistency — Add stripped-prefix matching to checkWithTrace() to match check() behavior

Full Changelog: v2.9.1...v2.9.3

HyperPerms v2.9.1

Choose a tag to compare

@nmang004nmang004 released this 09 Mar 00:31

v2.9.1 — Permission Resolution, Templates & PermissionsPlus Migration

Added

PermissionsPlus Migration Tool

Full migration support for servers transitioning from PermissionsPlus to HyperPerms.

  • /hp migrate permissionsplus — Preview migration (dry-run)
  • /hp migrate permissionsplus --confirm — Execute migration
  • Reads PermissionsPlus JSON data files and transforms groups, users, and permissions into HyperPerms format
  • Automatic permission cleaning and validation for PermissionsPlus-specific formats
  • Comprehensive test coverage for data models, permission cleaning, and validation

SSP Auto-Owner Assignment

First player to join a single-player (SSP) world is automatically assigned the owner group, removing the need for manual /hp user addgroup setup on fresh worlds.


Fixed

Permission Resolution Order

The resolver now evaluates permissions in most-specific-first order:

a.b.c → a.b.* → a.* → *

Previously, a broad wildcard like a.* could override a more specific grant or denial on a.b.c. This is now resolved — specific permissions always take priority.

Template Application with Existing Groups

/hp template apply no longer fails when groups from the template already exist on the server. Existing groups are gracefully skipped or merged instead of throwing an error.

Template Clearing Nodes and Tracks

Fixed UnsupportedOperationException when applying templates that clear existing nodes and tracks. Template application now uses proper mutable collection methods instead of operating on immutable list views.

SSP Owner Assignment Race Condition

Added synchronization guard to prevent duplicate owner group assignments when multiple players connect simultaneously during first server start.


Chore

  • Bumped version to 2.9.1
  • Updated CHANGELOG.md

Full Commit Log

TypeScopeDescription
featmigrationAdd PermissionsPlus data models
featmigrationAdd PermissionsPlus migrator with JSON reading and transformation
featmigrationRegister PermissionsPlus migrator in /hp migrate command
testmigrationAdd PermissionsPlus data model tests
testmigrationAdd PermissionsPlus permission cleaning and validation tests
refactormigrationApply code review fixes to PermissionsPlus migrator
fixresolverChange to most-specific-first permission resolution order
fixtemplateGracefully handle existing groups during template application
featsspAuto-assign owner group to first player
fixsspPrevent race condition in first-player owner assignment
fixtemplateUse proper mutable methods for clearing nodes and tracks
choreBump version to 2.9.1 and update changelog

v2.9.0-rc1: Permission Resolution, Template & SSP Fixes

Choose a tag to compare

@nmang004nmang004 released this 08 Mar 15:40

Fixes

  • Permission Resolution: Specific grants (e.g. + simpleclaims.edit-party) now correctly override global denies (- *). Resolution order changed to most-specific-first.
  • Template Application: Fixed "Failed to apply template: null" error when applying templates to servers with existing groups. Template applier now uses proper mutable methods for updating groups and tracks.
  • SSP Auto-Owner: First player on an empty server is automatically assigned the configured owner group.

Testing

Download HyperPerms-2.9.0.jar and replace your existing plugin JAR. Please report any issues.

HyperPerms v2.9.0

Choose a tag to compare

@derrickmehaffyderrickmehaffy released this 05 Mar 23:10

Hotfix: Web Editor Session Create

Fixed

  • Web editor returning 500 on /hp editor — The gzip compression introduced in 2.8.9 was applied to all session create requests, but the Cloudflare Worker API does not support Content-Encoding: gzip on incoming request bodies. This caused every /hp editor command to fail with "Server returned status 500". Compression is now only applied to payloads exceeding 500KB, keeping normal requests uncompressed while still protecting very large servers from HTTP 413 errors.

If you are on 2.8.9, update immediately.

HyperPerms v2.8.9

Choose a tag to compare

@derrickmehaffyderrickmehaffy released this 05 Mar 23:10

Architecture Rehaul & MMOSkillTree Integration

First-Class MMOSkillTree Support

HyperPerms now has full, first-class integration with MMOSkillTree — one of the biggest plugins on Hytale.

  • 200+ permission nodes registered across admin, command, skill, boost, and alternate prefix categories
  • All 23 skill nodesmmoskilltree.skill.mining, .woodcutting, .excavation, .harvesting, .fishing, .swords, .daggers, .polearms, .staves, .axes, .blunt, .archery, .unarmed, .defense, .taming, .acrobatics, .crafting, .repair, .alchemy, .enchanting, .cooking, .smithing, .building
  • All 140 XP boost permission nodes covering personal and global boosts for all skills, skill categories, and all-skills targets with varying multipliers, durations, and cooldowns
  • ziggfreed.* alternate prefix support — MMOSkillTree checks permissions through both mmoskilltree.* and ziggfreed.mmoskilltree.* prefixes. HyperPerms now correctly resolves both via bidirectional aliases
  • Hytale command path aliasescom.ziggfreed.mmoskilltree.command.* paths resolve to their mmoskilltree.command.* equivalents
  • Wildcard expansion for all MMST permission categories
  • Tab completion & web editor now show all MMST permission nodes
  • Updated RPG & Survival templates with appropriate MMST permissions at each rank tier (XP boosts scale with rank progression)

Staged Plugin Lifecycle

The plugin initialization system has been completely rewritten with a clean, modular architecture:

  • 11 ordered stages: Config → Storage → CoreManager → Resolver → Registry → Chat → Integration → Web → Scheduler → Analytics → DefaultGroups
  • PluginLifecycle orchestrator initializes stages in order and shuts them down in reverse — if any stage fails, previously initialized stages are safely torn down
  • ServiceContainer provides typed dependency injection across all stages
  • HyperPerms.java reduced from ~400 lines of monolithic init to ~25 lines — all setup logic now lives in dedicated Stage implementations

Annotation-Based Command Framework

The entire command system has been rebuilt using a declarative annotation-driven approach:

  • New annotations: @CommandGroup, @Command, @Arg, @OptionalArg, @Permission, @Confirm
  • CommandScanner automatically discovers and registers annotated command methods at startup
  • CommandDispatcher handles argument parsing, permission checks, and confirmation flows
  • 5 annotated command groups replace 42 individual command classes: GroupCommands, UserCommands, DebugCommands, RootCommands, PermsCommands, BackupCommands
  • Net reduction of ~1,500 lines with significantly better maintainability

Web Editor Improvements

  • Gzip compressed session requests — Session create payloads are now gzip compressed before sending to the API, preventing HTTP 413 errors on servers with many groups and permissions

Bug Fixes

  • Fixed config being null during early stage initialization
  • Fixed default groups being created before storage was fully ready
  • Integrated 2.8.8's centralized sync and diff-based permission logic into the new lifecycle system

HyperPerms v2.8.8

Choose a tag to compare

@derrickmehaffyderrickmehaffy released this 05 Mar 23:10

[2.8.8] - 2026-02-23

Server Version:2026.02.19-1a311a592

Fixed

  • Permission pollution in Hytale's permissions.json - syncPermissionsToHytale() previously pushed all resolved permissions on every change, causing hundreds of permissions to accumulate. Now uses diff-based sync that computes the delta between Hytale's current state and HyperPerms' resolved set, only adding missing and removing stale permissions
  • Race condition in concurrent permission syncs - Multiple threads (command thread, scheduler, CF pool, web editor) could call syncPermissionsToHytale() simultaneously for the same user, racing on Hytale's non-thread-safe HashSet view from getUserPermissions(). Added per-UUID synchronization locks and defensive copying of the live view
  • Scattered manual sync calls - Six user commands and HyperPermsPermissionProvider each had their own inline syncPermissionsToHytale() call via bootstrap reflection. Centralized all sync logic into a CacheInvalidator.setSyncListener() hook — every cache invalidation now automatically triggers Hytale sync for affected online users
  • Group commands invalidated entire cache - Group permission/property changes (setperm, unsetperm, setprefix, setsuffix, setweight, setexpiry, parent add/remove) called invalidateAll() instead of targeted invalidateGroup(), causing unnecessary cache churn for unrelated users
  • Expired permissions not synced to Hytale - ExpiryCleanupTask removed expired nodes but didn't invalidate the cache or trigger Hytale sync, so expired permissions remained active until the player reconnected
  • Inconsistent cache invalidation API - Some commands used getCache().invalidate() (bypassing sync) while others used getCacheInvalidator().invalidate() (with sync). Unified all commands to use getCacheInvalidator()
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Releases: HyperSystems-Development/HyperPerms

2.10.0 — Command tab-completion, QoL fixes & QuestLines Claims compatibility

Choose a tag to compare

@nmang004nmang004 released this 24 Jun 00:52

Server Version:0.5.6 (release) · 0.6.0-pre.4 (pre-release)

Quality-of-life release: tab-completion for /hp, instant command-tree refresh, and fixes for several silently-broken integration paths — including a QuestLines Claims compatibility fix that was handing out double (or triple) the claims a permission allowed. The same codebase now runs on both the Hytale release (0.5.x) and pre-release (0.6.0-pre.x) channels.

Added

  • Tab-completion for /hp commands. Group, track, permission-node and online-player arguments now suggest as you type (case-insensitive prefix match). Previously every argument was a plain string with no completion.
  • Instant command-tree refresh. When a player's groups or permissions change, the affected online player gets a fresh command tree immediately — newly-granted commands appear without a relog.
  • Clickable download link in the "update available" notification (alongside /hp update).
  • Startup self-check that verifies the Hytale-core reflection targets used by optional integrations resolve on the running build, logging a clear warning if any are missing.

Fixed

  • QuestLines Claims granted double (or triple) the claims/rent a permission allowed. QuestLines computes claim/rent limits by summing the numeric suffix of questlinesclaims.claim.chunks.<n> / questlinesclaims.rent.limit.<n> nodes across every provider, and across both a user's permissions and each of their groups' permissions. HyperPerms exposed the same fully-resolved set through several of those surfaces (getUserPermissions, the virtual user:<uuid> group, and the native-provider sync), so each node was counted 2–3×. When QuestLines is detected, HyperPerms now collapses those to a single summable source — boolean checks are unaffected, and servers without QuestLines see no change. (LuckPerms was already special-cased by QuestLines, which is why it behaved correctly.)
  • PlaceholderAPI offline-player fallback never worked — it referenced a non-existent class (…server.HytaleServer, missing .core) and a dead getPlayerManager() chain, silently returning null. Now uses Universe.get().getPlayer(uuid).
  • MysticNameTags nameplate refresh never worked — the World class literal omitted its .world sub-package.
  • Event listener leaks across /reload — chat, tab-list and update-notification listeners stored their registration handles but never called unregister() (a stale comment claimed no such API existed). They now unregister properly instead of leaving duplicate handlers.
  • Stale "ghost" entries in the player/tab list — HyperPerms only ever added player-list entries; quitting players are now removed via RemoveFromServerPlayerList instead of lingering.

Changed

  • Centralized the Hytale-core reflection string literals (Universe, PlayerRef, World) into ReflectionUtil so a future Hytale package move is a one-line fix and the optional integrations can't drift independently.

Upgrade

Drop-in replacement for 2.9.x — no config changes. Replace the jar in mods/ and restart, using the build that matches your server channel:

  • HyperPerms-2.10.0.jar — Hytale release servers (0.5.x, manifest ^0.5.6)
  • HyperPerms-2.10.0-prerelease.jar — Hytale pre-release servers (0.6.0-pre.x, manifest ^0.6.0-pre.4)

If you run QuestLines Claims, HyperPerms prunes any duplicate questlinesclaims.* entries a previous version wrote into the native provider the first time each player connects after updating.


Requirements: Hytale 0.5.6+ (release) or 0.6.0-pre.x (pre-release), Java 25
Full Changelog:2.9.6...2.10.0
Discord:https://discord.gg/SNPjyfkYPc

2.9.6 — Hytale 0.5.2 OP recognition hotfix

Choose a tag to compare

@nmang004nmang004 released this 29 May 13:36

Server Version:0.5.2

Hotfix for operator (OP) recognition on Hytale 0.5.2. If you're on 2.9.5 and your HyperPerms admins are showing as "not OP" in-game, update to 2.9.6.

Fixed

  • HyperPerms admins were not recognized as OP on 0.5.2. Hytale 0.5.2 determines operator status by group membership — it checks whether a player is in the hytale:Admin group (getGroupsForUser(uuid).contains("hytale:Admin")), and FlyCameraModule/WorldMapTracker key off group names too. HyperPerms funnels all resolution through a single user:<uuid> virtual group, so admins were never seen in hytale:Admin and showed as "not OP" even though their permission checks passed.
  • getGroupsForUser now also advertises hytale:Admin for any user who effectively resolves the * permission (superuser). Granting a HyperPerms group the * node makes its members OP, recognized by Hytale and OP-gated features. Permission resolution itself is unchanged (still funneled through user:<uuid>).

Changed

  • Reverted the authoritative-provider mode added in 2.9.5. HyperPerms no longer removes Hytale's built-in provider; it registers itself first and keeps the built-in provider registered (its removal aggravated the OP break, because Hytale's getGroupsForUser aggregates across all providers).

Upgrade

Drop-in replacement for 2.9.5/2.9.4. No config changes. Replace the jar in mods/ and restart.


Requirements: Hytale 0.5.2+, Java 25
Full Changelog:2.9.5...2.9.6
Discord:https://discord.gg/SNPjyfkYPc

2.9.5 — Hytale 0.5.2 Support

Choose a tag to compare

@nmang004nmang004 released this 29 May 12:34

Server Version:0.5.2 ("Update 5", rev 8b2f3de, Java 25)

Compatibility release for Hytale 0.5.2. Verified by booting the local 0.5.2 server: HyperPerms loads, enables, and registers as the authoritative permission provider with no errors.

Fixed

  • Plugin failed to load on 0.5.2 (manifest). 0.5.2 added a strict SemverRange codec that rejected the manifest's bare ServerVersion (0.5.2) and the spaced >= 1.0.2 optional-dependency range. Now uses ^0.5.2 and >=1.0.2. Without this the plugin did not load at all.
  • PermissionProvider interface conformance. 0.5.2 expanded the interface from 10 to 14 methods. Implemented the four new ones (setUserGroup, getGroupParent, getAllRegisteredGroups, getEffectiveGroupPermissions).
  • Deny-by-default permission model. A group using -* (deny-all) plus specific grants previously had every granted permission silently denied on native command checks. HyperPerms now resolves these correctly — standard "deny-all, then grant" setups work, and native checks agree with /hp check.

Changed

  • Authoritative permission provider. HyperPerms now removes Hytale's built-in provider while enabled (and restores it on disable), so it is the single source of permission decisions. Manage everything via /hp — vanilla /perm, /setgroup and /op operate on data HyperPerms no longer consults, and /op self is advisory-disabled while HyperPerms is active (grant admin via a group with the * node).
  • Default build channel is now release (targets 0.5.2). Use -Phytale_channel=pre-release for pre-release builds.

Added

  • Registered the 0.5.2 built-in nodes so they surface in the web editor and wildcard expansion: hytale.world_map.teleport.coordinate, hytale.world_map.teleport.marker, hytale.system.update.notify (+ matching wildcards).

Removed

  • Obsolete warnAboutVanillaGroupOverwrite startup check (tested the legacy OP/Default group keys that no longer exist in 0.5.2).

Requirements: Hytale 0.5.2+, Java 25
Full Changelog:2.9.4...2.9.5
Discord:https://discord.gg/SNPjyfkYPc

HyperPerms v2.9.4

Choose a tag to compare

@derrickmehaffyderrickmehaffy released this 02 Apr 08:39

Fixed

  • TabListListener runtime crashUniverse.getPlayers() return type differs between Maven artifact (Collection) and runtime server (List), causing NoSuchMethodError. Fixed by copying into new ArrayList<>() to decouple from the return type descriptor

Server Version:2026.03.26-89796e57b

Full Changelog:https://github.com/HyperSystems-Development/HyperPerms/blob/main/CHANGELOG.md

HyperPerms v2.9.3

Choose a tag to compare

@nmang004nmang004 released this 28 Mar 12:37

v2.9.3 — March 26 Server Support

Server Version:2026.03.26 (release & pre-release)

What's New (since 2.9.1)

Added

  • Per-world permissionssetperm and unsetperm commands (group and user) now accept an optional world argument to restrict permissions to a specific world
  • Context display in info commands — Group and user info now shows context restrictions (e.g. [world=Survival]) on permission nodes

Fixed

  • API compatibility — Updated TabListListener to handle Universe.get().getPlayers() returning Collection<PlayerRef> instead of List<PlayerRef>, fixing compilation against the March 26 server update
  • Group inheritance priority — Child group permissions now always take precedence over inherited parent group permissions, regardless of weight values
  • LuckPerms H2 migration version mismatch — Use isolated classloader when loading H2 driver from LuckPerms libs
  • H2 driver selection — Prefer modern H2 driver over legacy to match current LuckPerms database format
  • H2 migration column access — Use unquoted column name for ResultSet access
  • Analytics flush data loss — Prevent race condition where permission check counters could be lost during flush
  • ImportCommand silent failures — Await all group save futures before reporting success
  • Non-atomic node mutations — Synchronize compound removeIf+add operations in setNode and addGroup
  • SQL serialization — Use Gson instead of hand-rolled JSON parser for correct escaping of special characters
  • Cycle detection case sensitivity — Normalize group names to lowercase in inheritance cycle detection
  • Template loader race condition — Prevent concurrent template loading from clearing the map mid-load
  • Confirmation memory leak — Clean up expired pending confirmations to prevent unbounded map growth
  • Migration thread starvation — Use dedicated executor instead of common ForkJoinPool for LuckPerms migration
  • SQLite nested ResultSet — Collect all rows before loading nodes to avoid driver conflicts on single connection
  • SQLite backup consistency — Checkpoint WAL before copying database file to capture all committed writes
  • SQLite restore PRAGMAs — Re-enable WAL and foreign_keys after restoring a backup
  • Clone command data loss — Await save future in clone command before reporting success
  • Group rename atomicity — Create new group before deleting old to prevent data loss on crash; await all save futures
  • JSON storage path traversal — Validate names on load/delete paths to prevent directory traversal
  • WildcardMatcher trace inconsistency — Add stripped-prefix matching to checkWithTrace() to match check() behavior

Full Changelog: v2.9.1...v2.9.3

HyperPerms v2.9.1

Choose a tag to compare

@nmang004nmang004 released this 09 Mar 00:31

v2.9.1 — Permission Resolution, Templates & PermissionsPlus Migration

Added

PermissionsPlus Migration Tool

Full migration support for servers transitioning from PermissionsPlus to HyperPerms.

  • /hp migrate permissionsplus — Preview migration (dry-run)
  • /hp migrate permissionsplus --confirm — Execute migration
  • Reads PermissionsPlus JSON data files and transforms groups, users, and permissions into HyperPerms format
  • Automatic permission cleaning and validation for PermissionsPlus-specific formats
  • Comprehensive test coverage for data models, permission cleaning, and validation

SSP Auto-Owner Assignment

First player to join a single-player (SSP) world is automatically assigned the owner group, removing the need for manual /hp user addgroup setup on fresh worlds.


Fixed

Permission Resolution Order

The resolver now evaluates permissions in most-specific-first order:

a.b.c → a.b.* → a.* → *

Previously, a broad wildcard like a.* could override a more specific grant or denial on a.b.c. This is now resolved — specific permissions always take priority.

Template Application with Existing Groups

/hp template apply no longer fails when groups from the template already exist on the server. Existing groups are gracefully skipped or merged instead of throwing an error.

Template Clearing Nodes and Tracks

Fixed UnsupportedOperationException when applying templates that clear existing nodes and tracks. Template application now uses proper mutable collection methods instead of operating on immutable list views.

SSP Owner Assignment Race Condition

Added synchronization guard to prevent duplicate owner group assignments when multiple players connect simultaneously during first server start.


Chore

  • Bumped version to 2.9.1
  • Updated CHANGELOG.md

Full Commit Log

TypeScopeDescription
featmigrationAdd PermissionsPlus data models
featmigrationAdd PermissionsPlus migrator with JSON reading and transformation
featmigrationRegister PermissionsPlus migrator in /hp migrate command
testmigrationAdd PermissionsPlus data model tests
testmigrationAdd PermissionsPlus permission cleaning and validation tests
refactormigrationApply code review fixes to PermissionsPlus migrator
fixresolverChange to most-specific-first permission resolution order
fixtemplateGracefully handle existing groups during template application
featsspAuto-assign owner group to first player
fixsspPrevent race condition in first-player owner assignment
fixtemplateUse proper mutable methods for clearing nodes and tracks
choreBump version to 2.9.1 and update changelog

v2.9.0-rc1: Permission Resolution, Template & SSP Fixes

Choose a tag to compare

@nmang004nmang004 released this 08 Mar 15:40

Fixes

  • Permission Resolution: Specific grants (e.g. + simpleclaims.edit-party) now correctly override global denies (- *). Resolution order changed to most-specific-first.
  • Template Application: Fixed "Failed to apply template: null" error when applying templates to servers with existing groups. Template applier now uses proper mutable methods for updating groups and tracks.
  • SSP Auto-Owner: First player on an empty server is automatically assigned the configured owner group.

Testing

Download HyperPerms-2.9.0.jar and replace your existing plugin JAR. Please report any issues.

HyperPerms v2.9.0

Choose a tag to compare

@derrickmehaffyderrickmehaffy released this 05 Mar 23:10

Hotfix: Web Editor Session Create

Fixed

  • Web editor returning 500 on /hp editor — The gzip compression introduced in 2.8.9 was applied to all session create requests, but the Cloudflare Worker API does not support Content-Encoding: gzip on incoming request bodies. This caused every /hp editor command to fail with "Server returned status 500". Compression is now only applied to payloads exceeding 500KB, keeping normal requests uncompressed while still protecting very large servers from HTTP 413 errors.

If you are on 2.8.9, update immediately.

HyperPerms v2.8.9

Choose a tag to compare

@derrickmehaffyderrickmehaffy released this 05 Mar 23:10

Architecture Rehaul & MMOSkillTree Integration

First-Class MMOSkillTree Support

HyperPerms now has full, first-class integration with MMOSkillTree — one of the biggest plugins on Hytale.

  • 200+ permission nodes registered across admin, command, skill, boost, and alternate prefix categories
  • All 23 skill nodesmmoskilltree.skill.mining, .woodcutting, .excavation, .harvesting, .fishing, .swords, .daggers, .polearms, .staves, .axes, .blunt, .archery, .unarmed, .defense, .taming, .acrobatics, .crafting, .repair, .alchemy, .enchanting, .cooking, .smithing, .building
  • All 140 XP boost permission nodes covering personal and global boosts for all skills, skill categories, and all-skills targets with varying multipliers, durations, and cooldowns
  • ziggfreed.* alternate prefix support — MMOSkillTree checks permissions through both mmoskilltree.* and ziggfreed.mmoskilltree.* prefixes. HyperPerms now correctly resolves both via bidirectional aliases
  • Hytale command path aliasescom.ziggfreed.mmoskilltree.command.* paths resolve to their mmoskilltree.command.* equivalents
  • Wildcard expansion for all MMST permission categories
  • Tab completion & web editor now show all MMST permission nodes
  • Updated RPG & Survival templates with appropriate MMST permissions at each rank tier (XP boosts scale with rank progression)

Staged Plugin Lifecycle

The plugin initialization system has been completely rewritten with a clean, modular architecture:

  • 11 ordered stages: Config → Storage → CoreManager → Resolver → Registry → Chat → Integration → Web → Scheduler → Analytics → DefaultGroups
  • PluginLifecycle orchestrator initializes stages in order and shuts them down in reverse — if any stage fails, previously initialized stages are safely torn down
  • ServiceContainer provides typed dependency injection across all stages
  • HyperPerms.java reduced from ~400 lines of monolithic init to ~25 lines — all setup logic now lives in dedicated Stage implementations

Annotation-Based Command Framework

The entire command system has been rebuilt using a declarative annotation-driven approach:

  • New annotations: @CommandGroup, @Command, @Arg, @OptionalArg, @Permission, @Confirm
  • CommandScanner automatically discovers and registers annotated command methods at startup
  • CommandDispatcher handles argument parsing, permission checks, and confirmation flows
  • 5 annotated command groups replace 42 individual command classes: GroupCommands, UserCommands, DebugCommands, RootCommands, PermsCommands, BackupCommands
  • Net reduction of ~1,500 lines with significantly better maintainability

Web Editor Improvements

  • Gzip compressed session requests — Session create payloads are now gzip compressed before sending to the API, preventing HTTP 413 errors on servers with many groups and permissions

Bug Fixes

  • Fixed config being null during early stage initialization
  • Fixed default groups being created before storage was fully ready
  • Integrated 2.8.8's centralized sync and diff-based permission logic into the new lifecycle system

HyperPerms v2.8.8

Choose a tag to compare

@derrickmehaffyderrickmehaffy released this 05 Mar 23:10

[2.8.8] - 2026-02-23

Server Version:2026.02.19-1a311a592

Fixed

  • Permission pollution in Hytale's permissions.json - syncPermissionsToHytale() previously pushed all resolved permissions on every change, causing hundreds of permissions to accumulate. Now uses diff-based sync that computes the delta between Hytale's current state and HyperPerms' resolved set, only adding missing and removing stale permissions
  • Race condition in concurrent permission syncs - Multiple threads (command thread, scheduler, CF pool, web editor) could call syncPermissionsToHytale() simultaneously for the same user, racing on Hytale's non-thread-safe HashSet view from getUserPermissions(). Added per-UUID synchronization locks and defensive copying of the live view
  • Scattered manual sync calls - Six user commands and HyperPermsPermissionProvider each had their own inline syncPermissionsToHytale() call via bootstrap reflection. Centralized all sync logic into a CacheInvalidator.setSyncListener() hook — every cache invalidation now automatically triggers Hytale sync for affected online users
  • Group commands invalidated entire cache - Group permission/property changes (setperm, unsetperm, setprefix, setsuffix, setweight, setexpiry, parent add/remove) called invalidateAll() instead of targeted invalidateGroup(), causing unnecessary cache churn for unrelated users
  • Expired permissions not synced to Hytale - ExpiryCleanupTask removed expired nodes but didn't invalidate the cache or trigger Hytale sync, so expired permissions remained active until the player reconnected
  • Inconsistent cache invalidation API - Some commands used getCache().invalidate() (bypassing sync) while others used getCacheInvalidator().invalidate() (with sync). Unified all commands to use getCacheInvalidator()
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Releases: HyperSystems-Development/HyperPerms

2.10.0 — Command tab-completion, QoL fixes & QuestLines Claims compatibility

Choose a tag to compare

@nmang004nmang004 released this 24 Jun 00:52

Server Version:0.5.6 (release) · 0.6.0-pre.4 (pre-release)

Quality-of-life release: tab-completion for /hp, instant command-tree refresh, and fixes for several silently-broken integration paths — including a QuestLines Claims compatibility fix that was handing out double (or triple) the claims a permission allowed. The same codebase now runs on both the Hytale release (0.5.x) and pre-release (0.6.0-pre.x) channels.

Added

  • Tab-completion for /hp commands. Group, track, permission-node and online-player arguments now suggest as you type (case-insensitive prefix match). Previously every argument was a plain string with no completion.
  • Instant command-tree refresh. When a player's groups or permissions change, the affected online player gets a fresh command tree immediately — newly-granted commands appear without a relog.
  • Clickable download link in the "update available" notification (alongside /hp update).
  • Startup self-check that verifies the Hytale-core reflection targets used by optional integrations resolve on the running build, logging a clear warning if any are missing.

Fixed

  • QuestLines Claims granted double (or triple) the claims/rent a permission allowed. QuestLines computes claim/rent limits by summing the numeric suffix of questlinesclaims.claim.chunks.<n> / questlinesclaims.rent.limit.<n> nodes across every provider, and across both a user's permissions and each of their groups' permissions. HyperPerms exposed the same fully-resolved set through several of those surfaces (getUserPermissions, the virtual user:<uuid> group, and the native-provider sync), so each node was counted 2–3×. When QuestLines is detected, HyperPerms now collapses those to a single summable source — boolean checks are unaffected, and servers without QuestLines see no change. (LuckPerms was already special-cased by QuestLines, which is why it behaved correctly.)
  • PlaceholderAPI offline-player fallback never worked — it referenced a non-existent class (…server.HytaleServer, missing .core) and a dead getPlayerManager() chain, silently returning null. Now uses Universe.get().getPlayer(uuid).
  • MysticNameTags nameplate refresh never worked — the World class literal omitted its .world sub-package.
  • Event listener leaks across /reload — chat, tab-list and update-notification listeners stored their registration handles but never called unregister() (a stale comment claimed no such API existed). They now unregister properly instead of leaving duplicate handlers.
  • Stale "ghost" entries in the player/tab list — HyperPerms only ever added player-list entries; quitting players are now removed via RemoveFromServerPlayerList instead of lingering.

Changed

  • Centralized the Hytale-core reflection string literals (Universe, PlayerRef, World) into ReflectionUtil so a future Hytale package move is a one-line fix and the optional integrations can't drift independently.

Upgrade

Drop-in replacement for 2.9.x — no config changes. Replace the jar in mods/ and restart, using the build that matches your server channel:

  • HyperPerms-2.10.0.jar — Hytale release servers (0.5.x, manifest ^0.5.6)
  • HyperPerms-2.10.0-prerelease.jar — Hytale pre-release servers (0.6.0-pre.x, manifest ^0.6.0-pre.4)

If you run QuestLines Claims, HyperPerms prunes any duplicate questlinesclaims.* entries a previous version wrote into the native provider the first time each player connects after updating.


Requirements: Hytale 0.5.6+ (release) or 0.6.0-pre.x (pre-release), Java 25
Full Changelog:2.9.6...2.10.0
Discord:https://discord.gg/SNPjyfkYPc

2.9.6 — Hytale 0.5.2 OP recognition hotfix

Choose a tag to compare

@nmang004nmang004 released this 29 May 13:36

Server Version:0.5.2

Hotfix for operator (OP) recognition on Hytale 0.5.2. If you're on 2.9.5 and your HyperPerms admins are showing as "not OP" in-game, update to 2.9.6.

Fixed

  • HyperPerms admins were not recognized as OP on 0.5.2. Hytale 0.5.2 determines operator status by group membership — it checks whether a player is in the hytale:Admin group (getGroupsForUser(uuid).contains("hytale:Admin")), and FlyCameraModule/WorldMapTracker key off group names too. HyperPerms funnels all resolution through a single user:<uuid> virtual group, so admins were never seen in hytale:Admin and showed as "not OP" even though their permission checks passed.
  • getGroupsForUser now also advertises hytale:Admin for any user who effectively resolves the * permission (superuser). Granting a HyperPerms group the * node makes its members OP, recognized by Hytale and OP-gated features. Permission resolution itself is unchanged (still funneled through user:<uuid>).

Changed

  • Reverted the authoritative-provider mode added in 2.9.5. HyperPerms no longer removes Hytale's built-in provider; it registers itself first and keeps the built-in provider registered (its removal aggravated the OP break, because Hytale's getGroupsForUser aggregates across all providers).

Upgrade

Drop-in replacement for 2.9.5/2.9.4. No config changes. Replace the jar in mods/ and restart.


Requirements: Hytale 0.5.2+, Java 25
Full Changelog:2.9.5...2.9.6
Discord:https://discord.gg/SNPjyfkYPc

2.9.5 — Hytale 0.5.2 Support

Choose a tag to compare

@nmang004nmang004 released this 29 May 12:34

Server Version:0.5.2 ("Update 5", rev 8b2f3de, Java 25)

Compatibility release for Hytale 0.5.2. Verified by booting the local 0.5.2 server: HyperPerms loads, enables, and registers as the authoritative permission provider with no errors.

Fixed

  • Plugin failed to load on 0.5.2 (manifest). 0.5.2 added a strict SemverRange codec that rejected the manifest's bare ServerVersion (0.5.2) and the spaced >= 1.0.2 optional-dependency range. Now uses ^0.5.2 and >=1.0.2. Without this the plugin did not load at all.
  • PermissionProvider interface conformance. 0.5.2 expanded the interface from 10 to 14 methods. Implemented the four new ones (setUserGroup, getGroupParent, getAllRegisteredGroups, getEffectiveGroupPermissions).
  • Deny-by-default permission model. A group using -* (deny-all) plus specific grants previously had every granted permission silently denied on native command checks. HyperPerms now resolves these correctly — standard "deny-all, then grant" setups work, and native checks agree with /hp check.

Changed

  • Authoritative permission provider. HyperPerms now removes Hytale's built-in provider while enabled (and restores it on disable), so it is the single source of permission decisions. Manage everything via /hp — vanilla /perm, /setgroup and /op operate on data HyperPerms no longer consults, and /op self is advisory-disabled while HyperPerms is active (grant admin via a group with the * node).
  • Default build channel is now release (targets 0.5.2). Use -Phytale_channel=pre-release for pre-release builds.

Added

  • Registered the 0.5.2 built-in nodes so they surface in the web editor and wildcard expansion: hytale.world_map.teleport.coordinate, hytale.world_map.teleport.marker, hytale.system.update.notify (+ matching wildcards).

Removed

  • Obsolete warnAboutVanillaGroupOverwrite startup check (tested the legacy OP/Default group keys that no longer exist in 0.5.2).

Requirements: Hytale 0.5.2+, Java 25
Full Changelog:2.9.4...2.9.5
Discord:https://discord.gg/SNPjyfkYPc

HyperPerms v2.9.4

Choose a tag to compare

@derrickmehaffyderrickmehaffy released this 02 Apr 08:39

Fixed

  • TabListListener runtime crashUniverse.getPlayers() return type differs between Maven artifact (Collection) and runtime server (List), causing NoSuchMethodError. Fixed by copying into new ArrayList<>() to decouple from the return type descriptor

Server Version:2026.03.26-89796e57b

Full Changelog:https://github.com/HyperSystems-Development/HyperPerms/blob/main/CHANGELOG.md

HyperPerms v2.9.3

Choose a tag to compare

@nmang004nmang004 released this 28 Mar 12:37

v2.9.3 — March 26 Server Support

Server Version:2026.03.26 (release & pre-release)

What's New (since 2.9.1)

Added

  • Per-world permissionssetperm and unsetperm commands (group and user) now accept an optional world argument to restrict permissions to a specific world
  • Context display in info commands — Group and user info now shows context restrictions (e.g. [world=Survival]) on permission nodes

Fixed

  • API compatibility — Updated TabListListener to handle Universe.get().getPlayers() returning Collection<PlayerRef> instead of List<PlayerRef>, fixing compilation against the March 26 server update
  • Group inheritance priority — Child group permissions now always take precedence over inherited parent group permissions, regardless of weight values
  • LuckPerms H2 migration version mismatch — Use isolated classloader when loading H2 driver from LuckPerms libs
  • H2 driver selection — Prefer modern H2 driver over legacy to match current LuckPerms database format
  • H2 migration column access — Use unquoted column name for ResultSet access
  • Analytics flush data loss — Prevent race condition where permission check counters could be lost during flush
  • ImportCommand silent failures — Await all group save futures before reporting success
  • Non-atomic node mutations — Synchronize compound removeIf+add operations in setNode and addGroup
  • SQL serialization — Use Gson instead of hand-rolled JSON parser for correct escaping of special characters
  • Cycle detection case sensitivity — Normalize group names to lowercase in inheritance cycle detection
  • Template loader race condition — Prevent concurrent template loading from clearing the map mid-load
  • Confirmation memory leak — Clean up expired pending confirmations to prevent unbounded map growth
  • Migration thread starvation — Use dedicated executor instead of common ForkJoinPool for LuckPerms migration
  • SQLite nested ResultSet — Collect all rows before loading nodes to avoid driver conflicts on single connection
  • SQLite backup consistency — Checkpoint WAL before copying database file to capture all committed writes
  • SQLite restore PRAGMAs — Re-enable WAL and foreign_keys after restoring a backup
  • Clone command data loss — Await save future in clone command before reporting success
  • Group rename atomicity — Create new group before deleting old to prevent data loss on crash; await all save futures
  • JSON storage path traversal — Validate names on load/delete paths to prevent directory traversal
  • WildcardMatcher trace inconsistency — Add stripped-prefix matching to checkWithTrace() to match check() behavior

Full Changelog: v2.9.1...v2.9.3

HyperPerms v2.9.1

Choose a tag to compare

@nmang004nmang004 released this 09 Mar 00:31

v2.9.1 — Permission Resolution, Templates & PermissionsPlus Migration

Added

PermissionsPlus Migration Tool

Full migration support for servers transitioning from PermissionsPlus to HyperPerms.

  • /hp migrate permissionsplus — Preview migration (dry-run)
  • /hp migrate permissionsplus --confirm — Execute migration
  • Reads PermissionsPlus JSON data files and transforms groups, users, and permissions into HyperPerms format
  • Automatic permission cleaning and validation for PermissionsPlus-specific formats
  • Comprehensive test coverage for data models, permission cleaning, and validation

SSP Auto-Owner Assignment

First player to join a single-player (SSP) world is automatically assigned the owner group, removing the need for manual /hp user addgroup setup on fresh worlds.


Fixed

Permission Resolution Order

The resolver now evaluates permissions in most-specific-first order:

a.b.c → a.b.* → a.* → *

Previously, a broad wildcard like a.* could override a more specific grant or denial on a.b.c. This is now resolved — specific permissions always take priority.

Template Application with Existing Groups

/hp template apply no longer fails when groups from the template already exist on the server. Existing groups are gracefully skipped or merged instead of throwing an error.

Template Clearing Nodes and Tracks

Fixed UnsupportedOperationException when applying templates that clear existing nodes and tracks. Template application now uses proper mutable collection methods instead of operating on immutable list views.

SSP Owner Assignment Race Condition

Added synchronization guard to prevent duplicate owner group assignments when multiple players connect simultaneously during first server start.


Chore

  • Bumped version to 2.9.1
  • Updated CHANGELOG.md

Full Commit Log

TypeScopeDescription
featmigrationAdd PermissionsPlus data models
featmigrationAdd PermissionsPlus migrator with JSON reading and transformation
featmigrationRegister PermissionsPlus migrator in /hp migrate command
testmigrationAdd PermissionsPlus data model tests
testmigrationAdd PermissionsPlus permission cleaning and validation tests
refactormigrationApply code review fixes to PermissionsPlus migrator
fixresolverChange to most-specific-first permission resolution order
fixtemplateGracefully handle existing groups during template application
featsspAuto-assign owner group to first player
fixsspPrevent race condition in first-player owner assignment
fixtemplateUse proper mutable methods for clearing nodes and tracks
choreBump version to 2.9.1 and update changelog

v2.9.0-rc1: Permission Resolution, Template & SSP Fixes

Choose a tag to compare

@nmang004nmang004 released this 08 Mar 15:40

Fixes

  • Permission Resolution: Specific grants (e.g. + simpleclaims.edit-party) now correctly override global denies (- *). Resolution order changed to most-specific-first.
  • Template Application: Fixed "Failed to apply template: null" error when applying templates to servers with existing groups. Template applier now uses proper mutable methods for updating groups and tracks.
  • SSP Auto-Owner: First player on an empty server is automatically assigned the configured owner group.

Testing

Download HyperPerms-2.9.0.jar and replace your existing plugin JAR. Please report any issues.

HyperPerms v2.9.0

Choose a tag to compare

@derrickmehaffyderrickmehaffy released this 05 Mar 23:10

Hotfix: Web Editor Session Create

Fixed

  • Web editor returning 500 on /hp editor — The gzip compression introduced in 2.8.9 was applied to all session create requests, but the Cloudflare Worker API does not support Content-Encoding: gzip on incoming request bodies. This caused every /hp editor command to fail with "Server returned status 500". Compression is now only applied to payloads exceeding 500KB, keeping normal requests uncompressed while still protecting very large servers from HTTP 413 errors.

If you are on 2.8.9, update immediately.

HyperPerms v2.8.9

Choose a tag to compare

@derrickmehaffyderrickmehaffy released this 05 Mar 23:10

Architecture Rehaul & MMOSkillTree Integration

First-Class MMOSkillTree Support

HyperPerms now has full, first-class integration with MMOSkillTree — one of the biggest plugins on Hytale.

  • 200+ permission nodes registered across admin, command, skill, boost, and alternate prefix categories
  • All 23 skill nodesmmoskilltree.skill.mining, .woodcutting, .excavation, .harvesting, .fishing, .swords, .daggers, .polearms, .staves, .axes, .blunt, .archery, .unarmed, .defense, .taming, .acrobatics, .crafting, .repair, .alchemy, .enchanting, .cooking, .smithing, .building
  • All 140 XP boost permission nodes covering personal and global boosts for all skills, skill categories, and all-skills targets with varying multipliers, durations, and cooldowns
  • ziggfreed.* alternate prefix support — MMOSkillTree checks permissions through both mmoskilltree.* and ziggfreed.mmoskilltree.* prefixes. HyperPerms now correctly resolves both via bidirectional aliases
  • Hytale command path aliasescom.ziggfreed.mmoskilltree.command.* paths resolve to their mmoskilltree.command.* equivalents
  • Wildcard expansion for all MMST permission categories
  • Tab completion & web editor now show all MMST permission nodes
  • Updated RPG & Survival templates with appropriate MMST permissions at each rank tier (XP boosts scale with rank progression)

Staged Plugin Lifecycle

The plugin initialization system has been completely rewritten with a clean, modular architecture:

  • 11 ordered stages: Config → Storage → CoreManager → Resolver → Registry → Chat → Integration → Web → Scheduler → Analytics → DefaultGroups
  • PluginLifecycle orchestrator initializes stages in order and shuts them down in reverse — if any stage fails, previously initialized stages are safely torn down
  • ServiceContainer provides typed dependency injection across all stages
  • HyperPerms.java reduced from ~400 lines of monolithic init to ~25 lines — all setup logic now lives in dedicated Stage implementations

Annotation-Based Command Framework

The entire command system has been rebuilt using a declarative annotation-driven approach:

  • New annotations: @CommandGroup, @Command, @Arg, @OptionalArg, @Permission, @Confirm
  • CommandScanner automatically discovers and registers annotated command methods at startup
  • CommandDispatcher handles argument parsing, permission checks, and confirmation flows
  • 5 annotated command groups replace 42 individual command classes: GroupCommands, UserCommands, DebugCommands, RootCommands, PermsCommands, BackupCommands
  • Net reduction of ~1,500 lines with significantly better maintainability

Web Editor Improvements

  • Gzip compressed session requests — Session create payloads are now gzip compressed before sending to the API, preventing HTTP 413 errors on servers with many groups and permissions

Bug Fixes

  • Fixed config being null during early stage initialization
  • Fixed default groups being created before storage was fully ready
  • Integrated 2.8.8's centralized sync and diff-based permission logic into the new lifecycle system

HyperPerms v2.8.8

Choose a tag to compare

@derrickmehaffyderrickmehaffy released this 05 Mar 23:10

[2.8.8] - 2026-02-23

Server Version:2026.02.19-1a311a592

Fixed

  • Permission pollution in Hytale's permissions.json - syncPermissionsToHytale() previously pushed all resolved permissions on every change, causing hundreds of permissions to accumulate. Now uses diff-based sync that computes the delta between Hytale's current state and HyperPerms' resolved set, only adding missing and removing stale permissions
  • Race condition in concurrent permission syncs - Multiple threads (command thread, scheduler, CF pool, web editor) could call syncPermissionsToHytale() simultaneously for the same user, racing on Hytale's non-thread-safe HashSet view from getUserPermissions(). Added per-UUID synchronization locks and defensive copying of the live view
  • Scattered manual sync calls - Six user commands and HyperPermsPermissionProvider each had their own inline syncPermissionsToHytale() call via bootstrap reflection. Centralized all sync logic into a CacheInvalidator.setSyncListener() hook — every cache invalidation now automatically triggers Hytale sync for affected online users
  • Group commands invalidated entire cache - Group permission/property changes (setperm, unsetperm, setprefix, setsuffix, setweight, setexpiry, parent add/remove) called invalidateAll() instead of targeted invalidateGroup(), causing unnecessary cache churn for unrelated users
  • Expired permissions not synced to Hytale - ExpiryCleanupTask removed expired nodes but didn't invalidate the cache or trigger Hytale sync, so expired permissions remained active until the player reconnected
  • Inconsistent cache invalidation API - Some commands used getCache().invalidate() (bypassing sync) while others used getCacheInvalidator().invalidate() (with sync). Unified all commands to use getCacheInvalidator()
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Releases: HyperSystems-Development/HyperPerms

2.10.0 — Command tab-completion, QoL fixes & QuestLines Claims compatibility

Choose a tag to compare

@nmang004nmang004 released this 24 Jun 00:52

Server Version:0.5.6 (release) · 0.6.0-pre.4 (pre-release)

Quality-of-life release: tab-completion for /hp, instant command-tree refresh, and fixes for several silently-broken integration paths — including a QuestLines Claims compatibility fix that was handing out double (or triple) the claims a permission allowed. The same codebase now runs on both the Hytale release (0.5.x) and pre-release (0.6.0-pre.x) channels.

Added

  • Tab-completion for /hp commands. Group, track, permission-node and online-player arguments now suggest as you type (case-insensitive prefix match). Previously every argument was a plain string with no completion.
  • Instant command-tree refresh. When a player's groups or permissions change, the affected online player gets a fresh command tree immediately — newly-granted commands appear without a relog.
  • Clickable download link in the "update available" notification (alongside /hp update).
  • Startup self-check that verifies the Hytale-core reflection targets used by optional integrations resolve on the running build, logging a clear warning if any are missing.

Fixed

  • QuestLines Claims granted double (or triple) the claims/rent a permission allowed. QuestLines computes claim/rent limits by summing the numeric suffix of questlinesclaims.claim.chunks.<n> / questlinesclaims.rent.limit.<n> nodes across every provider, and across both a user's permissions and each of their groups' permissions. HyperPerms exposed the same fully-resolved set through several of those surfaces (getUserPermissions, the virtual user:<uuid> group, and the native-provider sync), so each node was counted 2–3×. When QuestLines is detected, HyperPerms now collapses those to a single summable source — boolean checks are unaffected, and servers without QuestLines see no change. (LuckPerms was already special-cased by QuestLines, which is why it behaved correctly.)
  • PlaceholderAPI offline-player fallback never worked — it referenced a non-existent class (…server.HytaleServer, missing .core) and a dead getPlayerManager() chain, silently returning null. Now uses Universe.get().getPlayer(uuid).
  • MysticNameTags nameplate refresh never worked — the World class literal omitted its .world sub-package.
  • Event listener leaks across /reload — chat, tab-list and update-notification listeners stored their registration handles but never called unregister() (a stale comment claimed no such API existed). They now unregister properly instead of leaving duplicate handlers.
  • Stale "ghost" entries in the player/tab list — HyperPerms only ever added player-list entries; quitting players are now removed via RemoveFromServerPlayerList instead of lingering.

Changed

  • Centralized the Hytale-core reflection string literals (Universe, PlayerRef, World) into ReflectionUtil so a future Hytale package move is a one-line fix and the optional integrations can't drift independently.

Upgrade

Drop-in replacement for 2.9.x — no config changes. Replace the jar in mods/ and restart, using the build that matches your server channel:

  • HyperPerms-2.10.0.jar — Hytale release servers (0.5.x, manifest ^0.5.6)
  • HyperPerms-2.10.0-prerelease.jar — Hytale pre-release servers (0.6.0-pre.x, manifest ^0.6.0-pre.4)

If you run QuestLines Claims, HyperPerms prunes any duplicate questlinesclaims.* entries a previous version wrote into the native provider the first time each player connects after updating.


Requirements: Hytale 0.5.6+ (release) or 0.6.0-pre.x (pre-release), Java 25
Full Changelog:2.9.6...2.10.0
Discord:https://discord.gg/SNPjyfkYPc

2.9.6 — Hytale 0.5.2 OP recognition hotfix

Choose a tag to compare

@nmang004nmang004 released this 29 May 13:36

Server Version:0.5.2

Hotfix for operator (OP) recognition on Hytale 0.5.2. If you're on 2.9.5 and your HyperPerms admins are showing as "not OP" in-game, update to 2.9.6.

Fixed

  • HyperPerms admins were not recognized as OP on 0.5.2. Hytale 0.5.2 determines operator status by group membership — it checks whether a player is in the hytale:Admin group (getGroupsForUser(uuid).contains("hytale:Admin")), and FlyCameraModule/WorldMapTracker key off group names too. HyperPerms funnels all resolution through a single user:<uuid> virtual group, so admins were never seen in hytale:Admin and showed as "not OP" even though their permission checks passed.
  • getGroupsForUser now also advertises hytale:Admin for any user who effectively resolves the * permission (superuser). Granting a HyperPerms group the * node makes its members OP, recognized by Hytale and OP-gated features. Permission resolution itself is unchanged (still funneled through user:<uuid>).

Changed

  • Reverted the authoritative-provider mode added in 2.9.5. HyperPerms no longer removes Hytale's built-in provider; it registers itself first and keeps the built-in provider registered (its removal aggravated the OP break, because Hytale's getGroupsForUser aggregates across all providers).

Upgrade

Drop-in replacement for 2.9.5/2.9.4. No config changes. Replace the jar in mods/ and restart.


Requirements: Hytale 0.5.2+, Java 25
Full Changelog:2.9.5...2.9.6
Discord:https://discord.gg/SNPjyfkYPc

2.9.5 — Hytale 0.5.2 Support

Choose a tag to compare

@nmang004nmang004 released this 29 May 12:34

Server Version:0.5.2 ("Update 5", rev 8b2f3de, Java 25)

Compatibility release for Hytale 0.5.2. Verified by booting the local 0.5.2 server: HyperPerms loads, enables, and registers as the authoritative permission provider with no errors.

Fixed

  • Plugin failed to load on 0.5.2 (manifest). 0.5.2 added a strict SemverRange codec that rejected the manifest's bare ServerVersion (0.5.2) and the spaced >= 1.0.2 optional-dependency range. Now uses ^0.5.2 and >=1.0.2. Without this the plugin did not load at all.
  • PermissionProvider interface conformance. 0.5.2 expanded the interface from 10 to 14 methods. Implemented the four new ones (setUserGroup, getGroupParent, getAllRegisteredGroups, getEffectiveGroupPermissions).
  • Deny-by-default permission model. A group using -* (deny-all) plus specific grants previously had every granted permission silently denied on native command checks. HyperPerms now resolves these correctly — standard "deny-all, then grant" setups work, and native checks agree with /hp check.

Changed

  • Authoritative permission provider. HyperPerms now removes Hytale's built-in provider while enabled (and restores it on disable), so it is the single source of permission decisions. Manage everything via /hp — vanilla /perm, /setgroup and /op operate on data HyperPerms no longer consults, and /op self is advisory-disabled while HyperPerms is active (grant admin via a group with the * node).
  • Default build channel is now release (targets 0.5.2). Use -Phytale_channel=pre-release for pre-release builds.

Added

  • Registered the 0.5.2 built-in nodes so they surface in the web editor and wildcard expansion: hytale.world_map.teleport.coordinate, hytale.world_map.teleport.marker, hytale.system.update.notify (+ matching wildcards).

Removed

  • Obsolete warnAboutVanillaGroupOverwrite startup check (tested the legacy OP/Default group keys that no longer exist in 0.5.2).

Requirements: Hytale 0.5.2+, Java 25
Full Changelog:2.9.4...2.9.5
Discord:https://discord.gg/SNPjyfkYPc

HyperPerms v2.9.4

Choose a tag to compare

@derrickmehaffyderrickmehaffy released this 02 Apr 08:39

Fixed

  • TabListListener runtime crashUniverse.getPlayers() return type differs between Maven artifact (Collection) and runtime server (List), causing NoSuchMethodError. Fixed by copying into new ArrayList<>() to decouple from the return type descriptor

Server Version:2026.03.26-89796e57b

Full Changelog:https://github.com/HyperSystems-Development/HyperPerms/blob/main/CHANGELOG.md

HyperPerms v2.9.3

Choose a tag to compare

@nmang004nmang004 released this 28 Mar 12:37

v2.9.3 — March 26 Server Support

Server Version:2026.03.26 (release & pre-release)

What's New (since 2.9.1)

Added

  • Per-world permissionssetperm and unsetperm commands (group and user) now accept an optional world argument to restrict permissions to a specific world
  • Context display in info commands — Group and user info now shows context restrictions (e.g. [world=Survival]) on permission nodes

Fixed

  • API compatibility — Updated TabListListener to handle Universe.get().getPlayers() returning Collection<PlayerRef> instead of List<PlayerRef>, fixing compilation against the March 26 server update
  • Group inheritance priority — Child group permissions now always take precedence over inherited parent group permissions, regardless of weight values
  • LuckPerms H2 migration version mismatch — Use isolated classloader when loading H2 driver from LuckPerms libs
  • H2 driver selection — Prefer modern H2 driver over legacy to match current LuckPerms database format
  • H2 migration column access — Use unquoted column name for ResultSet access
  • Analytics flush data loss — Prevent race condition where permission check counters could be lost during flush
  • ImportCommand silent failures — Await all group save futures before reporting success
  • Non-atomic node mutations — Synchronize compound removeIf+add operations in setNode and addGroup
  • SQL serialization — Use Gson instead of hand-rolled JSON parser for correct escaping of special characters
  • Cycle detection case sensitivity — Normalize group names to lowercase in inheritance cycle detection
  • Template loader race condition — Prevent concurrent template loading from clearing the map mid-load
  • Confirmation memory leak — Clean up expired pending confirmations to prevent unbounded map growth
  • Migration thread starvation — Use dedicated executor instead of common ForkJoinPool for LuckPerms migration
  • SQLite nested ResultSet — Collect all rows before loading nodes to avoid driver conflicts on single connection
  • SQLite backup consistency — Checkpoint WAL before copying database file to capture all committed writes
  • SQLite restore PRAGMAs — Re-enable WAL and foreign_keys after restoring a backup
  • Clone command data loss — Await save future in clone command before reporting success
  • Group rename atomicity — Create new group before deleting old to prevent data loss on crash; await all save futures
  • JSON storage path traversal — Validate names on load/delete paths to prevent directory traversal
  • WildcardMatcher trace inconsistency — Add stripped-prefix matching to checkWithTrace() to match check() behavior

Full Changelog: v2.9.1...v2.9.3

HyperPerms v2.9.1

Choose a tag to compare

@nmang004nmang004 released this 09 Mar 00:31

v2.9.1 — Permission Resolution, Templates & PermissionsPlus Migration

Added

PermissionsPlus Migration Tool

Full migration support for servers transitioning from PermissionsPlus to HyperPerms.

  • /hp migrate permissionsplus — Preview migration (dry-run)
  • /hp migrate permissionsplus --confirm — Execute migration
  • Reads PermissionsPlus JSON data files and transforms groups, users, and permissions into HyperPerms format
  • Automatic permission cleaning and validation for PermissionsPlus-specific formats
  • Comprehensive test coverage for data models, permission cleaning, and validation

SSP Auto-Owner Assignment

First player to join a single-player (SSP) world is automatically assigned the owner group, removing the need for manual /hp user addgroup setup on fresh worlds.


Fixed

Permission Resolution Order

The resolver now evaluates permissions in most-specific-first order:

a.b.c → a.b.* → a.* → *

Previously, a broad wildcard like a.* could override a more specific grant or denial on a.b.c. This is now resolved — specific permissions always take priority.

Template Application with Existing Groups

/hp template apply no longer fails when groups from the template already exist on the server. Existing groups are gracefully skipped or merged instead of throwing an error.

Template Clearing Nodes and Tracks

Fixed UnsupportedOperationException when applying templates that clear existing nodes and tracks. Template application now uses proper mutable collection methods instead of operating on immutable list views.

SSP Owner Assignment Race Condition

Added synchronization guard to prevent duplicate owner group assignments when multiple players connect simultaneously during first server start.


Chore

  • Bumped version to 2.9.1
  • Updated CHANGELOG.md

Full Commit Log

TypeScopeDescription
featmigrationAdd PermissionsPlus data models
featmigrationAdd PermissionsPlus migrator with JSON reading and transformation
featmigrationRegister PermissionsPlus migrator in /hp migrate command
testmigrationAdd PermissionsPlus data model tests
testmigrationAdd PermissionsPlus permission cleaning and validation tests
refactormigrationApply code review fixes to PermissionsPlus migrator
fixresolverChange to most-specific-first permission resolution order
fixtemplateGracefully handle existing groups during template application
featsspAuto-assign owner group to first player
fixsspPrevent race condition in first-player owner assignment
fixtemplateUse proper mutable methods for clearing nodes and tracks
choreBump version to 2.9.1 and update changelog

v2.9.0-rc1: Permission Resolution, Template & SSP Fixes

Choose a tag to compare

@nmang004nmang004 released this 08 Mar 15:40

Fixes

  • Permission Resolution: Specific grants (e.g. + simpleclaims.edit-party) now correctly override global denies (- *). Resolution order changed to most-specific-first.
  • Template Application: Fixed "Failed to apply template: null" error when applying templates to servers with existing groups. Template applier now uses proper mutable methods for updating groups and tracks.
  • SSP Auto-Owner: First player on an empty server is automatically assigned the configured owner group.

Testing

Download HyperPerms-2.9.0.jar and replace your existing plugin JAR. Please report any issues.

HyperPerms v2.9.0

Choose a tag to compare

@derrickmehaffyderrickmehaffy released this 05 Mar 23:10

Hotfix: Web Editor Session Create

Fixed

  • Web editor returning 500 on /hp editor — The gzip compression introduced in 2.8.9 was applied to all session create requests, but the Cloudflare Worker API does not support Content-Encoding: gzip on incoming request bodies. This caused every /hp editor command to fail with "Server returned status 500". Compression is now only applied to payloads exceeding 500KB, keeping normal requests uncompressed while still protecting very large servers from HTTP 413 errors.

If you are on 2.8.9, update immediately.

HyperPerms v2.8.9

Choose a tag to compare

@derrickmehaffyderrickmehaffy released this 05 Mar 23:10

Architecture Rehaul & MMOSkillTree Integration

First-Class MMOSkillTree Support

HyperPerms now has full, first-class integration with MMOSkillTree — one of the biggest plugins on Hytale.

  • 200+ permission nodes registered across admin, command, skill, boost, and alternate prefix categories
  • All 23 skill nodesmmoskilltree.skill.mining, .woodcutting, .excavation, .harvesting, .fishing, .swords, .daggers, .polearms, .staves, .axes, .blunt, .archery, .unarmed, .defense, .taming, .acrobatics, .crafting, .repair, .alchemy, .enchanting, .cooking, .smithing, .building
  • All 140 XP boost permission nodes covering personal and global boosts for all skills, skill categories, and all-skills targets with varying multipliers, durations, and cooldowns
  • ziggfreed.* alternate prefix support — MMOSkillTree checks permissions through both mmoskilltree.* and ziggfreed.mmoskilltree.* prefixes. HyperPerms now correctly resolves both via bidirectional aliases
  • Hytale command path aliasescom.ziggfreed.mmoskilltree.command.* paths resolve to their mmoskilltree.command.* equivalents
  • Wildcard expansion for all MMST permission categories
  • Tab completion & web editor now show all MMST permission nodes
  • Updated RPG & Survival templates with appropriate MMST permissions at each rank tier (XP boosts scale with rank progression)

Staged Plugin Lifecycle

The plugin initialization system has been completely rewritten with a clean, modular architecture:

  • 11 ordered stages: Config → Storage → CoreManager → Resolver → Registry → Chat → Integration → Web → Scheduler → Analytics → DefaultGroups
  • PluginLifecycle orchestrator initializes stages in order and shuts them down in reverse — if any stage fails, previously initialized stages are safely torn down
  • ServiceContainer provides typed dependency injection across all stages
  • HyperPerms.java reduced from ~400 lines of monolithic init to ~25 lines — all setup logic now lives in dedicated Stage implementations

Annotation-Based Command Framework

The entire command system has been rebuilt using a declarative annotation-driven approach:

  • New annotations: @CommandGroup, @Command, @Arg, @OptionalArg, @Permission, @Confirm
  • CommandScanner automatically discovers and registers annotated command methods at startup
  • CommandDispatcher handles argument parsing, permission checks, and confirmation flows
  • 5 annotated command groups replace 42 individual command classes: GroupCommands, UserCommands, DebugCommands, RootCommands, PermsCommands, BackupCommands
  • Net reduction of ~1,500 lines with significantly better maintainability

Web Editor Improvements

  • Gzip compressed session requests — Session create payloads are now gzip compressed before sending to the API, preventing HTTP 413 errors on servers with many groups and permissions

Bug Fixes

  • Fixed config being null during early stage initialization
  • Fixed default groups being created before storage was fully ready
  • Integrated 2.8.8's centralized sync and diff-based permission logic into the new lifecycle system

HyperPerms v2.8.8

Choose a tag to compare

@derrickmehaffyderrickmehaffy released this 05 Mar 23:10

[2.8.8] - 2026-02-23

Server Version:2026.02.19-1a311a592

Fixed

  • Permission pollution in Hytale's permissions.json - syncPermissionsToHytale() previously pushed all resolved permissions on every change, causing hundreds of permissions to accumulate. Now uses diff-based sync that computes the delta between Hytale's current state and HyperPerms' resolved set, only adding missing and removing stale permissions
  • Race condition in concurrent permission syncs - Multiple threads (command thread, scheduler, CF pool, web editor) could call syncPermissionsToHytale() simultaneously for the same user, racing on Hytale's non-thread-safe HashSet view from getUserPermissions(). Added per-UUID synchronization locks and defensive copying of the live view
  • Scattered manual sync calls - Six user commands and HyperPermsPermissionProvider each had their own inline syncPermissionsToHytale() call via bootstrap reflection. Centralized all sync logic into a CacheInvalidator.setSyncListener() hook — every cache invalidation now automatically triggers Hytale sync for affected online users
  • Group commands invalidated entire cache - Group permission/property changes (setperm, unsetperm, setprefix, setsuffix, setweight, setexpiry, parent add/remove) called invalidateAll() instead of targeted invalidateGroup(), causing unnecessary cache churn for unrelated users
  • Expired permissions not synced to Hytale - ExpiryCleanupTask removed expired nodes but didn't invalidate the cache or trigger Hytale sync, so expired permissions remained active until the player reconnected
  • Inconsistent cache invalidation API - Some commands used getCache().invalidate() (bypassing sync) while others used getCacheInvalidator().invalidate() (with sync). Unified all commands to use getCacheInvalidator()
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Releases: HyperSystems-Development/HyperPerms

2.10.0 — Command tab-completion, QoL fixes & QuestLines Claims compatibility

Choose a tag to compare

@nmang004nmang004 released this 24 Jun 00:52

Server Version:0.5.6 (release) · 0.6.0-pre.4 (pre-release)

Quality-of-life release: tab-completion for /hp, instant command-tree refresh, and fixes for several silently-broken integration paths — including a QuestLines Claims compatibility fix that was handing out double (or triple) the claims a permission allowed. The same codebase now runs on both the Hytale release (0.5.x) and pre-release (0.6.0-pre.x) channels.

Added

  • Tab-completion for /hp commands. Group, track, permission-node and online-player arguments now suggest as you type (case-insensitive prefix match). Previously every argument was a plain string with no completion.
  • Instant command-tree refresh. When a player's groups or permissions change, the affected online player gets a fresh command tree immediately — newly-granted commands appear without a relog.
  • Clickable download link in the "update available" notification (alongside /hp update).
  • Startup self-check that verifies the Hytale-core reflection targets used by optional integrations resolve on the running build, logging a clear warning if any are missing.

Fixed

  • QuestLines Claims granted double (or triple) the claims/rent a permission allowed. QuestLines computes claim/rent limits by summing the numeric suffix of questlinesclaims.claim.chunks.<n> / questlinesclaims.rent.limit.<n> nodes across every provider, and across both a user's permissions and each of their groups' permissions. HyperPerms exposed the same fully-resolved set through several of those surfaces (getUserPermissions, the virtual user:<uuid> group, and the native-provider sync), so each node was counted 2–3×. When QuestLines is detected, HyperPerms now collapses those to a single summable source — boolean checks are unaffected, and servers without QuestLines see no change. (LuckPerms was already special-cased by QuestLines, which is why it behaved correctly.)
  • PlaceholderAPI offline-player fallback never worked — it referenced a non-existent class (…server.HytaleServer, missing .core) and a dead getPlayerManager() chain, silently returning null. Now uses Universe.get().getPlayer(uuid).
  • MysticNameTags nameplate refresh never worked — the World class literal omitted its .world sub-package.
  • Event listener leaks across /reload — chat, tab-list and update-notification listeners stored their registration handles but never called unregister() (a stale comment claimed no such API existed). They now unregister properly instead of leaving duplicate handlers.
  • Stale "ghost" entries in the player/tab list — HyperPerms only ever added player-list entries; quitting players are now removed via RemoveFromServerPlayerList instead of lingering.

Changed

  • Centralized the Hytale-core reflection string literals (Universe, PlayerRef, World) into ReflectionUtil so a future Hytale package move is a one-line fix and the optional integrations can't drift independently.

Upgrade

Drop-in replacement for 2.9.x — no config changes. Replace the jar in mods/ and restart, using the build that matches your server channel:

  • HyperPerms-2.10.0.jar — Hytale release servers (0.5.x, manifest ^0.5.6)
  • HyperPerms-2.10.0-prerelease.jar — Hytale pre-release servers (0.6.0-pre.x, manifest ^0.6.0-pre.4)

If you run QuestLines Claims, HyperPerms prunes any duplicate questlinesclaims.* entries a previous version wrote into the native provider the first time each player connects after updating.


Requirements: Hytale 0.5.6+ (release) or 0.6.0-pre.x (pre-release), Java 25
Full Changelog:2.9.6...2.10.0
Discord:https://discord.gg/SNPjyfkYPc

2.9.6 — Hytale 0.5.2 OP recognition hotfix

Choose a tag to compare

@nmang004nmang004 released this 29 May 13:36

Server Version:0.5.2

Hotfix for operator (OP) recognition on Hytale 0.5.2. If you're on 2.9.5 and your HyperPerms admins are showing as "not OP" in-game, update to 2.9.6.

Fixed

  • HyperPerms admins were not recognized as OP on 0.5.2. Hytale 0.5.2 determines operator status by group membership — it checks whether a player is in the hytale:Admin group (getGroupsForUser(uuid).contains("hytale:Admin")), and FlyCameraModule/WorldMapTracker key off group names too. HyperPerms funnels all resolution through a single user:<uuid> virtual group, so admins were never seen in hytale:Admin and showed as "not OP" even though their permission checks passed.
  • getGroupsForUser now also advertises hytale:Admin for any user who effectively resolves the * permission (superuser). Granting a HyperPerms group the * node makes its members OP, recognized by Hytale and OP-gated features. Permission resolution itself is unchanged (still funneled through user:<uuid>).

Changed

  • Reverted the authoritative-provider mode added in 2.9.5. HyperPerms no longer removes Hytale's built-in provider; it registers itself first and keeps the built-in provider registered (its removal aggravated the OP break, because Hytale's getGroupsForUser aggregates across all providers).

Upgrade

Drop-in replacement for 2.9.5/2.9.4. No config changes. Replace the jar in mods/ and restart.


Requirements: Hytale 0.5.2+, Java 25
Full Changelog:2.9.5...2.9.6
Discord:https://discord.gg/SNPjyfkYPc

2.9.5 — Hytale 0.5.2 Support

Choose a tag to compare

@nmang004nmang004 released this 29 May 12:34

Server Version:0.5.2 ("Update 5", rev 8b2f3de, Java 25)

Compatibility release for Hytale 0.5.2. Verified by booting the local 0.5.2 server: HyperPerms loads, enables, and registers as the authoritative permission provider with no errors.

Fixed

  • Plugin failed to load on 0.5.2 (manifest). 0.5.2 added a strict SemverRange codec that rejected the manifest's bare ServerVersion (0.5.2) and the spaced >= 1.0.2 optional-dependency range. Now uses ^0.5.2 and >=1.0.2. Without this the plugin did not load at all.
  • PermissionProvider interface conformance. 0.5.2 expanded the interface from 10 to 14 methods. Implemented the four new ones (setUserGroup, getGroupParent, getAllRegisteredGroups, getEffectiveGroupPermissions).
  • Deny-by-default permission model. A group using -* (deny-all) plus specific grants previously had every granted permission silently denied on native command checks. HyperPerms now resolves these correctly — standard "deny-all, then grant" setups work, and native checks agree with /hp check.

Changed

  • Authoritative permission provider. HyperPerms now removes Hytale's built-in provider while enabled (and restores it on disable), so it is the single source of permission decisions. Manage everything via /hp — vanilla /perm, /setgroup and /op operate on data HyperPerms no longer consults, and /op self is advisory-disabled while HyperPerms is active (grant admin via a group with the * node).
  • Default build channel is now release (targets 0.5.2). Use -Phytale_channel=pre-release for pre-release builds.

Added

  • Registered the 0.5.2 built-in nodes so they surface in the web editor and wildcard expansion: hytale.world_map.teleport.coordinate, hytale.world_map.teleport.marker, hytale.system.update.notify (+ matching wildcards).

Removed

  • Obsolete warnAboutVanillaGroupOverwrite startup check (tested the legacy OP/Default group keys that no longer exist in 0.5.2).

Requirements: Hytale 0.5.2+, Java 25
Full Changelog:2.9.4...2.9.5
Discord:https://discord.gg/SNPjyfkYPc

HyperPerms v2.9.4

Choose a tag to compare

@derrickmehaffyderrickmehaffy released this 02 Apr 08:39

Fixed

  • TabListListener runtime crashUniverse.getPlayers() return type differs between Maven artifact (Collection) and runtime server (List), causing NoSuchMethodError. Fixed by copying into new ArrayList<>() to decouple from the return type descriptor

Server Version:2026.03.26-89796e57b

Full Changelog:https://github.com/HyperSystems-Development/HyperPerms/blob/main/CHANGELOG.md

HyperPerms v2.9.3

Choose a tag to compare

@nmang004nmang004 released this 28 Mar 12:37

v2.9.3 — March 26 Server Support

Server Version:2026.03.26 (release & pre-release)

What's New (since 2.9.1)

Added

  • Per-world permissionssetperm and unsetperm commands (group and user) now accept an optional world argument to restrict permissions to a specific world
  • Context display in info commands — Group and user info now shows context restrictions (e.g. [world=Survival]) on permission nodes

Fixed

  • API compatibility — Updated TabListListener to handle Universe.get().getPlayers() returning Collection<PlayerRef> instead of List<PlayerRef>, fixing compilation against the March 26 server update
  • Group inheritance priority — Child group permissions now always take precedence over inherited parent group permissions, regardless of weight values
  • LuckPerms H2 migration version mismatch — Use isolated classloader when loading H2 driver from LuckPerms libs
  • H2 driver selection — Prefer modern H2 driver over legacy to match current LuckPerms database format
  • H2 migration column access — Use unquoted column name for ResultSet access
  • Analytics flush data loss — Prevent race condition where permission check counters could be lost during flush
  • ImportCommand silent failures — Await all group save futures before reporting success
  • Non-atomic node mutations — Synchronize compound removeIf+add operations in setNode and addGroup
  • SQL serialization — Use Gson instead of hand-rolled JSON parser for correct escaping of special characters
  • Cycle detection case sensitivity — Normalize group names to lowercase in inheritance cycle detection
  • Template loader race condition — Prevent concurrent template loading from clearing the map mid-load
  • Confirmation memory leak — Clean up expired pending confirmations to prevent unbounded map growth
  • Migration thread starvation — Use dedicated executor instead of common ForkJoinPool for LuckPerms migration
  • SQLite nested ResultSet — Collect all rows before loading nodes to avoid driver conflicts on single connection
  • SQLite backup consistency — Checkpoint WAL before copying database file to capture all committed writes
  • SQLite restore PRAGMAs — Re-enable WAL and foreign_keys after restoring a backup
  • Clone command data loss — Await save future in clone command before reporting success
  • Group rename atomicity — Create new group before deleting old to prevent data loss on crash; await all save futures
  • JSON storage path traversal — Validate names on load/delete paths to prevent directory traversal
  • WildcardMatcher trace inconsistency — Add stripped-prefix matching to checkWithTrace() to match check() behavior

Full Changelog: v2.9.1...v2.9.3

HyperPerms v2.9.1

Choose a tag to compare

@nmang004nmang004 released this 09 Mar 00:31

v2.9.1 — Permission Resolution, Templates & PermissionsPlus Migration

Added

PermissionsPlus Migration Tool

Full migration support for servers transitioning from PermissionsPlus to HyperPerms.

  • /hp migrate permissionsplus — Preview migration (dry-run)
  • /hp migrate permissionsplus --confirm — Execute migration
  • Reads PermissionsPlus JSON data files and transforms groups, users, and permissions into HyperPerms format
  • Automatic permission cleaning and validation for PermissionsPlus-specific formats
  • Comprehensive test coverage for data models, permission cleaning, and validation

SSP Auto-Owner Assignment

First player to join a single-player (SSP) world is automatically assigned the owner group, removing the need for manual /hp user addgroup setup on fresh worlds.


Fixed

Permission Resolution Order

The resolver now evaluates permissions in most-specific-first order:

a.b.c → a.b.* → a.* → *

Previously, a broad wildcard like a.* could override a more specific grant or denial on a.b.c. This is now resolved — specific permissions always take priority.

Template Application with Existing Groups

/hp template apply no longer fails when groups from the template already exist on the server. Existing groups are gracefully skipped or merged instead of throwing an error.

Template Clearing Nodes and Tracks

Fixed UnsupportedOperationException when applying templates that clear existing nodes and tracks. Template application now uses proper mutable collection methods instead of operating on immutable list views.

SSP Owner Assignment Race Condition

Added synchronization guard to prevent duplicate owner group assignments when multiple players connect simultaneously during first server start.


Chore

  • Bumped version to 2.9.1
  • Updated CHANGELOG.md

Full Commit Log

TypeScopeDescription
featmigrationAdd PermissionsPlus data models
featmigrationAdd PermissionsPlus migrator with JSON reading and transformation
featmigrationRegister PermissionsPlus migrator in /hp migrate command
testmigrationAdd PermissionsPlus data model tests
testmigrationAdd PermissionsPlus permission cleaning and validation tests
refactormigrationApply code review fixes to PermissionsPlus migrator
fixresolverChange to most-specific-first permission resolution order
fixtemplateGracefully handle existing groups during template application
featsspAuto-assign owner group to first player
fixsspPrevent race condition in first-player owner assignment
fixtemplateUse proper mutable methods for clearing nodes and tracks
choreBump version to 2.9.1 and update changelog

v2.9.0-rc1: Permission Resolution, Template & SSP Fixes

Choose a tag to compare

@nmang004nmang004 released this 08 Mar 15:40

Fixes

  • Permission Resolution: Specific grants (e.g. + simpleclaims.edit-party) now correctly override global denies (- *). Resolution order changed to most-specific-first.
  • Template Application: Fixed "Failed to apply template: null" error when applying templates to servers with existing groups. Template applier now uses proper mutable methods for updating groups and tracks.
  • SSP Auto-Owner: First player on an empty server is automatically assigned the configured owner group.

Testing

Download HyperPerms-2.9.0.jar and replace your existing plugin JAR. Please report any issues.

HyperPerms v2.9.0

Choose a tag to compare

@derrickmehaffyderrickmehaffy released this 05 Mar 23:10

Hotfix: Web Editor Session Create

Fixed

  • Web editor returning 500 on /hp editor — The gzip compression introduced in 2.8.9 was applied to all session create requests, but the Cloudflare Worker API does not support Content-Encoding: gzip on incoming request bodies. This caused every /hp editor command to fail with "Server returned status 500". Compression is now only applied to payloads exceeding 500KB, keeping normal requests uncompressed while still protecting very large servers from HTTP 413 errors.

If you are on 2.8.9, update immediately.

HyperPerms v2.8.9

Choose a tag to compare

@derrickmehaffyderrickmehaffy released this 05 Mar 23:10

Architecture Rehaul & MMOSkillTree Integration

First-Class MMOSkillTree Support

HyperPerms now has full, first-class integration with MMOSkillTree — one of the biggest plugins on Hytale.

  • 200+ permission nodes registered across admin, command, skill, boost, and alternate prefix categories
  • All 23 skill nodesmmoskilltree.skill.mining, .woodcutting, .excavation, .harvesting, .fishing, .swords, .daggers, .polearms, .staves, .axes, .blunt, .archery, .unarmed, .defense, .taming, .acrobatics, .crafting, .repair, .alchemy, .enchanting, .cooking, .smithing, .building
  • All 140 XP boost permission nodes covering personal and global boosts for all skills, skill categories, and all-skills targets with varying multipliers, durations, and cooldowns
  • ziggfreed.* alternate prefix support — MMOSkillTree checks permissions through both mmoskilltree.* and ziggfreed.mmoskilltree.* prefixes. HyperPerms now correctly resolves both via bidirectional aliases
  • Hytale command path aliasescom.ziggfreed.mmoskilltree.command.* paths resolve to their mmoskilltree.command.* equivalents
  • Wildcard expansion for all MMST permission categories
  • Tab completion & web editor now show all MMST permission nodes
  • Updated RPG & Survival templates with appropriate MMST permissions at each rank tier (XP boosts scale with rank progression)

Staged Plugin Lifecycle

The plugin initialization system has been completely rewritten with a clean, modular architecture:

  • 11 ordered stages: Config → Storage → CoreManager → Resolver → Registry → Chat → Integration → Web → Scheduler → Analytics → DefaultGroups
  • PluginLifecycle orchestrator initializes stages in order and shuts them down in reverse — if any stage fails, previously initialized stages are safely torn down
  • ServiceContainer provides typed dependency injection across all stages
  • HyperPerms.java reduced from ~400 lines of monolithic init to ~25 lines — all setup logic now lives in dedicated Stage implementations

Annotation-Based Command Framework

The entire command system has been rebuilt using a declarative annotation-driven approach:

  • New annotations: @CommandGroup, @Command, @Arg, @OptionalArg, @Permission, @Confirm
  • CommandScanner automatically discovers and registers annotated command methods at startup
  • CommandDispatcher handles argument parsing, permission checks, and confirmation flows
  • 5 annotated command groups replace 42 individual command classes: GroupCommands, UserCommands, DebugCommands, RootCommands, PermsCommands, BackupCommands
  • Net reduction of ~1,500 lines with significantly better maintainability

Web Editor Improvements

  • Gzip compressed session requests — Session create payloads are now gzip compressed before sending to the API, preventing HTTP 413 errors on servers with many groups and permissions

Bug Fixes

  • Fixed config being null during early stage initialization
  • Fixed default groups being created before storage was fully ready
  • Integrated 2.8.8's centralized sync and diff-based permission logic into the new lifecycle system

HyperPerms v2.8.8

Choose a tag to compare

@derrickmehaffyderrickmehaffy released this 05 Mar 23:10

[2.8.8] - 2026-02-23

Server Version:2026.02.19-1a311a592

Fixed

  • Permission pollution in Hytale's permissions.json - syncPermissionsToHytale() previously pushed all resolved permissions on every change, causing hundreds of permissions to accumulate. Now uses diff-based sync that computes the delta between Hytale's current state and HyperPerms' resolved set, only adding missing and removing stale permissions
  • Race condition in concurrent permission syncs - Multiple threads (command thread, scheduler, CF pool, web editor) could call syncPermissionsToHytale() simultaneously for the same user, racing on Hytale's non-thread-safe HashSet view from getUserPermissions(). Added per-UUID synchronization locks and defensive copying of the live view
  • Scattered manual sync calls - Six user commands and HyperPermsPermissionProvider each had their own inline syncPermissionsToHytale() call via bootstrap reflection. Centralized all sync logic into a CacheInvalidator.setSyncListener() hook — every cache invalidation now automatically triggers Hytale sync for affected online users
  • Group commands invalidated entire cache - Group permission/property changes (setperm, unsetperm, setprefix, setsuffix, setweight, setexpiry, parent add/remove) called invalidateAll() instead of targeted invalidateGroup(), causing unnecessary cache churn for unrelated users
  • Expired permissions not synced to Hytale - ExpiryCleanupTask removed expired nodes but didn't invalidate the cache or trigger Hytale sync, so expired permissions remained active until the player reconnected
  • Inconsistent cache invalidation API - Some commands used getCache().invalidate() (bypassing sync) while others used getCacheInvalidator().invalidate() (with sync). Unified all commands to use getCacheInvalidator()