--- title: Permissions System type: docs weight: 12 --- The Permissions system provides fine-grained access control for commands, editor features, and custom plugin functionality. **Package:** `com.hypixel.hytale.server.core.permissions` ## Overview Hytale uses a permission system with: - **User permissions** - Directly assigned to individual players - **Group permissions** - Inherited by all members of a group - **Permission providers** - Custom logic for dynamic permissions ## Accessing the Permissions Module ```java import com.hypixel.hytale.server.core.permissions.PermissionsModule; // Use static get() method - NOT HytaleServer.get().getPermissionsModule() PermissionsModule permissions = PermissionsModule.get(); ``` ## Checking Permissions ```java UUID playerUuid = player.getPlayerRef().getUuid(); // Check if player has permission boolean canEdit = permissions.hasPermission(playerUuid, "hytale.editor.asset"); // Check in command context if (permissions.hasPermission(ctx.sender().getUuid(), "myplugin.admin")) { // Admin-only logic } ``` ## User Permissions Manage permissions for individual players: ```java UUID playerUuid = player.getPlayerRef().getUuid(); // Add permissions permissions.addUserPermission(playerUuid, Set.of( "myplugin.feature.create", "myplugin.feature.delete" )); // Remove permissions permissions.removeUserPermission(playerUuid, Set.of( "myplugin.feature.delete" )); ``` ## Group Permissions Groups allow shared permissions across multiple players: ### Managing Groups ```java // Add player to a group permissions.addUserToGroup(playerUuid, "moderators"); // Remove player from a group permissions.removeUserFromGroup(playerUuid, "moderators"); // Get all groups for a player Set groups = permissions.getGroupsForUser(playerUuid); ``` ### Group Permission Events Listen for group changes using specific event subclasses: ```java import com.hypixel.hytale.server.core.event.events.permissions.*; // Player ADDED to group getEventRegistry().register(PlayerGroupEvent.Added.class, event -> { UUID playerUuid = event.getPlayerUuid(); String group = event.getGroupName(); // Note: getGroupName(), NOT getGroup() log("Player joined group: " + group); }); // Player REMOVED from group getEventRegistry().register(PlayerGroupEvent.Removed.class, event -> { UUID playerUuid = event.getPlayerUuid(); String group = event.getGroupName(); log("Player left group: " + group); }); // Group permissions ADDED getEventRegistry().register(GroupPermissionChangeEvent.Added.class, event -> { String group = event.getGroupName(); Set added = event.getAddedPermissions(); log("Group " + group + " got permissions: " + added); }); // Group permissions REMOVED getEventRegistry().register(GroupPermissionChangeEvent.Removed.class, event -> { String group = event.getGroupName(); Set removed = event.getRemovedPermissions(); log("Group " + group + " lost permissions: " + removed); }); // Player permissions ADDED getEventRegistry().register(PlayerPermissionChangeEvent.PermissionsAdded.class, event -> { UUID playerUuid = event.getPlayerUuid(); Set added = event.getAddedPermissions(); }); // Player permissions REMOVED getEventRegistry().register(PlayerPermissionChangeEvent.PermissionsRemoved.class, event -> { UUID playerUuid = event.getPlayerUuid(); Set removed = event.getRemovedPermissions(); }); ``` ## Built-in Permissions Hytale includes many built-in permissions: ### Command Permissions | Permission | Description | |------------|-------------| | `hytale.command.*` | All command access | | `hytale.command.gamemode` | Change game mode | | `hytale.command.tp` | Teleportation | | `hytale.command.give` | Give items | | `hytale.command.time` | Time control | ### Editor Permissions | Permission | Description | |------------|-------------| | `hytale.editor.asset` | Asset editing | | `hytale.editor.packs.*` | Pack management | | `hytale.editor.builderTools` | Builder tools access | | `hytale.editor.brush.*` | Brush tools | | `hytale.editor.prefab.*` | Prefab editing | | `hytale.editor.selection.*` | Selection tools | | `hytale.editor.history` | Undo/redo history | ### Camera Permissions | Permission | Description | |------------|-------------| | `hytale.camera.flycam` | Free camera mode | ## Custom Permission Provider Implement `PermissionProvider` for dynamic permission logic: {{< callout type="info" >}} **Note:** `PermissionProvider` is an interface that provides sets of permissions, not a simple hasPermission check. The `PermissionsModule` checks these sets. {{< /callout >}} ```java import com.hypixel.hytale.server.core.permissions.provider.PermissionProvider; public class VIPPermissionProvider implements PermissionProvider { private final Map> vipPermissions = new ConcurrentHashMap<>(); private final Map> vipGroups = new ConcurrentHashMap<>(); @Override @Nonnull public String getName() { return "VIPPermissionProvider"; } @Override public Set getUserPermissions(@Nonnull UUID uuid) { // Return the permissions for this user // VIP users get extra permissions automatically if (isVIP(uuid)) { Set perms = new HashSet<>(vipPermissions.getOrDefault(uuid, Collections.emptySet())); perms.add("vip.lounge"); perms.add("vip.cosmetics"); return perms; } return vipPermissions.getOrDefault(uuid, Collections.emptySet()); } @Override public void addUserPermissions(@Nonnull UUID uuid, @Nonnull Set permissions) { vipPermissions.computeIfAbsent(uuid, k -> new HashSet<>()).addAll(permissions); } @Override public void removeUserPermissions(@Nonnull UUID uuid, @Nonnull Set permissions) { Set userPerms = vipPermissions.get(uuid); if (userPerms != null) { userPerms.removeAll(permissions); } } @Override public Set getGroupPermissions(@Nonnull String group) { return Collections.emptySet(); } @Override public void addGroupPermissions(@Nonnull String group, @Nonnull Set permissions) {} @Override public void removeGroupPermissions(@Nonnull String group, @Nonnull Set permissions) {} @Override public Set getGroupsForUser(@Nonnull UUID uuid) { return vipGroups.getOrDefault(uuid, Collections.emptySet()); } @Override public void addUserToGroup(@Nonnull UUID uuid, @Nonnull String group) { vipGroups.computeIfAbsent(uuid, k -> new HashSet<>()).add(group); } @Override public void removeUserFromGroup(@Nonnull UUID uuid, @Nonnull String group) { Set groups = vipGroups.get(uuid); if (groups != null) { groups.remove(group); } } private boolean isVIP(UUID uuid) { // Your VIP checking logic return vipDatabase.contains(uuid); } } ``` ### Registering Custom Providers ```java @Override public void start() { PermissionsModule permissions = PermissionsModule.get(); permissions.addProvider(new VIPPermissionProvider()); } ``` ## Permission Wildcards Permissions support wildcard matching: ```java // Grant all permissions under a namespace permissions.addUserPermission(playerUuid, Set.of("myplugin.*")); // This now passes: permissions.hasPermission(playerUuid, "myplugin.anything"); permissions.hasPermission(playerUuid, "myplugin.feature.nested"); ``` ## Command Permission Integration Commands automatically check permissions based on their ID: ```java public class AdminCommand extends AbstractCommand { public AdminCommand() { super("admin", "myplugin.commands.admin.description"); // Permission check is automatic based on command registration } @Override protected CompletableFuture execute(CommandContext ctx) { // Only players with appropriate permission reach here return null; } } ``` ## Practical Examples ### Role-Based Access ```java public class RoleManager { private final PermissionsModule permissions; public RoleManager() { this.permissions = PermissionsModule.get(); } public void promoteToModerator(UUID playerUuid) { permissions.addUserToGroup(playerUuid, "moderators"); permissions.addUserPermission(playerUuid, Set.of( "server.kick", "server.mute", "server.warn" )); } public void demoteFromModerator(UUID playerUuid) { permissions.removeUserFromGroup(playerUuid, "moderators"); permissions.removeUserPermission(playerUuid, Set.of( "server.kick", "server.mute", "server.warn" )); } public boolean canModerate(UUID playerUuid) { return permissions.getGroupsForUser(playerUuid).contains("moderators"); } } ``` ### Feature Gating ```java public void useFeature(Player player, String featureName) { UUID uuid = player.getPlayerRef().getUuid(); PermissionsModule perms = PermissionsModule.get(); String permission = "myplugin.feature." + featureName; if (!perms.hasPermission(uuid, permission)) { player.sendMessage(Message.translation("error.no_permission")); return; } // Execute feature executeFeature(player, featureName); } ``` ## Best Practices {{< callout type="info" >}} **Permission Guidelines:** - Use namespaced permissions (e.g., `myplugin.feature.name`) - Prefer groups for role-based access over individual permissions - Check permissions at entry points, not deep in logic - Use wildcards sparingly and intentionally {{< /callout >}} {{< callout type="warning" >}} **Security Note:** Always validate permissions server-side. Never trust client-reported permission states. {{< /callout >}}