Compare commits

..

No commits in common. "0b31a366cbe31b7b626108a9e24b0e20741c306d" and "bb8bb88489844eaa1e6bad030295fe029d8ebc5a" have entirely different histories.

73 changed files with 1110 additions and 1175 deletions

View file

@ -1,13 +1,4 @@
# ChipmunkMod # ChipmunkMod
My fork of [Chipmunk's ChipmunkMod](https://code.chipmunk.land/ChipmunkMC/chipmunkmod) My fork of [Chipmunk Sex Mod](https://code.chipmunk.land/ChipmunkMC/chipmunkmod)
# Development ignore messy code pls,. .,,.,...,.,.,
When commiting your changes, please use my code style.
In IntelliJ IDEA:
`Ctrl + Alt + S`, search `Code Style`, go to `Java`, click gear icon, `Import Scheme -> IntelliJ IDEA code style XML`,
use the `codestyle.xml` file in this repository
`Ctrl + Alt + Shift + H`, click `Configure Inspections...`, click gear icon, `Import Profile...`,
use the `inspections.xml` file in this repository

View file

@ -1,29 +0,0 @@
<code_scheme name="Project" version="173">
<JavaCodeStyleSettings>
<option name="GENERATE_FINAL_LOCALS" value="true" />
<option name="GENERATE_FINAL_PARAMETERS" value="true" />
<option name="VISIBILITY" value="protected" />
<option name="SPACE_BEFORE_OPENING_ANGLE_BRACKET_IN_TYPE_PARAMETER" value="true" />
<option name="SPACE_BEFORE_DECONSTRUCTION_LIST" value="true" />
</JavaCodeStyleSettings>
<JetCodeStyleSettings>
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
</JetCodeStyleSettings>
<codeStyleSettings language="JAVA">
<option name="RIGHT_MARGIN" value="120" />
<option name="KEEP_FIRST_COLUMN_COMMENT" value="false" />
<option name="ALIGN_MULTILINE_PARAMETERS_IN_CALLS" value="true" />
<option name="SPACE_WITHIN_BRACES" value="true" />
<option name="SPACE_WITHIN_ARRAY_INITIALIZER_BRACES" value="true" />
<option name="SPACE_BEFORE_METHOD_PARENTHESES" value="true" />
<option name="SPACE_BEFORE_ARRAY_INITIALIZER_LBRACE" value="true" />
<option name="KEEP_SIMPLE_BLOCKS_IN_ONE_LINE" value="true" />
<option name="KEEP_SIMPLE_METHODS_IN_ONE_LINE" value="true" />
<option name="KEEP_SIMPLE_LAMBDAS_IN_ONE_LINE" value="true" />
<option name="KEEP_SIMPLE_CLASSES_IN_ONE_LINE" value="true" />
<option name="KEEP_MULTIPLE_EXPRESSIONS_IN_ONE_LINE" value="true" />
</codeStyleSettings>
<codeStyleSettings language="kotlin">
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
</codeStyleSettings>
</code_scheme>

View file

@ -1,9 +0,0 @@
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="myName" value="Project Default" />
<inspection_tool class="LocalCanBeFinal" enabled="true" level="WARNING" enabled_by_default="true">
<option name="REPORT_VARIABLES" value="true" />
<option name="REPORT_PARAMETERS" value="true" />
</inspection_tool>
</profile>
</component>

View file

@ -19,13 +19,31 @@ import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
public class ChipmunkMod implements ModInitializer { public class ChipmunkMod implements ModInitializer {
public static final Logger LOGGER = LoggerFactory.getLogger("ChipmunkMod");
private static final Path CONFIG_PATH = FabricLoader.getInstance() private static final Path CONFIG_PATH = FabricLoader.getInstance()
.getConfigDir().resolve("chipmunkmod.json"); .getConfigDir().resolve("chipmunkmod.json");
public static final Logger LOGGER = LoggerFactory.getLogger("ChipmunkMod");
public static Configuration CONFIG; public static Configuration CONFIG;
public static ExecutorService executorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors()); public static ExecutorService executorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
@Override
public void onInitialize() {
// This code runs as soon as Minecraft is in a mod-load-ready state.
// However, some things (like resources) may still be uninitialized.
// Proceed with mild caution.
try {
CONFIG = loadConfig();
} catch (IOException exception) {
throw new RuntimeException("Could not load the config", exception);
}
SelfCare.INSTANCE.init();
LOGGER.info("Loaded ChipmunkMod (chayapak's fork)");
}
public static Configuration loadConfig() throws IOException { public static Configuration loadConfig() throws IOException {
final ChipmunkModMigrations migrations = new ChipmunkModMigrations(); final ChipmunkModMigrations migrations = new ChipmunkModMigrations();
final ObjectMapper.Factory customFactory = ObjectMapper.factoryBuilder() final ObjectMapper.Factory customFactory = ObjectMapper.factoryBuilder()
@ -59,21 +77,4 @@ public class ChipmunkMod implements ModInitializer {
return node.get(Configuration.class); return node.get(Configuration.class);
} }
@Override
public void onInitialize () {
// This code runs as soon as Minecraft is in a mod-load-ready state.
// However, some things (like resources) may still be uninitialized.
// Proceed with mild caution.
try {
CONFIG = loadConfig();
} catch (final IOException exception) {
throw new RuntimeException("Could not load the config", exception);
}
SelfCare.INSTANCE.init();
LOGGER.info("Loaded ChipmunkMod (chayapak's fork)");
}
} }

View file

@ -5,22 +5,23 @@ import com.mojang.brigadier.arguments.ArgumentType;
import com.mojang.brigadier.builder.LiteralArgumentBuilder; import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import com.mojang.brigadier.builder.RequiredArgumentBuilder; import com.mojang.brigadier.builder.RequiredArgumentBuilder;
import com.mojang.brigadier.exceptions.CommandSyntaxException; import com.mojang.brigadier.exceptions.CommandSyntaxException;
import land.chipmunk.chipmunkmod.commands.*;
import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource;
import net.minecraft.client.MinecraftClient;
import net.minecraft.command.CommandRegistryAccess;
import net.minecraft.text.ClickEvent; import net.minecraft.text.ClickEvent;
import net.minecraft.text.MutableText;
import net.minecraft.text.Text; import net.minecraft.text.Text;
import net.minecraft.text.Texts; import net.minecraft.text.Texts;
import net.minecraft.text.MutableText;
import net.minecraft.util.Formatting; import net.minecraft.util.Formatting;
import net.minecraft.command.CommandRegistryAccess;
import net.minecraft.client.MinecraftClient;
import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource;
import land.chipmunk.chipmunkmod.commands.*;
public class CommandManager { public class CommandManager {
public static CommandManager INSTANCE;
public CommandDispatcher<FabricClientCommandSource> dispatcher = new CommandDispatcher<>(); public CommandDispatcher<FabricClientCommandSource> dispatcher = new CommandDispatcher<>();
public String prefix; public String prefix;
public CommandManager (final String prefix, final CommandRegistryAccess commandRegistryAccess) { public static CommandManager INSTANCE;
public CommandManager(String prefix, CommandRegistryAccess commandRegistryAccess) {
this.prefix = prefix; this.prefix = prefix;
TestCommand.register(this.dispatcher); TestCommand.register(this.dispatcher);
@ -39,31 +40,23 @@ public class CommandManager {
SelfCareCommand.register(this.dispatcher); SelfCareCommand.register(this.dispatcher);
} }
public static LiteralArgumentBuilder<FabricClientCommandSource> literal (final String name) { public void executeCommand(String command) {
return LiteralArgumentBuilder.literal(name);
}
public static <T> RequiredArgumentBuilder<FabricClientCommandSource, T> argument (final String name, final ArgumentType<T> type) {
return RequiredArgumentBuilder.argument(name, type);
}
public void executeCommand (final String command) {
final MinecraftClient client = MinecraftClient.getInstance(); final MinecraftClient client = MinecraftClient.getInstance();
final FabricClientCommandSource commandSource = (FabricClientCommandSource) client.getNetworkHandler().getCommandSource(); final FabricClientCommandSource commandSource = (FabricClientCommandSource) client.getNetworkHandler().getCommandSource();
try { try {
dispatcher.execute(command, commandSource); dispatcher.execute(command, commandSource);
} catch (final CommandSyntaxException e) { } catch (CommandSyntaxException e) {
commandSource.sendError(Texts.toText(e.getRawMessage())); commandSource.sendError(Texts.toText(e.getRawMessage()));
final Text context = getContext(e); final Text context = getContext(e);
if (context != null) commandSource.sendError(context); if (context != null) commandSource.sendError(context);
} catch (final Exception e) { } catch (Exception e) {
commandSource.sendError(Text.of(e.getMessage())); commandSource.sendError(Text.of(e.getMessage()));
} }
} }
public Text getContext (final CommandSyntaxException exception) { public Text getContext(CommandSyntaxException exception) {
final int _cursor = exception.getCursor(); final int _cursor = exception.getCursor();
final String input = exception.getInput(); final String input = exception.getInput();
@ -87,4 +80,12 @@ public class CommandManager {
return text; 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

@ -22,50 +22,27 @@ public class LocationArgumentType implements ArgumentType<Object> {
private final boolean allowsPaths; private final boolean allowsPaths;
private final Path root; private final Path root;
private LocationArgumentType (final boolean allowsUrls, final boolean allowsPaths, final Path root) { private LocationArgumentType (boolean allowsUrls, boolean allowsPaths, Path root) {
this.allowsUrls = allowsUrls; this.allowsUrls = allowsUrls;
this.allowsPaths = allowsPaths; this.allowsPaths = allowsPaths;
this.root = root.toAbsolutePath().normalize(); this.root = root.toAbsolutePath().normalize();
} }
public static LocationArgumentType location (final Path rootPath) { return new LocationArgumentType(true, true, rootPath); } public static LocationArgumentType location (Path rootPath) { return new LocationArgumentType(true, true, rootPath); }
public static LocationArgumentType url () { return new LocationArgumentType(true, false, null); } public static LocationArgumentType url () { return new LocationArgumentType(true, false, null); }
public static LocationArgumentType filepath (Path rootPath) { return new LocationArgumentType(false, true, rootPath); }
public static LocationArgumentType filepath (final Path rootPath) { return new LocationArgumentType(false, true, rootPath); }
private static Object getLocation (final CommandContext<?> context, final String name) {
return context.getArgument(name, Object.class);
}
public static URL getUrl (final CommandContext<?> context, final String name) {
final Object location = getLocation(context, name);
if (location instanceof URL) return (URL) location;
try {
if (location instanceof Path) return new URI("file", "", "", -1, location.toString(), "", "").toURL();
} catch (final MalformedURLException | URISyntaxException ignored) {
return null; // The real question is whether this will actually ever get called
}
return null;
}
public static Path getPath (final CommandContext<?> context, final String name) {
final Object location = getLocation(context, name);
if (location instanceof Path) return (Path) location;
return null;
}
@Override @Override
public Object parse (final StringReader reader) throws CommandSyntaxException { public Object parse (StringReader reader) throws CommandSyntaxException {
final String remaining = reader.getString().substring(reader.getCursor()); final String remaining = reader.getString().substring(reader.getCursor());
if (allowsUrls && isUrlStart(remaining)) return parseUrl(reader); if (allowsUrls && isUrlStart(remaining)) return parseUrl(reader);
if (allowsPaths) return parsePath(reader); if (allowsPaths) return parsePath(reader);
return null; return null;
} }
public boolean isUrlStart (final String string) { return string.startsWith("http://") || string.startsWith("https://") || string.startsWith("ftp://"); } public boolean isUrlStart (String string) { return string.startsWith("http://") || string.startsWith("https://") || string.startsWith("ftp://"); }
public URL parseUrl (final StringReader reader) throws CommandSyntaxException { public URL parseUrl (StringReader reader) throws CommandSyntaxException {
final StringBuilder sb = new StringBuilder(); final StringBuilder sb = new StringBuilder();
while (reader.canRead() && reader.peek() != ' ') { while (reader.canRead() && reader.peek() != ' ') {
sb.append(reader.read()); sb.append(reader.read());
@ -73,16 +50,37 @@ public class LocationArgumentType implements ArgumentType<Object> {
try { try {
return new URI(sb.toString()).toURL(); return new URI(sb.toString()).toURL();
} catch (final MalformedURLException | URISyntaxException exception) { } catch (MalformedURLException | URISyntaxException exception) {
throw new SimpleCommandExceptionType(Text.literal(exception.getMessage())).create(); throw new SimpleCommandExceptionType(Text.literal(exception.getMessage())).create();
} }
} }
public Path parsePath (final StringReader reader) throws CommandSyntaxException { public Path parsePath (StringReader reader) throws CommandSyntaxException {
final String pathString = reader.readString(); final String pathString = reader.readString();
return Path.of(root.toString(), pathString).toAbsolutePath().normalize(); return Path.of(root.toString(), pathString).toAbsolutePath().normalize();
} }
private static Object getLocation (CommandContext<?> context, String name) {
return context.getArgument(name, Object.class);
}
public static URL getUrl (CommandContext<?> context, String name) {
final Object location = getLocation(context, name);
if (location instanceof URL) return (URL) location;
try {
if (location instanceof Path) return new URI("file", "", "", -1, location.toString(), "", "").toURL();
} catch (MalformedURLException | URISyntaxException ignored) {
return null; // The real question is whether this will actually ever get called
}
return null;
}
public static Path getPath (CommandContext<?> context, String name) {
final Object location = getLocation(context, name);
if (location instanceof Path) return (Path) location;
return null;
}
@Override @Override
public Collection<String> getExamples () { return EXAMPLES; } public Collection<String> getExamples () { return EXAMPLES; }
} }

View file

@ -1,11 +1,10 @@
package land.chipmunk.chipmunkmod.command.arguments; package land.chipmunk.chipmunkmod.command.arguments;
import com.mojang.brigadier.StringReader;
import com.mojang.brigadier.arguments.ArgumentType; import com.mojang.brigadier.arguments.ArgumentType;
import com.mojang.brigadier.StringReader;
import com.mojang.brigadier.exceptions.CommandSyntaxException; import com.mojang.brigadier.exceptions.CommandSyntaxException;
import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.Arrays;
public class TimestampArgumentType implements ArgumentType<Long> { public class TimestampArgumentType implements ArgumentType<Long> {
private static final Collection<String> EXAMPLES = Arrays.asList("0:01", "1:23", "6:09"); private static final Collection<String> EXAMPLES = Arrays.asList("0:01", "1:23", "6:09");
@ -16,7 +15,7 @@ public class TimestampArgumentType implements ArgumentType<Long> {
public static TimestampArgumentType timestamp () { return new TimestampArgumentType(); } public static TimestampArgumentType timestamp () { return new TimestampArgumentType(); }
@Override @Override
public Long parse (final StringReader reader) throws CommandSyntaxException { public Long parse (StringReader reader) throws CommandSyntaxException {
long seconds = 0L; long seconds = 0L;
long minutes = 0L; long minutes = 0L;

View file

@ -13,7 +13,7 @@ import static land.chipmunk.chipmunkmod.command.CommandManager.argument;
import static land.chipmunk.chipmunkmod.command.CommandManager.literal; import static land.chipmunk.chipmunkmod.command.CommandManager.literal;
public class AutoSkinCommand { public class AutoSkinCommand {
public static void register (final CommandDispatcher<FabricClientCommandSource> dispatcher) { public static void register (CommandDispatcher<FabricClientCommandSource> dispatcher) {
dispatcher.register( dispatcher.register(
literal("autoskin") literal("autoskin")
.then( .then(
@ -23,7 +23,7 @@ public class AutoSkinCommand {
); );
} }
public static int execute (final CommandContext<FabricClientCommandSource> context) { public static int execute(CommandContext<FabricClientCommandSource> context) {
final FabricClientCommandSource source = context.getSource(); final FabricClientCommandSource source = context.getSource();
final String username = getString(context, "username"); final String username = getString(context, "username");

View file

@ -5,25 +5,23 @@ 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 com.mojang.brigadier.exceptions.DynamicCommandExceptionType; import com.mojang.brigadier.exceptions.DynamicCommandExceptionType;
import land.chipmunk.chipmunkmod.modules.CommandLoopManager; import static land.chipmunk.chipmunkmod.command.CommandManager.literal;
import static land.chipmunk.chipmunkmod.command.CommandManager.argument;
import static com.mojang.brigadier.arguments.LongArgumentType.longArg;
import static com.mojang.brigadier.arguments.LongArgumentType.getLong;
import static com.mojang.brigadier.arguments.StringArgumentType.greedyString;
import static com.mojang.brigadier.arguments.StringArgumentType.getString;
import static com.mojang.brigadier.arguments.IntegerArgumentType.integer;
import static com.mojang.brigadier.arguments.IntegerArgumentType.getInteger;
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 land.chipmunk.chipmunkmod.modules.CommandLoopManager;
import java.util.List; import java.util.List;
import static com.mojang.brigadier.arguments.IntegerArgumentType.getInteger;
import static com.mojang.brigadier.arguments.IntegerArgumentType.integer;
import static com.mojang.brigadier.arguments.LongArgumentType.getLong;
import static com.mojang.brigadier.arguments.LongArgumentType.longArg;
import static com.mojang.brigadier.arguments.StringArgumentType.getString;
import static com.mojang.brigadier.arguments.StringArgumentType.greedyString;
import static land.chipmunk.chipmunkmod.command.CommandManager.argument;
import static land.chipmunk.chipmunkmod.command.CommandManager.literal;
public class CloopCommand { public class CloopCommand {
private static final DynamicCommandExceptionType INVALID_CLOOP_ID_EXCEPTION = new DynamicCommandExceptionType(id -> Text.translatable("Invalid cloop id: %s", Text.literal(String.valueOf(id)))); private static final DynamicCommandExceptionType INVALID_CLOOP_ID_EXCEPTION = new DynamicCommandExceptionType(id -> Text.translatable("Invalid cloop id: %s", Text.literal(String.valueOf(id))));
public static void register (final CommandDispatcher<FabricClientCommandSource> dispatcher) { public static void register (CommandDispatcher<FabricClientCommandSource> dispatcher) {
dispatcher.register( dispatcher.register(
literal("cloop") literal("cloop")
.then( .then(
@ -54,18 +52,18 @@ public class CloopCommand {
); );
} }
public static int addCloop (final CommandContext<FabricClientCommandSource> context) { public static int addCloop (CommandContext<FabricClientCommandSource> context) {
final FabricClientCommandSource source = context.getSource(); final FabricClientCommandSource source = context.getSource();
final long interval = getLong(context, "interval"); final long interval = getLong(context, "interval");
final String command = getString(context, "command"); final String command = getString(context, "command");
final int id = CommandLoopManager.INSTANCE.loopCommand(command, interval); int id = CommandLoopManager.INSTANCE.loopCommand(command, interval);
source.sendFeedback(Text.translatable("Successfully created a loop for command '%s' with id %s", Text.literal(command), Text.literal(String.valueOf(id)))); source.sendFeedback(Text.translatable("Successfully created a loop for command '%s' with id %s", Text.literal(command), Text.literal(String.valueOf(id))));
return Command.SINGLE_SUCCESS; return Command.SINGLE_SUCCESS;
} }
public static int removeCloop (final CommandContext<FabricClientCommandSource> context) throws CommandSyntaxException { public static int removeCloop (CommandContext<FabricClientCommandSource> context) throws CommandSyntaxException {
final FabricClientCommandSource source = context.getSource(); final FabricClientCommandSource source = context.getSource();
final CommandLoopManager manager = CommandLoopManager.INSTANCE; final CommandLoopManager manager = CommandLoopManager.INSTANCE;
final int id = getInteger(context, "id"); final int id = getInteger(context, "id");
@ -78,7 +76,7 @@ public class CloopCommand {
return Command.SINGLE_SUCCESS; return Command.SINGLE_SUCCESS;
} }
public static int clearCloops (final CommandContext<FabricClientCommandSource> context) { public static int clearCloops (CommandContext<FabricClientCommandSource> context) {
final FabricClientCommandSource source = context.getSource(); final FabricClientCommandSource source = context.getSource();
final CommandLoopManager manager = CommandLoopManager.INSTANCE; final CommandLoopManager manager = CommandLoopManager.INSTANCE;
@ -88,12 +86,12 @@ public class CloopCommand {
return Command.SINGLE_SUCCESS; return Command.SINGLE_SUCCESS;
} }
public static int listCloops (final CommandContext<FabricClientCommandSource> context) { public static int listCloops (CommandContext<FabricClientCommandSource> context) {
final FabricClientCommandSource source = context.getSource(); final FabricClientCommandSource source = context.getSource();
final List<CommandLoopManager.CommandLoop> loops = CommandLoopManager.INSTANCE.commandLoops; final List<CommandLoopManager.CommandLoop> loops = CommandLoopManager.INSTANCE.commandLoops;
int id = 0; int id = 0;
for (final CommandLoopManager.CommandLoop loop : loops) { for (CommandLoopManager.CommandLoop loop : loops) {
source.sendFeedback(Text.translatable("%s: %s (%s)", Text.literal(String.valueOf(id)), Text.literal(loop.command), Text.literal(String.valueOf(loop.interval)))); source.sendFeedback(Text.translatable("%s: %s (%s)", Text.literal(String.valueOf(id)), Text.literal(loop.command), Text.literal(String.valueOf(loop.interval))));
id++; id++;
} }

View file

@ -1,25 +1,28 @@
package land.chipmunk.chipmunkmod.commands; package land.chipmunk.chipmunkmod.commands;
import com.google.common.base.Suppliers;
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 land.chipmunk.chipmunkmod.modules.CommandCore;
import land.chipmunk.chipmunkmod.util.TextUtilities;
import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource;
import net.minecraft.nbt.NbtCompound;
import net.minecraft.text.Text;
import java.util.concurrent.CompletableFuture;
import static com.mojang.brigadier.arguments.BoolArgumentType.bool; import static com.mojang.brigadier.arguments.BoolArgumentType.bool;
import static com.mojang.brigadier.arguments.BoolArgumentType.getBool; import static com.mojang.brigadier.arguments.BoolArgumentType.getBool;
import static com.mojang.brigadier.arguments.StringArgumentType.getString;
import static com.mojang.brigadier.arguments.StringArgumentType.greedyString;
import static land.chipmunk.chipmunkmod.command.CommandManager.argument;
import static land.chipmunk.chipmunkmod.command.CommandManager.literal; import static land.chipmunk.chipmunkmod.command.CommandManager.literal;
import static land.chipmunk.chipmunkmod.command.CommandManager.argument;
import static com.mojang.brigadier.arguments.StringArgumentType.greedyString;
import static com.mojang.brigadier.arguments.StringArgumentType.getString;
import land.chipmunk.chipmunkmod.util.TextUtilities;
import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource;
import net.minecraft.text.Text;
import net.minecraft.nbt.NbtCompound;
import java.util.concurrent.CompletableFuture;
import land.chipmunk.chipmunkmod.modules.CommandCore;
public class CoreCommand { public class CoreCommand {
public static void register (final CommandDispatcher<FabricClientCommandSource> dispatcher) { public static void register(CommandDispatcher<FabricClientCommandSource> dispatcher) {
dispatcher.register( dispatcher.register(
literal("core") literal("core")
.then( .then(
@ -51,13 +54,13 @@ public class CoreCommand {
); );
} }
public static int run (final CommandContext<FabricClientCommandSource> context) { public static int run(CommandContext<FabricClientCommandSource> context) {
CommandCore.INSTANCE.run(getString(context, "command")); CommandCore.INSTANCE.run(getString(context, "command"));
return Command.SINGLE_SUCCESS; return Command.SINGLE_SUCCESS;
} }
public static int runTracked (final CommandContext<FabricClientCommandSource> context) { public static int runTracked(CommandContext<FabricClientCommandSource> context) {
final FabricClientCommandSource source = context.getSource(); final FabricClientCommandSource source = context.getSource();
final String command = getString(context, "command"); final String command = getString(context, "command");
@ -67,7 +70,7 @@ public class CoreCommand {
try { try {
final String output = tag.getString("LastOutput"); final String output = tag.getString("LastOutput");
if (output != null) source.sendFeedback(TextUtilities.fromJson(output)); if (output != null) source.sendFeedback(TextUtilities.fromJson(output));
} catch (final Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
} }
@ -77,13 +80,13 @@ public class CoreCommand {
return Command.SINGLE_SUCCESS; return Command.SINGLE_SUCCESS;
} }
public static int refill (final CommandContext<FabricClientCommandSource> context) { public static int refill(CommandContext<FabricClientCommandSource> context) {
CommandCore.INSTANCE.refill(); CommandCore.INSTANCE.refill();
return Command.SINGLE_SUCCESS; return Command.SINGLE_SUCCESS;
} }
public static int move (final CommandContext<FabricClientCommandSource> context) { public static int move(CommandContext<FabricClientCommandSource> context) {
final FabricClientCommandSource source = context.getSource(); final FabricClientCommandSource source = context.getSource();
CommandCore.INSTANCE.move(source.getClient().player.getPos()); CommandCore.INSTANCE.move(source.getClient().player.getPos());
@ -91,7 +94,7 @@ public class CoreCommand {
return Command.SINGLE_SUCCESS; return Command.SINGLE_SUCCESS;
} }
public static int runFillCommand (final CommandContext<FabricClientCommandSource> context) { public static int runFillCommand(CommandContext<FabricClientCommandSource> context) {
final FabricClientCommandSource source = context.getSource(); final FabricClientCommandSource source = context.getSource();
final boolean bool = getBool(context, "enabled"); final boolean bool = getBool(context, "enabled");

View file

@ -15,7 +15,7 @@ import static land.chipmunk.chipmunkmod.command.CommandManager.argument;
import static land.chipmunk.chipmunkmod.command.CommandManager.literal; import static land.chipmunk.chipmunkmod.command.CommandManager.literal;
public class CustomChatCommand { public class CustomChatCommand {
public static void register (final CommandDispatcher<FabricClientCommandSource> dispatcher) { public static void register (CommandDispatcher<FabricClientCommandSource> dispatcher) {
dispatcher.register( dispatcher.register(
literal("customchat") literal("customchat")
.then( .then(
@ -35,7 +35,7 @@ public class CustomChatCommand {
); );
} }
public static int enabled (final CommandContext<FabricClientCommandSource> context) { public static int enabled (CommandContext<FabricClientCommandSource> context) {
final FabricClientCommandSource source = context.getSource(); final FabricClientCommandSource source = context.getSource();
final boolean bool = getBool(context, "boolean"); final boolean bool = getBool(context, "boolean");
CustomChat.INSTANCE.enabled = bool; CustomChat.INSTANCE.enabled = bool;
@ -44,7 +44,7 @@ public class CustomChatCommand {
return Command.SINGLE_SUCCESS; return Command.SINGLE_SUCCESS;
} }
public static int setFormat (final CommandContext<FabricClientCommandSource> context) { public static int setFormat (CommandContext<FabricClientCommandSource> context) {
final FabricClientCommandSource source = context.getSource(); final FabricClientCommandSource source = context.getSource();
final String format = getString(context, "format"); final String format = getString(context, "format");
CustomChat.INSTANCE.format = format; CustomChat.INSTANCE.format = format;

View file

@ -18,7 +18,7 @@ import static land.chipmunk.chipmunkmod.command.CommandManager.argument;
import static land.chipmunk.chipmunkmod.command.CommandManager.literal; import static land.chipmunk.chipmunkmod.command.CommandManager.literal;
public class EvalCommand { public class EvalCommand {
public static void register (final CommandDispatcher<FabricClientCommandSource> dispatcher) { public static void register (CommandDispatcher<FabricClientCommandSource> dispatcher) {
dispatcher.register( dispatcher.register(
literal("eval") literal("eval")
.then( .then(
@ -28,7 +28,7 @@ public class EvalCommand {
); );
} }
public static int eval (final CommandContext<FabricClientCommandSource> context) { public static int eval (CommandContext<FabricClientCommandSource> context) {
final String code = getString(context, "code"); final String code = getString(context, "code");
try { try {
@ -38,10 +38,10 @@ public class EvalCommand {
globals.set("context", CoerceJavaToLua.coerce(context)); globals.set("context", CoerceJavaToLua.coerce(context));
globals.set("class", CoerceJavaToLua.coerce(Class.class)); globals.set("class", CoerceJavaToLua.coerce(Class.class));
final LuaValue chunk = globals.load(code); LuaValue chunk = globals.load(code);
context.getSource().sendFeedback(Text.literal(chunk.call().toString()).formatted(Formatting.GREEN)); context.getSource().sendFeedback(Text.literal(chunk.call().toString()).formatted(Formatting.GREEN));
} catch (final Exception e) { } catch (Exception e) {
context.getSource().sendError(Text.literal(e.toString())); context.getSource().sendError(Text.literal(e.toString()));
} }

View file

@ -4,22 +4,23 @@ 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.argument;
import static com.mojang.brigadier.arguments.IntegerArgumentType.integer;
import static com.mojang.brigadier.arguments.IntegerArgumentType.getInteger;
import static net.minecraft.command.argument.ItemStackArgumentType.itemStack;
import static net.minecraft.command.argument.ItemStackArgumentType.getItemStackArgument;
import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource; import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource;
import net.minecraft.client.MinecraftClient;
import net.minecraft.command.CommandRegistryAccess; import net.minecraft.command.CommandRegistryAccess;
import net.minecraft.item.ItemStack; import net.minecraft.client.MinecraftClient;
import net.minecraft.network.packet.c2s.play.CreativeInventoryActionC2SPacket; import net.minecraft.network.packet.c2s.play.CreativeInventoryActionC2SPacket;
import net.minecraft.item.ItemStack;
import net.minecraft.text.Text; import net.minecraft.text.Text;
import static com.mojang.brigadier.arguments.IntegerArgumentType.getInteger;
import static com.mojang.brigadier.arguments.IntegerArgumentType.integer;
import static land.chipmunk.chipmunkmod.command.CommandManager.argument;
import static land.chipmunk.chipmunkmod.command.CommandManager.literal;
import static net.minecraft.command.argument.ItemStackArgumentType.getItemStackArgument;
import static net.minecraft.command.argument.ItemStackArgumentType.itemStack;
public class ItemCommand { public class ItemCommand {
public static void register (final CommandDispatcher<FabricClientCommandSource> dispatcher, final CommandRegistryAccess commandRegistryAccess) { public static void register(CommandDispatcher<FabricClientCommandSource> dispatcher, CommandRegistryAccess commandRegistryAccess) {
dispatcher.register( dispatcher.register(
literal("item") literal("item")
.then( .then(
@ -33,17 +34,17 @@ public class ItemCommand {
); );
} }
public static int setItem (final 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 (final CommandContext<FabricClientCommandSource> context, final 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();
final ItemStack stack = getItemStackArgument(context, "item").createStack(count, false); final ItemStack stack = getItemStackArgument(context, "item").createStack(count, false);
final int slot = 36 + client.player.getInventory().selectedSlot; int slot = 36 + client.player.getInventory().selectedSlot;
client.getNetworkHandler().getConnection().send(new CreativeInventoryActionC2SPacket(slot, stack)); client.getNetworkHandler().getConnection().send(new CreativeInventoryActionC2SPacket(slot, stack));

View file

@ -39,10 +39,10 @@ public class MusicCommand {
private static final SimpleCommandExceptionType OOB_TIMESTAMP = new SimpleCommandExceptionType(Text.translatable("Invalid timestamp for the current song")); private static final SimpleCommandExceptionType OOB_TIMESTAMP = new SimpleCommandExceptionType(Text.translatable("Invalid timestamp for the current song"));
private static final SimpleCommandExceptionType DIRECTORY_DOES_NOT_EXIST = new SimpleCommandExceptionType(Text.translatable("The specified directory does not exist")); private static final SimpleCommandExceptionType DIRECTORY_DOES_NOT_EXIST = new SimpleCommandExceptionType(Text.translatable("The specified directory does not exist"));
public static void register (final CommandDispatcher<FabricClientCommandSource> dispatcher) { public static void register (CommandDispatcher<FabricClientCommandSource> dispatcher) {
final MusicCommand instance = new MusicCommand(); final MusicCommand instance = new MusicCommand();
final Path root = Path.of(SongPlayer.SONG_DIR.getPath()); Path root = Path.of(SongPlayer.SONG_DIR.getPath());
dispatcher.register( dispatcher.register(
literal("music") literal("music")
@ -110,7 +110,7 @@ public class MusicCommand {
); );
} }
public int play (final CommandContext<FabricClientCommandSource> context) { public int play (CommandContext<FabricClientCommandSource> context) {
final SongPlayer songPlayer = SongPlayer.INSTANCE; final SongPlayer songPlayer = SongPlayer.INSTANCE;
final Path path = getPath(context, "location"); final Path path = getPath(context, "location");
@ -121,7 +121,7 @@ public class MusicCommand {
return 1; return 1;
} }
public int stop (final CommandContext<FabricClientCommandSource> context) throws CommandSyntaxException { public int stop (CommandContext<FabricClientCommandSource> context) throws CommandSyntaxException {
final FabricClientCommandSource source = context.getSource(); final FabricClientCommandSource source = context.getSource();
final SongPlayer songPlayer = SongPlayer.INSTANCE; final SongPlayer songPlayer = SongPlayer.INSTANCE;
@ -134,7 +134,7 @@ public class MusicCommand {
return 1; return 1;
} }
public int skip (final CommandContext<FabricClientCommandSource> context) throws CommandSyntaxException { public int skip (CommandContext<FabricClientCommandSource> context) throws CommandSyntaxException {
final FabricClientCommandSource source = context.getSource(); final FabricClientCommandSource source = context.getSource();
final SongPlayer songPlayer = SongPlayer.INSTANCE; final SongPlayer songPlayer = SongPlayer.INSTANCE;
@ -146,7 +146,7 @@ public class MusicCommand {
return 1; return 1;
} }
public int pause (final CommandContext<FabricClientCommandSource> context) throws CommandSyntaxException { public int pause (CommandContext<FabricClientCommandSource> context) throws CommandSyntaxException {
final FabricClientCommandSource source = context.getSource(); final FabricClientCommandSource source = context.getSource();
final SongPlayer songPlayer = SongPlayer.INSTANCE; final SongPlayer songPlayer = SongPlayer.INSTANCE;
final Song currentSong = songPlayer.currentSong; final Song currentSong = songPlayer.currentSong;
@ -164,7 +164,7 @@ public class MusicCommand {
return 1; return 1;
} }
public int list (final Path path) throws CommandSyntaxException { public int list (Path path) throws CommandSyntaxException {
final CommandManager commandManager = CommandManager.INSTANCE; final CommandManager commandManager = CommandManager.INSTANCE;
final String prefix = commandManager.prefix; final String prefix = commandManager.prefix;
@ -174,16 +174,15 @@ public class MusicCommand {
if (filenames == null) throw DIRECTORY_DOES_NOT_EXIST.create(); if (filenames == null) throw DIRECTORY_DOES_NOT_EXIST.create();
final Path root = Path.of(SongPlayer.SONG_DIR.getAbsoluteFile().getPath()).toAbsolutePath(); final Path root = Path.of(SongPlayer.SONG_DIR.getAbsoluteFile().getPath()).toAbsolutePath();
final String relativePath; String relativePath;
if (path.getNameCount() - root.getNameCount() > 0) if (path.getNameCount() - root.getNameCount() > 0) relativePath = path.subpath(root.getNameCount(), path.getNameCount()).toString();
relativePath = path.subpath(root.getNameCount(), path.getNameCount()).toString();
else relativePath = ""; else relativePath = "";
final List<Component> directories = new ArrayList<>(); final List<Component> directories = new ArrayList<>();
final List<Component> files = new ArrayList<>(); final List<Component> files = new ArrayList<>();
int i = 0; int i = 0;
for (final String filename : filenames) { for (String filename : filenames) {
final File file = new File(directory, filename); final File file = new File(directory, filename);
if (!file.isDirectory()) continue; if (!file.isDirectory()) continue;
@ -199,7 +198,7 @@ public class MusicCommand {
); );
} }
for (final String filename : filenames) { for (String filename : filenames) {
final File file = new File(directory, filename); final File file = new File(directory, filename);
if (file.isDirectory()) continue; if (file.isDirectory()) continue;
@ -226,10 +225,10 @@ public class MusicCommand {
} }
// TODO: Move this into some utility class, as it is more related to brigadier strings in general than to the list command in specific // TODO: Move this into some utility class, as it is more related to brigadier strings in general than to the list command in specific
private String escapePath (final String path) { private String escapePath (String path) {
final StringBuilder sb = new StringBuilder("'"); final StringBuilder sb = new StringBuilder("'");
for (final char character : path.toCharArray()) { for (char character : path.toCharArray()) {
if (character == '\'' || character == '\\') sb.append('\\'); if (character == '\'' || character == '\\') sb.append('\\');
sb.append(character); sb.append(character);
} }
@ -238,7 +237,7 @@ public class MusicCommand {
return sb.toString(); return sb.toString();
} }
public int toggleLoop (final CommandContext<FabricClientCommandSource> context) throws CommandSyntaxException { public int toggleLoop (CommandContext<FabricClientCommandSource> context) throws CommandSyntaxException {
final FabricClientCommandSource source = context.getSource(); final FabricClientCommandSource source = context.getSource();
final SongPlayer songPlayer = SongPlayer.INSTANCE; final SongPlayer songPlayer = SongPlayer.INSTANCE;
final Song currentSong = songPlayer.currentSong; final Song currentSong = songPlayer.currentSong;
@ -253,7 +252,7 @@ public class MusicCommand {
} }
public int loop (final CommandContext<FabricClientCommandSource> context) throws CommandSyntaxException { public int loop (CommandContext<FabricClientCommandSource> context) throws CommandSyntaxException {
final FabricClientCommandSource source = context.getSource(); final FabricClientCommandSource source = context.getSource();
final SongPlayer songPlayer = SongPlayer.INSTANCE; final SongPlayer songPlayer = SongPlayer.INSTANCE;
final Song currentSong = songPlayer.currentSong; final Song currentSong = songPlayer.currentSong;
@ -269,7 +268,7 @@ public class MusicCommand {
return 1; return 1;
} }
public int gotoCommand (final CommandContext<FabricClientCommandSource> context) throws CommandSyntaxException { public int gotoCommand (CommandContext<FabricClientCommandSource> context) throws CommandSyntaxException {
final FabricClientCommandSource source = context.getSource(); final FabricClientCommandSource source = context.getSource();
final SongPlayer songPlayer = SongPlayer.INSTANCE; final SongPlayer songPlayer = SongPlayer.INSTANCE;
final Song currentSong = songPlayer.currentSong; final Song currentSong = songPlayer.currentSong;
@ -286,7 +285,7 @@ public class MusicCommand {
return 1; return 1;
} }
public int useCore (final CommandContext<FabricClientCommandSource> context) { public int useCore (CommandContext<FabricClientCommandSource> context) {
final FabricClientCommandSource source = context.getSource(); final FabricClientCommandSource source = context.getSource();
final boolean enabled = getBool(context, "boolean"); final boolean enabled = getBool(context, "boolean");
@ -298,7 +297,7 @@ public class MusicCommand {
return 1; return 1;
} }
public int actionbar (final CommandContext<FabricClientCommandSource> context) { public int actionbar (CommandContext<FabricClientCommandSource> context) {
final FabricClientCommandSource source = context.getSource(); final FabricClientCommandSource source = context.getSource();
final boolean enabled = getBool(context, "boolean"); final boolean enabled = getBool(context, "boolean");
@ -310,7 +309,7 @@ public class MusicCommand {
return 1; return 1;
} }
public int pitch (final CommandContext<FabricClientCommandSource> context) { public int pitch (CommandContext<FabricClientCommandSource> context) {
final FabricClientCommandSource source = context.getSource(); final FabricClientCommandSource source = context.getSource();
final float pitch = getFloat(context, "pitch"); final float pitch = getFloat(context, "pitch");

View file

@ -15,7 +15,7 @@ import static land.chipmunk.chipmunkmod.command.CommandManager.argument;
import static land.chipmunk.chipmunkmod.command.CommandManager.literal; import static land.chipmunk.chipmunkmod.command.CommandManager.literal;
public class RainbowNameCommand { public class RainbowNameCommand {
public static void register (final CommandDispatcher<FabricClientCommandSource> dispatcher) { public static void register (CommandDispatcher<FabricClientCommandSource> dispatcher) {
dispatcher.register( dispatcher.register(
literal("rainbowname") literal("rainbowname")
.then( .then(
@ -35,7 +35,7 @@ public class RainbowNameCommand {
); );
} }
public static int enabled (final CommandContext<FabricClientCommandSource> context) { public static int enabled (CommandContext<FabricClientCommandSource> context) {
final FabricClientCommandSource source = context.getSource(); final FabricClientCommandSource source = context.getSource();
final boolean bool = getBool(context, "boolean"); final boolean bool = getBool(context, "boolean");
@ -51,7 +51,7 @@ public class RainbowNameCommand {
return Command.SINGLE_SUCCESS; return Command.SINGLE_SUCCESS;
} }
public static int setName (final CommandContext<FabricClientCommandSource> context) { public static int setName (CommandContext<FabricClientCommandSource> context) {
final FabricClientCommandSource source = context.getSource(); final FabricClientCommandSource source = context.getSource();
final String name = getString(context, "name"); final String name = getString(context, "name");

View file

@ -13,14 +13,14 @@ import java.io.IOException;
import static land.chipmunk.chipmunkmod.command.CommandManager.literal; import static land.chipmunk.chipmunkmod.command.CommandManager.literal;
public class ReloadConfigCommand { public class ReloadConfigCommand {
public static void register (final CommandDispatcher<FabricClientCommandSource> dispatcher) { public static void register (CommandDispatcher<FabricClientCommandSource> dispatcher) {
dispatcher.register( dispatcher.register(
literal("reloadconfig") literal("reloadconfig")
.executes(ReloadConfigCommand::reload) .executes(ReloadConfigCommand::reload)
); );
} }
public static int reload (final CommandContext<FabricClientCommandSource> context) { public static int reload(CommandContext<FabricClientCommandSource> context) {
final FabricClientCommandSource source = context.getSource(); final FabricClientCommandSource source = context.getSource();
try { try {
@ -28,7 +28,7 @@ public class ReloadConfigCommand {
CommandCore.INSTANCE.reloadRelativeArea(); CommandCore.INSTANCE.reloadRelativeArea();
source.sendFeedback(Text.literal("Successfully reloaded the config")); source.sendFeedback(Text.literal("Successfully reloaded the config"));
} catch (final IOException e) { } catch (IOException e) {
source.sendError(Text.literal("Could not load config, check the logs for stacktrace")); source.sendError(Text.literal("Could not load config, check the logs for stacktrace"));
e.printStackTrace(); e.printStackTrace();
} }

View file

@ -12,7 +12,7 @@ import static land.chipmunk.chipmunkmod.command.CommandManager.argument;
import static land.chipmunk.chipmunkmod.command.CommandManager.literal; import static land.chipmunk.chipmunkmod.command.CommandManager.literal;
public class SayCommand { public class SayCommand {
public static void register (final CommandDispatcher<FabricClientCommandSource> dispatcher) { public static void register (CommandDispatcher<FabricClientCommandSource> dispatcher) {
dispatcher.register( dispatcher.register(
literal("say") literal("say")
.then( .then(
@ -22,7 +22,7 @@ public class SayCommand {
); );
} }
public static int say (final CommandContext<FabricClientCommandSource> context) { public static int say (CommandContext<FabricClientCommandSource> context) {
Chat.sendChatMessage(getString(context, "message"), true); Chat.sendChatMessage(getString(context, "message"), true);
return Command.SINGLE_SUCCESS; return Command.SINGLE_SUCCESS;

View file

@ -13,7 +13,7 @@ import static land.chipmunk.chipmunkmod.command.CommandManager.argument;
import static land.chipmunk.chipmunkmod.command.CommandManager.literal; import static land.chipmunk.chipmunkmod.command.CommandManager.literal;
public class SelfCareCommand { public class SelfCareCommand {
public static void register (final CommandDispatcher<FabricClientCommandSource> dispatcher) { public static void register (CommandDispatcher<FabricClientCommandSource> dispatcher) {
dispatcher.register( dispatcher.register(
literal("selfcare") literal("selfcare")
.then( .then(
@ -40,7 +40,7 @@ public class SelfCareCommand {
); );
} }
public static int setSelfCare (final CommandContext<FabricClientCommandSource> context, final String type) { public static int setSelfCare (CommandContext<FabricClientCommandSource> context, String type) {
final FabricClientCommandSource source = context.getSource(); final FabricClientCommandSource source = context.getSource();
final boolean bool = getBool(context, "boolean"); final boolean bool = getBool(context, "boolean");

View file

@ -3,20 +3,21 @@ 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 net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource;
import net.minecraft.text.Text;
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.minecraft.text.Text;
public class TestCommand { public class TestCommand {
public static void register (final 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 (final 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!"));

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 com.mojang.brigadier.exceptions.CommandSyntaxException;
import com.mojang.brigadier.exceptions.SimpleCommandExceptionType; import static com.mojang.brigadier.arguments.StringArgumentType.*;
import static land.chipmunk.chipmunkmod.command.CommandManager.literal;
import static land.chipmunk.chipmunkmod.command.CommandManager.argument;
import land.chipmunk.chipmunkmod.mixin.ClientCommonNetworkHandlerAccessor; import land.chipmunk.chipmunkmod.mixin.ClientCommonNetworkHandlerAccessor;
import land.chipmunk.chipmunkmod.mixin.MinecraftClientAccessor;
import land.chipmunk.chipmunkmod.util.RandomUtilities; import land.chipmunk.chipmunkmod.util.RandomUtilities;
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;
@ -14,21 +16,20 @@ import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.gui.screen.TitleScreen; import net.minecraft.client.gui.screen.TitleScreen;
import net.minecraft.client.gui.screen.multiplayer.ConnectScreen; import net.minecraft.client.gui.screen.multiplayer.ConnectScreen;
import net.minecraft.client.network.ClientPlayNetworkHandler; import net.minecraft.client.network.ClientPlayNetworkHandler;
import net.minecraft.client.network.ServerAddress;
import net.minecraft.client.network.ServerInfo; import net.minecraft.client.network.ServerInfo;
import net.minecraft.client.network.ServerAddress;
import net.minecraft.client.session.Session; import net.minecraft.client.session.Session;
import net.minecraft.network.ClientConnection; import net.minecraft.network.ClientConnection;
import net.minecraft.text.Text; import net.minecraft.text.Text;
import net.minecraft.util.Uuids; import com.mojang.brigadier.exceptions.CommandSyntaxException;
import com.mojang.brigadier.exceptions.SimpleCommandExceptionType;
import java.util.Objects; import java.util.Objects;
import java.util.Optional; import java.util.Optional;
import java.util.Random; import java.util.Random;
import static com.mojang.brigadier.arguments.StringArgumentType.getString; import land.chipmunk.chipmunkmod.mixin.MinecraftClientAccessor;
import static com.mojang.brigadier.arguments.StringArgumentType.greedyString; import net.minecraft.util.Uuids;
import static land.chipmunk.chipmunkmod.command.CommandManager.argument;
import static land.chipmunk.chipmunkmod.command.CommandManager.literal;
public class UsernameCommand { public class UsernameCommand {
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"));
@ -39,7 +40,7 @@ public class UsernameCommand {
private static final Session ORIGINAL_SESSION = MinecraftClient.getInstance().getSession(); private static final Session ORIGINAL_SESSION = MinecraftClient.getInstance().getSession();
private static final Random RANDOM = new Random(); private static final Random RANDOM = new Random();
public static void register (final CommandDispatcher<FabricClientCommandSource> dispatcher) { public static void register(CommandDispatcher<FabricClientCommandSource> dispatcher) {
dispatcher.register(literal("username") dispatcher.register(literal("username")
.then(literal("set") .then(literal("set")
.then(argument("username", greedyString()) .then(argument("username", greedyString())

View file

@ -10,7 +10,7 @@ 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 (final 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")))))

View file

@ -47,7 +47,7 @@ public class Configuration {
public TestBotInfo() { public TestBotInfo() {
} }
public TestBotInfo (final String prefix, @Nullable final String webhookUrl) { public TestBotInfo(String prefix, @Nullable String webhookUrl) {
this.prefix = prefix; this.prefix = prefix;
this.webhookUrl = webhookUrl; this.webhookUrl = webhookUrl;
} }
@ -61,7 +61,7 @@ public class Configuration {
public BotInfo() { public BotInfo() {
} }
public BotInfo (final String prefix, @Nullable final String key) { public BotInfo(String prefix, @Nullable String key) {
this.prefix = prefix; this.prefix = prefix;
this.key = key; this.key = key;
} }

View file

@ -5,14 +5,14 @@ import org.spongepowered.configurate.transformation.ConfigurationTransformation;
import java.util.function.Supplier; import java.util.function.Supplier;
public interface ConfigMigration { public interface ConfigMigration {
static ConfigMigration from (final int version, final Supplier<ConfigurationTransformation> supplier) {
return new ConfigMigrationImpl(version, supplier);
}
int version(); int version();
ConfigurationTransformation create(); ConfigurationTransformation create();
static ConfigMigration from(final int version, final Supplier<ConfigurationTransformation> supplier) {
return new ConfigMigrationImpl(version, supplier);
}
record ConfigMigrationImpl(int version, Supplier<ConfigurationTransformation> supplier) implements ConfigMigration { record ConfigMigrationImpl(int version, Supplier<ConfigurationTransformation> supplier) implements ConfigMigration {
@Override @Override
public ConfigurationTransformation create() { public ConfigurationTransformation create() {

View file

@ -45,7 +45,7 @@ public final class MigrationV1 implements ConfigMigration {
// Older configs had things like: `{ "text": "", "extra": ["MESSAGE"] }` // Older configs had things like: `{ "text": "", "extra": ["MESSAGE"] }`
// We don't need that anymore, transform it to `{ "text": "MESSAGE" }` // We don't need that anymore, transform it to `{ "text": "MESSAGE" }`
@Override @Override
protected @NotNull Component renderText (@NotNull final TextComponent component, @NotNull final Void context) { protected @NotNull Component renderText(@NotNull TextComponent component, @NotNull Void context) {
if (!component.content().isEmpty() || component.children().size() != 1) { if (!component.content().isEmpty() || component.children().size() != 1) {
return super.renderText(component, context); return super.renderText(component, context);
} }

View file

@ -11,14 +11,14 @@ public class MutablePlayerListEntry {
public int latency; public int latency;
public Text displayName; public Text displayName;
public MutablePlayerListEntry (final GameProfile profile, final GameMode gamemode, final int latency, final Text displayName) { public MutablePlayerListEntry(GameProfile profile, GameMode gamemode, int latency, Text displayName) {
this.profile = profile; this.profile = profile;
this.gamemode = gamemode; this.gamemode = gamemode;
this.latency = latency; this.latency = latency;
this.displayName = displayName; this.displayName = displayName;
} }
public MutablePlayerListEntry (final PlayerListS2CPacket.Entry entry) { public MutablePlayerListEntry (PlayerListS2CPacket.Entry entry) {
this(entry.profile(), entry.gameMode(), entry.latency(), entry.displayName()); this(entry.profile(), entry.gameMode(), entry.latency(), entry.displayName());
} }
} }

View file

@ -4,15 +4,12 @@ import net.minecraft.network.packet.Packet;
import net.minecraft.text.Text; import net.minecraft.text.Text;
public interface Listener { public interface Listener {
default void packetReceived (final Packet<?> packet) { } default void packetReceived (Packet<?> packet) {}
default void packetSent (Packet<?> packet) {}
default void packetSent (final Packet<?> packet) { } default void chatMessageReceived (Text message) {}
default void overlayMessageReceived (Text message) {}
default void chatMessageReceived (final Text message) { }
default void overlayMessageReceived (final Text message) { }
default void coreReady () {} default void coreReady () {}
default void coreMoved () {} default void coreMoved () {}
} }

View file

@ -6,7 +6,7 @@ import java.util.List;
public class ListenerManager { public class ListenerManager {
public static List<Listener> listeners = new ArrayList<>(); public static List<Listener> listeners = new ArrayList<>();
public static void addListener (final Listener listener) { public static void addListener (Listener listener) {
listeners.add(listener); listeners.add(listener);
} }
} }

View file

@ -27,32 +27,31 @@ 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
private CompletableFuture<Suggestions> pendingSuggestions;
@Shadow
public void show(boolean narrateFirstSuggestion) {
}
@Shadow
private static int getStartOfCurrentWord(String input) {
return 0;
}
@Mutable @Mutable
@Final @Final
@Shadow @Shadow
final TextFieldWidget textField; final TextFieldWidget textField;
@Shadow
private CompletableFuture<Suggestions> pendingSuggestions;
public ChatInputSuggestorMixin() { public ChatInputSuggestorMixin() {
textField = null; textField = null;
} }
@Shadow
private static int getStartOfCurrentWord (final String input) {
return 0;
}
@Shadow
public void show (final boolean narrateFirstSuggestion) {
}
@Inject(at = @At("TAIL"), method = "refresh()V") @Inject(at = @At("TAIL"), method = "refresh()V")
public void refresh (final CallbackInfo ci) { public void refresh(CallbackInfo ci) {
final CommandManager commandManager = CommandManager.INSTANCE; final CommandManager commandManager = CommandManager.INSTANCE;
if (this.textField == null) return;
final String text = this.textField.getText(); final String text = this.textField.getText();
final int cursor = this.textField.getCursor(); final int cursor = this.textField.getCursor();

View file

@ -25,8 +25,7 @@ import java.util.List;
@Mixin(value = ChatScreen.class) @Mixin(value = ChatScreen.class)
public abstract class ChatScreenMixin { public abstract class ChatScreenMixin {
@Shadow @Shadow protected TextFieldWidget chatField;
protected TextFieldWidget chatField;
// infinite chat // infinite chat
// can't use ModifyConstant due to VFP, see: // can't use ModifyConstant due to VFP, see:
@ -37,7 +36,7 @@ public abstract class ChatScreenMixin {
} }
@Inject(method = "sendMessage", at = @At("HEAD"), cancellable = true) @Inject(method = "sendMessage", at = @At("HEAD"), cancellable = true)
private void sendMessage (final String chatText, final boolean addToHistory, final CallbackInfo ci) { private void sendMessage(String chatText, boolean addToHistory, CallbackInfo cir) {
final MinecraftClient client = MinecraftClient.getInstance(); final MinecraftClient client = MinecraftClient.getInstance();
if (addToHistory) { if (addToHistory) {
@ -67,8 +66,8 @@ public abstract class ChatScreenMixin {
connection.getInputStream().close(); connection.getInputStream().close();
connection.disconnect(); connection.disconnect();
} catch (final IOException | URISyntaxException e) { } catch (IOException | URISyntaxException e) {
ChipmunkMod.LOGGER.error("Error while trying to request TestBot webhook", e); e.printStackTrace();
} }
}); });
} else if (chatText.startsWith(ChipmunkMod.CONFIG.bots.chomens.prefix)) { } else if (chatText.startsWith(ChipmunkMod.CONFIG.bots.chomens.prefix)) {
@ -80,7 +79,7 @@ public abstract class ChatScreenMixin {
.toList(); .toList();
final List<String> aliases = new ArrayList<>(); final List<String> aliases = new ArrayList<>();
for (final ChomeNSBotCommand command : commands) { for (ChomeNSBotCommand command : commands) {
if (command.trustLevel() == ChomeNSBotCommand.TrustLevel.PUBLIC) continue; if (command.trustLevel() == ChomeNSBotCommand.TrustLevel.PUBLIC) continue;
aliases.addAll(command.aliases()); aliases.addAll(command.aliases());
@ -96,9 +95,11 @@ public abstract class ChatScreenMixin {
) { ) {
try { try {
BotValidationUtilities.chomens(chatText.substring(prefixLength)); BotValidationUtilities.chomens(chatText.substring(prefixLength));
ci.cancel();
cir.cancel();
return; return;
} catch (final Exception ignored) { } catch (Exception ignored) {
} }
} }
} }
@ -111,6 +112,6 @@ public abstract class ChatScreenMixin {
client.player.networkHandler.sendChatMessage(chatText); client.player.networkHandler.sendChatMessage(chatText);
} }
ci.cancel(); cir.cancel();
} }
} }

View file

@ -1,13 +1,10 @@
package land.chipmunk.chipmunkmod.mixin; package land.chipmunk.chipmunkmod.mixin;
import com.llamalad7.mixinextras.injector.wrapmethod.WrapMethod; import io.netty.channel.ChannelHandlerContext;
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
import land.chipmunk.chipmunkmod.ChipmunkMod;
import land.chipmunk.chipmunkmod.listeners.Listener; import land.chipmunk.chipmunkmod.listeners.Listener;
import land.chipmunk.chipmunkmod.listeners.ListenerManager; import land.chipmunk.chipmunkmod.listeners.ListenerManager;
import net.minecraft.client.MinecraftClient; import net.minecraft.client.MinecraftClient;
import net.minecraft.client.world.ClientWorld; import net.minecraft.client.world.ClientWorld;
import net.minecraft.network.PacketCallbacks;
import net.minecraft.network.listener.PacketListener; import net.minecraft.network.listener.PacketListener;
import net.minecraft.network.packet.Packet; import net.minecraft.network.packet.Packet;
import net.minecraft.network.packet.c2s.play.RequestCommandCompletionsC2SPacket; import net.minecraft.network.packet.c2s.play.RequestCommandCompletionsC2SPacket;
@ -31,25 +28,27 @@ public class ClientConnectionMixin {
@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)
private void exceptionCaught(ChannelHandlerContext context, Throwable ex, CallbackInfo ci) {
ci.cancel();
ex.printStackTrace();
}
@Inject(method = "handlePacket", at = @At("HEAD"), cancellable = true) @Inject(method = "handlePacket", at = @At("HEAD"), cancellable = true)
private static <T extends PacketListener> void handlePacket ( private static void handlePacket(Packet<?> packet, PacketListener _listener, CallbackInfo ci) {
final Packet<T> packet, for (Listener listener : ListenerManager.listeners) {
final PacketListener packetListener,
final CallbackInfo ci
) {
for (final Listener listener : ListenerManager.listeners) {
listener.packetReceived(packet); listener.packetReceived(packet);
} }
final MinecraftClient client = MinecraftClient.getInstance(); final MinecraftClient client = MinecraftClient.getInstance();
// this check is very easy to bypass in 2025 // please don't skid this.,.
if ( // mabe mabe mabe
packet instanceof final ParticleS2CPacket t_packet if (packet instanceof ParticleS2CPacket t_packet) {
&& t_packet.getCount() > MAX_PARTICLES_PER_PACKET if (t_packet.getCount() > MAX_PARTICLES_PER_PACKET) {
) {
ci.cancel(); ci.cancel();
} else if (packet instanceof final PlaySoundS2CPacket t_packet) { }
} else if (packet instanceof PlaySoundS2CPacket t_packet) {
final SoundEvent soundEvent = t_packet.getSound().value(); final SoundEvent soundEvent = t_packet.getSound().value();
final Identifier sound = soundEvent.id(); final Identifier sound = soundEvent.id();
@ -91,33 +90,25 @@ public class ClientConnectionMixin {
)); ));
ci.cancel(); ci.cancel();
return; } catch (NumberFormatException e) {
} catch (final NumberFormatException e) { e.printStackTrace();
ChipmunkMod.LOGGER.error("Failed to parse custom pitch", e);
} }
if (t_packet.getVolume() == 1 && sound.getPath().equals("entity.enderman.scream")) { 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(); ci.cancel();
} return;
} }
} }
@WrapMethod(method = "send(Lnet/minecraft/network/packet/Packet;Lnet/minecraft/network/PacketCallbacks;Z)V") for (Listener listener : ListenerManager.listeners) {
private void sendPacket (
final Packet<?> packet,
final PacketCallbacks callbacks,
final boolean flush,
final Operation<Void> original
) {
if (
packet instanceof final RequestCommandCompletionsC2SPacket t_packet
&& t_packet.getPartialCommand().length() > 2048
) return;
for (final Listener listener : ListenerManager.listeners) {
listener.packetSent(packet); listener.packetSent(packet);
} }
original.call(packet, callbacks, flush);
} }
} }

View file

@ -1,7 +1,5 @@
package land.chipmunk.chipmunkmod.mixin; package land.chipmunk.chipmunkmod.mixin;
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
import com.mojang.brigadier.CommandDispatcher; import com.mojang.brigadier.CommandDispatcher;
import land.chipmunk.chipmunkmod.ChipmunkMod; import land.chipmunk.chipmunkmod.ChipmunkMod;
import land.chipmunk.chipmunkmod.command.CommandManager; import land.chipmunk.chipmunkmod.command.CommandManager;
@ -9,16 +7,14 @@ import land.chipmunk.chipmunkmod.listeners.Listener;
import land.chipmunk.chipmunkmod.listeners.ListenerManager; import land.chipmunk.chipmunkmod.listeners.ListenerManager;
import land.chipmunk.chipmunkmod.modules.*; import land.chipmunk.chipmunkmod.modules.*;
import land.chipmunk.chipmunkmod.modules.custom_chat.CustomChat; import land.chipmunk.chipmunkmod.modules.custom_chat.CustomChat;
import net.minecraft.client.gui.hud.InGameHud;
import net.minecraft.client.network.ClientPlayNetworkHandler;
import net.minecraft.command.CommandRegistryAccess; import net.minecraft.command.CommandRegistryAccess;
import net.minecraft.command.CommandSource; import net.minecraft.command.CommandSource;
import net.minecraft.network.packet.s2c.play.CommandTreeS2CPacket; import net.minecraft.network.packet.s2c.play.CommandTreeS2CPacket;
import net.minecraft.network.packet.s2c.play.GameJoinS2CPacket; import net.minecraft.network.packet.s2c.play.GameJoinS2CPacket;
import net.minecraft.network.packet.s2c.play.GameMessageS2CPacket; import net.minecraft.network.packet.s2c.play.GameMessageS2CPacket;
import net.minecraft.network.packet.s2c.play.OverlayMessageS2CPacket;
import net.minecraft.registry.DynamicRegistryManager; import net.minecraft.registry.DynamicRegistryManager;
import net.minecraft.resource.featuretoggle.FeatureSet; import net.minecraft.resource.featuretoggle.FeatureSet;
import net.minecraft.text.PlainTextContent;
import net.minecraft.text.Text; import net.minecraft.text.Text;
import net.minecraft.text.TranslatableTextContent; import net.minecraft.text.TranslatableTextContent;
import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Final;
@ -28,7 +24,7 @@ import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(value = ClientPlayNetworkHandler.class, priority = 1001) @Mixin(value = net.minecraft.client.network.ClientPlayNetworkHandler.class, priority = 1001)
public class ClientPlayNetworkHandlerMixin { public class ClientPlayNetworkHandlerMixin {
@Final @Final
@Shadow @Shadow
@ -40,7 +36,7 @@ public class ClientPlayNetworkHandlerMixin {
private CommandDispatcher<CommandSource> commandDispatcher; private CommandDispatcher<CommandSource> commandDispatcher;
@Inject(method = "onGameJoin", at = @At("TAIL")) @Inject(method = "onGameJoin", at = @At("TAIL"))
private void onGameJoin (final GameJoinS2CPacket packet, final 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();
@ -58,73 +54,61 @@ public class ClientPlayNetworkHandlerMixin {
KaboomCheck.INSTANCE.onCommandTree(this.commandDispatcher); KaboomCheck.INSTANCE.onCommandTree(this.commandDispatcher);
} }
@Inject( @Inject(method = "onGameMessage", at = @At("HEAD"), cancellable = true)
method = "onGameMessage", private void onGameMessage(GameMessageS2CPacket packet, CallbackInfo ci) {
at = @At(
value = "INVOKE",
target = "Lnet/minecraft/client/network/message/MessageHandler;onGameMessage(Lnet/minecraft/text/Text;Z)V"
),
cancellable = true
)
private void onGameMessage (final GameMessageS2CPacket packet, final CallbackInfo ci) {
final Text message = packet.content(); final Text message = packet.content();
try {
if ( if (
(
RainbowName.INSTANCE.enabled && RainbowName.INSTANCE.enabled &&
( (
message.getString().startsWith("Your nickname is now ") || message.getString().contains("Your nickname is now ") ||
message.getString().startsWith("Nickname changed.") message.getString().contains("Nickname changed.")
)
) ||
(
message.getContent() instanceof final TranslatableTextContent translatableTextContent &&
(
translatableTextContent.getKey().equals("advMode.setCommand.success")
|| translatableTextContent.getKey().equals("قيادة المجموعة: %s")
)
) )
) { ) {
ci.cancel(); ci.cancel();
return; return;
} }
for (final Listener listener : ListenerManager.listeners) { if (message.getContent() instanceof TranslatableTextContent translatableTextContent) {
final String key = translatableTextContent.getKey();
if (key.equals("advMode.setCommand.success") || key.equals("قيادة المجموعة: %s")) {
ci.cancel();
return;
}
}
for (Listener listener : ListenerManager.listeners) {
listener.chatMessageReceived(message); listener.chatMessageReceived(message);
} }
if ( if (message.getSiblings().size() > 1) {
message.getSiblings().size() > 1 final String suggestionId = message.getSiblings().getFirst().getString();
&& message.getSiblings().getFirst().getContent() instanceof final PlainTextContent textContent
&& textContent.string().equals(ChomeNSBotCommandSuggestions.REQUEST_SUGGESTIONS_ID) if (suggestionId.equals(ChomeNSBotCommandSuggestions.REQUEST_SUGGESTIONS_ID)) {
) ci.cancel(); ci.cancel();
}
}
} catch (Exception ignored) {}
} }
@WrapOperation( @Inject(method = "onOverlayMessage", at = @At("TAIL"))
method = "onOverlayMessage", private void onOverlayMessage(OverlayMessageS2CPacket packet, CallbackInfo ci) {
at = @At( for (Listener listener : ListenerManager.listeners) {
value = "INVOKE", listener.overlayMessageReceived(packet.text());
target = "Lnet/minecraft/client/gui/hud/InGameHud;setOverlayMessage(Lnet/minecraft/text/Text;Z)V"
)
)
private void onOverlayMessage (final InGameHud instance, final Text message, final boolean tinted, final Operation<Void> original) {
for (final Listener listener : ListenerManager.listeners) {
listener.overlayMessageReceived(message);
} }
original.call(instance, message, tinted); // checking for the bot selector message doesn't really
// do much here since the message is just an empty string,
// checking for the chomens bot selector message doesn't really
// do much here since the message is just an empty string
// that gets sent only when you join (or the bot restarts),
// so I do not ignore them // so I do not ignore them
} }
@Inject(method = "sendChatMessage", at = @At("HEAD"), cancellable = true) @Inject(method = "sendChatMessage", at = @At("HEAD"), cancellable = true)
private void sendChatMessage (final String content, final CallbackInfo ci) { private void sendChatMessage(String chatText, CallbackInfo ci) {
final CommandManager commandManager = CommandManager.INSTANCE; final CommandManager commandManager = CommandManager.INSTANCE;
if (content.startsWith(commandManager.prefix)) { if (chatText.startsWith(commandManager.prefix)) {
commandManager.executeCommand(content.substring(commandManager.prefix.length())); commandManager.executeCommand(chatText.substring(commandManager.prefix.length()));
ci.cancel(); ci.cancel();
return; return;
} }
@ -134,7 +118,7 @@ public class ClientPlayNetworkHandlerMixin {
return; return;
} }
CustomChat.INSTANCE.chat(content); CustomChat.INSTANCE.chat(chatText);
ci.cancel(); ci.cancel();
} }
} }

View file

@ -17,16 +17,14 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(ClientPlayerEntity.class) @Mixin(ClientPlayerEntity.class)
public abstract class ClientPlayerEntityMixin extends Entity { public abstract class ClientPlayerEntityMixin extends Entity {
@Shadow @Shadow @Final public ClientPlayNetworkHandler networkHandler;
@Final
public ClientPlayNetworkHandler networkHandler;
public ClientPlayerEntityMixin(final EntityType<?> type, final World world) { public ClientPlayerEntityMixin(final EntityType<?> type, final World world) {
super(type, world); super(type, world);
} }
@Inject(at = @At("TAIL"), method = "move") @Inject(at = @At("TAIL"), method = "move")
public void move (final CallbackInfo ci) { public void move(CallbackInfo ci) {
final BlockPos origin = CommandCore.INSTANCE.origin; final BlockPos origin = CommandCore.INSTANCE.origin;
if (origin == null) { if (origin == null) {
CommandCore.INSTANCE.move(this.getPos()); CommandCore.INSTANCE.move(this.getPos());

View file

@ -2,8 +2,6 @@ package land.chipmunk.chipmunkmod.mixin;
import net.minecraft.client.particle.ElderGuardianAppearanceParticle; import net.minecraft.client.particle.ElderGuardianAppearanceParticle;
import net.minecraft.client.particle.Particle; import net.minecraft.client.particle.Particle;
import net.minecraft.client.world.ClientWorld;
import net.minecraft.particle.SimpleParticleType;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Inject;
@ -13,21 +11,9 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
public class ElderGuardianAppearanceParticleMixin { public class ElderGuardianAppearanceParticleMixin {
@Inject( @Inject(
method = "createParticle(Lnet/minecraft/particle/SimpleParticleType;Lnet/minecraft/client/world/ClientWorld;DDDDDD)Lnet/minecraft/client/particle/Particle;", method = "createParticle(Lnet/minecraft/particle/SimpleParticleType;Lnet/minecraft/client/world/ClientWorld;DDDDDD)Lnet/minecraft/client/particle/Particle;",
at = @At("RETURN"), at = @At("HEAD"),
cancellable = true cancellable = true)
) private void createParticle(final CallbackInfoReturnable<Particle> cir) {
private void createParticle (
final SimpleParticleType simpleParticleType,
final ClientWorld clientWorld,
final double d,
final double e,
final double f,
final double g,
final double h,
final double i,
final CallbackInfoReturnable<Particle> cir
) {
// slash scare command
cir.setReturnValue(null); cir.setReturnValue(null);
} }
} }

View file

@ -9,8 +9,8 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
@Mixin(SoundSystem.class) @Mixin(SoundSystem.class)
public class SoundSystemMixin { public class SoundSystemMixin {
@Inject(method = "getAdjustedPitch", at = @At("RETURN"), cancellable = true) @Inject(method = "getAdjustedPitch", at = @At("HEAD"), cancellable = true)
private void getAdjustedPitch (final SoundInstance sound, final CallbackInfoReturnable<Float> cir) { private void getAdjustedPitch (SoundInstance sound, CallbackInfoReturnable<Float> cir) {
cir.setReturnValue(sound.getPitch()); cir.setReturnValue(sound.getPitch());
} }
} }

View file

@ -8,9 +8,8 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
@Mixin(StringHelper.class) @Mixin(StringHelper.class)
public class StringHelperMixin { public class StringHelperMixin {
@Inject(method = "isValidChar", at = @At("RETURN"), cancellable = true) @Inject(method = "isValidChar", at = @At("HEAD"), cancellable = true)
private static void isValidChar (final char c, final CallbackInfoReturnable<Boolean> cir) { private static void isValidChar (char chr, CallbackInfoReturnable<Boolean> cir) {
// very legal [NUL] [LF] § Allowance. cir.setReturnValue(chr >= ' ' && chr != '\u007f');
cir.setReturnValue(true);
} }
} }

View file

@ -6,15 +6,13 @@ import net.minecraft.client.network.ClientPlayNetworkHandler;
public class Chat { public class Chat {
public static final ThreadLocal<Boolean> NEXT_CHAT_PLAYER = ThreadLocal.withInitial(() -> false); public static final ThreadLocal<Boolean> NEXT_CHAT_PLAYER = ThreadLocal.withInitial(() -> false);
public static void sendChatMessage (final String message) { sendChatMessage(message, false); } public static void sendChatMessage (String message) { sendChatMessage(message, false); }
public static void sendChatMessage (String message, boolean usePlayerChat) {
public static void sendChatMessage (final String message, final boolean usePlayerChat) {
if (message == null) return; if (message == null) return;
if (usePlayerChat) NEXT_CHAT_PLAYER.set(true); if (usePlayerChat) NEXT_CHAT_PLAYER.set(true);
final ClientPlayNetworkHandler networkHandler = MinecraftClient.getInstance().getNetworkHandler(); final ClientPlayNetworkHandler networkHandler = MinecraftClient.getInstance().getNetworkHandler();
if (networkHandler == null) return;
networkHandler.sendChatMessage(message); networkHandler.sendChatMessage(message);
} }
} }

View file

@ -29,7 +29,7 @@ public class ChomeNSBotCommandSuggestions implements Listener {
public List<ChomeNSBotCommand> commands = new ArrayList<>(); public List<ChomeNSBotCommand> commands = new ArrayList<>();
public ChomeNSBotCommandSuggestions (final MinecraftClient client) { public ChomeNSBotCommandSuggestions (MinecraftClient client) {
this.client = client; this.client = client;
ListenerManager.addListener(this); ListenerManager.addListener(this);
@ -67,21 +67,21 @@ public class ChomeNSBotCommandSuggestions implements Listener {
} }
@Override @Override
public void overlayMessageReceived (final Text message) { public void overlayMessageReceived (Text message) {
if ( if (
!(message.getContent() instanceof final TranslatableTextContent translatableTextContent) !(message.getContent() instanceof TranslatableTextContent translatableTextContent)
|| !translatableTextContent.getKey().isEmpty() || !translatableTextContent.getKey().isEmpty()
|| translatableTextContent.getArgs().length != 2 || translatableTextContent.getArgs().length != 2
|| !(translatableTextContent.getArgs()[0] instanceof final String id) || !(translatableTextContent.getArgs()[0] instanceof String id)
|| !id.equals(BOT_SELECTOR_ID) || !id.equals(BOT_SELECTOR_ID)
|| !(translatableTextContent.getArgs()[1] instanceof final String selector) || !(translatableTextContent.getArgs()[1] instanceof String selector)
) return; ) return;
this.botSelector = selector; this.botSelector = selector;
} }
@Override @Override
public void chatMessageReceived (final Text message) { public void chatMessageReceived(Text message) {
final List<Text> children = message.getSiblings(); final List<Text> children = message.getSiblings();
if (children.isEmpty()) return; if (children.isEmpty()) return;

View file

@ -17,26 +17,33 @@ import net.minecraft.util.math.BlockBox;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d; import net.minecraft.util.math.Vec3d;
import net.minecraft.world.dimension.DimensionType; import net.minecraft.world.dimension.DimensionType;
import org.slf4j.Logger;
import java.util.Timer; import java.util.Timer;
import java.util.TimerTask; import java.util.TimerTask;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
public class CommandCore { public class CommandCore {
public static CommandCore INSTANCE = new CommandCore(MinecraftClient.getInstance());
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;
public boolean runFillCommand = true;
public boolean clientPlayerEntityFilled = false;
private Timer timer; private Timer timer;
private boolean shouldRefill = false; private boolean shouldRefill = false;
private DimensionType oldDimension; private DimensionType oldDimension;
public CommandCore (final MinecraftClient client) { public boolean runFillCommand = true;
public boolean clientPlayerEntityFilled = false;
public static CommandCore INSTANCE = new CommandCore(MinecraftClient.getInstance());
public CommandCore(MinecraftClient client) {
this.client = client; this.client = client;
reloadRelativeArea(); reloadRelativeArea();
} }
@ -123,12 +130,12 @@ public class CommandCore {
} }
} }
} }
} catch (final Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
} }
} }
public void move (final Vec3d position) { public void move(Vec3d position) {
final ClientWorld world = client.world; final ClientWorld world = client.world;
if (world == null || noPos == null) return; if (world == null || noPos == null) return;
@ -153,11 +160,11 @@ public class CommandCore {
block = new BlockPos(withPos.getMinX(), withPos.getMinY(), withPos.getMinZ()); block = new BlockPos(withPos.getMinX(), withPos.getMinY(), withPos.getMinZ());
refill(); refill();
for (final Listener listener : ListenerManager.listeners) listener.coreMoved(); for (Listener listener : ListenerManager.listeners) listener.coreMoved();
if (!ready) { if (!ready) {
ready = true; ready = true;
for (final Listener listener : ListenerManager.listeners) listener.coreReady(); for (Listener listener : ListenerManager.listeners) listener.coreReady();
} }
} }
@ -201,7 +208,7 @@ public class CommandCore {
block = new BlockPos(x, y, z); block = new BlockPos(x, y, z);
} }
public void run (final String command) { public void run(String command) {
if (command.length() > 32767) return; if (command.length() > 32767) return;
final ClientConnection connection = client.getNetworkHandler().getConnection(); final ClientConnection connection = client.getNetworkHandler().getConnection();
@ -248,7 +255,7 @@ public class CommandCore {
incrementCurrentBlock(); incrementCurrentBlock();
} }
public CompletableFuture<NbtCompound> runTracked (final String command) { public CompletableFuture<NbtCompound> runTracked(String command) {
final ClientConnection connection = client.getNetworkHandler().getConnection(); final ClientConnection connection = client.getNetworkHandler().getConnection();
if (block == null) return new CompletableFuture<>(); if (block == null) return new CompletableFuture<>();
@ -290,7 +297,7 @@ public class CommandCore {
incrementCurrentBlock(); incrementCurrentBlock();
final CompletableFuture<NbtCompound> future = new CompletableFuture<>(); CompletableFuture<NbtCompound> future = new CompletableFuture<>();
final Timer timer = new Timer(); final Timer timer = new Timer();

View file

@ -1,36 +1,39 @@
package land.chipmunk.chipmunkmod.modules; package land.chipmunk.chipmunkmod.modules;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.ArrayList;
import java.util.Timer; import java.util.Timer;
import java.util.TimerTask; import java.util.TimerTask;
public class CommandLoopManager { public class CommandLoopManager {
public static final CommandLoopManager INSTANCE = new CommandLoopManager(CommandCore.INSTANCE);
private final CommandCore core; private final CommandCore core;
public List<CommandLoop> commandLoops = new ArrayList<>(); public List<CommandLoop> commandLoops = new ArrayList<>();
public CommandLoopManager (final CommandCore core) { public CommandLoopManager (CommandCore core) {
this.core = core; this.core = core;
} }
public int loopCommand (final String command, final long interval) { public static final CommandLoopManager INSTANCE = new CommandLoopManager(CommandCore.INSTANCE);
public int loopCommand (String command, long interval) {
final CommandLoop loop = new CommandLoop(this.core, command, interval); final CommandLoop loop = new CommandLoop(this.core, command, interval);
commandLoops.add(loop); if (!commandLoops.add(loop)) return -1;
return commandLoops.size() - 1; return commandLoops.size() - 1;
} }
public boolean removeAndStop (final CommandLoop loop) { public boolean removeAndStop (CommandLoop loop) {
loop.stop(); loop.stop();
return commandLoops.remove(loop); return commandLoops.remove(loop);
} }
public boolean removeAndStop (final int id) { public boolean removeAndStop (int id) {
return removeAndStop(commandLoops.get(id)); return removeAndStop(commandLoops.get(id));
} }
public void clearLoops () { public void clearLoops () {
for (final CommandLoop loop : this.commandLoops) loop.stop(); for (CommandLoop loop : this.commandLoops) loop.stop();
commandLoops.clear(); commandLoops.clear();
} }
@ -42,7 +45,7 @@ public class CommandLoopManager {
public long interval; public long interval;
private Timer timer; private Timer timer;
public CommandLoop (final CommandCore core, final String command, final long interval) { public CommandLoop (CommandCore core, String command, long interval) {
this.core = core; this.core = core;
this.command = command; this.command = command;
this.interval = interval; this.interval = interval;
@ -50,9 +53,8 @@ public class CommandLoopManager {
timer.schedule(this.createTimerTask(), interval, interval); timer.schedule(this.createTimerTask(), interval, interval);
} }
private long interval (final long interval) { private long interval (long interval) {
if (timer == null) if (timer == null) throw new IllegalStateException("Attempted to set the interval of a stopped command loop");
throw new IllegalStateException("Attempted to set the interval of a stopped command loop");
timer.cancel(); timer.cancel();
timer.purge(); timer.purge();

View file

@ -5,9 +5,10 @@ import net.minecraft.client.MinecraftClient;
import net.minecraft.command.CommandSource; import net.minecraft.command.CommandSource;
public class KaboomCheck { public class KaboomCheck {
public static final KaboomCheck INSTANCE = new KaboomCheck();
private static final String CHECKED_COMMAND_OP = "extras:prefix"; // Added circa 2018 private static final String CHECKED_COMMAND_OP = "extras:prefix"; // Added circa 2018
private static final String CHECKED_COMMAND = "minecraft:op"; // It'd be a bit weird for non-Kaboom servers to allow /op without OP... private static final String CHECKED_COMMAND = "minecraft:op"; // It'd be a bit weird for non-Kaboom servers to allow /op without OP...
public static final KaboomCheck INSTANCE = new KaboomCheck();
private final MinecraftClient client = MinecraftClient.getInstance(); private final MinecraftClient client = MinecraftClient.getInstance();
public boolean isKaboom = false; public boolean isKaboom = false;

View file

@ -1,8 +1,9 @@
package land.chipmunk.chipmunkmod.modules; package land.chipmunk.chipmunkmod.modules;
import com.mojang.authlib.GameProfile; import com.mojang.authlib.GameProfile;
import land.chipmunk.chipmunkmod.ChipmunkMod;
import land.chipmunk.chipmunkmod.util.ColorUtilities; import land.chipmunk.chipmunkmod.util.ColorUtilities;
import land.chipmunk.chipmunkmod.util.RandomUtilities; import land.chipmunk.chipmunkmod.util.RandomUtilities;
import land.chipmunk.chipmunkmod.util.UUIDUtilities; import land.chipmunk.chipmunkmod.util.UUIDUtilities;
import net.kyori.adventure.text.Component; import net.kyori.adventure.text.Component;
@ -16,20 +17,18 @@ import java.util.Timer;
import java.util.TimerTask; import java.util.TimerTask;
public class RainbowName { public class RainbowName {
public static final RainbowName INSTANCE = new RainbowName(MinecraftClient.getInstance());
private final MinecraftClient client; private final MinecraftClient client;
public static final RainbowName INSTANCE = new RainbowName(MinecraftClient.getInstance());
private final Random random = new Random(); private final Random random = new Random();
public boolean enabled = false; public boolean enabled = false;
public String displayName;
private Timer timer = null; private Timer timer = null;
private String team;
private int startHue = 0;
public RainbowName (final MinecraftClient client) { private String team;
this.client = client; public String displayName;
this.displayName = client.getSession().getUsername(); private int startHue = 0;
}
public void init () { public void init () {
final TimerTask task = new TimerTask() { final TimerTask task = new TimerTask() {
@ -46,7 +45,6 @@ public class RainbowName {
public void enable () { public void enable () {
final ClientPlayNetworkHandler networkHandler = client.getNetworkHandler(); final ClientPlayNetworkHandler networkHandler = client.getNetworkHandler();
if (networkHandler == null) return;
final GameProfile profile = networkHandler.getProfile(); final GameProfile profile = networkHandler.getProfile();
final String username = RandomUtilities.emptyUsername(random); final String username = RandomUtilities.emptyUsername(random);
@ -62,10 +60,6 @@ public class RainbowName {
public void disable () { public void disable () {
final ClientPlayNetworkHandler networkHandler = client.getNetworkHandler(); final ClientPlayNetworkHandler networkHandler = client.getNetworkHandler();
if (networkHandler == null) {
enabled = false;
return;
}
final GameProfile profile = networkHandler.getProfile(); final GameProfile profile = networkHandler.getProfile();
CommandCore.INSTANCE.run("essentials:nick " + profile.getId() + " off"); CommandCore.INSTANCE.run("essentials:nick " + profile.getId() + " off");
@ -74,6 +68,11 @@ public class RainbowName {
enabled = false; enabled = false;
} }
public RainbowName (MinecraftClient client) {
this.client = client;
this.displayName = client.getSession().getUsername();
}
private void tick () { private void tick () {
try { try {
final ClientPlayNetworkHandler networkHandler = client.getNetworkHandler(); final ClientPlayNetworkHandler networkHandler = client.getNetworkHandler();
@ -87,15 +86,15 @@ public class RainbowName {
final GameProfile profile = networkHandler.getProfile(); final GameProfile profile = networkHandler.getProfile();
int hue = startHue; int hue = startHue;
final int increment = (int) (360.0 / Math.max(displayName.length(), 20)); int increment = (int) (360.0 / Math.max(displayName.length(), 20));
Component component = Component.empty(); Component component = Component.empty();
final StringBuilder essentialsNickname = new StringBuilder(); StringBuilder essentialsNickname = new StringBuilder();
for (final char character : displayName.toCharArray()) { for (char character : displayName.toCharArray()) {
final String color = String.format("%06x", ColorUtilities.hsvToRgb(hue, 100, 100)); String color = String.format("%06x", ColorUtilities.hsvToRgb(hue, 100, 100));
component = component.append(Component.text(character).color(TextColor.fromHexString("#" + color))); component = component.append(Component.text(character).color(TextColor.fromHexString("#" + color)));
essentialsNickname.append("§#").append(color).append(character != ' ' ? character : '_'); essentialsNickname.append("\u00a7#").append(color).append(character != ' ' ? character : '_');
hue = (hue + increment) % 360; hue = (hue + increment) % 360;
} }
@ -103,8 +102,8 @@ public class RainbowName {
CommandCore.INSTANCE.run("essentials:nick " + profile.getId() + " " + essentialsNickname); CommandCore.INSTANCE.run("essentials:nick " + profile.getId() + " " + essentialsNickname);
startHue = (startHue + increment) % 360; startHue = (startHue + increment) % 360;
} catch (final Exception e) { } catch (Exception e) {
ChipmunkMod.LOGGER.error("Error while ticking rainbow name", e); e.printStackTrace();
} }
} }

View file

@ -17,21 +17,27 @@ 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 {
public static final SelfCare INSTANCE = new SelfCare(MinecraftClient.getInstance(), 70L, 500L); // make the intervals in config? private final MinecraftClient client;
public final long interval; public final long interval;
public final long chatInterval; public final long chatInterval;
private final MinecraftClient client;
public boolean opEnabled = ChipmunkMod.CONFIG.selfCare.op; public boolean opEnabled = ChipmunkMod.CONFIG.selfCare.op;
public boolean gamemodeEnabled = ChipmunkMod.CONFIG.selfCare.gameMode; public boolean gamemodeEnabled = ChipmunkMod.CONFIG.selfCare.gameMode;
public boolean cspyEnabled = ChipmunkMod.CONFIG.selfCare.cspy; public boolean cspyEnabled = ChipmunkMod.CONFIG.selfCare.cspy;
public String skin;
public boolean hasSkin = false;
private int gameMode; private int gameMode;
public String skin;
private Timer timer; private Timer timer;
private Timer chatTimer; private Timer chatTimer;
private boolean cspy = false;
public SelfCare (final MinecraftClient client, final long interval, final long chatInterval) { private boolean cspy = false;
public boolean hasSkin = false;
public static final SelfCare INSTANCE = new SelfCare(MinecraftClient.getInstance(), 70L, 500L); // make the intervals in config?
public SelfCare(MinecraftClient client, long interval, long chatInterval) {
this.client = client; this.client = client;
this.interval = interval; this.interval = interval;
this.chatInterval = chatInterval; this.chatInterval = chatInterval;
@ -80,7 +86,7 @@ public class SelfCare implements Listener {
} }
@Override @Override
public void chatMessageReceived (final Text message) { public void chatMessageReceived(Text message) {
final String stringMessage = message.getString(); final String stringMessage = message.getString();
if (stringMessage.equals("Successfully enabled CommandSpy")) cspy = true; if (stringMessage.equals("Successfully enabled CommandSpy")) cspy = true;
@ -102,16 +108,13 @@ public class SelfCare implements Listener {
return; return;
} }
if (player != null && !player.hasPermissionLevel(2) && opEnabled && serverHasCommand("op")) if (player != null && !player.hasPermissionLevel(2) && opEnabled && serverHasCommand("op")) networkHandler.sendChatCommand("op @s[type=player]");
networkHandler.sendChatCommand("op @s[type=player]");
else if (gameMode != 1 && gamemodeEnabled) networkHandler.sendChatCommand("gamemode creative"); else if (gameMode != 1 && gamemodeEnabled) networkHandler.sendChatCommand("gamemode creative");
} }
public void chatTick() { public void chatTick() {
final ClientPlayNetworkHandler networkHandler = client.getNetworkHandler(); final ClientPlayNetworkHandler networkHandler = client.getNetworkHandler();
if (networkHandler == null) return;
if (!cspy && cspyEnabled) { if (!cspy && cspyEnabled) {
if (serverHasCommand("c")) networkHandler.sendChatCommand("c on"); if (serverHasCommand("c")) networkHandler.sendChatCommand("c on");
} else if (!hasSkin && !skin.equals("off")) { } else if (!hasSkin && !skin.equals("off")) {
@ -120,16 +123,16 @@ public class SelfCare implements Listener {
} }
@Override @Override
public void packetReceived (final Packet<?> packet) { public void packetReceived(Packet<?> packet) {
if (packet instanceof GameJoinS2CPacket) packetReceived((GameJoinS2CPacket) packet); if (packet instanceof GameJoinS2CPacket) packetReceived((GameJoinS2CPacket) packet);
else if (packet instanceof GameStateChangeS2CPacket) packetReceived((GameStateChangeS2CPacket) packet); else if (packet instanceof GameStateChangeS2CPacket) packetReceived((GameStateChangeS2CPacket) packet);
} }
public void packetReceived (final GameJoinS2CPacket packet) { public void packetReceived(GameJoinS2CPacket packet) {
gameMode = packet.commonPlayerSpawnInfo().gameMode().getId(); gameMode = packet.commonPlayerSpawnInfo().gameMode().getId();
} }
public void packetReceived (final GameStateChangeS2CPacket packet) { public void packetReceived(GameStateChangeS2CPacket packet) {
if (packet.getReason() != GameStateChangeS2CPacket.GAME_MODE_CHANGED) return; if (packet.getReason() != GameStateChangeS2CPacket.GAME_MODE_CHANGED) return;
gameMode = (int) packet.getValue(); gameMode = (int) packet.getValue();

View file

@ -25,33 +25,35 @@ import java.util.TimerTask;
public class SongPlayer { public class SongPlayer {
public static final String SELECTOR = "@a[tag=!nomusic,tag=!chipmunkmod_nomusic]"; public static final String SELECTOR = "@a[tag=!nomusic,tag=!chipmunkmod_nomusic]";
public static final SongPlayer INSTANCE = new SongPlayer(MinecraftClient.getInstance());
public static File SONG_DIR = new File("songs"); public static File SONG_DIR = new File("songs");
static { static {
if (!SONG_DIR.exists()) { if (!SONG_DIR.exists()) {
SONG_DIR.mkdir(); SONG_DIR.mkdir();
} }
} }
private final MinecraftClient client; public static final SongPlayer INSTANCE = new SongPlayer(MinecraftClient.getInstance());
public Song currentSong; public Song currentSong;
public LinkedList<Song> songQueue = new LinkedList<>(); public LinkedList<Song> songQueue = new LinkedList<>();
public Timer playTimer; public Timer playTimer;
public SongLoaderThread loaderThread; public SongLoaderThread loaderThread;
private int ticksUntilPausedActionbar = 20;
public boolean useCore = true; public boolean useCore = true;
public boolean actionbar = true; public boolean actionbar = true;
public float pitch = 0; public float pitch = 0;
private int ticksUntilPausedActionbar = 20;
public SongPlayer (final MinecraftClient client) { private final MinecraftClient client;
public SongPlayer (MinecraftClient client) {
this.client = client; this.client = client;
} }
// TODO: Less duplicate code // TODO: Less duplicate code
public void loadSong (final Path location) { public void loadSong (Path location) {
final ClientPlayerEntity player = client.player; final ClientPlayerEntity player = client.player;
if (player == null) return; if (player == null) return;
@ -66,13 +68,13 @@ public class SongPlayer {
player.sendMessage(Component.translatable("Loading %s", Component.text(location.toString(), NamedTextColor.DARK_GREEN)).color(NamedTextColor.GREEN)); player.sendMessage(Component.translatable("Loading %s", Component.text(location.toString(), NamedTextColor.DARK_GREEN)).color(NamedTextColor.GREEN));
_loaderThread.start(); _loaderThread.start();
loaderThread = _loaderThread; loaderThread = _loaderThread;
} catch (final SongLoaderException e) { } catch (SongLoaderException e) {
player.sendMessage(Component.translatable("Failed to load song: %s", Component.text(e.message.getString())).color(NamedTextColor.RED)); player.sendMessage(Component.translatable("Failed to load song: %s", Component.text(e.message.getString())).color(NamedTextColor.RED));
loaderThread = null; loaderThread = null;
} }
} }
public void loadSong (final URL location) { public void loadSong (URL location) {
final ClientPlayerEntity player = client.player; final ClientPlayerEntity player = client.player;
if (player == null) return; if (player == null) return;
@ -87,7 +89,7 @@ public class SongPlayer {
player.sendMessage(Component.translatable("Loading %s", Component.text(location.toString(), NamedTextColor.DARK_GREEN)).color(NamedTextColor.GREEN)); player.sendMessage(Component.translatable("Loading %s", Component.text(location.toString(), NamedTextColor.DARK_GREEN)).color(NamedTextColor.GREEN));
_loaderThread.start(); _loaderThread.start();
loaderThread = _loaderThread; loaderThread = _loaderThread;
} catch (final SongLoaderException e) { } catch (SongLoaderException e) {
player.sendMessage(Component.translatable("Failed to load song: %s", Component.text(e.message.getString())).color(NamedTextColor.RED)); player.sendMessage(Component.translatable("Failed to load song: %s", Component.text(e.message.getString())).color(NamedTextColor.RED));
loaderThread = null; loaderThread = null;
} }
@ -137,11 +139,9 @@ public class SongPlayer {
else ticksUntilPausedActionbar = 20; else ticksUntilPausedActionbar = 20;
try { try {
if (!useCore && actionbar && client.player != null) if (!useCore && actionbar && client.player != null) client.player.sendActionBar(generateActionbar());
client.player.sendActionBar(generateActionbar()); else if (actionbar) CommandCore.INSTANCE.run("title " + SELECTOR + " actionbar " + GsonComponentSerializer.gson().serialize(generateActionbar()));
else if (actionbar) } catch (Exception e) {
CommandCore.INSTANCE.run("title " + SELECTOR + " actionbar " + GsonComponentSerializer.gson().serialize(generateActionbar()));
} catch (final Exception e) {
e.printStackTrace(); e.printStackTrace();
} }
@ -150,8 +150,7 @@ public class SongPlayer {
handlePlaying(); handlePlaying();
if (currentSong.finished()) { if (currentSong.finished()) {
if (client.player != null) if (client.player != null) client.player.sendMessage(Component.translatable("Finished playing %s", Component.empty().append(currentSong.name).color(NamedTextColor.DARK_GREEN)).color(NamedTextColor.GREEN));
client.player.sendMessage(Component.translatable("Finished playing %s", Component.empty().append(currentSong.name).color(NamedTextColor.DARK_GREEN)).color(NamedTextColor.GREEN));
currentSong = null; currentSong = null;
} }
} }
@ -165,7 +164,7 @@ public class SongPlayer {
public Component generateActionbar () { public Component generateActionbar () {
final ClientPlayerEntity player = client.player; final ClientPlayerEntity player = client.player;
final Component component = Component.empty() Component component = Component.empty()
.append(Component.translatable("%s", player.getName().getString()).color(NamedTextColor.GREEN)) .append(Component.translatable("%s", player.getName().getString()).color(NamedTextColor.GREEN))
.append(Component.translatable(" | ", NamedTextColor.DARK_GRAY)) .append(Component.translatable(" | ", NamedTextColor.DARK_GRAY))
.append(Component.translatable("Now playing %s", Component.empty().append(currentSong.name).color(NamedTextColor.DARK_GREEN)).color(NamedTextColor.GREEN)) .append(Component.translatable("Now playing %s", Component.empty().append(currentSong.name).color(NamedTextColor.DARK_GREEN)).color(NamedTextColor.GREEN))
@ -195,7 +194,7 @@ public class SongPlayer {
return component; return component;
} }
public Component formatTime (final long millis) { public Component formatTime (long millis) {
final int seconds = (int) millis / 1000; final int seconds = (int) millis / 1000;
final String minutePart = String.valueOf(seconds / 60); final String minutePart = String.valueOf(seconds / 60);
@ -260,7 +259,7 @@ public class SongPlayer {
) )
); );
} }
} catch (final Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
} }
} }

View file

@ -0,0 +1,11 @@
package land.chipmunk.chipmunkmod.modules;
public class TransactionManager {
public static final TransactionManager INSTANCE = new TransactionManager();
private int transactionId = 0;
public int transactionId () { return transactionId; }
public int nextTransactionId () { return transactionId++; }
}

View file

@ -1,6 +1,7 @@
package land.chipmunk.chipmunkmod.modules.custom_chat; package land.chipmunk.chipmunkmod.modules.custom_chat;
import land.chipmunk.chipmunkmod.ChipmunkMod; import land.chipmunk.chipmunkmod.ChipmunkMod;
import land.chipmunk.chipmunkmod.modules.Chat; import land.chipmunk.chipmunkmod.modules.Chat;
import land.chipmunk.chipmunkmod.modules.CommandCore; import land.chipmunk.chipmunkmod.modules.CommandCore;
import land.chipmunk.chipmunkmod.modules.KaboomCheck; import land.chipmunk.chipmunkmod.modules.KaboomCheck;
@ -21,9 +22,9 @@ import java.util.TimerTask;
import java.util.regex.Pattern; import java.util.regex.Pattern;
public class CustomChat { public class CustomChat {
public static final CustomChat INSTANCE = new CustomChat(MinecraftClient.getInstance());
private static final GsonComponentSerializer GSON = GsonComponentSerializer.gson(); private static final GsonComponentSerializer GSON = GsonComponentSerializer.gson();
private static final CustomChatComponentRenderer RENDERER = new CustomChatComponentRenderer(); private static final CustomChatComponentRenderer RENDERER = new CustomChatComponentRenderer();
private static final LegacyComponentSerializer SERIALIZER = LegacyComponentSerializer private static final LegacyComponentSerializer SERIALIZER = LegacyComponentSerializer
// https://sus.red/abc?a=b&c=d will still break the click events, though // https://sus.red/abc?a=b&c=d will still break the click events, though
@ -52,14 +53,18 @@ public class CustomChat {
.useUnusualXRepeatedCharacterHexFormat() // &x&1&2&3&4&5&6abc .useUnusualXRepeatedCharacterHexFormat() // &x&1&2&3&4&5&6abc
.build(); .build();
private final MinecraftClient client; private final MinecraftClient client;
public static final CustomChat INSTANCE = new CustomChat(MinecraftClient.getInstance());
public boolean enabled = true; public boolean enabled = true;
public String format; public String format;
private Timer timer; private Timer timer;
public CustomChat (final MinecraftClient client) { public CustomChat (MinecraftClient client) {
this.client = client; this.client = client;
} }
@ -89,7 +94,7 @@ public class CustomChat {
timer.purge(); timer.purge();
} }
public void chat (final String message) { public void chat (String message) {
final ClientPlayerEntity player = client.player; final ClientPlayerEntity player = client.player;
if (player == null) return; if (player == null) return;
if (!enabled || !player.hasPermissionLevel(2) || !player.isCreative()) { if (!enabled || !player.hasPermissionLevel(2) || !player.isCreative()) {

View file

@ -17,31 +17,33 @@ public class Instrument {
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);
private static final Instrument[] VALUES = { HARP, BASEDRUM, SNARE, HAT, BASS, FLUTE, BELL, GUITAR, CHIME, XYLOPHONE, IRON_XYLOPHONE, COW_BELL, DIDGERIDOO, BIT, BANJO, PLING };
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 (final int id, final String name, final int offset, final 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 (final int id, final String name, final 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 = "block.note_block." + name; this.sound = "block.note_block." + name;
} }
public static Instrument of (final String sound) { public static Instrument of(String sound) {
return new Instrument(-1, null, 0, sound); return new Instrument(-1, null, 0, sound);
} }
public static Instrument fromId (final int id) { private static final 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]; return VALUES[id];
} }
} }

View file

@ -3,12 +3,8 @@ package land.chipmunk.chipmunkmod.song;
import land.chipmunk.chipmunkmod.util.DownloadUtilities; import land.chipmunk.chipmunkmod.util.DownloadUtilities;
import net.minecraft.util.math.Vec3d; import net.minecraft.util.math.Vec3d;
import javax.sound.midi.*; import java.io.*;
import java.io.ByteArrayInputStream; import java.net.*;
import java.io.File;
import java.io.IOException;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.security.KeyManagementException; import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException; import java.security.NoSuchAlgorithmException;
@ -16,13 +12,155 @@ import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
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 {
Sequence sequence = MidiSystem.getSequence(DownloadUtilities.DownloadToInputStream(url));
return getSong(sequence, Paths.get(url.toURI().getPath()).getFileName().toString());
}
public static Song getSongFromFile(File file) throws InvalidMidiDataException, IOException {
Sequence sequence = MidiSystem.getSequence(file);
return getSong(sequence, file.getName());
}
public static Song getSongFromBytes(byte[] bytes, String name) throws InvalidMidiDataException, IOException {
Sequence sequence = MidiSystem.getSequence(new ByteArrayInputStream(bytes));
return getSong(sequence, name);
}
public static Song getSong(Sequence sequence, String name) {
Song song = new Song(name);
long tpq = sequence.getResolution();
ArrayList<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()));
for (Track track : sequence.getTracks()) {
long microTime = 0;
int[] ids = new int[16];
int mpq = 500000;
int tempoEventIdx = 0;
long prevTick = 0;
for (int i = 0; i < track.size(); i++) {
MidiEvent event = track.get(i);
MidiMessage message = event.getMessage();
while (tempoEventIdx < tempoEvents.size() && event.getTick() > tempoEvents.get(tempoEventIdx).getTick()) {
long deltaTick = tempoEvents.get(tempoEventIdx).getTick() - prevTick;
prevTick = tempoEvents.get(tempoEventIdx).getTick();
microTime += (mpq / tpq) * deltaTick;
MetaMessage mm = (MetaMessage) tempoEvents.get(tempoEventIdx).getMessage();
byte[] data = mm.getData();
int new_mpq = (data[2] & 0xFF) | ((data[1] & 0xFF) << 8) | ((data[0] & 0xFF) << 16);
if (new_mpq != 0) mpq = new_mpq;
tempoEventIdx++;
}
if (message instanceof ShortMessage) {
ShortMessage sm = (ShortMessage) message;
if (sm.getCommand() == SET_INSTRUMENT) {
ids[sm.getChannel()] = sm.getData1();
} else if (sm.getCommand() == NOTE_ON) {
if (sm.getData2() == 0) continue;
int pitch = sm.getData1();
int velocity = sm.getData2();
long deltaTick = event.getTick() - prevTick;
prevTick = event.getTick();
microTime += (mpq / tpq) * deltaTick;
Note note;
if (sm.getChannel() == 9) {
note = getMidiPercussionNote(pitch, velocity, microTime);
} else {
note = getMidiInstrumentNote(ids[sm.getChannel()], pitch, velocity, microTime);
}
if (note != null) {
song.add(note);
}
long time = microTime / 1000L;
if (time > song.length) {
song.length = time;
}
} else if (sm.getCommand() == NOTE_OFF) {
long deltaTick = event.getTick() - prevTick;
prevTick = event.getTick();
microTime += (mpq / tpq) * deltaTick;
long time = microTime / 1000L;
if (time > song.length) {
song.length = time;
}
}
}
}
}
song.sort();
return song;
}
public static Note getMidiInstrumentNote(int midiInstrument, int midiPitch, int velocity, long microTime) {
Instrument instrument = null;
Instrument[] instrumentList = instrumentMap.get(midiInstrument);
if (instrumentList != null) {
for (Instrument candidateInstrument : instrumentList) {
if (midiPitch >= candidateInstrument.offset && midiPitch <= candidateInstrument.offset + 24) {
instrument = candidateInstrument;
break;
}
}
}
if (instrument == null) {
return null;
}
int pitch = midiPitch - instrument.offset;
float volume = (float) velocity / 127.0f;
long time = microTime / 1000L;
return new Note(instrument, pitch, volume, time, Vec3d.ZERO);
}
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;
return new Note(instrument, pitch, volume, time, Vec3d.ZERO);
}
return null;
}
public static HashMap<Integer, Instrument[]> instrumentMap = new HashMap<>(); public static HashMap<Integer, Instrument[]> instrumentMap = new HashMap<>();
public static HashMap<Integer, Integer> percussionMap = new HashMap<>();
static { static {
// Piano (HARP BASS BELL) // Piano (HARP BASS BELL)
@ -176,6 +314,8 @@ public class MidiConverter {
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<>();
static { static {
percussionMap.put(35, 10 + 25 * Instrument.BASEDRUM.id); percussionMap.put(35, 10 + 25 * Instrument.BASEDRUM.id);
percussionMap.put(36, 6 + 25 * Instrument.BASEDRUM.id); percussionMap.put(36, 6 + 25 * Instrument.BASEDRUM.id);
@ -231,142 +371,4 @@ public class MidiConverter {
percussionMap.put(86, 14 + 25 * Instrument.BASEDRUM.id); percussionMap.put(86, 14 + 25 * Instrument.BASEDRUM.id);
percussionMap.put(87, 7 + 25 * Instrument.BASEDRUM.id); percussionMap.put(87, 7 + 25 * Instrument.BASEDRUM.id);
} }
public static Song getSongFromUrl (final URL url) throws IOException, InvalidMidiDataException, URISyntaxException, NoSuchAlgorithmException, KeyManagementException {
final Sequence sequence = MidiSystem.getSequence(DownloadUtilities.DownloadToInputStream(url));
return getSong(sequence, Paths.get(url.toURI().getPath()).getFileName().toString());
}
public static Song getSongFromFile (final File file) throws InvalidMidiDataException, IOException {
final Sequence sequence = MidiSystem.getSequence(file);
return getSong(sequence, file.getName());
}
public static Song getSongFromBytes (final byte[] bytes, final String name) throws InvalidMidiDataException, IOException {
final Sequence sequence = MidiSystem.getSequence(new ByteArrayInputStream(bytes));
return getSong(sequence, name);
}
public static Song getSong (final Sequence sequence, final String name) {
final Song song = new Song(name);
final long tpq = sequence.getResolution();
final ArrayList<MidiEvent> tempoEvents = new ArrayList<>();
for (final Track track : sequence.getTracks()) {
for (int i = 0; i < track.size(); i++) {
final MidiEvent event = track.get(i);
final MidiMessage message = event.getMessage();
if (message instanceof final MetaMessage mm) {
if (mm.getType() == SET_TEMPO) {
tempoEvents.add(event);
}
}
}
}
Collections.sort(tempoEvents, (a, b) -> Long.compare(a.getTick(), b.getTick()));
for (final Track track : sequence.getTracks()) {
long microTime = 0;
final int[] ids = new int[16];
int mpq = 500000;
int tempoEventIdx = 0;
long prevTick = 0;
for (int i = 0; i < track.size(); i++) {
final MidiEvent event = track.get(i);
final MidiMessage message = event.getMessage();
while (tempoEventIdx < tempoEvents.size() && event.getTick() > tempoEvents.get(tempoEventIdx).getTick()) {
final long deltaTick = tempoEvents.get(tempoEventIdx).getTick() - prevTick;
prevTick = tempoEvents.get(tempoEventIdx).getTick();
microTime += (mpq / tpq) * deltaTick;
final MetaMessage mm = (MetaMessage) tempoEvents.get(tempoEventIdx).getMessage();
final byte[] data = mm.getData();
final 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 final ShortMessage sm) {
if (sm.getCommand() == SET_INSTRUMENT) {
ids[sm.getChannel()] = sm.getData1();
} else if (sm.getCommand() == NOTE_ON) {
if (sm.getData2() == 0) continue;
final int pitch = sm.getData1();
final int velocity = sm.getData2();
final long deltaTick = event.getTick() - prevTick;
prevTick = event.getTick();
microTime += (mpq / tpq) * deltaTick;
final 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);
}
final long time = microTime / 1000L;
if (time > song.length) {
song.length = time;
}
} else if (sm.getCommand() == NOTE_OFF) {
final long deltaTick = event.getTick() - prevTick;
prevTick = event.getTick();
microTime += (mpq / tpq) * deltaTick;
final long time = microTime / 1000L;
if (time > song.length) {
song.length = time;
}
}
}
}
}
song.sort();
return song;
}
public static Note getMidiInstrumentNote (final int midiInstrument, final int midiPitch, final int velocity, final long microTime) {
Instrument instrument = null;
final Instrument[] instrumentList = instrumentMap.get(midiInstrument);
if (instrumentList != null) {
for (final Instrument candidateInstrument : instrumentList) {
if (midiPitch >= candidateInstrument.offset && midiPitch <= candidateInstrument.offset + 24) {
instrument = candidateInstrument;
break;
}
}
}
if (instrument == null) {
return null;
}
final int pitch = midiPitch - instrument.offset;
final float volume = (float) velocity / 127.0f;
final long time = microTime / 1000L;
return new Note(instrument, pitch, volume, time, Vec3d.ZERO);
}
private static Note getMidiPercussionNote (final int midiPitch, final int velocity, final long microTime) {
if (percussionMap.containsKey(midiPitch)) {
final int noteId = percussionMap.get(midiPitch);
final int pitch = noteId % 25;
final float volume = (float) velocity / 127.0f;
final Instrument instrument = Instrument.fromId(noteId / 25);
final long time = microTime / 1000L;
return new Note(instrument, pitch, volume, time, Vec3d.ZERO);
}
return null;
}
} }

View file

@ -27,178 +27,6 @@ public class NBSConverter {
Instrument.PLING, Instrument.PLING,
}; };
public static Song getSongFromBytes (final byte[] bytes, final String fileName) throws IOException {
final 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) {
vanillaInstrumentCount = buffer.get();
}
if (format >= 3) {
songLength = buffer.getShort();
}
final short layerCount = buffer.getShort();
final String songName = getString(buffer, bytes.length);
final String songAuthor = getString(buffer, bytes.length);
final String songOriginalAuthor = getString(buffer, bytes.length);
final String songDescription = getString(buffer, bytes.length);
final short tempo = buffer.getShort();
final byte autoSaving = buffer.get();
final byte autoSavingDuration = buffer.get();
final byte timeSignature = buffer.get();
final int minutesSpent = buffer.getInt();
final int leftClicks = buffer.getInt();
final int rightClicks = buffer.getInt();
final int blocksAdded = buffer.getInt();
final int blocksRemoved = buffer.getInt();
final 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();
}
final ArrayList<NBSNote> nbsNotes = new ArrayList<>();
short tick = -1;
while (true) {
final int tickJumps = buffer.getShort();
if (tickJumps == 0) break;
tick += tickJumps;
short layer = -1;
while (true) {
final int layerJumps = buffer.getShort();
if (layerJumps == 0) break;
layer += layerJumps;
final 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);
}
}
final ArrayList<NBSLayer> nbsLayers = new ArrayList<>();
if (buffer.hasRemaining()) {
for (int i = 0; i < layerCount; i++) {
final 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);
}
}
final ArrayList<NBSCustomInstrument> customInstruments = new ArrayList<>();
if (buffer.hasRemaining()) {
final byte customInstrumentCount = buffer.get();
for (int i = 0; i < customInstrumentCount; i++) {
final 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;
customInstruments.add(customInstrument);
}
}
final 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 (final NBSNote note : nbsNotes) {
final Instrument instrument;
double key;
if (note.instrument < instrumentIndex.length) {
instrument = instrumentIndex[note.instrument];
key = (double) ((note.key * 100) + note.pitch) / 100;
} else {
final int index = note.instrument - instrumentIndex.length;
if (index >= customInstruments.size()) continue;
final NBSCustomInstrument customInstrument = customInstruments.get(index);
instrument = Instrument.of(customInstrument.name);
key = (note.key) + (customInstrument.pitch + (double) note.pitch / 100);
}
byte layerVolume = 100;
if (nbsLayers.size() > note.layer) {
layerVolume = nbsLayers.get(note.layer).volume;
}
while (key < 33) key += 12;
while (key > 57) key -= 12;
final double pitch = key - 33;
final int layerStereo = Byte.toUnsignedInt(nbsLayers.get(note.layer).stereo);
final int notePanning = Byte.toUnsignedInt(note.panning);
final double value;
if (layerStereo == 100 && notePanning != 100) value = notePanning;
else if (notePanning == 100 && layerStereo != 100) value = layerStereo;
else value = (double) (layerStereo + notePanning) / 2;
final double x;
if (value > 100) x = (value - 100) / -100;
else if (value == 100) x = 0;
else x = ((value - 100) * -1) / 100;
final Vec3d position = new Vec3d(x, 0, 0);
song.add(new Note(instrument, pitch, (float) note.velocity * (float) layerVolume / 10000f, getMilliTime(note.tick, tempo), position));
}
song.length = song.get(song.size() - 1).time + 50;
return song;
}
private static String getString (final ByteBuffer buffer, final int maxSize) throws IOException {
final int length = buffer.getInt();
if (length > maxSize) {
throw new IOException("String is too large");
}
final byte[] arr = new byte[length];
buffer.get(arr, 0, length);
return new String(arr);
}
private static int getMilliTime (final int tick, final int tempo) {
return 1000 * tick * 100 / tempo;
}
private static class NBSNote { private static class NBSNote {
public int tick; public int tick;
public short layer; public short layer;
@ -222,4 +50,176 @@ public class NBSConverter {
public byte pitch = 0; public byte pitch = 0;
public boolean key = false; 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) {
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) {
loop = buffer.get();
maxLoopCount = buffer.get();
loopStartTick = buffer.getShort();
}
ArrayList<NBSNote> nbsNotes = new ArrayList<>();
short tick = -1;
while (true) {
int tickJumps = buffer.getShort();
if (tickJumps == 0) break;
tick += tickJumps;
short layer = -1;
while (true) {
int layerJumps = buffer.getShort();
if (layerJumps == 0) break;
layer += layerJumps;
NBSNote note = new NBSNote();
note.tick = tick;
note.layer = layer;
note.instrument = buffer.get();
note.key = buffer.get();
if (format >= 4) {
note.velocity = buffer.get();
note.panning = buffer.get();
note.pitch = buffer.getShort();
}
nbsNotes.add(note);
}
}
ArrayList<NBSLayer> nbsLayers = new ArrayList<>();
if (buffer.hasRemaining()) {
for (int i = 0; i < layerCount; i++) {
NBSLayer layer = new NBSLayer();
layer.name = getString(buffer, bytes.length);
if (format >= 4) {
layer.lock = buffer.get();
}
layer.volume = buffer.get();
if (format >= 2) {
layer.stereo = buffer.get();
}
nbsLayers.add(layer);
}
}
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;
double key;
if (note.instrument < instrumentIndex.length) {
instrument = instrumentIndex[note.instrument];
key = (double) ((note.key * 100) + note.pitch) / 100;
} else {
int index = note.instrument - instrumentIndex.length;
if (index >= customInstruments.size()) continue;
NBSCustomInstrument customInstrument = customInstruments.get(index);
instrument = Instrument.of(customInstrument.name);
key = (note.key) + (customInstrument.pitch + (double) note.pitch / 100);
}
byte layerVolume = 100;
if (nbsLayers.size() > note.layer) {
layerVolume = nbsLayers.get(note.layer).volume;
}
while (key < 33) key += 12;
while (key > 57) key -= 12;
double pitch = key - 33;
final int layerStereo = Byte.toUnsignedInt(nbsLayers.get(note.layer).stereo);
final int notePanning = Byte.toUnsignedInt(note.panning);
double value;
if (layerStereo == 100 && notePanning != 100) value = notePanning;
else if (notePanning == 100 && layerStereo != 100) value = layerStereo;
else value = (double) (layerStereo + notePanning) / 2;
double x;
if (value > 100) x = (value - 100) / -100;
else if (value == 100) x = 0;
else x = ((value - 100) * -1) / 100;
final Vec3d position = new Vec3d(x, 0 ,0);
song.add(new Note(instrument, pitch, (float) note.velocity * (float) layerVolume / 10000f, getMilliTime(note.tick, tempo), position));
}
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

@ -10,7 +10,7 @@ public class Note implements Comparable<Note> {
public long time; public long time;
public Vec3d position; public Vec3d position;
public Note (final Instrument instrument, final double pitch, final float volume, final long time, final Vec3d position) { public Note(Instrument instrument, double pitch, float volume, long time, Vec3d position) {
this.instrument = instrument; this.instrument = instrument;
this.pitch = pitch; this.pitch = pitch;
this.volume = volume; this.volume = volume;
@ -19,7 +19,7 @@ public class Note implements Comparable<Note> {
} }
@Override @Override
public int compareTo (final Note other) { public int compareTo(Note other) {
return Long.compare(time, other.time); return Long.compare(time, other.time);
} }
} }

View file

@ -18,19 +18,19 @@ public class Song {
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 (final Component name) { public Song(Component name) {
this.name = name; this.name = name;
} }
public Song (final String name) { public Song(String name) {
this(Component.text(name)); this(Component.text(name));
} }
public Note get (final int i) { public Note get(int i) {
return notes.get(i); return notes.get(i);
} }
public void add (final Note e) { public void add(Note e) {
notes.add(e); notes.add(e);
} }
@ -59,7 +59,7 @@ public class Song {
} }
} }
public void setTime (final long t) { public void setTime(long t) {
time = t; time = t;
startTime = System.currentTimeMillis() - time; startTime = System.currentTimeMillis() - time;
position = 0; position = 0;

View file

@ -5,12 +5,12 @@ 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 (final Text message) { public SongLoaderException(Text message) {
super(); super();
this.message = message; this.message = message;
} }
public SongLoaderException (final Text message, final Throwable cause) { public SongLoaderException(Text message, Throwable cause) {
super(null, cause); super(null, cause);
this.message = message; this.message = message;
} }

View file

@ -6,31 +6,32 @@ import net.minecraft.text.Text;
import java.io.File; import java.io.File;
import java.net.URL; import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
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 {
public SongLoaderException exception;
public Song song;
private String location; private String location;
private File songPath; private File songPath;
private URL songUrl; private URL songUrl;
private final boolean isUrl; public SongLoaderException exception;
public Song song;
public SongLoaderThread (final URL location) throws SongLoaderException { private boolean isUrl;
public SongLoaderThread(URL location) throws SongLoaderException {
isUrl = true; isUrl = true;
songUrl = location; songUrl = location;
} }
public SongLoaderThread (final Path location) throws SongLoaderException { public SongLoaderThread(Path location) throws SongLoaderException {
isUrl = false; isUrl = false;
songPath = location.toFile(); songPath = location.toFile();
} }
public void run() { public void run() {
final byte[] bytes; byte[] bytes;
final String name; String name;
try { try {
if (isUrl) { if (isUrl) {
bytes = DownloadUtilities.DownloadToByteArray(songUrl); bytes = DownloadUtilities.DownloadToByteArray(songUrl);
@ -39,20 +40,20 @@ public class SongLoaderThread extends Thread {
bytes = Files.readAllBytes(songPath.toPath()); bytes = Files.readAllBytes(songPath.toPath());
name = songPath.getName(); name = songPath.getName();
} }
} catch (final Exception e) { } catch (Exception e) {
exception = new SongLoaderException(Text.literal(e.getMessage()), e); exception = new SongLoaderException(Text.literal(e.getMessage()), e);
return; return;
} }
try { try {
song = MidiConverter.getSongFromBytes(bytes, name); song = MidiConverter.getSongFromBytes(bytes, name);
} catch (final Exception e) { } catch (Exception e) {
} }
if (song == null) { if (song == null) {
try { try {
song = NBSConverter.getSongFromBytes(bytes, name); song = NBSConverter.getSongFromBytes(bytes, name);
} catch (final Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
} }
} }
@ -62,7 +63,7 @@ public class SongLoaderThread extends Thread {
} }
} }
private File getSongFile (final String name) { private File getSongFile(String name) {
return new File(SongPlayer.SONG_DIR, name); return new File(SongPlayer.SONG_DIR, name);
} }
} }

View file

@ -17,59 +17,57 @@ import java.security.NoSuchAlgorithmException;
import java.util.Arrays; import java.util.Arrays;
public class BotValidationUtilities { public class BotValidationUtilities {
public static int hbot (final String command) throws RuntimeException { public static int hbot (String command) throws RuntimeException {
final Configuration.BotInfo info = ChipmunkMod.CONFIG.bots.hbot; final Configuration.BotInfo info = ChipmunkMod.CONFIG.bots.hbot;
final MinecraftClient client = MinecraftClient.getInstance(); final MinecraftClient client = MinecraftClient.getInstance();
final ClientPlayNetworkHandler networkHandler = client.getNetworkHandler(); final ClientPlayNetworkHandler networkHandler = client.getNetworkHandler();
final String prefix = info.prefix; final String prefix = info.prefix;
final String key = info.key; final String key = info.key;
if (key == null) if (key == null) throw new RuntimeException("The key of the bot is unspecified (null), did you incorrectly add it to your config?");
throw new RuntimeException("The key of the bot is unspecified (null), did you incorrectly add it to your config?");
try { try {
final MessageDigest md = MessageDigest.getInstance("SHA-256"); MessageDigest md = MessageDigest.getInstance("SHA-256");
final String time = String.valueOf(System.currentTimeMillis() / 10000); String time = String.valueOf(System.currentTimeMillis() / 10000);
final String input = prefix + command.replaceAll("&[0-9a-fklmnor]", "") + ";" + client.player.getUuidAsString() + ";" + time + ";" + key; String input = prefix + command.replaceAll("&[0-9a-fklmnor]", "") + ";" + client.player.getUuidAsString() + ";" + time + ";" + key;
final byte[] hash = md.digest(input.getBytes(StandardCharsets.UTF_8)); byte[] hash = md.digest(input.getBytes(StandardCharsets.UTF_8));
final BigInteger bigInt = new BigInteger(1, Arrays.copyOfRange(hash, 0, 4)); BigInteger bigInt = new BigInteger(1, Arrays.copyOfRange(hash, 0, 4));
final String stringHash = bigInt.toString(Character.MAX_RADIX); String stringHash = bigInt.toString(Character.MAX_RADIX);
Chat.sendChatMessage(prefix + command + " " + stringHash, true); Chat.sendChatMessage(prefix + command + " " + stringHash, true);
} catch (final NoSuchAlgorithmException e) { } catch (NoSuchAlgorithmException e) {
e.printStackTrace(); e.printStackTrace();
} }
return Command.SINGLE_SUCCESS; return Command.SINGLE_SUCCESS;
} }
public static int sbot (final String command) throws RuntimeException { public static int sbot (String command) throws RuntimeException {
final Configuration.BotInfo info = ChipmunkMod.CONFIG.bots.sbot; final Configuration.BotInfo info = ChipmunkMod.CONFIG.bots.sbot;
final MinecraftClient client = MinecraftClient.getInstance(); final MinecraftClient client = MinecraftClient.getInstance();
final ClientPlayNetworkHandler networkHandler = client.getNetworkHandler(); final ClientPlayNetworkHandler networkHandler = client.getNetworkHandler();
final String prefix = info.prefix; final String prefix = info.prefix;
final String key = info.key; final String key = info.key;
if (key == null) if (key == null) throw new RuntimeException("The key of the bot is unspecified (null), did you incorrectly add it to your config?");
throw new RuntimeException("The key of the bot is unspecified (null), did you incorrectly add it to your config?");
try { try {
final MessageDigest md = MessageDigest.getInstance("MD5"); MessageDigest md = MessageDigest.getInstance("MD5");
final String time = String.valueOf(System.currentTimeMillis() / 20000); String time = String.valueOf(System.currentTimeMillis() / 20000);
final String input = prefix + command.replaceAll("&[0-9a-fklmnorx]", "") + ";" + client.player.getName().getString() + ";" + time + ";" + key; String input = prefix + command.replaceAll("&[0-9a-fklmnorx]", "") + ";" + client.player.getName().getString() + ";" + time + ";" + key;
final byte[] hash = md.digest(input.getBytes(StandardCharsets.UTF_8)); byte[] hash = md.digest(input.getBytes(StandardCharsets.UTF_8));
final BigInteger bigInt = new BigInteger(1, Arrays.copyOfRange(hash, 0, 4)); BigInteger bigInt = new BigInteger(1, Arrays.copyOfRange(hash, 0, 4));
final String stringHash = bigInt.toString(Character.MAX_RADIX); String stringHash = bigInt.toString(Character.MAX_RADIX);
Chat.sendChatMessage(prefix + command + " " + stringHash, true); Chat.sendChatMessage(prefix + command + " " + stringHash, true);
} catch (final NoSuchAlgorithmException e) { } catch (NoSuchAlgorithmException e) {
e.printStackTrace(); e.printStackTrace();
} }
return Command.SINGLE_SUCCESS; return Command.SINGLE_SUCCESS;
} }
public static int chomens (final String command) throws RuntimeException { public static int chomens (String command) throws RuntimeException {
final Configuration.BotInfo info = ChipmunkMod.CONFIG.bots.chomens; final Configuration.BotInfo info = ChipmunkMod.CONFIG.bots.chomens;
final MinecraftClient client = MinecraftClient.getInstance(); final MinecraftClient client = MinecraftClient.getInstance();
@ -78,16 +76,15 @@ public class BotValidationUtilities {
final String prefix = info.prefix; final String prefix = info.prefix;
final String key = info.key; final String key = info.key;
if (key == null) if (key == null) throw new RuntimeException("The key of the bot is unspecified (null), did you incorrectly add it to your config?");
throw new RuntimeException("The key of the bot is unspecified (null), did you incorrectly add it to your config?");
try { try {
final String[] arguments = command.split(" "); String[] arguments = command.split(" ");
final MessageDigest md = MessageDigest.getInstance("SHA-256"); MessageDigest md = MessageDigest.getInstance("SHA-256");
final String time = String.valueOf(System.currentTimeMillis() / 5_000); String time = String.valueOf(System.currentTimeMillis() / 5_000);
final String input = client.player.getUuidAsString() + arguments[0] + time + key; String input = client.player.getUuidAsString() + arguments[0] + time + key;
final byte[] hash = md.digest(input.getBytes(StandardCharsets.UTF_8)); byte[] hash = md.digest(input.getBytes(StandardCharsets.UTF_8));
String stringHash = new String(Hex.encodeHex(hash)).substring(0, 16); String stringHash = new String(Hex.encodeHex(hash)).substring(0, 16);
final boolean shouldSectionSign = CustomChat.INSTANCE.enabled && player.hasPermissionLevel(2) && player.isCreative(); final boolean shouldSectionSign = CustomChat.INSTANCE.enabled && player.hasPermissionLevel(2) && player.isCreative();
@ -111,59 +108,57 @@ public class BotValidationUtilities {
String.join(" ", restArguments); String.join(" ", restArguments);
Chat.sendChatMessage(toSend); Chat.sendChatMessage(toSend);
} catch (final NoSuchAlgorithmException e) { } catch (NoSuchAlgorithmException e) {
e.printStackTrace(); e.printStackTrace();
} }
return Command.SINGLE_SUCCESS; return Command.SINGLE_SUCCESS;
} }
public static int qilk (final String command) throws RuntimeException { public static int qilk (String command) throws RuntimeException {
final Configuration.BotInfo info = ChipmunkMod.CONFIG.bots.qilk; final Configuration.BotInfo info = ChipmunkMod.CONFIG.bots.qilk;
final MinecraftClient client = MinecraftClient.getInstance(); final MinecraftClient client = MinecraftClient.getInstance();
final String prefix = info.prefix; final String prefix = info.prefix;
final String key = info.key; final String key = info.key;
if (key == null) if (key == null) throw new RuntimeException("The key of the bot is unspecified (null), did you incorrectly add it to your config?");
throw new RuntimeException("The key of the bot is unspecified (null), did you incorrectly add it to your config?");
try { try {
final MessageDigest md = MessageDigest.getInstance("SHA-256"); MessageDigest md = MessageDigest.getInstance("SHA-256");
final long time = Math.floorDiv(System.currentTimeMillis(), 2000); long time = Math.floorDiv(System.currentTimeMillis(), 2000);
final String[] wholeArguments = command.split(" "); String[] wholeArguments = command.split(" ");
final String[] restArguments = Arrays.copyOfRange(wholeArguments, 1, wholeArguments.length); String[] restArguments = Arrays.copyOfRange(wholeArguments, 1, wholeArguments.length);
// lol this is literally chomens bot input with uwu and : // lol this is literally chomens bot input with uwu and :
final String input = "uwu:" + key + ":" + client.player.getUuidAsString() + ":" + wholeArguments[0] + ":" + time; String input = "uwu:" + key + ":" + client.player.getUuidAsString() + ":" + wholeArguments[0] + ":" + time;
final byte[] hash = md.digest(input.getBytes(StandardCharsets.UTF_8)); byte[] hash = md.digest(input.getBytes(StandardCharsets.UTF_8));
final String stringHash = new String(Hex.encodeHex(hash)); String stringHash = new String(Hex.encodeHex(hash));
Chat.sendChatMessage(prefix + wholeArguments[0] + " " + stringHash + " " + String.join(" ", restArguments), true); Chat.sendChatMessage(prefix + wholeArguments[0] + " " + stringHash + " " + String.join(" ", restArguments), true);
} catch (final NoSuchAlgorithmException e) { } catch (NoSuchAlgorithmException e) {
e.printStackTrace(); e.printStackTrace();
} }
return Command.SINGLE_SUCCESS; return Command.SINGLE_SUCCESS;
} }
public static int fnfboyfriend (final String command) { public static int fnfboyfriend (String command) {
try { try {
final String prefix = ChipmunkMod.CONFIG.bots.fnfboyfriend.prefix; final String prefix = ChipmunkMod.CONFIG.bots.fnfboyfriend.prefix;
final String[] arguments = command.split(" "); String[] arguments = command.split(" ");
final long currentTime = System.currentTimeMillis() / 2000; long currentTime = System.currentTimeMillis() / 2000;
final String key = ChipmunkMod.CONFIG.bots.fnfboyfriend.key; final String key = ChipmunkMod.CONFIG.bots.fnfboyfriend.key;
if (key == null) if (key == null) throw new RuntimeException("The key of the bot is unspecified (null), did you incorrectly add it to your config?");
throw new RuntimeException("The key of the bot is unspecified (null), did you incorrectly add it to your config?"); String input = currentTime + key;
final String input = currentTime + key; MessageDigest digest = MessageDigest.getInstance("SHA-256");
final MessageDigest digest = MessageDigest.getInstance("SHA-256"); byte[] hash = digest.digest(input.getBytes());
final byte[] hash = digest.digest(input.getBytes()); StringBuilder hexString = new StringBuilder();
final StringBuilder hexString = new StringBuilder(); for (byte b : hash) {
for (final byte b : hash) { String hex = Integer.toHexString(0xff & b);
final String hex = Integer.toHexString(0xff & b);
if (hex.length() == 1) hexString.append('0'); if (hex.length() == 1) hexString.append('0');
hexString.append(hex); hexString.append(hex);
} }
@ -173,25 +168,24 @@ public class BotValidationUtilities {
final String result = hexString.substring(0, 16); final String result = hexString.substring(0, 16);
Chat.sendChatMessage(prefix + arguments[0] + " " + result + " " + String.join(" ", restArguments)); Chat.sendChatMessage(prefix + arguments[0] + " " + result + " " + String.join(" ", restArguments));
} catch (final NoSuchAlgorithmException e) { } catch (NoSuchAlgorithmException e) {
e.printStackTrace(); e.printStackTrace();
} }
return Command.SINGLE_SUCCESS; return Command.SINGLE_SUCCESS;
} }
public static int nbot (final String command) throws RuntimeException { public static int nbot (String command) throws RuntimeException {
final Configuration.BotInfo info = ChipmunkMod.CONFIG.bots.nbot; final Configuration.BotInfo info = ChipmunkMod.CONFIG.bots.nbot;
final MinecraftClient client = MinecraftClient.getInstance(); final MinecraftClient client = MinecraftClient.getInstance();
final String prefix = info.prefix; final String prefix = info.prefix;
final String key = info.key; final String key = info.key;
if (key == null) if (key == null) throw new RuntimeException("The key of the bot is unspecified (null), did you incorrectly add it to your config?");
throw new RuntimeException("The key of the bot is unspecified (null), did you incorrectly add it to your config?");
try { try {
final String[] arguments = command.split(" "); String[] arguments = command.split(" ");
final MessageDigest md = MessageDigest.getInstance("SHA-256"); final MessageDigest md = MessageDigest.getInstance("SHA-256");
@ -221,32 +215,31 @@ public class BotValidationUtilities {
String.join(" ", restArguments); String.join(" ", restArguments);
Chat.sendChatMessage(toSend, true); Chat.sendChatMessage(toSend, true);
} catch (final NoSuchAlgorithmException e) { } catch (NoSuchAlgorithmException e) {
e.printStackTrace(); e.printStackTrace();
} }
return Command.SINGLE_SUCCESS; return Command.SINGLE_SUCCESS;
} }
public static int kittycorp (final String command) throws RuntimeException { public static int kittycorp (String command) throws RuntimeException {
final Configuration.BotInfo info = ChipmunkMod.CONFIG.bots.kittycorp; final Configuration.BotInfo info = ChipmunkMod.CONFIG.bots.kittycorp;
final ClientPlayNetworkHandler networkHandler = MinecraftClient.getInstance().getNetworkHandler(); final ClientPlayNetworkHandler networkHandler = MinecraftClient.getInstance().getNetworkHandler();
final String prefix = info.prefix; final String prefix = info.prefix;
final String key = info.key; final String key = info.key;
if (key == null) if (key == null) throw new RuntimeException("The key of the bot is unspecified (null), did you incorrectly add it to your config?");
throw new RuntimeException("The key of the bot is unspecified (null), did you incorrectly add it to your config?");
try { try {
final MessageDigest md = MessageDigest.getInstance("SHA-256"); MessageDigest md = MessageDigest.getInstance("SHA-256");
final String time = String.valueOf(System.currentTimeMillis() / 10000); String time = String.valueOf(System.currentTimeMillis() / 10000);
final String input = prefix + command.replaceAll("&[0-9a-fklmnorx]", "") + ";" + time + ";" + key; String input = prefix + command.replaceAll("&[0-9a-fklmnorx]", "") + ";" + time + ";" + key;
final byte[] hash = md.digest(input.getBytes(StandardCharsets.UTF_8)); byte[] hash = md.digest(input.getBytes(StandardCharsets.UTF_8));
final BigInteger bigInt = new BigInteger(1, Arrays.copyOfRange(hash, 0, 4)); BigInteger bigInt = new BigInteger(1, Arrays.copyOfRange(hash, 0, 4));
final String stringHash = bigInt.toString(Character.MAX_RADIX); String stringHash = bigInt.toString(Character.MAX_RADIX);
Chat.sendChatMessage(prefix + command + " " + stringHash, true); Chat.sendChatMessage(prefix + command + " " + stringHash, true);
} catch (final NoSuchAlgorithmException e) { } catch (NoSuchAlgorithmException e) {
e.printStackTrace(); e.printStackTrace();
} }

View file

@ -3,8 +3,8 @@ package land.chipmunk.chipmunkmod.util;
import java.awt.*; import java.awt.*;
public class ColorUtilities { public class ColorUtilities {
public static int hsvToRgb (final int hue, final int saturation, final int value) { public static int hsvToRgb (int hue, int saturation, int value) {
final Color color = Color.getHSBColor(hue / 360.0f, saturation / 100.0f, value / 100.0f); Color color = Color.getHSBColor(hue / 360.0f, saturation / 100.0f, value / 100.0f);
return color.getRGB() & 0xFFFFFF; return color.getRGB() & 0xFFFFFF;
} }
} }

View file

@ -14,18 +14,34 @@ import java.security.cert.X509Certificate;
public class DownloadUtilities { public class DownloadUtilities {
public static byte[] DownloadToByteArray (final URL url) throws IOException, KeyManagementException, NoSuchAlgorithmException { private static class DefaultTrustManager implements X509TrustManager {
final SSLContext ctx = SSLContext.getInstance("TLS");
@Override
public void checkClientTrusted(X509Certificate[] arg0, String arg1) {
}
@Override
public void checkServerTrusted(X509Certificate[] arg0, String arg1) {
}
@Override
public X509Certificate[] getAcceptedIssuers() {
return null;
}
}
public static byte[] DownloadToByteArray(URL url) throws IOException, KeyManagementException, NoSuchAlgorithmException {
SSLContext ctx = SSLContext.getInstance("TLS");
ctx.init(new KeyManager[0], new TrustManager[]{new DefaultTrustManager()}, new SecureRandom()); ctx.init(new KeyManager[0], new TrustManager[]{new DefaultTrustManager()}, new SecureRandom());
SSLContext.setDefault(ctx); SSLContext.setDefault(ctx);
final URLConnection conn = url.openConnection(); URLConnection conn = url.openConnection();
conn.setConnectTimeout(5000); conn.setConnectTimeout(5000);
conn.setReadTimeout(10000); conn.setReadTimeout(10000);
conn.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:86.0) Gecko/20100101 Firefox/86.0"); conn.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:86.0) Gecko/20100101 Firefox/86.0");
try (final BufferedInputStream downloadStream = new BufferedInputStream(conn.getInputStream())) { try (BufferedInputStream downloadStream = new BufferedInputStream(conn.getInputStream())) {
final ByteArrayOutputStream byteArrayStream = new ByteArrayOutputStream(); ByteArrayOutputStream byteArrayStream = new ByteArrayOutputStream();
final byte[] buf = new byte[1024]; byte[] buf = new byte[1024];
int n; int n;
while ((n = downloadStream.read(buf)) > 0) { while ((n = downloadStream.read(buf)) > 0) {
byteArrayStream.write(buf, 0, n); byteArrayStream.write(buf, 0, n);
@ -39,23 +55,7 @@ public class DownloadUtilities {
// Closing a ByteArrayInputStream has no effect, so I do not close it. // Closing a ByteArrayInputStream has no effect, so I do not close it.
} }
public static InputStream DownloadToInputStream (final URL url) throws KeyManagementException, NoSuchAlgorithmException, IOException { public static InputStream DownloadToInputStream(URL url) throws KeyManagementException, NoSuchAlgorithmException, IOException {
return new ByteArrayInputStream(DownloadToByteArray(url)); return new ByteArrayInputStream(DownloadToByteArray(url));
} }
private static class DefaultTrustManager implements X509TrustManager {
@Override
public void checkClientTrusted (final X509Certificate[] arg0, final String arg1) {
}
@Override
public void checkServerTrusted (final X509Certificate[] arg0, final String arg1) {
}
@Override
public X509Certificate[] getAcceptedIssuers () {
return null;
}
}
} }

View file

@ -1,11 +1,11 @@
package land.chipmunk.chipmunkmod.util; package land.chipmunk.chipmunkmod.util;
public class MathUtilities { public class MathUtilities {
public static double clamp (final double value, final double min, final double max) { public static double clamp (double value, double min, double max) {
return Math.max(Math.min(value, max), min); return Math.max(Math.min(value, max), min);
} }
public static float clamp (final float value, final float min, final float max) { public static float clamp (float value, float min, float max) {
return Math.max(Math.min(value, max), min); return Math.max(Math.min(value, max), min);
} }
} }

View file

@ -12,7 +12,7 @@ public final class RandomUtilities {
return RandomUtilities.emptyUsername(random, '&'); return RandomUtilities.emptyUsername(random, '&');
} }
public static String emptyUsername (final Random random, final char colorChar) { public static String emptyUsername(final Random random, char colorChar) {
final char[] buf = new char[16]; final char[] buf = new char[16];
for (int i = 0; i < 16; i += 2) { for (int i = 0; i < 16; i += 2) {

View file

@ -4,7 +4,7 @@ import net.minecraft.client.MinecraftClient;
import net.minecraft.client.network.ClientPlayNetworkHandler; import net.minecraft.client.network.ClientPlayNetworkHandler;
public class ServerUtilities { public class ServerUtilities {
public static boolean serverHasCommand (final String name) { public static boolean serverHasCommand (String name) {
final MinecraftClient client = MinecraftClient.getInstance(); final MinecraftClient client = MinecraftClient.getInstance();
final ClientPlayNetworkHandler networkHandler = client.getNetworkHandler(); final ClientPlayNetworkHandler networkHandler = client.getNetworkHandler();

View file

@ -9,7 +9,7 @@ import net.minecraft.text.Text;
import net.minecraft.text.TextContent; import net.minecraft.text.TextContent;
public class TextUtilities { public class TextUtilities {
public static MutableText fromJson (final String json) { public static MutableText fromJson (String json) {
return Text.Serialization.fromJson( return Text.Serialization.fromJson(
json, json,
Suppliers.ofInstance(DynamicRegistryManager.of(Registries.REGISTRIES)).get() Suppliers.ofInstance(DynamicRegistryManager.of(Registries.REGISTRIES)).get()
@ -18,7 +18,7 @@ public class TextUtilities {
public static String plainOrNull(final Text text) { public static String plainOrNull(final Text text) {
final TextContent content = text.getContent(); final TextContent content = text.getContent();
if (!(content instanceof final PlainTextContent plainContent)) return null; if (!(content instanceof PlainTextContent plainContent)) return null;
return plainContent.string(); return plainContent.string();
} }

View file

@ -4,7 +4,7 @@ import java.nio.ByteBuffer;
import java.util.UUID; import java.util.UUID;
public class UUIDUtilities { public class UUIDUtilities {
public static int[] intArray (final UUID uuid) { public static int[] intArray (UUID uuid) {
final ByteBuffer buffer = ByteBuffer.wrap(new byte[16]); final ByteBuffer buffer = ByteBuffer.wrap(new byte[16]);
buffer.putLong(0, uuid.getMostSignificantBits()); buffer.putLong(0, uuid.getMostSignificantBits());
buffer.putLong(8, uuid.getLeastSignificantBits()); buffer.putLong(8, uuid.getLeastSignificantBits());
@ -15,10 +15,10 @@ public class UUIDUtilities {
return intArray; return intArray;
} }
public static String snbt (final UUID uuid) { public static String snbt (UUID uuid) {
final int[] array = intArray(uuid); int[] array = intArray(uuid);
return "[I;" + array[0] + "," + array[1] + "," + array[2] + "," + array[3] + "]"; // TODO: improve lol return "[I;" + array[0] + "," + array[1] + "," + array[2] + "," + array[3] + "]"; // TODO: improve lol
} }
public static String selector (final UUID uuid) { return "@a[limit=1,nbt={UUID:" + snbt(uuid) + "}]"; } public static String selector (UUID uuid) { return "@a[limit=1,nbt={UUID:" + snbt(uuid) + "}]"; }
} }

View file

@ -10,10 +10,11 @@ import org.spongepowered.configurate.serialize.TypeSerializer;
import java.lang.reflect.Type; import java.lang.reflect.Type;
public class BlockBoxTypeSerializer implements TypeSerializer<BlockBox> { public class BlockBoxTypeSerializer implements TypeSerializer<BlockBox> {
public static final BlockBoxTypeSerializer INSTANCE = new BlockBoxTypeSerializer();
private static final String START = "start"; private static final String START = "start";
private static final String END = "end"; private static final String END = "end";
public static final BlockBoxTypeSerializer INSTANCE = new BlockBoxTypeSerializer();
private BlockBoxTypeSerializer() { private BlockBoxTypeSerializer() {
} }

View file

@ -9,11 +9,12 @@ import org.spongepowered.configurate.serialize.TypeSerializer;
import java.lang.reflect.Type; import java.lang.reflect.Type;
public class BlockPosTypeSerializer implements TypeSerializer<BlockPos> { public class BlockPosTypeSerializer implements TypeSerializer<BlockPos> {
public static final BlockPosTypeSerializer INSTANCE = new BlockPosTypeSerializer();
private static final String X = "x"; private static final String X = "x";
private static final String Y = "y"; private static final String Y = "y";
private static final String Z = "z"; private static final String Z = "z";
public static final BlockPosTypeSerializer INSTANCE = new BlockPosTypeSerializer();
private BlockPosTypeSerializer() { private BlockPosTypeSerializer() {
} }

View file

@ -11,8 +11,8 @@ import org.spongepowered.configurate.serialize.TypeSerializer;
import java.lang.reflect.Type; import java.lang.reflect.Type;
public class ComponentTypeSerializer implements TypeSerializer<Component> { public class ComponentTypeSerializer implements TypeSerializer<Component> {
public static final ComponentTypeSerializer INSTANCE = new ComponentTypeSerializer();
private static final GsonComponentSerializer GSON = GsonComponentSerializer.gson(); private static final GsonComponentSerializer GSON = GsonComponentSerializer.gson();
public static final ComponentTypeSerializer INSTANCE = new ComponentTypeSerializer();
private ComponentTypeSerializer() { private ComponentTypeSerializer() {
} }