Skip to content

Commit c59717d

Browse files
committed
Full permission system rewrite, you can now control boolean permissions with Bukkit
1 parent 9fb9cd6 commit c59717d

File tree

9 files changed

+114
-36
lines changed

9 files changed

+114
-36
lines changed

patches/minecraft/net/minecraft/commands/CommandSourceStack.java.patch

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,8 @@
2424
public boolean hasPermission(int p_81370_) {
2525
+ // CraftBukkit start
2626
+ com.mojang.brigadier.tree.CommandNode currentCommand = this.currentCommand;
27-
+ if (currentCommand != null && !org.kettingpowered.ketting.command.ForgeCommand.checkIfForgeCommand(currentCommand)) { //Ketting - skip if forge command
28-
+ return hasPermission(p_81370_, org.bukkit.craftbukkit.v1_20_R1.command.VanillaCommandWrapper.getPermission(currentCommand));
27+
+ if (currentCommand != null) {
28+
+ return org.kettingpowered.ketting.utils.PermissionHelper.handleSourceStackPermission(this, currentCommand, p_81370_);
2929
+ }
3030
+ // CraftBukkit end
3131
+

src/main/java/org/bukkit/craftbukkit/v1_20_R1/entity/CraftHumanEntity.java

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -234,12 +234,6 @@ public void setOp(boolean value) {
234234
perm.recalculatePermissions();
235235
}
236236

237-
//Ketting start
238-
public boolean isPermissibleInjected() {
239-
return !perm.getClass().getSimpleName().equals(PermissibleBase.class.getSimpleName());
240-
}
241-
//Ketting end
242-
243237
@Override
244238
public Set<PermissionAttachmentInfo> getEffectivePermissions() {
245239
return perm.getEffectivePermissions();

src/main/java/org/bukkit/craftbukkit/v1_20_R1/entity/CraftPlayer.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,13 +134,15 @@
134134
import org.bukkit.map.MapCursor;
135135
import org.bukkit.map.MapView;
136136
import org.bukkit.metadata.MetadataValue;
137+
import org.bukkit.permissions.Permission;
137138
import org.bukkit.plugin.Plugin;
138139
import org.bukkit.plugin.messaging.StandardMessenger;
139140
import org.bukkit.profile.PlayerProfile;
140141
import org.bukkit.scoreboard.Scoreboard;
141142
import org.jetbrains.annotations.NotNull;
142143

143144
import net.md_5.bungee.api.chat.BaseComponent; // Spigot
145+
import org.kettingpowered.ketting.utils.PermissionHelper;
144146

145147
@DelegateDeserialization(CraftOfflinePlayer.class)
146148
public class CraftPlayer extends CraftHumanEntity implements Player {
@@ -2202,4 +2204,16 @@ public Player.Spigot spigot()
22022204
return spigot;
22032205
}
22042206
// Spigot end
2207+
2208+
//Ketting start - permission handler
2209+
@Override
2210+
public boolean hasPermission(@NotNull String name) {
2211+
return PermissionHelper.handlePermission(this, name, () -> super.hasPermission(name));
2212+
}
2213+
2214+
@Override
2215+
public boolean hasPermission(@NotNull Permission perm) {
2216+
return PermissionHelper.handlePermission(this, perm, () -> super.hasPermission(perm));
2217+
}
2218+
//Ketting end
22052219
}

src/main/java/org/bukkit/permissions/PermissionDefault.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@ public enum PermissionDefault {
1212
TRUE("true"),
1313
FALSE("false"),
1414
OP("op", "isop", "operator", "isoperator", "admin", "isadmin"),
15-
NOT_OP("!op", "notop", "!operator", "notoperator", "!admin", "notadmin");
15+
NOT_OP("!op", "notop", "!operator", "notoperator", "!admin", "notadmin"),
16+
MODDED("ketting-modded"); //Ketting - permission handler
1617

1718
private final String[] names;
1819
private static final Map<String, PermissionDefault> lookup = new HashMap<String, PermissionDefault>();
@@ -61,6 +62,7 @@ public String toString() {
6162

6263
static {
6364
for (PermissionDefault value : values()) {
65+
if (value == MODDED) continue; //Ketting
6466
for (String name : value.names) {
6567
lookup.put(name, value);
6668
}

src/main/java/org/kettingpowered/ketting/command/ForgeCommandWrapper.java

Lines changed: 1 addition & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -28,22 +28,7 @@ public ForgeCommandWrapper(Commands dispatcher, CommandNode<CommandSourceStack>
2828

2929
public boolean execute(@NotNull CommandSender sender, @NotNull String commandLabel, @NotNull String[] args) {
3030
final CommandSourceStack listener = getListener(sender);
31-
if (KettingConfig.getInstance().OVERWRITE_FORGE_PERMISSIONS.getValue()) {
32-
//If we detect that the CraftPlayer permissible was injected into (ex. LuckPerms), we will use their permissions
33-
//instead of the Forge permissions defined in 'Commands.literal(...).requires(s -> s.hasPermission(..))'.
34-
//This will cause a problem though, as the Forge permissions will not be checked.
35-
//So you will have to manually set the Forge permissions by allowing ex. "forge.command.coolmodcommand" in LuckPerms.
36-
boolean permissibleInjected = false;
37-
if (sender instanceof CraftPlayer player)
38-
permissibleInjected = player.isPermissibleInjected();
39-
40-
if ((permissibleInjected && !testPermission(sender)) ||
41-
(!permissibleInjected && !forgeCommand.getRequirement().test(listener)))
42-
return true;
43-
} else {
44-
if (!forgeCommand.getRequirement().test(listener)) return true;
45-
}
46-
31+
if (!forgeCommand.getRequirement().test(listener)) return true;
4732
dispatcher.setForgeCommand(true);
4833
dispatcher.performPrefixedCommand(listener, "/"+toDispatcher(args, getName()), "/"+toDispatcher(args, commandLabel));
4934
dispatcher.setForgeCommand(false);

src/main/java/org/kettingpowered/ketting/command/KettingForwardingHandler.java

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import net.minecraftforge.server.permission.nodes.PermissionTypes;
99
import org.bukkit.Bukkit;
1010
import org.kettingpowered.ketting.internal.KettingConstants;
11+
import org.kettingpowered.ketting.utils.PermissionHelper;
1112

1213
import java.util.Set;
1314
import java.util.UUID;
@@ -18,6 +19,7 @@ public class KettingForwardingHandler implements IPermissionHandler {
1819

1920
public KettingForwardingHandler(IPermissionHandler delegate) {
2021
this.delegate = delegate;
22+
PermissionHelper.injectPermissions(getRegisteredNodes());
2123
}
2224

2325
public ResourceLocation getIdentifier() {
@@ -29,19 +31,29 @@ public Set<PermissionNode<?>> getRegisteredNodes() {
2931
}
3032

3133
public <T> T getPermission(ServerPlayer player, PermissionNode<T> node, PermissionDynamicContext<?>... context) {
32-
if (node.getType() == PermissionTypes.BOOLEAN) {
33-
return (T) (Object) player.getBukkitEntity().hasPermission(node.getNodeName());
34-
} else {
35-
return delegate.getPermission(player, node, context);
34+
try {
35+
if (node.getType() == PermissionTypes.BOOLEAN) {
36+
PermissionHelper.MODDED_CONTEXT = context;
37+
return (T) (Object) player.getBukkitEntity().hasPermission(node.getNodeName());
38+
} else {
39+
return delegate.getPermission(player, node, context);
40+
}
41+
} finally {
42+
PermissionHelper.MODDED_CONTEXT = PermissionHelper.MODDED_CONTEXT_EMPTY;
3643
}
3744
}
3845

3946
public <T> T getOfflinePermission(UUID uuid, PermissionNode<T> node, PermissionDynamicContext<?>... context) {
40-
var player = Bukkit.getPlayer(uuid);
41-
if (player != null && node.getType() == PermissionTypes.BOOLEAN) {
42-
return (T) (Object) player.hasPermission(node.getNodeName());
43-
} else {
44-
return delegate.getOfflinePermission(uuid, node, context);
47+
try {
48+
var player = Bukkit.getPlayer(uuid);
49+
if (player != null && node.getType() == PermissionTypes.BOOLEAN) {
50+
PermissionHelper.MODDED_CONTEXT = context;
51+
return (T) (Object) player.hasPermission(node.getNodeName());
52+
} else {
53+
return delegate.getOfflinePermission(uuid, node, context);
54+
}
55+
} finally {
56+
PermissionHelper.MODDED_CONTEXT = PermissionHelper.MODDED_CONTEXT_EMPTY;
4557
}
4658
}
4759
}

src/main/java/org/kettingpowered/ketting/config/KettingConfig.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ public KettingConfig(@NotNull String fileName) {
2323
"Github: https://github.com/kettingpowered/",
2424
"Discord: https://discord.kettingpowered.org/",
2525
""
26-
}, fileName, 3);
26+
}, fileName, 4);
2727
load();
2828
}
2929

@@ -33,7 +33,7 @@ public KettingConfig(@NotNull String fileName) {
3333
public final BooleanValue WARN_ON_NULL_NBT = new BooleanValue("debug.warn_on_null_nbt", true, "Print a warning to the console when something tries to set a null NBT tag.");
3434
public final BooleanValue WARN_ON_UNKNOWN_STRUCTURE_TYPE = new BooleanValue("debug.warn_on_unknown_structure_type", true, "Print a warning to the console when a structure type is unknown to Bukkit.");
3535

36-
public final BooleanValue OVERWRITE_FORGE_PERMISSIONS = new BooleanValue("forge.overwrite_forge_permissions", false, "--- WARNING - THIS WILL COMPLETELY DISABLE FORGE PERMISSION CHECKS --- Overwrite Forge permissions with Bukkit permissions, makes it possible to use a permission manager plugin for modded commands. If true, Forge permissions will be set to 'forge.command.MODDEDCOMMAND' where MODDEDCOMMAND is the name of the modded command.");
36+
public final BooleanValue REROUTE_FORGE_COMMAND_PERMISSIONS = new BooleanValue("ketting.reroute_forge_command_permissions", false, "If true, Ketting will reroute Forge command permissions to Bukkit permissions. This is useful if you want to use a permission plugin like LuckPerms with Forge commands.");
3737
public final BooleanValue SILENCE_PARSING_ERRORS = new BooleanValue("forge.silence_parsing_errors", true, "If true, this will minimize some general parsing errors from appearing in the console");
3838

3939
public final BooleanValue MERGE_WORLD_SYSTEMS = new BooleanValue("ketting.merge_world_systems", false, "If true, this will attempt to merge both the Forge and Bukkit world system into one, making dimensions exist in the world folder, and Bukkit worlds in their own folder.");
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
package org.kettingpowered.ketting.utils;
2+
3+
import com.mojang.brigadier.tree.CommandNode;
4+
import net.minecraft.commands.CommandSourceStack;
5+
import net.minecraft.server.level.ServerPlayer;
6+
import net.minecraftforge.server.permission.nodes.PermissionDynamicContext;
7+
import net.minecraftforge.server.permission.nodes.PermissionNode;
8+
import net.minecraftforge.server.permission.nodes.PermissionTypes;
9+
import org.bukkit.Bukkit;
10+
import org.bukkit.craftbukkit.v1_20_R1.command.VanillaCommandWrapper;
11+
import org.bukkit.craftbukkit.v1_20_R1.entity.CraftPlayer;
12+
import org.bukkit.permissions.Permission;
13+
import org.bukkit.permissions.PermissionDefault;
14+
import org.kettingpowered.ketting.command.ForgeCommand;
15+
import org.kettingpowered.ketting.command.ForgeCommandWrapper;
16+
import org.kettingpowered.ketting.config.KettingConfig;
17+
import org.kettingpowered.ketting.inject.ForgeInject;
18+
19+
import java.util.HashMap;
20+
import java.util.Map;
21+
import java.util.Set;
22+
import java.util.function.Supplier;
23+
24+
public final class PermissionHelper {
25+
26+
public static final Map<String, PermissionNode.PermissionResolver<Boolean>> MODDED_RESOLVERS = new HashMap<>();
27+
28+
public static final PermissionDynamicContext<?>[] MODDED_CONTEXT_EMPTY = new PermissionDynamicContext[0];
29+
public static PermissionDynamicContext<?>[] MODDED_CONTEXT = MODDED_CONTEXT_EMPTY;
30+
31+
public static boolean getModdedValue(String name, ServerPlayer player) {
32+
if (player == null)
33+
throw new IllegalArgumentException("Player cannot be null");
34+
35+
PermissionNode.PermissionResolver<Boolean> resolver = MODDED_RESOLVERS.get(name);
36+
return resolver != null && resolver.resolve(player, player.getUUID(), MODDED_CONTEXT);
37+
}
38+
39+
public static void injectPermissions(Set<PermissionNode<?>> nodes) {
40+
nodes.forEach(node -> {
41+
if (node.getType() != PermissionTypes.BOOLEAN) return;
42+
43+
String name = node.getNodeName();
44+
String description = node.getDescription() == null ? "" : node.getDescription().getString();
45+
Bukkit.getServer().getPluginManager().addPermission(new Permission(name, description, PermissionDefault.MODDED));
46+
ForgeInject.debug("Registering boolean permission {} to Bukkit", name);
47+
MODDED_RESOLVERS.put(name, (PermissionNode.PermissionResolver<Boolean>) node.getDefaultResolver());
48+
});
49+
}
50+
51+
public static boolean handlePermission(CraftPlayer player, String permission, Supplier<Boolean> delegate) {
52+
Permission perm = Bukkit.getServer().getPluginManager().getPermission(permission);
53+
return perm == null ? delegate.get() : handlePermission(player, perm, delegate);
54+
}
55+
56+
public static boolean handlePermission(CraftPlayer player, Permission permission, Supplier<Boolean> delegate) {
57+
if (!player.isPermissionSet(permission) && permission.getDefault() == PermissionDefault.MODDED)
58+
return getModdedValue(permission.getName(), player.getHandle());
59+
return delegate.get();
60+
}
61+
62+
public static boolean handleSourceStackPermission(CommandSourceStack stack, CommandNode node, int permissionLevel) {
63+
if (ForgeCommand.checkIfForgeCommand(node))
64+
return KettingConfig.getInstance().REROUTE_FORGE_COMMAND_PERMISSIONS.getValue()
65+
? ((stack.getLevel() == null) && stack.permissionLevel >= permissionLevel) || stack.getBukkitSender().hasPermission(ForgeCommandWrapper.getPermission(node))
66+
: stack.permissionLevel >= permissionLevel;
67+
return stack.hasPermission(permissionLevel, VanillaCommandWrapper.getPermission(node));
68+
}
69+
}

src/main/resources/META-INF/accesstransformer.cfg

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -469,6 +469,8 @@ private-f net.minecraft.world.level.storage.loot.LootPool f_79028_ # rolls
469469
private-f net.minecraft.world.level.storage.loot.LootPool f_79029_ # bonusRolls
470470

471471
#group KETTING
472+
public net.minecraft.commands.CommandSourceStack f_81291_ # permissionLevel
473+
472474
public net.minecraft.world.entity.projectile.ThrownTrident f_37555_ # tridentItem
473475
public net.minecraft.world.level.block.entity.SkullBlockEntity m_292605_(Lcom/mojang/authlib/GameProfile;)Ljava/util/concurrent/CompletableFuture; # fillProfileTextures
474476
public net.minecraft.world.level.Level m_142646_()Lnet/minecraft/world/level/entity/LevelEntityGetter; # getEntities

0 commit comments

Comments
 (0)