Reorder BuildInClipboardFormat and document changed JNBT classes (#807)

* Get rid of FastSchematicReader/Writer and document changed JNBT classes

This commit includes changes from upstream to the schematic classes
(`com.sk89q.worldedit.extent.clipboard.io`). It also documents the JNBT
classes, specifying what has been changed in FAWE. This was done in preparation
for the upcoming move to adventure-nbt.

The PlotSquared schematic handler classes will now use SpongeSchematicReader/Writer rather than FastSchematicReader/Writer.

This is yet untested and the entire branch is a W.I.P.

* Fix JNBT mutability misuse in FAWE

FAWE previously had mutable compound and list tags. The previous commit changed that, and this commit will fix misuse of the tag API.

I've tried to identify the places where mutability was assumed, but I might have missed something. This needs quite extensive testing.

This is yet another change which increases upstream compatibility in FAWE.

* Fix FAWE_Spigot_<..>#getEntity

* Fix JNBT usage in the AsyncBlockState code

* Readd FastSchematicReader/Writer and add a new schematic format (`FAST`)

* Update dead repository

* Implement missing AsyncChunk#getTileEntities

* handle entities properly and add "brokenentity" format

* Fix fast schematic reader
lazily reading means it's read in order of appearance in the inputstream so we need to read schematic version first (skip past everything) and then reset the stream

* Fix p2 FAWE

* Go back to fast schematics in P2/CompressedSchematicTag (#819)

* Fix compile

Co-authored-by: N0tMyFaultOG <mc.cache@web.de>
Co-authored-by: Alexander Söderberg <Sauilitired@users.noreply.github.com>
Co-authored-by: dordsor21 <dordsor21@gmail.com>
Co-authored-by: Aurora <aurora@relanet.eu>
This commit is contained in:
Alexander Söderberg 2021-01-04 19:18:23 +01:00 committed by GitHub
parent efcca5b66f
commit 3f0b9a2a92
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
56 changed files with 559 additions and 995 deletions

View File

@ -23,6 +23,7 @@ repositories {
name = "ProtocolLib Repo"
url = uri("https://repo.dmulloy2.net/nexus/repository/public/")
}
maven { url = uri("https://repo.inventivetalent.org/content/groups/public/") }
flatDir {dir(File("src/main/resources"))}
}
@ -71,7 +72,7 @@ dependencies {
"compile"("org.bstats:bstats-bukkit:1.8")
"compile"("com.intellectualsites.paster:Paster:1.0.1-SNAPSHOT")
// Third party
"implementation"("com.github.InventivetalentDev:MapManager:1.7.+") { isTransitive = false }
compileOnlyApi("org.inventivetalent:mapmanager:1.7.+") { isTransitive = false }
"implementation"("com.github.TechFortress:GriefPrevention:16.+") { isTransitive = false }
"implementation"("com.massivecraft:mcore:7.0.1") { isTransitive = false }
"implementation"("com.bekvon.bukkit.residence:Residence:4.5._13.1") { isTransitive = false }

View File

@ -12,15 +12,18 @@ import net.minecraft.server.v1_15_R1.NBTTagList;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Supplier;
public class LazyCompoundTag_1_15_2 extends CompoundTag {
private final Supplier<NBTTagCompound> nmsTag;
private CompoundTag cachedValue;
public LazyCompoundTag_1_15_2(Supplier<NBTTagCompound> tag) {
super(null);
super(new HashMap<>());
this.nmsTag = tag;
}
@ -34,12 +37,10 @@ public class LazyCompoundTag_1_15_2 extends CompoundTag {
@Override
public Map<String, Tag> getValue() {
Map<String, Tag> value = super.getValue();
if (value == null) {
Tag tag = WorldEditPlugin.getInstance().getBukkitImplAdapter().toNative(nmsTag.get());
setValue(((CompoundTag) tag).getValue());
if (cachedValue == null) {
cachedValue = (CompoundTag) WorldEditPlugin.getInstance().getBukkitImplAdapter().toNative(nmsTag.get());
}
return super.getValue();
return cachedValue.getValue();
}
public boolean containsKey(String key) {

View File

@ -12,15 +12,18 @@ import net.minecraft.server.v1_16_R1.NBTTagList;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Supplier;
public class LazyCompoundTag_1_16_1 extends CompoundTag {
private final Supplier<NBTTagCompound> nmsTag;
private CompoundTag cachedValue;
public LazyCompoundTag_1_16_1(Supplier<NBTTagCompound> tag) {
super(null);
super(new HashMap<>());
this.nmsTag = tag;
}
@ -34,12 +37,10 @@ public class LazyCompoundTag_1_16_1 extends CompoundTag {
@Override
public Map<String, Tag> getValue() {
Map<String, Tag> value = super.getValue();
if (value == null) {
Tag tag = WorldEditPlugin.getInstance().getBukkitImplAdapter().toNative(nmsTag.get());
setValue(((CompoundTag) tag).getValue());
if (cachedValue == null) {
cachedValue = (CompoundTag) WorldEditPlugin.getInstance().getBukkitImplAdapter().toNative(nmsTag.get());
}
return super.getValue();
return cachedValue.getValue();
}
public boolean containsKey(String key) {

View File

@ -12,15 +12,18 @@ import net.minecraft.server.v1_16_R2.NBTTagList;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Supplier;
public class LazyCompoundTag_1_16_2 extends CompoundTag {
private final Supplier<NBTTagCompound> nmsTag;
private CompoundTag cachedValue;
public LazyCompoundTag_1_16_2(Supplier<NBTTagCompound> tag) {
super(null);
super(new HashMap<>());
this.nmsTag = tag;
}
@ -34,12 +37,10 @@ public class LazyCompoundTag_1_16_2 extends CompoundTag {
@Override
public Map<String, Tag> getValue() {
Map<String, Tag> value = super.getValue();
if (value == null) {
Tag tag = WorldEditPlugin.getInstance().getBukkitImplAdapter().toNative(nmsTag.get());
setValue(((CompoundTag) tag).getValue());
if (cachedValue == null) {
cachedValue = (CompoundTag) WorldEditPlugin.getInstance().getBukkitImplAdapter().toNative(nmsTag.get());
}
return super.getValue();
return cachedValue.getValue();
}
public boolean containsKey(String key) {

View File

@ -12,15 +12,18 @@ import net.minecraft.server.v1_16_R3.NBTTagList;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Supplier;
public class LazyCompoundTag_1_16_4 extends CompoundTag {
private final Supplier<NBTTagCompound> nmsTag;
private CompoundTag cachedValue;
public LazyCompoundTag_1_16_4(Supplier<NBTTagCompound> tag) {
super(null);
super(new HashMap<>());
this.nmsTag = tag;
}
@ -34,12 +37,10 @@ public class LazyCompoundTag_1_16_4 extends CompoundTag {
@Override
public Map<String, Tag> getValue() {
Map<String, Tag> value = super.getValue();
if (value == null) {
Tag tag = WorldEditPlugin.getInstance().getBukkitImplAdapter().toNative(nmsTag.get());
setValue(((CompoundTag) tag).getValue());
if (cachedValue == null) {
cachedValue = (CompoundTag) WorldEditPlugin.getInstance().getBukkitImplAdapter().toNative(nmsTag.get());
}
return super.getValue();
return cachedValue.getValue();
}
public boolean containsKey(String key) {

View File

@ -1,6 +1,5 @@
package com.boydti.fawe.bukkit.regions.plotsquared;
import com.boydti.fawe.FaweAPI;
import com.boydti.fawe.FaweCache;
import com.boydti.fawe.object.clipboard.ReadOnlyClipboard;
import com.boydti.fawe.object.io.PGZIPOutputStream;
@ -16,10 +15,10 @@ import com.plotsquared.core.util.SchematicHandler;
import com.plotsquared.core.util.task.RunnableVal;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.jnbt.CompressedCompoundTag;
import com.sk89q.jnbt.CompressedSchematicTag;
import com.sk89q.jnbt.NBTInputStream;
import com.sk89q.jnbt.NBTOutputStream;
import com.sk89q.jnbt.Tag;
import com.sk89q.jnbt.fawe.CompressedSchematicTag;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.bukkit.BukkitAdapter;
import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard;

View File

@ -15,7 +15,7 @@ import com.github.intellectualsites.plotsquared.plot.util.SchematicHandler;
import com.github.intellectualsites.plotsquared.plot.util.block.LocalBlockQueue;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.jnbt.CompressedCompoundTag;
import com.sk89q.jnbt.CompressedSchematicTag;
import com.sk89q.jnbt.fawe.CompressedSchematicTag;
import com.sk89q.jnbt.NBTOutputStream;
import com.sk89q.jnbt.Tag;
import com.sk89q.worldedit.EditSession;
@ -65,6 +65,7 @@ public class FaweSchematicHandler extends SchematicHandler {
ReadOnlyClipboard clipboard = ReadOnlyClipboard.of(editSession, region, false, true);
Clipboard holder = new BlockArrayClipboard(region, clipboard);
CompressedSchematicTag tag = new CompressedSchematicTag(holder);
whenDone.run(tag);
});

View File

@ -1,6 +1,7 @@
package com.boydti.fawe.bukkit.wrapper;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.jnbt.Tag;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.bukkit.BukkitAdapter;
import com.sk89q.worldedit.world.block.BaseBlock;
@ -16,8 +17,12 @@ import org.bukkit.material.MaterialData;
import org.bukkit.metadata.MetadataValue;
import org.bukkit.plugin.Plugin;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
public class AsyncBlockState implements BlockState {
@ -25,10 +30,6 @@ public class AsyncBlockState implements BlockState {
private BlockData blockData;
private final AsyncBlock block;
public AsyncBlockState(AsyncBlock block) {
this(block, block.world.getFullBlock(block.x, block.y, block.z));
}
public AsyncBlockState(AsyncBlock block, BaseBlock state) {
this.state = state;
this.block = block;
@ -112,11 +113,11 @@ public class AsyncBlockState implements BlockState {
@Override
public void setBlockData(BlockData blockData) {
this.blockData = blockData;
CompoundTag nbt = state.getNbtData();
CompoundTag nbt = this.getNbtData();
BlockType oldType = state.getBlockType();
com.sk89q.worldedit.world.block.BlockState newState = BukkitAdapter.adapt(blockData);
if (nbt != null && newState.getBlockType() == oldType) {
state = newState.toBaseBlock(nbt);
this.setNbtData(nbt);
} else {
state = newState.toBaseBlock();
}
@ -146,14 +147,47 @@ public class AsyncBlockState implements BlockState {
}
}
public CompoundTag getNbtData() {
/**
* Returns the (unmodifiable) tag compound that belongs to this block state.
* If the block state is null, this will return null.
*
* @return NBT data
*/
public synchronized @Nullable CompoundTag getNbtData() {
if (this.state == null) {
return null;
}
return state.getNbtData();
}
public void setNbtData(CompoundTag nbt) {
/**
* Clone the NBT {@link CompoundTag} into a new {@link Map}.
*
* @return Modifiable clone of NBT data
*/
public @NotNull Map<String, Tag> cloneNbtMap() {
return Optional.ofNullable(this.getNbtData()).map(CompoundTag::getValue)
.map(HashMap::new).orElse(new HashMap<>());
}
/**
* Set the NBT data of the block.
*
* @param nbt New NBT data
*/
public synchronized void setNbtData(@Nullable final CompoundTag nbt) {
state = this.state.toBaseBlock(nbt);
}
/**
* Set the NBT data of the block.
*
* @param map New NBT data
*/
public void setNbtData(@NotNull final Map<String, Tag> map) {
this.setNbtData(new CompoundTag(map));
}
@Override
public byte getRawData() {
return (byte) (state.getInternalId() >> BlockTypesCache.BIT_OFFSET);
@ -163,7 +197,7 @@ public class AsyncBlockState implements BlockState {
public void setRawData(byte data) {
int combinedId = getTypeId() + (data << BlockTypesCache.BIT_OFFSET);
state = com.sk89q.worldedit.world.block.BlockState.getFromInternalId(combinedId)
.toBaseBlock(state.getNbtData());
.toBaseBlock(this.getNbtData());
this.blockData = BukkitAdapter.adapt(state);
}

View File

@ -16,17 +16,24 @@ import java.util.HashSet;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.function.Consumer;
import java.util.function.Supplier;
public final class AsyncDataContainer implements PersistentDataContainer {
private final CompoundTag root;
public AsyncDataContainer(CompoundTag root) {
this.root = root;
private final Supplier<CompoundTag> supplier;
private final Consumer<CompoundTag> consumer;
public AsyncDataContainer(
final @NotNull Supplier<CompoundTag> supplier,
final @NotNull Consumer<CompoundTag> consumer
) {
this.supplier = supplier;
this.consumer = consumer;
}
private CompoundTag root() {
CompoundTag value = (CompoundTag) root.getValue().get("PublicBukkitValues");
return value;
return (CompoundTag) supplier.get().getValue().get("PublicBukkitValues");
}
private Map<String, Tag> get() {
@ -40,8 +47,9 @@ public final class AsyncDataContainer implements PersistentDataContainer {
if (!create) {
return Collections.emptyMap();
}
Map<String, Tag> map = root.getValue();
final Map<String, Tag> map = new HashMap<>(root().getValue());
map.put("PublicBukkitValues", new CompoundTag(raw = new HashMap<>()));
this.consumer.accept(new CompoundTag(map));
} else {
raw = tag.getValue();
}
@ -52,7 +60,14 @@ public final class AsyncDataContainer implements PersistentDataContainer {
Validate.notNull(key, "The provided key for the custom value was null");
Validate.notNull(type, "The provided type for the custom value was null");
Validate.notNull(value, "The provided value for the custom value was null");
get().put(key.toString(), FaweCache.IMP.asTag(type.toPrimitive(value, null)));
// Modify public values
final Map<String, Tag> publicValues = new HashMap<>(this.get());
publicValues.put(key.toString(), FaweCache.IMP.asTag(type.toPrimitive(value, null)));
// Modify the root tag
final Map<String, Tag> map = new HashMap<>(root().getValue());
map.put("PublicBukkitValues", new CompoundTag(publicValues));
// Update the owning object
this.consumer.accept(new CompoundTag(map));
}
public <T, Z> boolean has(NamespacedKey key, PersistentDataType<T, Z> type) {
@ -60,7 +75,7 @@ public final class AsyncDataContainer implements PersistentDataContainer {
Validate.notNull(type, "The provided type for the custom value was null");
Tag value = get(false).get(key.toString());
if (value == null) {
return type == null;
return false;
}
return type.getPrimitiveType() == value.getValue().getClass();
}
@ -93,7 +108,14 @@ public final class AsyncDataContainer implements PersistentDataContainer {
public void remove(NamespacedKey key) {
Validate.notNull(key, "The provided key for the custom value was null");
get(false).remove(key.toString());
// Modify public values
final Map<String, Tag> publicValues = new HashMap<>(this.get(false));
publicValues.remove(key.toString());
// Modify the root tag
final Map<String, Tag> map = new HashMap<>(root().getValue());
map.put("PublicBukkitValues", new CompoundTag(publicValues));
// Update the owning object
this.consumer.accept(new CompoundTag(map));
}
public boolean isEmpty() {

View File

@ -19,6 +19,7 @@ import java.util.Locale;
import java.util.Map;
public class AsyncSign extends AsyncBlockState implements Sign {
public AsyncSign(AsyncBlock block, BaseBlock state) {
super(block, state);
}
@ -59,11 +60,12 @@ public class AsyncSign extends AsyncBlockState implements Sign {
@Override
public void setLine(int index, String line) throws IndexOutOfBoundsException {
CompoundTag nbt = getNbtData();
if (nbt != null) {
Map<String, Tag> map = nbt.getValue();
map.put("Text" + (index + 1), new StringTag(toJson(line)));
final Map<String, Tag> map = this.cloneNbtMap();
if (map.isEmpty()) {
return;
}
map.put("Text" + (index + 1), new StringTag(toJson(line)));
this.setNbtData(map);
}
@Override
@ -79,13 +81,13 @@ public class AsyncSign extends AsyncBlockState implements Sign {
@Override
@NotNull
public PersistentDataContainer getPersistentDataContainer() {
return new AsyncDataContainer(getNbtData());
return new AsyncDataContainer(this::getNbtData, this::setNbtData);
}
@Override
@Nullable
public DyeColor getColor() {
CompoundTag nbt = getNbtData();
CompoundTag nbt = this.getNbtData();
if (nbt != null) {
String color = nbt.getString("Color").toUpperCase(Locale.ROOT);
if (!color.isEmpty()) {
@ -97,10 +99,11 @@ public class AsyncSign extends AsyncBlockState implements Sign {
@Override
public void setColor(DyeColor color) {
CompoundTag nbt = getNbtData();
if (nbt != null) {
Map<String, Tag> map = nbt.getValue();
final Map<String, Tag> map = this.cloneNbtMap();
if (map.isEmpty()) {
return;
}
map.put("Color", new StringTag(color.name().toLowerCase(Locale.ROOT)));
}
this.setNbtData(map);
}
}

View File

@ -19,7 +19,6 @@
package com.sk89q.worldedit.bukkit.adapter.impl;
import com.boydti.fawe.Fawe;
import com.boydti.fawe.FaweCache;
import com.boydti.fawe.beta.IChunkGet;
import com.boydti.fawe.beta.implementation.packet.ChunkPacket;
@ -93,15 +92,15 @@ import org.bukkit.craftbukkit.v1_15_R1.entity.CraftPlayer;
import org.bukkit.craftbukkit.v1_15_R1.inventory.CraftItemStack;
import org.bukkit.entity.Player;
import javax.annotation.Nullable;
import java.lang.ref.WeakReference;
import java.util.HashMap;
import java.util.Map;
import java.util.OptionalInt;
import java.util.Set;
import java.util.function.Supplier;
import java.util.stream.Stream;
import javax.annotation.Nullable;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.slf4j.LoggerFactory.getLogger;
public final class FAWE_Spigot_v1_15_R2 extends CachedBukkitAdapter implements IDelegateBukkitImplAdapter<NBTBase> {
@ -271,13 +270,13 @@ public final class FAWE_Spigot_v1_15_R2 extends CachedBukkitAdapter implements I
if (id != null) {
EntityType type = com.sk89q.worldedit.world.entity.EntityTypes.get(id);
Supplier<CompoundTag> saveTag = () -> {
NBTTagCompound tag = new NBTTagCompound();
readEntityIntoTag(mcEntity, tag);
final NBTTagCompound minecraftTag = new NBTTagCompound();
readEntityIntoTag(mcEntity, minecraftTag);
//add Id for AbstractChangeSet to work
CompoundTag natve = (CompoundTag) toNative(tag);
natve.getValue().put("Id", new StringTag(id));
return natve;
final CompoundTag tag = (CompoundTag) toNative(minecraftTag);
final Map<String, Tag> tags = new HashMap<>(tag.getValue());
tags.put("Id", new StringTag(id));
return new CompoundTag(tags);
};
return new LazyBaseEntity(type, saveTag);
} else {
@ -351,7 +350,6 @@ public final class FAWE_Spigot_v1_15_R2 extends CachedBukkitAdapter implements I
}
}
}
public int ordinalToIbdID(char ordinal) {
synchronized (this) {
try {

View File

@ -92,15 +92,15 @@ import org.bukkit.craftbukkit.v1_16_R1.entity.CraftPlayer;
import org.bukkit.craftbukkit.v1_16_R1.inventory.CraftItemStack;
import org.bukkit.entity.Player;
import javax.annotation.Nullable;
import java.lang.ref.WeakReference;
import java.util.HashMap;
import java.util.Map;
import java.util.OptionalInt;
import java.util.Set;
import java.util.function.Supplier;
import java.util.stream.Stream;
import javax.annotation.Nullable;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.slf4j.LoggerFactory.getLogger;
public final class FAWE_Spigot_v1_16_R1 extends CachedBukkitAdapter implements IDelegateBukkitImplAdapter<NBTBase> {
@ -270,13 +270,13 @@ public final class FAWE_Spigot_v1_16_R1 extends CachedBukkitAdapter implements I
if (id != null) {
EntityType type = com.sk89q.worldedit.world.entity.EntityTypes.get(id);
Supplier<CompoundTag> saveTag = () -> {
NBTTagCompound tag = new NBTTagCompound();
readEntityIntoTag(mcEntity, tag);
final NBTTagCompound minecraftTag = new NBTTagCompound();
readEntityIntoTag(mcEntity, minecraftTag);
//add Id for AbstractChangeSet to work
CompoundTag natve = (CompoundTag) toNative(tag);
natve.getValue().put("Id", new StringTag(id));
return natve;
final CompoundTag tag = (CompoundTag) toNative(minecraftTag);
final Map<String, Tag> tags = new HashMap<>(tag.getValue());
tags.put("Id", new StringTag(id));
return new CompoundTag(tags);
};
return new LazyBaseEntity(type, saveTag);
} else {

View File

@ -92,15 +92,16 @@ import org.bukkit.craftbukkit.v1_16_R2.entity.CraftEntity;
import org.bukkit.craftbukkit.v1_16_R2.entity.CraftPlayer;
import org.bukkit.craftbukkit.v1_16_R2.inventory.CraftItemStack;
import org.bukkit.entity.Player;
import javax.annotation.Nullable;
import java.lang.ref.WeakReference;
import java.util.HashMap;
import java.util.Map;
import java.util.OptionalInt;
import java.util.Set;
import java.util.function.Supplier;
import java.util.stream.Stream;
import javax.annotation.Nullable;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.slf4j.LoggerFactory.getLogger;
public final class FAWE_Spigot_v1_16_R2 extends CachedBukkitAdapter implements IDelegateBukkitImplAdapter<NBTBase> {
@ -271,13 +272,13 @@ public final class FAWE_Spigot_v1_16_R2 extends CachedBukkitAdapter implements I
if (id != null) {
EntityType type = com.sk89q.worldedit.world.entity.EntityTypes.get(id);
Supplier<CompoundTag> saveTag = () -> {
NBTTagCompound tag = new NBTTagCompound();
readEntityIntoTag(mcEntity, tag);
final NBTTagCompound minecraftTag = new NBTTagCompound();
readEntityIntoTag(mcEntity, minecraftTag);
//add Id for AbstractChangeSet to work
CompoundTag natve = (CompoundTag) toNative(tag);
natve.getValue().put("Id", new StringTag(id));
return natve;
final CompoundTag tag = (CompoundTag) toNative(minecraftTag);
final Map<String, Tag> tags = new HashMap<>(tag.getValue());
tags.put("Id", new StringTag(id));
return new CompoundTag(tags);
};
return new LazyBaseEntity(type, saveTag);
} else {
@ -351,7 +352,6 @@ public final class FAWE_Spigot_v1_16_R2 extends CachedBukkitAdapter implements I
}
}
}
public int ordinalToIbdID(char ordinal) {
synchronized (this) {
try {

View File

@ -19,7 +19,6 @@
package com.sk89q.worldedit.bukkit.adapter.impl;
import com.bekvon.bukkit.residence.commands.material;
import com.boydti.fawe.FaweCache;
import com.boydti.fawe.beta.IChunkGet;
import com.boydti.fawe.beta.implementation.packet.ChunkPacket;
@ -96,6 +95,7 @@ import org.bukkit.entity.Player;
import javax.annotation.Nullable;
import java.lang.ref.WeakReference;
import java.util.HashMap;
import java.util.Map;
import java.util.OptionalInt;
import java.util.Set;
@ -272,13 +272,13 @@ public final class FAWE_Spigot_v1_16_R3 extends CachedBukkitAdapter implements I
if (id != null) {
EntityType type = com.sk89q.worldedit.world.entity.EntityTypes.get(id);
Supplier<CompoundTag> saveTag = () -> {
NBTTagCompound tag = new NBTTagCompound();
readEntityIntoTag(mcEntity, tag);
final NBTTagCompound minecraftTag = new NBTTagCompound();
readEntityIntoTag(mcEntity, minecraftTag);
//add Id for AbstractChangeSet to work
CompoundTag natve = (CompoundTag) toNative(tag);
natve.getValue().put("Id", new StringTag(id));
return natve;
final CompoundTag tag = (CompoundTag) toNative(minecraftTag);
final Map<String, Tag> tags = new HashMap<>(tag.getValue());
tags.put("Id", new StringTag(id));
return new CompoundTag(tags);
};
return new LazyBaseEntity(type, saveTag);
} else {

View File

@ -138,10 +138,8 @@ public abstract class AbstractChangeSet implements ChangeSet, IBatchProcessor {
}
if (!tilesTo.isEmpty()) {
for (Map.Entry<BlockVector3, CompoundTag> entry : tilesTo.entrySet()) {
CompoundTag nbt = entry.getValue();
BlockVector3 pos = entry.getKey();
MainUtil.setPosition(nbt, pos.getX() + bx, pos.getY(), pos.getZ() + bz);
addTileCreate(nbt);
addTileCreate(MainUtil.setPosition(entry.getValue(), pos.getX() + bx, pos.getY(), pos.getZ() + bz));
}
}
Set<UUID> entRemoves = set.getEntityRemoves();
@ -259,14 +257,12 @@ public abstract class AbstractChangeSet implements ChangeSet, IBatchProcessor {
public void add(EntityCreate change) {
CompoundTag tag = change.state.getNbtData();
MainUtil.setEntityInfo(tag, change.getEntity());
addEntityCreate(tag);
addEntityCreate(MainUtil.setEntityInfo(tag, change.getEntity()));
}
public void add(EntityRemove change) {
CompoundTag tag = change.state.getNbtData();
MainUtil.setEntityInfo(tag, change.getEntity());
addEntityRemove(tag);
addEntityRemove(MainUtil.setEntityInfo(tag, change.getEntity()));
}
@Override
@ -309,14 +305,12 @@ public abstract class AbstractChangeSet implements ChangeSet, IBatchProcessor {
if (from.hasNbtData()) {
CompoundTag nbt = from.getNbtData();
assert nbt != null;
MainUtil.setPosition(nbt, x, y, z);
addTileRemove(nbt);
addTileRemove(MainUtil.setPosition(nbt, x, y, z));
}
if (to.hasNbtData()) {
CompoundTag nbt = to.getNbtData();
assert nbt != null;
MainUtil.setPosition(nbt, x, y, z);
addTileCreate(nbt);
addTileCreate(MainUtil.setPosition(nbt, x, y, z));
}
int combinedFrom = from.getOrdinal();
int combinedTo = to.getOrdinal();
@ -332,8 +326,7 @@ public abstract class AbstractChangeSet implements ChangeSet, IBatchProcessor {
if (to.hasNbtData()) {
CompoundTag nbt = to.getNbtData();
assert nbt != null;
MainUtil.setPosition(nbt, x, y, z);
addTileCreate(nbt);
addTileCreate(MainUtil.setPosition(nbt, x, y, z));
}
int combinedTo = to.getInternalId();
add(x, y, z, combinedFrom, combinedTo);

View File

@ -24,6 +24,7 @@ import com.sk89q.worldedit.world.block.BlockTypes;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.annotation.Nullable;
import java.io.Closeable;
import java.io.DataInputStream;
import java.io.File;
@ -44,7 +45,6 @@ import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.stream.Collectors;
import javax.annotation.Nullable;
/**
* A clipboard with disk backed storage. (lower memory + loads on crash)
@ -390,11 +390,11 @@ public class DiskOptimizedClipboard extends LinearClipboard implements Closeable
@Override
public boolean setTile(int x, int y, int z, CompoundTag tag) {
nbtMap.put(new IntTriple(x, y, z), tag);
Map<String, Tag> values = tag.getValue();
final Map<String, Tag> values = new HashMap<>(tag.getValue());
values.put("x", new IntTag(x));
values.put("y", new IntTag(y));
values.put("z", new IntTag(z));
nbtMap.put(new IntTriple(x, y, z), new CompoundTag(values));
return true;
}

View File

@ -34,6 +34,9 @@ import net.jpountz.lz4.LZ4InputStream;
import net.jpountz.lz4.LZ4Utils;
import org.jetbrains.annotations.NotNull;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.imageio.ImageIO;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.BufferedOutputStream;
@ -66,6 +69,7 @@ import java.nio.file.attribute.BasicFileAttributes;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
@ -83,8 +87,6 @@ import java.util.zip.GZIPInputStream;
import java.util.zip.Inflater;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import javax.annotation.Nullable;
import javax.imageio.ImageIO;
import static java.lang.System.arraycopy;
import static org.slf4j.LoggerFactory.getLogger;
@ -448,24 +450,44 @@ public class MainUtil {
}
}
public static void setPosition(CompoundTag tag, int x, int y, int z) {
Map<String, Tag> value = tag.getValue();
/**
* Create a copy of the tag and modify the (x, y, z) coordinates
*
* @param tag Tag to copy
* @param x New X coordinate
* @param y New Y coordinate
* @param z New Z coordinate
* @return New tag
*/
public static @NotNull CompoundTag setPosition(@Nonnull CompoundTag tag, int x, int y, int z) {
Map<String, Tag> value = new HashMap<>(tag.getValue());
value.put("x", new IntTag(x));
value.put("y", new IntTag(y));
value.put("z", new IntTag(z));
return new CompoundTag(value);
}
public static void setEntityInfo(CompoundTag tag, Entity entity) {
Map<String, Tag> map = tag.getValue();
/**
* Create a copy of the tag and modify the entity inf
*
* @param tag Tag to copy
* @param entity Entity
* @return New tag
*/
public static @NotNull CompoundTag setEntityInfo(@NotNull CompoundTag tag, @NotNull Entity entity) {
Map<String, Tag> map = new HashMap<>(tag.getValue());
map.put("Id", new StringTag(entity.getState().getType().getId()));
ListTag pos = (ListTag) map.get("Pos");
if (pos != null) {
Location loc = entity.getLocation();
List<Tag> posList = ReflectionUtils.getList(pos.getValue());
// Create a copy, because the list is immutable...
List<Tag> posList = new ArrayList<>(pos.getValue());
posList.set(0, new DoubleTag(loc.getX()));
posList.set(1, new DoubleTag(loc.getY()));
posList.set(2, new DoubleTag(loc.getZ()));
map.put("Pos", new ListTag(pos.getType(), posList));
}
return new CompoundTag(map);
}
public static String getText(String url) throws IOException {

View File

@ -67,22 +67,6 @@ public class ReflectionUtils {
blankField(enumClass, "enumConstants"); // IBM JDK
}
public static <T> List<T> getList(List<T> list) {
try {
Class<? extends List<T>> clazz = (Class<? extends List<T>>) Class
.forName("java.util.Collections$UnmodifiableList");
if (!clazz.isInstance(list)) {
return list;
}
Field m = clazz.getDeclaredField("list");
m.setAccessible(true);
return (List<T>) m.get(list);
} catch (Throwable e) {
e.printStackTrace();
return list;
}
}
public static Object getHandle(Object wrapper) {
final Method getHandle = makeMethod(wrapper.getClass(), "getHandle");
return callMethod(getHandle, wrapper);

View File

@ -26,11 +26,6 @@ import java.util.Locale;
*/
public final class ByteArrayTag extends Tag {
@Override
public int getTypeCode() {
return NBTConstants.TYPE_BYTE_ARRAY;
}
private final byte[] value;
/**
@ -61,4 +56,11 @@ public final class ByteArrayTag extends Tag {
return "TAG_Byte_Array(" + hex + ")";
}
// FAWE Start
@Override
public int getTypeCode() {
return NBTConstants.TYPE_BYTE_ARRAY;
}
// FAWE End
}

View File

@ -19,14 +19,12 @@
package com.sk89q.jnbt;
import com.sk89q.jnbt.fawe.NumberTag;
/**
* The {@code TAG_Byte} tag.
*/
public final class ByteTag extends NumberTag {
@Override
public int getTypeCode() {
return NBTConstants.TYPE_BYTE;
}
private final byte value;
@ -50,4 +48,11 @@ public final class ByteTag extends NumberTag {
return "TAG_Byte(" + value + ")";
}
// FAWE Start
@Override
public int getTypeCode() {
return NBTConstants.TYPE_BYTE;
}
// FAWE End
}

View File

@ -19,6 +19,7 @@
package com.sk89q.jnbt;
import com.sk89q.jnbt.fawe.NumberTag;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.math.Vector3;
import com.sk89q.worldedit.util.Location;
@ -34,12 +35,7 @@ import java.util.UUID;
*/
public class CompoundTag extends Tag {
@Override
public int getTypeCode() {
return NBTConstants.TYPE_COMPOUND;
}
private Map<String, Tag> value;
private final Map<String, Tag> value;
/**
* Creates the tag with an empty name.
@ -48,7 +44,7 @@ public class CompoundTag extends Tag {
*/
public CompoundTag(Map<String, Tag> value) {
super();
this.value = value;
this.value = Collections.unmodifiableMap(value);
}
/**
@ -58,7 +54,7 @@ public class CompoundTag extends Tag {
* @return true if the tag contains the given key
*/
public boolean containsKey(String key) {
return getValue().containsKey(key);
return value.containsKey(key);
}
@Override
@ -66,17 +62,6 @@ public class CompoundTag extends Tag {
return value;
}
/**
* Return a new compound tag with the given values.
*
* @param value the value
* @return the new compound tag
*/
public CompoundTag setValue(Map<String, Tag> value) {
this.value = value;
return this;
}
/**
* Create a compound tag builder.
*
@ -96,7 +81,7 @@ public class CompoundTag extends Tag {
* @return a byte array
*/
public byte[] getByteArray(String key) {
Tag tag = getValue().get(key);
Tag tag = value.get(key);
if (tag instanceof ByteArrayTag) {
return ((ByteArrayTag) tag).getValue();
} else {
@ -114,7 +99,7 @@ public class CompoundTag extends Tag {
* @return a byte
*/
public byte getByte(String key) {
Tag tag = getValue().get(key);
Tag tag = value.get(key);
if (tag instanceof ByteTag) {
return ((ByteTag) tag).getValue();
} else {
@ -132,7 +117,7 @@ public class CompoundTag extends Tag {
* @return a double
*/
public double getDouble(String key) {
Tag tag = getValue().get(key);
Tag tag = value.get(key);
if (tag instanceof DoubleTag) {
return ((DoubleTag) tag).getValue();
} else {
@ -151,9 +136,25 @@ public class CompoundTag extends Tag {
* @return a double
*/
public double asDouble(String key) {
Tag tag = getValue().get(key);
if (tag instanceof NumberTag) {
return ((NumberTag) tag).getValue().doubleValue();
Tag tag = value.get(key);
if (tag instanceof ByteTag) {
return ((ByteTag) tag).getValue();
} else if (tag instanceof ShortTag) {
return ((ShortTag) tag).getValue();
} else if (tag instanceof IntTag) {
return ((IntTag) tag).getValue();
} else if (tag instanceof LongTag) {
return ((LongTag) tag).getValue();
} else if (tag instanceof FloatTag) {
return ((FloatTag) tag).getValue();
} else if (tag instanceof DoubleTag) {
return ((DoubleTag) tag).getValue();
} else {
return 0;
}
@ -169,7 +170,7 @@ public class CompoundTag extends Tag {
* @return a float
*/
public float getFloat(String key) {
Tag tag = getValue().get(key);
Tag tag = value.get(key);
if (tag instanceof FloatTag) {
return ((FloatTag) tag).getValue();
} else {
@ -187,7 +188,7 @@ public class CompoundTag extends Tag {
* @return an int array
*/
public int[] getIntArray(String key) {
Tag tag = getValue().get(key);
Tag tag = value.get(key);
if (tag instanceof IntArrayTag) {
return ((IntArrayTag) tag).getValue();
} else {
@ -205,7 +206,7 @@ public class CompoundTag extends Tag {
* @return an int
*/
public int getInt(String key) {
Tag tag = getValue().get(key);
Tag tag = value.get(key);
if (tag instanceof IntTag) {
return ((IntTag) tag).getValue();
} else {
@ -224,9 +225,25 @@ public class CompoundTag extends Tag {
* @return an int
*/
public int asInt(String key) {
Tag tag = getValue().get(key);
if (tag instanceof NumberTag) {
return ((NumberTag) tag).getValue().intValue();
Tag tag = value.get(key);
if (tag instanceof ByteTag) {
return ((ByteTag) tag).getValue();
} else if (tag instanceof ShortTag) {
return ((ShortTag) tag).getValue();
} else if (tag instanceof IntTag) {
return ((IntTag) tag).getValue();
} else if (tag instanceof LongTag) {
return ((LongTag) tag).getValue().intValue();
} else if (tag instanceof FloatTag) {
return ((FloatTag) tag).getValue().intValue();
} else if (tag instanceof DoubleTag) {
return ((DoubleTag) tag).getValue().intValue();
} else {
return 0;
}
@ -242,7 +259,7 @@ public class CompoundTag extends Tag {
* @return a list of tags
*/
public List<Tag> getList(String key) {
Tag tag = getValue().get(key);
Tag tag = value.get(key);
if (tag instanceof ListTag) {
return ((ListTag) tag).getValue();
} else {
@ -260,7 +277,7 @@ public class CompoundTag extends Tag {
* @return a tag list instance
*/
public ListTag getListTag(String key) {
Tag tag = getValue().get(key);
Tag tag = value.get(key);
if (tag instanceof ListTag) {
return (ListTag) tag;
} else {
@ -273,7 +290,7 @@ public class CompoundTag extends Tag {
*
* <p>If the key does not exist or its value is not a list tag,
* then an empty list will be returned. If the given key references
* a list but the list of a different type, then an empty
* a list but the list of of a different type, then an empty
* list will also be returned.</p>
*
* @param key the key
@ -283,7 +300,7 @@ public class CompoundTag extends Tag {
*/
@SuppressWarnings("unchecked")
public <T extends Tag> List<T> getList(String key, Class<T> listType) {
Tag tag = getValue().get(key);
Tag tag = value.get(key);
if (tag instanceof ListTag) {
ListTag listTag = (ListTag) tag;
if (listTag.getType().equals(listType)) {
@ -299,14 +316,14 @@ public class CompoundTag extends Tag {
/**
* Get a {@code long[]} named with the given key.
*
* <p>If the key does not exist or its value is not a long array tag,
* <p>If the key does not exist or its value is not an long array tag,
* then an empty array will be returned.</p>
*
* @param key the key
* @return an int array
*/
public long[] getLongArray(String key) {
Tag tag = getValue().get(key);
Tag tag = value.get(key);
if (tag instanceof LongArrayTag) {
return ((LongArrayTag) tag).getValue();
} else {
@ -324,7 +341,7 @@ public class CompoundTag extends Tag {
* @return a long
*/
public long getLong(String key) {
Tag tag = getValue().get(key);
Tag tag = value.get(key);
if (tag instanceof LongTag) {
return ((LongTag) tag).getValue();
} else {
@ -343,9 +360,25 @@ public class CompoundTag extends Tag {
* @return a long
*/
public long asLong(String key) {
Tag tag = getValue().get(key);
if (tag instanceof NumberTag) {
return ((NumberTag) tag).getValue().longValue();
Tag tag = value.get(key);
if (tag instanceof ByteTag) {
return ((ByteTag) tag).getValue();
} else if (tag instanceof ShortTag) {
return ((ShortTag) tag).getValue();
} else if (tag instanceof IntTag) {
return ((IntTag) tag).getValue();
} else if (tag instanceof LongTag) {
return ((LongTag) tag).getValue();
} else if (tag instanceof FloatTag) {
return ((FloatTag) tag).getValue().longValue();
} else if (tag instanceof DoubleTag) {
return ((DoubleTag) tag).getValue().longValue();
} else {
return 0L;
}
@ -361,7 +394,7 @@ public class CompoundTag extends Tag {
* @return a short
*/
public short getShort(String key) {
Tag tag = getValue().get(key);
Tag tag = value.get(key);
if (tag instanceof ShortTag) {
return ((ShortTag) tag).getValue();
} else {
@ -379,7 +412,7 @@ public class CompoundTag extends Tag {
* @return a string
*/
public String getString(String key) {
Tag tag = getValue().get(key);
Tag tag = value.get(key);
if (tag instanceof StringTag) {
return ((StringTag) tag).getValue();
} else {
@ -388,17 +421,17 @@ public class CompoundTag extends Tag {
}
@Override
public Map<String, Object> toRaw() {
HashMap<String, Object> raw = new HashMap<>();
if (this.getValue().isEmpty()) {
return raw;
public String toString() {
StringBuilder bldr = new StringBuilder();
bldr.append("TAG_Compound").append(": ").append(value.size()).append(" entries\r\n{\r\n");
for (Map.Entry<String, Tag> entry : value.entrySet()) {
bldr.append(" ").append(entry.getValue().toString().replaceAll("\r\n", "\r\n ")).append("\r\n");
}
for (Map.Entry<String, Tag> entry : getValue().entrySet()) {
raw.put(entry.getKey(), entry.getValue().toRaw());
}
return raw;
bldr.append("}");
return bldr.toString();
}
// FAWE Start
public UUID getUUID() {
long most = getLong("UUIDMost");
long least = getLong("UUIDLeast");
@ -421,15 +454,21 @@ public class CompoundTag extends Tag {
}
@Override
public String toString() {
Map<String, Tag> value = getValue();
StringBuilder bldr = new StringBuilder();
bldr.append("TAG_Compound").append(": ").append(getValue().size()).append(" entries\r\n{\r\n");
for (Map.Entry<String, Tag> entry : getValue().entrySet()) {
bldr.append(" ").append(entry.getValue().toString().replaceAll("\r\n", "\r\n ")).append("\r\n");
}
bldr.append("}");
return bldr.toString();
public int getTypeCode() {
return NBTConstants.TYPE_COMPOUND;
}
@Override
public Map<String, Object> toRaw() {
HashMap<String, Object> raw = new HashMap<>();
if (this.getValue().isEmpty()) {
return raw;
}
for (Map.Entry<String, Tag> entry : getValue().entrySet()) {
raw.put(entry.getKey(), entry.getValue().toRaw());
}
return raw;
}
// FAWE End
}

View File

@ -19,14 +19,12 @@
package com.sk89q.jnbt;
import com.sk89q.jnbt.fawe.NumberTag;
/**
* The {@code TAG_Double} tag.
*/
public final class DoubleTag extends NumberTag {
@Override
public int getTypeCode() {
return NBTConstants.TYPE_DOUBLE;
}
private final double value;
@ -50,4 +48,11 @@ public final class DoubleTag extends NumberTag {
return "TAG_Double(" + value + ")";
}
// FAWE Start
@Override
public int getTypeCode() {
return NBTConstants.TYPE_DOUBLE;
}
// FAWE End
}

View File

@ -24,11 +24,6 @@ package com.sk89q.jnbt;
*/
public final class EndTag extends Tag {
@Override
public int getTypeCode() {
return NBTConstants.TYPE_END;
}
@Override
public Object getValue() {
return null;
@ -39,4 +34,11 @@ public final class EndTag extends Tag {
return "TAG_End";
}
// FAWE Start
@Override
public int getTypeCode() {
return NBTConstants.TYPE_END;
}
// FAWE End
}

View File

@ -19,14 +19,12 @@
package com.sk89q.jnbt;
import com.sk89q.jnbt.fawe.NumberTag;
/**
* The {@code TAG_Float} tag.
*/
public final class FloatTag extends NumberTag {
@Override
public int getTypeCode() {
return NBTConstants.TYPE_FLOAT;
}
private final float value;
@ -50,4 +48,11 @@ public final class FloatTag extends NumberTag {
return "TAG_Float(" + value + ")";
}
// FAWE Start
@Override
public int getTypeCode() {
return NBTConstants.TYPE_FLOAT;
}
// FAWE End
}

View File

@ -28,11 +28,6 @@ import static com.google.common.base.Preconditions.checkNotNull;
*/
public final class IntArrayTag extends Tag {
@Override
public int getTypeCode() {
return NBTConstants.TYPE_INT_ARRAY;
}
private final int[] value;
/**
@ -64,4 +59,11 @@ public final class IntArrayTag extends Tag {
return "TAG_Int_Array(" + hex + ")";
}
// FAWE Start
@Override
public int getTypeCode() {
return NBTConstants.TYPE_INT_ARRAY;
}
// FAWE End
}

View File

@ -19,14 +19,12 @@
package com.sk89q.jnbt;
import com.sk89q.jnbt.fawe.NumberTag;
/**
* The {@code TAG_Int} tag.
*/
public final class IntTag extends NumberTag {
@Override
public int getTypeCode() {
return NBTConstants.TYPE_INT;
}
private final int value;
@ -50,4 +48,11 @@ public final class IntTag extends NumberTag {
return "TAG_Int(" + value + ")";
}
// FAWE Start
@Override
public int getTypeCode() {
return NBTConstants.TYPE_INT;
}
// FAWE End
}

View File

@ -19,10 +19,9 @@
package com.sk89q.jnbt;
import java.util.ArrayList;
import javax.annotation.Nullable;
import java.util.Collections;
import java.util.List;
import javax.annotation.Nullable;
import static com.google.common.base.Preconditions.checkNotNull;
@ -31,11 +30,6 @@ import static com.google.common.base.Preconditions.checkNotNull;
*/
public final class ListTag extends Tag {
@Override
public int getTypeCode() {
return NBTConstants.TYPE_LIST;
}
private final Class<? extends Tag> type;
private final List<Tag> value;
@ -421,18 +415,6 @@ public final class ListTag extends Tag {
}
}
@Override
public ArrayList toRaw() {
ArrayList<Object> raw = new ArrayList<>();
if (this.value.isEmpty()) {
return raw;
}
for (Tag elem : this.value) {
raw.add(elem.toRaw());
}
return raw;
}
@Override
public String toString() {
StringBuilder bldr = new StringBuilder();
@ -444,4 +426,11 @@ public final class ListTag extends Tag {
return bldr.toString();
}
// FAWE Start
@Override
public int getTypeCode() {
return NBTConstants.TYPE_LIST;
}
// FAWE End
}

View File

@ -28,11 +28,6 @@ import static com.google.common.base.Preconditions.checkNotNull;
*/
public class LongArrayTag extends Tag {
@Override
public int getTypeCode() {
return NBTConstants.TYPE_LONG_ARRAY;
}
private final long[] value;
/**
@ -64,4 +59,11 @@ public class LongArrayTag extends Tag {
return "TAG_Long_Array(" + hex + ")";
}
// FAWE Start
@Override
public int getTypeCode() {
return NBTConstants.TYPE_LONG_ARRAY;
}
// FAWE End
}

View File

@ -19,14 +19,12 @@
package com.sk89q.jnbt;
import com.sk89q.jnbt.fawe.NumberTag;
/**
* The {@code TAG_Long} tag.
*/
public final class LongTag extends NumberTag {
@Override
public int getTypeCode() {
return NBTConstants.TYPE_LONG;
}
private final long value;
@ -50,4 +48,11 @@ public final class LongTag extends NumberTag {
return "TAG_Long(" + value + ")";
}
// FAWE Start
@Override
public int getTypeCode() {
return NBTConstants.TYPE_LONG;
}
// FAWE End
}

View File

@ -20,14 +20,13 @@
package com.sk89q.jnbt;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
/**
* A class which holds constant values.
*/
public final class NBTConstants {
public static final Charset CHARSET = StandardCharsets.UTF_8;
public static final Charset CHARSET = Charset.forName("UTF-8");
public static final int TYPE_END = 0;
public static final int TYPE_BYTE = 1;

View File

@ -32,6 +32,8 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
// THIS CLASS HAS BEEN HEAVILY MODIFIED BY FAWE
/**
* This class reads <strong>NBT</strong>, or <strong>Named Binary Tag</strong>
* streams, and produces an object graph of subclasses of the {@code Tag}

View File

@ -32,6 +32,8 @@ import java.util.Map;
import static com.google.common.base.Preconditions.checkNotNull;
// THIS CLASS HAS BEEN HEAVILY MODIFIED BY FAWE
/**
* This class writes <strong>NBT</strong>, or <strong>Named Binary Tag</strong>
* {@code Tag} objects to an underlying {@code OutputStream}.

View File

@ -49,7 +49,7 @@ public final class NBTUtils {
return "TAG_Byte_Array";
} else if (clazz.equals(ByteTag.class)) {
return "TAG_Byte";
} else if (CompoundTag.class.isAssignableFrom(clazz)) {
} else if (clazz.equals(CompoundTag.class)) {
return "TAG_Compound";
} else if (clazz.equals(DoubleTag.class)) {
return "TAG_Double";

View File

@ -1,41 +0,0 @@
package com.sk89q.jnbt;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* Some data with a name
*/
public class NamedData<T> {
private final String name;
private final T data;
/**
* Create a new named tag.
*
* @param name the name
* @param data the data
*/
public NamedData(String name, T data) {
checkNotNull(name);
this.name = name;
this.data = data;
}
/**
* Get the name of the tag.
*
* @return the name
*/
public String getName() {
return name;
}
/**
* Get the tag.
*
* @return the tag
*/
public T getValue() {
return data;
}
}

View File

@ -19,14 +19,12 @@
package com.sk89q.jnbt;
import com.sk89q.jnbt.fawe.NumberTag;
/**
* The {@code TAG_Short} tag.
*/
public final class ShortTag extends NumberTag {
@Override
public int getTypeCode() {
return NBTConstants.TYPE_SHORT;
}
private final short value;
@ -50,4 +48,11 @@ public final class ShortTag extends NumberTag {
return "TAG_Short(" + value + ")";
}
// FAWE Start
@Override
public int getTypeCode() {
return NBTConstants.TYPE_SHORT;
}
// FAWE End
}

View File

@ -26,11 +26,6 @@ import static com.google.common.base.Preconditions.checkNotNull;
*/
public final class StringTag extends Tag {
@Override
public int getTypeCode() {
return NBTConstants.TYPE_STRING;
}
private final String value;
/**
@ -54,4 +49,11 @@ public final class StringTag extends Tag {
return "TAG_String(" + value + ")";
}
// FAWE Start
@Override
public int getTypeCode() {
return NBTConstants.TYPE_STRING;
}
// FAWE End
}

View File

@ -31,10 +31,12 @@ public abstract class Tag {
*/
public abstract Object getValue();
// FAWE Start
public Object toRaw() {
return getValue();
}
public abstract int getTypeCode();
// FAWE End
}

View File

@ -7,6 +7,7 @@ import java.util.HashMap;
import java.util.Map;
public abstract class CompressedCompoundTag<T> extends CompoundTag {
private T in;
public CompressedCompoundTag(T in) {
@ -41,4 +42,5 @@ public abstract class CompressedCompoundTag<T> extends CompoundTag {
throw new RuntimeException(e);
}
}
}

View File

@ -1,7 +1,9 @@
package com.sk89q.jnbt;
package com.sk89q.jnbt.fawe;
import com.boydti.fawe.object.io.FastByteArrayOutputStream;
import com.boydti.fawe.object.io.FastByteArraysInputStream;
import com.sk89q.jnbt.CompressedCompoundTag;
import com.sk89q.jnbt.NBTOutputStream;
import com.sk89q.worldedit.extent.clipboard.Clipboard;
import com.sk89q.worldedit.extent.clipboard.io.FastSchematicWriter;
import net.jpountz.lz4.LZ4BlockInputStream;
@ -10,6 +12,7 @@ import net.jpountz.lz4.LZ4BlockOutputStream;
import java.io.IOException;
public class CompressedSchematicTag extends CompressedCompoundTag<Clipboard> {
public CompressedSchematicTag(Clipboard holder) {
super(holder);
}
@ -26,4 +29,5 @@ public class CompressedSchematicTag extends CompressedCompoundTag<Clipboard> {
FastByteArraysInputStream in = new FastByteArraysInputStream(blocksOut.toByteArrays());
return new LZ4BlockInputStream(in);
}
}

View File

@ -1,6 +1,13 @@
package com.sk89q.jnbt;
package com.sk89q.jnbt.fawe;
import com.sk89q.jnbt.Tag;
/**
* A numerical {@link Tag}
*/
public abstract class NumberTag extends Tag {
@Override
public abstract Number getValue();
}

View File

@ -0,0 +1,4 @@
/**
* These are classes added by FAWE. They do not exist in WorldEdit
*/
package com.sk89q.jnbt.fawe;

View File

@ -86,40 +86,6 @@ public enum BuiltInClipboardFormat implements ClipboardFormat {
},
/**
* The Schematic format used by MCEdit.
*/
MCEDIT_SCHEMATIC("mcedit", "mce", "schematic") {
@Override
public String getPrimaryFileExtension() {
return "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 IOException("This format does not support saving, use `schem` or `sponge` as format"); // Is more helpful
}
@Override
public boolean isFormat(File file) {
String name = file.getName().toLowerCase(Locale.ROOT);
return name.endsWith(".schematic") || name.endsWith(".mcedit") || name.endsWith(".mce");
}
},
SPONGE_SCHEMATIC("sponge", "schem") {
@Override
@ -160,6 +126,48 @@ public enum BuiltInClipboardFormat implements ClipboardFormat {
}
},
/**
* The Schematic format used by MCEdit.
*/
MCEDIT_SCHEMATIC("mcedit", "mce", "schematic") {
@Override
public String getPrimaryFileExtension() {
return "schematic";
}
@Override
public ClipboardReader getReader(InputStream inputStream) throws IOException {
NBTInputStream nbtStream = new NBTInputStream(new GZIPInputStream(inputStream));
return new MCEditSchematicReader(nbtStream);
}
@Override
public ClipboardWriter getWriter(OutputStream outputStream) throws IOException {
throw new IOException("This format does not support saving");
}
@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;
}
},
BROKENENTITY("brokenentity", "legacyentity", "le", "be", "brokenentities", "legacyentities") {
@Override

View File

@ -58,6 +58,7 @@ import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
@ -350,7 +351,7 @@ public class FastSchematicReader extends NBTSchematicReader {
y = pos[1];
z = pos[2];
}
Map<String, Tag> values = tile.getValue();
Map<String, Tag> values = new HashMap<>(tile.getValue());
Tag id = values.get("Id");
if (id != null) {
values.put("x", new IntTag(x));
@ -361,17 +362,14 @@ public class FastSchematicReader extends NBTSchematicReader {
values.remove("Id");
values.remove("Pos");
tile = fixBlockEntity(tile);
clipboard.setTile(x, y, z, tile);
clipboard.setTile(x, y, z, fixBlockEntity(new CompoundTag(values)));
}
}
// entities
if (entities != null && !entities.isEmpty()) {
for (Map<String, Object> entRaw : entities) {
CompoundTag ent = FaweCache.IMP.asTag(entRaw);
Map<String, Tag> value = ent.getValue();
Map<String, Tag> value = new HashMap<>(FaweCache.IMP.asTag(entRaw).getValue());
StringTag id = (StringTag) value.get("Id");
if (id == null) {
id = (StringTag) value.get("id");
@ -384,7 +382,7 @@ public class FastSchematicReader extends NBTSchematicReader {
EntityType type = EntityTypes.parse(id.getValue());
if (type != null) {
ent = fixEntity(ent);
final CompoundTag ent = fixEntity(new CompoundTag(value));
BaseEntity state = new BaseEntity(type, ent);
Location loc = ent.getEntityLocation(clipboard);
if (brokenEntities) {

View File

@ -121,6 +121,7 @@ public class FastSchematicWriter implements ClipboardWriter {
outputStream.writeLazyCompoundTag("Schematic", out -> {
out.writeNamedTag("DataVersion", WorldEdit.getInstance().getPlatformManager().queryCapability(Capability.WORLD_EDITING).getDataVersion());
out.writeNamedTag("Version", CURRENT_VERSION);
out.writeNamedTag("FAWE", Fawe.get().getVersion().build);
out.writeNamedTag("Width", (short) width);
out.writeNamedTag("Height", (short) height);
out.writeNamedTag("Length", (short) length);
@ -162,7 +163,7 @@ public class FastSchematicWriter implements ClipboardWriter {
BaseBlock block = pos.getFullBlock(finalClipboard);
CompoundTag nbt = block.getNbtData();
if (nbt != null) {
Map<String, Tag> values = nbt.getValue();
Map<String, Tag> values = new HashMap<>(nbt.getValue());
// Positions are kept in NBT, we don't want that.
values.remove("x");
@ -180,7 +181,8 @@ public class FastSchematicWriter implements ClipboardWriter {
pos.getZ()
}));
numTiles++;
tilesOut.writeTagPayload(block.getNbtData());
tilesOut.writeTagPayload(new CompoundTag(values));
}
int ordinal = block.getOrdinal();

View File

@ -1,4 +0,0 @@
package com.sk89q.worldedit.extent.clipboard.io;
public class FaweFormat {
}

View File

@ -68,9 +68,7 @@ import static com.google.common.base.Preconditions.checkNotNull;
/**
* 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);
@ -207,7 +205,7 @@ public class MCEditSchematicReader extends NBTSchematicReader {
if (newBlock != null) {
for (NBTCompatibilityHandler handler : COMPATIBILITY_HANDLERS) {
if (handler.isAffectedBlock(newBlock)) {
newBlock = handler.updateNBT(block, values);
newBlock = handler.updateNBT(block, values).toImmutableState();
if (newBlock == null || values.isEmpty()) {
break;
}

View File

@ -1,536 +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 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.extent.clipboard.io;
import com.boydti.fawe.FaweCache;
import com.boydti.fawe.jnbt.streamer.StreamDelegate;
import com.boydti.fawe.jnbt.streamer.ValueReader;
import com.boydti.fawe.object.FaweInputStream;
import com.boydti.fawe.object.FaweOutputStream;
import com.boydti.fawe.object.clipboard.LinearClipboard;
import com.boydti.fawe.object.io.FastByteArrayOutputStream;
import com.boydti.fawe.object.io.FastByteArraysInputStream;
import com.boydti.fawe.object.io.ResettableFileInputStream;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.jnbt.NBTInputStream;
import com.sk89q.worldedit.entity.BaseEntity;
import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard;
import com.sk89q.worldedit.extent.clipboard.Clipboard;
import com.sk89q.worldedit.extent.clipboard.io.legacycompat.BannerBlockCompatibilityHandler;
import com.sk89q.worldedit.extent.clipboard.io.legacycompat.BedBlockCompatibilityHandler;
import com.sk89q.worldedit.extent.clipboard.io.legacycompat.EntityNBTCompatibilityHandler;
import com.sk89q.worldedit.extent.clipboard.io.legacycompat.FlowerPotCompatibilityHandler;
import com.sk89q.worldedit.extent.clipboard.io.legacycompat.NBTCompatibilityHandler;
import com.sk89q.worldedit.extent.clipboard.io.legacycompat.NoteBlockCompatibilityHandler;
import com.sk89q.worldedit.extent.clipboard.io.legacycompat.Pre13HangingCompatibilityHandler;
import com.sk89q.worldedit.extent.clipboard.io.legacycompat.SignCompatibilityHandler;
import com.sk89q.worldedit.extent.clipboard.io.legacycompat.SkullBlockCompatibilityHandler;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.registry.state.PropertyKey;
import com.sk89q.worldedit.util.Direction;
import com.sk89q.worldedit.util.Location;
import com.sk89q.worldedit.world.block.BaseBlock;
import com.sk89q.worldedit.world.block.BlockCategories;
import com.sk89q.worldedit.world.block.BlockID;
import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.block.BlockType;
import com.sk89q.worldedit.world.block.BlockTypeSwitch;
import com.sk89q.worldedit.world.block.BlockTypeSwitchBuilder;
import com.sk89q.worldedit.world.entity.EntityType;
import com.sk89q.worldedit.world.entity.EntityTypes;
import com.sk89q.worldedit.world.registry.BlockMaterial;
import com.sk89q.worldedit.world.registry.LegacyMapper;
import net.jpountz.lz4.LZ4BlockInputStream;
import net.jpountz.lz4.LZ4BlockOutputStream;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.BufferedInputStream;
import java.io.EOFException;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.function.Function;
import java.util.zip.GZIPInputStream;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.slf4j.LoggerFactory.getLogger;
/**
* Reads schematic files based that are compatible with MCEdit and other editors.
*/
public class SchematicReader implements ClipboardReader {
private static final Logger log = LoggerFactory.getLogger(SchematicReader.class);
private static final NBTCompatibilityHandler[] COMPATIBILITY_HANDLERS = {
new SignCompatibilityHandler(),
new FlowerPotCompatibilityHandler(),
new NoteBlockCompatibilityHandler(),
new SkullBlockCompatibilityHandler(),
new BannerBlockCompatibilityHandler(),
new BedBlockCompatibilityHandler()
};
private static final EntityNBTCompatibilityHandler[] ENTITY_COMPATIBILITY_HANDLERS = {
new Pre13HangingCompatibilityHandler()
};
private NBTInputStream inputStream;
private InputStream rootStream;
// private final DataFixer fixer; TODO
private FastByteArrayOutputStream idOut = new FastByteArrayOutputStream();
private FastByteArrayOutputStream dataOut = new FastByteArrayOutputStream();
private FastByteArrayOutputStream addOut;
private FastByteArrayOutputStream biomesOut;
private FaweOutputStream ids;
private FaweOutputStream datas;
private FaweOutputStream adds;
private FaweOutputStream biomes;
private List<Map<String, Object>> tiles;
private List<Map<String, Object>> entities;
private int width;
private int height;
private int length;
private int offsetX;
private int offsetY;
private int offsetZ;
private int originX;
private int originY;
private int originZ;
/**
* Create a new instance.
*
* @param inputStream the input stream to read from
*/
public SchematicReader(NBTInputStream inputStream) {
checkNotNull(inputStream);
this.inputStream = inputStream;
}
public void setUnderlyingStream(InputStream in) {
this.rootStream = in;
}
public StreamDelegate createDelegate() {
StreamDelegate root = new StreamDelegate();
StreamDelegate schematic = root.add("Schematic");
schematic.add("Width").withInt((i, v) -> width = v);
schematic.add("Height").withInt((i, v) -> height = v);
schematic.add("Length").withInt((i, v) -> length = v);
schematic.add("WEOriginX").withInt((i, v) -> originX = v);
schematic.add("WEOriginY").withInt((i, v) -> originY = v);
schematic.add("WEOriginZ").withInt((i, v) -> originZ = v);
StreamDelegate metadata = schematic.add("Metadata");
metadata.add("WEOffsetX").withInt((i, v) -> offsetX = v);
metadata.add("WEOffsetY").withInt((i, v) -> offsetY = v);
metadata.add("WEOffsetZ").withInt((i, v) -> offsetZ = v);
StreamDelegate blocksDelegate = schematic.add("Blocks");
blocksDelegate.withInfo((length, type) -> ids = new FaweOutputStream(new LZ4BlockOutputStream(idOut)));
blocksDelegate.withInt((index, value) -> ids.write(value));
StreamDelegate dataDelegate = schematic.add("Data");
dataDelegate.withInfo((length, type) -> datas = new FaweOutputStream(new LZ4BlockOutputStream(dataOut)));
dataDelegate.withInt((index, value) -> datas.write(value));
StreamDelegate addDelegate = schematic.add("AddBlocks");
addDelegate.withInfo((length, type) -> {
addOut = new FastByteArrayOutputStream();
adds = new FaweOutputStream(new LZ4BlockOutputStream(addOut));
});
addDelegate.withInt((index, value) -> {
if (value != 0) {
int first = value & 0x0F;
int second = (value & 0xF0) >> 4;
adds.write(first);
adds.write(second);
} else {
adds.write(0);
adds.write(0);
}
});
StreamDelegate tilesDelegate = schematic.add("TileEntities");
tilesDelegate.withInfo((length, type) -> tiles = new ArrayList<>(length));
tilesDelegate.withElem((ValueReader<Map<String, Object>>) (index, tile) -> tiles.add(tile));
StreamDelegate entitiesDelegate = schematic.add("Entities");
entitiesDelegate.withInfo((length, type) -> entities = new ArrayList<>(length));
entitiesDelegate.withElem(
(ValueReader<Map<String, Object>>) (index, entity) -> entities.add(entity));
return root;
}
private int readCombined(InputStream idIn, InputStream dataIn) throws IOException {
return ((idIn.read() & 0xFF) << 4) + (dataIn.read() & 0xF);
}
private int readCombined(InputStream idIn, InputStream dataIn, InputStream addIn) throws IOException {
return ((addIn.read() & 0xFF) << 8) + readCombined(idIn, dataIn);
}
private BlockState getBlock(int combined) {
BlockState state = LegacyMapper.getInstance().getBlockFromLegacyCombinedId(combined);
return state;
}
private void write(int index, BlockState block, LinearClipboard clipboard) {
clipboard.setBlock(index, block);
}
private void write(int x, int y, int z, BlockState block, Clipboard clipboard) {
clipboard.setBlock(x, y, z, block);
}
private void readwrite(int index, InputStream idIn, InputStream dataIn, LinearClipboard out) throws IOException {
readwrite(index, readCombined(idIn, dataIn), out);
}
private void readwrite(int x, int y, int z, InputStream idIn, InputStream dataIn, Clipboard out) throws IOException {
readwrite(x, y, z, readCombined(idIn, dataIn), out);
}
private void readwrite(int index, InputStream idIn, InputStream dataIn, InputStream addIn, LinearClipboard out) throws IOException {
readwrite(index, readCombined(idIn, dataIn, addIn), out);
}
private void readwrite(int x, int y, int z, InputStream idIn, InputStream dataIn, InputStream addIn, Clipboard out) throws IOException {
readwrite(x, y, z, readCombined(idIn, dataIn, addIn), out);
}
private void readwrite(int index, int combined, LinearClipboard out) throws IOException {
write(index, getBlock(combined), out);
}
private void readwrite(int x, int y, int z, int combined, Clipboard out) throws IOException {
write(x, y, z, getBlock(combined), out);
}
@Override
public Clipboard read(UUID uuid, Function<BlockVector3, Clipboard> createOutput) throws IOException {
try {
return readInternal(uuid, createOutput);
} catch (EOFException e) {
log.error("EOFException read in schematic. Did you give the schematic the wrong extension?");
log.error("We will attempt to rectify your mistake for you and load the schematic assuming it is named .schem not .schematic");
e.printStackTrace();
final InputStream stream;
if (rootStream instanceof FileInputStream) {
stream = new ResettableFileInputStream((FileInputStream) rootStream);
} else {
stream = rootStream;
}
BufferedInputStream buffered = new BufferedInputStream(stream);
NBTInputStream nbtStream = new NBTInputStream(new BufferedInputStream(new GZIPInputStream(buffered)));
return (new FastSchematicReader(nbtStream)).read(uuid, createOutput);
}
}
private Clipboard readInternal(UUID uuid, Function<BlockVector3, Clipboard> createOutput) throws IOException {
StreamDelegate root = createDelegate();
inputStream.readNamedTagLazy(root);
if (ids != null) {
ids.close();
}
if (datas != null) {
datas.close();
}
if (adds != null) {
adds.close();
}
if (biomes != null) {
biomes.close();
}
ids = null;
datas = null;
adds = null;
biomes = null;
BlockVector3 dimensions = BlockVector3.at(width, height, length);
BlockVector3 origin = BlockVector3.ZERO;
if (offsetX != Integer.MIN_VALUE && offsetY != Integer.MIN_VALUE && offsetZ != Integer.MIN_VALUE) {
origin = BlockVector3.at(-offsetX, -offsetY, -offsetZ);
}
Clipboard clipboard = createOutput.apply(dimensions);
try (InputStream dataIn = new LZ4BlockInputStream(new FastByteArraysInputStream(dataOut.toByteArrays())); InputStream idIn = new LZ4BlockInputStream(new FastByteArraysInputStream(idOut.toByteArrays()))) {
if (addOut != null) {
try (FaweInputStream addIn = new FaweInputStream(new LZ4BlockInputStream(new FastByteArraysInputStream(addOut.toByteArrays())))) {
if (clipboard instanceof LinearClipboard) {
LinearClipboard linear = (LinearClipboard) clipboard;
for (int y = 0, index = 0; y < height; y++) {
for (int z = 0; z < length; z++) {
for (int x = 0; x < width; x++, index++) {
readwrite(index, idIn, dataIn, addIn, linear);
}
}
}
} else {
for (int y = 0; y < height; y++) {
for (int z = 0; z < length; z++) {
for (int x = 0; x < width; x++) {
readwrite(x, y, z, idIn, dataIn, addIn, clipboard);
}
}
}
}
}
} else {
if (clipboard instanceof LinearClipboard) {
LinearClipboard linear = (LinearClipboard) clipboard;
for (int y = 0, index = 0; y < height; y++) {
for (int z = 0; z < length; z++) {
for (int x = 0; x < width; x++, index++) {
readwrite(index, idIn, dataIn, linear);
}
}
}
} else {
for (int y = 0; y < height; y++) {
for (int z = 0; z < length; z++) {
for (int x = 0; x < width; x++) {
readwrite(x, y, z, idIn, dataIn, clipboard);
}
}
}
}
}
}
// tiles
if (tiles != null && !tiles.isEmpty()) {
outer:
for (Map<String, Object> tileRaw : tiles) {
CompoundTag tile = FaweCache.IMP.asTag(tileRaw);
int x = (int) tileRaw.get("x");
int y = (int) tileRaw.get("y");
int z = (int) tileRaw.get("z");
BlockState block = clipboard.getBlock(x, y, z);
for (NBTCompatibilityHandler compat : COMPATIBILITY_HANDLERS) {
if (compat.isAffectedBlock(block)) {
block = compat.updateNBT(block, tile.getValue());
BaseBlock baseBlock = block.toBaseBlock(tile);
clipboard.setBlock(x, y, z, baseBlock);
continue outer;
}
}
clipboard.setTile(x, y, z, tile);
}
}
// entities
if (entities != null && !entities.isEmpty()) {
for (Map<String, Object> entRaw : entities) {
String id = (String) entRaw.get("id");
if (id == null) {
continue;
}
entRaw.put("Id", id);
EntityType type = EntityTypes.parse(id);
if (type != null) {
CompoundTag ent = FaweCache.IMP.asTag(entRaw);
for (EntityNBTCompatibilityHandler compat : ENTITY_COMPATIBILITY_HANDLERS) {
if (compat.isAffectedEntity(type, ent)) {
ent = compat.updateNBT(type, ent);
}
}
BaseEntity state = new BaseEntity(type, ent);
Location loc = ent.getEntityLocation(clipboard);
clipboard.createEntity(loc, state);
} else {
getLogger(SchematicReader.class).debug("Invalid entity: " + id);
}
}
}
fixStates(clipboard);
clipboard.setOrigin(origin);
BlockVector3 min = BlockVector3.at(originX, originY, originZ);
if (!min.equals(BlockVector3.ZERO)) {
clipboard = new BlockArrayClipboard(clipboard, min);
}
return clipboard;
}
private void fixStates(Clipboard fc) {
for (BlockVector3 pos : fc) {
BlockState block = pos.getBlock(fc);
if (block.getMaterial().isAir()) {
continue;
}
int x = pos.getX();
int y = pos.getY();
int z = pos.getZ();
BlockType type = block.getBlockType();
if (BlockCategories.STAIRS.contains(type)) {
Direction facing = block.getState(PropertyKey.FACING);
BlockVector3 forward = facing.toBlockVector();
Direction left = facing.getLeft();
Direction right = facing.getRight();
BlockState forwardBlock = fc.getBlock(x + forward.getBlockX(), y + forward.getBlockY(), z + forward.getBlockZ());
BlockType forwardType = forwardBlock.getBlockType();
if (forwardType.hasProperty(PropertyKey.SHAPE) && forwardType.hasProperty(PropertyKey.FACING)) {
Direction forwardFacing = forwardBlock.getState(PropertyKey.FACING);
if (forwardFacing == left) {
BlockState rightBlock = fc.getBlock(x + right.toBlockVector().getBlockX(), y + right.toBlockVector().getBlockY(), z + right.toBlockVector().getBlockZ());
BlockType rightType = rightBlock.getBlockType();
if (!rightType.hasProperty(PropertyKey.SHAPE) || rightBlock.getState(PropertyKey.FACING) != facing) {
pos.setBlock(fc, block.with(PropertyKey.SHAPE, "inner_left"));
}
return;
} else if (forwardFacing == right) {
BlockState leftBlock = fc.getBlock(x + left.toBlockVector().getBlockX(), y + left.toBlockVector().getBlockY(), z + left.toBlockVector().getBlockZ());
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"));
}
return;
}
}
BlockState backwardsBlock = fc.getBlock(x - forward.getBlockX(), y - forward.getBlockY(), z - forward.getBlockZ());
BlockType backwardsType = backwardsBlock.getBlockType();
if (backwardsType.hasProperty(PropertyKey.SHAPE) && backwardsType.hasProperty(PropertyKey.FACING)) {
Direction backwardsFacing = (Direction) backwardsBlock.getState(PropertyKey.FACING);
if (backwardsFacing == left) {
BlockState rightBlock = fc.getBlock(x + right.toBlockVector().getBlockX(), y + right.toBlockVector().getBlockY(), z + right.toBlockVector().getBlockZ());
BlockType rightType = rightBlock.getBlockType();
if (!rightType.hasProperty(PropertyKey.SHAPE) || rightBlock.getState(PropertyKey.FACING) != facing) {
pos.setBlock(fc, block.with(PropertyKey.SHAPE, "outer_left"));
}
return;
} else if (backwardsFacing == right) {
BlockState leftBlock = fc.getBlock(x + left.toBlockVector().getBlockX(), y + left.toBlockVector().getBlockY(), z + left.toBlockVector().getBlockZ());
BlockType leftType = leftBlock.getBlockType();
if (!leftType.hasProperty(PropertyKey.SHAPE) || leftBlock.getState(PropertyKey.FACING) != facing) {
pos.setBlock(fc, block.with(PropertyKey.SHAPE, "outer_right"));
}
return;
}
}
} else {
int group = group(type);
if (group == -1) {
return;
}
BlockState set = block;
if (set.getState(PropertyKey.NORTH) == Boolean.FALSE && merge(fc, group, x, y, z - 1)) {
set = set.with(PropertyKey.NORTH, true);
}
if (set.getState(PropertyKey.EAST) == Boolean.FALSE && merge(fc, group, x + 1, y, z)) {
set = set.with(PropertyKey.EAST, true);
}
if (set.getState(PropertyKey.SOUTH) == Boolean.FALSE && merge(fc, group, x, y, z + 1)) {
set = set.with(PropertyKey.SOUTH, true);
}
if (set.getState(PropertyKey.WEST) == Boolean.FALSE && merge(fc, group, x - 1, y, z)) {
set = set.with(PropertyKey.WEST, true);
}
if (group == 2) {
int ns = (set.getState(PropertyKey.NORTH) ? 1 : 0) + ((Boolean) set.getState(PropertyKey.SOUTH) ? 1 : 0);
int ew = (set.getState(PropertyKey.EAST) ? 1 : 0) + ((Boolean) set.getState(PropertyKey.WEST) ? 1 : 0);
if (Math.abs(ns - ew) != 2 || fc.getBlock(x, y + 1, z).getBlockType().getMaterial().isSolid()) {
set = set.with(PropertyKey.UP, true);
}
}
if (set != block) {
pos.setBlock(fc, set);
}
}
}
}
private BlockTypeSwitch<Boolean> fullCube = new BlockTypeSwitchBuilder<>(false).add(type -> {
BlockMaterial mat = type.getMaterial();
return (mat.isFullCube() && !mat.isFragileWhenPushed() && mat.getLightValue() == 0 && mat.isOpaque() && mat.isSolid() && !mat.isTranslucent());
}, true).build();
private boolean merge(Clipboard fc, int group, int x, int y, int z) {
BlockState block = fc.getBlock(x, y, z);
BlockType type = block.getBlockType();
return group(type) == group || fullCube.apply(type);
}
private int group(BlockType type) {
switch (type.getInternalId()) {
case BlockID.ACACIA_FENCE:
case BlockID.BIRCH_FENCE:
case BlockID.DARK_OAK_FENCE:
case BlockID.JUNGLE_FENCE:
case BlockID.OAK_FENCE:
case BlockID.SPRUCE_FENCE:
return 0;
case BlockID.NETHER_BRICK_FENCE:
return 1;
case BlockID.COBBLESTONE_WALL:
case BlockID.MOSSY_COBBLESTONE_WALL:
return 2;
case BlockID.IRON_BARS:
case BlockID.BLACK_STAINED_GLASS_PANE:
case BlockID.BLUE_STAINED_GLASS_PANE:
case BlockID.BROWN_MUSHROOM_BLOCK:
case BlockID.BROWN_STAINED_GLASS_PANE:
case BlockID.CYAN_STAINED_GLASS_PANE:
case BlockID.GLASS_PANE:
case BlockID.GRAY_STAINED_GLASS_PANE:
case BlockID.GREEN_STAINED_GLASS_PANE:
case BlockID.LIGHT_BLUE_STAINED_GLASS_PANE:
case BlockID.LIGHT_GRAY_STAINED_GLASS_PANE:
case BlockID.LIME_STAINED_GLASS_PANE:
case BlockID.MAGENTA_STAINED_GLASS_PANE:
case BlockID.ORANGE_STAINED_GLASS_PANE:
case BlockID.PINK_STAINED_GLASS_PANE:
case BlockID.PURPLE_STAINED_GLASS_PANE:
case BlockID.RED_STAINED_GLASS_PANE:
case BlockID.WHITE_STAINED_GLASS_PANE:
case BlockID.YELLOW_STAINED_GLASS_PANE:
return 3;
default:
return -1;
}
}
@Override
public void close() throws IOException {
inputStream.close();
}
}

View File

@ -68,7 +68,6 @@ import static com.google.common.base.Preconditions.checkNotNull;
/**
* Reads schematic files using the Sponge Schematic Specification.
*/
@Deprecated // High mem usage + slow
public class SpongeSchematicReader extends NBTSchematicReader {
private static final Logger log = LoggerFactory.getLogger(SpongeSchematicReader.class);
@ -102,6 +101,12 @@ public class SpongeSchematicReader extends NBTSchematicReader {
return readVersion1(schematicTag);
} else if (schematicVersion == 2) {
dataVersion = requireTag(schematic, "DataVersion", IntTag.class).getValue();
if (dataVersion < 0) {
log.warn("Schematic has an unknown data version ({}). Data may be incompatible.",
dataVersion);
// Do not DFU unknown data
dataVersion = liveDataVersion;
}
if (dataVersion > liveDataVersion) {
log.warn("Schematic was made in a newer Minecraft version ({} > {}). Data may be incompatible.",
dataVersion, liveDataVersion);
@ -130,7 +135,11 @@ public class SpongeSchematicReader extends NBTSchematicReader {
if (schematicVersion == 1) {
return OptionalInt.of(Constants.DATA_VERSION_MC_1_13_2);
} else if (schematicVersion == 2) {
return OptionalInt.of(requireTag(schematic, "DataVersion", IntTag.class).getValue());
int dataVersion = requireTag(schematic, "DataVersion", IntTag.class).getValue();
if (dataVersion < 0) {
return OptionalInt.empty();
}
return OptionalInt.of(dataVersion);
}
return OptionalInt.empty();
} catch (IOException e) {
@ -140,9 +149,6 @@ public class SpongeSchematicReader extends NBTSchematicReader {
private CompoundTag getBaseTag() 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
@ -321,8 +327,8 @@ public class SpongeSchematicReader extends NBTSchematicReader {
}
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?");
log.warn("Unknown biome type :" + key
+ " in palette. Are you missing a mod or using a schematic made in a newer version of Minecraft?");
}
Tag idTag = palettePart.getValue();
if (!(idTag instanceof IntTag)) {

View File

@ -23,8 +23,6 @@ import com.boydti.fawe.Fawe;
import com.google.common.collect.Maps;
import com.sk89q.jnbt.ByteArrayTag;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.jnbt.DoubleTag;
import com.sk89q.jnbt.FloatTag;
import com.sk89q.jnbt.IntArrayTag;
import com.sk89q.jnbt.IntTag;
import com.sk89q.jnbt.ListTag;
@ -37,7 +35,6 @@ import com.sk89q.worldedit.entity.BaseEntity;
import com.sk89q.worldedit.extension.platform.Capability;
import com.sk89q.worldedit.extent.clipboard.Clipboard;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.math.Vector3;
import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.util.Location;
import com.sk89q.worldedit.world.biome.BiomeType;
@ -57,7 +54,6 @@ import static com.google.common.base.Preconditions.checkNotNull;
/**
* Writes schematic files using the Sponge schematic format.
*/
@Deprecated // High mem usage + slow
public class SpongeSchematicWriter implements ClipboardWriter {
private static final int CURRENT_VERSION = 2;
@ -110,6 +106,7 @@ public class SpongeSchematicWriter implements ClipboardWriter {
schematic.put("Version", new IntTag(CURRENT_VERSION));
schematic.put("DataVersion", new IntTag(
WorldEdit.getInstance().getPlatformManager().queryCapability(Capability.WORLD_EDITING).getDataVersion()));
schematic.put("FAWEVersion", new IntTag(Fawe.get().getVersion().build));
Map<String, Tag> metadata = new HashMap<>();
metadata.put("WEOffsetX", new IntTag(offset.getBlockX()));
@ -270,21 +267,6 @@ public class SpongeSchematicWriter implements ClipboardWriter {
schematic.put("Entities", new ListTag(CompoundTag.class, entities));
}
public Tag writeVector(Vector3 vector) {
List<DoubleTag> list = new ArrayList<>();
list.add(new DoubleTag(vector.getX()));
list.add(new DoubleTag(vector.getY()));
list.add(new DoubleTag(vector.getZ()));
return new ListTag(DoubleTag.class, list);
}
public Tag writeRotation(Location location) {
List<FloatTag> list = new ArrayList<>();
list.add(new FloatTag(location.getYaw()));
list.add(new FloatTag(location.getPitch()));
return new ListTag(FloatTag.class, list);
}
@Override
public void close() throws IOException {
outputStream.close();

View File

@ -24,9 +24,8 @@ import com.sk89q.jnbt.CompoundTagBuilder;
import com.sk89q.jnbt.IntTag;
import com.sk89q.jnbt.ListTag;
import com.sk89q.jnbt.Tag;
import com.sk89q.worldedit.registry.state.DirectionalProperty;
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.block.BlockState;
import com.sk89q.worldedit.world.block.BlockStateHolder;
import com.sk89q.worldedit.world.block.BlockType;
@ -38,15 +37,15 @@ import java.util.Map;
public class BannerBlockCompatibilityHandler implements NBTCompatibilityHandler {
private static final DirectionalProperty FacingProperty;
private static final IntegerProperty RotationProperty;
private static final Property<Direction> FacingProperty;
private static final Property<Integer> RotationProperty;
static {
DirectionalProperty tempFacing;
IntegerProperty tempRotation;
Property<Direction> tempFacing;
Property<Integer> tempRotation;
try {
tempFacing = (DirectionalProperty) (Property<?>) BlockTypes.WHITE_WALL_BANNER.getProperty("facing");
tempRotation = (IntegerProperty) (Property<?>) BlockTypes.WHITE_BANNER.getProperty("rotation");
tempFacing = BlockTypes.WHITE_WALL_BANNER.getProperty("facing");
tempRotation = BlockTypes.WHITE_BANNER.getProperty("rotation");
} catch (NullPointerException | IllegalArgumentException | ClassCastException e) {
tempFacing = null;
tempRotation = null;
@ -62,7 +61,7 @@ public class BannerBlockCompatibilityHandler implements NBTCompatibilityHandler
}
@Override
public <B extends BlockStateHolder<B>> B updateNBT(B block, Map<String, Tag> values) {
public <B extends BlockStateHolder<B>> BlockStateHolder<?> updateNBT(B block, Map<String, Tag> values) {
Tag typeTag = values.get("Base");
if (typeTag instanceof IntTag) {
boolean isWall = block.getBlockType() == BlockTypes.WHITE_WALL_BANNER;
@ -73,10 +72,10 @@ public class BannerBlockCompatibilityHandler implements NBTCompatibilityHandler
BlockState state = type.getDefaultState();
if (isWall) {
Property facingProp = type.getProperty("facing");
Property<Direction> facingProp = type.getProperty("facing");
state = state.with(facingProp, block.getState(FacingProperty));
} else {
Property rotationProp = type.getProperty("rotation");
Property<Integer> rotationProp = type.getProperty("rotation");
state = state.with(rotationProp, block.getState(RotationProperty));
}
@ -102,7 +101,7 @@ public class BannerBlockCompatibilityHandler implements NBTCompatibilityHandler
}
values.put("Patterns", new ListTag(((ListTag) patternsTag).getType(), tempList));
}
return (B) state;
return state;
}
}
}

View File

@ -21,9 +21,8 @@ package com.sk89q.worldedit.extent.clipboard.io.legacycompat;
import com.sk89q.jnbt.IntTag;
import com.sk89q.jnbt.Tag;
import com.sk89q.worldedit.registry.state.DirectionalProperty;
import com.sk89q.worldedit.registry.state.EnumProperty;
import com.sk89q.worldedit.registry.state.Property;
import com.sk89q.worldedit.util.Direction;
import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.block.BlockStateHolder;
import com.sk89q.worldedit.world.block.BlockType;
@ -31,23 +30,24 @@ import com.sk89q.worldedit.world.block.BlockTypes;
import java.util.Map;
@SuppressWarnings("")
public class BedBlockCompatibilityHandler implements NBTCompatibilityHandler {
private static final DirectionalProperty FacingProperty;
private static final EnumProperty PartProperty;
private static final Property<Direction> FACING_PROPERTY;
private static final Property<String> PART_PROPERTY;
static {
DirectionalProperty tempFacing;
EnumProperty tempPart;
Property<Direction> tempFacing;
Property<String> tempPart;
try {
tempFacing = (DirectionalProperty) (Property<?>) BlockTypes.RED_BED.getProperty("facing");
tempPart = (EnumProperty) (Property<?>) BlockTypes.RED_BED.getProperty("part");
tempFacing = BlockTypes.RED_BED.getProperty("facing");
tempPart = BlockTypes.RED_BED.getProperty("part");
} catch (NullPointerException | IllegalArgumentException | ClassCastException e) {
tempFacing = null;
tempPart = null;
}
FacingProperty = tempFacing;
PartProperty = tempPart;
FACING_PROPERTY = tempFacing;
PART_PROPERTY = tempPart;
}
@Override
@ -56,7 +56,7 @@ public class BedBlockCompatibilityHandler implements NBTCompatibilityHandler {
}
@Override
public <B extends BlockStateHolder<B>> B updateNBT(B block, Map<String, Tag> values) {
public <B extends BlockStateHolder<B>> BlockStateHolder<?> updateNBT(B block, Map<String, Tag> values) {
Tag typeTag = values.get("color");
if (typeTag instanceof IntTag) {
String bedType = convertBedType(((IntTag) typeTag).getValue());
@ -65,17 +65,17 @@ public class BedBlockCompatibilityHandler implements NBTCompatibilityHandler {
if (type != null) {
BlockState state = type.getDefaultState();
Property facingProp = type.getProperty("facing");
state = state.with(facingProp, block.getState(FacingProperty));
Property<Direction> facingProp = type.getProperty("facing");
state = state.with(facingProp, block.getState(FACING_PROPERTY));
Property occupiedProp = type.getProperty("occupied");
Property<Boolean> occupiedProp = type.getProperty("occupied");
state = state.with(occupiedProp, false);
Property partProp = type.getProperty("part");
state = state.with(partProp, block.getState(PartProperty));
Property<String> partProp = type.getProperty("part");
state = state.with(partProp, block.getState(PART_PROPERTY));
values.remove("color");
return (B) state;
return state;
}
}
}

View File

@ -37,12 +37,12 @@ public class FlowerPotCompatibilityHandler implements NBTCompatibilityHandler {
}
@Override
public <B extends BlockStateHolder<B>> B updateNBT(B block, Map<String, Tag> values) {
public <B extends BlockStateHolder<B>> BlockStateHolder<?> updateNBT(B block, Map<String, Tag> values) {
Tag item = values.get("Item");
if (item instanceof StringTag) {
String id = ((StringTag) item).getValue();
if (id.isEmpty()) {
return (B) BlockTypes.FLOWER_POT.getDefaultState();
return BlockTypes.FLOWER_POT.getDefaultState();
}
int data = 0;
Tag dataTag = values.get("Data");
@ -52,7 +52,7 @@ public class FlowerPotCompatibilityHandler implements NBTCompatibilityHandler {
BlockState newState = convertLegacyBlockType(id, data);
if (newState != null) {
values.clear();
return (B) newState; // generics pls :\
return newState;
}
}
return block;

View File

@ -26,5 +26,6 @@ import java.util.Map;
public interface NBTCompatibilityHandler {
<B extends BlockStateHolder<B>> boolean isAffectedBlock(B block);
<B extends BlockStateHolder<B>> B updateNBT(B block, Map<String, Tag> values);
<B extends BlockStateHolder<B>> BlockStateHolder<?> updateNBT(B block, Map<String, Tag> values);
}

View File

@ -47,7 +47,7 @@ public class NoteBlockCompatibilityHandler implements NBTCompatibilityHandler {
}
@Override
public <B extends BlockStateHolder<B>> B updateNBT(B block, Map<String, Tag> values) {
public <B extends BlockStateHolder<B>> BlockStateHolder<?> updateNBT(B block, Map<String, Tag> values) {
// note that instrument was not stored (in state or nbt) previously.
// it will be updated to the block below when it gets set into the world for the first time
Tag noteTag = values.get("note");
@ -55,7 +55,7 @@ public class NoteBlockCompatibilityHandler implements NBTCompatibilityHandler {
Byte note = ((ByteTag) noteTag).getValue();
if (note != null) {
values.clear();
return (B) block.with(NoteProperty, (int) note).toImmutableState();
return block.with(NoteProperty, (int) note).toImmutableState();
}
}
return block;

View File

@ -26,8 +26,8 @@ import com.google.gson.JsonPrimitive;
import com.google.gson.JsonSyntaxException;
import com.sk89q.jnbt.StringTag;
import com.sk89q.jnbt.Tag;
import com.sk89q.worldedit.internal.util.DeprecationUtil;
import com.sk89q.worldedit.world.block.BlockStateHolder;
import com.sk89q.worldedit.world.block.BlockTypes;
import java.util.Map;
@ -35,11 +35,11 @@ public class SignCompatibilityHandler implements NBTCompatibilityHandler {
@Override
public <B extends BlockStateHolder<B>> boolean isAffectedBlock(B block) {
return block.getBlockType() == BlockTypes.SIGN || block.getBlockType() == BlockTypes.WALL_SIGN;
return DeprecationUtil.isSign(block.getBlockType());
}
@Override
public <B extends BlockStateHolder<B>> B updateNBT(B block, Map<String, Tag> values) {
public <B extends BlockStateHolder<B>> BlockStateHolder<?> updateNBT(B block, Map<String, Tag> values) {
for (int i = 0; i < 4; ++i) {
String key = "Text" + (i + 1);
Tag value = values.get(key);

View File

@ -21,8 +21,8 @@ package com.sk89q.worldedit.extent.clipboard.io.legacycompat;
import com.sk89q.jnbt.ByteTag;
import com.sk89q.jnbt.Tag;
import com.sk89q.worldedit.registry.state.DirectionalProperty;
import com.sk89q.worldedit.registry.state.Property;
import com.sk89q.worldedit.util.Direction;
import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.block.BlockStateHolder;
import com.sk89q.worldedit.world.block.BlockType;
@ -32,12 +32,12 @@ import java.util.Map;
public class SkullBlockCompatibilityHandler implements NBTCompatibilityHandler {
private static final DirectionalProperty FacingProperty;
private static final Property<Direction> FacingProperty;
static {
DirectionalProperty tempFacing;
Property<Direction> tempFacing;
try {
tempFacing = (DirectionalProperty) (Property<?>) BlockTypes.SKELETON_WALL_SKULL.getProperty("facing");
tempFacing = BlockTypes.SKELETON_WALL_SKULL.getProperty("facing");
} catch (NullPointerException | IllegalArgumentException | ClassCastException e) {
tempFacing = null;
}
@ -51,7 +51,7 @@ public class SkullBlockCompatibilityHandler implements NBTCompatibilityHandler {
}
@Override
public <B extends BlockStateHolder<B>> B updateNBT(B block, Map<String, Tag> values) {
public <B extends BlockStateHolder<B>> BlockStateHolder<?> updateNBT(B block, Map<String, Tag> values) {
boolean isWall = block.getBlockType() == BlockTypes.SKELETON_WALL_SKULL;
Tag typeTag = values.get("SkullType");
if (typeTag instanceof ByteTag) {
@ -61,18 +61,18 @@ public class SkullBlockCompatibilityHandler implements NBTCompatibilityHandler {
if (type != null) {
BlockState state = type.getDefaultState();
if (isWall) {
Property newProp = type.getProperty("facing");
Property<Direction> newProp = type.getProperty("facing");
state = state.with(newProp, block.getState(FacingProperty));
} else {
Tag rotTag = values.get("Rot");
if (rotTag instanceof ByteTag) {
Property newProp = type.getProperty("rotation");
Property<Integer> newProp = type.getProperty("rotation");
state = state.with(newProp, (int) ((ByteTag) rotTag).getValue());
}
}
values.remove("SkullType");
values.remove("Rot");
return (B) state;
return state;
}
}
}