- [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:
@@ -3,7 +3,7 @@ def projectIcon = "https://cdn.modrinth.com/data/Nn8Wasaq/a172c634683a11a2e9ae59
|
|||||||
def JDK = "21";
|
def JDK = "21";
|
||||||
def majorMc = "1.21";
|
def majorMc = "1.21";
|
||||||
def modLoaders = "neoforge|fabric|quilt";
|
def modLoaders = "neoforge|fabric|quilt";
|
||||||
def supportedMc = "1.21";
|
def supportedMc = "1.21|1.21.1";
|
||||||
def reltype = "port";
|
def reltype = "port";
|
||||||
|
|
||||||
pipeline {
|
pipeline {
|
||||||
|
@@ -1,53 +1,155 @@
|
|||||||
package com.hypherionmc.craterlib.api.commands;
|
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.authlib.BridgedGameProfile;
|
||||||
import com.hypherionmc.craterlib.nojang.commands.BridgedCommandSourceStack;
|
import com.hypherionmc.craterlib.nojang.commands.BridgedCommandSourceStack;
|
||||||
import com.hypherionmc.craterlib.nojang.world.entity.player.BridgedPlayer;
|
import com.hypherionmc.craterlib.nojang.world.entity.player.BridgedPlayer;
|
||||||
import com.hypherionmc.craterlib.utils.TriConsumer;
|
import com.hypherionmc.craterlib.utils.TriConsumer;
|
||||||
import com.mojang.brigadier.arguments.ArgumentType;
|
import com.mojang.brigadier.CommandDispatcher;
|
||||||
import lombok.Getter;
|
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 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.List;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
@Getter
|
|
||||||
public class CraterCommand {
|
public class CraterCommand {
|
||||||
|
|
||||||
private final HashMap<String, Pair<ArgumentType<?>, TriConsumer<?, ?, BridgedCommandSourceStack>>> arguments = new LinkedHashMap<>();
|
private final LiteralArgumentBuilder<CommandSourceStack> mojangCommand;
|
||||||
private Consumer<BridgedCommandSourceStack> executor;
|
private int permLevel = 4;
|
||||||
|
private String luckPermNode = "";
|
||||||
|
|
||||||
private final String commandName;
|
CraterCommand(LiteralArgumentBuilder<CommandSourceStack> cmd) {
|
||||||
private int permissionLevel = 4;
|
this.mojangCommand = cmd;
|
||||||
|
|
||||||
CraterCommand(String commandName) {
|
|
||||||
this.commandName = commandName;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static CraterCommand literal(String commandName) {
|
public static CraterCommand literal(String commandName) {
|
||||||
return new CraterCommand(commandName);
|
return new CraterCommand(Commands.literal(commandName));
|
||||||
}
|
}
|
||||||
|
|
||||||
public CraterCommand requiresPermission(int perm) {
|
public CraterCommand requiresPermission(int perm) {
|
||||||
this.permissionLevel = perm;
|
this.permLevel = perm;
|
||||||
|
this.mojangCommand.requires(this::checkPermission);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public CraterCommand withGameProfileArgument(String key, TriConsumer<BridgedPlayer, List<BridgedGameProfile>, BridgedCommandSourceStack> executor) {
|
public CraterCommand withNode(String key) {
|
||||||
arguments.put(key, Pair.of(GameProfileArgument.gameProfile(), executor));
|
this.luckPermNode = key;
|
||||||
return this;
|
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) {
|
public CraterCommand executes(Consumer<BridgedCommandSourceStack> ctx) {
|
||||||
executor = ctx;
|
return this.execute(stack -> {
|
||||||
return this;
|
ctx.accept(stack);
|
||||||
|
return 1;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean hasArguments() {
|
@Deprecated(forRemoval = true)
|
||||||
return !arguments.isEmpty();
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -4,7 +4,6 @@ import com.hypherionmc.craterlib.core.event.CraterEvent;
|
|||||||
import com.hypherionmc.craterlib.nojang.world.entity.player.BridgedPlayer;
|
import com.hypherionmc.craterlib.nojang.world.entity.player.BridgedPlayer;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.Setter;
|
|
||||||
|
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
@Getter
|
@Getter
|
||||||
|
@@ -2,14 +2,17 @@ package com.hypherionmc.craterlib.api.events.server;
|
|||||||
|
|
||||||
import com.hypherionmc.craterlib.api.commands.CraterCommand;
|
import com.hypherionmc.craterlib.api.commands.CraterCommand;
|
||||||
import com.hypherionmc.craterlib.core.event.CraterEvent;
|
import com.hypherionmc.craterlib.core.event.CraterEvent;
|
||||||
import com.hypherionmc.craterlib.nojang.commands.CommandsRegistry;
|
import com.mojang.brigadier.CommandDispatcher;
|
||||||
import lombok.NoArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
|
import net.minecraft.commands.CommandSourceStack;
|
||||||
|
|
||||||
@NoArgsConstructor
|
@AllArgsConstructor
|
||||||
public class CraterRegisterCommandEvent extends CraterEvent {
|
public class CraterRegisterCommandEvent extends CraterEvent {
|
||||||
|
|
||||||
|
private final CommandDispatcher<CommandSourceStack> stack;
|
||||||
|
|
||||||
public void registerCommand(CraterCommand cmd) {
|
public void registerCommand(CraterCommand cmd) {
|
||||||
CommandsRegistry.INSTANCE.registerCommand(cmd);
|
cmd.register(stack);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -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();
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@@ -2,7 +2,7 @@ package com.hypherionmc.craterlib.client.gui.config;
|
|||||||
|
|
||||||
import com.hypherionmc.craterlib.CraterConstants;
|
import com.hypherionmc.craterlib.CraterConstants;
|
||||||
import com.hypherionmc.craterlib.client.gui.config.widgets.*;
|
import com.hypherionmc.craterlib.client.gui.config.widgets.*;
|
||||||
import com.hypherionmc.craterlib.core.config.ModuleConfig;
|
import com.hypherionmc.craterlib.core.config.AbstractConfig;
|
||||||
import com.hypherionmc.craterlib.core.config.annotations.HideFromScreen;
|
import com.hypherionmc.craterlib.core.config.annotations.HideFromScreen;
|
||||||
import com.hypherionmc.craterlib.core.config.annotations.SubConfig;
|
import com.hypherionmc.craterlib.core.config.annotations.SubConfig;
|
||||||
import com.hypherionmc.craterlib.core.config.annotations.Tooltip;
|
import com.hypherionmc.craterlib.core.config.annotations.Tooltip;
|
||||||
@@ -44,11 +44,11 @@ public class CraterConfigScreen extends Screen {
|
|||||||
private static final int BOTTOM = 24;
|
private static final int BOTTOM = 24;
|
||||||
private final Screen parent;
|
private final Screen parent;
|
||||||
private final List<Option<?>> options = new ArrayList<>();
|
private final List<Option<?>> options = new ArrayList<>();
|
||||||
private final ModuleConfig config;
|
private final AbstractConfig config;
|
||||||
public double scrollerAmount;
|
public double scrollerAmount;
|
||||||
private boolean dragging;
|
private boolean dragging;
|
||||||
|
|
||||||
public CraterConfigScreen(ModuleConfig config, Screen parent, Object subConfig) {
|
public CraterConfigScreen(AbstractConfig config, Screen parent, Object subConfig) {
|
||||||
super(Component.translatable("cl." + config.getClass().getSimpleName().toLowerCase() + ".title"));
|
super(Component.translatable("cl." + config.getClass().getSimpleName().toLowerCase() + ".title"));
|
||||||
this.parent = parent;
|
this.parent = parent;
|
||||||
this.config = config;
|
this.config = config;
|
||||||
@@ -59,7 +59,7 @@ public class CraterConfigScreen extends Screen {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public CraterConfigScreen(ModuleConfig config, Screen parent) {
|
public CraterConfigScreen(AbstractConfig config, Screen parent) {
|
||||||
this(config, parent, null);
|
this(config, parent, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
package com.hypherionmc.craterlib.client.gui.config.widgets;
|
package com.hypherionmc.craterlib.client.gui.config.widgets;
|
||||||
|
|
||||||
import com.hypherionmc.craterlib.client.gui.config.CraterConfigScreen;
|
import com.hypherionmc.craterlib.client.gui.config.CraterConfigScreen;
|
||||||
import com.hypherionmc.craterlib.core.config.ModuleConfig;
|
import com.hypherionmc.craterlib.core.config.AbstractConfig;
|
||||||
import net.minecraft.client.Minecraft;
|
import net.minecraft.client.Minecraft;
|
||||||
import net.minecraft.client.gui.Font;
|
import net.minecraft.client.gui.Font;
|
||||||
import net.minecraft.client.gui.GuiGraphics;
|
import net.minecraft.client.gui.GuiGraphics;
|
||||||
@@ -15,10 +15,10 @@ import net.minecraft.network.chat.Component;
|
|||||||
public class SubConfigWidget<T> extends AbstractConfigWidget<T, Button> {
|
public class SubConfigWidget<T> extends AbstractConfigWidget<T, Button> {
|
||||||
|
|
||||||
private final Object subConfig;
|
private final Object subConfig;
|
||||||
private final ModuleConfig config;
|
private final AbstractConfig config;
|
||||||
private final Screen screen;
|
private final Screen screen;
|
||||||
|
|
||||||
public SubConfigWidget(ModuleConfig config, Screen screen, Object subConfig) {
|
public SubConfigWidget(AbstractConfig config, Screen screen, Object subConfig) {
|
||||||
this.config = config;
|
this.config = config;
|
||||||
this.subConfig = subConfig;
|
this.subConfig = subConfig;
|
||||||
this.screen = screen;
|
this.screen = screen;
|
||||||
|
@@ -0,0 +1,20 @@
|
|||||||
|
package com.hypherionmc.craterlib.compat;
|
||||||
|
|
||||||
|
import net.luckperms.api.LuckPerms;
|
||||||
|
import net.luckperms.api.LuckPermsProvider;
|
||||||
|
import net.luckperms.api.model.user.User;
|
||||||
|
import net.minecraft.server.level.ServerPlayer;
|
||||||
|
|
||||||
|
public class LuckPermsCompat {
|
||||||
|
|
||||||
|
public static final LuckPermsCompat INSTANCE = new LuckPermsCompat();
|
||||||
|
private final LuckPerms luckPerms = LuckPermsProvider.get();
|
||||||
|
|
||||||
|
LuckPermsCompat() {}
|
||||||
|
|
||||||
|
public boolean hasPermission(ServerPlayer player, String perm) {
|
||||||
|
User luckPermsUser = luckPerms.getPlayerAdapter(ServerPlayer.class).getUser(player);
|
||||||
|
return luckPermsUser.getCachedData().getPermissionData().checkPermission(perm).asBoolean();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,71 @@
|
|||||||
|
package com.hypherionmc.craterlib.core.config;
|
||||||
|
|
||||||
|
import com.hypherionmc.craterlib.core.config.formats.AbstractConfigFormat;
|
||||||
|
import com.hypherionmc.craterlib.core.config.formats.JsonConfigFormat;
|
||||||
|
import com.hypherionmc.craterlib.core.config.formats.TomlConfigFormat;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
import me.hypherionmc.moonconfig.core.Config;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
public abstract class AbstractConfig<S> {
|
||||||
|
|
||||||
|
/* Final Variables */
|
||||||
|
private final transient File configPath;
|
||||||
|
private final transient String networkID;
|
||||||
|
private final transient String configName;
|
||||||
|
private final transient String modId;
|
||||||
|
private transient boolean wasSaveCalled = false;
|
||||||
|
|
||||||
|
@Setter
|
||||||
|
private transient AbstractConfigFormat<S> configFormat;
|
||||||
|
|
||||||
|
public AbstractConfig(String modId, String configName) {
|
||||||
|
this(modId, null, configName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public AbstractConfig(String modId, @Nullable String subFolder, String configName) {
|
||||||
|
Config.setInsertionOrderPreserved(true);
|
||||||
|
|
||||||
|
if (!configName.endsWith(".toml") && !configName.endsWith(".json"))
|
||||||
|
configName = configName + ".toml";
|
||||||
|
|
||||||
|
File configDir = new File("config" + (subFolder == null ? "" : File.separator + subFolder));
|
||||||
|
configPath = new File(configDir, configName);
|
||||||
|
this.modId = modId;
|
||||||
|
this.networkID = modId + ":conf_" + configName.replace(".toml", "").replace(".json", "").replace("-", "_").toLowerCase();
|
||||||
|
this.configName = configName.replace(".toml", "").replace(".json", "");
|
||||||
|
configDir.mkdirs();
|
||||||
|
|
||||||
|
configFormat = configName.endsWith(".json") ? new JsonConfigFormat<>(configPath, this::onSave) : new TomlConfigFormat<>(configPath, this::onSave);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void registerAndSetup(S config) {
|
||||||
|
configFormat.register(config);
|
||||||
|
ConfigController.register_config(this);
|
||||||
|
this.configReloaded();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void saveConfig(S config) {
|
||||||
|
this.wasSaveCalled = true;
|
||||||
|
configFormat.saveConfig(config);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onSave() {
|
||||||
|
this.configReloaded();
|
||||||
|
this.wasSaveCalled = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public S readConfig(S config) {
|
||||||
|
return configFormat.readConfig(config);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void migrateConfig(S config) {
|
||||||
|
configFormat.migrateConfig(config);
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract void configReloaded();
|
||||||
|
}
|
@@ -3,6 +3,7 @@ package com.hypherionmc.craterlib.core.config;
|
|||||||
import com.hypherionmc.craterlib.CraterConstants;
|
import com.hypherionmc.craterlib.CraterConstants;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import me.hypherionmc.moonconfig.core.file.FileWatcher;
|
import me.hypherionmc.moonconfig.core.file.FileWatcher;
|
||||||
|
import org.apache.commons.lang3.tuple.Pair;
|
||||||
import org.jetbrains.annotations.ApiStatus;
|
import org.jetbrains.annotations.ApiStatus;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
@@ -18,7 +19,7 @@ public final class ConfigController implements Serializable {
|
|||||||
* Cache of registered configs
|
* Cache of registered configs
|
||||||
*/
|
*/
|
||||||
@Getter
|
@Getter
|
||||||
private static final HashMap<Object, FileWatcher> monitoredConfigs = new HashMap<>();
|
private static final HashMap<String, Pair<AbstractConfig, FileWatcher>> watchedConfigs = new HashMap<>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* INTERNAL METHOD - Register and watch the config
|
* INTERNAL METHOD - Register and watch the config
|
||||||
@@ -26,23 +27,34 @@ public final class ConfigController implements Serializable {
|
|||||||
* @param config - The config class to register and watch
|
* @param config - The config class to register and watch
|
||||||
*/
|
*/
|
||||||
@ApiStatus.Internal
|
@ApiStatus.Internal
|
||||||
|
@Deprecated
|
||||||
public static void register_config(ModuleConfig config) {
|
public static void register_config(ModuleConfig config) {
|
||||||
if (monitoredConfigs.containsKey(config)) {
|
register_config((AbstractConfig) config);
|
||||||
CraterConstants.LOG.error("Failed to register " + config.getConfigPath().getName() + ". Config already registered");
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* INTERNAL METHOD - Register and watch the config
|
||||||
|
*
|
||||||
|
* @param config - The config class to register and watch
|
||||||
|
*/
|
||||||
|
@ApiStatus.Internal
|
||||||
|
public static void register_config(AbstractConfig config) {
|
||||||
|
if (watchedConfigs.containsKey(config.getConfigPath().toString())) {
|
||||||
|
CraterConstants.LOG.error("Failed to register {}. Config already registered", config.getConfigPath().getName());
|
||||||
} else {
|
} else {
|
||||||
FileWatcher configWatcher = new FileWatcher();
|
FileWatcher configWatcher = new FileWatcher();
|
||||||
try {
|
try {
|
||||||
configWatcher.setWatch(config.getConfigPath(), () -> {
|
configWatcher.setWatch(config.getConfigPath(), () -> {
|
||||||
if (!config.isSaveCalled()) {
|
if (!config.isWasSaveCalled()) {
|
||||||
CraterConstants.LOG.info("Sending Reload Event for: " + config.getConfigPath().getName());
|
CraterConstants.LOG.info("Sending Reload Event for: {}", config.getConfigPath().getName());
|
||||||
config.configReloaded();
|
config.configReloaded();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
CraterConstants.LOG.error("Failed to register " + config.getConfigPath().getName() + " for auto reloading. " + e.getMessage());
|
CraterConstants.LOG.error("Failed to register {} for auto reloading. {}", config.getConfigPath().getName(), e.getMessage());
|
||||||
}
|
}
|
||||||
monitoredConfigs.put(config, configWatcher);
|
watchedConfigs.put(config.getConfigPath().toString(), Pair.of(config, configWatcher));
|
||||||
CraterConstants.LOG.info("Registered " + config.getConfigPath().getName() + " successfully!");
|
CraterConstants.LOG.info("Registered {} successfully!", config.getConfigPath().getName());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,9 +1,7 @@
|
|||||||
package com.hypherionmc.craterlib.core.config;
|
package com.hypherionmc.craterlib.core.config;
|
||||||
|
|
||||||
|
import com.hypherionmc.craterlib.core.config.formats.TomlConfigFormat;
|
||||||
import me.hypherionmc.moonconfig.core.CommentedConfig;
|
import me.hypherionmc.moonconfig.core.CommentedConfig;
|
||||||
import me.hypherionmc.moonconfig.core.Config;
|
|
||||||
import me.hypherionmc.moonconfig.core.conversion.ObjectConverter;
|
|
||||||
import me.hypherionmc.moonconfig.core.file.CommentedFileConfig;
|
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
|
||||||
@@ -12,17 +10,8 @@ import java.io.File;
|
|||||||
* Base Config class containing the save, upgrading and loading logic.
|
* Base Config class containing the save, upgrading and loading logic.
|
||||||
* All config classes must extend this class
|
* All config classes must extend this class
|
||||||
*/
|
*/
|
||||||
public class ModuleConfig {
|
@Deprecated
|
||||||
|
public class ModuleConfig extends AbstractConfig {
|
||||||
/* Final Variables */
|
|
||||||
private final transient File configPath;
|
|
||||||
private final transient String networkID;
|
|
||||||
|
|
||||||
private final transient String configName;
|
|
||||||
|
|
||||||
private final transient String modId;
|
|
||||||
|
|
||||||
private transient boolean isSaveCalled = false;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set up the config
|
* Set up the config
|
||||||
@@ -35,20 +24,7 @@ public class ModuleConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public ModuleConfig(String modId, String subFolder, String configName) {
|
public ModuleConfig(String modId, String subFolder, String configName) {
|
||||||
/* Preserve the order of the config values */
|
super(modId, subFolder.isEmpty() ? null : subFolder, configName);
|
||||||
Config.setInsertionOrderPreserved(true);
|
|
||||||
|
|
||||||
/* Configure Paths and Network SYNC ID */
|
|
||||||
File configDir = new File("config" + (subFolder.isEmpty() ? "" : File.separator + subFolder));
|
|
||||||
configPath = new File(configDir + File.separator + configName + ".toml");
|
|
||||||
networkID = modId + ":conf_" + configName.replace("-", "_");
|
|
||||||
this.modId = modId;
|
|
||||||
this.configName = configName;
|
|
||||||
|
|
||||||
/* Check if the required directories exists, otherwise we create them */
|
|
||||||
if (!configDir.exists()) {
|
|
||||||
configDir.mkdirs();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -57,14 +33,7 @@ public class ModuleConfig {
|
|||||||
* @param config - The config class to use
|
* @param config - The config class to use
|
||||||
*/
|
*/
|
||||||
public void registerAndSetup(ModuleConfig config) {
|
public void registerAndSetup(ModuleConfig config) {
|
||||||
if (!configPath.exists() || configPath.length() < 2) {
|
super.registerAndSetup(config);
|
||||||
saveConfig(config);
|
|
||||||
} else {
|
|
||||||
migrateConfig(config);
|
|
||||||
}
|
|
||||||
/* Register the Config for Watching and events */
|
|
||||||
ConfigController.register_config(this);
|
|
||||||
this.configReloaded();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -73,16 +42,7 @@ public class ModuleConfig {
|
|||||||
* @param conf - The config class to serialize and save
|
* @param conf - The config class to serialize and save
|
||||||
*/
|
*/
|
||||||
public void saveConfig(ModuleConfig conf) {
|
public void saveConfig(ModuleConfig conf) {
|
||||||
this.isSaveCalled = true;
|
super.registerAndSetup(conf);
|
||||||
/* Set up the Serializer and Config Object */
|
|
||||||
ObjectConverter converter = new ObjectConverter();
|
|
||||||
CommentedFileConfig config = CommentedFileConfig.builder(configPath).build();
|
|
||||||
|
|
||||||
/* Save the config and fire the reload events */
|
|
||||||
converter.toConfig(conf, config);
|
|
||||||
config.save();
|
|
||||||
configReloaded();
|
|
||||||
this.isSaveCalled = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -92,14 +52,7 @@ public class ModuleConfig {
|
|||||||
* @return - Returns the loaded version of the class
|
* @return - Returns the loaded version of the class
|
||||||
*/
|
*/
|
||||||
public <T> T loadConfig(Object conf) {
|
public <T> T loadConfig(Object conf) {
|
||||||
/* Set up the Serializer and Config Object */
|
return (T) super.readConfig(conf);
|
||||||
ObjectConverter converter = new ObjectConverter();
|
|
||||||
CommentedFileConfig config = CommentedFileConfig.builder(configPath).build();
|
|
||||||
config.load();
|
|
||||||
|
|
||||||
/* Load the config and return the loaded config */
|
|
||||||
converter.toObject(config, conf);
|
|
||||||
return (T) conf;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -108,31 +61,13 @@ public class ModuleConfig {
|
|||||||
* @param conf - The config class to load
|
* @param conf - The config class to load
|
||||||
*/
|
*/
|
||||||
public void migrateConfig(ModuleConfig conf) {
|
public void migrateConfig(ModuleConfig conf) {
|
||||||
/* Set up the Serializer and Config Objects */
|
super.migrateConfig(conf);
|
||||||
CommentedFileConfig config = CommentedFileConfig.builder(configPath).build();
|
|
||||||
CommentedFileConfig newConfig = CommentedFileConfig.builder(configPath).build();
|
|
||||||
config.load();
|
|
||||||
|
|
||||||
/* Upgrade the config */
|
|
||||||
new ObjectConverter().toConfig(conf, newConfig);
|
|
||||||
updateConfigValues(config, newConfig, newConfig, "");
|
|
||||||
newConfig.save();
|
|
||||||
|
|
||||||
config.close();
|
|
||||||
newConfig.close();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateConfigValues(CommentedConfig oldConfig, CommentedConfig newConfig, CommentedConfig outputConfig, String subKey) {
|
public void updateConfigValues(CommentedConfig oldConfig, CommentedConfig newConfig, CommentedConfig outputConfig, String subKey) {
|
||||||
/* Loop over the config keys and check what has changed */
|
if (getConfigFormat() instanceof TomlConfigFormat<?> t) {
|
||||||
newConfig.valueMap().forEach((key, value) -> {
|
t.updateConfigValues(oldConfig, newConfig, outputConfig, subKey);
|
||||||
String finalKey = subKey + (subKey.isEmpty() ? "" : ".") + key;
|
}
|
||||||
if (value instanceof CommentedConfig commentedConfig) {
|
|
||||||
updateConfigValues(oldConfig, commentedConfig, outputConfig, finalKey);
|
|
||||||
} else {
|
|
||||||
outputConfig.set(finalKey,
|
|
||||||
oldConfig.contains(finalKey) ? oldConfig.get(finalKey) : value);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -141,7 +76,7 @@ public class ModuleConfig {
|
|||||||
* @return - The FILE object containing the config file
|
* @return - The FILE object containing the config file
|
||||||
*/
|
*/
|
||||||
public File getConfigPath() {
|
public File getConfigPath() {
|
||||||
return configPath;
|
return super.getConfigPath();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -150,12 +85,13 @@ public class ModuleConfig {
|
|||||||
* @return - Returns the Sync ID in format modid:config_name
|
* @return - Returns the Sync ID in format modid:config_name
|
||||||
*/
|
*/
|
||||||
public String getNetworkID() {
|
public String getNetworkID() {
|
||||||
return networkID;
|
return super.getNetworkID();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fired whenever changes to the config are detected
|
* Fired whenever changes to the config are detected
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public void configReloaded() {
|
public void configReloaded() {
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -166,7 +102,7 @@ public class ModuleConfig {
|
|||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public String getConfigName() {
|
public String getConfigName() {
|
||||||
return configName;
|
return super.getConfigName();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -175,10 +111,10 @@ public class ModuleConfig {
|
|||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public String getModId() {
|
public String getModId() {
|
||||||
return modId;
|
return super.getModId();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isSaveCalled() {
|
public boolean isSaveCalled() {
|
||||||
return isSaveCalled;
|
return super.isWasSaveCalled();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,32 @@
|
|||||||
|
package com.hypherionmc.craterlib.core.config.formats;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import me.hypherionmc.moonconfig.core.Config;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
@Getter
|
||||||
|
public abstract class AbstractConfigFormat<S> {
|
||||||
|
|
||||||
|
private final File configPath;
|
||||||
|
private final Runnable onSave;
|
||||||
|
|
||||||
|
public void register(S conf) {
|
||||||
|
if (!configPath.exists() || configPath.length() < 2) {
|
||||||
|
saveConfig(conf);
|
||||||
|
} else {
|
||||||
|
migrateConfig(conf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean wasConfigChanged(Config old, Config newConfig) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract void saveConfig(S config);
|
||||||
|
public abstract S readConfig(S config);
|
||||||
|
public abstract void migrateConfig(S config);
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,67 @@
|
|||||||
|
package com.hypherionmc.craterlib.core.config.formats;
|
||||||
|
|
||||||
|
import me.hypherionmc.moonconfig.core.Config;
|
||||||
|
import me.hypherionmc.moonconfig.core.conversion.ObjectConverter;
|
||||||
|
import me.hypherionmc.moonconfig.core.file.FileConfig;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
|
||||||
|
public class JsonConfigFormat<S> extends AbstractConfigFormat<S> {
|
||||||
|
|
||||||
|
public JsonConfigFormat(File configPath, Runnable afterSave) {
|
||||||
|
super(configPath, afterSave);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void saveConfig(S conf) {
|
||||||
|
ObjectConverter converter = new ObjectConverter();
|
||||||
|
FileConfig config = FileConfig.builder(getConfigPath()).sync().build();
|
||||||
|
|
||||||
|
converter.toConfig(conf, config);
|
||||||
|
config.save();
|
||||||
|
getOnSave().run();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public S readConfig(S conf) {
|
||||||
|
/* Set up the Serializer and Config Object */
|
||||||
|
ObjectConverter converter = new ObjectConverter();
|
||||||
|
FileConfig config = FileConfig.builder(getConfigPath()).build();
|
||||||
|
config.load();
|
||||||
|
|
||||||
|
/* Load the config and return the loaded config */
|
||||||
|
converter.toObject(config, conf);
|
||||||
|
return conf;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void migrateConfig(S conf) {
|
||||||
|
/* Set up the Serializer and Config Objects */
|
||||||
|
FileConfig config = FileConfig.builder(getConfigPath()).build();
|
||||||
|
FileConfig newConfig = FileConfig.builder(getConfigPath()).sync().build();
|
||||||
|
config.load();
|
||||||
|
|
||||||
|
/* Upgrade the config */
|
||||||
|
if (wasConfigChanged(config, newConfig)) {
|
||||||
|
new ObjectConverter().toConfig(conf, newConfig);
|
||||||
|
updateConfigValues(config, newConfig, newConfig, "");
|
||||||
|
newConfig.save();
|
||||||
|
}
|
||||||
|
|
||||||
|
config.close();
|
||||||
|
newConfig.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateConfigValues(Config oldConfig, Config newConfig, Config outputConfig, String subKey) {
|
||||||
|
/* Loop over the config keys and check what has changed */
|
||||||
|
newConfig.valueMap().forEach((key, value) -> {
|
||||||
|
String finalKey = subKey + (subKey.isEmpty() ? "" : ".") + key;
|
||||||
|
if (value instanceof Config commentedConfig) {
|
||||||
|
updateConfigValues(oldConfig, commentedConfig, outputConfig, finalKey);
|
||||||
|
} else {
|
||||||
|
outputConfig.set(finalKey,
|
||||||
|
oldConfig.contains(finalKey) ? oldConfig.get(finalKey) : value);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,67 @@
|
|||||||
|
package com.hypherionmc.craterlib.core.config.formats;
|
||||||
|
|
||||||
|
import me.hypherionmc.moonconfig.core.CommentedConfig;
|
||||||
|
import me.hypherionmc.moonconfig.core.conversion.ObjectConverter;
|
||||||
|
import me.hypherionmc.moonconfig.core.file.CommentedFileConfig;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
|
||||||
|
public class TomlConfigFormat<S> extends AbstractConfigFormat<S> {
|
||||||
|
|
||||||
|
public TomlConfigFormat(File configPath, Runnable onSave) {
|
||||||
|
super(configPath, onSave);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void saveConfig(S conf) {
|
||||||
|
ObjectConverter converter = new ObjectConverter();
|
||||||
|
CommentedFileConfig config = CommentedFileConfig.builder(getConfigPath()).sync().build();
|
||||||
|
|
||||||
|
converter.toConfig(conf, config);
|
||||||
|
config.save();
|
||||||
|
getOnSave().run();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public S readConfig(S conf) {
|
||||||
|
/* Set up the Serializer and Config Object */
|
||||||
|
ObjectConverter converter = new ObjectConverter();
|
||||||
|
CommentedFileConfig config = CommentedFileConfig.builder(getConfigPath()).build();
|
||||||
|
config.load();
|
||||||
|
|
||||||
|
/* Load the config and return the loaded config */
|
||||||
|
converter.toObject(config, conf);
|
||||||
|
return conf;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void migrateConfig(S conf) {
|
||||||
|
/* Set up the Serializer and Config Objects */
|
||||||
|
CommentedFileConfig config = CommentedFileConfig.builder(getConfigPath()).build();
|
||||||
|
CommentedFileConfig newConfig = CommentedFileConfig.builder(getConfigPath()).sync().build();
|
||||||
|
config.load();
|
||||||
|
|
||||||
|
/* Upgrade the config */
|
||||||
|
if (wasConfigChanged(config, newConfig)) {
|
||||||
|
new ObjectConverter().toConfig(conf, newConfig);
|
||||||
|
updateConfigValues(config, newConfig, newConfig, "");
|
||||||
|
newConfig.save();
|
||||||
|
}
|
||||||
|
|
||||||
|
config.close();
|
||||||
|
newConfig.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateConfigValues(CommentedConfig oldConfig, CommentedConfig newConfig, CommentedConfig outputConfig, String subKey) {
|
||||||
|
/* Loop over the config keys and check what has changed */
|
||||||
|
newConfig.valueMap().forEach((key, value) -> {
|
||||||
|
String finalKey = subKey + (subKey.isEmpty() ? "" : ".") + key;
|
||||||
|
if (value instanceof CommentedConfig commentedConfig) {
|
||||||
|
updateConfigValues(oldConfig, commentedConfig, outputConfig, finalKey);
|
||||||
|
} else {
|
||||||
|
outputConfig.set(finalKey,
|
||||||
|
oldConfig.contains(finalKey) ? oldConfig.get(finalKey) : value);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,27 @@
|
|||||||
|
package com.hypherionmc.craterlib.mixin.events;
|
||||||
|
|
||||||
|
import com.hypherionmc.craterlib.api.events.server.ServerStatusEvent;
|
||||||
|
import com.hypherionmc.craterlib.core.event.CraterEventBus;
|
||||||
|
import com.hypherionmc.craterlib.nojang.network.protocol.status.WrappedServerStatus;
|
||||||
|
import net.minecraft.network.protocol.status.ServerStatus;
|
||||||
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
|
import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
@Mixin(ServerStatus.class)
|
||||||
|
public class ServerStatusMixin {
|
||||||
|
|
||||||
|
@Inject(method = "favicon", at = @At("RETURN"), cancellable = true)
|
||||||
|
private void injectIconEvent(CallbackInfoReturnable<Optional<ServerStatus.Favicon>> cir) {
|
||||||
|
ServerStatusEvent.FaviconRequestEvent event = new ServerStatusEvent.FaviconRequestEvent(cir.getReturnValue().isEmpty() ? Optional.empty() : Optional.of(new WrappedServerStatus.WrappedFavicon(cir.getReturnValue().get())));
|
||||||
|
CraterEventBus.INSTANCE.postEvent(event);
|
||||||
|
|
||||||
|
if (event.getNewIcon().isPresent()) {
|
||||||
|
cir.setReturnValue(Optional.of(event.getNewIcon().get().toMojang()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -16,6 +16,10 @@ public class BridgedCommandSourceStack {
|
|||||||
internal.sendSuccess(() -> ChatUtils.adventureToMojang(supplier.get()), bl);
|
internal.sendSuccess(() -> ChatUtils.adventureToMojang(supplier.get()), bl);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void sendFailure(Component text) {
|
||||||
|
internal.sendFailure(ChatUtils.adventureToMojang(text));
|
||||||
|
}
|
||||||
|
|
||||||
public CommandSourceStack toMojang() {
|
public CommandSourceStack toMojang() {
|
||||||
return internal;
|
return internal;
|
||||||
}
|
}
|
||||||
|
@@ -1,85 +0,0 @@
|
|||||||
package com.hypherionmc.craterlib.nojang.commands;
|
|
||||||
|
|
||||||
import com.hypherionmc.craterlib.api.commands.CraterCommand;
|
|
||||||
import com.hypherionmc.craterlib.nojang.authlib.BridgedGameProfile;
|
|
||||||
import com.hypherionmc.craterlib.nojang.world.entity.player.BridgedPlayer;
|
|
||||||
import com.hypherionmc.craterlib.utils.TriConsumer;
|
|
||||||
import com.mojang.authlib.GameProfile;
|
|
||||||
import com.mojang.brigadier.CommandDispatcher;
|
|
||||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
|
||||||
import lombok.AccessLevel;
|
|
||||||
import lombok.NoArgsConstructor;
|
|
||||||
import net.minecraft.commands.CommandSourceStack;
|
|
||||||
import net.minecraft.commands.Commands;
|
|
||||||
import net.minecraft.commands.arguments.GameProfileArgument;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
@NoArgsConstructor(access = AccessLevel.PRIVATE)
|
|
||||||
public class CommandsRegistry {
|
|
||||||
|
|
||||||
public static final CommandsRegistry INSTANCE = new CommandsRegistry();
|
|
||||||
|
|
||||||
private final List<CraterCommand> commands = new ArrayList<>();
|
|
||||||
|
|
||||||
public void registerCommand(CraterCommand cmd) {
|
|
||||||
commands.add(cmd);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void registerCommands(CommandDispatcher<CommandSourceStack> stack) {
|
|
||||||
commands.forEach(cmd -> {
|
|
||||||
if (cmd.hasArguments()) {
|
|
||||||
CommandWithArguments.register(cmd, stack);
|
|
||||||
} else {
|
|
||||||
CommandWithoutArguments.register(cmd, stack);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
static class CommandWithoutArguments {
|
|
||||||
|
|
||||||
public static void register(CraterCommand cmd, CommandDispatcher<CommandSourceStack> dispatcher) {
|
|
||||||
LiteralArgumentBuilder<CommandSourceStack> command = Commands.literal(cmd.getCommandName())
|
|
||||||
.requires(source -> source.hasPermission(cmd.getPermissionLevel()))
|
|
||||||
.executes(context -> {
|
|
||||||
cmd.getExecutor().accept(BridgedCommandSourceStack.of(context.getSource()));
|
|
||||||
return 1;
|
|
||||||
});
|
|
||||||
|
|
||||||
dispatcher.register(command);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
static class CommandWithArguments {
|
|
||||||
|
|
||||||
public static void register(CraterCommand cmd, CommandDispatcher<CommandSourceStack> dispatcher) {
|
|
||||||
LiteralArgumentBuilder<CommandSourceStack> command = Commands.literal(cmd.getCommandName())
|
|
||||||
.requires(source -> source.hasPermission(cmd.getPermissionLevel()));
|
|
||||||
|
|
||||||
cmd.getArguments().forEach((key, pair) -> command.then(Commands.argument(key, pair.getLeft()).executes(context -> {
|
|
||||||
|
|
||||||
// This is FUCKING UGLY.... Need to improve this in the future
|
|
||||||
if (pair.getLeft() instanceof GameProfileArgument) {
|
|
||||||
Collection<GameProfile> profiles = GameProfileArgument.getGameProfiles(context, key);
|
|
||||||
List<BridgedGameProfile> bridgedGameProfiles = new ArrayList<>();
|
|
||||||
|
|
||||||
profiles.forEach(p -> bridgedGameProfiles.add(BridgedGameProfile.of(p)));
|
|
||||||
|
|
||||||
((TriConsumer<BridgedPlayer, List<BridgedGameProfile>, BridgedCommandSourceStack>) pair.getRight())
|
|
||||||
.accept(BridgedPlayer.of(context.getSource().getPlayer()), bridgedGameProfiles, BridgedCommandSourceStack.of(context.getSource()));
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
})));
|
|
||||||
|
|
||||||
dispatcher.register(command);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@@ -0,0 +1,31 @@
|
|||||||
|
package com.hypherionmc.craterlib.nojang.network.protocol.status;
|
||||||
|
|
||||||
|
import net.minecraft.network.protocol.status.ServerStatus;
|
||||||
|
import org.jetbrains.annotations.ApiStatus;
|
||||||
|
|
||||||
|
public final class WrappedServerStatus {
|
||||||
|
|
||||||
|
public static final class WrappedFavicon {
|
||||||
|
|
||||||
|
private final ServerStatus.Favicon internal;
|
||||||
|
|
||||||
|
public WrappedFavicon(byte[] iconBytes) {
|
||||||
|
internal = new ServerStatus.Favicon(iconBytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ApiStatus.Internal
|
||||||
|
public WrappedFavicon(ServerStatus.Favicon internal) {
|
||||||
|
this.internal = internal;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] iconBytes() {
|
||||||
|
return internal.iconBytes();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ServerStatus.Favicon toMojang() {
|
||||||
|
return internal;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -57,6 +57,11 @@ public class BridgedPlayer {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void disconnect(Component message) {
|
||||||
|
if (isServerPlayer())
|
||||||
|
toMojangServerPlayer().connection.disconnect(ChatUtils.adventureToMojang(message));
|
||||||
|
}
|
||||||
|
|
||||||
public ServerPlayer toMojangServerPlayer() {
|
public ServerPlayer toMojangServerPlayer() {
|
||||||
return (ServerPlayer) internal;
|
return (ServerPlayer) internal;
|
||||||
}
|
}
|
||||||
|
@@ -108,4 +108,11 @@ public class ChatUtils {
|
|||||||
return mojangToAdventure(Component.translatable(Util.makeDescriptionId("biome", identifier.toMojang())));
|
return mojangToAdventure(Component.translatable(Util.makeDescriptionId("biome", identifier.toMojang())));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static net.kyori.adventure.text.Component format(String value) {
|
||||||
|
return net.kyori.adventure.text.Component.translatable(convertFormattingCodes(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String convertFormattingCodes(String input) {
|
||||||
|
return input.replaceAll("§([0-9a-fklmnor])", "\u00A7$1");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -16,7 +16,8 @@
|
|||||||
"events.CommandMixin",
|
"events.CommandMixin",
|
||||||
"events.PlayerAdvancementsMixin",
|
"events.PlayerAdvancementsMixin",
|
||||||
"events.PlayerListMixin",
|
"events.PlayerListMixin",
|
||||||
"events.ServerPlayerMixin"
|
"events.ServerPlayerMixin",
|
||||||
|
"events.ServerStatusMixin"
|
||||||
],
|
],
|
||||||
"injectors": {
|
"injectors": {
|
||||||
"defaultRequire": 1
|
"defaultRequire": 1
|
||||||
|
@@ -113,8 +113,8 @@ publisher {
|
|||||||
setVersionType("release")
|
setVersionType("release")
|
||||||
setChangelog("https://raw.githubusercontent.com/hypherionmc/changelogs/main/craterlib/changelog-fabric.md")
|
setChangelog("https://raw.githubusercontent.com/hypherionmc/changelogs/main/craterlib/changelog-fabric.md")
|
||||||
setProjectVersion("${minecraft_version}-${project.version}")
|
setProjectVersion("${minecraft_version}-${project.version}")
|
||||||
setDisplayName("[FABRIC/QUILT 1.21.0] CraterLib - ${project.version}")
|
setDisplayName("[FABRIC/QUILT 1.21.x] CraterLib - ${project.version}")
|
||||||
setGameVersions("1.21")
|
setGameVersions("1.21", "1.21.1")
|
||||||
setLoaders("fabric", "quilt")
|
setLoaders("fabric", "quilt")
|
||||||
setArtifact(remapJar)
|
setArtifact(remapJar)
|
||||||
setCurseEnvironment("both")
|
setCurseEnvironment("both")
|
||||||
|
@@ -9,7 +9,6 @@ import com.hypherionmc.craterlib.core.networking.CraterPacketNetwork;
|
|||||||
import com.hypherionmc.craterlib.core.networking.data.PacketSide;
|
import com.hypherionmc.craterlib.core.networking.data.PacketSide;
|
||||||
import com.hypherionmc.craterlib.core.platform.ModloaderEnvironment;
|
import com.hypherionmc.craterlib.core.platform.ModloaderEnvironment;
|
||||||
import com.hypherionmc.craterlib.network.CraterFabricNetworkHandler;
|
import com.hypherionmc.craterlib.network.CraterFabricNetworkHandler;
|
||||||
import com.hypherionmc.craterlib.nojang.commands.CommandsRegistry;
|
|
||||||
import com.hypherionmc.craterlib.nojang.server.BridgedMinecraftServer;
|
import com.hypherionmc.craterlib.nojang.server.BridgedMinecraftServer;
|
||||||
import net.fabricmc.api.ModInitializer;
|
import net.fabricmc.api.ModInitializer;
|
||||||
import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback;
|
import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback;
|
||||||
@@ -21,8 +20,7 @@ public class CraterLibInitializer implements ModInitializer {
|
|||||||
public void onInitialize() {
|
public void onInitialize() {
|
||||||
new CraterPacketNetwork(new CraterFabricNetworkHandler(PacketSide.SERVER));
|
new CraterPacketNetwork(new CraterFabricNetworkHandler(PacketSide.SERVER));
|
||||||
CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> {
|
CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> {
|
||||||
CraterEventBus.INSTANCE.postEvent(new CraterRegisterCommandEvent());
|
CraterEventBus.INSTANCE.postEvent(new CraterRegisterCommandEvent(dispatcher));
|
||||||
CommandsRegistry.INSTANCE.registerCommands(dispatcher);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
@@ -2,7 +2,6 @@ package com.hypherionmc.craterlib;
|
|||||||
|
|
||||||
import com.hypherionmc.craterlib.client.gui.config.CraterConfigScreen;
|
import com.hypherionmc.craterlib.client.gui.config.CraterConfigScreen;
|
||||||
import com.hypherionmc.craterlib.core.config.ConfigController;
|
import com.hypherionmc.craterlib.core.config.ConfigController;
|
||||||
import com.hypherionmc.craterlib.core.config.ModuleConfig;
|
|
||||||
import com.hypherionmc.craterlib.core.config.annotations.NoConfigScreen;
|
import com.hypherionmc.craterlib.core.config.annotations.NoConfigScreen;
|
||||||
import com.terraformersmc.modmenu.api.ConfigScreenFactory;
|
import com.terraformersmc.modmenu.api.ConfigScreenFactory;
|
||||||
import com.terraformersmc.modmenu.api.ModMenuApi;
|
import com.terraformersmc.modmenu.api.ModMenuApi;
|
||||||
@@ -19,9 +18,9 @@ public class CraterLibModMenuIntegration implements ModMenuApi {
|
|||||||
public Map<String, ConfigScreenFactory<?>> getProvidedConfigScreenFactories() {
|
public Map<String, ConfigScreenFactory<?>> getProvidedConfigScreenFactories() {
|
||||||
Map<String, ConfigScreenFactory<?>> configScreens = new HashMap<>();
|
Map<String, ConfigScreenFactory<?>> configScreens = new HashMap<>();
|
||||||
|
|
||||||
ConfigController.getMonitoredConfigs().forEach((conf, watcher) -> {
|
ConfigController.getWatchedConfigs().forEach((conf, watcher) -> {
|
||||||
if (!conf.getClass().isAnnotationPresent(NoConfigScreen.class)) {
|
if (!conf.getClass().isAnnotationPresent(NoConfigScreen.class)) {
|
||||||
configScreens.put(((ModuleConfig) conf).getModId(), screen -> new CraterConfigScreen((ModuleConfig) conf, screen));
|
configScreens.put(watcher.getLeft().getModId(), screen -> new CraterConfigScreen(watcher.getLeft(), screen));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@@ -27,8 +27,8 @@ public class ServerGamePacketListenerImplMixin {
|
|||||||
cancellable = true
|
cancellable = true
|
||||||
)
|
)
|
||||||
private void injectChatEvent(PlayerChatMessage arg, Component arg2, FilteredText arg3, CallbackInfo ci) {
|
private void injectChatEvent(PlayerChatMessage arg, Component arg2, FilteredText arg3, CallbackInfo ci) {
|
||||||
Component finalArg = arg2 == null ? arg.decoratedContent() : arg2;
|
Component finalcomp = arg2 == null ? arg.decoratedContent() : arg2;
|
||||||
CraterServerChatEvent event = new CraterServerChatEvent(BridgedPlayer.of(this.player), finalArg.getString(), ChatUtils.mojangToAdventure(finalArg));
|
CraterServerChatEvent event = new CraterServerChatEvent(BridgedPlayer.of(this.player), finalcomp.getString(), ChatUtils.mojangToAdventure(finalcomp));
|
||||||
CraterEventBus.INSTANCE.postEvent(event);
|
CraterEventBus.INSTANCE.postEvent(event);
|
||||||
if (event.wasCancelled())
|
if (event.wasCancelled())
|
||||||
ci.cancel();
|
ci.cancel();
|
||||||
|
@@ -0,0 +1,52 @@
|
|||||||
|
package com.hypherionmc.craterlib.mixin;
|
||||||
|
|
||||||
|
import com.hypherionmc.craterlib.api.events.server.ServerStatusEvent;
|
||||||
|
import com.hypherionmc.craterlib.core.event.CraterEventBus;
|
||||||
|
import com.hypherionmc.craterlib.utils.ChatUtils;
|
||||||
|
import net.minecraft.network.Connection;
|
||||||
|
import net.minecraft.network.protocol.status.ClientboundStatusResponsePacket;
|
||||||
|
import net.minecraft.network.protocol.status.ServerStatus;
|
||||||
|
import net.minecraft.network.protocol.status.ServerboundStatusRequestPacket;
|
||||||
|
import net.minecraft.server.network.ServerStatusPacketListenerImpl;
|
||||||
|
import org.spongepowered.asm.mixin.Final;
|
||||||
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.Shadow;
|
||||||
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
|
import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||||
|
|
||||||
|
@Mixin(ServerStatusPacketListenerImpl.class)
|
||||||
|
public class ServerStatusPacketListenerMixin {
|
||||||
|
|
||||||
|
@Shadow
|
||||||
|
@Final
|
||||||
|
private ServerStatus status;
|
||||||
|
|
||||||
|
@Shadow @Final private Connection connection;
|
||||||
|
|
||||||
|
@Inject(method = "handleStatusRequest",
|
||||||
|
at = @At(
|
||||||
|
value = "INVOKE",
|
||||||
|
target = "Lnet/minecraft/network/Connection;send(Lnet/minecraft/network/protocol/Packet;)V",
|
||||||
|
shift = At.Shift.BEFORE),
|
||||||
|
cancellable = true
|
||||||
|
)
|
||||||
|
private void injectHandleStatusRequest(ServerboundStatusRequestPacket arg, CallbackInfo ci) {
|
||||||
|
ServerStatusEvent.StatusRequestEvent event = new ServerStatusEvent.StatusRequestEvent(ChatUtils.mojangToAdventure(status.description()));
|
||||||
|
CraterEventBus.INSTANCE.postEvent(event);
|
||||||
|
|
||||||
|
if (event.getNewStatus() != null) {
|
||||||
|
ci.cancel();
|
||||||
|
this.connection.send(new ClientboundStatusResponsePacket(
|
||||||
|
new ServerStatus(ChatUtils.adventureToMojang(
|
||||||
|
event.getNewStatus()),
|
||||||
|
status.players(),
|
||||||
|
status.version(),
|
||||||
|
status.favicon(),
|
||||||
|
status.enforcesSecureChat()
|
||||||
|
)
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -9,7 +9,8 @@
|
|||||||
"TutorialMixin"
|
"TutorialMixin"
|
||||||
],
|
],
|
||||||
"server": [
|
"server": [
|
||||||
"ServerGamePacketListenerImplMixin"
|
"ServerGamePacketListenerImplMixin",
|
||||||
|
"ServerStatusPacketListenerMixin"
|
||||||
],
|
],
|
||||||
"injectors": {
|
"injectors": {
|
||||||
"defaultRequire": 1
|
"defaultRequire": 1
|
||||||
|
@@ -27,8 +27,8 @@ public class ServerGamePacketListenerImplMixin {
|
|||||||
cancellable = true
|
cancellable = true
|
||||||
)
|
)
|
||||||
private void injectChatEvent(Component component, PlayerChatMessage arg, FilteredText p_296589_, CallbackInfo ci) {
|
private void injectChatEvent(Component component, PlayerChatMessage arg, FilteredText p_296589_, CallbackInfo ci) {
|
||||||
Component finalArg = component == null ? arg.decoratedContent() : component;
|
Component finalcomp = component == null ? arg.decoratedContent() : component;
|
||||||
CraterServerChatEvent event = new CraterServerChatEvent(BridgedPlayer.of(this.player), finalArg.getString(), ChatUtils.mojangToAdventure(finalArg));
|
CraterServerChatEvent event = new CraterServerChatEvent(BridgedPlayer.of(this.player), finalcomp.getString(), ChatUtils.mojangToAdventure(finalcomp));
|
||||||
CraterEventBus.INSTANCE.postEvent(event);
|
CraterEventBus.INSTANCE.postEvent(event);
|
||||||
if (event.wasCancelled())
|
if (event.wasCancelled())
|
||||||
ci.cancel();
|
ci.cancel();
|
||||||
|
@@ -0,0 +1,53 @@
|
|||||||
|
package com.hypherionmc.craterlib.mixin;
|
||||||
|
|
||||||
|
import com.hypherionmc.craterlib.api.events.server.ServerStatusEvent;
|
||||||
|
import com.hypherionmc.craterlib.core.event.CraterEventBus;
|
||||||
|
import com.hypherionmc.craterlib.utils.ChatUtils;
|
||||||
|
import net.minecraft.network.Connection;
|
||||||
|
import net.minecraft.network.protocol.status.ClientboundStatusResponsePacket;
|
||||||
|
import net.minecraft.network.protocol.status.ServerStatus;
|
||||||
|
import net.minecraft.network.protocol.status.ServerboundStatusRequestPacket;
|
||||||
|
import net.minecraft.server.network.ServerStatusPacketListenerImpl;
|
||||||
|
import org.spongepowered.asm.mixin.Final;
|
||||||
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.Shadow;
|
||||||
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
|
import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||||
|
|
||||||
|
@Mixin(ServerStatusPacketListenerImpl.class)
|
||||||
|
public class ServerStatusPacketListenerMixin {
|
||||||
|
|
||||||
|
@Shadow
|
||||||
|
@Final
|
||||||
|
private ServerStatus status;
|
||||||
|
|
||||||
|
@Shadow @Final private Connection connection;
|
||||||
|
|
||||||
|
@Inject(method = "handleStatusRequest",
|
||||||
|
at = @At(
|
||||||
|
value = "INVOKE",
|
||||||
|
target = "Lnet/minecraft/network/Connection;send(Lnet/minecraft/network/protocol/Packet;)V",
|
||||||
|
shift = At.Shift.BEFORE),
|
||||||
|
cancellable = true
|
||||||
|
)
|
||||||
|
private void injectHandleStatusRequest(ServerboundStatusRequestPacket arg, CallbackInfo ci) {
|
||||||
|
ServerStatusEvent.StatusRequestEvent event = new ServerStatusEvent.StatusRequestEvent(ChatUtils.mojangToAdventure(status.description()));
|
||||||
|
CraterEventBus.INSTANCE.postEvent(event);
|
||||||
|
|
||||||
|
if (event.getNewStatus() != null) {
|
||||||
|
ci.cancel();
|
||||||
|
this.connection.send(new ClientboundStatusResponsePacket(
|
||||||
|
new ServerStatus(ChatUtils.adventureToMojang(
|
||||||
|
event.getNewStatus()),
|
||||||
|
status.players(),
|
||||||
|
status.version(),
|
||||||
|
status.favicon(),
|
||||||
|
status.enforcesSecureChat(),
|
||||||
|
status.isModded()
|
||||||
|
)
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -9,7 +9,8 @@
|
|||||||
"ConfigScreenHandlerMixin"
|
"ConfigScreenHandlerMixin"
|
||||||
],
|
],
|
||||||
"server": [
|
"server": [
|
||||||
"ServerGamePacketListenerImplMixin"
|
"ServerGamePacketListenerImplMixin",
|
||||||
|
"ServerStatusPacketListenerMixin"
|
||||||
],
|
],
|
||||||
"injectors": {
|
"injectors": {
|
||||||
"defaultRequire": 1
|
"defaultRequire": 1
|
||||||
|
@@ -106,8 +106,8 @@ publisher {
|
|||||||
setVersionType("release")
|
setVersionType("release")
|
||||||
setChangelog("https://raw.githubusercontent.com/hypherionmc/changelogs/main/craterlib/changelog-forge.md")
|
setChangelog("https://raw.githubusercontent.com/hypherionmc/changelogs/main/craterlib/changelog-forge.md")
|
||||||
setProjectVersion("${minecraft_version}-${project.version}")
|
setProjectVersion("${minecraft_version}-${project.version}")
|
||||||
setDisplayName("[NeoForge 1.21.0] CraterLib - ${project.version}")
|
setDisplayName("[NeoForge 1.21.x] CraterLib - ${project.version}")
|
||||||
setGameVersions("1.21")
|
setGameVersions("1.21", "1.21.1")
|
||||||
setLoaders("neoforge")
|
setLoaders("neoforge")
|
||||||
setArtifact(remapJar)
|
setArtifact(remapJar)
|
||||||
setCurseEnvironment("both")
|
setCurseEnvironment("both")
|
||||||
|
@@ -2,8 +2,8 @@ package com.hypherionmc.craterlib.client;
|
|||||||
|
|
||||||
import com.hypherionmc.craterlib.api.events.client.LateInitEvent;
|
import com.hypherionmc.craterlib.api.events.client.LateInitEvent;
|
||||||
import com.hypherionmc.craterlib.client.gui.config.CraterConfigScreen;
|
import com.hypherionmc.craterlib.client.gui.config.CraterConfigScreen;
|
||||||
|
import com.hypherionmc.craterlib.core.config.AbstractConfig;
|
||||||
import com.hypherionmc.craterlib.core.config.ConfigController;
|
import com.hypherionmc.craterlib.core.config.ConfigController;
|
||||||
import com.hypherionmc.craterlib.core.config.ModuleConfig;
|
|
||||||
import com.hypherionmc.craterlib.core.config.annotations.NoConfigScreen;
|
import com.hypherionmc.craterlib.core.config.annotations.NoConfigScreen;
|
||||||
import com.hypherionmc.craterlib.core.event.CraterEventBus;
|
import com.hypherionmc.craterlib.core.event.CraterEventBus;
|
||||||
import com.hypherionmc.craterlib.core.platform.ClientPlatform;
|
import com.hypherionmc.craterlib.core.platform.ClientPlatform;
|
||||||
@@ -51,9 +51,9 @@ public class NeoForgeClientHelper implements ClientPlatform {
|
|||||||
LateInitEvent event = new LateInitEvent(new BridgedMinecraft(), BridgedOptions.of(Minecraft.getInstance().options));
|
LateInitEvent event = new LateInitEvent(new BridgedMinecraft(), BridgedOptions.of(Minecraft.getInstance().options));
|
||||||
CraterEventBus.INSTANCE.postEvent(event);
|
CraterEventBus.INSTANCE.postEvent(event);
|
||||||
|
|
||||||
ConfigController.getMonitoredConfigs().forEach((conf, watcher) -> {
|
ConfigController.getWatchedConfigs().forEach((conf, watcher) -> {
|
||||||
if (!conf.getClass().isAnnotationPresent(NoConfigScreen.class)) {
|
if (!conf.getClass().isAnnotationPresent(NoConfigScreen.class)) {
|
||||||
ModuleConfig config = (ModuleConfig) conf;
|
AbstractConfig config = watcher.getLeft();
|
||||||
ModList.get().getModContainerById(config.getModId()).ifPresent(c -> c.registerExtensionPoint(IConfigScreenFactory.class, ((minecraft, screen) -> new CraterConfigScreen(config, screen))));
|
ModList.get().getModContainerById(config.getModId()).ifPresent(c -> c.registerExtensionPoint(IConfigScreenFactory.class, ((minecraft, screen) -> new CraterConfigScreen(config, screen))));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@@ -3,7 +3,6 @@ package com.hypherionmc.craterlib.common;
|
|||||||
import com.hypherionmc.craterlib.api.events.server.CraterRegisterCommandEvent;
|
import com.hypherionmc.craterlib.api.events.server.CraterRegisterCommandEvent;
|
||||||
import com.hypherionmc.craterlib.api.events.server.CraterServerLifecycleEvent;
|
import com.hypherionmc.craterlib.api.events.server.CraterServerLifecycleEvent;
|
||||||
import com.hypherionmc.craterlib.core.event.CraterEventBus;
|
import com.hypherionmc.craterlib.core.event.CraterEventBus;
|
||||||
import com.hypherionmc.craterlib.nojang.commands.CommandsRegistry;
|
|
||||||
import com.hypherionmc.craterlib.nojang.server.BridgedMinecraftServer;
|
import com.hypherionmc.craterlib.nojang.server.BridgedMinecraftServer;
|
||||||
import net.neoforged.bus.api.SubscribeEvent;
|
import net.neoforged.bus.api.SubscribeEvent;
|
||||||
import net.neoforged.neoforge.event.RegisterCommandsEvent;
|
import net.neoforged.neoforge.event.RegisterCommandsEvent;
|
||||||
@@ -36,8 +35,7 @@ public class NeoForgeServerEvents {
|
|||||||
|
|
||||||
@SubscribeEvent
|
@SubscribeEvent
|
||||||
public void onCommandRegister(RegisterCommandsEvent event) {
|
public void onCommandRegister(RegisterCommandsEvent event) {
|
||||||
CraterEventBus.INSTANCE.postEvent(new CraterRegisterCommandEvent());
|
CraterEventBus.INSTANCE.postEvent(new CraterRegisterCommandEvent(event.getDispatcher()));
|
||||||
CommandsRegistry.INSTANCE.registerCommands(event.getDispatcher());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -27,8 +27,8 @@ public class ServerGamePacketListenerImplMixin {
|
|||||||
cancellable = true
|
cancellable = true
|
||||||
)
|
)
|
||||||
private void injectChatEvent(Component component, PlayerChatMessage arg, FilteredText p_296589_, CallbackInfo ci) {
|
private void injectChatEvent(Component component, PlayerChatMessage arg, FilteredText p_296589_, CallbackInfo ci) {
|
||||||
Component finalArg = component == null ? arg.decoratedContent() : component;
|
Component finalcomp = component == null ? arg.decoratedContent() : component;
|
||||||
CraterServerChatEvent event = new CraterServerChatEvent(BridgedPlayer.of(this.player), finalArg.getString(), ChatUtils.mojangToAdventure(finalArg));
|
CraterServerChatEvent event = new CraterServerChatEvent(BridgedPlayer.of(this.player), finalcomp.getString(), ChatUtils.mojangToAdventure(finalcomp));
|
||||||
CraterEventBus.INSTANCE.postEvent(event);
|
CraterEventBus.INSTANCE.postEvent(event);
|
||||||
if (event.wasCancelled())
|
if (event.wasCancelled())
|
||||||
ci.cancel();
|
ci.cancel();
|
||||||
|
@@ -0,0 +1,53 @@
|
|||||||
|
package com.hypherionmc.craterlib.mixin;
|
||||||
|
|
||||||
|
import com.hypherionmc.craterlib.api.events.server.ServerStatusEvent;
|
||||||
|
import com.hypherionmc.craterlib.core.event.CraterEventBus;
|
||||||
|
import com.hypherionmc.craterlib.utils.ChatUtils;
|
||||||
|
import net.minecraft.network.Connection;
|
||||||
|
import net.minecraft.network.protocol.status.ClientboundStatusResponsePacket;
|
||||||
|
import net.minecraft.network.protocol.status.ServerStatus;
|
||||||
|
import net.minecraft.network.protocol.status.ServerboundStatusRequestPacket;
|
||||||
|
import net.minecraft.server.network.ServerStatusPacketListenerImpl;
|
||||||
|
import org.spongepowered.asm.mixin.Final;
|
||||||
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.Shadow;
|
||||||
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
|
import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||||
|
|
||||||
|
@Mixin(ServerStatusPacketListenerImpl.class)
|
||||||
|
public class ServerStatusPacketListenerMixin {
|
||||||
|
|
||||||
|
@Shadow
|
||||||
|
@Final
|
||||||
|
private ServerStatus status;
|
||||||
|
|
||||||
|
@Shadow @Final private Connection connection;
|
||||||
|
|
||||||
|
@Inject(method = "handleStatusRequest",
|
||||||
|
at = @At(
|
||||||
|
value = "INVOKE",
|
||||||
|
target = "Lnet/minecraft/network/Connection;send(Lnet/minecraft/network/protocol/Packet;)V",
|
||||||
|
shift = At.Shift.BEFORE),
|
||||||
|
cancellable = true
|
||||||
|
)
|
||||||
|
private void injectHandleStatusRequest(ServerboundStatusRequestPacket arg, CallbackInfo ci) {
|
||||||
|
ServerStatusEvent.StatusRequestEvent event = new ServerStatusEvent.StatusRequestEvent(ChatUtils.mojangToAdventure(status.description()));
|
||||||
|
CraterEventBus.INSTANCE.postEvent(event);
|
||||||
|
|
||||||
|
if (event.getNewStatus() != null) {
|
||||||
|
ci.cancel();
|
||||||
|
this.connection.send(new ClientboundStatusResponsePacket(
|
||||||
|
new ServerStatus(ChatUtils.adventureToMojang(
|
||||||
|
event.getNewStatus()),
|
||||||
|
status.players(),
|
||||||
|
status.version(),
|
||||||
|
status.favicon(),
|
||||||
|
status.enforcesSecureChat(),
|
||||||
|
status.isModded()
|
||||||
|
)
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -7,7 +7,8 @@
|
|||||||
],
|
],
|
||||||
"client": [],
|
"client": [],
|
||||||
"server": [
|
"server": [
|
||||||
"ServerGamePacketListenerImplMixin"
|
"ServerGamePacketListenerImplMixin",
|
||||||
|
"ServerStatusPacketListenerMixin"
|
||||||
],
|
],
|
||||||
"injectors": {
|
"injectors": {
|
||||||
"defaultRequire": 1
|
"defaultRequire": 1
|
||||||
|
@@ -16,7 +16,7 @@ A Library mod and modding api for easier multi-version minecraft and mod loader
|
|||||||
| 1.18.2-1.20.2 | ✳️ |
|
| 1.18.2-1.20.2 | ✳️ |
|
||||||
| 1.20.4 | ✳️ |
|
| 1.20.4 | ✳️ |
|
||||||
| 1.20.6 | ❌ |
|
| 1.20.6 | ❌ |
|
||||||
| 1.21 | ✳️ |
|
| 1.21.x | ✳️ |
|
||||||
|
|
||||||
- ❌ - Not Supported; no bug fixes or new features.
|
- ❌ - Not Supported; no bug fixes or new features.
|
||||||
- 🚧 - Work in Progress; not ready for release.
|
- 🚧 - Work in Progress; not ready for release.
|
||||||
|
@@ -57,11 +57,13 @@ subprojects {
|
|||||||
// All Projects
|
// All Projects
|
||||||
shade "me.hypherionmc.moon-config:core:${moon_config}"
|
shade "me.hypherionmc.moon-config:core:${moon_config}"
|
||||||
shade "me.hypherionmc.moon-config:toml:${moon_config}"
|
shade "me.hypherionmc.moon-config:toml:${moon_config}"
|
||||||
|
shade "me.hypherionmc.moon-config:json:${moon_config}"
|
||||||
shade "com.hypherionmc:rpcsdk:${rpc_sdk}"
|
shade "com.hypherionmc:rpcsdk:${rpc_sdk}"
|
||||||
shade "me.hypherionmc.sdlink:mcdiscordformatter-1.20.3:${discord_formatter}"
|
shade "me.hypherionmc.sdlink:mcdiscordformatter-1.20.3:${discord_formatter}"
|
||||||
shade "net.kyori:adventure-api:${adventure}"
|
shade "net.kyori:adventure-api:${adventure}"
|
||||||
shade "net.kyori:adventure-text-serializer-gson:${adventure}"
|
shade "net.kyori:adventure-text-serializer-gson:${adventure}"
|
||||||
|
|
||||||
|
compileOnly 'net.luckperms:api:5.4'
|
||||||
compileOnly("org.projectlombok:lombok:${lombok}")
|
compileOnly("org.projectlombok:lombok:${lombok}")
|
||||||
annotationProcessor("org.projectlombok:lombok:${lombok}")
|
annotationProcessor("org.projectlombok:lombok:${lombok}")
|
||||||
}
|
}
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
#Project
|
#Project
|
||||||
version_major=2
|
version_major=2
|
||||||
version_minor=0
|
version_minor=1
|
||||||
version_patch=3
|
version_patch=0
|
||||||
version_build=0
|
version_build=0
|
||||||
|
|
||||||
#Mod
|
#Mod
|
||||||
|
Reference in New Issue
Block a user