refactor: use LF line endings and use 4 spaces on all classes

This commit is contained in:
Chayapak Supasakul 2025-02-09 08:00:47 +07:00
parent 43527d9e6e
commit 50db974497
Signed by: ChomeNS
SSH key fingerprint: SHA256:0YoxhdyXsgbc0nfeB2N6FYE60mxMU7DS4uCUMaw2mvA
25 changed files with 2298 additions and 2255 deletions

View file

@ -16,71 +16,76 @@ import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource;
import land.chipmunk.chipmunkmod.commands.*; import land.chipmunk.chipmunkmod.commands.*;
public class CommandManager { public class CommandManager {
public CommandDispatcher<FabricClientCommandSource> dispatcher = new CommandDispatcher<>(); public CommandDispatcher<FabricClientCommandSource> dispatcher = new CommandDispatcher<>();
public String prefix; public String prefix;
public static CommandManager INSTANCE; public static CommandManager INSTANCE;
public CommandManager (String prefix, CommandRegistryAccess commandRegistryAccess) { public CommandManager(String prefix, CommandRegistryAccess commandRegistryAccess) {
this.prefix = prefix; this.prefix = prefix;
TestCommand.register(this.dispatcher); TestCommand.register(this.dispatcher);
CoreCommand.register(this.dispatcher); CoreCommand.register(this.dispatcher);
UsernameCommand.register(this.dispatcher); UsernameCommand.register(this.dispatcher);
CloopCommand.register(this.dispatcher); CloopCommand.register(this.dispatcher);
ValidateCommand.register(this.dispatcher); ValidateCommand.register(this.dispatcher);
ItemCommand.register(this.dispatcher, commandRegistryAccess); ItemCommand.register(this.dispatcher, commandRegistryAccess);
CustomChatCommand.register(this.dispatcher); CustomChatCommand.register(this.dispatcher);
EvalCommand.register(this.dispatcher); EvalCommand.register(this.dispatcher);
MusicCommand.register(this.dispatcher); MusicCommand.register(this.dispatcher);
RainbowNameCommand.register(this.dispatcher); RainbowNameCommand.register(this.dispatcher);
SayCommand.register(this.dispatcher); SayCommand.register(this.dispatcher);
AutoSkinCommand.register(this.dispatcher); AutoSkinCommand.register(this.dispatcher);
ReloadConfigCommand.register(this.dispatcher); ReloadConfigCommand.register(this.dispatcher);
SelfCareCommand.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 public void executeCommand(String command) {
.append(Text.literal(input.substring(Math.max(0, cursor - CommandSyntaxException.CONTEXT_AMOUNT), cursor))) final MinecraftClient client = MinecraftClient.getInstance();
.append(Text.literal(input.substring(cursor)).formatted(Formatting.RED, Formatting.UNDERLINE))
.append(Text.translatable("command.context.here").formatted(Formatting.RED, Formatting.ITALIC));
return text; final FabricClientCommandSource commandSource = (FabricClientCommandSource) client.getNetworkHandler().getCommandSource();
}
public static LiteralArgumentBuilder<FabricClientCommandSource> literal (String name) { return LiteralArgumentBuilder.literal(name); } try {
public static <T> RequiredArgumentBuilder<FabricClientCommandSource, T> argument (String name, ArgumentType<T> type) { return RequiredArgumentBuilder.argument(name, type); } 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<FabricClientCommandSource> literal(String name) {
return LiteralArgumentBuilder.literal(name);
}
public static <T> RequiredArgumentBuilder<FabricClientCommandSource, T> argument(String name, ArgumentType<T> type) {
return RequiredArgumentBuilder.argument(name, type);
}
} }

View file

@ -16,91 +16,93 @@ import land.chipmunk.chipmunkmod.util.TextUtilities;
import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource; import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource;
import net.minecraft.text.Text; import net.minecraft.text.Text;
import net.minecraft.nbt.NbtCompound; import net.minecraft.nbt.NbtCompound;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
import land.chipmunk.chipmunkmod.modules.CommandCore; import land.chipmunk.chipmunkmod.modules.CommandCore;
public class CoreCommand { public class CoreCommand {
public static void register (CommandDispatcher<FabricClientCommandSource> dispatcher) { public static void register(CommandDispatcher<FabricClientCommandSource> dispatcher) {
dispatcher.register( dispatcher.register(
literal("core") 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( .then(
argument("enabled", bool()) literal("run")
.executes(c -> runFillCommand(c)) .then(
argument("command", greedyString())
.executes(c -> run(c))
)
) )
)
);
}
public static int run (CommandContext<FabricClientCommandSource> context) { .then(
CommandCore.INSTANCE.run(getString(context, "command")); literal("runTracked")
.then(
argument("command", greedyString())
.executes(c -> runTracked(c))
)
)
return Command.SINGLE_SUCCESS; .then(literal("refill").executes(c -> refill(c)))
} .then(literal("move").executes(c -> move(c)))
public static int runTracked (CommandContext<FabricClientCommandSource> context) { .then(
final FabricClientCommandSource source = context.getSource(); literal("runFillCommand")
.then(
argument("enabled", bool())
.executes(c -> runFillCommand(c))
)
)
);
}
final String command = getString(context, "command"); public static int run(CommandContext<FabricClientCommandSource> context) {
CommandCore.INSTANCE.run(getString(context, "command"));
final CompletableFuture<NbtCompound> future = CommandCore.INSTANCE.runTracked(command); return Command.SINGLE_SUCCESS;
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; public static int runTracked(CommandContext<FabricClientCommandSource> context) {
}); final FabricClientCommandSource source = context.getSource();
return Command.SINGLE_SUCCESS; final String command = getString(context, "command");
}
public static int refill (CommandContext<FabricClientCommandSource> context) { final CompletableFuture<NbtCompound> future = CommandCore.INSTANCE.runTracked(command);
CommandCore.INSTANCE.refill(); future.thenApply(tag -> {
try {
final String output = tag.getString("LastOutput");
if (output != null) source.sendFeedback(TextUtilities.fromJson(output));
} catch (Exception e) {
e.printStackTrace();
}
return Command.SINGLE_SUCCESS; return tag;
} });
public static int move (CommandContext<FabricClientCommandSource> context) { return Command.SINGLE_SUCCESS;
final FabricClientCommandSource source = context.getSource(); }
CommandCore.INSTANCE.move(source.getClient().player.getPos()); public static int refill(CommandContext<FabricClientCommandSource> context) {
CommandCore.INSTANCE.refill();
return Command.SINGLE_SUCCESS; return Command.SINGLE_SUCCESS;
} }
public static int runFillCommand(CommandContext<FabricClientCommandSource> context) { public static int move(CommandContext<FabricClientCommandSource> context) {
final FabricClientCommandSource source = context.getSource(); final FabricClientCommandSource source = context.getSource();
final boolean bool = getBool(context, "enabled"); CommandCore.INSTANCE.move(source.getClient().player.getPos());
CommandCore.INSTANCE.runFillCommand = bool; return Command.SINGLE_SUCCESS;
}
source.sendFeedback(Text.literal("Running fill commands are now " + (bool ? "enabled" : "disabled"))); public static int runFillCommand(CommandContext<FabricClientCommandSource> context) {
final FabricClientCommandSource source = context.getSource();
return Command.SINGLE_SUCCESS; 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;
}
} }

View file

@ -4,12 +4,14 @@ import com.mojang.brigadier.Command;
import com.mojang.brigadier.CommandDispatcher; import com.mojang.brigadier.CommandDispatcher;
import com.mojang.brigadier.context.CommandContext; import com.mojang.brigadier.context.CommandContext;
import com.mojang.brigadier.exceptions.CommandSyntaxException; import com.mojang.brigadier.exceptions.CommandSyntaxException;
import static land.chipmunk.chipmunkmod.command.CommandManager.literal; import static land.chipmunk.chipmunkmod.command.CommandManager.literal;
import static land.chipmunk.chipmunkmod.command.CommandManager.argument; import static land.chipmunk.chipmunkmod.command.CommandManager.argument;
import static com.mojang.brigadier.arguments.IntegerArgumentType.integer; import static com.mojang.brigadier.arguments.IntegerArgumentType.integer;
import static com.mojang.brigadier.arguments.IntegerArgumentType.getInteger; import static com.mojang.brigadier.arguments.IntegerArgumentType.getInteger;
import static net.minecraft.command.argument.ItemStackArgumentType.itemStack; import static net.minecraft.command.argument.ItemStackArgumentType.itemStack;
import static net.minecraft.command.argument.ItemStackArgumentType.getItemStackArgument; import static net.minecraft.command.argument.ItemStackArgumentType.getItemStackArgument;
import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource; import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource;
import net.minecraft.command.CommandRegistryAccess; import net.minecraft.command.CommandRegistryAccess;
import net.minecraft.client.MinecraftClient; import net.minecraft.client.MinecraftClient;
@ -18,7 +20,7 @@ import net.minecraft.item.ItemStack;
import net.minecraft.text.Text; import net.minecraft.text.Text;
public class ItemCommand { public class ItemCommand {
public static void register (CommandDispatcher<FabricClientCommandSource> dispatcher, CommandRegistryAccess commandRegistryAccess) { public static void register(CommandDispatcher<FabricClientCommandSource> dispatcher, CommandRegistryAccess commandRegistryAccess) {
dispatcher.register( dispatcher.register(
literal("item") literal("item")
.then( .then(
@ -32,11 +34,11 @@ public class ItemCommand {
); );
} }
public static int setItem (CommandContext<FabricClientCommandSource> context) throws CommandSyntaxException { public static int setItem(CommandContext<FabricClientCommandSource> context) throws CommandSyntaxException {
return setItem(context, getInteger(context, "count")); return setItem(context, getInteger(context, "count"));
} }
public static int setItem (CommandContext<FabricClientCommandSource> context, int count) throws CommandSyntaxException { public static int setItem(CommandContext<FabricClientCommandSource> context, int count) throws CommandSyntaxException {
final FabricClientCommandSource source = context.getSource(); final FabricClientCommandSource source = context.getSource();
final MinecraftClient client = source.getClient(); final MinecraftClient client = source.getClient();

View file

@ -3,22 +3,24 @@ package land.chipmunk.chipmunkmod.commands;
import com.mojang.brigadier.Command; import com.mojang.brigadier.Command;
import com.mojang.brigadier.CommandDispatcher; import com.mojang.brigadier.CommandDispatcher;
import com.mojang.brigadier.context.CommandContext; import com.mojang.brigadier.context.CommandContext;
import static land.chipmunk.chipmunkmod.command.CommandManager.literal; import static land.chipmunk.chipmunkmod.command.CommandManager.literal;
import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource; import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource;
import net.minecraft.text.Text; import net.minecraft.text.Text;
public class TestCommand { public class TestCommand {
public static void register (CommandDispatcher<FabricClientCommandSource> dispatcher) { public static void register(CommandDispatcher<FabricClientCommandSource> dispatcher) {
dispatcher.register( dispatcher.register(
literal("test") literal("test")
.executes(c -> helloWorld(c)) .executes(c -> helloWorld(c))
); );
} }
public static int helloWorld (CommandContext<FabricClientCommandSource> context) { public static int helloWorld(CommandContext<FabricClientCommandSource> context) {
final FabricClientCommandSource source = context.getSource(); final FabricClientCommandSource source = context.getSource();
source.sendFeedback(Text.literal("Hello, world!")); source.sendFeedback(Text.literal("Hello, world!"));
return Command.SINGLE_SUCCESS; return Command.SINGLE_SUCCESS;
} }
} }

View file

@ -3,10 +3,12 @@ package land.chipmunk.chipmunkmod.commands;
import com.mojang.brigadier.Command; import com.mojang.brigadier.Command;
import com.mojang.brigadier.CommandDispatcher; import com.mojang.brigadier.CommandDispatcher;
import com.mojang.brigadier.context.CommandContext; import com.mojang.brigadier.context.CommandContext;
import static com.mojang.brigadier.arguments.StringArgumentType.greedyString; import static com.mojang.brigadier.arguments.StringArgumentType.greedyString;
import static com.mojang.brigadier.arguments.StringArgumentType.getString; import static com.mojang.brigadier.arguments.StringArgumentType.getString;
import static land.chipmunk.chipmunkmod.command.CommandManager.literal; import static land.chipmunk.chipmunkmod.command.CommandManager.literal;
import static land.chipmunk.chipmunkmod.command.CommandManager.argument; import static land.chipmunk.chipmunkmod.command.CommandManager.argument;
import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource; import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource;
import net.minecraft.client.MinecraftClient; import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.screen.TitleScreen; import net.minecraft.client.gui.screen.TitleScreen;
@ -17,52 +19,53 @@ import net.minecraft.client.session.Session;
import net.minecraft.text.Text; import net.minecraft.text.Text;
import com.mojang.brigadier.exceptions.CommandSyntaxException; import com.mojang.brigadier.exceptions.CommandSyntaxException;
import com.mojang.brigadier.exceptions.SimpleCommandExceptionType; import com.mojang.brigadier.exceptions.SimpleCommandExceptionType;
import java.util.Optional; import java.util.Optional;
import java.util.UUID; import java.util.UUID;
import land.chipmunk.chipmunkmod.mixin.MinecraftClientAccessor; import land.chipmunk.chipmunkmod.mixin.MinecraftClientAccessor;
public class UsernameCommand { public class UsernameCommand {
private static final Session ORIGINAL_SESSION = MinecraftClient.getInstance().getSession(); 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")); private static final SimpleCommandExceptionType USERNAME_TOO_LONG = new SimpleCommandExceptionType(Text.translatable("The specified username is longer than 16 characters"));
public static void register (CommandDispatcher<FabricClientCommandSource> dispatcher) { public static void register(CommandDispatcher<FabricClientCommandSource> dispatcher) {
dispatcher.register( dispatcher.register(
literal("username") literal("username")
.then( .then(
literal("set") literal("set")
.then( .then(
argument("username", greedyString()) argument("username", greedyString())
.executes(c -> updateUsername(c)) .executes(c -> updateUsername(c))
) )
) )
.then( .then(
literal("revert") literal("revert")
.executes(c -> updateSession(c, ORIGINAL_SESSION)) .executes(c -> updateSession(c, ORIGINAL_SESSION))
) )
); );
} }
public static int updateUsername (CommandContext<FabricClientCommandSource> context) throws CommandSyntaxException { public static int updateUsername(CommandContext<FabricClientCommandSource> context) throws CommandSyntaxException {
final String username = getString(context, "username"); final String username = getString(context, "username");
if (username.length() > 16) throw USERNAME_TOO_LONG.create(); 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); final Session session = new Session(username, new UUID(0L, 0L), "", Optional.empty(), Optional.empty(), Session.AccountType.MOJANG);
return updateSession(context, session); return updateSession(context, session);
} }
public static int updateSession (CommandContext<FabricClientCommandSource> context, Session session) throws CommandSyntaxException { public static int updateSession(CommandContext<FabricClientCommandSource> context, Session session) throws CommandSyntaxException {
final FabricClientCommandSource source = context.getSource(); final FabricClientCommandSource source = context.getSource();
final MinecraftClient client = source.getClient(); final MinecraftClient client = source.getClient();
((MinecraftClientAccessor) client).session(session); ((MinecraftClientAccessor) client).session(session);
// TODO: Put this in a separate class // TODO: Put this in a separate class
final ServerInfo info = client.getCurrentServerEntry(); final ServerInfo info = client.getCurrentServerEntry();
client.world.disconnect(); client.world.disconnect();
client.disconnect(); client.disconnect();
ConnectScreen.connect(new TitleScreen(), client, ServerAddress.parse(info.address), info, false, null); ConnectScreen.connect(new TitleScreen(), client, ServerAddress.parse(info.address), info, false, null);
return Command.SINGLE_SUCCESS; return Command.SINGLE_SUCCESS;
} }
} }

View file

@ -11,20 +11,20 @@ import static land.chipmunk.chipmunkmod.command.CommandManager.literal;
import static land.chipmunk.chipmunkmod.util.BotValidationUtilities.*; import static land.chipmunk.chipmunkmod.util.BotValidationUtilities.*;
public class ValidateCommand { public class ValidateCommand {
public static void register (CommandDispatcher<FabricClientCommandSource> dispatcher) { public static void register(CommandDispatcher<FabricClientCommandSource> dispatcher) {
dispatcher.register( dispatcher.register(
literal("validate") literal("validate")
.then(literal("hbot").then(argument("command", greedyString()).executes(c -> hbot(getString(c, "command"))))) .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("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("chipmunk").then(argument("command", greedyString()).executes(c -> chipmunk(getString(c, "command")))))
.then(literal("chomens").then(argument("command", greedyString()).executes(c -> { .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.")); 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")); return chomens(getString(c, "command"));
}))) })))
.then(literal("fnfboyfriend").then(argument("command", greedyString()).executes(c -> fnfboyfriend(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("nbot").then(argument("command", greedyString()).executes(c -> nbot(getString(c, "command")))))
.then(literal("kittycorp").then(argument("command", greedyString()).executes(c -> kittycorp(getString(c, "command"))))) .then(literal("kittycorp").then(argument("command", greedyString()).executes(c -> kittycorp(getString(c, "command")))))
); );
} }
} }

View file

@ -9,80 +9,86 @@ import org.spongepowered.configurate.objectmapping.ConfigSerializable;
@ConfigSerializable @ConfigSerializable
public class Configuration { public class Configuration {
public CommandManager commands = new CommandManager(); public CommandManager commands = new CommandManager();
public CommandCore core = new CommandCore(); public CommandCore core = new CommandCore();
public Bots bots = new Bots(); public Bots bots = new Bots();
public CustomChat customChat = new CustomChat(); public CustomChat customChat = new CustomChat();
public String autoSkinUsername = "off"; public String autoSkinUsername = "off";
@ConfigSerializable @ConfigSerializable
public static class CommandManager { public static class CommandManager {
public String prefix = "."; 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 @ConfigSerializable
public static class TestBotInfo { public static class CommandCore {
public String prefix; public BlockBox relativeArea = BlockBox.create(new BlockPos(0, 0, 0), new BlockPos(15, 0, 15));
public @Nullable String webhookUrl;
public TestBotInfo() {}
public TestBotInfo (String prefix, @Nullable String webhookUrl) {
this.prefix = prefix;
this.webhookUrl = webhookUrl;
} }
}
@ConfigSerializable @ConfigSerializable
public static class BotInfo { public static class Bots {
public String prefix; public BotInfo hbot = new BotInfo("#", null);
public @Nullable String key; public BotInfo sbot = new BotInfo(":", null);
public BotInfo chipmunk = new BotInfo("'", null);
public BotInfo() {} public ChomeNSBotInfo chomens = new ChomeNSBotInfo("*", null, null, null);
public BotInfo (String prefix, @Nullable String key) { public BotInfo fnfboyfriend = new BotInfo("~", null);
this.prefix = prefix; public BotInfo nbot = new BotInfo("?", null);
this.key = key; public BotInfo kittycorp = new BotInfo("^", null);
public TestBotInfo testbot = new TestBotInfo("-", null);
} }
}
@ConfigSerializable @ConfigSerializable
public static class CustomChat { public static class ChomeNSBotInfo {
public @NotNull Component format = public String prefix;
Component.translatable("chat.type.text", public @Nullable String key;
Component.selector("@s"), public @Nullable String authKey;
Component.text("MESSAGE") 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")
);
}
} }

View file

@ -27,10 +27,10 @@ public record ChomeNSBotCommand(String name, TrustLevel trustLevel, List<String>
ChipmunkMod.CONFIG.bots.chomens.prefix + name, trustLevel, List.of()); ChipmunkMod.CONFIG.bots.chomens.prefix + name, trustLevel, List.of());
final List<String> aliases = children.stream() final List<String> aliases = children.stream()
.skip(2) .skip(2)
.map(TextUtilities::plainOrNull) .map(TextUtilities::plainOrNull)
.filter(Objects::nonNull) .filter(Objects::nonNull)
.toList(); .toList();
return new ChomeNSBotCommand( return new ChomeNSBotCommand(
ChipmunkMod.CONFIG.bots.chomens.prefix + name, trustLevel, aliases); ChipmunkMod.CONFIG.bots.chomens.prefix + name, trustLevel, aliases);
} }
@ -47,7 +47,8 @@ public record ChomeNSBotCommand(String name, TrustLevel trustLevel, List<String>
try { try {
return TrustLevel.valueOf(trustLevelString); return TrustLevel.valueOf(trustLevelString);
} catch (final IllegalArgumentException ignored) {} } catch (final IllegalArgumentException ignored) {
}
return null; return null;
} }

View file

@ -27,73 +27,74 @@ import java.util.concurrent.CompletableFuture;
@Mixin(net.minecraft.client.gui.screen.ChatInputSuggestor.class) @Mixin(net.minecraft.client.gui.screen.ChatInputSuggestor.class)
public class ChatInputSuggestorMixin { public class ChatInputSuggestorMixin {
@Shadow @Shadow
private CompletableFuture<Suggestions> pendingSuggestions; private CompletableFuture<Suggestions> pendingSuggestions;
@Shadow @Shadow
public void show (boolean narrateFirstSuggestion) {} public void show(boolean narrateFirstSuggestion) {
}
@Shadow
private static int getStartOfCurrentWord (String input) { @Shadow
return 0; private static int getStartOfCurrentWord(String input) {
} return 0;
}
@Mutable
@Final @Mutable
@Shadow @Final
final TextFieldWidget textField; @Shadow
final TextFieldWidget textField;
public ChatInputSuggestorMixin () {
textField = null; public ChatInputSuggestorMixin() {
} textField = null;
}
@Inject(at = @At("TAIL"), method = "refresh()V")
public void refresh (CallbackInfo ci) { @Inject(at = @At("TAIL"), method = "refresh()V")
final CommandManager commandManager = CommandManager.INSTANCE; public void refresh(CallbackInfo ci) {
final CommandManager commandManager = CommandManager.INSTANCE;
final String text = this.textField.getText();
final int cursor = this.textField.getCursor(); final String text = this.textField.getText();
final int cursor = this.textField.getCursor();
final ClientPlayerEntity player = MinecraftClient.getInstance().player;
final ClientPlayerEntity player = MinecraftClient.getInstance().player;
final String chomeNSPrefix = ChipmunkMod.CONFIG.bots.chomens.prefix;
final String chomeNSPrefix = ChipmunkMod.CONFIG.bots.chomens.prefix;
if (!text.contains(" ") && text.startsWith(chomeNSPrefix) && player != null) {
final String textUpToCursor = text.substring(0, cursor); if (!text.contains(" ") && text.startsWith(chomeNSPrefix) && player != null) {
final String textUpToCursor = text.substring(0, cursor);
final List<String> commands = ChomeNSBotCommandSuggestions.INSTANCE.commands
.stream() final List<String> commands = ChomeNSBotCommandSuggestions.INSTANCE.commands
.map(ChomeNSBotCommand::name) .stream()
.toList(); .map(ChomeNSBotCommand::name)
.toList();
pendingSuggestions = CommandSource.suggestMatching(
commands, pendingSuggestions = CommandSource.suggestMatching(
new SuggestionsBuilder( commands,
textUpToCursor, new SuggestionsBuilder(
getStartOfCurrentWord(textUpToCursor) textUpToCursor,
) getStartOfCurrentWord(textUpToCursor)
); )
);
pendingSuggestions.thenRun(() -> {
if (!pendingSuggestions.isDone()) return; pendingSuggestions.thenRun(() -> {
if (!pendingSuggestions.isDone()) return;
show(true);
}); show(true);
} else if (cursor >= commandManager.prefix.length() && text.startsWith(commandManager.prefix)) { });
final StringReader reader = new StringReader(text); } else if (cursor >= commandManager.prefix.length() && text.startsWith(commandManager.prefix)) {
reader.setCursor(commandManager.prefix.length()); // Skip the prefix final StringReader reader = new StringReader(text);
reader.setCursor(commandManager.prefix.length()); // Skip the prefix
final MinecraftClient client = MinecraftClient.getInstance();
final MinecraftClient client = MinecraftClient.getInstance();
final ClientPlayNetworkHandler networkHandler = client.getNetworkHandler();
final ClientPlayNetworkHandler networkHandler = client.getNetworkHandler();
if (networkHandler == null) return;
if (networkHandler == null) return;
final CommandDispatcher<FabricClientCommandSource> dispatcher = commandManager.dispatcher;
final FabricClientCommandSource commandSource = (FabricClientCommandSource) networkHandler.getCommandSource(); final CommandDispatcher<FabricClientCommandSource> dispatcher = commandManager.dispatcher;
final FabricClientCommandSource commandSource = (FabricClientCommandSource) networkHandler.getCommandSource();
pendingSuggestions = dispatcher.getCompletionSuggestions(dispatcher.parse(reader, commandSource), cursor);
show(true); pendingSuggestions = dispatcher.getCompletionSuggestions(dispatcher.parse(reader, commandSource), cursor);
show(true);
}
} }
}
} }

View file

@ -28,120 +28,126 @@ import java.util.List;
@Mixin(value = net.minecraft.client.gui.screen.ChatScreen.class) @Mixin(value = net.minecraft.client.gui.screen.ChatScreen.class)
public abstract class ChatScreenMixin extends Screen { public abstract class ChatScreenMixin extends Screen {
@Shadow private String originalChatText; @Shadow
private String originalChatText;
@Shadow private int messageHistoryIndex; @Shadow
private int messageHistoryIndex;
@Shadow protected TextFieldWidget chatField; @Shadow
protected TextFieldWidget chatField;
@Shadow ChatInputSuggestor chatInputSuggestor; @Shadow
ChatInputSuggestor chatInputSuggestor;
@Shadow protected abstract void onChatFieldUpdate(String chatText); @Shadow
protected abstract void onChatFieldUpdate(String chatText);
protected ChatScreenMixin(Text title) { protected ChatScreenMixin(Text title) {
super(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)) { // infinite chat
ChipmunkMod.executorService.submit(() -> { @Inject(method = "init", at = @At("HEAD"), cancellable = true)
try { protected void init(CallbackInfo ci) {
final URL url = new URI(ChipmunkMod.CONFIG.bots.testbot.webhookUrl).toURL(); final MinecraftClient client = MinecraftClient.getInstance();
final HttpsURLConnection connection = (HttpsURLConnection) url.openConnection(); this.messageHistoryIndex = client.inGameHud.getChatHud().getMessageHistory().size();
connection.addRequestProperty("Content-Type", "application/json"); this.chatField = new TextFieldWidget(client.advanceValidatingTextRenderer, 4, this.height - 12, this.width - 4, 12, Text.translatable("chat.editBox")) {
connection.addRequestProperty("User-Agent", "ChipmunkMod"); protected MutableText getNarrationMessage() {
connection.setDoOutput(true); return super.getNarrationMessage().append(ChatScreenMixin.this.chatInputSuggestor.getNarration());
connection.setRequestMethod("POST"); }
};
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();
final JsonObject jsonObject = new JsonObject(); ci.cancel();
}
jsonObject.addProperty("username", "ChipmunkMod UwU"); @Inject(method = "sendMessage", at = @At("HEAD"), cancellable = true)
jsonObject.addProperty("content", MinecraftClient.getInstance().getSession().getUsername()); private void sendMessage(String chatText, boolean addToHistory, CallbackInfo cir) {
final MinecraftClient client = MinecraftClient.getInstance();
final OutputStream stream = connection.getOutputStream(); if (addToHistory) {
stream.write(jsonObject.toString().getBytes()); client.inGameHud.getChatHud().addToMessageHistory(chatText);
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<ChomeNSBotCommand> commands = ChomeNSBotCommandSuggestions.INSTANCE.commands;
final List<String> moreOrTrustedCommands = commands.stream() if (ChipmunkMod.CONFIG.bots.testbot.webhookUrl != null && chatText.startsWith(ChipmunkMod.CONFIG.bots.testbot.prefix)) {
.filter(command -> command.trustLevel() != ChomeNSBotCommand.TrustLevel.PUBLIC) ChipmunkMod.executorService.submit(() -> {
.map(command -> command.name().toLowerCase()) try {
.toList(); final URL url = new URI(ChipmunkMod.CONFIG.bots.testbot.webhookUrl).toURL();
final List<String> aliases = new ArrayList<>(); final HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
for (ChomeNSBotCommand command : commands) { connection.addRequestProperty("Content-Type", "application/json");
if (command.trustLevel() == ChomeNSBotCommand.TrustLevel.PUBLIC) continue; connection.addRequestProperty("User-Agent", "ChipmunkMod");
connection.setDoOutput(true);
connection.setRequestMethod("POST");
aliases.addAll(command.aliases()); final JsonObject jsonObject = new JsonObject();
}
final String chatCommand = chatText.toLowerCase().split("\\s")[0]; jsonObject.addProperty("username", "ChipmunkMod UwU");
jsonObject.addProperty("content", MinecraftClient.getInstance().getSession().getUsername());
final int prefixLength = ChipmunkMod.CONFIG.bots.chomens.prefix.length(); final OutputStream stream = connection.getOutputStream();
stream.write(jsonObject.toString().getBytes());
stream.flush();
stream.close();
if ( connection.getInputStream().close();
moreOrTrustedCommands.contains(chatCommand) || connection.disconnect();
aliases.contains(chatCommand.substring(prefixLength)) } catch (IOException | URISyntaxException e) {
) { e.printStackTrace();
try { }
BotValidationUtilities.chomens(chatText.substring(prefixLength)); });
} else if (chatText.startsWith(ChipmunkMod.CONFIG.bots.chomens.prefix)) {
final List<ChomeNSBotCommand> commands = ChomeNSBotCommandSuggestions.INSTANCE.commands;
cir.cancel(); final List<String> moreOrTrustedCommands = commands.stream()
.filter(command -> command.trustLevel() != ChomeNSBotCommand.TrustLevel.PUBLIC)
.map(command -> command.name().toLowerCase())
.toList();
return; final List<String> aliases = new ArrayList<>();
} catch (Exception ignored) {} 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();
} }
if (client.player == null) return;
if (chatText.startsWith("/")) {
client.player.networkHandler.sendChatCommand(chatText.substring(1));
} else {
client.player.networkHandler.sendChatMessage(chatText);
}
cir.cancel();
}
} }

View file

@ -23,74 +23,74 @@ import java.util.regex.Pattern;
@Mixin(net.minecraft.network.ClientConnection.class) @Mixin(net.minecraft.network.ClientConnection.class)
public class ClientConnectionMixin { public class ClientConnectionMixin {
@Unique @Unique
private static final double MAX_PARTICLES_PER_PACKET = 1000; private static final double MAX_PARTICLES_PER_PACKET = 1000;
@Unique @Unique
private static final Pattern CUSTOM_PITCH_PATTERN = Pattern.compile(".*\\.pitch\\.(.*)"); private static final Pattern CUSTOM_PITCH_PATTERN = Pattern.compile(".*\\.pitch\\.(.*)");
@Inject(method = "exceptionCaught", at = @At("HEAD"), cancellable = true) @Inject(method = "exceptionCaught", at = @At("HEAD"), cancellable = true)
private void exceptionCaught (ChannelHandlerContext context, Throwable ex, CallbackInfo ci) { 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(); ci.cancel();
} ex.printStackTrace();
} 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) { @Inject(method = "handlePacket", at = @At("HEAD"), cancellable = true)
listener.packetSent(packet); 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);
}
} }
}
} }

View file

@ -35,94 +35,102 @@ import java.time.Instant;
@Mixin(value = net.minecraft.client.network.ClientPlayNetworkHandler.class, priority = 1001) @Mixin(value = net.minecraft.client.network.ClientPlayNetworkHandler.class, priority = 1001)
public class ClientPlayNetworkHandlerMixin { public class ClientPlayNetworkHandlerMixin {
@Final @Final
@Shadow private FeatureSet enabledFeatures; @Shadow
@Final private FeatureSet enabledFeatures;
@Shadow private DynamicRegistryManager.Immutable combinedDynamicRegistries; @Final
@Shadow private LastSeenMessagesCollector lastSeenMessagesCollector; @Shadow
@Shadow private MessageChain.Packer messagePacker; private DynamicRegistryManager.Immutable combinedDynamicRegistries;
@Shadow private CommandDispatcher<CommandSource> commandDispatcher; @Shadow
private LastSeenMessagesCollector lastSeenMessagesCollector;
@Shadow
private MessageChain.Packer messagePacker;
@Shadow
private CommandDispatcher<CommandSource> commandDispatcher;
@Inject(method = "onGameJoin", at = @At("TAIL")) @Inject(method = "onGameJoin", at = @At("TAIL"))
private void onGameJoin (GameJoinS2CPacket packet, CallbackInfo ci) { private void onGameJoin(GameJoinS2CPacket packet, CallbackInfo ci) {
final CommandRegistryAccess commandRegistryAccess = CommandRegistryAccess.of(this.combinedDynamicRegistries, this.enabledFeatures); final CommandRegistryAccess commandRegistryAccess = CommandRegistryAccess.of(this.combinedDynamicRegistries, this.enabledFeatures);
KaboomCheck.INSTANCE.onJoin(); KaboomCheck.INSTANCE.onJoin();
CommandManager.INSTANCE = new CommandManager(ChipmunkMod.CONFIG.commands.prefix, commandRegistryAccess); CommandManager.INSTANCE = new CommandManager(ChipmunkMod.CONFIG.commands.prefix, commandRegistryAccess);
SelfCare.INSTANCE.onJoin(); SelfCare.INSTANCE.onJoin();
CommandCore.INSTANCE.init(); CommandCore.INSTANCE.init();
SongPlayer.INSTANCE.coreReady(); SongPlayer.INSTANCE.coreReady();
RainbowName.INSTANCE.init(); RainbowName.INSTANCE.init();
ChomeNSBotCommandSuggestions.INSTANCE.init(); ChomeNSBotCommandSuggestions.INSTANCE.init();
ChomeNSAuth.INSTANCE.init(); ChomeNSAuth.INSTANCE.init();
CustomChat.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)) { @Inject(method = "onCommandTree", at = @At("TAIL"))
final String content = chatText.substring(secret.length()); private void onCommandTree(final CommandTreeS2CPacket packet, final CallbackInfo ci) {
KaboomCheck.INSTANCE.onCommandTree(this.commandDispatcher);
Instant instant = Instant.now(); }
long l = NetworkEncryptionUtils.SecureRandomUtil.nextLong();
LastSeenMessagesCollector.LastSeenMessages lastSeenMessages = this.lastSeenMessagesCollector.collect(); @Inject(method = "onGameMessage", at = @At("HEAD"), cancellable = true)
MessageSignatureData messageSignatureData = this.messagePacker.pack(new MessageBody(content, instant, l, lastSeenMessages.lastSeen())); private void onGameMessage(GameMessageS2CPacket packet, CallbackInfo ci) {
MinecraftClient.getInstance().getNetworkHandler().sendPacket(new ChatMessageC2SPacket(content, instant, l, messageSignatureData, lastSeenMessages.update())); final Text message = packet.content();
ci.cancel(); 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();
}
} }
}
} }

View file

@ -8,7 +8,7 @@ import org.spongepowered.asm.mixin.gen.Accessor;
@Mixin(MinecraftClient.class) @Mixin(MinecraftClient.class)
public interface MinecraftClientAccessor { public interface MinecraftClientAccessor {
@Mutable @Mutable
@Accessor("session") @Accessor("session")
void session (Session session); void session(Session session);
} }

View file

@ -24,311 +24,311 @@ import java.util.TimerTask;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
public class CommandCore { public class CommandCore {
private final MinecraftClient client; private final MinecraftClient client;
public boolean ready = false; public boolean ready = false;
public BlockPos origin; public BlockPos origin;
public BlockBox noPos; public BlockBox noPos;
public BlockPos block; public BlockPos block;
public BlockBox withPos; public BlockBox withPos;
private Timer timer; private Timer timer;
private boolean shouldRefill = false; private boolean shouldRefill = false;
private DimensionType oldDimension; private DimensionType oldDimension;
public boolean runFillCommand = true; public boolean runFillCommand = true;
public boolean clientPlayerEntityFilled = false; public boolean clientPlayerEntityFilled = false;
public static CommandCore INSTANCE = new CommandCore(MinecraftClient.getInstance()); public static CommandCore INSTANCE = new CommandCore(MinecraftClient.getInstance());
public CommandCore (MinecraftClient client) { public CommandCore(MinecraftClient client) {
this.client = client; this.client = client;
reloadRelativeArea(); 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 init() {
} if (timer != null) cleanup();
public void reloadRelativeArea () { final TimerTask task = new TimerTask() {
noPos = ChipmunkMod.CONFIG.core.relativeArea; public void run() {
} tick();
}
};
public void check () { final TimerTask refillTask = new TimerTask() {
final ClientPlayNetworkHandler networkHandler = client.getNetworkHandler(); @Override
public void run() {
if (clientPlayerEntityFilled) {
clientPlayerEntityFilled = false;
return;
}
if (networkHandler == null || withPos == null || !ready) return; check();
final ClientPlayerEntity player = client.player; if (!shouldRefill) return;
final ClientWorld world = client.world;
if (player == null || world == null) return; refill();
if (oldDimension != null && !oldDimension.equals(world.getDimension())) move(client.player.getPos()); shouldRefill = false;
}
};
oldDimension = world.getDimension(); timer = new Timer();
try { timer.schedule(task, 50, 50);
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(); timer.schedule(refillTask, 50, 1000);
if (block instanceof CommandBlock) continue; move(client.player.getPos());
}
shouldRefill = true; private void tick() {
final ClientPlayNetworkHandler networkHandler = client.getNetworkHandler();
if (networkHandler == null) {
cleanup();
return; return;
}
} }
}
} catch (Exception e) {
e.printStackTrace();
}
}
public void move (Vec3d position) { reloadRelativeArea();
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( public void reloadRelativeArea() {
((int) position.getX() / 16) * 16, noPos = ChipmunkMod.CONFIG.core.relativeArea;
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()) { public void check() {
z = withPos.getMinZ(); final ClientPlayNetworkHandler networkHandler = client.getNetworkHandler();
y++;
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();
}
} }
if (y > withPos.getMaxY()) { public void move(Vec3d position) {
x = withPos.getMinX(); final ClientWorld world = client.world;
y = withPos.getMinY(); if (world == null || noPos == null) return;
z = withPos.getMinZ();
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();
}
} }
block = new BlockPos(x, y, z); public void refill() {
} if (!runFillCommand || withPos == null) return;
public void run (String command) { final String command = String.format(
if (command.length() > 32767) return; 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(),
final ClientConnection connection = client.getNetworkHandler().getConnection(); withPos.getMaxX(),
withPos.getMaxY(),
withPos.getMaxZ()
);
if (block == null) return; client.getNetworkHandler().sendChatCommand(command);
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 void incrementCurrentBlock() {
} if (withPos == null) return;
int x = block.getX();
int y = block.getY();
int z = block.getZ();
public CompletableFuture<NbtCompound> runTracked (String command) { x++;
final ClientConnection connection = client.getNetworkHandler().getConnection();
if (block == null) return new CompletableFuture<>(); if (x > withPos.getMaxX()) {
x = withPos.getMinX();
z++;
}
if (KaboomCheck.INSTANCE.isKaboom) { if (z > withPos.getMaxZ()) {
connection.send( z = withPos.getMinZ();
new UpdateCommandBlockC2SPacket( y++;
block, }
command,
CommandBlockBlockEntity.Type.AUTO,
true,
false,
true
)
);
} else {
connection.send(
new UpdateCommandBlockC2SPacket(
block,
"",
CommandBlockBlockEntity.Type.REDSTONE,
true,
false,
false
)
);
connection.send( if (y > withPos.getMaxY()) {
new UpdateCommandBlockC2SPacket( x = withPos.getMinX();
block, y = withPos.getMinY();
command, z = withPos.getMinZ();
CommandBlockBlockEntity.Type.REDSTONE, }
true,
false, block = new BlockPos(x, y, z);
true
)
);
} }
incrementCurrentBlock(); public void run(String command) {
if (command.length() > 32767) return;
CompletableFuture<NbtCompound> future = new CompletableFuture<>(); final ClientConnection connection = client.getNetworkHandler().getConnection();
final Timer timer = new Timer(); if (block == null) return;
final TimerTask queryTask = new TimerTask() { ChipmunkMod.LOGGER.info("Executing core command: {}", command);
public void run () {
client.getNetworkHandler().getDataQueryHandler().queryBlockNbt(block, future::complete);
timer.cancel(); // ? Is this necesary? 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<NbtCompound> 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<NbtCompound> 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(); timer.purge();
}
};
timer.schedule(queryTask, 50); withPos = null;
block = null;
return future; ready = false;
} }
public void cleanup () {
if (timer == null) return;
timer.cancel();
timer.purge();
withPos = null;
block = null;
ready = false;
}
} }

View file

@ -18,142 +18,147 @@ import java.util.TimerTask;
import static land.chipmunk.chipmunkmod.util.ServerUtilities.serverHasCommand; import static land.chipmunk.chipmunkmod.util.ServerUtilities.serverHasCommand;
public class SelfCare implements Listener { public class SelfCare implements Listener {
private final MinecraftClient client; private final MinecraftClient client;
public final long interval; public final long interval;
public final long chatInterval; public final long chatInterval;
public boolean opEnabled = true; public boolean opEnabled = true;
public boolean gamemodeEnabled = true; public boolean gamemodeEnabled = true;
public boolean cspyEnabled = true; public boolean cspyEnabled = true;
public boolean icuEnabled = true; public boolean icuEnabled = true;
private int gameMode; private int gameMode;
public String skin; public String skin;
private Timer timer; private Timer timer;
private Timer chatTimer; private Timer chatTimer;
private boolean cspy = false; private boolean cspy = false;
public boolean hasSkin = false; public boolean hasSkin = false;
private int positionPacketsPerSecond = 0; private int positionPacketsPerSecond = 0;
public static final SelfCare INSTANCE = new SelfCare(MinecraftClient.getInstance(), 70L, 500L); // make the intervals in config? public static final SelfCare INSTANCE = new SelfCare(MinecraftClient.getInstance(), 70L, 500L); // make the intervals in config?
public SelfCare (MinecraftClient client, long interval, long chatInterval) { public SelfCare(MinecraftClient client, long interval, long chatInterval) {
this.client = client; this.client = client;
this.interval = interval; this.interval = interval;
this.chatInterval = chatInterval; this.chatInterval = chatInterval;
this.skin = ChipmunkMod.CONFIG.autoSkinUsername == null ? "off" : ChipmunkMod.CONFIG.autoSkinUsername; // can this be null? this.skin = ChipmunkMod.CONFIG.autoSkinUsername == null ? "off" : ChipmunkMod.CONFIG.autoSkinUsername; // can this be null?
ListenerManager.addListener(this); 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]"); } public void init() {
else if (gameMode != 1 && gamemodeEnabled) networkHandler.sendChatCommand("gamemode creative"); }
else if (positionPacketsPerSecond >= 10 && icuEnabled) CommandCore.INSTANCE.run("sudo * icu stop");
}
public void chatTick () { public void onJoin() {
final ClientPlayNetworkHandler networkHandler = client.getNetworkHandler(); final TimerTask task = new TimerTask() {
public void run() {
tick();
}
};
if (!cspy && cspyEnabled) { if (serverHasCommand("c")) networkHandler.sendChatCommand("c on"); } final TimerTask chatTask = new TimerTask() {
else if (!hasSkin && !skin.equals("off")) { if (serverHasCommand("skin")) networkHandler.sendChatCommand("skin " + skin); } public void run() {
} chatTick();
}
};
@Override timer = new Timer();
public void packetReceived(Packet<?> packet) { chatTimer = new Timer();
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) { timer.schedule(task, interval, interval);
gameMode = packet.commonPlayerSpawnInfo().gameMode().getId(); chatTimer.schedule(chatTask, chatInterval, chatInterval);
} }
public void packetReceived(GameStateChangeS2CPacket packet) { public void cleanup() {
if (packet.getReason() != GameStateChangeS2CPacket.GAME_MODE_CHANGED) return; if (timer == null || chatTimer == null) return;
gameMode = (int) packet.getValue(); timer.cancel();
} timer.purge();
public void packetReceived(PlayerPositionLookS2CPacket packet) { chatTimer.cancel();
if (timer == null) return; chatTimer.purge();
try { gameMode = -1;
positionPacketsPerSecond++;
timer.schedule(new TimerTask() { hasSkin = false;
@Override cspy = false;
public void run() { }
positionPacketsPerSecond--;
@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();
} }
}, 1000);
} catch (Exception e) {
e.printStackTrace();
} }
}
} }

View file

@ -1,48 +1,49 @@
package land.chipmunk.chipmunkmod.song; package land.chipmunk.chipmunkmod.song;
public class Instrument { public class Instrument {
public static final Instrument HARP = new Instrument(0, "harp", 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 BASEDRUM = new Instrument(1, "basedrum", 0);
public static final Instrument SNARE = new Instrument(2, "snare", 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 HAT = new Instrument(3, "hat", 0);
public static final Instrument BASS = new Instrument(4, "bass", 30); public static final Instrument BASS = new Instrument(4, "bass", 30);
public static final Instrument FLUTE = new Instrument(5, "flute", 66); public static final Instrument FLUTE = new Instrument(5, "flute", 66);
public static final Instrument BELL = new Instrument(6, "bell", 78); public static final Instrument BELL = new Instrument(6, "bell", 78);
public static final Instrument GUITAR = new Instrument(7, "guitar", 42); public static final Instrument GUITAR = new Instrument(7, "guitar", 42);
public static final Instrument CHIME = new Instrument(8, "chime", 78); public static final Instrument CHIME = new Instrument(8, "chime", 78);
public static final Instrument XYLOPHONE = new Instrument(9, "xylophone", 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 IRON_XYLOPHONE = new Instrument(10, "iron_xylophone", 54);
public static final Instrument COW_BELL = new Instrument(11, "cow_bell", 66); 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 DIDGERIDOO = new Instrument(12, "didgeridoo", 30);
public static final Instrument BIT = new Instrument(13, "bit", 54); public static final Instrument BIT = new Instrument(13, "bit", 54);
public static final Instrument BANJO = new Instrument(14, "banjo", 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 PLING = new Instrument(15, "pling", 54);
public final int id; public final int id;
public final String name; public final String name;
public final int offset; public final int offset;
public final String sound; public final String sound;
private Instrument (int id, String name, int offset, String sound) { private Instrument(int id, String name, int offset, String sound) {
this.id = id; this.id = id;
this.name = name; this.name = name;
this.offset = offset; this.offset = offset;
this.sound = sound; this.sound = sound;
} }
private Instrument (int id, String name, int offset) { private Instrument(int id, String name, int offset) {
this.id = id; this.id = id;
this.name = name; this.name = name;
this.offset = offset; this.offset = offset;
this.sound = "minecraft:block.note_block." + name; this.sound = "minecraft:block.note_block." + name;
} }
public static Instrument of (String sound) { public static Instrument of(String sound) {
return new Instrument(-1, null, 0, 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}; 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]; public static Instrument fromId(int id) {
} return values[id];
}
} }

View file

@ -1,6 +1,7 @@
package land.chipmunk.chipmunkmod.song; package land.chipmunk.chipmunkmod.song;
import land.chipmunk.chipmunkmod.util.DownloadUtilities; import land.chipmunk.chipmunkmod.util.DownloadUtilities;
import java.io.*; import java.io.*;
import java.net.*; import java.net.*;
import java.nio.file.Paths; import java.nio.file.Paths;
@ -13,361 +14,360 @@ import java.util.HashMap;
import javax.sound.midi.*; import javax.sound.midi.*;
public class MidiConverter { public class MidiConverter {
public static final int SET_INSTRUMENT = 0xC0; public static final int SET_INSTRUMENT = 0xC0;
public static final int SET_TEMPO = 0x51; public static final int SET_TEMPO = 0x51;
public static final int NOTE_ON = 0x90; public static final int NOTE_ON = 0x90;
public static final int NOTE_OFF = 0x80; public static final int NOTE_OFF = 0x80;
public static Song getSongFromUrl(URL url) throws IOException, InvalidMidiDataException, URISyntaxException, NoSuchAlgorithmException, KeyManagementException { public static Song getSongFromUrl(URL url) throws IOException, InvalidMidiDataException, URISyntaxException, NoSuchAlgorithmException, KeyManagementException {
Sequence sequence = MidiSystem.getSequence(DownloadUtilities.DownloadToInputStream(url)); Sequence sequence = MidiSystem.getSequence(DownloadUtilities.DownloadToInputStream(url));
return getSong(sequence, Paths.get(url.toURI().getPath()).getFileName().toString()); 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<MidiEvent> 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);
}
}
}
} }
Collections.sort(tempoEvents, (a, b) -> Long.compare(a.getTick(), b.getTick())); public static Song getSongFromFile(File file) throws InvalidMidiDataException, IOException {
Sequence sequence = MidiSystem.getSequence(file);
return getSong(sequence, file.getName());
}
for (Track track : sequence.getTracks()) { public static Song getSongFromBytes(byte[] bytes, String name) throws InvalidMidiDataException, IOException {
Sequence sequence = MidiSystem.getSequence(new ByteArrayInputStream(bytes));
return getSong(sequence, name);
}
long microTime = 0; public static Song getSong(Sequence sequence, String name) {
int[] ids = new int[16]; Song song = new Song(name);
int mpq = 500000;
int tempoEventIdx = 0;
long prevTick = 0;
for (int i = 0; i < track.size(); i++) { long tpq = sequence.getResolution();
MidiEvent event = track.get(i);
MidiMessage message = event.getMessage();
while (tempoEventIdx < tempoEvents.size() && event.getTick() > tempoEvents.get(tempoEventIdx).getTick()) { ArrayList<MidiEvent> tempoEvents = new ArrayList<>();
long deltaTick = tempoEvents.get(tempoEventIdx).getTick() - prevTick; for (Track track : sequence.getTracks()) {
prevTick = tempoEvents.get(tempoEventIdx).getTick(); for (int i = 0; i < track.size(); i++) {
microTime += (mpq/tpq) * deltaTick; MidiEvent event = track.get(i);
MidiMessage message = event.getMessage();
MetaMessage mm = (MetaMessage) tempoEvents.get(tempoEventIdx).getMessage(); if (message instanceof MetaMessage) {
byte[] data = mm.getData(); MetaMessage mm = (MetaMessage) message;
int new_mpq = (data[2]&0xFF) | ((data[1]&0xFF)<<8) | ((data[0]&0xFF)<<16); if (mm.getType() == SET_TEMPO) {
if (new_mpq != 0) mpq = new_mpq; tempoEvents.add(event);
tempoEventIdx++; }
}
}
} }
if (message instanceof ShortMessage) { Collections.sort(tempoEvents, (a, b) -> Long.compare(a.getTick(), b.getTick()));
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; for (Track track : sequence.getTracks()) {
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 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; long time = microTime / 1000L;
if (time > song.length) {
song.length = time; return new Note(instrument, pitch, volume, 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 null;
} }
song.sort(); public static HashMap<Integer, Instrument[]> instrumentMap = new HashMap<>();
return song; 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
public static Note getMidiInstrumentNote(int midiInstrument, int midiPitch, int velocity, long microTime) { // Chromatic Percussion (IRON_XYLOPHONE XYLOPHONE BASS)
Instrument instrument = null; instrumentMap.put(8, new Instrument[]{Instrument.IRON_XYLOPHONE, Instrument.BASS, Instrument.XYLOPHONE}); // Celesta
Instrument[] instrumentList = instrumentMap.get(midiInstrument); instrumentMap.put(9, new Instrument[]{Instrument.IRON_XYLOPHONE, Instrument.BASS, Instrument.XYLOPHONE}); // Glockenspiel
if (instrumentList != null) { instrumentMap.put(10, new Instrument[]{Instrument.IRON_XYLOPHONE, Instrument.BASS, Instrument.XYLOPHONE}); // Music Box
for (Instrument candidateInstrument : instrumentList) { instrumentMap.put(11, new Instrument[]{Instrument.IRON_XYLOPHONE, Instrument.BASS, Instrument.XYLOPHONE}); // Vibraphone
if (midiPitch >= candidateInstrument.offset && midiPitch <= candidateInstrument.offset+24) { instrumentMap.put(12, new Instrument[]{Instrument.IRON_XYLOPHONE, Instrument.BASS, Instrument.XYLOPHONE}); // Marimba
instrument = candidateInstrument; instrumentMap.put(13, new Instrument[]{Instrument.IRON_XYLOPHONE, Instrument.BASS, Instrument.XYLOPHONE}); // Xylophone
break; 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
}
}
if (instrument == null) { // Organ (BIT DIDGERIDOO BELL)
return null; 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
int pitch = midiPitch-instrument.offset; // Guitar (BIT DIDGERIDOO BELL)
float volume = (float) velocity / 127.0f; instrumentMap.put(24, new Instrument[]{Instrument.GUITAR, Instrument.HARP, Instrument.BASS, Instrument.BELL}); // Acoustic Guitar (nylon)
long time = microTime / 1000L; 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
return new Note(instrument, pitch, volume, time); // 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
private static Note getMidiPercussionNote (int midiPitch, int velocity, long microTime) { // Strings
if (percussionMap.containsKey(midiPitch)) { instrumentMap.put(40, new Instrument[]{Instrument.FLUTE, Instrument.GUITAR, Instrument.BASS, Instrument.BELL}); // Violin
int noteId = percussionMap.get(midiPitch); instrumentMap.put(41, new Instrument[]{Instrument.FLUTE, Instrument.GUITAR, Instrument.BASS, Instrument.BELL}); // Viola
int pitch = noteId % 25; instrumentMap.put(42, new Instrument[]{Instrument.FLUTE, Instrument.GUITAR, Instrument.BASS, Instrument.BELL}); // Cello
float volume = (float) velocity / 127.0f; instrumentMap.put(43, new Instrument[]{Instrument.FLUTE, Instrument.GUITAR, Instrument.BASS, Instrument.BELL}); // Contrabass
Instrument instrument = Instrument.fromId(noteId / 25); instrumentMap.put(44, new Instrument[]{Instrument.BIT, Instrument.DIDGERIDOO, Instrument.BELL}); // Tremolo Strings
long time = microTime / 1000L; 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
return new Note(instrument, pitch, volume, time); // Ensenble
} instrumentMap.put(48, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); // String Ensemble 1
return null; 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
public static HashMap<Integer, Instrument[]> instrumentMap = new HashMap<>(); // Brass
static { instrumentMap.put(56, new Instrument[]{Instrument.BIT, Instrument.DIDGERIDOO, Instrument.BELL});
// Piano (HARP BASS BELL) instrumentMap.put(57, new Instrument[]{Instrument.BIT, Instrument.DIDGERIDOO, Instrument.BELL});
instrumentMap.put(0, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); // Acoustic Grand Piano instrumentMap.put(58, new Instrument[]{Instrument.BIT, Instrument.DIDGERIDOO, Instrument.BELL});
instrumentMap.put(1, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); // Bright Acoustic Piano instrumentMap.put(59, new Instrument[]{Instrument.BIT, Instrument.DIDGERIDOO, Instrument.BELL});
instrumentMap.put(2, new Instrument[]{Instrument.BIT, Instrument.DIDGERIDOO, Instrument.BELL}); // Electric Grand Piano instrumentMap.put(60, new Instrument[]{Instrument.BIT, Instrument.DIDGERIDOO, Instrument.BELL});
instrumentMap.put(3, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); // Honky-tonk Piano instrumentMap.put(61, new Instrument[]{Instrument.BIT, Instrument.DIDGERIDOO, Instrument.BELL});
instrumentMap.put(4, new Instrument[]{Instrument.BIT, Instrument.DIDGERIDOO, Instrument.BELL}); // Electric Piano 1 instrumentMap.put(62, new Instrument[]{Instrument.BIT, Instrument.DIDGERIDOO, Instrument.BELL});
instrumentMap.put(5, new Instrument[]{Instrument.BIT, Instrument.DIDGERIDOO, Instrument.BELL}); // Electric Piano 2 instrumentMap.put(63, new Instrument[]{Instrument.BIT, Instrument.DIDGERIDOO, Instrument.BELL});
instrumentMap.put(6, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); // Harpsichord
instrumentMap.put(7, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL}); // Clavinet
// Chromatic Percussion (IRON_XYLOPHONE XYLOPHONE BASS) // Reed
instrumentMap.put(8, new Instrument[]{Instrument.IRON_XYLOPHONE, Instrument.BASS, Instrument.XYLOPHONE}); // Celesta instrumentMap.put(64, new Instrument[]{Instrument.FLUTE, Instrument.DIDGERIDOO, Instrument.IRON_XYLOPHONE, Instrument.BELL});
instrumentMap.put(9, new Instrument[]{Instrument.IRON_XYLOPHONE, Instrument.BASS, Instrument.XYLOPHONE}); // Glockenspiel instrumentMap.put(65, new Instrument[]{Instrument.FLUTE, Instrument.DIDGERIDOO, Instrument.IRON_XYLOPHONE, Instrument.BELL});
instrumentMap.put(10, new Instrument[]{Instrument.IRON_XYLOPHONE, Instrument.BASS, Instrument.XYLOPHONE}); // Music Box instrumentMap.put(66, new Instrument[]{Instrument.FLUTE, Instrument.DIDGERIDOO, Instrument.IRON_XYLOPHONE, Instrument.BELL});
instrumentMap.put(11, new Instrument[]{Instrument.IRON_XYLOPHONE, Instrument.BASS, Instrument.XYLOPHONE}); // Vibraphone instrumentMap.put(67, new Instrument[]{Instrument.FLUTE, Instrument.DIDGERIDOO, Instrument.IRON_XYLOPHONE, Instrument.BELL});
instrumentMap.put(12, new Instrument[]{Instrument.IRON_XYLOPHONE, Instrument.BASS, Instrument.XYLOPHONE}); // Marimba instrumentMap.put(68, new Instrument[]{Instrument.FLUTE, Instrument.DIDGERIDOO, Instrument.IRON_XYLOPHONE, Instrument.BELL});
instrumentMap.put(13, new Instrument[]{Instrument.IRON_XYLOPHONE, Instrument.BASS, Instrument.XYLOPHONE}); // Xylophone instrumentMap.put(69, new Instrument[]{Instrument.FLUTE, Instrument.DIDGERIDOO, Instrument.IRON_XYLOPHONE, Instrument.BELL});
instrumentMap.put(14, new Instrument[]{Instrument.IRON_XYLOPHONE, Instrument.BASS, Instrument.XYLOPHONE}); // Tubular Bells instrumentMap.put(70, new Instrument[]{Instrument.FLUTE, Instrument.DIDGERIDOO, Instrument.IRON_XYLOPHONE, Instrument.BELL});
instrumentMap.put(15, new Instrument[]{Instrument.IRON_XYLOPHONE, Instrument.BASS, Instrument.XYLOPHONE}); // Dulcimer instrumentMap.put(71, new Instrument[]{Instrument.FLUTE, Instrument.DIDGERIDOO, Instrument.IRON_XYLOPHONE, Instrument.BELL});
// Organ (BIT DIDGERIDOO BELL) // Pipe
instrumentMap.put(16, new Instrument[]{Instrument.DIDGERIDOO, Instrument.BIT, Instrument.XYLOPHONE}); // Drawbar Organ instrumentMap.put(72, new Instrument[]{Instrument.FLUTE, Instrument.DIDGERIDOO, Instrument.IRON_XYLOPHONE, Instrument.BELL});
instrumentMap.put(17, new Instrument[]{Instrument.DIDGERIDOO, Instrument.BIT, Instrument.XYLOPHONE}); // Percussive Organ instrumentMap.put(73, new Instrument[]{Instrument.FLUTE, Instrument.DIDGERIDOO, Instrument.IRON_XYLOPHONE, Instrument.BELL});
instrumentMap.put(18, new Instrument[]{Instrument.DIDGERIDOO, Instrument.BIT, Instrument.XYLOPHONE}); // Rock Organ instrumentMap.put(74, new Instrument[]{Instrument.FLUTE, Instrument.DIDGERIDOO, Instrument.IRON_XYLOPHONE, Instrument.BELL});
instrumentMap.put(19, new Instrument[]{Instrument.DIDGERIDOO, Instrument.BIT, Instrument.XYLOPHONE}); // Church Organ instrumentMap.put(75, new Instrument[]{Instrument.FLUTE, Instrument.DIDGERIDOO, Instrument.IRON_XYLOPHONE, Instrument.BELL});
instrumentMap.put(20, new Instrument[]{Instrument.DIDGERIDOO, Instrument.BIT, Instrument.XYLOPHONE}); // Reed Organ instrumentMap.put(76, new Instrument[]{Instrument.FLUTE, Instrument.DIDGERIDOO, Instrument.IRON_XYLOPHONE, Instrument.BELL});
instrumentMap.put(21, new Instrument[]{Instrument.DIDGERIDOO, Instrument.BIT, Instrument.XYLOPHONE}); // Accordian instrumentMap.put(77, new Instrument[]{Instrument.FLUTE, Instrument.DIDGERIDOO, Instrument.IRON_XYLOPHONE, Instrument.BELL});
instrumentMap.put(22, new Instrument[]{Instrument.DIDGERIDOO, Instrument.BIT, Instrument.XYLOPHONE}); // Harmonica instrumentMap.put(78, new Instrument[]{Instrument.FLUTE, Instrument.DIDGERIDOO, Instrument.IRON_XYLOPHONE, Instrument.BELL});
instrumentMap.put(23, new Instrument[]{Instrument.DIDGERIDOO, Instrument.BIT, Instrument.XYLOPHONE}); // Tango Accordian instrumentMap.put(79, new Instrument[]{Instrument.FLUTE, Instrument.DIDGERIDOO, Instrument.IRON_XYLOPHONE, Instrument.BELL});
// Guitar (BIT DIDGERIDOO BELL) // Synth Lead
instrumentMap.put(24, new Instrument[]{Instrument.GUITAR, Instrument.HARP, Instrument.BASS, Instrument.BELL}); // Acoustic Guitar (nylon) instrumentMap.put(80, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL});
instrumentMap.put(25, new Instrument[]{Instrument.GUITAR, Instrument.HARP, Instrument.BASS, Instrument.BELL}); // Acoustic Guitar (steel) instrumentMap.put(81, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL});
instrumentMap.put(26, new Instrument[]{Instrument.GUITAR, Instrument.HARP, Instrument.BASS, Instrument.BELL}); // Electric Guitar (jazz) instrumentMap.put(82, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL});
instrumentMap.put(27, new Instrument[]{Instrument.GUITAR, Instrument.HARP, Instrument.BASS, Instrument.BELL}); // Electric Guitar (clean) instrumentMap.put(83, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL});
instrumentMap.put(28, new Instrument[]{Instrument.GUITAR, Instrument.HARP, Instrument.BASS, Instrument.BELL}); // Electric Guitar (muted) instrumentMap.put(84, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL});
instrumentMap.put(29, new Instrument[]{Instrument.DIDGERIDOO, Instrument.BIT, Instrument.XYLOPHONE}); // Overdriven Guitar instrumentMap.put(85, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL});
instrumentMap.put(30, new Instrument[]{Instrument.DIDGERIDOO, Instrument.BIT, Instrument.XYLOPHONE}); // Distortion Guitar instrumentMap.put(86, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL});
instrumentMap.put(31, new Instrument[]{Instrument.GUITAR, Instrument.HARP, Instrument.BASS, Instrument.BELL}); // Guitar Harmonics instrumentMap.put(87, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL});
// Bass // Synth Pad
instrumentMap.put(32, new Instrument[]{Instrument.BASS, Instrument.HARP, Instrument.BELL}); // Acoustic Bass instrumentMap.put(88, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL});
instrumentMap.put(33, new Instrument[]{Instrument.BASS, Instrument.HARP, Instrument.BELL}); // Electric Bass (finger) instrumentMap.put(89, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL});
instrumentMap.put(34, new Instrument[]{Instrument.BASS, Instrument.HARP, Instrument.BELL}); // Electric Bass (pick) instrumentMap.put(90, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL});
instrumentMap.put(35, new Instrument[]{Instrument.BASS, Instrument.HARP, Instrument.BELL}); // Fretless Bass instrumentMap.put(91, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL});
instrumentMap.put(36, new Instrument[]{Instrument.DIDGERIDOO, Instrument.BIT, Instrument.XYLOPHONE}); // Slap Bass 1 instrumentMap.put(92, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL});
instrumentMap.put(37, new Instrument[]{Instrument.DIDGERIDOO, Instrument.BIT, Instrument.XYLOPHONE}); // Slap Bass 2 instrumentMap.put(93, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL});
instrumentMap.put(38, new Instrument[]{Instrument.DIDGERIDOO, Instrument.BIT, Instrument.XYLOPHONE}); // Synth Bass 1 instrumentMap.put(94, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL});
instrumentMap.put(39, new Instrument[]{Instrument.DIDGERIDOO, Instrument.BIT, Instrument.XYLOPHONE}); // Synth Bass 2 instrumentMap.put(95, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL});
// Strings // Synth Effects
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
// 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
// instrumentMap.put(96, new Instrument[]{}); // instrumentMap.put(96, new Instrument[]{});
// instrumentMap.put(97, new Instrument[]{}); // instrumentMap.put(97, new Instrument[]{});
instrumentMap.put(98, new Instrument[]{Instrument.BIT, Instrument.DIDGERIDOO, 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(99, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL});
instrumentMap.put(100, 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(101, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL});
instrumentMap.put(102, 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(103, new Instrument[]{Instrument.HARP, Instrument.BASS, Instrument.BELL});
// Ethnic // Ethnic
instrumentMap.put(104, new Instrument[]{Instrument.BANJO, Instrument.BASS, Instrument.BELL}); instrumentMap.put(104, new Instrument[]{Instrument.BANJO, Instrument.BASS, Instrument.BELL});
instrumentMap.put(105, 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(106, new Instrument[]{Instrument.BANJO, Instrument.BASS, Instrument.BELL});
instrumentMap.put(107, 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(108, new Instrument[]{Instrument.BANJO, Instrument.BASS, Instrument.BELL});
instrumentMap.put(109, new Instrument[]{Instrument.HARP, Instrument.DIDGERIDOO, 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(110, new Instrument[]{Instrument.HARP, Instrument.DIDGERIDOO, Instrument.BELL});
instrumentMap.put(111, new Instrument[]{Instrument.HARP, Instrument.DIDGERIDOO, Instrument.BELL}); instrumentMap.put(111, new Instrument[]{Instrument.HARP, Instrument.DIDGERIDOO, Instrument.BELL});
// Percussive // Percussive
instrumentMap.put(112, new Instrument[]{Instrument.IRON_XYLOPHONE, Instrument.BASS, Instrument.XYLOPHONE}); 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(113, new Instrument[]{Instrument.IRON_XYLOPHONE, Instrument.BASS, Instrument.XYLOPHONE});
instrumentMap.put(114, 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(115, new Instrument[]{Instrument.IRON_XYLOPHONE, Instrument.BASS, Instrument.XYLOPHONE});
instrumentMap.put(116, 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(117, new Instrument[]{Instrument.IRON_XYLOPHONE, Instrument.BASS, Instrument.XYLOPHONE});
instrumentMap.put(118, 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}); instrumentMap.put(119, new Instrument[]{Instrument.IRON_XYLOPHONE, Instrument.BASS, Instrument.XYLOPHONE});
} }
public static HashMap<Integer, Integer> percussionMap = new HashMap<>(); public static HashMap<Integer, Integer> percussionMap = new HashMap<>();
static {
percussionMap.put(35, 10 + 25*Instrument.BASEDRUM.id); static {
percussionMap.put(36, 6 + 25*Instrument.BASEDRUM.id); percussionMap.put(35, 10 + 25 * Instrument.BASEDRUM.id);
percussionMap.put(37, 6 + 25*Instrument.HAT.id); percussionMap.put(36, 6 + 25 * Instrument.BASEDRUM.id);
percussionMap.put(38, 8 + 25*Instrument.SNARE.id); percussionMap.put(37, 6 + 25 * Instrument.HAT.id);
percussionMap.put(39, 6 + 25*Instrument.HAT.id); percussionMap.put(38, 8 + 25 * Instrument.SNARE.id);
percussionMap.put(40, 4 + 25*Instrument.SNARE.id); percussionMap.put(39, 6 + 25 * Instrument.HAT.id);
percussionMap.put(41, 6 + 25*Instrument.BASEDRUM.id); percussionMap.put(40, 4 + 25 * Instrument.SNARE.id);
percussionMap.put(42, 22 + 25*Instrument.SNARE.id); percussionMap.put(41, 6 + 25 * Instrument.BASEDRUM.id);
percussionMap.put(43, 13 + 25*Instrument.BASEDRUM.id); percussionMap.put(42, 22 + 25 * Instrument.SNARE.id);
percussionMap.put(44, 22 + 25*Instrument.SNARE.id); percussionMap.put(43, 13 + 25 * Instrument.BASEDRUM.id);
percussionMap.put(45, 15 + 25*Instrument.BASEDRUM.id); percussionMap.put(44, 22 + 25 * Instrument.SNARE.id);
percussionMap.put(46, 18 + 25*Instrument.SNARE.id); percussionMap.put(45, 15 + 25 * Instrument.BASEDRUM.id);
percussionMap.put(47, 20 + 25*Instrument.BASEDRUM.id); percussionMap.put(46, 18 + 25 * Instrument.SNARE.id);
percussionMap.put(48, 23 + 25*Instrument.BASEDRUM.id); percussionMap.put(47, 20 + 25 * Instrument.BASEDRUM.id);
percussionMap.put(49, 17 + 25*Instrument.SNARE.id); percussionMap.put(48, 23 + 25 * Instrument.BASEDRUM.id);
percussionMap.put(50, 23 + 25*Instrument.BASEDRUM.id); percussionMap.put(49, 17 + 25 * Instrument.SNARE.id);
percussionMap.put(51, 24 + 25*Instrument.SNARE.id); percussionMap.put(50, 23 + 25 * Instrument.BASEDRUM.id);
percussionMap.put(52, 8 + 25*Instrument.SNARE.id); percussionMap.put(51, 24 + 25 * Instrument.SNARE.id);
percussionMap.put(53, 13 + 25*Instrument.SNARE.id); percussionMap.put(52, 8 + 25 * Instrument.SNARE.id);
percussionMap.put(54, 18 + 25*Instrument.HAT.id); percussionMap.put(53, 13 + 25 * Instrument.SNARE.id);
percussionMap.put(55, 18 + 25*Instrument.SNARE.id); percussionMap.put(54, 18 + 25 * Instrument.HAT.id);
percussionMap.put(56, 1 + 25*Instrument.HAT.id); percussionMap.put(55, 18 + 25 * Instrument.SNARE.id);
percussionMap.put(57, 13 + 25*Instrument.SNARE.id); percussionMap.put(56, 1 + 25 * Instrument.HAT.id);
percussionMap.put(58, 2 + 25*Instrument.HAT.id); percussionMap.put(57, 13 + 25 * Instrument.SNARE.id);
percussionMap.put(59, 13 + 25*Instrument.SNARE.id); percussionMap.put(58, 2 + 25 * Instrument.HAT.id);
percussionMap.put(60, 9 + 25*Instrument.HAT.id); percussionMap.put(59, 13 + 25 * Instrument.SNARE.id);
percussionMap.put(61, 2 + 25*Instrument.HAT.id); percussionMap.put(60, 9 + 25 * Instrument.HAT.id);
percussionMap.put(62, 8 + 25*Instrument.HAT.id); percussionMap.put(61, 2 + 25 * Instrument.HAT.id);
percussionMap.put(63, 22 + 25*Instrument.BASEDRUM.id); percussionMap.put(62, 8 + 25 * Instrument.HAT.id);
percussionMap.put(64, 15 + 25*Instrument.BASEDRUM.id); percussionMap.put(63, 22 + 25 * Instrument.BASEDRUM.id);
percussionMap.put(65, 13 + 25*Instrument.SNARE.id); percussionMap.put(64, 15 + 25 * Instrument.BASEDRUM.id);
percussionMap.put(66, 8 + 25*Instrument.SNARE.id); percussionMap.put(65, 13 + 25 * Instrument.SNARE.id);
percussionMap.put(67, 8 + 25*Instrument.HAT.id); percussionMap.put(66, 8 + 25 * Instrument.SNARE.id);
percussionMap.put(68, 3 + 25*Instrument.HAT.id); percussionMap.put(67, 8 + 25 * Instrument.HAT.id);
percussionMap.put(69, 20 + 25*Instrument.HAT.id); percussionMap.put(68, 3 + 25 * Instrument.HAT.id);
percussionMap.put(70, 23 + 25*Instrument.HAT.id); percussionMap.put(69, 20 + 25 * Instrument.HAT.id);
percussionMap.put(71, 24 + 25*Instrument.HAT.id); percussionMap.put(70, 23 + 25 * Instrument.HAT.id);
percussionMap.put(72, 24 + 25*Instrument.HAT.id); percussionMap.put(71, 24 + 25 * Instrument.HAT.id);
percussionMap.put(73, 17 + 25*Instrument.HAT.id); percussionMap.put(72, 24 + 25 * Instrument.HAT.id);
percussionMap.put(74, 11 + 25*Instrument.HAT.id); percussionMap.put(73, 17 + 25 * Instrument.HAT.id);
percussionMap.put(75, 18 + 25*Instrument.HAT.id); percussionMap.put(74, 11 + 25 * Instrument.HAT.id);
percussionMap.put(76, 9 + 25*Instrument.HAT.id); percussionMap.put(75, 18 + 25 * Instrument.HAT.id);
percussionMap.put(77, 5 + 25*Instrument.HAT.id); percussionMap.put(76, 9 + 25 * Instrument.HAT.id);
percussionMap.put(78, 22 + 25*Instrument.HAT.id); percussionMap.put(77, 5 + 25 * Instrument.HAT.id);
percussionMap.put(79, 19 + 25*Instrument.SNARE.id); percussionMap.put(78, 22 + 25 * Instrument.HAT.id);
percussionMap.put(80, 17 + 25*Instrument.HAT.id); percussionMap.put(79, 19 + 25 * Instrument.SNARE.id);
percussionMap.put(81, 22 + 25*Instrument.HAT.id); percussionMap.put(80, 17 + 25 * Instrument.HAT.id);
percussionMap.put(82, 22 + 25*Instrument.SNARE.id); percussionMap.put(81, 22 + 25 * Instrument.HAT.id);
percussionMap.put(83, 24 + 25*Instrument.CHIME.id); percussionMap.put(82, 22 + 25 * Instrument.SNARE.id);
percussionMap.put(84, 24 + 25*Instrument.CHIME.id); percussionMap.put(83, 24 + 25 * Instrument.CHIME.id);
percussionMap.put(85, 21 + 25*Instrument.HAT.id); percussionMap.put(84, 24 + 25 * Instrument.CHIME.id);
percussionMap.put(86, 14 + 25*Instrument.BASEDRUM.id); percussionMap.put(85, 21 + 25 * Instrument.HAT.id);
percussionMap.put(87, 7 + 25*Instrument.BASEDRUM.id); percussionMap.put(86, 14 + 25 * Instrument.BASEDRUM.id);
} percussionMap.put(87, 7 + 25 * Instrument.BASEDRUM.id);
}
} }

View file

@ -6,192 +6,192 @@ import java.nio.ByteOrder;
import java.util.ArrayList; import java.util.ArrayList;
public class NBSConverter { public class NBSConverter {
public static Instrument[] instrumentIndex = new Instrument[] { public static Instrument[] instrumentIndex = new Instrument[]{
Instrument.HARP, Instrument.HARP,
Instrument.BASS, Instrument.BASS,
Instrument.BASEDRUM, Instrument.BASEDRUM,
Instrument.SNARE, Instrument.SNARE,
Instrument.HAT, Instrument.HAT,
Instrument.GUITAR, Instrument.GUITAR,
Instrument.FLUTE, Instrument.FLUTE,
Instrument.BELL, Instrument.BELL,
Instrument.CHIME, Instrument.CHIME,
Instrument.XYLOPHONE, Instrument.XYLOPHONE,
Instrument.IRON_XYLOPHONE, Instrument.IRON_XYLOPHONE,
Instrument.COW_BELL, Instrument.COW_BELL,
Instrument.DIDGERIDOO, Instrument.DIDGERIDOO,
Instrument.BIT, Instrument.BIT,
Instrument.BANJO, Instrument.BANJO,
Instrument.PLING, Instrument.PLING,
}; };
private static class NBSNote { private static class NBSNote {
public int tick; public int tick;
public short layer; public short layer;
public byte instrument; public byte instrument;
public byte key; public byte key;
public byte velocity = 100; public byte velocity = 100;
public byte panning = 100; public byte panning = 100;
public short pitch = 0; 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();
} }
if (format >= 1) { private static class NBSLayer {
vanillaInstrumentCount = buffer.get(); public String name;
} public byte lock = 0;
if (format >= 3) { public byte volume;
songLength = buffer.getShort(); public byte stereo = 100;
} }
short layerCount = buffer.getShort(); private static class NBSCustomInstrument {
String songName = getString(buffer, bytes.length); public String name;
String songAuthor = getString(buffer, bytes.length); public String file;
String songOriginalAuthor = getString(buffer, bytes.length); public byte pitch = 0;
String songDescription = getString(buffer, bytes.length); public boolean key = false;
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();
} }
ArrayList<NBSNote> nbsNotes = new ArrayList<>(); public static Song getSongFromBytes(byte[] bytes, String fileName) throws IOException {
short tick = -1; ByteBuffer buffer = ByteBuffer.wrap(bytes);
while (true) { buffer.order(ByteOrder.LITTLE_ENDIAN);
int tickJumps = buffer.getShort();
if (tickJumps == 0) break;
tick += tickJumps;
short layer = -1; short songLength = 0;
while (true) { byte format = 0;
int layerJumps = buffer.getShort(); byte vanillaInstrumentCount = 0;
if (layerJumps == 0) break; songLength = buffer.getShort(); // If it's not 0, then it uses the old format
layer += layerJumps; if (songLength == 0) {
NBSNote note = new NBSNote(); format = buffer.get();
note.tick = tick; }
note.layer = layer;
note.instrument = buffer.get(); if (format >= 1) {
note.key = buffer.get(); 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) { if (format >= 4) {
note.velocity = buffer.get(); loop = buffer.get();
note.panning = buffer.get(); maxLoopCount = buffer.get();
note.pitch = buffer.getShort(); loopStartTick = buffer.getShort();
} }
nbsNotes.add(note);
}
}
ArrayList<NBSLayer> nbsLayers = new ArrayList<>(); ArrayList<NBSNote> nbsNotes = new ArrayList<>();
if (buffer.hasRemaining()) { short tick = -1;
for (int i=0; i<layerCount; i++) { while (true) {
NBSLayer layer = new NBSLayer(); int tickJumps = buffer.getShort();
layer.name = getString(buffer, bytes.length); if (tickJumps == 0) break;
if (format >= 4) { tick += tickJumps;
layer.lock = buffer.get();
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) { ArrayList<NBSLayer> nbsLayers = new ArrayList<>();
layer.stereo = buffer.get(); 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<NBSCustomInstrument> 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<NBSCustomInstrument> customInstruments = new ArrayList<>(); private static String getString(ByteBuffer buffer, int maxSize) throws IOException {
if (buffer.hasRemaining()) { int length = buffer.getInt();
byte customInstrumentCount = buffer.get(); if (length > maxSize) {
for (int i = 0; i < customInstrumentCount; i++) { throw new IOException("String is too large");
NBSCustomInstrument customInstrument = new NBSCustomInstrument(); }
customInstrument.name = getString(buffer, bytes.length); byte arr[] = new byte[length];
customInstrument.file = getString(buffer, bytes.length); buffer.get(arr, 0, length);
customInstrument.pitch = buffer.get(); return new String(arr);
customInstrument.key = buffer.get() == 0 ? false : true;
customInstruments.add(customInstrument);
}
} }
Song song = new Song(songName.trim().length() > 0 ? songName : fileName); private static int getMilliTime(int tick, int tempo) {
if (loop > 0) { return 1000 * tick * 100 / tempo;
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;
}
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;
}
} }

View file

@ -2,32 +2,30 @@ package land.chipmunk.chipmunkmod.song;
public class Note implements Comparable<Note> { public class Note implements Comparable<Note> {
public Instrument instrument; public Instrument instrument;
public int pitch; public int pitch;
public float volume; public float volume;
public long time; public long time;
public Note (Instrument instrument, int pitch, float volume, long time) { public Note(Instrument instrument, int pitch, float volume, long time) {
this.instrument = instrument; this.instrument = instrument;
this.pitch = pitch; this.pitch = pitch;
this.volume = volume; this.volume = volume;
this.time = time; this.time = time;
} }
@Override @Override
public int compareTo(Note other) { public int compareTo(Note other) {
if (time < other.time) { if (time < other.time) {
return -1; 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 () { public int noteId() {
return pitch + instrument.id * 25; return pitch + instrument.id * 25;
} }
} }

View file

@ -1,131 +1,132 @@
package land.chipmunk.chipmunkmod.song; package land.chipmunk.chipmunkmod.song;
import net.kyori.adventure.text.Component; import net.kyori.adventure.text.Component;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
public class Song { public class Song {
public ArrayList<Note> notes = new ArrayList<>(); public ArrayList<Note> notes = new ArrayList<>();
public Component name; public Component name;
public int position = 0; // Current note index public int position = 0; // Current note index
public boolean looping = false; public boolean looping = false;
public boolean paused = true; public boolean paused = true;
public long startTime = 0; // Start time in millis since unix epoch public long startTime = 0; // Start time in millis since unix epoch
public long length = 0; // Milliseconds in the song public long length = 0; // Milliseconds in the song
public long time = 0; // Time since start of song public long time = 0; // Time since start of song
public long loopPosition = 0; // Milliseconds into the song to start looping public long loopPosition = 0; // Milliseconds into the song to start looping
public int loopCount = 0; // Number of times to loop public int loopCount = 0; // Number of times to loop
public int currentLoop = 0; // Number of loops so far public int currentLoop = 0; // Number of loops so far
public Song (Component name) { public Song(Component name) {
this.name = name; this.name = name;
}
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(String name) {
* Pauses song (does nothing if already paused) this(Component.text(name));
*/
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 void setTime (long t) { public Note get(int i) {
time = t; return notes.get(i);
startTime = System.currentTimeMillis() - time;
position = 0;
while (position < notes.size() && notes.get(position).time < t) {
position++;
} }
}
public void advanceTime () { public void add(Note e) {
time = System.currentTimeMillis() - startTime; notes.add(e);
} }
public boolean reachedNextNote () { public void sort() {
if (position < notes.size()) { Collections.sort(notes);
return notes.get(position).time <= time; }
} else {
if (time > length && shouldLoop()) { /**
loop(); * Starts playing song (does nothing if already playing)
if (position < notes.size()) { */
return notes.get(position).time <= time; public void play() {
} else { if (paused) {
return false; paused = false;
startTime = System.currentTimeMillis() - time;
} }
} else {
return false;
}
} }
}
public Note getNextNote () { /**
if (position >= notes.size()) { * Pauses song (does nothing if already paused)
if (shouldLoop()) { */
loop(); public void pause() {
} else { if (!paused) {
return null; 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 () { public void setTime(long t) {
return time > length && !shouldLoop(); time = t;
} startTime = System.currentTimeMillis() - time;
position = 0;
private void loop () { while (position < notes.size() && notes.get(position).time < t) {
position = 0; position++;
startTime += length - loopPosition; }
time -= length - loopPosition;
while (position < notes.size() && notes.get(position).time < loopPosition) {
position++;
} }
currentLoop++;
}
private boolean shouldLoop () { public void advanceTime() {
if (looping) { time = System.currentTimeMillis() - startTime;
if (loopCount == 0) {
return true;
} else {
return currentLoop < loopCount;
}
} else {
return false;
} }
}
public int size () { public boolean reachedNextNote() {
return notes.size(); 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();
}
} }

View file

@ -3,20 +3,20 @@ package land.chipmunk.chipmunkmod.song;
import net.minecraft.text.Text; import net.minecraft.text.Text;
public class SongLoaderException extends Exception { public class SongLoaderException extends Exception {
public final Text message; public final Text message;
public SongLoaderException (Text message) { public SongLoaderException(Text message) {
super(); super();
this.message = message; this.message = message;
} }
public SongLoaderException (Text message, Throwable cause) { public SongLoaderException(Text message, Throwable cause) {
super(null, cause); super(null, cause);
this.message = message; this.message = message;
} }
@Override @Override
public String getMessage () { public String getMessage() {
return message.getString(); return message.getString();
} }
} }

View file

@ -11,58 +11,58 @@ import java.nio.file.Files;
import java.nio.file.Paths; import java.nio.file.Paths;
public class SongLoaderThread extends Thread { public class SongLoaderThread extends Thread {
private String location; private String location;
private File songPath; private File songPath;
private URL songUrl; private URL songUrl;
public SongLoaderException exception; public SongLoaderException exception;
public Song song; public Song song;
private boolean isUrl; private boolean isUrl;
public SongLoaderThread (URL location) throws SongLoaderException { public SongLoaderThread(URL location) throws SongLoaderException {
isUrl = true; isUrl = true;
songUrl = location; 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;
} }
try { public SongLoaderThread(Path location) throws SongLoaderException {
song = MidiConverter.getSongFromBytes(bytes, name); isUrl = false;
} catch (Exception e) { songPath = location.toFile();
} }
if (song == null) { public void run() {
try { byte[] bytes;
song = NBSConverter.getSongFromBytes(bytes, name); String name;
} catch (Exception e) { 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) { private File getSongFile(String name) {
exception = new SongLoaderException(Text.translatable("Invalid song format")); return new File(SongPlayer.SONG_DIR, name);
} }
}
private File getSongFile (String name) {
return new File(SongPlayer.SONG_DIR, name);
}
} }

View file

@ -14,46 +14,48 @@ import java.security.cert.X509Certificate;
public class DownloadUtilities { public class DownloadUtilities {
private static class DefaultTrustManager implements X509TrustManager { private static class DefaultTrustManager implements X509TrustManager {
@Override @Override
public void checkClientTrusted(X509Certificate[] arg0, String arg1) {} 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;
} }
}
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 { @Override
return new ByteArrayInputStream(DownloadToByteArray(url)); 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));
}
} }