init
This commit is contained in:
@@ -0,0 +1,95 @@
|
||||
# Provider Integration
|
||||
|
||||
How we plug into Hytale's permission system without Hytale knowing we're there.
|
||||
|
||||
## The SPI
|
||||
|
||||
```java
|
||||
package com.hypixel.hytale.server.core.permissions.provider;
|
||||
|
||||
public interface PermissionProvider {
|
||||
String getName();
|
||||
void addUserPermissions(UUID, Set<String>);
|
||||
void removeUserPermissions(UUID, Set<String>);
|
||||
Set<String> getUserPermissions(UUID);
|
||||
void addGroupPermissions(String, Set<String>);
|
||||
void removeGroupPermissions(String, Set<String>);
|
||||
Set<String> getGroupPermissions(String);
|
||||
void addUserToGroup(UUID, String);
|
||||
void removeUserFromGroup(UUID, String);
|
||||
Set<String> getGroupsForUser(UUID);
|
||||
void setUserGroup(UUID, String);
|
||||
String getGroupParent(String);
|
||||
Set<String> getAllRegisteredGroups();
|
||||
Set<String> getEffectiveGroupPermissions(String);
|
||||
}
|
||||
```
|
||||
|
||||
That's the contract. Our [RanksPermissionProvider](../src/main/java/net/kewwbec/ranks/provider/RanksPermissionProvider.java) implements every method.
|
||||
|
||||
## The module's API
|
||||
|
||||
`PermissionsModule.get()` exposes:
|
||||
|
||||
```java
|
||||
void addProvider(PermissionProvider);
|
||||
void removeProvider(PermissionProvider);
|
||||
List<PermissionProvider> getProviders();
|
||||
PermissionProvider getFirstPermissionProvider();
|
||||
boolean areProvidersTampered();
|
||||
```
|
||||
|
||||
When a `hasPermission(uuid, node)` call comes in, the module consults the providers in order. If you've replaced the default with ours, only ours answers. If you've left ours alongside the default, the module's logic combines them (typically OR for "has the permission").
|
||||
|
||||
## How we register
|
||||
|
||||
`RanksPlugin.start()`:
|
||||
|
||||
```java
|
||||
PermissionsModule perms = PermissionsModule.get();
|
||||
|
||||
if (config.provider.replace_default) {
|
||||
for (PermissionProvider existing : new ArrayList<>(perms.getProviders())) {
|
||||
if (!RanksPermissionProvider.NAME.equals(existing.getName())) {
|
||||
perms.removeProvider(existing);
|
||||
removedProviders.add(existing); // remember to restore on shutdown
|
||||
}
|
||||
}
|
||||
}
|
||||
perms.addProvider(provider);
|
||||
```
|
||||
|
||||
On `shutdown()` we reverse: remove ours, re-add anything we removed. This is so a clean reload of our plugin doesn't leave the server permission-less.
|
||||
|
||||
## What "replace" actually changes
|
||||
|
||||
When `replace_default = true`:
|
||||
|
||||
- Hytale's file-backed provider (which stores groups/users in JSON on disk) is removed.
|
||||
- Its data is **not** copied into MySQL automatically. If you had pre-existing OPs from the file, they're gone the moment we register (until you reassign them via `/op` or `/grant`, which now writes to MySQL).
|
||||
- If you ever uninstall this plugin, the file-backed provider is restored - but your MySQL data stays in MySQL, so it won't be visible to that provider.
|
||||
|
||||
If you have existing OPs you need to preserve:
|
||||
|
||||
1. Before installing Ranks, write down who's in which group from the Hytale file.
|
||||
2. Install Ranks, boot once - this creates the schema and seeds the built-in groups.
|
||||
3. Run `/op Bob`, `/op Alice` etc. once for each existing OP - this writes to our DB.
|
||||
|
||||
For larger migrations (lots of users, custom groups), a one-off SQL import is the right move; we don't ship one because every server's pre-existing state is different.
|
||||
|
||||
## Hytale's `/op`, `/perm` commands
|
||||
|
||||
Look at the `commands/` package under `com.hypixel.hytale.server.core.permissions` in the SDK. Each one calls into `PermissionsModule` which routes to providers. With our provider registered, those commands now read/write our MySQL.
|
||||
|
||||
This is the main reason "replace default" is the recommended mode: it means there's only one source of truth, and all the existing Hytale tooling keeps working.
|
||||
|
||||
## Conflicts to watch
|
||||
|
||||
- If you set `areProvidersTampered()` somehow gets flagged, Hytale might warn about non-default providers. We are intentionally replacing; the warning is expected.
|
||||
- If another plugin also registers a `PermissionProvider`, the load order matters. We register in `start()`. If a later-loading plugin also calls `addProvider`, we coexist as providers 1 and 2. The module decides who answers first.
|
||||
|
||||
## Caching considerations
|
||||
|
||||
Every `hasPermission` call goes through our provider. We aggressively cache (see [06_Cross_Server_Caching.md](06_Cross_Server_Caching.md)). The first call after a cache miss hits MySQL; subsequent calls are in-memory.
|
||||
|
||||
If the cache gets stale (e.g. the bus drops an invalidation message), permissions can drift for up to whatever interval the player stays connected. To force-refresh: revoke and re-grant their rank (which invalidates), or restart the server.
|
||||
Reference in New Issue
Block a user