From 50db974497fc97972af91e913046ed72d91e1bb7 Mon Sep 17 00:00:00 2001 From: ChomeNS <95471003+chomens@users.noreply.github.com> Date: Sun, 9 Feb 2025 08:00:47 +0700 Subject: [PATCH] refactor: use LF line endings and use 4 spaces on all classes --- .../chipmunk/chipmunkmod/ChipmunkMod.java | 160 ++--- .../chipmunkmod/command/CommandManager.java | 177 ++--- .../chipmunkmod/commands/CoreCommand.java | 214 +++--- .../chipmunkmod/commands/ItemCommand.java | 8 +- .../chipmunkmod/commands/TestCommand.java | 50 +- .../chipmunkmod/commands/UsernameCommand.java | 139 ++-- .../chipmunkmod/commands/ValidateCommand.java | 60 +- .../chipmunkmod/config/Configuration.java | 144 ++-- .../chipmunkmod/data/ChomeNSBotCommand.java | 11 +- .../mixin/ChatInputSuggestorMixin.java | 199 +++--- .../chipmunkmod/mixin/ChatScreenMixin.java | 300 ++++---- .../mixin/ClientConnectionMixin.java | 192 ++--- .../mixin/ClientPlayNetworkHandlerMixin.java | 264 +++---- .../mixin/ClientPlayerEntityMixin.java | 84 +-- .../mixin/MinecraftClientAccessor.java | 28 +- .../chipmunkmod/modules/CommandCore.java | 668 +++++++++--------- .../chipmunkmod/modules/SelfCare.java | 323 ++++----- .../chipmunk/chipmunkmod/song/Instrument.java | 79 ++- .../chipmunkmod/song/MidiConverter.java | 658 ++++++++--------- .../chipmunkmod/song/NBSConverter.java | 340 ++++----- .../land/chipmunk/chipmunkmod/song/Note.java | 46 +- .../land/chipmunk/chipmunkmod/song/Song.java | 213 +++--- .../chipmunkmod/song/SongLoaderException.java | 26 +- .../chipmunkmod/song/SongLoaderThread.java | 90 +-- .../chipmunkmod/util/DownloadUtilities.java | 80 ++- 25 files changed, 2298 insertions(+), 2255 deletions(-) diff --git a/src/main/java/land/chipmunk/chipmunkmod/ChipmunkMod.java b/src/main/java/land/chipmunk/chipmunkmod/ChipmunkMod.java index c8b918d..f9ed1a0 100644 --- a/src/main/java/land/chipmunk/chipmunkmod/ChipmunkMod.java +++ b/src/main/java/land/chipmunk/chipmunkmod/ChipmunkMod.java @@ -1,80 +1,80 @@ -package land.chipmunk.chipmunkmod; - -import land.chipmunk.chipmunkmod.config.ChipmunkModMigrations; -import land.chipmunk.chipmunkmod.config.Configuration; -import land.chipmunk.chipmunkmod.modules.SelfCare; -import land.chipmunk.chipmunkmod.util.configurate.ConfigurateUtilities; -import net.fabricmc.api.ModInitializer; -import net.fabricmc.loader.api.FabricLoader; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.spongepowered.configurate.BasicConfigurationNode; -import org.spongepowered.configurate.gson.GsonConfigurationLoader; -import org.spongepowered.configurate.objectmapping.ObjectMapper; -import org.spongepowered.configurate.util.NamingSchemes; - -import java.io.IOException; -import java.nio.file.Path; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; - -public class ChipmunkMod implements ModInitializer { - private static final Path CONFIG_PATH = FabricLoader.getInstance() - .getConfigDir().resolve("chipmunkmod.json"); - - public static final Logger LOGGER = LoggerFactory.getLogger("ChipmunkMod"); - public static Configuration CONFIG; - - public static ExecutorService executorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors()); - - @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. - - try { - CONFIG = loadConfig(); - } catch (IOException exception) { - throw new RuntimeException("Could not load the config", exception); - } - - SelfCare.INSTANCE.init(); - - LOGGER.info("Loaded ChipmunkMod (chayapak's fork)"); - } - - public static Configuration loadConfig() throws IOException { - final ChipmunkModMigrations migrations = new ChipmunkModMigrations(); - final ObjectMapper.Factory customFactory = ObjectMapper.factoryBuilder() - .defaultNamingScheme(NamingSchemes.CAMEL_CASE) - .build(); - - final GsonConfigurationLoader loader = GsonConfigurationLoader.builder() - .defaultOptions(options -> options - .serializers(build -> build - .registerAnnotatedObjects(customFactory) - .registerAll(ConfigurateUtilities.customSerializers())) - .shouldCopyDefaults(true)) - .indent(4) - .path(CONFIG_PATH) - .build(); - - // Configurate will create parent directories for us, so we don't need to do it - final BasicConfigurationNode node = loader.load(); - if (node.empty()) { // Config empty, fill it with defaults - final Configuration defaults = new Configuration(); - node.set(Configuration.class, defaults); - migrations.setLatest(node); - loader.save(node); - - return defaults; - } - - if (migrations.migrate(node)) { // Migrated, write new config - loader.save(node); - } - - return node.get(Configuration.class); - } -} +package land.chipmunk.chipmunkmod; + +import land.chipmunk.chipmunkmod.config.ChipmunkModMigrations; +import land.chipmunk.chipmunkmod.config.Configuration; +import land.chipmunk.chipmunkmod.modules.SelfCare; +import land.chipmunk.chipmunkmod.util.configurate.ConfigurateUtilities; +import net.fabricmc.api.ModInitializer; +import net.fabricmc.loader.api.FabricLoader; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.spongepowered.configurate.BasicConfigurationNode; +import org.spongepowered.configurate.gson.GsonConfigurationLoader; +import org.spongepowered.configurate.objectmapping.ObjectMapper; +import org.spongepowered.configurate.util.NamingSchemes; + +import java.io.IOException; +import java.nio.file.Path; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +public class ChipmunkMod implements ModInitializer { + private static final Path CONFIG_PATH = FabricLoader.getInstance() + .getConfigDir().resolve("chipmunkmod.json"); + + public static final Logger LOGGER = LoggerFactory.getLogger("ChipmunkMod"); + public static Configuration CONFIG; + + public static ExecutorService executorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors()); + + @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. + + try { + CONFIG = loadConfig(); + } catch (IOException exception) { + throw new RuntimeException("Could not load the config", exception); + } + + SelfCare.INSTANCE.init(); + + LOGGER.info("Loaded ChipmunkMod (chayapak's fork)"); + } + + public static Configuration loadConfig() throws IOException { + final ChipmunkModMigrations migrations = new ChipmunkModMigrations(); + final ObjectMapper.Factory customFactory = ObjectMapper.factoryBuilder() + .defaultNamingScheme(NamingSchemes.CAMEL_CASE) + .build(); + + final GsonConfigurationLoader loader = GsonConfigurationLoader.builder() + .defaultOptions(options -> options + .serializers(build -> build + .registerAnnotatedObjects(customFactory) + .registerAll(ConfigurateUtilities.customSerializers())) + .shouldCopyDefaults(true)) + .indent(4) + .path(CONFIG_PATH) + .build(); + + // Configurate will create parent directories for us, so we don't need to do it + final BasicConfigurationNode node = loader.load(); + if (node.empty()) { // Config empty, fill it with defaults + final Configuration defaults = new Configuration(); + node.set(Configuration.class, defaults); + migrations.setLatest(node); + loader.save(node); + + return defaults; + } + + if (migrations.migrate(node)) { // Migrated, write new config + loader.save(node); + } + + return node.get(Configuration.class); + } +} diff --git a/src/main/java/land/chipmunk/chipmunkmod/command/CommandManager.java b/src/main/java/land/chipmunk/chipmunkmod/command/CommandManager.java index 0781d47..1c07df6 100644 --- a/src/main/java/land/chipmunk/chipmunkmod/command/CommandManager.java +++ b/src/main/java/land/chipmunk/chipmunkmod/command/CommandManager.java @@ -1,86 +1,91 @@ -package land.chipmunk.chipmunkmod.command; - -import com.mojang.brigadier.CommandDispatcher; -import com.mojang.brigadier.arguments.ArgumentType; -import com.mojang.brigadier.builder.LiteralArgumentBuilder; -import com.mojang.brigadier.builder.RequiredArgumentBuilder; -import com.mojang.brigadier.exceptions.CommandSyntaxException; -import net.minecraft.text.ClickEvent; -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.commands.*; - -public class CommandManager { - public CommandDispatcher dispatcher = new CommandDispatcher<>(); - public String prefix; - - 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); - MusicCommand.register(this.dispatcher); - RainbowNameCommand.register(this.dispatcher); - SayCommand.register(this.dispatcher); - AutoSkinCommand.register(this.dispatcher); - ReloadConfigCommand.register(this.dispatcher); - SelfCareCommand.register(this.dispatcher); - } - - public void executeCommand (String command) { - final MinecraftClient client = MinecraftClient.getInstance(); - - final FabricClientCommandSource commandSource = (FabricClientCommandSource) client.getNetworkHandler().getCommandSource(); - - try { - dispatcher.execute(command, commandSource); - } catch (CommandSyntaxException e) { - commandSource.sendError(Texts.toText(e.getRawMessage())); - final Text context = getContext(e); - if (context != null) commandSource.sendError(context); - } catch (Exception e) { - commandSource.sendError(Text.of(e.getMessage())); - } - } - - public Text getContext (CommandSyntaxException exception) { - final int _cursor = exception.getCursor(); - final String input = exception.getInput(); - - if (input == null || _cursor < 0) { - return null; - } - final MutableText text = Text.literal("") - .formatted(Formatting.GRAY); - text.setStyle(text.getStyle().withClickEvent(new ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, prefix + input))); - - final int cursor = Math.min(input.length(), _cursor); - - if (cursor > CommandSyntaxException.CONTEXT_AMOUNT) { - text.append(Text.literal("...")); - } - - 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)); - - 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); } -} +package land.chipmunk.chipmunkmod.command; + +import com.mojang.brigadier.CommandDispatcher; +import com.mojang.brigadier.arguments.ArgumentType; +import com.mojang.brigadier.builder.LiteralArgumentBuilder; +import com.mojang.brigadier.builder.RequiredArgumentBuilder; +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import net.minecraft.text.ClickEvent; +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.commands.*; + +public class CommandManager { + public CommandDispatcher dispatcher = new CommandDispatcher<>(); + public String prefix; + + 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); + MusicCommand.register(this.dispatcher); + RainbowNameCommand.register(this.dispatcher); + SayCommand.register(this.dispatcher); + AutoSkinCommand.register(this.dispatcher); + ReloadConfigCommand.register(this.dispatcher); + SelfCareCommand.register(this.dispatcher); + } + + public void executeCommand(String command) { + final MinecraftClient client = MinecraftClient.getInstance(); + + final FabricClientCommandSource commandSource = (FabricClientCommandSource) client.getNetworkHandler().getCommandSource(); + + try { + dispatcher.execute(command, commandSource); + } catch (CommandSyntaxException e) { + commandSource.sendError(Texts.toText(e.getRawMessage())); + final Text context = getContext(e); + if (context != null) commandSource.sendError(context); + } catch (Exception e) { + commandSource.sendError(Text.of(e.getMessage())); + } + } + + public Text getContext(CommandSyntaxException exception) { + final int _cursor = exception.getCursor(); + final String input = exception.getInput(); + + if (input == null || _cursor < 0) { + return null; + } + final MutableText text = Text.literal("") + .formatted(Formatting.GRAY); + text.setStyle(text.getStyle().withClickEvent(new ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, prefix + input))); + + final int cursor = Math.min(input.length(), _cursor); + + if (cursor > CommandSyntaxException.CONTEXT_AMOUNT) { + text.append(Text.literal("...")); + } + + 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)); + + 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); + } +} diff --git a/src/main/java/land/chipmunk/chipmunkmod/commands/CoreCommand.java b/src/main/java/land/chipmunk/chipmunkmod/commands/CoreCommand.java index 2efdc8a..00f3fcd 100644 --- a/src/main/java/land/chipmunk/chipmunkmod/commands/CoreCommand.java +++ b/src/main/java/land/chipmunk/chipmunkmod/commands/CoreCommand.java @@ -1,106 +1,108 @@ -package land.chipmunk.chipmunkmod.commands; - -import com.google.common.base.Suppliers; -import com.mojang.brigadier.Command; -import com.mojang.brigadier.CommandDispatcher; -import com.mojang.brigadier.context.CommandContext; - -import static com.mojang.brigadier.arguments.BoolArgumentType.bool; -import static com.mojang.brigadier.arguments.BoolArgumentType.getBool; -import static land.chipmunk.chipmunkmod.command.CommandManager.literal; -import static land.chipmunk.chipmunkmod.command.CommandManager.argument; -import static com.mojang.brigadier.arguments.StringArgumentType.greedyString; -import static com.mojang.brigadier.arguments.StringArgumentType.getString; - -import land.chipmunk.chipmunkmod.util.TextUtilities; -import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource; -import net.minecraft.text.Text; -import net.minecraft.nbt.NbtCompound; -import java.util.concurrent.CompletableFuture; -import land.chipmunk.chipmunkmod.modules.CommandCore; - -public class CoreCommand { - public static void register (CommandDispatcher dispatcher) { - dispatcher.register( - literal("core") - .then( - literal("run") - .then( - argument("command", greedyString()) - .executes(c -> run(c)) - ) - ) - - .then( - literal("runTracked") - .then( - argument("command", greedyString()) - .executes(c -> runTracked(c)) - ) - ) - - .then(literal("refill").executes(c -> refill(c))) - .then(literal("move").executes(c -> move(c))) - - .then( - literal("runFillCommand") - .then( - argument("enabled", bool()) - .executes(c -> runFillCommand(c)) - ) - ) - ); - } - - public static int run (CommandContext context) { - CommandCore.INSTANCE.run(getString(context, "command")); - - return Command.SINGLE_SUCCESS; - } - - public static int runTracked (CommandContext context) { - final FabricClientCommandSource source = context.getSource(); - - final String command = getString(context, "command"); - - final CompletableFuture future = CommandCore.INSTANCE.runTracked(command); - future.thenApply(tag -> { - try { - final String output = tag.getString("LastOutput"); - if (output != null) source.sendFeedback(TextUtilities.fromJson(output)); - } catch (Exception e) { - e.printStackTrace(); - } - - return tag; - }); - - return Command.SINGLE_SUCCESS; - } - - public static int refill (CommandContext context) { - CommandCore.INSTANCE.refill(); - - return Command.SINGLE_SUCCESS; - } - - public static int move (CommandContext context) { - final FabricClientCommandSource source = context.getSource(); - - CommandCore.INSTANCE.move(source.getClient().player.getPos()); - - return Command.SINGLE_SUCCESS; - } - - public static int runFillCommand(CommandContext context) { - final FabricClientCommandSource source = context.getSource(); - - final boolean bool = getBool(context, "enabled"); - - CommandCore.INSTANCE.runFillCommand = bool; - - source.sendFeedback(Text.literal("Running fill commands are now " + (bool ? "enabled" : "disabled"))); - - return Command.SINGLE_SUCCESS; - } -} +package land.chipmunk.chipmunkmod.commands; + +import com.google.common.base.Suppliers; +import com.mojang.brigadier.Command; +import com.mojang.brigadier.CommandDispatcher; +import com.mojang.brigadier.context.CommandContext; + +import static com.mojang.brigadier.arguments.BoolArgumentType.bool; +import static com.mojang.brigadier.arguments.BoolArgumentType.getBool; +import static land.chipmunk.chipmunkmod.command.CommandManager.literal; +import static land.chipmunk.chipmunkmod.command.CommandManager.argument; +import static com.mojang.brigadier.arguments.StringArgumentType.greedyString; +import static com.mojang.brigadier.arguments.StringArgumentType.getString; + +import land.chipmunk.chipmunkmod.util.TextUtilities; +import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource; +import net.minecraft.text.Text; +import net.minecraft.nbt.NbtCompound; + +import java.util.concurrent.CompletableFuture; + +import land.chipmunk.chipmunkmod.modules.CommandCore; + +public class CoreCommand { + public static void register(CommandDispatcher dispatcher) { + dispatcher.register( + literal("core") + .then( + literal("run") + .then( + argument("command", greedyString()) + .executes(c -> run(c)) + ) + ) + + .then( + literal("runTracked") + .then( + argument("command", greedyString()) + .executes(c -> runTracked(c)) + ) + ) + + .then(literal("refill").executes(c -> refill(c))) + .then(literal("move").executes(c -> move(c))) + + .then( + literal("runFillCommand") + .then( + argument("enabled", bool()) + .executes(c -> runFillCommand(c)) + ) + ) + ); + } + + public static int run(CommandContext context) { + CommandCore.INSTANCE.run(getString(context, "command")); + + return Command.SINGLE_SUCCESS; + } + + public static int runTracked(CommandContext context) { + final FabricClientCommandSource source = context.getSource(); + + final String command = getString(context, "command"); + + final CompletableFuture future = CommandCore.INSTANCE.runTracked(command); + future.thenApply(tag -> { + try { + final String output = tag.getString("LastOutput"); + if (output != null) source.sendFeedback(TextUtilities.fromJson(output)); + } catch (Exception e) { + e.printStackTrace(); + } + + return tag; + }); + + return Command.SINGLE_SUCCESS; + } + + public static int refill(CommandContext context) { + CommandCore.INSTANCE.refill(); + + return Command.SINGLE_SUCCESS; + } + + public static int move(CommandContext context) { + final FabricClientCommandSource source = context.getSource(); + + CommandCore.INSTANCE.move(source.getClient().player.getPos()); + + return Command.SINGLE_SUCCESS; + } + + public static int runFillCommand(CommandContext context) { + final FabricClientCommandSource source = context.getSource(); + + final boolean bool = getBool(context, "enabled"); + + CommandCore.INSTANCE.runFillCommand = bool; + + source.sendFeedback(Text.literal("Running fill commands is now " + (bool ? "enabled" : "disabled"))); + + return Command.SINGLE_SUCCESS; + } +} diff --git a/src/main/java/land/chipmunk/chipmunkmod/commands/ItemCommand.java b/src/main/java/land/chipmunk/chipmunkmod/commands/ItemCommand.java index c2837a0..59c92dd 100644 --- a/src/main/java/land/chipmunk/chipmunkmod/commands/ItemCommand.java +++ b/src/main/java/land/chipmunk/chipmunkmod/commands/ItemCommand.java @@ -4,12 +4,14 @@ 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; @@ -18,7 +20,7 @@ import net.minecraft.item.ItemStack; import net.minecraft.text.Text; public class ItemCommand { - public static void register (CommandDispatcher dispatcher, CommandRegistryAccess commandRegistryAccess) { + public static void register(CommandDispatcher dispatcher, CommandRegistryAccess commandRegistryAccess) { dispatcher.register( literal("item") .then( @@ -32,11 +34,11 @@ public class ItemCommand { ); } - public static int setItem (CommandContext context) throws CommandSyntaxException { + public static int setItem(CommandContext context) throws CommandSyntaxException { return setItem(context, getInteger(context, "count")); } - public static int setItem (CommandContext context, int count) throws CommandSyntaxException { + public static int setItem(CommandContext context, int count) throws CommandSyntaxException { final FabricClientCommandSource source = context.getSource(); final MinecraftClient client = source.getClient(); diff --git a/src/main/java/land/chipmunk/chipmunkmod/commands/TestCommand.java b/src/main/java/land/chipmunk/chipmunkmod/commands/TestCommand.java index 9fb9a00..7bbaa5c 100644 --- a/src/main/java/land/chipmunk/chipmunkmod/commands/TestCommand.java +++ b/src/main/java/land/chipmunk/chipmunkmod/commands/TestCommand.java @@ -1,24 +1,26 @@ -package land.chipmunk.chipmunkmod.commands; - -import com.mojang.brigadier.Command; -import com.mojang.brigadier.CommandDispatcher; -import com.mojang.brigadier.context.CommandContext; -import static land.chipmunk.chipmunkmod.command.CommandManager.literal; -import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource; -import net.minecraft.text.Text; - -public class TestCommand { - public static void register (CommandDispatcher dispatcher) { - dispatcher.register( - literal("test") - .executes(c -> helloWorld(c)) - ); - } - - public static int helloWorld (CommandContext context) { - final FabricClientCommandSource source = context.getSource(); - source.sendFeedback(Text.literal("Hello, world!")); - - return Command.SINGLE_SUCCESS; - } -} +package land.chipmunk.chipmunkmod.commands; + +import com.mojang.brigadier.Command; +import com.mojang.brigadier.CommandDispatcher; +import com.mojang.brigadier.context.CommandContext; + +import static land.chipmunk.chipmunkmod.command.CommandManager.literal; + +import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource; +import net.minecraft.text.Text; + +public class TestCommand { + public static void register(CommandDispatcher dispatcher) { + dispatcher.register( + literal("test") + .executes(c -> helloWorld(c)) + ); + } + + public static int helloWorld(CommandContext context) { + final FabricClientCommandSource source = context.getSource(); + source.sendFeedback(Text.literal("Hello, world!")); + + return Command.SINGLE_SUCCESS; + } +} diff --git a/src/main/java/land/chipmunk/chipmunkmod/commands/UsernameCommand.java b/src/main/java/land/chipmunk/chipmunkmod/commands/UsernameCommand.java index 6a506ac..eb96209 100644 --- a/src/main/java/land/chipmunk/chipmunkmod/commands/UsernameCommand.java +++ b/src/main/java/land/chipmunk/chipmunkmod/commands/UsernameCommand.java @@ -1,68 +1,71 @@ -package land.chipmunk.chipmunkmod.commands; - -import com.mojang.brigadier.Command; -import com.mojang.brigadier.CommandDispatcher; -import com.mojang.brigadier.context.CommandContext; -import static com.mojang.brigadier.arguments.StringArgumentType.greedyString; -import static com.mojang.brigadier.arguments.StringArgumentType.getString; -import static land.chipmunk.chipmunkmod.command.CommandManager.literal; -import static land.chipmunk.chipmunkmod.command.CommandManager.argument; -import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.gui.screen.TitleScreen; -import net.minecraft.client.gui.screen.multiplayer.ConnectScreen; -import net.minecraft.client.network.ServerInfo; -import net.minecraft.client.network.ServerAddress; -import net.minecraft.client.session.Session; -import net.minecraft.text.Text; -import com.mojang.brigadier.exceptions.CommandSyntaxException; -import com.mojang.brigadier.exceptions.SimpleCommandExceptionType; -import java.util.Optional; -import java.util.UUID; - -import land.chipmunk.chipmunkmod.mixin.MinecraftClientAccessor; - -public class UsernameCommand { - private static final Session ORIGINAL_SESSION = MinecraftClient.getInstance().getSession(); - private static final SimpleCommandExceptionType USERNAME_TOO_LONG = new SimpleCommandExceptionType(Text.translatable("The specified username is longer than 16 characters")); - - public static void register (CommandDispatcher dispatcher) { - dispatcher.register( - literal("username") - .then( - literal("set") - .then( - argument("username", greedyString()) - .executes(c -> updateUsername(c)) - ) - ) - .then( - literal("revert") - .executes(c -> updateSession(c, ORIGINAL_SESSION)) - ) - ); - } - - public static int updateUsername (CommandContext context) throws CommandSyntaxException { - final String username = getString(context, "username"); - if (username.length() > 16) throw USERNAME_TOO_LONG.create(); - final Session session = new Session(username, new UUID(0L, 0L), "", Optional.empty(), Optional.empty(), Session.AccountType.MOJANG); - return updateSession(context, session); - } - - public static int updateSession (CommandContext context, Session session) throws CommandSyntaxException { - final FabricClientCommandSource source = context.getSource(); - - final MinecraftClient client = source.getClient(); - - ((MinecraftClientAccessor) client).session(session); - - // TODO: Put this in a separate class - final ServerInfo info = client.getCurrentServerEntry(); - client.world.disconnect(); - client.disconnect(); - ConnectScreen.connect(new TitleScreen(), client, ServerAddress.parse(info.address), info, false, null); - - return Command.SINGLE_SUCCESS; - } -} +package land.chipmunk.chipmunkmod.commands; + +import com.mojang.brigadier.Command; +import com.mojang.brigadier.CommandDispatcher; +import com.mojang.brigadier.context.CommandContext; + +import static com.mojang.brigadier.arguments.StringArgumentType.greedyString; +import static com.mojang.brigadier.arguments.StringArgumentType.getString; +import static land.chipmunk.chipmunkmod.command.CommandManager.literal; +import static land.chipmunk.chipmunkmod.command.CommandManager.argument; + +import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.screen.TitleScreen; +import net.minecraft.client.gui.screen.multiplayer.ConnectScreen; +import net.minecraft.client.network.ServerInfo; +import net.minecraft.client.network.ServerAddress; +import net.minecraft.client.session.Session; +import net.minecraft.text.Text; +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import com.mojang.brigadier.exceptions.SimpleCommandExceptionType; + +import java.util.Optional; +import java.util.UUID; + +import land.chipmunk.chipmunkmod.mixin.MinecraftClientAccessor; + +public class UsernameCommand { + private static final Session ORIGINAL_SESSION = MinecraftClient.getInstance().getSession(); + private static final SimpleCommandExceptionType USERNAME_TOO_LONG = new SimpleCommandExceptionType(Text.translatable("The specified username is longer than 16 characters")); + + public static void register(CommandDispatcher dispatcher) { + dispatcher.register( + literal("username") + .then( + literal("set") + .then( + argument("username", greedyString()) + .executes(c -> updateUsername(c)) + ) + ) + .then( + literal("revert") + .executes(c -> updateSession(c, ORIGINAL_SESSION)) + ) + ); + } + + public static int updateUsername(CommandContext context) throws CommandSyntaxException { + final String username = getString(context, "username"); + if (username.length() > 16) throw USERNAME_TOO_LONG.create(); + final Session session = new Session(username, new UUID(0L, 0L), "", Optional.empty(), Optional.empty(), Session.AccountType.MOJANG); + return updateSession(context, session); + } + + public static int updateSession(CommandContext context, Session session) throws CommandSyntaxException { + final FabricClientCommandSource source = context.getSource(); + + final MinecraftClient client = source.getClient(); + + ((MinecraftClientAccessor) client).session(session); + + // TODO: Put this in a separate class + final ServerInfo info = client.getCurrentServerEntry(); + client.world.disconnect(); + client.disconnect(); + ConnectScreen.connect(new TitleScreen(), client, ServerAddress.parse(info.address), info, false, null); + + return Command.SINGLE_SUCCESS; + } +} diff --git a/src/main/java/land/chipmunk/chipmunkmod/commands/ValidateCommand.java b/src/main/java/land/chipmunk/chipmunkmod/commands/ValidateCommand.java index 9923ea1..25c4d2c 100644 --- a/src/main/java/land/chipmunk/chipmunkmod/commands/ValidateCommand.java +++ b/src/main/java/land/chipmunk/chipmunkmod/commands/ValidateCommand.java @@ -1,30 +1,30 @@ -package land.chipmunk.chipmunkmod.commands; - -import com.mojang.brigadier.CommandDispatcher; -import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource; -import net.minecraft.text.Text; - -import static com.mojang.brigadier.arguments.StringArgumentType.getString; -import static com.mojang.brigadier.arguments.StringArgumentType.greedyString; -import static land.chipmunk.chipmunkmod.command.CommandManager.argument; -import static land.chipmunk.chipmunkmod.command.CommandManager.literal; -import static land.chipmunk.chipmunkmod.util.BotValidationUtilities.*; - -public class ValidateCommand { - public static void register (CommandDispatcher dispatcher) { - dispatcher.register( - literal("validate") - .then(literal("hbot").then(argument("command", greedyString()).executes(c -> hbot(getString(c, "command"))))) - .then(literal("sbot").then(argument("command", greedyString()).executes(c -> sbot(getString(c, "command"))))) - // .then(literal("chipmunk").then(argument("command", greedyString()).executes(c -> chipmunk(getString(c, "command"))))) - .then(literal("chomens").then(argument("command", greedyString()).executes(c -> { - c.getSource().sendFeedback(Text.literal("Warning: Manual ChomeNS Bot validation is deprecated. Please use the completions from typing the bot's prefix.")); - - return chomens(getString(c, "command")); - }))) - .then(literal("fnfboyfriend").then(argument("command", greedyString()).executes(c -> fnfboyfriend(getString(c, "command"))))) - .then(literal("nbot").then(argument("command", greedyString()).executes(c -> nbot(getString(c, "command"))))) - .then(literal("kittycorp").then(argument("command", greedyString()).executes(c -> kittycorp(getString(c, "command"))))) - ); - } -} +package land.chipmunk.chipmunkmod.commands; + +import com.mojang.brigadier.CommandDispatcher; +import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource; +import net.minecraft.text.Text; + +import static com.mojang.brigadier.arguments.StringArgumentType.getString; +import static com.mojang.brigadier.arguments.StringArgumentType.greedyString; +import static land.chipmunk.chipmunkmod.command.CommandManager.argument; +import static land.chipmunk.chipmunkmod.command.CommandManager.literal; +import static land.chipmunk.chipmunkmod.util.BotValidationUtilities.*; + +public class ValidateCommand { + public static void register(CommandDispatcher dispatcher) { + dispatcher.register( + literal("validate") + .then(literal("hbot").then(argument("command", greedyString()).executes(c -> hbot(getString(c, "command"))))) + .then(literal("sbot").then(argument("command", greedyString()).executes(c -> sbot(getString(c, "command"))))) + // .then(literal("chipmunk").then(argument("command", greedyString()).executes(c -> chipmunk(getString(c, "command"))))) + .then(literal("chomens").then(argument("command", greedyString()).executes(c -> { + c.getSource().sendFeedback(Text.literal("Warning: Manual ChomeNS Bot validation is deprecated. Please use the completions from typing the bot's prefix.")); + + return chomens(getString(c, "command")); + }))) + .then(literal("fnfboyfriend").then(argument("command", greedyString()).executes(c -> fnfboyfriend(getString(c, "command"))))) + .then(literal("nbot").then(argument("command", greedyString()).executes(c -> nbot(getString(c, "command"))))) + .then(literal("kittycorp").then(argument("command", greedyString()).executes(c -> kittycorp(getString(c, "command"))))) + ); + } +} diff --git a/src/main/java/land/chipmunk/chipmunkmod/config/Configuration.java b/src/main/java/land/chipmunk/chipmunkmod/config/Configuration.java index d2da3a8..e0b03a5 100644 --- a/src/main/java/land/chipmunk/chipmunkmod/config/Configuration.java +++ b/src/main/java/land/chipmunk/chipmunkmod/config/Configuration.java @@ -9,80 +9,86 @@ import org.spongepowered.configurate.objectmapping.ConfigSerializable; @ConfigSerializable public class Configuration { - public CommandManager commands = new CommandManager(); - public CommandCore core = new CommandCore(); - public Bots bots = new Bots(); - public CustomChat customChat = new CustomChat(); - public String autoSkinUsername = "off"; + public CommandManager commands = new CommandManager(); + public CommandCore core = new CommandCore(); + public Bots bots = new Bots(); + public CustomChat customChat = new CustomChat(); + public String autoSkinUsername = "off"; - @ConfigSerializable - public static class CommandManager { - public String prefix = "."; - } - - @ConfigSerializable - public static class CommandCore { - public BlockBox relativeArea = BlockBox.create(new BlockPos(0, 0, 0), new BlockPos(15, 0, 15)); - } - - @ConfigSerializable - public static class Bots { - public BotInfo hbot = new BotInfo("#", null); - public BotInfo sbot = new BotInfo(":", null); - public BotInfo chipmunk = new BotInfo("'", null); - public ChomeNSBotInfo chomens = new ChomeNSBotInfo("*", null, null, null); - public BotInfo fnfboyfriend = new BotInfo("~", null); - public BotInfo nbot = new BotInfo("?", null); - public BotInfo kittycorp = new BotInfo("^", null); - public TestBotInfo testbot = new TestBotInfo("-", null); - } - - @ConfigSerializable - public static class ChomeNSBotInfo { - public String prefix; - public @Nullable String key; - public @Nullable String authKey; - public @Nullable String formatKey; - - public ChomeNSBotInfo() {} - public ChomeNSBotInfo (String prefix, @Nullable String key, @Nullable String authKey, @Nullable String formatKey) { - this.prefix = prefix; - this.key = key; - this.authKey = authKey; - this.formatKey = formatKey; + @ConfigSerializable + public static class CommandManager { + public String prefix = "."; } - } - @ConfigSerializable - public static class TestBotInfo { - public String prefix; - public @Nullable String webhookUrl; - - public TestBotInfo() {} - public TestBotInfo (String prefix, @Nullable String webhookUrl) { - this.prefix = prefix; - this.webhookUrl = webhookUrl; + @ConfigSerializable + public static class CommandCore { + public BlockBox relativeArea = BlockBox.create(new BlockPos(0, 0, 0), new BlockPos(15, 0, 15)); } - } - @ConfigSerializable - public static class BotInfo { - public String prefix; - public @Nullable String key; - - public BotInfo() {} - public BotInfo (String prefix, @Nullable String key) { - this.prefix = prefix; - this.key = key; + @ConfigSerializable + public static class Bots { + public BotInfo hbot = new BotInfo("#", null); + public BotInfo sbot = new BotInfo(":", null); + public BotInfo chipmunk = new BotInfo("'", null); + public ChomeNSBotInfo chomens = new ChomeNSBotInfo("*", null, null, null); + public BotInfo fnfboyfriend = new BotInfo("~", null); + public BotInfo nbot = new BotInfo("?", null); + public BotInfo kittycorp = new BotInfo("^", null); + public TestBotInfo testbot = new TestBotInfo("-", null); } - } - @ConfigSerializable - public static class CustomChat { - public @NotNull Component format = - Component.translatable("chat.type.text", - Component.selector("@s"), - Component.text("MESSAGE") - ); - } + @ConfigSerializable + public static class ChomeNSBotInfo { + public String prefix; + public @Nullable String key; + public @Nullable String authKey; + public @Nullable String formatKey; + + public ChomeNSBotInfo() { + } + + public ChomeNSBotInfo(String prefix, @Nullable String key, @Nullable String authKey, @Nullable String formatKey) { + this.prefix = prefix; + this.key = key; + this.authKey = authKey; + this.formatKey = formatKey; + } + } + + @ConfigSerializable + public static class TestBotInfo { + public String prefix; + public @Nullable String webhookUrl; + + public TestBotInfo() { + } + + public TestBotInfo(String prefix, @Nullable String webhookUrl) { + this.prefix = prefix; + this.webhookUrl = webhookUrl; + } + } + + @ConfigSerializable + public static class BotInfo { + public String prefix; + public @Nullable String key; + + public BotInfo() { + } + + public BotInfo(String prefix, @Nullable String key) { + this.prefix = prefix; + this.key = key; + } + } + + @ConfigSerializable + public static class CustomChat { + public @NotNull Component format = + Component.translatable("chat.type.text", + Component.selector("@s"), + Component.text("MESSAGE") + ); + } } diff --git a/src/main/java/land/chipmunk/chipmunkmod/data/ChomeNSBotCommand.java b/src/main/java/land/chipmunk/chipmunkmod/data/ChomeNSBotCommand.java index 8e8ed87..18864ab 100644 --- a/src/main/java/land/chipmunk/chipmunkmod/data/ChomeNSBotCommand.java +++ b/src/main/java/land/chipmunk/chipmunkmod/data/ChomeNSBotCommand.java @@ -27,10 +27,10 @@ public record ChomeNSBotCommand(String name, TrustLevel trustLevel, List ChipmunkMod.CONFIG.bots.chomens.prefix + name, trustLevel, List.of()); final List aliases = children.stream() - .skip(2) - .map(TextUtilities::plainOrNull) - .filter(Objects::nonNull) - .toList(); + .skip(2) + .map(TextUtilities::plainOrNull) + .filter(Objects::nonNull) + .toList(); return new ChomeNSBotCommand( ChipmunkMod.CONFIG.bots.chomens.prefix + name, trustLevel, aliases); } @@ -47,7 +47,8 @@ public record ChomeNSBotCommand(String name, TrustLevel trustLevel, List try { return TrustLevel.valueOf(trustLevelString); - } catch (final IllegalArgumentException ignored) {} + } catch (final IllegalArgumentException ignored) { + } return null; } diff --git a/src/main/java/land/chipmunk/chipmunkmod/mixin/ChatInputSuggestorMixin.java b/src/main/java/land/chipmunk/chipmunkmod/mixin/ChatInputSuggestorMixin.java index 314aaf6..74a6ff7 100644 --- a/src/main/java/land/chipmunk/chipmunkmod/mixin/ChatInputSuggestorMixin.java +++ b/src/main/java/land/chipmunk/chipmunkmod/mixin/ChatInputSuggestorMixin.java @@ -1,99 +1,100 @@ -package land.chipmunk.chipmunkmod.mixin; - -import com.mojang.brigadier.CommandDispatcher; -import com.mojang.brigadier.StringReader; -import com.mojang.brigadier.suggestion.Suggestions; -import com.mojang.brigadier.suggestion.SuggestionsBuilder; -import land.chipmunk.chipmunkmod.ChipmunkMod; -import land.chipmunk.chipmunkmod.command.CommandManager; -import land.chipmunk.chipmunkmod.data.ChomeNSBotCommand; -import land.chipmunk.chipmunkmod.modules.ChomeNSBotCommandSuggestions; -import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.gui.widget.TextFieldWidget; -import net.minecraft.client.network.ClientPlayNetworkHandler; -import net.minecraft.client.network.ClientPlayerEntity; -import net.minecraft.command.CommandSource; -import org.spongepowered.asm.mixin.Final; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Mutable; -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 java.util.List; -import java.util.concurrent.CompletableFuture; - -@Mixin(net.minecraft.client.gui.screen.ChatInputSuggestor.class) -public class ChatInputSuggestorMixin { - @Shadow - private CompletableFuture pendingSuggestions; - - @Shadow - public void show (boolean narrateFirstSuggestion) {} - - @Shadow - private static int getStartOfCurrentWord (String input) { - return 0; - } - - @Mutable - @Final - @Shadow - final TextFieldWidget textField; - - public ChatInputSuggestorMixin () { - textField = null; - } - - @Inject(at = @At("TAIL"), method = "refresh()V") - public void refresh (CallbackInfo ci) { - final CommandManager commandManager = CommandManager.INSTANCE; - - final String text = this.textField.getText(); - final int cursor = this.textField.getCursor(); - - final ClientPlayerEntity player = MinecraftClient.getInstance().player; - - final String chomeNSPrefix = ChipmunkMod.CONFIG.bots.chomens.prefix; - - if (!text.contains(" ") && text.startsWith(chomeNSPrefix) && player != null) { - final String textUpToCursor = text.substring(0, cursor); - - final List commands = ChomeNSBotCommandSuggestions.INSTANCE.commands - .stream() - .map(ChomeNSBotCommand::name) - .toList(); - - pendingSuggestions = CommandSource.suggestMatching( - commands, - new SuggestionsBuilder( - textUpToCursor, - getStartOfCurrentWord(textUpToCursor) - ) - ); - - pendingSuggestions.thenRun(() -> { - if (!pendingSuggestions.isDone()) return; - - show(true); - }); - } else if (cursor >= commandManager.prefix.length() && text.startsWith(commandManager.prefix)) { - final StringReader reader = new StringReader(text); - reader.setCursor(commandManager.prefix.length()); // Skip the prefix - - final MinecraftClient client = MinecraftClient.getInstance(); - - final ClientPlayNetworkHandler networkHandler = client.getNetworkHandler(); - - if (networkHandler == null) return; - - final CommandDispatcher dispatcher = commandManager.dispatcher; - final FabricClientCommandSource commandSource = (FabricClientCommandSource) networkHandler.getCommandSource(); - - pendingSuggestions = dispatcher.getCompletionSuggestions(dispatcher.parse(reader, commandSource), cursor); - show(true); - } - } -} +package land.chipmunk.chipmunkmod.mixin; + +import com.mojang.brigadier.CommandDispatcher; +import com.mojang.brigadier.StringReader; +import com.mojang.brigadier.suggestion.Suggestions; +import com.mojang.brigadier.suggestion.SuggestionsBuilder; +import land.chipmunk.chipmunkmod.ChipmunkMod; +import land.chipmunk.chipmunkmod.command.CommandManager; +import land.chipmunk.chipmunkmod.data.ChomeNSBotCommand; +import land.chipmunk.chipmunkmod.modules.ChomeNSBotCommandSuggestions; +import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.widget.TextFieldWidget; +import net.minecraft.client.network.ClientPlayNetworkHandler; +import net.minecraft.client.network.ClientPlayerEntity; +import net.minecraft.command.CommandSource; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Mutable; +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 java.util.List; +import java.util.concurrent.CompletableFuture; + +@Mixin(net.minecraft.client.gui.screen.ChatInputSuggestor.class) +public class ChatInputSuggestorMixin { + @Shadow + private CompletableFuture pendingSuggestions; + + @Shadow + public void show(boolean narrateFirstSuggestion) { + } + + @Shadow + private static int getStartOfCurrentWord(String input) { + return 0; + } + + @Mutable + @Final + @Shadow + final TextFieldWidget textField; + + public ChatInputSuggestorMixin() { + textField = null; + } + + @Inject(at = @At("TAIL"), method = "refresh()V") + public void refresh(CallbackInfo ci) { + final CommandManager commandManager = CommandManager.INSTANCE; + + final String text = this.textField.getText(); + final int cursor = this.textField.getCursor(); + + final ClientPlayerEntity player = MinecraftClient.getInstance().player; + + final String chomeNSPrefix = ChipmunkMod.CONFIG.bots.chomens.prefix; + + if (!text.contains(" ") && text.startsWith(chomeNSPrefix) && player != null) { + final String textUpToCursor = text.substring(0, cursor); + + final List commands = ChomeNSBotCommandSuggestions.INSTANCE.commands + .stream() + .map(ChomeNSBotCommand::name) + .toList(); + + pendingSuggestions = CommandSource.suggestMatching( + commands, + new SuggestionsBuilder( + textUpToCursor, + getStartOfCurrentWord(textUpToCursor) + ) + ); + + pendingSuggestions.thenRun(() -> { + if (!pendingSuggestions.isDone()) return; + + show(true); + }); + } else if (cursor >= commandManager.prefix.length() && text.startsWith(commandManager.prefix)) { + final StringReader reader = new StringReader(text); + reader.setCursor(commandManager.prefix.length()); // Skip the prefix + + final MinecraftClient client = MinecraftClient.getInstance(); + + final ClientPlayNetworkHandler networkHandler = client.getNetworkHandler(); + + if (networkHandler == null) return; + + final CommandDispatcher dispatcher = commandManager.dispatcher; + final FabricClientCommandSource commandSource = (FabricClientCommandSource) networkHandler.getCommandSource(); + + pendingSuggestions = dispatcher.getCompletionSuggestions(dispatcher.parse(reader, commandSource), cursor); + show(true); + } + } +} diff --git a/src/main/java/land/chipmunk/chipmunkmod/mixin/ChatScreenMixin.java b/src/main/java/land/chipmunk/chipmunkmod/mixin/ChatScreenMixin.java index 8b6eafb..b49a90f 100644 --- a/src/main/java/land/chipmunk/chipmunkmod/mixin/ChatScreenMixin.java +++ b/src/main/java/land/chipmunk/chipmunkmod/mixin/ChatScreenMixin.java @@ -1,147 +1,153 @@ -package land.chipmunk.chipmunkmod.mixin; - -import com.google.gson.JsonObject; -import land.chipmunk.chipmunkmod.ChipmunkMod; -import land.chipmunk.chipmunkmod.data.ChomeNSBotCommand; -import land.chipmunk.chipmunkmod.modules.ChomeNSBotCommandSuggestions; -import land.chipmunk.chipmunkmod.util.BotValidationUtilities; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.gui.screen.ChatInputSuggestor; -import net.minecraft.client.gui.screen.Screen; -import net.minecraft.client.gui.widget.TextFieldWidget; -import net.minecraft.text.MutableText; -import net.minecraft.text.Text; -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 javax.net.ssl.HttpsURLConnection; -import java.io.IOException; -import java.io.OutputStream; -import java.net.URI; -import java.net.URISyntaxException; -import java.net.URL; -import java.util.ArrayList; -import java.util.List; - -@Mixin(value = net.minecraft.client.gui.screen.ChatScreen.class) -public abstract class ChatScreenMixin extends Screen { - @Shadow private String originalChatText; - - @Shadow private int messageHistoryIndex; - - @Shadow protected TextFieldWidget chatField; - - @Shadow ChatInputSuggestor chatInputSuggestor; - - @Shadow protected abstract void onChatFieldUpdate(String chatText); - - protected ChatScreenMixin(Text title) { - super(title); - } - - // infinite chat - @Inject(method = "init", at = @At("HEAD"), cancellable = true) - protected void init (CallbackInfo ci) { - final MinecraftClient client = MinecraftClient.getInstance(); - - this.messageHistoryIndex = client.inGameHud.getChatHud().getMessageHistory().size(); - this.chatField = new TextFieldWidget(client.advanceValidatingTextRenderer, 4, this.height - 12, this.width - 4, 12, Text.translatable("chat.editBox")) { - protected MutableText getNarrationMessage() { - return super.getNarrationMessage().append(ChatScreenMixin.this.chatInputSuggestor.getNarration()); - } - }; - this.chatField.setMaxLength(Integer.MAX_VALUE); - this.chatField.setDrawsBackground(false); - this.chatField.setText(this.originalChatText); - this.chatField.setChangedListener(this::onChatFieldUpdate); - this.chatField.setFocusUnlocked(false); - this.addSelectableChild(this.chatField); - this.chatInputSuggestor = new ChatInputSuggestor(this.client, this, this.chatField, this.textRenderer, false, false, 1, 10, true, -805306368); - this.chatInputSuggestor.setCanLeave(false); - this.chatInputSuggestor.refresh(); - - ci.cancel(); - } - - @Inject(method = "sendMessage", at = @At("HEAD"), cancellable = true) - private void sendMessage (String chatText, boolean addToHistory, CallbackInfo cir) { - final MinecraftClient client = MinecraftClient.getInstance(); - - if (addToHistory) { - client.inGameHud.getChatHud().addToMessageHistory(chatText); - } - - if (ChipmunkMod.CONFIG.bots.testbot.webhookUrl != null && chatText.startsWith(ChipmunkMod.CONFIG.bots.testbot.prefix)) { - ChipmunkMod.executorService.submit(() -> { - try { - final URL url = new URI(ChipmunkMod.CONFIG.bots.testbot.webhookUrl).toURL(); - - final HttpsURLConnection connection = (HttpsURLConnection) url.openConnection(); - connection.addRequestProperty("Content-Type", "application/json"); - connection.addRequestProperty("User-Agent", "ChipmunkMod"); - connection.setDoOutput(true); - connection.setRequestMethod("POST"); - - final JsonObject jsonObject = new JsonObject(); - - jsonObject.addProperty("username", "ChipmunkMod UwU"); - jsonObject.addProperty("content", MinecraftClient.getInstance().getSession().getUsername()); - - final OutputStream stream = connection.getOutputStream(); - stream.write(jsonObject.toString().getBytes()); - stream.flush(); - stream.close(); - - connection.getInputStream().close(); - connection.disconnect(); - } catch (IOException | URISyntaxException e) { - e.printStackTrace(); - } - }); - } else if (chatText.startsWith(ChipmunkMod.CONFIG.bots.chomens.prefix)) { - final List commands = ChomeNSBotCommandSuggestions.INSTANCE.commands; - - final List moreOrTrustedCommands = commands.stream() - .filter(command -> command.trustLevel() != ChomeNSBotCommand.TrustLevel.PUBLIC) - .map(command -> command.name().toLowerCase()) - .toList(); - - final List aliases = new ArrayList<>(); - for (ChomeNSBotCommand command : commands) { - if (command.trustLevel() == ChomeNSBotCommand.TrustLevel.PUBLIC) continue; - - aliases.addAll(command.aliases()); - } - - final String chatCommand = chatText.toLowerCase().split("\\s")[0]; - - final int prefixLength = ChipmunkMod.CONFIG.bots.chomens.prefix.length(); - - if ( - moreOrTrustedCommands.contains(chatCommand) || - aliases.contains(chatCommand.substring(prefixLength)) - ) { - try { - BotValidationUtilities.chomens(chatText.substring(prefixLength)); - - cir.cancel(); - - return; - } catch (Exception ignored) {} - } - } - - if (client.player == null) return; - - if (chatText.startsWith("/")) { - client.player.networkHandler.sendChatCommand(chatText.substring(1)); - } else { - client.player.networkHandler.sendChatMessage(chatText); - } - - cir.cancel(); - } -} +package land.chipmunk.chipmunkmod.mixin; + +import com.google.gson.JsonObject; +import land.chipmunk.chipmunkmod.ChipmunkMod; +import land.chipmunk.chipmunkmod.data.ChomeNSBotCommand; +import land.chipmunk.chipmunkmod.modules.ChomeNSBotCommandSuggestions; +import land.chipmunk.chipmunkmod.util.BotValidationUtilities; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.screen.ChatInputSuggestor; +import net.minecraft.client.gui.screen.Screen; +import net.minecraft.client.gui.widget.TextFieldWidget; +import net.minecraft.text.MutableText; +import net.minecraft.text.Text; +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 javax.net.ssl.HttpsURLConnection; +import java.io.IOException; +import java.io.OutputStream; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.URL; +import java.util.ArrayList; +import java.util.List; + +@Mixin(value = net.minecraft.client.gui.screen.ChatScreen.class) +public abstract class ChatScreenMixin extends Screen { + @Shadow + private String originalChatText; + + @Shadow + private int messageHistoryIndex; + + @Shadow + protected TextFieldWidget chatField; + + @Shadow + ChatInputSuggestor chatInputSuggestor; + + @Shadow + protected abstract void onChatFieldUpdate(String chatText); + + protected ChatScreenMixin(Text title) { + super(title); + } + + // infinite chat + @Inject(method = "init", at = @At("HEAD"), cancellable = true) + protected void init(CallbackInfo ci) { + final MinecraftClient client = MinecraftClient.getInstance(); + + this.messageHistoryIndex = client.inGameHud.getChatHud().getMessageHistory().size(); + this.chatField = new TextFieldWidget(client.advanceValidatingTextRenderer, 4, this.height - 12, this.width - 4, 12, Text.translatable("chat.editBox")) { + protected MutableText getNarrationMessage() { + return super.getNarrationMessage().append(ChatScreenMixin.this.chatInputSuggestor.getNarration()); + } + }; + this.chatField.setMaxLength(Integer.MAX_VALUE); + this.chatField.setDrawsBackground(false); + this.chatField.setText(this.originalChatText); + this.chatField.setChangedListener(this::onChatFieldUpdate); + this.chatField.setFocusUnlocked(false); + this.addSelectableChild(this.chatField); + this.chatInputSuggestor = new ChatInputSuggestor(this.client, this, this.chatField, this.textRenderer, false, false, 1, 10, true, -805306368); + this.chatInputSuggestor.setCanLeave(false); + this.chatInputSuggestor.refresh(); + + ci.cancel(); + } + + @Inject(method = "sendMessage", at = @At("HEAD"), cancellable = true) + private void sendMessage(String chatText, boolean addToHistory, CallbackInfo cir) { + final MinecraftClient client = MinecraftClient.getInstance(); + + if (addToHistory) { + client.inGameHud.getChatHud().addToMessageHistory(chatText); + } + + if (ChipmunkMod.CONFIG.bots.testbot.webhookUrl != null && chatText.startsWith(ChipmunkMod.CONFIG.bots.testbot.prefix)) { + ChipmunkMod.executorService.submit(() -> { + try { + final URL url = new URI(ChipmunkMod.CONFIG.bots.testbot.webhookUrl).toURL(); + + final HttpsURLConnection connection = (HttpsURLConnection) url.openConnection(); + connection.addRequestProperty("Content-Type", "application/json"); + connection.addRequestProperty("User-Agent", "ChipmunkMod"); + connection.setDoOutput(true); + connection.setRequestMethod("POST"); + + final JsonObject jsonObject = new JsonObject(); + + jsonObject.addProperty("username", "ChipmunkMod UwU"); + jsonObject.addProperty("content", MinecraftClient.getInstance().getSession().getUsername()); + + final OutputStream stream = connection.getOutputStream(); + stream.write(jsonObject.toString().getBytes()); + stream.flush(); + stream.close(); + + connection.getInputStream().close(); + connection.disconnect(); + } catch (IOException | URISyntaxException e) { + e.printStackTrace(); + } + }); + } else if (chatText.startsWith(ChipmunkMod.CONFIG.bots.chomens.prefix)) { + final List commands = ChomeNSBotCommandSuggestions.INSTANCE.commands; + + final List moreOrTrustedCommands = commands.stream() + .filter(command -> command.trustLevel() != ChomeNSBotCommand.TrustLevel.PUBLIC) + .map(command -> command.name().toLowerCase()) + .toList(); + + final List aliases = new ArrayList<>(); + for (ChomeNSBotCommand command : commands) { + if (command.trustLevel() == ChomeNSBotCommand.TrustLevel.PUBLIC) continue; + + aliases.addAll(command.aliases()); + } + + final String chatCommand = chatText.toLowerCase().split("\\s")[0]; + + final int prefixLength = ChipmunkMod.CONFIG.bots.chomens.prefix.length(); + + if ( + moreOrTrustedCommands.contains(chatCommand) || + aliases.contains(chatCommand.substring(prefixLength)) + ) { + try { + BotValidationUtilities.chomens(chatText.substring(prefixLength)); + + cir.cancel(); + + return; + } catch (Exception ignored) { + } + } + } + + if (client.player == null) return; + + if (chatText.startsWith("/")) { + client.player.networkHandler.sendChatCommand(chatText.substring(1)); + } else { + client.player.networkHandler.sendChatMessage(chatText); + } + + cir.cancel(); + } +} diff --git a/src/main/java/land/chipmunk/chipmunkmod/mixin/ClientConnectionMixin.java b/src/main/java/land/chipmunk/chipmunkmod/mixin/ClientConnectionMixin.java index 2043b4b..83c1169 100644 --- a/src/main/java/land/chipmunk/chipmunkmod/mixin/ClientConnectionMixin.java +++ b/src/main/java/land/chipmunk/chipmunkmod/mixin/ClientConnectionMixin.java @@ -1,96 +1,96 @@ -package land.chipmunk.chipmunkmod.mixin; - -import io.netty.channel.ChannelHandlerContext; -import land.chipmunk.chipmunkmod.listeners.Listener; -import land.chipmunk.chipmunkmod.listeners.ListenerManager; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.world.ClientWorld; -import net.minecraft.network.listener.PacketListener; -import net.minecraft.network.packet.Packet; -import net.minecraft.network.packet.c2s.play.RequestCommandCompletionsC2SPacket; -import net.minecraft.network.packet.s2c.play.ParticleS2CPacket; -import net.minecraft.network.packet.s2c.play.PlaySoundS2CPacket; -import net.minecraft.sound.SoundEvent; -import net.minecraft.util.Identifier; -import org.spongepowered.asm.mixin.Mixin; -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 java.util.regex.Matcher; -import java.util.regex.Pattern; - -@Mixin(net.minecraft.network.ClientConnection.class) -public class ClientConnectionMixin { - @Unique - private static final double MAX_PARTICLES_PER_PACKET = 1000; - @Unique - private static final Pattern CUSTOM_PITCH_PATTERN = Pattern.compile(".*\\.pitch\\.(.*)"); - - @Inject(method = "exceptionCaught", at = @At("HEAD"), cancellable = true) - private void exceptionCaught (ChannelHandlerContext context, Throwable ex, CallbackInfo ci) { - ci.cancel(); - ex.printStackTrace(); - } - - @Inject(method = "handlePacket", at = @At("HEAD"), cancellable = true) - private static void handlePacket (Packet packet, PacketListener _listener, CallbackInfo ci) { - for (Listener listener : ListenerManager.listeners) { - listener.packetReceived(packet); - } - - final MinecraftClient client = MinecraftClient.getInstance(); - - // please don't skid this.,. - // mabe mabe mabe - if (packet instanceof ParticleS2CPacket t_packet) { - if (t_packet.getCount() > MAX_PARTICLES_PER_PACKET) { - ci.cancel(); - } - } else if (packet instanceof PlaySoundS2CPacket t_packet) { - final SoundEvent soundEvent = t_packet.getSound().value(); - - final Identifier sound = soundEvent.id(); - - final Matcher matcher = CUSTOM_PITCH_PATTERN.matcher(sound.getPath()); - - if (!matcher.find()) return; - - try { - final String stringPitch = matcher.group(1); - - final float pitch = Float.parseFloat(stringPitch); - - final ClientWorld world = client.world; - - if (world == null) return; - - // huge mess - final SoundEvent newSound = SoundEvent.of(Identifier.of(sound.getNamespace(), sound.getPath().substring(0, sound.getPath().length() - (".pitch." + stringPitch).length()))); - - client.executeSync(() -> world.playSound(client.player, t_packet.getX(), t_packet.getY(), t_packet.getZ(), newSound, t_packet.getCategory(), t_packet.getVolume(), pitch, t_packet.getSeed())); - - ci.cancel(); - } catch (NumberFormatException e) { - e.printStackTrace(); - } - - if (t_packet.getVolume() == 1 && sound.getPath().equals("entity.enderman.scream")) ci.cancel(); - } - } - - @Inject(at = @At("HEAD"), method = "send(Lnet/minecraft/network/packet/Packet;)V", cancellable = true) - private void sendPacket (Packet packet, CallbackInfo ci) { - if (packet instanceof RequestCommandCompletionsC2SPacket t_packet) { - if (t_packet.getPartialCommand().length() > 2048) { - ci.cancel(); - return; - } - } - - for (Listener listener : ListenerManager.listeners) { - listener.packetSent(packet); - } - } -} +package land.chipmunk.chipmunkmod.mixin; + +import io.netty.channel.ChannelHandlerContext; +import land.chipmunk.chipmunkmod.listeners.Listener; +import land.chipmunk.chipmunkmod.listeners.ListenerManager; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.world.ClientWorld; +import net.minecraft.network.listener.PacketListener; +import net.minecraft.network.packet.Packet; +import net.minecraft.network.packet.c2s.play.RequestCommandCompletionsC2SPacket; +import net.minecraft.network.packet.s2c.play.ParticleS2CPacket; +import net.minecraft.network.packet.s2c.play.PlaySoundS2CPacket; +import net.minecraft.sound.SoundEvent; +import net.minecraft.util.Identifier; +import org.spongepowered.asm.mixin.Mixin; +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 java.util.regex.Matcher; +import java.util.regex.Pattern; + +@Mixin(net.minecraft.network.ClientConnection.class) +public class ClientConnectionMixin { + @Unique + private static final double MAX_PARTICLES_PER_PACKET = 1000; + @Unique + private static final Pattern CUSTOM_PITCH_PATTERN = Pattern.compile(".*\\.pitch\\.(.*)"); + + @Inject(method = "exceptionCaught", at = @At("HEAD"), cancellable = true) + private void exceptionCaught(ChannelHandlerContext context, Throwable ex, CallbackInfo ci) { + ci.cancel(); + ex.printStackTrace(); + } + + @Inject(method = "handlePacket", at = @At("HEAD"), cancellable = true) + private static void handlePacket(Packet packet, PacketListener _listener, CallbackInfo ci) { + for (Listener listener : ListenerManager.listeners) { + listener.packetReceived(packet); + } + + final MinecraftClient client = MinecraftClient.getInstance(); + + // please don't skid this.,. + // mabe mabe mabe + if (packet instanceof ParticleS2CPacket t_packet) { + if (t_packet.getCount() > MAX_PARTICLES_PER_PACKET) { + ci.cancel(); + } + } else if (packet instanceof PlaySoundS2CPacket t_packet) { + final SoundEvent soundEvent = t_packet.getSound().value(); + + final Identifier sound = soundEvent.id(); + + final Matcher matcher = CUSTOM_PITCH_PATTERN.matcher(sound.getPath()); + + if (!matcher.find()) return; + + try { + final String stringPitch = matcher.group(1); + + final float pitch = Float.parseFloat(stringPitch); + + final ClientWorld world = client.world; + + if (world == null) return; + + // huge mess + final SoundEvent newSound = SoundEvent.of(Identifier.of(sound.getNamespace(), sound.getPath().substring(0, sound.getPath().length() - (".pitch." + stringPitch).length()))); + + client.executeSync(() -> world.playSound(client.player, t_packet.getX(), t_packet.getY(), t_packet.getZ(), newSound, t_packet.getCategory(), t_packet.getVolume(), pitch, t_packet.getSeed())); + + ci.cancel(); + } catch (NumberFormatException e) { + e.printStackTrace(); + } + + if (t_packet.getVolume() == 1 && sound.getPath().equals("entity.enderman.scream")) ci.cancel(); + } + } + + @Inject(at = @At("HEAD"), method = "send(Lnet/minecraft/network/packet/Packet;)V", cancellable = true) + private void sendPacket(Packet packet, CallbackInfo ci) { + if (packet instanceof RequestCommandCompletionsC2SPacket t_packet) { + if (t_packet.getPartialCommand().length() > 2048) { + ci.cancel(); + return; + } + } + + for (Listener listener : ListenerManager.listeners) { + listener.packetSent(packet); + } + } +} diff --git a/src/main/java/land/chipmunk/chipmunkmod/mixin/ClientPlayNetworkHandlerMixin.java b/src/main/java/land/chipmunk/chipmunkmod/mixin/ClientPlayNetworkHandlerMixin.java index 461957e..e540b2a 100644 --- a/src/main/java/land/chipmunk/chipmunkmod/mixin/ClientPlayNetworkHandlerMixin.java +++ b/src/main/java/land/chipmunk/chipmunkmod/mixin/ClientPlayNetworkHandlerMixin.java @@ -1,128 +1,136 @@ -package land.chipmunk.chipmunkmod.mixin; - -import com.mojang.brigadier.CommandDispatcher; -import land.chipmunk.chipmunkmod.ChipmunkMod; -import land.chipmunk.chipmunkmod.command.CommandManager; -import land.chipmunk.chipmunkmod.listeners.Listener; -import land.chipmunk.chipmunkmod.listeners.ListenerManager; -import land.chipmunk.chipmunkmod.modules.*; -import land.chipmunk.chipmunkmod.modules.custom_chat.CustomChat; -import net.minecraft.client.MinecraftClient; -import net.minecraft.command.CommandRegistryAccess; -import net.minecraft.command.CommandSource; -import net.minecraft.network.encryption.NetworkEncryptionUtils; -import net.minecraft.network.message.LastSeenMessagesCollector; -import net.minecraft.network.message.MessageBody; -import net.minecraft.network.message.MessageChain; -import net.minecraft.network.message.MessageSignatureData; -import net.minecraft.network.packet.c2s.play.ChatMessageC2SPacket; -import net.minecraft.network.packet.s2c.play.CommandTreeS2CPacket; -import net.minecraft.network.packet.s2c.play.GameJoinS2CPacket; -import net.minecraft.network.packet.s2c.play.GameMessageS2CPacket; -import net.minecraft.registry.DynamicRegistryManager; -import net.minecraft.resource.featuretoggle.FeatureSet; -import net.minecraft.text.PlainTextContent; -import net.minecraft.text.Text; -import net.minecraft.text.TranslatableTextContent; -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; - -import java.time.Instant; - -@Mixin(value = net.minecraft.client.network.ClientPlayNetworkHandler.class, priority = 1001) -public class ClientPlayNetworkHandlerMixin { - @Final - @Shadow private FeatureSet enabledFeatures; - @Final - @Shadow private DynamicRegistryManager.Immutable combinedDynamicRegistries; - @Shadow private LastSeenMessagesCollector lastSeenMessagesCollector; - @Shadow private MessageChain.Packer messagePacker; - @Shadow private CommandDispatcher commandDispatcher; - - @Inject(method = "onGameJoin", at = @At("TAIL")) - private void onGameJoin (GameJoinS2CPacket packet, CallbackInfo ci) { - final CommandRegistryAccess commandRegistryAccess = CommandRegistryAccess.of(this.combinedDynamicRegistries, this.enabledFeatures); - - KaboomCheck.INSTANCE.onJoin(); - CommandManager.INSTANCE = new CommandManager(ChipmunkMod.CONFIG.commands.prefix, commandRegistryAccess); - SelfCare.INSTANCE.onJoin(); - CommandCore.INSTANCE.init(); - SongPlayer.INSTANCE.coreReady(); - RainbowName.INSTANCE.init(); - ChomeNSBotCommandSuggestions.INSTANCE.init(); - ChomeNSAuth.INSTANCE.init(); - CustomChat.INSTANCE.init(); - } - - @Inject(method = "onCommandTree", at = @At("TAIL")) - private void onCommandTree(final CommandTreeS2CPacket packet, final CallbackInfo ci) { - KaboomCheck.INSTANCE.onCommandTree(this.commandDispatcher); - } - - @Inject(method = "onGameMessage", at = @At("HEAD"), cancellable = true) - private void onGameMessage (GameMessageS2CPacket packet, CallbackInfo ci) { - final Text message = packet.content(); - - try { - if (RainbowName.INSTANCE.enabled) { - if (message.getString().contains("Your nickname is now ") || message.getString().contains("Nickname changed.")) { - ci.cancel(); - return; - } - } - - try { - if (((TranslatableTextContent) message.getContent()).getKey().equals("advMode.setCommand.success")) { - ci.cancel(); - return; - } - } catch (ClassCastException ignored) {} - - for (Listener listener : ListenerManager.listeners) { - listener.chatMessageReceived(message); - } - - try { - final String suggestionId = message.getSiblings().getFirst().getString(); - final String authId = ((PlainTextContent) message.getContent()).string(); - - if (suggestionId.equals(ChomeNSBotCommandSuggestions.ID) || authId.equals(ChomeNSAuth.INSTANCE.id)) { - ci.cancel(); - } - } catch (Exception ignored) {} - } catch (Exception ignored) {} - } - - @Inject(method = "sendChatMessage", at = @At("HEAD"), cancellable = true) - private void sendChatMessage (String chatText, CallbackInfo ci) { - final CommandManager commandManager = CommandManager.INSTANCE; - - final String secret = String.valueOf(Chat.secret); - - if (chatText.startsWith(commandManager.prefix)) { - commandManager.executeCommand(chatText.substring(commandManager.prefix.length())); - - ci.cancel(); - } else if (!chatText.startsWith("/") && !chatText.startsWith(secret)) { - CustomChat.INSTANCE.chat(chatText); - - ci.cancel(); - } - - if (chatText.startsWith(secret)) { - final String content = chatText.substring(secret.length()); - - Instant instant = Instant.now(); - long l = NetworkEncryptionUtils.SecureRandomUtil.nextLong(); - LastSeenMessagesCollector.LastSeenMessages lastSeenMessages = this.lastSeenMessagesCollector.collect(); - MessageSignatureData messageSignatureData = this.messagePacker.pack(new MessageBody(content, instant, l, lastSeenMessages.lastSeen())); - MinecraftClient.getInstance().getNetworkHandler().sendPacket(new ChatMessageC2SPacket(content, instant, l, messageSignatureData, lastSeenMessages.update())); - - ci.cancel(); - } - } -} +package land.chipmunk.chipmunkmod.mixin; + +import com.mojang.brigadier.CommandDispatcher; +import land.chipmunk.chipmunkmod.ChipmunkMod; +import land.chipmunk.chipmunkmod.command.CommandManager; +import land.chipmunk.chipmunkmod.listeners.Listener; +import land.chipmunk.chipmunkmod.listeners.ListenerManager; +import land.chipmunk.chipmunkmod.modules.*; +import land.chipmunk.chipmunkmod.modules.custom_chat.CustomChat; +import net.minecraft.client.MinecraftClient; +import net.minecraft.command.CommandRegistryAccess; +import net.minecraft.command.CommandSource; +import net.minecraft.network.encryption.NetworkEncryptionUtils; +import net.minecraft.network.message.LastSeenMessagesCollector; +import net.minecraft.network.message.MessageBody; +import net.minecraft.network.message.MessageChain; +import net.minecraft.network.message.MessageSignatureData; +import net.minecraft.network.packet.c2s.play.ChatMessageC2SPacket; +import net.minecraft.network.packet.s2c.play.CommandTreeS2CPacket; +import net.minecraft.network.packet.s2c.play.GameJoinS2CPacket; +import net.minecraft.network.packet.s2c.play.GameMessageS2CPacket; +import net.minecraft.registry.DynamicRegistryManager; +import net.minecraft.resource.featuretoggle.FeatureSet; +import net.minecraft.text.PlainTextContent; +import net.minecraft.text.Text; +import net.minecraft.text.TranslatableTextContent; +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; + +import java.time.Instant; + +@Mixin(value = net.minecraft.client.network.ClientPlayNetworkHandler.class, priority = 1001) +public class ClientPlayNetworkHandlerMixin { + @Final + @Shadow + private FeatureSet enabledFeatures; + @Final + @Shadow + private DynamicRegistryManager.Immutable combinedDynamicRegistries; + @Shadow + private LastSeenMessagesCollector lastSeenMessagesCollector; + @Shadow + private MessageChain.Packer messagePacker; + @Shadow + private CommandDispatcher commandDispatcher; + + @Inject(method = "onGameJoin", at = @At("TAIL")) + private void onGameJoin(GameJoinS2CPacket packet, CallbackInfo ci) { + final CommandRegistryAccess commandRegistryAccess = CommandRegistryAccess.of(this.combinedDynamicRegistries, this.enabledFeatures); + + KaboomCheck.INSTANCE.onJoin(); + CommandManager.INSTANCE = new CommandManager(ChipmunkMod.CONFIG.commands.prefix, commandRegistryAccess); + SelfCare.INSTANCE.onJoin(); + CommandCore.INSTANCE.init(); + SongPlayer.INSTANCE.coreReady(); + RainbowName.INSTANCE.init(); + ChomeNSBotCommandSuggestions.INSTANCE.init(); + ChomeNSAuth.INSTANCE.init(); + CustomChat.INSTANCE.init(); + } + + @Inject(method = "onCommandTree", at = @At("TAIL")) + private void onCommandTree(final CommandTreeS2CPacket packet, final CallbackInfo ci) { + KaboomCheck.INSTANCE.onCommandTree(this.commandDispatcher); + } + + @Inject(method = "onGameMessage", at = @At("HEAD"), cancellable = true) + private void onGameMessage(GameMessageS2CPacket packet, CallbackInfo ci) { + final Text message = packet.content(); + + try { + if (RainbowName.INSTANCE.enabled) { + if (message.getString().contains("Your nickname is now ") || message.getString().contains("Nickname changed.")) { + ci.cancel(); + return; + } + } + + try { + if (((TranslatableTextContent) message.getContent()).getKey().equals("advMode.setCommand.success")) { + ci.cancel(); + return; + } + } catch (ClassCastException ignored) { + } + + for (Listener listener : ListenerManager.listeners) { + listener.chatMessageReceived(message); + } + + try { + final String suggestionId = message.getSiblings().getFirst().getString(); + final String authId = ((PlainTextContent) message.getContent()).string(); + + if (suggestionId.equals(ChomeNSBotCommandSuggestions.ID) || authId.equals(ChomeNSAuth.INSTANCE.id)) { + ci.cancel(); + } + } catch (Exception ignored) { + } + } catch (Exception ignored) { + } + } + + @Inject(method = "sendChatMessage", at = @At("HEAD"), cancellable = true) + private void sendChatMessage(String chatText, CallbackInfo ci) { + final CommandManager commandManager = CommandManager.INSTANCE; + + final String secret = String.valueOf(Chat.secret); + + if (chatText.startsWith(commandManager.prefix)) { + commandManager.executeCommand(chatText.substring(commandManager.prefix.length())); + + ci.cancel(); + } else if (!chatText.startsWith("/") && !chatText.startsWith(secret)) { + CustomChat.INSTANCE.chat(chatText); + + ci.cancel(); + } + + if (chatText.startsWith(secret)) { + final String content = chatText.substring(secret.length()); + + Instant instant = Instant.now(); + long l = NetworkEncryptionUtils.SecureRandomUtil.nextLong(); + LastSeenMessagesCollector.LastSeenMessages lastSeenMessages = this.lastSeenMessagesCollector.collect(); + MessageSignatureData messageSignatureData = this.messagePacker.pack(new MessageBody(content, instant, l, lastSeenMessages.lastSeen())); + MinecraftClient.getInstance().getNetworkHandler().sendPacket(new ChatMessageC2SPacket(content, instant, l, messageSignatureData, lastSeenMessages.update())); + + ci.cancel(); + } + } +} diff --git a/src/main/java/land/chipmunk/chipmunkmod/mixin/ClientPlayerEntityMixin.java b/src/main/java/land/chipmunk/chipmunkmod/mixin/ClientPlayerEntityMixin.java index d80e454..9f1fa36 100644 --- a/src/main/java/land/chipmunk/chipmunkmod/mixin/ClientPlayerEntityMixin.java +++ b/src/main/java/land/chipmunk/chipmunkmod/mixin/ClientPlayerEntityMixin.java @@ -1,42 +1,42 @@ -package land.chipmunk.chipmunkmod.mixin; - -import land.chipmunk.chipmunkmod.modules.CommandCore; -import net.minecraft.client.network.ClientPlayNetworkHandler; -import net.minecraft.client.network.ClientPlayerEntity; -import net.minecraft.entity.Entity; -import net.minecraft.entity.EntityType; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.ChunkPos; -import net.minecraft.world.World; -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(ClientPlayerEntity.class) -public abstract class ClientPlayerEntityMixin extends Entity { - @Shadow @Final public ClientPlayNetworkHandler networkHandler; - - public ClientPlayerEntityMixin(final EntityType type, final World world) { - super(type, world); - } - - @Inject(at = @At("TAIL"), method = "move") - public void move(CallbackInfo ci) { - final BlockPos origin = CommandCore.INSTANCE.origin; - if (origin == null) { - CommandCore.INSTANCE.move(this.getPos()); - return; - } - - final int distanceSquared = this.getChunkPos().getSquaredDistance(new ChunkPos(origin)); - final int distance = (int) Math.sqrt(distanceSquared); - - if (distance > networkHandler.getWorld().getSimulationDistance()) { - CommandCore.INSTANCE.clientPlayerEntityFilled = true; - CommandCore.INSTANCE.move(this.getPos()); - } - } -} +package land.chipmunk.chipmunkmod.mixin; + +import land.chipmunk.chipmunkmod.modules.CommandCore; +import net.minecraft.client.network.ClientPlayNetworkHandler; +import net.minecraft.client.network.ClientPlayerEntity; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityType; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.ChunkPos; +import net.minecraft.world.World; +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(ClientPlayerEntity.class) +public abstract class ClientPlayerEntityMixin extends Entity { + @Shadow @Final public ClientPlayNetworkHandler networkHandler; + + public ClientPlayerEntityMixin(final EntityType type, final World world) { + super(type, world); + } + + @Inject(at = @At("TAIL"), method = "move") + public void move(CallbackInfo ci) { + final BlockPos origin = CommandCore.INSTANCE.origin; + if (origin == null) { + CommandCore.INSTANCE.move(this.getPos()); + return; + } + + final int distanceSquared = this.getChunkPos().getSquaredDistance(new ChunkPos(origin)); + final int distance = (int) Math.sqrt(distanceSquared); + + if (distance > networkHandler.getWorld().getSimulationDistance()) { + CommandCore.INSTANCE.clientPlayerEntityFilled = true; + CommandCore.INSTANCE.move(this.getPos()); + } + } +} diff --git a/src/main/java/land/chipmunk/chipmunkmod/mixin/MinecraftClientAccessor.java b/src/main/java/land/chipmunk/chipmunkmod/mixin/MinecraftClientAccessor.java index dad746f..0f93627 100644 --- a/src/main/java/land/chipmunk/chipmunkmod/mixin/MinecraftClientAccessor.java +++ b/src/main/java/land/chipmunk/chipmunkmod/mixin/MinecraftClientAccessor.java @@ -1,14 +1,14 @@ -package land.chipmunk.chipmunkmod.mixin; - -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.session.Session; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Mutable; -import org.spongepowered.asm.mixin.gen.Accessor; - -@Mixin(MinecraftClient.class) -public interface MinecraftClientAccessor { - @Mutable - @Accessor("session") - void session (Session session); -} +package land.chipmunk.chipmunkmod.mixin; + +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.session.Session; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Mutable; +import org.spongepowered.asm.mixin.gen.Accessor; + +@Mixin(MinecraftClient.class) +public interface MinecraftClientAccessor { + @Mutable + @Accessor("session") + void session(Session session); +} diff --git a/src/main/java/land/chipmunk/chipmunkmod/modules/CommandCore.java b/src/main/java/land/chipmunk/chipmunkmod/modules/CommandCore.java index fef6075..80a2d93 100644 --- a/src/main/java/land/chipmunk/chipmunkmod/modules/CommandCore.java +++ b/src/main/java/land/chipmunk/chipmunkmod/modules/CommandCore.java @@ -1,334 +1,334 @@ -package land.chipmunk.chipmunkmod.modules; - -import land.chipmunk.chipmunkmod.ChipmunkMod; -import land.chipmunk.chipmunkmod.listeners.Listener; -import land.chipmunk.chipmunkmod.listeners.ListenerManager; -import net.minecraft.block.Block; -import net.minecraft.block.CommandBlock; -import net.minecraft.block.entity.CommandBlockBlockEntity; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.network.ClientPlayNetworkHandler; -import net.minecraft.client.network.ClientPlayerEntity; -import net.minecraft.client.world.ClientWorld; -import net.minecraft.nbt.NbtCompound; -import net.minecraft.network.ClientConnection; -import net.minecraft.network.packet.c2s.play.UpdateCommandBlockC2SPacket; -import net.minecraft.util.math.BlockBox; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.Vec3d; -import net.minecraft.world.dimension.DimensionType; -import org.slf4j.Logger; - -import java.util.Timer; -import java.util.TimerTask; -import java.util.concurrent.CompletableFuture; - -public class CommandCore { - private final MinecraftClient client; - public boolean ready = false; - public BlockPos origin; - public BlockBox noPos; - public BlockPos block; - public BlockBox withPos; - - private Timer timer; - - private boolean shouldRefill = false; - - private DimensionType oldDimension; - - public boolean runFillCommand = true; - - public boolean clientPlayerEntityFilled = false; - - public static CommandCore INSTANCE = new CommandCore(MinecraftClient.getInstance()); - - public CommandCore (MinecraftClient client) { - this.client = client; - reloadRelativeArea(); - } - - public void init () { - if (timer != null) cleanup(); - - final TimerTask task = new TimerTask() { - public void run () { - tick(); - } - }; - - final TimerTask refillTask = new TimerTask() { - @Override - public void run() { - if (clientPlayerEntityFilled) { - clientPlayerEntityFilled = false; - return; - } - - check(); - - if (!shouldRefill) return; - - refill(); - - shouldRefill = false; - } - }; - - timer = new Timer(); - - timer.schedule(task, 50, 50); - - timer.schedule(refillTask, 50, 1000); - - move(client.player.getPos()); - } - - private void tick () { - final ClientPlayNetworkHandler networkHandler = client.getNetworkHandler(); - - if (networkHandler == null) { - cleanup(); - - return; - } - - reloadRelativeArea(); - } - - public void reloadRelativeArea () { - noPos = ChipmunkMod.CONFIG.core.relativeArea; - } - - public void check () { - final ClientPlayNetworkHandler networkHandler = client.getNetworkHandler(); - - if (networkHandler == null || withPos == null || !ready) return; - - final ClientPlayerEntity player = client.player; - final ClientWorld world = client.world; - - if (player == null || world == null) return; - - if (oldDimension != null && !oldDimension.equals(world.getDimension())) move(client.player.getPos()); - - oldDimension = world.getDimension(); - - try { - for (int x = withPos.getMinX(); x <= withPos.getMaxX(); x++) { - for (int y = withPos.getMinY(); y <= withPos.getMaxY(); y++) { - for (int z = withPos.getMinZ(); z <= withPos.getMaxZ(); z++) { - final BlockPos pos = new BlockPos(x, y, z); - - final Block block = world.getBlockState(pos).getBlock(); - - if (block instanceof CommandBlock) continue; - - shouldRefill = true; - - return; - } - } - } - } catch (Exception e) { - e.printStackTrace(); - } - } - - public void move (Vec3d position) { - final ClientWorld world = client.world; - if (world == null || noPos == null) return; - - final DimensionType dimension = world.getDimension(); - - final int dimMinY = dimension.minY(); - final int dimMaxY = dimension.height() + dimMinY - 1; // -1 accounts for block at Y=0 - int yOffset = 0; - if (noPos.getMinY() < dimMinY) { - yOffset = dimMinY - noPos.getMinY(); - } else if (noPos.getMaxY() > dimMaxY) { - yOffset = dimMaxY - noPos.getMaxY(); - } - - origin = new BlockPos( - ((int) position.getX() / 16) * 16, - noPos.getMinY() + yOffset, - ((int) position.getZ() / 16) * 16 - ); - - withPos = noPos.offset(origin.getX(), yOffset, origin.getZ()); - block = new BlockPos(withPos.getMinX(), withPos.getMinY(), withPos.getMinZ()); - refill(); - - for (Listener listener : ListenerManager.listeners) listener.coreMoved(); - if (!ready) { - ready = true; - - for (Listener listener : ListenerManager.listeners) listener.coreReady(); - } - } - - public void refill () { - if (!runFillCommand || withPos == null) return; - - final String command = String.format( - KaboomCheck.INSTANCE.isKaboom ? - "fill %s %s %s %s %s %s repeating_command_block replace" : - "fill %s %s %s %s %s %s command_block", - withPos.getMinX(), - withPos.getMinY(), - withPos.getMinZ(), - - withPos.getMaxX(), - withPos.getMaxY(), - withPos.getMaxZ() - ); - - client.getNetworkHandler().sendChatCommand(command); - } - - public void incrementCurrentBlock () { - if (withPos == null) return; - int x = block.getX(); - int y = block.getY(); - int z = block.getZ(); - - x++; - - if (x > withPos.getMaxX()) { - x = withPos.getMinX(); - z++; - } - - if (z > withPos.getMaxZ()) { - z = withPos.getMinZ(); - y++; - } - - if (y > withPos.getMaxY()) { - x = withPos.getMinX(); - y = withPos.getMinY(); - z = withPos.getMinZ(); - } - - block = new BlockPos(x, y, z); - } - - public void run (String command) { - if (command.length() > 32767) return; - - final ClientConnection connection = client.getNetworkHandler().getConnection(); - - if (block == null) return; - - ChipmunkMod.LOGGER.info("Executing core command: {}", command); - - if (KaboomCheck.INSTANCE.isKaboom) { - connection.send( - new UpdateCommandBlockC2SPacket( - block, - command, - CommandBlockBlockEntity.Type.AUTO, - false, - false, - true - ) - ); - } else { - connection.send( - new UpdateCommandBlockC2SPacket( - block, - "", - CommandBlockBlockEntity.Type.REDSTONE, - false, - false, - false - ) - ); - - connection.send( - new UpdateCommandBlockC2SPacket( - block, - command, - CommandBlockBlockEntity.Type.REDSTONE, - false, - false, - true - ) - ); - } - - incrementCurrentBlock(); - } - - public CompletableFuture runTracked (String command) { - final ClientConnection connection = client.getNetworkHandler().getConnection(); - - if (block == null) return new CompletableFuture<>(); - - if (KaboomCheck.INSTANCE.isKaboom) { - connection.send( - new UpdateCommandBlockC2SPacket( - block, - command, - CommandBlockBlockEntity.Type.AUTO, - true, - false, - true - ) - ); - } else { - connection.send( - new UpdateCommandBlockC2SPacket( - block, - "", - CommandBlockBlockEntity.Type.REDSTONE, - true, - false, - false - ) - ); - - connection.send( - new UpdateCommandBlockC2SPacket( - block, - command, - CommandBlockBlockEntity.Type.REDSTONE, - true, - false, - true - ) - ); - } - - incrementCurrentBlock(); - - CompletableFuture future = new CompletableFuture<>(); - - final Timer timer = new Timer(); - - final TimerTask queryTask = new TimerTask() { - public void run () { - client.getNetworkHandler().getDataQueryHandler().queryBlockNbt(block, future::complete); - - timer.cancel(); // ? Is this necesary? - timer.purge(); - } - }; - - timer.schedule(queryTask, 50); - - return future; - } - - public void cleanup () { - if (timer == null) return; - - timer.cancel(); - timer.purge(); - - withPos = null; - block = null; - ready = false; - } -} +package land.chipmunk.chipmunkmod.modules; + +import land.chipmunk.chipmunkmod.ChipmunkMod; +import land.chipmunk.chipmunkmod.listeners.Listener; +import land.chipmunk.chipmunkmod.listeners.ListenerManager; +import net.minecraft.block.Block; +import net.minecraft.block.CommandBlock; +import net.minecraft.block.entity.CommandBlockBlockEntity; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.network.ClientPlayNetworkHandler; +import net.minecraft.client.network.ClientPlayerEntity; +import net.minecraft.client.world.ClientWorld; +import net.minecraft.nbt.NbtCompound; +import net.minecraft.network.ClientConnection; +import net.minecraft.network.packet.c2s.play.UpdateCommandBlockC2SPacket; +import net.minecraft.util.math.BlockBox; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Vec3d; +import net.minecraft.world.dimension.DimensionType; +import org.slf4j.Logger; + +import java.util.Timer; +import java.util.TimerTask; +import java.util.concurrent.CompletableFuture; + +public class CommandCore { + private final MinecraftClient client; + public boolean ready = false; + public BlockPos origin; + public BlockBox noPos; + public BlockPos block; + public BlockBox withPos; + + private Timer timer; + + private boolean shouldRefill = false; + + private DimensionType oldDimension; + + public boolean runFillCommand = true; + + public boolean clientPlayerEntityFilled = false; + + public static CommandCore INSTANCE = new CommandCore(MinecraftClient.getInstance()); + + public CommandCore(MinecraftClient client) { + this.client = client; + reloadRelativeArea(); + } + + public void init() { + if (timer != null) cleanup(); + + final TimerTask task = new TimerTask() { + public void run() { + tick(); + } + }; + + final TimerTask refillTask = new TimerTask() { + @Override + public void run() { + if (clientPlayerEntityFilled) { + clientPlayerEntityFilled = false; + return; + } + + check(); + + if (!shouldRefill) return; + + refill(); + + shouldRefill = false; + } + }; + + timer = new Timer(); + + timer.schedule(task, 50, 50); + + timer.schedule(refillTask, 50, 1000); + + move(client.player.getPos()); + } + + private void tick() { + final ClientPlayNetworkHandler networkHandler = client.getNetworkHandler(); + + if (networkHandler == null) { + cleanup(); + + return; + } + + reloadRelativeArea(); + } + + public void reloadRelativeArea() { + noPos = ChipmunkMod.CONFIG.core.relativeArea; + } + + public void check() { + final ClientPlayNetworkHandler networkHandler = client.getNetworkHandler(); + + if (networkHandler == null || withPos == null || !ready) return; + + final ClientPlayerEntity player = client.player; + final ClientWorld world = client.world; + + if (player == null || world == null) return; + + if (oldDimension != null && !oldDimension.equals(world.getDimension())) move(client.player.getPos()); + + oldDimension = world.getDimension(); + + try { + for (int x = withPos.getMinX(); x <= withPos.getMaxX(); x++) { + for (int y = withPos.getMinY(); y <= withPos.getMaxY(); y++) { + for (int z = withPos.getMinZ(); z <= withPos.getMaxZ(); z++) { + final BlockPos pos = new BlockPos(x, y, z); + + final Block block = world.getBlockState(pos).getBlock(); + + if (block instanceof CommandBlock) continue; + + shouldRefill = true; + + return; + } + } + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + public void move(Vec3d position) { + final ClientWorld world = client.world; + if (world == null || noPos == null) return; + + final DimensionType dimension = world.getDimension(); + + final int dimMinY = dimension.minY(); + final int dimMaxY = dimension.height() + dimMinY - 1; // -1 accounts for block at Y=0 + int yOffset = 0; + if (noPos.getMinY() < dimMinY) { + yOffset = dimMinY - noPos.getMinY(); + } else if (noPos.getMaxY() > dimMaxY) { + yOffset = dimMaxY - noPos.getMaxY(); + } + + origin = new BlockPos( + ((int) position.getX() / 16) * 16, + noPos.getMinY() + yOffset, + ((int) position.getZ() / 16) * 16 + ); + + withPos = noPos.offset(origin.getX(), yOffset, origin.getZ()); + block = new BlockPos(withPos.getMinX(), withPos.getMinY(), withPos.getMinZ()); + refill(); + + for (Listener listener : ListenerManager.listeners) listener.coreMoved(); + if (!ready) { + ready = true; + + for (Listener listener : ListenerManager.listeners) listener.coreReady(); + } + } + + public void refill() { + if (!runFillCommand || withPos == null) return; + + final String command = String.format( + KaboomCheck.INSTANCE.isKaboom ? + "fill %s %s %s %s %s %s repeating_command_block replace" : + "fill %s %s %s %s %s %s command_block", + withPos.getMinX(), + withPos.getMinY(), + withPos.getMinZ(), + + withPos.getMaxX(), + withPos.getMaxY(), + withPos.getMaxZ() + ); + + client.getNetworkHandler().sendChatCommand(command); + } + + public void incrementCurrentBlock() { + if (withPos == null) return; + int x = block.getX(); + int y = block.getY(); + int z = block.getZ(); + + x++; + + if (x > withPos.getMaxX()) { + x = withPos.getMinX(); + z++; + } + + if (z > withPos.getMaxZ()) { + z = withPos.getMinZ(); + y++; + } + + if (y > withPos.getMaxY()) { + x = withPos.getMinX(); + y = withPos.getMinY(); + z = withPos.getMinZ(); + } + + block = new BlockPos(x, y, z); + } + + public void run(String command) { + if (command.length() > 32767) return; + + final ClientConnection connection = client.getNetworkHandler().getConnection(); + + if (block == null) return; + + ChipmunkMod.LOGGER.info("Executing core command: {}", command); + + if (KaboomCheck.INSTANCE.isKaboom) { + connection.send( + new UpdateCommandBlockC2SPacket( + block, + command, + CommandBlockBlockEntity.Type.AUTO, + false, + false, + true + ) + ); + } else { + connection.send( + new UpdateCommandBlockC2SPacket( + block, + "", + CommandBlockBlockEntity.Type.REDSTONE, + false, + false, + false + ) + ); + + connection.send( + new UpdateCommandBlockC2SPacket( + block, + command, + CommandBlockBlockEntity.Type.REDSTONE, + false, + false, + true + ) + ); + } + + incrementCurrentBlock(); + } + + public CompletableFuture runTracked(String command) { + final ClientConnection connection = client.getNetworkHandler().getConnection(); + + if (block == null) return new CompletableFuture<>(); + + if (KaboomCheck.INSTANCE.isKaboom) { + connection.send( + new UpdateCommandBlockC2SPacket( + block, + command, + CommandBlockBlockEntity.Type.AUTO, + true, + false, + true + ) + ); + } else { + connection.send( + new UpdateCommandBlockC2SPacket( + block, + "", + CommandBlockBlockEntity.Type.REDSTONE, + true, + false, + false + ) + ); + + connection.send( + new UpdateCommandBlockC2SPacket( + block, + command, + CommandBlockBlockEntity.Type.REDSTONE, + true, + false, + true + ) + ); + } + + incrementCurrentBlock(); + + CompletableFuture future = new CompletableFuture<>(); + + final Timer timer = new Timer(); + + final TimerTask queryTask = new TimerTask() { + public void run() { + client.getNetworkHandler().getDataQueryHandler().queryBlockNbt(block, future::complete); + + timer.cancel(); // ? Is this necesary? + timer.purge(); + } + }; + + timer.schedule(queryTask, 50); + + return future; + } + + public void cleanup() { + if (timer == null) return; + + timer.cancel(); + timer.purge(); + + withPos = null; + block = null; + ready = false; + } +} diff --git a/src/main/java/land/chipmunk/chipmunkmod/modules/SelfCare.java b/src/main/java/land/chipmunk/chipmunkmod/modules/SelfCare.java index ab88f06..c6fbc79 100644 --- a/src/main/java/land/chipmunk/chipmunkmod/modules/SelfCare.java +++ b/src/main/java/land/chipmunk/chipmunkmod/modules/SelfCare.java @@ -1,159 +1,164 @@ -package land.chipmunk.chipmunkmod.modules; - -import land.chipmunk.chipmunkmod.ChipmunkMod; -import land.chipmunk.chipmunkmod.listeners.Listener; -import land.chipmunk.chipmunkmod.listeners.ListenerManager; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.network.ClientPlayNetworkHandler; -import net.minecraft.client.network.ClientPlayerEntity; -import net.minecraft.network.packet.Packet; -import net.minecraft.network.packet.s2c.play.GameJoinS2CPacket; -import net.minecraft.network.packet.s2c.play.GameStateChangeS2CPacket; -import net.minecraft.network.packet.s2c.play.PlayerPositionLookS2CPacket; -import net.minecraft.text.Text; - -import java.util.Timer; -import java.util.TimerTask; - -import static land.chipmunk.chipmunkmod.util.ServerUtilities.serverHasCommand; - -public class SelfCare implements Listener { - private final MinecraftClient client; - public final long interval; - public final long chatInterval; - - public boolean opEnabled = true; - public boolean gamemodeEnabled = true; - public boolean cspyEnabled = true; - public boolean icuEnabled = true; - - private int gameMode; - - public String skin; - - private Timer timer; - private Timer chatTimer; - - private boolean cspy = false; - public boolean hasSkin = false; - - private int positionPacketsPerSecond = 0; - - public static final SelfCare INSTANCE = new SelfCare(MinecraftClient.getInstance(), 70L, 500L); // make the intervals in config? - - public SelfCare (MinecraftClient client, long interval, long chatInterval) { - this.client = client; - this.interval = interval; - this.chatInterval = chatInterval; - - this.skin = ChipmunkMod.CONFIG.autoSkinUsername == null ? "off" : ChipmunkMod.CONFIG.autoSkinUsername; // can this be null? - - ListenerManager.addListener(this); - } - - public void init () {} - - public void onJoin () { - final TimerTask task = new TimerTask() { - public void run () { - tick(); - } - }; - - final TimerTask chatTask = new TimerTask() { - public void run () { - chatTick(); - } - }; - - timer = new Timer(); - chatTimer = new Timer(); - - timer.schedule(task, interval, interval); - chatTimer.schedule(chatTask, chatInterval, chatInterval); - } - - public void cleanup () { - if (timer == null || chatTimer == null) return; - - timer.cancel(); - timer.purge(); - - chatTimer.cancel(); - chatTimer.purge(); - - gameMode = -1; - - hasSkin = false; - cspy = false; - } - - @Override - public void chatMessageReceived (Text message) { - final String stringMessage = message.getString(); - - if (stringMessage.equals("Successfully enabled CommandSpy")) cspy = true; - else if (stringMessage.equals("Successfully disabled CommandSpy")) cspy = false; - - else if (stringMessage.equals("Successfully set your skin to " + skin + "'s")) hasSkin = true; - else if ( - stringMessage.equals("Successfully removed your skin") || - stringMessage.startsWith("Successfully set your skin to ") - ) hasSkin = false; - } - - public void tick () { - final ClientPlayerEntity player = client.player; - final ClientPlayNetworkHandler networkHandler = client.getNetworkHandler(); - - if (networkHandler == null) { - cleanup(); - return; - } - - if (player != null && !player.hasPermissionLevel(2) && opEnabled) { if (serverHasCommand("op")) networkHandler.sendChatCommand("op @s[type=player]"); } - else if (gameMode != 1 && gamemodeEnabled) networkHandler.sendChatCommand("gamemode creative"); - else if (positionPacketsPerSecond >= 10 && icuEnabled) CommandCore.INSTANCE.run("sudo * icu stop"); - } - - public void chatTick () { - final ClientPlayNetworkHandler networkHandler = client.getNetworkHandler(); - - if (!cspy && cspyEnabled) { if (serverHasCommand("c")) networkHandler.sendChatCommand("c on"); } - else if (!hasSkin && !skin.equals("off")) { if (serverHasCommand("skin")) networkHandler.sendChatCommand("skin " + skin); } - } - - @Override - public void packetReceived(Packet packet) { - if (packet instanceof GameJoinS2CPacket) packetReceived((GameJoinS2CPacket) packet); - else if (packet instanceof GameStateChangeS2CPacket) packetReceived((GameStateChangeS2CPacket) packet); - else if (packet instanceof PlayerPositionLookS2CPacket) packetReceived((PlayerPositionLookS2CPacket) packet); - } - - public void packetReceived(GameJoinS2CPacket packet) { - gameMode = packet.commonPlayerSpawnInfo().gameMode().getId(); - } - - public void packetReceived(GameStateChangeS2CPacket packet) { - if (packet.getReason() != GameStateChangeS2CPacket.GAME_MODE_CHANGED) return; - - gameMode = (int) packet.getValue(); - } - - public void packetReceived(PlayerPositionLookS2CPacket packet) { - if (timer == null) return; - - try { - positionPacketsPerSecond++; - - timer.schedule(new TimerTask() { - @Override - public void run() { - positionPacketsPerSecond--; - } - }, 1000); - } catch (Exception e) { - e.printStackTrace(); - } - } -} +package land.chipmunk.chipmunkmod.modules; + +import land.chipmunk.chipmunkmod.ChipmunkMod; +import land.chipmunk.chipmunkmod.listeners.Listener; +import land.chipmunk.chipmunkmod.listeners.ListenerManager; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.network.ClientPlayNetworkHandler; +import net.minecraft.client.network.ClientPlayerEntity; +import net.minecraft.network.packet.Packet; +import net.minecraft.network.packet.s2c.play.GameJoinS2CPacket; +import net.minecraft.network.packet.s2c.play.GameStateChangeS2CPacket; +import net.minecraft.network.packet.s2c.play.PlayerPositionLookS2CPacket; +import net.minecraft.text.Text; + +import java.util.Timer; +import java.util.TimerTask; + +import static land.chipmunk.chipmunkmod.util.ServerUtilities.serverHasCommand; + +public class SelfCare implements Listener { + private final MinecraftClient client; + public final long interval; + public final long chatInterval; + + public boolean opEnabled = true; + public boolean gamemodeEnabled = true; + public boolean cspyEnabled = true; + public boolean icuEnabled = true; + + private int gameMode; + + public String skin; + + private Timer timer; + private Timer chatTimer; + + private boolean cspy = false; + public boolean hasSkin = false; + + private int positionPacketsPerSecond = 0; + + public static final SelfCare INSTANCE = new SelfCare(MinecraftClient.getInstance(), 70L, 500L); // make the intervals in config? + + public SelfCare(MinecraftClient client, long interval, long chatInterval) { + this.client = client; + this.interval = interval; + this.chatInterval = chatInterval; + + this.skin = ChipmunkMod.CONFIG.autoSkinUsername == null ? "off" : ChipmunkMod.CONFIG.autoSkinUsername; // can this be null? + + ListenerManager.addListener(this); + } + + public void init() { + } + + public void onJoin() { + final TimerTask task = new TimerTask() { + public void run() { + tick(); + } + }; + + final TimerTask chatTask = new TimerTask() { + public void run() { + chatTick(); + } + }; + + timer = new Timer(); + chatTimer = new Timer(); + + timer.schedule(task, interval, interval); + chatTimer.schedule(chatTask, chatInterval, chatInterval); + } + + public void cleanup() { + if (timer == null || chatTimer == null) return; + + timer.cancel(); + timer.purge(); + + chatTimer.cancel(); + chatTimer.purge(); + + gameMode = -1; + + hasSkin = false; + cspy = false; + } + + @Override + public void chatMessageReceived(Text message) { + final String stringMessage = message.getString(); + + if (stringMessage.equals("Successfully enabled CommandSpy")) cspy = true; + else if (stringMessage.equals("Successfully disabled CommandSpy")) cspy = false; + + else if (stringMessage.equals("Successfully set your skin to " + skin + "'s")) hasSkin = true; + else if ( + stringMessage.equals("Successfully removed your skin") || + stringMessage.startsWith("Successfully set your skin to ") + ) hasSkin = false; + } + + public void tick() { + final ClientPlayerEntity player = client.player; + final ClientPlayNetworkHandler networkHandler = client.getNetworkHandler(); + + if (networkHandler == null) { + cleanup(); + return; + } + + if (player != null && !player.hasPermissionLevel(2) && opEnabled) { + if (serverHasCommand("op")) networkHandler.sendChatCommand("op @s[type=player]"); + } else if (gameMode != 1 && gamemodeEnabled) networkHandler.sendChatCommand("gamemode creative"); + else if (positionPacketsPerSecond >= 10 && icuEnabled) CommandCore.INSTANCE.run("sudo * icu stop"); + } + + public void chatTick() { + final ClientPlayNetworkHandler networkHandler = client.getNetworkHandler(); + + if (!cspy && cspyEnabled) { + if (serverHasCommand("c")) networkHandler.sendChatCommand("c on"); + } else if (!hasSkin && !skin.equals("off")) { + if (serverHasCommand("skin")) networkHandler.sendChatCommand("skin " + skin); + } + } + + @Override + public void packetReceived(Packet packet) { + if (packet instanceof GameJoinS2CPacket) packetReceived((GameJoinS2CPacket) packet); + else if (packet instanceof GameStateChangeS2CPacket) packetReceived((GameStateChangeS2CPacket) packet); + else if (packet instanceof PlayerPositionLookS2CPacket) packetReceived((PlayerPositionLookS2CPacket) packet); + } + + public void packetReceived(GameJoinS2CPacket packet) { + gameMode = packet.commonPlayerSpawnInfo().gameMode().getId(); + } + + public void packetReceived(GameStateChangeS2CPacket packet) { + if (packet.getReason() != GameStateChangeS2CPacket.GAME_MODE_CHANGED) return; + + gameMode = (int) packet.getValue(); + } + + public void packetReceived(PlayerPositionLookS2CPacket packet) { + if (timer == null) return; + + try { + positionPacketsPerSecond++; + + timer.schedule(new TimerTask() { + @Override + public void run() { + positionPacketsPerSecond--; + } + }, 1000); + } catch (Exception e) { + e.printStackTrace(); + } + } +} diff --git a/src/main/java/land/chipmunk/chipmunkmod/song/Instrument.java b/src/main/java/land/chipmunk/chipmunkmod/song/Instrument.java index 8d8850e..7162f31 100644 --- a/src/main/java/land/chipmunk/chipmunkmod/song/Instrument.java +++ b/src/main/java/land/chipmunk/chipmunkmod/song/Instrument.java @@ -1,48 +1,49 @@ package land.chipmunk.chipmunkmod.song; public class Instrument { - public static final Instrument HARP = new Instrument(0, "harp", 54); - public static final Instrument BASEDRUM = new Instrument(1, "basedrum", 0); - public static final Instrument SNARE = new Instrument(2, "snare", 0); - public static final Instrument HAT = new Instrument(3, "hat", 0); - public static final Instrument BASS = new Instrument(4, "bass", 30); - public static final Instrument FLUTE = new Instrument(5, "flute", 66); - public static final Instrument BELL = new Instrument(6, "bell", 78); - public static final Instrument GUITAR = new Instrument(7, "guitar", 42); - public static final Instrument CHIME = new Instrument(8, "chime", 78); - public static final Instrument XYLOPHONE = new Instrument(9, "xylophone", 78); - public static final Instrument IRON_XYLOPHONE = new Instrument(10, "iron_xylophone", 54); - public static final Instrument COW_BELL = new Instrument(11, "cow_bell", 66); - public static final Instrument DIDGERIDOO = new Instrument(12, "didgeridoo", 30); - public static final Instrument BIT = new Instrument(13, "bit", 54); - public static final Instrument BANJO = new Instrument(14, "banjo", 54); - public static final Instrument PLING = new Instrument(15, "pling", 54); + public static final Instrument HARP = new Instrument(0, "harp", 54); + public static final Instrument BASEDRUM = new Instrument(1, "basedrum", 0); + public static final Instrument SNARE = new Instrument(2, "snare", 0); + public static final Instrument HAT = new Instrument(3, "hat", 0); + public static final Instrument BASS = new Instrument(4, "bass", 30); + public static final Instrument FLUTE = new Instrument(5, "flute", 66); + public static final Instrument BELL = new Instrument(6, "bell", 78); + public static final Instrument GUITAR = new Instrument(7, "guitar", 42); + public static final Instrument CHIME = new Instrument(8, "chime", 78); + public static final Instrument XYLOPHONE = new Instrument(9, "xylophone", 78); + public static final Instrument IRON_XYLOPHONE = new Instrument(10, "iron_xylophone", 54); + public static final Instrument COW_BELL = new Instrument(11, "cow_bell", 66); + public static final Instrument DIDGERIDOO = new Instrument(12, "didgeridoo", 30); + public static final Instrument BIT = new Instrument(13, "bit", 54); + public static final Instrument BANJO = new Instrument(14, "banjo", 54); + public static final Instrument PLING = new Instrument(15, "pling", 54); - public final int id; - public final String name; - public final int offset; - public final String sound; + public final int id; + public final String name; + public final int offset; + public final String sound; - private Instrument (int id, String name, int offset, String sound) { - this.id = id; - this.name = name; - this.offset = offset; - this.sound = sound; - } + private Instrument(int id, String name, int offset, String sound) { + this.id = id; + this.name = name; + this.offset = offset; + this.sound = sound; + } - private Instrument (int id, String name, int offset) { - this.id = id; - this.name = name; - this.offset = offset; - this.sound = "minecraft:block.note_block." + name; - } + private Instrument(int id, String name, int offset) { + this.id = id; + this.name = name; + this.offset = offset; + this.sound = "minecraft:block.note_block." + name; + } - public static Instrument of (String sound) { - return new Instrument(-1, null, 0, sound); - } + public static Instrument of(String sound) { + return new Instrument(-1, null, 0, sound); + } - private static Instrument[] values = {HARP, BASEDRUM, SNARE, HAT, BASS, FLUTE, BELL, GUITAR, CHIME, XYLOPHONE, IRON_XYLOPHONE, COW_BELL, DIDGERIDOO, BIT, BANJO, PLING}; - public static Instrument fromId (int id) { - return values[id]; - } + private static Instrument[] values = {HARP, BASEDRUM, SNARE, HAT, BASS, FLUTE, BELL, GUITAR, CHIME, XYLOPHONE, IRON_XYLOPHONE, COW_BELL, DIDGERIDOO, BIT, BANJO, PLING}; + + public static Instrument fromId(int id) { + return values[id]; + } } diff --git a/src/main/java/land/chipmunk/chipmunkmod/song/MidiConverter.java b/src/main/java/land/chipmunk/chipmunkmod/song/MidiConverter.java index 053a31f..d8d3c0c 100644 --- a/src/main/java/land/chipmunk/chipmunkmod/song/MidiConverter.java +++ b/src/main/java/land/chipmunk/chipmunkmod/song/MidiConverter.java @@ -1,6 +1,7 @@ package land.chipmunk.chipmunkmod.song; import land.chipmunk.chipmunkmod.util.DownloadUtilities; + import java.io.*; import java.net.*; import java.nio.file.Paths; @@ -13,361 +14,360 @@ import java.util.HashMap; import javax.sound.midi.*; public class MidiConverter { - public static final int SET_INSTRUMENT = 0xC0; - public static final int SET_TEMPO = 0x51; - public static final int NOTE_ON = 0x90; - public static final int NOTE_OFF = 0x80; + public static final int SET_INSTRUMENT = 0xC0; + public static final int SET_TEMPO = 0x51; + public static final int NOTE_ON = 0x90; + public static final int NOTE_OFF = 0x80; - public static Song getSongFromUrl(URL url) throws IOException, InvalidMidiDataException, URISyntaxException, NoSuchAlgorithmException, KeyManagementException { - Sequence sequence = MidiSystem.getSequence(DownloadUtilities.DownloadToInputStream(url)); - return getSong(sequence, Paths.get(url.toURI().getPath()).getFileName().toString()); - } - - public static Song getSongFromFile(File file) throws InvalidMidiDataException, IOException { - Sequence sequence = MidiSystem.getSequence(file); - return getSong(sequence, file.getName()); - } - - public static Song getSongFromBytes(byte[] bytes, String name) throws InvalidMidiDataException, IOException { - Sequence sequence = MidiSystem.getSequence(new ByteArrayInputStream(bytes)); - return getSong(sequence, name); - } - - public static Song getSong(Sequence sequence, String name) { - Song song = new Song(name); - - long tpq = sequence.getResolution(); - - ArrayList tempoEvents = new ArrayList<>(); - for (Track track : sequence.getTracks()) { - for (int i = 0; i < track.size(); i++) { - MidiEvent event = track.get(i); - MidiMessage message = event.getMessage(); - if (message instanceof MetaMessage) { - MetaMessage mm = (MetaMessage) message; - if (mm.getType() == SET_TEMPO) { - tempoEvents.add(event); - } - } - } + public static Song getSongFromUrl(URL url) throws IOException, InvalidMidiDataException, URISyntaxException, NoSuchAlgorithmException, KeyManagementException { + Sequence sequence = MidiSystem.getSequence(DownloadUtilities.DownloadToInputStream(url)); + return getSong(sequence, Paths.get(url.toURI().getPath()).getFileName().toString()); } - - Collections.sort(tempoEvents, (a, b) -> Long.compare(a.getTick(), b.getTick())); - - for (Track track : sequence.getTracks()) { - long microTime = 0; - int[] ids = new int[16]; - int mpq = 500000; - int tempoEventIdx = 0; - long prevTick = 0; - - for (int i = 0; i < track.size(); i++) { - MidiEvent event = track.get(i); - MidiMessage message = event.getMessage(); - - while (tempoEventIdx < tempoEvents.size() && event.getTick() > tempoEvents.get(tempoEventIdx).getTick()) { - long deltaTick = tempoEvents.get(tempoEventIdx).getTick() - prevTick; - prevTick = tempoEvents.get(tempoEventIdx).getTick(); - microTime += (mpq/tpq) * deltaTick; - - MetaMessage mm = (MetaMessage) tempoEvents.get(tempoEventIdx).getMessage(); - byte[] data = mm.getData(); - int new_mpq = (data[2]&0xFF) | ((data[1]&0xFF)<<8) | ((data[0]&0xFF)<<16); - if (new_mpq != 0) mpq = new_mpq; - tempoEventIdx++; + public static Song getSongFromFile(File file) throws InvalidMidiDataException, IOException { + Sequence sequence = MidiSystem.getSequence(file); + return getSong(sequence, file.getName()); + } + + public static Song getSongFromBytes(byte[] bytes, String name) throws InvalidMidiDataException, IOException { + Sequence sequence = MidiSystem.getSequence(new ByteArrayInputStream(bytes)); + return getSong(sequence, name); + } + + public static Song getSong(Sequence sequence, String name) { + Song song = new Song(name); + + long tpq = sequence.getResolution(); + + ArrayList tempoEvents = new ArrayList<>(); + for (Track track : sequence.getTracks()) { + for (int i = 0; i < track.size(); i++) { + MidiEvent event = track.get(i); + MidiMessage message = event.getMessage(); + if (message instanceof MetaMessage) { + MetaMessage mm = (MetaMessage) message; + if (mm.getType() == SET_TEMPO) { + tempoEvents.add(event); + } + } + } } - - if (message instanceof ShortMessage) { - ShortMessage sm = (ShortMessage) message; - if (sm.getCommand() == SET_INSTRUMENT) { - ids[sm.getChannel()] = sm.getData1(); - } - else if (sm.getCommand() == NOTE_ON) { - if (sm.getData2() == 0) continue; - int pitch = sm.getData1(); - int velocity = sm.getData2(); - long deltaTick = event.getTick() - prevTick; - prevTick = event.getTick(); - microTime += (mpq/tpq) * deltaTick; - Note note; - if (sm.getChannel() == 9) { - note = getMidiPercussionNote(pitch, velocity, microTime); - } - else { - note = getMidiInstrumentNote(ids[sm.getChannel()], pitch, velocity, microTime); - } - if (note != null) { - song.add(note); - } + Collections.sort(tempoEvents, (a, b) -> Long.compare(a.getTick(), b.getTick())); + for (Track track : sequence.getTracks()) { + + long microTime = 0; + int[] ids = new int[16]; + int mpq = 500000; + int tempoEventIdx = 0; + long prevTick = 0; + + for (int i = 0; i < track.size(); i++) { + MidiEvent event = track.get(i); + MidiMessage message = event.getMessage(); + + while (tempoEventIdx < tempoEvents.size() && event.getTick() > tempoEvents.get(tempoEventIdx).getTick()) { + long deltaTick = tempoEvents.get(tempoEventIdx).getTick() - prevTick; + prevTick = tempoEvents.get(tempoEventIdx).getTick(); + microTime += (mpq / tpq) * deltaTick; + + MetaMessage mm = (MetaMessage) tempoEvents.get(tempoEventIdx).getMessage(); + byte[] data = mm.getData(); + int new_mpq = (data[2] & 0xFF) | ((data[1] & 0xFF) << 8) | ((data[0] & 0xFF) << 16); + if (new_mpq != 0) mpq = new_mpq; + tempoEventIdx++; + } + + if (message instanceof ShortMessage) { + ShortMessage sm = (ShortMessage) message; + if (sm.getCommand() == SET_INSTRUMENT) { + ids[sm.getChannel()] = sm.getData1(); + } else if (sm.getCommand() == NOTE_ON) { + if (sm.getData2() == 0) continue; + int pitch = sm.getData1(); + int velocity = sm.getData2(); + long deltaTick = event.getTick() - prevTick; + prevTick = event.getTick(); + microTime += (mpq / tpq) * deltaTick; + + Note note; + if (sm.getChannel() == 9) { + note = getMidiPercussionNote(pitch, velocity, microTime); + } else { + note = getMidiInstrumentNote(ids[sm.getChannel()], pitch, velocity, microTime); + } + if (note != null) { + song.add(note); + } + + long time = microTime / 1000L; + if (time > song.length) { + song.length = time; + } + } else if (sm.getCommand() == NOTE_OFF) { + long deltaTick = event.getTick() - prevTick; + prevTick = event.getTick(); + microTime += (mpq / tpq) * deltaTick; + long time = microTime / 1000L; + if (time > song.length) { + song.length = time; + } + } + } + } + } + + song.sort(); + + return song; + } + + public static Note getMidiInstrumentNote(int midiInstrument, int midiPitch, int velocity, long microTime) { + Instrument instrument = null; + Instrument[] instrumentList = instrumentMap.get(midiInstrument); + if (instrumentList != null) { + for (Instrument candidateInstrument : instrumentList) { + if (midiPitch >= candidateInstrument.offset && midiPitch <= candidateInstrument.offset + 24) { + instrument = candidateInstrument; + break; + } + } + } + + if (instrument == null) { + return null; + } + + int pitch = midiPitch - instrument.offset; + float volume = (float) velocity / 127.0f; + long time = microTime / 1000L; + + return new Note(instrument, pitch, volume, time); + } + + private static Note getMidiPercussionNote(int midiPitch, int velocity, long microTime) { + if (percussionMap.containsKey(midiPitch)) { + int noteId = percussionMap.get(midiPitch); + int pitch = noteId % 25; + float volume = (float) velocity / 127.0f; + Instrument instrument = Instrument.fromId(noteId / 25); long time = microTime / 1000L; - if (time > song.length) { - song.length = time; - } - } - else if (sm.getCommand() == NOTE_OFF) { - long deltaTick = event.getTick() - prevTick; - prevTick = event.getTick(); - microTime += (mpq/tpq) * deltaTick; - long time = microTime / 1000L; - if (time > song.length) { - song.length = time; - } - } + + return new Note(instrument, pitch, volume, time); } - } + return null; } - song.sort(); - - return song; - } + public static HashMap instrumentMap = new HashMap<>(); - public static Note getMidiInstrumentNote(int midiInstrument, int midiPitch, int velocity, long microTime) { - Instrument instrument = null; - Instrument[] instrumentList = instrumentMap.get(midiInstrument); - if (instrumentList != null) { - for (Instrument candidateInstrument : instrumentList) { - if (midiPitch >= candidateInstrument.offset && midiPitch <= candidateInstrument.offset+24) { - instrument = candidateInstrument; - break; - } - } - } + static { + // Piano (HARP BASS BELL) + instrumentMap.put(0, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); // Acoustic Grand Piano + instrumentMap.put(1, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); // Bright Acoustic Piano + instrumentMap.put(2, new Instrument[]{Instrument.BIT, Instrument.DIDGERIDOO, Instrument.BELL}); // Electric Grand Piano + instrumentMap.put(3, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); // Honky-tonk Piano + instrumentMap.put(4, new Instrument[]{Instrument.BIT, Instrument.DIDGERIDOO, Instrument.BELL}); // Electric Piano 1 + instrumentMap.put(5, new Instrument[]{Instrument.BIT, Instrument.DIDGERIDOO, Instrument.BELL}); // Electric Piano 2 + instrumentMap.put(6, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); // Harpsichord + instrumentMap.put(7, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); // Clavinet - if (instrument == null) { - return null; - } + // Chromatic Percussion (IRON_XYLOPHONE XYLOPHONE BASS) + instrumentMap.put(8, new Instrument[]{Instrument.IRON_XYLOPHONE, Instrument.BASS, Instrument.XYLOPHONE}); // Celesta + instrumentMap.put(9, new Instrument[]{Instrument.IRON_XYLOPHONE, Instrument.BASS, Instrument.XYLOPHONE}); // Glockenspiel + instrumentMap.put(10, new Instrument[]{Instrument.IRON_XYLOPHONE, Instrument.BASS, Instrument.XYLOPHONE}); // Music Box + instrumentMap.put(11, new Instrument[]{Instrument.IRON_XYLOPHONE, Instrument.BASS, Instrument.XYLOPHONE}); // Vibraphone + instrumentMap.put(12, new Instrument[]{Instrument.IRON_XYLOPHONE, Instrument.BASS, Instrument.XYLOPHONE}); // Marimba + instrumentMap.put(13, new Instrument[]{Instrument.IRON_XYLOPHONE, Instrument.BASS, Instrument.XYLOPHONE}); // Xylophone + instrumentMap.put(14, new Instrument[]{Instrument.IRON_XYLOPHONE, Instrument.BASS, Instrument.XYLOPHONE}); // Tubular Bells + instrumentMap.put(15, new Instrument[]{Instrument.IRON_XYLOPHONE, Instrument.BASS, Instrument.XYLOPHONE}); // Dulcimer - int pitch = midiPitch-instrument.offset; - float volume = (float) velocity / 127.0f; - long time = microTime / 1000L; + // Organ (BIT DIDGERIDOO BELL) + instrumentMap.put(16, new Instrument[]{Instrument.DIDGERIDOO, Instrument.BIT, Instrument.XYLOPHONE}); // Drawbar Organ + instrumentMap.put(17, new Instrument[]{Instrument.DIDGERIDOO, Instrument.BIT, Instrument.XYLOPHONE}); // Percussive Organ + instrumentMap.put(18, new Instrument[]{Instrument.DIDGERIDOO, Instrument.BIT, Instrument.XYLOPHONE}); // Rock Organ + instrumentMap.put(19, new Instrument[]{Instrument.DIDGERIDOO, Instrument.BIT, Instrument.XYLOPHONE}); // Church Organ + instrumentMap.put(20, new Instrument[]{Instrument.DIDGERIDOO, Instrument.BIT, Instrument.XYLOPHONE}); // Reed Organ + instrumentMap.put(21, new Instrument[]{Instrument.DIDGERIDOO, Instrument.BIT, Instrument.XYLOPHONE}); // Accordian + instrumentMap.put(22, new Instrument[]{Instrument.DIDGERIDOO, Instrument.BIT, Instrument.XYLOPHONE}); // Harmonica + instrumentMap.put(23, new Instrument[]{Instrument.DIDGERIDOO, Instrument.BIT, Instrument.XYLOPHONE}); // Tango Accordian - return new Note(instrument, pitch, volume, time); - } + // Guitar (BIT DIDGERIDOO BELL) + instrumentMap.put(24, new Instrument[]{Instrument.GUITAR, Instrument.HARP, Instrument.BASS, Instrument.BELL}); // Acoustic Guitar (nylon) + instrumentMap.put(25, new Instrument[]{Instrument.GUITAR, Instrument.HARP, Instrument.BASS, Instrument.BELL}); // Acoustic Guitar (steel) + instrumentMap.put(26, new Instrument[]{Instrument.GUITAR, Instrument.HARP, Instrument.BASS, Instrument.BELL}); // Electric Guitar (jazz) + instrumentMap.put(27, new Instrument[]{Instrument.GUITAR, Instrument.HARP, Instrument.BASS, Instrument.BELL}); // Electric Guitar (clean) + instrumentMap.put(28, new Instrument[]{Instrument.GUITAR, Instrument.HARP, Instrument.BASS, Instrument.BELL}); // Electric Guitar (muted) + instrumentMap.put(29, new Instrument[]{Instrument.DIDGERIDOO, Instrument.BIT, Instrument.XYLOPHONE}); // Overdriven Guitar + instrumentMap.put(30, new Instrument[]{Instrument.DIDGERIDOO, Instrument.BIT, Instrument.XYLOPHONE}); // Distortion Guitar + instrumentMap.put(31, new Instrument[]{Instrument.GUITAR, Instrument.HARP, Instrument.BASS, Instrument.BELL}); // Guitar Harmonics - private static Note getMidiPercussionNote (int midiPitch, int velocity, long microTime) { - if (percussionMap.containsKey(midiPitch)) { - int noteId = percussionMap.get(midiPitch); - int pitch = noteId % 25; - float volume = (float) velocity / 127.0f; - Instrument instrument = Instrument.fromId(noteId / 25); - long time = microTime / 1000L; + // Bass + instrumentMap.put(32, new Instrument[]{Instrument.BASS, Instrument.HARP, Instrument.BELL}); // Acoustic Bass + instrumentMap.put(33, new Instrument[]{Instrument.BASS, Instrument.HARP, Instrument.BELL}); // Electric Bass (finger) + instrumentMap.put(34, new Instrument[]{Instrument.BASS, Instrument.HARP, Instrument.BELL}); // Electric Bass (pick) + instrumentMap.put(35, new Instrument[]{Instrument.BASS, Instrument.HARP, Instrument.BELL}); // Fretless Bass + instrumentMap.put(36, new Instrument[]{Instrument.DIDGERIDOO, Instrument.BIT, Instrument.XYLOPHONE}); // Slap Bass 1 + instrumentMap.put(37, new Instrument[]{Instrument.DIDGERIDOO, Instrument.BIT, Instrument.XYLOPHONE}); // Slap Bass 2 + instrumentMap.put(38, new Instrument[]{Instrument.DIDGERIDOO, Instrument.BIT, Instrument.XYLOPHONE}); // Synth Bass 1 + instrumentMap.put(39, new Instrument[]{Instrument.DIDGERIDOO, Instrument.BIT, Instrument.XYLOPHONE}); // Synth Bass 2 - return new Note(instrument, pitch, volume, time); - } - return null; - } + // Strings + instrumentMap.put(40, new Instrument[]{Instrument.FLUTE, Instrument.GUITAR, Instrument.BASS, Instrument.BELL}); // Violin + instrumentMap.put(41, new Instrument[]{Instrument.FLUTE, Instrument.GUITAR, Instrument.BASS, Instrument.BELL}); // Viola + instrumentMap.put(42, new Instrument[]{Instrument.FLUTE, Instrument.GUITAR, Instrument.BASS, Instrument.BELL}); // Cello + instrumentMap.put(43, new Instrument[]{Instrument.FLUTE, Instrument.GUITAR, Instrument.BASS, Instrument.BELL}); // Contrabass + instrumentMap.put(44, new Instrument[]{Instrument.BIT, Instrument.DIDGERIDOO, Instrument.BELL}); // Tremolo Strings + instrumentMap.put(45, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); // Pizzicato Strings + instrumentMap.put(46, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.CHIME}); // Orchestral Harp + instrumentMap.put(47, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); // Timpani - public static HashMap instrumentMap = new HashMap<>(); - static { - // Piano (HARP BASS BELL) - instrumentMap.put(0, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); // Acoustic Grand Piano - instrumentMap.put(1, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); // Bright Acoustic Piano - instrumentMap.put(2, new Instrument[]{Instrument.BIT, Instrument.DIDGERIDOO, Instrument.BELL}); // Electric Grand Piano - instrumentMap.put(3, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); // Honky-tonk Piano - instrumentMap.put(4, new Instrument[]{Instrument.BIT, Instrument.DIDGERIDOO, Instrument.BELL}); // Electric Piano 1 - instrumentMap.put(5, new Instrument[]{Instrument.BIT, Instrument.DIDGERIDOO, Instrument.BELL}); // Electric Piano 2 - instrumentMap.put(6, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); // Harpsichord - instrumentMap.put(7, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); // Clavinet + // Ensenble + instrumentMap.put(48, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); // String Ensemble 1 + instrumentMap.put(49, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); // String Ensemble 2 + instrumentMap.put(50, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); // Synth Strings 1 + instrumentMap.put(51, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); // Synth Strings 2 + instrumentMap.put(52, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); // Choir Aahs + instrumentMap.put(53, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); // Voice Oohs + instrumentMap.put(54, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); // Synth Choir + instrumentMap.put(55, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); // Orchestra Hit - // Chromatic Percussion (IRON_XYLOPHONE XYLOPHONE BASS) - instrumentMap.put(8, new Instrument[]{Instrument.IRON_XYLOPHONE, Instrument.BASS, Instrument.XYLOPHONE}); // Celesta - instrumentMap.put(9, new Instrument[]{Instrument.IRON_XYLOPHONE, Instrument.BASS, Instrument.XYLOPHONE}); // Glockenspiel - instrumentMap.put(10, new Instrument[]{Instrument.IRON_XYLOPHONE, Instrument.BASS, Instrument.XYLOPHONE}); // Music Box - instrumentMap.put(11, new Instrument[]{Instrument.IRON_XYLOPHONE, Instrument.BASS, Instrument.XYLOPHONE}); // Vibraphone - instrumentMap.put(12, new Instrument[]{Instrument.IRON_XYLOPHONE, Instrument.BASS, Instrument.XYLOPHONE}); // Marimba - instrumentMap.put(13, new Instrument[]{Instrument.IRON_XYLOPHONE, Instrument.BASS, Instrument.XYLOPHONE}); // Xylophone - instrumentMap.put(14, new Instrument[]{Instrument.IRON_XYLOPHONE, Instrument.BASS, Instrument.XYLOPHONE}); // Tubular Bells - instrumentMap.put(15, new Instrument[]{Instrument.IRON_XYLOPHONE, Instrument.BASS, Instrument.XYLOPHONE}); // Dulcimer + // Brass + instrumentMap.put(56, new Instrument[]{Instrument.BIT, Instrument.DIDGERIDOO, Instrument.BELL}); + instrumentMap.put(57, new Instrument[]{Instrument.BIT, Instrument.DIDGERIDOO, Instrument.BELL}); + instrumentMap.put(58, new Instrument[]{Instrument.BIT, Instrument.DIDGERIDOO, Instrument.BELL}); + instrumentMap.put(59, new Instrument[]{Instrument.BIT, Instrument.DIDGERIDOO, Instrument.BELL}); + instrumentMap.put(60, new Instrument[]{Instrument.BIT, Instrument.DIDGERIDOO, Instrument.BELL}); + instrumentMap.put(61, new Instrument[]{Instrument.BIT, Instrument.DIDGERIDOO, Instrument.BELL}); + instrumentMap.put(62, new Instrument[]{Instrument.BIT, Instrument.DIDGERIDOO, Instrument.BELL}); + instrumentMap.put(63, new Instrument[]{Instrument.BIT, Instrument.DIDGERIDOO, Instrument.BELL}); - // Organ (BIT DIDGERIDOO BELL) - instrumentMap.put(16, new Instrument[]{Instrument.DIDGERIDOO, Instrument.BIT, Instrument.XYLOPHONE}); // Drawbar Organ - instrumentMap.put(17, new Instrument[]{Instrument.DIDGERIDOO, Instrument.BIT, Instrument.XYLOPHONE}); // Percussive Organ - instrumentMap.put(18, new Instrument[]{Instrument.DIDGERIDOO, Instrument.BIT, Instrument.XYLOPHONE}); // Rock Organ - instrumentMap.put(19, new Instrument[]{Instrument.DIDGERIDOO, Instrument.BIT, Instrument.XYLOPHONE}); // Church Organ - instrumentMap.put(20, new Instrument[]{Instrument.DIDGERIDOO, Instrument.BIT, Instrument.XYLOPHONE}); // Reed Organ - instrumentMap.put(21, new Instrument[]{Instrument.DIDGERIDOO, Instrument.BIT, Instrument.XYLOPHONE}); // Accordian - instrumentMap.put(22, new Instrument[]{Instrument.DIDGERIDOO, Instrument.BIT, Instrument.XYLOPHONE}); // Harmonica - instrumentMap.put(23, new Instrument[]{Instrument.DIDGERIDOO, Instrument.BIT, Instrument.XYLOPHONE}); // Tango Accordian + // Reed + instrumentMap.put(64, new Instrument[]{Instrument.FLUTE, Instrument.DIDGERIDOO, Instrument.IRON_XYLOPHONE, Instrument.BELL}); + instrumentMap.put(65, new Instrument[]{Instrument.FLUTE, Instrument.DIDGERIDOO, Instrument.IRON_XYLOPHONE, Instrument.BELL}); + instrumentMap.put(66, new Instrument[]{Instrument.FLUTE, Instrument.DIDGERIDOO, Instrument.IRON_XYLOPHONE, Instrument.BELL}); + instrumentMap.put(67, new Instrument[]{Instrument.FLUTE, Instrument.DIDGERIDOO, Instrument.IRON_XYLOPHONE, Instrument.BELL}); + instrumentMap.put(68, new Instrument[]{Instrument.FLUTE, Instrument.DIDGERIDOO, Instrument.IRON_XYLOPHONE, Instrument.BELL}); + instrumentMap.put(69, new Instrument[]{Instrument.FLUTE, Instrument.DIDGERIDOO, Instrument.IRON_XYLOPHONE, Instrument.BELL}); + instrumentMap.put(70, new Instrument[]{Instrument.FLUTE, Instrument.DIDGERIDOO, Instrument.IRON_XYLOPHONE, Instrument.BELL}); + instrumentMap.put(71, new Instrument[]{Instrument.FLUTE, Instrument.DIDGERIDOO, Instrument.IRON_XYLOPHONE, Instrument.BELL}); - // Guitar (BIT DIDGERIDOO BELL) - instrumentMap.put(24, new Instrument[]{Instrument.GUITAR, Instrument.HARP, Instrument.BASS, Instrument.BELL}); // Acoustic Guitar (nylon) - instrumentMap.put(25, new Instrument[]{Instrument.GUITAR, Instrument.HARP, Instrument.BASS, Instrument.BELL}); // Acoustic Guitar (steel) - instrumentMap.put(26, new Instrument[]{Instrument.GUITAR, Instrument.HARP, Instrument.BASS, Instrument.BELL}); // Electric Guitar (jazz) - instrumentMap.put(27, new Instrument[]{Instrument.GUITAR, Instrument.HARP, Instrument.BASS, Instrument.BELL}); // Electric Guitar (clean) - instrumentMap.put(28, new Instrument[]{Instrument.GUITAR, Instrument.HARP, Instrument.BASS, Instrument.BELL}); // Electric Guitar (muted) - instrumentMap.put(29, new Instrument[]{Instrument.DIDGERIDOO, Instrument.BIT, Instrument.XYLOPHONE}); // Overdriven Guitar - instrumentMap.put(30, new Instrument[]{Instrument.DIDGERIDOO, Instrument.BIT, Instrument.XYLOPHONE}); // Distortion Guitar - instrumentMap.put(31, new Instrument[]{Instrument.GUITAR, Instrument.HARP, Instrument.BASS, Instrument.BELL}); // Guitar Harmonics + // Pipe + instrumentMap.put(72, new Instrument[]{Instrument.FLUTE, Instrument.DIDGERIDOO, Instrument.IRON_XYLOPHONE, Instrument.BELL}); + instrumentMap.put(73, new Instrument[]{Instrument.FLUTE, Instrument.DIDGERIDOO, Instrument.IRON_XYLOPHONE, Instrument.BELL}); + instrumentMap.put(74, new Instrument[]{Instrument.FLUTE, Instrument.DIDGERIDOO, Instrument.IRON_XYLOPHONE, Instrument.BELL}); + instrumentMap.put(75, new Instrument[]{Instrument.FLUTE, Instrument.DIDGERIDOO, Instrument.IRON_XYLOPHONE, Instrument.BELL}); + instrumentMap.put(76, new Instrument[]{Instrument.FLUTE, Instrument.DIDGERIDOO, Instrument.IRON_XYLOPHONE, Instrument.BELL}); + instrumentMap.put(77, new Instrument[]{Instrument.FLUTE, Instrument.DIDGERIDOO, Instrument.IRON_XYLOPHONE, Instrument.BELL}); + instrumentMap.put(78, new Instrument[]{Instrument.FLUTE, Instrument.DIDGERIDOO, Instrument.IRON_XYLOPHONE, Instrument.BELL}); + instrumentMap.put(79, new Instrument[]{Instrument.FLUTE, Instrument.DIDGERIDOO, Instrument.IRON_XYLOPHONE, Instrument.BELL}); - // Bass - instrumentMap.put(32, new Instrument[]{Instrument.BASS, Instrument.HARP, Instrument.BELL}); // Acoustic Bass - instrumentMap.put(33, new Instrument[]{Instrument.BASS, Instrument.HARP, Instrument.BELL}); // Electric Bass (finger) - instrumentMap.put(34, new Instrument[]{Instrument.BASS, Instrument.HARP, Instrument.BELL}); // Electric Bass (pick) - instrumentMap.put(35, new Instrument[]{Instrument.BASS, Instrument.HARP, Instrument.BELL}); // Fretless Bass - instrumentMap.put(36, new Instrument[]{Instrument.DIDGERIDOO, Instrument.BIT, Instrument.XYLOPHONE}); // Slap Bass 1 - instrumentMap.put(37, new Instrument[]{Instrument.DIDGERIDOO, Instrument.BIT, Instrument.XYLOPHONE}); // Slap Bass 2 - instrumentMap.put(38, new Instrument[]{Instrument.DIDGERIDOO, Instrument.BIT, Instrument.XYLOPHONE}); // Synth Bass 1 - instrumentMap.put(39, new Instrument[]{Instrument.DIDGERIDOO, Instrument.BIT, Instrument.XYLOPHONE}); // Synth Bass 2 + // Synth Lead + instrumentMap.put(80, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); + instrumentMap.put(81, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); + instrumentMap.put(82, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); + instrumentMap.put(83, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); + instrumentMap.put(84, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); + instrumentMap.put(85, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); + instrumentMap.put(86, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); + instrumentMap.put(87, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); - // Strings - instrumentMap.put(40, new Instrument[]{Instrument.FLUTE, Instrument.GUITAR, Instrument.BASS, Instrument.BELL}); // Violin - instrumentMap.put(41, new Instrument[]{Instrument.FLUTE, Instrument.GUITAR, Instrument.BASS, Instrument.BELL}); // Viola - instrumentMap.put(42, new Instrument[]{Instrument.FLUTE, Instrument.GUITAR, Instrument.BASS, Instrument.BELL}); // Cello - instrumentMap.put(43, new Instrument[]{Instrument.FLUTE, Instrument.GUITAR, Instrument.BASS, Instrument.BELL}); // Contrabass - instrumentMap.put(44, new Instrument[]{Instrument.BIT, Instrument.DIDGERIDOO, Instrument.BELL}); // Tremolo Strings - instrumentMap.put(45, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); // Pizzicato Strings - instrumentMap.put(46, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.CHIME}); // Orchestral Harp - instrumentMap.put(47, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); // Timpani + // Synth Pad + instrumentMap.put(88, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); + instrumentMap.put(89, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); + instrumentMap.put(90, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); + instrumentMap.put(91, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); + instrumentMap.put(92, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); + instrumentMap.put(93, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); + instrumentMap.put(94, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); + instrumentMap.put(95, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); - // Ensenble - instrumentMap.put(48, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); // String Ensemble 1 - instrumentMap.put(49, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); // String Ensemble 2 - instrumentMap.put(50, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); // Synth Strings 1 - instrumentMap.put(51, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); // Synth Strings 2 - instrumentMap.put(52, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); // Choir Aahs - instrumentMap.put(53, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); // Voice Oohs - instrumentMap.put(54, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); // Synth Choir - instrumentMap.put(55, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); // Orchestra Hit - - // Brass - instrumentMap.put(56, new Instrument[]{Instrument.BIT, Instrument.DIDGERIDOO, Instrument.BELL}); - instrumentMap.put(57, new Instrument[]{Instrument.BIT, Instrument.DIDGERIDOO, Instrument.BELL}); - instrumentMap.put(58, new Instrument[]{Instrument.BIT, Instrument.DIDGERIDOO, Instrument.BELL}); - instrumentMap.put(59, new Instrument[]{Instrument.BIT, Instrument.DIDGERIDOO, Instrument.BELL}); - instrumentMap.put(60, new Instrument[]{Instrument.BIT, Instrument.DIDGERIDOO, Instrument.BELL}); - instrumentMap.put(61, new Instrument[]{Instrument.BIT, Instrument.DIDGERIDOO, Instrument.BELL}); - instrumentMap.put(62, new Instrument[]{Instrument.BIT, Instrument.DIDGERIDOO, Instrument.BELL}); - instrumentMap.put(63, new Instrument[]{Instrument.BIT, Instrument.DIDGERIDOO, Instrument.BELL}); - - // Reed - instrumentMap.put(64, new Instrument[]{Instrument.FLUTE, Instrument.DIDGERIDOO, Instrument.IRON_XYLOPHONE, Instrument.BELL}); - instrumentMap.put(65, new Instrument[]{Instrument.FLUTE, Instrument.DIDGERIDOO, Instrument.IRON_XYLOPHONE, Instrument.BELL}); - instrumentMap.put(66, new Instrument[]{Instrument.FLUTE, Instrument.DIDGERIDOO, Instrument.IRON_XYLOPHONE, Instrument.BELL}); - instrumentMap.put(67, new Instrument[]{Instrument.FLUTE, Instrument.DIDGERIDOO, Instrument.IRON_XYLOPHONE, Instrument.BELL}); - instrumentMap.put(68, new Instrument[]{Instrument.FLUTE, Instrument.DIDGERIDOO, Instrument.IRON_XYLOPHONE, Instrument.BELL}); - instrumentMap.put(69, new Instrument[]{Instrument.FLUTE, Instrument.DIDGERIDOO, Instrument.IRON_XYLOPHONE, Instrument.BELL}); - instrumentMap.put(70, new Instrument[]{Instrument.FLUTE, Instrument.DIDGERIDOO, Instrument.IRON_XYLOPHONE, Instrument.BELL}); - instrumentMap.put(71, new Instrument[]{Instrument.FLUTE, Instrument.DIDGERIDOO, Instrument.IRON_XYLOPHONE, Instrument.BELL}); - - // Pipe - instrumentMap.put(72, new Instrument[]{Instrument.FLUTE, Instrument.DIDGERIDOO, Instrument.IRON_XYLOPHONE, Instrument.BELL}); - instrumentMap.put(73, new Instrument[]{Instrument.FLUTE, Instrument.DIDGERIDOO, Instrument.IRON_XYLOPHONE, Instrument.BELL}); - instrumentMap.put(74, new Instrument[]{Instrument.FLUTE, Instrument.DIDGERIDOO, Instrument.IRON_XYLOPHONE, Instrument.BELL}); - instrumentMap.put(75, new Instrument[]{Instrument.FLUTE, Instrument.DIDGERIDOO, Instrument.IRON_XYLOPHONE, Instrument.BELL}); - instrumentMap.put(76, new Instrument[]{Instrument.FLUTE, Instrument.DIDGERIDOO, Instrument.IRON_XYLOPHONE, Instrument.BELL}); - instrumentMap.put(77, new Instrument[]{Instrument.FLUTE, Instrument.DIDGERIDOO, Instrument.IRON_XYLOPHONE, Instrument.BELL}); - instrumentMap.put(78, new Instrument[]{Instrument.FLUTE, Instrument.DIDGERIDOO, Instrument.IRON_XYLOPHONE, Instrument.BELL}); - instrumentMap.put(79, new Instrument[]{Instrument.FLUTE, Instrument.DIDGERIDOO, Instrument.IRON_XYLOPHONE, Instrument.BELL}); - - // Synth Lead - instrumentMap.put(80, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); - instrumentMap.put(81, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); - instrumentMap.put(82, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); - instrumentMap.put(83, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); - instrumentMap.put(84, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); - instrumentMap.put(85, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); - instrumentMap.put(86, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); - instrumentMap.put(87, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); - - // Synth Pad - instrumentMap.put(88, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); - instrumentMap.put(89, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); - instrumentMap.put(90, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); - instrumentMap.put(91, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); - instrumentMap.put(92, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); - instrumentMap.put(93, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); - instrumentMap.put(94, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); - instrumentMap.put(95, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); - - // Synth Effects + // Synth Effects // instrumentMap.put(96, new Instrument[]{}); // instrumentMap.put(97, new Instrument[]{}); - instrumentMap.put(98, new Instrument[]{Instrument.BIT, Instrument.DIDGERIDOO, Instrument.BELL}); - instrumentMap.put(99, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); - instrumentMap.put(100, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); - instrumentMap.put(101, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); - instrumentMap.put(102, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); - instrumentMap.put(103, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); + instrumentMap.put(98, new Instrument[]{Instrument.BIT, Instrument.DIDGERIDOO, Instrument.BELL}); + instrumentMap.put(99, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); + instrumentMap.put(100, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); + instrumentMap.put(101, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); + instrumentMap.put(102, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); + instrumentMap.put(103, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); - // Ethnic - instrumentMap.put(104, new Instrument[]{Instrument.BANJO, Instrument.BASS, Instrument.BELL}); - instrumentMap.put(105, new Instrument[]{Instrument.BANJO, Instrument.BASS, Instrument.BELL}); - instrumentMap.put(106, new Instrument[]{Instrument.BANJO, Instrument.BASS, Instrument.BELL}); - instrumentMap.put(107, new Instrument[]{Instrument.BANJO, Instrument.BASS, Instrument.BELL}); - instrumentMap.put(108, new Instrument[]{Instrument.BANJO, Instrument.BASS, Instrument.BELL}); - instrumentMap.put(109, new Instrument[]{Instrument.HARP, Instrument.DIDGERIDOO, Instrument.BELL}); - instrumentMap.put(110, new Instrument[]{Instrument.HARP, Instrument.DIDGERIDOO, Instrument.BELL}); - instrumentMap.put(111, new Instrument[]{Instrument.HARP, Instrument.DIDGERIDOO, Instrument.BELL}); + // Ethnic + instrumentMap.put(104, new Instrument[]{Instrument.BANJO, Instrument.BASS, Instrument.BELL}); + instrumentMap.put(105, new Instrument[]{Instrument.BANJO, Instrument.BASS, Instrument.BELL}); + instrumentMap.put(106, new Instrument[]{Instrument.BANJO, Instrument.BASS, Instrument.BELL}); + instrumentMap.put(107, new Instrument[]{Instrument.BANJO, Instrument.BASS, Instrument.BELL}); + instrumentMap.put(108, new Instrument[]{Instrument.BANJO, Instrument.BASS, Instrument.BELL}); + instrumentMap.put(109, new Instrument[]{Instrument.HARP, Instrument.DIDGERIDOO, Instrument.BELL}); + instrumentMap.put(110, new Instrument[]{Instrument.HARP, Instrument.DIDGERIDOO, Instrument.BELL}); + instrumentMap.put(111, new Instrument[]{Instrument.HARP, Instrument.DIDGERIDOO, Instrument.BELL}); - // Percussive - instrumentMap.put(112, new Instrument[]{Instrument.IRON_XYLOPHONE, Instrument.BASS, Instrument.XYLOPHONE}); - instrumentMap.put(113, new Instrument[]{Instrument.IRON_XYLOPHONE, Instrument.BASS, Instrument.XYLOPHONE}); - instrumentMap.put(114, new Instrument[]{Instrument.IRON_XYLOPHONE, Instrument.BASS, Instrument.XYLOPHONE}); - instrumentMap.put(115, new Instrument[]{Instrument.IRON_XYLOPHONE, Instrument.BASS, Instrument.XYLOPHONE}); - instrumentMap.put(116, new Instrument[]{Instrument.IRON_XYLOPHONE, Instrument.BASS, Instrument.XYLOPHONE}); - instrumentMap.put(117, new Instrument[]{Instrument.IRON_XYLOPHONE, Instrument.BASS, Instrument.XYLOPHONE}); - instrumentMap.put(118, new Instrument[]{Instrument.IRON_XYLOPHONE, Instrument.BASS, Instrument.XYLOPHONE}); - instrumentMap.put(119, new Instrument[]{Instrument.IRON_XYLOPHONE, Instrument.BASS, Instrument.XYLOPHONE}); - } + // Percussive + instrumentMap.put(112, new Instrument[]{Instrument.IRON_XYLOPHONE, Instrument.BASS, Instrument.XYLOPHONE}); + instrumentMap.put(113, new Instrument[]{Instrument.IRON_XYLOPHONE, Instrument.BASS, Instrument.XYLOPHONE}); + instrumentMap.put(114, new Instrument[]{Instrument.IRON_XYLOPHONE, Instrument.BASS, Instrument.XYLOPHONE}); + instrumentMap.put(115, new Instrument[]{Instrument.IRON_XYLOPHONE, Instrument.BASS, Instrument.XYLOPHONE}); + instrumentMap.put(116, new Instrument[]{Instrument.IRON_XYLOPHONE, Instrument.BASS, Instrument.XYLOPHONE}); + instrumentMap.put(117, new Instrument[]{Instrument.IRON_XYLOPHONE, Instrument.BASS, Instrument.XYLOPHONE}); + instrumentMap.put(118, new Instrument[]{Instrument.IRON_XYLOPHONE, Instrument.BASS, Instrument.XYLOPHONE}); + instrumentMap.put(119, new Instrument[]{Instrument.IRON_XYLOPHONE, Instrument.BASS, Instrument.XYLOPHONE}); + } - public static HashMap percussionMap = new HashMap<>(); - static { - percussionMap.put(35, 10 + 25*Instrument.BASEDRUM.id); - percussionMap.put(36, 6 + 25*Instrument.BASEDRUM.id); - percussionMap.put(37, 6 + 25*Instrument.HAT.id); - percussionMap.put(38, 8 + 25*Instrument.SNARE.id); - percussionMap.put(39, 6 + 25*Instrument.HAT.id); - percussionMap.put(40, 4 + 25*Instrument.SNARE.id); - percussionMap.put(41, 6 + 25*Instrument.BASEDRUM.id); - percussionMap.put(42, 22 + 25*Instrument.SNARE.id); - percussionMap.put(43, 13 + 25*Instrument.BASEDRUM.id); - percussionMap.put(44, 22 + 25*Instrument.SNARE.id); - percussionMap.put(45, 15 + 25*Instrument.BASEDRUM.id); - percussionMap.put(46, 18 + 25*Instrument.SNARE.id); - percussionMap.put(47, 20 + 25*Instrument.BASEDRUM.id); - percussionMap.put(48, 23 + 25*Instrument.BASEDRUM.id); - percussionMap.put(49, 17 + 25*Instrument.SNARE.id); - percussionMap.put(50, 23 + 25*Instrument.BASEDRUM.id); - percussionMap.put(51, 24 + 25*Instrument.SNARE.id); - percussionMap.put(52, 8 + 25*Instrument.SNARE.id); - percussionMap.put(53, 13 + 25*Instrument.SNARE.id); - percussionMap.put(54, 18 + 25*Instrument.HAT.id); - percussionMap.put(55, 18 + 25*Instrument.SNARE.id); - percussionMap.put(56, 1 + 25*Instrument.HAT.id); - percussionMap.put(57, 13 + 25*Instrument.SNARE.id); - percussionMap.put(58, 2 + 25*Instrument.HAT.id); - percussionMap.put(59, 13 + 25*Instrument.SNARE.id); - percussionMap.put(60, 9 + 25*Instrument.HAT.id); - percussionMap.put(61, 2 + 25*Instrument.HAT.id); - percussionMap.put(62, 8 + 25*Instrument.HAT.id); - percussionMap.put(63, 22 + 25*Instrument.BASEDRUM.id); - percussionMap.put(64, 15 + 25*Instrument.BASEDRUM.id); - percussionMap.put(65, 13 + 25*Instrument.SNARE.id); - percussionMap.put(66, 8 + 25*Instrument.SNARE.id); - percussionMap.put(67, 8 + 25*Instrument.HAT.id); - percussionMap.put(68, 3 + 25*Instrument.HAT.id); - percussionMap.put(69, 20 + 25*Instrument.HAT.id); - percussionMap.put(70, 23 + 25*Instrument.HAT.id); - percussionMap.put(71, 24 + 25*Instrument.HAT.id); - percussionMap.put(72, 24 + 25*Instrument.HAT.id); - percussionMap.put(73, 17 + 25*Instrument.HAT.id); - percussionMap.put(74, 11 + 25*Instrument.HAT.id); - percussionMap.put(75, 18 + 25*Instrument.HAT.id); - percussionMap.put(76, 9 + 25*Instrument.HAT.id); - percussionMap.put(77, 5 + 25*Instrument.HAT.id); - percussionMap.put(78, 22 + 25*Instrument.HAT.id); - percussionMap.put(79, 19 + 25*Instrument.SNARE.id); - percussionMap.put(80, 17 + 25*Instrument.HAT.id); - percussionMap.put(81, 22 + 25*Instrument.HAT.id); - percussionMap.put(82, 22 + 25*Instrument.SNARE.id); - percussionMap.put(83, 24 + 25*Instrument.CHIME.id); - percussionMap.put(84, 24 + 25*Instrument.CHIME.id); - percussionMap.put(85, 21 + 25*Instrument.HAT.id); - percussionMap.put(86, 14 + 25*Instrument.BASEDRUM.id); - percussionMap.put(87, 7 + 25*Instrument.BASEDRUM.id); - } + public static HashMap percussionMap = new HashMap<>(); + + static { + percussionMap.put(35, 10 + 25 * Instrument.BASEDRUM.id); + percussionMap.put(36, 6 + 25 * Instrument.BASEDRUM.id); + percussionMap.put(37, 6 + 25 * Instrument.HAT.id); + percussionMap.put(38, 8 + 25 * Instrument.SNARE.id); + percussionMap.put(39, 6 + 25 * Instrument.HAT.id); + percussionMap.put(40, 4 + 25 * Instrument.SNARE.id); + percussionMap.put(41, 6 + 25 * Instrument.BASEDRUM.id); + percussionMap.put(42, 22 + 25 * Instrument.SNARE.id); + percussionMap.put(43, 13 + 25 * Instrument.BASEDRUM.id); + percussionMap.put(44, 22 + 25 * Instrument.SNARE.id); + percussionMap.put(45, 15 + 25 * Instrument.BASEDRUM.id); + percussionMap.put(46, 18 + 25 * Instrument.SNARE.id); + percussionMap.put(47, 20 + 25 * Instrument.BASEDRUM.id); + percussionMap.put(48, 23 + 25 * Instrument.BASEDRUM.id); + percussionMap.put(49, 17 + 25 * Instrument.SNARE.id); + percussionMap.put(50, 23 + 25 * Instrument.BASEDRUM.id); + percussionMap.put(51, 24 + 25 * Instrument.SNARE.id); + percussionMap.put(52, 8 + 25 * Instrument.SNARE.id); + percussionMap.put(53, 13 + 25 * Instrument.SNARE.id); + percussionMap.put(54, 18 + 25 * Instrument.HAT.id); + percussionMap.put(55, 18 + 25 * Instrument.SNARE.id); + percussionMap.put(56, 1 + 25 * Instrument.HAT.id); + percussionMap.put(57, 13 + 25 * Instrument.SNARE.id); + percussionMap.put(58, 2 + 25 * Instrument.HAT.id); + percussionMap.put(59, 13 + 25 * Instrument.SNARE.id); + percussionMap.put(60, 9 + 25 * Instrument.HAT.id); + percussionMap.put(61, 2 + 25 * Instrument.HAT.id); + percussionMap.put(62, 8 + 25 * Instrument.HAT.id); + percussionMap.put(63, 22 + 25 * Instrument.BASEDRUM.id); + percussionMap.put(64, 15 + 25 * Instrument.BASEDRUM.id); + percussionMap.put(65, 13 + 25 * Instrument.SNARE.id); + percussionMap.put(66, 8 + 25 * Instrument.SNARE.id); + percussionMap.put(67, 8 + 25 * Instrument.HAT.id); + percussionMap.put(68, 3 + 25 * Instrument.HAT.id); + percussionMap.put(69, 20 + 25 * Instrument.HAT.id); + percussionMap.put(70, 23 + 25 * Instrument.HAT.id); + percussionMap.put(71, 24 + 25 * Instrument.HAT.id); + percussionMap.put(72, 24 + 25 * Instrument.HAT.id); + percussionMap.put(73, 17 + 25 * Instrument.HAT.id); + percussionMap.put(74, 11 + 25 * Instrument.HAT.id); + percussionMap.put(75, 18 + 25 * Instrument.HAT.id); + percussionMap.put(76, 9 + 25 * Instrument.HAT.id); + percussionMap.put(77, 5 + 25 * Instrument.HAT.id); + percussionMap.put(78, 22 + 25 * Instrument.HAT.id); + percussionMap.put(79, 19 + 25 * Instrument.SNARE.id); + percussionMap.put(80, 17 + 25 * Instrument.HAT.id); + percussionMap.put(81, 22 + 25 * Instrument.HAT.id); + percussionMap.put(82, 22 + 25 * Instrument.SNARE.id); + percussionMap.put(83, 24 + 25 * Instrument.CHIME.id); + percussionMap.put(84, 24 + 25 * Instrument.CHIME.id); + percussionMap.put(85, 21 + 25 * Instrument.HAT.id); + percussionMap.put(86, 14 + 25 * Instrument.BASEDRUM.id); + percussionMap.put(87, 7 + 25 * Instrument.BASEDRUM.id); + } } diff --git a/src/main/java/land/chipmunk/chipmunkmod/song/NBSConverter.java b/src/main/java/land/chipmunk/chipmunkmod/song/NBSConverter.java index c78d962..d1e4419 100644 --- a/src/main/java/land/chipmunk/chipmunkmod/song/NBSConverter.java +++ b/src/main/java/land/chipmunk/chipmunkmod/song/NBSConverter.java @@ -6,192 +6,192 @@ import java.nio.ByteOrder; import java.util.ArrayList; public class NBSConverter { - public static Instrument[] instrumentIndex = new Instrument[] { - Instrument.HARP, - Instrument.BASS, - Instrument.BASEDRUM, - Instrument.SNARE, - Instrument.HAT, - Instrument.GUITAR, - Instrument.FLUTE, - Instrument.BELL, - Instrument.CHIME, - Instrument.XYLOPHONE, - Instrument.IRON_XYLOPHONE, - Instrument.COW_BELL, - Instrument.DIDGERIDOO, - Instrument.BIT, - Instrument.BANJO, - Instrument.PLING, - }; + public static Instrument[] instrumentIndex = new Instrument[]{ + Instrument.HARP, + Instrument.BASS, + Instrument.BASEDRUM, + Instrument.SNARE, + Instrument.HAT, + Instrument.GUITAR, + Instrument.FLUTE, + Instrument.BELL, + Instrument.CHIME, + Instrument.XYLOPHONE, + Instrument.IRON_XYLOPHONE, + Instrument.COW_BELL, + Instrument.DIDGERIDOO, + Instrument.BIT, + Instrument.BANJO, + Instrument.PLING, + }; - private static class NBSNote { - public int tick; - public short layer; - public byte instrument; - public byte key; - public byte velocity = 100; - public byte panning = 100; - public short pitch = 0; - } - - private static class NBSLayer { - public String name; - public byte lock = 0; - public byte volume; - public byte stereo = 100; - } - - private static class NBSCustomInstrument { - public String name; - public String file; - public byte pitch = 0; - public boolean key = false; - } - - public static Song getSongFromBytes(byte[] bytes, String fileName) throws IOException { - ByteBuffer buffer = ByteBuffer.wrap(bytes); - buffer.order(ByteOrder.LITTLE_ENDIAN); - - short songLength = 0; - byte format = 0; - byte vanillaInstrumentCount = 0; - songLength = buffer.getShort(); // If it's not 0, then it uses the old format - if (songLength == 0) { - format = buffer.get(); + private static class NBSNote { + public int tick; + public short layer; + public byte instrument; + public byte key; + public byte velocity = 100; + public byte panning = 100; + public short pitch = 0; } - if (format >= 1) { - vanillaInstrumentCount = buffer.get(); - } - if (format >= 3) { - songLength = buffer.getShort(); + private static class NBSLayer { + public String name; + public byte lock = 0; + public byte volume; + public byte stereo = 100; } - short layerCount = buffer.getShort(); - String songName = getString(buffer, bytes.length); - String songAuthor = getString(buffer, bytes.length); - String songOriginalAuthor = getString(buffer, bytes.length); - String songDescription = getString(buffer, bytes.length); - short tempo = buffer.getShort(); - byte autoSaving = buffer.get(); - byte autoSavingDuration = buffer.get(); - byte timeSignature = buffer.get(); - int minutesSpent = buffer.getInt(); - int leftClicks = buffer.getInt(); - int rightClicks = buffer.getInt(); - int blocksAdded = buffer.getInt(); - int blocksRemoved = buffer.getInt(); - String origFileName = getString(buffer, bytes.length); - - byte loop = 0; - byte maxLoopCount = 0; - short loopStartTick = 0; - if (format >= 4) { - loop = buffer.get(); - maxLoopCount = buffer.get(); - loopStartTick = buffer.getShort(); + private static class NBSCustomInstrument { + public String name; + public String file; + public byte pitch = 0; + public boolean key = false; } - ArrayList nbsNotes = new ArrayList<>(); - short tick = -1; - while (true) { - int tickJumps = buffer.getShort(); - if (tickJumps == 0) break; - tick += tickJumps; + public static Song getSongFromBytes(byte[] bytes, String fileName) throws IOException { + ByteBuffer buffer = ByteBuffer.wrap(bytes); + buffer.order(ByteOrder.LITTLE_ENDIAN); - short layer = -1; - while (true) { - int layerJumps = buffer.getShort(); - if (layerJumps == 0) break; - layer += layerJumps; - NBSNote note = new NBSNote(); - note.tick = tick; - note.layer = layer; - note.instrument = buffer.get(); - note.key = buffer.get(); + short songLength = 0; + byte format = 0; + byte vanillaInstrumentCount = 0; + songLength = buffer.getShort(); // If it's not 0, then it uses the old format + if (songLength == 0) { + format = buffer.get(); + } + + if (format >= 1) { + vanillaInstrumentCount = buffer.get(); + } + if (format >= 3) { + songLength = buffer.getShort(); + } + + short layerCount = buffer.getShort(); + String songName = getString(buffer, bytes.length); + String songAuthor = getString(buffer, bytes.length); + String songOriginalAuthor = getString(buffer, bytes.length); + String songDescription = getString(buffer, bytes.length); + short tempo = buffer.getShort(); + byte autoSaving = buffer.get(); + byte autoSavingDuration = buffer.get(); + byte timeSignature = buffer.get(); + int minutesSpent = buffer.getInt(); + int leftClicks = buffer.getInt(); + int rightClicks = buffer.getInt(); + int blocksAdded = buffer.getInt(); + int blocksRemoved = buffer.getInt(); + String origFileName = getString(buffer, bytes.length); + + byte loop = 0; + byte maxLoopCount = 0; + short loopStartTick = 0; if (format >= 4) { - note.velocity = buffer.get(); - note.panning = buffer.get(); - note.pitch = buffer.getShort(); + loop = buffer.get(); + maxLoopCount = buffer.get(); + loopStartTick = buffer.getShort(); } - nbsNotes.add(note); - } - } - ArrayList nbsLayers = new ArrayList<>(); - if (buffer.hasRemaining()) { - for (int i=0; i= 4) { - layer.lock = buffer.get(); + ArrayList nbsNotes = new ArrayList<>(); + short tick = -1; + while (true) { + int tickJumps = buffer.getShort(); + if (tickJumps == 0) break; + tick += tickJumps; + + short layer = -1; + while (true) { + int layerJumps = buffer.getShort(); + if (layerJumps == 0) break; + layer += layerJumps; + NBSNote note = new NBSNote(); + note.tick = tick; + note.layer = layer; + note.instrument = buffer.get(); + note.key = buffer.get(); + if (format >= 4) { + note.velocity = buffer.get(); + note.panning = buffer.get(); + note.pitch = buffer.getShort(); + } + nbsNotes.add(note); + } } - layer.volume = buffer.get(); - if (format >= 2) { - layer.stereo = buffer.get(); + + ArrayList nbsLayers = new ArrayList<>(); + if (buffer.hasRemaining()) { + for (int i = 0; i < layerCount; i++) { + NBSLayer layer = new NBSLayer(); + layer.name = getString(buffer, bytes.length); + if (format >= 4) { + layer.lock = buffer.get(); + } + layer.volume = buffer.get(); + if (format >= 2) { + layer.stereo = buffer.get(); + } + nbsLayers.add(layer); + } } - nbsLayers.add(layer); - } + + ArrayList customInstruments = new ArrayList<>(); + if (buffer.hasRemaining()) { + byte customInstrumentCount = buffer.get(); + for (int i = 0; i < customInstrumentCount; i++) { + NBSCustomInstrument customInstrument = new NBSCustomInstrument(); + customInstrument.name = getString(buffer, bytes.length); + customInstrument.file = getString(buffer, bytes.length); + customInstrument.pitch = buffer.get(); + customInstrument.key = buffer.get() == 0 ? false : true; + customInstruments.add(customInstrument); + } + } + + Song song = new Song(songName.trim().length() > 0 ? songName : fileName); + if (loop > 0) { + song.looping = true; + song.loopPosition = getMilliTime(loopStartTick, tempo); + song.loopCount = maxLoopCount; + } + for (NBSNote note : nbsNotes) { + Instrument instrument; + int key = note.key; + if (note.instrument < instrumentIndex.length) { + instrument = instrumentIndex[note.instrument]; + } else { + int index = note.instrument - instrumentIndex.length; + if (index >= customInstruments.size()) continue; + NBSCustomInstrument customInstrument = customInstruments.get(index); + instrument = Instrument.of(customInstrument.name); + key += customInstrument.pitch; + } + + byte layerVolume = 100; + if (nbsLayers.size() > note.layer) { + layerVolume = nbsLayers.get(note.layer).volume; + } + + int pitch = key - 33; + song.add(new Note(instrument, pitch, (float) note.velocity * (float) layerVolume / 10000f, getMilliTime(note.tick, tempo))); + } + + song.length = song.get(song.size() - 1).time + 50; + + return song; } - ArrayList customInstruments = new ArrayList<>(); - if (buffer.hasRemaining()) { - byte customInstrumentCount = buffer.get(); - for (int i = 0; i < customInstrumentCount; i++) { - NBSCustomInstrument customInstrument = new NBSCustomInstrument(); - customInstrument.name = getString(buffer, bytes.length); - customInstrument.file = getString(buffer, bytes.length); - customInstrument.pitch = buffer.get(); - customInstrument.key = buffer.get() == 0 ? false : true; - customInstruments.add(customInstrument); - } + private static String getString(ByteBuffer buffer, int maxSize) throws IOException { + int length = buffer.getInt(); + if (length > maxSize) { + throw new IOException("String is too large"); + } + byte arr[] = new byte[length]; + buffer.get(arr, 0, length); + return new String(arr); } - Song song = new Song(songName.trim().length() > 0 ? songName : fileName); - if (loop > 0) { - song.looping = true; - song.loopPosition = getMilliTime(loopStartTick, tempo); - song.loopCount = maxLoopCount; + private static int getMilliTime(int tick, int tempo) { + return 1000 * tick * 100 / tempo; } - for (NBSNote note : nbsNotes) { - Instrument instrument; - int key = note.key; - if (note.instrument < instrumentIndex.length) { - instrument = instrumentIndex[note.instrument]; - } else { - int index = note.instrument - instrumentIndex.length; - if (index >= customInstruments.size()) continue; - NBSCustomInstrument customInstrument = customInstruments.get(index); - instrument = Instrument.of(customInstrument.name); - key += customInstrument.pitch; - } - - byte layerVolume = 100; - if (nbsLayers.size() > note.layer) { - layerVolume = nbsLayers.get(note.layer).volume; - } - - int pitch = key-33; - song.add(new Note(instrument, pitch, (float) note.velocity * (float) layerVolume / 10000f, getMilliTime(note.tick, tempo))); - } - - song.length = song.get(song.size()-1).time + 50; - - return song; - } - - private static String getString (ByteBuffer buffer, int maxSize) throws IOException { - int length = buffer.getInt(); - if (length > maxSize) { - throw new IOException("String is too large"); - } - byte arr[] = new byte[length]; - buffer.get(arr, 0, length); - return new String(arr); - } - - private static int getMilliTime(int tick, int tempo) { - return 1000 * tick * 100 / tempo; - } } diff --git a/src/main/java/land/chipmunk/chipmunkmod/song/Note.java b/src/main/java/land/chipmunk/chipmunkmod/song/Note.java index f50496d..337d6c8 100644 --- a/src/main/java/land/chipmunk/chipmunkmod/song/Note.java +++ b/src/main/java/land/chipmunk/chipmunkmod/song/Note.java @@ -2,32 +2,30 @@ package land.chipmunk.chipmunkmod.song; public class Note implements Comparable { - public Instrument instrument; - public int pitch; - public float volume; - public long time; + public Instrument instrument; + public int pitch; + public float volume; + public long time; - public Note (Instrument instrument, int pitch, float volume, long time) { - this.instrument = instrument; - this.pitch = pitch; - this.volume = volume; - this.time = time; - } + public Note(Instrument instrument, int pitch, float volume, long time) { + this.instrument = instrument; + this.pitch = pitch; + this.volume = volume; + this.time = time; + } - @Override - public int compareTo(Note other) { - if (time < other.time) { - return -1; + @Override + public int compareTo(Note other) { + if (time < other.time) { + return -1; + } else if (time > other.time) { + return 1; + } else { + return 0; + } } - else if (time > other.time) { - return 1; - } - else { - return 0; - } - } - public int noteId () { - return pitch + instrument.id * 25; - } + public int noteId() { + return pitch + instrument.id * 25; + } } diff --git a/src/main/java/land/chipmunk/chipmunkmod/song/Song.java b/src/main/java/land/chipmunk/chipmunkmod/song/Song.java index 6220a2a..af5e64c 100644 --- a/src/main/java/land/chipmunk/chipmunkmod/song/Song.java +++ b/src/main/java/land/chipmunk/chipmunkmod/song/Song.java @@ -1,131 +1,132 @@ package land.chipmunk.chipmunkmod.song; import net.kyori.adventure.text.Component; + import java.util.ArrayList; import java.util.Collections; public class Song { - public ArrayList notes = new ArrayList<>(); - public Component name; - public int position = 0; // Current note index - public boolean looping = false; - public boolean paused = true; - public long startTime = 0; // Start time in millis since unix epoch - public long length = 0; // Milliseconds in the song - public long time = 0; // Time since start of song - public long loopPosition = 0; // Milliseconds into the song to start looping - public int loopCount = 0; // Number of times to loop - public int currentLoop = 0; // Number of loops so far - - public Song (Component name) { - this.name = name; - } + public ArrayList notes = new ArrayList<>(); + public Component name; + public int position = 0; // Current note index + public boolean looping = false; + public boolean paused = true; + public long startTime = 0; // Start time in millis since unix epoch + public long length = 0; // Milliseconds in the song + public long time = 0; // Time since start of song + public long loopPosition = 0; // Milliseconds into the song to start looping + public int loopCount = 0; // Number of times to loop + public int currentLoop = 0; // Number of loops so far - public Song (String name) { - this(Component.text(name)); - } - - public Note get (int i) { - return notes.get(i); - } - - public void add (Note e) { - notes.add(e); - } - - public void sort () { - Collections.sort(notes); - } - - /** - * Starts playing song (does nothing if already playing) - */ - public void play () { - if (paused) { - paused = false; - startTime = System.currentTimeMillis() - time; + public Song(Component name) { + this.name = name; } - } - /** - * Pauses song (does nothing if already paused) - */ - public void pause () { - if (!paused) { - paused = true; - // Recalculates time so that the song will continue playing after the exact point it was paused - advanceTime(); + public Song(String name) { + this(Component.text(name)); } - } - public void setTime (long t) { - time = t; - startTime = System.currentTimeMillis() - time; - position = 0; - while (position < notes.size() && notes.get(position).time < t) { - position++; + public Note get(int i) { + return notes.get(i); } - } - public void advanceTime () { - time = System.currentTimeMillis() - startTime; - } + public void add(Note e) { + notes.add(e); + } - public boolean reachedNextNote () { - if (position < notes.size()) { - return notes.get(position).time <= time; - } else { - if (time > length && shouldLoop()) { - loop(); - if (position < notes.size()) { - return notes.get(position).time <= time; - } else { - return false; + public void sort() { + Collections.sort(notes); + } + + /** + * Starts playing song (does nothing if already playing) + */ + public void play() { + if (paused) { + paused = false; + startTime = System.currentTimeMillis() - time; } - } else { - return false; - } } - } - public Note getNextNote () { - if (position >= notes.size()) { - if (shouldLoop()) { - loop(); - } else { - return null; - } + /** + * Pauses song (does nothing if already paused) + */ + public void pause() { + if (!paused) { + paused = true; + // Recalculates time so that the song will continue playing after the exact point it was paused + advanceTime(); + } } - return notes.get(position++); - } - public boolean finished () { - return time > length && !shouldLoop(); - } - - private void loop () { - position = 0; - startTime += length - loopPosition; - time -= length - loopPosition; - while (position < notes.size() && notes.get(position).time < loopPosition) { - position++; + public void setTime(long t) { + time = t; + startTime = System.currentTimeMillis() - time; + position = 0; + while (position < notes.size() && notes.get(position).time < t) { + position++; + } } - currentLoop++; - } - private boolean shouldLoop () { - if (looping) { - if (loopCount == 0) { - return true; - } else { - return currentLoop < loopCount; - } - } else { - return false; + public void advanceTime() { + time = System.currentTimeMillis() - startTime; } - } - public int size () { - return notes.size(); - } + public boolean reachedNextNote() { + if (position < notes.size()) { + return notes.get(position).time <= time; + } else { + if (time > length && shouldLoop()) { + loop(); + if (position < notes.size()) { + return notes.get(position).time <= time; + } else { + return false; + } + } else { + return false; + } + } + } + + public Note getNextNote() { + if (position >= notes.size()) { + if (shouldLoop()) { + loop(); + } else { + return null; + } + } + return notes.get(position++); + } + + public boolean finished() { + return time > length && !shouldLoop(); + } + + private void loop() { + position = 0; + startTime += length - loopPosition; + time -= length - loopPosition; + while (position < notes.size() && notes.get(position).time < loopPosition) { + position++; + } + currentLoop++; + } + + private boolean shouldLoop() { + if (looping) { + if (loopCount == 0) { + return true; + } else { + return currentLoop < loopCount; + } + } else { + return false; + } + } + + public int size() { + return notes.size(); + } } diff --git a/src/main/java/land/chipmunk/chipmunkmod/song/SongLoaderException.java b/src/main/java/land/chipmunk/chipmunkmod/song/SongLoaderException.java index ea0bb7f..9bb272e 100644 --- a/src/main/java/land/chipmunk/chipmunkmod/song/SongLoaderException.java +++ b/src/main/java/land/chipmunk/chipmunkmod/song/SongLoaderException.java @@ -3,20 +3,20 @@ package land.chipmunk.chipmunkmod.song; import net.minecraft.text.Text; public class SongLoaderException extends Exception { - public final Text message; + public final Text message; - public SongLoaderException (Text message) { - super(); - this.message = message; - } + public SongLoaderException(Text message) { + super(); + this.message = message; + } - public SongLoaderException (Text message, Throwable cause) { - super(null, cause); - this.message = message; - } + public SongLoaderException(Text message, Throwable cause) { + super(null, cause); + this.message = message; + } - @Override - public String getMessage () { - return message.getString(); - } + @Override + public String getMessage() { + return message.getString(); + } } diff --git a/src/main/java/land/chipmunk/chipmunkmod/song/SongLoaderThread.java b/src/main/java/land/chipmunk/chipmunkmod/song/SongLoaderThread.java index b02323f..7790e12 100644 --- a/src/main/java/land/chipmunk/chipmunkmod/song/SongLoaderThread.java +++ b/src/main/java/land/chipmunk/chipmunkmod/song/SongLoaderThread.java @@ -11,58 +11,58 @@ import java.nio.file.Files; import java.nio.file.Paths; public class SongLoaderThread extends Thread { - private String location; - private File songPath; - private URL songUrl; - public SongLoaderException exception; - public Song song; + private String location; + private File songPath; + private URL songUrl; + public SongLoaderException exception; + public Song song; - private boolean isUrl; + private boolean isUrl; - public SongLoaderThread (URL location) throws SongLoaderException { - isUrl = true; - songUrl = location; - } - - public SongLoaderThread (Path location) throws SongLoaderException { - isUrl = false; - songPath = location.toFile(); - } - - public void run () { - byte[] bytes; - String name; - try { - if (isUrl) { - bytes = DownloadUtilities.DownloadToByteArray(songUrl); - name = Paths.get(songUrl.toURI().getPath()).getFileName().toString(); - } else { - bytes = Files.readAllBytes(songPath.toPath()); - name = songPath.getName(); - } - } catch (Exception e) { - exception = new SongLoaderException(Text.literal(e.getMessage()), e); - return; + public SongLoaderThread(URL location) throws SongLoaderException { + isUrl = true; + songUrl = location; } - try { - song = MidiConverter.getSongFromBytes(bytes, name); - } catch (Exception e) { + public SongLoaderThread(Path location) throws SongLoaderException { + isUrl = false; + songPath = location.toFile(); } - if (song == null) { - try { - song = NBSConverter.getSongFromBytes(bytes, name); - } catch (Exception e) { - } + public void run() { + byte[] bytes; + String name; + try { + if (isUrl) { + bytes = DownloadUtilities.DownloadToByteArray(songUrl); + name = Paths.get(songUrl.toURI().getPath()).getFileName().toString(); + } else { + bytes = Files.readAllBytes(songPath.toPath()); + name = songPath.getName(); + } + } catch (Exception e) { + exception = new SongLoaderException(Text.literal(e.getMessage()), e); + return; + } + + try { + song = MidiConverter.getSongFromBytes(bytes, name); + } catch (Exception e) { + } + + if (song == null) { + try { + song = NBSConverter.getSongFromBytes(bytes, name); + } catch (Exception e) { + } + } + + if (song == null) { + exception = new SongLoaderException(Text.translatable("Invalid song format")); + } } - if (song == null) { - exception = new SongLoaderException(Text.translatable("Invalid song format")); + private File getSongFile(String name) { + return new File(SongPlayer.SONG_DIR, name); } - } - - private File getSongFile (String name) { - return new File(SongPlayer.SONG_DIR, name); - } } diff --git a/src/main/java/land/chipmunk/chipmunkmod/util/DownloadUtilities.java b/src/main/java/land/chipmunk/chipmunkmod/util/DownloadUtilities.java index e1f5ffa..091cde2 100644 --- a/src/main/java/land/chipmunk/chipmunkmod/util/DownloadUtilities.java +++ b/src/main/java/land/chipmunk/chipmunkmod/util/DownloadUtilities.java @@ -14,46 +14,48 @@ import java.security.cert.X509Certificate; public class DownloadUtilities { - private static class DefaultTrustManager implements X509TrustManager { + private static class DefaultTrustManager implements X509TrustManager { - @Override - public void checkClientTrusted(X509Certificate[] arg0, String arg1) {} - - @Override - public void checkServerTrusted(X509Certificate[] arg0, String arg1) {} - - @Override - public X509Certificate[] getAcceptedIssuers() { - return null; - } - } - - public static byte[] DownloadToByteArray(URL url) throws IOException, KeyManagementException, NoSuchAlgorithmException { - SSLContext ctx = SSLContext.getInstance("TLS"); - ctx.init(new KeyManager[0], new TrustManager[] {new DefaultTrustManager()}, new SecureRandom()); - SSLContext.setDefault(ctx); - URLConnection conn = url.openConnection(); - conn.setConnectTimeout(5000); - conn.setReadTimeout(10000); - conn.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:86.0) Gecko/20100101 Firefox/86.0"); - - try (BufferedInputStream downloadStream = new BufferedInputStream(conn.getInputStream())) { - ByteArrayOutputStream byteArrayStream = new ByteArrayOutputStream(); - byte[] buf = new byte[1024]; - int n; - while ((n = downloadStream.read(buf)) > 0) { - byteArrayStream.write(buf, 0, n); - - if (Thread.interrupted()) { - return null; + @Override + public void checkClientTrusted(X509Certificate[] arg0, String arg1) { } - } - return byteArrayStream.toByteArray(); - } - // Closing a ByteArrayInputStream has no effect, so I do not close it. - } - public static InputStream DownloadToInputStream(URL url) throws KeyManagementException, NoSuchAlgorithmException, IOException { - return new ByteArrayInputStream(DownloadToByteArray(url)); - } + @Override + public void checkServerTrusted(X509Certificate[] arg0, String arg1) { + } + + @Override + public X509Certificate[] getAcceptedIssuers() { + return null; + } + } + + public static byte[] DownloadToByteArray(URL url) throws IOException, KeyManagementException, NoSuchAlgorithmException { + SSLContext ctx = SSLContext.getInstance("TLS"); + ctx.init(new KeyManager[0], new TrustManager[]{new DefaultTrustManager()}, new SecureRandom()); + SSLContext.setDefault(ctx); + URLConnection conn = url.openConnection(); + conn.setConnectTimeout(5000); + conn.setReadTimeout(10000); + conn.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:86.0) Gecko/20100101 Firefox/86.0"); + + try (BufferedInputStream downloadStream = new BufferedInputStream(conn.getInputStream())) { + ByteArrayOutputStream byteArrayStream = new ByteArrayOutputStream(); + byte[] buf = new byte[1024]; + int n; + while ((n = downloadStream.read(buf)) > 0) { + byteArrayStream.write(buf, 0, n); + + if (Thread.interrupted()) { + return null; + } + } + return byteArrayStream.toByteArray(); + } + // Closing a ByteArrayInputStream has no effect, so I do not close it. + } + + public static InputStream DownloadToInputStream(URL url) throws KeyManagementException, NoSuchAlgorithmException, IOException { + return new ByteArrayInputStream(DownloadToByteArray(url)); + } }