This commit is contained in:
MattBDev 2021-01-06 12:53:34 -05:00
commit 653d362806
107 changed files with 1624 additions and 1778 deletions

View File

@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists 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 zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists

6
renovate.json Normal file
View File

@ -0,0 +1,6 @@
{
"extends": [
"config:base"
],
"ignoreDeps": ["guava", "rhino-runtime", "mockito-core", "antlr4", "antlr4-runtime", "paranamer"]
}

View File

@ -23,6 +23,7 @@ repositories {
name = "ProtocolLib Repo" name = "ProtocolLib Repo"
url = uri("https://repo.dmulloy2.net/nexus/repository/public/") 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"))} flatDir {dir(File("src/main/resources"))}
} }
@ -56,7 +57,7 @@ dependencies {
"compileOnly"("org.jetbrains:annotations:20.1.0") "compileOnly"("org.jetbrains:annotations:20.1.0")
"testCompileOnly"("org.jetbrains:annotations:20.1.0") "testCompileOnly"("org.jetbrains:annotations:20.1.0")
"compileOnly"("org.spigotmc:spigot:1.16.4-R0.1-SNAPSHOT") "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") { "compileOnly"("com.sk89q:dummypermscompat:1.10") {
exclude("com.github.MilkBowl", "VaultAPI") exclude("com.github.MilkBowl", "VaultAPI")
} }
@ -68,15 +69,16 @@ dependencies {
exclude("com.sk89q.worldedit.worldedit-libs", "bukkit") exclude("com.sk89q.worldedit.worldedit-libs", "bukkit")
exclude("com.sk89q.worldedit.worldedit-libs", "core") 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 // 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.github.TechFortress:GriefPrevention:16.+") { isTransitive = false }
"implementation"("com.massivecraft:mcore:7.0.1") { 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.bekvon.bukkit.residence:Residence:4.5._13.1") { isTransitive = false }
"implementation"("com.palmergames.bukkit:towny:0.84.0.9") { 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.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") { tasks.named<Copy>("processResources") {
@ -107,17 +109,17 @@ tasks.named<ShadowJar>("shadowJar") {
include(dependency("org.slf4j:slf4j-api")) include(dependency("org.slf4j:slf4j-api"))
include(dependency("org.apache.logging.log4j:log4j-slf4j-impl")) include(dependency("org.apache.logging.log4j:log4j-slf4j-impl"))
include(dependency("org.antlr:antlr4-runtime")) 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") { 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") { relocate("it.unimi.dsi.fastutil", "com.sk89q.worldedit.bukkit.fastutil") {
include(dependency("it.unimi.dsi:fastutil")) include(dependency("it.unimi.dsi:fastutil"))
} }
relocate("org.bstats", "com.boydti.metrics") { 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"))
} }
} }
} }

View File

