Initial core implementation
This commit is contained in:
parent
92612c6b32
commit
26fd290b92
9 changed files with 288 additions and 2 deletions
|
@ -16,6 +16,8 @@ repositories {
|
||||||
// Loom adds the essential maven repositories to download Minecraft and libraries from automatically.
|
// Loom adds the essential maven repositories to download Minecraft and libraries from automatically.
|
||||||
// See https://docs.gradle.org/current/userguide/declaring_repositories.html
|
// See https://docs.gradle.org/current/userguide/declaring_repositories.html
|
||||||
// for more information about repositories.
|
// for more information about repositories.
|
||||||
|
|
||||||
|
mavenCentral()
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
|
@ -31,6 +33,12 @@ dependencies {
|
||||||
// These are included in the Fabric API production distribution and allow you to update your mod to the latest modules at a later more convenient time.
|
// These are included in the Fabric API production distribution and allow you to update your mod to the latest modules at a later more convenient time.
|
||||||
|
|
||||||
// modImplementation "net.fabricmc.fabric-api:fabric-api-deprecated:${project.fabric_version}"
|
// modImplementation "net.fabricmc.fabric-api:fabric-api-deprecated:${project.fabric_version}"
|
||||||
|
|
||||||
|
compileOnly 'org.projectlombok:lombok:1.18.24'
|
||||||
|
annotationProcessor 'org.projectlombok:lombok:1.18.24'
|
||||||
|
|
||||||
|
testCompileOnly 'org.projectlombok:lombok:1.18.24'
|
||||||
|
testAnnotationProcessor 'org.projectlombok:lombok:1.18.24'
|
||||||
}
|
}
|
||||||
|
|
||||||
processResources {
|
processResources {
|
||||||
|
|
2
lombok.config
Normal file
2
lombok.config
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
config.stopBubbling = true
|
||||||
|
lombok.accessors.fluent = true
|
|
@ -8,7 +8,7 @@ public class ChipmunkMod implements ModInitializer {
|
||||||
// This logger is used to write text to the console and the log file.
|
// 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.
|
// 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.
|
// That way, it's clear which mod wrote info, warnings, and errors.
|
||||||
public static final Logger LOGGER = LoggerFactory.getLogger("modid");
|
public static final Logger LOGGER = LoggerFactory.getLogger("chipmunkmod");
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onInitialize () {
|
public void onInitialize () {
|
||||||
|
|
|
@ -66,5 +66,6 @@ public class CommandManager {
|
||||||
|
|
||||||
static {
|
static {
|
||||||
TestCommand.register(dispatcher);
|
TestCommand.register(dispatcher);
|
||||||
|
CoreCommand.register(dispatcher);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -0,0 +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;
|
||||||
|
}
|
||||||
|
}
|
13
src/main/java/land/chipmunk/chipmunkmod/data/BlockArea.java
Normal file
13
src/main/java/land/chipmunk/chipmunkmod/data/BlockArea.java
Normal file
|
@ -0,0 +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;
|
||||||
|
}
|
|
@ -0,0 +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);
|
||||||
|
}
|
||||||
|
}
|
148
src/main/java/land/chipmunk/chipmunkmod/modules/CommandCore.java
Normal file
148
src/main/java/land/chipmunk/chipmunkmod/modules/CommandCore.java
Normal file
|
@ -0,0 +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 minecraft:chain_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.SEQUENCE, 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* @Override
|
||||||
|
public void disconnected (DisconnectedEvent event) {
|
||||||
|
origin = null;
|
||||||
|
currentBlockRelative = null;
|
||||||
|
ready = false;
|
||||||
|
} */
|
||||||
|
}
|
|
@ -9,7 +9,8 @@
|
||||||
"ChatScreenMixin",
|
"ChatScreenMixin",
|
||||||
"ChatInputSuggestorMixin",
|
"ChatInputSuggestorMixin",
|
||||||
"ClientPlayNetworkHandlerAccessor",
|
"ClientPlayNetworkHandlerAccessor",
|
||||||
"ClientConnectionMixin"
|
"ClientConnectionMixin",
|
||||||
|
"ClientPlayerEntityMixin"
|
||||||
],
|
],
|
||||||
"injectors": {
|
"injectors": {
|
||||||
"defaultRequire": 1
|
"defaultRequire": 1
|
||||||
|
|
Loading…
Reference in a new issue