From 70e94de967ecfccf5d54afda9d74754f49b82eb1 Mon Sep 17 00:00:00 2001 From: Chipmunk <65827213+ChipmunkMC@users.noreply.github.com> Date: Tue, 9 May 2023 22:58:42 -0400 Subject: [PATCH] it works i guess --- build.gradle | 2 +- gradle.properties | 6 +- .../chipmunk/infocommands/InfoCommands.java | 123 ++++++++++++++++++ .../mixin/CommandManagerMixin.java | 23 ++++ .../java/net/fabricmc/example/ExampleMod.java | 21 --- .../fabricmc/example/mixin/ExampleMixin.java | 16 --- src/main/resources/fabric.mod.json | 19 ++- ...d.mixins.json => infocommands.mixins.json} | 6 +- 8 files changed, 161 insertions(+), 55 deletions(-) create mode 100644 src/main/java/land/chipmunk/infocommands/InfoCommands.java create mode 100644 src/main/java/land/chipmunk/infocommands/mixin/CommandManagerMixin.java delete mode 100644 src/main/java/net/fabricmc/example/ExampleMod.java delete mode 100644 src/main/java/net/fabricmc/example/mixin/ExampleMixin.java rename src/main/resources/{modid.mixins.json => infocommands.mixins.json} (64%) diff --git a/build.gradle b/build.gradle index b6cb6c0..3f25fab 100644 --- a/build.gradle +++ b/build.gradle @@ -21,7 +21,7 @@ dependencies { modImplementation "net.fabricmc:fabric-loader:${project.loader_version}" // Fabric API. This is technically optional, but you probably want it anyway. - modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}" + // modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}" // Uncomment the following line to enable the deprecated Fabric API modules. // These are included in the Fabric API production distribution and allow you to update your mod to the latest modules at a later more convenient time. diff --git a/gradle.properties b/gradle.properties index d9f5bbe..2c1937e 100644 --- a/gradle.properties +++ b/gradle.properties @@ -9,9 +9,9 @@ org.gradle.parallel=true loader_version=0.14.19 # Mod Properties - mod_version = 1.0.0 - maven_group = com.example - archives_base_name = fabric-example-mod + mod_version = rolling + maven_group = land.chipmunk + archives_base_name = infocommands # Dependencies fabric_version=0.79.0+1.19.4 diff --git a/src/main/java/land/chipmunk/infocommands/InfoCommands.java b/src/main/java/land/chipmunk/infocommands/InfoCommands.java new file mode 100644 index 0000000..da071e1 --- /dev/null +++ b/src/main/java/land/chipmunk/infocommands/InfoCommands.java @@ -0,0 +1,123 @@ +package land.chipmunk.infocommands; + +import net.fabricmc.api.ModInitializer; +import net.fabricmc.loader.api.FabricLoader; +import net.fabricmc.loader.api.ModContainer; +import net.fabricmc.loader.api.metadata.ModMetadata; +import net.fabricmc.loader.api.metadata.Person; +import net.minecraft.server.command.ServerCommandSource; +import com.mojang.brigadier.Command; +import com.mojang.brigadier.CommandDispatcher; +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import com.mojang.brigadier.exceptions.DynamicCommandExceptionType; +import com.mojang.brigadier.context.CommandContext; +import com.mojang.brigadier.tree.LiteralCommandNode; +import static net.minecraft.server.command.CommandManager.literal; +import static net.minecraft.server.command.CommandManager.argument; +import static com.mojang.brigadier.arguments.StringArgumentType.word; +import static com.mojang.brigadier.arguments.StringArgumentType.getString; +import net.minecraft.text.Text; +import net.minecraft.text.MutableText; +import net.minecraft.util.Formatting; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import java.util.Optional; +import java.util.Collection; + +public class InfoCommands implements ModInitializer { + // public static final Logger LOGGER = LoggerFactory.getLogger("infocommands"); + private static final DynamicCommandExceptionType UNKNOWN_MOD_EXCEPTION = new DynamicCommandExceptionType(modid -> Text.literal("Unable to find mod '").append(String.valueOf(modid)).append(Text.literal("'"))); + + @Override + public void onInitialize() { + } + + public static void registerCommands (CommandDispatcher dispatcher) { + final LiteralCommandNode modsNode = dispatcher.register(literal("mods").executes(InfoCommands::listMods)); + dispatcher.register(literal("plugins").executes(InfoCommands::listMods).redirect(modsNode)); + dispatcher.register(literal("pl").executes(InfoCommands::listMods).redirect(modsNode)); + + final LiteralCommandNode versionNode = dispatcher.register( + literal("version") + .executes(InfoCommands::sendVersion) + .then( + argument("mod", word()) + .executes(InfoCommands::sendModInfo) + ) + ); + dispatcher.register(literal("ver").executes(InfoCommands::sendVersion).redirect(versionNode)); + dispatcher.register(literal("about").executes(InfoCommands::sendVersion).redirect(versionNode)); + } + + public static int listMods (CommandContext context) { + final MutableText output = Text.literal("Mods: "); + + for (ModContainer container : FabricLoader.getInstance().getAllMods()) { + final ModMetadata metadata = container.getMetadata(); + if (metadata.getType().equals("builtin")) continue; + if (output.getSiblings().size() != 0) output.append(Text.literal(", ")); + + String name = metadata.getName(); + if (name == null) name = metadata.getId(); + + output.append(Text.literal(name).formatted(Formatting.GREEN)); + } + + context.getSource().sendFeedback(output, false); + return Command.SINGLE_SUCCESS; + } + + public static int sendVersion (CommandContext context) { + final FabricLoader loader = FabricLoader.getInstance(); + + final ModContainer minecraftContainer = loader.getModContainer("minecraft").get(); + final ModContainer loaderContainer = loader.getModContainer("fabricloader").get(); + + context.getSource().sendFeedback( + Text.literal("This server is running Fabric Loader version ") + .append(Text.literal(loaderContainer.getMetadata().getVersion().toString())) + .append(Text.literal(" (on MC ")) + .append(Text.literal(minecraftContainer.getMetadata().getVersion().toString())) + .append(Text.literal(")")) + , false); + + return Command.SINGLE_SUCCESS; + } + + public static int sendModInfo (CommandContext context) throws CommandSyntaxException { + final FabricLoader loader = FabricLoader.getInstance(); + + final String modid = getString(context, "mod"); + final Optional optional = loader.getModContainer(modid); + if (!optional.isPresent()) throw UNKNOWN_MOD_EXCEPTION.create(modid); + + final ModContainer container = optional.get(); + final ModMetadata metadata = container.getMetadata(); + + final MutableText output = Text.literal(metadata.getName()) + .append(Text.literal(" version ")) + .append(Text.literal(metadata.getVersion().toString())); + + final String description = metadata.getDescription(); + if (!description.isEmpty()) { + output.append(Text.literal("\n")); + output.append(Text.literal(description)); + } + + final Collection authors = metadata.getAuthors(); + if (authors.size() != 0) { + final MutableText list = Text.literal("\nAuthors: "); + + for (Person person : authors) { + if (list.getSiblings().size() != 0) list.append(Text.literal(", ").formatted(Formatting.GRAY)); + list.append(Text.literal(person.getName())); + } + + output.append(list); + } + + context.getSource().sendFeedback(output, false); + + return Command.SINGLE_SUCCESS; + } +} diff --git a/src/main/java/land/chipmunk/infocommands/mixin/CommandManagerMixin.java b/src/main/java/land/chipmunk/infocommands/mixin/CommandManagerMixin.java new file mode 100644 index 0000000..a85a244 --- /dev/null +++ b/src/main/java/land/chipmunk/infocommands/mixin/CommandManagerMixin.java @@ -0,0 +1,23 @@ +package land.chipmunk.infocommands.mixin; + +import land.chipmunk.infocommands.InfoCommands; +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; +import net.minecraft.server.command.CommandManager; +import net.minecraft.server.command.ServerCommandSource; +import net.minecraft.command.CommandRegistryAccess; +import com.mojang.brigadier.CommandDispatcher; + +@Mixin(CommandManager.class) +public abstract class CommandManagerMixin { + @Shadow + private CommandDispatcher dispatcher; + + @Inject(at = @At(value = "INVOKE", target = "Lcom/mojang/brigadier/CommandDispatcher;setConsumer(Lcom/mojang/brigadier/ResultConsumer;)V", remap = false), method = "") + private void init (CommandManager.RegistrationEnvironment environment, CommandRegistryAccess commandRegistryAccess, CallbackInfo info) { + InfoCommands.registerCommands(dispatcher); + } +} diff --git a/src/main/java/net/fabricmc/example/ExampleMod.java b/src/main/java/net/fabricmc/example/ExampleMod.java deleted file mode 100644 index a964189..0000000 --- a/src/main/java/net/fabricmc/example/ExampleMod.java +++ /dev/null @@ -1,21 +0,0 @@ -package net.fabricmc.example; - -import net.fabricmc.api.ModInitializer; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class ExampleMod implements ModInitializer { - // This logger is used to write text to the console and the log file. - // It is considered best practice to use your mod id as the logger's name. - // That way, it's clear which mod wrote info, warnings, and errors. - public static final Logger LOGGER = LoggerFactory.getLogger("modid"); - - @Override - public void onInitialize() { - // This code runs as soon as Minecraft is in a mod-load-ready state. - // However, some things (like resources) may still be uninitialized. - // Proceed with mild caution. - - LOGGER.info("Hello Fabric world!"); - } -} diff --git a/src/main/java/net/fabricmc/example/mixin/ExampleMixin.java b/src/main/java/net/fabricmc/example/mixin/ExampleMixin.java deleted file mode 100644 index 356cb38..0000000 --- a/src/main/java/net/fabricmc/example/mixin/ExampleMixin.java +++ /dev/null @@ -1,16 +0,0 @@ -package net.fabricmc.example.mixin; - -import net.fabricmc.example.ExampleMod; -import net.minecraft.client.gui.screen.TitleScreen; -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.CallbackInfo; - -@Mixin(TitleScreen.class) -public class ExampleMixin { - @Inject(at = @At("HEAD"), method = "init()V") - private void init(CallbackInfo info) { - ExampleMod.LOGGER.info("This line is printed by an example mod mixin!"); - } -} diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index e2176c7..3d6d775 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -1,16 +1,16 @@ { "schemaVersion": 1, - "id": "modid", - "version": "${version}", + "id": "infocommands", + "version": "rolling", - "name": "Example Mod", - "description": "This is an example description! Tell everyone what your mod is about!", + "name": "infocommands", + "description": "A simple fabric mod that adds bukkit-style server info commands", "authors": [ - "Me!" + "_ChipMC_" ], "contact": { - "homepage": "https://fabricmc.net/", - "sources": "https://github.com/FabricMC/fabric-example-mod" + "homepage": "https://code.chipmunk.land/ChipmunkMC/infocommands", + "sources": "https://code.chipmunk.land/ChipmunkMC/infocommands" }, "license": "CC0-1.0", @@ -19,16 +19,15 @@ "environment": "*", "entrypoints": { "main": [ - "net.fabricmc.example.ExampleMod" + "land.chipmunk.infocommands.InfoCommands" ] }, "mixins": [ - "modid.mixins.json" + "infocommands.mixins.json" ], "depends": { "fabricloader": ">=0.14.19", - "fabric-api": "*", "minecraft": "~1.19.4", "java": ">=17" }, diff --git a/src/main/resources/modid.mixins.json b/src/main/resources/infocommands.mixins.json similarity index 64% rename from src/main/resources/modid.mixins.json rename to src/main/resources/infocommands.mixins.json index 7c42cb4..45119da 100644 --- a/src/main/resources/modid.mixins.json +++ b/src/main/resources/infocommands.mixins.json @@ -1,12 +1,10 @@ { "required": true, "minVersion": "0.8", - "package": "net.fabricmc.example.mixin", + "package": "land.chipmunk.infocommands.mixin", "compatibilityLevel": "JAVA_17", "mixins": [ - ], - "client": [ - "ExampleMixin" + "CommandManagerMixin" ], "injectors": { "defaultRequire": 1