Apply transformations to NBT data of tile entities (fixes rotation of skulls)

This commit is contained in:
FrozenBrain 2016-05-19 19:16:59 +02:00 committed by wizjany
parent 8f50f5adfb
commit 4a7683d5bf
2 changed files with 123 additions and 1 deletions

View File

@ -19,12 +19,17 @@
package com.sk89q.worldedit.function.block; package com.sk89q.worldedit.function.block;
import com.sk89q.worldedit.extent.Extent; import com.sk89q.jnbt.CompoundTag;
import com.sk89q.jnbt.CompoundTagBuilder;
import com.sk89q.worldedit.Vector; import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.blocks.BaseBlock; import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.function.RegionFunction; import com.sk89q.worldedit.function.RegionFunction;
import com.sk89q.worldedit.internal.helper.MCDirections;
import com.sk89q.worldedit.math.transform.Transform; import com.sk89q.worldedit.math.transform.Transform;
import com.sk89q.worldedit.util.Direction;
import com.sk89q.worldedit.util.Direction.Flag;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
@ -66,7 +71,46 @@ public class ExtentBlockCopy implements RegionFunction {
BaseBlock block = source.getBlock(position); BaseBlock block = source.getBlock(position);
Vector orig = position.subtract(from); Vector orig = position.subtract(from);
Vector transformed = transform.apply(orig); Vector transformed = transform.apply(orig);
// Apply transformations to NBT data if necessary
block = transformNbtData(block);
return destination.setBlock(transformed.add(to), block); return destination.setBlock(transformed.add(to), block);
} }
/**
* Transform NBT data in the given block state and return a new instance
* if the NBT data needs to be transformed.
*
* @param state the existing state
* @return a new state or the existing one
*/
private BaseBlock transformNbtData(BaseBlock state) {
CompoundTag tag = state.getNbtData();
if (tag != null) {
// Handle blocks which store their rotation in NBT
if (tag.containsKey("Rot")) {
int rot = tag.asInt("Rot");
Direction direction = MCDirections.fromRotation(rot);
if (direction != null) {
Vector vector = transform.apply(direction.toVector()).subtract(transform.apply(Vector.ZERO)).normalize();
Direction newDirection = Direction.findClosest(vector, Flag.CARDINAL | Flag.ORDINAL | Flag.SECONDARY_ORDINAL);
if (newDirection != null) {
CompoundTagBuilder builder = tag.createBuilder();
builder.putByte("Rot", (byte) MCDirections.toRotation(newDirection));
return new BaseBlock(state.getId(), state.getData(), builder.build());
}
}
}
}
return state;
}
} }

View File

@ -77,4 +77,82 @@ public final class MCDirections {
} }
} }
public static Direction fromRotation(int i) {
switch (i) {
case 0:
return Direction.SOUTH;
case 1:
return Direction.SOUTH_SOUTHWEST;
case 2:
return Direction.SOUTHWEST;
case 3:
return Direction.WEST_SOUTHWEST;
case 4:
return Direction.WEST;
case 5:
return Direction.WEST_NORTHWEST;
case 6:
return Direction.NORTHWEST;
case 7:
return Direction.NORTH_NORTHWEST;
case 8:
return Direction.NORTH;
case 9:
return Direction.NORTH_NORTHEAST;
case 10:
return Direction.NORTHEAST;
case 11:
return Direction.EAST_NORTHEAST;
case 12:
return Direction.EAST;
case 13:
return Direction.EAST_SOUTHEAST;
case 14:
return Direction.SOUTHEAST;
case 15:
return Direction.SOUTH_SOUTHEAST;
default:
return Direction.NORTH;
}
}
public static int toRotation(Direction direction) {
switch (direction) {
case SOUTH:
return 0;
case SOUTH_SOUTHWEST:
return 1;
case SOUTHWEST:
return 2;
case WEST_SOUTHWEST:
return 3;
case WEST:
return 4;
case WEST_NORTHWEST:
return 5;
case NORTHWEST:
return 6;
case NORTH_NORTHWEST:
return 7;
case NORTH:
return 8;
case NORTH_NORTHEAST:
return 9;
case NORTHEAST:
return 10;
case EAST_NORTHEAST:
return 11;
case EAST:
return 12;
case EAST_SOUTHEAST:
return 13;
case SOUTHEAST:
return 14;
case SOUTH_SOUTHEAST:
return 15;
default:
return 0;
}
}
} }