|
37 | 37 | import com.sk89q.worldedit.util.Location; |
38 | 38 | import com.sk89q.worldedit.util.concurrency.LazyReference; |
39 | 39 | import com.sk89q.worldedit.world.entity.EntityTypes; |
| 40 | +import org.enginehub.linbus.tree.LinByteTag; |
40 | 41 | import org.enginehub.linbus.tree.LinCompoundTag; |
41 | 42 | import org.enginehub.linbus.tree.LinFloatTag; |
42 | 43 | import org.enginehub.linbus.tree.LinIntArrayTag; |
43 | 44 | import org.enginehub.linbus.tree.LinListTag; |
44 | | -import org.enginehub.linbus.tree.LinIntArrayTag; |
45 | 45 | import org.enginehub.linbus.tree.LinNumberTag; |
46 | 46 | import org.enginehub.linbus.tree.LinTag; |
| 47 | +import org.enginehub.linbus.tree.LinStringTag; |
47 | 48 | import org.enginehub.linbus.tree.LinTagType; |
48 | 49 |
|
49 | 50 | import java.util.UUID; |
@@ -275,26 +276,48 @@ private BaseEntity transformNbtData(BaseEntity state) { |
275 | 276 | } |
276 | 277 |
|
277 | 278 | 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()); |
284 | 281 | Vector3 vector = transform |
285 | 282 | .apply(direction.toVector()) |
286 | 283 | .subtract(transform.apply(Vector3.ZERO)) |
287 | 284 | .normalize(); |
288 | 285 | 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 |
295 | 317 | ); |
296 | | - builder.putByte(facingKey, facingValue); |
| 318 | + builder.putByte(itemRotationKey, newItemRotation); |
297 | 319 | } |
| 320 | + |
298 | 321 | } |
299 | 322 | } |
300 | 323 |
|
@@ -346,6 +369,50 @@ private BaseEntity transformNbtData(BaseEntity state) { |
346 | 369 | return state; |
347 | 370 | } |
348 | 371 |
|
| 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 | + |
349 | 416 | private record FacingTagData(String facingKey, LinNumberTag<?> tagFacing) { |
350 | 417 | } |
351 | 418 |
|
|
0 commit comments