9.8 KiB
title, type, weight
| title | type | weight |
|---|---|---|
| Permissions System | docs | 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
import com.hypixel.hytale.server.core.permissions.PermissionsModule;
// Use static get() method - NOT HytaleServer.get().getPermissionsModule()
PermissionsModule permissions = PermissionsModule.get();
Checking Permissions
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:
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
// 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<String> groups = permissions.getGroupsForUser(playerUuid);
Group Permission Events
Listen for group changes using specific event subclasses:
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<String> added = event.getAddedPermissions();
log("Group " + group + " got permissions: " + added);
});
// Group permissions REMOVED
getEventRegistry().register(GroupPermissionChangeEvent.Removed.class, event -> {
String group = event.getGroupName();
Set<String> removed = event.getRemovedPermissions();
log("Group " + group + " lost permissions: " + removed);
});
// Player permissions ADDED
getEventRegistry().register(PlayerPermissionChangeEvent.PermissionsAdded.class, event -> {
UUID playerUuid = event.getPlayerUuid();
Set<String> added = event.getAddedPermissions();
});
// Player permissions REMOVED
getEventRegistry().register(PlayerPermissionChangeEvent.PermissionsRemoved.class, event -> {
UUID playerUuid = event.getPlayerUuid();
Set<String> 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 >}}
import com.hypixel.hytale.server.core.permissions.provider.PermissionProvider;
public class VIPPermissionProvider implements PermissionProvider {
private final Map<UUID, Set<String>> vipPermissions = new ConcurrentHashMap<>();
private final Map<UUID, Set<String>> vipGroups = new ConcurrentHashMap<>();
@Override
@Nonnull
public String getName() {
return "VIPPermissionProvider";
}
@Override
public Set<String> getUserPermissions(@Nonnull UUID uuid) {
// Return the permissions for this user
// VIP users get extra permissions automatically
if (isVIP(uuid)) {
Set<String> 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<String> permissions) {
vipPermissions.computeIfAbsent(uuid, k -> new HashSet<>()).addAll(permissions);
}
@Override
public void removeUserPermissions(@Nonnull UUID uuid, @Nonnull Set<String> permissions) {
Set<String> userPerms = vipPermissions.get(uuid);
if (userPerms != null) {
userPerms.removeAll(permissions);
}
}
@Override
public Set<String> getGroupPermissions(@Nonnull String group) {
return Collections.emptySet();
}
@Override
public void addGroupPermissions(@Nonnull String group, @Nonnull Set<String> permissions) {}
@Override
public void removeGroupPermissions(@Nonnull String group, @Nonnull Set<String> permissions) {}
@Override
public Set<String> 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<String> 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
@Override
public void start() {
PermissionsModule permissions = PermissionsModule.get();
permissions.addProvider(new VIPPermissionProvider());
}
Permission Wildcards
Permissions support wildcard matching:
// 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:
public class AdminCommand extends AbstractCommand {
public AdminCommand() {
super("admin", "myplugin.commands.admin.description");
// Permission check is automatic based on command registration
}
@Override
protected CompletableFuture<Void> execute(CommandContext ctx) {
// Only players with appropriate permission reach here
return null;
}
}
Practical Examples
Role-Based Access
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
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 >}}