no more parsing of java structure templates

This commit is contained in:
onebeastchris 2024-03-24 00:56:01 +01:00
parent eabed1f0b0
commit c9d4b9a797
8 changed files with 121 additions and 234 deletions

View file

@ -27,12 +27,8 @@ package org.geysermc.geyser.platform.mod.world;
import com.github.steveice10.mc.protocol.data.game.entity.player.GameMode;
import com.github.steveice10.mc.protocol.data.game.level.block.BlockEntityInfo;
import it.unimi.dsi.fastutil.ints.IntArrayList;
import it.unimi.dsi.fastutil.ints.IntList;
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
import net.minecraft.SharedConstants;
import net.minecraft.core.BlockPos;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.nbt.ByteArrayTag;
import net.minecraft.nbt.ByteTag;
import net.minecraft.nbt.CompoundTag;
@ -44,12 +40,10 @@ import net.minecraft.nbt.IntTag;
import net.minecraft.nbt.ListTag;
import net.minecraft.nbt.LongArrayTag;
import net.minecraft.nbt.LongTag;
import net.minecraft.nbt.NbtUtils;
import net.minecraft.nbt.ShortTag;
import net.minecraft.nbt.StringTag;
import net.minecraft.nbt.Tag;
import net.minecraft.nbt.TagVisitor;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.item.ItemStack;
@ -60,23 +54,15 @@ import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.entity.BannerBlockEntity;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.entity.LecternBlockEntity;
import net.minecraft.world.level.block.entity.StructureBlockEntity;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
import net.minecraft.world.level.chunk.ChunkAccess;
import net.minecraft.world.level.chunk.ChunkStatus;
import net.minecraft.world.level.chunk.LevelChunk;
import net.minecraft.world.level.chunk.LevelChunkSection;
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.cloudburstmc.math.vector.Vector3i;
import org.cloudburstmc.nbt.NbtList;
import org.cloudburstmc.nbt.NbtMap;
import org.cloudburstmc.nbt.NbtMapBuilder;
import org.cloudburstmc.nbt.NbtType;
import org.cloudburstmc.protocol.bedrock.data.structure.StructureTemplateResponseType;
import org.cloudburstmc.protocol.bedrock.packet.StructureTemplateDataRequestPacket;
import org.cloudburstmc.protocol.bedrock.packet.StructureTemplateDataResponsePacket;
import org.geysermc.erosion.util.LecternUtils;
import org.geysermc.geyser.level.GeyserWorldManager;
import org.geysermc.geyser.network.GameProtocol;
@ -87,7 +73,6 @@ import org.geysermc.geyser.util.BlockEntityUtils;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
public class GeyserModWorldManager extends GeyserWorldManager {
@ -227,131 +212,6 @@ public class GeyserModWorldManager extends GeyserWorldManager {
NbtMap blockEntityTag = lecternTag.build();
BlockEntityUtils.updateBlockEntity(session, blockEntityTag, Vector3i.from(x, y, z));
}
@Override
public void handleStructureDataRequest(StructureTemplateDataRequestPacket packet, GeyserSession session) {
server.execute(() -> {
ResourceLocation location = ResourceLocation.tryParse(packet.getName());
if (location == null) {
sendNoStructureFound(session);
return;
}
Optional<StructureTemplate> structure = server.getStructureManager().get(location);
if (structure.isEmpty()) {
sendNoStructureFound(session);
return;
}
// Required to find structure block
ServerPlayer player = this.getPlayer(session);
if (player == null) {
sendNoStructureFound(session);
return;
}
BlockEntity blockEntity = player.level().getBlockEntity(new BlockPos(packet.getPosition().getX(), packet.getPosition().getY(), packet.getPosition().getZ()));
if (!(blockEntity instanceof StructureBlockEntity)) {
sendNoStructureFound(session);
return;
}
StructureTemplate structureTemplate = structure.get();
// Easiest to use a tag, I guess
CompoundTag tag = structure.get().save(new CompoundTag());
int sizeX = structureTemplate.getSize().getX();
int sizeY = structureTemplate.getSize().getY();
int sizeZ = structureTemplate.getSize().getZ();
NbtMapBuilder builder = NbtMap.builder();
builder.putInt("format_version", 1);
builder.putList("structure_world_origin", NbtType.INT, packet.getPosition().getX(), packet.getPosition().getY(), packet.getPosition().getZ()); // ???
builder.putList("size", NbtType.INT, sizeX, sizeY, sizeZ);
IntList layerZero = new IntArrayList();
//layerZero.add(0); // ??
IntList layerOne = new IntArrayList();
//layerOne.add(-1); // palette header???
List<NbtMap> bedrockPalette = new ObjectArrayList<>();
ListTag javaPalette = tag.getList("palette", 10);
ListTag blocks = tag.getList("blocks", 10);
for (int y = 0; y < sizeY; y++) {
for (int x = 0; x < sizeX; x++) {
for (int z = 0; z < sizeZ; z++) {
boolean hasAppliedBlock = false;
for (int i = 0; i < blocks.size(); i++) {
CompoundTag currentBlock = blocks.getCompound(i);
ListTag pos = currentBlock.getList("pos", 6);
if (pos.getInt(0) != x && pos.getInt(1) != y && pos.getInt(2) != z) {
// Position doesn't match
continue;
}
// Lookup the table of which Java block this is mapped to
CompoundTag javaBlock = javaPalette.getCompound(currentBlock.getInt("state"));
BlockState blockState = NbtUtils.readBlockState(BuiltInRegistries.BLOCK.asLookup(), javaBlock);
int javaId = Block.getId(blockState);
int bedrockIndex = getOrAddToBedrockPalette(session, javaId, bedrockPalette);
layerZero.add(bedrockIndex);
var optional = blockState.getOptionalValue(BlockStateProperties.WATERLOGGED);
if (optional.isPresent() && optional.get()) {
layerOne.add(1);
} else {
layerOne.add(0);
}
blocks.remove(i); // Already used
hasAppliedBlock = true;
break;
}
if (!hasAppliedBlock) {
// Not found - air?
layerZero.add(getOrAddToBedrockPalette(session,0, bedrockPalette));
layerOne.add(-1);
}
}
}
}
NbtMapBuilder structureBuilder = NbtMap.builder();
structureBuilder.putList("block_indices", NbtType.LIST, new NbtList<>(NbtType.INT, layerZero), new NbtList<>(NbtType.INT, layerOne));
structureBuilder.putList("entities", NbtType.COMPOUND);
structureBuilder.putCompound("palette", NbtMap.builder().putCompound("default",
NbtMap.builder().putList("block_palette", NbtType.COMPOUND, bedrockPalette)
.putCompound("block_position_data", NbtMap.EMPTY).build()).build());
builder.putCompound("structure", structureBuilder.build());
System.out.println(builder);
StructureTemplateDataResponsePacket responsePacket = new StructureTemplateDataResponsePacket();
responsePacket.setName(packet.getName());
responsePacket.setSave(true);
responsePacket.setTag(builder.build());
responsePacket.setType(StructureTemplateResponseType.QUERY);
session.sendUpstreamPacket(responsePacket);
});
}
protected int getOrAddToBedrockPalette(GeyserSession session, int javaState, List<NbtMap> bedrockPalette) {
NbtMap tag = session.getBlockMappings().getBedrockBlock(javaState).getState();
for (int i = 0; i < bedrockPalette.size(); i++) {
if (tag == bedrockPalette.get(i)) {
return i;
}
}
bedrockPalette.add(tag);
return bedrockPalette.size() - 1;
}
protected void sendNoStructureFound(GeyserSession session) {
StructureTemplateDataResponsePacket packet = new StructureTemplateDataResponsePacket();
packet.setName("");
packet.setSave(false);
packet.setType(StructureTemplateResponseType.NONE);
session.sendUpstreamPacket(packet);
}
@Override
public boolean hasPermission(GeyserSession session, String permission) {

View file

@ -36,13 +36,7 @@ import org.bukkit.entity.Player;
import org.bukkit.plugin.Plugin;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.cloudburstmc.nbt.NbtList;
import org.cloudburstmc.nbt.NbtMap;
import org.cloudburstmc.nbt.NbtMapBuilder;
import org.cloudburstmc.nbt.NbtType;
import org.cloudburstmc.protocol.bedrock.data.structure.StructureTemplateResponseType;
import org.cloudburstmc.protocol.bedrock.packet.StructureTemplateDataRequestPacket;
import org.cloudburstmc.protocol.bedrock.packet.StructureTemplateDataResponsePacket;
import org.geysermc.erosion.bukkit.BukkitLecterns;
import org.geysermc.erosion.bukkit.BukkitUtils;
import org.geysermc.erosion.bukkit.PickBlockUtils;
@ -65,19 +59,6 @@ import java.util.concurrent.CompletableFuture;
public class GeyserSpigotWorldManager extends WorldManager {
private final Plugin plugin;
private final BukkitLecterns lecterns;
private static final NbtMap EMPTY_STRUCTURE_DATA;
static {
NbtMapBuilder builder = NbtMap.builder();
builder.putInt("format_version", 1);
builder.putCompound("structure", NbtMap.builder()
.putList("block_indices", NbtType.LIST, NbtList.EMPTY, NbtList.EMPTY)
.putList("entities", NbtType.COMPOUND)
.putCompound("palette", NbtMap.EMPTY)
.build());
builder.putList("structure_world_origin", NbtType.INT, 0, 0, 0);
EMPTY_STRUCTURE_DATA = builder.build();
}
public GeyserSpigotWorldManager(Plugin plugin) {
this.plugin = plugin;
@ -149,27 +130,6 @@ public class GeyserSpigotWorldManager extends WorldManager {
}
}
// TODO adapt to actually send the requests
@Override
public void handleStructureDataRequest(StructureTemplateDataRequestPacket packet, GeyserSession session) {
// Always send a blank form
sendEmptyStructureData(session, packet);
}
/**
* Send an empty structure data that tricks Bedrock into thinking it loaded successfully
*/
protected void sendEmptyStructureData(GeyserSession session, StructureTemplateDataRequestPacket packet) {
StructureTemplateDataResponsePacket responsePacket = new StructureTemplateDataResponsePacket();
responsePacket.setName(packet.getName());
responsePacket.setSave(true);
responsePacket.setTag(EMPTY_STRUCTURE_DATA.toBuilder()
.putList("size", NbtType.INT, packet.getSettings().getSize().getX(), packet.getSettings().getSize().getY(), packet.getSettings().getSize().getZ())
.build());
responsePacket.setType(StructureTemplateResponseType.QUERY);
session.sendUpstreamPacket(responsePacket);
}
private @Nullable Chunk getChunk(World world, int x, int z) {
if (!world.isChunkLoaded(x, z)) {
return null;

View file

@ -34,13 +34,8 @@ import it.unimi.dsi.fastutil.objects.ObjectArrayList;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.cloudburstmc.math.vector.Vector3i;
import org.cloudburstmc.nbt.NbtList;
import org.cloudburstmc.nbt.NbtMap;
import org.cloudburstmc.nbt.NbtMapBuilder;
import org.cloudburstmc.nbt.NbtType;
import org.cloudburstmc.protocol.bedrock.data.structure.StructureTemplateResponseType;
import org.cloudburstmc.protocol.bedrock.packet.StructureTemplateDataRequestPacket;
import org.cloudburstmc.protocol.bedrock.packet.StructureTemplateDataResponsePacket;
import org.geysermc.erosion.packet.backendbound.BackendboundBatchBlockEntityPacket;
import org.geysermc.erosion.packet.backendbound.BackendboundBatchBlockRequestPacket;
import org.geysermc.erosion.packet.backendbound.BackendboundBlockEntityPacket;
@ -57,20 +52,6 @@ import java.util.concurrent.CompletableFuture;
public class GeyserWorldManager extends WorldManager {
private final Object2ObjectMap<String, String> gameruleCache = new Object2ObjectOpenHashMap<>();
private static final NbtMap EMPTY_STRUCTURE_DATA;
static {
NbtMapBuilder builder = NbtMap.builder();
builder.putInt("format_version", 1);
builder.putCompound("structure", NbtMap.builder()
.putList("block_indices", NbtType.LIST, NbtList.EMPTY, NbtList.EMPTY)
.putList("entities", NbtType.COMPOUND)
.putCompound("palette", NbtMap.EMPTY)
.build());
builder.putList("structure_world_origin", NbtType.INT, 0, 0, 0);
EMPTY_STRUCTURE_DATA = builder.build();
}
@Override
public int getBlockAt(GeyserSession session, int x, int y, int z) {
var erosionHandler = session.getErosionHandler().getAsActive();
@ -154,26 +135,6 @@ public class GeyserWorldManager extends WorldManager {
BlockEntityUtils.updateBlockEntity(session, lecternTag.build(), Vector3i.from(x, y, z));
}
@Override
public void handleStructureDataRequest(StructureTemplateDataRequestPacket packet, GeyserSession session) {
// Always send a blank form
sendEmptyStructureData(session, packet);
}
/**
* Send an empty structure data that tricks Bedrock into thinking it loaded successfully
*/
protected void sendEmptyStructureData(GeyserSession session, StructureTemplateDataRequestPacket packet) {
StructureTemplateDataResponsePacket responsePacket = new StructureTemplateDataResponsePacket();
responsePacket.setName(packet.getName());
responsePacket.setSave(true);
responsePacket.setTag(EMPTY_STRUCTURE_DATA.toBuilder()
.putList("size", NbtType.INT, packet.getSettings().getSize().getX(), packet.getSettings().getSize().getY(), packet.getSettings().getSize().getZ())
.build());
responsePacket.setType(StructureTemplateResponseType.QUERY);
session.sendUpstreamPacket(responsePacket);
}
@Override
public boolean shouldExpectLecternHandled(GeyserSession session) {
return session.getErosionHandler().isActive();

View file

@ -32,7 +32,6 @@ import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.cloudburstmc.math.vector.Vector3i;
import org.cloudburstmc.protocol.bedrock.packet.StructureTemplateDataRequestPacket;
import org.geysermc.erosion.util.BlockPositionIterator;
import org.geysermc.geyser.session.GeyserSession;
@ -127,14 +126,6 @@ public abstract class WorldManager {
*/
public abstract void sendLecternData(GeyserSession session, int x, int z, List<BlockEntityInfo> blockEntityInfos);
/**
* Handle Bedrock requesting data for a structure.
*
* @param session the session of the player requested structure information
* @param packet the packet the Bedrock client has sent
*/
public abstract void handleStructureDataRequest(StructureTemplateDataRequestPacket packet, GeyserSession session);
/**
* @return whether we should expect lectern data to update, or if we have to fall back on a workaround.
*/

View file

@ -602,6 +602,12 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource {
@Setter
private @Nullable ItemData currentBook = null;
/**
* Stores the current structure block position, if we are in one
*/
@Setter @Getter
private @Nullable Vector3i currentStructureBlock;
private final GeyserCameraData cameraData;
private final GeyserEntityData entityData;

View file

@ -37,8 +37,6 @@ public class StructureBlockBlockEntityTranslator extends BlockEntityTranslator {
@Override
public void translateTag(NbtMapBuilder builder, CompoundTag tag, int blockState) {
GeyserImpl.getInstance().getLogger().info("structure block tag: " +
tag.toString() + " " + builder.toString() + " " + blockState);
if (tag.size() < 5) {
return; // These values aren't here
}

View file

@ -25,24 +25,88 @@
package org.geysermc.geyser.translator.protocol.bedrock;
import com.github.steveice10.mc.protocol.data.game.inventory.UpdateStructureBlockAction;
import com.github.steveice10.mc.protocol.data.game.inventory.UpdateStructureBlockMode;
import com.github.steveice10.mc.protocol.data.game.level.block.StructureMirror;
import com.github.steveice10.mc.protocol.data.game.level.block.StructureRotation;
import com.github.steveice10.mc.protocol.packet.ingame.serverbound.inventory.ServerboundSetStructureBlockPacket;
import org.cloudburstmc.nbt.NbtList;
import org.cloudburstmc.nbt.NbtMap;
import org.cloudburstmc.nbt.NbtMapBuilder;
import org.cloudburstmc.nbt.NbtType;
import org.cloudburstmc.protocol.bedrock.data.structure.StructureTemplateRequestOperation;
import org.cloudburstmc.protocol.bedrock.data.structure.StructureTemplateResponseType;
import org.cloudburstmc.protocol.bedrock.packet.StructureTemplateDataRequestPacket;
import org.cloudburstmc.protocol.bedrock.packet.StructureTemplateDataResponsePacket;
import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.translator.protocol.PacketTranslator;
import org.geysermc.geyser.translator.protocol.Translator;
/**
* Packet used in Bedrock to load structures into the structure block GUI.
* Packet used in Bedrock to load structure size into the structure block GUI.
* <p>
* Java does not have this functionality.
* Java does not have this preview, instead, Java clients are forced out of the GUI to look at the area.
*/
@Translator(packet = StructureTemplateDataRequestPacket.class)
public class BedrockStructureTemplateDataRequestTranslator extends PacketTranslator<StructureTemplateDataRequestPacket> {
private static final NbtMap EMPTY_STRUCTURE_DATA;
static {
NbtMapBuilder builder = NbtMap.builder();
builder.putInt("format_version", 1);
builder.putCompound("structure", NbtMap.builder()
.putList("block_indices", NbtType.LIST, NbtList.EMPTY, NbtList.EMPTY)
.putList("entities", NbtType.COMPOUND)
.putCompound("palette", NbtMap.EMPTY)
.build());
builder.putList("structure_world_origin", NbtType.INT, 0, 0, 0);
EMPTY_STRUCTURE_DATA = builder.build();
}
@Override
public void translate(GeyserSession session, StructureTemplateDataRequestPacket packet) {
GeyserImpl.getInstance().getLogger().info(packet.toString());
GeyserImpl.getInstance().getLogger().error(packet.toString());
if (packet.getOperation().equals(StructureTemplateRequestOperation.QUERY_SAVED_STRUCTURE)) {
session.setCurrentStructureBlock(packet.getPosition());
session.getGeyser().getWorldManager().handleStructureDataRequest(packet, session);
// Request a "load" from Java server so it sends us the structures size :p
var settings = packet.getSettings();
com.github.steveice10.mc.protocol.data.game.level.block.StructureRotation rotation = switch (settings.getRotation()) {
case ROTATE_90 -> StructureRotation.CLOCKWISE_90;
case ROTATE_180 -> StructureRotation.CLOCKWISE_180;
case ROTATE_270 -> StructureRotation.COUNTERCLOCKWISE_90;
default -> StructureRotation.NONE;
};
ServerboundSetStructureBlockPacket structureBlockPacket = new ServerboundSetStructureBlockPacket(
packet.getPosition(),
UpdateStructureBlockAction.LOAD_STRUCTURE,
UpdateStructureBlockMode.LOAD,
packet.getName(),
settings.getOffset(),
settings.getSize(),
StructureMirror.NONE,
rotation,
"",
settings.getIntegrityValue(),
settings.getIntegritySeed(),
settings.isIgnoringEntities(),
false,
true
);
session.sendDownstreamPacket(structureBlockPacket);
} else {
StructureTemplateDataResponsePacket responsePacket = new StructureTemplateDataResponsePacket();
responsePacket.setName(packet.getName());
responsePacket.setSave(true);
responsePacket.setTag(EMPTY_STRUCTURE_DATA.toBuilder()
.putList("size", NbtType.INT, packet.getSettings().getSize().getX(),
packet.getSettings().getSize().getY(), packet.getSettings().getSize().getZ())
.build());
responsePacket.setType(StructureTemplateResponseType.QUERY);
session.sendUpstreamPacket(responsePacket);
}
}
}

View file

@ -28,11 +28,19 @@ package org.geysermc.geyser.translator.protocol.java.level;
import com.github.steveice10.mc.protocol.data.game.entity.player.GameMode;
import com.github.steveice10.mc.protocol.data.game.level.block.BlockEntityType;
import com.github.steveice10.mc.protocol.packet.ingame.clientbound.level.ClientboundBlockEntityDataPacket;
import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
import org.cloudburstmc.math.vector.Vector3i;
import org.cloudburstmc.nbt.NbtList;
import org.cloudburstmc.nbt.NbtMap;
import org.cloudburstmc.nbt.NbtMapBuilder;
import org.cloudburstmc.nbt.NbtType;
import org.cloudburstmc.protocol.bedrock.data.definitions.BlockDefinition;
import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerType;
import org.cloudburstmc.protocol.bedrock.data.structure.StructureTemplateResponseType;
import org.cloudburstmc.protocol.bedrock.packet.ContainerOpenPacket;
import org.cloudburstmc.protocol.bedrock.packet.StructureTemplateDataResponsePacket;
import org.cloudburstmc.protocol.bedrock.packet.UpdateBlockPacket;
import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.level.block.BlockStateValues;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.translator.level.block.entity.BlockEntityTranslator;
@ -45,6 +53,20 @@ import org.geysermc.geyser.util.BlockEntityUtils;
@Translator(packet = ClientboundBlockEntityDataPacket.class)
public class JavaBlockEntityDataTranslator extends PacketTranslator<ClientboundBlockEntityDataPacket> {
private static final NbtMap EMPTY_STRUCTURE_DATA;
static {
NbtMapBuilder builder = NbtMap.builder();
builder.putInt("format_version", 1);
builder.putCompound("structure", NbtMap.builder()
.putList("block_indices", NbtType.LIST, NbtList.EMPTY, NbtList.EMPTY)
.putList("entities", NbtType.COMPOUND)
.putCompound("palette", NbtMap.EMPTY)
.build());
builder.putList("structure_world_origin", NbtType.INT, 0, 0, 0);
EMPTY_STRUCTURE_DATA = builder.build();
}
@Override
public void translate(GeyserSession session, ClientboundBlockEntityDataPacket packet) {
final BlockEntityType type = packet.getType();
@ -95,5 +117,30 @@ public class JavaBlockEntityDataTranslator extends PacketTranslator<ClientboundB
openPacket.setUniqueEntityId(-1);
session.sendUpstreamPacket(openPacket);
}
// On Java edition, if we are trying to load a structure, we expect the server to send us the size of the structure.
// On 1.20.4, the server does here - we can pass that through to Bedrock so we're properly selecting the area selection
if (type == BlockEntityType.STRUCTURE_BLOCK && session.getGameMode() == GameMode.CREATIVE &&
packet.getPosition().equals(session.getCurrentStructureBlock()) && packet.getNbt() != null && packet.getNbt().size() > 5) {
CompoundTag map = packet.getNbt();
String mode = (String) map.get("mode").getValue();
if (!mode.equalsIgnoreCase("LOAD")) {
GeyserImpl.getInstance().getLogger().info(mode);
return;
}
StructureTemplateDataResponsePacket responsePacket = new StructureTemplateDataResponsePacket();
responsePacket.setName((String) map.get("name").getValue());
responsePacket.setSave(true);
responsePacket.setTag(EMPTY_STRUCTURE_DATA.toBuilder()
.putList("size", NbtType.INT, (int) map.get("sizeX").getValue(), (int) map.get("sizeY").getValue(), (int) map.get("sizeZ").getValue())
.build());
responsePacket.setType(StructureTemplateResponseType.QUERY);
GeyserImpl.getInstance().getLogger().info(responsePacket.toString());
session.sendUpstreamPacket(responsePacket);
session.setCurrentStructureBlock(null);
}
}
}