feat: silently /fill core using place block core (finally !!!!!!!!!)

i was also attempting to fix tracked core, but it really seems like the server is checking the distance between you and the block (since we are using the query block NBT packet instead of tellraw), although i have checked the vanilla minecraft code, they don't seem to check for it. maybe it's just a skill issue on my part, but it used to work in the original version of chipmunkmod, if i remember correctly
anyway, now it's basically a silent fill. you can still do `.core runFillCommand false` to still disable the place block core
This commit is contained in:
Chayapak Supasakul 2025-04-19 18:31:23 +07:00
parent 0cc74be280
commit a6d6ed198c
Signed by: ChomeNS
SSH key fingerprint: SHA256:0YoxhdyXsgbc0nfeB2N6FYE60mxMU7DS4uCUMaw2mvA

View file

@ -4,18 +4,30 @@ import land.chipmunk.chipmunkmod.ChipmunkMod;
import land.chipmunk.chipmunkmod.listeners.Listener;
import land.chipmunk.chipmunkmod.listeners.ListenerManager;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.CommandBlock;
import net.minecraft.block.entity.CommandBlockBlockEntity;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.network.ClientPlayNetworkHandler;
import net.minecraft.client.network.ClientPlayerEntity;
import net.minecraft.client.network.ClientPlayerInteractionManager;
import net.minecraft.client.world.ClientWorld;
import net.minecraft.component.ComponentMap;
import net.minecraft.component.DataComponentTypes;
import net.minecraft.component.type.NbtComponent;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
import net.minecraft.nbt.NbtCompound;
import net.minecraft.network.ClientConnection;
import net.minecraft.network.packet.c2s.play.CreativeInventoryActionC2SPacket;
import net.minecraft.network.packet.c2s.play.UpdateCommandBlockC2SPacket;
import net.minecraft.util.math.BlockBox;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import net.minecraft.network.packet.c2s.play.UpdateSelectedSlotC2SPacket;
import net.minecraft.registry.Registries;
import net.minecraft.state.property.Property;
import net.minecraft.util.Hand;
import net.minecraft.util.Util;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.util.math.*;
import net.minecraft.world.chunk.Chunk;
import net.minecraft.world.dimension.DimensionType;
@ -25,14 +37,17 @@ import java.util.concurrent.CompletableFuture;
public class CommandCore {
public static CommandCore INSTANCE = new CommandCore(MinecraftClient.getInstance());
private final MinecraftClient client;
public boolean ready = false;
public BlockPos origin;
public BlockBox noPos;
public BlockPos block;
public BlockBox withPos;
public BlockPos block;
public boolean runFillCommand = true;
public boolean alreadyFilled = false;
private Timer timer;
private boolean shouldRefill = false;
private DimensionType oldDimension;
@ -85,7 +100,6 @@ public class CommandCore {
if (networkHandler == null) {
cleanup();
return;
}
@ -127,7 +141,7 @@ public class CommandCore {
}
}
} catch (final Exception e) {
e.printStackTrace();
ChipmunkMod.LOGGER.error("Error while checking if core needs refilling", e);
}
}
@ -156,6 +170,11 @@ public class CommandCore {
block = new BlockPos(withPos.getMinX(), withPos.getMinY(), withPos.getMinZ());
refill();
final Timer timer = new Timer();
final TimerTask task = new TimerTask() {
@Override
public void run () {
for (final Listener listener : ListenerManager.listeners) listener.coreMoved();
if (!ready) {
ready = true;
@ -163,6 +182,10 @@ public class CommandCore {
for (final Listener listener : ListenerManager.listeners) listener.coreReady();
}
}
};
timer.schedule(task, 75);
}
public void refill () {
final ClientPlayNetworkHandler networkHandler = client.getNetworkHandler();
@ -185,7 +208,7 @@ public class CommandCore {
withPos.getMaxZ()
);
client.getNetworkHandler().sendChatCommand(command);
runPlaceBlock(command);
}
public void incrementCurrentBlock () {
@ -305,26 +328,137 @@ public class CommandCore {
);
}
incrementCurrentBlock();
final CompletableFuture<NbtCompound> future = new CompletableFuture<>();
final Timer timer = new Timer();
final BlockPos oldBlock = block;
final TimerTask queryTask = new TimerTask() {
public void run () {
client.getNetworkHandler().getDataQueryHandler().queryBlockNbt(block, future::complete);
timer.cancel(); // ? Is this necessary?
timer.purge();
client.getNetworkHandler().getDataQueryHandler().queryBlockNbt(oldBlock, future::complete);
}
};
timer.schedule(queryTask, 50);
incrementCurrentBlock();
return future;
}
public void runPlaceBlock (final String command) {
final ClientPlayNetworkHandler networkHandler = client.getNetworkHandler();
if (networkHandler == null) return;
final ClientConnection connection = networkHandler.getConnection();
final ClientPlayerEntity player = client.player;
final ClientWorld world = client.world;
if (player == null || world == null || !player.isInCreativeMode()) return;
final ClientPlayerInteractionManager interactionManager = client.interactionManager;
if (interactionManager == null) return;
final float yaw = player.getYaw();
final float pitch = player.getPitch();
// Anti Block when flying around
final BlockPos position = player.getBlockPos().add(
(int) Math.round(3 * Math.cos(Math.toRadians(yaw))),
3 * (pitch < 0 ? -1 : 1),
(int) Math.round(3 * Math.sin(Math.toRadians(yaw)))
);
// stolen from two five hundred million dollars
final BlockState oldBlockState = world.getBlockState(position);
final int freeHotBarSlot = player.getInventory().getEmptySlot();
final int slot = 36 + freeHotBarSlot;
final int oldSelectedSlot = player.getInventory().selectedSlot;
final ItemStack oldStack = player.getInventory().getStack(slot).copy();
final ItemStack commandBlock = new ItemStack(Items.COMMAND_BLOCK);
final NbtCompound data = new NbtCompound();
data.putString("id", "minecraft:command_block");
data.putString("Command", command);
data.putBoolean("auto", true);
final NbtCompound blockEntityTag = new NbtCompound();
blockEntityTag.put("BlockEntityTag", data);
commandBlock.applyComponentsFrom(
ComponentMap.builder()
.add(DataComponentTypes.CUSTOM_DATA, NbtComponent.of(blockEntityTag))
.add(DataComponentTypes.BLOCK_ENTITY_DATA, NbtComponent.of(data))
.build()
);
connection.send(new CreativeInventoryActionC2SPacket(slot, commandBlock));
if (oldSelectedSlot != freeHotBarSlot) {
connection.send(new UpdateSelectedSlotC2SPacket(freeHotBarSlot));
}
interactionManager.breakBlock(position);
interactionManager.interactBlock(
player,
Hand.MAIN_HAND,
new BlockHitResult(
new Vec3d(position),
Direction.UP,
position,
false
)
);
if (oldSelectedSlot != freeHotBarSlot) {
connection.send(new UpdateSelectedSlotC2SPacket(oldSelectedSlot));
}
connection.send(new CreativeInventoryActionC2SPacket(slot, oldStack));
final Timer timer = new Timer();
final TimerTask task = new TimerTask() {
@Override
public void run () {
final StringBuilder command = new StringBuilder(
String.format(
"setblock %d %d %d %s",
position.getX(),
position.getY(),
position.getZ(),
Registries.BLOCK.getId(oldBlockState.getBlock())
)
);
if (!oldBlockState.getProperties().isEmpty()) {
command.append('[');
for (final Property<?> property : oldBlockState.getProperties()) {
command.append(property.getName())
.append('=')
.append(Util.getValueAsString(property, property.getType()))
.append(',');
}
command.deleteCharAt(command.length() - 1);
command.append(']');
}
CommandCore.this.run(command.toString());
}
};
timer.schedule(task, 100); // assuming the core has already been filled at this point
}
public void cleanup () {
if (timer == null) return;