1
0
mirror of https://github.com/lucko/LuckPerms.git synced 2025-08-31 10:01:45 +02:00

Implement Fabric meta/options API

This commit is contained in:
Luck
2022-07-17 11:54:14 +01:00
parent bf93077474
commit fbc0787a1e
5 changed files with 74 additions and 9 deletions

View File

@@ -29,7 +29,7 @@ dependencies {
modImplementation(fabricApi.module(it, '0.55.2+1.19')) modImplementation(fabricApi.module(it, '0.55.2+1.19'))
} }
include(modImplementation('me.lucko:fabric-permissions-api:0.1-SNAPSHOT')) include(modImplementation('me.lucko:fabric-permissions-api:0.2-SNAPSHOT'))
implementation project(':common') implementation project(':common')
} }

View File

@@ -46,7 +46,7 @@ import me.lucko.luckperms.fabric.listeners.FabricAutoOpListener;
import me.lucko.luckperms.fabric.listeners.FabricCommandListUpdater; import me.lucko.luckperms.fabric.listeners.FabricCommandListUpdater;
import me.lucko.luckperms.fabric.listeners.FabricConnectionListener; import me.lucko.luckperms.fabric.listeners.FabricConnectionListener;
import me.lucko.luckperms.fabric.listeners.FabricOtherListeners; import me.lucko.luckperms.fabric.listeners.FabricOtherListeners;
import me.lucko.luckperms.fabric.listeners.PermissionCheckListener; import me.lucko.luckperms.fabric.listeners.FabricPermissionsApiListener;
import me.lucko.luckperms.fabric.messaging.FabricMessagingFactory; import me.lucko.luckperms.fabric.messaging.FabricMessagingFactory;
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents; import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents;
@@ -88,7 +88,7 @@ public class LPFabricPlugin extends AbstractLuckPermsPlugin {
this.connectionListener = new FabricConnectionListener(this); this.connectionListener = new FabricConnectionListener(this);
this.connectionListener.registerListeners(); this.connectionListener.registerListeners();
new PermissionCheckListener(this).registerListeners(); new FabricPermissionsApiListener(this).registerListeners();
// Command registration also need to occur early, and will persist across game states as well. // Command registration also need to occur early, and will persist across game states as well.
this.commandManager = new FabricCommandExecutor(this); this.commandManager = new FabricCommandExecutor(this);

View File

@@ -25,7 +25,9 @@
package me.lucko.luckperms.fabric.listeners; package me.lucko.luckperms.fabric.listeners;
import me.lucko.fabric.api.permissions.v0.OptionRequestEvent;
import me.lucko.fabric.api.permissions.v0.PermissionCheckEvent; import me.lucko.fabric.api.permissions.v0.PermissionCheckEvent;
import me.lucko.luckperms.common.cacheddata.result.StringResult;
import me.lucko.luckperms.common.cacheddata.result.TristateResult; import me.lucko.luckperms.common.cacheddata.result.TristateResult;
import me.lucko.luckperms.common.query.QueryOptionsImpl; import me.lucko.luckperms.common.query.QueryOptionsImpl;
import me.lucko.luckperms.common.verbose.VerboseCheckTarget; import me.lucko.luckperms.common.verbose.VerboseCheckTarget;
@@ -41,31 +43,44 @@ import net.minecraft.server.network.ServerPlayerEntity;
import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.NonNull;
import java.util.Optional;
/** /**
* Listener to route permission checks made via fabric-permissions-api to LuckPerms. * Listener to route permission checks made via fabric-permissions-api to LuckPerms.
*/ */
public class PermissionCheckListener { public class FabricPermissionsApiListener {
private final LPFabricPlugin plugin; private final LPFabricPlugin plugin;
public PermissionCheckListener(LPFabricPlugin plugin) { public FabricPermissionsApiListener(LPFabricPlugin plugin) {
this.plugin = plugin; this.plugin = plugin;
} }
public void registerListeners() { public void registerListeners() {
PermissionCheckEvent.EVENT.register(this::onPermissionCheck); PermissionCheckEvent.EVENT.register(this::onPermissionCheck);
OptionRequestEvent.EVENT.register(this::onOptionRequest);
} }
private @NonNull TriState onPermissionCheck(CommandSource source, String permission) { private @NonNull TriState onPermissionCheck(CommandSource source, String permission) {
if (source instanceof ServerCommandSource) { if (source instanceof ServerCommandSource) {
Entity entity = ((ServerCommandSource) source).getEntity(); Entity entity = ((ServerCommandSource) source).getEntity();
if (entity instanceof ServerPlayerEntity) { if (entity instanceof ServerPlayerEntity) {
return onPlayerPermissionCheck((ServerPlayerEntity) entity, permission); return playerPermissionCheck((ServerPlayerEntity) entity, permission);
} }
} }
return onOtherPermissionCheck(source, permission); return otherPermissionCheck(source, permission);
} }
private TriState onPlayerPermissionCheck(ServerPlayerEntity player, String permission) { private @NonNull Optional<String> onOptionRequest(CommandSource source, String key) {
if (source instanceof ServerCommandSource) {
Entity entity = ((ServerCommandSource) source).getEntity();
if (entity instanceof ServerPlayerEntity) {
return playerGetOption((ServerPlayerEntity) entity, key);
}
}
return otherGetOption(source, key);
}
private TriState playerPermissionCheck(ServerPlayerEntity player, String permission) {
switch (((MixinUser) player).hasPermission(permission)) { switch (((MixinUser) player).hasPermission(permission)) {
case TRUE: case TRUE:
return TriState.TRUE; return TriState.TRUE;
@@ -78,7 +93,7 @@ public class PermissionCheckListener {
} }
} }
private TriState onOtherPermissionCheck(CommandSource source, String permission) { private TriState otherPermissionCheck(CommandSource source, String permission) {
if (source instanceof ServerCommandSource) { if (source instanceof ServerCommandSource) {
String name = ((ServerCommandSource) source).getName(); String name = ((ServerCommandSource) source).getName();
VerboseCheckTarget target = VerboseCheckTarget.internal(name); VerboseCheckTarget target = VerboseCheckTarget.internal(name);
@@ -90,4 +105,19 @@ public class PermissionCheckListener {
return TriState.DEFAULT; return TriState.DEFAULT;
} }
private Optional<String> playerGetOption(ServerPlayerEntity player, String key) {
return Optional.ofNullable(((MixinUser) player).getOption(key));
}
private Optional<String> otherGetOption(CommandSource source, String key) {
if (source instanceof ServerCommandSource) {
String name = ((ServerCommandSource) source).getName();
VerboseCheckTarget target = VerboseCheckTarget.internal(name);
this.plugin.getVerboseHandler().offerMetaCheckEvent(CheckOrigin.PLATFORM_API, target, QueryOptionsImpl.DEFAULT_CONTEXTUAL, key, StringResult.nullResult());
}
return Optional.empty();
}
} }

View File

@@ -25,6 +25,7 @@
package me.lucko.luckperms.fabric.mixin; package me.lucko.luckperms.fabric.mixin;
import me.lucko.luckperms.common.cacheddata.type.MetaCache;
import me.lucko.luckperms.common.cacheddata.type.PermissionCache; import me.lucko.luckperms.common.cacheddata.type.PermissionCache;
import me.lucko.luckperms.common.context.manager.QueryOptionsCache; import me.lucko.luckperms.common.context.manager.QueryOptionsCache;
import me.lucko.luckperms.common.locale.TranslationManager; import me.lucko.luckperms.common.locale.TranslationManager;
@@ -136,6 +137,36 @@ public abstract class ServerPlayerEntityMixin implements MixinUser {
return data.checkPermission(permission, CheckOrigin.PLATFORM_API_HAS_PERMISSION).result(); return data.checkPermission(permission, CheckOrigin.PLATFORM_API_HAS_PERMISSION).result();
} }
@Override
public String getOption(String key) {
if (key == null) {
throw new NullPointerException("key");
}
if (this.luckperms$user == null || this.luckperms$queryOptions == null) {
// "fake" players will have our mixin, but won't have been initialised.
return null;
}
return getOption(key, this.luckperms$queryOptions.getQueryOptions());
}
@Override
public String getOption(String key, QueryOptions queryOptions) {
if (key == null) {
throw new NullPointerException("key");
}
if (queryOptions == null) {
throw new NullPointerException("queryOptions");
}
final User user = this.luckperms$user;
if (user == null || this.luckperms$queryOptions == null) {
// "fake" players will have our mixin, but won't have been initialised.
return null;
}
MetaCache cache = user.getCachedData().getMetaData(queryOptions);
return cache.getMetaOrChatMetaValue(key, CheckOrigin.PLATFORM_API);
}
@Inject(at = @At("TAIL"), method = "copyFrom") @Inject(at = @At("TAIL"), method = "copyFrom")
private void luckperms_copyFrom(ServerPlayerEntity oldPlayer, boolean alive, CallbackInfo ci) { private void luckperms_copyFrom(ServerPlayerEntity oldPlayer, boolean alive, CallbackInfo ci) {

View File

@@ -68,4 +68,8 @@ public interface MixinUser {
Tristate hasPermission(String permission, QueryOptions queryOptions); Tristate hasPermission(String permission, QueryOptions queryOptions);
String getOption(String key);
String getOption(String key, QueryOptions queryOptions);
} }