feat: FINALLY chunk parsing with actual working core complete check

This commit is contained in:
ChomeNS
2025-02-18 20:41:51 +07:00
parent 2462fdd361
commit c1d269b812
5 changed files with 134 additions and 39 deletions

View File

@@ -0,0 +1,48 @@
package me.chayapak1.chomens_bot.chunk;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import me.chayapak1.chomens_bot.data.chunk.ChunkPos;
import org.geysermc.mcprotocollib.protocol.codec.MinecraftTypes;
import org.geysermc.mcprotocollib.protocol.data.game.chunk.ChunkSection;
// Author: hhhzzzsss
public class ChunkColumn {
public final ChunkPos pos;
public final ChunkSection[] chunks;
private final int minY;
public ChunkColumn (ChunkPos chunkPos, byte[] data, int worldHeight, int minY) {
this.pos = chunkPos;
this.minY = minY;
final ByteBuf in = Unpooled.wrappedBuffer(data);
final int numSections = -Math.floorDiv(-worldHeight, 16);
chunks = new ChunkSection[numSections];
for (int i = 0; i < numSections; i++) {
chunks[i] = MinecraftTypes.readChunkSection(in);
}
}
public int getBlock (int x, int y, int z) {
int yIndex = (y - minY) >> 4;
if (chunks[yIndex] == null) return 0;
return chunks[yIndex].getBlock(x, y & 15, z);
}
public void setBlock (int x, int y, int z, int id) {
int yIndex = (y - minY) >> 4;
if (chunks[yIndex] == null) {
chunks[yIndex] = new ChunkSection();
chunks[yIndex].setBlock(0, 0, 0, 0);
}
chunks[yIndex].setBlock(x, y & 15, z, id);
}
}

View File

@@ -0,0 +1,4 @@
package me.chayapak1.chomens_bot.data.chunk;
public record ChunkPos (int x, int z) {
}

View File

