diff --git a/src/main/java/land/chipmunk/chipmunkmod/ChipmunkMod.java b/src/main/java/land/chipmunk/chipmunkmod/ChipmunkMod.java index 243db66..211140b 100644 --- a/src/main/java/land/chipmunk/chipmunkmod/ChipmunkMod.java +++ b/src/main/java/land/chipmunk/chipmunkmod/ChipmunkMod.java @@ -1,5 +1,7 @@ package land.chipmunk.chipmunkmod; +import com.google.gson.GsonBuilder; +import land.chipmunk.chipmunkmod.util.gson.BlockPosTypeAdapter; import net.fabricmc.api.ModInitializer; import java.io.InputStream; import java.io.FileInputStream; @@ -9,6 +11,8 @@ import java.io.BufferedWriter; import java.io.File; import java.io.FileWriter; import java.io.IOException; + +import net.minecraft.util.math.BlockPos; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.google.gson.Gson; @@ -40,7 +44,9 @@ public class ChipmunkMod implements ModInitializer { private static Configuration loadConfig () throws IOException { CONFIG_DIR.mkdirs(); - final Gson gson = new Gson(); + final Gson gson = new GsonBuilder() + .registerTypeAdapter(BlockPos.class, new BlockPosTypeAdapter()) + .create(); final File file = CONFIG_FILE; if (!file.exists()) { diff --git a/src/main/java/land/chipmunk/chipmunkmod/command/CommandManager.java b/src/main/java/land/chipmunk/chipmunkmod/command/CommandManager.java index 79e155c..6e32ad1 100644 --- a/src/main/java/land/chipmunk/chipmunkmod/command/CommandManager.java +++ b/src/main/java/land/chipmunk/chipmunkmod/command/CommandManager.java @@ -11,16 +11,36 @@ import net.minecraft.text.Text; import net.minecraft.text.Texts; import net.minecraft.text.MutableText; import net.minecraft.util.Formatting; +import net.minecraft.command.CommandRegistryAccess; import net.minecraft.client.MinecraftClient; import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource; -import land.chipmunk.chipmunkmod.ChipmunkMod; import land.chipmunk.chipmunkmod.commands.*; public class CommandManager { - public static CommandDispatcher dispatcher = new CommandDispatcher<>(); - public static String prefix = ChipmunkMod.CONFIG.commands.prefix; + public CommandDispatcher dispatcher = new CommandDispatcher<>(); + public String prefix; - public static void executeCommand (String command) { + public static CommandManager INSTANCE; + + public CommandManager (String prefix, CommandRegistryAccess commandRegistryAccess) { + this.prefix = prefix; + + TestCommand.register(this.dispatcher); + CoreCommand.register(this.dispatcher); + UsernameCommand.register(this.dispatcher); + CloopCommand.register(this.dispatcher); + ValidateCommand.register(this.dispatcher); + ItemCommand.register(this.dispatcher, commandRegistryAccess); + CustomChatCommand.register(this.dispatcher); + EvalCommand.register(this.dispatcher); + FullBrightCommand.register(this.dispatcher); + MusicCommand.register(this.dispatcher); + RainbowNameCommand.register(this.dispatcher); + SayCommand.register(this.dispatcher); + SelfCareCommand.register(this.dispatcher); + } + + public void executeCommand (String command) { final MinecraftClient client = MinecraftClient.getInstance(); final FabricClientCommandSource commandSource = (FabricClientCommandSource) client.getNetworkHandler().getCommandSource(); @@ -38,7 +58,7 @@ public class CommandManager { } } - public static Text getContext (CommandSyntaxException exception) { + public Text getContext (CommandSyntaxException exception) { final int _cursor = exception.getCursor(); final String input = exception.getInput(); @@ -46,7 +66,7 @@ public class CommandManager { return null; } final MutableText text = Text.literal("") - .formatted(Formatting.GRAY); + .formatted(Formatting.GRAY); text.setStyle(text.getStyle().withClickEvent(new ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, prefix + input))); final int cursor = Math.min(input.length(), _cursor); @@ -56,28 +76,13 @@ public class CommandManager { } text - .append(Text.literal(input.substring(Math.max(0, cursor - CommandSyntaxException.CONTEXT_AMOUNT), cursor))) - .append(Text.literal(input.substring(cursor)).formatted(Formatting.RED, Formatting.UNDERLINE)) - .append(Text.translatable("command.context.here").formatted(Formatting.RED, Formatting.ITALIC)); + .append(Text.literal(input.substring(Math.max(0, cursor - CommandSyntaxException.CONTEXT_AMOUNT), cursor))) + .append(Text.literal(input.substring(cursor)).formatted(Formatting.RED, Formatting.UNDERLINE)) + .append(Text.translatable("command.context.here").formatted(Formatting.RED, Formatting.ITALIC)); return text; } public static LiteralArgumentBuilder literal (String name) { return LiteralArgumentBuilder.literal(name); } public static RequiredArgumentBuilder argument (String name, ArgumentType type) { return RequiredArgumentBuilder.argument(name, type); } - - static { - TestCommand.register(dispatcher); - CoreCommand.register(dispatcher); - UsernameCommand.register(dispatcher); - ValidateCommand.register(dispatcher); - CloopCommand.register(dispatcher); - CustomChatCommand.register(dispatcher); - SayCommand.register(dispatcher); - SelfCareCommand.register(dispatcher); - FullBrightCommand.register(dispatcher); - MusicCommand.register(dispatcher); - RainbowNameCommand.register(dispatcher); - EvalCommand.register(dispatcher); - } -} \ No newline at end of file +} diff --git a/src/main/java/land/chipmunk/chipmunkmod/commands/ItemCommand.java b/src/main/java/land/chipmunk/chipmunkmod/commands/ItemCommand.java new file mode 100644 index 0000000..c2837a0 --- /dev/null +++ b/src/main/java/land/chipmunk/chipmunkmod/commands/ItemCommand.java @@ -0,0 +1,58 @@ +package land.chipmunk.chipmunkmod.commands; + +import com.mojang.brigadier.Command; +import com.mojang.brigadier.CommandDispatcher; +import com.mojang.brigadier.context.CommandContext; +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import static land.chipmunk.chipmunkmod.command.CommandManager.literal; +import static land.chipmunk.chipmunkmod.command.CommandManager.argument; +import static com.mojang.brigadier.arguments.IntegerArgumentType.integer; +import static com.mojang.brigadier.arguments.IntegerArgumentType.getInteger; +import static net.minecraft.command.argument.ItemStackArgumentType.itemStack; +import static net.minecraft.command.argument.ItemStackArgumentType.getItemStackArgument; +import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource; +import net.minecraft.command.CommandRegistryAccess; +import net.minecraft.client.MinecraftClient; +import net.minecraft.network.packet.c2s.play.CreativeInventoryActionC2SPacket; +import net.minecraft.item.ItemStack; +import net.minecraft.text.Text; + +public class ItemCommand { + public static void register (CommandDispatcher dispatcher, CommandRegistryAccess commandRegistryAccess) { + dispatcher.register( + literal("item") + .then( + argument("item", itemStack(commandRegistryAccess)) + .executes(c -> setItem(c, 1)) + .then( + argument("count", integer(1, 64)) + .executes(c -> setItem(c)) + ) + ) + ); + } + + public static int setItem (CommandContext context) throws CommandSyntaxException { + return setItem(context, getInteger(context, "count")); + } + + public static int setItem (CommandContext context, int count) throws CommandSyntaxException { + final FabricClientCommandSource source = context.getSource(); + final MinecraftClient client = source.getClient(); + + final ItemStack stack = getItemStackArgument(context, "item").createStack(count, false); + + int slot = 36 + client.player.getInventory().selectedSlot; + + client.getNetworkHandler().getConnection().send(new CreativeInventoryActionC2SPacket(slot, stack)); + + source.sendFeedback( + Text.translatable( + "Replaced your held item with %s %s", + Text.literal(String.valueOf(count)), + stack.toHoverableText() + ) + ); + return Command.SINGLE_SUCCESS; + } +} diff --git a/src/main/java/land/chipmunk/chipmunkmod/commands/MusicCommand.java b/src/main/java/land/chipmunk/chipmunkmod/commands/MusicCommand.java index b4a1e7c..b2bc007 100644 --- a/src/main/java/land/chipmunk/chipmunkmod/commands/MusicCommand.java +++ b/src/main/java/land/chipmunk/chipmunkmod/commands/MusicCommand.java @@ -147,7 +147,10 @@ public class MusicCommand { public int list (CommandContext context, Path path) throws CommandSyntaxException { final FabricClientCommandSource source = context.getSource(); - final String prefix = CommandManager.prefix; + + final CommandManager commandManager = CommandManager.INSTANCE; + + final String prefix = commandManager.prefix; final File directory = path.toFile(); final String[] filenames = directory.list(); diff --git a/src/main/java/land/chipmunk/chipmunkmod/mixin/ChatInputSuggestorMixin.java b/src/main/java/land/chipmunk/chipmunkmod/mixin/ChatInputSuggestorMixin.java index 910d4e1..634c8c6 100644 --- a/src/main/java/land/chipmunk/chipmunkmod/mixin/ChatInputSuggestorMixin.java +++ b/src/main/java/land/chipmunk/chipmunkmod/mixin/ChatInputSuggestorMixin.java @@ -42,15 +42,17 @@ public class ChatInputSuggestorMixin { public void refresh (CallbackInfo ci) { if (slashOptional) return; + final CommandManager commandManager = CommandManager.INSTANCE; + final String text = this.textField.getText(); final int cursor = this.textField.getCursor(); - if (cursor < CommandManager.prefix.length() || !text.startsWith(CommandManager.prefix)) return; + if (cursor < commandManager.prefix.length() || !text.startsWith(commandManager.prefix)) return; final StringReader reader = new StringReader(text); - reader.setCursor(CommandManager.prefix.length()); // Skip the prefix + reader.setCursor(commandManager.prefix.length()); // Skip the prefix - final CommandDispatcher dispatcher = CommandManager.dispatcher; + final CommandDispatcher dispatcher = commandManager.dispatcher; final MinecraftClient client = MinecraftClient.getInstance(); final FabricClientCommandSource commandSource = (FabricClientCommandSource) client.getNetworkHandler().getCommandSource(); diff --git a/src/main/java/land/chipmunk/chipmunkmod/mixin/ChatScreenMixin.java b/src/main/java/land/chipmunk/chipmunkmod/mixin/ChatScreenMixin.java index d7525a4..9fec4fe 100644 --- a/src/main/java/land/chipmunk/chipmunkmod/mixin/ChatScreenMixin.java +++ b/src/main/java/land/chipmunk/chipmunkmod/mixin/ChatScreenMixin.java @@ -17,8 +17,10 @@ public class ChatScreenMixin { @Inject(at = @At("HEAD"), method = "sendMessage", cancellable = true) public void sendMessage(String chatText, boolean addToHistory, CallbackInfoReturnable cir) { - if (chatText.startsWith(CommandManager.prefix)) { - CommandManager.executeCommand(chatText.substring(CommandManager.prefix.length())); + final CommandManager commandManager = CommandManager.INSTANCE; + + if (chatText.startsWith(commandManager.prefix)) { + commandManager.executeCommand(chatText.substring(commandManager.prefix.length())); if (addToHistory) MinecraftClient.getInstance().inGameHud.getChatHud().addToMessageHistory(chatText); diff --git a/src/main/java/land/chipmunk/chipmunkmod/mixin/ClientPlayNetworkHandlerMixin.java b/src/main/java/land/chipmunk/chipmunkmod/mixin/ClientPlayNetworkHandlerMixin.java index 462c627..24c5ba4 100644 --- a/src/main/java/land/chipmunk/chipmunkmod/mixin/ClientPlayNetworkHandlerMixin.java +++ b/src/main/java/land/chipmunk/chipmunkmod/mixin/ClientPlayNetworkHandlerMixin.java @@ -1,23 +1,29 @@ package land.chipmunk.chipmunkmod.mixin; -import land.chipmunk.chipmunkmod.modules.*; -import net.minecraft.network.packet.s2c.play.GameJoinS2CPacket; 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.network.packet.s2c.play.GameJoinS2CPacket; +import net.minecraft.command.CommandRegistryAccess; +import net.minecraft.resource.featuretoggle.FeatureSet; +import net.minecraft.registry.CombinedDynamicRegistries; +import net.minecraft.client.network.ClientDynamicRegistryType; +import land.chipmunk.chipmunkmod.ChipmunkMod; +import land.chipmunk.chipmunkmod.command.CommandManager; +import land.chipmunk.chipmunkmod.modules.SelfCare; @Mixin(net.minecraft.client.network.ClientPlayNetworkHandler.class) public class ClientPlayNetworkHandlerMixin { + @Shadow private FeatureSet enabledFeatures; + @Shadow private CombinedDynamicRegistries combinedDynamicRegistries; + @Inject(method = "onGameJoin", at = @At("TAIL")) private void onGameJoin (GameJoinS2CPacket packet, CallbackInfo ci) { - SelfCare.INSTANCE.init(); - SongPlayer.INSTANCE.coreReady(); - RainbowName.INSTANCE.init(); - } + final CommandRegistryAccess commandRegistryAccess = CommandRegistryAccess.of(this.combinedDynamicRegistries.getCombinedRegistryManager(), this.enabledFeatures); - @Inject(method = "onGameJoin", at = @At("HEAD")) - private void onGameJoin2 (GameJoinS2CPacket packet, CallbackInfo ci) { - Players.INSTANCE.init(); + CommandManager.INSTANCE = new CommandManager(ChipmunkMod.CONFIG.commands.prefix, commandRegistryAccess); + SelfCare.INSTANCE.init(); } } diff --git a/src/main/java/land/chipmunk/chipmunkmod/modules/CommandCore.java b/src/main/java/land/chipmunk/chipmunkmod/modules/CommandCore.java index b06cba2..b8a2b20 100644 --- a/src/main/java/land/chipmunk/chipmunkmod/modules/CommandCore.java +++ b/src/main/java/land/chipmunk/chipmunkmod/modules/CommandCore.java @@ -1,5 +1,6 @@ package land.chipmunk.chipmunkmod.modules; +import land.chipmunk.chipmunkmod.ChipmunkMod; import land.chipmunk.chipmunkmod.data.BlockArea; import lombok.Getter; import lombok.Setter; @@ -17,12 +18,12 @@ import java.util.concurrent.CompletableFuture; public class CommandCore { private final MinecraftClient client; - @Getter @Setter private boolean ready = false; + @Getter @Setter private boolean ready = false; @Getter @Setter private BlockPos origin; @Getter private final BlockArea relativeArea; @Getter @Setter private BlockPos currentBlockRelative; - public static CommandCore INSTANCE = new CommandCore(MinecraftClient.getInstance(), new BlockArea(new BlockPos(0, 0, 0), new BlockPos(15, 2, 15))); + public static CommandCore INSTANCE = new CommandCore(MinecraftClient.getInstance(), ChipmunkMod.CONFIG.core.relativeArea); public CommandCore (MinecraftClient client, BlockArea relativeArea) { this.client = client; @@ -36,9 +37,9 @@ public class CommandCore { } origin = new BlockPos( - ((int) position.getX() / 16) * 16, - 0, // TODO: Use the actual bottom of the world instead of hardcoding to 0 - ((int) position.getZ() / 16) * 16 + ((int) position.getX() / 16) * 16, + 0, // TODO: Use the actual bottom of the world instead of hardcoding to 0 + ((int) position.getZ() / 16) * 16 ); if (currentBlockRelative == null) currentBlockRelative = new BlockPos(relativeArea.start()); @@ -51,14 +52,14 @@ public class CommandCore { final BlockPos relEnd = relativeArea.end(); final String command = String.format( - "fill %s %s %s %s %s %s command_block", - relStart.getX() + origin.getX(), - relStart.getY() + origin.getY(), - relStart.getZ() + origin.getZ(), + "fill %s %s %s %s %s %s command_block", + relStart.getX() + origin.getX(), + relStart.getY() + origin.getY(), + relStart.getZ() + origin.getZ(), - relEnd.getX() + origin.getX(), - relEnd.getY() + origin.getY(), - relEnd.getZ() + origin.getZ() + relEnd.getX() + origin.getX(), + relEnd.getY() + origin.getY(), + relEnd.getZ() + origin.getZ() ); client.getNetworkHandler().sendChatCommand(command); diff --git a/src/main/java/land/chipmunk/chipmunkmod/util/gson/BlockPosTypeAdapter.java b/src/main/java/land/chipmunk/chipmunkmod/util/gson/BlockPosTypeAdapter.java new file mode 100644 index 0000000..b6dc460 --- /dev/null +++ b/src/main/java/land/chipmunk/chipmunkmod/util/gson/BlockPosTypeAdapter.java @@ -0,0 +1,40 @@ +package land.chipmunk.chipmunkmod.util.gson; + +import net.minecraft.util.math.BlockPos; +import com.google.gson.TypeAdapter; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonToken; +import com.google.gson.stream.JsonWriter; +import java.io.IOException; + +public class BlockPosTypeAdapter extends TypeAdapter { + @Override + public BlockPos read (JsonReader reader) throws IOException { + int x = 0; + int y = 0; + int z = 0; + + reader.beginObject(); + + while (!reader.peek().equals(JsonToken.END_OBJECT)) { + if (reader.peek().equals(JsonToken.NAME)) { + String name = reader.nextName(); + + // ? Is there a better way to do this? + if (name.equals("x")) x = reader.nextInt(); + else if (name.equals("y")) y = reader.nextInt(); + else if (name.equals("z")) z = reader.nextInt(); + else reader.skipValue(); + } + } + + reader.endObject(); + + return new BlockPos(x, y, z); + } + + @Override + public void write (JsonWriter out, BlockPos vec) throws IOException { + // TODO: make this do something lmfaooo + } +}