Forward Bukkit permissions to Forge

This commit is contained in:
IzzelAliz 2022-06-06 14:31:57 +08:00
parent 23e365fc14
commit aad0b1cab3
No known key found for this signature in database
GPG Key ID: EE50E123A11D8338
5 changed files with 109 additions and 2 deletions

View File

@ -1,5 +1,7 @@
package io.izzel.arclight.common.mixin.bukkit;
import io.izzel.arclight.common.mod.server.ArclightForgePermissible;
import io.izzel.arclight.i18n.ArclightConfig;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.player.Player;
import org.bukkit.craftbukkit.v.CraftServer;
@ -7,10 +9,14 @@ import org.bukkit.craftbukkit.v.entity.CraftEntity;
import org.bukkit.craftbukkit.v.entity.CraftHumanEntity;
import org.bukkit.craftbukkit.v.inventory.CraftInventory;
import org.bukkit.craftbukkit.v.inventory.CraftInventoryPlayer;
import org.bukkit.permissions.PermissibleBase;
import org.bukkit.permissions.ServerOperator;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Mutable;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;
@Mixin(value = CraftHumanEntity.class, remap = false)
public abstract class CraftHumanEntityMixin extends CraftEntity {
@ -24,6 +30,15 @@ public abstract class CraftHumanEntityMixin extends CraftEntity {
super(server, entity);
}
@Redirect(method = "<init>", at = @At(value = "NEW", target = "org/bukkit/permissions/PermissibleBase"))
private PermissibleBase arclight$forwardPerm(ServerOperator opable) {
if (ArclightConfig.spec().getCompat().isForwardPermissionReverse()) {
return new ArclightForgePermissible(opable);
} else {
return new PermissibleBase(opable);
}
}
@Override
public void setHandle(Entity entity) {
super.setHandle(entity);

View File

@ -0,0 +1,77 @@
package io.izzel.arclight.common.mod.server;
import io.izzel.arclight.api.Unsafe;
import net.minecraft.server.level.ServerPlayer;
import net.minecraftforge.server.permission.PermissionAPI;
import net.minecraftforge.server.permission.handler.IPermissionHandler;
import net.minecraftforge.server.permission.nodes.PermissionDynamicContextKey;
import net.minecraftforge.server.permission.nodes.PermissionNode;
import net.minecraftforge.server.permission.nodes.PermissionType;
import net.minecraftforge.server.permission.nodes.PermissionTypes;
import org.bukkit.craftbukkit.v.entity.CraftHumanEntity;
import org.bukkit.permissions.PermissibleBase;
import org.bukkit.permissions.Permission;
import org.bukkit.permissions.ServerOperator;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodType;
public class ArclightForgePermissible extends PermissibleBase {
private final CraftHumanEntity player;
public ArclightForgePermissible(@Nullable ServerOperator opable) {
super(opable);
this.player = (CraftHumanEntity) opable;
}
@Override
public boolean hasPermission(@NotNull String inName) {
var node = newNode(inName, (player, playerUUID, context) -> super.hasPermission(inName));
if (player.getHandle() instanceof ServerPlayer player) {
return getHandler().getPermission(player, node);
} else {
return getHandler().getOfflinePermission(player.getUniqueId(), node);
}
}
@Override
public boolean hasPermission(@NotNull Permission perm) {
var node = newNode(perm.getName(), (player, playerUUID, context) -> super.hasPermission(perm));
if (player.getHandle() instanceof ServerPlayer player) {
return getHandler().getPermission(player, node);
} else {
return getHandler().getOfflinePermission(player.getUniqueId(), node);
}
}
private static final MethodHandle H_handler, H_newNode;
private static IPermissionHandler getHandler() {
try {
return (IPermissionHandler) H_handler.invokeExact();
} catch (Throwable e) {
throw new RuntimeException(e);
}
}
@SuppressWarnings("unchecked")
private static <T> PermissionNode<T> newNode(String nodeName, PermissionNode.PermissionResolver<T> defaultResolver, PermissionDynamicContextKey... dynamics) {
try {
return (PermissionNode<T>) H_newNode.invokeExact(nodeName, PermissionTypes.BOOLEAN, defaultResolver, dynamics);
} catch (Throwable e) {
throw new RuntimeException(e);
}
}
static {
try {
H_handler = Unsafe.lookup().findStaticGetter(PermissionAPI.class, "activeHandler", IPermissionHandler.class);
H_newNode = Unsafe.lookup().findConstructor(PermissionNode.class, MethodType.methodType(void.class, String.class, PermissionType.class, PermissionNode.PermissionResolver.class, PermissionDynamicContextKey[].class));
} catch (Throwable t) {
throw new RuntimeException(t);
}
}
}

View File

@ -5,6 +5,7 @@ import ninja.leaping.configurate.objectmapping.serialize.ConfigSerializable;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
@ConfigSerializable
@ -23,7 +24,7 @@ public class CompatSpec {
private List<String> extraLogicWorlds;
@Setting("forward-permission")
private boolean forwardPermission;
private String forwardPermission;
public Map<String, MaterialPropertySpec> getMaterials() {
return materials;
@ -50,6 +51,10 @@ public class CompatSpec {
}
public boolean isForwardPermission() {
return forwardPermission;
return Objects.equals(forwardPermission, "true");
}
public boolean isForwardPermissionReverse() {
return Objects.equals(forwardPermission, "reverse");
}
}

View File

@ -115,5 +115,10 @@ comments {
"Extra worlds running logic"
"If any mods do not function well, try search class names in logs related to [EXT_LOGIC] and add them here"
]
forward-permission.comment = [
"true - Forward Forge permission query to Bukkit"
"false - Disable permission forward"
"reverse - Forward Bukkit player perimission query to Forge"
]
}
}

View File

@ -115,5 +115,10 @@ comments {
"额外运行逻辑的维度类名"
"如果有模组世界/功能运行不正常,尝试在日志中搜索和 [EXT_LOGIC] 有关的对应类名并添加"
]
forward-permission.comment = [
"true - 将 Forge 权限查询请求转发至 Bukkit"
"false - 不启用权限转发"
"reverse - 将 Bukkit 玩家权限查询请求转发至 Forge"
]
}
}