- [FEAT] New APIs for Maintenance Mode and rewrite commands system

- [FEAT] Improved config system to fix old loading bugs and support JSON
- [FEAT] LuckPerms support for commands
This commit is contained in:
2024-08-10 15:17:10 +02:00
parent e14ac2a136
commit 614fb0bc49
352 changed files with 6045 additions and 1798 deletions

View File

@@ -1,53 +1,155 @@
package com.hypherionmc.craterlib.api.commands;
import com.hypherionmc.craterlib.compat.LuckPermsCompat;
import com.hypherionmc.craterlib.core.platform.ModloaderEnvironment;
import com.hypherionmc.craterlib.nojang.authlib.BridgedGameProfile;
import com.hypherionmc.craterlib.nojang.commands.BridgedCommandSourceStack;
import com.hypherionmc.craterlib.nojang.world.entity.player.BridgedPlayer;
import com.hypherionmc.craterlib.utils.TriConsumer;
import com.mojang.brigadier.arguments.ArgumentType;
import lombok.Getter;
import com.mojang.brigadier.CommandDispatcher;
import com.mojang.brigadier.arguments.BoolArgumentType;
import com.mojang.brigadier.arguments.IntegerArgumentType;
import com.mojang.brigadier.arguments.StringArgumentType;
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import net.minecraft.commands.CommandSourceStack;
import net.minecraft.commands.Commands;
import net.minecraft.commands.arguments.GameProfileArgument;
import org.apache.commons.lang3.tuple.Pair;
import net.minecraft.world.entity.player.Player;
import org.jetbrains.annotations.ApiStatus;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.function.Consumer;
@Getter
public class CraterCommand {
private final HashMap<String, Pair<ArgumentType<?>, TriConsumer<?, ?, BridgedCommandSourceStack>>> arguments = new LinkedHashMap<>();
private Consumer<BridgedCommandSourceStack> executor;
private final LiteralArgumentBuilder<CommandSourceStack> mojangCommand;
private int permLevel = 4;
private String luckPermNode = "";
private final String commandName;
private int permissionLevel = 4;
CraterCommand(String commandName) {
this.commandName = commandName;
CraterCommand(LiteralArgumentBuilder<CommandSourceStack> cmd) {
this.mojangCommand = cmd;
}
public static CraterCommand literal(String commandName) {
return new CraterCommand(commandName);
return new CraterCommand(Commands.literal(commandName));
}
public CraterCommand requiresPermission(int perm) {
this.permissionLevel = perm;
this.permLevel = perm;
this.mojangCommand.requires(this::checkPermission);
return this;
}
public CraterCommand withGameProfileArgument(String key, TriConsumer<BridgedPlayer, List<BridgedGameProfile>, BridgedCommandSourceStack> executor) {
arguments.put(key, Pair.of(GameProfileArgument.gameProfile(), executor));
public CraterCommand withNode(String key) {
this.luckPermNode = key;
return this;
}
public CraterCommand then(CraterCommand child) {
this.mojangCommand.then(child.mojangCommand);
return this;
}
public CraterCommand withGameProfilesArgument(String key, CommandExecutorWithArgs<List<BridgedGameProfile>> executor) {
this.mojangCommand.then(Commands.argument(key, GameProfileArgument.gameProfile())
.executes(context -> executor.run(
BridgedPlayer.of(context.getSource().getPlayer()),
GameProfileArgument.getGameProfiles(context, key).stream().map(BridgedGameProfile::of).toList(),
BridgedCommandSourceStack.of(context.getSource()))
));
return this;
}
public CraterCommand withBoolArgument(String key, CommandExecutorWithArgs<Boolean> executor) {
this.mojangCommand.then(Commands.argument(key, BoolArgumentType.bool())
.executes(context -> executor.run(
BridgedPlayer.of(context.getSource().getPlayer()),
BoolArgumentType.getBool(context, key),
BridgedCommandSourceStack.of(context.getSource())
)));
return this;
}
public CraterCommand withWordArgument(String key, CommandExecutorWithArgs<String> executor) {
this.mojangCommand.then(Commands.argument(key, StringArgumentType.word())
.executes(context -> executor.run(
BridgedPlayer.of(context.getSource().getPlayer()),
StringArgumentType.getString(context, key),
BridgedCommandSourceStack.of(context.getSource())
)));
return this;
}
public CraterCommand withStringArgument(String key, CommandExecutorWithArgs<String> executor) {
this.mojangCommand.then(Commands.argument(key, StringArgumentType.string())
.executes(context -> executor.run(
BridgedPlayer.of(context.getSource().getPlayer()),
StringArgumentType.getString(context, key),
BridgedCommandSourceStack.of(context.getSource())
)));
return this;
}
public CraterCommand withPhraseArgument(String key, CommandExecutorWithArgs<String> executor) {
this.mojangCommand.then(Commands.argument(key, StringArgumentType.greedyString())
.executes(context -> executor.run(
BridgedPlayer.of(context.getSource().getPlayer()),
StringArgumentType.getString(context, key),
BridgedCommandSourceStack.of(context.getSource())
)));
return this;
}
public CraterCommand withIntegerArgument(String key, CommandExecutorWithArgs<Integer> executor) {
this.mojangCommand.then(Commands.argument(key, IntegerArgumentType.integer())
.executes(context -> executor.run(
BridgedPlayer.of(context.getSource().getPlayer()),
IntegerArgumentType.getInteger(context, key),
BridgedCommandSourceStack.of(context.getSource())
)));
return this;
}
public CraterCommand execute(SingleCommandExecutor<BridgedCommandSourceStack> executor) {
this.mojangCommand.executes(context -> executor.run(BridgedCommandSourceStack.of(context.getSource())));
return this;
}
@Deprecated(forRemoval = true)
public CraterCommand executes(Consumer<BridgedCommandSourceStack> ctx) {
executor = ctx;
return this;
return this.execute(stack -> {
ctx.accept(stack);
return 1;
});
}
public boolean hasArguments() {
return !arguments.isEmpty();
@Deprecated(forRemoval = true)
public CraterCommand withGameProfileArgument(String key, TriConsumer<BridgedPlayer, List<BridgedGameProfile>, BridgedCommandSourceStack> executor) {
return this.withGameProfilesArgument(key, (player, argument, stack) -> {
executor.accept(player, argument, stack);
return 1;
});
}
@ApiStatus.Internal
public void register(CommandDispatcher<CommandSourceStack> stack) {
stack.register(this.mojangCommand);
}
private boolean checkPermission(CommandSourceStack stack) {
if (!ModloaderEnvironment.INSTANCE.isModLoaded("luckperms") || !stack.isPlayer() || luckPermNode.isEmpty())
return stack.hasPermission(this.permLevel);
return LuckPermsCompat.INSTANCE.hasPermission(stack.getPlayer(), this.luckPermNode) || stack.hasPermission(this.permLevel);
}
@FunctionalInterface
public interface CommandExecutorWithArgs<S> {
int run(BridgedPlayer player, S argument, BridgedCommandSourceStack stack);
}
@FunctionalInterface
public interface SingleCommandExecutor<S> {
int run(S stack);
}
}

View File

@@ -4,7 +4,6 @@ import com.hypherionmc.craterlib.core.event.CraterEvent;
import com.hypherionmc.craterlib.nojang.world.entity.player.BridgedPlayer;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.Setter;
@RequiredArgsConstructor
@Getter

View File

@@ -2,14 +2,17 @@ package com.hypherionmc.craterlib.api.events.server;
import com.hypherionmc.craterlib.api.commands.CraterCommand;
import com.hypherionmc.craterlib.core.event.CraterEvent;
import com.hypherionmc.craterlib.nojang.commands.CommandsRegistry;
import lombok.NoArgsConstructor;
import com.mojang.brigadier.CommandDispatcher;
import lombok.AllArgsConstructor;
import net.minecraft.commands.CommandSourceStack;
@NoArgsConstructor
@AllArgsConstructor
public class CraterRegisterCommandEvent extends CraterEvent {
private final CommandDispatcher<CommandSourceStack> stack;
public void registerCommand(CraterCommand cmd) {
CommandsRegistry.INSTANCE.registerCommand(cmd);
cmd.register(stack);
}
}

View File

@@ -0,0 +1,35 @@
package com.hypherionmc.craterlib.api.events.server;
import com.hypherionmc.craterlib.core.event.CraterEvent;
import com.hypherionmc.craterlib.nojang.network.protocol.status.WrappedServerStatus;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.Setter;
import net.kyori.adventure.text.Component;
import org.jetbrains.annotations.Nullable;
import java.util.Optional;
public class ServerStatusEvent {
@RequiredArgsConstructor
@Getter
@Setter
public static class StatusRequestEvent extends CraterEvent {
private final Component status;
@Nullable
private Component newStatus = null;
}
@RequiredArgsConstructor
@Getter
@Setter
public static class FaviconRequestEvent extends CraterEvent {
private final Optional<WrappedServerStatus.WrappedFavicon> favicon;
private Optional<WrappedServerStatus.WrappedFavicon> newIcon = Optional.empty();
}
}