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.
|
||||
// See https://docs.gradle.org/current/userguide/declaring_repositories.html
|
||||
// for more information about repositories.
|
||||
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
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.
|
||||
|
||||
// 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 {
|
||||
|
|
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.
|
||||
// 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("modid");
|
||||
public static final Logger LOGGER = LoggerFactory.getLogger("chipmunkmod");
|
||||
|
||||
@Override
|
||||
public void onInitialize () {
|
||||
|
|
|
@ -66,5 +66,6 @@ public class CommandManager {
|
|||
|
||||
static {
|
||||
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",
|
||||
"ChatInputSuggestorMixin",
|
||||
"ClientPlayNetworkHandlerAccessor",
|
||||
"ClientConnectionMixin"
|
||||
"ClientConnectionMixin",
|
||||
"ClientPlayerEntityMixin"
|
||||
],
|
||||
"injectors": {
|
||||
"defaultRequire": 1
|
||||
|
|
Loading…
Reference in a new issue