geforkt von Mirrors/FastAsyncWorldEdit
Merge branch 'main' of https://github.com/IntellectualSites/FastAsyncWorldEdit
Dieser Commit ist enthalten in:
Commit
653d362806
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
@ -1,5 +1,5 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.6.1-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.7.1-bin.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
|
6
renovate.json
Normale Datei
6
renovate.json
Normale Datei
@ -0,0 +1,6 @@
|
||||
{
|
||||
"extends": [
|
||||
"config:base"
|
||||
],
|
||||
"ignoreDeps": ["guava", "rhino-runtime", "mockito-core", "antlr4", "antlr4-runtime", "paranamer"]
|
||||
}
|
@ -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"))}
|
||||
}
|
||||
|
||||
@ -56,7 +57,7 @@ dependencies {
|
||||
"compileOnly"("org.jetbrains:annotations:20.1.0")
|
||||
"testCompileOnly"("org.jetbrains:annotations:20.1.0")
|
||||
"compileOnly"("org.spigotmc:spigot:1.16.4-R0.1-SNAPSHOT")
|
||||
"implementation"("io.papermc:paperlib:1.0.4")
|
||||
"implementation"("io.papermc:paperlib:1.0.6")
|
||||
"compileOnly"("com.sk89q:dummypermscompat:1.10") {
|
||||
exclude("com.github.MilkBowl", "VaultAPI")
|
||||
}
|
||||
@ -68,15 +69,16 @@ dependencies {
|
||||
exclude("com.sk89q.worldedit.worldedit-libs", "bukkit")
|
||||
exclude("com.sk89q.worldedit.worldedit-libs", "core")
|
||||
}
|
||||
"compile"("org.bstats:bstats-bukkit:1.7")
|
||||
"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 }
|
||||
"implementation"("com.palmergames.bukkit:towny:0.84.0.9") { isTransitive = false }
|
||||
"implementation"("com.thevoxelbox.voxelsniper:voxelsniper:5.171.0") { isTransitive = false }
|
||||
"implementation"("com.comphenix.protocol:ProtocolLib:4.5.0") { isTransitive = false }
|
||||
"implementation"("com.comphenix.protocol:ProtocolLib:4.5.1") { isTransitive = false }
|
||||
}
|
||||
|
||||
tasks.named<Copy>("processResources") {
|
||||
@ -107,17 +109,17 @@ tasks.named<ShadowJar>("shadowJar") {
|
||||
include(dependency("org.slf4j:slf4j-api"))
|
||||
include(dependency("org.apache.logging.log4j:log4j-slf4j-impl"))
|
||||
include(dependency("org.antlr:antlr4-runtime"))
|
||||
relocate("org.bstats", "com.sk89q.worldedit.bukkit.bstats") {
|
||||
include(dependency("org.bstats:bstats-bukkit:1.7"))
|
||||
}
|
||||
relocate("io.papermc.lib", "com.sk89q.worldedit.bukkit.paperlib") {
|
||||
include(dependency("io.papermc:paperlib:1.0.4"))
|
||||
include(dependency("io.papermc:paperlib:1.0.6"))
|
||||
}
|
||||
relocate("it.unimi.dsi.fastutil", "com.sk89q.worldedit.bukkit.fastutil") {
|
||||
include(dependency("it.unimi.dsi:fastutil"))
|
||||
}
|
||||
relocate("org.bstats", "com.boydti.metrics") {
|
||||
include(dependency("org.bstats:bstats-bukkit:1.7"))
|
||||
include(dependency("org.bstats:bstats-bukkit:1.8"))
|
||||
}
|
||||
relocate("com.intellectualsites.paster", "com.boydti.fawe.paster") {
|
||||
include(dependency("com.intellectualsites.paster:Paster:1.0.1-SNAPSHOT"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -190,7 +190,6 @@ public final class BukkitAdapter_1_15_2 extends NMSAdapter {
|
||||
return;
|
||||
}
|
||||
if (playerChunk.hasBeenLoaded()) {
|
||||
TaskManager.IMP.sync(() -> {
|
||||
try {
|
||||
int dirtyBits = fieldDirtyBits.getInt(playerChunk);
|
||||
if (dirtyBits == 0) {
|
||||
@ -216,11 +215,7 @@ public final class BukkitAdapter_1_15_2 extends NMSAdapter {
|
||||
} catch (IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
});
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -4,7 +4,6 @@ import com.boydti.fawe.Fawe;
|
||||
import com.boydti.fawe.FaweCache;
|
||||
import com.boydti.fawe.beta.IChunkGet;
|
||||
import com.boydti.fawe.beta.IChunkSet;
|
||||
import com.boydti.fawe.beta.implementation.blocks.CharBlocks;
|
||||
import com.boydti.fawe.beta.implementation.blocks.CharGetBlocks;
|
||||
import com.boydti.fawe.beta.implementation.lighting.HeightMapType;
|
||||
import com.boydti.fawe.beta.implementation.queue.QueueHandler;
|
||||
@ -90,6 +89,7 @@ public class BukkitGetBlocks_1_15_2 extends CharGetBlocks {
|
||||
public NibbleArray[] skyLight = new NibbleArray[16];
|
||||
private boolean createCopy = false;
|
||||
private BukkitGetBlocks_1_15_2_Copy copy = null;
|
||||
private boolean forceLoadSections = true;
|
||||
|
||||
public BukkitGetBlocks_1_15_2(World world, int chunkX, int chunkZ) {
|
||||
this(((CraftWorld) world).getHandle(), chunkX, chunkZ);
|
||||
@ -316,7 +316,8 @@ public class BukkitGetBlocks_1_15_2 extends CharGetBlocks {
|
||||
|
||||
@Override
|
||||
public <T extends Future<T>> T call(IChunkSet set, Runnable finalizer) {
|
||||
copy = createCopy ? new BukkitGetBlocks_1_15_2_Copy(world, getChunkX(), getChunkZ()) : null;
|
||||
forceLoadSections = false;
|
||||
copy = createCopy ? new BukkitGetBlocks_1_15_2_Copy(world) : null;
|
||||
try {
|
||||
WorldServer nmsWorld = world;
|
||||
Chunk nmsChunk = ensureLoaded(nmsWorld, chunkX, chunkZ);
|
||||
@ -357,13 +358,14 @@ public class BukkitGetBlocks_1_15_2 extends CharGetBlocks {
|
||||
if (!set.hasSection(layer)) {
|
||||
continue;
|
||||
}
|
||||
if (createCopy) {
|
||||
copy.storeSection(layer);
|
||||
}
|
||||
|
||||
bitMask |= 1 << layer;
|
||||
|
||||
char[] setArr = set.load(layer);
|
||||
char[] setArr = set.load(layer).clone();
|
||||
if (createCopy) {
|
||||
copy.storeSection(layer, load(layer).clone());
|
||||
}
|
||||
|
||||
ChunkSection newSection;
|
||||
ChunkSection existingSection = sections[layer];
|
||||
if (existingSection == null) {
|
||||
@ -392,7 +394,7 @@ public class BukkitGetBlocks_1_15_2 extends CharGetBlocks {
|
||||
this.nmsChunk = nmsChunk;
|
||||
this.sections = null;
|
||||
this.reset();
|
||||
} else if (existingSection != getSections()[layer]) {
|
||||
} else if (existingSection != getSections(false)[layer]) {
|
||||
this.sections[layer] = existingSection;
|
||||
this.reset();
|
||||
} else if (!Arrays.equals(update(layer, new char[4096]), load(layer))) {
|
||||
@ -403,7 +405,6 @@ public class BukkitGetBlocks_1_15_2 extends CharGetBlocks {
|
||||
newSection = BukkitAdapter_1_15_2.newChunkSection(layer, this::load, setArr, fastmode);
|
||||
if (!BukkitAdapter_1_15_2.setSectionAtomic(sections, existingSection, newSection, layer)) {
|
||||
log.error("Failed to set chunk section:" + chunkX + "," + chunkZ + " layer: " + layer);
|
||||
continue;
|
||||
} else {
|
||||
updateGet(this, nmsChunk, sections, newSection, setArr, layer);
|
||||
}
|
||||
@ -470,9 +471,7 @@ public class BukkitGetBlocks_1_15_2 extends CharGetBlocks {
|
||||
|
||||
Set<UUID> entityRemoves = set.getEntityRemoves();
|
||||
if (entityRemoves != null && !entityRemoves.isEmpty()) {
|
||||
if (syncTasks == null) {
|
||||
syncTasks = new Runnable[3];
|
||||
}
|
||||
|
||||
syncTasks[2] = () -> {
|
||||
final List<Entity>[] entities = nmsChunk.getEntitySlices();
|
||||
@ -632,12 +631,14 @@ public class BukkitGetBlocks_1_15_2 extends CharGetBlocks {
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
} finally {
|
||||
forceLoadSections = true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized char[] update(int layer, char[] data) {
|
||||
ChunkSection section = getSections()[layer];
|
||||
ChunkSection section = getSections(true)[layer];
|
||||
// Section is null, return empty array
|
||||
if (section == null) {
|
||||
data = new char[4096];
|
||||
@ -752,7 +753,10 @@ public class BukkitGetBlocks_1_15_2 extends CharGetBlocks {
|
||||
}
|
||||
}
|
||||
|
||||
public ChunkSection[] getSections() {
|
||||
public ChunkSection[] getSections(boolean force) {
|
||||
if (force && forceLoadSections) {
|
||||
return sections = getChunk().getSections().clone();
|
||||
}
|
||||
ChunkSection[] tmp = sections;
|
||||
if (tmp == null) {
|
||||
synchronized (this) {
|
||||
@ -804,7 +808,7 @@ public class BukkitGetBlocks_1_15_2 extends CharGetBlocks {
|
||||
|
||||
@Override
|
||||
public boolean hasSection(int layer) {
|
||||
return getSections()[layer] != null;
|
||||
return getSections(false)[layer] != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -817,10 +821,10 @@ public class BukkitGetBlocks_1_15_2 extends CharGetBlocks {
|
||||
return super.trim(true);
|
||||
} else {
|
||||
for (int i = 0; i < 16; i++) {
|
||||
if (!hasSection(i) || super.sections[i] == CharBlocks.EMPTY) {
|
||||
if (!hasSection(i) || !super.sections[i].isFull()) {
|
||||
continue;
|
||||
}
|
||||
ChunkSection existing = getSections()[i];
|
||||
ChunkSection existing = getSections(true)[i];
|
||||
try {
|
||||
final DataPaletteBlock<IBlockData> blocksExisting = existing.getBlocks();
|
||||
|
||||
|
@ -2,6 +2,10 @@ package com.boydti.fawe.bukkit.adapter.mc1_15_2;
|
||||
|
||||
|
||||
import com.boydti.fawe.FaweCache;
|
||||
import com.boydti.fawe.beta.IBlocks;
|
||||
import com.boydti.fawe.beta.IChunkGet;
|
||||
import com.boydti.fawe.beta.IChunkSet;
|
||||
import com.boydti.fawe.beta.implementation.lighting.HeightMapType;
|
||||
import com.boydti.fawe.bukkit.adapter.mc1_15_2.nbt.LazyCompoundTag_1_15_2;
|
||||
import com.google.common.base.Suppliers;
|
||||
import com.sk89q.jnbt.CompoundTag;
|
||||
@ -21,22 +25,25 @@ import net.minecraft.server.v1_15_R1.TileEntity;
|
||||
import net.minecraft.server.v1_15_R1.WorldServer;
|
||||
import org.bukkit.craftbukkit.v1_15_R1.block.CraftBlock;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.annotations.Range;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
public class BukkitGetBlocks_1_15_2_Copy extends BukkitGetBlocks_1_15_2 {
|
||||
public class BukkitGetBlocks_1_15_2_Copy implements IChunkGet {
|
||||
|
||||
private final Map<BlockVector3, CompoundTag> tiles = new HashMap<>();
|
||||
private final Set<CompoundTag> entities = new HashSet<>();
|
||||
private BiomeStorage biomeStorage;
|
||||
private final char[][] blocks = new char[16][4096];
|
||||
private final char[][] blocks = new char[16][];
|
||||
private final WorldServer world;
|
||||
|
||||
protected BukkitGetBlocks_1_15_2_Copy(WorldServer world, int X, int Z) {
|
||||
super(world, X, Z);
|
||||
protected BukkitGetBlocks_1_15_2_Copy(WorldServer world) {
|
||||
this.world = world;
|
||||
}
|
||||
|
||||
protected void storeTile(TileEntity tile) {
|
||||
@ -87,6 +94,16 @@ public class BukkitGetBlocks_1_15_2_Copy extends BukkitGetBlocks_1_15_2 {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCreateCopy(boolean createCopy) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCreateCopy() {
|
||||
return false;
|
||||
}
|
||||
|
||||
protected void storeBiomes(BiomeStorage biomeStorage) {
|
||||
this.biomeStorage = new BiomeStorage(BukkitAdapter_1_15_2.getBiomeArray(biomeStorage).clone());
|
||||
}
|
||||
@ -105,8 +122,18 @@ public class BukkitGetBlocks_1_15_2_Copy extends BukkitGetBlocks_1_15_2 {
|
||||
return base != null ? BukkitAdapter.adapt(CraftBlock.biomeBaseToBiome(base)) : null;
|
||||
}
|
||||
|
||||
protected void storeSection(int layer) {
|
||||
blocks[layer] = update(layer, null).clone();
|
||||
@Override
|
||||
public boolean trim(boolean aggressive, int layer) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IBlocks reset() {
|
||||
return null;
|
||||
}
|
||||
|
||||
protected void storeSection(int layer, char[] data) {
|
||||
blocks[layer] = data;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -115,15 +142,50 @@ public class BukkitGetBlocks_1_15_2_Copy extends BukkitGetBlocks_1_15_2 {
|
||||
return state.toBaseBlock(this, x, y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasSection(@Range(from = 0, to = 15) int layer) {
|
||||
return blocks[layer] != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public char[] load(int layer) {
|
||||
return blocks[layer];
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockState getBlock(int x, int y, int z) {
|
||||
return BlockTypesCache.states[get(x, y, z)];
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSkyLight(int x, int y, int z) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getEmmittedLight(int x, int y, int z) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getHeightMap(HeightMapType type) {
|
||||
return new int[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends Future<T>> T call(IChunkSet set, Runnable finalize) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public char get(int x, int y, int z) {
|
||||
final int layer = y >> 4;
|
||||
final int index = (y & 15) << 8 | z << 4 | x;
|
||||
return blocks[layer][index];
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean trim(boolean aggressive) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -58,7 +58,7 @@ public class FAWEWorldNativeAccess_1_15_2 implements WorldNativeAccess<Chunk, IB
|
||||
|
||||
@Override
|
||||
public IBlockData toNative(com.sk89q.worldedit.world.block.BlockState state) {
|
||||
int stateId = BlockStateIdAccess.getBlockStateId(state);
|
||||
int stateId = adapter.ordinalToIbdID(state.getOrdinalChar());
|
||||
return BlockStateIdAccess.isValidInternalId(stateId)
|
||||
? Block.getByCombinedId(stateId)
|
||||
: ((CraftBlockData) BukkitAdapter.adapt(state)).getState();
|
||||
@ -72,7 +72,8 @@ public class FAWEWorldNativeAccess_1_15_2 implements WorldNativeAccess<Chunk, IB
|
||||
@Nullable
|
||||
@Override
|
||||
public IBlockData setBlockState(Chunk chunk, BlockPosition position, IBlockData state) {
|
||||
return chunk.setType(position, state, false);
|
||||
return chunk.setType(position, state,
|
||||
this.sideEffectSet != null && this.sideEffectSet.shouldApply(SideEffect.UPDATE));
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -166,9 +167,4 @@ public class FAWEWorldNativeAccess_1_15_2 implements WorldNativeAccess<Chunk, IB
|
||||
public void onBlockStateChange(BlockPosition pos, IBlockData oldState, IBlockData newState) {
|
||||
getWorld().a(pos, oldState, newState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <B extends BlockStateHolder<B>> boolean setBlock(BlockVector3 position, B block, SideEffectSet sideEffects) throws WorldEditException {
|
||||
return this.adapter.setBlock(this.getChunk(position.getBlockX() >> 4, position.getBlockZ() >> 4).bukkitChunk, position.getBlockX(), position.getBlockY(), position.getBlockZ(), block, sideEffectSet.shouldApply(SideEffect.LIGHTING));
|
||||
}
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -187,7 +187,6 @@ public final class BukkitAdapter_1_16_1 extends NMSAdapter {
|
||||
return;
|
||||
}
|
||||
if (playerChunk.hasBeenLoaded()) {
|
||||
TaskManager.IMP.sync(() -> {
|
||||
try {
|
||||
int dirtyBits = fieldDirtyBits.getInt(playerChunk);
|
||||
if (dirtyBits == 0) {
|
||||
@ -214,8 +213,6 @@ public final class BukkitAdapter_1_16_1 extends NMSAdapter {
|
||||
} catch (IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4,7 +4,6 @@ import com.boydti.fawe.Fawe;
|
||||
import com.boydti.fawe.FaweCache;
|
||||
import com.boydti.fawe.beta.IChunkGet;
|
||||
import com.boydti.fawe.beta.IChunkSet;
|
||||
import com.boydti.fawe.beta.implementation.blocks.CharBlocks;
|
||||
import com.boydti.fawe.beta.implementation.blocks.CharGetBlocks;
|
||||
import com.boydti.fawe.beta.implementation.lighting.HeightMapType;
|
||||
import com.boydti.fawe.beta.implementation.queue.QueueHandler;
|
||||
@ -90,6 +89,7 @@ public class BukkitGetBlocks_1_16_1 extends CharGetBlocks {
|
||||
public NibbleArray[] skyLight = new NibbleArray[16];
|
||||
private boolean createCopy = false;
|
||||
private BukkitGetBlocks_1_16_1_Copy copy = null;
|
||||
private boolean forceLoadSections = true;
|
||||
|
||||
public BukkitGetBlocks_1_16_1(World world, int chunkX, int chunkZ) {
|
||||
this(((CraftWorld) world).getHandle(), chunkX, chunkZ);
|
||||
@ -316,7 +316,8 @@ public class BukkitGetBlocks_1_16_1 extends CharGetBlocks {
|
||||
|
||||
@Override
|
||||
public <T extends Future<T>> T call(IChunkSet set, Runnable finalizer) {
|
||||
copy = createCopy ? new BukkitGetBlocks_1_16_1_Copy(world, getChunkX(), getChunkZ()) : null;
|
||||
forceLoadSections = false;
|
||||
copy = createCopy ? new BukkitGetBlocks_1_16_1_Copy(world) : null;
|
||||
try {
|
||||
WorldServer nmsWorld = world;
|
||||
Chunk nmsChunk = ensureLoaded(nmsWorld, chunkX, chunkZ);
|
||||
@ -357,13 +358,14 @@ public class BukkitGetBlocks_1_16_1 extends CharGetBlocks {
|
||||
if (!set.hasSection(layer)) {
|
||||
continue;
|
||||
}
|
||||
if (createCopy) {
|
||||
copy.storeSection(layer);
|
||||
}
|
||||
|
||||
bitMask |= 1 << layer;
|
||||
|
||||
char[] setArr = set.load(layer);
|
||||
char[] setArr = set.load(layer).clone();
|
||||
if (createCopy) {
|
||||
copy.storeSection(layer, load(layer).clone());
|
||||
}
|
||||
|
||||
ChunkSection newSection;
|
||||
ChunkSection existingSection = sections[layer];
|
||||
if (existingSection == null) {
|
||||
@ -392,7 +394,7 @@ public class BukkitGetBlocks_1_16_1 extends CharGetBlocks {
|
||||
this.nmsChunk = nmsChunk;
|
||||
this.sections = null;
|
||||
this.reset();
|
||||
} else if (existingSection != getSections()[layer]) {
|
||||
} else if (existingSection != getSections(false)[layer]) {
|
||||
this.sections[layer] = existingSection;
|
||||
this.reset();
|
||||
} else if (!Arrays.equals(update(layer, new char[4096]), load(layer))) {
|
||||
@ -405,7 +407,6 @@ public class BukkitGetBlocks_1_16_1 extends CharGetBlocks {
|
||||
if (!BukkitAdapter_1_16_1
|
||||
.setSectionAtomic(sections, existingSection, newSection, layer)) {
|
||||
log.error("Failed to set chunk section:" + chunkX + "," + chunkZ + " layer: " + layer);
|
||||
continue;
|
||||
} else {
|
||||
updateGet(this, nmsChunk, sections, newSection, setArr, layer);
|
||||
}
|
||||
@ -472,9 +473,7 @@ public class BukkitGetBlocks_1_16_1 extends CharGetBlocks {
|
||||
|
||||
Set<UUID> entityRemoves = set.getEntityRemoves();
|
||||
if (entityRemoves != null && !entityRemoves.isEmpty()) {
|
||||
if (syncTasks == null) {
|
||||
syncTasks = new Runnable[3];
|
||||
}
|
||||
|
||||
syncTasks[2] = () -> {
|
||||
final List<Entity>[] entities = nmsChunk.getEntitySlices();
|
||||
@ -634,12 +633,14 @@ public class BukkitGetBlocks_1_16_1 extends CharGetBlocks {
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
} finally {
|
||||
forceLoadSections = true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized char[] update(int layer, char[] data) {
|
||||
ChunkSection section = getSections()[layer];
|
||||
ChunkSection section = getSections(true)[layer];
|
||||
// Section is null, return empty array
|
||||
if (section == null) {
|
||||
data = new char[4096];
|
||||
@ -754,7 +755,10 @@ public class BukkitGetBlocks_1_16_1 extends CharGetBlocks {
|
||||
}
|
||||
}
|
||||
|
||||
public ChunkSection[] getSections() {
|
||||
public ChunkSection[] getSections(boolean force) {
|
||||
if (force && forceLoadSections) {
|
||||
return sections = getChunk().getSections().clone();
|
||||
}
|
||||
ChunkSection[] tmp = sections;
|
||||
if (tmp == null) {
|
||||
synchronized (this) {
|
||||
@ -806,7 +810,7 @@ public class BukkitGetBlocks_1_16_1 extends CharGetBlocks {
|
||||
|
||||
@Override
|
||||
public boolean hasSection(int layer) {
|
||||
return getSections()[layer] != null;
|
||||
return getSections(false)[layer] != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -819,10 +823,10 @@ public class BukkitGetBlocks_1_16_1 extends CharGetBlocks {
|
||||
return super.trim(true);
|
||||
} else {
|
||||
for (int i = 0; i < 16; i++) {
|
||||
if (!hasSection(i) || super.sections[i] == CharBlocks.EMPTY) {
|
||||
if (!hasSection(i) || !super.sections[i].isFull()) {
|
||||
continue;
|
||||
}
|
||||
ChunkSection existing = getSections()[i];
|
||||
ChunkSection existing = getSections(true)[i];
|
||||
try {
|
||||
final DataPaletteBlock<IBlockData> blocksExisting = existing.getBlocks();
|
||||
|
||||
|
@ -2,6 +2,10 @@ package com.boydti.fawe.bukkit.adapter.mc1_16_1;
|
||||
|
||||
|
||||
import com.boydti.fawe.FaweCache;
|
||||
import com.boydti.fawe.beta.IBlocks;
|
||||
import com.boydti.fawe.beta.IChunkGet;
|
||||
import com.boydti.fawe.beta.IChunkSet;
|
||||
import com.boydti.fawe.beta.implementation.lighting.HeightMapType;
|
||||
import com.boydti.fawe.bukkit.adapter.mc1_16_1.nbt.LazyCompoundTag_1_16_1;
|
||||
import com.google.common.base.Suppliers;
|
||||
import com.sk89q.jnbt.CompoundTag;
|
||||
@ -16,28 +20,30 @@ import com.sk89q.worldedit.world.block.BlockTypesCache;
|
||||
import net.minecraft.server.v1_16_R1.BiomeBase;
|
||||
import net.minecraft.server.v1_16_R1.BiomeStorage;
|
||||
import net.minecraft.server.v1_16_R1.Entity;
|
||||
import net.minecraft.server.v1_16_R1.IRegistry;
|
||||
import net.minecraft.server.v1_16_R1.NBTTagCompound;
|
||||
import net.minecraft.server.v1_16_R1.TileEntity;
|
||||
import net.minecraft.server.v1_16_R1.WorldServer;
|
||||
import org.bukkit.craftbukkit.v1_16_R1.block.CraftBlock;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.annotations.Range;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
public class BukkitGetBlocks_1_16_1_Copy extends BukkitGetBlocks_1_16_1 {
|
||||
public class BukkitGetBlocks_1_16_1_Copy implements IChunkGet {
|
||||
|
||||
private final Map<BlockVector3, CompoundTag> tiles = new HashMap<>();
|
||||
private final Set<CompoundTag> entities = new HashSet<>();
|
||||
private BiomeStorage biomeStorage;
|
||||
private final char[][] blocks = new char[16][4096];
|
||||
private final char[][] blocks = new char[16][];
|
||||
private final WorldServer world;
|
||||
|
||||
protected BukkitGetBlocks_1_16_1_Copy(WorldServer world, int X, int Z) {
|
||||
super(world, X, Z);
|
||||
protected BukkitGetBlocks_1_16_1_Copy(WorldServer world) {
|
||||
this.world = world;
|
||||
}
|
||||
|
||||
protected void storeTile(TileEntity tile) {
|
||||
@ -88,6 +94,16 @@ public class BukkitGetBlocks_1_16_1_Copy extends BukkitGetBlocks_1_16_1 {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCreateCopy(boolean createCopy) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCreateCopy() {
|
||||
return false;
|
||||
}
|
||||
|
||||
protected void storeBiomes(BiomeStorage biomeStorage) {
|
||||
this.biomeStorage = new BiomeStorage(BukkitAdapter_1_16_1.getBiomeArray(biomeStorage).clone());
|
||||
}
|
||||
@ -106,8 +122,18 @@ public class BukkitGetBlocks_1_16_1_Copy extends BukkitGetBlocks_1_16_1 {
|
||||
return base != null ? BukkitAdapter.adapt(CraftBlock.biomeBaseToBiome(base)) : null;
|
||||
}
|
||||
|
||||
protected void storeSection(int layer) {
|
||||
blocks[layer] = update(layer, null).clone();
|
||||
@Override
|
||||
public boolean trim(boolean aggressive, int layer) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IBlocks reset() {
|
||||
return null;
|
||||
}
|
||||
|
||||
protected void storeSection(int layer, char[] data) {
|
||||
blocks[layer] = data;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -116,15 +142,50 @@ public class BukkitGetBlocks_1_16_1_Copy extends BukkitGetBlocks_1_16_1 {
|
||||
return state.toBaseBlock(this, x, y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasSection(@Range(from = 0, to = 15) int layer) {
|
||||
return blocks[layer] != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public char[] load(int layer) {
|
||||
return blocks[layer];
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockState getBlock(int x, int y, int z) {
|
||||
return BlockTypesCache.states[get(x, y, z)];
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSkyLight(int x, int y, int z) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getEmmittedLight(int x, int y, int z) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getHeightMap(HeightMapType type) {
|
||||
return new int[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends Future<T>> T call(IChunkSet set, Runnable finalize) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public char get(int x, int y, int z) {
|
||||
final int layer = y >> 4;
|
||||
final int index = (y & 15) << 8 | z << 4 | x;
|
||||
return blocks[layer][index];
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean trim(boolean aggressive) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -59,7 +59,7 @@ public class FAWEWorldNativeAccess_1_16 implements WorldNativeAccess<Chunk, IBlo
|
||||
|
||||
@Override
|
||||
public IBlockData toNative(BlockState state) {
|
||||
int stateId = BlockStateIdAccess.getBlockStateId(state);
|
||||
int stateId = adapter.ordinalToIbdID(state.getOrdinalChar());
|
||||
return BlockStateIdAccess.isValidInternalId(stateId)
|
||||
? Block.getByCombinedId(stateId)
|
||||
: ((CraftBlockData) BukkitAdapter.adapt(state)).getState();
|
||||
@ -73,7 +73,8 @@ public class FAWEWorldNativeAccess_1_16 implements WorldNativeAccess<Chunk, IBlo
|
||||
@Nullable
|
||||
@Override
|
||||
public IBlockData setBlockState(Chunk chunk, BlockPosition position, IBlockData state) {
|
||||
return chunk.setType(position, state, false);
|
||||
return chunk.setType(position, state,
|
||||
this.sideEffectSet != null && this.sideEffectSet.shouldApply(SideEffect.UPDATE));
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -167,9 +168,4 @@ public class FAWEWorldNativeAccess_1_16 implements WorldNativeAccess<Chunk, IBlo
|
||||
public void onBlockStateChange(BlockPosition pos, IBlockData oldState, IBlockData newState) {
|
||||
getWorld().a(pos, oldState, newState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <B extends BlockStateHolder<B>> boolean setBlock(BlockVector3 position, B block, SideEffectSet sideEffects) throws WorldEditException {
|
||||
return this.adapter.setBlock(this.getChunk(position.getBlockX() >> 4, position.getBlockZ() >> 4).bukkitChunk, position.getBlockX(), position.getBlockY(), position.getBlockZ(), block, sideEffectSet.shouldApply(SideEffect.LIGHTING));
|
||||
}
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -199,7 +199,6 @@ public final class BukkitAdapter_1_16_2 extends NMSAdapter {
|
||||
return;
|
||||
}
|
||||
if (playerChunk.hasBeenLoaded()) {
|
||||
TaskManager.IMP.sync(() -> {
|
||||
ChunkCoordIntPair chunkCoordIntPair = new ChunkCoordIntPair(chunkX, chunkZ);
|
||||
Optional<Chunk> optional = ((Either) playerChunk.a().getNow(PlayerChunk.UNLOADED_CHUNK)).left();
|
||||
if (optional.isPresent()) {
|
||||
@ -209,7 +208,8 @@ public final class BukkitAdapter_1_16_2 extends NMSAdapter {
|
||||
});
|
||||
|
||||
if (lighting) {
|
||||
boolean trustEdges = true; //This needs to be true otherwise Minecraft will update lighting from/at the chunk edges (bad)
|
||||
//This needs to be true otherwise Minecraft will update lighting from/at the chunk edges (bad)
|
||||
boolean trustEdges = true;
|
||||
PacketPlayOutLightUpdate packet = new PacketPlayOutLightUpdate(chunkCoordIntPair, nmsWorld.getChunkProvider().getLightEngine(), trustEdges);
|
||||
playerChunk.players.a(chunkCoordIntPair, false).forEach(p -> {
|
||||
p.playerConnection.sendPacket(packet);
|
||||
@ -220,7 +220,7 @@ public final class BukkitAdapter_1_16_2 extends NMSAdapter {
|
||||
PooledLinkedHashSets.PooledObjectLinkedOpenHashSet<?> objects =
|
||||
nmsWorld.getChunkProvider().playerChunkMap.playerViewDistanceNoTickMap.getObjectsInRange(chunkX, chunkZ);
|
||||
if (objects == null) {
|
||||
return null;
|
||||
return;
|
||||
}
|
||||
for (Object obj : objects.getBackingSet()) {
|
||||
if (obj == null) {
|
||||
@ -233,8 +233,8 @@ public final class BukkitAdapter_1_16_2 extends NMSAdapter {
|
||||
p.playerConnection.sendPacket(chunkpacket);
|
||||
|
||||
if (lighting) {
|
||||
boolean trustEdges =
|
||||
true; //This needs to be true otherwise Minecraft will update lighting from/at the chunk edges (bad)
|
||||
//This needs to be true otherwise Minecraft will update lighting from/at the chunk edges (bad)
|
||||
boolean trustEdges = true;
|
||||
PacketPlayOutLightUpdate packet =
|
||||
new PacketPlayOutLightUpdate(chunkCoordIntPair, nmsWorld.getChunkProvider().getLightEngine(), trustEdges);
|
||||
p.playerConnection.sendPacket(packet);
|
||||
@ -242,8 +242,6 @@ public final class BukkitAdapter_1_16_2 extends NMSAdapter {
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4,7 +4,6 @@ import com.boydti.fawe.Fawe;
|
||||
import com.boydti.fawe.FaweCache;
|
||||
import com.boydti.fawe.beta.IChunkGet;
|
||||
import com.boydti.fawe.beta.IChunkSet;
|
||||
import com.boydti.fawe.beta.implementation.blocks.CharBlocks;
|
||||
import com.boydti.fawe.beta.implementation.blocks.CharGetBlocks;
|
||||
import com.boydti.fawe.beta.implementation.lighting.HeightMapType;
|
||||
import com.boydti.fawe.beta.implementation.queue.QueueHandler;
|
||||
@ -91,6 +90,7 @@ public class BukkitGetBlocks_1_16_2 extends CharGetBlocks {
|
||||
public NibbleArray[] skyLight = new NibbleArray[16];
|
||||
private boolean createCopy = false;
|
||||
private BukkitGetBlocks_1_16_2_Copy copy = null;
|
||||
private boolean forceLoadSections = true;
|
||||
|
||||
public BukkitGetBlocks_1_16_2(World world, int chunkX, int chunkZ) {
|
||||
this(((CraftWorld) world).getHandle(), chunkX, chunkZ);
|
||||
@ -319,7 +319,8 @@ public class BukkitGetBlocks_1_16_2 extends CharGetBlocks {
|
||||
|
||||
@Override
|
||||
public <T extends Future<T>> T call(IChunkSet set, Runnable finalizer) {
|
||||
copy = createCopy ? new BukkitGetBlocks_1_16_2_Copy(world, getChunkX(), getChunkZ()) : null;
|
||||
forceLoadSections = false;
|
||||
copy = createCopy ? new BukkitGetBlocks_1_16_2_Copy(world) : null;
|
||||
try {
|
||||
WorldServer nmsWorld = world;
|
||||
Chunk nmsChunk = ensureLoaded(nmsWorld, chunkX, chunkZ);
|
||||
@ -360,13 +361,14 @@ public class BukkitGetBlocks_1_16_2 extends CharGetBlocks {
|
||||
if (!set.hasSection(layer)) {
|
||||
continue;
|
||||
}
|
||||
if (createCopy) {
|
||||
copy.storeSection(layer);
|
||||
}
|
||||
|
||||
bitMask |= 1 << layer;
|
||||
|
||||
char[] setArr = set.load(layer);
|
||||
char[] setArr = set.load(layer).clone();
|
||||
if (createCopy) {
|
||||
copy.storeSection(layer, load(layer).clone());
|
||||
}
|
||||
|
||||
ChunkSection newSection;
|
||||
ChunkSection existingSection = sections[layer];
|
||||
if (existingSection == null) {
|
||||
@ -395,7 +397,7 @@ public class BukkitGetBlocks_1_16_2 extends CharGetBlocks {
|
||||
this.nmsChunk = nmsChunk;
|
||||
this.sections = null;
|
||||
this.reset();
|
||||
} else if (existingSection != getSections()[layer]) {
|
||||
} else if (existingSection != getSections(false)[layer]) {
|
||||
this.sections[layer] = existingSection;
|
||||
this.reset();
|
||||
} else if (!Arrays.equals(update(layer, new char[4096]), load(layer))) {
|
||||
@ -408,7 +410,6 @@ public class BukkitGetBlocks_1_16_2 extends CharGetBlocks {
|
||||
if (!BukkitAdapter_1_16_2
|
||||
.setSectionAtomic(sections, existingSection, newSection, layer)) {
|
||||
log.error("Failed to set chunk section:" + chunkX + "," + chunkZ + " layer: " + layer);
|
||||
continue;
|
||||
} else {
|
||||
updateGet(this, nmsChunk, sections, newSection, setArr, layer);
|
||||
}
|
||||
@ -475,9 +476,7 @@ public class BukkitGetBlocks_1_16_2 extends CharGetBlocks {
|
||||
|
||||
Set<UUID> entityRemoves = set.getEntityRemoves();
|
||||
if (entityRemoves != null && !entityRemoves.isEmpty()) {
|
||||
if (syncTasks == null) {
|
||||
syncTasks = new Runnable[3];
|
||||
}
|
||||
|
||||
syncTasks[2] = () -> {
|
||||
final List<Entity>[] entities = nmsChunk.getEntitySlices();
|
||||
@ -637,12 +636,14 @@ public class BukkitGetBlocks_1_16_2 extends CharGetBlocks {
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
} finally {
|
||||
forceLoadSections = true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized char[] update(int layer, char[] data) {
|
||||
ChunkSection section = getSections()[layer];
|
||||
ChunkSection section = getSections(true)[layer];
|
||||
// Section is null, return empty array
|
||||
if (section == null) {
|
||||
data = new char[4096];
|
||||
@ -757,7 +758,10 @@ public class BukkitGetBlocks_1_16_2 extends CharGetBlocks {
|
||||
}
|
||||
}
|
||||
|
||||
public ChunkSection[] getSections() {
|
||||
public ChunkSection[] getSections(boolean force) {
|
||||
if (force && forceLoadSections) {
|
||||
return sections = getChunk().getSections().clone();
|
||||
}
|
||||
ChunkSection[] tmp = sections;
|
||||
if (tmp == null) {
|
||||
synchronized (this) {
|
||||
@ -809,7 +813,7 @@ public class BukkitGetBlocks_1_16_2 extends CharGetBlocks {
|
||||
|
||||
@Override
|
||||
public boolean hasSection(int layer) {
|
||||
return getSections()[layer] != null;
|
||||
return getSections(false)[layer] != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -822,10 +826,10 @@ public class BukkitGetBlocks_1_16_2 extends CharGetBlocks {
|
||||
return super.trim(true);
|
||||
} else {
|
||||
for (int i = 0; i < 16; i++) {
|
||||
if (!hasSection(i) || super.sections[i] == CharBlocks.EMPTY) {
|
||||
if (!hasSection(i) || !super.sections[i].isFull()) {
|
||||
continue;
|
||||
}
|
||||
ChunkSection existing = getSections()[i];
|
||||
ChunkSection existing = getSections(true)[i];
|
||||
try {
|
||||
final DataPaletteBlock<IBlockData> blocksExisting = existing.getBlocks();
|
||||
|
||||
|
@ -2,6 +2,10 @@ package com.boydti.fawe.bukkit.adapter.mc1_16_2;
|
||||
|
||||
|
||||
import com.boydti.fawe.FaweCache;
|
||||
import com.boydti.fawe.beta.IBlocks;
|
||||
import com.boydti.fawe.beta.IChunkGet;
|
||||
import com.boydti.fawe.beta.IChunkSet;
|
||||
import com.boydti.fawe.beta.implementation.lighting.HeightMapType;
|
||||
import com.boydti.fawe.bukkit.adapter.mc1_16_2.nbt.LazyCompoundTag_1_16_2;
|
||||
import com.google.common.base.Suppliers;
|
||||
import com.sk89q.jnbt.CompoundTag;
|
||||
@ -22,22 +26,25 @@ import net.minecraft.server.v1_16_R2.TileEntity;
|
||||
import net.minecraft.server.v1_16_R2.WorldServer;
|
||||
import org.bukkit.craftbukkit.v1_16_R2.block.CraftBlock;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.annotations.Range;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
public class BukkitGetBlocks_1_16_2_Copy extends BukkitGetBlocks_1_16_2 {
|
||||
public class BukkitGetBlocks_1_16_2_Copy implements IChunkGet {
|
||||
|
||||
private final Map<BlockVector3, CompoundTag> tiles = new HashMap<>();
|
||||
private final Set<CompoundTag> entities = new HashSet<>();
|
||||
private BiomeStorage biomeStorage;
|
||||
private final char[][] blocks = new char[16][4096];
|
||||
private final char[][] blocks = new char[16][];
|
||||
private final WorldServer world;
|
||||
|
||||
protected BukkitGetBlocks_1_16_2_Copy(WorldServer world, int X, int Z) {
|
||||
super(world, X, Z);
|
||||
protected BukkitGetBlocks_1_16_2_Copy(WorldServer world) {
|
||||
this.world = world;
|
||||
}
|
||||
|
||||
protected void storeTile(TileEntity tile) {
|
||||
@ -88,6 +95,16 @@ public class BukkitGetBlocks_1_16_2_Copy extends BukkitGetBlocks_1_16_2 {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCreateCopy(boolean createCopy) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCreateCopy() {
|
||||
return false;
|
||||
}
|
||||
|
||||
protected void storeBiomes(BiomeStorage biomeStorage) {
|
||||
this.biomeStorage = new BiomeStorage(biomeStorage.g, BukkitAdapter_1_16_2.getBiomeArray(biomeStorage).clone());
|
||||
}
|
||||
@ -106,8 +123,18 @@ public class BukkitGetBlocks_1_16_2_Copy extends BukkitGetBlocks_1_16_2 {
|
||||
return base != null ? BukkitAdapter.adapt(CraftBlock.biomeBaseToBiome(world.r().b(IRegistry.ay), base)) : null;
|
||||
}
|
||||
|
||||
protected void storeSection(int layer) {
|
||||
blocks[layer] = update(layer, null).clone();
|
||||
@Override
|
||||
public boolean trim(boolean aggressive, int layer) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IBlocks reset() {
|
||||
return null;
|
||||
}
|
||||
|
||||
protected void storeSection(int layer, char[] data) {
|
||||
blocks[layer] = data;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -116,15 +143,50 @@ public class BukkitGetBlocks_1_16_2_Copy extends BukkitGetBlocks_1_16_2 {
|
||||
return state.toBaseBlock(this, x, y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasSection(@Range(from = 0, to = 15) int layer) {
|
||||
return blocks[layer] != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public char[] load(int layer) {
|
||||
return blocks[layer];
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockState getBlock(int x, int y, int z) {
|
||||
return BlockTypesCache.states[get(x, y, z)];
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSkyLight(int x, int y, int z) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getEmmittedLight(int x, int y, int z) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getHeightMap(HeightMapType type) {
|
||||
return new int[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends Future<T>> T call(IChunkSet set, Runnable finalize) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public char get(int x, int y, int z) {
|
||||
final int layer = y >> 4;
|
||||
final int index = (y & 15) << 8 | z << 4 | x;
|
||||
return blocks[layer][index];
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean trim(boolean aggressive) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -59,7 +59,7 @@ public class FAWEWorldNativeAccess_1_16 implements WorldNativeAccess<Chunk, IBlo
|
||||
|
||||
@Override
|
||||
public IBlockData toNative(BlockState state) {
|
||||
int stateId = BlockStateIdAccess.getBlockStateId(state);
|
||||
int stateId = adapter.ordinalToIbdID(state.getOrdinalChar());
|
||||
return BlockStateIdAccess.isValidInternalId(stateId)
|
||||
? Block.getByCombinedId(stateId)
|
||||
: ((CraftBlockData) BukkitAdapter.adapt(state)).getState();
|
||||
@ -73,7 +73,8 @@ public class FAWEWorldNativeAccess_1_16 implements WorldNativeAccess<Chunk, IBlo
|
||||
@Nullable
|
||||
@Override
|
||||
public IBlockData setBlockState(Chunk chunk, BlockPosition position, IBlockData state) {
|
||||
return chunk.setType(position, state, false);
|
||||
return chunk.setType(position, state,
|
||||
this.sideEffectSet != null && this.sideEffectSet.shouldApply(SideEffect.UPDATE));
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -167,9 +168,4 @@ public class FAWEWorldNativeAccess_1_16 implements WorldNativeAccess<Chunk, IBlo
|
||||
public void onBlockStateChange(BlockPosition pos, IBlockData oldState, IBlockData newState) {
|
||||
getWorld().a(pos, oldState, newState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <B extends BlockStateHolder<B>> boolean setBlock(BlockVector3 position, B block, SideEffectSet sideEffects) throws WorldEditException {
|
||||
return this.adapter.setBlock(this.getChunk(position.getBlockX() >> 4, position.getBlockZ() >> 4).bukkitChunk, position.getBlockX(), position.getBlockY(), position.getBlockZ(), block, sideEffectSet.shouldApply(SideEffect.LIGHTING));
|
||||
}
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -199,7 +199,6 @@ public final class BukkitAdapter_1_16_4 extends NMSAdapter {
|
||||
return;
|
||||
}
|
||||
if (playerChunk.hasBeenLoaded()) {
|
||||
TaskManager.IMP.sync(() -> {
|
||||
ChunkCoordIntPair chunkCoordIntPair = new ChunkCoordIntPair(chunkX, chunkZ);
|
||||
Optional<Chunk> optional = ((Either) playerChunk.a().getNow(PlayerChunk.UNLOADED_CHUNK)).left();
|
||||
if (optional.isPresent()) {
|
||||
@ -209,8 +208,11 @@ public final class BukkitAdapter_1_16_4 extends NMSAdapter {
|
||||
});
|
||||
|
||||
if (lighting) {
|
||||
boolean trustEdges = true; //This needs to be true otherwise Minecraft will update lighting from/at the chunk edges (bad)
|
||||
PacketPlayOutLightUpdate packet = new PacketPlayOutLightUpdate(chunkCoordIntPair, nmsWorld.getChunkProvider().getLightEngine(), trustEdges);
|
||||
//This needs to be true otherwise Minecraft will update lighting from/at the chunk edges (bad)
|
||||
boolean trustEdges = true;
|
||||
PacketPlayOutLightUpdate packet =
|
||||
new PacketPlayOutLightUpdate(chunkCoordIntPair, nmsWorld.getChunkProvider().getLightEngine(),
|
||||
trustEdges);
|
||||
playerChunk.players.a(chunkCoordIntPair, false).forEach(p -> {
|
||||
p.playerConnection.sendPacket(packet);
|
||||
});
|
||||
@ -218,9 +220,10 @@ public final class BukkitAdapter_1_16_4 extends NMSAdapter {
|
||||
} else if (PaperLib.isPaper()) {
|
||||
//Require generic here to work with multiple dependencies trying to take control.
|
||||
PooledLinkedHashSets.PooledObjectLinkedOpenHashSet<?> objects =
|
||||
nmsWorld.getChunkProvider().playerChunkMap.playerViewDistanceNoTickMap.getObjectsInRange(chunkX, chunkZ);
|
||||
nmsWorld.getChunkProvider().playerChunkMap.playerViewDistanceNoTickMap
|
||||
.getObjectsInRange(chunkX, chunkZ);
|
||||
if (objects == null) {
|
||||
return null;
|
||||
return;
|
||||
}
|
||||
for (Object obj : objects.getBackingSet()) {
|
||||
if (obj == null) {
|
||||
@ -233,17 +236,15 @@ public final class BukkitAdapter_1_16_4 extends NMSAdapter {
|
||||
p.playerConnection.sendPacket(chunkpacket);
|
||||
|
||||
if (lighting) {
|
||||
boolean trustEdges =
|
||||
true; //This needs to be true otherwise Minecraft will update lighting from/at the chunk edges (bad)
|
||||
PacketPlayOutLightUpdate packet =
|
||||
new PacketPlayOutLightUpdate(chunkCoordIntPair, nmsWorld.getChunkProvider().getLightEngine(), trustEdges);
|
||||
//This needs to be true otherwise Minecraft will update lighting from/at the chunk edges (bad)
|
||||
boolean trustEdges = true;
|
||||
PacketPlayOutLightUpdate packet = new PacketPlayOutLightUpdate(chunkCoordIntPair,
|
||||
nmsWorld.getChunkProvider().getLightEngine(), trustEdges);
|
||||
p.playerConnection.sendPacket(packet);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4,7 +4,6 @@ import com.boydti.fawe.Fawe;
|
||||
import com.boydti.fawe.FaweCache;
|
||||
import com.boydti.fawe.beta.IChunkGet;
|
||||
import com.boydti.fawe.beta.IChunkSet;
|
||||
import com.boydti.fawe.beta.implementation.blocks.CharBlocks;
|
||||
import com.boydti.fawe.beta.implementation.blocks.CharGetBlocks;
|
||||
import com.boydti.fawe.beta.implementation.lighting.HeightMapType;
|
||||
import com.boydti.fawe.beta.implementation.queue.QueueHandler;
|
||||
@ -91,6 +90,7 @@ public class BukkitGetBlocks_1_16_4 extends CharGetBlocks {
|
||||
public NibbleArray[] skyLight = new NibbleArray[16];
|
||||
private boolean createCopy = false;
|
||||
private BukkitGetBlocks_1_16_4_Copy copy = null;
|
||||
private boolean forceLoadSections = true;
|
||||
|
||||
public BukkitGetBlocks_1_16_4(World world, int chunkX, int chunkZ) {
|
||||
this(((CraftWorld) world).getHandle(), chunkX, chunkZ);
|
||||
@ -319,7 +319,8 @@ public class BukkitGetBlocks_1_16_4 extends CharGetBlocks {
|
||||
|
||||
@Override
|
||||
public <T extends Future<T>> T call(IChunkSet set, Runnable finalizer) {
|
||||
copy = createCopy ? new BukkitGetBlocks_1_16_4_Copy(world, getChunkX(), getChunkZ()) : null;
|
||||
forceLoadSections = false;
|
||||
copy = createCopy ? new BukkitGetBlocks_1_16_4_Copy(world) : null;
|
||||
try {
|
||||
WorldServer nmsWorld = world;
|
||||
Chunk nmsChunk = ensureLoaded(nmsWorld, chunkX, chunkZ);
|
||||
@ -360,13 +361,14 @@ public class BukkitGetBlocks_1_16_4 extends CharGetBlocks {
|
||||
if (!set.hasSection(layer)) {
|
||||
continue;
|
||||
}
|
||||
if (createCopy) {
|
||||
copy.storeSection(layer);
|
||||
}
|
||||
|
||||
bitMask |= 1 << layer;
|
||||
|
||||
char[] setArr = set.load(layer);
|
||||
char[] setArr = set.load(layer).clone();
|
||||
if (createCopy) {
|
||||
copy.storeSection(layer, load(layer).clone());
|
||||
}
|
||||
|
||||
ChunkSection newSection;
|
||||
ChunkSection existingSection = sections[layer];
|
||||
if (existingSection == null) {
|
||||
@ -395,7 +397,7 @@ public class BukkitGetBlocks_1_16_4 extends CharGetBlocks {
|
||||
this.nmsChunk = nmsChunk;
|
||||
this.sections = null;
|
||||
this.reset();
|
||||
} else if (existingSection != getSections()[layer]) {
|
||||
} else if (existingSection != getSections(false)[layer]) {
|
||||
this.sections[layer] = existingSection;
|
||||
this.reset();
|
||||
} else if (!Arrays.equals(update(layer, new char[4096]), load(layer))) {
|
||||
@ -408,7 +410,6 @@ public class BukkitGetBlocks_1_16_4 extends CharGetBlocks {
|
||||
if (!BukkitAdapter_1_16_4
|
||||
.setSectionAtomic(sections, existingSection, newSection, layer)) {
|
||||
log.error("Failed to set chunk section:" + chunkX + "," + chunkZ + " layer: " + layer);
|
||||
continue;
|
||||
} else {
|
||||
updateGet(this, nmsChunk, sections, newSection, setArr, layer);
|
||||
}
|
||||
@ -475,9 +476,7 @@ public class BukkitGetBlocks_1_16_4 extends CharGetBlocks {
|
||||
|
||||
Set<UUID> entityRemoves = set.getEntityRemoves();
|
||||
if (entityRemoves != null && !entityRemoves.isEmpty()) {
|
||||
if (syncTasks == null) {
|
||||
syncTasks = new Runnable[3];
|
||||
}
|
||||
|
||||
syncTasks[2] = () -> {
|
||||
final List<Entity>[] entities = nmsChunk.getEntitySlices();
|
||||
@ -637,12 +636,14 @@ public class BukkitGetBlocks_1_16_4 extends CharGetBlocks {
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
} finally {
|
||||
forceLoadSections = true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized char[] update(int layer, char[] data) {
|
||||
ChunkSection section = getSections()[layer];
|
||||
ChunkSection section = getSections(true)[layer];
|
||||
// Section is null, return empty array
|
||||
if (section == null) {
|
||||
data = new char[4096];
|
||||
@ -757,7 +758,10 @@ public class BukkitGetBlocks_1_16_4 extends CharGetBlocks {
|
||||
}
|
||||
}
|
||||
|
||||
public ChunkSection[] getSections() {
|
||||
public ChunkSection[] getSections(boolean force) {
|
||||
if (force && forceLoadSections) {
|
||||
return sections = getChunk().getSections().clone();
|
||||
}
|
||||
ChunkSection[] tmp = sections;
|
||||
if (tmp == null) {
|
||||
synchronized (this) {
|
||||
@ -809,7 +813,7 @@ public class BukkitGetBlocks_1_16_4 extends CharGetBlocks {
|
||||
|
||||
@Override
|
||||
public boolean hasSection(int layer) {
|
||||
return getSections()[layer] != null;
|
||||
return getSections(false)[layer] != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -822,10 +826,10 @@ public class BukkitGetBlocks_1_16_4 extends CharGetBlocks {
|
||||
return super.trim(true);
|
||||
} else {
|
||||
for (int i = 0; i < 16; i++) {
|
||||
if (!hasSection(i) || super.sections[i] == CharBlocks.EMPTY) {
|
||||
if (!hasSection(i) || !super.sections[i].isFull()) {
|
||||
continue;
|
||||
}
|
||||
ChunkSection existing = getSections()[i];
|
||||
ChunkSection existing = getSections(true)[i];
|
||||
try {
|
||||
final DataPaletteBlock<IBlockData> blocksExisting = existing.getBlocks();
|
||||
|
||||
|
@ -2,6 +2,10 @@ package com.boydti.fawe.bukkit.adapter.mc1_16_4;
|
||||
|
||||
|
||||
import com.boydti.fawe.FaweCache;
|
||||
import com.boydti.fawe.beta.IBlocks;
|
||||
import com.boydti.fawe.beta.IChunkGet;
|
||||
import com.boydti.fawe.beta.IChunkSet;
|
||||
import com.boydti.fawe.beta.implementation.lighting.HeightMapType;
|
||||
import com.boydti.fawe.bukkit.adapter.mc1_16_4.nbt.LazyCompoundTag_1_16_4;
|
||||
import com.google.common.base.Suppliers;
|
||||
import com.sk89q.jnbt.CompoundTag;
|
||||
@ -22,22 +26,25 @@ import net.minecraft.server.v1_16_R3.TileEntity;
|
||||
import net.minecraft.server.v1_16_R3.WorldServer;
|
||||
import org.bukkit.craftbukkit.v1_16_R3.block.CraftBlock;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.annotations.Range;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
public class BukkitGetBlocks_1_16_4_Copy extends BukkitGetBlocks_1_16_4 {
|
||||
public class BukkitGetBlocks_1_16_4_Copy implements IChunkGet {
|
||||
|
||||
private final Map<BlockVector3, CompoundTag> tiles = new HashMap<>();
|
||||
private final Set<CompoundTag> entities = new HashSet<>();
|
||||
private BiomeStorage biomeStorage;
|
||||
private final char[][] blocks = new char[16][4096];
|
||||
private final char[][] blocks = new char[16][];
|
||||
private final WorldServer world;
|
||||
|
||||
protected BukkitGetBlocks_1_16_4_Copy(WorldServer world, int X, int Z) {
|
||||
super(world, X, Z);
|
||||
protected BukkitGetBlocks_1_16_4_Copy(WorldServer world) {
|
||||
this.world = world;
|
||||
}
|
||||
|
||||
protected void storeTile(TileEntity tile) {
|
||||
@ -88,6 +95,16 @@ public class BukkitGetBlocks_1_16_4_Copy extends BukkitGetBlocks_1_16_4 {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCreateCopy(boolean createCopy) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCreateCopy() {
|
||||
return false;
|
||||
}
|
||||
|
||||
protected void storeBiomes(BiomeStorage biomeStorage) {
|
||||
this.biomeStorage = new BiomeStorage(biomeStorage.g, BukkitAdapter_1_16_4.getBiomeArray(biomeStorage).clone());
|
||||
}
|
||||
@ -106,8 +123,18 @@ public class BukkitGetBlocks_1_16_4_Copy extends BukkitGetBlocks_1_16_4 {
|
||||
return base != null ? BukkitAdapter.adapt(CraftBlock.biomeBaseToBiome(world.r().b(IRegistry.ay), base)) : null;
|
||||
}
|
||||
|
||||
protected void storeSection(int layer) {
|
||||
blocks[layer] = update(layer, null).clone();
|
||||
@Override
|
||||
public boolean trim(boolean aggressive, int layer) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IBlocks reset() {
|
||||
return null;
|
||||
}
|
||||
|
||||
protected void storeSection(int layer, char[] data) {
|
||||
blocks[layer] = data;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -116,15 +143,50 @@ public class BukkitGetBlocks_1_16_4_Copy extends BukkitGetBlocks_1_16_4 {
|
||||
return state.toBaseBlock(this, x, y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasSection(@Range(from = 0, to = 15) int layer) {
|
||||
return blocks[layer] != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public char[] load(int layer) {
|
||||
return blocks[layer];
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockState getBlock(int x, int y, int z) {
|
||||
return BlockTypesCache.states[get(x, y, z)];
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSkyLight(int x, int y, int z) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getEmmittedLight(int x, int y, int z) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getHeightMap(HeightMapType type) {
|
||||
return new int[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends Future<T>> T call(IChunkSet set, Runnable finalize) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public char get(int x, int y, int z) {
|
||||
final int layer = y >> 4;
|
||||
final int index = (y & 15) << 8 | z << 4 | x;
|
||||
return blocks[layer][index];
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean trim(boolean aggressive) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -60,7 +60,7 @@ public class FAWEWorldNativeAccess_1_16 implements WorldNativeAccess<Chunk, IBlo
|
||||
|
||||
@Override
|
||||
public IBlockData toNative(BlockState state) {
|
||||
int stateId = BlockStateIdAccess.getBlockStateId(state);
|
||||
int stateId = adapter.ordinalToIbdID(state.getOrdinalChar());
|
||||
return BlockStateIdAccess.isValidInternalId(stateId)
|
||||
? Block.getByCombinedId(stateId)
|
||||
: ((CraftBlockData) BukkitAdapter.adapt(state)).getState();
|
||||
@ -74,7 +74,8 @@ public class FAWEWorldNativeAccess_1_16 implements WorldNativeAccess<Chunk, IBlo
|
||||
@Nullable
|
||||
@Override
|
||||
public IBlockData setBlockState(Chunk chunk, BlockPosition position, IBlockData state) {
|
||||
return chunk.setType(position, state, false);
|
||||
return chunk.setType(position, state,
|
||||
this.sideEffectSet != null && this.sideEffectSet.shouldApply(SideEffect.UPDATE));
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -168,9 +169,4 @@ public class FAWEWorldNativeAccess_1_16 implements WorldNativeAccess<Chunk, IBlo
|
||||
public void onBlockStateChange(BlockPosition pos, IBlockData oldState, IBlockData newState) {
|
||||
getWorld().a(pos, oldState, newState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <B extends BlockStateHolder<B>> boolean setBlock(BlockVector3 position, B block, SideEffectSet sideEffects) throws WorldEditException {
|
||||
return this.adapter.setBlock(this.getChunk(position.getBlockX() >> 4, position.getBlockZ() >> 4).bukkitChunk, position.getBlockX(), position.getBlockY(), position.getBlockZ(), block, sideEffectSet.shouldApply(SideEffect.LIGHTING));
|
||||
}
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
@ -9,36 +8,46 @@ import com.boydti.fawe.util.IOUtil;
|
||||
import com.boydti.fawe.util.TaskManager;
|
||||
import com.plotsquared.core.PlotSquared;
|
||||
import com.plotsquared.core.location.Location;
|
||||
import com.plotsquared.core.plot.schematic.Schematic;
|
||||
import com.plotsquared.core.queue.LocalBlockQueue;
|
||||
import com.plotsquared.core.util.MainUtil;
|
||||
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;
|
||||
import com.sk89q.worldedit.extent.clipboard.Clipboard;
|
||||
import com.sk89q.worldedit.extent.clipboard.io.BuiltInClipboardFormat;
|
||||
import com.sk89q.worldedit.extent.clipboard.io.FastSchematicReader;
|
||||
import com.sk89q.worldedit.extent.clipboard.io.FastSchematicWriter;
|
||||
import com.sk89q.worldedit.extent.clipboard.io.MCEditSchematicReader;
|
||||
import com.sk89q.worldedit.extent.clipboard.io.SpongeSchematicReader;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
import com.sk89q.worldedit.regions.CuboidRegion;
|
||||
import com.sk89q.worldedit.world.World;
|
||||
import net.jpountz.lz4.LZ4BlockInputStream;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.EOFException;
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.URL;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.zip.GZIPInputStream;
|
||||
|
||||
import static org.bukkit.Bukkit.getWorld;
|
||||
|
||||
@ -114,16 +123,14 @@ public class FaweSchematicHandler extends SchematicHandler {
|
||||
com.plotsquared.core.util.task.TaskManager.runTask(whenDone);
|
||||
return;
|
||||
}
|
||||
CompoundTag weTag = (CompoundTag) FaweCache.IMP.asTag(tag);
|
||||
if (weTag instanceof CompressedSchematicTag) {
|
||||
Clipboard clipboard = ((CompressedSchematicTag) weTag).getSource();
|
||||
URL url = FaweAPI.upload(clipboard, BuiltInClipboardFormat.SPONGE_SCHEMATIC);
|
||||
whenDone.run(url);
|
||||
return;
|
||||
}
|
||||
final CompoundTag weTag = (CompoundTag) FaweCache.IMP.asTag(tag);
|
||||
MainUtil.upload(uuid, file, "schem", new RunnableVal<OutputStream>() {
|
||||
@Override
|
||||
public void run(OutputStream output) {
|
||||
if (weTag instanceof CompressedSchematicTag) {
|
||||
Clipboard clipboard = ((CompressedSchematicTag) weTag).getSource();
|
||||
BuiltInClipboardFormat.SPONGE_SCHEMATIC.write(output, clipboard);
|
||||
}
|
||||
try {
|
||||
try (PGZIPOutputStream gzip = new PGZIPOutputStream(output)) {
|
||||
try (NBTOutputStream nos = new NBTOutputStream(gzip)) {
|
||||
@ -137,4 +144,42 @@ public class FaweSchematicHandler extends SchematicHandler {
|
||||
}
|
||||
}, whenDone);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Schematic getSchematic(@NotNull InputStream is) {
|
||||
try {
|
||||
FastSchematicReader schematicReader = new FastSchematicReader(
|
||||
new NBTInputStream(new BufferedInputStream(new GZIPInputStream(new BufferedInputStream(is)))));
|
||||
Clipboard clip = schematicReader.read();
|
||||
return new Schematic(clip);
|
||||
} catch (IOException e) {
|
||||
if (e instanceof EOFException) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
SpongeSchematicReader schematicReader =
|
||||
new SpongeSchematicReader(new NBTInputStream(new GZIPInputStream(is)));
|
||||
Clipboard clip = schematicReader.read();
|
||||
return new Schematic(clip);
|
||||
} catch (IOException e2) {
|
||||
if (e2 instanceof EOFException) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
MCEditSchematicReader schematicReader =
|
||||
new MCEditSchematicReader(new NBTInputStream(new GZIPInputStream(is)));
|
||||
Clipboard clip = schematicReader.read();
|
||||
return new Schematic(clip);
|
||||
} catch (IOException e3) {
|
||||
e.printStackTrace();
|
||||
PlotSquared.debug(
|
||||
is.toString() + " | " + is.getClass().getCanonicalName() + " is not in GZIP format : " + e
|
||||
.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
});
|
||||
|
@ -26,8 +26,8 @@ import org.bukkit.plugin.Plugin;
|
||||
import org.bukkit.util.BoundingBox;
|
||||
import org.bukkit.util.RayTraceResult;
|
||||
import org.bukkit.util.Vector;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
@ -70,32 +70,32 @@ public class AsyncBlock implements Block {
|
||||
return world.getBlock(x, y, z).getBlockType().getInternalId();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Nonnull
|
||||
@Override
|
||||
public AsyncBlock getRelative(int modX, int modY, int modZ) {
|
||||
return new AsyncBlock(world, x + modX, y + modY, z + modZ);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Nonnull
|
||||
@Override
|
||||
public AsyncBlock getRelative(BlockFace face) {
|
||||
return this.getRelative(face.getModX(), face.getModY(), face.getModZ());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Nonnull
|
||||
@Override
|
||||
public AsyncBlock getRelative(BlockFace face, int distance) {
|
||||
return this.getRelative(face.getModX() * distance, face.getModY() * distance,
|
||||
face.getModZ() * distance);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Nonnull
|
||||
@Override
|
||||
public Material getType() {
|
||||
return getBlockData().getMaterial();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Nonnull
|
||||
@Override
|
||||
public BlockData getBlockData() {
|
||||
return BukkitAdapter.adapt(world.getBlock(x, y, z));
|
||||
@ -141,7 +141,7 @@ public class AsyncBlock implements Block {
|
||||
return (byte) 15;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Nonnull
|
||||
@Override
|
||||
public AsyncWorld getWorld() {
|
||||
return world;
|
||||
@ -162,7 +162,7 @@ public class AsyncBlock implements Block {
|
||||
return z;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Nonnull
|
||||
@Override
|
||||
public Location getLocation() {
|
||||
return new Location(world, x, y, z);
|
||||
@ -179,14 +179,14 @@ public class AsyncBlock implements Block {
|
||||
return loc;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Nonnull
|
||||
@Override
|
||||
public AsyncChunk getChunk() {
|
||||
return world.getChunkAt(x >> 4, z >> 4);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBlockData(@NotNull BlockData blockData) {
|
||||
public void setBlockData(@Nonnull BlockData blockData) {
|
||||
try {
|
||||
world.setBlock(x, y, z, BukkitAdapter.adapt(blockData));
|
||||
} catch (WorldEditException e) {
|
||||
@ -195,12 +195,12 @@ public class AsyncBlock implements Block {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBlockData(@NotNull BlockData blockData, boolean b) {
|
||||
public void setBlockData(@Nonnull BlockData blockData, boolean b) {
|
||||
setBlockData(blockData);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setType(@NotNull Material type) {
|
||||
public void setType(@Nonnull Material type) {
|
||||
try {
|
||||
world.setBlock(x, y, z, BukkitAdapter.asBlockType(type).getDefaultState());
|
||||
} catch (WorldEditException e) {
|
||||
@ -209,12 +209,12 @@ public class AsyncBlock implements Block {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setType(@NotNull Material type, boolean applyPhysics) {
|
||||
public void setType(@Nonnull Material type, boolean applyPhysics) {
|
||||
setType(type);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockFace getFace(@NotNull Block block) {
|
||||
public BlockFace getFace(@Nonnull Block block) {
|
||||
BlockFace[] directions = BlockFace.values();
|
||||
for (BlockFace face : directions) {
|
||||
if (this.getX() + face.getModX() == block.getX()
|
||||
@ -226,7 +226,7 @@ public class AsyncBlock implements Block {
|
||||
return null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Nonnull
|
||||
@Override
|
||||
public AsyncBlockState getState() {
|
||||
BaseBlock state = world.getFullBlock(x, y, z);
|
||||
@ -250,19 +250,19 @@ public class AsyncBlock implements Block {
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
@Nonnull
|
||||
public AsyncBlockState getState(boolean useSnapshot) {
|
||||
return getState();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Nonnull
|
||||
@Override
|
||||
public Biome getBiome() {
|
||||
return world.getAdapter().adapt(world.getBiomeType(x, y, z));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBiome(@NotNull Biome bio) {
|
||||
public void setBiome(@Nonnull Biome bio) {
|
||||
BiomeType biome = world.getAdapter().adapt(bio);
|
||||
world.setBiome(x, 0, z, biome);
|
||||
}
|
||||
@ -278,17 +278,17 @@ public class AsyncBlock implements Block {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBlockFacePowered(@NotNull BlockFace face) {
|
||||
public boolean isBlockFacePowered(@Nonnull BlockFace face) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBlockFaceIndirectlyPowered(@NotNull BlockFace face) {
|
||||
public boolean isBlockFaceIndirectlyPowered(@Nonnull BlockFace face) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBlockPower(@NotNull BlockFace face) {
|
||||
public int getBlockPower(@Nonnull BlockFace face) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -314,6 +314,21 @@ public class AsyncBlock implements Block {
|
||||
return world.getBlock(x, y, z).getMaterial().isLiquid();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBuildable() {
|
||||
return this.getUnsafeBlock().isBuildable();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBurnable() {
|
||||
return this.getType().isBurnable();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isReplaceable() {
|
||||
return this.getUnsafeBlock().isReplaceable();
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getTemperature() {
|
||||
return this.getWorld().getTemperature(this.getX(), this.getZ());
|
||||
@ -324,7 +339,7 @@ public class AsyncBlock implements Block {
|
||||
return this.getWorld().getHumidity(this.getX(), this.getZ());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Nonnull
|
||||
@Override
|
||||
public PistonMoveReaction getPistonMoveReaction() {
|
||||
return PistonMoveReaction.IGNORE;
|
||||
@ -341,23 +356,23 @@ public class AsyncBlock implements Block {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean breakNaturally(@NotNull ItemStack tool) {
|
||||
public boolean breakNaturally(@Nonnull ItemStack tool) {
|
||||
return TaskManager.IMP.sync(() -> getUnsafeBlock().breakNaturally(tool));
|
||||
}
|
||||
|
||||
public boolean breakNaturally(@NotNull ItemStack tool, boolean value) {
|
||||
public boolean breakNaturally(@Nonnull ItemStack tool, boolean value) {
|
||||
return TaskManager.IMP.sync(() -> getUnsafeBlock().breakNaturally(tool));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Nonnull
|
||||
@Override
|
||||
public Collection<ItemStack> getDrops() {
|
||||
return TaskManager.IMP.sync(() -> getUnsafeBlock().getDrops());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Nonnull
|
||||
@Override
|
||||
public Collection<ItemStack> getDrops(@NotNull ItemStack tool) {
|
||||
public Collection<ItemStack> getDrops(@Nonnull ItemStack tool) {
|
||||
return TaskManager.IMP.sync(() -> getUnsafeBlock().getDrops(tool));
|
||||
}
|
||||
|
||||
@ -366,23 +381,23 @@ public class AsyncBlock implements Block {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMetadata(@NotNull String metadataKey, @NotNull MetadataValue newMetadataValue) {
|
||||
public void setMetadata(@Nonnull String metadataKey, @Nonnull MetadataValue newMetadataValue) {
|
||||
this.getUnsafeBlock().setMetadata(metadataKey, newMetadataValue);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Nonnull
|
||||
@Override
|
||||
public List<MetadataValue> getMetadata(@NotNull String metadataKey) {
|
||||
public List<MetadataValue> getMetadata(@Nonnull String metadataKey) {
|
||||
return this.getUnsafeBlock().getMetadata(metadataKey);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasMetadata(@NotNull String metadataKey) {
|
||||
public boolean hasMetadata(@Nonnull String metadataKey) {
|
||||
return this.getUnsafeBlock().hasMetadata(metadataKey);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeMetadata(@NotNull String metadataKey, @NotNull Plugin owningPlugin) {
|
||||
public void removeMetadata(@Nonnull String metadataKey, @Nonnull Plugin owningPlugin) {
|
||||
this.getUnsafeBlock().removeMetadata(metadataKey, owningPlugin);
|
||||
}
|
||||
|
||||
@ -392,12 +407,12 @@ public class AsyncBlock implements Block {
|
||||
}
|
||||
|
||||
@Override
|
||||
public RayTraceResult rayTrace(@NotNull Location arg0, @NotNull Vector arg1, double arg2,
|
||||
@NotNull FluidCollisionMode arg3) {
|
||||
public RayTraceResult rayTrace(@Nonnull Location arg0, @Nonnull Vector arg1, double arg2,
|
||||
@Nonnull FluidCollisionMode arg3) {
|
||||
return this.getUnsafeBlock().rayTrace(arg0, arg1, arg2, arg3);
|
||||
}
|
||||
|
||||
public boolean applyBoneMeal(@NotNull BlockFace face) {
|
||||
public boolean applyBoneMeal(@Nonnull BlockFace face) {
|
||||
throw new UnsupportedOperationException("FAWE does not support this yet");
|
||||
}
|
||||
|
||||
@ -405,22 +420,28 @@ public class AsyncBlock implements Block {
|
||||
throw new UnsupportedOperationException("FAWE does not support this yet");
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Nonnull
|
||||
@Override
|
||||
public float getDestroySpeed(@NotNull ItemStack itemStack) {
|
||||
public float getDestroySpeed(@Nonnull ItemStack itemStack) {
|
||||
throw new UnsupportedOperationException("FAWE does not support this yet");
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Nonnull
|
||||
@Override
|
||||
public BoundingBox getBoundingBox() {
|
||||
return this.getUnsafeBlock().getBoundingBox();
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
@Nonnull
|
||||
public BlockSoundGroup getSoundGroup() {
|
||||
return TaskManager.IMP.sync(() -> getUnsafeBlock().getSoundGroup());
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nonnull
|
||||
public boolean isSolid() {
|
||||
return this.getType().isSolid();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -6,6 +6,7 @@ import com.boydti.fawe.util.TaskManager;
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.ChunkSnapshot;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.BlockState;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.entity.Entity;
|
||||
@ -14,6 +15,8 @@ import org.bukkit.plugin.Plugin;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class AsyncChunk implements Chunk {
|
||||
@ -120,6 +123,16 @@ public class AsyncChunk implements Chunk {
|
||||
return TaskManager.IMP.sync(() -> world.getChunkAt(x, z).getTileEntities(useSnapshot));
|
||||
}
|
||||
|
||||
@NotNull @Override
|
||||
public Collection<BlockState> getTileEntities(@NotNull Predicate<Block> blockPredicate,
|
||||
boolean useSnapshot) {
|
||||
if (!isLoaded()) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
return TaskManager.IMP.sync(() -> world.getChunkAt(x, z)
|
||||
.getTileEntities(blockPredicate, useSnapshot));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLoaded() {
|
||||
return world.isChunkLoaded(x, z);
|
||||
|
@ -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() {
|
||||
|
@ -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();
|
||||
map.put("Color", new StringTag(color.name().toLowerCase(Locale.ROOT)));
|
||||
final Map<String, Tag> map = this.cloneNbtMap();
|
||||
if (map.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
map.put("Color", new StringTag(color.name().toLowerCase(Locale.ROOT)));
|
||||
this.setNbtData(map);
|
||||
}
|
||||
}
|
||||
|
@ -19,7 +19,6 @@
|
||||
|
||||
package com.sk89q.worldedit.bukkit;
|
||||
|
||||
|
||||
import com.boydti.fawe.Fawe;
|
||||
import com.boydti.fawe.bukkit.FaweBukkit;
|
||||
import com.google.common.base.Joiner;
|
||||
@ -93,19 +92,6 @@ import static com.sk89q.worldedit.internal.anvil.ChunkDeleter.DELCHUNKS_FILE_NAM
|
||||
*/
|
||||
public class WorldEditPlugin extends JavaPlugin { //implements TabCompleter
|
||||
|
||||
// This must be before the Logger is initialized, which fails in 1.8
|
||||
private static final String FAILED_VERSION_CHECK =
|
||||
"\n**********************************************\n"
|
||||
+ "** This Minecraft version (%s) is not supported by this version of WorldEdit.\n"
|
||||
+ "** Please download an OLDER version of WorldEdit which does.\n"
|
||||
+ "**********************************************\n";
|
||||
|
||||
static {
|
||||
if (PaperLib.getMinecraftVersion() < 13) {
|
||||
throw new IllegalStateException(String.format(FAILED_VERSION_CHECK, Bukkit.getVersion()));
|
||||
}
|
||||
}
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(WorldEditPlugin.class);
|
||||
public static final String CUI_PLUGIN_CHANNEL = "worldedit:cui";
|
||||
private static WorldEditPlugin INSTANCE;
|
||||
|
@ -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,20 +92,21 @@ 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> {
|
||||
private final Spigot_v1_15_R2 parent;
|
||||
private char[] ibdToStateOrdinal;
|
||||
private int[] ordinalToIbdID;
|
||||
// ------------------------------------------------------------------------
|
||||
// Code that may break between versions of Minecraft
|
||||
// ------------------------------------------------------------------------
|
||||
@ -124,12 +124,15 @@ public final class FAWE_Spigot_v1_15_R2 extends CachedBukkitAdapter implements I
|
||||
if (ibdToStateOrdinal != null && ibdToStateOrdinal[1] != 0) {
|
||||
return false;
|
||||
}
|
||||
ibdToStateOrdinal = new char[Block.REGISTRY_ID.a()]; // size
|
||||
ibdToStateOrdinal = new char[BlockTypesCache.states.length]; // size
|
||||
ordinalToIbdID = new int[ibdToStateOrdinal.length]; // size
|
||||
for (int i = 0; i < ibdToStateOrdinal.length; i++) {
|
||||
BlockState state = BlockTypesCache.states[i];
|
||||
BlockMaterial_1_15_2 material = (BlockMaterial_1_15_2) state.getMaterial();
|
||||
int id = Block.REGISTRY_ID.getId(material.getState());
|
||||
ibdToStateOrdinal[id] = state.getOrdinalChar();
|
||||
char ordinal = state.getOrdinalChar();
|
||||
ibdToStateOrdinal[id] = ordinal;
|
||||
ordinalToIbdID[ordinal] = id;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -267,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 {
|
||||
@ -347,6 +350,16 @@ public final class FAWE_Spigot_v1_15_R2 extends CachedBukkitAdapter implements I
|
||||
}
|
||||
}
|
||||
}
|
||||
public int ordinalToIbdID(char ordinal) {
|
||||
synchronized (this) {
|
||||
try {
|
||||
return ordinalToIbdID[ordinal];
|
||||
} catch (NullPointerException e) {
|
||||
init();
|
||||
return ordinalToIbdID(ordinal);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public <B extends BlockStateHolder<B>> BlockData adapt(B state) {
|
||||
|
@ -92,20 +92,21 @@ 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> {
|
||||
private final Spigot_v1_16_R1 parent;
|
||||
private char[] ibdToStateOrdinal;
|
||||
private int[] ordinalToIbdID;
|
||||
// ------------------------------------------------------------------------
|
||||
// Code that may break between versions of Minecraft
|
||||
// ------------------------------------------------------------------------
|
||||
@ -123,12 +124,15 @@ public final class FAWE_Spigot_v1_16_R1 extends CachedBukkitAdapter implements I
|
||||
if (ibdToStateOrdinal != null && ibdToStateOrdinal[1] != 0) {
|
||||
return false;
|
||||
}
|
||||
ibdToStateOrdinal = new char[Block.REGISTRY_ID.a()]; // size
|
||||
ibdToStateOrdinal = new char[BlockTypesCache.states.length]; // size
|
||||
ordinalToIbdID = new int[ibdToStateOrdinal.length]; // size
|
||||
for (int i = 0; i < ibdToStateOrdinal.length; i++) {
|
||||
BlockState state = BlockTypesCache.states[i];
|
||||
BlockMaterial_1_16_1 material = (BlockMaterial_1_16_1) state.getMaterial();
|
||||
int id = Block.REGISTRY_ID.getId(material.getState());
|
||||
ibdToStateOrdinal[id] = state.getOrdinalChar();
|
||||
char ordinal = state.getOrdinalChar();
|
||||
ibdToStateOrdinal[id] = ordinal;
|
||||
ordinalToIbdID[ordinal] = id;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -266,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 {
|
||||
@ -347,6 +351,17 @@ public final class FAWE_Spigot_v1_16_R1 extends CachedBukkitAdapter implements I
|
||||
}
|
||||
}
|
||||
|
||||
public int ordinalToIbdID(char ordinal) {
|
||||
synchronized (this) {
|
||||
try {
|
||||
return ordinalToIbdID[ordinal];
|
||||
} catch (NullPointerException e) {
|
||||
init();
|
||||
return ordinalToIbdID(ordinal);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public <B extends BlockStateHolder<B>> BlockData adapt(B state) {
|
||||
BlockMaterial_1_16_1 material = (BlockMaterial_1_16_1) state.getMaterial();
|
||||
|
@ -92,20 +92,22 @@ 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> {
|
||||
private final Spigot_v1_16_R2 parent;
|
||||
private char[] ibdToStateOrdinal;
|
||||
private int[] ordinalToIbdID;
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// Code that may break between versions of Minecraft
|
||||
@ -124,12 +126,15 @@ public final class FAWE_Spigot_v1_16_R2 extends CachedBukkitAdapter implements I
|
||||
if (ibdToStateOrdinal != null && ibdToStateOrdinal[1] != 0) {
|
||||
return false;
|
||||
}
|
||||
ibdToStateOrdinal = new char[Block.REGISTRY_ID.a()]; // size
|
||||
ibdToStateOrdinal = new char[BlockTypesCache.states.length]; // size
|
||||
ordinalToIbdID = new int[ibdToStateOrdinal.length]; // size
|
||||
for (int i = 0; i < ibdToStateOrdinal.length; i++) {
|
||||
BlockState state = BlockTypesCache.states[i];
|
||||
BlockMaterial_1_16_2 material = (BlockMaterial_1_16_2) state.getMaterial();
|
||||
int id = Block.REGISTRY_ID.getId(material.getState());
|
||||
ibdToStateOrdinal[id] = state.getOrdinalChar();
|
||||
char ordinal = state.getOrdinalChar();
|
||||
ibdToStateOrdinal[id] = ordinal;
|
||||
ordinalToIbdID[ordinal] = id;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -267,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 {
|
||||
@ -347,6 +352,16 @@ public final class FAWE_Spigot_v1_16_R2 extends CachedBukkitAdapter implements I
|
||||
}
|
||||
}
|
||||
}
|
||||
public int ordinalToIbdID(char ordinal) {
|
||||
synchronized (this) {
|
||||
try {
|
||||
return ordinalToIbdID[ordinal];
|
||||
} catch (NullPointerException e) {
|
||||
init();
|
||||
return ordinalToIbdID(ordinal);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public <B extends BlockStateHolder<B>> BlockData adapt(B state) {
|
||||
|
@ -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;
|
||||
@ -107,6 +107,7 @@ import static org.slf4j.LoggerFactory.getLogger;
|
||||
public final class FAWE_Spigot_v1_16_R3 extends CachedBukkitAdapter implements IDelegateBukkitImplAdapter<NBTBase> {
|
||||
private final Spigot_v1_16_R3 parent;
|
||||
private char[] ibdToStateOrdinal;
|
||||
private int[] ordinalToIbdID;
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// Code that may break between versions of Minecraft
|
||||
@ -125,12 +126,15 @@ public final class FAWE_Spigot_v1_16_R3 extends CachedBukkitAdapter implements I
|
||||
if (ibdToStateOrdinal != null && ibdToStateOrdinal[1] != 0) {
|
||||
return false;
|
||||
}
|
||||
ibdToStateOrdinal = new char[Block.REGISTRY_ID.a()]; // size
|
||||
ibdToStateOrdinal = new char[BlockTypesCache.states.length]; // size
|
||||
ordinalToIbdID = new int[ibdToStateOrdinal.length]; // size
|
||||
for (int i = 0; i < ibdToStateOrdinal.length; i++) {
|
||||
BlockState state = BlockTypesCache.states[i];
|
||||
BlockMaterial_1_16_4 material = (BlockMaterial_1_16_4) state.getMaterial();
|
||||
int id = Block.REGISTRY_ID.getId(material.getState());
|
||||
ibdToStateOrdinal[id] = state.getOrdinalChar();
|
||||
char ordinal = state.getOrdinalChar();
|
||||
ibdToStateOrdinal[id] = ordinal;
|
||||
ordinalToIbdID[ordinal] = id;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -268,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 {
|
||||
@ -349,6 +353,17 @@ public final class FAWE_Spigot_v1_16_R3 extends CachedBukkitAdapter implements I
|
||||
}
|
||||
}
|
||||
|
||||
public int ordinalToIbdID(char ordinal) {
|
||||
synchronized (this) {
|
||||
try {
|
||||
return ordinalToIbdID[ordinal];
|
||||
} catch (NullPointerException e) {
|
||||
init();
|
||||
return ordinalToIbdID(ordinal);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public <B extends BlockStateHolder<B>> BlockData adapt(B state) {
|
||||
BlockMaterial_1_16_4 material = (BlockMaterial_1_16_4) state.getMaterial();
|
||||
|
@ -28,14 +28,14 @@ configurations.all {
|
||||
|
||||
dependencies {
|
||||
"api"(project(":worldedit-libs:core"))
|
||||
"implementation"("de.schlichtherle:truezip:6.8.3")
|
||||
"implementation"("net.java.truevfs:truevfs-profile-default_2.13:0.12.1")
|
||||
"implementation"("de.schlichtherle:truezip:6.8.4")
|
||||
"implementation"("net.java.truevfs:truevfs-profile-default_2.13:0.12.2")
|
||||
"implementation"("org.mozilla:rhino-runtime:1.7.12")
|
||||
"implementation"("org.yaml:snakeyaml:1.23")
|
||||
"implementation"("org.yaml:snakeyaml:1.27")
|
||||
"implementation"("com.google.guava:guava:${Versions.GUAVA}")
|
||||
"implementation"("com.google.code.findbugs:jsr305:3.0.2")
|
||||
"implementation"("com.google.code.gson:gson:${Versions.GSON}")
|
||||
"implementation"("org.slf4j:slf4j-api:1.7.27")
|
||||
"implementation"("org.slf4j:slf4j-api:1.7.30")
|
||||
"implementation"("it.unimi.dsi:fastutil:${Versions.FAST_UTIL}")
|
||||
|
||||
val antlrVersion = "4.7.2"
|
||||
@ -51,14 +51,15 @@ dependencies {
|
||||
"annotationProcessor"("com.google.auto.value:auto-value:${Versions.AUTO_VALUE}")
|
||||
"testImplementation"("ch.qos.logback:logback-core:${Versions.LOGBACK}")
|
||||
"testImplementation"("ch.qos.logback:logback-classic:${Versions.LOGBACK}")
|
||||
"compile"("com.github.luben:zstd-jni:1.4.3-1")
|
||||
"compile"("com.github.luben:zstd-jni:1.4.8-1")
|
||||
"compileOnly"("net.fabiozumbi12:redprotect:1.9.6")
|
||||
"compile"("com.github.intellectualsites.plotsquared:PlotSquared-API:latest") {
|
||||
isTransitive = false
|
||||
}
|
||||
"compile"("com.plotsquared:PlotSquared-Core:5.12.2") {
|
||||
"compile"("com.plotsquared:PlotSquared-Core:5.13.3") {
|
||||
isTransitive = false
|
||||
}
|
||||
"api"("com.intellectualsites.paster:Paster:1.0.1-SNAPSHOT")
|
||||
}
|
||||
|
||||
tasks.named<Test>("test") {
|
||||
@ -109,7 +110,7 @@ tasks.named<Copy>("processResources") {
|
||||
}
|
||||
tasks.named<ShadowJar>("shadowJar") {
|
||||
dependencies {
|
||||
include(dependency("com.github.luben:zstd-jni:1.4.3-1"))
|
||||
include(dependency("com.github.luben:zstd-jni:1.4.8-1"))
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -235,7 +235,7 @@ public class Fawe {
|
||||
// Setting up config.yml
|
||||
File file = new File(this.implementation.getDirectory(), "config.yml");
|
||||
Settings.IMP.PLATFORM = implementation.getPlatform().replace("\"", "");
|
||||
try (InputStream stream = getClass().getResourceAsStream(File.separator + "fawe.properties");
|
||||
try (InputStream stream = getClass().getResourceAsStream("/fawe.properties");
|
||||
BufferedReader br = new BufferedReader(new InputStreamReader(stream))) {
|
||||
String versionString = br.readLine();
|
||||
String commitString = br.readLine();
|
||||
|
@ -9,19 +9,28 @@ import org.jetbrains.annotations.Range;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
public abstract class CharBlocks implements IBlocks {
|
||||
|
||||
public static final Logger logger = LoggerFactory.getLogger(CharBlocks.class);
|
||||
|
||||
public static final Section FULL = new Section() {
|
||||
protected static final Section FULL = new Section() {
|
||||
@Override
|
||||
public final char[] get(CharBlocks blocks, int layer) {
|
||||
return blocks.blocks[layer];
|
||||
}
|
||||
};
|
||||
public static final Section EMPTY = new Section() {
|
||||
|
||||
@Override
|
||||
public final synchronized char[] get(CharBlocks blocks, int layer) {
|
||||
public final boolean isFull() {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
protected static final Section EMPTY = new Section() {
|
||||
@Override
|
||||
public final char[] get(CharBlocks blocks, int layer) {
|
||||
blocks.loadLock.lock();
|
||||
try {
|
||||
char[] arr = blocks.blocks[layer];
|
||||
if (arr == null) {
|
||||
arr = blocks.blocks[layer] = blocks.update(layer, null);
|
||||
@ -38,10 +47,19 @@ public abstract class CharBlocks implements IBlocks {
|
||||
blocks.sections[layer] = FULL;
|
||||
}
|
||||
return arr;
|
||||
} finally {
|
||||
blocks.loadLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean isFull() {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
public final char[][] blocks;
|
||||
public final Section[] sections;
|
||||
private final ReentrantLock loadLock = new ReentrantLock ();
|
||||
|
||||
public CharBlocks() {
|
||||
blocks = new char[16][];
|
||||
@ -55,7 +73,7 @@ public abstract class CharBlocks implements IBlocks {
|
||||
public boolean trim(boolean aggressive) {
|
||||
boolean result = true;
|
||||
for (int i = 0; i < 16; i++) {
|
||||
if (sections[i] == EMPTY && blocks[i] != null) {
|
||||
if (!sections[i].isFull() && blocks[i] != null) {
|
||||
blocks[i] = null;
|
||||
} else {
|
||||
result = false;
|
||||
@ -67,7 +85,7 @@ public abstract class CharBlocks implements IBlocks {
|
||||
@Override
|
||||
public boolean trim(boolean aggressive, int layer) {
|
||||
boolean result = true;
|
||||
if (sections[layer] == EMPTY && blocks[layer] != null) {
|
||||
if (!sections[layer].isFull() && blocks[layer] != null) {
|
||||
blocks[layer] = null;
|
||||
} else {
|
||||
result = false;
|
||||
@ -99,7 +117,7 @@ public abstract class CharBlocks implements IBlocks {
|
||||
|
||||
@Override
|
||||
public boolean hasSection(@Range(from = 0, to = 15) int layer) {
|
||||
return sections[layer] == FULL;
|
||||
return sections[layer].isFull();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -149,6 +167,8 @@ public abstract class CharBlocks implements IBlocks {
|
||||
|
||||
public abstract char[] get(CharBlocks blocks, @Range(from = 0, to = 15) int layer);
|
||||
|
||||
public abstract boolean isFull();
|
||||
|
||||
public final char get(CharBlocks blocks, @Range(from = 0, to = 15) int layer, int index) {
|
||||
return get(blocks, layer)[index];
|
||||
}
|
||||
|
@ -140,7 +140,7 @@ public class ParallelQueueExtent extends PassthroughExtent implements IQueueWrap
|
||||
return
|
||||
// Apply a filter over a region
|
||||
apply(region, searchMask
|
||||
.toFilter(new CountFilter()), false) // Adapt the mask to a filter which counts
|
||||
.toFilter(new CountFilter()), searchMask.replacesAir()) // Adapt the mask to a filter which counts
|
||||
.getParent() // Get the counter of this mask
|
||||
.getTotal(); // Get the total from the counter
|
||||
}
|
||||
|
@ -200,7 +200,7 @@ public class StreamDelegate {
|
||||
Object raw = is.readTagPayloadRaw(type, depth);
|
||||
valueReader.apply(0, raw);
|
||||
} else {
|
||||
is.readTagPaylodLazy(type, depth + 1, this);
|
||||
is.readTagPayloadLazy(type, depth + 1, this);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -137,10 +137,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();
|
||||
@ -176,11 +174,12 @@ public abstract class AbstractChangeSet implements ChangeSet, IBatchProcessor {
|
||||
int zz = z + bz;
|
||||
for (int x = 0; x < 16; x++, index++) {
|
||||
int xx = bx + x;
|
||||
int combinedFrom = blocksGet[index];
|
||||
if (combinedFrom == 0) {
|
||||
combinedFrom = BlockID.AIR;
|
||||
int from = blocksGet[index];
|
||||
if (from == 0) {
|
||||
from = BlockID.AIR;
|
||||
}
|
||||
int combinedTo = blocksSet[index];
|
||||
final int combinedFrom = from;
|
||||
final int combinedTo = blocksSet[index];
|
||||
if (combinedTo != 0) {
|
||||
add(xx, yy, zz, combinedFrom, combinedTo);
|
||||
}
|
||||
@ -249,14 +248,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
|
||||
@ -299,14 +296,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();
|
||||
@ -322,8 +317,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);
|
||||
@ -357,7 +351,7 @@ public abstract class AbstractChangeSet implements ChangeSet, IBatchProcessor {
|
||||
wrappedTask.run();
|
||||
return Futures.immediateCancelledFuture();
|
||||
} else {
|
||||
return Fawe.get().getQueueHandler().async(wrappedTask);
|
||||
return Fawe.get().getQueueHandler().submit(wrappedTask);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -152,10 +152,8 @@ public class CPUOptimizedClipboard extends LinearClipboard {
|
||||
@Override
|
||||
public Collection<CompoundTag> getTileEntities() {
|
||||
convertTilesToIndex();
|
||||
for (Map.Entry<Integer, CompoundTag> entry : nbtMapIndex.entrySet()) {
|
||||
int index = entry.getKey();
|
||||
CompoundTag tag = entry.getValue();
|
||||
Map<String, Tag> values = tag.getValue();
|
||||
nbtMapIndex.replaceAll((index, tag) -> {
|
||||
Map<String, Tag> values = new HashMap<>(tag.getValue());
|
||||
if (!values.containsKey("x")) {
|
||||
int y = index / getArea();
|
||||
index -= y * getArea();
|
||||
@ -164,23 +162,26 @@ public class CPUOptimizedClipboard extends LinearClipboard {
|
||||
values.put("x", new IntTag(x));
|
||||
values.put("y", new IntTag(y));
|
||||
values.put("z", new IntTag(z));
|
||||
return new CompoundTag(values);
|
||||
} else {
|
||||
return tag;
|
||||
}
|
||||
}
|
||||
});
|
||||
return nbtMapIndex.values();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setTile(int x, int y, int z, CompoundTag tag) {
|
||||
nbtMapLoc.put(new IntTriple(x, y, z), tag);
|
||||
nbtMapLoc.put(new IntTriple(x, y, z), new CompoundTag(tag.getValue()));
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean setTile(int index, CompoundTag tag) {
|
||||
nbtMapIndex.put(index, tag);
|
||||
Map<String, Tag> values = tag.getValue();
|
||||
final Map<String, Tag> values = new HashMap<>(tag.getValue());
|
||||
values.remove("x");
|
||||
values.remove("y");
|
||||
values.remove("z");
|
||||
nbtMapIndex.put(index, new CompoundTag(values));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -21,10 +21,6 @@ import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Best used when clipboard selections are small, or using legacy formats
|
||||
* (Small being < Integer.MAX_VALUE/BLOCK_SIZE_BYTES blocks)
|
||||
*/
|
||||
public abstract class LinearClipboard extends SimpleClipboard {
|
||||
|
||||
protected final HashSet<ClipboardEntity> entities = new HashSet<>();
|
||||
|
@ -257,11 +257,11 @@ public class MemoryOptimizedClipboard extends LinearClipboard {
|
||||
|
||||
@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;
|
||||
}
|
||||
|
||||
|
@ -14,7 +14,7 @@ public abstract class SimpleClipboard implements Clipboard {
|
||||
SimpleClipboard(BlockVector3 dimensions) {
|
||||
this.size = dimensions;
|
||||
long longVolume = (long) getWidth() * (long) getHeight() * (long) getLength();
|
||||
if (longVolume >= Integer.MAX_VALUE >> 2) {
|
||||
if (longVolume >= Integer.MAX_VALUE) {
|
||||
throw new IllegalArgumentException("Dimensions are too large for this clipboard format.");
|
||||
}
|
||||
this.area = getWidth() * getLength();
|
||||
|
@ -16,4 +16,9 @@ public class AirMask extends BlockMask {
|
||||
return new AirMask(getExtent());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean replacesAir() {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -37,4 +37,9 @@ public class IdDataMask extends AbstractExtentMask implements ResettableMask {
|
||||
return new IdDataMask(getExtent());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean replacesAir() {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -38,4 +38,9 @@ public class IdMask extends AbstractExtentMask implements ResettableMask {
|
||||
return new IdMask(getExtent());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean replacesAir() {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,298 +0,0 @@
|
||||
package com.boydti.fawe.util;
|
||||
|
||||
import com.boydti.fawe.Fawe;
|
||||
import com.google.common.base.Charsets;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
import com.sk89q.worldedit.util.paste.Paster;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStream;
|
||||
import java.lang.management.ManagementFactory;
|
||||
import java.lang.management.RuntimeMXBean;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
import java.nio.file.Files;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* Single class paster for the Incendo paste service
|
||||
*
|
||||
* @author Sauilitired
|
||||
*/
|
||||
@SuppressWarnings({"unused", "WeakerAccess"})
|
||||
public final class IncendoPaster implements Paster {
|
||||
|
||||
/**
|
||||
* Upload service URL
|
||||
*/
|
||||
public static final String UPLOAD_PATH = "https://athion.net/ISPaster/paste/upload";
|
||||
/**
|
||||
* Valid paste applications
|
||||
*/
|
||||
public static final Collection<String>
|
||||
VALID_APPLICATIONS = Arrays
|
||||
.asList("plotsquared", "fastasyncworldedit", "incendopermissions", "kvantum");
|
||||
|
||||
private final Collection<PasteFile> files = new ArrayList<>();
|
||||
private final String pasteApplication;
|
||||
|
||||
/**
|
||||
* Construct a new paster
|
||||
*
|
||||
* @param pasteApplication The application that is sending the paste
|
||||
*/
|
||||
public IncendoPaster(final String pasteApplication) {
|
||||
if (pasteApplication == null || pasteApplication.isEmpty()) {
|
||||
throw new IllegalArgumentException("paste application cannot be null, nor empty");
|
||||
}
|
||||
if (!VALID_APPLICATIONS.contains(pasteApplication.toLowerCase(Locale.ROOT))) {
|
||||
throw new IllegalArgumentException(
|
||||
String.format("Unknown application name: %s", pasteApplication));
|
||||
}
|
||||
this.pasteApplication = pasteApplication;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Callable<URL> paste(String content) {
|
||||
return new PasteTask(content);
|
||||
}
|
||||
|
||||
private final class PasteTask implements Callable<URL> {
|
||||
|
||||
private PasteTask(String content) {}
|
||||
|
||||
@Override
|
||||
public URL call() throws Exception {
|
||||
return new URL(debugPaste());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an immutable collection containing all the files that have been added to this paster
|
||||
*
|
||||
* @return Unmodifiable collection
|
||||
*/
|
||||
public final Collection<PasteFile> getFiles() {
|
||||
return Collections.unmodifiableCollection(this.files);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a file to the paster
|
||||
*
|
||||
* @param file File to paste
|
||||
*/
|
||||
public void addFile(final PasteFile file) {
|
||||
if (file == null) {
|
||||
throw new IllegalArgumentException("File cannot be null");
|
||||
}
|
||||
// Check to see that no duplicate files are submitted
|
||||
for (final PasteFile pasteFile : this.files) {
|
||||
if (pasteFile.fileName.equalsIgnoreCase(file.getFileName())) {
|
||||
throw new IllegalArgumentException(String.format("Found duplicate file with name %s",
|
||||
file.getFileName()));
|
||||
}
|
||||
}
|
||||
this.files.add(file);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a JSON string from the submitted information
|
||||
*
|
||||
* @return compiled JSON string
|
||||
*/
|
||||
private String toJsonString() {
|
||||
final StringBuilder builder = new StringBuilder("{\n");
|
||||
builder.append("\"paste_application\": \"").append(this.pasteApplication).append("\",\n\"files\": \"");
|
||||
Iterator<PasteFile> fileIterator = this.files.iterator();
|
||||
while (fileIterator.hasNext()) {
|
||||
final PasteFile file = fileIterator.next();
|
||||
builder.append(file.getFileName());
|
||||
if (fileIterator.hasNext()) {
|
||||
builder.append(",");
|
||||
}
|
||||
}
|
||||
builder.append("\",\n");
|
||||
fileIterator = this.files.iterator();
|
||||
while (fileIterator.hasNext()) {
|
||||
final PasteFile file = fileIterator.next();
|
||||
builder.append("\"file-").append(file.getFileName()).append("\": \"")
|
||||
.append(file.getContent().replaceAll("\"", "\\\\\"")).append("\"");
|
||||
if (fileIterator.hasNext()) {
|
||||
builder.append(",\n");
|
||||
}
|
||||
}
|
||||
builder.append("\n}");
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Upload the paste and return the status message
|
||||
*
|
||||
* @return Status message
|
||||
* @throws Throwable any and all exceptions
|
||||
*/
|
||||
public final String upload() throws Throwable {
|
||||
final URL url = new URL(UPLOAD_PATH);
|
||||
final URLConnection connection = url.openConnection();
|
||||
final HttpURLConnection httpURLConnection = (HttpURLConnection) connection;
|
||||
httpURLConnection.setRequestMethod("POST");
|
||||
httpURLConnection.setDoOutput(true);
|
||||
final byte[] content = toJsonString().getBytes(Charsets.UTF_8);
|
||||
httpURLConnection.setFixedLengthStreamingMode(content.length);
|
||||
httpURLConnection.setRequestProperty("Content-Type", "application/json");
|
||||
httpURLConnection.setRequestProperty("Accept", "*/*");
|
||||
httpURLConnection.connect();
|
||||
try (final OutputStream stream = httpURLConnection.getOutputStream()) {
|
||||
stream.write(content);
|
||||
}
|
||||
if (!httpURLConnection.getResponseMessage().contains("OK")) {
|
||||
throw new IllegalStateException(String.format("Server returned status: %d %s",
|
||||
httpURLConnection.getResponseCode(), httpURLConnection.getResponseMessage()));
|
||||
}
|
||||
final StringBuilder input = new StringBuilder();
|
||||
try (final BufferedReader inputStream = new BufferedReader(new InputStreamReader(httpURLConnection.getInputStream()))) {
|
||||
String line;
|
||||
while ((line = inputStream.readLine()) != null) {
|
||||
input.append(line).append("\n");
|
||||
}
|
||||
}
|
||||
return input.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Simple class that represents a paste file
|
||||
*/
|
||||
public static class PasteFile {
|
||||
|
||||
private final String fileName;
|
||||
private final String content;
|
||||
|
||||
/**
|
||||
* Construct a new paste file
|
||||
*
|
||||
* @param fileName File name, cannot be empty, nor null
|
||||
* @param content File content, cannot be empty, nor null
|
||||
*/
|
||||
public PasteFile(final String fileName, final String content) {
|
||||
if (fileName == null || fileName.isEmpty()) {
|
||||
throw new IllegalArgumentException("file name cannot be null, nor empty");
|
||||
}
|
||||
if (content == null || content.isEmpty()) {
|
||||
throw new IllegalArgumentException("content cannot be null, nor empty");
|
||||
}
|
||||
this.fileName = fileName;
|
||||
this.content = content;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the file name
|
||||
*
|
||||
* @return File name
|
||||
*/
|
||||
public String getFileName() {
|
||||
return this.fileName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the file content as a single string
|
||||
*
|
||||
* @return File content
|
||||
*/
|
||||
public String getContent() {
|
||||
return this.content;
|
||||
}
|
||||
}
|
||||
|
||||
public static String debugPaste() throws IOException {
|
||||
final IncendoPaster incendoPaster = new IncendoPaster("fastasyncworldedit");
|
||||
|
||||
StringBuilder b = new StringBuilder();
|
||||
b.append(
|
||||
"# Welcome to this paste\n# It is meant to provide us at IntellectualSites with better information about your "
|
||||
+ "problem\n");
|
||||
b.append("\n# Server Information\n");
|
||||
b.append(Fawe.imp().getDebugInfo());
|
||||
b.append("\n# YAY! Now, let's see what we can find in your JVM\n");
|
||||
Runtime runtime = Runtime.getRuntime();
|
||||
RuntimeMXBean rb = ManagementFactory.getRuntimeMXBean();
|
||||
b.append("Uptime: ").append(TimeUnit.MINUTES.convert(rb.getUptime(), TimeUnit.MILLISECONDS))
|
||||
.append(" minutes").append('\n');
|
||||
b.append("JVM Flags: ").append(rb.getInputArguments()).append('\n');
|
||||
b.append("Free Memory: ").append(runtime.freeMemory() / 1024 / 1024).append(" MB").append('\n');
|
||||
b.append("Max Memory: ").append(runtime.maxMemory() / 1024 / 1024).append(" MB").append('\n');
|
||||
b.append("Total Memory: ").append(runtime.totalMemory() / 1024 / 1024).append(" MB").append('\n');
|
||||
b.append("Available Processors: ").append(runtime.availableProcessors()).append('\n');
|
||||
b.append("Java Name: ").append(rb.getVmName()).append('\n');
|
||||
b.append("Java Version: '").append(System.getProperty("java.version")).append("'\n");
|
||||
b.append("Java Vendor: '").append(System.getProperty("java.vendor")).append("'\n");
|
||||
b.append("Operating System: '").append(System.getProperty("os.name")).append("'\n");
|
||||
b.append("OS Version: ").append(System.getProperty("os.version")).append('\n');
|
||||
b.append("OS Arch: ").append(System.getProperty("os.arch")).append('\n');
|
||||
b.append("# Okay :D Great. You are now ready to create your bug report!");
|
||||
b.append("\n# You can do so at https://github.com/IntellectualSites/FastAsyncWorldEdit/issues");
|
||||
b.append("\n# or via our Discord at https://discord.gg/KxkjDVg");
|
||||
incendoPaster.addFile(new IncendoPaster.PasteFile("information", b.toString()));
|
||||
|
||||
try {
|
||||
final File logFile = new File(Fawe.imp().getDirectory(), "../../logs/latest.log");
|
||||
final String file;
|
||||
if (Files.size(logFile.toPath()) > 14_000_000) {
|
||||
file = "too big :(";
|
||||
} else {
|
||||
file = readFile(logFile);
|
||||
}
|
||||
incendoPaster.addFile(new IncendoPaster.PasteFile("latest.log", file));
|
||||
} catch (IOException ignored) {
|
||||
}
|
||||
|
||||
incendoPaster.addFile(new PasteFile("config.yml", readFile(new File(Fawe.imp().getDirectory(), "config.yml"))));
|
||||
incendoPaster.addFile(new PasteFile("config-legacy.yml", readFile(new File(Fawe.imp().getDirectory(), "config-legacy.yml"))));
|
||||
|
||||
final String rawResponse;
|
||||
try {
|
||||
rawResponse = incendoPaster.upload();
|
||||
} catch (Throwable throwable) {
|
||||
throw new IOException(String.format("Failed to upload files: %s", throwable.getMessage()), throwable);
|
||||
}
|
||||
final JsonObject jsonObject = new JsonParser().parse(rawResponse).getAsJsonObject();
|
||||
|
||||
if (jsonObject.has("created")) {
|
||||
final String pasteId = jsonObject.get("paste_id").getAsString();
|
||||
return String.format("https://athion.net/ISPaster/paste/view/%s", pasteId);
|
||||
} else {
|
||||
throw new IOException(String.format("Failed to upload files: %s",
|
||||
jsonObject.get("response").getAsString()));
|
||||
}
|
||||
}
|
||||
|
||||
private static String readFile(final File file) throws IOException {
|
||||
final StringBuilder content = new StringBuilder();
|
||||
final List<String> lines = new ArrayList<>();
|
||||
try (final BufferedReader reader = new BufferedReader(new FileReader(file))) {
|
||||
String line;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
lines.add(line);
|
||||
}
|
||||
}
|
||||
for (int i = Math.max(0, lines.size() - 1000); i < lines.size(); i++) {
|
||||
content.append(lines.get(i)).append("\n");
|
||||
}
|
||||
return content.toString();
|
||||
}
|
||||
|
||||
}
|
@ -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 {
|
||||
|
@ -1,5 +1,6 @@
|
||||
package com.boydti.fawe.util;
|
||||
|
||||
import com.plotsquared.core.util.PseudoRandom;
|
||||
import com.sk89q.worldedit.world.block.BlockType;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
||||
|
||||
@ -34,6 +35,8 @@ public class RandomTextureUtil extends CachedTextureUtil {
|
||||
if (i < 0) {
|
||||
int i1 = -i;
|
||||
return -ThreadLocalRandom.current().nextInt(i1);
|
||||
} else if( i == 0) {
|
||||
return 0;
|
||||
} else {
|
||||
return ThreadLocalRandom.current().nextInt(i);
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -629,7 +629,6 @@ public class TextureUtil implements TextureHolder {
|
||||
mods.add(modId);
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
String modelsDir = "assets/%1$s/models/block/%2$s.json";
|
||||
String texturesDir = "assets/%1$s/textures/%2$s.png";
|
||||
@ -638,14 +637,14 @@ public class TextureUtil implements TextureHolder {
|
||||
}.getType();
|
||||
|
||||
for (BlockType blockType : BlockTypesCache.values) {
|
||||
if (!blockType.getMaterial().isFullCube()) {
|
||||
if (!blockType.getMaterial().isFullCube() || blockType.getId().toLowerCase().contains("shulker")) {
|
||||
continue;
|
||||
}
|
||||
int combined = blockType.getInternalId();
|
||||
String id = blockType.getId();
|
||||
String[] split = id.split(":", 2);
|
||||
String name = split.length == 1 ? id : split[1];
|
||||
String nameSpace = split.length == 1 ? "minecraft" : split[0];
|
||||
String nameSpace = split.length == 1 ? "" : split[0];
|
||||
|
||||
Map<String, String> texturesMap = new ConcurrentHashMap<>();
|
||||
// Read models
|
||||
@ -684,8 +683,11 @@ public class TextureUtil implements TextureHolder {
|
||||
continue;
|
||||
}
|
||||
|
||||
String[] texSplit = models.iterator().next().split(":");
|
||||
String texture = texSplit[texSplit.length - 1];
|
||||
|
||||
textureFileName =
|
||||
String.format(texturesDir, nameSpace, models.iterator().next());
|
||||
String.format(texturesDir, nameSpace, texture);
|
||||
}
|
||||
|
||||
BufferedImage image = readImage(zipFile, textureFileName);
|
||||
|
@ -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
|
||||
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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}
|
||||
@ -61,6 +63,14 @@ public final class NBTInputStream implements Closeable {
|
||||
this.is = dis;
|
||||
}
|
||||
|
||||
public void mark(int mark) {
|
||||
is.mark(mark);
|
||||
}
|
||||
|
||||
public void reset() throws IOException {
|
||||
is.reset();
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads an NBT tag from the stream.
|
||||
*
|
||||
@ -99,7 +109,7 @@ public final class NBTInputStream implements Closeable {
|
||||
if (child != null) {
|
||||
child.acceptRoot(this, type, 0);
|
||||
} else {
|
||||
readTagPaylodLazy(type, 0);
|
||||
readTagPayloadLazy(type, 0);
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
@ -119,7 +129,7 @@ public final class NBTInputStream implements Closeable {
|
||||
|
||||
private byte[] buf;
|
||||
|
||||
public void readTagPaylodLazy(int type, int depth) throws IOException {
|
||||
public void readTagPayloadLazy(int type, int depth) throws IOException {
|
||||
switch (type) {
|
||||
case NBTConstants.TYPE_END:
|
||||
return;
|
||||
@ -152,7 +162,7 @@ public final class NBTInputStream implements Closeable {
|
||||
int childType = is.readByte();
|
||||
length = is.readInt();
|
||||
for (int i = 0; i < length; ++i) {
|
||||
readTagPaylodLazy(childType, depth + 1);
|
||||
readTagPayloadLazy(childType, depth + 1);
|
||||
}
|
||||
return;
|
||||
}
|
||||
@ -165,7 +175,7 @@ public final class NBTInputStream implements Closeable {
|
||||
return;
|
||||
}
|
||||
is.skipBytes(is.readShort() & 0xFFFF);
|
||||
readTagPaylodLazy(childType, depth + 1);
|
||||
readTagPayloadLazy(childType, depth + 1);
|
||||
}
|
||||
}
|
||||
case NBTConstants.TYPE_INT_ARRAY: {
|
||||
@ -181,7 +191,7 @@ public final class NBTInputStream implements Closeable {
|
||||
}
|
||||
}
|
||||
|
||||
public void readTagPaylodLazy(int type, int depth, StreamDelegate scope) throws IOException {
|
||||
public void readTagPayloadLazy(int type, int depth, StreamDelegate scope) throws IOException {
|
||||
switch (type) {
|
||||
case NBTConstants.TYPE_END:
|
||||
return;
|
||||
@ -293,11 +303,11 @@ public final class NBTInputStream implements Closeable {
|
||||
child = scope.get0();
|
||||
if (child == null) {
|
||||
for (int i = 0; i < length; ++i) {
|
||||
readTagPaylodLazy(childType, depth + 1);
|
||||
readTagPayloadLazy(childType, depth + 1);
|
||||
}
|
||||
} else {
|
||||
for (int i = 0; i < length; ++i) {
|
||||
readTagPaylodLazy(childType, depth + 1, child);
|
||||
readTagPayloadLazy(childType, depth + 1, child);
|
||||
}
|
||||
}
|
||||
return;
|
||||
@ -330,9 +340,9 @@ public final class NBTInputStream implements Closeable {
|
||||
}
|
||||
StreamDelegate child = scope.get(is);
|
||||
if (child == null) {
|
||||
readTagPaylodLazy(childType, depth + 1);
|
||||
readTagPayloadLazy(childType, depth + 1);
|
||||
} else {
|
||||
readTagPaylodLazy(childType, depth + 1, child);
|
||||
readTagPayloadLazy(childType, depth + 1, child);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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}.
|
||||
|
@ -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";
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
@ -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
|
||||
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
@ -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();
|
||||
|
||||
}
|
@ -0,0 +1,4 @@
|
||||
/**
|
||||
* These are classes added by FAWE. They do not exist in WorldEdit
|
||||
*/
|
||||
package com.sk89q.jnbt.fawe;
|
@ -125,8 +125,6 @@ import com.sk89q.worldedit.util.formatting.text.TranslatableComponent;
|
||||
import com.sk89q.worldedit.world.World;
|
||||
import com.sk89q.worldedit.world.biome.BiomeType;
|
||||
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.BlockStateHolder;
|
||||
import com.sk89q.worldedit.world.block.BlockType;
|
||||
@ -148,6 +146,7 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
@ -2046,18 +2045,18 @@ public class EditSession extends PassthroughExtent implements AutoCloseable {
|
||||
|
||||
int yy;
|
||||
|
||||
double nextXn = invRadiusX;
|
||||
double nextXn = 0;
|
||||
forX: for (int x = 0; x <= ceilRadiusX; ++x) {
|
||||
final double xn = nextXn;
|
||||
double dx = xn * xn;
|
||||
nextXn = (x + 1) * invRadiusX;
|
||||
double nextZn = invRadiusZ;
|
||||
double nextZn = 0;
|
||||
forZ: for (int z = 0; z <= ceilRadiusZ; ++z) {
|
||||
final double zn = nextZn;
|
||||
double dz = zn * zn;
|
||||
double dxz = dx + dz;
|
||||
nextZn = (z + 1) * invRadiusZ;
|
||||
double nextYn = invRadiusY;
|
||||
double nextYn = 0;
|
||||
|
||||
forY: for (int y = 0; y <= ceilRadiusY; ++y) {
|
||||
final double yn = nextYn;
|
||||
@ -2767,7 +2766,7 @@ public class EditSession extends PassthroughExtent implements AutoCloseable {
|
||||
newVset = this.getHollowed(newVset);
|
||||
}
|
||||
}
|
||||
return setBlocks(newVset, pattern);
|
||||
return this.changes += setBlocks(newVset, pattern);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2840,7 +2839,7 @@ public class EditSession extends PassthroughExtent implements AutoCloseable {
|
||||
if (!filled) {
|
||||
vset = getHollowed(vset);
|
||||
}
|
||||
return setBlocks(vset, pattern);
|
||||
return this.changes += setBlocks(vset, pattern);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2892,7 +2891,7 @@ public class EditSession extends PassthroughExtent implements AutoCloseable {
|
||||
if (!filled) {
|
||||
newVset = this.getHollowed(newVset);
|
||||
}
|
||||
return setBlocks(newVset, pattern);
|
||||
return this.changes += setBlocks(newVset, pattern);
|
||||
}
|
||||
return changes;
|
||||
}
|
||||
@ -3008,23 +3007,21 @@ public class EditSession extends PassthroughExtent implements AutoCloseable {
|
||||
}
|
||||
|
||||
public int makeBiomeShape(final Region region, final Vector3 zero, final Vector3 unit, final BiomeType biomeType,
|
||||
final String expressionString, final boolean hollow)
|
||||
throws ExpressionException, MaxChangedBlocksException {
|
||||
final String expressionString, final boolean hollow) throws ExpressionException {
|
||||
return makeBiomeShape(region, zero, unit, biomeType, expressionString, hollow, WorldEdit.getInstance().getConfiguration().calculationTimeout);
|
||||
}
|
||||
|
||||
public int makeBiomeShape(final Region region, final Vector3 zero, final Vector3 unit, final BiomeType biomeType,
|
||||
final String expressionString, final boolean hollow, final int timeout)
|
||||
throws ExpressionException, MaxChangedBlocksException {
|
||||
final String expressionString, final boolean hollow, final int timeout) throws ExpressionException {
|
||||
|
||||
final Expression expression = Expression.compile(expressionString, "x", "z");
|
||||
final Expression expression = Expression.compile(expressionString, "x", "y", "z");
|
||||
expression.optimize();
|
||||
|
||||
final EditSession editSession = this;
|
||||
final WorldEditExpressionEnvironment environment = new WorldEditExpressionEnvironment(editSession, unit, zero);
|
||||
expression.setEnvironment(environment);
|
||||
|
||||
final int[] timedOut = {0};
|
||||
AtomicInteger timedOut = new AtomicInteger();
|
||||
final ArbitraryBiomeShape shape = new ArbitraryBiomeShape(region) {
|
||||
@Override
|
||||
protected BiomeType getBiome(int x, int y, int z, BiomeType defaultBiomeType) {
|
||||
@ -3041,7 +3038,7 @@ public class EditSession extends PassthroughExtent implements AutoCloseable {
|
||||
// TODO: Allow biome setting via a script variable (needs BiomeType<->int mapping)
|
||||
return defaultBiomeType;
|
||||
} catch (ExpressionTimeoutException e) {
|
||||
timedOut[0] = timedOut[0] + 1;
|
||||
timedOut.getAndIncrement();
|
||||
return null;
|
||||
} catch (Exception e) {
|
||||
log.warn("Failed to create shape", e);
|
||||
@ -3050,10 +3047,10 @@ public class EditSession extends PassthroughExtent implements AutoCloseable {
|
||||
}
|
||||
};
|
||||
int changed = shape.generate(this, biomeType, hollow);
|
||||
if (timedOut[0] > 0) {
|
||||
if (timedOut.get() > 0) {
|
||||
throw new ExpressionTimeoutException(
|
||||
String.format("%d blocks changed. %d blocks took too long to evaluate (increase time with //timeout)",
|
||||
changed, timedOut[0]));
|
||||
String.format("%d biomes changed. %d biomes took too long to evaluate (increase time with //timeout)",
|
||||
changed, timedOut.get()));
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
|
@ -85,7 +85,6 @@ import com.sk89q.worldedit.command.util.CommandPermissionsConditionGenerator;
|
||||
import com.sk89q.worldedit.command.util.CreatureButcher;
|
||||
import com.sk89q.worldedit.entity.Player;
|
||||
import com.sk89q.worldedit.extension.platform.Actor;
|
||||
import com.sk89q.worldedit.extension.platform.binding.ProvideBindings;
|
||||
import com.sk89q.worldedit.extent.clipboard.Clipboard;
|
||||
import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormats;
|
||||
import com.sk89q.worldedit.function.Contextual;
|
||||
@ -130,6 +129,7 @@ import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URI;
|
||||
import java.net.URL;
|
||||
import java.nio.file.FileSystems;
|
||||
import java.util.List;
|
||||
|
||||
@ -498,22 +498,23 @@ public class BrushCommands {
|
||||
set(context, brush).setSize(radius).setFill(fill);
|
||||
}
|
||||
|
||||
@Command(
|
||||
name = "image",
|
||||
@Command(name = "image",
|
||||
desc = "Use a height map to paint a surface",
|
||||
descFooter = "Use a height map to paint any surface.\n"
|
||||
)
|
||||
@CommandPermissions("worldedit.brush.stencil")
|
||||
public void imageBrush(LocalSession session, InjectedValueAccess context,
|
||||
@Arg(desc = "The size of the brush", def = "5")
|
||||
Expression radius, ProvideBindings.ImageUri imageUri,
|
||||
@Arg(def = "1", desc = "scale height")
|
||||
double yscale,
|
||||
@Switch(name = 'a', desc = "Use image Alpha")
|
||||
boolean alpha,
|
||||
@Switch(name = 'f', desc = "Blend the image with existing terrain")
|
||||
boolean fadeOut) throws WorldEditException, IOException {
|
||||
BufferedImage image = imageUri.load();
|
||||
descFooter = "Use a height map to paint any surface.\n")
|
||||
@CommandPermissions("worldedit.brush.image")
|
||||
public void imageBrush(LocalSession session,
|
||||
InjectedValueAccess context,
|
||||
@Arg(desc = "Image URL (imgur only)") String imageURL,
|
||||
@Arg(desc = "The size of the brush", def = "5") Expression radius,
|
||||
@Arg(def = "1", desc = "scale height") double yscale,
|
||||
@Switch(name = 'a', desc = "Use image Alpha") boolean alpha,
|
||||
@Switch(name = 'f', desc = "Blend the image with existing terrain") boolean fadeOut)
|
||||
throws WorldEditException, IOException {
|
||||
URL url = new URL(imageURL);
|
||||
if (!url.getHost().equalsIgnoreCase("i.imgur.com")) {
|
||||
throw new IOException("Only i.imgur.com links are allowed!");
|
||||
}
|
||||
BufferedImage image = MainUtil.readImage(url);
|
||||
worldEdit.checkMaxBrushRadius(radius);
|
||||
if (yscale != 1) {
|
||||
ImageUtil.scaleAlpha(image, yscale);
|
||||
|
@ -277,7 +277,7 @@ public class ClipboardCommands {
|
||||
)
|
||||
@Deprecated
|
||||
@CommandPermissions({"worldedit.clipboard.download"})
|
||||
public void download(final Player player, final LocalSession session, @Arg(name = "format", desc = "String", def = "schem") final String formatName) throws WorldEditException {
|
||||
public void download(final Player player, final LocalSession session, @Arg(name = "format", desc = "String", def = "fast") final String formatName) throws WorldEditException {
|
||||
final ClipboardFormat format = ClipboardFormats.findByAlias(formatName);
|
||||
if (format == null) {
|
||||
player.print(Caption.of("fawe.worldedit.clipboard.clipboard.invalid.format", formatName));
|
||||
|
@ -58,7 +58,7 @@ import org.enginehub.piston.annotation.param.Arg;
|
||||
import org.enginehub.piston.annotation.param.Switch;
|
||||
import org.jetbrains.annotations.Range;
|
||||
|
||||
import java.awt.RenderingHints;
|
||||
import java.awt.*;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
@ -131,16 +131,22 @@ public class GenerationCommands {
|
||||
)
|
||||
@CommandPermissions("worldedit.generation.image")
|
||||
@Logging(PLACEMENT)
|
||||
public void image(Actor actor, LocalSession session, EditSession editSession, String argStr, @Arg(desc = "boolean", def = "true") boolean randomize,
|
||||
@Arg(desc = "TODO", def = "100") int threshold, @Arg(desc = "BlockVector2", def = "") BlockVector2 dimensions) throws WorldEditException, IOException {
|
||||
public void image(Actor actor,
|
||||
LocalSession session,
|
||||
EditSession editSession,
|
||||
@Arg(desc = "Image URL (imgur only)") String imageURL,
|
||||
@Arg(desc = "boolean", def = "true") boolean randomize,
|
||||
@Arg(desc = "TODO", def = "100") int threshold,
|
||||
@Arg(desc = "BlockVector2", def = "") BlockVector2 dimensions) throws WorldEditException, IOException {
|
||||
TextureUtil tu = Fawe.get().getCachedTextureUtil(randomize, 0, threshold);
|
||||
URL url = new URL(argStr);
|
||||
URL url = new URL(imageURL);
|
||||
if (!url.getHost().equalsIgnoreCase("i.imgur.com")) {
|
||||
throw new IOException("Only i.imgur.com links are allowed!");
|
||||
}
|
||||
BufferedImage image = MainUtil.readImage(url);
|
||||
if (dimensions != null) {
|
||||
image = ImageUtil.getScaledInstance(image, dimensions.getBlockX(), dimensions.getBlockZ(), RenderingHints.VALUE_INTERPOLATION_BILINEAR, false);
|
||||
image = ImageUtil.getScaledInstance(image, dimensions.getBlockX(), dimensions.getBlockZ(),
|
||||
RenderingHints.VALUE_INTERPOLATION_BILINEAR, false);
|
||||
}
|
||||
|
||||
BlockVector3 pos1 = session.getPlacementPosition(actor);
|
||||
|
@ -147,7 +147,7 @@ public class SchematicCommands {
|
||||
@Deprecated
|
||||
@CommandPermissions({"worldedit.clipboard.load", "worldedit.schematic.load", "worldedit.schematic.load.web", "worldedit.schematic.load.asset"})
|
||||
public void loadall(Player player, LocalSession session,
|
||||
@Arg(desc = "Format name.", def = "schematic")
|
||||
@Arg(desc = "Format name.", def = "fast")
|
||||
String formatName,
|
||||
@Arg(desc = "File name.")
|
||||
String filename,
|
||||
@ -223,7 +223,7 @@ public class SchematicCommands {
|
||||
public void load(Actor actor, LocalSession session,
|
||||
@Arg(desc = "File name.")
|
||||
String filename,
|
||||
@Arg(desc = "Format name.", def = "sponge")
|
||||
@Arg(desc = "Format name.", def = "fast")
|
||||
String formatName) throws FilenameException {
|
||||
LocalConfiguration config = worldEdit.getConfiguration();
|
||||
|
||||
@ -323,7 +323,7 @@ public class SchematicCommands {
|
||||
public void save(Actor actor, LocalSession session,
|
||||
@Arg(desc = "File name.")
|
||||
String filename,
|
||||
@Arg(desc = "Format name.", def = "sponge")
|
||||
@Arg(desc = "Format name.", def = "fast")
|
||||
String formatName,
|
||||
@Switch(name = 'f', desc = "Overwrite an existing file.")
|
||||
boolean allowOverwrite,
|
||||
|
@ -22,7 +22,7 @@ package com.sk89q.worldedit.command;
|
||||
import com.boydti.fawe.Fawe;
|
||||
import com.boydti.fawe.FaweVersion;
|
||||
import com.boydti.fawe.config.Settings;
|
||||
import com.boydti.fawe.util.IncendoPaster;
|
||||
import com.intellectualsites.paster.IncendoPaster;
|
||||
import com.sk89q.worldedit.LocalSession;
|
||||
import com.sk89q.worldedit.WorldEdit;
|
||||
import com.sk89q.worldedit.WorldEditException;
|
||||
@ -47,6 +47,7 @@ import org.enginehub.piston.annotation.param.Arg;
|
||||
import org.enginehub.piston.annotation.param.ArgFlag;
|
||||
import org.enginehub.piston.annotation.param.Switch;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.time.ZoneId;
|
||||
import java.time.ZonedDateTime;
|
||||
@ -139,7 +140,10 @@ public class WorldEditCommands {
|
||||
public void report(Actor actor) throws WorldEditException {
|
||||
String dest;
|
||||
try {
|
||||
dest = IncendoPaster.debugPaste();
|
||||
final File logFile = new File(Fawe.imp().getDirectory(), "../../logs/latest.log");
|
||||
final File config = new File(Fawe.imp().getDirectory(), "config.yml");
|
||||
final File legacyConfig = new File(Fawe.imp().getDirectory(), "config-legacy.yml");
|
||||
dest = IncendoPaster.debugPaste(logFile, Fawe.imp().getDebugInfo(), config, legacyConfig);
|
||||
} catch (IOException e) {
|
||||
actor.printInfo(TextComponent.of(e.getMessage()));
|
||||
return;
|
||||
|
@ -24,8 +24,11 @@ import com.boydti.fawe.object.io.ResettableFileInputStream;
|
||||
import com.boydti.fawe.object.schematic.MinecraftStructure;
|
||||
import com.boydti.fawe.object.schematic.PNGWriter;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.sk89q.jnbt.CompoundTag;
|
||||
import com.sk89q.jnbt.NBTInputStream;
|
||||
import com.sk89q.jnbt.NBTOutputStream;
|
||||
import com.sk89q.jnbt.NamedTag;
|
||||
import com.sk89q.jnbt.Tag;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.BufferedOutputStream;
|
||||
@ -35,6 +38,7 @@ import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.zip.GZIPInputStream;
|
||||
import java.util.zip.GZIPOutputStream;
|
||||
@ -44,40 +48,7 @@ import java.util.zip.GZIPOutputStream;
|
||||
*/
|
||||
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") {
|
||||
FAST("fast", "fawe") {
|
||||
|
||||
@Override
|
||||
public String getPrimaryFileExtension() {
|
||||
@ -115,6 +86,129 @@ public enum BuiltInClipboardFormat implements ClipboardFormat {
|
||||
|
||||
},
|
||||
|
||||
SPONGE_SCHEMATIC("sponge", "schem") {
|
||||
|
||||
@Override
|
||||
public String getPrimaryFileExtension() {
|
||||
return "schem";
|
||||
}
|
||||
@Override
|
||||
public ClipboardReader getReader(InputStream inputStream) throws IOException {
|
||||
NBTInputStream nbtStream = new NBTInputStream(new GZIPInputStream(inputStream));
|
||||
return new SpongeSchematicReader(nbtStream);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClipboardWriter getWriter(OutputStream outputStream) throws IOException {
|
||||
NBTOutputStream nbtStream = new NBTOutputStream(new GZIPOutputStream(outputStream));
|
||||
return new SpongeSchematicWriter(nbtStream);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFormat(File file) {
|
||||
try (NBTInputStream str = new NBTInputStream(new GZIPInputStream(new FileInputStream(file)))) {
|
||||
NamedTag rootTag = str.readNamedTag();
|
||||
if (!rootTag.getName().equals("Schematic")) {
|
||||
return false;
|
||||
}
|
||||
CompoundTag schematicTag = (CompoundTag) rootTag.getTag();
|
||||
|
||||
// Check
|
||||
Map<String, Tag> schematic = schematicTag.getValue();
|
||||
if (!schematic.containsKey("Version")) {
|
||||
return false;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 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
|
||||
public String getPrimaryFileExtension() {
|
||||
return "schem";
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClipboardReader getReader(InputStream inputStream) throws IOException {
|
||||
if (inputStream instanceof FileInputStream) {
|
||||
inputStream = new ResettableFileInputStream((FileInputStream) inputStream);
|
||||
}
|
||||
BufferedInputStream buffered = new BufferedInputStream(inputStream);
|
||||
NBTInputStream nbtStream = new NBTInputStream(new BufferedInputStream(new GZIPInputStream(buffered)));
|
||||
FastSchematicReader reader = new FastSchematicReader(nbtStream);
|
||||
reader.setBrokenEntities(true);
|
||||
return reader;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClipboardWriter getWriter(OutputStream outputStream) throws IOException {
|
||||
OutputStream gzip;
|
||||
if (outputStream instanceof PGZIPOutputStream || outputStream instanceof GZIPOutputStream) {
|
||||
gzip = outputStream;
|
||||
} else {
|
||||
outputStream = new BufferedOutputStream(outputStream);
|
||||
gzip = new PGZIPOutputStream(outputStream);
|
||||
}
|
||||
NBTOutputStream nbtStream = new NBTOutputStream(new BufferedOutputStream(gzip));
|
||||
FastSchematicWriter writer = new FastSchematicWriter(nbtStream);
|
||||
writer.setBrokenEntities(true);
|
||||
return writer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFormat(File file) {
|
||||
return false;
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
* The structure block format:
|
||||
* http://minecraft.gamepedia.com/Structure_block_file_format
|
||||
|
@ -30,10 +30,12 @@ import com.boydti.fawe.object.io.FastByteArraysInputStream;
|
||||
import com.sk89q.jnbt.CompoundTag;
|
||||
import com.sk89q.jnbt.IntTag;
|
||||
import com.sk89q.jnbt.NBTInputStream;
|
||||
import com.sk89q.jnbt.NamedTag;
|
||||
import com.sk89q.jnbt.StringTag;
|
||||
import com.sk89q.jnbt.Tag;
|
||||
import com.sk89q.worldedit.WorldEdit;
|
||||
import com.sk89q.worldedit.entity.BaseEntity;
|
||||
import com.sk89q.worldedit.entity.Entity;
|
||||
import com.sk89q.worldedit.extension.input.InputParseException;
|
||||
import com.sk89q.worldedit.extension.platform.Capability;
|
||||
import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard;
|
||||
@ -45,6 +47,7 @@ import com.sk89q.worldedit.world.DataFixer;
|
||||
import com.sk89q.worldedit.world.biome.BiomeType;
|
||||
import com.sk89q.worldedit.world.biome.BiomeTypes;
|
||||
import com.sk89q.worldedit.world.block.BlockState;
|
||||
import com.sk89q.worldedit.world.block.BlockTypes;
|
||||
import com.sk89q.worldedit.world.block.BlockTypesCache;
|
||||
import com.sk89q.worldedit.world.entity.EntityType;
|
||||
import com.sk89q.worldedit.world.entity.EntityTypes;
|
||||
@ -55,9 +58,11 @@ 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;
|
||||
import java.util.OptionalInt;
|
||||
import java.util.UUID;
|
||||
import java.util.function.Function;
|
||||
|
||||
@ -70,9 +75,10 @@ public class FastSchematicReader extends NBTSchematicReader {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(FastSchematicReader.class);
|
||||
private final NBTInputStream inputStream;
|
||||
private DataFixer fixer = null;
|
||||
private DataFixer fixer;
|
||||
private int dataVersion = -1;
|
||||
private int version = -1;
|
||||
private int faweWritten = -1;
|
||||
|
||||
private FastByteArrayOutputStream blocksOut;
|
||||
private FaweOutputStream blocks;
|
||||
@ -92,6 +98,8 @@ public class FastSchematicReader extends NBTSchematicReader {
|
||||
private char[] palette;
|
||||
private char[] biomePalette;
|
||||
private BlockVector3 min = BlockVector3.ZERO;
|
||||
private boolean brokenEntities = false;
|
||||
private boolean isWorldEdit = false;
|
||||
|
||||
|
||||
/**
|
||||
@ -105,6 +113,10 @@ public class FastSchematicReader extends NBTSchematicReader {
|
||||
this.fixer = WorldEdit.getInstance().getPlatformManager().queryCapability(Capability.WORLD_EDITING).getDataFixer();
|
||||
}
|
||||
|
||||
public void setBrokenEntities(boolean brokenEntities) {
|
||||
this.brokenEntities = brokenEntities;
|
||||
}
|
||||
|
||||
private String fix(String palettePart) {
|
||||
if (fixer == null || dataVersion == -1) {
|
||||
return palettePart;
|
||||
@ -133,7 +145,7 @@ public class FastSchematicReader extends NBTSchematicReader {
|
||||
return fixer.fixUp(DataFixer.FixTypes.BIOME, biomePalettePart, dataVersion);
|
||||
}
|
||||
|
||||
public StreamDelegate createDelegate() {
|
||||
public StreamDelegate createVersionDelegate() {
|
||||
StreamDelegate root = new StreamDelegate();
|
||||
StreamDelegate schematic = root.add("Schematic");
|
||||
schematic.add("DataVersion").withInt((i, v) -> dataVersion = v);
|
||||
@ -143,6 +155,12 @@ public class FastSchematicReader extends NBTSchematicReader {
|
||||
dataVersion = Constants.DATA_VERSION_MC_1_13_2;
|
||||
}
|
||||
});
|
||||
return root;
|
||||
}
|
||||
|
||||
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);
|
||||
@ -152,17 +170,23 @@ public class FastSchematicReader extends NBTSchematicReader {
|
||||
metadata.add("WEOffsetX").withInt((i, v) -> offsetX = v);
|
||||
metadata.add("WEOffsetY").withInt((i, v) -> offsetY = v);
|
||||
metadata.add("WEOffsetZ").withInt((i, v) -> offsetZ = v);
|
||||
metadata.add("FAWEVersion").withInt((i, v) -> faweWritten = v);
|
||||
|
||||
StreamDelegate worldEditSection = metadata.add("WorldEdit");
|
||||
worldEditSection.withValue((ValueReader<String>) (index, v) -> isWorldEdit = true);
|
||||
|
||||
|
||||
StreamDelegate paletteDelegate = schematic.add("Palette");
|
||||
paletteDelegate.withValue((ValueReader<Map<String, Object>>) (ignore, v) -> {
|
||||
palette = new char[v.size()];
|
||||
for (Entry<String, Object> entry : v.entrySet()) {
|
||||
BlockState state = null;
|
||||
try {
|
||||
BlockState state;
|
||||
String palettePart = fix(entry.getKey());
|
||||
try {
|
||||
state = BlockState.get(palettePart);
|
||||
} catch (InputParseException e) {
|
||||
e.printStackTrace();
|
||||
} catch (InputParseException ignored) {
|
||||
log.warn("Invalid BlockState in palette: " + palettePart + ". Block will be replaced with air.");
|
||||
state = BlockTypes.AIR.getDefaultState();
|
||||
}
|
||||
int index = (int) entry.getValue();
|
||||
palette[index] = (char) state.getOrdinal();
|
||||
@ -224,10 +248,14 @@ public class FastSchematicReader extends NBTSchematicReader {
|
||||
@Override
|
||||
public Clipboard read(UUID uuid, Function<BlockVector3, Clipboard> createOutput) throws IOException {
|
||||
StreamDelegate root = createDelegate();
|
||||
StreamDelegate versions = createVersionDelegate();
|
||||
inputStream.mark(Integer.MAX_VALUE);
|
||||
inputStream.readNamedTagLazy(versions);
|
||||
inputStream.reset();
|
||||
inputStream.readNamedTagLazy(root);
|
||||
|
||||
if (version != 1 && version != 2) {
|
||||
throw new IOException("This schematic version is currently not supported");
|
||||
throw new IOException("This schematic version is currently not supported (" + version + ")");
|
||||
}
|
||||
|
||||
if (blocks != null) {
|
||||
@ -240,9 +268,11 @@ public class FastSchematicReader extends NBTSchematicReader {
|
||||
biomes = null;
|
||||
|
||||
BlockVector3 dimensions = BlockVector3.at(width, height, length);
|
||||
BlockVector3 origin = BlockVector3.ZERO;
|
||||
BlockVector3 origin;
|
||||
if (offsetX != Integer.MIN_VALUE && offsetY != Integer.MIN_VALUE && offsetZ != Integer.MIN_VALUE) {
|
||||
origin = BlockVector3.at(-offsetX, -offsetY, -offsetZ);
|
||||
} else {
|
||||
origin = BlockVector3.ZERO;
|
||||
}
|
||||
|
||||
Clipboard clipboard = createOutput.apply(dimensions);
|
||||
@ -326,7 +356,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));
|
||||
@ -337,22 +367,19 @@ 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");
|
||||
if (id == null) {
|
||||
return null;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
value.put("id", id);
|
||||
@ -360,10 +387,29 @@ 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) {
|
||||
clipboard.createEntity(loc, state);
|
||||
continue;
|
||||
}
|
||||
if (!isWorldEdit && faweWritten == -1) {
|
||||
int locX = loc.getBlockX();
|
||||
int locY = loc.getBlockY();
|
||||
int locZ = loc.getBlockZ();
|
||||
BlockVector3 max = min.add(dimensions).subtract(BlockVector3.ONE);
|
||||
if (locX < min.getX() || locY < min.getY() || locZ < min.getZ()
|
||||
|| locX > max.getX() || locY > max.getY() || locZ > max.getZ()) {
|
||||
for (Entity e : clipboard.getEntities()) {
|
||||
clipboard.removeEntity(e);
|
||||
}
|
||||
log.error("Detected schematic entity outside clipboard region. FAWE will not load entities. "
|
||||
+ "Please try loading the schematic with the format \"legacyentity\"");
|
||||
break;
|
||||
}
|
||||
}
|
||||
clipboard.createEntity(loc.setPosition(loc.subtract(min.toVector3())), state);
|
||||
} else {
|
||||
log.debug("Invalid entity: " + id);
|
||||
}
|
||||
@ -372,7 +418,7 @@ public class FastSchematicReader extends NBTSchematicReader {
|
||||
clipboard.setOrigin(origin);
|
||||
|
||||
if (!min.equals(BlockVector3.ZERO)) {
|
||||
new BlockArrayClipboard(clipboard, min);
|
||||
clipboard = new BlockArrayClipboard(clipboard, min);
|
||||
}
|
||||
|
||||
return clipboard;
|
||||
|
@ -19,10 +19,10 @@
|
||||
|
||||
package com.sk89q.worldedit.extent.clipboard.io;
|
||||
|
||||
import com.boydti.fawe.Fawe;
|
||||
import com.boydti.fawe.jnbt.streamer.IntValueReader;
|
||||
import com.boydti.fawe.object.FaweOutputStream;
|
||||
import com.boydti.fawe.util.IOUtil;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.sk89q.jnbt.CompoundTag;
|
||||
import com.sk89q.jnbt.IntArrayTag;
|
||||
import com.sk89q.jnbt.ListTag;
|
||||
@ -39,6 +39,7 @@ import com.sk89q.worldedit.extent.clipboard.Clipboard;
|
||||
import com.sk89q.worldedit.function.visitor.Order;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
import com.sk89q.worldedit.regions.Region;
|
||||
import com.sk89q.worldedit.util.Location;
|
||||
import com.sk89q.worldedit.world.biome.BiomeType;
|
||||
import com.sk89q.worldedit.world.biome.BiomeTypes;
|
||||
import com.sk89q.worldedit.world.block.BaseBlock;
|
||||
@ -58,8 +59,6 @@ import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
@ -72,6 +71,7 @@ public class FastSchematicWriter implements ClipboardWriter {
|
||||
|
||||
private static final int MAX_SIZE = Short.MAX_VALUE - Short.MIN_VALUE;
|
||||
private final NBTOutputStream outputStream;
|
||||
private boolean brokenEntities = false;
|
||||
|
||||
/**
|
||||
* Create a new schematic writer.
|
||||
@ -83,6 +83,10 @@ public class FastSchematicWriter implements ClipboardWriter {
|
||||
this.outputStream = outputStream;
|
||||
}
|
||||
|
||||
public void setBrokenEntities(boolean brokenEntities) {
|
||||
this.brokenEntities = brokenEntities;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(Clipboard clipboard) throws IOException {
|
||||
// For now always write the latest version. Maybe provide support for earlier if more appear.
|
||||
@ -132,6 +136,7 @@ public class FastSchematicWriter implements ClipboardWriter {
|
||||
out1.writeNamedTag("WEOffsetX", offset.getBlockX());
|
||||
out1.writeNamedTag("WEOffsetY", offset.getBlockY());
|
||||
out1.writeNamedTag("WEOffsetZ", offset.getBlockZ());
|
||||
out1.writeNamedTag("FAWEVersion", Fawe.get().getVersion().build);
|
||||
});
|
||||
|
||||
ByteArrayOutputStream blocksCompressed = new ByteArrayOutputStream();
|
||||
@ -157,7 +162,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");
|
||||
@ -175,7 +180,8 @@ public class FastSchematicWriter implements ClipboardWriter {
|
||||
pos.getZ()
|
||||
}));
|
||||
numTiles++;
|
||||
tilesOut.writeTagPayload(block.getNbtData());
|
||||
|
||||
tilesOut.writeTagPayload(new CompoundTag(values));
|
||||
}
|
||||
|
||||
int ordinal = block.getOrdinal();
|
||||
@ -240,8 +246,12 @@ public class FastSchematicWriter implements ClipboardWriter {
|
||||
|
||||
// Store our location data, overwriting any
|
||||
values.remove("id");
|
||||
Location loc = entity.getLocation();
|
||||
if (!brokenEntities) {
|
||||
loc = loc.setPosition(loc.add(min.toVector3()));
|
||||
}
|
||||
values.put("Id", new StringTag(state.getType().getId()));
|
||||
values.put("Pos", writeVector(entity.getLocation()));
|
||||
values.put("Pos", writeVector(loc));
|
||||
values.put("Rotation", writeRotation(entity.getLocation()));
|
||||
|
||||
CompoundTag entityTag = new CompoundTag(values);
|
||||
@ -311,30 +321,6 @@ public class FastSchematicWriter implements ClipboardWriter {
|
||||
}
|
||||
}
|
||||
|
||||
private void writeEntities(Clipboard clipboard, NBTOutputStream schematic) throws IOException {
|
||||
List<CompoundTag> entities = clipboard.getEntities().stream().map(e -> {
|
||||
BaseEntity state = e.getState();
|
||||
if (state == null) {
|
||||
return null;
|
||||
}
|
||||
Map<String, Tag> values = Maps.newHashMap();
|
||||
CompoundTag rawData = state.getNbtData();
|
||||
if (rawData != null) {
|
||||
values.putAll(rawData.getValue());
|
||||
}
|
||||
values.remove("id");
|
||||
values.put("Id", new StringTag(state.getType().getId()));
|
||||
values.put("Pos", writeVector(e.getLocation().toVector()));
|
||||
values.put("Rotation", writeRotation(e.getLocation()));
|
||||
|
||||
return new CompoundTag(values);
|
||||
}).filter(Objects::nonNull).collect(Collectors.toList());
|
||||
if (entities.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
schematic.writeNamedTag("Entities", new ListTag(CompoundTag.class, entities));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
outputStream.close();
|
||||
|
@ -1,4 +0,0 @@
|
||||
package com.sk89q.worldedit.extent.clipboard.io;
|
||||
|
||||
public class FaweFormat {
|
||||
}
|
@ -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;
|
||||
}
|
||||
@ -302,7 +300,7 @@ public class MCEditSchematicReader extends NBTSchematicReader {
|
||||
}
|
||||
|
||||
private String convertEntityId(String id) {
|
||||
switch(id) {
|
||||
switch (id) {
|
||||
case "AreaEffectCloud": return "area_effect_cloud";
|
||||
case "ArmorStand": return "armor_stand";
|
||||
case "CaveSpider": return "cave_spider";
|
||||
|
@ -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)) {
|
||||
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();
|
||||
}
|
||||
}
|
@ -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)) {
|
||||
|
@ -19,11 +19,10 @@
|
||||
|
||||
package com.sk89q.worldedit.extent.clipboard.io;
|
||||
|
||||
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;
|
||||
@ -36,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;
|
||||
@ -56,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;
|
||||
@ -114,6 +111,7 @@ public class SpongeSchematicWriter implements ClipboardWriter {
|
||||
metadata.put("WEOffsetX", new IntTag(offset.getBlockX()));
|
||||
metadata.put("WEOffsetY", new IntTag(offset.getBlockY()));
|
||||
metadata.put("WEOffsetZ", new IntTag(offset.getBlockZ()));
|
||||
metadata.put("FAWEVersion", new IntTag(Fawe.get().getVersion().build));
|
||||
|
||||
schematic.put("Metadata", new CompoundTag(metadata));
|
||||
|
||||
@ -268,21 +266,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();
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -22,6 +22,7 @@ package com.sk89q.worldedit.function.mask;
|
||||
import com.sk89q.worldedit.extent.Extent;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
import com.sk89q.worldedit.world.block.BlockCategory;
|
||||
import com.sk89q.worldedit.world.block.BlockTypes;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
@ -61,4 +62,9 @@ public class BlockCategoryMask extends AbstractExtentMask {
|
||||
public Mask copy() {
|
||||
return new BlockCategoryMask(getExtent(), category);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean replacesAir() {
|
||||
return category.contains(BlockTypes.AIR);
|
||||
}
|
||||
}
|
||||
|
@ -29,12 +29,12 @@ import com.sk89q.worldedit.world.block.BlockTypes;
|
||||
import com.sk89q.worldedit.world.block.BlockTypesCache;
|
||||
import com.sk89q.worldedit.world.block.ImmutableBaseBlock;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.function.Predicate;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
@ -185,7 +185,7 @@ public class BlockMask extends ABlockMask {
|
||||
|
||||
@Override
|
||||
public boolean test(BlockState state) {
|
||||
return ordinals[state.getOrdinal()] || replacesAir() && state.getOrdinal() <= 3;
|
||||
return ordinals[state.getOrdinal()] || replacesAir() && state.getOrdinal() == 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -259,19 +259,16 @@ public class BlockMask extends ABlockMask {
|
||||
|
||||
int setTypes = 0;
|
||||
BlockType setType = null;
|
||||
BlockType unsetType = null;
|
||||
int totalTypes = 0;
|
||||
|
||||
for (BlockType type : BlockTypesCache.values) {
|
||||
if (type != null) {
|
||||
totalTypes++;
|
||||
boolean hasAll = true;
|
||||
boolean hasAny = false;
|
||||
List<BlockState> all = type.getAllStates();
|
||||
for (BlockState state : all) {
|
||||
totalStates++;
|
||||
hasAll &= test(state);
|
||||
hasAny = true;
|
||||
}
|
||||
if (hasAll) {
|
||||
setTypes++;
|
||||
@ -326,6 +323,7 @@ public class BlockMask extends ABlockMask {
|
||||
cloned[BlockTypes.AIR.getDefaultState().getOrdinal()] = false;
|
||||
cloned[BlockTypes.CAVE_AIR.getDefaultState().getOrdinal()] = false;
|
||||
cloned[BlockTypes.VOID_AIR.getDefaultState().getOrdinal()] = false;
|
||||
cloned[0] = false;
|
||||
}
|
||||
return new BlockMask(getExtent(), cloned);
|
||||
}
|
||||
|
Einige Dateien werden nicht angezeigt, da zu viele Dateien in diesem Diff geändert wurden Mehr anzeigen
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren