Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions src/main/java/serverutils/ServerUtilitiesCommon.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,16 @@
import java.util.UUID;
import java.util.function.Function;

import javax.annotation.Nullable;

import net.minecraft.util.IChatComponent;
import net.minecraftforge.common.ForgeChunkManager;
import net.minecraftforge.common.MinecraftForge;

import com.gtnewhorizon.gtnhlib.brigadier.BrigadierApi;
import com.gtnewhorizon.gtnhlib.config.ConfigurationManager;
import com.mojang.brigadier.tree.CommandNode;
import com.mojang.brigadier.tree.LiteralCommandNode;

import cpw.mods.fml.common.FMLCommonHandler;
import cpw.mods.fml.common.Loader;
Expand All @@ -40,6 +45,8 @@
import serverutils.lib.util.ServerUtils;
import serverutils.lib.util.permission.PermissionAPI;
import serverutils.net.ServerUtilitiesNetHandler;
import serverutils.ranks.ICommandWithPermission;
import serverutils.ranks.Rank;
import serverutils.ranks.ServerUtilitiesPermissionHandler;
import serverutils.task.CleanupTask;
import serverutils.task.DecayTask;
Expand Down Expand Up @@ -123,6 +130,30 @@ public void onServerStarting(FMLServerStartingEvent event) {
public void onServerStarted(FMLServerStartedEvent event) {
Universe.onServerStarted(event);
registerTasks();

if (ranks.enabled && ranks.command_permissions) {
for (CommandNode<?> node : BrigadierApi.getCommandDispatcher().getRoot().getChildren()) {
if (node instanceof LiteralCommandNode<?>literalNode) {
registerBrigadierCommands(literalNode, (ICommandWithPermission) literalNode, null);
}
}
}
}

private static void registerBrigadierCommands(LiteralCommandNode<?> literalNode, ICommandWithPermission cmdPerm,
@Nullable String parentNode) {
String node = parentNode == null
? Rank.NODE_COMMAND + '.' + cmdPerm.serverutilities$getModId() + "." + literalNode.getLiteral()
: parentNode + "." + literalNode.getLiteral();

cmdPerm.serverutilities$setPermissionNode(node.toLowerCase());
cmdPerm.serverUtilities$registerPermissions();

for (CommandNode<?> child : literalNode.getChildren()) {
if (child instanceof LiteralCommandNode<?>childLiteral) {
registerBrigadierCommands(childLiteral, (ICommandWithPermission) childLiteral, node);
}
}
}

public void onServerStopping(FMLServerStoppingEvent event) {
Expand Down
17 changes: 13 additions & 4 deletions src/main/java/serverutils/core/ServerUtilitiesCore.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@
import java.util.Map;
import java.util.Set;

import com.gtnewhorizon.gtnhlib.config.ConfigException;
import net.minecraft.launchwrapper.Launch;
import net.minecraft.launchwrapper.LaunchClassLoader;

import com.gtnewhorizon.gtnhlib.config.ConfigurationManager;
import com.gtnewhorizon.gtnhmixins.IEarlyMixinLoader;
import com.gtnewhorizon.gtnhmixins.builders.IMixins;
Expand All @@ -19,11 +21,18 @@ public class ServerUtilitiesCore implements IFMLLoadingPlugin, IEarlyMixinLoader

static {
try {
ConfigurationManager.registerConfig(ServerUtilitiesConfig.class);
ConfigurationManager.registerConfig(AuroraConfig.class);
} catch (ConfigException e) {
var cleF = LaunchClassLoader.class.getDeclaredField("classLoaderExceptions");
cleF.setAccessible(true);
@SuppressWarnings("unchecked")
var cle = (Set<String>) cleF.get(Launch.classLoader);
// for Brigadier
cle.remove("com.mojang.");
} catch (NoSuchFieldException | IllegalAccessException e) {
throw new RuntimeException(e);
}

ConfigurationManager.registerConfig(ServerUtilitiesConfig.class);
ConfigurationManager.registerConfig(AuroraConfig.class);
}

@Override
Expand Down
33 changes: 27 additions & 6 deletions src/main/java/serverutils/lib/command/CommandUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@
import net.minecraft.util.IChatComponent;
import net.minecraftforge.common.DimensionManager;

import com.gtnewhorizon.gtnhlib.brigadier.BrigadierApi;
import com.mojang.brigadier.tree.CommandNode;

import serverutils.ServerUtilities;
import serverutils.ServerUtilitiesConfig;
import serverutils.lib.data.ForgePlayer;
Expand Down Expand Up @@ -180,14 +183,32 @@ public static List<ICommandWithPermission> getPermissionCommands() {
if (!Ranks.isActive() || !ServerUtilitiesConfig.ranks.command_permissions) return Collections.emptyList();
List<ICommandWithPermission> list = new ArrayList<>();
for (ICommand cmd : ServerUtils.getServer().getCommandManager().getCommands().values()) {
ICommandWithPermission command = (ICommandWithPermission) cmd;
if (command instanceof CommandTreeBase tree) {
for (ICommand child : tree.getSubCommands()) {
list.add((ICommandWithPermission) child);
addCommand(list, (ICommandWithPermission) cmd);
}

BrigadierApi.getCommandDispatcher().getRoot().getChildren().forEach((command) -> {
if (command instanceof ICommandWithPermission cmd) {
addCommand(list, cmd);
}
});
return list;
}

private static void addCommand(List<ICommandWithPermission> list, ICommandWithPermission command) {
list.add(command);

if (command instanceof CommandTreeBase tree) {
for (ICommand child : tree.getSubCommands()) {
list.add((ICommandWithPermission) child);
}
}

if (command instanceof CommandNode<?>node) {
for (CommandNode<?> child : node.getChildren()) {
if (child instanceof ICommandWithPermission cmdPerm) {
addCommand(list, cmdPerm);
}
}
list.add(command);
}
return list;
}
}
4 changes: 4 additions & 0 deletions src/main/java/serverutils/mixin/Mixins.java
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,10 @@ public enum Mixins implements IMixins {
.setPhase(Phase.EARLY)
.setApplyIf(() -> mixins.farmlandTramplingProtection)
.addCommonMixins("minecraft.MixinBlockFarmland")),
BRIGADIER_COMMAND_PERMISSIONS(new MixinBuilder("Make command permissions work with Brigadier commands")
.setPhase(Phase.LATE)
.setApplyIf(() -> ranks.enabled && ranks.command_permissions)
.addCommonMixins("brigadier.MixinCommandNode", "brigadier.MixinLiteralCommandNode")),
;
// spotless:on

Expand Down
16 changes: 12 additions & 4 deletions src/main/java/serverutils/net/MessageRanks.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
import net.minecraft.util.EnumChatFormatting;
import net.minecraft.util.IChatComponent;

import com.mojang.brigadier.tree.CommandNode;

import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import it.unimi.dsi.fastutil.ints.IntComparators;
Expand Down Expand Up @@ -138,12 +140,18 @@ public MessageRanks(Ranks r, ForgePlayer p) {
for (ICommandWithPermission command : CommandUtils.getPermissionCommands()) {
String node = command.serverutilities$getPermissionNode();
DefaultPermissionLevel level = DefaultPermissionHandler.INSTANCE.getDefaultPermissionLevel(node);
IChatComponent name = new ChatComponentText(
EnumChatFormatting.BLUE + "[" + command.serverutilities$getModName() + "]\n");
ConfigBoolean val = new ConfigBoolean(level == DefaultPermissionLevel.ALL);
IChatComponent desc = new ChatComponentText(
EnumChatFormatting.BLUE + "[" + command.serverutilities$getModName() + "]\n");

if (command instanceof ICommand cmd) {
desc = desc.appendSibling(CommandUtils.getTranslatedUsage(cmd, p.getPlayer()));
} else if (command instanceof CommandNode<?>cmdNode) {
desc = desc.appendSibling(new ChatComponentText(cmdNode.getUsageText()));
}

commandPermissions.add(node, val, val, StringUtils.FLAG_ID_PERIOD_DEFAULTS)
.setDisplayName(new ChatComponentTranslation(node)).setInfo(
name.appendSibling(CommandUtils.getTranslatedUsage((ICommand) command, p.getPlayer())));
.setDisplayName(new ChatComponentTranslation(node)).setInfo(desc);
}
}
}
Expand Down
54 changes: 50 additions & 4 deletions src/main/java/serverutils/ranks/ICommandWithPermission.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,17 @@
import java.util.HashMap;
import java.util.Map;

import net.minecraft.command.CommandBase;
import net.minecraft.command.ICommand;
import net.minecraft.entity.player.EntityPlayerMP;

import org.jetbrains.annotations.NotNull;
import cpw.mods.fml.common.Loader;
import cpw.mods.fml.common.LoaderState;
import serverutils.ServerUtilitiesPermissions;
import serverutils.data.NodeEntry;
import serverutils.lib.command.CommandTreeBase;
import serverutils.lib.util.permission.DefaultPermissionLevel;
import serverutils.lib.util.permission.PermissionAPI;

public interface ICommandWithPermission {

Expand All @@ -15,11 +23,49 @@ public interface ICommandWithPermission {

String serverutilities$getPermissionNode();

void serverutilities$setPermissionNode(@NotNull String node);
void serverutilities$setPermissionNode(String node);

String serverutilities$getModName();

void serverutilities$setModName(@NotNull String modName);
void serverutilities$setModName(String modName);

boolean serverutilities$hasPermission(EntityPlayerMP player);
default String serverutilities$getModId() {
return "";
}

default void serverutilities$setModId(String modId) {}

default boolean serverutilities$hasPermission(EntityPlayerMP player) {
return false;
}

default void serverUtilities$registerPermissions() {
String node = this.serverutilities$getPermissionNode();
DefaultPermissionLevel level = serverUtilities$getDefaultLevel();

if (this instanceof CommandTreeBase tree) {
for (ICommand c : tree.getSubCommands()) {
ICommandWithPermission child = (ICommandWithPermission) c;
child.serverutilities$setPermissionNode(node.toLowerCase() + '.' + c.getCommandName());
child.serverutilities$setModName(this.serverutilities$getModName());
child.serverUtilities$registerPermissions();
}
}

if (Loader.instance().getLoaderState().ordinal() > LoaderState.PREINITIALIZATION.ordinal()) {
PermissionAPI.registerNode(node, level, "");
} else {
ServerUtilitiesPermissions.earlyPermissions.add(new NodeEntry(node, level, ""));
}
}

default DefaultPermissionLevel serverUtilities$getDefaultLevel() {
if (this instanceof CommandBase cmdBase) {
return cmdBase.getRequiredPermissionLevel() > 0 ? DefaultPermissionLevel.OP : DefaultPermissionLevel.ALL;
}

// Command permissions function as overrides, so it's fine to return OP for non-CommandBase commands
// Only used for display purposes in the rank edit GUI
return DefaultPermissionLevel.OP;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import net.minecraft.command.CommandBase;
import net.minecraft.command.CommandHandler;
import net.minecraft.command.ICommand;
import net.minecraft.command.ICommandSender;
Expand All @@ -19,13 +18,8 @@
import com.llamalad7.mixinextras.sugar.Local;

import cpw.mods.fml.common.Loader;
import cpw.mods.fml.common.LoaderState;
import cpw.mods.fml.common.ModContainer;
import serverutils.ServerUtilitiesPermissions;
import serverutils.data.NodeEntry;
import serverutils.lib.command.CommandTreeBase;
import serverutils.lib.util.permission.DefaultPermissionLevel;
import serverutils.lib.util.permission.PermissionAPI;
import serverutils.ranks.ICommandWithPermission;
import serverutils.ranks.Rank;

Expand Down Expand Up @@ -71,35 +65,6 @@ public abstract class MixinCommandHandler {
ICommandWithPermission cmd = (ICommandWithPermission) command;
cmd.serverutilities$setPermissionNode(PERMISSION_REPLACE_MATCHER.reset(node.toLowerCase()).replaceAll("_"));
cmd.serverutilities$setModName(container == null ? "Minecraft" : container.getName());
serverUtilities$registerPermissions(cmd);
}

@Unique
private DefaultPermissionLevel serverUtilities$getDefaultLevel(ICommandWithPermission command) {
if (command instanceof CommandBase cmdBase) {
return cmdBase.getRequiredPermissionLevel() > 0 ? DefaultPermissionLevel.OP : DefaultPermissionLevel.ALL;
}
return DefaultPermissionLevel.OP;
}

@Unique
private void serverUtilities$registerPermissions(ICommandWithPermission command) {
String node = command.serverutilities$getPermissionNode();
DefaultPermissionLevel level = serverUtilities$getDefaultLevel(command);

if (command instanceof CommandTreeBase tree) {
for (ICommand c : tree.getSubCommands()) {
ICommandWithPermission child = (ICommandWithPermission) c;
child.serverutilities$setPermissionNode(node.toLowerCase() + '.' + c.getCommandName());
child.serverutilities$setModName(command.serverutilities$getModName());
serverUtilities$registerPermissions(child);
}
}

if (Loader.instance().getLoaderState().ordinal() > LoaderState.PREINITIALIZATION.ordinal()) {
PermissionAPI.registerNode(node, level, "");
} else {
ServerUtilitiesPermissions.earlyPermissions.add(new NodeEntry(node, level, ""));
}
cmd.serverUtilities$registerPermissions();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package serverutils.mixins.late.brigadier;

import net.minecraft.entity.player.EntityPlayerMP;

import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;

import com.llamalad7.mixinextras.injector.ModifyReturnValue;
import com.llamalad7.mixinextras.sugar.Local;
import com.mojang.brigadier.tree.CommandNode;

import cpw.mods.fml.common.eventhandler.Event;
import serverutils.ranks.ICommandWithPermission;
import serverutils.ranks.Ranks;

@Mixin(value = CommandNode.class, remap = false)
public abstract class MixinCommandNode<S> {

@ModifyReturnValue(method = "canUse", at = @At(value = "RETURN"), remap = false)
private boolean serverutilities$brigadierExecute(boolean original, @Local(argsOnly = true) S source) {
if (!(source instanceof EntityPlayerMP player) || !(this instanceof ICommandWithPermission permission)) {
return original;
}

Event.Result result = Ranks.INSTANCE
.getPermissionResult(player, permission.serverutilities$getPermissionNode(), true);
if (result == Event.Result.DEFAULT) {
return original;
}

return result == Event.Result.ALLOW;
}
}
Loading
Loading