@ -190,37 +190,32 @@ public final class BukkitAdapter_1_15_2 extends NMSAdapter {
return; return;
} }
if (playerChunk.hasBeenLoaded()) { if (playerChunk.hasBeenLoaded()) {
TaskManager.IMP.sync(() -> { try {
try { int dirtyBits = fieldDirtyBits.getInt(playerChunk);
int dirtyBits = fieldDirtyBits.getInt(playerChunk); if (dirtyBits == 0) {
if (dirtyBits == 0) { nmsWorld.getChunkProvider().playerChunkMap.a(playerChunk);
nmsWorld.getChunkProvider().playerChunkMap.a(playerChunk);
}
if (mask == 0) {
dirtyBits = 65535;
} else {
dirtyBits |= mask;
}
fieldDirtyBits.set(playerChunk, dirtyBits);
fieldDirtyCount.set(playerChunk, 64);
if (lighting) {
ChunkCoordIntPair chunkCoordIntPair = new ChunkCoordIntPair(chunkX, chunkZ);
PacketPlayOutLightUpdate packet = new PacketPlayOutLightUpdate(chunkCoordIntPair, nmsWorld.getChunkProvider().getLightEngine());
playerChunk.players.a(chunkCoordIntPair, false).forEach(p -> {
p.playerConnection.sendPacket(packet);
});
}
} catch (IllegalAccessException e) {
e.printStackTrace();
} }
return null; if (mask == 0) {
}); dirtyBits = 65535;
return; } else {
dirtyBits |= mask;
}
fieldDirtyBits.set(playerChunk, dirtyBits);
fieldDirtyCount.set(playerChunk, 64);
if (lighting) {
ChunkCoordIntPair chunkCoordIntPair = new ChunkCoordIntPair(chunkX, chunkZ);
PacketPlayOutLightUpdate packet = new PacketPlayOutLightUpdate(chunkCoordIntPair, nmsWorld.getChunkProvider().getLightEngine());
playerChunk.players.a(chunkCoordIntPair, false).forEach(p -> {
p.playerConnection.sendPacket(packet);
});
}
} catch (IllegalAccessException e) {
e.printStackTrace();
}
} }
return;
} }
/* /*

View File

@ -4,7 +4,6 @@ import com.boydti.fawe.Fawe;
import com.boydti.fawe.FaweCache; import com.boydti.fawe.FaweCache;
import com.boydti.fawe.beta.IChunkGet; import com.boydti.fawe.beta.IChunkGet;
import com.boydti.fawe.beta.IChunkSet; 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.blocks.CharGetBlocks;
import com.boydti.fawe.beta.implementation.lighting.HeightMapType; import com.boydti.fawe.beta.implementation.lighting.HeightMapType;
import com.boydti.fawe.beta.implementation.queue.QueueHandler; 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]; public NibbleArray[] skyLight = new NibbleArray[16];
private boolean createCopy = false; private boolean createCopy = false;
private BukkitGetBlocks_1_15_2_Copy copy = null; private BukkitGetBlocks_1_15_2_Copy copy = null;
private boolean forceLoadSections = true;
public BukkitGetBlocks_1_15_2(World world, int chunkX, int chunkZ) { public BukkitGetBlocks_1_15_2(World world, int chunkX, int chunkZ) {
this(((CraftWorld) world).getHandle(), chunkX, chunkZ); this(((CraftWorld) world).getHandle(), chunkX, chunkZ);
@ -316,7 +316,8 @@ public class BukkitGetBlocks_1_15_2 extends CharGetBlocks {
@Override @Override
public <T extends Future<T>> T call(IChunkSet set, Runnable finalizer) { 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 { try {
WorldServer nmsWorld = world; WorldServer nmsWorld = world;
Chunk nmsChunk = ensureLoaded(nmsWorld, chunkX, chunkZ); Chunk nmsChunk = ensureLoaded(nmsWorld, chunkX, chunkZ);
@ -357,13 +358,14 @@ public class BukkitGetBlocks_1_15_2 extends CharGetBlocks {
if (!set.hasSection(layer)) { if (!set.hasSection(layer)) {
continue; continue;
} }
if (createCopy) {
copy.storeSection(layer);
}
bitMask |= 1 << 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 newSection;
ChunkSection existingSection = sections[layer]; ChunkSection existingSection = sections[layer];
if (existingSection == null) { if (existingSection == null) {
@ -392,7 +394,7 @@ public class BukkitGetBlocks_1_15_2 extends CharGetBlocks {
this.nmsChunk = nmsChunk; this.nmsChunk = nmsChunk;
this.sections = null; this.sections = null;
this.reset(); this.reset();
} else if (existingSection != getSections()[layer]) { } else if (existingSection != getSections(false)[layer]) {
this.sections[layer] = existingSection; this.sections[layer] = existingSection;
this.reset(); this.reset();
} else if (!Arrays.equals(update(layer, new char[4096]), load(layer))) { } 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); newSection = BukkitAdapter_1_15_2.newChunkSection(layer, this::load, setArr, fastmode);
if (!BukkitAdapter_1_15_2.setSectionAtomic(sections, existingSection, newSection, layer)) { if (!BukkitAdapter_1_15_2.setSectionAtomic(sections, existingSection, newSection, layer)) {
log.error("Failed to set chunk section:" + chunkX + "," + chunkZ + " layer: " + layer); log.error("Failed to set chunk section:" + chunkX + "," + chunkZ + " layer: " + layer);
continue;
} else { } else {
updateGet(this, nmsChunk, sections, newSection, setArr, layer); updateGet(this, nmsChunk, sections, newSection, setArr, layer);
} }
@ -470,9 +471,7 @@ public class BukkitGetBlocks_1_15_2 extends CharGetBlocks {
Set<UUID> entityRemoves = set.getEntityRemoves(); Set<UUID> entityRemoves = set.getEntityRemoves();
if (entityRemoves != null && !entityRemoves.isEmpty()) { if (entityRemoves != null && !entityRemoves.isEmpty()) {
if (syncTasks == null) { syncTasks = new Runnable[3];
syncTasks = new Runnable[3];
}
syncTasks[2] = () -> { syncTasks[2] = () -> {
final List<Entity>[] entities = nmsChunk.getEntitySlices(); final List<Entity>[] entities = nmsChunk.getEntitySlices();
@ -632,12 +631,14 @@ public class BukkitGetBlocks_1_15_2 extends CharGetBlocks {
} catch (Throwable e) { } catch (Throwable e) {
e.printStackTrace(); e.printStackTrace();
return null; return null;
} finally {
forceLoadSections = true;
} }
} }
@Override @Override
public synchronized char[] update(int layer, char[] data) { public synchronized char[] update(int layer, char[] data) {
ChunkSection section = getSections()[layer]; ChunkSection section = getSections(true)[layer];
// Section is null, return empty array // Section is null, return empty array
if (section == null) { if (section == null) {
data = new char[4096]; 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; ChunkSection[] tmp = sections;
if (tmp == null) { if (tmp == null) {
synchronized (this) { synchronized (this) {
@ -804,7 +808,7 @@ public class BukkitGetBlocks_1_15_2 extends CharGetBlocks {
@Override @Override
public boolean hasSection(int layer) { public boolean hasSection(int layer) {
return getSections()[layer] != null; return getSections(false)[layer] != null;
} }
@Override @Override
@ -817,10 +821,10 @@ public class BukkitGetBlocks_1_15_2 extends CharGetBlocks {
return super.trim(true); return super.trim(true);
} else { } else {
for (int i = 0; i < 16; i++) { for (int i = 0; i < 16; i++) {
if (!hasSection(i) || super.sections[i] == CharBlocks.EMPTY) { if (!hasSection(i) || !super.sections[i].isFull()) {
continue; continue;
} }
ChunkSection existing = getSections()[i]; ChunkSection existing = getSections(true)[i];
try { try {
final DataPaletteBlock<IBlockData> blocksExisting = existing.getBlocks(); final DataPaletteBlock<IBlockData> blocksExisting = existing.getBlocks();

View File

@ -2,6 +2,10 @@ package com.boydti.fawe.bukkit.adapter.mc1_15_2;
import com.boydti.fawe.FaweCache; 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.boydti.fawe.bukkit.adapter.mc1_15_2.nbt.LazyCompoundTag_1_15_2;
import com.google.common.base.Suppliers; import com.google.common.base.Suppliers;
import com.sk89q.jnbt.CompoundTag; 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 net.minecraft.server.v1_15_R1.WorldServer;
import org.bukkit.craftbukkit.v1_15_R1.block.CraftBlock; import org.bukkit.craftbukkit.v1_15_R1.block.CraftBlock;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.Range;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.UUID; 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 Map<BlockVector3, CompoundTag> tiles = new HashMap<>();
private final Set<CompoundTag> entities = new HashSet<>(); private final Set<CompoundTag> entities = new HashSet<>();
private BiomeStorage biomeStorage; 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) { protected BukkitGetBlocks_1_15_2_Copy(WorldServer world) {
super(world, X, Z); this.world = world;
} }
protected void storeTile(TileEntity tile) { protected void storeTile(TileEntity tile) {
@ -87,6 +94,16 @@ public class BukkitGetBlocks_1_15_2_Copy extends BukkitGetBlocks_1_15_2 {
return null; return null;
} }
@Override
public void setCreateCopy(boolean createCopy) {
}
@Override
public boolean isCreateCopy() {
return false;
}
protected void storeBiomes(BiomeStorage biomeStorage) { protected void storeBiomes(BiomeStorage biomeStorage) {
this.biomeStorage = new BiomeStorage(BukkitAdapter_1_15_2.getBiomeArray(biomeStorage).clone()); 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; return base != null ? BukkitAdapter.adapt(CraftBlock.biomeBaseToBiome(base)) : null;
} }
protected void storeSection(int layer) { @Override
blocks[layer] = update(layer, null).clone(); 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 @Override
@ -115,15 +142,50 @@ public class BukkitGetBlocks_1_15_2_Copy extends BukkitGetBlocks_1_15_2 {
return state.toBaseBlock(this, x, y, z); 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 @Override
public BlockState getBlock(int x, int y, int z) { public BlockState getBlock(int x, int y, int z) {
return BlockTypesCache.states[get(x, y, z)]; return BlockTypesCache.states[get(x, y, z)];
} }
@Override @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) { public char get(int x, int y, int z) {
final int layer = y >> 4; final int layer = y >> 4;
final int index = (y & 15) << 8 | z << 4 | x; final int index = (y & 15) << 8 | z << 4 | x;
return blocks[layer][index]; return blocks[layer][index];
} }
@Override
public boolean trim(boolean aggressive) {
return false;
}
} }

View File

@ -58,7 +58,7 @@ public class FAWEWorldNativeAccess_1_15_2 implements WorldNativeAccess<Chunk, IB
@Override @Override
public IBlockData toNative(com.sk89q.worldedit.world.block.BlockState state) { 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) return BlockStateIdAccess.isValidInternalId(stateId)
? Block.getByCombinedId(stateId) ? Block.getByCombinedId(stateId)
: ((CraftBlockData) BukkitAdapter.adapt(state)).getState(); : ((CraftBlockData) BukkitAdapter.adapt(state)).getState();
@ -72,7 +72,8 @@ public class FAWEWorldNativeAccess_1_15_2 implements WorldNativeAccess<Chunk, IB
@Nullable @Nullable
@Override @Override
public IBlockData setBlockState(Chunk chunk, BlockPosition position, IBlockData state) { 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 @Override
@ -166,9 +167,4 @@ public class FAWEWorldNativeAccess_1_15_2 implements WorldNativeAccess<Chunk, IB
public void onBlockStateChange(BlockPosition pos, IBlockData oldState, IBlockData newState) { public void onBlockStateChange(BlockPosition pos, IBlockData oldState, IBlockData newState) {
getWorld().a(pos, oldState, 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));
}
} }

View File

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

View File

@ -187,35 +187,32 @@ public final class BukkitAdapter_1_16_1 extends NMSAdapter {
return; return;
} }
if (playerChunk.hasBeenLoaded()) { if (playerChunk.hasBeenLoaded()) {
TaskManager.IMP.sync(() -> { try {
try { int dirtyBits = fieldDirtyBits.getInt(playerChunk);
int dirtyBits = fieldDirtyBits.getInt(playerChunk); if (dirtyBits == 0) {
if (dirtyBits == 0) { nmsWorld.getChunkProvider().playerChunkMap.a(playerChunk);
nmsWorld.getChunkProvider().playerChunkMap.a(playerChunk);
}
if (mask == 0) {
dirtyBits = 65535;
} else {
dirtyBits |= mask;
}
fieldDirtyBits.set(playerChunk, dirtyBits);
fieldDirtyCount.set(playerChunk, 64);
if (lighting) {
ChunkCoordIntPair chunkCoordIntPair = new ChunkCoordIntPair(chunkX, chunkZ);
boolean trustEdges = false; //Added in 1.16.1 Not sure what it does.
PacketPlayOutLightUpdate packet = new PacketPlayOutLightUpdate(chunkCoordIntPair, nmsWorld.getChunkProvider().getLightEngine(), trustEdges);
playerChunk.players.a(chunkCoordIntPair, false).forEach(p -> {
p.playerConnection.sendPacket(packet);
});
}
} catch (IllegalAccessException e) {
e.printStackTrace();
} }
return null; if (mask == 0) {
}); dirtyBits = 65535;
} else {
dirtyBits |= mask;
}
fieldDirtyBits.set(playerChunk, dirtyBits);
fieldDirtyCount.set(playerChunk, 64);
if (lighting) {
ChunkCoordIntPair chunkCoordIntPair = new ChunkCoordIntPair(chunkX, chunkZ);
boolean trustEdges = false; //Added in 1.16.1 Not sure what it does.
PacketPlayOutLightUpdate packet = new PacketPlayOutLightUpdate(chunkCoordIntPair, nmsWorld.getChunkProvider().getLightEngine(), trustEdges);
playerChunk.players.a(chunkCoordIntPair, false).forEach(p -> {
p.playerConnection.sendPacket(packet);
});
}
} catch (IllegalAccessException e) {
e.printStackTrace();
}
} }
} }

View File

@ -4,7 +4,6 @@ import com.boydti.fawe.Fawe;
import com.boydti.fawe.FaweCache; import com.boydti.fawe.FaweCache;
import com.boydti.fawe.beta.IChunkGet; import com.boydti.fawe.beta.IChunkGet;
import com.boydti.fawe.beta.IChunkSet; 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.blocks.CharGetBlocks;
import com.boydti.fawe.beta.implementation.lighting.HeightMapType; import com.boydti.fawe.beta.implementation.lighting.HeightMapType;
import com.boydti.fawe.beta.implementation.queue.QueueHandler; 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]; public NibbleArray[] skyLight = new NibbleArray[16];
private boolean createCopy = false; private boolean createCopy = false;
private BukkitGetBlocks_1_16_1_Copy copy = null; private BukkitGetBlocks_1_16_1_Copy copy = null;
private boolean forceLoadSections = true;
public BukkitGetBlocks_1_16_1(World world, int chunkX, int chunkZ) { public BukkitGetBlocks_1_16_1(World world, int chunkX, int chunkZ) {
this(((CraftWorld) world).getHandle(), chunkX, chunkZ); this(((CraftWorld) world).getHandle(), chunkX, chunkZ);
@ -316,7 +316,8 @@ public class BukkitGetBlocks_1_16_1 extends CharGetBlocks {
@Override @Override
public <T extends Future<T>> T call(IChunkSet set, Runnable finalizer) { 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 { try {
WorldServer nmsWorld = world; WorldServer nmsWorld = world;
Chunk nmsChunk = ensureLoaded(nmsWorld, chunkX, chunkZ); Chunk nmsChunk = ensureLoaded(nmsWorld, chunkX, chunkZ);
@ -357,13 +358,14 @@ public class BukkitGetBlocks_1_16_1 extends CharGetBlocks {
if (!set.hasSection(layer)) { if (!set.hasSection(layer)) {
continue; continue;
} }
if (createCopy) {
copy.storeSection(layer);
}
bitMask |= 1 << 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 newSection;
ChunkSection existingSection = sections[layer]; ChunkSection existingSection = sections[layer];
if (existingSection == null) { if (existingSection == null) {
@ -392,7 +394,7 @@ public class BukkitGetBlocks_1_16_1 extends CharGetBlocks {
this.nmsChunk = nmsChunk; this.nmsChunk = nmsChunk;
this.sections = null; this.sections = null;
this.reset(); this.reset();
} else if (existingSection != getSections()[layer]) { } else if (existingSection != getSections(false)[layer]) {
this.sections[layer] = existingSection; this.sections[layer] = existingSection;
this.reset(); this.reset();
} else if (!Arrays.equals(update(layer, new char[4096]), load(layer))) { } 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 if (!BukkitAdapter_1_16_1
.setSectionAtomic(sections, existingSection, newSection, layer)) { .setSectionAtomic(sections, existingSection, newSection, layer)) {
log.error("Failed to set chunk section:" + chunkX + "," + chunkZ + " layer: " + layer); log.error("Failed to set chunk section:" + chunkX + "," + chunkZ + " layer: " + layer);
continue;
} else { } else {
updateGet(this, nmsChunk, sections, newSection, setArr, layer); updateGet(this, nmsChunk, sections, newSection, setArr, layer);
} }
@ -472,9 +473,7 @@ public class BukkitGetBlocks_1_16_1 extends CharGetBlocks {
Set<UUID> entityRemoves = set.getEntityRemoves(); Set<UUID> entityRemoves = set.getEntityRemoves();
if (entityRemoves != null && !entityRemoves.isEmpty()) { if (entityRemoves != null && !entityRemoves.isEmpty()) {
if (syncTasks == null) { syncTasks = new Runnable[3];
syncTasks = new Runnable[3];
}
syncTasks[2] = () -> { syncTasks[2] = () -> {
final List<Entity>[] entities = nmsChunk.getEntitySlices(); final List<Entity>[] entities = nmsChunk.getEntitySlices();
@ -634,12 +633,14 @@ public class BukkitGetBlocks_1_16_1 extends CharGetBlocks {
} catch (Throwable e) { } catch (Throwable e) {
e.printStackTrace(); e.printStackTrace();
return null; return null;
} finally {
forceLoadSections = true;
} }
} }
@Override @Override
public synchronized char[] update(int layer, char[] data) { public synchronized char[] update(int layer, char[] data) {
ChunkSection section = getSections()[layer]; ChunkSection section = getSections(true)[layer];
// Section is null, return empty array // Section is null, return empty array
if (section == null) { if (section == null) {
data = new char[4096]; 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; ChunkSection[] tmp = sections;
if (tmp == null) { if (tmp == null) {
synchronized (this) { synchronized (this) {
@ -806,7 +810,7 @@ public class BukkitGetBlocks_1_16_1 extends CharGetBlocks {
@Override @Override
public boolean hasSection(int layer) { public boolean hasSection(int layer) {
return getSections()[layer] != null; return getSections(false)[layer] != null;
} }
@Override @Override
@ -819,10 +823,10 @@ public class BukkitGetBlocks_1_16_1 extends CharGetBlocks {
return super.trim(true); return super.trim(true);
} else { } else {
for (int i = 0; i < 16; i++) { for (int i = 0; i < 16; i++) {
if (!hasSection(i) || super.sections[i] == CharBlocks.EMPTY) { if (!hasSection(i) || !super.sections[i].isFull()) {
continue; continue;
} }
ChunkSection existing = getSections()[i]; ChunkSection existing = getSections(true)[i];
try { try {
final DataPaletteBlock<IBlockData> blocksExisting = existing.getBlocks(); final DataPaletteBlock<IBlockData> blocksExisting = existing.getBlocks();

View File

@ -2,6 +2,10 @@ package com.boydti.fawe.bukkit.adapter.mc1_16_1;
import com.boydti.fawe.FaweCache; 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.boydti.fawe.bukkit.adapter.mc1_16_1.nbt.LazyCompoundTag_1_16_1;
import com.google.common.base.Suppliers; import com.google.common.base.Suppliers;
import com.sk89q.jnbt.CompoundTag; 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.BiomeBase;
import net.minecraft.server.v1_16_R1.BiomeStorage; import net.minecraft.server.v1_16_R1.BiomeStorage;
import net.minecraft.server.v1_16_R1.Entity; 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.NBTTagCompound;
import net.minecraft.server.v1_16_R1.TileEntity; import net.minecraft.server.v1_16_R1.TileEntity;
import net.minecraft.server.v1_16_R1.WorldServer; import net.minecraft.server.v1_16_R1.WorldServer;
import org.bukkit.craftbukkit.v1_16_R1.block.CraftBlock; import org.bukkit.craftbukkit.v1_16_R1.block.CraftBlock;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.Range;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.UUID; 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 Map<BlockVector3, CompoundTag> tiles = new HashMap<>();
private final Set<CompoundTag> entities = new HashSet<>(); private final Set<CompoundTag> entities = new HashSet<>();
private BiomeStorage biomeStorage; 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) { protected BukkitGetBlocks_1_16_1_Copy(WorldServer world) {
super(world, X, Z); this.world = world;
} }
protected void storeTile(TileEntity tile) { protected void storeTile(TileEntity tile) {
@ -88,6 +94,16 @@ public class BukkitGetBlocks_1_16_1_Copy extends BukkitGetBlocks_1_16_1 {
return null; return null;
} }
@Override
public void setCreateCopy(boolean createCopy) {
}
@Override
public boolean isCreateCopy() {
return false;
}
protected void storeBiomes(BiomeStorage biomeStorage) { protected void storeBiomes(BiomeStorage biomeStorage) {
this.biomeStorage = new BiomeStorage(BukkitAdapter_1_16_1.getBiomeArray(biomeStorage).clone()); 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; return base != null ? BukkitAdapter.adapt(CraftBlock.biomeBaseToBiome(base)) : null;
} }
protected void storeSection(int layer) { @Override
blocks[layer] = update(layer, null).clone(); 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 @Override
@ -116,15 +142,50 @@ public class BukkitGetBlocks_1_16_1_Copy extends BukkitGetBlocks_1_16_1 {
return state.toBaseBlock(this, x, y, z); 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 @Override
public BlockState getBlock(int x, int y, int z) { public BlockState getBlock(int x, int y, int z) {
return BlockTypesCache.states[get(x, y, z)]; return BlockTypesCache.states[get(x, y, z)];
} }
@Override @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) { public char get(int x, int y, int z) {
final int layer = y >> 4; final int layer = y >> 4;
final int index = (y & 15) << 8 | z << 4 | x; final int index = (y & 15) << 8 | z << 4 | x;
return blocks[layer][index]; return blocks[layer][index];
} }
@Override
public boolean trim(boolean aggressive) {
return false;
}
} }

View File

@ -59,7 +59,7 @@ public class FAWEWorldNativeAccess_1_16 implements WorldNativeAccess<Chunk, IBlo
@Override @Override
public IBlockData toNative(BlockState state) { public IBlockData toNative(BlockState state) {
int stateId = BlockStateIdAccess.getBlockStateId(state); int stateId = adapter.ordinalToIbdID(state.getOrdinalChar());
return BlockStateIdAccess.isValidInternalId(stateId) return BlockStateIdAccess.isValidInternalId(stateId)
? Block.getByCombinedId(stateId) ? Block.getByCombinedId(stateId)
: ((CraftBlockData) BukkitAdapter.adapt(state)).getState(); : ((CraftBlockData) BukkitAdapter.adapt(state)).getState();
@ -73,7 +73,8 @@ public class FAWEWorldNativeAccess_1_16 implements WorldNativeAccess<Chunk, IBlo
@Nullable @Nullable
@Override @Override
public IBlockData setBlockState(Chunk chunk, BlockPosition position, IBlockData state) { 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 @Override
@ -167,9 +168,4 @@ public class FAWEWorldNativeAccess_1_16 implements WorldNativeAccess<Chunk, IBlo
public void onBlockStateChange(BlockPosition pos, IBlockData oldState, IBlockData newState) { public void onBlockStateChange(BlockPosition pos, IBlockData oldState, IBlockData newState) {
getWorld().a(pos, oldState, 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));
}
} }

View File

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

View File

@ -199,51 +199,49 @@ public final class BukkitAdapter_1_16_2 extends NMSAdapter {
return; return;
} }
if (playerChunk.hasBeenLoaded()) { if (playerChunk.hasBeenLoaded()) {
TaskManager.IMP.sync(() -> { ChunkCoordIntPair chunkCoordIntPair = new ChunkCoordIntPair(chunkX, chunkZ);
ChunkCoordIntPair chunkCoordIntPair = new ChunkCoordIntPair(chunkX, chunkZ); Optional<Chunk> optional = ((Either) playerChunk.a().getNow(PlayerChunk.UNLOADED_CHUNK)).left();
Optional<Chunk> optional = ((Either) playerChunk.a().getNow(PlayerChunk.UNLOADED_CHUNK)).left(); if (optional.isPresent()) {
if (optional.isPresent()) { PacketPlayOutMapChunk chunkpacket = new PacketPlayOutMapChunk(optional.get(), 65535);
PacketPlayOutMapChunk chunkpacket = new PacketPlayOutMapChunk(optional.get(), 65535); playerChunk.players.a(chunkCoordIntPair, false).forEach(p -> {
p.playerConnection.sendPacket(chunkpacket);
});
if (lighting) {
//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 -> { playerChunk.players.a(chunkCoordIntPair, false).forEach(p -> {
p.playerConnection.sendPacket(chunkpacket); p.playerConnection.sendPacket(packet);
}); });
}
} 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);
if (objects == null) {
return;
}
for (Object obj : objects.getBackingSet()) {
if (obj == null) {
continue;
}
EntityPlayer p = (EntityPlayer) obj;
Chunk chunk = nmsWorld.getChunkProvider().getChunkAtIfLoadedImmediately(chunkX, chunkZ);
if (chunk != null) {
PacketPlayOutMapChunk chunkpacket = new PacketPlayOutMapChunk(chunk, 65535);
p.playerConnection.sendPacket(chunkpacket);
if (lighting) { 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)
PacketPlayOutLightUpdate packet = new PacketPlayOutLightUpdate(chunkCoordIntPair, nmsWorld.getChunkProvider().getLightEngine(), trustEdges); boolean trustEdges = true;
playerChunk.players.a(chunkCoordIntPair, false).forEach(p -> { PacketPlayOutLightUpdate packet =
new PacketPlayOutLightUpdate(chunkCoordIntPair, nmsWorld.getChunkProvider().getLightEngine(), trustEdges);
p.playerConnection.sendPacket(packet); p.playerConnection.sendPacket(packet);
});
}
} 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);
if (objects == null) {
return null;
}
for (Object obj : objects.getBackingSet()) {
if (obj == null) {
continue;
}
EntityPlayer p = (EntityPlayer) obj;
Chunk chunk = nmsWorld.getChunkProvider().getChunkAtIfLoadedImmediately(chunkX, chunkZ);
if (chunk != null) {
PacketPlayOutMapChunk chunkpacket = new PacketPlayOutMapChunk(chunk, 65535);
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);
p.playerConnection.sendPacket(packet);
}
} }
} }
} }
return null; }
});
} }
} }

View File

@ -4,7 +4,6 @@ import com.boydti.fawe.Fawe;
import com.boydti.fawe.FaweCache; import com.boydti.fawe.FaweCache;
import com.boydti.fawe.beta.IChunkGet; import com.boydti.fawe.beta.IChunkGet;
import com.boydti.fawe.beta.IChunkSet; 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.blocks.CharGetBlocks;
import com.boydti.fawe.beta.implementation.lighting.HeightMapType; import com.boydti.fawe.beta.implementation.lighting.HeightMapType;
import com.boydti.fawe.beta.implementation.queue.QueueHandler; 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]; public NibbleArray[] skyLight = new NibbleArray[16];
private boolean createCopy = false; private boolean createCopy = false;
private BukkitGetBlocks_1_16_2_Copy copy = null; private BukkitGetBlocks_1_16_2_Copy copy = null;
private boolean forceLoadSections = true;
public BukkitGetBlocks_1_16_2(World world, int chunkX, int chunkZ) { public BukkitGetBlocks_1_16_2(World world, int chunkX, int chunkZ) {
this(((CraftWorld) world).getHandle(), chunkX, chunkZ); this(((CraftWorld) world).getHandle(), chunkX, chunkZ);
@ -319,7 +319,8 @@ public class BukkitGetBlocks_1_16_2 extends CharGetBlocks {
@Override @Override
public <T extends Future<T>> T call(IChunkSet set, Runnable finalizer) { 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 { try {
WorldServer nmsWorld = world; WorldServer nmsWorld = world;
Chunk nmsChunk = ensureLoaded(nmsWorld, chunkX, chunkZ); Chunk nmsChunk = ensureLoaded(nmsWorld, chunkX, chunkZ);
@ -360,13 +361,14 @@ public class BukkitGetBlocks_1_16_2 extends CharGetBlocks {
if (!set.hasSection(layer)) { if (!set.hasSection(layer)) {
continue; continue;
} }
if (createCopy) {
copy.storeSection(layer);
}
bitMask |= 1 << 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 newSection;
ChunkSection existingSection = sections[layer]; ChunkSection existingSection = sections[layer];
if (existingSection == null) { if (existingSection == null) {
@ -395,7 +397,7 @@ public class BukkitGetBlocks_1_16_2 extends CharGetBlocks {
this.nmsChunk = nmsChunk; this.nmsChunk = nmsChunk;
this.sections = null; this.sections = null;
this.reset(); this.reset();
} else if (existingSection != getSections()[layer]) { } else if (existingSection != getSections(false)[layer]) {
this.sections[layer] = existingSection; this.sections[layer] = existingSection;
this.reset(); this.reset();
} else if (!Arrays.equals(update(layer, new char[4096]), load(layer))) { } 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 if (!BukkitAdapter_1_16_2
.setSectionAtomic(sections, existingSection, newSection, layer)) { .setSectionAtomic(sections, existingSection, newSection, layer)) {
log.error("Failed to set chunk section:" + chunkX + "," + chunkZ + " layer: " + layer); log.error("Failed to set chunk section:" + chunkX + "," + chunkZ + " layer: " + layer);
continue;
} else { } else {
updateGet(this, nmsChunk, sections, newSection, setArr, layer); updateGet(this, nmsChunk, sections, newSection, setArr, layer);
} }
@ -475,9 +476,7 @@ public class BukkitGetBlocks_1_16_2 extends CharGetBlocks {
Set<UUID> entityRemoves = set.getEntityRemoves(); Set<UUID> entityRemoves = set.getEntityRemoves();
if (entityRemoves != null && !entityRemoves.isEmpty()) { if (entityRemoves != null && !entityRemoves.isEmpty()) {
if (syncTasks == null) { syncTasks = new Runnable[3];
syncTasks = new Runnable[3];
}
syncTasks[2] = () -> { syncTasks[2] = () -> {
final List<Entity>[] entities = nmsChunk.getEntitySlices(); final List<Entity>[] entities = nmsChunk.getEntitySlices();
@ -637,12 +636,14 @@ public class BukkitGetBlocks_1_16_2 extends CharGetBlocks {
} catch (Throwable e) { } catch (Throwable e) {
e.printStackTrace(); e.printStackTrace();
return null; return null;
} finally {
forceLoadSections = true;
} }
} }
@Override @Override
public synchronized char[] update(int layer, char[] data) { public synchronized char[] update(int layer, char[] data) {
ChunkSection section = getSections()[layer]; ChunkSection section = getSections(true)[layer];
// Section is null, return empty array // Section is null, return empty array
if (section == null) { if (section == null) {
data = new char[4096]; 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; ChunkSection[] tmp = sections;
if (tmp == null) { if (tmp == null) {
synchronized (this) { synchronized (this) {
@ -809,7 +813,7 @@ public class BukkitGetBlocks_1_16_2 extends CharGetBlocks {
@Override @Override
public boolean hasSection(int layer) { public boolean hasSection(int layer) {
return getSections()[layer] != null; return getSections(false)[layer] != null;
} }
@Override @Override
@ -822,10 +826,10 @@ public class BukkitGetBlocks_1_16_2 extends CharGetBlocks {
return super.trim(true); return super.trim(true);
} else { } else {
for (int i = 0; i < 16; i++) { for (int i = 0; i < 16; i++) {
if (!hasSection(i) || super.sections[i] == CharBlocks.EMPTY) { if (!hasSection(i) || !super.sections[i].isFull()) {
continue; continue;
} }
ChunkSection existing = getSections()[i]; ChunkSection existing = getSections(true)[i];
try { try {
final DataPaletteBlock<IBlockData> blocksExisting = existing.getBlocks(); final DataPaletteBlock<IBlockData> blocksExisting = existing.getBlocks();

View File

@ -2,6 +2,10 @@ package com.boydti.fawe.bukkit.adapter.mc1_16_2;
import com.boydti.fawe.FaweCache; 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.boydti.fawe.bukkit.adapter.mc1_16_2.nbt.LazyCompoundTag_1_16_2;
import com.google.common.base.Suppliers; import com.google.common.base.Suppliers;
import com.sk89q.jnbt.CompoundTag; 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 net.minecraft.server.v1_16_R2.WorldServer;
import org.bukkit.craftbukkit.v1_16_R2.block.CraftBlock; import org.bukkit.craftbukkit.v1_16_R2.block.CraftBlock;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.Range;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.UUID; 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 Map<BlockVector3, CompoundTag> tiles = new HashMap<>();
private final Set<CompoundTag> entities = new HashSet<>(); private final Set<CompoundTag> entities = new HashSet<>();
private BiomeStorage biomeStorage; 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) { protected BukkitGetBlocks_1_16_2_Copy(WorldServer world) {
super(world, X, Z); this.world = world;
} }
protected void storeTile(TileEntity tile) { protected void storeTile(TileEntity tile) {
@ -88,6 +95,16 @@ public class BukkitGetBlocks_1_16_2_Copy extends BukkitGetBlocks_1_16_2 {
return null; return null;
} }
@Override
public void setCreateCopy(boolean createCopy) {
}
@Override
public boolean isCreateCopy() {
return false;
}
protected void storeBiomes(BiomeStorage biomeStorage) { protected void storeBiomes(BiomeStorage biomeStorage) {
this.biomeStorage = new BiomeStorage(biomeStorage.g, BukkitAdapter_1_16_2.getBiomeArray(biomeStorage).clone()); 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; return base != null ? BukkitAdapter.adapt(CraftBlock.biomeBaseToBiome(world.r().b(IRegistry.ay), base)) : null;
} }
protected void storeSection(int layer) { @Override
blocks[layer] = update(layer, null).clone(); 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 @Override
@ -116,15 +143,50 @@ public class BukkitGetBlocks_1_16_2_Copy extends BukkitGetBlocks_1_16_2 {
return state.toBaseBlock(this, x, y, z); 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 @Override
public BlockState getBlock(int x, int y, int z) { public BlockState getBlock(int x, int y, int z) {
return BlockTypesCache.states[get(x, y, z)]; return BlockTypesCache.states[get(x, y, z)];
} }
@Override @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) { public char get(int x, int y, int z) {
final int layer = y >> 4; final int layer = y >> 4;
final int index = (y & 15) << 8 | z << 4 | x; final int index = (y & 15) << 8 | z << 4 | x;
return blocks[layer][index]; return blocks[layer][index];
} }
@Override
public boolean trim(boolean aggressive) {
return false;
}
} }

View File

@ -59,7 +59,7 @@ public class FAWEWorldNativeAccess_1_16 implements WorldNativeAccess<Chunk, IBlo
@Override @Override
public IBlockData toNative(BlockState state) { public IBlockData toNative(BlockState state) {
int stateId = BlockStateIdAccess.getBlockStateId(state); int stateId = adapter.ordinalToIbdID(state.getOrdinalChar());
return BlockStateIdAccess.isValidInternalId(stateId) return BlockStateIdAccess.isValidInternalId(stateId)
? Block.getByCombinedId(stateId) ? Block.getByCombinedId(stateId)
: ((CraftBlockData) BukkitAdapter.adapt(state)).getState(); : ((CraftBlockData) BukkitAdapter.adapt(state)).getState();
@ -73,7 +73,8 @@ public class FAWEWorldNativeAccess_1_16 implements WorldNativeAccess<Chunk, IBlo
@Nullable @Nullable
@Override @Override
public IBlockData setBlockState(Chunk chunk, BlockPosition position, IBlockData state) { 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 @Override
@ -167,9 +168,4 @@ public class FAWEWorldNativeAccess_1_16 implements WorldNativeAccess<Chunk, IBlo
public void onBlockStateChange(BlockPosition pos, IBlockData oldState, IBlockData newState) { public void onBlockStateChange(BlockPosition pos, IBlockData oldState, IBlockData newState) {
getWorld().a(pos, oldState, 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));
}
} }

View File

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

View File

@ -199,51 +199,52 @@ public final class BukkitAdapter_1_16_4 extends NMSAdapter {
return; return;
} }
if (playerChunk.hasBeenLoaded()) { if (playerChunk.hasBeenLoaded()) {
TaskManager.IMP.sync(() -> { ChunkCoordIntPair chunkCoordIntPair = new ChunkCoordIntPair(chunkX, chunkZ);
ChunkCoordIntPair chunkCoordIntPair = new ChunkCoordIntPair(chunkX, chunkZ); Optional<Chunk> optional = ((Either) playerChunk.a().getNow(PlayerChunk.UNLOADED_CHUNK)).left();
Optional<Chunk> optional = ((Either) playerChunk.a().getNow(PlayerChunk.UNLOADED_CHUNK)).left(); if (optional.isPresent()) {
if (optional.isPresent()) { PacketPlayOutMapChunk chunkpacket = new PacketPlayOutMapChunk(optional.get(), 65535);
PacketPlayOutMapChunk chunkpacket = new PacketPlayOutMapChunk(optional.get(), 65535); playerChunk.players.a(chunkCoordIntPair, false).forEach(p -> {
p.playerConnection.sendPacket(chunkpacket);
});
if (lighting) {
//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 -> { playerChunk.players.a(chunkCoordIntPair, false).forEach(p -> {
p.playerConnection.sendPacket(chunkpacket); p.playerConnection.sendPacket(packet);
}); });
}
} 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);
if (objects == null) {
return;
}
for (Object obj : objects.getBackingSet()) {
if (obj == null) {
continue;
}
EntityPlayer p = (EntityPlayer) obj;
Chunk chunk = nmsWorld.getChunkProvider().getChunkAtIfLoadedImmediately(chunkX, chunkZ);
if (chunk != null) {
PacketPlayOutMapChunk chunkpacket = new PacketPlayOutMapChunk(chunk, 65535);
p.playerConnection.sendPacket(chunkpacket);
if (lighting) { 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)
PacketPlayOutLightUpdate packet = new PacketPlayOutLightUpdate(chunkCoordIntPair, nmsWorld.getChunkProvider().getLightEngine(), trustEdges); boolean trustEdges = true;
playerChunk.players.a(chunkCoordIntPair, false).forEach(p -> { PacketPlayOutLightUpdate packet = new PacketPlayOutLightUpdate(chunkCoordIntPair,
nmsWorld.getChunkProvider().getLightEngine(), trustEdges);
p.playerConnection.sendPacket(packet); p.playerConnection.sendPacket(packet);
});
}
} 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);
if (objects == null) {
return null;
}
for (Object obj : objects.getBackingSet()) {
if (obj == null) {
continue;
}
EntityPlayer p = (EntityPlayer) obj;
Chunk chunk = nmsWorld.getChunkProvider().getChunkAtIfLoadedImmediately(chunkX, chunkZ);
if (chunk != null) {
PacketPlayOutMapChunk chunkpacket = new PacketPlayOutMapChunk(chunk, 65535);
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);
p.playerConnection.sendPacket(packet);
}
} }
} }
} }
return null; }
});
} }
} }

View File

@ -4,7 +4,6 @@ import com.boydti.fawe.Fawe;
import com.boydti.fawe.FaweCache; import com.boydti.fawe.FaweCache;
import com.boydti.fawe.beta.IChunkGet; import com.boydti.fawe.beta.IChunkGet;
import com.boydti.fawe.beta.IChunkSet; 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.blocks.CharGetBlocks;
import com.boydti.fawe.beta.implementation.lighting.HeightMapType; import com.boydti.fawe.beta.implementation.lighting.HeightMapType;
import com.boydti.fawe.beta.implementation.queue.QueueHandler; 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]; public NibbleArray[] skyLight = new NibbleArray[16];
private boolean createCopy = false; private boolean createCopy = false;
private BukkitGetBlocks_1_16_4_Copy copy = null; private BukkitGetBlocks_1_16_4_Copy copy = null;
private boolean forceLoadSections = true;
public BukkitGetBlocks_1_16_4(World world, int chunkX, int chunkZ) { public BukkitGetBlocks_1_16_4(World world, int chunkX, int chunkZ) {
this(((CraftWorld) world).getHandle(), chunkX, chunkZ); this(((CraftWorld) world).getHandle(), chunkX, chunkZ);
@ -319,7 +319,8 @@ public class BukkitGetBlocks_1_16_4 extends CharGetBlocks {
@Override @Override
public <T extends Future<T>> T call(IChunkSet set, Runnable finalizer) { 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 { try {
WorldServer nmsWorld = world; WorldServer nmsWorld = world;
Chunk nmsChunk = ensureLoaded(nmsWorld, chunkX, chunkZ); Chunk nmsChunk = ensureLoaded(nmsWorld, chunkX, chunkZ);
@ -360,13 +361,14 @@ public class BukkitGetBlocks_1_16_4 extends CharGetBlocks {
if (!set.hasSection(layer)) { if (!set.hasSection(layer)) {
continue; continue;
} }
if (createCopy) {
copy.storeSection(layer);
}
bitMask |= 1 << 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 newSection;
ChunkSection existingSection = sections[layer]; ChunkSection existingSection = sections[layer];
if (existingSection == null) { if (existingSection == null) {
@ -395,7 +397,7 @@ public class BukkitGetBlocks_1_16_4 extends CharGetBlocks {
this.nmsChunk = nmsChunk; this.nmsChunk = nmsChunk;
this.sections = null; this.sections = null;
this.reset(); this.reset();
} else if (existingSection != getSections()[layer]) { } else if (existingSection != getSections(false)[layer]) {
this.sections[layer] = existingSection; this.sections[layer] = existingSection;
this.reset(); this.reset();
} else if (!Arrays.equals(update(layer, new char[4096]), load(layer))) { } 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 if (!BukkitAdapter_1_16_4
.setSectionAtomic(sections, existingSection, newSection, layer)) { .setSectionAtomic(sections, existingSection, newSection, layer)) {
log.error("Failed to set chunk section:" + chunkX + "," + chunkZ + " layer: " + layer); log.error("Failed to set chunk section:" + chunkX + "," + chunkZ + " layer: " + layer);
continue;
} else { } else {
updateGet(this, nmsChunk, sections, newSection, setArr, layer); updateGet(this, nmsChunk, sections, newSection, setArr, layer);
} }
@ -475,9 +476,7 @@ public class BukkitGetBlocks_1_16_4 extends CharGetBlocks {
Set<UUID> entityRemoves = set.getEntityRemoves(); Set<UUID> entityRemoves = set.getEntityRemoves();
if (entityRemoves != null && !entityRemoves.isEmpty()) { if (entityRemoves != null && !entityRemoves.isEmpty()) {
if (syncTasks == null) { syncTasks = new Runnable[3];
syncTasks = new Runnable[3];
}
syncTasks[2] = () -> { syncTasks[2] = () -> {
final List<Entity>[] entities = nmsChunk.getEntitySlices(); final List<Entity>[] entities = nmsChunk.getEntitySlices();
@ -637,12 +636,14 @@ public class BukkitGetBlocks_1_16_4 extends CharGetBlocks {
} catch (Throwable e) { } catch (Throwable e) {
e.printStackTrace(); e.printStackTrace();
return null; return null;
} finally {
forceLoadSections = true;
} }
} }
@Override @Override
public synchronized char[] update(int layer, char[] data) { public synchronized char[] update(int layer, char[] data) {
ChunkSection section = getSections()[layer]; ChunkSection section = getSections(true)[layer];
// Section is null, return empty array // Section is null, return empty array
if (section == null) { if (section == null) {
data = new char[4096]; 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; ChunkSection[] tmp = sections;
if (tmp == null) { if (tmp == null) {
synchronized (this) { synchronized (this) {
@ -809,7 +813,7 @@ public class BukkitGetBlocks_1_16_4 extends CharGetBlocks {
@Override @Override
public boolean hasSection(int layer) { public boolean hasSection(int layer) {
return getSections()[layer] != null; return getSections(false)[layer] != null;
} }
@Override @Override
@ -822,10 +826,10 @@ public class BukkitGetBlocks_1_16_4 extends CharGetBlocks {
return super.trim(true); return super.trim(true);
} else { } else {
for (int i = 0; i < 16; i++) { for (int i = 0; i < 16; i++) {
if (!hasSection(i) || super.sections[i] == CharBlocks.EMPTY) { if (!hasSection(i) || !super.sections[i].isFull()) {
continue; continue;
} }
ChunkSection existing = getSections()[i]; ChunkSection existing = getSections(true)[i];
try { try {
final DataPaletteBlock<IBlockData> blocksExisting = existing.getBlocks(); final DataPaletteBlock<IBlockData> blocksExisting = existing.getBlocks();

View File

@ -2,6 +2,10 @@ package com.boydti.fawe.bukkit.adapter.mc1_16_4;
import com.boydti.fawe.FaweCache; 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.boydti.fawe.bukkit.adapter.mc1_16_4.nbt.LazyCompoundTag_1_16_4;
import com.google.common.base.Suppliers; import com.google.common.base.Suppliers;
import com.sk89q.jnbt.CompoundTag; 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 net.minecraft.server.v1_16_R3.WorldServer;
import org.bukkit.craftbukkit.v1_16_R3.block.CraftBlock; import org.bukkit.craftbukkit.v1_16_R3.block.CraftBlock;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.Range;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.UUID; 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 Map<BlockVector3, CompoundTag> tiles = new HashMap<>();
private final Set<CompoundTag> entities = new HashSet<>(); private final Set<CompoundTag> entities = new HashSet<>();
private BiomeStorage biomeStorage; 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) { protected BukkitGetBlocks_1_16_4_Copy(WorldServer world) {
super(world, X, Z); this.world = world;
} }
protected void storeTile(TileEntity tile) { protected void storeTile(TileEntity tile) {
@ -88,6 +95,16 @@ public class BukkitGetBlocks_1_16_4_Copy extends BukkitGetBlocks_1_16_4 {
return null; return null;
} }
@Override
public void setCreateCopy(boolean createCopy) {
}
@Override
public boolean isCreateCopy() {
return false;
}
protected void storeBiomes(BiomeStorage biomeStorage) { protected void storeBiomes(BiomeStorage biomeStorage) {
this.biomeStorage = new BiomeStorage(biomeStorage.g, BukkitAdapter_1_16_4.getBiomeArray(biomeStorage).clone()); 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; return base != null ? BukkitAdapter.adapt(CraftBlock.biomeBaseToBiome(world.r().b(IRegistry.ay), base)) : null;
} }
protected void storeSection(int layer) { @Override
blocks[layer] = update(layer, null).clone(); 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 @Override
@ -116,15 +143,50 @@ public class BukkitGetBlocks_1_16_4_Copy extends BukkitGetBlocks_1_16_4 {
return state.toBaseBlock(this, x, y, z); 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 @Override
public BlockState getBlock(int x, int y, int z) { public BlockState getBlock(int x, int y, int z) {
return BlockTypesCache.states[get(x, y, z)]; return BlockTypesCache.states[get(x, y, z)];
} }
@Override @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) { public char get(int x, int y, int z) {
final int layer = y >> 4; final int layer = y >> 4;
final int index = (y & 15) << 8 | z << 4 | x; final int index = (y & 15) << 8 | z << 4 | x;
return blocks[layer][index]; return blocks[layer][index];
} }
@Override
public boolean trim(boolean aggressive) {
return false;
}
} }

View File

@ -60,7 +60,7 @@ public class FAWEWorldNativeAccess_1_16 implements WorldNativeAccess<Chunk, IBlo
@Override @Override
public IBlockData toNative(BlockState state) { public IBlockData toNative(BlockState state) {
int stateId = BlockStateIdAccess.getBlockStateId(state); int stateId = adapter.ordinalToIbdID(state.getOrdinalChar());
return BlockStateIdAccess.isValidInternalId(stateId) return BlockStateIdAccess.isValidInternalId(stateId)
? Block.getByCombinedId(stateId) ? Block.getByCombinedId(stateId)
: ((CraftBlockData) BukkitAdapter.adapt(state)).getState(); : ((CraftBlockData) BukkitAdapter.adapt(state)).getState();
@ -74,7 +74,8 @@ public class FAWEWorldNativeAccess_1_16 implements WorldNativeAccess<Chunk, IBlo
@Nullable @Nullable
@Override @Override
public IBlockData setBlockState(Chunk chunk, BlockPosition position, IBlockData state) { 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 @Override
@ -168,9 +169,4 @@ public class FAWEWorldNativeAccess_1_16 implements WorldNativeAccess<Chunk, IBlo
public void onBlockStateChange(BlockPosition pos, IBlockData oldState, IBlockData newState) { public void onBlockStateChange(BlockPosition pos, IBlockData oldState, IBlockData newState) {
getWorld().a(pos, oldState, 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));
}
} }

View File

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

View File

@ -1,6 +1,5 @@
package com.boydti.fawe.bukkit.regions.plotsquared; package com.boydti.fawe.bukkit.regions.plotsquared;
import com.boydti.fawe.FaweAPI;
import com.boydti.fawe.FaweCache; import com.boydti.fawe.FaweCache;
import com.boydti.fawe.object.clipboard.ReadOnlyClipboard; import com.boydti.fawe.object.clipboard.ReadOnlyClipboard;
import com.boydti.fawe.object.io.PGZIPOutputStream; 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.boydti.fawe.util.TaskManager;
import com.plotsquared.core.PlotSquared; import com.plotsquared.core.PlotSquared;
import com.plotsquared.core.location.Location; import com.plotsquared.core.location.Location;
import com.plotsquared.core.plot.schematic.Schematic;
import com.plotsquared.core.queue.LocalBlockQueue; import com.plotsquared.core.queue.LocalBlockQueue;
import com.plotsquared.core.util.MainUtil; import com.plotsquared.core.util.MainUtil;
import com.plotsquared.core.util.SchematicHandler; import com.plotsquared.core.util.SchematicHandler;
import com.plotsquared.core.util.task.RunnableVal; import com.plotsquared.core.util.task.RunnableVal;
import com.sk89q.jnbt.CompoundTag; import com.sk89q.jnbt.CompoundTag;
import com.sk89q.jnbt.CompressedCompoundTag; import com.sk89q.jnbt.CompressedCompoundTag;
import com.sk89q.jnbt.CompressedSchematicTag; import com.sk89q.jnbt.NBTInputStream;
import com.sk89q.jnbt.NBTOutputStream; import com.sk89q.jnbt.NBTOutputStream;
import com.sk89q.jnbt.Tag; import com.sk89q.jnbt.Tag;
import com.sk89q.jnbt.fawe.CompressedSchematicTag;
import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.bukkit.BukkitAdapter; import com.sk89q.worldedit.bukkit.BukkitAdapter;
import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard; import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard;
import com.sk89q.worldedit.extent.clipboard.Clipboard; import com.sk89q.worldedit.extent.clipboard.Clipboard;
import com.sk89q.worldedit.extent.clipboard.io.BuiltInClipboardFormat; 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.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.math.BlockVector3;
import com.sk89q.worldedit.regions.CuboidRegion; import com.sk89q.worldedit.regions.CuboidRegion;
import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.World;
import net.jpountz.lz4.LZ4BlockInputStream; import net.jpountz.lz4.LZ4BlockInputStream;
import org.jetbrains.annotations.NotNull;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream; import java.io.BufferedOutputStream;
import java.io.EOFException;
import java.io.File; import java.io.File;
import java.io.FileNotFoundException; import java.io.FileNotFoundException;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
import java.net.URL; import java.net.URL;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.UUID; import java.util.UUID;
import java.util.zip.GZIPInputStream;
import static org.bukkit.Bukkit.getWorld; import static org.bukkit.Bukkit.getWorld;
@ -114,16 +123,14 @@ public class FaweSchematicHandler extends SchematicHandler {
com.plotsquared.core.util.task.TaskManager.runTask(whenDone); com.plotsquared.core.util.task.TaskManager.runTask(whenDone);
return; return;
} }
CompoundTag weTag = (CompoundTag) FaweCache.IMP.asTag(tag); final 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;
}
MainUtil.upload(uuid, file, "schem", new RunnableVal<OutputStream>() { MainUtil.upload(uuid, file, "schem", new RunnableVal<OutputStream>() {
@Override @Override
public void run(OutputStream output) { public void run(OutputStream output) {
if (weTag instanceof CompressedSchematicTag) {
Clipboard clipboard = ((CompressedSchematicTag) weTag).getSource();
BuiltInClipboardFormat.SPONGE_SCHEMATIC.write(output, clipboard);
}
try { try {
try (PGZIPOutputStream gzip = new PGZIPOutputStream(output)) { try (PGZIPOutputStream gzip = new PGZIPOutputStream(output)) {
try (NBTOutputStream nos = new NBTOutputStream(gzip)) { try (NBTOutputStream nos = new NBTOutputStream(gzip)) {
@ -137,4 +144,42 @@ public class FaweSchematicHandler extends SchematicHandler {
} }
}, whenDone); }, 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;
}
} }

View File

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

View File

@ -26,8 +26,8 @@ import org.bukkit.plugin.Plugin;
import org.bukkit.util.BoundingBox; import org.bukkit.util.BoundingBox;
import org.bukkit.util.RayTraceResult; import org.bukkit.util.RayTraceResult;
import org.bukkit.util.Vector; import org.bukkit.util.Vector;
import org.jetbrains.annotations.NotNull;
import javax.annotation.Nonnull;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
@ -70,32 +70,32 @@ public class AsyncBlock implements Block {
return world.getBlock(x, y, z).getBlockType().getInternalId(); return world.getBlock(x, y, z).getBlockType().getInternalId();
} }
@NotNull @Nonnull
@Override @Override
public AsyncBlock getRelative(int modX, int modY, int modZ) { public AsyncBlock getRelative(int modX, int modY, int modZ) {
return new AsyncBlock(world, x + modX, y + modY, z + modZ); return new AsyncBlock(world, x + modX, y + modY, z + modZ);
} }
@NotNull @Nonnull
@Override @Override
public AsyncBlock getRelative(BlockFace face) { public AsyncBlock getRelative(BlockFace face) {
return this.getRelative(face.getModX(), face.getModY(), face.getModZ()); return this.getRelative(face.getModX(), face.getModY(), face.getModZ());
} }
@NotNull @Nonnull
@Override @Override
public AsyncBlock getRelative(BlockFace face, int distance) { public AsyncBlock getRelative(BlockFace face, int distance) {
return this.getRelative(face.getModX() * distance, face.getModY() * distance, return this.getRelative(face.getModX() * distance, face.getModY() * distance,
face.getModZ() * distance); face.getModZ() * distance);
} }
@NotNull @Nonnull
@Override @Override
public Material getType() { public Material getType() {
return getBlockData().getMaterial(); return getBlockData().getMaterial();
} }
@NotNull @Nonnull
@Override @Override
public BlockData getBlockData() { public BlockData getBlockData() {
return BukkitAdapter.adapt(world.getBlock(x, y, z)); return BukkitAdapter.adapt(world.getBlock(x, y, z));
@ -141,7 +141,7 @@ public class AsyncBlock implements Block {
return (byte) 15; return (byte) 15;
} }
@NotNull @Nonnull
@Override @Override
public AsyncWorld getWorld() { public AsyncWorld getWorld() {
return world; return world;
@ -162,7 +162,7 @@ public class AsyncBlock implements Block {
return z; return z;
} }
@NotNull @Nonnull
@Override @Override
public Location getLocation() { public Location getLocation() {
return new Location(world, x, y, z); return new Location(world, x, y, z);
@ -179,14 +179,14 @@ public class AsyncBlock implements Block {
return loc; return loc;
} }
@NotNull @Nonnull
@Override @Override
public AsyncChunk getChunk() { public AsyncChunk getChunk() {
return world.getChunkAt(x >> 4, z >> 4); return world.getChunkAt(x >> 4, z >> 4);
} }
@Override @Override
public void setBlockData(@NotNull BlockData blockData) { public void setBlockData(@Nonnull BlockData blockData) {
try { try {
world.setBlock(x, y, z, BukkitAdapter.adapt(blockData)); world.setBlock(x, y, z, BukkitAdapter.adapt(blockData));
} catch (WorldEditException e) { } catch (WorldEditException e) {
@ -195,12 +195,12 @@ public class AsyncBlock implements Block {
} }
@Override @Override
public void setBlockData(@NotNull BlockData blockData, boolean b) { public void setBlockData(@Nonnull BlockData blockData, boolean b) {
setBlockData(blockData); setBlockData(blockData);
} }
@Override @Override
public void setType(@NotNull Material type) { public void setType(@Nonnull Material type) {
try { try {
world.setBlock(x, y, z, BukkitAdapter.asBlockType(type).getDefaultState()); world.setBlock(x, y, z, BukkitAdapter.asBlockType(type).getDefaultState());
} catch (WorldEditException e) { } catch (WorldEditException e) {
@ -209,12 +209,12 @@ public class AsyncBlock implements Block {
} }
@Override @Override
public void setType(@NotNull Material type, boolean applyPhysics) { public void setType(@Nonnull Material type, boolean applyPhysics) {
setType(type); setType(type);
} }
@Override @Override
public BlockFace getFace(@NotNull Block block) { public BlockFace getFace(@Nonnull Block block) {
BlockFace[] directions = BlockFace.values(); BlockFace[] directions = BlockFace.values();
for (BlockFace face : directions) { for (BlockFace face : directions) {
if (this.getX() + face.getModX() == block.getX() if (this.getX() + face.getModX() == block.getX()
@ -226,7 +226,7 @@ public class AsyncBlock implements Block {
return null; return null;
} }
@NotNull @Nonnull
@Override @Override
public AsyncBlockState getState() { public AsyncBlockState getState() {
BaseBlock state = world.getFullBlock(x, y, z); BaseBlock state = world.getFullBlock(x, y, z);
@ -250,19 +250,19 @@ public class AsyncBlock implements Block {
} }
@Override @Override
@NotNull @Nonnull
public AsyncBlockState getState(boolean useSnapshot) { public AsyncBlockState getState(boolean useSnapshot) {
return getState(); return getState();
} }
@NotNull @Nonnull
@Override @Override
public Biome getBiome() { public Biome getBiome() {
return world.getAdapter().adapt(world.getBiomeType(x, y, z)); return world.getAdapter().adapt(world.getBiomeType(x, y, z));
} }
@Override @Override
public void setBiome(@NotNull Biome bio) { public void setBiome(@Nonnull Biome bio) {
BiomeType biome = world.getAdapter().adapt(bio); BiomeType biome = world.getAdapter().adapt(bio);
world.setBiome(x, 0, z, biome); world.setBiome(x, 0, z, biome);
} }
@ -278,17 +278,17 @@ public class AsyncBlock implements Block {
} }
@Override @Override
public boolean isBlockFacePowered(@NotNull BlockFace face) { public boolean isBlockFacePowered(@Nonnull BlockFace face) {
return false; return false;
} }
@Override @Override
public boolean isBlockFaceIndirectlyPowered(@NotNull BlockFace face) { public boolean isBlockFaceIndirectlyPowered(@Nonnull BlockFace face) {
return false; return false;
} }
@Override @Override
public int getBlockPower(@NotNull BlockFace face) { public int getBlockPower(@Nonnull BlockFace face) {
return 0; return 0;
} }
@ -314,6 +314,21 @@ public class AsyncBlock implements Block {
return world.getBlock(x, y, z).getMaterial().isLiquid(); 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 @Override
public double getTemperature() { public double getTemperature() {
return this.getWorld().getTemperature(this.getX(), this.getZ()); 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()); return this.getWorld().getHumidity(this.getX(), this.getZ());
} }
@NotNull @Nonnull
@Override @Override
public PistonMoveReaction getPistonMoveReaction() { public PistonMoveReaction getPistonMoveReaction() {
return PistonMoveReaction.IGNORE; return PistonMoveReaction.IGNORE;
@ -341,23 +356,23 @@ public class AsyncBlock implements Block {
} }
@Override @Override
public boolean breakNaturally(@NotNull ItemStack tool) { public boolean breakNaturally(@Nonnull ItemStack tool) {
return TaskManager.IMP.sync(() -> getUnsafeBlock().breakNaturally(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)); return TaskManager.IMP.sync(() -> getUnsafeBlock().breakNaturally(tool));
} }
@NotNull @Nonnull
@Override @Override
public Collection<ItemStack> getDrops() { public Collection<ItemStack> getDrops() {
return TaskManager.IMP.sync(() -> getUnsafeBlock().getDrops()); return TaskManager.IMP.sync(() -> getUnsafeBlock().getDrops());
} }
@NotNull @Nonnull
@Override @Override
public Collection<ItemStack> getDrops(@NotNull ItemStack tool) { public Collection<ItemStack> getDrops(@Nonnull ItemStack tool) {
return TaskManager.IMP.sync(() -> getUnsafeBlock().getDrops(tool)); return TaskManager.IMP.sync(() -> getUnsafeBlock().getDrops(tool));
} }
@ -366,23 +381,23 @@ public class AsyncBlock implements Block {
} }
@Override @Override
public void setMetadata(@NotNull String metadataKey, @NotNull MetadataValue newMetadataValue) { public void setMetadata(@Nonnull String metadataKey, @Nonnull MetadataValue newMetadataValue) {
this.getUnsafeBlock().setMetadata(metadataKey, newMetadataValue); this.getUnsafeBlock().setMetadata(metadataKey, newMetadataValue);
} }
@NotNull @Nonnull
@Override @Override
public List<MetadataValue> getMetadata(@NotNull String metadataKey) { public List<MetadataValue> getMetadata(@Nonnull String metadataKey) {
return this.getUnsafeBlock().getMetadata(metadataKey); return this.getUnsafeBlock().getMetadata(metadataKey);
} }
@Override @Override
public boolean hasMetadata(@NotNull String metadataKey) { public boolean hasMetadata(@Nonnull String metadataKey) {
return this.getUnsafeBlock().hasMetadata(metadataKey); return this.getUnsafeBlock().hasMetadata(metadataKey);
} }
@Override @Override
public void removeMetadata(@NotNull String metadataKey, @NotNull Plugin owningPlugin) { public void removeMetadata(@Nonnull String metadataKey, @Nonnull Plugin owningPlugin) {
this.getUnsafeBlock().removeMetadata(metadataKey, owningPlugin); this.getUnsafeBlock().removeMetadata(metadataKey, owningPlugin);
} }
@ -392,12 +407,12 @@ public class AsyncBlock implements Block {
} }
@Override @Override
public RayTraceResult rayTrace(@NotNull Location arg0, @NotNull Vector arg1, double arg2, public RayTraceResult rayTrace(@Nonnull Location arg0, @Nonnull Vector arg1, double arg2,
@NotNull FluidCollisionMode arg3) { @Nonnull FluidCollisionMode arg3) {
return this.getUnsafeBlock().rayTrace(arg0, arg1, arg2, 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"); 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"); throw new UnsupportedOperationException("FAWE does not support this yet");
} }
@NotNull @Nonnull
@Override @Override
public float getDestroySpeed(@NotNull ItemStack itemStack) { public float getDestroySpeed(@Nonnull ItemStack itemStack) {
throw new UnsupportedOperationException("FAWE does not support this yet"); throw new UnsupportedOperationException("FAWE does not support this yet");
} }
@NotNull @Nonnull
@Override @Override
public BoundingBox getBoundingBox() { public BoundingBox getBoundingBox() {
return this.getUnsafeBlock().getBoundingBox(); return this.getUnsafeBlock().getBoundingBox();
} }
@Override @Override
@NotNull @Nonnull
public BlockSoundGroup getSoundGroup() { public BlockSoundGroup getSoundGroup() {
return TaskManager.IMP.sync(() -> getUnsafeBlock().getSoundGroup()); return TaskManager.IMP.sync(() -> getUnsafeBlock().getSoundGroup());
} }
@Override
@Nonnull
public boolean isSolid() {
return this.getType().isSolid();
}
} }

View File

@ -1,6 +1,7 @@
package com.boydti.fawe.bukkit.wrapper; package com.boydti.fawe.bukkit.wrapper;
import com.sk89q.jnbt.CompoundTag; import com.sk89q.jnbt.CompoundTag;
import com.sk89q.jnbt.Tag;
import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.bukkit.BukkitAdapter; import com.sk89q.worldedit.bukkit.BukkitAdapter;
import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BaseBlock;
@ -16,8 +17,12 @@ import org.bukkit.material.MaterialData;
import org.bukkit.metadata.MetadataValue; import org.bukkit.metadata.MetadataValue;
import org.bukkit.plugin.Plugin; import org.bukkit.plugin.Plugin;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Optional;
public class AsyncBlockState implements BlockState { public class AsyncBlockState implements BlockState {
@ -25,10 +30,6 @@ public class AsyncBlockState implements BlockState {
private BlockData blockData; private BlockData blockData;
private final AsyncBlock block; 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) { public AsyncBlockState(AsyncBlock block, BaseBlock state) {
this.state = state; this.state = state;
this.block = block; this.block = block;
@ -112,11 +113,11 @@ public class AsyncBlockState implements BlockState {
@Override @Override
public void setBlockData(BlockData blockData) { public void setBlockData(BlockData blockData) {
this.blockData = blockData; this.blockData = blockData;
CompoundTag nbt = state.getNbtData(); CompoundTag nbt = this.getNbtData();
BlockType oldType = state.getBlockType(); BlockType oldType = state.getBlockType();
com.sk89q.worldedit.world.block.BlockState newState = BukkitAdapter.adapt(blockData); com.sk89q.worldedit.world.block.BlockState newState = BukkitAdapter.adapt(blockData);
if (nbt != null && newState.getBlockType() == oldType) { if (nbt != null && newState.getBlockType() == oldType) {
state = newState.toBaseBlock(nbt); this.setNbtData(nbt);
} else { } else {
state = newState.toBaseBlock(); 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(); 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); 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 @Override
public byte getRawData() { public byte getRawData() {
return (byte) (state.getInternalId() >> BlockTypesCache.BIT_OFFSET); return (byte) (state.getInternalId() >> BlockTypesCache.BIT_OFFSET);
@ -163,7 +197,7 @@ public class AsyncBlockState implements BlockState {
public void setRawData(byte data) { public void setRawData(byte data) {
int combinedId = getTypeId() + (data << BlockTypesCache.BIT_OFFSET); int combinedId = getTypeId() + (data << BlockTypesCache.BIT_OFFSET);
state = com.sk89q.worldedit.world.block.BlockState.getFromInternalId(combinedId) state = com.sk89q.worldedit.world.block.BlockState.getFromInternalId(combinedId)
.toBaseBlock(state.getNbtData()); .toBaseBlock(this.getNbtData());
this.blockData = BukkitAdapter.adapt(state); this.blockData = BukkitAdapter.adapt(state);
} }

View File

@ -6,6 +6,7 @@ import com.boydti.fawe.util.TaskManager;
import org.bukkit.Chunk; import org.bukkit.Chunk;
import org.bukkit.ChunkSnapshot; import org.bukkit.ChunkSnapshot;
import org.bukkit.World; import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.block.BlockState; import org.bukkit.block.BlockState;
import org.bukkit.block.data.BlockData; import org.bukkit.block.data.BlockData;
import org.bukkit.entity.Entity; import org.bukkit.entity.Entity;
@ -14,6 +15,8 @@ import org.bukkit.plugin.Plugin;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import java.util.Collection; import java.util.Collection;
import java.util.Collections;
import java.util.function.Predicate;
import java.util.function.Supplier; import java.util.function.Supplier;
public class AsyncChunk implements Chunk { public class AsyncChunk implements Chunk {
@ -120,6 +123,16 @@ public class AsyncChunk implements Chunk {
return TaskManager.IMP.sync(() -> world.getChunkAt(x, z).getTileEntities(useSnapshot)); 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 @Override
public boolean isLoaded() { public boolean isLoaded() {
return world.isChunkLoaded(x, z); return world.isChunkLoaded(x, z);

View File

@ -16,17 +16,24 @@ import java.util.HashSet;
import java.util.Map; import java.util.Map;
import java.util.Objects; import java.util.Objects;
import java.util.Set; import java.util.Set;
import java.util.function.Consumer;
import java.util.function.Supplier;
public final class AsyncDataContainer implements PersistentDataContainer { public final class AsyncDataContainer implements PersistentDataContainer {
private final CompoundTag root;
public AsyncDataContainer(CompoundTag root) { private final Supplier<CompoundTag> supplier;
this.root = root; 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() { private CompoundTag root() {
CompoundTag value = (CompoundTag) root.getValue().get("PublicBukkitValues"); return (CompoundTag) supplier.get().getValue().get("PublicBukkitValues");
return value;
} }
private Map<String, Tag> get() { private Map<String, Tag> get() {
@ -40,8 +47,9 @@ public final class AsyncDataContainer implements PersistentDataContainer {
if (!create) { if (!create) {
return Collections.emptyMap(); 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<>())); map.put("PublicBukkitValues", new CompoundTag(raw = new HashMap<>()));
this.consumer.accept(new CompoundTag(map));
} else { } else {
raw = tag.getValue(); 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(key, "The provided key for the custom value was null");
Validate.notNull(type, "The provided type 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"); 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) { 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"); Validate.notNull(type, "The provided type for the custom value was null");
Tag value = get(false).get(key.toString()); Tag value = get(false).get(key.toString());
if (value == null) { if (value == null) {
return type == null; return false;
} }
return type.getPrimitiveType() == value.getValue().getClass(); return type.getPrimitiveType() == value.getValue().getClass();
} }
@ -93,7 +108,14 @@ public final class AsyncDataContainer implements PersistentDataContainer {
public void remove(NamespacedKey key) { public void remove(NamespacedKey key) {
Validate.notNull(key, "The provided key for the custom value was null"); 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() { public boolean isEmpty() {

View File

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

View File

@ -19,7 +19,6 @@
package com.sk89q.worldedit.bukkit; package com.sk89q.worldedit.bukkit;
import com.boydti.fawe.Fawe; import com.boydti.fawe.Fawe;
import com.boydti.fawe.bukkit.FaweBukkit; import com.boydti.fawe.bukkit.FaweBukkit;
import com.google.common.base.Joiner; 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 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); private static final Logger log = LoggerFactory.getLogger(WorldEditPlugin.class);
public static final String CUI_PLUGIN_CHANNEL = "worldedit:cui"; public static final String CUI_PLUGIN_CHANNEL = "worldedit:cui";
private static WorldEditPlugin INSTANCE; private static WorldEditPlugin INSTANCE;

View File

@ -19,7 +19,6 @@
package com.sk89q.worldedit.bukkit.adapter.impl; package com.sk89q.worldedit.bukkit.adapter.impl;
import com.boydti.fawe.Fawe;
import com.boydti.fawe.FaweCache; import com.boydti.fawe.FaweCache;
import com.boydti.fawe.beta.IChunkGet; import com.boydti.fawe.beta.IChunkGet;
import com.boydti.fawe.beta.implementation.packet.ChunkPacket; 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.craftbukkit.v1_15_R1.inventory.CraftItemStack;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import javax.annotation.Nullable;
import java.lang.ref.WeakReference; import java.lang.ref.WeakReference;
import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.OptionalInt; import java.util.OptionalInt;
import java.util.Set; import java.util.Set;
import java.util.function.Supplier; import java.util.function.Supplier;
import java.util.stream.Stream; import java.util.stream.Stream;
import javax.annotation.Nullable;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.slf4j.LoggerFactory.getLogger; import static org.slf4j.LoggerFactory.getLogger;
public final class FAWE_Spigot_v1_15_R2 extends CachedBukkitAdapter implements IDelegateBukkitImplAdapter<NBTBase> { public final class FAWE_Spigot_v1_15_R2 extends CachedBukkitAdapter implements IDelegateBukkitImplAdapter<NBTBase> {
private final Spigot_v1_15_R2 parent; private final Spigot_v1_15_R2 parent;
private char[] ibdToStateOrdinal; private char[] ibdToStateOrdinal;
private int[] ordinalToIbdID;
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
// Code that may break between versions of Minecraft // 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) { if (ibdToStateOrdinal != null && ibdToStateOrdinal[1] != 0) {
return false; 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++) { for (int i = 0; i < ibdToStateOrdinal.length; i++) {
BlockState state = BlockTypesCache.states[i]; BlockState state = BlockTypesCache.states[i];
BlockMaterial_1_15_2 material = (BlockMaterial_1_15_2) state.getMaterial(); BlockMaterial_1_15_2 material = (BlockMaterial_1_15_2) state.getMaterial();
int id = Block.REGISTRY_ID.getId(material.getState()); int id = Block.REGISTRY_ID.getId(material.getState());
ibdToStateOrdinal[id] = state.getOrdinalChar(); char ordinal = state.getOrdinalChar();
ibdToStateOrdinal[id] = ordinal;
ordinalToIbdID[ordinal] = id;
} }
return true; return true;
} }
@ -267,13 +270,13 @@ public final class FAWE_Spigot_v1_15_R2 extends CachedBukkitAdapter implements I
if (id != null) { if (id != null) {
EntityType type = com.sk89q.worldedit.world.entity.EntityTypes.get(id); EntityType type = com.sk89q.worldedit.world.entity.EntityTypes.get(id);
Supplier<CompoundTag> saveTag = () -> { Supplier<CompoundTag> saveTag = () -> {
NBTTagCompound tag = new NBTTagCompound(); final NBTTagCompound minecraftTag = new NBTTagCompound();
readEntityIntoTag(mcEntity, tag); readEntityIntoTag(mcEntity, minecraftTag);
//add Id for AbstractChangeSet to work //add Id for AbstractChangeSet to work
CompoundTag natve = (CompoundTag) toNative(tag); final CompoundTag tag = (CompoundTag) toNative(minecraftTag);
natve.getValue().put("Id", new StringTag(id)); final Map<String, Tag> tags = new HashMap<>(tag.getValue());
return natve; tags.put("Id", new StringTag(id));
return new CompoundTag(tags);
}; };
return new LazyBaseEntity(type, saveTag); return new LazyBaseEntity(type, saveTag);
} else { } 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 @Override
public <B extends BlockStateHolder<B>> BlockData adapt(B state) { public <B extends BlockStateHolder<B>> BlockData adapt(B state) {

View File

@ -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.craftbukkit.v1_16_R1.inventory.CraftItemStack;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import javax.annotation.Nullable;
import java.lang.ref.WeakReference; import java.lang.ref.WeakReference;
import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.OptionalInt; import java.util.OptionalInt;
import java.util.Set; import java.util.Set;
import java.util.function.Supplier; import java.util.function.Supplier;
import java.util.stream.Stream; import java.util.stream.Stream;
import javax.annotation.Nullable;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.slf4j.LoggerFactory.getLogger; import static org.slf4j.LoggerFactory.getLogger;
public final class FAWE_Spigot_v1_16_R1 extends CachedBukkitAdapter implements IDelegateBukkitImplAdapter<NBTBase> { public final class FAWE_Spigot_v1_16_R1 extends CachedBukkitAdapter implements IDelegateBukkitImplAdapter<NBTBase> {
private final Spigot_v1_16_R1 parent; private final Spigot_v1_16_R1 parent;
private char[] ibdToStateOrdinal; private char[] ibdToStateOrdinal;
private int[] ordinalToIbdID;
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
// Code that may break between versions of Minecraft // 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) { if (ibdToStateOrdinal != null && ibdToStateOrdinal[1] != 0) {
return false; 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++) { for (int i = 0; i < ibdToStateOrdinal.length; i++) {
BlockState state = BlockTypesCache.states[i]; BlockState state = BlockTypesCache.states[i];
BlockMaterial_1_16_1 material = (BlockMaterial_1_16_1) state.getMaterial(); BlockMaterial_1_16_1 material = (BlockMaterial_1_16_1) state.getMaterial();
int id = Block.REGISTRY_ID.getId(material.getState()); int id = Block.REGISTRY_ID.getId(material.getState());
ibdToStateOrdinal[id] = state.getOrdinalChar(); char ordinal = state.getOrdinalChar();
ibdToStateOrdinal[id] = ordinal;
ordinalToIbdID[ordinal] = id;
} }
return true; return true;
} }
@ -266,13 +270,13 @@ public final class FAWE_Spigot_v1_16_R1 extends CachedBukkitAdapter implements I
if (id != null) { if (id != null) {
EntityType type = com.sk89q.worldedit.world.entity.EntityTypes.get(id); EntityType type = com.sk89q.worldedit.world.entity.EntityTypes.get(id);
Supplier<CompoundTag> saveTag = () -> { Supplier<CompoundTag> saveTag = () -> {
NBTTagCompound tag = new NBTTagCompound(); final NBTTagCompound minecraftTag = new NBTTagCompound();
readEntityIntoTag(mcEntity, tag); readEntityIntoTag(mcEntity, minecraftTag);
//add Id for AbstractChangeSet to work //add Id for AbstractChangeSet to work
CompoundTag natve = (CompoundTag) toNative(tag); final CompoundTag tag = (CompoundTag) toNative(minecraftTag);
natve.getValue().put("Id", new StringTag(id)); final Map<String, Tag> tags = new HashMap<>(tag.getValue());
return natve; tags.put("Id", new StringTag(id));
return new CompoundTag(tags);
}; };
return new LazyBaseEntity(type, saveTag); return new LazyBaseEntity(type, saveTag);
} else { } 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 @Override
public <B extends BlockStateHolder<B>> BlockData adapt(B state) { public <B extends BlockStateHolder<B>> BlockData adapt(B state) {
BlockMaterial_1_16_1 material = (BlockMaterial_1_16_1) state.getMaterial(); BlockMaterial_1_16_1 material = (BlockMaterial_1_16_1) state.getMaterial();

View File

@ -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.entity.CraftPlayer;
import org.bukkit.craftbukkit.v1_16_R2.inventory.CraftItemStack; import org.bukkit.craftbukkit.v1_16_R2.inventory.CraftItemStack;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import javax.annotation.Nullable;
import java.lang.ref.WeakReference; import java.lang.ref.WeakReference;
import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.OptionalInt; import java.util.OptionalInt;
import java.util.Set; import java.util.Set;
import java.util.function.Supplier; import java.util.function.Supplier;
import java.util.stream.Stream; import java.util.stream.Stream;
import javax.annotation.Nullable;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.slf4j.LoggerFactory.getLogger; import static org.slf4j.LoggerFactory.getLogger;
public final class FAWE_Spigot_v1_16_R2 extends CachedBukkitAdapter implements IDelegateBukkitImplAdapter<NBTBase> { public final class FAWE_Spigot_v1_16_R2 extends CachedBukkitAdapter implements IDelegateBukkitImplAdapter<NBTBase> {
private final Spigot_v1_16_R2 parent; private final Spigot_v1_16_R2 parent;
private char[] ibdToStateOrdinal; private char[] ibdToStateOrdinal;
private int[] ordinalToIbdID;
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
// Code that may break between versions of Minecraft // 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) { if (ibdToStateOrdinal != null && ibdToStateOrdinal[1] != 0) {
return false; 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++) { for (int i = 0; i < ibdToStateOrdinal.length; i++) {
BlockState state = BlockTypesCache.states[i]; BlockState state = BlockTypesCache.states[i];
BlockMaterial_1_16_2 material = (BlockMaterial_1_16_2) state.getMaterial(); BlockMaterial_1_16_2 material = (BlockMaterial_1_16_2) state.getMaterial();
int id = Block.REGISTRY_ID.getId(material.getState()); int id = Block.REGISTRY_ID.getId(material.getState());
ibdToStateOrdinal[id] = state.getOrdinalChar(); char ordinal = state.getOrdinalChar();
ibdToStateOrdinal[id] = ordinal;
ordinalToIbdID[ordinal] = id;
} }
return true; return true;
} }
@ -267,13 +272,13 @@ public final class FAWE_Spigot_v1_16_R2 extends CachedBukkitAdapter implements I
if (id != null) { if (id != null) {
EntityType type = com.sk89q.worldedit.world.entity.EntityTypes.get(id); EntityType type = com.sk89q.worldedit.world.entity.EntityTypes.get(id);
Supplier<CompoundTag> saveTag = () -> { Supplier<CompoundTag> saveTag = () -> {
NBTTagCompound tag = new NBTTagCompound(); final NBTTagCompound minecraftTag = new NBTTagCompound();
readEntityIntoTag(mcEntity, tag); readEntityIntoTag(mcEntity, minecraftTag);
//add Id for AbstractChangeSet to work //add Id for AbstractChangeSet to work
CompoundTag natve = (CompoundTag) toNative(tag); final CompoundTag tag = (CompoundTag) toNative(minecraftTag);
natve.getValue().put("Id", new StringTag(id)); final Map<String, Tag> tags = new HashMap<>(tag.getValue());
return natve; tags.put("Id", new StringTag(id));
return new CompoundTag(tags);
}; };
return new LazyBaseEntity(type, saveTag); return new LazyBaseEntity(type, saveTag);
} else { } 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 @Override
public <B extends BlockStateHolder<B>> BlockData adapt(B state) { public <B extends BlockStateHolder<B>> BlockData adapt(B state) {

View File

@ -19,7 +19,6 @@
package com.sk89q.worldedit.bukkit.adapter.impl; package com.sk89q.worldedit.bukkit.adapter.impl;
import com.bekvon.bukkit.residence.commands.material;
import com.boydti.fawe.FaweCache; import com.boydti.fawe.FaweCache;
import com.boydti.fawe.beta.IChunkGet; import com.boydti.fawe.beta.IChunkGet;
import com.boydti.fawe.beta.implementation.packet.ChunkPacket; import com.boydti.fawe.beta.implementation.packet.ChunkPacket;
@ -96,6 +95,7 @@ import org.bukkit.entity.Player;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.lang.ref.WeakReference; import java.lang.ref.WeakReference;
import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.OptionalInt; import java.util.OptionalInt;
import java.util.Set; 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> { public final class FAWE_Spigot_v1_16_R3 extends CachedBukkitAdapter implements IDelegateBukkitImplAdapter<NBTBase> {
private final Spigot_v1_16_R3 parent; private final Spigot_v1_16_R3 parent;
private char[] ibdToStateOrdinal; private char[] ibdToStateOrdinal;
private int[] ordinalToIbdID;
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
// Code that may break between versions of Minecraft // 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) { if (ibdToStateOrdinal != null && ibdToStateOrdinal[1] != 0) {
return false; 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++) { for (int i = 0; i < ibdToStateOrdinal.length; i++) {
BlockState state = BlockTypesCache.states[i]; BlockState state = BlockTypesCache.states[i];
BlockMaterial_1_16_4 material = (BlockMaterial_1_16_4) state.getMaterial(); BlockMaterial_1_16_4 material = (BlockMaterial_1_16_4) state.getMaterial();
int id = Block.REGISTRY_ID.getId(material.getState()); int id = Block.REGISTRY_ID.getId(material.getState());
ibdToStateOrdinal[id] = state.getOrdinalChar(); char ordinal = state.getOrdinalChar();
ibdToStateOrdinal[id] = ordinal;
ordinalToIbdID[ordinal] = id;
} }
return true; return true;
} }
@ -268,13 +272,13 @@ public final class FAWE_Spigot_v1_16_R3 extends CachedBukkitAdapter implements I
if (id != null) { if (id != null) {
EntityType type = com.sk89q.worldedit.world.entity.EntityTypes.get(id); EntityType type = com.sk89q.worldedit.world.entity.EntityTypes.get(id);
Supplier<CompoundTag> saveTag = () -> { Supplier<CompoundTag> saveTag = () -> {
NBTTagCompound tag = new NBTTagCompound(); final NBTTagCompound minecraftTag = new NBTTagCompound();
readEntityIntoTag(mcEntity, tag); readEntityIntoTag(mcEntity, minecraftTag);
//add Id for AbstractChangeSet to work //add Id for AbstractChangeSet to work
CompoundTag natve = (CompoundTag) toNative(tag); final CompoundTag tag = (CompoundTag) toNative(minecraftTag);
natve.getValue().put("Id", new StringTag(id)); final Map<String, Tag> tags = new HashMap<>(tag.getValue());
return natve; tags.put("Id", new StringTag(id));
return new CompoundTag(tags);
}; };
return new LazyBaseEntity(type, saveTag); return new LazyBaseEntity(type, saveTag);
} else { } 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 @Override
public <B extends BlockStateHolder<B>> BlockData adapt(B state) { public <B extends BlockStateHolder<B>> BlockData adapt(B state) {
BlockMaterial_1_16_4 material = (BlockMaterial_1_16_4) state.getMaterial(); BlockMaterial_1_16_4 material = (BlockMaterial_1_16_4) state.getMaterial();

View File

@ -28,14 +28,14 @@ configurations.all {
dependencies { dependencies {
"api"(project(":worldedit-libs:core")) "api"(project(":worldedit-libs:core"))
"implementation"("de.schlichtherle:truezip:6.8.3") "implementation"("de.schlichtherle:truezip:6.8.4")
"implementation"("net.java.truevfs:truevfs-profile-default_2.13:0.12.1") "implementation"("net.java.truevfs:truevfs-profile-default_2.13:0.12.2")
"implementation"("org.mozilla:rhino-runtime:1.7.12") "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.guava:guava:${Versions.GUAVA}")
"implementation"("com.google.code.findbugs:jsr305:3.0.2") "implementation"("com.google.code.findbugs:jsr305:3.0.2")
"implementation"("com.google.code.gson:gson:${Versions.GSON}") "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}") "implementation"("it.unimi.dsi:fastutil:${Versions.FAST_UTIL}")
val antlrVersion = "4.7.2" val antlrVersion = "4.7.2"
@ -51,14 +51,15 @@ dependencies {
"annotationProcessor"("com.google.auto.value:auto-value:${Versions.AUTO_VALUE}") "annotationProcessor"("com.google.auto.value:auto-value:${Versions.AUTO_VALUE}")
"testImplementation"("ch.qos.logback:logback-core:${Versions.LOGBACK}") "testImplementation"("ch.qos.logback:logback-core:${Versions.LOGBACK}")
"testImplementation"("ch.qos.logback:logback-classic:${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") "compileOnly"("net.fabiozumbi12:redprotect:1.9.6")
"compile"("com.github.intellectualsites.plotsquared:PlotSquared-API:latest") { "compile"("com.github.intellectualsites.plotsquared:PlotSquared-API:latest") {
isTransitive = false isTransitive = false
} }
"compile"("com.plotsquared:PlotSquared-Core:5.12.2") { "compile"("com.plotsquared:PlotSquared-Core:5.13.3") {
isTransitive = false isTransitive = false
} }
"api"("com.intellectualsites.paster:Paster:1.0.1-SNAPSHOT")
} }
tasks.named<Test>("test") { tasks.named<Test>("test") {
@ -109,7 +110,7 @@ tasks.named<Copy>("processResources") {
} }
tasks.named<ShadowJar>("shadowJar") { tasks.named<ShadowJar>("shadowJar") {
dependencies { dependencies {
include(dependency("com.github.luben:zstd-jni:1.4.3-1")) include(dependency("com.github.luben:zstd-jni:1.4.8-1"))
} }
} }

View File

@ -235,8 +235,8 @@ public class Fawe {
// Setting up config.yml // Setting up config.yml
File file = new File(this.implementation.getDirectory(), "config.yml"); File file = new File(this.implementation.getDirectory(), "config.yml");
Settings.IMP.PLATFORM = implementation.getPlatform().replace("\"", ""); 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))) { BufferedReader br = new BufferedReader(new InputStreamReader(stream))) {
String versionString = br.readLine(); String versionString = br.readLine();
String commitString = br.readLine(); String commitString = br.readLine();
String dateString = br.readLine(); String dateString = br.readLine();

View File

@ -9,39 +9,57 @@ import org.jetbrains.annotations.Range;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.util.concurrent.locks.ReentrantLock;
public abstract class CharBlocks implements IBlocks { public abstract class CharBlocks implements IBlocks {
public static final Logger logger = LoggerFactory.getLogger(CharBlocks.class); public static final Logger logger = LoggerFactory.getLogger(CharBlocks.class);
public static final Section FULL = new Section() { protected static final Section FULL = new Section() {
@Override @Override
public final char[] get(CharBlocks blocks, int layer) { public final char[] get(CharBlocks blocks, int layer) {
return blocks.blocks[layer]; return blocks.blocks[layer];
} }
};
public static final Section EMPTY = new Section() {
@Override @Override
public final synchronized char[] get(CharBlocks blocks, int layer) { public final boolean isFull() {
char[] arr = blocks.blocks[layer]; return true;
if (arr == null) { }
arr = blocks.blocks[layer] = blocks.update(layer, null); };
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) { if (arr == null) {
throw new IllegalStateException("Array cannot be null: " + blocks.getClass()); arr = blocks.blocks[layer] = blocks.update(layer, null);
if (arr == null) {
throw new IllegalStateException("Array cannot be null: " + blocks.getClass());
}
} else {
blocks.blocks[layer] = blocks.update(layer, arr);
if (blocks.blocks[layer] == null) {
throw new IllegalStateException("Array cannot be null (update): " + blocks.getClass());
}
} }
} else { if (blocks.blocks[layer] != null) {
blocks.blocks[layer] = blocks.update(layer, arr); blocks.sections[layer] = FULL;
if (blocks.blocks[layer] == null) {
throw new IllegalStateException("Array cannot be null (update): " + blocks.getClass());
} }
return arr;
} finally {
blocks.loadLock.unlock();
} }
if (blocks.blocks[layer] != null) { }
blocks.sections[layer] = FULL;
} @Override
return arr; public final boolean isFull() {
return false;
} }
}; };
public final char[][] blocks; public final char[][] blocks;
public final Section[] sections; public final Section[] sections;
private final ReentrantLock loadLock = new ReentrantLock ();
public CharBlocks() { public CharBlocks() {
blocks = new char[16][]; blocks = new char[16][];
@ -55,7 +73,7 @@ public abstract class CharBlocks implements IBlocks {
public boolean trim(boolean aggressive) { public boolean trim(boolean aggressive) {
boolean result = true; boolean result = true;
for (int i = 0; i < 16; i++) { for (int i = 0; i < 16; i++) {
if (sections[i] == EMPTY && blocks[i] != null) { if (!sections[i].isFull() && blocks[i] != null) {
blocks[i] = null; blocks[i] = null;
} else { } else {
result = false; result = false;
@ -67,7 +85,7 @@ public abstract class CharBlocks implements IBlocks {
@Override @Override
public boolean trim(boolean aggressive, int layer) { public boolean trim(boolean aggressive, int layer) {
boolean result = true; boolean result = true;
if (sections[layer] == EMPTY && blocks[layer] != null) { if (!sections[layer].isFull() && blocks[layer] != null) {
blocks[layer] = null; blocks[layer] = null;
} else { } else {
result = false; result = false;
@ -99,7 +117,7 @@ public abstract class CharBlocks implements IBlocks {
@Override @Override
public boolean hasSection(@Range(from = 0, to = 15) int layer) { public boolean hasSection(@Range(from = 0, to = 15) int layer) {
return sections[layer] == FULL; return sections[layer].isFull();
} }
@Override @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 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) { public final char get(CharBlocks blocks, @Range(from = 0, to = 15) int layer, int index) {
return get(blocks, layer)[index]; return get(blocks, layer)[index];
} }

View File

@ -140,7 +140,7 @@ public class ParallelQueueExtent extends PassthroughExtent implements IQueueWrap
return return
// Apply a filter over a region // Apply a filter over a region
apply(region, searchMask 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 .getParent() // Get the counter of this mask
.getTotal(); // Get the total from the counter .getTotal(); // Get the total from the counter
} }

View File

@ -200,7 +200,7 @@ public class StreamDelegate {
Object raw = is.readTagPayloadRaw(type, depth); Object raw = is.readTagPayloadRaw(type, depth);
valueReader.apply(0, raw); valueReader.apply(0, raw);
} else { } else {
is.readTagPaylodLazy(type, depth + 1, this); is.readTagPayloadLazy(type, depth + 1, this);
} }
} }

View File

@ -137,10 +137,8 @@ public abstract class AbstractChangeSet implements ChangeSet, IBatchProcessor {
} }
if (!tilesTo.isEmpty()) { if (!tilesTo.isEmpty()) {
for (Map.Entry<BlockVector3, CompoundTag> entry : tilesTo.entrySet()) { for (Map.Entry<BlockVector3, CompoundTag> entry : tilesTo.entrySet()) {
CompoundTag nbt = entry.getValue();
BlockVector3 pos = entry.getKey(); BlockVector3 pos = entry.getKey();
MainUtil.setPosition(nbt, pos.getX() + bx, pos.getY(), pos.getZ() + bz); addTileCreate(MainUtil.setPosition(entry.getValue(), pos.getX() + bx, pos.getY(), pos.getZ() + bz));
addTileCreate(nbt);
} }
} }
Set<UUID> entRemoves = set.getEntityRemoves(); Set<UUID> entRemoves = set.getEntityRemoves();
@ -176,11 +174,12 @@ public abstract class AbstractChangeSet implements ChangeSet, IBatchProcessor {
int zz = z + bz; int zz = z + bz;
for (int x = 0; x < 16; x++, index++) { for (int x = 0; x < 16; x++, index++) {
int xx = bx + x; int xx = bx + x;
int combinedFrom = blocksGet[index]; int from = blocksGet[index];
if (combinedFrom == 0) { if (from == 0) {
combinedFrom = BlockID.AIR; from = BlockID.AIR;
} }
int combinedTo = blocksSet[index]; final int combinedFrom = from;
final int combinedTo = blocksSet[index];
if (combinedTo != 0) { if (combinedTo != 0) {
add(xx, yy, zz, combinedFrom, combinedTo); add(xx, yy, zz, combinedFrom, combinedTo);
} }
@ -249,14 +248,12 @@ public abstract class AbstractChangeSet implements ChangeSet, IBatchProcessor {
public void add(EntityCreate change) { public void add(EntityCreate change) {
CompoundTag tag = change.state.getNbtData(); CompoundTag tag = change.state.getNbtData();
MainUtil.setEntityInfo(tag, change.getEntity()); addEntityCreate(MainUtil.setEntityInfo(tag, change.getEntity()));
addEntityCreate(tag);
} }
public void add(EntityRemove change) { public void add(EntityRemove change) {
CompoundTag tag = change.state.getNbtData(); CompoundTag tag = change.state.getNbtData();
MainUtil.setEntityInfo(tag, change.getEntity()); addEntityRemove(MainUtil.setEntityInfo(tag, change.getEntity()));
addEntityRemove(tag);
} }
@Override @Override
@ -299,14 +296,12 @@ public abstract class AbstractChangeSet implements ChangeSet, IBatchProcessor {
if (from.hasNbtData()) { if (from.hasNbtData()) {
CompoundTag nbt = from.getNbtData(); CompoundTag nbt = from.getNbtData();
assert nbt != null; assert nbt != null;
MainUtil.setPosition(nbt, x, y, z); addTileRemove(MainUtil.setPosition(nbt, x, y, z));
addTileRemove(nbt);
} }
if (to.hasNbtData()) { if (to.hasNbtData()) {
CompoundTag nbt = to.getNbtData(); CompoundTag nbt = to.getNbtData();
assert nbt != null; assert nbt != null;
MainUtil.setPosition(nbt, x, y, z); addTileCreate(MainUtil.setPosition(nbt, x, y, z));
addTileCreate(nbt);
} }
int combinedFrom = from.getOrdinal(); int combinedFrom = from.getOrdinal();
int combinedTo = to.getOrdinal(); int combinedTo = to.getOrdinal();
@ -322,8 +317,7 @@ public abstract class AbstractChangeSet implements ChangeSet, IBatchProcessor {
if (to.hasNbtData()) { if (to.hasNbtData()) {
CompoundTag nbt = to.getNbtData(); CompoundTag nbt = to.getNbtData();
assert nbt != null; assert nbt != null;
MainUtil.setPosition(nbt, x, y, z); addTileCreate(MainUtil.setPosition(nbt, x, y, z));
addTileCreate(nbt);
} }
int combinedTo = to.getInternalId(); int combinedTo = to.getInternalId();
add(x, y, z, combinedFrom, combinedTo); add(x, y, z, combinedFrom, combinedTo);
@ -357,7 +351,7 @@ public abstract class AbstractChangeSet implements ChangeSet, IBatchProcessor {
wrappedTask.run(); wrappedTask.run();
return Futures.immediateCancelledFuture(); return Futures.immediateCancelledFuture();
} else { } else {
return Fawe.get().getQueueHandler().async(wrappedTask); return Fawe.get().getQueueHandler().submit(wrappedTask);
} }
} }
} }

View File

@ -152,10 +152,8 @@ public class CPUOptimizedClipboard extends LinearClipboard {
@Override @Override
public Collection<CompoundTag> getTileEntities() { public Collection<CompoundTag> getTileEntities() {
convertTilesToIndex(); convertTilesToIndex();
for (Map.Entry<Integer, CompoundTag> entry : nbtMapIndex.entrySet()) { nbtMapIndex.replaceAll((index, tag) -> {
int index = entry.getKey(); Map<String, Tag> values = new HashMap<>(tag.getValue());
CompoundTag tag = entry.getValue();
Map<String, Tag> values = tag.getValue();
if (!values.containsKey("x")) { if (!values.containsKey("x")) {
int y = index / getArea(); int y = index / getArea();
index -= y * getArea(); index -= y * getArea();
@ -164,23 +162,26 @@ public class CPUOptimizedClipboard extends LinearClipboard {
values.put("x", new IntTag(x)); values.put("x", new IntTag(x));
values.put("y", new IntTag(y)); values.put("y", new IntTag(y));
values.put("z", new IntTag(z)); values.put("z", new IntTag(z));
return new CompoundTag(values);
} else {
return tag;
} }
} });
return nbtMapIndex.values(); return nbtMapIndex.values();
} }
@Override @Override
public boolean setTile(int x, int y, int z, CompoundTag tag) { 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; return true;
} }
public boolean setTile(int index, CompoundTag tag) { public boolean setTile(int index, CompoundTag tag) {
nbtMapIndex.put(index, tag); final Map<String, Tag> values = new HashMap<>(tag.getValue());
Map<String, Tag> values = tag.getValue();
values.remove("x"); values.remove("x");
values.remove("y"); values.remove("y");
values.remove("z"); values.remove("z");
nbtMapIndex.put(index, new CompoundTag(values));
return true; return true;
} }

View File

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

View File

@ -21,10 +21,6 @@ import java.util.HashSet;
import java.util.Iterator; import java.util.Iterator;
import java.util.UUID; 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 { public abstract class LinearClipboard extends SimpleClipboard {
protected final HashSet<ClipboardEntity> entities = new HashSet<>(); protected final HashSet<ClipboardEntity> entities = new HashSet<>();

View File

@ -257,11 +257,11 @@ public class MemoryOptimizedClipboard extends LinearClipboard {
@Override @Override
public boolean setTile(int x, int y, int z, CompoundTag tag) { public boolean setTile(int x, int y, int z, CompoundTag tag) {
nbtMap.put(new IntTriple(x, y, z), tag); final Map<String, Tag> values = new HashMap<>(tag.getValue());
Map<String, Tag> values = tag.getValue();
values.put("x", new IntTag(x)); values.put("x", new IntTag(x));
values.put("y", new IntTag(y)); values.put("y", new IntTag(y));
values.put("z", new IntTag(z)); values.put("z", new IntTag(z));
nbtMap.put(new IntTriple(x, y, z), new CompoundTag(values));
return true; return true;
} }

View File

@ -14,7 +14,7 @@ public abstract class SimpleClipboard implements Clipboard {
SimpleClipboard(BlockVector3 dimensions) { SimpleClipboard(BlockVector3 dimensions) {
this.size = dimensions; this.size = dimensions;
long longVolume = (long) getWidth() * (long) getHeight() * (long) getLength(); 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."); throw new IllegalArgumentException("Dimensions are too large for this clipboard format.");
} }
this.area = getWidth() * getLength(); this.area = getWidth() * getLength();

View File

@ -16,4 +16,9 @@ public class AirMask extends BlockMask {
return new AirMask(getExtent()); return new AirMask(getExtent());
} }
@Override
public boolean replacesAir() {
return true;
}
} }

View File

@ -37,4 +37,9 @@ public class IdDataMask extends AbstractExtentMask implements ResettableMask {
return new IdDataMask(getExtent()); return new IdDataMask(getExtent());
} }
@Override
public boolean replacesAir() {
return true;
}
} }

View File

@ -38,4 +38,9 @@ public class IdMask extends AbstractExtentMask implements ResettableMask {
return new IdMask(getExtent()); return new IdMask(getExtent());
} }
@Override
public boolean replacesAir() {
return true;
}
} }

View File

@ -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();
}
}

View File

@ -34,6 +34,9 @@ import net.jpountz.lz4.LZ4InputStream;
import net.jpountz.lz4.LZ4Utils; import net.jpountz.lz4.LZ4Utils;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.imageio.ImageIO;
import java.awt.Graphics2D; import java.awt.Graphics2D;
import java.awt.image.BufferedImage; import java.awt.image.BufferedImage;
import java.io.BufferedOutputStream; import java.io.BufferedOutputStream;
@ -66,6 +69,7 @@ import java.nio.file.attribute.BasicFileAttributes;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Comparator; import java.util.Comparator;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.Locale;
import java.util.Map; import java.util.Map;
@ -83,8 +87,6 @@ import java.util.zip.GZIPInputStream;
import java.util.zip.Inflater; import java.util.zip.Inflater;
import java.util.zip.ZipEntry; import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream; import java.util.zip.ZipInputStream;
import javax.annotation.Nullable;
import javax.imageio.ImageIO;
import static java.lang.System.arraycopy; import static java.lang.System.arraycopy;
import static org.slf4j.LoggerFactory.getLogger; 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("x", new IntTag(x));
value.put("y", new IntTag(y)); value.put("y", new IntTag(y));
value.put("z", new IntTag(z)); 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())); map.put("Id", new StringTag(entity.getState().getType().getId()));
ListTag pos = (ListTag) map.get("Pos"); ListTag pos = (ListTag) map.get("Pos");
if (pos != null) { if (pos != null) {
Location loc = entity.getLocation(); 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(0, new DoubleTag(loc.getX()));
posList.set(1, new DoubleTag(loc.getY())); posList.set(1, new DoubleTag(loc.getY()));
posList.set(2, new DoubleTag(loc.getZ())); 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 { public static String getText(String url) throws IOException {

View File

@ -1,5 +1,6 @@
package com.boydti.fawe.util; package com.boydti.fawe.util;
import com.plotsquared.core.util.PseudoRandom;
import com.sk89q.worldedit.world.block.BlockType; import com.sk89q.worldedit.world.block.BlockType;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
@ -34,6 +35,8 @@ public class RandomTextureUtil extends CachedTextureUtil {
if (i < 0) { if (i < 0) {
int i1 = -i; int i1 = -i;
return -ThreadLocalRandom.current().nextInt(i1); return -ThreadLocalRandom.current().nextInt(i1);
} else if( i == 0) {
return 0;
} else { } else {
return ThreadLocalRandom.current().nextInt(i); return ThreadLocalRandom.current().nextInt(i);
} }

View File

@ -67,22 +67,6 @@ public class ReflectionUtils {
blankField(enumClass, "enumConstants"); // IBM JDK 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) { public static Object getHandle(Object wrapper) {
final Method getHandle = makeMethod(wrapper.getClass(), "getHandle"); final Method getHandle = makeMethod(wrapper.getClass(), "getHandle");
return callMethod(getHandle, wrapper); return callMethod(getHandle, wrapper);

View File

@ -629,7 +629,6 @@ public class TextureUtil implements TextureHolder {
mods.add(modId); mods.add(modId);
} }
} }
continue;
} }
String modelsDir = "assets/%1$s/models/block/%2$s.json"; String modelsDir = "assets/%1$s/models/block/%2$s.json";
String texturesDir = "assets/%1$s/textures/%2$s.png"; String texturesDir = "assets/%1$s/textures/%2$s.png";
@ -638,14 +637,14 @@ public class TextureUtil implements TextureHolder {
}.getType(); }.getType();
for (BlockType blockType : BlockTypesCache.values) { for (BlockType blockType : BlockTypesCache.values) {
if (!blockType.getMaterial().isFullCube()) { if (!blockType.getMaterial().isFullCube() || blockType.getId().toLowerCase().contains("shulker")) {
continue; continue;
} }
int combined = blockType.getInternalId(); int combined = blockType.getInternalId();
String id = blockType.getId(); String id = blockType.getId();
String[] split = id.split(":", 2); String[] split = id.split(":", 2);
String name = split.length == 1 ? id : split[1]; 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<>(); Map<String, String> texturesMap = new ConcurrentHashMap<>();
// Read models // Read models
@ -684,8 +683,11 @@ public class TextureUtil implements TextureHolder {
continue; continue;
} }
String[] texSplit = models.iterator().next().split(":");
String texture = texSplit[texSplit.length - 1];
textureFileName = textureFileName =
String.format(texturesDir, nameSpace, models.iterator().next()); String.format(texturesDir, nameSpace, texture);
} }
BufferedImage image = readImage(zipFile, textureFileName); BufferedImage image = readImage(zipFile, textureFileName);

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -19,10 +19,9 @@
package com.sk89q.jnbt; package com.sk89q.jnbt;
import java.util.ArrayList; import javax.annotation.Nullable;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import javax.annotation.Nullable;
import static com.google.common.base.Preconditions.checkNotNull; 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 { public final class ListTag extends Tag {
@Override
public int getTypeCode() {
return NBTConstants.TYPE_LIST;
}
private final Class<? extends Tag> type; private final Class<? extends Tag> type;
private final List<Tag> value; 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 @Override
public String toString() { public String toString() {
StringBuilder bldr = new StringBuilder(); StringBuilder bldr = new StringBuilder();
@ -444,4 +426,11 @@ public final class ListTag extends Tag {
return bldr.toString(); return bldr.toString();
} }
// FAWE Start
@Override
public int getTypeCode() {
return NBTConstants.TYPE_LIST;
}
// FAWE End
} }

View File

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

View File

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

View File

@ -20,14 +20,13 @@
package com.sk89q.jnbt; package com.sk89q.jnbt;
import java.nio.charset.Charset; import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
/** /**
* A class which holds constant values. * A class which holds constant values.
*/ */
public final class NBTConstants { 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_END = 0;
public static final int TYPE_BYTE = 1; public static final int TYPE_BYTE = 1;

View File

@ -32,6 +32,8 @@ import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
// THIS CLASS HAS BEEN HEAVILY MODIFIED BY FAWE
/** /**
* This class reads <strong>NBT</strong>, or <strong>Named Binary Tag</strong> * This class reads <strong>NBT</strong>, or <strong>Named Binary Tag</strong>
* streams, and produces an object graph of subclasses of the {@code Tag} * 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; 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. * Reads an NBT tag from the stream.
* *
@ -99,7 +109,7 @@ public final class NBTInputStream implements Closeable {
if (child != null) { if (child != null) {
child.acceptRoot(this, type, 0); child.acceptRoot(this, type, 0);
} else { } else {
readTagPaylodLazy(type, 0); readTagPayloadLazy(type, 0);
} }
} catch (Throwable e) { } catch (Throwable e) {
e.printStackTrace(); e.printStackTrace();
@ -119,7 +129,7 @@ public final class NBTInputStream implements Closeable {
private byte[] buf; private byte[] buf;
public void readTagPaylodLazy(int type, int depth) throws IOException { public void readTagPayloadLazy(int type, int depth) throws IOException {
switch (type) { switch (type) {
case NBTConstants.TYPE_END: case NBTConstants.TYPE_END:
return; return;
@ -152,7 +162,7 @@ public final class NBTInputStream implements Closeable {
int childType = is.readByte(); int childType = is.readByte();
length = is.readInt(); length = is.readInt();
for (int i = 0; i < length; ++i) { for (int i = 0; i < length; ++i) {
readTagPaylodLazy(childType, depth + 1); readTagPayloadLazy(childType, depth + 1);
} }
return; return;
} }
@ -165,7 +175,7 @@ public final class NBTInputStream implements Closeable {
return; return;
} }
is.skipBytes(is.readShort() & 0xFFFF); is.skipBytes(is.readShort() & 0xFFFF);
readTagPaylodLazy(childType, depth + 1); readTagPayloadLazy(childType, depth + 1);
} }
} }
case NBTConstants.TYPE_INT_ARRAY: { 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) { switch (type) {
case NBTConstants.TYPE_END: case NBTConstants.TYPE_END:
return; return;
@ -293,11 +303,11 @@ public final class NBTInputStream implements Closeable {
child = scope.get0(); child = scope.get0();
if (child == null) { if (child == null) {
for (int i = 0; i < length; ++i) { for (int i = 0; i < length; ++i) {
readTagPaylodLazy(childType, depth + 1); readTagPayloadLazy(childType, depth + 1);
} }
} else { } else {
for (int i = 0; i < length; ++i) { for (int i = 0; i < length; ++i) {
readTagPaylodLazy(childType, depth + 1, child); readTagPayloadLazy(childType, depth + 1, child);
} }
} }
return; return;
@ -330,9 +340,9 @@ public final class NBTInputStream implements Closeable {
} }
StreamDelegate child = scope.get(is); StreamDelegate child = scope.get(is);
if (child == null) { if (child == null) {
readTagPaylodLazy(childType, depth + 1); readTagPayloadLazy(childType, depth + 1);
} else { } else {
readTagPaylodLazy(childType, depth + 1, child); readTagPayloadLazy(childType, depth + 1, child);
} }
} }
} }
@ -461,7 +471,7 @@ public final class NBTInputStream implements Closeable {
case NBTConstants.TYPE_END: case NBTConstants.TYPE_END:
if (depth == 0) { if (depth == 0) {
throw new IOException( throw new IOException(
"TAG_End found without a TAG_Compound/TAG_List tag preceding it."); "TAG_End found without a TAG_Compound/TAG_List tag preceding it.");
} else { } else {
return null; return null;
} }

View File

@ -32,6 +32,8 @@ import java.util.Map;
import static com.google.common.base.Preconditions.checkNotNull; 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> * This class writes <strong>NBT</strong>, or <strong>Named Binary Tag</strong>
* {@code Tag} objects to an underlying {@code OutputStream}. * {@code Tag} objects to an underlying {@code OutputStream}.

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -125,8 +125,6 @@ import com.sk89q.worldedit.util.formatting.text.TranslatableComponent;
import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.World;
import com.sk89q.worldedit.world.biome.BiomeType; import com.sk89q.worldedit.world.biome.BiomeType;
import com.sk89q.worldedit.world.block.BaseBlock; 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.BlockState;
import com.sk89q.worldedit.world.block.BlockStateHolder; import com.sk89q.worldedit.world.block.BlockStateHolder;
import com.sk89q.worldedit.world.block.BlockType; import com.sk89q.worldedit.world.block.BlockType;
@ -148,6 +146,7 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.UUID; 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.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
@ -2046,18 +2045,18 @@ public class EditSession extends PassthroughExtent implements AutoCloseable {
int yy; int yy;
double nextXn = invRadiusX; double nextXn = 0;
forX: for (int x = 0; x <= ceilRadiusX; ++x) { forX: for (int x = 0; x <= ceilRadiusX; ++x) {
final double xn = nextXn; final double xn = nextXn;
double dx = xn * xn; double dx = xn * xn;
nextXn = (x + 1) * invRadiusX; nextXn = (x + 1) * invRadiusX;
double nextZn = invRadiusZ; double nextZn = 0;
forZ: for (int z = 0; z <= ceilRadiusZ; ++z) { forZ: for (int z = 0; z <= ceilRadiusZ; ++z) {
final double zn = nextZn; final double zn = nextZn;
double dz = zn * zn; double dz = zn * zn;
double dxz = dx + dz; double dxz = dx + dz;
nextZn = (z + 1) * invRadiusZ; nextZn = (z + 1) * invRadiusZ;
double nextYn = invRadiusY; double nextYn = 0;
forY: for (int y = 0; y <= ceilRadiusY; ++y) { forY: for (int y = 0; y <= ceilRadiusY; ++y) {
final double yn = nextYn; final double yn = nextYn;
@ -2767,7 +2766,7 @@ public class EditSession extends PassthroughExtent implements AutoCloseable {
newVset = this.getHollowed(newVset); 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) { if (!filled) {
vset = getHollowed(vset); 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) { if (!filled) {
newVset = this.getHollowed(newVset); newVset = this.getHollowed(newVset);
} }
return setBlocks(newVset, pattern); return this.changes += setBlocks(newVset, pattern);
} }
return changes; 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, public int makeBiomeShape(final Region region, final Vector3 zero, final Vector3 unit, final BiomeType biomeType,
final String expressionString, final boolean hollow) final String expressionString, final boolean hollow) throws ExpressionException {
throws ExpressionException, MaxChangedBlocksException {
return makeBiomeShape(region, zero, unit, biomeType, expressionString, hollow, WorldEdit.getInstance().getConfiguration().calculationTimeout); 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, public int makeBiomeShape(final Region region, final Vector3 zero, final Vector3 unit, final BiomeType biomeType,
final String expressionString, final boolean hollow, final int timeout) final String expressionString, final boolean hollow, final int timeout) throws ExpressionException {
throws ExpressionException, MaxChangedBlocksException {
final Expression expression = Expression.compile(expressionString, "x", "z"); final Expression expression = Expression.compile(expressionString, "x", "y", "z");
expression.optimize(); expression.optimize();
final EditSession editSession = this; final EditSession editSession = this;
final WorldEditExpressionEnvironment environment = new WorldEditExpressionEnvironment(editSession, unit, zero); final WorldEditExpressionEnvironment environment = new WorldEditExpressionEnvironment(editSession, unit, zero);
expression.setEnvironment(environment); expression.setEnvironment(environment);
final int[] timedOut = {0}; AtomicInteger timedOut = new AtomicInteger();
final ArbitraryBiomeShape shape = new ArbitraryBiomeShape(region) { final ArbitraryBiomeShape shape = new ArbitraryBiomeShape(region) {
@Override @Override
protected BiomeType getBiome(int x, int y, int z, BiomeType defaultBiomeType) { 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) // TODO: Allow biome setting via a script variable (needs BiomeType<->int mapping)
return defaultBiomeType; return defaultBiomeType;
} catch (ExpressionTimeoutException e) { } catch (ExpressionTimeoutException e) {
timedOut[0] = timedOut[0] + 1; timedOut.getAndIncrement();
return null; return null;
} catch (Exception e) { } catch (Exception e) {
log.warn("Failed to create shape", 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); int changed = shape.generate(this, biomeType, hollow);
if (timedOut[0] > 0) { if (timedOut.get() > 0) {
throw new ExpressionTimeoutException( throw new ExpressionTimeoutException(
String.format("%d blocks changed. %d blocks took too long to evaluate (increase time with //timeout)", String.format("%d biomes changed. %d biomes took too long to evaluate (increase time with //timeout)",
changed, timedOut[0])); changed, timedOut.get()));
} }
return changed; return changed;
} }

View File

@ -85,7 +85,6 @@ import com.sk89q.worldedit.command.util.CommandPermissionsConditionGenerator;
import com.sk89q.worldedit.command.util.CreatureButcher; import com.sk89q.worldedit.command.util.CreatureButcher;
import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.extension.platform.Actor; 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.Clipboard;
import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormats; import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormats;
import com.sk89q.worldedit.function.Contextual; import com.sk89q.worldedit.function.Contextual;
@ -130,6 +129,7 @@ import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.net.URI; import java.net.URI;
import java.net.URL;
import java.nio.file.FileSystems; import java.nio.file.FileSystems;
import java.util.List; import java.util.List;
@ -498,22 +498,23 @@ public class BrushCommands {
set(context, brush).setSize(radius).setFill(fill); set(context, brush).setSize(radius).setFill(fill);
} }
@Command( @Command(name = "image",
name = "image",
desc = "Use a height map to paint a surface", desc = "Use a height map to paint a surface",
descFooter = "Use a height map to paint any surface.\n" descFooter = "Use a height map to paint any surface.\n")
) @CommandPermissions("worldedit.brush.image")
@CommandPermissions("worldedit.brush.stencil") public void imageBrush(LocalSession session,
public void imageBrush(LocalSession session, InjectedValueAccess context, InjectedValueAccess context,
@Arg(desc = "The size of the brush", def = "5") @Arg(desc = "Image URL (imgur only)") String imageURL,
Expression radius, ProvideBindings.ImageUri imageUri, @Arg(desc = "The size of the brush", def = "5") Expression radius,
@Arg(def = "1", desc = "scale height") @Arg(def = "1", desc = "scale height") double yscale,
double yscale, @Switch(name = 'a', desc = "Use image Alpha") boolean alpha,
@Switch(name = 'a', desc = "Use image Alpha") @Switch(name = 'f', desc = "Blend the image with existing terrain") boolean fadeOut)
boolean alpha, throws WorldEditException, IOException {
@Switch(name = 'f', desc = "Blend the image with existing terrain") URL url = new URL(imageURL);
boolean fadeOut) throws WorldEditException, IOException { if (!url.getHost().equalsIgnoreCase("i.imgur.com")) {
BufferedImage image = imageUri.load(); throw new IOException("Only i.imgur.com links are allowed!");
}
BufferedImage image = MainUtil.readImage(url);
worldEdit.checkMaxBrushRadius(radius); worldEdit.checkMaxBrushRadius(radius);
if (yscale != 1) { if (yscale != 1) {
ImageUtil.scaleAlpha(image, yscale); ImageUtil.scaleAlpha(image, yscale);

View File

@ -277,7 +277,7 @@ public class ClipboardCommands {
) )
@Deprecated @Deprecated
@CommandPermissions({"worldedit.clipboard.download"}) @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); final ClipboardFormat format = ClipboardFormats.findByAlias(formatName);
if (format == null) { if (format == null) {
player.print(Caption.of("fawe.worldedit.clipboard.clipboard.invalid.format", formatName)); player.print(Caption.of("fawe.worldedit.clipboard.clipboard.invalid.format", formatName));

View File

@ -58,7 +58,7 @@ import org.enginehub.piston.annotation.param.Arg;
import org.enginehub.piston.annotation.param.Switch; import org.enginehub.piston.annotation.param.Switch;
import org.jetbrains.annotations.Range; import org.jetbrains.annotations.Range;
import java.awt.RenderingHints; import java.awt.*;
import java.awt.image.BufferedImage; import java.awt.image.BufferedImage;
import java.io.IOException; import java.io.IOException;
import java.net.URL; import java.net.URL;
@ -131,20 +131,26 @@ public class GenerationCommands {
) )
@CommandPermissions("worldedit.generation.image") @CommandPermissions("worldedit.generation.image")
@Logging(PLACEMENT) @Logging(PLACEMENT)
public void image(Actor actor, LocalSession session, EditSession editSession, String argStr, @Arg(desc = "boolean", def = "true") boolean randomize, public void image(Actor actor,
@Arg(desc = "TODO", def = "100") int threshold, @Arg(desc = "BlockVector2", def = "") BlockVector2 dimensions) throws WorldEditException, IOException { 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); 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")) { if (!url.getHost().equalsIgnoreCase("i.imgur.com")) {
throw new IOException("Only i.imgur.com links are allowed!"); throw new IOException("Only i.imgur.com links are allowed!");
} }
BufferedImage image = MainUtil.readImage(url); BufferedImage image = MainUtil.readImage(url);
if (dimensions != null) { 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); BlockVector3 pos1 = session.getPlacementPosition(actor);
BlockVector3 pos2 = pos1.add(image.getWidth() - 1, 0, image.getHeight() - 1); BlockVector3 pos2 = pos1.add(image.getWidth() - 1, 0, image.getHeight() - 1);
CuboidRegion region = new CuboidRegion(pos1, pos2); CuboidRegion region = new CuboidRegion(pos1, pos2);
int[] count = new int[1]; int[] count = new int[1];
final BufferedImage finalImage = image; final BufferedImage finalImage = image;

View File

@ -147,7 +147,7 @@ public class SchematicCommands {
@Deprecated @Deprecated
@CommandPermissions({"worldedit.clipboard.load", "worldedit.schematic.load", "worldedit.schematic.load.web", "worldedit.schematic.load.asset"}) @CommandPermissions({"worldedit.clipboard.load", "worldedit.schematic.load", "worldedit.schematic.load.web", "worldedit.schematic.load.asset"})
public void loadall(Player player, LocalSession session, public void loadall(Player player, LocalSession session,
@Arg(desc = "Format name.", def = "schematic") @Arg(desc = "Format name.", def = "fast")
String formatName, String formatName,
@Arg(desc = "File name.") @Arg(desc = "File name.")
String filename, String filename,
@ -223,7 +223,7 @@ public class SchematicCommands {
public void load(Actor actor, LocalSession session, public void load(Actor actor, LocalSession session,
@Arg(desc = "File name.") @Arg(desc = "File name.")
String filename, String filename,
@Arg(desc = "Format name.", def = "sponge") @Arg(desc = "Format name.", def = "fast")
String formatName) throws FilenameException { String formatName) throws FilenameException {
LocalConfiguration config = worldEdit.getConfiguration(); LocalConfiguration config = worldEdit.getConfiguration();
@ -323,7 +323,7 @@ public class SchematicCommands {
public void save(Actor actor, LocalSession session, public void save(Actor actor, LocalSession session,
@Arg(desc = "File name.") @Arg(desc = "File name.")
String filename, String filename,
@Arg(desc = "Format name.", def = "sponge") @Arg(desc = "Format name.", def = "fast")
String formatName, String formatName,
@Switch(name = 'f', desc = "Overwrite an existing file.") @Switch(name = 'f', desc = "Overwrite an existing file.")
boolean allowOverwrite, boolean allowOverwrite,

View File

@ -22,7 +22,7 @@ package com.sk89q.worldedit.command;
import com.boydti.fawe.Fawe; import com.boydti.fawe.Fawe;
import com.boydti.fawe.FaweVersion; import com.boydti.fawe.FaweVersion;
import com.boydti.fawe.config.Settings; 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.LocalSession;
import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.WorldEditException; 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.ArgFlag;
import org.enginehub.piston.annotation.param.Switch; import org.enginehub.piston.annotation.param.Switch;
import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.time.ZoneId; import java.time.ZoneId;
import java.time.ZonedDateTime; import java.time.ZonedDateTime;
@ -139,7 +140,10 @@ public class WorldEditCommands {
public void report(Actor actor) throws WorldEditException { public void report(Actor actor) throws WorldEditException {
String dest; String dest;
try { 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) { } catch (IOException e) {
actor.printInfo(TextComponent.of(e.getMessage())); actor.printInfo(TextComponent.of(e.getMessage()));
return; return;

View File

@ -24,8 +24,11 @@ import com.boydti.fawe.object.io.ResettableFileInputStream;
import com.boydti.fawe.object.schematic.MinecraftStructure; import com.boydti.fawe.object.schematic.MinecraftStructure;
import com.boydti.fawe.object.schematic.PNGWriter; import com.boydti.fawe.object.schematic.PNGWriter;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.jnbt.NBTInputStream; import com.sk89q.jnbt.NBTInputStream;
import com.sk89q.jnbt.NBTOutputStream; import com.sk89q.jnbt.NBTOutputStream;
import com.sk89q.jnbt.NamedTag;
import com.sk89q.jnbt.Tag;
import java.io.BufferedInputStream; import java.io.BufferedInputStream;
import java.io.BufferedOutputStream; import java.io.BufferedOutputStream;
@ -35,6 +38,7 @@ import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
import java.util.Locale; import java.util.Locale;
import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.zip.GZIPInputStream; import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream; import java.util.zip.GZIPOutputStream;
@ -44,40 +48,7 @@ import java.util.zip.GZIPOutputStream;
*/ */
public enum BuiltInClipboardFormat implements ClipboardFormat { public enum BuiltInClipboardFormat implements ClipboardFormat {
/** FAST("fast", "fawe") {
* The Schematic format used by MCEdit.
*/
MCEDIT_SCHEMATIC("mcedit", "mce", "schematic") {
@Override
public String getPrimaryFileExtension() {
return "schematic";
}
@Override
public ClipboardReader getReader(InputStream inputStream) throws IOException {
if (inputStream instanceof FileInputStream) {
inputStream = new ResettableFileInputStream((FileInputStream) inputStream);
}
BufferedInputStream buffered = new BufferedInputStream(inputStream);
NBTInputStream nbtStream = new NBTInputStream(new BufferedInputStream(new GZIPInputStream(buffered)));
SchematicReader input = new SchematicReader(nbtStream);
input.setUnderlyingStream(inputStream);
return input;
}
@Override
public ClipboardWriter getWriter(OutputStream outputStream) throws IOException {
throw new IOException("This format does not support saving, use `schem` or `sponge` as format"); // Is more helpful
}
@Override
public boolean isFormat(File file) {
String name = file.getName().toLowerCase(Locale.ROOT);
return name.endsWith(".schematic") || name.endsWith(".mcedit") || name.endsWith(".mce");
}
},
SPONGE_SCHEMATIC("sponge", "schem") {
@Override @Override
public String getPrimaryFileExtension() { 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: * The structure block format:
* http://minecraft.gamepedia.com/Structure_block_file_format * http://minecraft.gamepedia.com/Structure_block_file_format

View File

@ -30,10 +30,12 @@ import com.boydti.fawe.object.io.FastByteArraysInputStream;
import com.sk89q.jnbt.CompoundTag; import com.sk89q.jnbt.CompoundTag;
import com.sk89q.jnbt.IntTag; import com.sk89q.jnbt.IntTag;
import com.sk89q.jnbt.NBTInputStream; import com.sk89q.jnbt.NBTInputStream;
import com.sk89q.jnbt.NamedTag;
import com.sk89q.jnbt.StringTag; import com.sk89q.jnbt.StringTag;
import com.sk89q.jnbt.Tag; import com.sk89q.jnbt.Tag;
import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.entity.BaseEntity; import com.sk89q.worldedit.entity.BaseEntity;
import com.sk89q.worldedit.entity.Entity;
import com.sk89q.worldedit.extension.input.InputParseException; import com.sk89q.worldedit.extension.input.InputParseException;
import com.sk89q.worldedit.extension.platform.Capability; import com.sk89q.worldedit.extension.platform.Capability;
import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard; 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.BiomeType;
import com.sk89q.worldedit.world.biome.BiomeTypes; import com.sk89q.worldedit.world.biome.BiomeTypes;
import com.sk89q.worldedit.world.block.BlockState; 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.block.BlockTypesCache;
import com.sk89q.worldedit.world.entity.EntityType; import com.sk89q.worldedit.world.entity.EntityType;
import com.sk89q.worldedit.world.entity.EntityTypes; import com.sk89q.worldedit.world.entity.EntityTypes;
@ -55,9 +58,11 @@ import org.slf4j.LoggerFactory;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
import java.util.OptionalInt;
import java.util.UUID; import java.util.UUID;
import java.util.function.Function; import java.util.function.Function;
@ -70,9 +75,10 @@ public class FastSchematicReader extends NBTSchematicReader {
private static final Logger log = LoggerFactory.getLogger(FastSchematicReader.class); private static final Logger log = LoggerFactory.getLogger(FastSchematicReader.class);
private final NBTInputStream inputStream; private final NBTInputStream inputStream;
private DataFixer fixer = null; private DataFixer fixer;
private int dataVersion = -1; private int dataVersion = -1;
private int version = -1; private int version = -1;
private int faweWritten = -1;
private FastByteArrayOutputStream blocksOut; private FastByteArrayOutputStream blocksOut;
private FaweOutputStream blocks; private FaweOutputStream blocks;
@ -92,6 +98,8 @@ public class FastSchematicReader extends NBTSchematicReader {
private char[] palette; private char[] palette;
private char[] biomePalette; private char[] biomePalette;
private BlockVector3 min = BlockVector3.ZERO; 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(); this.fixer = WorldEdit.getInstance().getPlatformManager().queryCapability(Capability.WORLD_EDITING).getDataFixer();
} }
public void setBrokenEntities(boolean brokenEntities) {
this.brokenEntities = brokenEntities;
}
private String fix(String palettePart) { private String fix(String palettePart) {
if (fixer == null || dataVersion == -1) { if (fixer == null || dataVersion == -1) {
return palettePart; return palettePart;
@ -133,7 +145,7 @@ public class FastSchematicReader extends NBTSchematicReader {
return fixer.fixUp(DataFixer.FixTypes.BIOME, biomePalettePart, dataVersion); return fixer.fixUp(DataFixer.FixTypes.BIOME, biomePalettePart, dataVersion);
} }
public StreamDelegate createDelegate() { public StreamDelegate createVersionDelegate() {
StreamDelegate root = new StreamDelegate(); StreamDelegate root = new StreamDelegate();
StreamDelegate schematic = root.add("Schematic"); StreamDelegate schematic = root.add("Schematic");
schematic.add("DataVersion").withInt((i, v) -> dataVersion = v); 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; 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("Width").withInt((i, v) -> width = v);
schematic.add("Height").withInt((i, v) -> height = v); schematic.add("Height").withInt((i, v) -> height = v);
schematic.add("Length").withInt((i, v) -> length = 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("WEOffsetX").withInt((i, v) -> offsetX = v);
metadata.add("WEOffsetY").withInt((i, v) -> offsetY = v); metadata.add("WEOffsetY").withInt((i, v) -> offsetY = v);
metadata.add("WEOffsetZ").withInt((i, v) -> offsetZ = 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"); StreamDelegate paletteDelegate = schematic.add("Palette");
paletteDelegate.withValue((ValueReader<Map<String, Object>>) (ignore, v) -> { paletteDelegate.withValue((ValueReader<Map<String, Object>>) (ignore, v) -> {
palette = new char[v.size()]; palette = new char[v.size()];
for (Entry<String, Object> entry : v.entrySet()) { for (Entry<String, Object> entry : v.entrySet()) {
BlockState state = null; BlockState state;
String palettePart = fix(entry.getKey());
try { try {
String palettePart = fix(entry.getKey());
state = BlockState.get(palettePart); state = BlockState.get(palettePart);
} catch (InputParseException e) { } catch (InputParseException ignored) {
e.printStackTrace(); log.warn("Invalid BlockState in palette: " + palettePart + ". Block will be replaced with air.");
state = BlockTypes.AIR.getDefaultState();
} }
int index = (int) entry.getValue(); int index = (int) entry.getValue();
palette[index] = (char) state.getOrdinal(); palette[index] = (char) state.getOrdinal();
@ -224,10 +248,14 @@ public class FastSchematicReader extends NBTSchematicReader {
@Override @Override
public Clipboard read(UUID uuid, Function<BlockVector3, Clipboard> createOutput) throws IOException { public Clipboard read(UUID uuid, Function<BlockVector3, Clipboard> createOutput) throws IOException {
StreamDelegate root = createDelegate(); StreamDelegate root = createDelegate();
StreamDelegate versions = createVersionDelegate();
inputStream.mark(Integer.MAX_VALUE);
inputStream.readNamedTagLazy(versions);
inputStream.reset();
inputStream.readNamedTagLazy(root); inputStream.readNamedTagLazy(root);
if (version != 1 && version != 2) { 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) { if (blocks != null) {
@ -240,9 +268,11 @@ public class FastSchematicReader extends NBTSchematicReader {
biomes = null; biomes = null;
BlockVector3 dimensions = BlockVector3.at(width, height, length); 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) { if (offsetX != Integer.MIN_VALUE && offsetY != Integer.MIN_VALUE && offsetZ != Integer.MIN_VALUE) {
origin = BlockVector3.at(-offsetX, -offsetY, -offsetZ); origin = BlockVector3.at(-offsetX, -offsetY, -offsetZ);
} else {
origin = BlockVector3.ZERO;
} }
Clipboard clipboard = createOutput.apply(dimensions); Clipboard clipboard = createOutput.apply(dimensions);
@ -326,7 +356,7 @@ public class FastSchematicReader extends NBTSchematicReader {
y = pos[1]; y = pos[1];
z = pos[2]; z = pos[2];
} }
Map<String, Tag> values = tile.getValue(); Map<String, Tag> values = new HashMap<>(tile.getValue());
Tag id = values.get("Id"); Tag id = values.get("Id");
if (id != null) { if (id != null) {
values.put("x", new IntTag(x)); values.put("x", new IntTag(x));
@ -337,22 +367,19 @@ public class FastSchematicReader extends NBTSchematicReader {
values.remove("Id"); values.remove("Id");
values.remove("Pos"); values.remove("Pos");
tile = fixBlockEntity(tile); clipboard.setTile(x, y, z, fixBlockEntity(new CompoundTag(values)));
clipboard.setTile(x, y, z, tile);
} }
} }
// entities // entities
if (entities != null && !entities.isEmpty()) { if (entities != null && !entities.isEmpty()) {
for (Map<String, Object> entRaw : entities) { for (Map<String, Object> entRaw : entities) {
CompoundTag ent = FaweCache.IMP.asTag(entRaw); Map<String, Tag> value = new HashMap<>(FaweCache.IMP.asTag(entRaw).getValue());
Map<String, Tag> value = ent.getValue();
StringTag id = (StringTag) value.get("Id"); StringTag id = (StringTag) value.get("Id");
if (id == null) { if (id == null) {
id = (StringTag) value.get("id"); id = (StringTag) value.get("id");
if (id == null) { if (id == null) {
return null; continue;
} }
} }
value.put("id", id); value.put("id", id);
@ -360,10 +387,29 @@ public class FastSchematicReader extends NBTSchematicReader {
EntityType type = EntityTypes.parse(id.getValue()); EntityType type = EntityTypes.parse(id.getValue());
if (type != null) { if (type != null) {
ent = fixEntity(ent); final CompoundTag ent = fixEntity(new CompoundTag(value));
BaseEntity state = new BaseEntity(type, ent); BaseEntity state = new BaseEntity(type, ent);
Location loc = ent.getEntityLocation(clipboard); Location loc = ent.getEntityLocation(clipboard);
clipboard.createEntity(loc, state); 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 { } else {
log.debug("Invalid entity: " + id); log.debug("Invalid entity: " + id);
} }
@ -372,7 +418,7 @@ public class FastSchematicReader extends NBTSchematicReader {
clipboard.setOrigin(origin); clipboard.setOrigin(origin);
if (!min.equals(BlockVector3.ZERO)) { if (!min.equals(BlockVector3.ZERO)) {
new BlockArrayClipboard(clipboard, min); clipboard = new BlockArrayClipboard(clipboard, min);
} }
return clipboard; return clipboard;

View File

@ -19,10 +19,10 @@
package com.sk89q.worldedit.extent.clipboard.io; package com.sk89q.worldedit.extent.clipboard.io;
import com.boydti.fawe.Fawe;
import com.boydti.fawe.jnbt.streamer.IntValueReader; import com.boydti.fawe.jnbt.streamer.IntValueReader;
import com.boydti.fawe.object.FaweOutputStream; import com.boydti.fawe.object.FaweOutputStream;
import com.boydti.fawe.util.IOUtil; import com.boydti.fawe.util.IOUtil;
import com.google.common.collect.Maps;
import com.sk89q.jnbt.CompoundTag; import com.sk89q.jnbt.CompoundTag;
import com.sk89q.jnbt.IntArrayTag; import com.sk89q.jnbt.IntArrayTag;
import com.sk89q.jnbt.ListTag; 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.function.visitor.Order;
import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.regions.Region; 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.BiomeType;
import com.sk89q.worldedit.world.biome.BiomeTypes; import com.sk89q.worldedit.world.biome.BiomeTypes;
import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BaseBlock;
@ -58,8 +59,6 @@ import java.util.HashMap;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;
import static com.google.common.base.Preconditions.checkNotNull; 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 static final int MAX_SIZE = Short.MAX_VALUE - Short.MIN_VALUE;
private final NBTOutputStream outputStream; private final NBTOutputStream outputStream;
private boolean brokenEntities = false;
/** /**
* Create a new schematic writer. * Create a new schematic writer.
@ -83,6 +83,10 @@ public class FastSchematicWriter implements ClipboardWriter {
this.outputStream = outputStream; this.outputStream = outputStream;
} }
public void setBrokenEntities(boolean brokenEntities) {
this.brokenEntities = brokenEntities;
}
@Override @Override
public void write(Clipboard clipboard) throws IOException { public void write(Clipboard clipboard) throws IOException {
// For now always write the latest version. Maybe provide support for earlier if more appear. // For now always write the latest version. Maybe provide support for earlier if more appear.
@ -123,15 +127,16 @@ public class FastSchematicWriter implements ClipboardWriter {
// The Sponge format Offset refers to the 'min' points location in the world. That's our 'Origin' // The Sponge format Offset refers to the 'min' points location in the world. That's our 'Origin'
out.writeNamedTag("Offset", new int[]{ out.writeNamedTag("Offset", new int[]{
min.getBlockX(), min.getBlockX(),
min.getBlockY(), min.getBlockY(),
min.getBlockZ(), min.getBlockZ(),
}); });
out.writeLazyCompoundTag("Metadata", out1 -> { out.writeLazyCompoundTag("Metadata", out1 -> {
out1.writeNamedTag("WEOffsetX", offset.getBlockX()); out1.writeNamedTag("WEOffsetX", offset.getBlockX());
out1.writeNamedTag("WEOffsetY", offset.getBlockY()); out1.writeNamedTag("WEOffsetY", offset.getBlockY());
out1.writeNamedTag("WEOffsetZ", offset.getBlockZ()); out1.writeNamedTag("WEOffsetZ", offset.getBlockZ());
out1.writeNamedTag("FAWEVersion", Fawe.get().getVersion().build);
}); });
ByteArrayOutputStream blocksCompressed = new ByteArrayOutputStream(); ByteArrayOutputStream blocksCompressed = new ByteArrayOutputStream();
@ -157,7 +162,7 @@ public class FastSchematicWriter implements ClipboardWriter {
BaseBlock block = pos.getFullBlock(finalClipboard); BaseBlock block = pos.getFullBlock(finalClipboard);
CompoundTag nbt = block.getNbtData(); CompoundTag nbt = block.getNbtData();
if (nbt != null) { 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. // Positions are kept in NBT, we don't want that.
values.remove("x"); values.remove("x");
@ -170,12 +175,13 @@ public class FastSchematicWriter implements ClipboardWriter {
// Dum. // Dum.
values.remove("id"); values.remove("id");
values.put("Pos", new IntArrayTag(new int[]{ values.put("Pos", new IntArrayTag(new int[]{
pos.getX(), pos.getX(),
pos.getY(), pos.getY(),
pos.getZ() pos.getZ()
})); }));
numTiles++; numTiles++;
tilesOut.writeTagPayload(block.getNbtData());
tilesOut.writeTagPayload(new CompoundTag(values));
} }
int ordinal = block.getOrdinal(); int ordinal = block.getOrdinal();
@ -240,8 +246,12 @@ public class FastSchematicWriter implements ClipboardWriter {
// Store our location data, overwriting any // Store our location data, overwriting any
values.remove("id"); 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("Id", new StringTag(state.getType().getId()));
values.put("Pos", writeVector(entity.getLocation())); values.put("Pos", writeVector(loc));
values.put("Rotation", writeRotation(entity.getLocation())); values.put("Rotation", writeRotation(entity.getLocation()));
CompoundTag entityTag = new CompoundTag(values); 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 @Override
public void close() throws IOException { public void close() throws IOException {
outputStream.close(); outputStream.close();

View File

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

View File

@ -68,26 +68,24 @@ import static com.google.common.base.Preconditions.checkNotNull;
/** /**
* Reads schematic files that are compatible with MCEdit and other editors. * Reads schematic files that are compatible with MCEdit and other editors.
* @deprecated Use SchematicStreamer
*/ */
@Deprecated
public class MCEditSchematicReader extends NBTSchematicReader { public class MCEditSchematicReader extends NBTSchematicReader {
private static final Logger log = LoggerFactory.getLogger(MCEditSchematicReader.class); private static final Logger log = LoggerFactory.getLogger(MCEditSchematicReader.class);
private final NBTInputStream inputStream; private final NBTInputStream inputStream;
private final DataFixer fixer; private final DataFixer fixer;
private static final ImmutableList<NBTCompatibilityHandler> COMPATIBILITY_HANDLERS private static final ImmutableList<NBTCompatibilityHandler> COMPATIBILITY_HANDLERS
= ImmutableList.of( = ImmutableList.of(
new SignCompatibilityHandler(), new SignCompatibilityHandler(),
new FlowerPotCompatibilityHandler(), new FlowerPotCompatibilityHandler(),
new NoteBlockCompatibilityHandler(), new NoteBlockCompatibilityHandler(),
new SkullBlockCompatibilityHandler(), new SkullBlockCompatibilityHandler(),
new BannerBlockCompatibilityHandler(), new BannerBlockCompatibilityHandler(),
new BedBlockCompatibilityHandler() new BedBlockCompatibilityHandler()
); );
private static final ImmutableList<EntityNBTCompatibilityHandler> ENTITY_COMPATIBILITY_HANDLERS private static final ImmutableList<EntityNBTCompatibilityHandler> ENTITY_COMPATIBILITY_HANDLERS
= ImmutableList.of( = ImmutableList.of(
new Pre13HangingCompatibilityHandler() new Pre13HangingCompatibilityHandler()
); );
/** /**
@ -99,8 +97,8 @@ public class MCEditSchematicReader extends NBTSchematicReader {
checkNotNull(inputStream); checkNotNull(inputStream);
this.inputStream = inputStream; this.inputStream = inputStream;
this.fixer = null; this.fixer = null;
//com.sk89q.worldedit.WorldEdit.getInstance().getPlatformManager().queryCapability( //com.sk89q.worldedit.WorldEdit.getInstance().getPlatformManager().queryCapability(
//com.sk89q.worldedit.extension.platform.Capability.WORLD_EDITING).getDataFixer(); //com.sk89q.worldedit.extension.platform.Capability.WORLD_EDITING).getDataFixer();
} }
@Override @Override
@ -207,7 +205,7 @@ public class MCEditSchematicReader extends NBTSchematicReader {
if (newBlock != null) { if (newBlock != null) {
for (NBTCompatibilityHandler handler : COMPATIBILITY_HANDLERS) { for (NBTCompatibilityHandler handler : COMPATIBILITY_HANDLERS) {
if (handler.isAffectedBlock(newBlock)) { if (handler.isAffectedBlock(newBlock)) {
newBlock = handler.updateNBT(block, values); newBlock = handler.updateNBT(block, values).toImmutableState();
if (newBlock == null || values.isEmpty()) { if (newBlock == null || values.isEmpty()) {
break; break;
} }
@ -256,7 +254,7 @@ public class MCEditSchematicReader extends NBTSchematicReader {
int combined = block << 8 | data; int combined = block << 8 | data;
if (unknownBlocks.add(combined)) { if (unknownBlocks.add(combined)) {
log.warn("Unknown block when loading schematic: " log.warn("Unknown block when loading schematic: "
+ block + ":" + data + ". This is most likely a bad schematic."); + block + ":" + data + ". This is most likely a bad schematic.");
} }
} }
} catch (WorldEditException ignored) { // BlockArrayClipboard won't throw this } catch (WorldEditException ignored) { // BlockArrayClipboard won't throw this
@ -302,7 +300,7 @@ public class MCEditSchematicReader extends NBTSchematicReader {
} }
private String convertEntityId(String id) { private String convertEntityId(String id) {
switch(id) { switch (id) {
case "AreaEffectCloud": return "area_effect_cloud"; case "AreaEffectCloud": return "area_effect_cloud";
case "ArmorStand": return "armor_stand"; case "ArmorStand": return "armor_stand";
case "CaveSpider": return "cave_spider"; case "CaveSpider": return "cave_spider";

View File

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

View File

@ -68,7 +68,6 @@ import static com.google.common.base.Preconditions.checkNotNull;
/** /**
* Reads schematic files using the Sponge Schematic Specification. * Reads schematic files using the Sponge Schematic Specification.
*/ */
@Deprecated // High mem usage + slow
public class SpongeSchematicReader extends NBTSchematicReader { public class SpongeSchematicReader extends NBTSchematicReader {
private static final Logger log = LoggerFactory.getLogger(SpongeSchematicReader.class); private static final Logger log = LoggerFactory.getLogger(SpongeSchematicReader.class);
@ -93,7 +92,7 @@ public class SpongeSchematicReader extends NBTSchematicReader {
Map<String, Tag> schematic = schematicTag.getValue(); Map<String, Tag> schematic = schematicTag.getValue();
final Platform platform = WorldEdit.getInstance().getPlatformManager() final Platform platform = WorldEdit.getInstance().getPlatformManager()
.queryCapability(Capability.WORLD_EDITING); .queryCapability(Capability.WORLD_EDITING);
int liveDataVersion = platform.getDataVersion(); int liveDataVersion = platform.getDataVersion();
if (schematicVersion == 1) { if (schematicVersion == 1) {
@ -102,17 +101,23 @@ public class SpongeSchematicReader extends NBTSchematicReader {
return readVersion1(schematicTag); return readVersion1(schematicTag);
} else if (schematicVersion == 2) { } else if (schematicVersion == 2) {
dataVersion = requireTag(schematic, "DataVersion", IntTag.class).getValue(); 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) { if (dataVersion > liveDataVersion) {
log.warn("Schematic was made in a newer Minecraft version ({} > {}). Data may be incompatible.", log.warn("Schematic was made in a newer Minecraft version ({} > {}). Data may be incompatible.",
dataVersion, liveDataVersion); dataVersion, liveDataVersion);
} else if (dataVersion < liveDataVersion) { } else if (dataVersion < liveDataVersion) {
fixer = platform.getDataFixer(); fixer = platform.getDataFixer();
if (fixer != null) { if (fixer != null) {
log.debug("Schematic was made in an older Minecraft version ({} < {}), will attempt DFU.", log.debug("Schematic was made in an older Minecraft version ({} < {}), will attempt DFU.",
dataVersion, liveDataVersion); dataVersion, liveDataVersion);
} else { } else {
log.info("Schematic was made in an older Minecraft version ({} < {}), but DFU is not available. Data may be incompatible.", log.info("Schematic was made in an older Minecraft version ({} < {}), but DFU is not available. Data may be incompatible.",
dataVersion, liveDataVersion); dataVersion, liveDataVersion);
} }
} }
@ -130,7 +135,11 @@ public class SpongeSchematicReader extends NBTSchematicReader {
if (schematicVersion == 1) { if (schematicVersion == 1) {
return OptionalInt.of(Constants.DATA_VERSION_MC_1_13_2); return OptionalInt.of(Constants.DATA_VERSION_MC_1_13_2);
} else if (schematicVersion == 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(); return OptionalInt.empty();
} catch (IOException e) { } catch (IOException e) {
@ -140,9 +149,6 @@ public class SpongeSchematicReader extends NBTSchematicReader {
private CompoundTag getBaseTag() throws IOException { private CompoundTag getBaseTag() throws IOException {
NamedTag rootTag = inputStream.readNamedTag(); 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(); CompoundTag schematicTag = (CompoundTag) rootTag.getTag();
// Check // Check
@ -226,9 +232,9 @@ public class SpongeSchematicReader extends NBTSchematicReader {
} }
if (tileEntities != null) { if (tileEntities != null) {
List<Map<String, Tag>> tileEntityTags = tileEntities.getValue().stream() List<Map<String, Tag>> tileEntityTags = tileEntities.getValue().stream()
.map(tag -> (CompoundTag) tag) .map(tag -> (CompoundTag) tag)
.map(CompoundTag::getValue) .map(CompoundTag::getValue)
.collect(Collectors.toList()); .collect(Collectors.toList());
for (Map<String, Tag> tileEntity : tileEntityTags) { for (Map<String, Tag> tileEntity : tileEntityTags) {
int[] pos = requireTag(tileEntity, "Pos", IntArrayTag.class).getValue(); int[] pos = requireTag(tileEntity, "Pos", IntArrayTag.class).getValue();
@ -321,8 +327,8 @@ public class SpongeSchematicReader extends NBTSchematicReader {
} }
BiomeType biome = BiomeTypes.get(key); BiomeType biome = BiomeTypes.get(key);
if (biome == null) { if (biome == null) {
log.warn("Unknown biome type :" + key + log.warn("Unknown biome type :" + key
" in palette. Are you missing a mod or using a schematic made in a newer version of Minecraft?"); + " in palette. Are you missing a mod or using a schematic made in a newer version of Minecraft?");
} }
Tag idTag = palettePart.getValue(); Tag idTag = palettePart.getValue();
if (!(idTag instanceof IntTag)) { if (!(idTag instanceof IntTag)) {
@ -385,8 +391,8 @@ public class SpongeSchematicReader extends NBTSchematicReader {
EntityType entityType = EntityTypes.get(id); EntityType entityType = EntityTypes.get(id);
if (entityType != null) { if (entityType != null) {
Location location = NBTConversions.toLocation(clipboard, Location location = NBTConversions.toLocation(clipboard,
requireTag(tags, "Pos", ListTag.class), requireTag(tags, "Pos", ListTag.class),
requireTag(tags, "Rotation", ListTag.class)); requireTag(tags, "Rotation", ListTag.class));
BaseEntity state = new BaseEntity(entityType, entityTag); BaseEntity state = new BaseEntity(entityType, entityTag);
clipboard.createEntity(location, state); clipboard.createEntity(location, state);
} else { } else {

View File

@ -19,11 +19,10 @@
package com.sk89q.worldedit.extent.clipboard.io; package com.sk89q.worldedit.extent.clipboard.io;
import com.boydti.fawe.Fawe;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
import com.sk89q.jnbt.ByteArrayTag; import com.sk89q.jnbt.ByteArrayTag;
import com.sk89q.jnbt.CompoundTag; import com.sk89q.jnbt.CompoundTag;
import com.sk89q.jnbt.DoubleTag;
import com.sk89q.jnbt.FloatTag;
import com.sk89q.jnbt.IntArrayTag; import com.sk89q.jnbt.IntArrayTag;
import com.sk89q.jnbt.IntTag; import com.sk89q.jnbt.IntTag;
import com.sk89q.jnbt.ListTag; 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.extension.platform.Capability;
import com.sk89q.worldedit.extent.clipboard.Clipboard; import com.sk89q.worldedit.extent.clipboard.Clipboard;
import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.math.Vector3;
import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.util.Location; import com.sk89q.worldedit.util.Location;
import com.sk89q.worldedit.world.biome.BiomeType; 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. * Writes schematic files using the Sponge schematic format.
*/ */
@Deprecated // High mem usage + slow
public class SpongeSchematicWriter implements ClipboardWriter { public class SpongeSchematicWriter implements ClipboardWriter {
private static final int CURRENT_VERSION = 2; private static final int CURRENT_VERSION = 2;
@ -108,12 +105,13 @@ public class SpongeSchematicWriter implements ClipboardWriter {
Map<String, Tag> schematic = new HashMap<>(); Map<String, Tag> schematic = new HashMap<>();
schematic.put("Version", new IntTag(CURRENT_VERSION)); schematic.put("Version", new IntTag(CURRENT_VERSION));
schematic.put("DataVersion", new IntTag( schematic.put("DataVersion", new IntTag(
WorldEdit.getInstance().getPlatformManager().queryCapability(Capability.WORLD_EDITING).getDataVersion())); WorldEdit.getInstance().getPlatformManager().queryCapability(Capability.WORLD_EDITING).getDataVersion()));
Map<String, Tag> metadata = new HashMap<>(); Map<String, Tag> metadata = new HashMap<>();
metadata.put("WEOffsetX", new IntTag(offset.getBlockX())); metadata.put("WEOffsetX", new IntTag(offset.getBlockX()));
metadata.put("WEOffsetY", new IntTag(offset.getBlockY())); metadata.put("WEOffsetY", new IntTag(offset.getBlockY()));
metadata.put("WEOffsetZ", new IntTag(offset.getBlockZ())); metadata.put("WEOffsetZ", new IntTag(offset.getBlockZ()));
metadata.put("FAWEVersion", new IntTag(Fawe.get().getVersion().build));
schematic.put("Metadata", new CompoundTag(metadata)); schematic.put("Metadata", new CompoundTag(metadata));
@ -123,9 +121,9 @@ public class SpongeSchematicWriter implements ClipboardWriter {
// The Sponge format Offset refers to the 'min' points location in the world. That's our 'Origin' // The Sponge format Offset refers to the 'min' points location in the world. That's our 'Origin'
schematic.put("Offset", new IntArrayTag(new int[]{ schematic.put("Offset", new IntArrayTag(new int[]{
min.getBlockX(), min.getBlockX(),
min.getBlockY(), min.getBlockY(),
min.getBlockZ(), min.getBlockZ(),
})); }));
int paletteMax = 0; int paletteMax = 0;
@ -268,21 +266,6 @@ public class SpongeSchematicWriter implements ClipboardWriter {
schematic.put("Entities", new ListTag(CompoundTag.class, entities)); 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 @Override
public void close() throws IOException { public void close() throws IOException {
outputStream.close(); outputStream.close();

View File

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

View File

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

View File

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

View File

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

View File

@ -47,7 +47,7 @@ public class NoteBlockCompatibilityHandler implements NBTCompatibilityHandler {
} }
@Override @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. // 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 // it will be updated to the block below when it gets set into the world for the first time
Tag noteTag = values.get("note"); Tag noteTag = values.get("note");
@ -55,7 +55,7 @@ public class NoteBlockCompatibilityHandler implements NBTCompatibilityHandler {
Byte note = ((ByteTag) noteTag).getValue(); Byte note = ((ByteTag) noteTag).getValue();
if (note != null) { if (note != null) {
values.clear(); values.clear();
return (B) block.with(NoteProperty, (int) note).toImmutableState(); return block.with(NoteProperty, (int) note).toImmutableState();
} }
} }
return block; return block;

View File

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

View File

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

View File

@ -22,6 +22,7 @@ package com.sk89q.worldedit.function.mask;
import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.world.block.BlockCategory; import com.sk89q.worldedit.world.block.BlockCategory;
import com.sk89q.worldedit.world.block.BlockTypes;
import javax.annotation.Nullable; import javax.annotation.Nullable;
@ -61,4 +62,9 @@ public class BlockCategoryMask extends AbstractExtentMask {
public Mask copy() { public Mask copy() {
return new BlockCategoryMask(getExtent(), category); return new BlockCategoryMask(getExtent(), category);
} }
@Override
public boolean replacesAir() {
return category.contains(BlockTypes.AIR);
}
} }

View File

@ -29,12 +29,12 @@ import com.sk89q.worldedit.world.block.BlockTypes;
import com.sk89q.worldedit.world.block.BlockTypesCache; import com.sk89q.worldedit.world.block.BlockTypesCache;
import com.sk89q.worldedit.world.block.ImmutableBaseBlock; import com.sk89q.worldedit.world.block.ImmutableBaseBlock;
import javax.annotation.Nullable;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.function.Predicate; import java.util.function.Predicate;
import javax.annotation.Nullable;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
@ -185,7 +185,7 @@ public class BlockMask extends ABlockMask {
@Override @Override
public boolean test(BlockState state) { public boolean test(BlockState state) {
return ordinals[state.getOrdinal()] || replacesAir() && state.getOrdinal() <= 3; return ordinals[state.getOrdinal()] || replacesAir() && state.getOrdinal() == 0;
} }
@Override @Override
@ -259,19 +259,16 @@ public class BlockMask extends ABlockMask {
int setTypes = 0; int setTypes = 0;
BlockType setType = null; BlockType setType = null;
BlockType unsetType = null;
int totalTypes = 0; int totalTypes = 0;
for (BlockType type : BlockTypesCache.values) { for (BlockType type : BlockTypesCache.values) {
if (type != null) { if (type != null) {
totalTypes++; totalTypes++;
boolean hasAll = true; boolean hasAll = true;
boolean hasAny = false;
List<BlockState> all = type.getAllStates(); List<BlockState> all = type.getAllStates();
for (BlockState state : all) { for (BlockState state : all) {
totalStates++; totalStates++;
hasAll &= test(state); hasAll &= test(state);
hasAny = true;
} }
if (hasAll) { if (hasAll) {
setTypes++; setTypes++;
@ -326,6 +323,7 @@ public class BlockMask extends ABlockMask {
cloned[BlockTypes.AIR.getDefaultState().getOrdinal()] = false; cloned[BlockTypes.AIR.getDefaultState().getOrdinal()] = false;
cloned[BlockTypes.CAVE_AIR.getDefaultState().getOrdinal()] = false; cloned[BlockTypes.CAVE_AIR.getDefaultState().getOrdinal()] = false;
cloned[BlockTypes.VOID_AIR.getDefaultState().getOrdinal()] = false; cloned[BlockTypes.VOID_AIR.getDefaultState().getOrdinal()] = false;
cloned[0] = false;
} }
return new BlockMask(getExtent(), cloned); return new BlockMask(getExtent(), cloned);
} }

Some files were not shown because too many files have changed in this diff Show More