restore offsets so we are sending correct values to the java server regarding where we want the structure to be placed

This commit is contained in:
onebeastchris 2024-03-27 16:16:32 +01:00
parent a30d49acba
commit 2aa6dce227
6 changed files with 77 additions and 120 deletions

View File

@ -610,8 +610,8 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource {
private @Nullable Vector3i currentStructureBlock;
/**
* Stores current structure block settings so we know what rotation to undo
* if Bedrock decides to change the rotation
* Is stored so we know which rotation/mirror offsetting to undo when sending
* the structure load request to the Java server.
*/
@Setter @Getter
private @Nullable StructureSettings structureSettings;

View File

@ -87,73 +87,16 @@ public class StructureBlockBlockEntityTranslator extends BlockEntityTranslator {
xStructureSize, getOrDefault(tag.get("sizeY"), 0), zStructureSize,
posX, getOrDefault(tag.get("posY"), 0), posZ);
/*
int newXStructureSize = xStructureSize;
int newZStructureSize = zStructureSize;
// Modify positions if mirrored - Bedrock doesn't have this
if (bedrockMirror == (byte) StructureMirror.Z.ordinal()) {
posX = posX + xStructureSize;
newXStructureSize = xStructureSize * -1;
} else if (bedrockMirror == (byte) StructureMirror.X.ordinal()) {
posZ = posZ + zStructureSize;
newZStructureSize = zStructureSize * -1;
}
// Bedrock rotates with the same origin; Java does not
StructureRotation structureRotation = StructureRotation.values()[bedrockRotation];
switch (structureRotation) {
case ROTATE_90 -> {
if (xStructureSize >= 0) {
posX += 1;
}
if (zStructureSize < 0) {
posZ += 1;
}
posX -= zStructureSize;
}
case ROTATE_180 -> {
if (xStructureSize >= 0) {
posX += 1;
}
if (zStructureSize >= 0) {
posZ += 1;
}
posX -= xStructureSize;
posZ -= zStructureSize;
}
case ROTATE_270 -> {
if (xStructureSize < 0) {
posX += 1;
}
if (zStructureSize >= 0) {
posZ += 1;
}
posZ -= xStructureSize;
}
default -> {
if (xStructureSize < 0) {
posX += 1;
}
if (zStructureSize < 0) {
posZ += 1;
}
}
}
*/
Vector3i offset = sizeAndOffset[0];
builder.putInt("xStructureOffset", offset.getX());
builder.putInt("yStructureOffset", offset.getY());
builder.putInt("zStructureOffset", offset.getZ());
Vector3i size = sizeAndOffset[1];
builder.putInt("xStructureSize", size.getX());
builder.putInt("yStructureSize", size.getY());
builder.putInt("zStructureSize", size.getZ());
Vector3i offset = sizeAndOffset[0];
builder.putInt("xStructureOffset", offset.getX());
builder.putInt("yStructureOffset", offset.getY());
builder.putInt("zStructureOffset", offset.getZ());
builder.putFloat("integrity", getOrDefault(tag.get("integrity"), 0f)); // Is 1.0f by default on Java but 100.0f on Bedrock
// Java's "showair" is unrepresented

View File

@ -35,7 +35,6 @@ import org.cloudburstmc.protocol.bedrock.data.structure.StructureBlockType;
import org.cloudburstmc.protocol.bedrock.data.structure.StructureEditorData;
import org.cloudburstmc.protocol.bedrock.data.structure.StructureSettings;
import org.cloudburstmc.protocol.bedrock.packet.StructureBlockUpdatePacket;
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;
@ -46,7 +45,6 @@ public class BedrockStructureBlockUpdateTranslator extends PacketTranslator<Stru
@Override
public void translate(GeyserSession session, StructureBlockUpdatePacket packet) {
GeyserImpl.getInstance().getLogger().info(packet.toString());
StructureEditorData data = packet.getEditorData();
StructureSettings settings = data.getSettings();
@ -66,10 +64,9 @@ public class BedrockStructureBlockUpdateTranslator extends PacketTranslator<Stru
default -> UpdateStructureBlockMode.SAVE;
};
// Ignore mirror - Java appears to mirror on an axis, while Bedrock mirrors in place
StructureMirror mirror = switch (data.getSettings().getMirror()) {
case X -> StructureMirror.FRONT_BACK;
case XZ -> StructureMirror.LEFT_RIGHT;
case Z -> StructureMirror.LEFT_RIGHT;
default -> StructureMirror.NONE;
};

View File

@ -33,14 +33,14 @@ import com.github.steveice10.mc.protocol.packet.ingame.serverbound.inventory.Ser
import org.cloudburstmc.math.vector.Vector3i;
import org.cloudburstmc.protocol.bedrock.data.structure.StructureTemplateRequestOperation;
import org.cloudburstmc.protocol.bedrock.packet.StructureTemplateDataRequestPacket;
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;
import org.geysermc.geyser.util.StructureBlockUtils;
/**
* Packet used in Bedrock to load structure size into the structure block GUI.
* Packet used in Bedrock to load structure size into the structure block GUI. It is sent every time the GUI is opened.
* Or, if the player updates the structure name. Which we can use to request the structure size from the Java server!
* <p>
* Java does not have this preview, instead, Java clients are forced out of the GUI to look at the area.
*/
@ -49,14 +49,10 @@ public class BedrockStructureTemplateDataRequestTranslator extends PacketTransla
@Override
public void translate(GeyserSession session, StructureTemplateDataRequestPacket packet) {
// This packet is actually rather neat. Each time Bedrock players open the structure block,
// it is sent. Which allows us to cache what rotation operation we might need to (un)do :p
GeyserImpl.getInstance().getLogger().info(packet.toString());
if (packet.getOperation().equals(StructureTemplateRequestOperation.QUERY_SAVED_STRUCTURE)) {
// If we send a load packet to the Java server when the structure size is known, we place the structure.
if (!packet.getSettings().getSize().equals(Vector3i.ZERO)) {
if (session.getStructureSettings() == null) {
// This ensures we don't add more rotation offsetting than needed
session.setStructureSettings(packet.getSettings());
}
// Otherwise, the Bedrock client can't load the structure in

View File

@ -104,8 +104,8 @@ public class JavaBlockEntityDataTranslator extends PacketTranslator<ClientboundB
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
// When a Java client is trying to load a structure, it expects the server to send it the size of the structure.
// On 1.20.4, the server does so here - we can pass that through to Bedrock, so we're properly selecting the area.
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();
@ -143,12 +143,13 @@ public class JavaBlockEntityDataTranslator extends PacketTranslator<ClientboundB
Vector3i size = sizeAndOffset[1];
StructureBlockUtils.sendStructureData(session, size.getX(), size.getY(), size.getZ(), name);
// Create dummy structure settings that store size, offset, mirror and rotation.
StructureSettings settings = new StructureSettings("",
false,
false,
false,
size,
sizeAndOffset[1],
sizeAndOffset[0],
-1,
StructureRotation.from(bedrockRotation),
StructureMirror.from(bedrockMirror),

View File

@ -37,6 +37,7 @@ import org.cloudburstmc.protocol.bedrock.data.structure.StructureTemplateRespons
import org.cloudburstmc.protocol.bedrock.packet.StructureTemplateDataRequestPacket;
import org.cloudburstmc.protocol.bedrock.packet.StructureTemplateDataResponsePacket;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.text.ChatColor;
public class StructureBlockUtils {
@ -79,57 +80,73 @@ public class StructureBlockUtils {
return new Vector3i[] {newSettings.getOffset(), newSettings.getSize()};
}
// Remove offsets for old
return removeOffset(old.getRotation(), old.getMirror(), old.getOffset(), old.getSize());
// Remove offsets for new
//return removeOffset(newSettings.getRotation(), newSettings.getMirror(), temp[0], temp[1]);
}
private static Vector3i[] removeOffset(StructureRotation rotation, StructureMirror mirror,
Vector3i offset, Vector3i size) {
int sizeX = size.getX();
int sizeY = size.getY();
int sizeZ = size.getZ();
Vector3i offset = old.getOffset();
Vector3i size = old.getSize();
int offsetX = offset.getX();
int offsetY = offset.getY();
int offsetZ = offset.getZ();
// Undo mirror/rotation changes
switch (rotation) {
case NONE:
break;
case ROTATE_90:
int tempX = offsetX;
offsetX = offsetZ;
offsetZ = sizeX - 1 - tempX;
int tempSizeX = sizeX;
sizeX = sizeZ;
sizeZ = tempSizeX;
break;
case ROTATE_180:
offsetX = sizeX - 1 - offsetX;
offsetZ = sizeZ - 1 - offsetZ;
break;
case ROTATE_270:
int tempY = offsetY;
offsetY = offsetZ;
offsetZ = sizeZ - 1 - tempY;
int tempSizeZ = sizeZ;
sizeZ = sizeX;
sizeX = tempSizeZ;
break;
// First: Let's get the original size. It's not modified when rotating, just with mirroring
int originalSizeX = size.getX();
int originalSizeZ = size.getZ();
switch (old.getMirror()) {
case X -> {
originalSizeX *= -1;
offsetX = offsetX - originalSizeX;
}
case Z -> {
originalSizeZ *= -1;
offsetZ = offsetZ - originalSizeZ;
}
case XZ -> session.sendMessage(ChatColor.RED + "Mirroring on both axis is not possible on Java. Not mirroring!");
}
if (mirror == StructureMirror.Z) {
offsetX = sizeX - 1 - offsetX;
} else if (mirror == StructureMirror.X) {
offsetZ = sizeZ - 1 - offsetZ;
switch (old.getRotation()) {
case ROTATE_90 -> {
if (originalSizeX >= 0) {
offsetX -= 1;
}
if (originalSizeZ < 0) {
offsetZ -= 1;
}
offsetX += originalSizeZ;
}
case ROTATE_180 -> {
if (originalSizeX >= 0) {
offsetX -= 1;
}
if (originalSizeZ >= 0) {
offsetZ -= 1;
}
offsetX += originalSizeX;
offsetZ += originalSizeZ;
}
case ROTATE_270 -> {
if (originalSizeX < 0) {
offsetX -= 1;
}
if (originalSizeZ >= 0) {
offsetZ -= 1;
}
offsetZ += originalSizeX;
}
default -> {
if (originalSizeX < 0) {
offsetX -= 1;
}
if (originalSizeZ < 0) {
offsetZ -= 1;
}
}
}
return new Vector3i[]{Vector3i.from(offsetX, offsetY, offsetZ), Vector3i.from(sizeX, sizeY, sizeZ)};
Vector3i originalOffset = Vector3i.from(offsetX, offset.getY(), offsetZ);
Vector3i originalSize = Vector3i.from(originalSizeX, size.getY(), originalSizeZ);
return new Vector3i[]{originalOffset, originalSize};
}
public static Vector3i[] addOffsets(byte bedrockRotation, byte bedrockMirror,
@ -187,6 +204,9 @@ public class StructureBlockUtils {
}
}
return new Vector3i[]{Vector3i.from(offsetX, offsetY, offsetZ), Vector3i.from(newXStructureSize, sizeY, newZStructureSize)};
Vector3i offset = Vector3i.from(offsetX, offsetY, offsetZ);
Vector3i size = Vector3i.from(newXStructureSize, sizeY, newZStructureSize);
return new Vector3i[]{offset, size};
}
}