PermissionsModule (JavaPlugin singleton)
├── List<PermissionProvider> providers (CopyOnWriteArrayList)
│ ├── HytalePermissionsProvider (default, index 0)
│ └── ... custom providers (e.g., HyperPermsPermissionProvider)
├── Map<String, Set<String>> virtualGroups (game-mode-based permissions)
└── Built-in commands: /op, /perm
Package: com.hypixel.hytale.server.core.permissions
Singleton access: PermissionsModule.get()
public void addProvider(@Nonnull PermissionProvider provider);
public void removeProvider(@Nonnull PermissionProvider provider);
@Nonnull public List<PermissionProvider> getProviders();
public PermissionProvider getFirstPermissionProvider(); // First in list handles mutations
public boolean areProvidersTampered(); // true if not just default providerpublic boolean hasPermission(@Nonnull UUID uuid, @Nonnull String id);
public boolean hasPermission(@Nonnull UUID uuid, @Nonnull String id, boolean def);Check order:
- Iterates providers in order
- For each provider: checks
getUserPermissions(uuid)for direct match - Then checks each group in
getGroupsForUser(uuid)→getGroupPermissions(group) - Then checks
virtualGroupsfor group matches - Returns
defif no match found
@Nullable
public static Boolean hasPermission(@Nullable Set<String> nodes, @Nonnull String id);Matching rules (in order):
*in nodes →TRUE(universal grant)-*in nodes →FALSE(universal deny)- Exact
idmatch →TRUE - Exact
-idmatch →FALSE - Wildcard hierarchy: splits
idby., checksprefix.*and-prefix.*at each level - No match →
null(continue to next provider/group)
public void addUserPermission(@Nonnull UUID uuid, @Nonnull Set<String> permissions);
public void removeUserPermission(@Nonnull UUID uuid, @Nonnull Set<String> permissions);
public void addGroupPermission(@Nonnull String group, @Nonnull Set<String> permissions);
public void removeGroupPermission(@Nonnull String group, @Nonnull Set<String> permissions);
public void addUserToGroup(@Nonnull UUID uuid, @Nonnull String group);
public void removeUserFromGroup(@Nonnull UUID uuid, @Nonnull String group);
@Nonnull public Set<String> getGroupsForUser(@Nonnull UUID uuid); // Aggregates all providersEach mutation dispatches corresponding events (see 02-event-system.md).
public void setVirtualGroups(@Nonnull Map<String, Set<String>> virtualGroups);Virtual groups are game-mode-based permission sets. By default:
Creativemode grantshytale.editor.builderTools- Command permissions are grouped by
GameModeviasetPermissionGroup()
Package: com.hypixel.hytale.server.core.permissions.provider
public interface PermissionProvider {
@Nonnull String getName();
// User permissions
void addUserPermissions(@Nonnull UUID uuid, @Nonnull Set<String> permissions);
void removeUserPermissions(@Nonnull UUID uuid, @Nonnull Set<String> permissions);
Set<String> getUserPermissions(@Nonnull UUID uuid);
// Group permissions
void addGroupPermissions(@Nonnull String groupName, @Nonnull Set<String> permissions);
void removeGroupPermissions(@Nonnull String groupName, @Nonnull Set<String> permissions);
Set<String> getGroupPermissions(@Nonnull String groupName);
// User-group membership
void addUserToGroup(@Nonnull UUID uuid, @Nonnull String groupName);
void removeUserFromGroup(@Nonnull UUID uuid, @Nonnull String groupName);
Set<String> getGroupsForUser(@Nonnull UUID uuid);
}public interface PermissionHolder {
boolean hasPermission(String permission);
}Used by CommandSender and other systems that need permission checks.
Package: com.hypixel.hytale.server.core.permissions
public class HytalePermissions {
public static final String NAMESPACE = "hytale";
public static final String COMMAND_BASE = "hytale.command";
// Editor permissions
public static final String ASSET_EDITOR = "hytale.editor.asset";
public static final String ASSET_EDITOR_PACKS_CREATE = "hytale.editor.packs.create";
public static final String ASSET_EDITOR_PACKS_EDIT = "hytale.editor.packs.edit";
public static final String ASSET_EDITOR_PACKS_DELETE = "hytale.editor.packs.delete";
public static final String BUILDER_TOOLS_EDITOR = "hytale.editor.builderTools";
public static final String EDITOR_BRUSH_USE = "hytale.editor.brush.use";
public static final String EDITOR_BRUSH_CONFIG = "hytale.editor.brush.config";
public static final String EDITOR_PREFAB_USE = "hytale.editor.prefab.use";
public static final String EDITOR_PREFAB_MANAGE = "hytale.editor.prefab.manage";
public static final String EDITOR_SELECTION_USE = "hytale.editor.selection.use";
public static final String EDITOR_SELECTION_CLIPBOARD = "hytale.editor.selection.clipboard";
public static final String EDITOR_SELECTION_MODIFY = "hytale.editor.selection.modify";
public static final String EDITOR_HISTORY = "hytale.editor.history";
public static final String FLY_CAM = "hytale.camera.flycam";
// Helper methods
@Nonnull public static String fromCommand(@Nonnull String name);
// Returns: "hytale.command.{name}"
@Nonnull public static String fromCommand(@Nonnull String name, @Nonnull String subCommand);
// Returns: "hytale.command.{name}.{subCommand}"
}public class HyperPermsPermissionProvider implements PermissionProvider {
@Override
public String getName() { return "HyperPerms"; }
@Override
public Set<String> getUserPermissions(UUID uuid) {
// Return resolved permissions including wildcards, contexts, inheritance
return new CaseInsensitiveSet(resolved.getExpandedPermissions(registry));
}
@Override
public Set<String> getGroupsForUser(UUID uuid) {
Set<String> allGroups = new HashSet<>();
collectInheritedGroups(user.getInheritedGroups(), allGroups);
// Add virtual user group for direct permissions
allGroups.add("user:" + uuid.toString());
return allGroups;
}
}
// Registration in plugin start():
PermissionsModule.get().addProvider(permissionProvider);
// Removal in plugin shutdown():
PermissionsModule.get().removeProvider(permissionProvider);- First provider handles mutations:
addUserPermission()etc. always delegate togetFirstPermissionProvider() - All providers checked for reads:
hasPermission()andgetGroupsForUser()iterate all providers - Case sensitivity: Hytale's built-in system is case-sensitive; HyperPerms wraps in
CaseInsensitiveSetfor compatibility - Wildcard support: Built-in supports
*,-*, andprefix.*/-prefix.*hierarchies - Negation: Prefix
-negates a permission node