This commit is contained in:
Jesse Boyd 2019-07-18 04:24:21 +10:00
parent 905fbf5a0b
commit ff94a1e5ed
No known key found for this signature in database
GPG Key ID: 59F1DE6293AF6E1F
26 changed files with 326 additions and 381 deletions

View File

@ -9,25 +9,14 @@ import com.boydti.fawe.object.number.MutableLong;
import com.boydti.fawe.util.MainUtil;
import com.boydti.fawe.util.MathMan;
import com.boydti.fawe.util.ReflectionUtils;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.jnbt.IntTag;
import com.sk89q.jnbt.ListTag;
import com.sk89q.jnbt.NBTConstants;
import com.sk89q.jnbt.NBTInputStream;
import com.sk89q.jnbt.NBTOutputStream;
import com.sk89q.jnbt.Tag;
import com.sk89q.jnbt.*;
import com.sk89q.worldedit.world.biome.BiomeType;
import com.sk89q.worldedit.world.biome.BiomeTypes;
import java.io.DataOutput;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.UUID;
import java.util.*;
import java.util.function.BiConsumer;
public class MCAChunk extends FaweChunk<Void> {
@ -88,9 +77,6 @@ public class MCAChunk extends FaweChunk<Void> {
}
public void write(NBTOutputStream nbtOut) throws IOException {
nbtOut.writeNamedTagName("", NBTConstants.TYPE_COMPOUND);
nbtOut.writeLazyCompoundTag("Level", out -> {
out.writeNamedTag("V", (byte) 1);
@ -107,7 +93,7 @@ public class MCAChunk extends FaweChunk<Void> {
out.writeNamedEmptyList("TileEntities");
} else {
out.writeNamedTag("TileEntities", new ListTag(CompoundTag.class,
new ArrayList<>(tiles.values())));
new ArrayList<>(tiles.values())));
}
out.writeNamedTag("InhabitedTime", inhabitedTime);
out.writeNamedTag("LastUpdate", lastUpdate);
@ -116,9 +102,12 @@ public class MCAChunk extends FaweChunk<Void> {
}
out.writeNamedTag("HeightMap", heightMap);
out.writeNamedTagName("Sections", NBTConstants.TYPE_LIST);
nbtOut.writeByte(NBTConstants.TYPE_COMPOUND);
int len = (int) Arrays.stream(ids).filter(Objects::nonNull).count();
nbtOut.writeInt(len);
nbtOut.getOutputStream().writeByte(NBTConstants.TYPE_COMPOUND);
int len = 0;
for (int[] id : ids) {
if (id != null) len++;
}
nbtOut.getOutputStream().writeInt(len);
for (int layer = 0; layer < ids.length; layer++) {
int[] idLayer = ids[layer];
if (idLayer == null) {
@ -436,9 +425,9 @@ public class MCAChunk extends FaweChunk<Void> {
blockLight = new byte[16][];
NBTStreamer streamer = new NBTStreamer(nis);
streamer.addReader(".Level.InhabitedTime",
(BiConsumer<Integer, Long>) (index, value) -> inhabitedTime = value);
(BiConsumer<Integer, Long>) (index, value) -> inhabitedTime = value);
streamer.addReader(".Level.LastUpdate",
(BiConsumer<Integer, Long>) (index, value) -> lastUpdate = value);
(BiConsumer<Integer, Long>) (index, value) -> lastUpdate = value);
streamer.addReader(".Level.Sections.#", (BiConsumer<Integer, CompoundTag>) (index, tag) -> {
int layer = tag.getByte("Y");
ids[layer] = tag.getIntArray("Blocks");
@ -446,31 +435,31 @@ public class MCAChunk extends FaweChunk<Void> {
blockLight[layer] = tag.getByteArray("BlockLight");
});
streamer.addReader(".Level.TileEntities.#",
(BiConsumer<Integer, CompoundTag>) (index, tile) -> {
int x1 = tile.getInt("x") & 15;
int y = tile.getInt("y");
int z1 = tile.getInt("z") & 15;
short pair = MathMan.tripleBlockCoord(x1, y, z1);
tiles.put(pair, tile);
});
(BiConsumer<Integer, CompoundTag>) (index, tile) -> {
int x1 = tile.getInt("x") & 15;
int y = tile.getInt("y");
int z1 = tile.getInt("z") & 15;
short pair = MathMan.tripleBlockCoord(x1, y, z1);
tiles.put(pair, tile);
});
streamer.addReader(".Level.Entities.#",
(BiConsumer<Integer, CompoundTag>) (index, entityTag) -> {
if (entities == null) {
entities = new HashMap<>();
}
long least = entityTag.getLong("UUIDLeast");
long most = entityTag.getLong("UUIDMost");
entities.put(new UUID(most, least), entityTag);
});
(BiConsumer<Integer, CompoundTag>) (index, entityTag) -> {
if (entities == null) {
entities = new HashMap<>();
}
long least = entityTag.getLong("UUIDLeast");
long most = entityTag.getLong("UUIDMost");
entities.put(new UUID(most, least), entityTag);
});
streamer.addReader(".Level.Biomes",
(BiConsumer<Integer, byte[]>) (index, value) -> biomes = value);
(BiConsumer<Integer, byte[]>) (index, value) -> biomes = value);
streamer.addReader(".Level.HeightMap",
(BiConsumer<Integer, int[]>) (index, value) -> heightMap = value);
(BiConsumer<Integer, int[]>) (index, value) -> heightMap = value);
if (readPos) {
streamer.addReader(".Level.xPos",
(BiConsumer<Integer, Integer>) (index, value) -> MCAChunk.this.setLoc(getParent(), value, getZ()));
(BiConsumer<Integer, Integer>) (index, value) -> MCAChunk.this.setLoc(getParent(), value, getZ()));
streamer.addReader(".Level.zPos",
(BiConsumer<Integer, Integer>) (index, value) -> MCAChunk.this.setLoc(getParent(), getX(), value));
(BiConsumer<Integer, Integer>) (index, value) -> MCAChunk.this.setLoc(getParent(), getX(), value));
}
streamer.readFully();
}
@ -610,14 +599,14 @@ public class MCAChunk extends FaweChunk<Void> {
public BiomeType[] getBiomeArray() {
BiomeType[] arr = new BiomeType[256];
for (int i = 0; i < arr.length; i++) {
arr[i] = BiomeTypes.register(biomes[i]);
arr[i] = BiomeTypes.get(biomes[i]);
}
return arr;
}
@Override
public BiomeType getBiomeType(int x, int z) {
return BiomeTypes.register(biomes[(x & 15) + ((z & 15) << 4)]);
return BiomeTypes.get(biomes[(x & 15) + ((z & 15) << 4)]);
}
@Override
@ -804,4 +793,4 @@ public class MCAChunk extends FaweChunk<Void> {
public FaweChunk call() {
throw new UnsupportedOperationException("Not supported");
}
}
}

