Skip to content

Commit 0e13fa7

Browse files
TiagoFar78dordsor21
authored andcommitted
fix item frame rotation (#2820)
1 parent 0bcd256 commit 0e13fa7

1 file changed

Lines changed: 81 additions & 14 deletions

File tree

worldedit-core/src/main/java/com/sk89q/worldedit/function/entity/ExtentEntityCopy.java

Lines changed: 81 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -37,13 +37,14 @@
3737
import com.sk89q.worldedit.util.Location;
3838
import com.sk89q.worldedit.util.concurrency.LazyReference;
3939
import com.sk89q.worldedit.world.entity.EntityTypes;
40+
import org.enginehub.linbus.tree.LinByteTag;
4041
import org.enginehub.linbus.tree.LinCompoundTag;
4142
import org.enginehub.linbus.tree.LinFloatTag;
4243
import org.enginehub.linbus.tree.LinIntArrayTag;
4344
import org.enginehub.linbus.tree.LinListTag;
44-
import org.enginehub.linbus.tree.LinIntArrayTag;
4545
import org.enginehub.linbus.tree.LinNumberTag;
4646
import org.enginehub.linbus.tree.LinTag;
47+
import org.enginehub.linbus.tree.LinStringTag;
4748
import org.enginehub.linbus.tree.LinTagType;
4849

4950
import java.util.UUID;
@@ -275,26 +276,48 @@ private BaseEntity transformNbtData(BaseEntity state) {
275276
}
276277

277278
if (tryGetFacingData(tag) instanceof FacingTagData(String facingKey, LinNumberTag<?> tagFacing)) {
278-
boolean isPainting = state.getType() == EntityTypes.PAINTING; // Paintings have different facing values
279-
Direction direction = isPainting
280-
? MCDirections.fromHorizontalHanging(tagFacing.value().intValue())
281-
: MCDirections.fromHanging(tagFacing.value().intValue());
282-
283-
if (direction != null) {
279+
if (state.getType() == EntityTypes.PAINTING) { // Paintings have different facing values
280+
Direction direction = MCDirections.fromHorizontalHanging(tagFacing.value().intValue());
284281
Vector3 vector = transform
285282
.apply(direction.toVector())
286283
.subtract(transform.apply(Vector3.ZERO))
287284
.normalize();
288285
Direction newDirection = Direction.findClosest(vector, Flag.CARDINAL);
289-
290-
if (newDirection != null) {
291-
byte facingValue = (byte) (
292-
isPainting
293-
? MCDirections.toHorizontalHanging(newDirection)
294-
: MCDirections.toHanging(newDirection)
286+
byte facingValue = (byte) MCDirections.toHorizontalHanging(newDirection);
287+
builder.putByte(facingKey, facingValue);
288+
} else {
289+
Direction facingDirection = MCDirections.fromHanging(tagFacing.value().intValue());
290+
Vector3 facingVector = transform
291+
.apply(facingDirection.toVector())
292+
.subtract(transform.apply(Vector3.ZERO))
293+
.normalize();
294+
Direction newFacingDirection = Direction.findClosest(facingVector, Flag.CARDINAL | Flag.UPRIGHT);
295+
byte facingValue = (byte) MCDirections.toHanging(newFacingDirection);
296+
builder.putByte(facingKey, facingValue);
297+
298+
String itemRotationKey = "ItemRotation";
299+
if (!transform.isIdentity() && tag.value().get(itemRotationKey) instanceof LinByteTag tagItemRotation) {
300+
String itemId = getItemInItemFrame(tag);
301+
int availableRotations = itemId != null && itemId.equals("minecraft:filled_map") ? 4 : 8;
302+
Direction rotationBaseDirection =
303+
facingDirection == Direction.UP || facingDirection == Direction.DOWN
304+
? Direction.NORTH
305+
: Direction.UP;
306+
int itemRotation = tagItemRotation.value().intValue();
307+
Vector3 rotationVector = getItemRotationVector(
308+
rotationBaseDirection, facingDirection.toVector(), itemRotation, availableRotations
309+
);
310+
Vector3 newRotationVector = transform.apply(rotationVector);
311+
Direction newRotationBaseDirection =
312+
newFacingDirection == Direction.UP || newFacingDirection == Direction.DOWN
313+
? Direction.NORTH
314+
: Direction.UP;
315+
byte newItemRotation = (byte) getItemRotationSteps(
316+
newRotationBaseDirection, newFacingDirection, newRotationVector, availableRotations
295317
);
296-
builder.putByte(facingKey, facingValue);
318+
builder.putByte(itemRotationKey, newItemRotation);
297319
}
320+
298321
}
299322
}
300323

@@ -346,6 +369,50 @@ private BaseEntity transformNbtData(BaseEntity state) {
346369
return state;
347370
}
348371

372+
private Vector3 getItemRotationVector(Direction baseDirection, Vector3 facingVector, int itemRotation, int rotations) {
373+
Vector3 baseVec = baseDirection.toVector().normalize();
374+
double angle = Math.toRadians(itemRotation * (360f / rotations));
375+
Vector3 rotated = rotateAroundAxis(baseVec, facingVector, -angle);
376+
return rotated.normalize();
377+
}
378+
379+
private Vector3 rotateAroundAxis(Vector3 vec, Vector3 axis, double angle) {
380+
axis = axis.normalize();
381+
double cos = Math.cos(angle);
382+
double sin = Math.sin(angle);
383+
return vec.multiply(cos).add(axis.cross(vec).multiply(sin)).add(axis.multiply(axis.dot(vec) * (1 - cos)));
384+
}
385+
386+
private int getItemRotationSteps(Direction baseDirection, Direction facingDirection, Vector3 targetVector, int rotations) {
387+
Vector3 baseVec = baseDirection.toVector();
388+
389+
double det = facingDirection.toVector().dot(baseVec.cross(targetVector));
390+
double dot = baseVec.dot(targetVector);
391+
double signedAngle = Math.atan2(det, dot);
392+
393+
double stepsDouble = -signedAngle / (Math.PI / (rotations / 2f));
394+
int steps = (int) Math.round(stepsDouble) % rotations;
395+
if (steps < 0) {
396+
steps += rotations;
397+
}
398+
399+
if (facingDirection == Direction.DOWN) {
400+
steps = (steps + (rotations / 2)) % rotations;
401+
}
402+
403+
return steps;
404+
}
405+
406+
private String getItemInItemFrame(LinCompoundTag tag) {
407+
if (tag.value().get("Item") instanceof LinCompoundTag tagItem) {
408+
if (tagItem.value().get("id") instanceof LinStringTag tagId) {
409+
return tagId.value();
410+
}
411+
}
412+
413+
return null;
414+
}
415+
349416
private record FacingTagData(String facingKey, LinNumberTag<?> tagFacing) {
350417
}
351418

0 commit comments

Comments
 (0)