Implement Fabric meta/options API

This commit is contained in:
Luck 2022-07-17 11:54:14 +01:00
parent bf93077474
commit fbc0787a1e
No known key found for this signature in database
GPG Key ID: EFA9B3EC5FD90F8B
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'))
}
include(modImplementation('me.lucko:fabric-permissions-api:0.1-SNAPSHOT'))
include(modImplementation('me.lucko:fabric-permissions-api:0.2-SNAPSHOT'))
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.FabricConnectionListener;
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 net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents;
@ -88,7 +88,7 @@ public class LPFabricPlugin extends AbstractLuckPermsPlugin {
this.connectionListener = new FabricConnectionListener(this);
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.
this.commandManager = new FabricCommandExecutor(this);

View File

@ -25,7 +25,9 @@
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.luckperms.common.cacheddata.result.StringResult;
import me.lucko.luckperms.common.cacheddata.result.TristateResult;
import me.lucko.luckperms.common.query.QueryOptionsImpl;
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 java.util.Optional;
/**
* Listener to route permission checks made via fabric-permissions-api to LuckPerms.
*/
public class PermissionCheckListener {
public class FabricPermissionsApiListener {
private final LPFabricPlugin plugin;
public PermissionCheckListener(LPFabricPlugin plugin) {
public FabricPermissionsApiListener(LPFabricPlugin plugin) {
this.plugin = plugin;
}
public void registerListeners() {
PermissionCheckEvent.EVENT.register(this::onPermissionCheck);
OptionRequestEvent.EVENT.register(this::onOptionRequest);
}
private @NonNull TriState onPermissionCheck(CommandSource source, String permission) {
if (source instanceof ServerCommandSource) {
Entity entity = ((ServerCommandSource) source).getEntity();
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)) {
case 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) {
String name = ((ServerCommandSource) source).getName();
VerboseCheckTarget target = VerboseCheckTarget.internal(name);
@ -90,4 +105,19 @@ public class PermissionCheckListener {
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;
import me.lucko.luckperms.common.cacheddata.type.MetaCache;
import me.lucko.luckperms.common.cacheddata.type.PermissionCache;
import me.lucko.luckperms.common.context.manager.QueryOptionsCache;
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();
}
@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")
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);
String getOption(String key);
String getOption(String key, QueryOptions queryOptions);
}