Plenty of changes to core block behavior to become more compatible with upstream WorldEdit (still more to be done!)

This commit is contained in:
IronApollo
2019-01-31 10:08:58 -05:00
parent 271b45f3ba
commit e53535319d
116 changed files with 3666 additions and 3774 deletions

View File

@ -79,7 +79,7 @@ public class LazyBlock extends BaseBlock {
@Override
public CompoundTag getNbtData() {
if (!loaded) {
BlockState loadedBlock = extent.getFullBlock(position);
BlockState loadedBlock = extent.getFullBlock(position).toImmutableState();
this.nbtData = loadedBlock.getNbtData();
loaded = true;
}

View File

@ -31,6 +31,7 @@ import com.sk89q.worldedit.extension.platform.Platform;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.extent.clipboard.Clipboard;
import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormat;
import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormats;
import com.sk89q.worldedit.internal.registry.AbstractFactory;
import com.sk89q.worldedit.internal.registry.InputParser;
import com.sk89q.worldedit.math.BlockVector3;
@ -222,7 +223,7 @@ public class FaweAPI {
* @see com.boydti.fawe.object.schematic.Schematic
*/
public static Schematic load(File file) throws IOException {
return ClipboardFormat.SCHEMATIC.load(file);
return ClipboardFormats.findByFile(file).load(file);
}
/**

View File

@ -22,7 +22,6 @@ import com.sk89q.minecraft.util.commands.Command;
import com.sk89q.minecraft.util.commands.CommandPermissions;
import com.sk89q.worldedit.*;
import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.blocks.BlockType;
import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.function.pattern.RandomPattern;

View File

@ -36,7 +36,9 @@ import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.extension.input.InputParseException;
import com.sk89q.worldedit.extension.input.ParserContext;
import com.sk89q.worldedit.extent.clipboard.Clipboard;
import com.sk89q.worldedit.extent.clipboard.io.BuiltInClipboardFormat;
import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormat;
import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormats;
import com.sk89q.worldedit.function.mask.Mask;
import com.sk89q.worldedit.function.pattern.BlockPattern;
import com.sk89q.worldedit.function.pattern.Pattern;
@ -502,7 +504,7 @@ public class CFICommands extends MethodCommands {
HeightMapMCAGenerator gen = assertSettings(fp).getGenerator();
World world = fp.getWorld();
MultiClipboardHolder multi = ClipboardFormat.SCHEMATIC.loadAllFromInput(fp.getPlayer(), schematic, null, true);
MultiClipboardHolder multi = ClipboardFormats.loadAllFromInput(fp.getPlayer(), schematic, null, true);
if (multi == null) {
return;
}

View File

@ -202,10 +202,10 @@ public abstract class IntFaweChunk<T, V extends FaweQueue> extends FaweChunk<T>
}
vs[j] = combinedId;
this.count[i]++;
switch (BlockTypes.getFromStateId(combinedId)) {
case AIR:
case CAVE_AIR:
case VOID_AIR:
switch (BlockTypes.getFromStateId(combinedId).getResource().toUpperCase()) {
case "AIR":
case "CAVE_AIR":
case "VOID_AIR":
this.air[i]++;
return;
default:

View File

@ -201,25 +201,25 @@ public class SchematicStreamer extends NBTStreamer {
fc.forEach(new FaweClipboard.BlockReader() {
@Override
public void run(int x, int y, int z, BlockState block) {
BlockTypes type = block.getBlockType();
switch (type) {
case ACACIA_STAIRS:
case BIRCH_STAIRS:
case BRICK_STAIRS:
case COBBLESTONE_STAIRS:
case DARK_OAK_STAIRS:
case DARK_PRISMARINE_STAIRS:
case JUNGLE_STAIRS:
case NETHER_BRICK_STAIRS:
case OAK_STAIRS:
case PRISMARINE_BRICK_STAIRS:
case PRISMARINE_STAIRS:
case PURPUR_STAIRS:
case QUARTZ_STAIRS:
case RED_SANDSTONE_STAIRS:
case SANDSTONE_STAIRS:
case SPRUCE_STAIRS:
case STONE_BRICK_STAIRS:
BlockType type = block.getBlockType();
switch (type.getResource().toUpperCase()) {
case "ACACIA_STAIRS":
case "BIRCH_STAIRS":
case "BRICK_STAIRS":
case "COBBLESTONE_STAIRS":
case "DARK_OAK_STAIRS":
case "DARK_PRISMARINE_STAIRS":
case "JUNGLE_STAIRS":
case "NETHER_BRICK_STAIRS":
case "OAK_STAIRS":
case "PRISMARINE_BRICK_STAIRS":
case "PRISMARINE_STAIRS":
case "PURPUR_STAIRS":
case "QUARTZ_STAIRS":
case "RED_SANDSTONE_STAIRS":
case "SANDSTONE_STAIRS":
case "SPRUCE_STAIRS":
case "STONE_BRICK_STAIRS":
Object half = block.getState(PropertyKey.HALF);
Direction facing = block.getState(PropertyKey.FACING);
@ -228,19 +228,19 @@ public class SchematicStreamer extends NBTStreamer {
Direction right = facing.getRight();
BlockStateHolder forwardBlock = fc.getBlock(x + forward.getBlockX(), y + forward.getBlockY(), z + forward.getBlockZ());
BlockTypes forwardType = forwardBlock.getBlockType();
BlockType forwardType = forwardBlock.getBlockType();
if (forwardType.hasProperty(PropertyKey.SHAPE) && forwardType.hasProperty(PropertyKey.FACING)) {
Direction forwardFacing = (Direction) forwardBlock.getState(PropertyKey.FACING);
if (forwardFacing == left) {
BlockStateHolder rightBlock = fc.getBlock(x + right.getBlockX(), y + right.getBlockY(), z + right.getBlockZ());
BlockTypes rightType = rightBlock.getBlockType();
BlockType rightType = rightBlock.getBlockType();
if (!rightType.hasProperty(PropertyKey.SHAPE) || rightBlock.getState(PropertyKey.FACING) != facing) {
fc.setBlock(x, y, z, block.with(PropertyKey.SHAPE, "inner_left"));
}
return;
} else if (forwardFacing == right) {
BlockStateHolder leftBlock = fc.getBlock(x + left.getBlockX(), y + left.getBlockY(), z + left.getBlockZ());
BlockTypes leftType = leftBlock.getBlockType();
BlockType leftType = leftBlock.getBlockType();
if (!leftType.hasProperty(PropertyKey.SHAPE) || leftBlock.getState(PropertyKey.FACING) != facing) {
fc.setBlock(x, y, z, block.with(PropertyKey.SHAPE, "inner_right"));
}
@ -249,19 +249,19 @@ public class SchematicStreamer extends NBTStreamer {
}
BlockStateHolder backwardsBlock = fc.getBlock(x - forward.getBlockX(), y - forward.getBlockY(), z - forward.getBlockZ());
BlockTypes backwardsType = backwardsBlock.getBlockType();
BlockType backwardsType = backwardsBlock.getBlockType();
if (backwardsType.hasProperty(PropertyKey.SHAPE) && backwardsType.hasProperty(PropertyKey.FACING)) {
Direction backwardsFacing = (Direction) backwardsBlock.getState(PropertyKey.FACING);
if (backwardsFacing == left) {
BlockStateHolder rightBlock = fc.getBlock(x + right.getBlockX(), y + right.getBlockY(), z + right.getBlockZ());
BlockTypes rightType = rightBlock.getBlockType();
BlockType rightType = rightBlock.getBlockType();
if (!rightType.hasProperty(PropertyKey.SHAPE) || rightBlock.getState(PropertyKey.FACING) != facing) {
fc.setBlock(x, y, z, block.with(PropertyKey.SHAPE, "outer_left"));
}
return;
} else if (backwardsFacing == right) {
BlockStateHolder leftBlock = fc.getBlock(x + left.getBlockX(), y + left.getBlockY(), z + left.getBlockZ());
BlockTypes leftType = leftBlock.getBlockType();
BlockType leftType = leftBlock.getBlockType();
if (!leftType.hasProperty(PropertyKey.SHAPE) || leftBlock.getState(PropertyKey.FACING) != facing) {
fc.setBlock(x, y, z, block.with(PropertyKey.SHAPE, "outer_right"));
}
@ -301,43 +301,43 @@ public class SchematicStreamer extends NBTStreamer {
private boolean merge(int group, int x, int y, int z) {
BlockStateHolder block = fc.getBlock(x, y, z);
BlockTypes type = block.getBlockType();
BlockType type = block.getBlockType();
return group(type) == group || fullCube.apply(type);
}
private int group(BlockTypes type) {
switch (type) {
case ACACIA_FENCE:
case BIRCH_FENCE:
case DARK_OAK_FENCE:
case JUNGLE_FENCE:
case OAK_FENCE:
case SPRUCE_FENCE:
private int group(BlockType type) {
switch (type.getResource().toUpperCase()) {
case "ACACIA_FENCE":
case "BIRCH_FENCE":
case "DARK_OAK_FENCE":
case "JUNGLE_FENCE":
case "OAK_FENCE":
case "SPRUCE_FENCE":
return 0;
case NETHER_BRICK_FENCE:
case "NETHER_BRICK_FENCE":
return 1;
case COBBLESTONE_WALL:
case MOSSY_COBBLESTONE_WALL:
case "COBBLESTONE_WALL":
case "MOSSY_COBBLESTONE_WALL":
return 2;
case IRON_BARS:
case BLACK_STAINED_GLASS_PANE:
case BLUE_STAINED_GLASS_PANE:
case BROWN_MUSHROOM_BLOCK:
case BROWN_STAINED_GLASS_PANE:
case CYAN_STAINED_GLASS_PANE:
case GLASS_PANE:
case GRAY_STAINED_GLASS_PANE:
case GREEN_STAINED_GLASS_PANE:
case LIGHT_BLUE_STAINED_GLASS_PANE:
case LIGHT_GRAY_STAINED_GLASS_PANE:
case LIME_STAINED_GLASS_PANE:
case MAGENTA_STAINED_GLASS_PANE:
case ORANGE_STAINED_GLASS_PANE:
case PINK_STAINED_GLASS_PANE:
case PURPLE_STAINED_GLASS_PANE:
case RED_STAINED_GLASS_PANE:
case WHITE_STAINED_GLASS_PANE:
case YELLOW_STAINED_GLASS_PANE:
case "IRON_BARS":
case "BLACK_STAINED_GLASS_PANE":
case "BLUE_STAINED_GLASS_PANE":
case "BROWN_MUSHROOM_BLOCK":
case "BROWN_STAINED_GLASS_PANE":
case "CYAN_STAINED_GLASS_PANE":
case "GLASS_PANE":
case "GRAY_STAINED_GLASS_PANE":
case "GREEN_STAINED_GLASS_PANE":
case "LIGHT_BLUE_STAINED_GLASS_PANE":
case "LIGHT_GRAY_STAINED_GLASS_PANE":
case "LIME_STAINED_GLASS_PANE":
case "MAGENTA_STAINED_GLASS_PANE":
case "ORANGE_STAINED_GLASS_PANE":
case "PINK_STAINED_GLASS_PANE":
case "PURPLE_STAINED_GLASS_PANE":
case "RED_STAINED_GLASS_PANE":
case "WHITE_STAINED_GLASS_PANE":
case "YELLOW_STAINED_GLASS_PANE":
return 3;
default:
return -1;
@ -450,6 +450,7 @@ public class SchematicStreamer extends NBTStreamer {
public Clipboard getClipboard() throws IOException {
try {
setupClipboard(0);
addDimensionReaders();
addBlockReaders();
readFully();

View File

@ -4,6 +4,7 @@ import com.boydti.fawe.Fawe;
import com.boydti.fawe.FaweCache;
import com.boydti.fawe.util.MathMan;
import com.boydti.fawe.util.TextureUtil;
import com.sk89q.worldedit.world.block.BlockType;
import com.sk89q.worldedit.world.block.BlockTypes;
import java.awt.image.BufferedImage;
@ -80,12 +81,12 @@ public final class HeightMapMCADrawer {
if (height + 1 < waterHeight) {
int waterId = gen.primtives.waterId;
int waterColor = 0;
BlockTypes waterType = BlockTypes.get(waterId);
switch (waterType) {
case WATER:
BlockType waterType = BlockTypes.get(waterId);
switch (waterType.getResource().toUpperCase()) {
case "WATER":
color = tu.averageColor((0x11 << 16) + (0x66 << 8) + (0xCC), color);
break;
case LAVA:
case "LAVA":
color = (0xCC << 16) + (0x33 << 8) + (0);
break;
default:

View File

@ -445,9 +445,9 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
private final void setLayerHeight(int index, int blockHeight, int layerHeight) {
int floorState = floor.get()[index];
switch (BlockTypes.getFromStateId(floorState)) {
case SNOW:
case SNOW_BLOCK:
switch (BlockTypes.getFromStateId(floorState).getResource().toUpperCase()) {
case "SNOW":
case "SNOW_BLOCK":
if (layerHeight != 0) {
this.heights.setByte(index, (byte) (blockHeight + 1));
this.floor.setInt(index, (BlockTypes.SNOW.getInternalId() + layerHeight));
@ -470,9 +470,9 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
private final void setLayerHeightRaw(int index, int blockHeight, int layerHeight) {
int floorState = floor.get()[index];
switch (BlockTypes.getFromStateId(floorState)) {
case SNOW:
case SNOW_BLOCK:
switch (BlockTypes.getFromStateId(floorState).getResource().toUpperCase()) {
case "SNOW":
case "SNOW_BLOCK":
if (layerHeight != 0) {
this.heights.getByteArray()[index] = (byte) (blockHeight + 1);
this.floor.getIntArray()[index] = (BlockTypes.SNOW.getInternalId() + layerHeight);

View File

@ -172,9 +172,9 @@ public class CavesGen extends GenBase {
if ((d11 > -0.7D) && (d9 * d9 + d11 * d11 + d10 * d10 < 1.0D)) {
BlockStateHolder material = chunk.getLazyBlock(bx + local_x, local_y, bz + local_z);
BlockStateHolder materialAbove = chunk.getLazyBlock(bx + local_x, local_y + 1, bz + local_z);
switch (material.getBlockType()) {
case GRASS:
case MYCELIUM:
switch (material.getBlockType().getResource().toUpperCase()) {
case "GRASS":
case "MYCELIUM":
grassFound = true;
break;
}
@ -205,13 +205,13 @@ public class CavesGen extends GenBase {
}
protected boolean isSuitableBlock(BlockStateHolder material, BlockStateHolder materialAbove) {
switch (material.getBlockType()) {
case AIR:
case CAVE_AIR:
case VOID_AIR:
case WATER:
case LAVA:
case BEDROCK:
switch (material.getBlockType().getResource().toUpperCase()) {
case "AIR":
case "CAVE_AIR":
case "VOID_AIR":
case "WATER":
case "LAVA":
case "BEDROCK":
return false;
default:
return true;

View File

@ -5,6 +5,7 @@ import com.boydti.fawe.object.changeset.FaweChangeSet;
import com.boydti.fawe.object.queue.DelegateFaweQueue;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.worldedit.world.biome.BaseBiome;
import com.sk89q.worldedit.world.block.BlockType;
import com.sk89q.worldedit.world.block.BlockTypes;
public class ChangeSetFaweQueue extends DelegateFaweQueue {
@ -28,7 +29,7 @@ public class ChangeSetFaweQueue extends DelegateFaweQueue {
if (super.setBlock(x, y, z, combinedId)) {
int combinedFrom = getParent().getCombinedId4Data(x, y, z);
BlockTypes typeFrom = BlockTypes.getFromStateId(combinedFrom);
BlockType typeFrom = BlockTypes.getFromStateId(combinedFrom);
if (typeFrom.getMaterial().hasContainer()) {
CompoundTag nbt = getParent().getTileEntity(x, y, z);
if (nbt != null) {

View File

@ -120,7 +120,7 @@ public abstract class FaweChunk<T> implements Callable<FaweChunk> {
try {
CompoundTag tile = getTile(x & 15, y, z & 15);
if (tile != null) {
return BaseBlock.getFromInternalId(combined, tile);
return BaseBlock.getFromInternalId(combined, tile).toImmutableState();
}
} catch (Throwable e) {
MainUtil.handleError(e);

View File

@ -23,6 +23,7 @@ import com.sk89q.worldedit.regions.CuboidRegion;
import com.sk89q.worldedit.world.World;
import com.sk89q.worldedit.world.biome.BaseBiome;
import com.sk89q.worldedit.world.block.BlockStateHolder;
import com.sk89q.worldedit.world.block.BlockType;
import com.sk89q.worldedit.world.block.BlockTypes;
import java.io.File;
@ -78,7 +79,7 @@ public interface FaweQueue extends HasFaweQueue, Extent {
if (state.getMaterial().hasContainer()) {
CompoundTag tile = getTileEntity(x, y, z);
if (tile != null) {
return BaseBlock.getFromInternalId(combinedId4Data, tile);
return BaseBlock.getFromInternalId(combinedId4Data, tile).toImmutableState();
}
}
return state;
@ -94,8 +95,8 @@ public interface FaweQueue extends HasFaweQueue, Extent {
}
@Override
default BlockState getFullBlock(BlockVector3 position) {
return getLazyBlock(position.getBlockX(), position.getBlockY(), position.getBlockZ());
default BaseBlock getFullBlock(BlockVector3 position) {
return getLazyBlock(position.getBlockX(), position.getBlockY(), position.getBlockZ()).toBaseBlock();
}
@Override
@ -275,18 +276,18 @@ public interface FaweQueue extends HasFaweQueue, Extent {
for (int y = 0; y <= getMaxY(); y++) {
int combined = getCombinedId4Data(xx, y, zz);
BlockState state = BlockState.getFromInternalId(combined);
BlockTypes type = state.getBlockType();
switch (type.getTypeEnum()) {
case AIR:
case VOID_AIR:
case CAVE_AIR:
BlockType type = state.getBlockType();
switch (type.getResource().toUpperCase()) {
case "AIR":
case "VOID_AIR":
case "CAVE_AIR":
continue;
}
mutable.mutY(y);
CompoundTag tile = getTileEntity(x, y, z);
if (tile != null) {
BaseBlock block = BaseBlock.getFromInternalId(combined, tile);
onEach.run(mutable.toBlockVector3(), block);
onEach.run(mutable.toBlockVector3(), block.toImmutableState());
} else {
onEach.run(mutable.toBlockVector3(), state);
}
@ -308,7 +309,7 @@ public interface FaweQueue extends HasFaweQueue, Extent {
if (combined == 0) {
continue;
}
BlockTypes type = BlockTypes.getFromStateId(combined);
BlockType type = BlockTypes.getFromStateId(combined);
if (type.getMaterial().hasContainer()) {
CompoundTag tile = getTileEntity(x, y, z);
if (tile != null) {
@ -316,7 +317,7 @@ public interface FaweQueue extends HasFaweQueue, Extent {
mutable.mutZ(zz);
mutable.mutY(y);
BaseBlock block = BaseBlock.getFromInternalId(combined, tile);
onEach.run(mutable.toBlockVector3(), block);
onEach.run(mutable.toBlockVector3(), block.toImmutableState());
}
}
}

View File

@ -10,6 +10,7 @@ import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.extension.input.InputParseException;
import com.sk89q.worldedit.extension.input.ParserContext;
import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormat;
import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormats;
import com.sk89q.worldedit.function.mask.Mask;
import com.sk89q.worldedit.function.pattern.Pattern;
import java.io.IOException;
@ -34,7 +35,7 @@ public abstract class ScrollAction implements ScrollTool {
}
String filename = split[1];
try {
MultiClipboardHolder multi = ClipboardFormat.SCHEMATIC.loadAllFromInput(player, filename, null, message);
MultiClipboardHolder multi = ClipboardFormats.loadAllFromInput(player, filename, null, message);
if (multi == null) {
return null;
}

View File

@ -10,6 +10,7 @@ import com.sk89q.worldedit.event.platform.PlayerInputEvent;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.math.Vector3;
import com.sk89q.worldedit.world.SimpleWorld;
import com.sk89q.worldedit.world.block.BaseBlock;
import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.block.BlockStateHolder;
@ -22,8 +23,8 @@ public interface VirtualWorld extends SimpleWorld, FaweQueue, Closeable {
FaweChunk getSnapshot(int chunkX, int chunkZ);
@Override
default BlockState getFullBlock(BlockVector3 position) {
return getLazyBlock(position);
default BaseBlock getFullBlock(BlockVector3 position) {
return getLazyBlock(position).toBaseBlock();
}
@Override

View File

@ -115,10 +115,10 @@ public class VisualChunk extends FaweChunk<FaweChunk> {
public void setBlock(int x, int y, int z, int combinedId) {
int index = getIndex(x, y, z);
try {
switch (BlockTypes.getFromStateId(combinedId)) {
case AIR:
case CAVE_AIR:
case VOID_AIR:
switch (BlockTypes.getFromStateId(combinedId).getResource().toUpperCase()) {
case "AIR":
case "CAVE_AIR":
case "VOID_AIR":
add.clear(index);
remove.set(index);
break;

View File

@ -11,6 +11,7 @@ import com.sk89q.worldedit.extent.inventory.BlockBagException;
import com.sk89q.worldedit.history.UndoContext;
import com.sk89q.worldedit.history.change.Change;
import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.block.BlockType;
import com.sk89q.worldedit.world.block.BlockTypes;
public class MutableFullBlockChange implements Change {
@ -60,9 +61,9 @@ public class MutableFullBlockChange implements Change {
}
public void perform(FaweQueue queue) {
BlockTypes idFrom = BlockTypes.getFromStateId(from);
BlockType idFrom = BlockTypes.getFromStateId(from);
if (blockBag != null) {
BlockTypes idTo = BlockTypes.getFromStateId(to);
BlockType idTo = BlockTypes.getFromStateId(to);
if (idFrom != idTo) {
if (allowFetch && from != 0) {
try {

View File

@ -17,6 +17,7 @@ import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.world.biome.BaseBiome;
import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.block.BlockStateHolder;
import com.sk89q.worldedit.world.block.BlockType;
import com.sk89q.worldedit.world.block.BlockTypes;
import java.util.ArrayList;
@ -147,12 +148,12 @@ public class CPUOptimizedClipboard extends FaweClipboard {
@Override
public BlockState getBlock(int index) {
int combinedId = states[index];
BlockTypes type = BlockTypes.getFromStateId(combinedId);
BlockType type = BlockTypes.getFromStateId(combinedId);
BlockState state = type.withStateId(combinedId);
if (type.getMaterial().hasContainer()) {
CompoundTag nbt = getTag(index);
if (nbt != null) {
return new BaseBlock(state, nbt);
return new BaseBlock(state, nbt).toImmutableState();
}
}
return state;
@ -174,10 +175,10 @@ public class CPUOptimizedClipboard extends FaweClipboard {
for (int z = 0; z < length; z++) {
for (int x = 0; x < width; x++, index++) {
BlockState block = getBlock(index);
switch (block.getBlockType()) {
case AIR:
case CAVE_AIR:
case VOID_AIR:
switch (block.getBlockType().getResource().toUpperCase()) {
case "AIR":
case "CAVE_AIR":
case "VOID_AIR":
continue;
default:
task.run(x, y, z, block);

View File

@ -21,6 +21,7 @@ import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.regions.CuboidRegion;
import com.sk89q.worldedit.world.biome.BaseBiome;
import com.sk89q.worldedit.world.block.BlockStateHolder;
import com.sk89q.worldedit.world.block.BlockType;
import com.sk89q.worldedit.world.block.BlockTypes;
import java.io.Closeable;
@ -371,14 +372,14 @@ public class DiskOptimizedClipboard extends FaweClipboard implements Closeable {
for (int z = 0; z < length; z++) {
for (int x = 0; x < width; x++, pos += 4) {
int combinedId = mbb.getInt(pos);
BlockTypes type = BlockTypes.getFromStateId(combinedId);
BlockType type = BlockTypes.getFromStateId(combinedId);
BlockState state = type.withStateId(combinedId);
if (type.getMaterial().hasContainer()) {
trio.set(x, y, z);
CompoundTag nbt = nbtMap.get(trio);
if (nbt != null) {
BaseBlock block = new BaseBlock(state, nbt);
task.run(x, y, z, block);
task.run(x, y, z, block.toImmutableState());
continue;
}
}
@ -402,11 +403,11 @@ public class DiskOptimizedClipboard extends FaweClipboard implements Closeable {
for (int z = 0; z < length; z++) {
for (int x = 0; x < width; x++, pos += 4) {
int combinedId = mbb.getInt(pos);
BlockTypes type = BlockTypes.getFromStateId(combinedId);
switch (type) {
case AIR:
case CAVE_AIR:
case VOID_AIR:
BlockType type = BlockTypes.getFromStateId(combinedId);
switch (type.getResource().toUpperCase()) {
case "AIR":
case "CAVE_AIR":
case "VOID_AIR":
continue;
default:
BlockState state = type.withStateId(combinedId);
@ -415,7 +416,7 @@ public class DiskOptimizedClipboard extends FaweClipboard implements Closeable {
CompoundTag nbt = nbtMap.get(trio);
if (nbt != null) {
BaseBlock block = new BaseBlock(state, nbt);
task.run(x, y, z, block);
task.run(x, y, z, block.toImmutableState());
continue;
}
}
@ -436,12 +437,12 @@ public class DiskOptimizedClipboard extends FaweClipboard implements Closeable {
try {
int index = HEADER_SIZE + (getIndex(x, y, z) << 2);
int combinedId = mbb.getInt(index);
BlockTypes type = BlockTypes.getFromStateId(combinedId);
BlockType type = BlockTypes.getFromStateId(combinedId);
BlockState state = type.withStateId(combinedId);
if (type.getMaterial().hasContainer() && !nbtMap.isEmpty()) {
CompoundTag nbt = nbtMap.get(new IntegerTrio(x, y, z));
if (nbt != null) {
return new BaseBlock(state, nbt);
return new BaseBlock(state, nbt).toImmutableState();
}
}
return state;
@ -458,7 +459,7 @@ public class DiskOptimizedClipboard extends FaweClipboard implements Closeable {
try {
int diskIndex = (HEADER_SIZE) + (i << 2);
int combinedId = mbb.getInt(diskIndex);
BlockTypes type = BlockTypes.getFromStateId(combinedId);
BlockType type = BlockTypes.getFromStateId(combinedId);
BlockState state = type.withStateId(combinedId);
if (type.getMaterial().hasContainer() && !nbtMap.isEmpty()) {
CompoundTag nbt;
@ -481,7 +482,7 @@ public class DiskOptimizedClipboard extends FaweClipboard implements Closeable {
nbt = nbtMap.get(new IntegerTrio(x, y, z));
}
if (nbt != null) {
return new BaseBlock(state, nbt);
return new BaseBlock(state, nbt).toImmutableState();
}
}
return state;

View File

@ -2,6 +2,7 @@ package com.boydti.fawe.object.clipboard;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.world.block.BaseBlock;
import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.entity.BaseEntity;
import com.sk89q.worldedit.entity.Entity;
@ -73,8 +74,8 @@ public class EmptyClipboard implements Clipboard {
}
@Override
public BlockState getFullBlock(BlockVector3 position) {
return EditSession.nullBlock;
public BaseBlock getFullBlock(BlockVector3 position) {
return EditSession.nullBlock.toBaseBlock();
}
@Override

View File

@ -18,6 +18,7 @@ import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.world.biome.BaseBiome;
import com.sk89q.worldedit.world.block.BlockStateHolder;
import com.sk89q.worldedit.world.block.BlockType;
import com.sk89q.worldedit.world.block.BlockTypes;
import net.jpountz.util.SafeUtils;
@ -203,10 +204,11 @@ public class MemoryOptimizedClipboard extends FaweClipboard {
}
}
if (lastCombinedIds == null) {
switch (BlockTypes.getFromStateId(v)) {
case AIR:
case CAVE_AIR:
case VOID_AIR:
BlockType bt = BlockTypes.getFromStateId(v);
switch (bt.getResource().toUpperCase()) {
case "AIR":
case "CAVE_AIR":
case "VOID_AIR":
return;
}
lastCombinedIds = new byte[BLOCK_SIZE];
@ -270,12 +272,12 @@ public class MemoryOptimizedClipboard extends FaweClipboard {
@Override
public BlockState getBlock(int index) {
int combinedId = getCombinedId(index);
BlockTypes type = BlockTypes.getFromStateId(combinedId);
BlockType type = BlockTypes.getFromStateId(combinedId);
BlockState state = type.withStateId(combinedId);
if (type.getMaterial().hasContainer()) {
CompoundTag nbt = getTag(index);
if (nbt != null) {
return new BaseBlock(state, nbt);
return new BaseBlock(state, nbt).toImmutableState();
}
}
return state;
@ -297,10 +299,10 @@ public class MemoryOptimizedClipboard extends FaweClipboard {
for (int z = 0; z < length; z++) {
for (int x = 0; x < width; x++, index++) {
BlockState block = getBlock(index);
switch (block.getBlockType()) {
case AIR:
case CAVE_AIR:
case VOID_AIR:
switch (block.getBlockType().getResource().toUpperCase()) {
case "AIR":
case "CAVE_AIR":
case "VOID_AIR":
continue;
default:
task.run(x, y, z, block);

View File

@ -2,6 +2,7 @@ package com.boydti.fawe.object.extent;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.world.block.BaseBlock;
import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.entity.BaseEntity;
import com.sk89q.worldedit.entity.Entity;
@ -44,8 +45,8 @@ public class EmptyExtent implements Extent {
}
@Override
public BlockState getFullBlock(BlockVector3 position) {
return EditSession.nullBlock;
public BaseBlock getFullBlock(BlockVector3 position) {
return EditSession.nullBlock.toBaseBlock();
}
@Override

View File

@ -123,12 +123,12 @@ public class FastWorldEditExtent extends AbstractDelegateExtent implements HasFa
@Override
public BlockState getLazyBlock(int x, int y, int z) {
int combinedId4Data = queue.getCombinedId4Data(x, y, z, 0);
BlockTypes type = BlockTypes.getFromStateId(combinedId4Data);
BlockType type = BlockTypes.getFromStateId(combinedId4Data);
BlockState state = type.withStateId(combinedId4Data);
if (type.getMaterial().hasContainer()) {
CompoundTag tile = queue.getTileEntity(x, y, z);
if (tile != null) {
return new BaseBlock(state, tile);
return new BaseBlock(state, tile).toImmutableState();
}
}
return state;

View File

@ -53,12 +53,12 @@ public class NullExtent extends FaweRegionExtent {
}
@Override
public BaseBlock getBlock(final BlockVector3 arg0) {
public BlockState getBlock(final BlockVector3 arg0) {
throw new FaweException(reason);
}
@Override
public BaseBlock getLazyBlock(final BlockVector3 arg0) {
public BlockState getLazyBlock(final BlockVector3 arg0) {
throw new FaweException(reason);
}
@ -78,7 +78,7 @@ public class NullExtent extends FaweRegionExtent {
}
@Override
public BaseBlock getLazyBlock(int x, int y, int z) {
public BlockState getLazyBlock(int x, int y, int z) {
throw new FaweException(reason);
}

View File

@ -1,6 +1,7 @@
package com.boydti.fawe.object.extent;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.world.block.BaseBlock;
import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.extent.transform.BlockTransformExtent;
@ -80,17 +81,22 @@ public class TransformExtent extends BlockTransformExtent {
@Override
public BlockState getLazyBlock(int x, int y, int z) {
return transformFast(super.getLazyBlock(getPos(x, y, z)));
return transformFast(super.getLazyBlock(getPos(x, y, z))).toImmutableState();
}
@Override
public BlockState getLazyBlock(BlockVector3 position) {
return transformFast(super.getLazyBlock(getPos(position)));
return transformFast(super.getLazyBlock(getPos(position))).toImmutableState();
}
@Override
public BlockState getBlock(BlockVector3 position) {
return transformFast(super.getBlock(getPos(position)));
return transformFast(super.getBlock(getPos(position))).toImmutableState();
}
@Override
public BaseBlock getFullBlock(BlockVector3 position) {
return transformFast(super.getFullBlock(getPos(position)).toImmutableState());
}
@Override
@ -102,14 +108,14 @@ public class TransformExtent extends BlockTransformExtent {
}
@Override
public boolean setBlock(int x, int y, int z, BlockStateHolder block) throws WorldEditException {
return super.setBlock(getPos(x, y, z), transformFastInverse((BlockState) block));
public <B extends BlockStateHolder<B>> boolean setBlock(int x, int y, int z, B block) throws WorldEditException {
return super.setBlock(getPos(x, y, z), transformFastInverse((BlockState)block));
}
@Override
public boolean setBlock(BlockVector3 location, BlockStateHolder block) throws WorldEditException {
return super.setBlock(getPos(location), transformFastInverse((BlockState) block));
public <B extends BlockStateHolder<B>> boolean setBlock(BlockVector3 location, B block) throws WorldEditException {
return super.setBlock(getPos(location), transformFastInverse((BlockState)block));
}
@Override

View File

@ -1,7 +1,7 @@
package com.boydti.fawe.object.pattern;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.world.block.BaseBlock;
import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.entity.BaseEntity;
import com.sk89q.worldedit.entity.Entity;
@ -97,8 +97,8 @@ public class PatternExtent extends AbstractPattern implements Extent {
}
@Override
public BlockState getFullBlock(BlockVector3 position) {
return getBlock(position);
public BaseBlock getFullBlock(BlockVector3 position) {
return getBlock(position).toBaseBlock();
}
@Override

View File

@ -62,7 +62,7 @@ public class PropertyPattern extends AbstractExtentPattern {
}
}
private void add(BlockTypes type, PropertyKey key, Operator operator, MutableCharSequence value, boolean wrap) {
private void add(BlockType type, PropertyKey key, Operator operator, MutableCharSequence value, boolean wrap) {
if (!type.hasProperty(key)) return;
AbstractProperty property = (AbstractProperty) type.getProperty(key);
BlockState defaultState = type.getDefaultState();
@ -129,14 +129,14 @@ public class PropertyPattern extends AbstractExtentPattern {
charSequence.setString(input);
charSequence.setSubstring(0, propStart);
BlockTypes type = null;
List<BlockTypes> blockTypeList = null;
BlockType type = null;
List<BlockType> blockTypeList = null;
if (StringMan.isAlphanumericUnd(charSequence)) {
type = BlockTypes.get(charSequence);
} else {
String regex = charSequence.toString();
blockTypeList = new ArrayList<>();
for (BlockTypes myType : BlockTypes.values) {
for (BlockType myType : BlockTypes.values) {
if (myType.getId().matches(regex)) {
blockTypeList.add(myType);
}
@ -164,7 +164,7 @@ public class PropertyPattern extends AbstractExtentPattern {
char firstChar = input.charAt(last + 1);
if (type != null) add(type, key, operator, charSequence, wrap);
else {
for (BlockTypes myType : blockTypeList) {
for (BlockType myType : blockTypeList) {
add(myType, key, operator, charSequence, wrap);
}
}
@ -203,7 +203,7 @@ public class PropertyPattern extends AbstractExtentPattern {
if (newOrdinal != ordinal) {
CompoundTag nbt = block.getNbtData();
BlockState newState = BlockState.getFromOrdinal(newOrdinal);
return nbt != null ? new BaseBlock(newState, nbt) : newState;
return nbt != null ? new BaseBlock(newState, nbt).toImmutableState() : newState;
}
return orDefault;
}

View File

@ -4,7 +4,6 @@ import com.boydti.fawe.FaweCache;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.blocks.BlockType;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.function.mask.SolidBlockMask;
import com.sk89q.worldedit.function.pattern.AbstractPattern;

View File

@ -178,14 +178,9 @@ public class StructureFormat implements ClipboardReader, ClipboardWriter {
for (BlockVector3 point : region) {
BlockStateHolder block = clipboard.getBlock(point);
int combined = block.getInternalId();
BlockTypes type = block.getBlockType();
BlockType type = block.getBlockType();
switch (type) {
case STRUCTURE_VOID:
continue;
default:
}
if (indexes.containsKey(combined)) {
if (type == BlockTypes.STRUCTURE_VOID || indexes.containsKey(combined)) {
continue;
}
@ -194,7 +189,7 @@ public class StructureFormat implements ClipboardReader, ClipboardWriter {
paletteEntry.put("Name", type.getId());
if (block.getInternalId() != type.getInternalId()) {
Map<String, Object> properties = null;
for (AbstractProperty property : (List<AbstractProperty>) type.getProperties()) {
for (AbstractProperty property : (List<AbstractProperty<?>>) type.getProperties()) {
int propIndex = property.getIndex(block.getInternalId());
if (propIndex != 0) {
if (properties == null) properties = new HashMap<>();
@ -218,8 +213,8 @@ public class StructureFormat implements ClipboardReader, ClipboardWriter {
BlockVector3 min = region.getMinimumPoint();
for (BlockVector3 point : region) {
BlockStateHolder block = clipboard.getBlock(point);
switch (block.getBlockType()) {
case STRUCTURE_VOID:
switch (block.getBlockType().getResource().toUpperCase()) {
case "STRUCTURE_VOID":
continue;
default:
int combined = block.getInternalId();

View File

@ -23,6 +23,7 @@ import com.sk89q.worldedit.event.platform.InputType;
import com.sk89q.worldedit.event.platform.PlayerInputEvent;
import com.sk89q.worldedit.extent.clipboard.Clipboard;
import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormat;
import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormats;
import com.sk89q.worldedit.extent.clipboard.io.ClipboardReader;
import com.sk89q.worldedit.math.BlockVector2;
import com.sk89q.worldedit.math.BlockVector3;
@ -128,7 +129,7 @@ public class SchemVis extends ImmutableVirtualWorld {
File file = new File(cachedFile.getParentFile(), filename.substring(1, filename.length() - 7));
URI uri = file.toURI();
ClipboardFormat format = ClipboardFormat.findByFile(file);
ClipboardFormat format = ClipboardFormats.findByFile(file);
format.hold(player, uri, new FileInputStream(file));
BBC.SCHEMATIC_LOADED.send(player, filename);
session.setVirtualWorld(null);
@ -144,7 +145,7 @@ public class SchemVis extends ImmutableVirtualWorld {
File file = new File(clicked.getParentFile(), filename.substring(1, filename.length() - 7));
URI uri = file.toURI();
ClipboardFormat format = ClipboardFormat.findByFile(file);
ClipboardFormat format = ClipboardFormats.findByFile(file);
boolean contains = existing instanceof URIClipboardHolder && ((URIClipboardHolder) existing).contains(uri);
if (contains) {
@ -386,7 +387,7 @@ public class SchemVis extends ImmutableVirtualWorld {
player.sendMessage(BBC.getPrefix() + "Converting: " + file);
cached.createNewFile();
try (FileInputStream in = new FileInputStream(file)) {
ClipboardFormat format = ClipboardFormat.findByFile(file);
ClipboardFormat format = ClipboardFormats.findByFile(file);
if (format != null) {
ClipboardReader reader = format.getReader(in);
Clipboard clipboard = reader.read();

View File

@ -10,9 +10,9 @@ import java.io.FileNotFoundException;
public class CachedTextureUtil extends DelegateTextureUtil {
private final TextureUtil parent;
private transient Int2ObjectOpenHashMap<BlockTypes> colorBlockMap;
private transient Int2ObjectOpenHashMap<BlockType> colorBlockMap;
private transient Int2ObjectOpenHashMap<Integer> colorBiomeMap;
private transient Int2ObjectOpenHashMap<BlockTypes[]> colorLayerMap;
private transient Int2ObjectOpenHashMap<BlockType[]> colorLayerMap;
public CachedTextureUtil(TextureUtil parent) throws FileNotFoundException {
super(parent);
@ -23,8 +23,8 @@ public class CachedTextureUtil extends DelegateTextureUtil {
}
@Override
public BlockTypes[] getNearestLayer(int color) {
BlockTypes[] closest = colorLayerMap.get(color);
public BlockType[] getNearestLayer(int color) {
BlockType[] closest = colorLayerMap.get(color);
if (closest != null) {
return closest;
}
@ -49,12 +49,12 @@ public class CachedTextureUtil extends DelegateTextureUtil {
}
@Override
public BlockTypes getNearestBlock(int color) {
BlockTypes value = colorBlockMap.get(color);
public BlockType getNearestBlock(int color) {
BlockType value = colorBlockMap.get(color);
if (value != null) {
return value;
}
BlockTypes result = parent.getNearestBlock(color);
BlockType result = parent.getNearestBlock(color);
if (result != null) {
colorBlockMap.put((int) color, result);
}

View File

@ -19,7 +19,7 @@ public class DelegateTextureUtil extends TextureUtil {
}
@Override
public BlockTypes getNearestBlock(int color) {
public BlockType getNearestBlock(int color) {
return parent.getNearestBlock(color);
}
@ -34,7 +34,7 @@ public class DelegateTextureUtil extends TextureUtil {
}
@Override
public BlockTypes[] getNearestLayer(int color) {
public BlockType[] getNearestLayer(int color) {
return parent.getNearestLayer(color);
}

View File

@ -26,14 +26,14 @@ public class FilteredTextureUtil extends TextureUtil {
this.validBlockIds = new int[distances.length];
int num = 0;
for (int i = 0; i < parent.validBlockIds.length; i++) {
BlockTypes block = BlockTypes.get(parent.validBlockIds[i]);
BlockType block = BlockTypes.get(parent.validBlockIds[i]);
if (blocks.contains(block)) num++;
}
this.validBlockIds = new int[num];
this.validColors = new int[num];
num = 0;
for (int i = 0; i < parent.validBlockIds.length; i++) {
BlockTypes block = BlockTypes.get(parent.validBlockIds[i]);
BlockType block = BlockTypes.get(parent.validBlockIds[i]);
if (blocks.contains(block)) {
validBlockIds[num] = parent.validBlockIds[i];
validColors[num++] = parent.validColors[i];

View File

@ -12,6 +12,7 @@ import com.github.luben.zstd.ZstdOutputStream;
import com.sk89q.jnbt.*;
import com.sk89q.worldedit.entity.Entity;
import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormat;
import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormats;
import com.sk89q.worldedit.history.changeset.ChangeSet;
import com.sk89q.worldedit.util.Location;
import java.awt.Graphics2D;
@ -889,7 +890,7 @@ public class MainUtil {
public static File resolve(File dir, String filename, @Nullable ClipboardFormat format, boolean allowDir) {
if (format != null) {
if (!filename.matches(".*\\.[\\w].*")) {
filename = filename + "." + format.getExtension();
filename = filename + "." + format.getPrimaryFileExtension();
}
return MainUtil.resolveRelative(new File(dir, filename));
}
@ -897,8 +898,8 @@ public class MainUtil {
File file = MainUtil.resolveRelative(new File(dir, filename));
if (file.exists() && file.isDirectory()) return file;
}
for (ClipboardFormat f : ClipboardFormat.values) {
File file = MainUtil.resolveRelative(new File(dir, filename + "." + f.getExtension()));
for (ClipboardFormat f : ClipboardFormats.getAll()) {
File file = MainUtil.resolveRelative(new File(dir, filename + "." + f.getPrimaryFileExtension()));
if (file.exists()) return file;
}
return null;

View File

@ -79,14 +79,14 @@ public class RandomTextureUtil extends CachedTextureUtil {
}
@Override
public BlockTypes getNearestBlock(int color) {
public BlockType getNearestBlock(int color) {
int offsetColor = offsets.getOrDefault(color, 0);
if (offsetColor != 0) {
offsetColor = addRandomColor(color, offsetColor);
} else {
offsetColor = color;
}
BlockTypes res = super.getNearestBlock(offsetColor);
BlockType res = super.getNearestBlock(offsetColor);
if (res == null) return null;
int newColor = getColor(res);
{

View File

@ -372,7 +372,7 @@ public class TextureUtil implements TextureHolder{
}
}
public BlockTypes getNearestBlock(int color) {
public BlockType getNearestBlock(int color) {
long min = Long.MAX_VALUE;
int closest = 0;
int red1 = (color >> 16) & 0xFF;
@ -420,7 +420,7 @@ public class TextureUtil implements TextureHolder{
return BlockTypes.get(closest);
}
private BlockTypes[] layerBuffer = new BlockTypes[2];
private BlockType[] layerBuffer = new BlockType[2];
/**
* Returns the block combined ids as an array
@ -428,7 +428,7 @@ public class TextureUtil implements TextureHolder{
* @param color
* @return
*/
public BlockTypes[] getNearestLayer(int color) {
public BlockType[] getNearestLayer(int color) {
int[] closest = null;
long min = Long.MAX_VALUE;
int red1 = (color >> 16) & 0xFF;

View File

@ -6,9 +6,9 @@ import com.boydti.fawe.object.RunnableVal;
import com.boydti.fawe.util.EditSessionBuilder;
import com.boydti.fawe.util.TaskManager;
import com.sk89q.worldedit.*;
import com.sk89q.worldedit.world.block.BaseBlock;
import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.blocks.BaseItemStack;
import com.sk89q.worldedit.blocks.BlockType;
import com.sk89q.worldedit.entity.BaseEntity;
import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.extension.platform.AbstractPlayerActor;
@ -51,7 +51,7 @@ public class PlayerWrapper extends AbstractPlayerActor {
}
@Override
public BlockState getBlockInHand(HandSide handSide) throws WorldEditException {
public BaseBlock getBlockInHand(HandSide handSide) throws WorldEditException {
return parent.getBlockInHand(handSide);
}

View File

@ -20,6 +20,7 @@ import com.sk89q.worldedit.util.TreeGenerator;
import com.sk89q.worldedit.world.AbstractWorld;
import com.sk89q.worldedit.world.World;
import com.sk89q.worldedit.world.biome.BaseBiome;
import com.sk89q.worldedit.world.block.BaseBlock;
import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.block.BlockStateHolder;
import com.sk89q.worldedit.world.block.BlockType;
@ -240,7 +241,7 @@ public class WorldWrapper extends AbstractWorld {
}
@Override
public BlockState getFullBlock(BlockVector3 position) {
public BaseBlock getFullBlock(BlockVector3 position) {
return parent.getFullBlock(position);
}

View File

@ -28,6 +28,7 @@ import com.sk89q.worldedit.command.SchematicCommands;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard;
import com.sk89q.worldedit.extent.clipboard.Clipboard;
import com.sk89q.worldedit.extent.clipboard.io.BuiltInClipboardFormat;
import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormat;
import com.sk89q.worldedit.function.operation.ForwardExtentCopy;
import com.sk89q.worldedit.function.operation.Operations;
@ -149,7 +150,7 @@ public class CuboidClipboard {
}
private BaseBlock adapt(BlockState state) {
if (state instanceof BaseBlock) return (BaseBlock) state;
// if (state instanceof BaseBlock) return (BaseBlock) state;
return new BaseBlock(state);
}
@ -173,7 +174,7 @@ public class CuboidClipboard {
}
public boolean setBlock(int x, int y, int z, BaseBlock block) {
return setBlock(x, y, z, (BlockState) block);
return setBlock(x, y, z, block.toImmutableState());
}
public boolean setBlock(int x, int y, int z, BlockState block) {
@ -270,7 +271,7 @@ public class CuboidClipboard {
if (region.contains(pt)) {
setBlock(x, y, z, editSession.getBlock(pt));
} else {
setBlock(x, y, z, null);
setBlock(x, y, z, (BlockState)null);
}
}
}
@ -435,7 +436,7 @@ public class CuboidClipboard {
Operations.completeLegacy(result.copyTo(target));
this.clipboard = target;
}
new Schematic(clipboard).save(path, ClipboardFormat.SPONGE_SCHEMATIC);
new Schematic(clipboard).save(path, BuiltInClipboardFormat.SPONGE_SCHEMATIC);
}
/**
@ -450,7 +451,7 @@ public class CuboidClipboard {
@Deprecated
public static CuboidClipboard loadSchematic(File path) throws DataException, IOException {
checkNotNull(path);
return new CuboidClipboard((BlockVector3) ClipboardFormat.SCHEMATIC.load(path).getClipboard());
return new CuboidClipboard((BlockVector3) BuiltInClipboardFormat.MCEDIT_SCHEMATIC.load(path).getClipboard());
}
/**

View File

@ -981,7 +981,7 @@ public class EditSession extends AbstractDelegateExtent implements HasFaweQueue,
}
@Override
public BlockState getFullBlock(BlockVector3 position) {
public BaseBlock getFullBlock(BlockVector3 position) {
return world.getFullBlock(position);
}
@ -1094,12 +1094,12 @@ public class EditSession extends AbstractDelegateExtent implements HasFaweQueue,
}
@Deprecated
public boolean setBlock(int x, int y, int z, BaseBlock block) {
return setBlock(x, y, z, (BlockState) block);
return setBlock(x, y, z, block.toImmutableState());
}
@Deprecated
public boolean setBlock(BlockVector3 position, BaseBlock block) throws MaxChangedBlocksException {
return setBlock(position, (BlockState) block);
return setBlock(position, block.toImmutableState());
}
@SuppressWarnings("deprecation")
@ -2502,16 +2502,16 @@ public class EditSession extends AbstractDelegateExtent implements HasFaweQueue,
}
for (int y = maxY; y >= 1; --y) {
final BlockType type = getBlockType(x, y, z);
switch (type.getTypeEnum()) {
case ICE:
switch (type.getResource().toUpperCase()) {
case "ICE":
this.setBlock(x, y, z, BlockTypes.WATER.getDefaultState());
break;
case SNOW:
case "SNOW":
this.setBlock(x, y, z, BlockTypes.AIR.getDefaultState());
break;
case CAVE_AIR:
case VOID_AIR:
case AIR:
case "CAVE_AIR":
case "VOID_AIR":
case "AIR":
continue;
default:
break;
@ -2574,20 +2574,20 @@ public class EditSession extends AbstractDelegateExtent implements HasFaweQueue,
outer:
for (int y = maxY; y >= 1; --y) {
BlockType type = getBlockType(x, y, z);
switch (type.getTypeEnum()) {
case AIR:
case CAVE_AIR:
case VOID_AIR:
switch (type.getResource().toUpperCase()) {
case "AIR":
case "CAVE_AIR":
case "VOID_AIR":
continue;
case WATER:
case "WATER":
this.setBlock(x, y, z, BlockTypes.ICE.getDefaultState());
break outer;
case ACACIA_LEAVES: // TODO FIXME get leaves dynamically
case BIRCH_LEAVES:
case DARK_OAK_LEAVES:
case JUNGLE_LEAVES:
case OAK_LEAVES:
case SPRUCE_LEAVES:
case "ACACIA_LEAVES": // TODO FIXME get leaves dynamically
case "BIRCH_LEAVES":
case "DARK_OAK_LEAVES":
case "JUNGLE_LEAVES":
case "OAK_LEAVES":
case "SPRUCE_LEAVES":
// int ceilRadius = (int) Math.ceil(radius);
// for (int x = ox - ceilRadius; x <= ox + ceilRadius; ++x) {
// for (int z = oz - ceilRadius; z <= oz + ceilRadius; ++z) {
@ -2670,12 +2670,12 @@ public class EditSession extends AbstractDelegateExtent implements HasFaweQueue,
loop:
for (int y = maxY; y >= 1; --y) {
BlockType block = getBlockType(x, y, z);
switch (block.getTypeEnum()) {
case DIRT:
switch (block.getResource().toUpperCase()) {
case "DIRT":
this.setBlock(x, y, z, BlockTypes.GRASS_BLOCK.getDefaultState());
break loop;
case WATER:
case LAVA:
case "WATER":
case "LAVA":
break loop;
default:
if (block.getMaterial().isMovementBlocker()) {
@ -2770,18 +2770,18 @@ public class EditSession extends AbstractDelegateExtent implements HasFaweQueue,
this.changes++;
for (int y = basePosition.getBlockY(); y >= (basePosition.getBlockY() - 10); --y) {
BlockType type = getBlockType(x, y, z);
switch (type.getTypeEnum()) {
case GRASS:
case DIRT:
switch (type.getResource().toUpperCase()) {
case "GRASS":
case "DIRT":
treeType.generate(this, BlockVector3.at(x, y + 1, z));
this.changes++;
break;
case SNOW:
case "SNOW":
setBlock(BlockVector3.at(x, y, z), BlockTypes.AIR.getDefaultState());
break;
case AIR:
case CAVE_AIR:
case VOID_AIR:
case "AIR":
case "CAVE_AIR":
case "VOID_AIR":
continue;
default:
break;

View File

@ -22,6 +22,7 @@ package com.sk89q.worldedit;
import com.sk89q.worldedit.util.logging.LogFormat;
import com.sk89q.worldedit.world.block.BlockType;
import com.sk89q.worldedit.world.block.BlockTypes;
import com.sk89q.worldedit.world.item.ItemType;
import com.sk89q.worldedit.world.item.ItemTypes;
import com.sk89q.worldedit.world.registry.LegacyMapper;
import com.sk89q.worldedit.world.snapshot.SnapshotRepository;
@ -53,7 +54,7 @@ public abstract class LocalConfiguration {
public String logFile = "";
public String logFormat = LogFormat.DEFAULT_FORMAT;
public boolean registerHelp = true; // what is the point of this, it's not even used
public ItemTypes wandItem = ItemTypes.WOODEN_AXE;
public String wandItem = ItemTypes.WOODEN_AXE.getId();
public boolean superPickaxeDrop = true;
public boolean superPickaxeManyDrop = true;
public boolean noDoubleSlash = false;
@ -61,7 +62,7 @@ public abstract class LocalConfiguration {
public boolean useInventoryOverride = false;
public boolean useInventoryCreativeOverride = false;
public boolean navigationUseGlass = true;
public ItemTypes navigationWand = ItemTypes.COMPASS;
public String navigationWand = ItemTypes.COMPASS.getId();
public int navigationWandMaxDistance = 50;
public int scriptTimeout = 3000;
public Set<BlockType> allowedDataCycleBlocks = new HashSet<>();

View File

@ -1030,12 +1030,12 @@ public class LocalSession implements TextureHolder {
}
public void setTool(BaseItem item, @Nullable Tool tool, Player player) throws InvalidToolBindException {
ItemTypes type = item.getType();
ItemType type = item.getType();
if (type.hasBlockType() && type.getBlockType().getMaterial().isAir()) {
throw new InvalidToolBindException(type, "Blocks can't be used");
} else if (type == config.wandItem) {
} else if (type.getId().equalsIgnoreCase(config.wandItem)) {
throw new InvalidToolBindException(type, "Already used for the wand");
} else if (type == config.navigationWand) {
} else if (type.getId().equalsIgnoreCase(config.navigationWand)) {
throw new InvalidToolBindException(type, "Already used for the navigation wand");
}
Tool previous;

View File

@ -69,8 +69,8 @@ public class BaseItem implements NbtValued {
*
* @return the type
*/
public ItemTypes getType() {
return (ItemTypes) this.itemType;
public ItemType getType() {
return this.itemType;
}
/**

View File

@ -1,220 +0,0 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.blocks;
import com.sk89q.worldedit.registry.state.PropertyGroup;
import com.sk89q.worldedit.registry.state.PropertyKey;
import com.sk89q.worldedit.world.block.BlockStateHolder;
import com.sk89q.worldedit.world.block.BlockTypes;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* Block types.
*
* {@deprecated Please use {@link com.sk89q.worldedit.world.block.BlockType }}
*/
@Deprecated
public class BlockType {
public static double centralTopLimit(com.sk89q.worldedit.world.block.BlockType type) {
checkNotNull(type);
return centralTopLimit(type.getDefaultState());
}
public static double centralBottomLimit(BlockStateHolder block) {
checkNotNull(block);
BlockTypes type = block.getBlockType();
switch (type) {
case CREEPER_WALL_HEAD:
case DRAGON_WALL_HEAD:
case PLAYER_WALL_HEAD:
case ZOMBIE_WALL_HEAD: return 0.25;
case ACACIA_SLAB:
case BIRCH_SLAB:
case BRICK_SLAB:
case COBBLESTONE_SLAB:
case DARK_OAK_SLAB:
case DARK_PRISMARINE_SLAB:
case JUNGLE_SLAB:
case NETHER_BRICK_SLAB:
case OAK_SLAB:
case PETRIFIED_OAK_SLAB:
case PRISMARINE_BRICK_SLAB:
case PRISMARINE_SLAB:
case PURPUR_SLAB:
case QUARTZ_SLAB:
case RED_SANDSTONE_SLAB:
case SANDSTONE_SLAB:
case SPRUCE_SLAB:
case STONE_BRICK_SLAB:
case STONE_SLAB: {
String state = (String) block.getState(PropertyKey.TYPE);
if (state == null) return 0;
switch (state) {
case "double":
case "bottom":
return 0;
case "top":
return 0.5;
}
}
case ACACIA_TRAPDOOR:
case BIRCH_TRAPDOOR:
case DARK_OAK_TRAPDOOR:
case IRON_TRAPDOOR:
case JUNGLE_TRAPDOOR:
case OAK_TRAPDOOR:
case SPRUCE_TRAPDOOR:
if (block.getState(PropertyKey.OPEN) == Boolean.TRUE) {
return 1;
} else if ("bottom".equals(block.getState(PropertyKey.HALF))) {
return 0.8125;
} else {
return 0;
}
case ACACIA_FENCE_GATE:
case BIRCH_FENCE_GATE:
case DARK_OAK_FENCE_GATE:
case JUNGLE_FENCE_GATE:
case OAK_FENCE_GATE:
case SPRUCE_FENCE_GATE: return block.getState(PropertyKey.OPEN) == Boolean.TRUE ? 1 : 0;
default:
if (type.getMaterial().isMovementBlocker()) return 0;
return 1;
}
}
/**
* Returns the y offset a player falls to when falling onto the top of a block at xp+0.5/zp+0.5.
*
* @param block the block
* @return the y offset
*/
public static double centralTopLimit(BlockStateHolder block) {
checkNotNull(block);
BlockTypes type = block.getBlockType();
switch (type) {
case BLACK_BED:
case BLUE_BED:
case BROWN_BED:
case CYAN_BED:
case GRAY_BED:
case GREEN_BED:
case LIGHT_BLUE_BED:
case LIGHT_GRAY_BED:
case LIME_BED:
case MAGENTA_BED:
case ORANGE_BED:
case PINK_BED:
case PURPLE_BED:
case RED_BED:
case WHITE_BED:
case YELLOW_BED: return 0.5625;
case BREWING_STAND: return 0.875;
case CAKE: return (block.getState(PropertyKey.BITES) == (Integer) 6) ? 0 : 0.4375;
case CAULDRON: return 0.3125;
case COCOA: return 0.750;
case ENCHANTING_TABLE: return 0.75;
case END_PORTAL_FRAME: return block.getState(PropertyKey.EYE) == Boolean.TRUE ? 1 : 0.8125;
case CREEPER_HEAD:
case DRAGON_HEAD:
case PISTON_HEAD:
case PLAYER_HEAD:
case ZOMBIE_HEAD: return 0.5;
case CREEPER_WALL_HEAD:
case DRAGON_WALL_HEAD:
case PLAYER_WALL_HEAD:
case ZOMBIE_WALL_HEAD: return 0.75;
case ACACIA_FENCE:
case BIRCH_FENCE:
case DARK_OAK_FENCE:
case JUNGLE_FENCE:
case NETHER_BRICK_FENCE:
case OAK_FENCE:
case SPRUCE_FENCE: return 1.5;
case ACACIA_SLAB:
case BIRCH_SLAB:
case BRICK_SLAB:
case COBBLESTONE_SLAB:
case DARK_OAK_SLAB:
case DARK_PRISMARINE_SLAB:
case JUNGLE_SLAB:
case NETHER_BRICK_SLAB:
case OAK_SLAB:
case PETRIFIED_OAK_SLAB:
case PRISMARINE_BRICK_SLAB:
case PRISMARINE_SLAB:
case PURPUR_SLAB:
case QUARTZ_SLAB:
case RED_SANDSTONE_SLAB:
case SANDSTONE_SLAB:
case SPRUCE_SLAB:
case STONE_BRICK_SLAB:
case STONE_SLAB: {
String state = (String) block.getState(PropertyKey.TYPE);
if (state == null) return 0.5;
switch (state) {
case "bottom":
return 0.5;
case "top":
case "double":
return 1;
}
}
case LILY_PAD: return 0.015625;
case REPEATER: return 0.125;
case SOUL_SAND: return 0.875;
case COBBLESTONE_WALL:
case MOSSY_COBBLESTONE_WALL: return 1.5;
case FLOWER_POT: return 0.375;
case COMPARATOR: return 0.125;
case DAYLIGHT_DETECTOR: return 0.375;
case HOPPER: return 0.625;
case ACACIA_TRAPDOOR:
case BIRCH_TRAPDOOR:
case DARK_OAK_TRAPDOOR:
case IRON_TRAPDOOR:
case JUNGLE_TRAPDOOR:
case OAK_TRAPDOOR:
case SPRUCE_TRAPDOOR:
if (block.getState(PropertyKey.OPEN) == Boolean.TRUE) {
return 0;
} else if ("top".equals(block.getState(PropertyKey.HALF))) {
return 1;
} else {
return 0.1875;
}
case ACACIA_FENCE_GATE:
case BIRCH_FENCE_GATE:
case DARK_OAK_FENCE_GATE:
case JUNGLE_FENCE_GATE:
case OAK_FENCE_GATE:
case SPRUCE_FENCE_GATE: return block.getState(PropertyKey.OPEN) == Boolean.TRUE ? 0 : 1.5;
default:
if (type.hasProperty(PropertyKey.LAYERS)) {
return PropertyGroup.LEVEL.get(block) * 0.0625;
}
if (!type.getMaterial().isMovementBlocker()) return 0;
return 1;
}
}
}

View File

@ -57,6 +57,7 @@ import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.extension.input.ParserContext;
import com.sk89q.worldedit.extent.clipboard.Clipboard;
import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormat;
import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormats;
import com.sk89q.worldedit.function.mask.ExistingBlockMask;
import com.sk89q.worldedit.function.mask.Mask;
import com.sk89q.worldedit.function.mask.SingleBlockTypeMask;
@ -469,7 +470,7 @@ public class BrushCommands extends BrushProcessor {
try {
MultiClipboardHolder clipboards = ClipboardFormat.SCHEMATIC.loadAllFromInput(player, clipboard, null, true);
MultiClipboardHolder clipboards = ClipboardFormats.loadAllFromInput(player, clipboard, null, true);
if (clipboards == null) {
BBC.SCHEMATIC_NOT_FOUND.send(player, clipboard);
return null;

View File

@ -55,7 +55,9 @@ import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.event.extent.PasteEvent;
import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard;
import com.sk89q.worldedit.extent.clipboard.Clipboard;
import com.sk89q.worldedit.extent.clipboard.io.BuiltInClipboardFormat;
import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormat;
import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormats;
import com.sk89q.worldedit.extent.clipboard.io.ClipboardWriter;
import com.sk89q.worldedit.function.block.BlockReplace;
import com.sk89q.worldedit.function.mask.Mask;
@ -296,7 +298,7 @@ public class ClipboardCommands extends MethodCommands {
@Deprecated
@CommandPermissions({"worldedit.clipboard.download"})
public void download(final Player player, final LocalSession session, @Optional("schematic") final String formatName) throws CommandException, WorldEditException {
final ClipboardFormat format = ClipboardFormat.findByAlias(formatName);
final ClipboardFormat format = ClipboardFormats.findByAlias(formatName);
if (format == null) {
BBC.CLIPBOARD_INVALID_FORMAT.send(player, formatName);
return;
@ -356,8 +358,8 @@ public class ClipboardCommands extends MethodCommands {
} else {
target = clipboard;
}
switch (format) {
case PNG:
switch (format.getName()) {
case "PNG":
try {
FastByteArrayOutputStream baos = new FastByteArrayOutputStream(Short.MAX_VALUE);
ClipboardWriter writer = format.getWriter(baos);
@ -369,7 +371,7 @@ public class ClipboardCommands extends MethodCommands {
url = null;
}
break;
case SCHEMATIC:
case "SCHEMATIC":
if (Settings.IMP.WEB.URL.isEmpty()) {
BBC.SETTING_DISABLE.send(player, "web.url");
return;
@ -380,30 +382,30 @@ public class ClipboardCommands extends MethodCommands {
url = null;
break;
}
}
if (url == null) {
BBC.GENERATING_LINK_FAILED.send(player);
} else {
String urlText = url.toString();
if (Settings.IMP.WEB.SHORTEN_URLS) {
try {
urlText = MainUtil.getText("https://empcraft.com/s/?" + URLEncoder.encode(url.toString(), "UTF-8"));
} catch (IOException e) {
e.printStackTrace();
}
}
if (Fawe.imp().getPlatform().equalsIgnoreCase("nukkit")) {
FormBuilder form = Fawe.imp().getFormBuilder();
FawePlayer<Object> fp = FawePlayer.wrap(player);
if (form != null && fp != FakePlayer.getConsole().toFawePlayer()) {
form.setTitle("Download Clipboard");
form.addInput("url:", urlText, urlText);
form.display(fp);
return;
}
}
BBC.DOWNLOAD_LINK.send(player, urlText);
}
if (url == null) {
BBC.GENERATING_LINK_FAILED.send(player);
} else {
String urlText = url.toString();
if (Settings.IMP.WEB.SHORTEN_URLS) {
try {
urlText = MainUtil.getText("https://empcraft.com/s/?" + URLEncoder.encode(url.toString(), "UTF-8"));
} catch (IOException e) {
e.printStackTrace();
}
}
if (Fawe.imp().getPlatform().equalsIgnoreCase("nukkit")) {
FormBuilder form = Fawe.imp().getFormBuilder();
FawePlayer<Object> fp = FawePlayer.wrap(player);
if (form != null && fp != FakePlayer.getConsole().toFawePlayer()) {
form.setTitle("Download Clipboard");
form.addInput("url:", urlText, urlText);
form.display(fp);
return;
}
}
BBC.DOWNLOAD_LINK.send(player, urlText);
}
}
}
@Command(
@ -416,7 +418,7 @@ public class ClipboardCommands extends MethodCommands {
)
@CommandPermissions({"worldedit.clipboard.asset"})
public void asset(final Player player, final LocalSession session, String category) throws CommandException, WorldEditException {
final ClipboardFormat format = ClipboardFormat.SCHEMATIC;
final ClipboardFormat format = BuiltInClipboardFormat.MCEDIT_SCHEMATIC;
ClipboardHolder holder = session.getClipboard();
Clipboard clipboard = holder.getClipboard();
final Transform transform = holder.getTransform();
@ -430,7 +432,7 @@ public class ClipboardCommands extends MethodCommands {
} else {
target = clipboard;
}
BBC.GENERATING_LINK.send(player, format.name());
BBC.GENERATING_LINK.send(player, format.getName());
if (Settings.IMP.WEB.ASSETS.isEmpty()) {
BBC.SETTING_DISABLE.send(player, "web.assets");
return;
@ -478,7 +480,7 @@ public class ClipboardCommands extends MethodCommands {
}
Clipboard clipboard = holder.getClipboard();
Region region = clipboard.getRegion();
BlockVector3 to = atOrigin ? clipboard.getOrigin() : session.getPlacementPosition(player);
BlockVector3 to = atOrigin ? clipboard.getOrigin() : session.getPlacementPosition(player);
checkPaste(player, editSession, to, holder, clipboard);
Operation operation = holder
.createPaste(editSession)

View File

@ -187,7 +187,7 @@ public class GeneralCommands {
int found = 0;
for (ItemType searchType : ItemTypes.values) {
for (ItemType searchType : ItemTypes.values()) {
if (found >= 15) {
actor.print(BBC.getPrefix() + "Too many results!");
break;

View File

@ -284,7 +284,7 @@ public class OptionsCommands {
int found = 0;
for (ItemType searchType : ItemTypes.values) {
for (ItemType searchType : ItemTypes.values()) {
if (found >= 15) {
actor.print(BBC.getPrefix() + "Too many results!");
break;

View File

@ -16,6 +16,7 @@ import com.sk89q.worldedit.extension.platform.Actor;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.extent.clipboard.Clipboard;
import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormat;
import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormats;
import com.sk89q.worldedit.function.mask.Mask;
import com.sk89q.worldedit.function.pattern.ClipboardPattern;
import com.sk89q.worldedit.function.pattern.Pattern;
@ -191,7 +192,7 @@ public class PatternCommands extends MethodCommands {
clipboards = Collections.singletonList(clipboard);
break;
default:
MultiClipboardHolder multi = ClipboardFormat.SCHEMATIC.loadAllFromInput(player, location, null, true);
MultiClipboardHolder multi = ClipboardFormats.loadAllFromInput(player, location, null, true);
clipboards = multi != null ? multi.getHolders() : null;
break;
}

View File

@ -45,6 +45,7 @@ import com.sk89q.worldedit.event.extent.PlayerSaveClipboardEvent;
import com.sk89q.worldedit.extension.platform.Actor;
import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard;
import com.sk89q.worldedit.extent.clipboard.Clipboard;
import com.sk89q.worldedit.extent.clipboard.io.BuiltInClipboardFormat;
import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormat;
import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormats;
import com.sk89q.worldedit.extent.clipboard.io.ClipboardWriter;
@ -99,13 +100,13 @@ public class SchematicCommands extends MethodCommands {
@Deprecated
@CommandPermissions({"worldedit.clipboard.load", "worldedit.schematic.load", "worldedit.schematic.load.web", "worldedit.schematic.load.asset"})
public void loadall(final Player player, final LocalSession session, @Optional("schematic") final String formatName, final String filename, @Switch('r') boolean randomRotate) throws FilenameException {
final ClipboardFormat format = ClipboardFormat.findByAlias(formatName);
final ClipboardFormat format = ClipboardFormats.findByAlias(formatName);
if (format == null) {
BBC.CLIPBOARD_INVALID_FORMAT.send(player, formatName);
return;
}
try {
MultiClipboardHolder all = format.loadAllFromInput(player, filename, null, true);
MultiClipboardHolder all = ClipboardFormats.loadAllFromInput(player, filename, null, true);
if (all != null) {
session.addClipboard(all);
BBC.SCHEMATIC_LOADED.send(player, filename);
@ -192,7 +193,7 @@ public class SchematicCommands extends MethodCommands {
@CommandPermissions({"worldedit.clipboard.load", "worldedit.schematic.load", "worldedit.schematic.load.asset", "worldedit.schematic.load.web", "worldedit.schematic.load.other"})
public void load(final Player player, final LocalSession session, @Optional() final String formatName, String filename) throws FilenameException {
final LocalConfiguration config = this.worldEdit.getConfiguration();
ClipboardFormat format = formatName == null ? null : ClipboardFormat.findByAlias(formatName);
ClipboardFormat format = formatName == null ? null : ClipboardFormats.findByAlias(formatName);
InputStream in = null;
try {
URI uri;
@ -207,7 +208,7 @@ public class SchematicCommands extends MethodCommands {
ReadableByteChannel rbc = Channels.newChannel(url.openStream());
in = Channels.newInputStream(rbc);
uri = url.toURI();
if (format == null) format = ClipboardFormat.SCHEMATIC;
if (format == null) format = BuiltInClipboardFormat.MCEDIT_SCHEMATIC;
} else {
if (!player.hasPermission("worldedit.schematic.load") && !player.hasPermission("worldedit.clipboard.load")) {
BBC.NO_PERM.send(player, "worldedit.clipboard.load");
@ -235,7 +236,7 @@ public class SchematicCommands extends MethodCommands {
}
if (format == null && filename.matches(".*\\.[\\w].*")) {
String extension = filename.substring(filename.lastIndexOf('.') + 1, filename.length());
format = ClipboardFormat.findByExtension(extension);
format = ClipboardFormats.findByExtension(extension);
}
f = MainUtil.resolve(dir, filename, format, false);
}
@ -250,7 +251,7 @@ public class SchematicCommands extends MethodCommands {
return;
}
if (format == null) {
format = ClipboardFormat.findByFile(f);
format = ClipboardFormats.findByFile(f);
if (format == null) {
BBC.CLIPBOARD_INVALID_FORMAT.send(player, f.getName());
return;
@ -281,7 +282,7 @@ public class SchematicCommands extends MethodCommands {
@CommandPermissions({"worldedit.clipboard.save", "worldedit.schematic.save", "worldedit.schematic.save.other"})
public void save(final Player player, final LocalSession session, @Optional("schem") final String formatName, String filename, @Switch('g') boolean global) throws CommandException, WorldEditException {
final LocalConfiguration config = this.worldEdit.getConfiguration();
final ClipboardFormat format = ClipboardFormat.findByAlias(formatName);
final ClipboardFormat format = ClipboardFormats.findByAlias(formatName);
if (format == null) {
player.printError("Unknown schematic format: " + formatName);
return;
@ -298,14 +299,14 @@ public class SchematicCommands extends MethodCommands {
filename = filename.substring(3);
}
}
File f = this.worldEdit.getSafeSaveFile(player, dir, filename, format.getExtension(), format.getExtension());
if (f.getName().replaceAll("." + format.getExtension(), "").isEmpty()) {
File f = this.worldEdit.getSafeSaveFile(player, dir, filename, format.getPrimaryFileExtension(), format.getPrimaryFileExtension());
if (f.getName().replaceAll("." + format.getPrimaryFileExtension(), "").isEmpty()) {
File directory = f.getParentFile();
if (directory.exists()) {
int max = MainUtil.getMaxFileId(directory);
f = new File(directory, max + "." + format.getExtension());
f = new File(directory, max + "." + format.getPrimaryFileExtension());
} else {
f = new File(directory, "1." + format.getExtension());
f = new File(directory, "1." + format.getPrimaryFileExtension());
}
}
final File parent = f.getParentFile();
@ -477,9 +478,9 @@ public class SchematicCommands extends MethodCommands {
Message m = new Message(BBC.SCHEMATIC_FORMAT).newline();
String baseCmd = Commands.getAlias(SchematicCommands.class, "schematic") + " " + Commands.getAlias(SchematicCommands.class, "save");
boolean first = true;
for (final ClipboardFormat format : ClipboardFormat.values) {
for (final ClipboardFormat format : ClipboardFormats.getAll()) {
StringBuilder builder = new StringBuilder();
builder.append(format.name()).append(": ");
builder.append(format.getName()).append(": ");
for (final String lookupName : format.getAliases()) {
if (!first) {
builder.append(", ");
@ -487,7 +488,7 @@ public class SchematicCommands extends MethodCommands {
builder.append(lookupName);
first = false;
}
String cmd = baseCmd + " " + format.name() + " <filename>";
String cmd = baseCmd + " " + format.getName() + " <filename>";
m.text(builder).suggestTip(cmd).newline();
first = true;
}

View File

@ -37,7 +37,6 @@ import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.blocks.BaseItemStack;
import com.sk89q.worldedit.blocks.BlockType;
import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.extension.input.ParserContext;
import com.sk89q.worldedit.extension.platform.permission.ActorSelectorLimits;
@ -287,7 +286,7 @@ public class SelectionCommands {
)
@CommandPermissions("worldedit.wand")
public void wand(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
player.giveItem(new BaseItemStack(we.getConfiguration().wandItem, 1));
player.giveItem(new BaseItemStack(ItemTypes.parse(we.getConfiguration().wandItem), 1));
BBC.SELECTION_WAND.send(player);
if (!FawePlayer.wrap(player).hasPermission("fawe.tips"))
BBC.TIP_SEL_LIST.or(BBC.TIP_SELECT_CONNECTED, BBC.TIP_SET_POS1, BBC.TIP_FARWAND, BBC.TIP_DISCORD).send(player);

View File

@ -67,6 +67,7 @@ import com.sk89q.worldedit.extension.platform.Capability;
import com.sk89q.worldedit.extension.platform.CommandManager;
import com.sk89q.worldedit.extension.platform.Platform;
import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormat;
import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormats;
import com.sk89q.worldedit.function.mask.ExistingBlockMask;
import com.sk89q.worldedit.function.mask.Mask;
import com.sk89q.worldedit.function.operation.Operations;
@ -903,7 +904,7 @@ public class UtilityCommands extends MethodCommands {
}
if (formatName != null) {
final ClipboardFormat cf = ClipboardFormat.findByAlias(formatName);
final ClipboardFormat cf = ClipboardFormats.findByAlias(formatName);
forEachFile = new DelegateConsumer<File>(forEachFile) {
@Override
public void accept(File file) {
@ -1013,7 +1014,7 @@ public class UtilityCommands extends MethodCommands {
dir = root;
}
ClipboardFormat format = ClipboardFormat.findByFile(file);
ClipboardFormat format = ClipboardFormats.findByFile(file);
URI relative = dir.toURI().relativize(file.toURI());
StringBuilder name = new StringBuilder();
if (relative.isAbsolute()) {

View File

@ -132,12 +132,12 @@ public class FloatingTreeRemover implements BlockTool {
if (visited.add(next)) {
BlockState state = world.getBlock(next);
BlockTypes type = state.getBlockType();
switch (type) {
case AIR:
case CAVE_AIR:
case VOID_AIR:
case SNOW:
BlockType type = state.getBlockType();
switch (type.getResource().toUpperCase()) {
case "AIR":
case "CAVE_AIR":
case "VOID_AIR":
case "SNOW":
continue;
}
if (isTreeBlock(state.getBlockType())) {

View File

@ -75,7 +75,7 @@ public interface Player extends Entity, Actor {
*
* @return the item id of the item the player is holding
*/
BlockState getBlockInHand(HandSide handSide) throws WorldEditException;
BaseBlock getBlockInHand(HandSide handSide) throws WorldEditException;
/**
* Gives the player an item.

View File

@ -55,6 +55,7 @@ import com.sk89q.worldedit.util.HandSide;
import com.sk89q.worldedit.world.World;
import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.block.BlockStateHolder;
import com.sk89q.worldedit.world.block.BlockType;
import com.sk89q.worldedit.world.block.BlockTypes;
import com.sk89q.worldedit.world.registry.LegacyMapper;
@ -77,7 +78,7 @@ public class DefaultBlockParser extends InputParser<BlockStateHolder> {
private static BlockState getBlockInHand(Actor actor, HandSide handSide) throws InputParseException {
if (actor instanceof Player) {
try {
return ((Player) actor).getBlockInHand(handSide);
return ((Player) actor).getBlockInHand(handSide).toImmutableState();
} catch (NotABlockException e) {
throw new InputParseException("You're not holding a block!");
} catch (WorldEditException e) {
@ -179,7 +180,7 @@ public class DefaultBlockParser extends InputParser<BlockStateHolder> {
} else if (MathMan.isInteger(split[0])) {
state = LegacyMapper.getInstance().getBlockFromLegacy(Integer.parseInt(split[0]), Integer.parseInt(split[1]));
} else {
BlockTypes type = BlockTypes.get(split[0].toLowerCase());
BlockType type = BlockTypes.get(split[0].toLowerCase());
if (type != null) {
state = LegacyMapper.getInstance().getBlockFromLegacy(type.getLegacyCombinedId() >> 4, Integer.parseInt(split[1]));
}
@ -238,7 +239,7 @@ public class DefaultBlockParser extends InputParser<BlockStateHolder> {
state = item.getType().getBlockType().getDefaultState();
nbt = item.getNbtData();
} else {
BlockTypes type = BlockTypes.parse(typeString.toLowerCase());
BlockType type = BlockTypes.parse(typeString.toLowerCase());
if (type != null) state = type.getDefaultState();
if (state == null) {
throw new NoMatchException("Does not match a valid block type: '" + input + "'");
@ -261,7 +262,7 @@ public class DefaultBlockParser extends InputParser<BlockStateHolder> {
}
// Check if the item is allowed
BlockTypes blockType = state.getBlockType();
BlockType blockType = state.getBlockType();
if (context.isRestricted()) {
Actor actor = context.requireActor();

View File

@ -53,7 +53,7 @@ public class DefaultItemParser extends InputParser<BaseItem> {
if (type != null) {
Integer legacy = LegacyMapper.getInstance().getLegacyCombined(type);
if (legacy != null) {
ItemTypes newType = LegacyMapper.getInstance().getItemFromLegacy(legacy >> 4, Integer.parseInt(split[1]));
ItemType newType = LegacyMapper.getInstance().getItemFromLegacy(legacy >> 4, Integer.parseInt(split[1]));
if (newType != null) type = newType;
}
}

View File

@ -33,8 +33,9 @@ import com.sk89q.worldedit.util.Location;
import com.sk89q.worldedit.util.TargetBlock;
import com.sk89q.worldedit.util.auth.AuthorizationException;
import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.blocks.BlockType;
import com.sk89q.worldedit.world.block.BlockStateHolder;
import com.sk89q.worldedit.world.block.BlockType;
import com.sk89q.worldedit.world.block.BlockTypeUtil;
import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.block.BlockTypes;
import com.sk89q.worldedit.world.gamemode.GameMode;
@ -125,7 +126,7 @@ public abstract class AbstractPlayerActor implements Actor, Player, Cloneable {
if (y - 1 != origY) {
final BlockVector3 pos = BlockVector3.at(x, y - 2, z);
final BlockStateHolder state = world.getBlock(pos);
setPosition(Vector3.at(x + 0.5, y - 2 + BlockType.centralTopLimit(state), z + 0.5));
setPosition(Vector3.at(x + 0.5, y - 2 + BlockTypeUtil.centralTopLimit(state), z + 0.5));
// setPosition(Vector3.at(x + 0.5, y - 2 + 1, z + 0.5));
}
@ -147,7 +148,7 @@ public abstract class AbstractPlayerActor implements Actor, Player, Cloneable {
final BlockVector3 pos = BlockVector3.at(x, y, z);
final BlockState id = world.getBlock(pos);
if (id.getBlockType().getMaterial().isMovementBlocker()) {
setPosition(Vector3.at(x + 0.5, y + + BlockType.centralTopLimit(id), z + 0.5));
setPosition(Vector3.at(x + 0.5, y + + BlockTypeUtil.centralTopLimit(id), z + 0.5));
return;
}
@ -182,18 +183,18 @@ public abstract class AbstractPlayerActor implements Actor, Player, Cloneable {
BlockState state;
if (level >= maxY) state = BlockTypes.VOID_AIR.getDefaultState();
else state = world.getBlock(BlockVector3.at(x, level, z));
BlockTypes type = state.getBlockType();
BlockType type = state.getBlockType();
BlockMaterial material = type.getMaterial();
if (!material.isFullCube() || !material.isMovementBlocker()) {
if (!lastState) {
lastState = BlockType.centralBottomLimit(state) != 1;
lastState = BlockTypeUtil.centralBottomLimit(state) != 1;
continue;
}
if (freeStart == -1) {
freeStart = level + BlockType.centralTopLimit(state);
freeStart = level + BlockTypeUtil.centralTopLimit(state);
} else {
double bottomLimit = BlockType.centralBottomLimit(state);
double bottomLimit = BlockTypeUtil.centralBottomLimit(state);
double space = level + bottomLimit - freeStart;
if (space >= height) {
setPosition(Vector3.at(x + 0.5, freeStart, z + 0.5));
@ -234,18 +235,18 @@ public abstract class AbstractPlayerActor implements Actor, Player, Cloneable {
BlockState state;
if (level >= maxY) state = BlockTypes.VOID_AIR.getDefaultState();
else state = world.getBlock(BlockVector3.at(x, level, z));
BlockTypes type = state.getBlockType();
BlockType type = state.getBlockType();
BlockMaterial material = type.getMaterial();
if (!material.isFullCube() || !material.isMovementBlocker()) {
if (!lastState) {
lastState = BlockType.centralTopLimit(state) != 0;
lastState = BlockTypeUtil.centralTopLimit(state) != 0;
continue;
}
if (freeEnd == -1) {
freeEnd = level + BlockType.centralBottomLimit(state);
freeEnd = level + BlockTypeUtil.centralBottomLimit(state);
} else {
double topLimit = BlockType.centralTopLimit(state);
double topLimit = BlockTypeUtil.centralTopLimit(state);
double freeStart = level + topLimit;
double space = freeEnd - freeStart;
if (space >= height) {
@ -398,7 +399,7 @@ public abstract class AbstractPlayerActor implements Actor, Player, Cloneable {
}
@Override
public BlockState getBlockInHand(HandSide handSide) throws WorldEditException {
public BaseBlock getBlockInHand(HandSide handSide) throws WorldEditException {
final ItemType typeId = getItemInHand(handSide).getType();
if (typeId.hasBlockType()) {
return typeId.getBlockType().getDefaultState().toBaseBlock();

View File

@ -319,7 +319,7 @@ public class PlatformManager {
}
if (event.getType() == Interaction.HIT) {
if (session.isToolControlEnabled() && playerActor.getItemInHand(HandSide.MAIN_HAND).getType().equals(getConfiguration().wandItem)) {
if (session.isToolControlEnabled() && playerActor.getItemInHand(HandSide.MAIN_HAND).getType().getId().equals(getConfiguration().wandItem)) {
FawePlayer<?> fp = FawePlayer.wrap(playerActor);
if (!actor.hasPermission("worldedit.selection.pos")) {
return;
@ -378,7 +378,7 @@ public class PlatformManager {
//>>>>>>> 399e0ad5... Refactor vector system to be cleaner
}
} else if (event.getType() == Interaction.OPEN) {
if (session.isToolControlEnabled() && playerActor.getItemInHand(HandSide.MAIN_HAND).getType().equals(getConfiguration().wandItem)) {
if (session.isToolControlEnabled() && playerActor.getItemInHand(HandSide.MAIN_HAND).getType().getId().equals(getConfiguration().wandItem)) {
FawePlayer<?> fp = FawePlayer.wrap(playerActor);
if (!actor.hasPermission("worldedit.selection.pos")) {
return;

View File

@ -20,7 +20,7 @@
package com.sk89q.worldedit.extension.platform;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.world.block.BaseBlock;
import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.block.BlockStateHolder;
@ -70,7 +70,7 @@ public class PlayerProxy extends AbstractPlayerActor {
@Override
public BlockState getBlockInHand(HandSide handSide) throws WorldEditException {
public BaseBlock getBlockInHand(HandSide handSide) throws WorldEditException {
return basePlayer.getBlockInHand(handSide);
}

View File

@ -81,7 +81,7 @@ public class AbstractDelegateExtent implements LightingExtent {
}
@Override
public BlockState getFullBlock(BlockVector3 position) {
public BaseBlock getFullBlock(BlockVector3 position) {
return extent.getFullBlock(position);
}
@ -138,7 +138,7 @@ public class AbstractDelegateExtent implements LightingExtent {
}
@Override
public boolean setBlock(int x, int y, int z, BlockStateHolder block) throws WorldEditException {
public <T extends BlockStateHolder<T>> boolean setBlock(int x, int y, int z, T block) throws WorldEditException {
// mutable.mutX(x);
// mutable.mutY(y);
// mutable.mutZ(z);
@ -150,7 +150,7 @@ public class AbstractDelegateExtent implements LightingExtent {
}
@Override
public boolean setBlock(BlockVector3 location, BlockStateHolder block) throws WorldEditException {
public <T extends BlockStateHolder<T>> boolean setBlock(BlockVector3 location, T block) throws WorldEditException {
return extent.setBlock(location, block);
}

View File

@ -118,19 +118,19 @@ public interface Extent extends InputExtent, OutputExtent {
@Override
default BlockState getBlock(BlockVector3 position) {
return getFullBlock(position);
return getFullBlock(position).toImmutableState();
}
@Override
default BlockState getLazyBlock(BlockVector3 position) {
return getFullBlock(position);
return getFullBlock(position).toImmutableState();
}
default BlockState getLazyBlock(int x, int y, int z) {
return getLazyBlock(BlockVector3.at(x, y, z));
}
default boolean setBlock(int x, int y, int z, BlockStateHolder state) throws WorldEditException {
default <T extends BlockStateHolder<T>> boolean setBlock(int x, int y, int z, T state) throws WorldEditException {
return setBlock(BlockVector3.at(x, y, z), state);
}

View File

@ -80,7 +80,7 @@ public interface InputExtent {
* @param position position of the block
* @return the block
*/
BlockState getFullBlock(BlockVector3 position);
BaseBlock getFullBlock(BlockVector3 position);
/**
* Get the biome at the given location.

View File

@ -50,7 +50,7 @@ public interface OutputExtent {
* @return true if the block was successfully set (return value may not be accurate)
* @throws WorldEditException thrown on an error
*/
boolean setBlock(BlockVector3 position, BlockStateHolder block) throws WorldEditException;
<T extends BlockStateHolder<T>> boolean setBlock(BlockVector3 position, T block) throws WorldEditException;
/**
* Set the biome.

View File

@ -234,8 +234,8 @@ public class BlockArrayClipboard implements Clipboard, LightingExtent, Closeable
//>>>>>>> 399e0ad5... Refactor vector system to be cleaner
@Override
public BlockState getFullBlock(BlockVector3 position) {
return getLazyBlock(position);
public BaseBlock getFullBlock(BlockVector3 position) {
return getLazyBlock(position).toBaseBlock();
}
@Override

View File

@ -19,28 +19,220 @@
package com.sk89q.worldedit.extent.clipboard.io;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Map;
import java.util.Set;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;
import com.boydti.fawe.object.clipboard.AbstractClipboardFormat;
import com.boydti.fawe.object.io.PGZIPOutputStream;
import com.boydti.fawe.object.io.ResettableFileInputStream;
import com.boydti.fawe.object.schematic.PNGWriter;
import com.boydti.fawe.object.schematic.StructureFormat;
import com.google.common.collect.ImmutableSet;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.jnbt.NBTConstants;
import com.sk89q.jnbt.NBTInputStream;
import com.sk89q.jnbt.NBTOutputStream;
import com.sk89q.jnbt.NamedTag;
import com.sk89q.jnbt.Tag;
/**
* A collection of supported clipboard formats.
*/
@Deprecated
public class BuiltInClipboardFormat {
public static final ClipboardFormat MCEDIT_SCHEMATIC = ClipboardFormat.SCHEMATIC;
public static final ClipboardFormat SPONGE_SCHEMATIC = ClipboardFormat.SPONGE_SCHEMATIC;
public static final ClipboardFormat STRUCTURE = ClipboardFormat.STRUCTURE;
public static final ClipboardFormat PNG = ClipboardFormat.PNG;
public enum BuiltInClipboardFormat implements ClipboardFormat{
/**
* The Schematic format used by many software.
*/
@Deprecated
public static final ClipboardFormat[] values() {
return ClipboardFormat.values;
}
@Deprecated
public static ClipboardFormat valueOf(String value) {
switch (value) {
case "MCEDIT_SCHEMATIC":
value = "SCHEMATIC";
break;
MCEDIT_SCHEMATIC("mcedit", "mce", "schematic") {
@Override
public ClipboardReader getReader(InputStream inputStream) throws IOException {
if (inputStream instanceof FileInputStream) {
inputStream = new ResettableFileInputStream((FileInputStream) inputStream);
}
BufferedInputStream buffered = new BufferedInputStream(inputStream);
NBTInputStream nbtStream = new NBTInputStream(new BufferedInputStream(new GZIPInputStream(buffered)));
SchematicReader input = new SchematicReader(nbtStream);
input.setUnderlyingStream(inputStream);
return input;
}
return ClipboardFormat.valueOf(value);
@Override
public ClipboardWriter getWriter(OutputStream outputStream) throws IOException {
throw new UnsupportedOperationException("No longer supported.");
}
@Override
public boolean isFormat(File file) {
try (NBTInputStream str = new NBTInputStream(new GZIPInputStream(new FileInputStream(file)))) {
NamedTag rootTag = str.readNamedTag();
if (!rootTag.getName().equals("Schematic")) {
return false;
}
CompoundTag schematicTag = (CompoundTag) rootTag.getTag();
// Check
Map<String, Tag> schematic = schematicTag.getValue();
if (!schematic.containsKey("Materials")) {
return false;
}
} catch (Exception e) {
return false;
}
return true;
}
@Override
public String getPrimaryFileExtension() {
return "schematic";
}
},
@Deprecated
SPONGE_SCHEMATIC("sponge", "schem") {
@Override
public ClipboardReader getReader(InputStream inputStream) throws IOException {
if (inputStream instanceof FileInputStream) {
inputStream = new ResettableFileInputStream((FileInputStream) inputStream);
}
BufferedInputStream buffered = new BufferedInputStream(inputStream);
NBTInputStream nbtStream = new NBTInputStream(new BufferedInputStream(new GZIPInputStream(buffered)));
SpongeSchematicReader input = new SpongeSchematicReader(nbtStream);
return input;
}
@Override
public ClipboardWriter getWriter(OutputStream outputStream) throws IOException {
OutputStream gzip;
if (outputStream instanceof PGZIPOutputStream || outputStream instanceof GZIPOutputStream) {
gzip = outputStream;
} else {
outputStream = new BufferedOutputStream(outputStream);
PGZIPOutputStream pigz = new PGZIPOutputStream(outputStream);
gzip = pigz;
}
NBTOutputStream nbtStream = new NBTOutputStream(new BufferedOutputStream(gzip));
return new SpongeSchematicWriter(nbtStream);
}
@Override
public boolean isFormat(File file) {
try (NBTInputStream str = new NBTInputStream(new GZIPInputStream(new FileInputStream(file)))) {
NamedTag rootTag = str.readNamedTag();
if (!rootTag.getName().equals("Schematic")) {
return false;
}
CompoundTag schematicTag = (CompoundTag) rootTag.getTag();
// Check
Map<String, Tag> schematic = schematicTag.getValue();
if (!schematic.containsKey("Version")) {
return false;
}
} catch (Exception e) {
return false;
}
return true;
}
@Override
public String getPrimaryFileExtension() {
return "schem";
}
},
/**
* The structure block format:
* http://minecraft.gamepedia.com/Structure_block_file_format
*/
STRUCTURE("structure", "nbt") {
@Override
public ClipboardReader getReader(InputStream inputStream) throws IOException {
inputStream = new BufferedInputStream(inputStream);
NBTInputStream nbtStream = new NBTInputStream(new BufferedInputStream(new GZIPInputStream(inputStream)));
return new StructureFormat(nbtStream);
}
@Override
public ClipboardWriter getWriter(OutputStream outputStream) throws IOException {
outputStream = new BufferedOutputStream(outputStream);
OutputStream gzip;
if (outputStream instanceof PGZIPOutputStream || outputStream instanceof GZIPOutputStream) {
gzip = outputStream;
} else {
PGZIPOutputStream pigz = new PGZIPOutputStream(outputStream);
gzip = pigz;
}
NBTOutputStream nbtStream = new NBTOutputStream(new BufferedOutputStream(gzip));
return new StructureFormat(nbtStream);
}
@Override
public boolean isFormat(File file) {
return file.getName().endsWith(".nbt");
}
@Override
public String getPrimaryFileExtension() {
return "nbt";
}
},
/**
* Isometric PNG writer
*/
PNG("png", "image") {
@Override
public ClipboardReader getReader(InputStream inputStream) throws IOException {
return null;
}
@Override
public ClipboardWriter getWriter(OutputStream outputStream) throws IOException {
return new PNGWriter(new BufferedOutputStream(outputStream));
}
@Override
public boolean isFormat(File file) {
return file.getName().endsWith(".png");
}
@Override
public String getPrimaryFileExtension() {
return "png";
}
};
private final ImmutableSet<String> aliases;
BuiltInClipboardFormat(String... aliases) {
this.aliases = ImmutableSet.copyOf(aliases);
}
@Override
public String getName() {
return name();
}
@Override
public Set<String> getAliases() {
return this.aliases;
}
@Override
public Set<String> getFileExtensions() {
return ImmutableSet.of(getPrimaryFileExtension());
}
}

View File

@ -19,275 +19,84 @@
package com.sk89q.worldedit.extent.clipboard.io;
import com.boydti.fawe.config.BBC;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URI;
import java.net.URL;
import java.util.HashMap;
import java.util.Set;
import static com.google.common.base.Preconditions.checkNotNull;
import com.boydti.fawe.config.Settings;
import com.boydti.fawe.jnbt.NBTStreamer;
import com.boydti.fawe.object.RunnableVal;
import com.boydti.fawe.object.clipboard.*;
import com.boydti.fawe.object.io.FastByteArrayOutputStream;
import com.boydti.fawe.object.clipboard.URIClipboardHolder;
import com.boydti.fawe.object.io.PGZIPOutputStream;
import com.boydti.fawe.object.io.ResettableFileInputStream;
import com.boydti.fawe.object.schematic.PNGWriter;
import com.boydti.fawe.object.schematic.Schematic;
import com.boydti.fawe.object.schematic.StructureFormat;
import com.boydti.fawe.util.MainUtil;
import com.boydti.fawe.util.ReflectionUtils;
import com.google.common.io.ByteSource;
import com.google.common.io.Files;
import com.google.gson.Gson;
import com.sk89q.jnbt.*;
import com.sk89q.worldedit.LocalConfiguration;
import com.sk89q.worldedit.LocalSession;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.extension.platform.Actor;
import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard;
import com.sk89q.worldedit.extent.clipboard.Clipboard;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.session.ClipboardHolder;
import com.sk89q.worldedit.world.block.BlockTypes;
import java.io.*;
import java.lang.reflect.Array;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.channels.Channels;
import java.nio.channels.ReadableByteChannel;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.regex.Pattern;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import javax.annotation.Nullable;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* A collection of supported clipboard formats.
*/
public enum ClipboardFormat {
/**
* The Schematic format used by many software.
*/
@Deprecated
SCHEMATIC(new AbstractClipboardFormat("SCHEMATIC", "mcedit", "mce", "schematic") {
@Override
public ClipboardReader getReader(InputStream inputStream) throws IOException {
if (inputStream instanceof FileInputStream) {
inputStream = new ResettableFileInputStream((FileInputStream) inputStream);
}
BufferedInputStream buffered = new BufferedInputStream(inputStream);
NBTInputStream nbtStream = new NBTInputStream(new BufferedInputStream(new GZIPInputStream(buffered)));
SchematicReader input = new SchematicReader(nbtStream);
input.setUnderlyingStream(inputStream);
return input;
}
@Override
public ClipboardWriter getWriter(OutputStream outputStream) throws IOException {
throw new UnsupportedOperationException("No longer supported.");
}
@Override
public boolean isFormat(File file) {
if (!file.getName().toLowerCase().endsWith(".schematic")) return false;
DataInputStream str = null;
try {
str = new DataInputStream(new GZIPInputStream(new FileInputStream(file)));
if ((str.readByte() & 0xFF) != NBTConstants.TYPE_COMPOUND) {
return false;
}
byte[] nameBytes = new byte[str.readShort() & 0xFFFF];
str.readFully(nameBytes);
String name = new String(nameBytes, NBTConstants.CHARSET);
return name.equals("Schematic");
} catch (IOException e) {
return false;
} finally {
if (str != null) {
try {
str.close();
} catch (IOException ignored) {
}
}
}
}
@Override
public String getExtension() {
return "schematic";
}
}),
@Deprecated
SPONGE_SCHEMATIC(new AbstractClipboardFormat("SPONGE", "sponge", "schem") {
@Override
public ClipboardReader getReader(InputStream inputStream) throws IOException {
if (inputStream instanceof FileInputStream) {
inputStream = new ResettableFileInputStream((FileInputStream) inputStream);
}
BufferedInputStream buffered = new BufferedInputStream(inputStream);
NBTInputStream nbtStream = new NBTInputStream(new BufferedInputStream(new GZIPInputStream(buffered)));
SpongeSchematicReader input = new SpongeSchematicReader(nbtStream);
return input;
}
@Override
public ClipboardWriter getWriter(OutputStream outputStream) throws IOException {
OutputStream gzip;
if (outputStream instanceof PGZIPOutputStream || outputStream instanceof GZIPOutputStream) {
gzip = outputStream;
} else {
outputStream = new BufferedOutputStream(outputStream);
PGZIPOutputStream pigz = new PGZIPOutputStream(outputStream);
gzip = pigz;
}
NBTOutputStream nbtStream = new NBTOutputStream(new BufferedOutputStream(gzip));
return new SpongeSchematicWriter(nbtStream);
}
@Override
public boolean isFormat(File file) {
if (!file.getName().toLowerCase().endsWith(".schem")) return false;
DataInputStream str = null;
try {
str = new DataInputStream(new GZIPInputStream(new FileInputStream(file)));
if ((str.readByte() & 0xFF) != NBTConstants.TYPE_COMPOUND) {
return false;
}
byte[] nameBytes = new byte[str.readShort() & 0xFFFF];
str.readFully(nameBytes);
String name = new String(nameBytes, NBTConstants.CHARSET);
return name.equals("Schematic");
} catch (IOException e) {
return false;
} finally {
if (str != null) {
try {
str.close();
} catch (IOException ignored) {
}
}
}
}
@Override
public String getExtension() {
return "schem";
}
}),
/**
* The structure block format:
* http://minecraft.gamepedia.com/Structure_block_file_format
*/
STRUCTURE(new AbstractClipboardFormat("STRUCTURE", "structure", "nbt") {
@Override
public ClipboardReader getReader(InputStream inputStream) throws IOException {
inputStream = new BufferedInputStream(inputStream);
NBTInputStream nbtStream = new NBTInputStream(new BufferedInputStream(new GZIPInputStream(inputStream)));
return new StructureFormat(nbtStream);
}
@Override
public ClipboardWriter getWriter(OutputStream outputStream) throws IOException {
outputStream = new BufferedOutputStream(outputStream);
OutputStream gzip;
if (outputStream instanceof PGZIPOutputStream || outputStream instanceof GZIPOutputStream) {
gzip = outputStream;
} else {
PGZIPOutputStream pigz = new PGZIPOutputStream(outputStream);
gzip = pigz;
}
NBTOutputStream nbtStream = new NBTOutputStream(new BufferedOutputStream(gzip));
return new StructureFormat(nbtStream);
}
@Override
public boolean isFormat(File file) {
return file.getName().endsWith(".nbt");
}
@Override
public String getExtension() {
return "nbt";
}
}),
/**
* Isometric PNG writer
*/
PNG(new AbstractClipboardFormat("PNG", "png", "image") {
@Override
public ClipboardReader getReader(InputStream inputStream) throws IOException {
return null;
}
@Override
public ClipboardWriter getWriter(OutputStream outputStream) throws IOException {
return new PNGWriter(new BufferedOutputStream(outputStream));
}
@Override
public boolean isFormat(File file) {
return file.getName().endsWith(".png");
}
@Override
public String getExtension() {
return "png";
}
}),
;
public static final ClipboardFormat[] values;
private static final Map<String, ClipboardFormat> aliasMap;
static {
aliasMap = new ConcurrentHashMap<>(8, 0.9f, 1);
for (ClipboardFormat emum : ClipboardFormat.values()) {
for (String alias : emum.getAliases()) {
aliasMap.put(alias, emum);
}
}
values = values();
}
private IClipboardFormat format;
ClipboardFormat() {
}
ClipboardFormat(IClipboardFormat format) {
this.format = format;
}
public interface ClipboardFormat {
/**
* Returns the name of this format.
*
* @return The name of the format
*/
public String getName() {
return name();
}
String getName();
/**
* Get a set of aliases.
*
* @return a set of aliases
*/
Set<String> getAliases();
/**
* Create a reader.
*
* @param inputStream the input stream
* @return a reader
* @throws IOException thrown on I/O error
*/
ClipboardReader getReader(InputStream inputStream) throws IOException;
/**
* Create a writer.
*
* @param outputStream the output stream
* @return a writer
* @throws IOException thrown on I/O error
*/
ClipboardWriter getWriter(OutputStream outputStream) throws IOException;
/**
* Return whether the given file is of this format.
*
* @param file the file
* @return true if the given file is of this format
*/
boolean isFormat(File file);
/**
* Get the file extension this format primarily uses.
*
* @return The primary file extension
*/
public String getPrimaryFileExtension() {
return getExtension();
}
String getPrimaryFileExtension();
/**
* Get the file extensions this format is commonly known to use. This should
@ -295,12 +104,43 @@ public enum ClipboardFormat {
*
* @return The file extensions this format might be known by
*/
public Set<String> getFileExtensions() {
return Collections.singleton(getPrimaryFileExtension());
Set<String> getFileExtensions();
/**
* Set the player's clipboard
* @param player
* @param uri
* @param in
* @return the held clipboard
* @throws IOException
*/
default ClipboardHolder hold(Player player, URI uri, InputStream in) throws IOException {
checkNotNull(player);
checkNotNull(uri);
checkNotNull(in);
final ClipboardReader reader = getReader(in);
final Clipboard clipboard;
LocalSession session = WorldEdit.getInstance().getSessionManager().get(player);
session.setClipboard(null);
clipboard = reader.read(player.getUniqueId());
URIClipboardHolder holder = new URIClipboardHolder(uri, clipboard);
session.setClipboard(holder);
return holder;
}
default Schematic load(File file) throws IOException {
return load(new FileInputStream(file));
}
public URL uploadPublic(final Clipboard clipboard, String category, String user) {
default Schematic load(InputStream stream) throws IOException {
return new Schematic(getReader(stream).read());
}
default URL uploadPublic(final Clipboard clipboard, String category, String user) {
// summary
// blocks
HashMap<String, Object> map = new HashMap<String, Object>();
@ -318,158 +158,20 @@ public enum ClipboardFormat {
}
});
}
public static MultiClipboardHolder loadAllFromInput(Actor player, String input, ClipboardFormat format, boolean message) throws IOException {
checkNotNull(player);
checkNotNull(input);
WorldEdit worldEdit = WorldEdit.getInstance();
LocalConfiguration config = worldEdit.getConfiguration();
if (input.startsWith("url:")) {
if (!player.hasPermission("worldedit.schematic.load.web")) {
if (message) BBC.NO_PERM.send(player, "worldedit.schematic.load.web");
return null;
default URL uploadAnonymous(final Clipboard clipboard) {
return MainUtil.upload(null, null, getPrimaryFileExtension(), new RunnableVal<OutputStream>() {
@Override
public void run(OutputStream value) {
write(value, clipboard);
}
URL base = new URL(Settings.IMP.WEB.URL);
input = new URL(base, "uploads/" + input.substring(4) + ".schematic").toString();
}
if (input.startsWith("http")) {
if (!player.hasPermission("worldedit.schematic.load.asset")) {
if (message) BBC.NO_PERM.send(player, "worldedit.schematic.load.asset");
return null;
}
URL url = new URL(input);
URL webInterface = new URL(Settings.IMP.WEB.ASSETS);
if (!url.getHost().equalsIgnoreCase(webInterface.getHost())) {
if (message) BBC.WEB_UNAUTHORIZED.send(player, url);
return null;
}
MultiClipboardHolder clipboards = loadAllFromUrl(url);
return clipboards;
} else {
if (Settings.IMP.PATHS.PER_PLAYER_SCHEMATICS && Pattern.compile("[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}").matcher(input).find() && !player.hasPermission("worldedit.schematic.load.other")) {
BBC.NO_PERM.send(player, "worldedit.schematic.load.other");
return null;
}
File working = worldEdit.getWorkingDirectoryFile(config.saveDir);
File dir = Settings.IMP.PATHS.PER_PLAYER_SCHEMATICS ? new File(working, player.getUniqueId().toString()) : working;
File f;
if (input.startsWith("#")) {
String[] extensions;
if (format != null) {
extensions = format.getFileExtensions().toArray(new String[0]);
} else {
extensions = ClipboardFormats.getFileExtensionArray();
}
f = player.openFileOpenDialog(extensions);
if (f == null || !f.exists()) {
if (message) player.printError("Schematic " + input + " does not exist! (" + f + ")");
return null;
}
} else {
if (Settings.IMP.PATHS.PER_PLAYER_SCHEMATICS && Pattern.compile("[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}").matcher(input).find() && !player.hasPermission("worldedit.schematic.load.other")) {
if (message) BBC.NO_PERM.send(player, "worldedit.schematic.load.other");
return null;
}
if (format == null && input.matches(".*\\.[\\w].*")) {
String extension = input.substring(input.lastIndexOf('.') + 1, input.length());
format = ClipboardFormat.findByExtension(extension);
}
f = MainUtil.resolve(dir, input, format, true);
}
if (f == null || !f.exists()) {
if (!input.contains("../")) {
dir = worldEdit.getWorkingDirectoryFile(config.saveDir);
f = MainUtil.resolve(dir, input, format, true);
}
}
if (f == null || !f.exists() || !MainUtil.isInSubDirectory(working, f)) {
if (message) player.printError("Schematic " + input + " does not exist! (" + ((f == null) ? false : f.exists()) + "|" + f + "|" + (f == null ? false : !MainUtil.isInSubDirectory(working, f)) + ")");
return null;
}
if (format == null && f.isFile()) {
format = ClipboardFormat.findByFile(f);
if (format == null) {
BBC.CLIPBOARD_INVALID_FORMAT.send(player, f.getName());
return null;
}
}
if (!f.exists()) {
if (message) BBC.SCHEMATIC_NOT_FOUND.send(player, input);
return null;
}
if (!f.isDirectory()) {
ByteSource source = Files.asByteSource(f);
URI uri = f.toURI();
return new MultiClipboardHolder(uri, new LazyClipboardHolder(f.toURI(), source, format, null));
}
URIClipboardHolder[] clipboards = loadAllFromDirectory(f);
if (clipboards.length < 1) {
if (message) BBC.SCHEMATIC_NOT_FOUND.send(player, input);
return null;
}
return new MultiClipboardHolder(f.toURI(), clipboards);
}
}
public static URIClipboardHolder[] loadAllFromDirectory(File dir) {
HashSet<String> extensions = new HashSet<>(Arrays.asList(ClipboardFormats.getFileExtensionArray()));
File[] files = dir.listFiles(pathname -> {
String input = pathname.getName();
String extension = input.substring(input.lastIndexOf('.') + 1, input.length());
return (extensions.contains(extension.toLowerCase()));
});
LazyClipboardHolder[] clipboards = new LazyClipboardHolder[files.length];
for (int i = 0; i < files.length; i++) {
File file = files[i];
ByteSource source = Files.asByteSource(file);
ClipboardFormat format = ClipboardFormat.findByFile(file);
clipboards[i] = new LazyClipboardHolder(file.toURI(), source, format, null);
}
return clipboards;
}
public static MultiClipboardHolder loadAllFromUrl(URL url) throws IOException {
List<LazyClipboardHolder> clipboards = new ArrayList<>();
try (ReadableByteChannel rbc = Channels.newChannel(url.openStream())) {
try (InputStream in = Channels.newInputStream(rbc)) {
try (ZipInputStream zip = new ZipInputStream(in)) {
ZipEntry entry;
byte[] buffer = new byte[8192];
while ((entry = zip.getNextEntry()) != null) {
String filename = entry.getName();
String extension = filename.substring(filename.lastIndexOf('.') + 1, filename.length());
ClipboardFormat format = findByExtension(filename);
if (format != null) {
FastByteArrayOutputStream out = new FastByteArrayOutputStream();
int len = 0;
while ((len = zip.read(buffer)) > 0) {
out.write(buffer, 0, len);
}
byte[] array = out.toByteArray();
ByteSource source = ByteSource.wrap(array);
LazyClipboardHolder clipboard = new LazyClipboardHolder(url.toURI(), source, format, null);
clipboards.add(clipboard);
}
}
} catch (URISyntaxException e) {
e.printStackTrace();
}
}
}
LazyClipboardHolder[] arr = clipboards.toArray(new LazyClipboardHolder[clipboards.size()]);
try {
MultiClipboardHolder multi = new MultiClipboardHolder(url.toURI());
for (LazyClipboardHolder h : arr) multi.add(h);
return multi;
} catch (URISyntaxException e) {
throw new RuntimeException(e);
}
}
private void write(OutputStream value, Clipboard clipboard) {
default void write(OutputStream value, Clipboard clipboard) {
try {
try (PGZIPOutputStream gzip = new PGZIPOutputStream(value)) {
try (ClipboardWriter writer = format.getWriter(gzip)) {
try (ClipboardWriter writer = getWriter(gzip)) {
writer.write(clipboard);
}
}
@ -477,164 +179,4 @@ public enum ClipboardFormat {
e.printStackTrace();
}
}
public URL uploadAnonymous(final Clipboard clipboard) {
return MainUtil.upload(null, null, format.getExtension(), new RunnableVal<OutputStream>() {
@Override
public void run(OutputStream value) {
write(value, clipboard);
}
});
}
public IClipboardFormat getFormat() {
return format;
}
/**
* Get a set of aliases.
*
* @return a set of aliases
*/
public Set<String> getAliases() {
return format.getAliases();
}
/**
* Create a reader.
*
* @param inputStream the input stream
* @return a reader
* @throws IOException thrown on I/O error
*/
public ClipboardReader getReader(InputStream inputStream) throws IOException {
return format.getReader(inputStream);
}
/**
* Create a writer.
*
* @param outputStream the output stream
* @return a writer
* @throws IOException thrown on I/O error
*/
public ClipboardWriter getWriter(OutputStream outputStream) throws IOException {
return format.getWriter(outputStream);
}
/**
* Set the player's clipboard
* @param player
* @param uri
* @param in
* @return the held clipboard
* @throws IOException
*/
public ClipboardHolder hold(Player player, URI uri, InputStream in) throws IOException {
checkNotNull(player);
checkNotNull(uri);
checkNotNull(in);
final ClipboardReader reader = getReader(in);
final Clipboard clipboard;
LocalSession session = WorldEdit.getInstance().getSessionManager().get(player);
session.setClipboard(null);
clipboard = reader.read(player.getUniqueId());
URIClipboardHolder holder = new URIClipboardHolder(uri, clipboard);
session.setClipboard(holder);
return holder;
}
public Schematic load(File file) throws IOException {
return load(new FileInputStream(file));
}
public Schematic load(InputStream stream) throws IOException {
return new Schematic(this.getReader(stream).read());
}
/**
* Get the file extension used
*
* @return file extension string
*/
public String getExtension() {
return format.getExtension();
}
/**
* Return whether the given file is of this format.
*
* @param file the file
* @return true if the given file is of this format
*/
public boolean isFormat(File file) {
return format.isFormat(file);
}
/**
* Find the clipboard format named by the given alias.
*
* @param alias the alias
* @return the format, otherwise null if none is matched
*/
@Nullable
public static ClipboardFormat findByAlias(String alias) {
checkNotNull(alias);
return aliasMap.get(alias.toLowerCase(Locale.ENGLISH).trim());
}
@Nullable
public static ClipboardFormat findByExtension(String extension) {
checkNotNull(extension);
extension = extension.toLowerCase();
for (ClipboardFormat format : values) {
if (format.getFileExtensions().contains(extension)) {
return format;
}
}
return null;
}
/**
* Detect the format given a file.
*
* @param file the file
* @return the format, otherwise null if one cannot be detected
*/
@Nullable
public static ClipboardFormat findByFile(File file) {
checkNotNull(file);
for (ClipboardFormat format : EnumSet.allOf(ClipboardFormat.class)) {
if (format.isFormat(file)) {
return format;
}
}
return null;
}
public static ClipboardFormat addFormat(IClipboardFormat instance) {
ClipboardFormat newEnum = ReflectionUtils.addEnum(ClipboardFormat.class, instance.getName());
newEnum.format = instance;
for (String alias : newEnum.getAliases()) {
aliasMap.put(alias, newEnum);
}
ArrayList<ClipboardFormat> newValues = new ArrayList<>(Arrays.asList(values));
newValues.add(newEnum);
ClipboardFormat[] newValuesArray = newValues.toArray(new ClipboardFormat[newValues.size()]);
try {
ReflectionUtils.setFailsafeFieldValue(ClipboardFormat.class.getDeclaredField("values"), null, newValuesArray);
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return newEnum;
}
}

View File

@ -19,17 +19,77 @@
package com.sk89q.worldedit.extent.clipboard.io;
import static com.google.common.base.Preconditions.checkNotNull;
import com.boydti.fawe.config.BBC;
import com.boydti.fawe.config.Settings;
import com.boydti.fawe.object.clipboard.LazyClipboardHolder;
import com.boydti.fawe.object.clipboard.MultiClipboardHolder;
import com.boydti.fawe.object.clipboard.URIClipboardHolder;
import com.boydti.fawe.object.io.FastByteArrayOutputStream;
import com.boydti.fawe.util.MainUtil;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimap;
import com.google.common.collect.Multimaps;
import com.google.common.io.ByteSource;
import com.google.common.io.Files;
import com.sk89q.worldedit.LocalConfiguration;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.extension.platform.Actor;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.channels.Channels;
import java.nio.channels.ReadableByteChannel;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
import java.util.regex.Pattern;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import javax.annotation.Nullable;
import java.io.File;
import java.util.*;
import static com.google.common.base.Preconditions.checkNotNull;
public class ClipboardFormats {
private static final Map<String, ClipboardFormat> aliasMap = new HashMap<>();
private static final Multimap<String, ClipboardFormat> fileExtensionMap = HashMultimap.create();
private static final List<ClipboardFormat> registeredFormats = new ArrayList<>();
public static void registerClipboardFormat(ClipboardFormat format) {
checkNotNull(format);
for (String key : format.getAliases()) {
String lowKey = key.toLowerCase(Locale.ENGLISH);
ClipboardFormat old = aliasMap.put(lowKey, format);
if (old != null) {
aliasMap.put(lowKey, old);
WorldEdit.logger.warning(format.getClass().getName() + " cannot override existing alias '" + lowKey + "' used by " + old.getClass().getName());
}
}
for (String ext : format.getFileExtensions()) {
String lowExt = ext.toLowerCase(Locale.ENGLISH);
fileExtensionMap.put(lowExt, format);
}
registeredFormats.add(format);
}
static {
for (BuiltInClipboardFormat format : BuiltInClipboardFormat.values()) {
registerClipboardFormat(format);
}
}
/**
* Find the clipboard format named by the given alias.
*
@ -39,7 +99,8 @@ public class ClipboardFormats {
*/
@Nullable
public static ClipboardFormat findByAlias(String alias) {
return ClipboardFormat.findByAlias(alias);
checkNotNull(alias);
return aliasMap.get(alias.toLowerCase(Locale.ENGLISH).trim());
}
/**
@ -53,7 +114,7 @@ public class ClipboardFormats {
public static ClipboardFormat findByFile(File file) {
checkNotNull(file);
for (ClipboardFormat format : ClipboardFormat.values) {
for (ClipboardFormat format : registeredFormats) {
if (format.isFormat(file)) {
return format;
}
@ -61,22 +122,36 @@ public class ClipboardFormats {
return null;
}
/**
* Detect the format using the given extension
* @param string
* the extension
* @return the format, otherwise null if one cannot be detected
*/
@Nullable
public static ClipboardFormat findByExtension(String extension) {
checkNotNull(extension);
Collection<Entry<String, ClipboardFormat>> entries = getFileExtensionMap().entries();
for(Map.Entry<String, ClipboardFormat> entry : entries) {
if(entry.getKey().equalsIgnoreCase(extension)) {
return entry.getValue();
}
}
return null;
}
/**
* @return a multimap from a file extension to the potential matching formats.
*/
public static Multimap<String, ClipboardFormat> getFileExtensionMap() {
HashMultimap<String, ClipboardFormat> map = HashMultimap.create();
for (ClipboardFormat format : ClipboardFormat.values) {
for (String ext : format.getFileExtensions()) {
map.put(ext, format);
}
}
return map;
return Multimaps.unmodifiableMultimap(fileExtensionMap);
}
public static Collection<ClipboardFormat> getAll() {
return Arrays.asList(ClipboardFormat.values);
return Collections.unmodifiableCollection(registeredFormats);
}
/**
@ -84,13 +159,156 @@ public class ClipboardFormats {
* It is not in SchematicCommands because it may rely on internal register calls.
*/
public static String[] getFileExtensionArray() {
List<String> exts = new ArrayList<>();
HashMultimap<String, ClipboardFormat> map = HashMultimap.create();
for (ClipboardFormat format : ClipboardFormat.values) {
exts.addAll(format.getFileExtensions());
}
return exts.toArray(new String[exts.size()]);
return fileExtensionMap.keySet().toArray(new String[fileExtensionMap.keySet().size()]);
}
private ClipboardFormats() {}
private ClipboardFormats() {
}
public static MultiClipboardHolder loadAllFromInput(Actor player, String input, ClipboardFormat format, boolean message) throws IOException {
checkNotNull(player);
checkNotNull(input);
WorldEdit worldEdit = WorldEdit.getInstance();
LocalConfiguration config = worldEdit.getConfiguration();
if (input.startsWith("url:")) {
if (!player.hasPermission("worldedit.schematic.load.web")) {
if (message) BBC.NO_PERM.send(player, "worldedit.schematic.load.web");
return null;
}
URL base = new URL(Settings.IMP.WEB.URL);
input = new URL(base, "uploads/" + input.substring(4) + ".schematic").toString();
}
if (input.startsWith("http")) {
if (!player.hasPermission("worldedit.schematic.load.asset")) {
if (message) BBC.NO_PERM.send(player, "worldedit.schematic.load.asset");
return null;
}
URL url = new URL(input);
URL webInterface = new URL(Settings.IMP.WEB.ASSETS);
if (!url.getHost().equalsIgnoreCase(webInterface.getHost())) {
if (message) BBC.WEB_UNAUTHORIZED.send(player, url);
return null;
}
MultiClipboardHolder clipboards = loadAllFromUrl(url);
return clipboards;
} else {
if (Settings.IMP.PATHS.PER_PLAYER_SCHEMATICS && Pattern.compile("[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}").matcher(input).find() && !player.hasPermission("worldedit.schematic.load.other")) {
BBC.NO_PERM.send(player, "worldedit.schematic.load.other");
return null;
}
File working = worldEdit.getWorkingDirectoryFile(config.saveDir);
File dir = Settings.IMP.PATHS.PER_PLAYER_SCHEMATICS ? new File(working, player.getUniqueId().toString()) : working;
File f;
if (input.startsWith("#")) {
String[] extensions;
if (format != null) {
extensions = format.getFileExtensions().toArray(new String[0]);
} else {
extensions = ClipboardFormats.getFileExtensionArray();
}
f = player.openFileOpenDialog(extensions);
if (f == null || !f.exists()) {
if (message) player.printError("Schematic " + input + " does not exist! (" + f + ")");
return null;
}
} else {
if (Settings.IMP.PATHS.PER_PLAYER_SCHEMATICS && Pattern.compile("[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}").matcher(input).find() && !player.hasPermission("worldedit.schematic.load.other")) {
if (message) BBC.NO_PERM.send(player, "worldedit.schematic.load.other");
return null;
}
if (format == null && input.matches(".*\\.[\\w].*")) {
String extension = input.substring(input.lastIndexOf('.') + 1, input.length());
format = findByExtension(extension);
}
f = MainUtil.resolve(dir, input, format, true);
}
if (f == null || !f.exists()) {
if (!input.contains("../")) {
dir = worldEdit.getWorkingDirectoryFile(config.saveDir);
f = MainUtil.resolve(dir, input, format, true);
}
}
if (f == null || !f.exists() || !MainUtil.isInSubDirectory(working, f)) {
if (message) player.printError("Schematic " + input + " does not exist! (" + ((f == null) ? false : f.exists()) + "|" + f + "|" + (f == null ? false : !MainUtil.isInSubDirectory(working, f)) + ")");
return null;
}
if (format == null && f.isFile()) {
format = findByFile(f);
if (format == null) {
BBC.CLIPBOARD_INVALID_FORMAT.send(player, f.getName());
return null;
}
}
if (!f.exists()) {
if (message) BBC.SCHEMATIC_NOT_FOUND.send(player, input);
return null;
}
if (!f.isDirectory()) {
ByteSource source = Files.asByteSource(f);
URI uri = f.toURI();
return new MultiClipboardHolder(uri, new LazyClipboardHolder(f.toURI(), source, format, null));
}
URIClipboardHolder[] clipboards = loadAllFromDirectory(f);
if (clipboards.length < 1) {
if (message) BBC.SCHEMATIC_NOT_FOUND.send(player, input);
return null;
}
return new MultiClipboardHolder(f.toURI(), clipboards);
}
}
public static URIClipboardHolder[] loadAllFromDirectory(File dir) {
HashSet<String> extensions = new HashSet<>(Arrays.asList(ClipboardFormats.getFileExtensionArray()));
File[] files = dir.listFiles(pathname -> {
String input = pathname.getName();
String extension = input.substring(input.lastIndexOf('.') + 1, input.length());
return (extensions.contains(extension.toLowerCase()));
});
LazyClipboardHolder[] clipboards = new LazyClipboardHolder[files.length];
for (int i = 0; i < files.length; i++) {
File file = files[i];
ByteSource source = Files.asByteSource(file);
ClipboardFormat format = findByFile(file);
clipboards[i] = new LazyClipboardHolder(file.toURI(), source, format, null);
}
return clipboards;
}
public static MultiClipboardHolder loadAllFromUrl(URL url) throws IOException {
List<LazyClipboardHolder> clipboards = new ArrayList<>();
try (ReadableByteChannel rbc = Channels.newChannel(url.openStream())) {
try (InputStream in = Channels.newInputStream(rbc)) {
try (ZipInputStream zip = new ZipInputStream(in)) {
ZipEntry entry;
byte[] buffer = new byte[8192];
while ((entry = zip.getNextEntry()) != null) {
String filename = entry.getName();
String extension = filename.substring(filename.lastIndexOf('.') + 1, filename.length());
ClipboardFormat format = findByExtension(filename);
if (format != null) {
FastByteArrayOutputStream out = new FastByteArrayOutputStream();
int len = 0;
while ((len = zip.read(buffer)) > 0) {
out.write(buffer, 0, len);
}
byte[] array = out.toByteArray();
ByteSource source = ByteSource.wrap(array);
LazyClipboardHolder clipboard = new LazyClipboardHolder(url.toURI(), source, format, null);
clipboards.add(clipboard);
}
}
} catch (URISyntaxException e) {
e.printStackTrace();
}
}
}
LazyClipboardHolder[] arr = clipboards.toArray(new LazyClipboardHolder[clipboards.size()]);
try {
MultiClipboardHolder multi = new MultiClipboardHolder(url.toURI());
for (LazyClipboardHolder h : arr) multi.add(h);
return multi;
} catch (URISyntaxException e) {
throw new RuntimeException(e);
}
}
}

View File

@ -1,335 +1,330 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.extent.transform;
import static com.google.common.base.Preconditions.checkNotNull;
import com.boydti.fawe.object.extent.ResettableExtent;
import com.boydti.fawe.util.ReflectionUtils;
import com.google.common.collect.Sets;
import com.sk89q.jnbt.ByteTag;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.jnbt.Tag;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.internal.helper.MCDirections;
import com.sk89q.worldedit.math.transform.AffineTransform;
import com.sk89q.worldedit.math.transform.Transform;
import com.sk89q.worldedit.registry.state.AbstractProperty;
import static com.google.common.base.Preconditions.checkNotNull;
import com.google.common.collect.Sets;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.world.block.BaseBlock;
import com.sk89q.worldedit.extent.AbstractDelegateExtent;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.math.BlockVector2;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.math.Vector3;
import com.sk89q.worldedit.math.transform.AffineTransform;
import com.sk89q.worldedit.math.transform.Transform;
import com.sk89q.worldedit.registry.state.BooleanProperty;
import com.sk89q.worldedit.registry.state.DirectionalProperty;
import com.sk89q.worldedit.registry.state.EnumProperty;
import com.sk89q.worldedit.registry.state.IntegerProperty;
import com.sk89q.worldedit.registry.state.Property;
import com.sk89q.worldedit.util.Direction;
import com.sk89q.worldedit.world.biome.BaseBiome;
import com.sk89q.worldedit.world.block.BaseBlock;
import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.block.BlockStateHolder;
import com.sk89q.worldedit.world.block.BlockTypes;
import javax.annotation.Nullable;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.OptionalInt;
import java.util.Set;
import java.util.stream.Collectors;
import javax.annotation.Nullable;
/**
* Transforms blocks themselves (but not their position) according to a
* given transform.
*/
public class BlockTransformExtent extends ResettableExtent {
private Transform transform;
private Transform transformInverse;
private int[] BLOCK_ROTATION_BITMASK;
private int[][] BLOCK_TRANSFORM;
private int[][] BLOCK_TRANSFORM_INVERSE;
private int[] ALL = new int[0];
private Transform transform;
public BlockTransformExtent(Extent parent) {
this(parent, new AffineTransform());
}
public BlockTransformExtent(Extent parent, Transform transform) {
super(parent);
/**
* Create a new instance.
*
* @param extent the extent
*/
public BlockTransformExtent(Extent extent, Transform transform) {
super(extent);
checkNotNull(transform);
this.transform = transform;
this.transformInverse = this.transform.inverse();
cache();
}
private List<Direction> getDirections(AbstractProperty property) {
if (property instanceof DirectionalProperty) {
DirectionalProperty directional = (DirectionalProperty) property;
directional.getValues();
} else {
switch (property.getKey()) {
case HALF:
case ROTATION:
case AXIS:
case FACING:
case SHAPE:
case NORTH:
case EAST:
case SOUTH:
case WEST:
}
}
return null;
/**
* Get the transform.
*
* @return the transform
*/
public Transform getTransform() {
return transform;
}
/**
* Set the transform
* @param affine
*/
public void setTransform(Transform affine) {
this.transform = affine;
}
// @Override
// public BlockState getBlock(BlockVector3 position) {
// return transformBlock(super.getBlock(position), false);
// }
//
// @Override
// public BaseBlock getFullBlock(BlockVector3 position) {
// return transformBlock(super.getFullBlock(position), false);
// }
// @Override
// public boolean setBlock(BlockVector3 location, BlockStateHolder block) throws WorldEditException {
// return super.setBlock(location, transformBlock(block, true));
// }
// /**
// * Transform the given block using the given transform.
// *
// * <p>The provided block is modified.</p>
// *
// * @param block the block
// * @param transform the transform
// * @return the same block
// */
// public static <T extends BlockStateHolder> T transform(T block, Transform transform) {
// return transform(block, transform, block);
// }
/**
* Transform a block without making a copy.
*
* @param block the block
* @param reverse true to transform in the opposite direction
* @return the same block
*/
private <T extends BlockStateHolder<T>> T transformBlock(T block, boolean reverse) {
return transform(block, reverse ? transform.inverse() : transform);
}
@Override
public BlockState getLazyBlock(BlockVector3 position) {
return transformFast(super.getLazyBlock(position)).toImmutableState();
}
@Override
public BlockState getLazyBlock(int x, int y, int z) {
return transformFast(super.getLazyBlock(x, y, z)).toImmutableState();
}
@Override
public BlockState getBlock(BlockVector3 position) {
return transformFast(super.getBlock(position)).toImmutableState();
}
@Override
public BaseBlock getFullBlock(BlockVector3 position) {
return transformFast(super.getFullBlock(position).toImmutableState());
}
@Override
public <B extends BlockStateHolder<B>> boolean setBlock(int x, int y, int z, B block) throws WorldEditException {
return super.setBlock(x, y, z, transformFastInverse((BlockState)block));
}
@Override
public <B extends BlockStateHolder<B>> boolean setBlock(BlockVector3 location, B block) throws WorldEditException {
return super.setBlock(location, transformFastInverse((BlockState)block));
}
private static final Set<String> directionNames = Sets.newHashSet("north", "south", "east", "west");
// /**
// * Transform the given block using the given transform.
// *
// * @param block the block
// * @param transform the transform
// * @param changedBlock the block to change
// * @return the changed block
// */
// private static <T extends BlockStateHolder> T transform(T block, Transform transform, T changedBlock) {
// checkNotNull(block);
// checkNotNull(transform);
//
// List<? extends Property> properties = block.getBlockType().getProperties();
//
// for (Property property : properties) {
// if (property instanceof DirectionalProperty) {
// Direction value = (Direction) block.getState(property);
// if (value != null) {
// Vector3 newValue = getNewStateValue((DirectionalProperty) property, transform, value.toVector());
// if (newValue != null) {
// changedBlock = (T) changedBlock.with(property, Direction.findClosest(newValue, Direction.Flag.ALL));
// }
// }
// }
// }
/**
* Transform the given block using the given transform.
*
* <p>The provided block is <em>not</em> modified.</p>
*
* @param block the block
* @param transform the transform
* @return the same block
*/
public static <B extends BlockStateHolder<B>> B transform(B block, Transform transform) {
checkNotNull(block);
checkNotNull(transform);
B result = block;
List<? extends Property<?>> properties = block.getBlockType().getProperties();
for (Property<?> property : properties) {
if (property instanceof DirectionalProperty) {
DirectionalProperty dirProp = (DirectionalProperty) property;
Direction value = (Direction) block.getState(property);
if (value != null) {
Vector3 newValue = getNewStateValue(dirProp.getValues(), transform, value.toVector());
if (newValue != null) {
result = result.with(dirProp, Direction.findClosest(newValue, Direction.Flag.ALL));
}
}
} else if (property instanceof EnumProperty) {
EnumProperty enumProp = (EnumProperty) property;
if (property.getName().equals("axis")) {
// We have an axis - this is something we can do the rotations to :sunglasses:
Direction value = null;
switch ((String) block.getState(property)) {
case "x":
value = Direction.EAST;
break;
case "y":
value = Direction.UP;
break;
case "z":
value = Direction.NORTH;
break;
}
if (value != null) {
Vector3 newValue = getNewStateValue(Direction.valuesOf(Direction.Flag.UPRIGHT | Direction.Flag.CARDINAL), transform, value.toVector());
if (newValue != null) {
String axis = null;
Direction newDir = Direction.findClosest(newValue, Direction.Flag.UPRIGHT | Direction.Flag.CARDINAL);
if (newDir == Direction.NORTH || newDir == Direction.SOUTH) {
axis = "z";
} else if (newDir == Direction.EAST || newDir == Direction.WEST) {
axis = "x";
} else if (newDir == Direction.UP || newDir == Direction.DOWN) {
axis = "y";
}
if (axis != null) {
result = result.with(enumProp, axis);
}
}
}
}
} else if (property instanceof IntegerProperty) {
IntegerProperty intProp = (IntegerProperty) property;
if (property.getName().equals("rotation")) {
if (intProp.getValues().size() == 16) {
Optional<Direction> direction = Direction.fromRotationIndex(block.getState(intProp));
int horizontalFlags = Direction.Flag.CARDINAL | Direction.Flag.ORDINAL | Direction.Flag.SECONDARY_ORDINAL;
if (direction.isPresent()) {
Vector3 vec = getNewStateValue(Direction.valuesOf(horizontalFlags), transform, direction.get().toVector());
if (vec != null) {
OptionalInt newRotation = Direction.findClosest(vec, horizontalFlags).toRotationIndex();
if (newRotation.isPresent()) {
result = result.with(intProp, newRotation.getAsInt());
}
}
}
}
}
}
}
List<String> directionalProperties = properties.stream()
.filter(prop -> prop instanceof BooleanProperty)
.filter(prop -> directionNames.contains(prop.getName()))
.filter(property -> (Boolean) block.getState(property))
.map(Property::getName)
.map(String::toUpperCase)
.map(Direction::valueOf)
.map(dir -> Direction.findClosest(transform.apply(dir.toVector()), Direction.Flag.CARDINAL))
.filter(Objects::nonNull)
.map(Direction::name)
.map(String::toLowerCase)
.collect(Collectors.toList());
if (directionalProperties.size() > 0) {
for (String directionName : directionNames) {
result = result.with(block.getBlockType().getProperty(directionName), directionalProperties.contains(directionName));
}
}
return result;
}
public final BaseBlock transformFast(BlockState block) {
BaseBlock transformed = transformBlock(block, false).toBaseBlock();
if (block.hasNbtData()) {
CompoundTag tag = block.getNbtData();
if (tag.containsKey("Rot")) {
int rot = tag.asInt("Rot");
Direction direction = Direction.fromRotationIndex(rot).get();
if (direction != null) {
Vector3 applyAbsolute = transform.apply(direction.toVector());
Vector3 applyOrigin = transform.apply(Vector3.ZERO);
Vector3 newAbsolute = Vector3.at(applyAbsolute.getX() - applyOrigin.getX(), applyAbsolute.getY() - applyOrigin.getY(), applyAbsolute.getZ() - applyOrigin.getZ());
Direction newDirection = Direction.findClosest(newAbsolute, Direction.Flag.CARDINAL | Direction.Flag.ORDINAL | Direction.Flag.SECONDARY_ORDINAL);
if (newDirection != null) {
Map<String, Tag> values = ReflectionUtils.getMap(tag.getValue());
values.put("Rot", new ByteTag((byte) newDirection.toRotationIndex().getAsInt()));
}
}
transformed.setNbtData(tag);
}
}
return transformed;
}
public final BaseBlock transformFastInverse(BlockState block) {
BaseBlock transformed = transformBlock(block, true).toBaseBlock();
if (block.hasNbtData()) {
CompoundTag tag = block.getNbtData();
if (tag.containsKey("Rot")) {
int rot = tag.asInt("Rot");
Direction direction = Direction.fromRotationIndex(rot).get();
if (direction != null) {
Vector3 applyAbsolute = getTransform().inverse().apply(direction.toVector());
Vector3 applyOrigin = getTransform().inverse().apply(Vector3.ZERO);
Vector3 newAbsolute = Vector3.at(applyAbsolute.getX() - applyOrigin.getX(), applyAbsolute.getY() - applyOrigin.getY(), applyAbsolute.getZ() - applyOrigin.getZ());
Direction newDirection = Direction.findClosest(newAbsolute, Direction.Flag.CARDINAL | Direction.Flag.ORDINAL | Direction.Flag.SECONDARY_ORDINAL);
if (newDirection != null) {
Map<String, Tag> values = ReflectionUtils.getMap(tag.getValue());
values.put("Rot", new ByteTag((byte) newDirection.toRotationIndex().getAsInt()));
}
}
}
transformed.setNbtData(tag);
}
return transformed;
}
/**
* Get the new value with the transformed direction.
*
* @param allowedStates the allowed states
* @param transform the transform
* @param oldDirection the old direction to transform
* @return a new state or null if none could be found
*/
@Nullable
//<<<<<<< HEAD
private static Integer getNewStateIndex(Transform transform, List<Direction> directions, int oldIndex) {
Direction oldDirection = directions.get(oldIndex);
Vector3 oldVector = oldDirection.toVector();
Vector3 newVector = transform.apply(oldVector).subtract(transform.apply(Vector3.ZERO)).normalize();
int newIndex = oldIndex;
double closest = oldVector.normalize().dot(newVector);
//=======
// private static Vector3 getNewStateValue(DirectionalProperty state, Transform transform, Vector3 oldDirection) {
// Vector3 newDirection = transform.apply(oldDirection).subtract(transform.apply(Vector3.ZERO)).normalize();
// Vector3 newValue = null;
// double closest = -2;
//>>>>>>> 399e0ad5... Refactor vector system to be cleaner
private static Vector3 getNewStateValue(List<Direction> allowedStates, Transform transform, Vector3 oldDirection) {
Vector3 newDirection = transform.apply(oldDirection).subtract(transform.apply(Vector3.ZERO)).normalize();
Vector3 newValue = null;
double closest = -2;
boolean found = false;
for (int i = 0; i < directions.size(); i++) {
Direction v = directions.get(i);
double dot = v.toVector().normalize().dot(newVector);
if (dot > closest) {
for (Direction v : allowedStates) {
double dot = v.toVector().normalize().dot(newDirection);
if (dot >= closest) {
closest = dot;
newIndex = i;
newValue = v.toVector();
found = true;
}
}
if (found) {
return newIndex;
return newValue;
} else {
return null;
}
}
private void cache() {
BLOCK_ROTATION_BITMASK = new int[BlockTypes.size()];
BLOCK_TRANSFORM = new int[BlockTypes.size()][];
BLOCK_TRANSFORM_INVERSE = new int[BlockTypes.size()][];
outer:
for (int i = 0; i < BLOCK_TRANSFORM.length; i++) {
BLOCK_TRANSFORM[i] = ALL;
BLOCK_TRANSFORM_INVERSE[i] = ALL;
BlockTypes type = BlockTypes.get(i);
int bitMask = 0;
for (AbstractProperty property : (Collection<AbstractProperty>) type.getProperties()) {
Collection<Direction> directions = getDirections(property);
if (directions != null) {
BLOCK_TRANSFORM[i] = null;
BLOCK_TRANSFORM_INVERSE[i] = null;
bitMask |= property.getBitMask();
}
}
if (bitMask != 0) {
BLOCK_ROTATION_BITMASK[i] = bitMask;
}
}
}
@Override
public ResettableExtent setExtent(Extent extent) {
return super.setExtent(extent);
}
public Transform getTransform() {
return transform;
}
public void setTransform(Transform affine) {
this.transform = affine;
this.transformInverse = this.transform.inverse();
cache();
}
private final BlockState transform(BlockState state, int[][] transformArray, Transform transform) {
int typeId = state.getInternalBlockTypeId();
int[] arr = transformArray[typeId];
if (arr == ALL) return state;
if (arr == null) {
arr = transformArray[typeId] = new int[state.getBlockType().getMaxStateId() + 1];
Arrays.fill(arr, -1);
}
int mask = BLOCK_ROTATION_BITMASK[typeId];
int internalId = state.getInternalId();
int maskedId = internalId & mask;
int newMaskedId = arr[maskedId];
if (newMaskedId != -1) {
return BlockState.getFromInternalId(newMaskedId | (internalId & (~mask)));
}
newMaskedId = state.getInternalId();
BlockTypes type = state.getBlockType();
for (AbstractProperty property : (Collection<AbstractProperty>) type.getProperties()) {
List<Direction> directions = getDirections(property);
if (directions != null) {
Integer newIndex = getNewStateIndex(transform, directions, property.getIndex(state.getInternalId()));
if (newIndex != null) {
newMaskedId = property.modifyIndex(newMaskedId, newIndex);
}
}
}
arr[maskedId] = newMaskedId & mask;
return BlockState.getFromInternalId(newMaskedId);
}
public final BlockState transformFast(BlockState block) {
BlockState transformed = transform(block, BLOCK_TRANSFORM, transform);
if (block.hasNbtData()) {
CompoundTag tag = block.getNbtData();
if (tag.containsKey("Rot")) {
int rot = tag.asInt("Rot");
Direction direction = MCDirections.fromRotation(rot);
if (direction != null) {
Vector3 applyAbsolute = transform.apply(direction.toVector());
Vector3 applyOrigin = transform.apply(Vector3.ZERO);
Direction newDirection = Direction.findClosest(applyAbsolute.subtract(applyOrigin), Direction.Flag.CARDINAL | Direction.Flag.ORDINAL | Direction.Flag.SECONDARY_ORDINAL);
if (newDirection != null) {
Map<String, Tag> values = ReflectionUtils.getMap(tag.getValue());
values.put("Rot", new ByteTag((byte) MCDirections.toRotation(newDirection)));
}
}
transformed = new BaseBlock(transformed, tag);
}
}
return transformed;
}
public final BlockState transformFastInverse(BlockState block) {
BlockState transformed = transform(block, BLOCK_TRANSFORM_INVERSE, transformInverse);
if (block.hasNbtData()) {
CompoundTag tag = block.getNbtData();
if (tag.containsKey("Rot")) {
int rot = tag.asInt("Rot");
Direction direction = MCDirections.fromRotation(rot);
if (direction != null) {
Vector3 applyAbsolute = transformInverse.apply(direction.toVector());
Vector3 applyOrigin = transformInverse.apply(Vector3.ZERO);
Direction newDirection = Direction.findClosest(applyAbsolute.subtract(applyOrigin), Direction.Flag.CARDINAL | Direction.Flag.ORDINAL | Direction.Flag.SECONDARY_ORDINAL);
if (newDirection != null) {
Map<String, Tag> values = ReflectionUtils.getMap(tag.getValue());
values.put("Rot", new ByteTag((byte) MCDirections.toRotation(newDirection)));
}
}
}
transformed = new BaseBlock(transformed, tag);
}
return transformed;
}
@Override
public BlockState getLazyBlock(int x, int y, int z) {
return transformFast(super.getLazyBlock(x, y, z));
}
@Override
public BlockState getLazyBlock(BlockVector3 position) {
return transformFast(super.getLazyBlock(position));
}
@Override
public BlockState getBlock(BlockVector3 position) {
return transformFast(super.getBlock(position));
}
@Override
public BaseBiome getBiome(BlockVector2 position) {
return super.getBiome(position);
}
@Override
public boolean setBlock(int x, int y, int z, BlockStateHolder block) throws WorldEditException {
return super.setBlock(x, y, z, transformFastInverse((BlockState) block));
}
@Override
public boolean setBlock(BlockVector3 location, BlockStateHolder block) throws WorldEditException {
return super.setBlock(location, transformFastInverse((BlockState) block));
}
}

View File

@ -62,7 +62,7 @@ public class BlockMask extends AbstractExtentMask {
for (int i = 0; i < bitSets.length; i++) {
if (bitSets[i] != null) {
long[] set = bitSets[i];
BlockTypes type = BlockTypes.get(i);
BlockType type = BlockTypes.get(i);
if (set == ALL) {
strings.add(type.getId());
} else {
@ -137,7 +137,7 @@ public class BlockMask extends AbstractExtentMask {
boolean single = true;
int and = type.getInternalId();
List<? extends Property> properties = type.getProperties();
for (AbstractProperty prop : (List<AbstractProperty>) type.getProperties()) {
for (AbstractProperty prop : (List<AbstractProperty<?>>) type.getProperties()) {
List values = prop.getValues();
int numSet = 0;
for (int i = 0; i < values.size(); i++) {

View File

@ -90,15 +90,15 @@ public class BlockMaskBuilder {
charSequence.setString(input);
charSequence.setSubstring(0, propStart);
BlockTypes type = null;
List<BlockTypes> blockTypeList = null;
BlockType type = null;
List<BlockType> blockTypeList = null;
if (StringMan.isAlphanumericUnd(charSequence)) {
type = BlockTypes.parse(charSequence.toString());
add(type);
} else {
String regex = charSequence.toString();
blockTypeList = new ArrayList<>();
for (BlockTypes myType : BlockTypes.values) {
for (BlockType myType : BlockTypes.values) {
if (myType.getId().matches(regex)) {
blockTypeList.add(myType);
add(myType);
@ -135,14 +135,14 @@ public class BlockMaskBuilder {
filtered = filterRegexOrOperator(type, key, operator, charSequence);
}
else {
for (BlockTypes myType : blockTypeList) {
for (BlockType myType : blockTypeList) {
filtered |= filterRegexOrOperator(myType, key, operator, charSequence);
}
}
if (!filtered) {
String value = charSequence.toString();
final PropertyKey fKey = key;
Collection<BlockTypes> types = type != null ? Collections.singleton(type) : blockTypeList;
Collection<BlockType> types = type != null ? Collections.singleton(type) : blockTypeList;
throw new SuggestInputParseException("No value for " + input, input, () -> {
HashSet<String> values = new HashSet<>();
types.forEach(t -> {
@ -206,7 +206,7 @@ public class BlockMaskBuilder {
if (StringMan.isAlphanumericUnd(input)) {
add(BlockTypes.parse(input));
} else {
for (BlockTypes myType : BlockTypes.values) {
for (BlockType myType : BlockTypes.values) {
if (myType.getId().matches(input)) {
add(myType);
}
@ -225,7 +225,7 @@ public class BlockMaskBuilder {
return (states == BlockMask.ALL || FastBitSet.get(states, localI));
}
private void suggest(String input, String property, Collection<BlockTypes> finalTypes) throws InputParseException {
private void suggest(String input, String property, Collection<BlockType> finalTypes) throws InputParseException {
throw new SuggestInputParseException(input + " does not have: " + property, input, () -> {
Set<PropertyKey> keys = new HashSet<>();
finalTypes.forEach(t -> t.getProperties().stream().forEach(p -> keys.add(p.getKey())));
@ -346,7 +346,7 @@ public class BlockMaskBuilder {
bitSets[i] = null;
continue;
}
List<AbstractProperty> properties = (List<AbstractProperty>) type.getProperties();
List<AbstractProperty<?>> properties = (List<AbstractProperty<?>>) type.getProperties();
for (AbstractProperty prop : properties) {
List values = prop.getValues();
for (int j = 0; j < values.size(); j++) {
@ -425,7 +425,7 @@ public class BlockMaskBuilder {
if (!typePredicate.test(type)) {
continue;
}
for (AbstractProperty prop : (List<AbstractProperty>) type.getProperties()) {
for (AbstractProperty prop : (List<AbstractProperty<?>>) type.getProperties()) {
List values = prop.getValues();
for (int j = 0; j < values.size(); j++) {
int localI = j << prop.getBitOffset() >> BlockTypes.BIT_OFFSET;
@ -533,7 +533,7 @@ public class BlockMaskBuilder {
}
int set = 0;
int clear = 0;
for (AbstractProperty prop : (List<AbstractProperty>) type.getProperties()) {
for (AbstractProperty prop : (List<AbstractProperty<?>>) type.getProperties()) {
List values = prop.getValues();
for (int j = 0; j < values.size(); j++) {
int localI = j << prop.getBitOffset() >> BlockTypes.BIT_OFFSET;

View File

@ -4,7 +4,7 @@ package com.sk89q.worldedit.function.mask;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.blocks.BlockType;
import com.sk89q.worldedit.world.block.BlockType;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.world.block.BlockTypes;
@ -14,7 +14,7 @@ public class SolidBlockMask extends BlockTypeMask {
public static boolean[] getTypes() {
boolean[] types = new boolean[BlockTypes.size()];
for (BlockTypes type : BlockTypes.values) {
for (BlockType type : BlockTypes.values) {
types[type.getInternalId()] = type.getMaterial().isSolid();
}
return types;

View File

@ -90,13 +90,8 @@ public class ForwardExtentCopy implements Operation {
* @param source the source extent
* @param region the region to copy
* @param destination the destination extent
<<<<<<< HEAD
* @param to the destination position
* @see #ForwardExtentCopy(Extent, Region, Vector, Extent, Vector) the main constructor
=======
* @param to the destination position
* @see #ForwardExtentCopy(Extent, Region, BlockVector3, Extent, BlockVector3) the main constructor
>>>>>>> 399e0ad5... Refactor vector system to be cleaner
*/
public ForwardExtentCopy(Extent source, Region region, Extent destination, BlockVector3 to) {
this(source, region, region.getMinimumPoint(), destination, to);

View File

@ -131,6 +131,7 @@ public class PasteBuilder {
if (ignoreAirBlocks) {
copy.setSourceMask(new ExistingBlockMask(clipboard));
}
System.out.println("PasteBuilder info: extent: " + extent.toString() + "; copy: " + copy + "; transform: " + transform);
return copy;
}

View File

@ -22,8 +22,13 @@ package com.sk89q.worldedit.util;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.math.Vector3;
import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Optional;
import java.util.OptionalInt;
import javax.annotation.Nullable;
/**
* A collection of cardinal, ordinal, and secondary-ordinal directions.
@ -55,12 +60,9 @@ public enum Direction {
private final Vector3 direction;
private final BlockVector3 blockVector;
private final int flags, left, right;
private static HashMap<String, Direction> map = new HashMap<>();
public static final Direction[] values = values();
public static final Direction[] cardinal = new Direction[]{ NORTH, EAST, SOUTH, WEST };
static {
for (Direction dir : Direction.values()) {
map.put(dir.name(), dir);
@ -68,24 +70,24 @@ public enum Direction {
}
}
private Direction(Vector3 vector, int flags, int left, int right) {
Direction(Vector3 vector, int flags, int left, int right) {
this.direction = vector.normalize();
this.blockVector = BlockVector3.at(Math.signum(vector.getX()), Math.signum(vector.getY()), Math.signum(vector.getZ()));
this.flags = flags;
this.left = left;
this.right = right;
}
public static Direction get(CharSequence sequence) {
return map.get(sequence);
}
public Direction getLeft() {
return left != -1 ? values[left] : null;
return left != -1 ? values()[left] : null;
}
public Direction getRight() {
return right != -1 ? values[right] : null;
return right != -1 ? values()[right] : null;
}
public double getX() {
@ -163,11 +165,6 @@ public enum Direction {
return direction;
}
@Override
public String toString() {
return name().toLowerCase();
}
/**
* Get the vector.
*
@ -208,6 +205,110 @@ public enum Direction {
return closest;
}
/**
* Gets all directions with the given flags.
*
* @param flags The flags
* @return The directions that fit the flags
*/
public static List<Direction> valuesOf(int flags) {
List<Direction> directions = new ArrayList<>();
for (Direction direction : values()) {
if ((~flags & direction.flags) == 0) {
directions.add(direction);
}
}
return directions;
}
/**
* Converts a rotation index into a Direction.
*
* <p>
* Rotation indexes are used in BlockStates, such as sign posts.
* </p>
*
* @param rotation The rotation index
* @return The direction, if applicable
*/
public static Optional<Direction> fromRotationIndex(int rotation) {
switch (rotation) {
case 0:
return Optional.of(SOUTH);
case 1:
return Optional.of(SOUTH_SOUTHWEST);
case 2:
return Optional.of(SOUTHWEST);
case 3:
return Optional.of(WEST_SOUTHWEST);
case 4:
return Optional.of(WEST);
case 5:
return Optional.of(WEST_NORTHWEST);
case 6:
return Optional.of(NORTHWEST);
case 7:
return Optional.of(NORTH_NORTHWEST);
case 8:
return Optional.of(NORTH);
case 9:
return Optional.of(NORTH_NORTHEAST);
case 10:
return Optional.of(NORTHEAST);
case 11:
return Optional.of(EAST_NORTHEAST);
case 12:
return Optional.of(EAST);
case 13:
return Optional.of(EAST_SOUTHEAST);
case 14:
return Optional.of(SOUTHEAST);
case 15:
return Optional.of(SOUTH_SOUTHEAST);
}
return Optional.empty();
}
public OptionalInt toRotationIndex() {
switch (this) {
case SOUTH:
return OptionalInt.of(0);
case SOUTH_SOUTHWEST:
return OptionalInt.of(1);
case SOUTHWEST:
return OptionalInt.of(2);
case WEST_SOUTHWEST:
return OptionalInt.of(3);
case WEST:
return OptionalInt.of(4);
case WEST_NORTHWEST:
return OptionalInt.of(5);
case NORTHWEST:
return OptionalInt.of(6);
case NORTH_NORTHWEST:
return OptionalInt.of(7);
case NORTH:
return OptionalInt.of(8);
case NORTH_NORTHEAST:
return OptionalInt.of(9);
case NORTHEAST:
return OptionalInt.of(10);
case EAST_NORTHEAST:
return OptionalInt.of(11);
case EAST:
return OptionalInt.of(12);
case EAST_SOUTHEAST:
return OptionalInt.of(13);
case SOUTHEAST:
return OptionalInt.of(14);
case SOUTH_SOUTHEAST:
return OptionalInt.of(15);
}
return OptionalInt.empty();
}
/**
* Flags to use with {@link #findClosest(Vector3, int)}.
*/
@ -224,4 +325,3 @@ public enum Direction {
}
}

View File

@ -100,14 +100,20 @@ public class PropertiesConfiguration extends LocalConfiguration {
logFile = getString("log-file", logFile);
logFormat = getString("log-format", logFormat);
registerHelp = getBool("register-help", registerHelp);
wandItem = ItemTypes.parse(getString("wand-item", wandItem.getId()));
wandItem = getString("wand-item", wandItem);
try {
wandItem = LegacyMapper.getInstance().getItemFromLegacy(Integer.parseInt(wandItem)).getId();
} catch (Throwable e) {}
superPickaxeDrop = getBool("super-pickaxe-drop-items", superPickaxeDrop);
superPickaxeManyDrop = getBool("super-pickaxe-many-drop-items", superPickaxeManyDrop);
noDoubleSlash = getBool("no-double-slash", noDoubleSlash);
useInventory = getBool("use-inventory", useInventory);
useInventoryOverride = getBool("use-inventory-override", useInventoryOverride);
useInventoryCreativeOverride = getBool("use-inventory-creative-override", useInventoryCreativeOverride);
navigationWand = ItemTypes.parse(getString("navigation-wand.item", navigationWand.getId()));
navigationWand = getString("nav-wand-item", navigationWand);
try {
navigationWand = LegacyMapper.getInstance().getItemFromLegacy(Integer.parseInt(navigationWand)).getId();
} catch (Throwable e) {}
navigationWandMaxDistance = getInt("nav-wand-distance", navigationWandMaxDistance);
navigationUseGlass = getBool("nav-use-glass", navigationUseGlass);
scriptTimeout = getInt("scripting-timeout", scriptTimeout);

View File

@ -57,7 +57,7 @@ public class YAMLConfiguration extends LocalConfiguration {
}
profile = config.getBoolean("debug", profile);
wandItem = ItemTypes.parse(config.getString("wand-item", wandItem.getId()));
wandItem = ItemTypes.parse(config.getString("wand-item", wandItem)).getId();
defaultChangeLimit = Math.max(-1, config.getInt(
"limits.max-blocks-changed.default", defaultChangeLimit));
@ -105,7 +105,7 @@ public class YAMLConfiguration extends LocalConfiguration {
useInventoryCreativeOverride = config.getBoolean("use-inventory.creative-mode-overrides",
useInventoryCreativeOverride);
navigationWand = ItemTypes.parse(config.getString("navigation-wand.item", navigationWand.getId()));
navigationWand = ItemTypes.parse(config.getString("navigation-wand.item", navigationWand)).getId();
navigationWandMaxDistance = config.getInt("navigation-wand.max-distance", navigationWandMaxDistance);
navigationUseGlass = config.getBoolean("navigation.use-glass", navigationUseGlass);

View File

@ -93,7 +93,7 @@ public abstract class AbstractWorld implements World {
@Override
public BlockState getLazyBlock(BlockVector3 position) {
return new BaseBlock(getBlock(position));
return new BaseBlock(getBlock(position)).toImmutableState();
}
@Override

View File

@ -59,8 +59,8 @@ public interface SimpleWorld extends World {
}
@Override
default BlockState getFullBlock(BlockVector3 position) {
return getLazyBlock(position);
default BaseBlock getFullBlock(BlockVector3 position) {
return getLazyBlock(position).toBaseBlock();
}
@Override

View File

@ -34,9 +34,15 @@ import com.sk89q.worldedit.world.registry.BlockMaterial;
import com.sk89q.worldedit.world.registry.LegacyMapper;
import com.sk89q.worldedit.blocks.TileEntityBlock;
import com.sk89q.worldedit.function.mask.Mask;
import com.sk89q.worldedit.function.mask.SingleBlockStateMask;
import com.sk89q.worldedit.function.mask.SingleBlockTypeMask;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.registry.state.Property;
import com.sk89q.worldedit.registry.state.PropertyKey;
import javax.annotation.Nullable;
import java.util.Map;
import java.util.Objects;
/**
@ -48,7 +54,7 @@ import java.util.Objects;
* snapshot of blocks correctly, so, for example, the NBT data for a block
* may be missing.</p>
*/
public class BaseBlock extends BlockState {
public class BaseBlock implements BlockStateHolder<BaseBlock>, TileEntityBlock {
private final BlockState blockState;
@Nullable
@ -69,11 +75,6 @@ public class BaseBlock extends BlockState {
// this(blockState, blockState.getNbtData());
// }
@Deprecated
public BaseBlock(BlockTypes id) {
this(id.getDefaultState());
}
/**
* Construct a block with the given type and default data.
* @deprecated Just use the BlockType.getDefaultState()
@ -101,7 +102,6 @@ public class BaseBlock extends BlockState {
* @param nbtData NBT data, which must be provided
*/
public BaseBlock(BlockState state, CompoundTag nbtData) {
// super(state.getBlockType());
checkNotNull(nbtData);
this.blockState = state;
this.nbtData = nbtData;
@ -145,11 +145,6 @@ public class BaseBlock extends BlockState {
this(other.toImmutableState(), other.getNbtData());
}
@Override
public BlockState toFuzzy() {
return blockState;
}
@Override
public String getNbtId() {
CompoundTag nbtData = getNbtData();
@ -181,12 +176,15 @@ public class BaseBlock extends BlockState {
@Override
public boolean equals(Object o) {
if (!(o instanceof BaseBlock)) {
if (!hasNbtData() && o instanceof BlockStateHolder) {
return Objects.equals(toImmutableState(), ((BlockStateHolder<?>) o).toImmutableState());
}
return false;
}
final BaseBlock otherBlock = (BaseBlock) o;
return this.equals(otherBlock) && Objects.equals(getNbtData(), otherBlock.getNbtData());
return this.blockState.equalsFuzzy(otherBlock.blockState) && Objects.equals(getNbtData(), otherBlock.getNbtData());
}
@Override
@ -205,7 +203,7 @@ public class BaseBlock extends BlockState {
}
@Override
public BlockTypes getBlockType() {
public BlockType getBlockType() {
return blockState.getBlockType();
}
@ -244,4 +242,65 @@ public class BaseBlock extends BlockState {
}
}
@Override
public boolean apply(Extent extent, BlockVector3 get, BlockVector3 set) throws WorldEditException {
// TODO Auto-generated method stub
return false;
}
@Override
public boolean hasNbtData() {
return this.nbtData != null;
}
@Override
public BlockStateHolder withPropertyId(int propertyId) {
return getBlockType().withPropertyId(propertyId);
}
@Override
public int getInternalBlockTypeId() {
return toImmutableState().getInternalBlockTypeId();
}
@Override
public int getInternalPropertiesId() {
return toImmutableState().getInternalPropertiesId();
}
@Override
public Mask toMask(Extent extent) {
return new SingleBlockStateMask(extent, toImmutableState());
}
@Override
public <V> BaseBlock with(Property<V> property, V value) {
return toImmutableState().with(property, value).toBaseBlock();
}
@Override
public <V> BlockStateHolder with(PropertyKey property, V value) {
return toImmutableState().with(property, value);
}
@Override
public <V> V getState(Property<V> property) {
return toImmutableState().getState(property);
}
@Override
public <V> V getState(PropertyKey property) {
return toImmutableState().getState(property);
}
@Override
public Map<Property<?>, Object> getStates() {
return toImmutableState().getStates();
}
@Override
public boolean equalsFuzzy(BlockStateHolder o) {
return toImmutableState().equalsFuzzy(o);
}
}

View File

@ -39,6 +39,7 @@ import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.registry.state.AbstractProperty;
import com.sk89q.worldedit.registry.state.Property;
import com.sk89q.worldedit.registry.state.PropertyKey;
import com.sk89q.worldedit.world.registry.BlockMaterial;
import javax.annotation.Nullable;
import java.util.*;
@ -49,13 +50,26 @@ import java.util.stream.Stream;
* An immutable class that represents the state a block can be in.
*/
@SuppressWarnings("unchecked")
public abstract class BlockState implements BlockStateHolder<BlockState> {
public class BlockState implements BlockStateHolder<BlockState> {
private final BlockType blockType;
private BaseBlock emptyBaseBlock;
BlockState(BlockType blockType) {
this.blockType = blockType;
this.emptyBaseBlock = new BaseBlock(this);
}
BlockState(BlockType blockType, BaseBlock baseBlock){
this.blockType = blockType;
this.emptyBaseBlock = baseBlock;
}
/**
* Returns a temporary BlockState for a given internal id
* @param combinedId
* @deprecated magic number
* @return BlockState
*/
@Deprecated
public static BlockState getFromInternalId(int combinedId) throws InputParseException {
return BlockTypes.getFromStateId(combinedId).withStateId(combinedId);
@ -85,17 +99,6 @@ public abstract class BlockState implements BlockStateHolder<BlockState> {
public static BlockState get(@Nullable BlockType type, String state) throws InputParseException {
return get(type, state, null);
}
// private BlockTypes blockType;
// private BaseBlock emptyBaseBlock;
// Neighbouring state table.
private Table<Property<?>, Object, BlockState> states;
// protected BlockState(BlockTypes blockType) {
//// protected BlockState() {
// this.blockType = blockType;
// this.emptyBaseBlock = new BaseBlock(this);
// }
/**
* Returns a temporary BlockState for a given type and string
@ -265,7 +268,7 @@ public abstract class BlockState implements BlockStateHolder<BlockState> {
@Override
public <V> BlockState with(final Property<V> property, final V value) {
try {
BlockTypes type = getBlockType();
BlockType type = getBlockType();
int newState = ((AbstractProperty) property).modify(this.getInternalId(), value);
return newState != this.getInternalId() ? type.withStateId(newState) : this;
} catch (ClassCastException e) {
@ -276,7 +279,7 @@ public abstract class BlockState implements BlockStateHolder<BlockState> {
@Override
public <V> BlockState with(final PropertyKey property, final V value) {
try {
BlockTypes type = getBlockType();
BlockType type = getBlockType();
int newState = ((AbstractProperty) type.getProperty(property)).modify(this.getInternalId(), value);
return newState != this.getInternalId() ? type.withStateId(newState) : this;
} catch (ClassCastException e) {
@ -309,13 +312,10 @@ public abstract class BlockState implements BlockStateHolder<BlockState> {
return (Map<Property<?>, Object>) map;
}
// @Override
// public BaseBlock toBaseBlock() {
//// if (this.fuzzy) {
//// throw new IllegalArgumentException("Can't create a BaseBlock from a fuzzy BlockState!");
//// }
// return this.emptyBaseBlock;
// }
@Override
public BaseBlock toBaseBlock() {
return this.emptyBaseBlock;
}
@Override
public BaseBlock toBaseBlock(CompoundTag compoundTag) {
@ -325,10 +325,10 @@ public abstract class BlockState implements BlockStateHolder<BlockState> {
return new BaseBlock(this, compoundTag);
}
// @Override
// public BlockTypes getBlockType() {
// return this.blockType;
// }
@Override
public BlockType getBlockType() {
return this.blockType;
}
/**
* Deprecated, use masks - not try to this fuzzy/non fuzzy state nonsense
@ -364,4 +364,20 @@ public abstract class BlockState implements BlockStateHolder<BlockState> {
public String toString() {
return getAsString();
}
@Override
public int getInternalId() {
return blockType.getInternalId();
}
@Override
public BlockMaterial getMaterial() {
return blockType.getMaterial();
}
@Override
public int getOrdinal() {
//?
return 0;
}
}

View File

@ -38,7 +38,7 @@ public interface BlockStateHolder<T extends BlockStateHolder> extends FawePatter
*
* @return The type
*/
BlockTypes getBlockType();
BlockType getBlockType();
/**
* Magic number (legacy uses)
@ -46,9 +46,7 @@ public interface BlockStateHolder<T extends BlockStateHolder> extends FawePatter
* @return
*/
@Deprecated
default BlockStateHolder withPropertyId(int propertyId) {
return getBlockType().withPropertyId(propertyId);
}
BlockStateHolder withPropertyId(int propertyId);
/**
* Get combined id (legacy uses)
@ -60,18 +58,13 @@ public interface BlockStateHolder<T extends BlockStateHolder> extends FawePatter
@Deprecated
int getOrdinal();
default BlockMaterial getMaterial() {
return getBlockType().getMaterial();
}
BlockMaterial getMaterial();
/**
* Get type id (legacy uses)
* @return
*/
@Deprecated
default int getInternalBlockTypeId() {
return getBlockType().getInternalId();
}
int getInternalBlockTypeId();
/**
* Get the block data (legacy uses)
@ -132,11 +125,7 @@ public interface BlockStateHolder<T extends BlockStateHolder> extends FawePatter
boolean equalsFuzzy(BlockStateHolder o);
/**
<<<<<<< HEAD
* Returns an immutable BlockStateHolder from this BlockStateHolder.
=======
* Returns an immutable {@link BlockState} from this BlockStateHolder.
>>>>>>> f54d6afb... Make BaseBlock more memory efficient, and make it clear in the API that it's not intended to be used for every single block.
*
* @return A BlockState
*/

View File

@ -7,12 +7,12 @@ import com.sk89q.worldedit.world.registry.BlockMaterial;
public class BlockStateImpl extends BlockState {
private final int internalId;
private final int ordinal;
private final BlockTypes type;
private final BlockType type;
private BlockMaterial material;
private BaseBlock baseBlock;
protected BlockStateImpl(BlockTypes type, int internalId, int ordinal) {
// super(type);
protected BlockStateImpl(BlockType type, int internalId, int ordinal) {
super(type);
this.type = type;
this.internalId = internalId;
this.ordinal = ordinal;
@ -44,7 +44,7 @@ public class BlockStateImpl extends BlockState {
}
@Override
public final BlockTypes getBlockType() {
public final BlockType getBlockType() {
return type;
}

View File

@ -33,6 +33,7 @@ import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.world.registry.BlockMaterial;
import com.sk89q.worldedit.extension.platform.Capability;
import com.sk89q.worldedit.registry.NamespacedRegistry;
import com.sk89q.worldedit.registry.state.AbstractProperty;
import com.sk89q.worldedit.registry.state.Property;
import com.sk89q.worldedit.registry.state.PropertyKey;
import com.sk89q.worldedit.world.item.ItemType;
@ -40,30 +41,55 @@ import com.sk89q.worldedit.world.item.ItemTypes;
import com.sk89q.worldedit.world.registry.BundledBlockData;
import com.sk89q.worldedit.world.registry.LegacyMapper;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
public interface BlockType extends FawePattern, Comparable<BlockTypes> {
default BlockTypes getTypeEnum() {
return (BlockTypes) this;
}
public class BlockType implements FawePattern {
public static final NamespacedRegistry<BlockType> REGISTRY = new NamespacedRegistry<>("block type");
private final @Nonnull String id;
private ArrayList<BlockState> states;
public final Function<BlockState, BlockState> defaultValue;
private BlockTypes.Settings settings;
private BlockMaterial material;
public BlockType(@Nonnull String id) {
this(id, null);
}
public BlockType(@Nonnull String id, Function<BlockState, BlockState> defaultValue) {
this.id = id;
this.defaultValue = defaultValue;
}
public void setStates(ArrayList<BlockState> states) {
this.states = states;
}
public void setSettings(BlockTypes.Settings settings) {
this.settings = settings;
}
public BlockTypes.Settings getSettings(){
return settings;
}
public ArrayList<BlockState> updateStates(){
if(settings != null) {
return settings.localStates = new ArrayList<BlockState>(settings.localStates.stream().map(state -> new BlockStateImpl(this, state.getInternalId(), state.getOrdinal())).collect(Collectors.toList()));
}else {
return null;
}
}
@Deprecated
int getMaxStateId();
@Override
default boolean apply(Extent extent, BlockVector3 get, BlockVector3 set) throws WorldEditException {
return extent.setBlock(set, this.getDefaultState());
}
@Override
default BlockStateHolder apply(BlockVector3 position) {
return this.getDefaultState();
}
default Mask toMask(Extent extent) {
return new SingleBlockTypeMask(extent, this);
public int getMaxStateId() {
return settings.permutations;
}
/**
@ -71,15 +97,17 @@ public interface BlockType extends FawePattern, Comparable<BlockTypes> {
*
* @return The id
*/
String getId();
public String getId() {
return this.id;
}
default String getNamespace() {
public String getNamespace() {
String id = getId();
int i = id.indexOf(':');
return i == -1 ? "minecraft" : id.substring(0, i);
}
default String getResource() {
public String getResource() {
String id = getId();
return id.substring(id.indexOf(':') + 1);
}
@ -89,7 +117,7 @@ public interface BlockType extends FawePattern, Comparable<BlockTypes> {
*
* @return The name, or ID
*/
default String getName() {
public String getName() {
BundledBlockData.BlockEntry entry = BundledBlockData.getInstance().findById(this.getId());
if (entry == null) {
return getId();
@ -99,28 +127,41 @@ public interface BlockType extends FawePattern, Comparable<BlockTypes> {
}
@Deprecated
default BlockState withPropertyId(int internalPropertiesId) {
if (internalPropertiesId == 0) return getDefaultState();
return BlockState.getFromInternalId(getInternalId() + (internalPropertiesId << BlockTypes.BIT_OFFSET));
public BlockState withPropertyId(int propertyId) {
if (settings.stateOrdinals == null) return settings.defaultState;
return states.get(settings.stateOrdinals[propertyId]);
}
@Deprecated
public BlockState withStateId(int internalStateId) {
return this.withPropertyId(internalStateId >> BlockTypes.BIT_OFFSET);
}
/**
* Gets the properties of this BlockType in a {@code key->property} mapping.
* Properties string in the form property1=foo,prop2=bar
* @param properties
* @return
*/
public BlockState withProperties(String properties) {
int id = getInternalId();
for (String keyPair : properties.split(",")) {
String[] split = keyPair.split("=");
String name = split[0];
String value = split[1];
AbstractProperty btp = settings.propertiesMap.get(name);
id = btp.modify(id, btp.getValueFor(value));
}
return withStateId(id);
}
/**
* Gets the properties of this BlockType in a key->property mapping.
*
* @return The properties map
*/
@Deprecated
default Map<String, ? extends Property> getPropertyMap() {
List<? extends Property> properties = getProperties();
if (properties.isEmpty()) {
return Collections.emptyMap();
}
Map<String, Property> map = new HashMap<>(properties.size());
for (Property property : properties) {
map.put(property.getName(), property);
}
return map;
public Map<String, ? extends Property<?>> getPropertyMap() {
return this.settings.propertiesMap;
}
/**
@ -129,11 +170,13 @@ public interface BlockType extends FawePattern, Comparable<BlockTypes> {
* @return the properties
*/
@Deprecated
List<? extends Property> getProperties();
public List<? extends Property<?>> getProperties() {
return this.settings.propertiesList;
}
@Deprecated
default Set<? extends Property> getPropertiesSet() {
return new HashSet<>(getProperties());
public Set<? extends Property<?>> getPropertiesSet() {
return this.settings.propertiesSet;
}
/**
@ -143,20 +186,22 @@ public interface BlockType extends FawePattern, Comparable<BlockTypes> {
* @return The property
*/
@Deprecated
default <V> Property<V> getProperty(String name) {
Property<V> property = getPropertyMap().get(name);
checkArgument(property != null, "%s has no property named %s", this, name);
return property;
public <V> Property<V> getProperty(String name) {
checkArgument(this.settings.propertiesMap.get(name) != null, "%s has no property named %s", this, name);
return (Property<V>) this.settings.propertiesMap.get(name);
}
default boolean hasProperty(PropertyKey key) {
return getPropertyMap().containsKey(key.getId());
public boolean hasProperty(PropertyKey key) {
int ordinal = key.ordinal();
return this.settings.propertiesMapArr.length > ordinal ? this.settings.propertiesMapArr[ordinal] != null : false;
}
default <V> Property<V> getProperty(PropertyKey key) {
Property<V> property = getPropertyMap().get(key.getId());
checkArgument(property != null, "%s has no property named %s", this, key.getId());
return property;
public <V> Property<V> getProperty(PropertyKey key) {
try {
return (Property<V>) this.settings.propertiesMapArr[key.ordinal()];
} catch (IndexOutOfBoundsException ignore) {
return null;
}
}
/**
@ -164,28 +209,54 @@ public interface BlockType extends FawePattern, Comparable<BlockTypes> {
*
* @return The default state
*/
BlockState getDefaultState();
public BlockState getDefaultState() {
BlockState defaultState = this.settings.defaultState;
if (defaultValue != null) {
defaultState = defaultValue.apply(defaultState);
}
return defaultState;
}
/**
* Gets a list of all possible states for this BlockType.
*
* @return All possible states
* Slow
* @return collection of states
*/
List<BlockState> getAllStates();
@Deprecated
public List<BlockState> getAllStates() {
if (settings.stateOrdinals == null) return Collections.singletonList(getDefaultState());
return IntStream.of(settings.stateOrdinals).filter(i -> i != -1).mapToObj(i -> states.get(i)).collect(Collectors.toList());
}
/**
* Gets a state of this BlockType with the given properties.
*
* @return The state, if it exists
*/
BlockState getState(Map<Property<?>, Object> key);
public BlockState getState(Map<Property<?>, Object> key) {
int id = getInternalId();
for (Map.Entry<Property<?>, Object> iter : key.entrySet()) {
Property<?> prop = iter.getKey();
Object value = iter.getValue();
/*
* TODO:
* This is likely wrong. The only place this seems to currently (Dec 23 2018)
* be invoked is via ForgeWorld, and value is a String when invoked there...
*/
AbstractProperty btp = this.settings.propertiesMap.get(prop.getName());
checkArgument(btp != null, "%s has no property named %s", this, prop.getName());
id = btp.modify(id, btp.getValueFor((String)value));
}
return withStateId(id);
}
/**
* Gets whether this block type has an item representation.
*
* @return If it has an item
*/
default boolean hasItemType() {
public boolean hasItemType() {
return getItemType() != null;
}
@ -195,8 +266,8 @@ public interface BlockType extends FawePattern, Comparable<BlockTypes> {
* @return The item representation
*/
@Nullable
default ItemType getItemType() {
return ItemTypes.get(this.getTypeEnum());
public ItemType getItemType() {
return ItemTypes.get(this);
}
/**
@ -204,7 +275,11 @@ public interface BlockType extends FawePattern, Comparable<BlockTypes> {
*
* @return The material
*/
BlockMaterial getMaterial();
public BlockMaterial getMaterial() {
return this.material == null ?
WorldEdit.getInstance().getPlatformManager().queryCapability(Capability.GAME_HOOKS).getRegistries().getBlockRegistry().getMaterial(this)
: this.material;
}
/**
* Gets the legacy ID. Needed for legacy reasons.
@ -213,7 +288,7 @@ public interface BlockType extends FawePattern, Comparable<BlockTypes> {
*
* @return legacy id or 0, if unknown
*/
default int getLegacyCombinedId() {
public int getLegacyCombinedId() {
Integer combinedId = LegacyMapper.getInstance().getLegacyCombined(this);
return combinedId == null ? 0 : combinedId;
}
@ -225,16 +300,43 @@ public interface BlockType extends FawePattern, Comparable<BlockTypes> {
*
* @return internal id
*/
int getInternalId();
public int getInternalId() {
return this.settings.internalId;
}
@Override
boolean equals(Object obj);
public int hashCode() {
return this.id.hashCode();
}
@Override
int hashCode();
public boolean equals(Object obj) {
return obj instanceof BlockType && this.id.equals(((BlockType) obj).id);
}
@Override
public String toString() {
return getId();
}
@Override
public boolean apply(Extent extent, BlockVector3 get, BlockVector3 set) throws WorldEditException {
return extent.setBlock(set, this.getDefaultState());
}
@Override
public BlockStateHolder apply(BlockVector3 position) {
return this.getDefaultState();
}
public Mask toMask(Extent extent) {
return new SingleBlockTypeMask(extent, this);
}
@Deprecated
default int getLegacyId() {
public int getLegacyId() {
Integer id = LegacyMapper.getInstance().getLegacyCombined(this.getDefaultState());
if (id != null) {
return id >> 4;

View File

@ -17,7 +17,7 @@ public class BlockTypeSwitchBuilder<T> {
}
public BlockTypeSwitchBuilder<T> add(Predicate<BlockType> predicate, T task) {
for (BlockTypes type : BlockTypes.values) {
for (BlockType type : BlockTypes.values) {
if (predicate.test(type)) {
this.runnables[type.getInternalId()] = task;
}

View File

@ -0,0 +1,214 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.world.block;
import com.sk89q.worldedit.registry.state.PropertyGroup;
import com.sk89q.worldedit.registry.state.PropertyKey;
import com.sk89q.worldedit.world.block.BlockStateHolder;
import com.sk89q.worldedit.world.block.BlockTypes;
import static com.google.common.base.Preconditions.checkNotNull;
public class BlockTypeUtil {
public static double centralTopLimit(com.sk89q.worldedit.world.block.BlockType type) {
checkNotNull(type);
return centralTopLimit(type.getDefaultState());
}
public static double centralBottomLimit(BlockStateHolder block) {
checkNotNull(block);
BlockType type = block.getBlockType();
switch (type.getResource().toUpperCase()) {
case "CREEPER_WALL_HEAD":
case "DRAGON_WALL_HEAD":
case "PLAYER_WALL_HEAD":
case "ZOMBIE_WALL_HEAD": return 0.25;
case "ACACIA_SLAB":
case "BIRCH_SLAB":
case "BRICK_SLAB":
case "COBBLESTONE_SLAB":
case "DARK_OAK_SLAB":
case "DARK_PRISMARINE_SLAB":
case "JUNGLE_SLAB":
case "NETHER_BRICK_SLAB":
case "OAK_SLAB":
case "PETRIFIED_OAK_SLAB":
case "PRISMARINE_BRICK_SLAB":
case "PRISMARINE_SLAB":
case "PURPUR_SLAB":
case "QUARTZ_SLAB":
case "RED_SANDSTONE_SLAB":
case "SANDSTONE_SLAB":
case "SPRUCE_SLAB":
case "STONE_BRICK_SLAB":
case "STONE_SLAB": {
String state = (String) block.getState(PropertyKey.TYPE);
if (state == null) return 0;
switch (state) {
case "double":
case "bottom":
return 0;
case "top":
return 0.5;
}
}
case "ACACIA_TRAPDOOR":
case "BIRCH_TRAPDOOR":
case "DARK_OAK_TRAPDOOR":
case "IRON_TRAPDOOR":
case "JUNGLE_TRAPDOOR":
case "OAK_TRAPDOOR":
case "SPRUCE_TRAPDOOR":
if (block.getState(PropertyKey.OPEN) == Boolean.TRUE) {
return 1;
} else if ("bottom".equals(block.getState(PropertyKey.HALF))) {
return 0.8125;
} else {
return 0;
}
case "ACACIA_FENCE_GATE":
case "BIRCH_FENCE_GATE":
case "DARK_OAK_FENCE_GATE":
case "JUNGLE_FENCE_GATE":
case "OAK_FENCE_GATE":
case "SPRUCE_FENCE_GATE": return block.getState(PropertyKey.OPEN) == Boolean.TRUE ? 1 : 0;
default:
if (type.getMaterial().isMovementBlocker()) return 0;
return 1;
}
}
/**
* Returns the y offset a player falls to when falling onto the top of a block at xp+0.5/zp+0.5.
*
* @param block the block
* @return the y offset
*/
public static double centralTopLimit(BlockStateHolder block) {
checkNotNull(block);
BlockType type = block.getBlockType();
switch (type.getResource().toUpperCase()) {
case "BLACK_BED":
case "BLUE_BED":
case "BROWN_BED":
case "CYAN_BED":
case "GRAY_BED":
case "GREEN_BED":
case "LIGHT_BLUE_BED":
case "LIGHT_GRAY_BED":
case "LIME_BED":
case "MAGENTA_BED":
case "ORANGE_BED":
case "PINK_BED":
case "PURPLE_BED":
case "RED_BED":
case "WHITE_BED":
case "YELLOW_BED": return 0.5625;
case "BREWING_STAND": return 0.875;
case "CAKE": return (block.getState(PropertyKey.BITES) == (Integer) 6) ? 0 : 0.4375;
case "CAULDRON": return 0.3125;
case "COCOA": return 0.750;
case "ENCHANTING_TABLE": return 0.75;
case "END_PORTAL_FRAME": return block.getState(PropertyKey.EYE) == Boolean.TRUE ? 1 : 0.8125;
case "CREEPER_HEAD":
case "DRAGON_HEAD":
case "PISTON_HEAD":
case "PLAYER_HEAD":
case "ZOMBIE_HEAD": return 0.5;
case "CREEPER_WALL_HEAD":
case "DRAGON_WALL_HEAD":
case "PLAYER_WALL_HEAD":
case "ZOMBIE_WALL_HEAD": return 0.75;
case "ACACIA_FENCE":
case "BIRCH_FENCE":
case "DARK_OAK_FENCE":
case "JUNGLE_FENCE":
case "NETHER_BRICK_FENCE":
case "OAK_FENCE":
case "SPRUCE_FENCE": return 1.5;
case "ACACIA_SLAB":
case "BIRCH_SLAB":
case "BRICK_SLAB":
case "COBBLESTONE_SLAB":
case "DARK_OAK_SLAB":
case "DARK_PRISMARINE_SLAB":
case "JUNGLE_SLAB":
case "NETHER_BRICK_SLAB":
case "OAK_SLAB":
case "PETRIFIED_OAK_SLAB":
case "PRISMARINE_BRICK_SLAB":
case "PRISMARINE_SLAB":
case "PURPUR_SLAB":
case "QUARTZ_SLAB":
case "RED_SANDSTONE_SLAB":
case "SANDSTONE_SLAB":
case "SPRUCE_SLAB":
case "STONE_BRICK_SLAB":
case "STONE_SLAB": {
String state = (String) block.getState(PropertyKey.TYPE);
if (state == null) return 0.5;
switch (state) {
case "bottom":
return 0.5;
case "top":
case "double":
return 1;
}
}
case "LILY_PAD": return 0.015625;
case "REPEATER": return 0.125;
case "SOUL_SAND": return 0.875;
case "COBBLESTONE_WALL":
case "MOSSY_COBBLESTONE_WALL": return 1.5;
case "FLOWER_POT": return 0.375;
case "COMPARATOR": return 0.125;
case "DAYLIGHT_DETECTOR": return 0.375;
case "HOPPER": return 0.625;
case "ACACIA_TRAPDOOR":
case "BIRCH_TRAPDOOR":
case "DARK_OAK_TRAPDOOR":
case "IRON_TRAPDOOR":
case "JUNGLE_TRAPDOOR":
case "OAK_TRAPDOOR":
case "SPRUCE_TRAPDOOR":
if (block.getState(PropertyKey.OPEN) == Boolean.TRUE) {
return 0;
} else if ("top".equals(block.getState(PropertyKey.HALF))) {
return 1;
} else {
return 0.1875;
}
case "ACACIA_FENCE_GATE":
case "BIRCH_FENCE_GATE":
case "DARK_OAK_FENCE_GATE":
case "JUNGLE_FENCE_GATE":
case "OAK_FENCE_GATE":
case "SPRUCE_FENCE_GATE": return block.getState(PropertyKey.OPEN) == Boolean.TRUE ? 0 : 1.5;
default:
if (type.hasProperty(PropertyKey.LAYERS)) {
return PropertyGroup.LEVEL.get(block) * 0.0625;
}
if (!type.getMaterial().isMovementBlocker()) return 0;
return 1;
}
}
}

View File

@ -21,18 +21,46 @@ package com.sk89q.worldedit.world.entity;
import com.sk89q.worldedit.registry.NamespacedRegistry;
public interface EntityType {
String getId();
public class EntityType {
public static final NamespacedRegistry<EntityType> REGISTRY = new NamespacedRegistry<>("entity type");
private String id;
public EntityType(String id) {
// If it has no namespace, assume minecraft.
if (!id.contains(":")) {
id = "minecraft:" + id;
}
this.id = id;
}
public String getId() {
return this.id;
}
/**
* Gets the name of this item, or the ID if the name cannot be found.
*
* @return The name, or ID
*/
default String getName() {
public String getName() {
return getId();
}
@Deprecated
public int getInternalId();
}
@Override
public String toString() {
return getId();
}
@Override
public int hashCode() {
return this.id.hashCode();
}
@Override
public boolean equals(Object obj) {
return obj instanceof EntityType && this.id.equals(((EntityType) obj).id);
}
}

View File

@ -19,166 +19,121 @@
package com.sk89q.worldedit.world.entity;
import com.boydti.fawe.util.ReflectionUtils;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.blocks.BaseItem;
import com.sk89q.worldedit.blocks.BaseItemStack;
import com.sk89q.worldedit.entity.BaseEntity;
import com.sk89q.worldedit.extension.platform.Capability;
import com.sk89q.worldedit.world.block.BlockTypes;
import com.sk89q.worldedit.world.item.ItemType;
import com.sk89q.worldedit.world.registry.LegacyMapper;
import javax.annotation.Nullable;
import java.util.*;
public enum EntityTypes implements EntityType {
/*
-----------------------------------------------------
Replaced at runtime by the entity registry
-----------------------------------------------------
*/
__RESERVED__,
AREA_EFFECT_CLOUD,
ARMOR_STAND,
ARROW,
BAT,
BLAZE,
BOAT,
CAVE_SPIDER,
CHEST_MINECART,
CHICKEN,
COD,
COMMAND_BLOCK_MINECART,
COW,
CREEPER,
DOLPHIN,
DONKEY,
DRAGON_FIREBALL,
DROWNED,
EGG,
ELDER_GUARDIAN,
END_CRYSTAL,
ENDER_DRAGON,
ENDER_PEARL,
ENDERMAN,
ENDERMITE,
EVOKER,
EVOKER_FANGS,
EXPERIENCE_BOTTLE,
EXPERIENCE_ORB,
EYE_OF_ENDER,
FALLING_BLOCK,
FIREBALL,
FIREWORK_ROCKET,
FISHING_BOBBER,
FURNACE_MINECART,
GHAST,
GIANT,
GUARDIAN,
HOPPER_MINECART,
HORSE,
HUSK,
ILLUSIONER,
IRON_GOLEM,
ITEM,
ITEM_FRAME,
LEASH_KNOT,
LIGHTNING_BOLT,
LLAMA,
LLAMA_SPIT,
MAGMA_CUBE,
MINECART,
MOOSHROOM,
MULE,
OCELOT,
PAINTING,
PARROT,
PHANTOM,
PIG,
PLAYER,
POLAR_BEAR,
POTION,
PUFFERFISH,
RABBIT,
SALMON,
SHEEP,
SHULKER,
SHULKER_BULLET,
SILVERFISH,
SKELETON,
SKELETON_HORSE,
SLIME,
SMALL_FIREBALL,
SNOW_GOLEM,
SNOWBALL,
SPAWNER_MINECART,
SPECTRAL_ARROW,
SPIDER,
SQUID,
STRAY,
TNT,
TNT_MINECART,
TRIDENT,
TROPICAL_FISH,
TURTLE,
VEX,
VILLAGER,
VINDICATOR,
WITCH,
WITHER,
WITHER_SKELETON,
WITHER_SKULL,
WOLF,
ZOMBIE,
ZOMBIE_HORSE,
ZOMBIE_PIGMAN,
ZOMBIE_VILLAGER,
public class EntityTypes {
;
public static final EntityType AREA_EFFECT_CLOUD = register("minecraft:area_effect_cloud");
public static final EntityType ARMOR_STAND = register("minecraft:armor_stand");
public static final EntityType ARROW = register("minecraft:arrow");
public static final EntityType BAT = register("minecraft:bat");
public static final EntityType BLAZE = register("minecraft:blaze");
public static final EntityType BOAT = register("minecraft:boat");
public static final EntityType CAVE_SPIDER = register("minecraft:cave_spider");
public static final EntityType CHEST_MINECART = register("minecraft:chest_minecart");
public static final EntityType CHICKEN = register("minecraft:chicken");
public static final EntityType COD = register("minecraft:cod");
public static final EntityType COMMAND_BLOCK_MINECART = register("minecraft:command_block_minecart");
public static final EntityType COW = register("minecraft:cow");
public static final EntityType CREEPER = register("minecraft:creeper");
public static final EntityType DOLPHIN = register("minecraft:dolphin");
public static final EntityType DONKEY = register("minecraft:donkey");
public static final EntityType DRAGON_FIREBALL = register("minecraft:dragon_fireball");
public static final EntityType DROWNED = register("minecraft:drowned");
public static final EntityType EGG = register("minecraft:egg");
public static final EntityType ELDER_GUARDIAN = register("minecraft:elder_guardian");
public static final EntityType END_CRYSTAL = register("minecraft:end_crystal");
public static final EntityType ENDER_DRAGON = register("minecraft:ender_dragon");
public static final EntityType ENDER_PEARL = register("minecraft:ender_pearl");
public static final EntityType ENDERMAN = register("minecraft:enderman");
public static final EntityType ENDERMITE = register("minecraft:endermite");
public static final EntityType EVOKER = register("minecraft:evoker");
public static final EntityType EVOKER_FANGS = register("minecraft:evoker_fangs");
public static final EntityType EXPERIENCE_BOTTLE = register("minecraft:experience_bottle");
public static final EntityType EXPERIENCE_ORB = register("minecraft:experience_orb");
public static final EntityType EYE_OF_ENDER = register("minecraft:eye_of_ender");
public static final EntityType FALLING_BLOCK = register("minecraft:falling_block");
public static final EntityType FIREBALL = register("minecraft:fireball");
public static final EntityType FIREWORK_ROCKET = register("minecraft:firework_rocket");
public static final EntityType FISHING_BOBBER = register("minecraft:fishing_bobber");
public static final EntityType FURNACE_MINECART = register("minecraft:furnace_minecart");
public static final EntityType GHAST = register("minecraft:ghast");
public static final EntityType GIANT = register("minecraft:giant");
public static final EntityType GUARDIAN = register("minecraft:guardian");
public static final EntityType HOPPER_MINECART = register("minecraft:hopper_minecart");
public static final EntityType HORSE = register("minecraft:horse");
public static final EntityType HUSK = register("minecraft:husk");
public static final EntityType ILLUSIONER = register("minecraft:illusioner");
public static final EntityType IRON_GOLEM = register("minecraft:iron_golem");
public static final EntityType ITEM = register("minecraft:item");
public static final EntityType ITEM_FRAME = register("minecraft:item_frame");
public static final EntityType LEASH_KNOT = register("minecraft:leash_knot");
public static final EntityType LIGHTNING_BOLT = register("minecraft:lightning_bolt");
public static final EntityType LLAMA = register("minecraft:llama");
public static final EntityType LLAMA_SPIT = register("minecraft:llama_spit");
public static final EntityType MAGMA_CUBE = register("minecraft:magma_cube");
public static final EntityType MINECART = register("minecraft:minecart");
public static final EntityType MOOSHROOM = register("minecraft:mooshroom");
public static final EntityType MULE = register("minecraft:mule");
public static final EntityType OCELOT = register("minecraft:ocelot");
public static final EntityType PAINTING = register("minecraft:painting");
public static final EntityType PARROT = register("minecraft:parrot");
public static final EntityType PHANTOM = register("minecraft:phantom");
public static final EntityType PIG = register("minecraft:pig");
public static final EntityType PLAYER = register("minecraft:player");
public static final EntityType POLAR_BEAR = register("minecraft:polar_bear");
public static final EntityType POTION = register("minecraft:potion");
public static final EntityType PUFFERFISH = register("minecraft:pufferfish");
public static final EntityType RABBIT = register("minecraft:rabbit");
public static final EntityType SALMON = register("minecraft:salmon");
public static final EntityType SHEEP = register("minecraft:sheep");
public static final EntityType SHULKER = register("minecraft:shulker");
public static final EntityType SHULKER_BULLET = register("minecraft:shulker_bullet");
public static final EntityType SILVERFISH = register("minecraft:silverfish");
public static final EntityType SKELETON = register("minecraft:skeleton");
public static final EntityType SKELETON_HORSE = register("minecraft:skeleton_horse");
public static final EntityType SLIME = register("minecraft:slime");
public static final EntityType SMALL_FIREBALL = register("minecraft:small_fireball");
public static final EntityType SNOW_GOLEM = register("minecraft:snow_golem");
public static final EntityType SNOWBALL = register("minecraft:snowball");
public static final EntityType SPAWNER_MINECART = register("minecraft:spawner_minecart");
public static final EntityType SPECTRAL_ARROW = register("minecraft:spectral_arrow");
public static final EntityType SPIDER = register("minecraft:spider");
public static final EntityType SQUID = register("minecraft:squid");
public static final EntityType STRAY = register("minecraft:stray");
public static final EntityType TNT = register("minecraft:tnt");
public static final EntityType TNT_MINECART = register("minecraft:tnt_minecart");
public static final EntityType TRIDENT = register("minecraft:trident");
public static final EntityType TROPICAL_FISH = register("minecraft:tropical_fish");
public static final EntityType TURTLE = register("minecraft:turtle");
public static final EntityType VEX = register("minecraft:vex");
public static final EntityType VILLAGER = register("minecraft:villager");
public static final EntityType VINDICATOR = register("minecraft:vindicator");
public static final EntityType WITCH = register("minecraft:witch");
public static final EntityType WITHER = register("minecraft:wither");
public static final EntityType WITHER_SKELETON = register("minecraft:wither_skeleton");
public static final EntityType WITHER_SKULL = register("minecraft:wither_skull");
public static final EntityType WOLF = register("minecraft:wolf");
public static final EntityType ZOMBIE = register("minecraft:zombie");
public static final EntityType ZOMBIE_HORSE = register("minecraft:zombie_horse");
public static final EntityType ZOMBIE_PIGMAN = register("minecraft:zombie_pigman");
public static final EntityType ZOMBIE_VILLAGER = register("minecraft:zombie_villager");
private String id;
private int internalId;
EntityTypes() {
this(null);
private EntityTypes() {
}
EntityTypes(String id) {
init(id);
private static EntityType register(final String id) {
return register(new EntityType(id));
}
private void init(String id) {
if (id == null) id = "minecraft:" + name().toLowerCase();
// If it has no namespace, assume minecraft.
else if (!id.contains(":")) {
id = "minecraft:" + id;
}
this.id = id;
this.internalId = ordinal();
public static EntityType register(final EntityType entityType) {
return EntityType.REGISTRY.register(entityType.getId(), entityType);
}
@Override
public String getId() {
return id;
public static @Nullable EntityType get(final String id) {
return EntityType.REGISTRY.get(id);
}
@Override
public String toString() {
return getId();
}
@Override
public int getInternalId() {
return internalId;
}
/*
-----------------------------------------------------
Static Initializer
-----------------------------------------------------
*/
public static EntityType parse(String id) {
if (id.startsWith("minecraft:")) id = id.substring(10);
switch (id) {
@ -246,64 +201,4 @@ public enum EntityTypes implements EntityType {
}
}
private static final Map<String, EntityTypes> $REGISTRY = new HashMap<>();
private static int $LENGTH;
public static final EntityTypes[] values;
static {
try {
Collection<String> ents = WorldEdit.getInstance().getPlatformManager().queryCapability(Capability.GAME_HOOKS).getRegistries().getEntityRegistry().registerEntities();
EntityTypes[] oldValues = values();
$LENGTH = oldValues.length;
LinkedHashSet<EntityTypes> newValues = new LinkedHashSet<>(Arrays.asList(oldValues));
if (!ents.isEmpty()) { // No types found - use defaults
for (String ent : ents) {
EntityTypes registered = register(ent);
if (!newValues.contains(registered)) newValues.add(registered);
}
}
// Cache the values
values = newValues.toArray(new EntityTypes[newValues.size()]);
} catch (Throwable e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
private static EntityTypes register(final String id) {
// Get the enum name (remove namespace if minecraft:)
int propStart = id.indexOf('[');
String typeName = id.substring(0, propStart == -1 ? id.length() : propStart);
String enumName = (typeName.startsWith("minecraft:") ? typeName.substring(10) : typeName).toUpperCase();
// Check existing
EntityTypes existing = null;
try { existing = valueOf(enumName.toUpperCase()); } catch (IllegalArgumentException ignore) {}
if (existing == null) {
existing = ReflectionUtils.addEnum(EntityTypes.class, enumName);
}
int internalId = existing.ordinal();
if (existing.id == null) {
existing.init(null);
}
if (internalId == 0 && existing != __RESERVED__) {
existing.internalId = $LENGTH++;
}
if (typeName.startsWith("minecraft:")) $REGISTRY.put(typeName.substring(10), existing);
$REGISTRY.put(typeName, existing);
return existing;
}
public static final @Nullable EntityTypes get(final String id) {
return $REGISTRY.get(id);
}
@Deprecated
public static final EntityTypes get(final int ordinal) {
return values[ordinal];
}
public static int size() {
return values.length;
}
}
}

View File

@ -19,29 +19,58 @@
package com.sk89q.worldedit.world.item;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.blocks.BaseItem;
import com.sk89q.worldedit.extension.platform.Capability;
import com.sk89q.worldedit.registry.NamespacedRegistry;
import com.sk89q.worldedit.world.block.BlockType;
import com.sk89q.worldedit.world.block.BlockTypes;
import com.sk89q.worldedit.world.registry.LegacyMapper;
import javax.annotation.Nullable;
public interface ItemType {
public class ItemType {
default ItemTypes toEnum() {
return (ItemTypes) this;
public static final NamespacedRegistry<ItemType> REGISTRY = new NamespacedRegistry<>("item type");
private String id;
private BlockType blockType;
private int internalId;
private BaseItem defaultState;
public ItemType(String id) {
// If it has no namespace, assume minecraft.
if (!id.contains(":")) {
id = "minecraft:" + id;
}
this.id = id;
this.blockType = BlockTypes.get(this.id);
}
String getId();
int getInternalId();
public String getId() {
return this.id;
}
public int getInternalId() {
return this.internalId;
}
public void setInternalId(int internalId) {
this.internalId = internalId;
}
/**
* Gets the name of this item, or the ID if the name cannot be found.
*
* @return The name, or ID
*/
String getName();
public String getName() {
String name = WorldEdit.getInstance().getPlatformManager().queryCapability(Capability.GAME_HOOKS).getRegistries().getItemRegistry().getName(this);
if (name == null) {
return getId();
} else {
return name;
}
}
/**
@ -49,7 +78,7 @@ public interface ItemType {
*
* @return If it has a block
*/
default boolean hasBlockType() {
public boolean hasBlockType() {
return getBlockType() != null;
}
@ -59,11 +88,34 @@ public interface ItemType {
* @return The block representation
*/
@Nullable
default BlockTypes getBlockType() {
return BlockTypes.get(getId());
public BlockType getBlockType() {
return this.blockType;
}
public void setBlockType(BlockType blockType) {
this.blockType = blockType;
}
public BaseItem getDefaultState() {
return this.defaultState;
}
public void setDefaultState(BaseItem defaultState) {
this.defaultState = defaultState;
}
default BaseItem getDefaultState() {
return new BaseItem(this);
@Override
public String toString() {
return getId();
}
}
@Override
public int hashCode() {
return this.id.hashCode();
}
@Override
public boolean equals(Object obj) {
return obj instanceof ItemType && this.id.equals(((ItemType) obj).id);
}
}

View File

@ -55,7 +55,7 @@ public interface BlockRegistry {
* @param blockType the block
* @return a map of states where the key is the state's ID
*/
Map<String, ? extends Property> getProperties(BlockType blockType);
Map<String, ? extends Property<?>> getProperties(BlockType blockType);
/**

View File

@ -41,7 +41,7 @@ public class BundledBlockRegistry implements BlockRegistry {
@Nullable
@Override
public Map<String, ? extends Property> getProperties(BlockType blockType) {
public Map<String, ? extends Property<?>> getProperties(BlockType blockType) {
return Collections.emptyMap(); // Oof
}

View File

@ -44,4 +44,11 @@ public class BundledItemRegistry implements ItemRegistry {
public Collection<String> registerItems() {
return Collections.emptyList();
}
@Nullable
@Override
public String getName(ItemType itemType) {
BundledItemData.ItemEntry itemEntry = BundledItemData.getInstance().findById(itemType.getId());
return itemEntry != null ? itemEntry.localizedName : null;
}
}

View File

@ -22,6 +22,7 @@ package com.sk89q.worldedit.world.registry;
import com.sk89q.worldedit.blocks.BaseItem;
import com.sk89q.worldedit.entity.BaseEntity;
import com.sk89q.worldedit.entity.Entity;
import com.sk89q.worldedit.world.entity.EntityType;
import com.sk89q.worldedit.world.entity.EntityTypes;
import com.sk89q.worldedit.world.item.ItemType;
import com.sk89q.worldedit.world.item.ItemTypes;
@ -43,7 +44,7 @@ public interface EntityRegistry {
*/
@Nullable
default BaseEntity createFromId(String id) {
EntityTypes entType = EntityTypes.get(id);
EntityType entType = EntityTypes.get(id);
return entType == null ? null : new BaseEntity(entType);
}

View File

@ -20,6 +20,7 @@
package com.sk89q.worldedit.world.registry;
import com.sk89q.worldedit.blocks.BaseItem;
import com.sk89q.worldedit.world.item.ItemType;
import javax.annotation.Nullable;
import java.util.Collection;
@ -42,5 +43,14 @@ public interface ItemRegistry {
default Collection<String> registerItems() {
return Collections.emptyList();
}
/**
* Gets the name for the given item.
*
* @param itemType the item
* @return The name, or null if it's unknown
*/
@Nullable
String getName(ItemType itemType);
}

View File

@ -57,7 +57,7 @@ public class LegacyMapper {
private final Int2ObjectArrayMap<Integer> blockStateToLegacyId4Data = new Int2ObjectArrayMap<>();
private final Int2ObjectArrayMap<Integer> extraId4DataToStateId = new Int2ObjectArrayMap<>();
private final int[] blockArr = new int[4096];
private final BiMap<Integer, ItemTypes> itemMap = HashBiMap.create();
private final BiMap<Integer, ItemType> itemMap = HashBiMap.create();
/**
* Create a new instance.
@ -96,7 +96,7 @@ public class LegacyMapper {
try {
BlockStateHolder blockState = BlockState.get(null, blockEntry.getValue());
// BlockState blockState = WorldEdit.getInstance().getBlockFactory().parseFromInput(blockEntry.getValue(), parserContext).toImmutableState();
BlockTypes type = blockState.getBlockType();
BlockType type = blockState.getBlockType();
if (type.hasProperty(PropertyKey.WATERLOGGED)) {
blockState = blockState.with(PropertyKey.WATERLOGGED, false);
}
@ -134,11 +134,11 @@ public class LegacyMapper {
}
@Nullable
public ItemTypes getItemFromLegacy(int legacyId) {
public ItemType getItemFromLegacy(int legacyId) {
return itemMap.get(legacyId << 4);
}
public ItemTypes getItemFromLegacy(String input) {
public ItemType getItemFromLegacy(String input) {
if (input.startsWith("minecraft:")) input = input.substring(10);
return itemMap.get(getCombinedId(input));
}
@ -149,7 +149,7 @@ public class LegacyMapper {
}
@Nullable
public ItemTypes getItemFromLegacy(int legacyId, int data) {
public ItemType getItemFromLegacy(int legacyId, int data) {
return itemMap.get((legacyId << 4) + data);
}