Config support
can prob be improved but that will be done later :trollface:
This commit is contained in:
parent
2023ae3cd1
commit
88dc82eb1e
17 changed files with 738 additions and 664 deletions
85
src/main/java/land/chipmunk/chipmunkmod/ChipmunkMod.java
Normal file → Executable file
85
src/main/java/land/chipmunk/chipmunkmod/ChipmunkMod.java
Normal file → Executable file
|
@ -1,21 +1,64 @@
|
|||
package land.chipmunk.chipmunkmod;
|
||||
|
||||
import net.fabricmc.api.ModInitializer;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class ChipmunkMod implements ModInitializer {
|
||||
// This logger is used to write text to the console and the log file.
|
||||
// It is considered best practice to use your mod id as the logger's name.
|
||||
// That way, it's clear which mod wrote info, warnings, and errors.
|
||||
public static final Logger LOGGER = LoggerFactory.getLogger("chipmunkmod");
|
||||
|
||||
@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.
|
||||
|
||||
LOGGER.info("Hello Fabric world!");
|
||||
}
|
||||
}
|
||||
package land.chipmunk.chipmunkmod;
|
||||
|
||||
import net.fabricmc.api.ModInitializer;
|
||||
import java.io.InputStream;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.File;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import com.google.gson.Gson;
|
||||
|
||||
public class ChipmunkMod implements ModInitializer {
|
||||
// This logger is used to write text to the console and the log file.
|
||||
// It is considered best practice to use your mod id as the logger's name.
|
||||
// That way, it's clear which mod wrote info, warnings, and errors.
|
||||
public static final Logger LOGGER = LoggerFactory.getLogger("chipmunkmod");
|
||||
public static Configuration CONFIG;
|
||||
|
||||
@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 {
|
||||
new File("config").mkdirs(); // TODO: Clean this up
|
||||
CONFIG = loadConfig();
|
||||
} catch (IOException exception) {
|
||||
throw new RuntimeException("Could not load the config", exception);
|
||||
}
|
||||
|
||||
LOGGER.info("Hello Fabric world!");
|
||||
}
|
||||
|
||||
public static Configuration loadConfig () throws IOException {
|
||||
final Gson gson = new Gson();
|
||||
final File file = new File("config/chipmunkmod.json");
|
||||
|
||||
if (!file.exists()) {
|
||||
InputStream is = ClassLoader.getSystemClassLoader().getResourceAsStream("default_config.json");
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
|
||||
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
while (reader.ready()) sb.append((char) reader.read());
|
||||
final String defaultConfig = sb.toString();
|
||||
|
||||
// Write the default config
|
||||
BufferedWriter configWriter = new BufferedWriter(new FileWriter(file));
|
||||
configWriter.write(defaultConfig);
|
||||
configWriter.close();
|
||||
|
||||
return gson.fromJson(defaultConfig, Configuration.class);
|
||||
}
|
||||
|
||||
InputStream is = new FileInputStream(file);
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
|
||||
|
||||
return gson.fromJson(reader, Configuration.class);
|
||||
}
|
||||
}
|
||||
|
|
17
src/main/java/land/chipmunk/chipmunkmod/Configuration.java
Executable file
17
src/main/java/land/chipmunk/chipmunkmod/Configuration.java
Executable file
|
@ -0,0 +1,17 @@
|
|||
package land.chipmunk.chipmunkmod;
|
||||
|
||||
import land.chipmunk.chipmunkmod.data.BlockArea;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
|
||||
public class Configuration {
|
||||
public CommandManager commands = new CommandManager();
|
||||
public CommandCore core = new CommandCore();
|
||||
|
||||
public class CommandManager {
|
||||
public String prefix = ".";
|
||||
}
|
||||
|
||||
public class CommandCore {
|
||||
public BlockArea relativeArea = new BlockArea(new BlockPos(0, 0, 0), new BlockPos(15, 0, 15));
|
||||
}
|
||||
}
|
145
src/main/java/land/chipmunk/chipmunkmod/command/CommandManager.java
Normal file → Executable file
145
src/main/java/land/chipmunk/chipmunkmod/command/CommandManager.java
Normal file → Executable file
|
@ -1,73 +1,74 @@
|
|||
package land.chipmunk.chipmunkmod.command;
|
||||
|
||||
import com.mojang.brigadier.CommandDispatcher;
|
||||
import com.mojang.brigadier.arguments.ArgumentType;
|
||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||
import com.mojang.brigadier.builder.RequiredArgumentBuilder;
|
||||
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||
import net.minecraft.command.CommandException;
|
||||
import net.minecraft.text.ClickEvent;
|
||||
import net.minecraft.text.Text;
|
||||
import net.minecraft.text.Texts;
|
||||
import net.minecraft.text.MutableText;
|
||||
import net.minecraft.util.Formatting;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource;
|
||||
import land.chipmunk.chipmunkmod.commands.*;
|
||||
|
||||
public class CommandManager {
|
||||
public static CommandDispatcher<FabricClientCommandSource> dispatcher = new CommandDispatcher();
|
||||
public static String prefix = ".";
|
||||
|
||||
public static void executeCommand (String command) {
|
||||
final MinecraftClient client = MinecraftClient.getInstance();
|
||||
|
||||
final FabricClientCommandSource commandSource = (FabricClientCommandSource) client.getNetworkHandler().getCommandSource();
|
||||
|
||||
try {
|
||||
dispatcher.execute(command, commandSource);
|
||||
} catch (CommandSyntaxException e) {
|
||||
commandSource.sendError(Texts.toText(e.getRawMessage()));
|
||||
final Text context = getContext(e);
|
||||
if (context != null) commandSource.sendError(context);
|
||||
} catch (CommandException e) {
|
||||
commandSource.sendError(e.getTextMessage());
|
||||
} catch (RuntimeException e) {
|
||||
commandSource.sendError(Text.of(e.getMessage()));
|
||||
}
|
||||
}
|
||||
|
||||
public static Text getContext (CommandSyntaxException exception) {
|
||||
final int _cursor = exception.getCursor();
|
||||
final String input = exception.getInput();
|
||||
|
||||
if (input == null || _cursor < 0) {
|
||||
return null;
|
||||
}
|
||||
final MutableText text = Text.literal("")
|
||||
.formatted(Formatting.GRAY);
|
||||
text.setStyle(text.getStyle().withClickEvent(new ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, prefix + input)));
|
||||
|
||||
final int cursor = Math.min(input.length(), _cursor);
|
||||
|
||||
if (cursor > CommandSyntaxException.CONTEXT_AMOUNT) {
|
||||
text.append(Text.literal("..."));
|
||||
}
|
||||
|
||||
text
|
||||
.append(Text.literal(input.substring(Math.max(0, cursor - CommandSyntaxException.CONTEXT_AMOUNT), cursor)))
|
||||
.append(Text.literal(input.substring(cursor)).formatted(Formatting.RED, Formatting.UNDERLINE))
|
||||
.append(Text.translatable("command.context.here").formatted(Formatting.RED, Formatting.ITALIC));
|
||||
|
||||
return text;
|
||||
}
|
||||
|
||||
public static LiteralArgumentBuilder<FabricClientCommandSource> literal (String name) { return LiteralArgumentBuilder.<FabricClientCommandSource>literal(name); }
|
||||
public static <T> RequiredArgumentBuilder<FabricClientCommandSource, T> argument (String name, ArgumentType<T> type) { return RequiredArgumentBuilder.<FabricClientCommandSource, T>argument(name, type); }
|
||||
|
||||
static {
|
||||
TestCommand.register(dispatcher);
|
||||
CoreCommand.register(dispatcher);
|
||||
UsernameCommand.register(dispatcher);
|
||||
}
|
||||
package land.chipmunk.chipmunkmod.command;
|
||||
|
||||
import com.mojang.brigadier.CommandDispatcher;
|
||||
import com.mojang.brigadier.arguments.ArgumentType;
|
||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||
import com.mojang.brigadier.builder.RequiredArgumentBuilder;
|
||||
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||
import net.minecraft.command.CommandException;
|
||||
import net.minecraft.text.ClickEvent;
|
||||
import net.minecraft.text.Text;
|
||||
import net.minecraft.text.Texts;
|
||||
import net.minecraft.text.MutableText;
|
||||
import net.minecraft.util.Formatting;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource;
|
||||
import land.chipmunk.chipmunkmod.ChipmunkMod;
|
||||
import land.chipmunk.chipmunkmod.commands.*;
|
||||
|
||||
public class CommandManager {
|
||||
public static CommandDispatcher<FabricClientCommandSource> dispatcher = new CommandDispatcher();
|
||||
public static String prefix = ChipmunkMod.CONFIG.commands.prefix;
|
||||
|
||||
public static void executeCommand (String command) {
|
||||
final MinecraftClient client = MinecraftClient.getInstance();
|
||||
|
||||
final FabricClientCommandSource commandSource = (FabricClientCommandSource) client.getNetworkHandler().getCommandSource();
|
||||
|
||||
try {
|
||||
dispatcher.execute(command, commandSource);
|
||||
} catch (CommandSyntaxException e) {
|
||||
commandSource.sendError(Texts.toText(e.getRawMessage()));
|
||||
final Text context = getContext(e);
|
||||
if (context != null) commandSource.sendError(context);
|
||||
} catch (CommandException e) {
|
||||
commandSource.sendError(e.getTextMessage());
|
||||
} catch (RuntimeException e) {
|
||||
commandSource.sendError(Text.of(e.getMessage()));
|
||||
}
|
||||
}
|
||||
|
||||
public static Text getContext (CommandSyntaxException exception) {
|
||||
final int _cursor = exception.getCursor();
|
||||
final String input = exception.getInput();
|
||||
|
||||
if (input == null || _cursor < 0) {
|
||||
return null;
|
||||
}
|
||||
final MutableText text = Text.literal("")
|
||||
.formatted(Formatting.GRAY);
|
||||
text.setStyle(text.getStyle().withClickEvent(new ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, prefix + input)));
|
||||
|
||||
final int cursor = Math.min(input.length(), _cursor);
|
||||
|
||||
if (cursor > CommandSyntaxException.CONTEXT_AMOUNT) {
|
||||
text.append(Text.literal("..."));
|
||||
}
|
||||
|
||||
text
|
||||
.append(Text.literal(input.substring(Math.max(0, cursor - CommandSyntaxException.CONTEXT_AMOUNT), cursor)))
|
||||
.append(Text.literal(input.substring(cursor)).formatted(Formatting.RED, Formatting.UNDERLINE))
|
||||
.append(Text.translatable("command.context.here").formatted(Formatting.RED, Formatting.ITALIC));
|
||||
|
||||
return text;
|
||||
}
|
||||
|
||||
public static LiteralArgumentBuilder<FabricClientCommandSource> literal (String name) { return LiteralArgumentBuilder.<FabricClientCommandSource>literal(name); }
|
||||
public static <T> RequiredArgumentBuilder<FabricClientCommandSource, T> argument (String name, ArgumentType<T> type) { return RequiredArgumentBuilder.<FabricClientCommandSource, T>argument(name, type); }
|
||||
|
||||
static {
|
||||
TestCommand.register(dispatcher);
|
||||
CoreCommand.register(dispatcher);
|
||||
UsernameCommand.register(dispatcher);
|
||||
}
|
||||
}
|
158
src/main/java/land/chipmunk/chipmunkmod/commands/CoreCommand.java
Normal file → Executable file
158
src/main/java/land/chipmunk/chipmunkmod/commands/CoreCommand.java
Normal file → Executable file
|
@ -1,79 +1,79 @@
|
|||
package land.chipmunk.chipmunkmod.commands;
|
||||
|
||||
import com.mojang.brigadier.Command;
|
||||
import com.mojang.brigadier.CommandDispatcher;
|
||||
import com.mojang.brigadier.context.CommandContext;
|
||||
import static land.chipmunk.chipmunkmod.command.CommandManager.literal;
|
||||
import static land.chipmunk.chipmunkmod.command.CommandManager.argument;
|
||||
import static com.mojang.brigadier.arguments.StringArgumentType.greedyString;
|
||||
import static com.mojang.brigadier.arguments.StringArgumentType.getString;
|
||||
import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource;
|
||||
import net.minecraft.text.Text;
|
||||
import net.minecraft.nbt.NbtCompound;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import land.chipmunk.chipmunkmod.modules.CommandCore;
|
||||
|
||||
public class CoreCommand {
|
||||
public static void register (CommandDispatcher<FabricClientCommandSource> dispatcher) {
|
||||
dispatcher.register(
|
||||
literal("core")
|
||||
.then(
|
||||
literal("run")
|
||||
.then(
|
||||
argument("command", greedyString())
|
||||
.executes(c -> run(c))
|
||||
)
|
||||
)
|
||||
|
||||
.then(
|
||||
literal("runTracked")
|
||||
.then(
|
||||
argument("command", greedyString())
|
||||
.executes(c -> runTracked(c))
|
||||
)
|
||||
)
|
||||
|
||||
.then(literal("refill").executes(c -> refill(c)))
|
||||
.then(literal("move").executes(c -> move(c)))
|
||||
);
|
||||
}
|
||||
|
||||
public static int run (CommandContext<FabricClientCommandSource> context) {
|
||||
CommandCore.INSTANCE.run(getString(context, "command"));
|
||||
|
||||
return Command.SINGLE_SUCCESS;
|
||||
}
|
||||
|
||||
public static int runTracked (CommandContext<FabricClientCommandSource> context) {
|
||||
final FabricClientCommandSource source = context.getSource();
|
||||
|
||||
final String command = getString(context, "command");
|
||||
|
||||
final CompletableFuture<NbtCompound> future = CommandCore.INSTANCE.runTracked(command);
|
||||
future.thenApply(tag -> {
|
||||
try {
|
||||
final String output = tag.getString("LastOutput");
|
||||
if (output != null) source.sendFeedback(Text.Serializer.fromJson(output));
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
|
||||
return tag;
|
||||
});
|
||||
|
||||
return Command.SINGLE_SUCCESS;
|
||||
}
|
||||
|
||||
public static int refill (CommandContext<FabricClientCommandSource> context) {
|
||||
CommandCore.INSTANCE.refill();
|
||||
|
||||
return Command.SINGLE_SUCCESS;
|
||||
}
|
||||
|
||||
public static int move (CommandContext<FabricClientCommandSource> context) {
|
||||
final FabricClientCommandSource source = context.getSource();
|
||||
|
||||
CommandCore.INSTANCE.move(source.getClient().player.getPos());
|
||||
|
||||
return Command.SINGLE_SUCCESS;
|
||||
}
|
||||
}
|
||||
package land.chipmunk.chipmunkmod.commands;
|
||||
|
||||
import com.mojang.brigadier.Command;
|
||||
import com.mojang.brigadier.CommandDispatcher;
|
||||
import com.mojang.brigadier.context.CommandContext;
|
||||
import static land.chipmunk.chipmunkmod.command.CommandManager.literal;
|
||||
import static land.chipmunk.chipmunkmod.command.CommandManager.argument;
|
||||
import static com.mojang.brigadier.arguments.StringArgumentType.greedyString;
|
||||
import static com.mojang.brigadier.arguments.StringArgumentType.getString;
|
||||
import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource;
|
||||
import net.minecraft.text.Text;
|
||||
import net.minecraft.nbt.NbtCompound;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import land.chipmunk.chipmunkmod.modules.CommandCore;
|
||||
|
||||
public class CoreCommand {
|
||||
public static void register (CommandDispatcher<FabricClientCommandSource> dispatcher) {
|
||||
dispatcher.register(
|
||||
literal("core")
|
||||
.then(
|
||||
literal("run")
|
||||
.then(
|
||||
argument("command", greedyString())
|
||||
.executes(c -> run(c))
|
||||
)
|
||||
)
|
||||
|
||||
.then(
|
||||
literal("runTracked")
|
||||
.then(
|
||||
argument("command", greedyString())
|
||||
.executes(c -> runTracked(c))
|
||||
)
|
||||
)
|
||||
|
||||
.then(literal("refill").executes(c -> refill(c)))
|
||||
.then(literal("move").executes(c -> move(c)))
|
||||
);
|
||||
}
|
||||
|
||||
public static int run (CommandContext<FabricClientCommandSource> context) {
|
||||
CommandCore.INSTANCE.run(getString(context, "command"));
|
||||
|
||||
return Command.SINGLE_SUCCESS;
|
||||
}
|
||||
|
||||
public static int runTracked (CommandContext<FabricClientCommandSource> context) {
|
||||
final FabricClientCommandSource source = context.getSource();
|
||||
|
||||
final String command = getString(context, "command");
|
||||
|
||||
final CompletableFuture<NbtCompound> future = CommandCore.INSTANCE.runTracked(command);
|
||||
future.thenApply(tag -> {
|
||||
try {
|
||||
final String output = tag.getString("LastOutput");
|
||||
if (output != null) source.sendFeedback(Text.Serializer.fromJson(output));
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
|
||||
return tag;
|
||||
});
|
||||
|
||||
return Command.SINGLE_SUCCESS;
|
||||
}
|
||||
|
||||
public static int refill (CommandContext<FabricClientCommandSource> context) {
|
||||
CommandCore.INSTANCE.refill();
|
||||
|
||||
return Command.SINGLE_SUCCESS;
|
||||
}
|
||||
|
||||
public static int move (CommandContext<FabricClientCommandSource> context) {
|
||||
final FabricClientCommandSource source = context.getSource();
|
||||
|
||||
CommandCore.INSTANCE.move(source.getClient().player.getPos());
|
||||
|
||||
return Command.SINGLE_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
|
48
src/main/java/land/chipmunk/chipmunkmod/commands/TestCommand.java
Normal file → Executable file
48
src/main/java/land/chipmunk/chipmunkmod/commands/TestCommand.java
Normal file → Executable file
|
@ -1,24 +1,24 @@
|
|||
package land.chipmunk.chipmunkmod.commands;
|
||||
|
||||
import com.mojang.brigadier.Command;
|
||||
import com.mojang.brigadier.CommandDispatcher;
|
||||
import com.mojang.brigadier.context.CommandContext;
|
||||
import static land.chipmunk.chipmunkmod.command.CommandManager.literal;
|
||||
import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource;
|
||||
import net.minecraft.text.Text;
|
||||
|
||||
public class TestCommand {
|
||||
public static void register (CommandDispatcher<FabricClientCommandSource> dispatcher) {
|
||||
dispatcher.register(
|
||||
literal("test")
|
||||
.executes(c -> helloWorld(c))
|
||||
);
|
||||
}
|
||||
|
||||
public static int helloWorld (CommandContext<FabricClientCommandSource> context) {
|
||||
final FabricClientCommandSource source = context.getSource();
|
||||
source.sendFeedback(Text.literal("Hello, world!"));
|
||||
|
||||
return Command.SINGLE_SUCCESS;
|
||||
}
|
||||
}
|
||||
package land.chipmunk.chipmunkmod.commands;
|
||||
|
||||
import com.mojang.brigadier.Command;
|
||||
import com.mojang.brigadier.CommandDispatcher;
|
||||
import com.mojang.brigadier.context.CommandContext;
|
||||
import static land.chipmunk.chipmunkmod.command.CommandManager.literal;
|
||||
import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource;
|
||||
import net.minecraft.text.Text;
|
||||
|
||||
public class TestCommand {
|
||||
public static void register (CommandDispatcher<FabricClientCommandSource> dispatcher) {
|
||||
dispatcher.register(
|
||||
literal("test")
|
||||
.executes(c -> helloWorld(c))
|
||||
);
|
||||
}
|
||||
|
||||
public static int helloWorld (CommandContext<FabricClientCommandSource> context) {
|
||||
final FabricClientCommandSource source = context.getSource();
|
||||
source.sendFeedback(Text.literal("Hello, world!"));
|
||||
|
||||
return Command.SINGLE_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
|
134
src/main/java/land/chipmunk/chipmunkmod/commands/UsernameCommand.java
Normal file → Executable file
134
src/main/java/land/chipmunk/chipmunkmod/commands/UsernameCommand.java
Normal file → Executable file
|
@ -1,67 +1,67 @@
|
|||
package land.chipmunk.chipmunkmod.commands;
|
||||
|
||||
import com.mojang.brigadier.Command;
|
||||
import com.mojang.brigadier.CommandDispatcher;
|
||||
import com.mojang.brigadier.context.CommandContext;
|
||||
import static com.mojang.brigadier.arguments.StringArgumentType.greedyString;
|
||||
import static com.mojang.brigadier.arguments.StringArgumentType.getString;
|
||||
import static land.chipmunk.chipmunkmod.command.CommandManager.literal;
|
||||
import static land.chipmunk.chipmunkmod.command.CommandManager.argument;
|
||||
import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.client.gui.screen.ConnectScreen;
|
||||
import net.minecraft.client.gui.screen.TitleScreen;
|
||||
import net.minecraft.client.gui.screen.multiplayer.MultiplayerScreen;
|
||||
import net.minecraft.client.network.ServerInfo;
|
||||
import net.minecraft.client.network.ServerAddress;
|
||||
import net.minecraft.client.util.Session;
|
||||
import net.minecraft.text.Text;
|
||||
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||
import com.mojang.brigadier.exceptions.SimpleCommandExceptionType;
|
||||
import java.util.Optional;
|
||||
import land.chipmunk.chipmunkmod.mixin.MinecraftClientAccessor;
|
||||
|
||||
public class UsernameCommand {
|
||||
private static final Session ORIGINAL_SESSION = ((MinecraftClientAccessor) MinecraftClient.getInstance()).session();
|
||||
private static final SimpleCommandExceptionType USERNAME_TOO_LONG = new SimpleCommandExceptionType(Text.translatable("The specified username is longer than 16 characters"));
|
||||
|
||||
public static void register (CommandDispatcher<FabricClientCommandSource> dispatcher) {
|
||||
dispatcher.register(
|
||||
literal("username")
|
||||
.then(
|
||||
literal("set")
|
||||
.then(
|
||||
argument("username", greedyString())
|
||||
.executes(c -> updateUsername(c))
|
||||
)
|
||||
)
|
||||
.then(
|
||||
literal("revert")
|
||||
.executes(c -> updateSession(c, ORIGINAL_SESSION))
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
public static int updateUsername (CommandContext<FabricClientCommandSource> context) throws CommandSyntaxException {
|
||||
final String username = getString(context, "username");
|
||||
if (username.length() > 16) throw USERNAME_TOO_LONG.create();
|
||||
final Session session = new Session(username, "", "", Optional.empty(), Optional.empty(), Session.AccountType.MOJANG);
|
||||
return updateSession(context, session);
|
||||
}
|
||||
|
||||
public static int updateSession (CommandContext<FabricClientCommandSource> context, Session session) throws CommandSyntaxException {
|
||||
final FabricClientCommandSource source = context.getSource();
|
||||
|
||||
final MinecraftClient client = source.getClient();
|
||||
|
||||
((MinecraftClientAccessor) client).session(session);
|
||||
|
||||
// TODO: Put this in a separate class
|
||||
final ServerInfo info = client.getCurrentServerEntry();
|
||||
client.world.disconnect();
|
||||
client.disconnect();
|
||||
ConnectScreen.connect(new MultiplayerScreen(new TitleScreen()), client, ServerAddress.parse(info.address), info);
|
||||
|
||||
return Command.SINGLE_SUCCESS;
|
||||
}
|
||||
}
|
||||
package land.chipmunk.chipmunkmod.commands;
|
||||
|
||||
import com.mojang.brigadier.Command;
|
||||
import com.mojang.brigadier.CommandDispatcher;
|
||||
import com.mojang.brigadier.context.CommandContext;
|
||||
import static com.mojang.brigadier.arguments.StringArgumentType.greedyString;
|
||||
import static com.mojang.brigadier.arguments.StringArgumentType.getString;
|
||||
import static land.chipmunk.chipmunkmod.command.CommandManager.literal;
|
||||
import static land.chipmunk.chipmunkmod.command.CommandManager.argument;
|
||||
import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.client.gui.screen.ConnectScreen;
|
||||
import net.minecraft.client.gui.screen.TitleScreen;
|
||||
import net.minecraft.client.gui.screen.multiplayer.MultiplayerScreen;
|
||||
import net.minecraft.client.network.ServerInfo;
|
||||
import net.minecraft.client.network.ServerAddress;
|
||||
import net.minecraft.client.util.Session;
|
||||
import net.minecraft.text.Text;
|
||||
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||
import com.mojang.brigadier.exceptions.SimpleCommandExceptionType;
|
||||
import java.util.Optional;
|
||||
import land.chipmunk.chipmunkmod.mixin.MinecraftClientAccessor;
|
||||
|
||||
public class UsernameCommand {
|
||||
private static final Session ORIGINAL_SESSION = ((MinecraftClientAccessor) MinecraftClient.getInstance()).session();
|
||||
private static final SimpleCommandExceptionType USERNAME_TOO_LONG = new SimpleCommandExceptionType(Text.translatable("The specified username is longer than 16 characters"));
|
||||
|
||||
public static void register (CommandDispatcher<FabricClientCommandSource> dispatcher) {
|
||||
dispatcher.register(
|
||||
literal("username")
|
||||
.then(
|
||||
literal("set")
|
||||
.then(
|
||||
argument("username", greedyString())
|
||||
.executes(c -> updateUsername(c))
|
||||
)
|
||||
)
|
||||
.then(
|
||||
literal("revert")
|
||||
.executes(c -> updateSession(c, ORIGINAL_SESSION))
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
public static int updateUsername (CommandContext<FabricClientCommandSource> context) throws CommandSyntaxException {
|
||||
final String username = getString(context, "username");
|
||||
if (username.length() > 16) throw USERNAME_TOO_LONG.create();
|
||||
final Session session = new Session(username, "", "", Optional.empty(), Optional.empty(), Session.AccountType.MOJANG);
|
||||
return updateSession(context, session);
|
||||
}
|
||||
|
||||
public static int updateSession (CommandContext<FabricClientCommandSource> context, Session session) throws CommandSyntaxException {
|
||||
final FabricClientCommandSource source = context.getSource();
|
||||
|
||||
final MinecraftClient client = source.getClient();
|
||||
|
||||
((MinecraftClientAccessor) client).session(session);
|
||||
|
||||
// TODO: Put this in a separate class
|
||||
final ServerInfo info = client.getCurrentServerEntry();
|
||||
client.world.disconnect();
|
||||
client.disconnect();
|
||||
ConnectScreen.connect(new MultiplayerScreen(new TitleScreen()), client, ServerAddress.parse(info.address), info);
|
||||
|
||||
return Command.SINGLE_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
|
26
src/main/java/land/chipmunk/chipmunkmod/data/BlockArea.java
Normal file → Executable file
26
src/main/java/land/chipmunk/chipmunkmod/data/BlockArea.java
Normal file → Executable file
|
@ -1,13 +1,13 @@
|
|||
package land.chipmunk.chipmunkmod.data;
|
||||
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
|
||||
// ? Am I reinventing the wheel here?
|
||||
@AllArgsConstructor
|
||||
@Data
|
||||
public class BlockArea {
|
||||
private BlockPos start;
|
||||
private BlockPos end;
|
||||
}
|
||||
package land.chipmunk.chipmunkmod.data;
|
||||
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
|
||||
// ? Am I reinventing the wheel here?
|
||||
@AllArgsConstructor
|
||||
@Data
|
||||
public class BlockArea {
|
||||
private BlockPos start;
|
||||
private BlockPos end;
|
||||
}
|
||||
|
|
100
src/main/java/land/chipmunk/chipmunkmod/mixin/ChatInputSuggestorMixin.java
Normal file → Executable file
100
src/main/java/land/chipmunk/chipmunkmod/mixin/ChatInputSuggestorMixin.java
Normal file → Executable file
|
@ -1,50 +1,50 @@
|
|||
package land.chipmunk.chipmunkmod.mixin;
|
||||
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import com.mojang.brigadier.suggestion.Suggestions;
|
||||
import net.minecraft.client.gui.widget.TextFieldWidget;
|
||||
import com.mojang.brigadier.CommandDispatcher;
|
||||
import com.mojang.brigadier.StringReader;
|
||||
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||
import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import land.chipmunk.chipmunkmod.command.CommandManager;
|
||||
|
||||
@Mixin(net.minecraft.client.gui.screen.ChatInputSuggestor.class)
|
||||
public class ChatInputSuggestorMixin {
|
||||
@Shadow
|
||||
CompletableFuture<Suggestions> pendingSuggestions;
|
||||
|
||||
@Shadow
|
||||
public void show (boolean narrateFirstSuggestion) {}
|
||||
|
||||
@Shadow
|
||||
final TextFieldWidget textField;
|
||||
|
||||
public ChatInputSuggestorMixin () {
|
||||
textField = null;
|
||||
}
|
||||
|
||||
@Inject(at = @At("TAIL"), method = "refresh()V")
|
||||
public void onRefresh (CallbackInfo ci) {
|
||||
final String text = this.textField.getText();
|
||||
final int cursor = this.textField.getCursor();
|
||||
|
||||
if (cursor < CommandManager.prefix.length() || !text.startsWith(CommandManager.prefix)) return;
|
||||
|
||||
final StringReader reader = new StringReader(text);
|
||||
reader.setCursor(CommandManager.prefix.length()); // Skip the prefix
|
||||
|
||||
final CommandDispatcher<FabricClientCommandSource> dispatcher = CommandManager.dispatcher;
|
||||
final MinecraftClient client = MinecraftClient.getInstance();
|
||||
final FabricClientCommandSource commandSource = (FabricClientCommandSource) client.getNetworkHandler().getCommandSource();
|
||||
|
||||
pendingSuggestions = dispatcher.getCompletionSuggestions(dispatcher.parse(reader, commandSource), cursor);
|
||||
show(true);
|
||||
}
|
||||
}
|
||||
package land.chipmunk.chipmunkmod.mixin;
|
||||
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import com.mojang.brigadier.suggestion.Suggestions;
|
||||
import net.minecraft.client.gui.widget.TextFieldWidget;
|
||||
import com.mojang.brigadier.CommandDispatcher;
|
||||
import com.mojang.brigadier.StringReader;
|
||||
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||
import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import land.chipmunk.chipmunkmod.command.CommandManager;
|
||||
|
||||
@Mixin(net.minecraft.client.gui.screen.ChatInputSuggestor.class)
|
||||
public class ChatInputSuggestorMixin {
|
||||
@Shadow
|
||||
CompletableFuture<Suggestions> pendingSuggestions;
|
||||
|
||||
@Shadow
|
||||
public void show (boolean narrateFirstSuggestion) {}
|
||||
|
||||
@Shadow
|
||||
final TextFieldWidget textField;
|
||||
|
||||
public ChatInputSuggestorMixin () {
|
||||
textField = null;
|
||||
}
|
||||
|
||||
@Inject(at = @At("TAIL"), method = "refresh()V")
|
||||
public void onRefresh (CallbackInfo ci) {
|
||||
final String text = this.textField.getText();
|
||||
final int cursor = this.textField.getCursor();
|
||||
|
||||
if (cursor < CommandManager.prefix.length() || !text.startsWith(CommandManager.prefix)) return;
|
||||
|
||||
final StringReader reader = new StringReader(text);
|
||||
reader.setCursor(CommandManager.prefix.length()); // Skip the prefix
|
||||
|
||||
final CommandDispatcher<FabricClientCommandSource> dispatcher = CommandManager.dispatcher;
|
||||
final MinecraftClient client = MinecraftClient.getInstance();
|
||||
final FabricClientCommandSource commandSource = (FabricClientCommandSource) client.getNetworkHandler().getCommandSource();
|
||||
|
||||
pendingSuggestions = dispatcher.getCompletionSuggestions(dispatcher.parse(reader, commandSource), cursor);
|
||||
show(true);
|
||||
}
|
||||
}
|
||||
|
|
44
src/main/java/land/chipmunk/chipmunkmod/mixin/ChatScreenMixin.java
Normal file → Executable file
44
src/main/java/land/chipmunk/chipmunkmod/mixin/ChatScreenMixin.java
Normal file → Executable file
|
@ -1,22 +1,22 @@
|
|||
package land.chipmunk.chipmunkmod.mixin;
|
||||
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import land.chipmunk.chipmunkmod.command.CommandManager;
|
||||
|
||||
@Mixin(net.minecraft.client.gui.screen.ChatScreen.class)
|
||||
public class ChatScreenMixin {
|
||||
@Inject(at = @At("HEAD"), method = "sendMessage", cancellable = true)
|
||||
public void sendMessage(String chatText, boolean addToHistory, CallbackInfoReturnable<Boolean> cir) {
|
||||
if (chatText.startsWith(CommandManager.prefix)) {
|
||||
CommandManager.executeCommand(chatText.substring(CommandManager.prefix.length()));
|
||||
|
||||
if (addToHistory) MinecraftClient.getInstance().inGameHud.getChatHud().addToMessageHistory(chatText);
|
||||
|
||||
cir.setReturnValue(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
package land.chipmunk.chipmunkmod.mixin;
|
||||
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import land.chipmunk.chipmunkmod.command.CommandManager;
|
||||
|
||||
@Mixin(net.minecraft.client.gui.screen.ChatScreen.class)
|
||||
public class ChatScreenMixin {
|
||||
@Inject(at = @At("HEAD"), method = "sendMessage", cancellable = true)
|
||||
public void sendMessage(String chatText, boolean addToHistory, CallbackInfoReturnable<Boolean> cir) {
|
||||
if (chatText.startsWith(CommandManager.prefix)) {
|
||||
CommandManager.executeCommand(chatText.substring(CommandManager.prefix.length()));
|
||||
|
||||
if (addToHistory) MinecraftClient.getInstance().inGameHud.getChatHud().addToMessageHistory(chatText);
|
||||
|
||||
cir.setReturnValue(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
40
src/main/java/land/chipmunk/chipmunkmod/mixin/ClientConnectionMixin.java
Normal file → Executable file
40
src/main/java/land/chipmunk/chipmunkmod/mixin/ClientConnectionMixin.java
Normal file → Executable file
|
@ -1,20 +1,20 @@
|
|||
package land.chipmunk.chipmunkmod.mixin;
|
||||
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
import net.minecraft.client.network.ClientPlayNetworkHandler;
|
||||
import net.minecraft.text.Text;
|
||||
import land.chipmunk.chipmunkmod.modules.CommandCore;
|
||||
import land.chipmunk.chipmunkmod.modules.SelfCare;
|
||||
|
||||
@Mixin(net.minecraft.network.ClientConnection.class)
|
||||
public class ClientConnectionMixin {
|
||||
@Inject(at = @At("HEAD"), method = "disconnect", cancellable = true)
|
||||
public void disconnect (Text disconnectReason, CallbackInfo ci) {
|
||||
if (disconnectReason == ClientPlayNetworkHandlerAccessor.chatValidationFailedText()) {
|
||||
ci.cancel();
|
||||
}
|
||||
}
|
||||
}
|
||||
package land.chipmunk.chipmunkmod.mixin;
|
||||
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
import net.minecraft.client.network.ClientPlayNetworkHandler;
|
||||
import net.minecraft.text.Text;
|
||||
import land.chipmunk.chipmunkmod.modules.CommandCore;
|
||||
import land.chipmunk.chipmunkmod.modules.SelfCare;
|
||||
|
||||
@Mixin(net.minecraft.network.ClientConnection.class)
|
||||
public class ClientConnectionMixin {
|
||||
@Inject(at = @At("HEAD"), method = "disconnect", cancellable = true)
|
||||
public void disconnect (Text disconnectReason, CallbackInfo ci) {
|
||||
if (disconnectReason == ClientPlayNetworkHandlerAccessor.chatValidationFailedText()) {
|
||||
ci.cancel();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
22
src/main/java/land/chipmunk/chipmunkmod/mixin/ClientPlayNetworkHandlerAccessor.java
Normal file → Executable file
22
src/main/java/land/chipmunk/chipmunkmod/mixin/ClientPlayNetworkHandlerAccessor.java
Normal file → Executable file
|
@ -1,11 +1,11 @@
|
|||
package land.chipmunk.chipmunkmod.mixin;
|
||||
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.gen.Accessor;
|
||||
import net.minecraft.text.Text;
|
||||
|
||||
@Mixin(net.minecraft.client.network.ClientPlayNetworkHandler.class)
|
||||
public interface ClientPlayNetworkHandlerAccessor {
|
||||
@Accessor("CHAT_VALIDATION_FAILED_TEXT")
|
||||
public static Text chatValidationFailedText () { throw new AssertionError(); }
|
||||
}
|
||||
package land.chipmunk.chipmunkmod.mixin;
|
||||
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.gen.Accessor;
|
||||
import net.minecraft.text.Text;
|
||||
|
||||
@Mixin(net.minecraft.client.network.ClientPlayNetworkHandler.class)
|
||||
public interface ClientPlayNetworkHandlerAccessor {
|
||||
@Accessor("CHAT_VALIDATION_FAILED_TEXT")
|
||||
public static Text chatValidationFailedText () { throw new AssertionError(); }
|
||||
}
|
||||
|
|
32
src/main/java/land/chipmunk/chipmunkmod/mixin/ClientPlayNetworkHandlerMixin.java
Normal file → Executable file
32
src/main/java/land/chipmunk/chipmunkmod/mixin/ClientPlayNetworkHandlerMixin.java
Normal file → Executable file
|
@ -1,16 +1,16 @@
|
|||
package land.chipmunk.chipmunkmod.mixin;
|
||||
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
import net.minecraft.network.packet.s2c.play.GameJoinS2CPacket;
|
||||
import land.chipmunk.chipmunkmod.modules.SelfCare;
|
||||
|
||||
@Mixin(net.minecraft.client.network.ClientPlayNetworkHandler.class)
|
||||
public class ClientPlayNetworkHandlerMixin {
|
||||
@Inject(method = "onGameJoin", at = @At("TAIL"))
|
||||
private void onGameJoin (GameJoinS2CPacket packet, CallbackInfo ci) {
|
||||
SelfCare.INSTANCE.init();
|
||||
}
|
||||
}
|
||||
package land.chipmunk.chipmunkmod.mixin;
|
||||
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
import net.minecraft.network.packet.s2c.play.GameJoinS2CPacket;
|
||||
import land.chipmunk.chipmunkmod.modules.SelfCare;
|
||||
|
||||
@Mixin(net.minecraft.client.network.ClientPlayNetworkHandler.class)
|
||||
public class ClientPlayNetworkHandlerMixin {
|
||||
@Inject(method = "onGameJoin", at = @At("TAIL"))
|
||||
private void onGameJoin (GameJoinS2CPacket packet, CallbackInfo ci) {
|
||||
SelfCare.INSTANCE.init();
|
||||
}
|
||||
}
|
||||
|
|
68
src/main/java/land/chipmunk/chipmunkmod/mixin/ClientPlayerEntityMixin.java
Normal file → Executable file
68
src/main/java/land/chipmunk/chipmunkmod/mixin/ClientPlayerEntityMixin.java
Normal file → Executable file
|
@ -1,34 +1,34 @@
|
|||
package land.chipmunk.chipmunkmod.mixin;
|
||||
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
import net.minecraft.client.network.ClientPlayerEntity;
|
||||
import net.minecraft.entity.MovementType;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.client.world.ClientWorld;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Vec2f;
|
||||
import land.chipmunk.chipmunkmod.modules.CommandCore;
|
||||
|
||||
@Mixin(ClientPlayerEntity.class)
|
||||
public class ClientPlayerEntityMixin {
|
||||
private static MinecraftClient CLIENT = MinecraftClient.getInstance();
|
||||
|
||||
@Inject(at = @At("HEAD"), method = "move")
|
||||
public void move (MovementType type, Vec3d relPos, CallbackInfo ci) {
|
||||
if ((ClientPlayerEntity) (Object) this != CLIENT.player) return;
|
||||
|
||||
final Vec3d position = ((ClientPlayerEntity) (Object) this).getPos().add(relPos);
|
||||
|
||||
final ClientWorld world = CLIENT.getNetworkHandler().getWorld();
|
||||
|
||||
final BlockPos origin = CommandCore.INSTANCE.origin();
|
||||
if (origin == null) { CommandCore.INSTANCE.move(position); return; }
|
||||
final int distance = (int) Math.sqrt(new Vec2f(origin.getX() / 16, origin.getZ() / 16).distanceSquared(new Vec2f((int) position.getX() / 16, (int) position.getZ() / 16)));
|
||||
if (distance > world.getSimulationDistance()) CommandCore.INSTANCE.move(position);
|
||||
}
|
||||
}
|
||||
package land.chipmunk.chipmunkmod.mixin;
|
||||
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
import net.minecraft.client.network.ClientPlayerEntity;
|
||||
import net.minecraft.entity.MovementType;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.client.world.ClientWorld;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Vec2f;
|
||||
import land.chipmunk.chipmunkmod.modules.CommandCore;
|
||||
|
||||
@Mixin(ClientPlayerEntity.class)
|
||||
public class ClientPlayerEntityMixin {
|
||||
private static MinecraftClient CLIENT = MinecraftClient.getInstance();
|
||||
|
||||
@Inject(at = @At("HEAD"), method = "move")
|
||||
public void move (MovementType type, Vec3d relPos, CallbackInfo ci) {
|
||||
if ((ClientPlayerEntity) (Object) this != CLIENT.player) return;
|
||||
|
||||
final Vec3d position = ((ClientPlayerEntity) (Object) this).getPos().add(relPos);
|
||||
|
||||
final ClientWorld world = CLIENT.getNetworkHandler().getWorld();
|
||||
|
||||
final BlockPos origin = CommandCore.INSTANCE.origin();
|
||||
if (origin == null) { CommandCore.INSTANCE.move(position); return; }
|
||||
final int distance = (int) Math.sqrt(new Vec2f(origin.getX() / 16, origin.getZ() / 16).distanceSquared(new Vec2f((int) position.getX() / 16, (int) position.getZ() / 16)));
|
||||
if (distance > world.getSimulationDistance()) CommandCore.INSTANCE.move(position);
|
||||
}
|
||||
}
|
||||
|
|
32
src/main/java/land/chipmunk/chipmunkmod/mixin/MinecraftClientAccessor.java
Normal file → Executable file
32
src/main/java/land/chipmunk/chipmunkmod/mixin/MinecraftClientAccessor.java
Normal file → Executable file
|
@ -1,16 +1,16 @@
|
|||
package land.chipmunk.chipmunkmod.mixin;
|
||||
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Mutable;
|
||||
import org.spongepowered.asm.mixin.gen.Accessor;
|
||||
import net.minecraft.client.util.Session;
|
||||
|
||||
@Mixin(net.minecraft.client.MinecraftClient.class)
|
||||
public interface MinecraftClientAccessor {
|
||||
@Accessor("session")
|
||||
Session session ();
|
||||
|
||||
@Mutable
|
||||
@Accessor("session")
|
||||
void session (Session session);
|
||||
}
|
||||
package land.chipmunk.chipmunkmod.mixin;
|
||||
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Mutable;
|
||||
import org.spongepowered.asm.mixin.gen.Accessor;
|
||||
import net.minecraft.client.util.Session;
|
||||
|
||||
@Mixin(net.minecraft.client.MinecraftClient.class)
|
||||
public interface MinecraftClientAccessor {
|
||||
@Accessor("session")
|
||||
Session session ();
|
||||
|
||||
@Mutable
|
||||
@Accessor("session")
|
||||
void session (Session session);
|
||||
}
|
||||
|
|
295
src/main/java/land/chipmunk/chipmunkmod/modules/CommandCore.java
Normal file → Executable file
295
src/main/java/land/chipmunk/chipmunkmod/modules/CommandCore.java
Normal file → Executable file
|
@ -1,147 +1,148 @@
|
|||
package land.chipmunk.chipmunkmod.modules;
|
||||
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.network.ClientConnection;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.network.packet.c2s.play.UpdateCommandBlockC2SPacket;
|
||||
import net.minecraft.block.entity.CommandBlockBlockEntity;
|
||||
import net.minecraft.nbt.NbtCompound;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import java.util.List;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.function.Consumer;
|
||||
import land.chipmunk.chipmunkmod.data.BlockArea;
|
||||
|
||||
public class CommandCore {
|
||||
private MinecraftClient client;
|
||||
@Getter @Setter private boolean ready = false;
|
||||
@Getter @Setter private BlockPos origin;
|
||||
// TODO: Make it configurable
|
||||
@Getter private final BlockArea relativeArea = new BlockArea(new BlockPos(0, 0, 0), new BlockPos(15, 0, 15));
|
||||
@Getter @Setter private BlockPos currentBlockRelative;
|
||||
|
||||
public static CommandCore INSTANCE = new CommandCore(MinecraftClient.getInstance());
|
||||
|
||||
public CommandCore (MinecraftClient client) {
|
||||
this.client = client;
|
||||
}
|
||||
|
||||
public void move (Vec3d position) {
|
||||
if (!ready) {
|
||||
ready = true;
|
||||
// for (Listener listener : listeners) listener.ready();
|
||||
}
|
||||
|
||||
origin = new BlockPos(
|
||||
((int) position.getX() / 16) * 16,
|
||||
0, // TODO: Use the actual bottom of the world instead of hardcoding to 0
|
||||
((int) position.getZ() / 16) * 16
|
||||
);
|
||||
|
||||
if (currentBlockRelative == null) currentBlockRelative = new BlockPos(relativeArea.start());
|
||||
refill();
|
||||
}
|
||||
|
||||
public void refill () {
|
||||
// final PositionManager position = client.position();
|
||||
final BlockPos relStart = relativeArea.start();
|
||||
final BlockPos relEnd = relativeArea.end();
|
||||
|
||||
final String command = String.format(
|
||||
"fill %s %s %s %s %s %s command_block",
|
||||
relStart.getX() + origin.getX(),
|
||||
relStart.getY() + origin.getY(),
|
||||
relStart.getZ() + origin.getZ(),
|
||||
|
||||
relEnd.getX() + origin.getX(),
|
||||
relEnd.getY() + origin.getY(),
|
||||
relEnd.getZ() + origin.getZ()
|
||||
);
|
||||
|
||||
client.getNetworkHandler().sendChatCommand(command);
|
||||
}
|
||||
|
||||
public void incrementCurrentBlock () {
|
||||
final BlockPos start = relativeArea.start();
|
||||
final BlockPos end = relativeArea.end();
|
||||
|
||||
int x = currentBlockRelative.getX();
|
||||
int y = currentBlockRelative.getY();
|
||||
int z = currentBlockRelative.getZ();
|
||||
|
||||
x++;
|
||||
|
||||
if (x > end.getX()) {
|
||||
x = start.getX();
|
||||
z++;
|
||||
}
|
||||
|
||||
if (z > end.getZ()) {
|
||||
z = start.getZ();
|
||||
y++;
|
||||
}
|
||||
|
||||
if (y > end.getY()) {
|
||||
x = start.getX();
|
||||
y = start.getY();
|
||||
z = start.getZ();
|
||||
}
|
||||
|
||||
currentBlockRelative = new BlockPos(x, y, z);
|
||||
}
|
||||
|
||||
public BlockPos currentBlockAbsolute () {
|
||||
return currentBlockRelative.add(origin);
|
||||
}
|
||||
|
||||
public void run (String command) {
|
||||
final ClientConnection connection = client.getNetworkHandler().getConnection();
|
||||
final BlockPos currentBlock = currentBlockAbsolute();
|
||||
|
||||
// TODO: Support using repeating command blocks (on kaboom-like servers) (because less packets)
|
||||
connection.send(new UpdateCommandBlockC2SPacket(currentBlock, "", CommandBlockBlockEntity.Type.REDSTONE, false, false, false));
|
||||
connection.send(new UpdateCommandBlockC2SPacket(currentBlock, command, CommandBlockBlockEntity.Type.REDSTONE, false, false, true));
|
||||
|
||||
incrementCurrentBlock();
|
||||
}
|
||||
|
||||
public CompletableFuture<NbtCompound> runTracked (String command) {
|
||||
final ClientConnection connection = client.getNetworkHandler().getConnection();
|
||||
final BlockPos currentBlock = currentBlockAbsolute();
|
||||
|
||||
// TODO: Support using repeating command blocks (on kaboom-like servers) (because less packets)
|
||||
connection.send(new UpdateCommandBlockC2SPacket(currentBlock, "", CommandBlockBlockEntity.Type.SEQUENCE, false, false, false));
|
||||
connection.send(new UpdateCommandBlockC2SPacket(currentBlock, command, CommandBlockBlockEntity.Type.REDSTONE, true, false, true));
|
||||
|
||||
incrementCurrentBlock();
|
||||
|
||||
CompletableFuture<NbtCompound> future = new CompletableFuture<NbtCompound>();
|
||||
|
||||
final Timer timer = new Timer();
|
||||
|
||||
final TimerTask queryTask = new TimerTask() {
|
||||
public void run () {
|
||||
client.getNetworkHandler().getDataQueryHandler().queryBlockNbt(currentBlock,
|
||||
tag -> { future.complete(tag); });
|
||||
|
||||
timer.cancel(); // ? Is this necesary?
|
||||
timer.purge();
|
||||
}
|
||||
};
|
||||
|
||||
timer.schedule(queryTask, 50);
|
||||
|
||||
return future;
|
||||
}
|
||||
|
||||
public void cleanup () {
|
||||
origin = null;
|
||||
currentBlockRelative = null;
|
||||
ready = false;
|
||||
}
|
||||
}
|
||||
package land.chipmunk.chipmunkmod.modules;
|
||||
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.network.ClientConnection;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.network.packet.c2s.play.UpdateCommandBlockC2SPacket;
|
||||
import net.minecraft.block.entity.CommandBlockBlockEntity;
|
||||
import net.minecraft.nbt.NbtCompound;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import java.util.List;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.function.Consumer;
|
||||
import land.chipmunk.chipmunkmod.ChipmunkMod;
|
||||
import land.chipmunk.chipmunkmod.data.BlockArea;
|
||||
|
||||
public class CommandCore {
|
||||
private MinecraftClient client;
|
||||
@Getter @Setter private boolean ready = false;
|
||||
@Getter @Setter private BlockPos origin;
|
||||
@Getter private final BlockArea relativeArea;
|
||||
@Getter @Setter private BlockPos currentBlockRelative;
|
||||
|
||||
public static CommandCore INSTANCE = new CommandCore(MinecraftClient.getInstance(), ChipmunkMod.CONFIG.core.relativeArea);
|
||||
|
||||
public CommandCore (MinecraftClient client, BlockArea relativeArea) {
|
||||
this.client = client;
|
||||
this.relativeArea = relativeArea;
|
||||
}
|
||||
|
||||
public void move (Vec3d position) {
|
||||
if (!ready) {
|
||||
ready = true;
|
||||
// for (Listener listener : listeners) listener.ready();
|
||||
}
|
||||
|
||||
origin = new BlockPos(
|
||||
((int) position.getX() / 16) * 16,
|
||||
0, // TODO: Use the actual bottom of the world instead of hardcoding to 0
|
||||
((int) position.getZ() / 16) * 16
|
||||
);
|
||||
|
||||
if (currentBlockRelative == null) currentBlockRelative = new BlockPos(relativeArea.start());
|
||||
refill();
|
||||
}
|
||||
|
||||
public void refill () {
|
||||
// final PositionManager position = client.position();
|
||||
final BlockPos relStart = relativeArea.start();
|
||||
final BlockPos relEnd = relativeArea.end();
|
||||
|
||||
final String command = String.format(
|
||||
"fill %s %s %s %s %s %s command_block",
|
||||
relStart.getX() + origin.getX(),
|
||||
relStart.getY() + origin.getY(),
|
||||
relStart.getZ() + origin.getZ(),
|
||||
|
||||
relEnd.getX() + origin.getX(),
|
||||
relEnd.getY() + origin.getY(),
|
||||
relEnd.getZ() + origin.getZ()
|
||||
);
|
||||
|
||||
client.getNetworkHandler().sendChatCommand(command);
|
||||
}
|
||||
|
||||
public void incrementCurrentBlock () {
|
||||
final BlockPos start = relativeArea.start();
|
||||
final BlockPos end = relativeArea.end();
|
||||
|
||||
int x = currentBlockRelative.getX();
|
||||
int y = currentBlockRelative.getY();
|
||||
int z = currentBlockRelative.getZ();
|
||||
|
||||
x++;
|
||||
|
||||
if (x > end.getX()) {
|
||||
x = start.getX();
|
||||
z++;
|
||||
}
|
||||
|
||||
if (z > end.getZ()) {
|
||||
z = start.getZ();
|
||||
y++;
|
||||
}
|
||||
|
||||
if (y > end.getY()) {
|
||||
x = start.getX();
|
||||
y = start.getY();
|
||||
z = start.getZ();
|
||||
}
|
||||
|
||||
currentBlockRelative = new BlockPos(x, y, z);
|
||||
}
|
||||
|
||||
public BlockPos currentBlockAbsolute () {
|
||||
return currentBlockRelative.add(origin);
|
||||
}
|
||||
|
||||
public void run (String command) {
|
||||
final ClientConnection connection = client.getNetworkHandler().getConnection();
|
||||
final BlockPos currentBlock = currentBlockAbsolute();
|
||||
|
||||
// TODO: Support using repeating command blocks (on kaboom-like servers) (because less packets)
|
||||
connection.send(new UpdateCommandBlockC2SPacket(currentBlock, "", CommandBlockBlockEntity.Type.REDSTONE, false, false, false));
|
||||
connection.send(new UpdateCommandBlockC2SPacket(currentBlock, command, CommandBlockBlockEntity.Type.REDSTONE, false, false, true));
|
||||
|
||||
incrementCurrentBlock();
|
||||
}
|
||||
|
||||
public CompletableFuture<NbtCompound> runTracked (String command) {
|
||||
final ClientConnection connection = client.getNetworkHandler().getConnection();
|
||||
final BlockPos currentBlock = currentBlockAbsolute();
|
||||
|
||||
// TODO: Support using repeating command blocks (on kaboom-like servers) (because less packets)
|
||||
connection.send(new UpdateCommandBlockC2SPacket(currentBlock, "", CommandBlockBlockEntity.Type.SEQUENCE, false, false, false));
|
||||
connection.send(new UpdateCommandBlockC2SPacket(currentBlock, command, CommandBlockBlockEntity.Type.REDSTONE, true, false, true));
|
||||
|
||||
incrementCurrentBlock();
|
||||
|
||||
CompletableFuture<NbtCompound> future = new CompletableFuture<NbtCompound>();
|
||||
|
||||
final Timer timer = new Timer();
|
||||
|
||||
final TimerTask queryTask = new TimerTask() {
|
||||
public void run () {
|
||||
client.getNetworkHandler().getDataQueryHandler().queryBlockNbt(currentBlock,
|
||||
tag -> { future.complete(tag); });
|
||||
|
||||
timer.cancel(); // ? Is this necesary?
|
||||
timer.purge();
|
||||
}
|
||||
};
|
||||
|
||||
timer.schedule(queryTask, 50);
|
||||
|
||||
return future;
|
||||
}
|
||||
|
||||
public void cleanup () {
|
||||
origin = null;
|
||||
currentBlockRelative = null;
|
||||
ready = false;
|
||||
}
|
||||
}
|
||||
|
|
144
src/main/java/land/chipmunk/chipmunkmod/modules/SelfCare.java
Normal file → Executable file
144
src/main/java/land/chipmunk/chipmunkmod/modules/SelfCare.java
Normal file → Executable file
|
@ -1,72 +1,72 @@
|
|||
package land.chipmunk.chipmunkmod.modules;
|
||||
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.client.network.ClientPlayNetworkHandler;
|
||||
import net.minecraft.client.network.ClientPlayerEntity;
|
||||
import com.mojang.brigadier.tree.CommandNode;
|
||||
import com.mojang.brigadier.tree.LiteralCommandNode;
|
||||
import lombok.Getter;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
|
||||
public class SelfCare {
|
||||
private final MinecraftClient client;
|
||||
@Getter private long interval;
|
||||
|
||||
private Timer timer = null;
|
||||
|
||||
public static final SelfCare INSTANCE = new SelfCare(MinecraftClient.getInstance(), 70L);
|
||||
|
||||
public SelfCare (MinecraftClient client, long interval) {
|
||||
this.client = client;
|
||||
this.interval = interval;
|
||||
}
|
||||
|
||||
public void init () {
|
||||
final TimerTask task = new TimerTask() {
|
||||
public void run () {
|
||||
tick();
|
||||
}
|
||||
};
|
||||
|
||||
if (timer != null) cleanup();
|
||||
|
||||
timer = new Timer();
|
||||
timer.schedule(task, interval, interval);
|
||||
}
|
||||
|
||||
public void cleanup () {
|
||||
if (timer == null) return;
|
||||
|
||||
timer.cancel();
|
||||
timer.purge();
|
||||
timer = null;
|
||||
}
|
||||
|
||||
public void tick () {
|
||||
final ClientPlayerEntity player = client.player;
|
||||
final ClientPlayNetworkHandler networkHandler = client.getNetworkHandler();
|
||||
|
||||
if (networkHandler == null) {
|
||||
cleanup();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!player.hasPermissionLevel(2)) { if (serverHasCommand("op")) networkHandler.sendChatCommand("op @s[type=player]"); }
|
||||
else if (!client.player.isCreative()) networkHandler.sendChatCommand("gamemode creative");
|
||||
}
|
||||
|
||||
// TODO: Move this into a separate class related to server info gathering (and yes, I plan on making this d y n a m i c and require little to no configuration for most servers)
|
||||
private boolean serverHasCommand (String name) {
|
||||
final ClientPlayNetworkHandler networkHandler = client.getNetworkHandler();
|
||||
|
||||
for (CommandNode node : networkHandler.getCommandDispatcher().getRoot().getChildren()) {
|
||||
if (!(node instanceof LiteralCommandNode)) continue;
|
||||
final LiteralCommandNode literal = (LiteralCommandNode) node;
|
||||
|
||||
if (literal.getLiteral().equals(name)) return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
package land.chipmunk.chipmunkmod.modules;
|
||||
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.client.network.ClientPlayNetworkHandler;
|
||||
import net.minecraft.client.network.ClientPlayerEntity;
|
||||
import com.mojang.brigadier.tree.CommandNode;
|
||||
import com.mojang.brigadier.tree.LiteralCommandNode;
|
||||
import lombok.Getter;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
|
||||
public class SelfCare {
|
||||
private final MinecraftClient client;
|
||||
@Getter private long interval;
|
||||
|
||||
private Timer timer = null;
|
||||
|
||||
public static final SelfCare INSTANCE = new SelfCare(MinecraftClient.getInstance(), 70L);
|
||||
|
||||
public SelfCare (MinecraftClient client, long interval) {
|
||||
this.client = client;
|
||||
this.interval = interval;
|
||||
}
|
||||
|
||||
public void init () {
|
||||
final TimerTask task = new TimerTask() {
|
||||
public void run () {
|
||||
tick();
|
||||
}
|
||||
};
|
||||
|
||||
if (timer != null) cleanup();
|
||||
|
||||
timer = new Timer();
|
||||
timer.schedule(task, interval, interval);
|
||||
}
|
||||
|
||||
public void cleanup () {
|
||||
if (timer == null) return;
|
||||
|
||||
timer.cancel();
|
||||
timer.purge();
|
||||
timer = null;
|
||||
}
|
||||
|
||||
public void tick () {
|
||||
final ClientPlayerEntity player = client.player;
|
||||
final ClientPlayNetworkHandler networkHandler = client.getNetworkHandler();
|
||||
|
||||
if (networkHandler == null) {
|
||||
cleanup();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!player.hasPermissionLevel(2)) { if (serverHasCommand("op")) networkHandler.sendChatCommand("op @s[type=player]"); }
|
||||
else if (!client.player.isCreative()) networkHandler.sendChatCommand("gamemode creative");
|
||||
}
|
||||
|
||||
// TODO: Move this into a separate class related to server info gathering (and yes, I plan on making this d y n a m i c and require little to no configuration for most servers)
|
||||
private boolean serverHasCommand (String name) {
|
||||
final ClientPlayNetworkHandler networkHandler = client.getNetworkHandler();
|
||||
|
||||
for (CommandNode node : networkHandler.getCommandDispatcher().getRoot().getChildren()) {
|
||||
if (!(node instanceof LiteralCommandNode)) continue;
|
||||
final LiteralCommandNode literal = (LiteralCommandNode) node;
|
||||
|
||||
if (literal.getLiteral().equals(name)) return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
12
src/main/resources/default_config.json
Normal file
12
src/main/resources/default_config.json
Normal file
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
"commands": {
|
||||
"prefix": "."
|
||||
},
|
||||
|
||||
"core": {
|
||||
"relativeArea": {
|
||||
"start": { "x": 0, "y": 0, "z": 0 },
|
||||
"end": { "x": 15, "y": 0, "z": 15 }
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue