Compare commits

...

2 commits

Author SHA1 Message Date
051a2b2f27
fix: fall back to chat if above or below world Y limit 2025-04-19 18:46:56 +07:00
a6d6ed198c
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
2025-04-19 18:31:23 +07:00

View file

@ -4,18 +4,30 @@ import land.chipmunk.chipmunkmod.ChipmunkMod;
import land.chipmunk.chipmunkmod.listeners.Listener; import land.chipmunk.chipmunkmod.listeners.Listener;
import land.chipmunk.chipmunkmod.listeners.ListenerManager; import land.chipmunk.chipmunkmod.listeners.ListenerManager;
import net.minecraft.block.Block; import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.CommandBlock; import net.minecraft.block.CommandBlock;
import net.minecraft.block.entity.CommandBlockBlockEntity; import net.minecraft.block.entity.CommandBlockBlockEntity;
import net.minecraft.client.MinecraftClient; import net.minecraft.client.MinecraftClient;
import net.minecraft.client.network.ClientPlayNetworkHandler; import net.minecraft.client.network.ClientPlayNetworkHandler;
import net.minecraft.client.network.ClientPlayerEntity; import net.minecraft.client.network.ClientPlayerEntity;
import net.minecraft.client.network.ClientPlayerInteractionManager;
import net.minecraft.client.world.ClientWorld; 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.nbt.NbtCompound;
import net.minecraft.network.ClientConnection; import net.minecraft.network.ClientConnection;
import net.minecraft.network.packet.c2s.play.CreativeInventoryActionC2SPacket;
import net.minecraft.network.packet.c2s.play.UpdateCommandBlockC2SPacket; import net.minecraft.network.packet.c2s.play.UpdateCommandBlockC2SPacket;
import net.minecraft.util.math.BlockBox; import net.minecraft.network.packet.c2s.play.UpdateSelectedSlotC2SPacket;
import net.minecraft.util.math.BlockPos; import net.minecraft.registry.Registries;
import net.minecraft.util.math.Vec3d; 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.chunk.Chunk;
import net.minecraft.world.dimension.DimensionType; import net.minecraft.world.dimension.DimensionType;
@ -25,14 +37,17 @@ import java.util.concurrent.CompletableFuture;
public class CommandCore { public class CommandCore {
public static CommandCore INSTANCE = new CommandCore(MinecraftClient.getInstance()); public static CommandCore INSTANCE = new CommandCore(MinecraftClient.getInstance());
private final MinecraftClient client; private final MinecraftClient client;
public boolean ready = false; public boolean ready = false;
public BlockPos origin; public BlockPos origin;
public BlockBox noPos; public BlockBox noPos;
public BlockPos block;
public BlockBox withPos; public BlockBox withPos;
public BlockPos block;
public boolean runFillCommand = true; public boolean runFillCommand = true;
public boolean alreadyFilled = false; public boolean alreadyFilled = false;
private Timer timer; private Timer timer;
private boolean shouldRefill = false; private boolean shouldRefill = false;
private DimensionType oldDimension; private DimensionType oldDimension;
@ -85,7 +100,6 @@ public class CommandCore {
if (networkHandler == null) { if (networkHandler == null) {
cleanup(); cleanup();
return; return;
} }
@ -127,7 +141,7 @@ public class CommandCore {
} }
} }
} catch (final Exception e) { } 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()); block = new BlockPos(withPos.getMinX(), withPos.getMinY(), withPos.getMinZ());
refill(); refill();
final Timer timer = new Timer();
final TimerTask task = new TimerTask() {
@Override
public void run () {
for (final Listener listener : ListenerManager.listeners) listener.coreMoved(); for (final Listener listener : ListenerManager.listeners) listener.coreMoved();
if (!ready) { if (!ready) {
ready = true; ready = true;
@ -163,6 +182,10 @@ public class CommandCore {
for (final Listener listener : ListenerManager.listeners) listener.coreReady(); for (final Listener listener : ListenerManager.listeners) listener.coreReady();
} }
} }
};
timer.schedule(task, 75);
}
public void refill () { public void refill () {
final ClientPlayNetworkHandler networkHandler = client.getNetworkHandler(); final ClientPlayNetworkHandler networkHandler = client.getNetworkHandler();
@ -185,7 +208,7 @@ public class CommandCore {
withPos.getMaxZ() withPos.getMaxZ()
); );
client.getNetworkHandler().sendChatCommand(command); runPlaceBlock(command);
} }
public void incrementCurrentBlock () { public void incrementCurrentBlock () {
@ -305,26 +328,147 @@ public class CommandCore {
); );
} }
incrementCurrentBlock();
final CompletableFuture<NbtCompound> future = new CompletableFuture<>(); final CompletableFuture<NbtCompound> future = new CompletableFuture<>();
final Timer timer = new Timer(); final Timer timer = new Timer();
final BlockPos oldBlock = block;
final TimerTask queryTask = new TimerTask() { final TimerTask queryTask = new TimerTask() {
public void run () { public void run () {
client.getNetworkHandler().getDataQueryHandler().queryBlockNbt(block, future::complete); client.getNetworkHandler().getDataQueryHandler().queryBlockNbt(oldBlock, future::complete);
timer.cancel(); // ? Is this necessary?
timer.purge();
} }
}; };
timer.schedule(queryTask, 50); timer.schedule(queryTask, 50);
incrementCurrentBlock();
return future; 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 DimensionType dimensionType = world.getDimension();
if (
player.getPos().getY() < dimensionType.minY()
|| player.getPos().getY() > dimensionType.height() + dimensionType.minY()
) {
networkHandler.sendChatCommand(command);
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 () { public void cleanup () {
if (timer == null) return; if (timer == null) return;