diff --git a/src/main/java/com/minecrafttas/tasmod/TASmod.java b/src/main/java/com/minecrafttas/tasmod/TASmod.java index fb9bdaaf..69fb8eb3 100644 --- a/src/main/java/com/minecrafttas/tasmod/TASmod.java +++ b/src/main/java/com/minecrafttas/tasmod/TASmod.java @@ -13,7 +13,6 @@ import com.minecrafttas.mctcommon.networking.Server; import com.minecrafttas.tasmod.commands.CommandClearInputs; import com.minecrafttas.tasmod.commands.CommandFileCommand; -import com.minecrafttas.tasmod.commands.CommandFolder; import com.minecrafttas.tasmod.commands.CommandFullPlay; import com.minecrafttas.tasmod.commands.CommandFullRecord; import com.minecrafttas.tasmod.commands.CommandLoadTAS; @@ -136,7 +135,6 @@ public void onServerInit(MinecraftServer server) { CommandRegistry.registerServerCommand(new CommandPlay(), server); CommandRegistry.registerServerCommand(new CommandSaveTAS(), server); CommandRegistry.registerServerCommand(new CommandLoadTAS(), server); - CommandRegistry.registerServerCommand(new CommandFolder(), server); CommandRegistry.registerServerCommand(new CommandClearInputs(), server); CommandRegistry.registerServerCommand(new CommandSavestate(), server); CommandRegistry.registerServerCommand(new CommandFullRecord(), server); diff --git a/src/main/java/com/minecrafttas/tasmod/TASmodClient.java b/src/main/java/com/minecrafttas/tasmod/TASmodClient.java index b4edba1c..3684aae2 100644 --- a/src/main/java/com/minecrafttas/tasmod/TASmodClient.java +++ b/src/main/java/com/minecrafttas/tasmod/TASmodClient.java @@ -22,6 +22,7 @@ import com.minecrafttas.mctcommon.networking.Client; import com.minecrafttas.mctcommon.networking.PacketHandlerRegistry; import com.minecrafttas.mctcommon.networking.Server; +import com.minecrafttas.tasmod.commands.client.CommandFolder; import com.minecrafttas.tasmod.gui.InfoHud; import com.minecrafttas.tasmod.handlers.LoadingScreenHandler; import com.minecrafttas.tasmod.playback.PlaybackControllerClient; @@ -141,6 +142,8 @@ public void onInitializeClient() { optionsFileCommandExtension = new OptionsFileCommandExtension(); labelFileCommandExtension = new LabelFileCommandExtension(); + TASmodAPIRegistry.CLIENT_COMMANDS.register(new CommandFolder()); + registerEventListeners(); registerNetworkPacketHandlers(); diff --git a/src/main/java/com/minecrafttas/tasmod/commands/CommandRecord.java b/src/main/java/com/minecrafttas/tasmod/commands/CommandRecord.java index 7934574f..2ba6abbe 100644 --- a/src/main/java/com/minecrafttas/tasmod/commands/CommandRecord.java +++ b/src/main/java/com/minecrafttas/tasmod/commands/CommandRecord.java @@ -10,7 +10,6 @@ import net.minecraft.command.ICommandSender; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.server.MinecraftServer; -import net.minecraft.util.math.BlockPos; import net.minecraft.util.text.TextComponentString; import net.minecraft.util.text.TextFormatting; @@ -51,9 +50,4 @@ public void execute(MinecraftServer server, ICommandSender sender, String[] args } } - - @Override - public List getTabCompletions(MinecraftServer server, ICommandSender sender, String[] args, BlockPos targetPos) { - return super.getTabCompletions(server, sender, args, targetPos); - } } diff --git a/src/main/java/com/minecrafttas/tasmod/commands/client/ClientCommandBase.java b/src/main/java/com/minecrafttas/tasmod/commands/client/ClientCommandBase.java new file mode 100644 index 00000000..6a890da2 --- /dev/null +++ b/src/main/java/com/minecrafttas/tasmod/commands/client/ClientCommandBase.java @@ -0,0 +1,13 @@ +package com.minecrafttas.tasmod.commands.client; + +import com.minecrafttas.mctcommon.registry.Registerable; + +import net.minecraft.command.CommandBase; + +public abstract class ClientCommandBase extends CommandBase implements Registerable { + + @Override + public String getExtensionName() { + return this.getName(); + } +} diff --git a/src/main/java/com/minecrafttas/tasmod/commands/client/ClientCommandRegistry.java b/src/main/java/com/minecrafttas/tasmod/commands/client/ClientCommandRegistry.java new file mode 100644 index 00000000..f5c32951 --- /dev/null +++ b/src/main/java/com/minecrafttas/tasmod/commands/client/ClientCommandRegistry.java @@ -0,0 +1,85 @@ +package com.minecrafttas.tasmod.commands.client; + +import java.util.Collection; +import java.util.LinkedHashMap; + +import com.minecrafttas.mctcommon.registry.AbstractRegistry; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.entity.EntityPlayerSP; +import net.minecraft.command.CommandBase; +import net.minecraft.util.text.ChatType; +import net.minecraft.util.text.TextComponentString; + +public class ClientCommandRegistry extends AbstractRegistry { + public ClientCommandRegistry() { + super("CLIENTCOMMAND_REGISTRY", new LinkedHashMap<>()); + } + + /** + *

Checks the chat message for client commands and runs them + * + * @param chatMessage The chat message to check + * @return Boolean, whether the command execution should be canceled + */ + public boolean runClientCommands(String chatMessage) { + if (!chatMessage.startsWith("/")) { + return false; + } + chatMessage = chatMessage.substring(1); + for (String commandName : REGISTRY.keySet()) { + if (chatMessage.startsWith(commandName)) { + Minecraft mc = Minecraft.getMinecraft(); + EntityPlayerSP player = mc.player; + ClientCommandBase command = REGISTRY.get(commandName); + + String[] args = chatMessage.split(" "); + args = dropFirstString(args); + try { + command.execute(null, player, args); + } catch (Exception e) { + mc.ingameGUI.addChatMessage(ChatType.CHAT, new TextComponentString(e.getMessage())); + } + return true; + } + } + return false; + } + + /** + *

Checks the tab completion request for client commands and runs {@link CommandBase#getTabCompletions(net.minecraft.server.MinecraftServer, net.minecraft.command.ICommandSender, String[], net.minecraft.util.math.BlockPos) getTabCompletions()} + * + * @param chatMessage The chat message to check + * @return Boolean, whether the vanilla tab completion should be canceled + */ + public String[] runTabCompletions(String chatMessage) { + if (!chatMessage.startsWith("/")) { + return null; + } + + chatMessage = chatMessage.substring(1); + for (String commandName : REGISTRY.keySet()) { + if (chatMessage.startsWith(commandName)) { + Minecraft mc = Minecraft.getMinecraft(); + EntityPlayerSP player = mc.player; + ClientCommandBase command = REGISTRY.get(commandName); + + String[] args = chatMessage.split(" "); + args = dropFirstString(args); + + return command.getTabCompletions(null, player, args, null).toArray(new String[] {}); + } + } + return null; + } + + private static String[] dropFirstString(String[] strings) { + String[] strings2 = new String[strings.length - 1]; + System.arraycopy(strings, 1, strings2, 0, strings.length - 1); + return strings2; + } + + public Collection getClientCommandList() { + return REGISTRY.values(); + } +} diff --git a/src/main/java/com/minecrafttas/tasmod/commands/CommandFolder.java b/src/main/java/com/minecrafttas/tasmod/commands/client/CommandFolder.java similarity index 72% rename from src/main/java/com/minecrafttas/tasmod/commands/CommandFolder.java rename to src/main/java/com/minecrafttas/tasmod/commands/client/CommandFolder.java index 94497364..ba844ef3 100644 --- a/src/main/java/com/minecrafttas/tasmod/commands/CommandFolder.java +++ b/src/main/java/com/minecrafttas/tasmod/commands/client/CommandFolder.java @@ -1,4 +1,4 @@ -package com.minecrafttas.tasmod.commands; +package com.minecrafttas.tasmod.commands.client; import static com.minecrafttas.tasmod.TASmod.LOGGER; @@ -8,19 +8,14 @@ import java.util.ArrayList; import java.util.List; -import com.minecrafttas.tasmod.TASmod; import com.minecrafttas.tasmod.TASmodClient; -import com.minecrafttas.tasmod.networking.TASmodBufferBuilder; -import com.minecrafttas.tasmod.registries.TASmodPackets; -import net.minecraft.command.CommandBase; import net.minecraft.command.CommandException; import net.minecraft.command.ICommandSender; -import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.server.MinecraftServer; import net.minecraft.util.math.BlockPos; -public class CommandFolder extends CommandBase { +public class CommandFolder extends ClientCommandBase { @Override public String getName() { @@ -40,16 +35,10 @@ public int getRequiredPermissionLevel() { @Override public void execute(MinecraftServer server, ICommandSender sender, String[] args) throws CommandException { if (args.length == 1) { - short action = 0; if (args[0].equalsIgnoreCase("savestates")) { - action = 0; + openSavestates(); } else if (args[0].equalsIgnoreCase("tasfiles")) { - action = 1; - } - try { - TASmod.server.sendTo((EntityPlayerMP) sender, new TASmodBufferBuilder(TASmodPackets.OPEN_FOLDER).writeShort(action)); - } catch (Exception e) { - e.printStackTrace(); + openTASFolder(); } } } @@ -65,7 +54,7 @@ public List getTabCompletions(MinecraftServer server, ICommandSender sen return tab; } - public static void openTASFolder() { + private void openTASFolder() { Path file = TASmodClient.tasfiledirectory; try { TASmodClient.createTASfileDir(); @@ -76,7 +65,7 @@ public static void openTASFolder() { } } - public static void openSavestates() { + private void openSavestates() { Path file = TASmodClient.savestatedirectory; try { TASmodClient.createSavestatesDir(); diff --git a/src/main/java/com/minecrafttas/tasmod/mixin/clientcommands/MixinEntityPlayerSP.java b/src/main/java/com/minecrafttas/tasmod/mixin/clientcommands/MixinEntityPlayerSP.java new file mode 100644 index 00000000..f83aa049 --- /dev/null +++ b/src/main/java/com/minecrafttas/tasmod/mixin/clientcommands/MixinEntityPlayerSP.java @@ -0,0 +1,21 @@ +package com.minecrafttas.tasmod.mixin.clientcommands; + +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; + +import com.minecrafttas.tasmod.registries.TASmodAPIRegistry; + +import net.minecraft.client.entity.EntityPlayerSP; + +@Mixin(EntityPlayerSP.class) +public class MixinEntityPlayerSP { + + @Inject(method = "sendChatMessage", at = @At("HEAD"), cancellable = true) + public void inject_sendChatMessage(String message, CallbackInfo ci) { + if (TASmodAPIRegistry.CLIENT_COMMANDS.runClientCommands(message)) { + ci.cancel(); + } + } +} diff --git a/src/main/java/com/minecrafttas/tasmod/mixin/clientcommands/MixinTabCompleter.java b/src/main/java/com/minecrafttas/tasmod/mixin/clientcommands/MixinTabCompleter.java new file mode 100644 index 00000000..2102f271 --- /dev/null +++ b/src/main/java/com/minecrafttas/tasmod/mixin/clientcommands/MixinTabCompleter.java @@ -0,0 +1,51 @@ +package com.minecrafttas.tasmod.mixin.clientcommands; + +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import com.minecrafttas.tasmod.registries.TASmodAPIRegistry; + +import net.minecraft.client.gui.GuiTextField; +import net.minecraft.util.TabCompleter; + +@Mixin(TabCompleter.class) +public abstract class MixinTabCompleter { + + @Shadow + @Final + private GuiTextField textField; + @Shadow + private boolean requestedCompletions; + + @Unique + private String[] clientCompletions = null; + + @Inject(method = "requestCompletions", at = @At("HEAD"), cancellable = true) + public void inject_requestTabCompletions(String currentCommand, CallbackInfo ci) { + if (currentCommand.length() >= 1) { + clientCompletions = TASmodAPIRegistry.CLIENT_COMMANDS.runTabCompletions(currentCommand); + if (clientCompletions == null) { + } + if (clientCompletions != null) { + requestedCompletions = true; + ci.cancel(); + } + } + } + + @Inject(method = "complete", at = @At("RETURN")) + public void inject_tabComplete(CallbackInfo ci) { + if (clientCompletions != null) { + this.setCompletions(clientCompletions); + clientCompletions = null; + } + } + + @Shadow + protected abstract void setCompletions(String... strings); +} diff --git a/src/main/java/com/minecrafttas/tasmod/registries/TASmodAPIRegistry.java b/src/main/java/com/minecrafttas/tasmod/registries/TASmodAPIRegistry.java index 308cedf9..67a84a3b 100644 --- a/src/main/java/com/minecrafttas/tasmod/registries/TASmodAPIRegistry.java +++ b/src/main/java/com/minecrafttas/tasmod/registries/TASmodAPIRegistry.java @@ -1,38 +1,50 @@ package com.minecrafttas.tasmod.registries; +import com.minecrafttas.tasmod.commands.client.ClientCommandBase; +import com.minecrafttas.tasmod.commands.client.ClientCommandRegistry; import com.minecrafttas.tasmod.playback.filecommands.PlaybackFileCommandsRegistry; import com.minecrafttas.tasmod.playback.metadata.PlaybackMetadataRegistry; import com.minecrafttas.tasmod.playback.tasfile.flavor.SerialiserFlavorBase; import com.minecrafttas.tasmod.playback.tasfile.flavor.SerialiserFlavorRegistry; import com.minecrafttas.tasmod.playback.tasfile.flavor.builtin.Beta1Flavor; +import net.minecraft.command.CommandBase; + public class TASmodAPIRegistry { /** - * Registry for registering custom metadata that is stored in the TASfile.
- *
- * The default metadata includes general information such as author name, - * savestate/rerecord count and category.
- *
- * Any custom class has to implement PlaybackMetadataExtension + *

Registry for registering custom metadata that is stored in the TASfile. + * + *

The default metadata includes general information such as author name,
+ * savestate/rerecord count and category. + * + *

Any custom class has to implement PlaybackMetadataExtension */ public static final PlaybackMetadataRegistry PLAYBACK_METADATA = new PlaybackMetadataRegistry(); /** - * Registry for registering custom behavior for each tick during recording and playback.
- *
- * File commands give the opportunity to run commands on each recorded tick and each played back tick.
+ *

Registry for registering custom behavior for each tick during recording and playback. + * + *

File commands give the opportunity to run commands on each recorded tick and each played back tick.
* File commands also have access to the TASfile so that data can be stored and read in/from the TASfile. * */ public static final PlaybackFileCommandsRegistry PLAYBACK_FILE_COMMAND = new PlaybackFileCommandsRegistry(); /** - * Registry for registering custom serialiser flavors that dictate the syntax of the inputs stored in the TASfile.
- *
- * Either create a new flavor by extending {@link SerialiserFlavorBase}
- * or extend an existing flavor (like {@link Beta1Flavor}) and overwrite parts of the methods.
- *
- * The resulting flavor can be registered here and can be found as a saving option with /saveTAS + *

Registry for registering custom serialiser flavors that dictate the syntax of the inputs stored in the TASfile. + * + *

Either create a new flavor by extending {@link SerialiserFlavorBase}
+ * or extend an existing flavor (like {@link Beta1Flavor}) and overwrite parts of the methods. + * + *

The resulting flavor can be registered here and can be found as a saving option with /saveTAS */ public static final SerialiserFlavorRegistry SERIALISER_FLAVOR = new SerialiserFlavorRegistry(); + + /** + *

Registry for registering commands that are only executed on the client + * + *

Create a new ClientCommand by extending {@link ClientCommandBase},
+ * then create a command like normal, as it extends from the vanilla {@link CommandBase} + */ + public static final ClientCommandRegistry CLIENT_COMMANDS = new ClientCommandRegistry(); } diff --git a/src/main/java/com/minecrafttas/tasmod/registries/TASmodPackets.java b/src/main/java/com/minecrafttas/tasmod/registries/TASmodPackets.java index 3e4e392b..7c8b2094 100644 --- a/src/main/java/com/minecrafttas/tasmod/registries/TASmodPackets.java +++ b/src/main/java/com/minecrafttas/tasmod/registries/TASmodPackets.java @@ -3,7 +3,6 @@ import com.minecrafttas.mctcommon.networking.Client.Side; import com.minecrafttas.mctcommon.networking.CompactPacketHandler; import com.minecrafttas.mctcommon.networking.interfaces.PacketID; -import com.minecrafttas.tasmod.commands.CommandFolder; import com.minecrafttas.tasmod.playback.PlaybackControllerClient; import com.minecrafttas.tasmod.playback.PlaybackControllerClient.TASstate; import com.minecrafttas.tasmod.playback.filecommands.PlaybackFileCommand.PlaybackFileCommandExtension; @@ -184,29 +183,6 @@ public enum TASmodPackets implements PacketID { * boolean enable Whether the extensions should be enabled or disabled */ PLAYBACK_FILECOMMAND_ENABLE, - /** - *

Opens a TASmod related folder on the file system - *

The action describes which folder to open: - *

    - *
  1. Savestate-Folder
  2. - *
  3. TASFiles-Folder
  4. - *
- * - *

Side: CLIENT
- * ARGS: short action - */ - OPEN_FOLDER(Side.CLIENT, (buf, clientID) -> { - short action = buf.getShort(); - switch (action) { - case 0: - CommandFolder.openSavestates(); - break; - case 1: - CommandFolder.openTASFolder(); - default: - break; - } - }), /** *

Clears the current gui screen on the client * diff --git a/src/main/resources/tasmod.mixin.json b/src/main/resources/tasmod.mixin.json index 266d586e..ed795f87 100644 --- a/src/main/resources/tasmod.mixin.json +++ b/src/main/resources/tasmod.mixin.json @@ -44,6 +44,9 @@ "events.MixinGuiIngame", "events.MixinEntityRenderer", + "clientcommands.MixinEntityPlayerSP", + "clientcommands.MixinTabCompleter", + // Playbackhooks "playbackhooks.MixinMinecraft", "playbackhooks.MixinEntityRenderer",