View File

@ -41,7 +41,8 @@ public class FaweTimer implements Runnable {
if (tick < lastGetTPSTick + tickInterval) {
return lastGetTPSValue;
}
double total = Arrays.stream(history).sum();
double total = 0;
for (double v : history) total += v;
lastGetTPSValue = total / history.length;
lastGetTPSTick = tick;
return lastGetTPSValue;

View File

@ -408,7 +408,6 @@ public class PlatformManager {
}
try {
Tool tool = session.getTool(player.getItemInHand(HandSide.MAIN_HAND).getType());
switch (event.getInputType()) {
case PRIMARY: {
if (getConfiguration().navigationWandMaxDistance > 0 && player.getItemInHand(HandSide.MAIN_HAND).getType().getId().equals(getConfiguration().navigationWand)) {
@ -426,7 +425,7 @@ public class PlatformManager {
event.setCancelled(true);
return;
}
Tool tool = session.getTool(player);
if (tool instanceof DoubleActionTraceTool && tool.canUse(player)) {
FawePlayer<?> fp = FawePlayer.wrap(player);
fp.runAsyncIfFree(() -> reset((DoubleActionTraceTool) tool).actSecondary(queryCapability(Capability.WORLD_EDITING), getConfiguration(), player, session));
@ -450,7 +449,7 @@ public class PlatformManager {
event.setCancelled(true);
return;
}
Tool tool = session.getTool(player);
if (tool instanceof TraceTool && tool.canUse(player)) {
FawePlayer<?> fp = FawePlayer.wrap(player);
//todo this needs to be fixed so the event is canceled after actPrimary is used and returns true

View File

@ -62,7 +62,9 @@ import java.util.Map;
/**
* Reads schematic files that are compatible with MCEdit and other editors.
* @deprecated Use SchematicStreamer
*/
@Deprecated
public class MCEditSchematicReader extends NBTSchematicReader {
private static final Logger log = LoggerFactory.getLogger(MCEditSchematicReader.class);
@ -355,6 +357,10 @@ public class MCEditSchematicReader extends NBTSchematicReader {
private String convertBlockEntityId(String id) {
switch (id) {
case "Chest":
return "chest";
case "Sign":
return "sign";
case "Cauldron":
return "brewing_stand";
case "Control":

View File

@ -125,49 +125,22 @@ public class SpongeSchematicReader extends NBTSchematicReader {
}
}
private Clipboard reader(UUID uuid) throws IOException {
NamedTag rootTag = inputStream.readNamedTag();
if (!rootTag.getName().equals("Schematic")) {
throw new IOException("Tag 'Schematic' does not exist or is not first");
}
CompoundTag schematicTag = (CompoundTag) rootTag.getTag();
// Check
Map<String, Tag> schematic = schematicTag.getValue();
int version = requireTag(schematic, "Version", IntTag.class).getValue();
final Platform platform = WorldEdit.getInstance().getPlatformManager()
.queryCapability(Capability.WORLD_EDITING);
int liveDataVersion = platform.getDataVersion();
if (version == 1) {
dataVersion = 1631; // this is a relatively safe assumption unless someone imports a schematic from 1.12, e.g. sponge 7.1-
fixer = platform.getDataFixer();
return readVersion1(uuid);
} else if (version == 2) {
dataVersion = requireTag(schematic, "DataVersion", IntTag.class).getValue();
if (dataVersion > liveDataVersion) {
log.warn("Schematic was made in a newer Minecraft version ({} > {}). Data may be incompatible.",
dataVersion, liveDataVersion);
} else if (dataVersion < liveDataVersion) {
fixer = platform.getDataFixer();
if (fixer != null) {
log.info("Schematic was made in an older Minecraft version ({} < {}), will attempt DFU.",
dataVersion, liveDataVersion);
} else {
log.info("Schematic was made in an older Minecraft version ({} < {}), but DFU is not available. Data may be incompatible.",
dataVersion, liveDataVersion);
}
}
BlockArrayClipboard clip = readVersion1(uuid);
return readVersion2(clip, schematicTag);
}
throw new IOException("This schematic version is currently not supported");
private String fix(String palettePart) {
if (fixer == null || dataVersion == -1) return palettePart;
return fixer.fixUp(DataFixer.FixTypes.BLOCK_STATE, palettePart, dataVersion);
}
private BlockArrayClipboard readVersion1(UUID uuid) throws IOException {
private CompoundTag fixBlockEntity(CompoundTag tag) {
if (fixer == null || dataVersion == -1) return tag;
return fixer.fixUp(DataFixer.FixTypes.BLOCK_ENTITY, tag, dataVersion);
}
private CompoundTag fixEntity(CompoundTag tag) {
if (fixer == null || dataVersion == -1) return tag;
return fixer.fixUp(DataFixer.FixTypes.ENTITY, tag, dataVersion);
}
private Clipboard reader(UUID uuid) throws IOException {
width = height = length = offsetX = offsetY = offsetZ = Integer.MIN_VALUE;
final BlockArrayClipboard clipboard = new BlockArrayClipboard(new CuboidRegion(BlockVector3.at(0, 0, 0), BlockVector3.at(0, 0, 0)), fc);
@ -176,6 +149,7 @@ public class SpongeSchematicReader extends NBTSchematicReader {
NBTStreamer streamer = new NBTStreamer(inputStream);
streamer.addReader("Schematic.DataVersion", (BiConsumer<Integer, Short>) (i, v) -> dataVersion = v);
streamer.addReader("Schematic.Width", (BiConsumer<Integer, Short>) (i, v) -> width = v);
streamer.addReader("Schematic.Height", (BiConsumer<Integer, Short>) (i, v) -> height = v);
streamer.addReader("Schematic.Length", (BiConsumer<Integer, Short>) (i, v) -> length = v);
@ -188,7 +162,8 @@ public class SpongeSchematicReader extends NBTSchematicReader {
for (Map.Entry<String, Tag> entry : v.entrySet()) {
BlockState state = null;
try {
state = BlockState.get(entry.getKey());
String palettePart = fix(entry.getKey());
state = BlockState.get(palettePart);
} catch (InputParseException e) {
e.printStackTrace();
}
@ -196,6 +171,9 @@ public class SpongeSchematicReader extends NBTSchematicReader {
palette[index] = (char) state.getOrdinal();
}
});
/// readBiomes
streamer.addReader("Schematic.BlockData.#", new NBTStreamer.LazyReader() {
@Override
public void accept(Integer arrayLen, DataInputStream dis) {
@ -224,21 +202,40 @@ public class SpongeSchematicReader extends NBTSchematicReader {
int x = pos[0];
int y = pos[1];
int z = pos[2];
Map<String, Tag> values = value.getValue();
Tag id = values.get("Id");
if (id != null) {
values.put("x", new IntTag(x));
values.put("y", new IntTag(y));
values.put("z", new IntTag(z));
values.put("id", id);
}
values.remove("Id");
values.remove("Pos");
value = fixBlockEntity(value);
fc.setTile(x, y, z, value);
});
streamer.addReader("Schematic.Entities.#", (BiConsumer<Integer, CompoundTag>) (index, compound) -> {
if (fc == null) {
setupClipboard(0, uuid);
}
String id = compound.getString("id");
if (id.isEmpty()) {
return;
Map<String, Tag> value = compound.getValue();
StringTag id = (StringTag) value.get("Id");
if (id == null) {
id = (StringTag) value.get("id");
if (id == null) {
return;
}
} else {
value.put("id", id);
value.remove("Id");
}
ListTag positionTag = compound.getListTag("Pos");
ListTag directionTag = compound.getListTag("Rotation");
EntityType type = EntityTypes.parse(id);
EntityType type = EntityTypes.parse(id.getValue());
if (type != null) {
compound.getValue().put("Id", new StringTag(type.getId()));
compound = fixEntity(compound);
BaseEntity state = new BaseEntity(type, compound);
fc.createEntity(clipboard, positionTag.asDouble(0), positionTag.asDouble(1), positionTag.asDouble(2), (float) directionTag.asDouble(0), (float) directionTag.asDouble(1), state);
} else {
@ -274,7 +271,7 @@ public class SpongeSchematicReader extends NBTSchematicReader {
try (FaweInputStream fis = new FaweInputStream(new LZ4BlockInputStream(new FastByteArraysInputStream(biomesOut.toByteArrays())))) {
int volume = width * length;
for (int index = 0; index < volume; index++) {
fc.setBiome(index, BiomeTypes.register(fis.read()));
fc.setBiome(index, BiomeTypes.get(fis.read()));
}
}
}
@ -283,17 +280,6 @@ public class SpongeSchematicReader extends NBTSchematicReader {
return clipboard;
}
private Clipboard readVersion2(BlockArrayClipboard version1, CompoundTag schematicTag) throws IOException {
Map<String, Tag> schematic = schematicTag.getValue();
if (schematic.containsKey("BiomeData")) {
readBiomes(version1, schematic);
}
if (schematic.containsKey("Entities")) {
readEntities(version1, schematic);
}
return version1;
}
private void readBiomes(BlockArrayClipboard clipboard, Map<String, Tag> schematic) throws IOException {
ByteArrayTag dataTag = requireTag(schematic, "BiomeData", ByteArrayTag.class);
IntTag maxTag = requireTag(schematic, "BiomePaletteMax", IntTag.class);
@ -309,7 +295,7 @@ public class SpongeSchematicReader extends NBTSchematicReader {
if (fixer != null) {
key = fixer.fixUp(DataFixer.FixTypes.BIOME, key, dataVersion);
}
BiomeType biome = BiomeTypes.register(key);
BiomeType biome = BiomeTypes.get(key);
if (biome == null) {
log.warn("Unknown biome type :" + key +
" in palette. Are you missing a mod or using a schematic made in a newer version of Minecraft?");
@ -352,37 +338,6 @@ public class SpongeSchematicReader extends NBTSchematicReader {
}
}
private void readEntities(BlockArrayClipboard clipboard, Map<String, Tag> schematic) throws IOException {
List<Tag> entList = requireTag(schematic, "Entities", ListTag.class).getValue();
if (entList.isEmpty()) {
return;
}
for (Tag et : entList) {
if (!(et instanceof CompoundTag)) {
continue;
}
CompoundTag entityTag = (CompoundTag) et;
Map<String, Tag> tags = entityTag.getValue();
String id = requireTag(tags, "Id", StringTag.class).getValue();
entityTag = entityTag.createBuilder().putString("id", id).remove("Id").build();
if (fixer != null) {
entityTag = fixer.fixUp(DataFixer.FixTypes.ENTITY, entityTag, dataVersion);
}
EntityType entityType = EntityTypes.get(id);
if (entityType != null) {
Location location = NBTConversions.toLocation(clipboard,
requireTag(tags, "Pos", ListTag.class),
requireTag(tags, "Rotation", ListTag.class));
BaseEntity state = new BaseEntity(entityType, entityTag);
clipboard.createEntity(location, state);
} else {
log.warn("Unknown entity when pasting schematic: " + id);
}
}
}
@Override
public void close() throws IOException {
inputStream.close();

View File

@ -25,8 +25,10 @@ import com.boydti.fawe.util.IOUtil;
import static com.google.common.base.Preconditions.checkNotNull;
import com.google.common.collect.Maps;
import com.sk89q.jnbt.*;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.entity.BaseEntity;
import com.sk89q.worldedit.entity.Entity;
import com.sk89q.worldedit.extension.platform.Capability;
import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard;
import com.sk89q.worldedit.extent.clipboard.Clipboard;
import com.sk89q.worldedit.math.BlockVector2;
@ -107,7 +109,8 @@ public class SpongeSchematicWriter implements ClipboardWriter {
final DataOutput rawStream = outputStream.getOutputStream();
outputStream.writeLazyCompoundTag("Schematic", out -> {
out.writeNamedTag("Version", 1);
out.writeNamedTag("DataVersion", WorldEdit.getInstance().getPlatformManager().queryCapability(Capability.WORLD_EDITING).getDataVersion());
out.writeNamedTag("Version", CURRENT_VERSION);
out.writeNamedTag("Width", (short) width);
out.writeNamedTag("Height", (short) height);
out.writeNamedTag("Length", (short) length);
@ -224,6 +227,11 @@ public class SpongeSchematicWriter implements ClipboardWriter {
out.writeNamedEmptyList("TileEntities");
}
if (clipboard.hasBiomes()) {
writeBiomes(clipboard, out);
}
TODO optimize
List<Tag> entities = new ArrayList<>();
for (Entity entity : clipboard.getEntities()) {
BaseEntity state = entity.getState();
@ -238,7 +246,8 @@ public class SpongeSchematicWriter implements ClipboardWriter {
}
// Store our location data, overwriting any
values.put("id", new StringTag(state.getType().getId()));
values.remove("id");
values.put("Id", new StringTag(state.getType().getId()));
values.put("Pos", writeVector(entity.getLocation()));
values.put("Rotation", writeRotation(entity.getLocation()));
@ -251,20 +260,11 @@ public class SpongeSchematicWriter implements ClipboardWriter {
} else {
out.writeNamedTag("Entities", new ListTag(CompoundTag.class, entities));
}
// version 2 stuff
if (clipboard.hasBiomes()) {
writeBiomes(clipboard, out);
}
if (!clipboard.getEntities().isEmpty()) {
writeEntities(clipboard, out);
}
});
}
private void writeBiomes(Clipboard clipboard, NBTOutputStream schematic) throws IOException {
TODO optimize
BlockVector3 min = clipboard.getMinimumPoint();
int width = clipboard.getRegion().getWidth();
int length = clipboard.getRegion().getLength();

View File

@ -94,11 +94,19 @@ public class BlockTransformExtent extends ResettableExtent {
}
private static long[] adapt(Direction... dirs) {
return Arrays.stream(dirs).mapToLong(dir -> 1L << dir.ordinal()).toArray();
long[] arr = new long[dirs.length];
for (int i = 0; i < arr.length; i++) {
arr[i] = 1L << dirs[i].ordinal();
}
return arr;
}
private static long[] adapt(Long... dirs) {
return Arrays.stream(dirs).mapToLong(dir -> dir).toArray();
long[] arr = new long[dirs.length];
for (int i = 0; i < arr.length; i++) {
arr[i] = dirs[i];
}
return arr;
}
private static long[] getDirections(AbstractProperty property) {
@ -506,37 +514,4 @@ public class BlockTransformExtent extends ResettableExtent {
public boolean setBlock(int x, int y, int z, BlockStateHolder block) throws WorldEditException {
return super.setBlock(x, y, z, transformInverse(block));
}
/**
* 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
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 (Direction v : allowedStates) {
double dot = v.toVector().normalize().dot(newDirection);
if (dot >= closest) {
closest = dot;
newValue = v.toVector();
found = true;
}
}
if (found) {
return newValue;
} else {
return null;
}
}
}

View File

@ -34,7 +34,7 @@ import java.util.List;
*/
public class CombinedRegionFunction implements RegionFunction {
private final List<RegionFunction> functions = new ArrayList<>();
private RegionFunction[] functions;
/**
* Create a combined region function.
@ -49,7 +49,7 @@ public class CombinedRegionFunction implements RegionFunction {
*/
public CombinedRegionFunction(Collection<RegionFunction> functions) {
checkNotNull(functions);
this.functions.addAll(functions);
this.functions = functions.toArray(new RegionFunction[functions.size()]);
}
/**
@ -58,7 +58,7 @@ public class CombinedRegionFunction implements RegionFunction {
* @param function an array of functions to match
*/
public CombinedRegionFunction(RegionFunction... function) {
this(Arrays.asList(checkNotNull(function)));
this.functions = function;
}
public static CombinedRegionFunction combine(RegionFunction function, RegionFunction add) {
@ -82,7 +82,9 @@ public class CombinedRegionFunction implements RegionFunction {
*/
public void add(Collection<RegionFunction> functions) {
checkNotNull(functions);
this.functions.addAll(functions);
ArrayList<RegionFunction> functionsList = new ArrayList<>(Arrays.asList(this.functions));
functionsList.addAll(functions);
this.functions = functionsList.toArray(new RegionFunction[functionsList.size()]);
}
/**
@ -98,11 +100,9 @@ public class CombinedRegionFunction implements RegionFunction {
public boolean apply(BlockVector3 position) throws WorldEditException {
boolean ret = false;
for (RegionFunction function : functions) {
if (function.apply(position)) {
ret = true;
}
ret |= (function.apply(position));
}
return ret;
}
}
}

View File

@ -80,14 +80,7 @@ public class Naturalizer implements LayerFunction {
}
private boolean naturalize(BlockVector3 position, int depth) throws WorldEditException {
BlockState block = editSession.getBlock(position);
BlockState targetBlock = getTargetBlock(depth);
if (block.equalsFuzzy(targetBlock)) {
return false;
}
return editSession.setBlock(position, targetBlock);
return editSession.setBlock(position, getTargetBlock(depth));
}
@Override

View File

@ -110,7 +110,7 @@ public class BlockTypeMask extends AbstractExtentMask {
@Override
public boolean test(BlockVector3 vector) {
return types[getExtent().getBlock(vector).getInternalId()];
return types[getExtent().getBlock(vector).getBlockType().getInternalId()];
}
@Nullable

View File

@ -15,7 +15,7 @@ public class SingleBlockTypeMask extends AbstractExtentMask {
@Override
public boolean test(BlockVector3 vector) {
return getExtent().getBlock(vector).getInternalId() == internalId;
return getExtent().getBlock(vector).getBlockType().getInternalId() == internalId;
}
@Override

View File

@ -3,12 +3,15 @@ package com.sk89q.worldedit.function.operation;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.function.RegionFunction;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.math.MutableBlockVector3;
import com.sk89q.worldedit.math.MutableVector3;
import com.sk89q.worldedit.math.Vector3;
import com.sk89q.worldedit.math.transform.Transform;
import com.sk89q.worldedit.regions.CuboidRegion;
import com.sk89q.worldedit.regions.Region;
import java.util.List;
import java.util.Vector;
public class BackwardsExtentBlockCopy implements Operation {
private final Region region;
@ -16,7 +19,8 @@ public class BackwardsExtentBlockCopy implements Operation {
private final RegionFunction function;
private final BlockVector3 origin;
// private Vector mutable = new MutableBlockVector3();
private MutableBlockVector3 mutBV3 = new MutableBlockVector3();
private MutableVector3 mutV3 = new MutableVector3();
BackwardsExtentBlockCopy(Region region, BlockVector3 origin, Transform transform, RegionFunction function) {
this.region = region;
@ -56,7 +60,14 @@ public class BackwardsExtentBlockCopy implements Operation {
}
private BlockVector3 transform(Transform transform, BlockVector3 pt) {
return transform.apply(Vector3.at(pt.getBlockX() - origin.getBlockX(), pt.getBlockY() - origin.getBlockY(), pt.getBlockZ() - origin.getBlockZ())).toBlockPoint().add(origin.getBlockX(), origin.getBlockY(), origin.getBlockZ());
mutV3.mutX(((pt.getBlockX() - origin.getBlockX())));
mutV3.mutY(((pt.getBlockY() - origin.getBlockY())));
mutV3.mutZ(((pt.getBlockZ() - origin.getBlockZ())));
Vector3 tmp = transform.apply(mutV3);
mutBV3.mutX((tmp.getBlockX() + origin.getBlockX()));
mutBV3.mutY((tmp.getBlockY() + origin.getBlockY()));
mutBV3.mutZ((tmp.getBlockZ() + origin.getBlockZ()));
return mutBV3;
}
@Override

View File

@ -75,7 +75,7 @@ public class ForwardExtentCopy implements Operation {
private int repetitions = 1;
private Mask sourceMask = Masks.alwaysTrue();
private boolean removingEntities;
private boolean copyingEntities = true; // default to true for backwards compatibility, sort of
private boolean copyingEntities = true; // default to true for backwards compatibility, sort of // No, it's not for compatibility, it makes sense for entities to be copied and people will get annoyed if it doesn't
private boolean copyingBiomes;
private RegionFunction sourceFunction = null;
private Transform transform = new Identity();

View File

@ -27,6 +27,8 @@ import com.sk89q.worldedit.WorldEditException;
*/
public final class Operations {
private static final RunContext context = new RunContext();
private Operations() {
}
@ -38,7 +40,7 @@ public final class Operations {
*/
public static void complete(Operation op) throws WorldEditException {
while (op != null) {
op = op.resume(new RunContext());
op = op.resume(context);
}
}
@ -52,7 +54,7 @@ public final class Operations {
public static void completeLegacy(Operation op) throws MaxChangedBlocksException {
while (op != null) {
try {
op = op.resume(new RunContext());
op = op.resume(context);
} catch (MaxChangedBlocksException e) {
throw e;
} catch (WorldEditException e) {
@ -71,7 +73,7 @@ public final class Operations {
public static void completeBlindly(Operation op) {
while (op != null) {
try {
op = op.resume(new RunContext());
op = op.resume(context);
} catch (WorldEditException e) {
throw new RuntimeException(e);
}

View File

@ -19,7 +19,9 @@
package com.sk89q.worldedit.function.pattern;
import com.sk89q.minecraft.util.commands.Link;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.command.UtilityCommands;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.world.block.BaseBlock;
@ -28,6 +30,7 @@ import com.sk89q.worldedit.world.block.BlockStateHolder;
/**
* Returns a {@link BlockStateHolder} for a given position.
*/
@Link(clazz = UtilityCommands.class, value = "patterns")
public interface Pattern {
/**

View File

@ -20,28 +20,60 @@
package com.sk89q.worldedit.function.pattern;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.function.mask.BlockMaskBuilder;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.registry.state.Property;
import com.sk89q.worldedit.registry.state.PropertyKey;
import com.sk89q.worldedit.world.block.BaseBlock;
import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.block.BlockType;
import com.sk89q.worldedit.world.block.BlockTypes;
import java.lang.ref.SoftReference;
import java.util.Map;
import java.util.function.BiPredicate;
import java.util.function.Predicate;
/**
* Removes the waterlogged state from blocks if possible. If not possible, returns air.
*/
public class WaterloggedRemover extends AbstractExtentPattern {
private static SoftReference<BlockState[]> cache = new SoftReference<>(null);
private synchronized BlockState[] getRemap() {
BlockState[] remap = this.cache.get();
if (remap != null) return remap;
this.cache = new SoftReference<>(remap = new BlockState[BlockTypes.states.length]);
// init
for (int i = 0; i < remap.length; i++) {
BlockState state = remap[i];
BlockType type = state.getBlockType();
if (!type.hasProperty(PropertyKey.WATERLOGGED)) {
continue;
}
if (state.getState(PropertyKey.WATERLOGGED) == Boolean.TRUE) {
remap[i] = state.with(PropertyKey.WATERLOGGED, false);
}
}
return remap;
}
private final BlockState[] remap;
public WaterloggedRemover(Extent extent) {
super(extent);
this.remap = getRemap();
}
@Override
public BaseBlock apply(BlockVector3 position) {
BaseBlock block = getExtent().getFullBlock(position);
@SuppressWarnings("unchecked")
Property<Object> prop = (Property<Object>) block.getBlockType().getPropertyMap().getOrDefault("waterlogged", null);
if (prop != null) {
return block.with(prop, false);
BlockState newState = remap[block.getOrdinal()];
if (newState != null) {
return newState.toBaseBlock(block.getNbtData());
}
return BlockTypes.AIR.getDefaultState().toBaseBlock();
}
}
}

View File

@ -39,7 +39,9 @@ import java.util.List;
/**
* Utility class to apply region functions to {@link com.sk89q.worldedit.regions.Region}.
* @deprecated let the queue iterate, not the region function which lacks any kind of optimizations / parallelism
*/
@Deprecated
public class RegionVisitor implements Operation {
public final Region region;

View File

@ -19,6 +19,7 @@
package com.sk89q.worldedit.math;
import com.google.common.collect.ComparisonChain;
import com.sk89q.worldedit.math.transform.AffineTransform;
import java.util.Comparator;
@ -47,26 +48,18 @@ public class BlockVector2 {
* cdef
* </pre>
*/
public static final Comparator<BlockVector2> COMPARING_GRID_ARRANGEMENT =
Comparator.comparingInt(BlockVector2::getZ).thenComparingInt(BlockVector2::getX);
public static final Comparator<BlockVector2> COMPARING_GRID_ARRANGEMENT = (a, b) -> {
return ComparisonChain.start()
.compare(a.getBlockZ(), b.getBlockZ())
.compare(a.getBlockX(), b.getBlockX())
.result();
};
public static BlockVector2 at(double x, double z) {
return at((int) Math.floor(x), (int) Math.floor(z));
}
public static BlockVector2 at(int x, int z) {
switch (x) {
case 0:
if (z == 0) {
return ZERO;
}
break;
case 1:
if (z == 1) {
return ONE;
}
break;
}
return new BlockVector2(x, z);
}
@ -349,27 +342,6 @@ public class BlockVector2 {
return divide(n, n);
}
/**
* Shift all components right.
*
* @param x the value to shift x by
* @param z the value to shift z by
* @return a new vector
*/
public BlockVector2 shr(int x, int z) {
return at(this.x >> x, this.z >> z);
}
/**
* Shift all components right by {@code n}.
*
* @param n the value to shift by
* @return a new vector
*/
public BlockVector2 shr(int n) {
return shr(n, n);
}
/**
* Get the length of the vector.
*
@ -519,8 +491,8 @@ public class BlockVector2 {
*/
public BlockVector2 getMinimum(BlockVector2 v2) {
return new BlockVector2(
Math.min(x, v2.x),
Math.min(z, v2.z)
Math.min(x, v2.x),
Math.min(z, v2.z)
);
}
@ -532,8 +504,8 @@ public class BlockVector2 {
*/
public BlockVector2 getMaximum(BlockVector2 v2) {
return new BlockVector2(
Math.max(x, v2.x),
Math.max(z, v2.z)
Math.max(x, v2.x),
Math.max(z, v2.z)
);
}
@ -599,4 +571,5 @@ public class BlockVector2 {
public String toString() {
return "(" + x + ", " + z + ")";
}
}
}

View File

@ -44,20 +44,6 @@ public class BlockVector3 {
}
public static BlockVector3 at(int x, int y, int z) {
// switch for efficiency on typical cases
// in MC y is rarely 0/1 on selections
switch (y) {
case 0:
if (x == 0 && z == 0) {
return ZERO;
}
break;
case 1:
if (x == 1 && z == 1) {
return ONE;
}
break;
}
return new BlockVector3(x, y, z);
}

View File

@ -33,19 +33,6 @@ public class Vector2 {
public static final Vector2 ONE = new Vector2(1, 1);
public static Vector2 at(double x, double z) {
int xTrunc = (int) x;
switch (xTrunc) {
case 0:
if (x == 0 && z == 0) {
return ZERO;
}
break;
case 1:
if (x == 1 && z == 1) {
return ONE;
}
break;
}
return new Vector2(x, z);
}

View File

@ -39,21 +39,6 @@ public class Vector3 {
public static final Vector3 ONE = new Vector3(1, 1, 1);
public static Vector3 at(double x, double y, double z) {
// switch for efficiency on typical cases
// in MC y is rarely 0/1 on selections
int yTrunc = (int) y;
switch (yTrunc) {
case 0:
if (x == 0 && y == 0 && z == 0) {
return ZERO;
}
break;
case 1:
if (x == 1 && y == 1 && z == 1) {
return ONE;
}
break;
}
return new Vector3(x, y, z);
}
@ -651,9 +636,9 @@ public class Vector3 {
@Override
public String toString() {
String x = "" + getX();
String y = "" + getY();
String z = "" + getZ();
String x = (getX() == getBlockX() ? "" + getBlockX() : "" + getX());
String y = (getY() == getBlockY() ? "" + getBlockY() : "" + getY());
String z = (getZ() == getBlockZ() ? "" + getBlockZ() : "" + getZ());
return "(" + x + ", " + y + ", " + z + ")";
}

View File

@ -65,7 +65,7 @@ public class BiomeType implements RegistryItem, Keyed {
@Override
public int hashCode() {
return this.id.hashCode();
return this.internalId; // stop changing this
}
@Override

View File

@ -280,11 +280,7 @@ public class BaseBlock implements BlockStateHolder<BaseBlock>, TileEntityBlock {
@Override
public int hashCode() {
int ret = toImmutableState().hashCode() << 3;
if (hasNbtData()) {
ret += getNbtData().hashCode();
}
return ret;
return blockState.hashCode(); // stop changing this
}
@Override

View File

@ -280,17 +280,16 @@ public class BlockState implements BlockStateHolder<BlockState>, FawePattern {
@Override
public boolean equalsFuzzy(BlockStateHolder<?> o) {
if (null == o) {
return false;
}
if (this == o) {
// Added a reference equality check for speediness
return true;
}
if (o.getClass() == BlockState.class) {
return o.getOrdinal() == this.getOrdinal();
}
if (null == o) {
return false;
}
return o.equalsFuzzy(this);
}

View File

@ -99,6 +99,18 @@ public class BlockType implements FawePattern, Keyed {
}
}
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);
}
@Deprecated
public BlockState withPropertyId(int propertyId) {
if (settings.stateOrdinals == null) return settings.defaultState;
@ -140,11 +152,7 @@ public class BlockType implements FawePattern, Keyed {
* @return The property
*/
public <V> Property<V> getProperty(String name) {
// Assume it works, CCE later at runtime if not.
@SuppressWarnings("unchecked")
Property<V> property = (Property<V>) getPropertyMap().get(name);
checkArgument(property != null, "%s has no property named %s", this, name);
return property;
return (Property<V>) this.settings.propertiesMap.get(name); // stop changing this (performance)
}
public boolean hasProperty(PropertyKey key) {
@ -269,12 +277,12 @@ public class BlockType implements FawePattern, Keyed {
@Override
public int hashCode() {
return this.id.hashCode();
return settings.internalId; // stop changing this to WEs bad hashcode
}
@Override
public boolean equals(Object obj) {
return obj instanceof BlockType && this.id.equals(((BlockType) obj).id);
return obj == this; // stop changing this to a shitty string comparison
}

View File

@ -20,6 +20,7 @@
package com.sk89q.worldedit.world.entity;
import javax.annotation.Nullable;
import java.util.Locale;
public class EntityTypes {
@ -133,71 +134,113 @@ public class EntityTypes {
return EntityType.REGISTRY.get(id);
}
public static EntityType parse(String id) {
private static String convertEntityId(String id) {
if (id.startsWith("minecraft:")) id = id.substring(10);
switch (id) {
case "FallingSand": return EntityTypes.FALLING_BLOCK;
case "FireworksRocketEntity": return EntityTypes.FIREWORK_ROCKET;
case "LavaSlime": return EntityTypes.MAGMA_CUBE;
case "MinecartChest": return EntityTypes.CHEST_MINECART;
case "MinecartCommandBlock": return EntityTypes.COMMAND_BLOCK_MINECART;
case "MinecartFurnace": return EntityTypes.FURNACE_MINECART;
case "MinecartHopper": return EntityTypes.HOPPER_MINECART;
case "MinecartRideable": return EntityTypes.MINECART;
case "MinecartSpawner": return EntityTypes.SPAWNER_MINECART;
case "MinecartTNT": return EntityTypes.TNT_MINECART;
case "MushroomCow": return EntityTypes.MOOSHROOM;
case "PigZombie": return EntityTypes.ZOMBIE_PIGMAN;
case "PrimedTnt": return EntityTypes.TNT;
case "SnowMan": return EntityTypes.SNOW_GOLEM;
case "ThrownEgg": return EntityTypes.EGG;
case "ThrownEnderpearl": return EntityTypes.ENDER_PEARL;
case "ThrownExpBottle": return EntityTypes.EXPERIENCE_BOTTLE;
case "ThrownPotion": return EntityTypes.POTION;
case "WitherBoss": return EntityTypes.WITHER;
case "XPOrb": return EntityTypes.EXPERIENCE_ORB;
default:
switch(id) {
case "AreaEffectCloud": return "area_effect_cloud";
case "ArmorStand": return "armor_stand";
case "CaveSpider": return "cave_spider";
case "MinecartChest": return "chest_minecart";
case "DragonFireball": return "dragon_fireball";
case "ThrownEgg": return "egg";
case "EnderDragon": return "ender_dragon";
case "ThrownEnderpearl": return "ender_pearl";
case "FallingSand": return "falling_block";
case "FireworksRocketEntity": return "fireworks_rocket";
case "MinecartFurnace": return "furnace_minecart";
case "MinecartHopper": return "hopper_minecart";
case "EntityHorse": return "horse";
case "ItemFrame": return "item_frame";
case "LeashKnot": return "leash_knot";
case "LightningBolt": return "lightning_bolt";
case "LavaSlime": return "magma_cube";
case "MinecartRideable": return "minecart";
case "MushroomCow": return "mooshroom";
case "Ozelot": return "ocelot";
case "PolarBear": return "polar_bear";
case "ThrownPotion": return "potion";
case "ShulkerBullet": return "shulker_bullet";
case "SmallFireball": return "small_fireball";
case "MinecartSpawner": return "spawner_minecart";
case "SpectralArrow": return "spectral_arrow";
case "PrimedTnt": return "tnt";
case "MinecartTNT": return "tnt_minecart";
case "VillagerGolem": return "villager_golem";
case "WitherBoss": return "wither";
case "WitherSkull": return "wither_skull";
case "PigZombie": return "zombie_pigman";
case "XPOrb": return "experience_orb";
case "ThrownExpBottle": return "experience_bottle";
case "EyeOfEnderSignal": return "eye_of_ender";
case "EnderCrystal": return "end_crystal";
case "MinecartCommandBlock": return "command_block_minecart";
case "SnowMan": return "snow_golem";
case "areaeffectcloud": return "area_effect_cloud";
case "armorstand": return "armor_stand";
case "cavespider": return "cave_spider";
case "minecartchest": return "chest_minecart";
case "dragonfireball": return "dragon_fireball";
case "thrownegg": return "egg";
case "enderdragon": return "ender_dragon";
case "thrownenderpearl": return "ender_pearl";
case "fallingsand": return "falling_block";
case "fireworksrocketentity": return "fireworks_rocket";
case "minecartfurnace": return "furnace_minecart";
case "minecarthopper": return "hopper_minecart";
case "entityhorse": return "horse";
case "itemframe": return "item_frame";
case "leashknot": return "leash_knot";
case "lightningbolt": return "lightning_bolt";
case "lavaslime": return "magma_cube";
case "minecartrideable": return "minecart";
case "mushroomcow": return "mooshroom";
case "ozelot": return "ocelot";
case "polarbear": return "polar_bear";
case "thrownpotion": return "potion";
case "shulkerbullet": return "shulker_bullet";
case "smallfireball": return "small_fireball";
case "minecartspawner": return "spawner_minecart";
case "spectralarrow": return "spectral_arrow";
case "primedtnt": return "tnt";
case "minecarttnt": return "tnt_minecart";
case "villagergolem": return "villager_golem";
case "witherboss": return "wither";
case "witherskull": return "wither_skull";
case "pigzombie": return "zombie_pigman";
case "xporb":
case "xp_orb":
return "experience_orb";
case "thrownexpbottle":
case "xp_bottle":
return "experience_bottle";
case "eyeofendersignal":
case "eye_of_ender_signal":
return "eye_of_ender";
case "endercrystal":
case "ender_crystal":
return "end_crystal";
case "fireworks_rocket": return "firework_rocket";
case "minecartcommandblock":
case "commandblock_minecart":
return "command_block_minecart";
case "snowman":
return "snow_golem";
case "villager_golem": return "iron_golem";
case "evocation_fangs": return "evoker_fangs";
case "evocation_illager": return "evoker";
case "vindication_illager": return "vindicator";
case "illusion_illager": return "illusioner";
default: {
if (Character.isUpperCase(id.charAt(0))) {
StringBuilder result = new StringBuilder();
for (int i = 0; i < id.length(); i++) {
char c = id.charAt(i);
if (Character.isUpperCase(c)) {
c = Character.toLowerCase(c);
if (i != 0) result.append('_');
}
result.append(c);
}
return parse(result.toString());
}
switch (id.toLowerCase()) {
case "xp_orb":
return EntityTypes.EXPERIENCE_ORB;
case "xp_bottle":
return EntityTypes.EXPERIENCE_BOTTLE;
case "eye_of_ender_signal":
return EntityTypes.EYE_OF_ENDER;
case "ender_crystal":
return EntityTypes.END_CRYSTAL;
case "fireworks_rocket":
return EntityTypes.FIREWORK_ROCKET;
case "commandblock_minecart":
return EntityTypes.COMMAND_BLOCK_MINECART;
case "snowman":
return EntityTypes.SNOW_GOLEM;
case "villager_golem":
return EntityTypes.IRON_GOLEM;
case "evocation_fangs":
return EntityTypes.EVOKER_FANGS;
case "evocation_illager":
return EntityTypes.EVOKER;
case "vindication_illager":
return EntityTypes.VINDICATOR;
case "illusion_illager":
return EntityTypes.ILLUSIONER;
default:
return get(id);
return convertEntityId(id.toLowerCase(Locale.ROOT));
}
return id;
}
}
}
public static EntityType parse(String id) {
return get(convertEntityId(id));
}
}