@@ -11,7 +11,6 @@ import org.cloudburstmc.nbt.NbtMap;
import org.cloudburstmc.nbt.NbtMapBuilder;
import org.geysermc.mcprotocollib.network.Session;
import org.geysermc.mcprotocollib.network.event.session.DisconnectedEvent;
import org.geysermc.mcprotocollib.network.packet.Packet;
import org.geysermc.mcprotocollib.protocol.data.game.entity.object.Direction;
import org.geysermc.mcprotocollib.protocol.data.game.entity.player.Hand;
import org.geysermc.mcprotocollib.protocol.data.game.entity.player.PlayerAction;
@@ -20,11 +19,7 @@ import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponen
import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentType;
import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentTypes;
import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents;
import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockChangeEntry;
import org.geysermc.mcprotocollib.protocol.data.game.level.block.CommandBlockMode;
import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.level.ClientboundBlockUpdatePacket;
import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.level.ClientboundLevelChunkWithLightPacket;
import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.level.ClientboundSectionBlocksUpdatePacket;
import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.inventory.ServerboundSetCommandBlockPacket;
import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.inventory.ServerboundSetCreativeModeSlotPacket;
import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.player.ServerboundPlayerActionPacket;
@@ -87,6 +82,8 @@ public class CorePlugin extends PositionPlugin.Listener {
}
bot.executor.scheduleAtFixedRate(() -> {
checkCoreTick();
if (!shouldRefill) return;
refill();
@@ -102,13 +99,6 @@ public class CorePlugin extends PositionPlugin.Listener {
reset();
}
@Override
public void packetReceived(Session session, Packet packet) {
if (packet instanceof ClientboundBlockUpdatePacket) CorePlugin.this.packetReceived((ClientboundBlockUpdatePacket) packet);
else if (packet instanceof ClientboundSectionBlocksUpdatePacket) CorePlugin.this.packetReceived((ClientboundSectionBlocksUpdatePacket) packet);
else if (packet instanceof ClientboundLevelChunkWithLightPacket) CorePlugin.this.packetReceived((ClientboundLevelChunkWithLightPacket) packet);
}
});
bot.tick.addListener(new TickPlugin.Listener() {
@@ -217,7 +207,7 @@ public class CorePlugin extends PositionPlugin.Listener {
final CompletableFuture<String> future = bot.query.block(coreBlock, "LastOutput");
future.thenApplyAsync(output -> {
if (output == null) return output;
if (output == null) return null;
trackedFuture.complete(
Component.join(
@@ -284,29 +274,24 @@ public class CorePlugin extends PositionPlugin.Listener {
session.send(new ServerboundUseItemOnPacket(temporaryBlockPosition, Direction.UP, Hand.MAIN_HAND, 0.5f, 0.5f, 0.5f, false, false, 1));
}
public void packetReceived (ClientboundBlockUpdatePacket packet) {
final BlockChangeEntry entry = packet.getEntry();
public boolean isCoreComplete () {
if (!ready) return false;
final Vector3i position = entry.getPosition();
for (int x = from.getX(); x <= to.getX(); x++) {
for (int y = from.getY(); y <= to.getY(); y++) {
for (int z = from.getZ(); z <= to.getZ(); z++) {
final int block = bot.world.getBlock(x, y, z);
if (isCore(position) && !isCommandBlockState(entry.getBlock())) shouldRefill = true;
}
public void packetReceived (ClientboundSectionBlocksUpdatePacket packet) {
final BlockChangeEntry[] entries = packet.getEntries();
for (BlockChangeEntry entry : entries) {
final Vector3i position = entry.getPosition();
if (isCore(position) && !isCommandBlockState(entry.getBlock())) {
shouldRefill = true;
break;
if (!isCommandBlockState(block)) return false;
}
}
}
return true;
}
public void packetReceived (ClientboundLevelChunkWithLightPacket packet) {
shouldRefill = true; // worst fix
private void checkCoreTick () {
if (!isCoreComplete()) shouldRefill = true;
}
private boolean isCommandBlockState (int blockState) {

View File

@@ -1,17 +1,21 @@
package me.chayapak1.chomens_bot.plugins;
import me.chayapak1.chomens_bot.Bot;
import me.chayapak1.chomens_bot.chunk.ChunkColumn;
import me.chayapak1.chomens_bot.data.chunk.ChunkPos;
import org.cloudburstmc.math.vector.Vector3i;
import org.cloudburstmc.nbt.NbtMap;
import org.geysermc.mcprotocollib.network.Session;
import org.geysermc.mcprotocollib.network.event.session.DisconnectedEvent;
import org.geysermc.mcprotocollib.network.packet.Packet;
import org.geysermc.mcprotocollib.protocol.data.game.RegistryEntry;
import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockChangeEntry;
import org.geysermc.mcprotocollib.protocol.packet.configuration.clientbound.ClientboundRegistryDataPacket;
import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.ClientboundLoginPacket;
import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.ClientboundRespawnPacket;
import me.chayapak1.chomens_bot.Bot;
import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.level.ClientboundSetSimulationDistancePacket;
import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.level.*;
import java.util.ArrayList;
import java.util.List;
import java.util.*;
public class WorldPlugin extends Bot.Listener {
public int minY = 0;
@@ -19,6 +23,8 @@ public class WorldPlugin extends Bot.Listener {
public int simulationDistance = 8;
private final Map<ChunkPos, ChunkColumn> chunks = new HashMap<>();
public List<RegistryEntry> registry = null;
private final List<Listener> listeners = new ArrayList<>();
@@ -33,6 +39,15 @@ public class WorldPlugin extends Bot.Listener {
else if (packet instanceof ClientboundRespawnPacket t_packet) packetReceived(t_packet);
else if (packet instanceof ClientboundRegistryDataPacket t_packet) packetReceived(t_packet);
else if (packet instanceof ClientboundSetSimulationDistancePacket t_packet) packetReceived(t_packet);
else if (packet instanceof ClientboundLevelChunkWithLightPacket t_packet) packetReceived(t_packet);
else if (packet instanceof ClientboundForgetLevelChunkPacket t_packet) packetReceived(t_packet);
else if (packet instanceof ClientboundBlockUpdatePacket t_packet) packetReceived(t_packet);
else if (packet instanceof ClientboundSectionBlocksUpdatePacket t_packet) packetReceived(t_packet);
}
@Override
public void disconnected (DisconnectedEvent event) {
chunks.clear();
}
private void worldChanged (String dimension) {
@@ -53,26 +68,69 @@ public class WorldPlugin extends Bot.Listener {
for (Listener listener : listeners) listener.worldChanged(dimension);
}
public void packetReceived (ClientboundRegistryDataPacket packet) {
private void packetReceived (ClientboundRegistryDataPacket packet) {
if (!packet.getRegistry().value().equals("dimension_type")) return;
registry = packet.getEntries();
}
public void packetReceived (ClientboundLoginPacket packet) {
private void packetReceived (ClientboundLoginPacket packet) {
simulationDistance = packet.getSimulationDistance();
worldChanged(packet.getCommonPlayerSpawnInfo().getWorldName().asString());
}
public void packetReceived (ClientboundRespawnPacket packet) {
private void packetReceived (ClientboundRespawnPacket packet) {
worldChanged(packet.getCommonPlayerSpawnInfo().getWorldName().asString());
}
public void packetReceived (ClientboundSetSimulationDistancePacket packet) {
private void packetReceived (ClientboundSetSimulationDistancePacket packet) {
simulationDistance = packet.getSimulationDistance();
}
private void packetReceived (ClientboundLevelChunkWithLightPacket packet) {
final ChunkPos pos = new ChunkPos(packet.getX(), packet.getZ());
final ChunkColumn column = new ChunkColumn(pos, packet.getChunkData(), maxY, minY);
chunks.put(pos, column);
}
private void packetReceived (ClientboundForgetLevelChunkPacket packet) {
chunks.remove(new ChunkPos(packet.getX(), packet.getZ()));
}
private void packetReceived (ClientboundBlockUpdatePacket packet) {
final Vector3i position = packet.getEntry().getPosition();
final int id = packet.getEntry().getBlock();
setBlock(position.getX(), position.getY(), position.getZ(), id);
}
private void packetReceived (ClientboundSectionBlocksUpdatePacket packet) {
for (BlockChangeEntry entry : packet.getEntries()) {
final Vector3i position = entry.getPosition();
final int id = entry.getBlock();
setBlock(position.getX(), position.getY(), position.getZ(), id);
}
}
public ChunkColumn getChunk (int x, int z) { return chunks.get(new ChunkPos(x, z)); }
public ChunkColumn getChunk (ChunkPos pos) { return chunks.get(pos); }
public Collection<ChunkColumn> getChunks () { return chunks.values(); }
public int getBlock (int x, int y, int z) {
final ChunkPos chunkPos = new ChunkPos(Math.floorDiv(x, 16), Math.floorDiv(z, 16));
final ChunkColumn chunk = chunks.get(chunkPos);
return chunk == null ? 0 : chunks.get(chunkPos).getBlock(x & 15, y, z & 15);
}
// should this be public?
public void setBlock (int x, int y, int z, int id) {
final ChunkPos chunkPos = new ChunkPos(Math.floorDiv(x, 16), Math.floorDiv(z, 16));
if (!chunks.containsKey(chunkPos)) return;
chunks.get(chunkPos).setBlock(x & 15, y, z & 15, id);
}
public static class Listener {
public void worldChanged (String dimension) {}
}