commanding-pipeline diff

This commit is contained in:
Jesse Boyd 2019-10-23 05:23:52 +01:00
parent fb91456bdd
commit 2080e9786b
No known key found for this signature in database
GPG Key ID: 59F1DE6293AF6E1F
193 changed files with 5449 additions and 3491 deletions

View File

@ -13,6 +13,7 @@ fun Project.applyCommonConfiguration() {
maven { url = uri("https://oss.sonatype.org/content/repositories/snapshots/") } maven { url = uri("https://oss.sonatype.org/content/repositories/snapshots/") }
maven { url = uri("http://empcraft.com/maven2") } maven { url = uri("http://empcraft.com/maven2") }
maven { url = uri("https://repo.destroystokyo.com/repository/maven-public") } maven { url = uri("https://repo.destroystokyo.com/repository/maven-public") }
maven { url = uri("https://ci.athion.net/job/FAWE-Piston/ws/") }
ivy { url = uri("https://ci.athion.net/job") ivy { url = uri("https://ci.athion.net/job")
patternLayout { patternLayout {
artifact("/[organisation]/[revision]/artifact/[module].[ext]") artifact("/[organisation]/[revision]/artifact/[module].[ext]")
@ -23,4 +24,5 @@ fun Project.applyCommonConfiguration() {
cacheChangingModulesFor(10, "minutes") cacheChangingModulesFor(10, "minutes")
} }
} }
} }

View File

@ -1,7 +1,7 @@
object Versions { object Versions {
const val TEXT = "3.0.1" const val TEXT = "3.0.1"
const val TEXT_EXTRAS = "3.0.2" const val TEXT_EXTRAS = "3.0.2"
const val PISTON = "0.5.2" const val PISTON = "0.5.3-SNAPSHOT"
const val AUTO_VALUE = "1.6.5" const val AUTO_VALUE = "1.6.5"
const val JUNIT = "5.5.0" const val JUNIT = "5.5.0"
const val MOCKITO = "3.0.0" const val MOCKITO = "3.0.0"

View File

@ -36,6 +36,7 @@ dependencies {
"compile"("it.unimi.dsi:fastutil:8.2.1") "compile"("it.unimi.dsi:fastutil:8.2.1")
"api"("com.destroystokyo.paper:paper-api:1.14.4-R0.1-SNAPSHOT") { "api"("com.destroystokyo.paper:paper-api:1.14.4-R0.1-SNAPSHOT") {
exclude("junit", "junit") exclude("junit", "junit")
isTransitive = false
} }
"compileOnly"("org.spigotmc:spigot:1.14.4-R0.1-SNAPSHOT") "compileOnly"("org.spigotmc:spigot:1.14.4-R0.1-SNAPSHOT")
"implementation"("io.papermc:paperlib:1.0.2") "implementation"("io.papermc:paperlib:1.0.2")
@ -58,9 +59,6 @@ dependencies {
"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-API:4.4.0-SNAPSHOT") { isTransitive = false } "implementation"("com.comphenix.protocol:ProtocolLib-API:4.4.0-SNAPSHOT") { isTransitive = false }
"implementation"("com.wasteofplastic:askyblock:3.0.8.2") { isTransitive = false } "implementation"("com.wasteofplastic:askyblock:3.0.8.2") { isTransitive = false }
"compile"("com.github.intellectualsites.plotsquared:PlotSquared-API:latest") {
isTransitive = false
}
} }
tasks.named<Copy>("processResources") { tasks.named<Copy>("processResources") {

View File

@ -2,6 +2,7 @@ package com.boydti.fawe.bukkit;
import com.boydti.fawe.config.BBC; import com.boydti.fawe.config.BBC;
import com.boydti.fawe.object.FaweCommand; import com.boydti.fawe.object.FaweCommand;
import com.sk89q.worldedit.bukkit.BukkitAdapter;
import com.sk89q.worldedit.bukkit.BukkitBlockCommandSender; import com.sk89q.worldedit.bukkit.BukkitBlockCommandSender;
import com.sk89q.worldedit.bukkit.BukkitCommandSender; import com.sk89q.worldedit.bukkit.BukkitCommandSender;
import com.sk89q.worldedit.bukkit.BukkitPlayer; import com.sk89q.worldedit.bukkit.BukkitPlayer;
@ -40,7 +41,7 @@ public class BukkitCommand implements CommandExecutor {
* @return a wrapped player * @return a wrapped player
*/ */
public com.sk89q.worldedit.bukkit.BukkitPlayer wrapPlayer(Player player) { public com.sk89q.worldedit.bukkit.BukkitPlayer wrapPlayer(Player player) {
return new BukkitPlayer(WorldEditPlugin.getInstance(), player); return BukkitAdapter.adapt(player);
} }
public Actor wrapCommandSender(CommandSender sender) { public Actor wrapCommandSender(CommandSender sender) {

View File

@ -18,7 +18,6 @@ import com.boydti.fawe.bukkit.regions.ResidenceFeature;
import com.boydti.fawe.bukkit.regions.TownyFeature; import com.boydti.fawe.bukkit.regions.TownyFeature;
import com.boydti.fawe.bukkit.regions.Worldguard; import com.boydti.fawe.bukkit.regions.Worldguard;
import com.boydti.fawe.bukkit.regions.WorldguardFlag; import com.boydti.fawe.bukkit.regions.WorldguardFlag;
import com.boydti.fawe.bukkit.regions.plotquared.PlotSquaredFeature;
import com.boydti.fawe.bukkit.util.BukkitTaskMan; import com.boydti.fawe.bukkit.util.BukkitTaskMan;
import com.boydti.fawe.bukkit.util.ItemUtil; import com.boydti.fawe.bukkit.util.ItemUtil;
import com.boydti.fawe.bukkit.util.VaultUtil; import com.boydti.fawe.bukkit.util.VaultUtil;
@ -31,6 +30,7 @@ import com.boydti.fawe.util.TaskManager;
import com.boydti.fawe.util.WEManager; import com.boydti.fawe.util.WEManager;
import com.boydti.fawe.util.image.ImageViewer; import com.boydti.fawe.util.image.ImageViewer;
import com.sk89q.worldedit.bukkit.BukkitAdapter; import com.sk89q.worldedit.bukkit.BukkitAdapter;
import com.sk89q.worldedit.bukkit.BukkitPlayer;
import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.World;
import io.papermc.lib.PaperLib; import io.papermc.lib.PaperLib;
import java.io.File; import java.io.File;
@ -84,13 +84,6 @@ public class FaweBukkit implements IFawe, Listener {
if (PaperLib.isPaper() && Settings.IMP.EXPERIMENTAL.DYNAMIC_CHUNK_RENDERING > 1) { if (PaperLib.isPaper() && Settings.IMP.EXPERIMENTAL.DYNAMIC_CHUNK_RENDERING > 1) {
new RenderListener(plugin); new RenderListener(plugin);
} }
if (Bukkit.getPluginManager().getPlugin("PlotSquared") != null) {
try {
WEManager.IMP.managers.add(new PlotSquaredFeature());
} catch (Exception ignored) {
//Not everyone uses or needs PlotSquared.
}
}
} catch (final Throwable e) { } catch (final Throwable e) {
e.printStackTrace(); e.printStackTrace();
Bukkit.getServer().shutdown(); Bukkit.getServer().shutdown();
@ -159,11 +152,6 @@ public class FaweBukkit implements IFawe, Listener {
return null; return null;
} }
@Override
public int getPlayerCount() {
return plugin.getServer().getOnlinePlayers().size();
}
@Override @Override
public boolean isOnlineMode() { public boolean isOnlineMode() {
return Bukkit.getOnlineMode(); return Bukkit.getOnlineMode();
@ -203,25 +191,22 @@ public class FaweBukkit implements IFawe, Listener {
@Override @Override
public com.sk89q.worldedit.entity.Player wrap(final Object obj) { public com.sk89q.worldedit.entity.Player wrap(final Object obj) {
if (obj.getClass() == String.class) { Player player = null;
if (obj.getClass() == Player.class) {
player = (Player) obj;
}
else if (obj.getClass() == String.class) {
String name = (String) obj; String name = (String) obj;
com.sk89q.worldedit.entity.Player existing = Fawe.get().getCachedPlayer(name); player = Bukkit.getPlayer(name);
if (existing != null) {
return existing;
}
Player player = Bukkit.getPlayer(name);
return player != null ? BukkitAdapter.adapt(player) : null;
} }
if (obj.getClass() == UUID.class) { else if (obj.getClass() == UUID.class) {
UUID uuid = (UUID) obj; UUID uuid = (UUID) obj;
com.sk89q.worldedit.entity.Player existing = Fawe.get().getCachedPlayer(uuid); player = Bukkit.getPlayer(uuid);
if (existing != null) {
return existing;
}
Player player = Bukkit.getPlayer(uuid);
return player != null ? BukkitAdapter.adapt(player) : null;
} }
return null; if (player == null) {
throw new IllegalArgumentException("Unknown player type: " + obj);
}
return BukkitAdapter.adapt(player);
} }
@Override public void startMetrics() { @Override public void startMetrics() {
@ -379,12 +364,8 @@ public class FaweBukkit implements IFawe, Listener {
@EventHandler(priority = EventPriority.MONITOR) @EventHandler(priority = EventPriority.MONITOR)
public void onPlayerQuit(PlayerQuitEvent event) { public void onPlayerQuit(PlayerQuitEvent event) {
Player player = event.getPlayer(); Player player = event.getPlayer();
String name = player.getName(); BukkitPlayer wePlayer = BukkitAdapter.adapt(player);
com.sk89q.worldedit.entity.Player wePlayer = Fawe.get().getCachedPlayer(name); wePlayer.unregister();
if (wePlayer != null) {
wePlayer.unregister();
Fawe.get().unregister(name);
}
} }
@Override @Override

View File

@ -1,12 +1,14 @@
package com.boydti.fawe.bukkit.adapter; package com.boydti.fawe.bukkit.adapter;
import com.destroystokyo.paper.util.ReentrantLockWithGetOwner;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock; import java.util.concurrent.locks.ReentrantLock;
public class DelegateLock extends ReentrantLock { public class DelegateLock extends ReentrantLockWithGetOwner {
private final Lock parent; private final Lock parent;
private volatile boolean modified; private volatile boolean modified;
private final AtomicInteger count; private final AtomicInteger count;

View File

@ -37,21 +37,6 @@ import java.util.function.Supplier;
public class BukkitAdapter_1_14 { public class BukkitAdapter_1_14 {
/*
World world = WorldWrapper.unwrap(extent);
if (world == null) throw new IllegalArgumentException("Get must be a world.");
if (world instanceof BukkitWorld) {
this.bukkitWorld = ((BukkitWorld) world).getWorld();
} else {
this.bukkitWorld = Bukkit.getWorld(world.getName());
}
checkNotNull(this.bukkitWorld);
CraftWorld craftWorld = ((CraftWorld) bukkitWorld);
this.nmsWorld = craftWorld.getHandle();
*/
/* /*
NMS fields NMS fields
*/ */
@ -89,15 +74,15 @@ public class BukkitAdapter_1_14 {
fieldDirtyCount = PlayerChunk.class.getDeclaredField("dirtyCount"); fieldDirtyCount = PlayerChunk.class.getDeclaredField("dirtyCount");
fieldDirtyCount.setAccessible(true); fieldDirtyCount.setAccessible(true);
fieldDirtyBits = PlayerChunk.class.getDeclaredField("h"); fieldDirtyBits = PlayerChunk.class.getDeclaredField("r");
fieldDirtyBits.setAccessible(true); fieldDirtyBits.setAccessible(true);
{ {
Field tmp = null; Field tmp = null;
try { try {
tmp = DataPaletteBlock.class.getDeclaredField("j");
} catch (NoSuchFieldException paper) {
tmp = DataPaletteBlock.class.getDeclaredField("writeLock"); tmp = DataPaletteBlock.class.getDeclaredField("writeLock");
} catch (NoSuchFieldException paper) {
tmp = DataPaletteBlock.class.getDeclaredField("j");
} }
fieldLock = tmp; fieldLock = tmp;
fieldLock.setAccessible(true); fieldLock.setAccessible(true);
@ -310,8 +295,8 @@ public class BukkitAdapter_1_14 {
} }
public static void setCount(final int tickingBlockCount, final int nonEmptyBlockCount, final ChunkSection section) throws NoSuchFieldException, IllegalAccessException { public static void setCount(final int tickingBlockCount, final int nonEmptyBlockCount, final ChunkSection section) throws NoSuchFieldException, IllegalAccessException {
fieldFluidCount.set(section, 0); // TODO FIXME fieldFluidCount.setShort(section, (short) 0); // TODO FIXME
fieldTickingBlockCount.set(section, tickingBlockCount); fieldTickingBlockCount.setShort(section, (short) tickingBlockCount);
fieldNonEmptyBlockCount.set(section, nonEmptyBlockCount); fieldNonEmptyBlockCount.setShort(section, (short) nonEmptyBlockCount);
} }
} }

View File

@ -6,8 +6,11 @@ import com.boydti.fawe.beta.IChunkSet;
import com.boydti.fawe.beta.implementation.QueueHandler; import com.boydti.fawe.beta.implementation.QueueHandler;
import com.boydti.fawe.beta.implementation.blocks.CharGetBlocks; import com.boydti.fawe.beta.implementation.blocks.CharGetBlocks;
import com.boydti.fawe.bukkit.adapter.DelegateLock; import com.boydti.fawe.bukkit.adapter.DelegateLock;
import com.boydti.fawe.object.collection.AdaptedMap;
import com.boydti.fawe.object.collection.AdaptedSetCollection;
import com.boydti.fawe.object.collection.BitArray4096; import com.boydti.fawe.object.collection.BitArray4096;
import com.boydti.fawe.util.ReflectionUtils; import com.boydti.fawe.util.ReflectionUtils;
import com.google.common.collect.Iterables;
import com.sk89q.jnbt.CompoundTag; import com.sk89q.jnbt.CompoundTag;
import com.sk89q.jnbt.ListTag; import com.sk89q.jnbt.ListTag;
import com.sk89q.jnbt.LongTag; import com.sk89q.jnbt.LongTag;
@ -17,7 +20,9 @@ import com.sk89q.worldedit.bukkit.BukkitAdapter;
import com.sk89q.worldedit.bukkit.WorldEditPlugin; import com.sk89q.worldedit.bukkit.WorldEditPlugin;
import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter; import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter;
import com.sk89q.worldedit.internal.Constants; import com.sk89q.worldedit.internal.Constants;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.world.biome.BiomeType; import com.sk89q.worldedit.world.biome.BiomeType;
import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.block.BlockTypes; import com.sk89q.worldedit.world.block.BlockTypes;
import net.minecraft.server.v1_14_R1.BiomeBase; import net.minecraft.server.v1_14_R1.BiomeBase;
import net.minecraft.server.v1_14_R1.BlockPosition; import net.minecraft.server.v1_14_R1.BlockPosition;
@ -40,16 +45,13 @@ import org.bukkit.block.Biome;
import org.bukkit.craftbukkit.v1_14_R1.CraftWorld; import org.bukkit.craftbukkit.v1_14_R1.CraftWorld;
import org.bukkit.craftbukkit.v1_14_R1.block.CraftBlock; import org.bukkit.craftbukkit.v1_14_R1.block.CraftBlock;
import org.bukkit.event.entity.CreatureSpawnEvent; import org.bukkit.event.entity.CreatureSpawnEvent;
import org.jetbrains.annotations.NotNull;
import java.util.Arrays; import javax.annotation.Nullable;
import java.util.Collection; import java.util.*;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.Callable; import java.util.concurrent.Callable;
import java.util.concurrent.Future; import java.util.concurrent.Future;
import java.util.function.Function;
public class BukkitGetBlocks_1_14 extends CharGetBlocks { public class BukkitGetBlocks_1_14 extends CharGetBlocks {
public ChunkSection[] sections; public ChunkSection[] sections;
@ -82,10 +84,114 @@ public class BukkitGetBlocks_1_14 extends CharGetBlocks {
@Override @Override
public CompoundTag getTag(int x, int y, int z) { public CompoundTag getTag(int x, int y, int z) {
// TODO TileEntity tile = getChunk().getTileEntity(new BlockPosition((x & 15) + (X << 4), y, (z & 15) + (Z << 4)));
BukkitImplAdapter adapter = WorldEditPlugin.getInstance().getBukkitImplAdapter();
return (CompoundTag) adapter.toNative(tile);
}
private static final Function<BlockPosition, BlockVector3> posNms2We = new Function<BlockPosition, BlockVector3>() {
@Override
public BlockVector3 apply(BlockPosition v) {
return BlockVector3.at(v.getX(), v.getY(), v.getZ());
}
};
private final static Function<TileEntity, CompoundTag> nmsTile2We = new Function<TileEntity, CompoundTag>() {
@Override
public CompoundTag apply(TileEntity tileEntity) {
BukkitImplAdapter adapter = WorldEditPlugin.getInstance().getBukkitImplAdapter();
return (CompoundTag) adapter.toNative(tileEntity.b());
}
};
@Override
public Map<BlockVector3, CompoundTag> getTiles() {
Map<BlockPosition, TileEntity> nmsTiles = getChunk().getTileEntities();
if (nmsTiles.isEmpty()) {
return Collections.emptyMap();
}
return AdaptedMap.immutable(nmsTiles, posNms2We, nmsTile2We);
}
@Override
public CompoundTag getEntity(UUID uuid) {
org.bukkit.entity.Entity bukkitEnt = world.getEntity(uuid);
if (bukkitEnt != null) {
return BukkitAdapter.adapt(bukkitEnt).getState().getNbtData();
}
for (List<Entity> entry : getChunk().getEntitySlices()) {
if (entry != null) {
for (Entity entity : entry) {
if (uuid.equals(entity.getUniqueID())) {
return BukkitAdapter.adapt(bukkitEnt).getState().getNbtData();
}
}
}
}
return null; return null;
} }
@Override
public Set<CompoundTag> getEntities() {
List<Entity>[] slices = getChunk().getEntitySlices();
int size = 0;
for (List<Entity> slice : slices) {
if (slice != null) size += slice.size();
}
if (slices.length == 0) {
return Collections.emptySet();
}
int finalSize = size;
return new AbstractSet<CompoundTag>() {
@Override
public int size() {
return finalSize;
}
@Override
public boolean isEmpty() {
return false;
}
@Override
public boolean contains(Object get) {
if (!(get instanceof CompoundTag)) {
return false;
}
CompoundTag getTag = (CompoundTag) get;
Map<String, Tag> value = getTag.getValue();
CompoundTag getParts = (CompoundTag) value.get("UUID");
UUID getUUID = new UUID(getParts.getLong("Most"), getParts.getLong("Least"));
for (List<Entity> slice : slices) {
if (slice != null) {
for (Entity entity : slice) {
UUID uuid = entity.getUniqueID();
if (uuid.equals(getUUID)) {
return true;
}
}
}
}
return false;
}
@NotNull
@Override
public Iterator<CompoundTag> iterator() {
Iterable<CompoundTag> result = Iterables.transform(Iterables.concat(slices), new com.google.common.base.Function<Entity, CompoundTag>() {
@Nullable
@Override
public CompoundTag apply(@Nullable Entity input) {
BukkitImplAdapter adapter = WorldEditPlugin.getInstance().getBukkitImplAdapter();
NBTTagCompound tag = new NBTTagCompound();
return (CompoundTag) adapter.toNative(input.save(tag));
}
});
return result.iterator();
}
};
}
@Override @Override
public char[] load(int layer) { public char[] load(int layer) {
return load(layer, null); return load(layer, null);
@ -120,7 +226,6 @@ public class BukkitGetBlocks_1_14 extends CharGetBlocks {
Chunk nmsChunk = BukkitAdapter_1_14.ensureLoaded(nmsWorld, X, Z); Chunk nmsChunk = BukkitAdapter_1_14.ensureLoaded(nmsWorld, X, Z);
// Remove existing tiles // Remove existing tiles
{ {
Map<BlockPosition, TileEntity> tiles = nmsChunk.getTileEntities(); Map<BlockPosition, TileEntity> tiles = nmsChunk.getTileEntities();
if (!tiles.isEmpty()) { if (!tiles.isEmpty()) {
@ -299,19 +404,19 @@ public class BukkitGetBlocks_1_14 extends CharGetBlocks {
} }
// set tiles // set tiles
Map<Short, CompoundTag> tiles = set.getTiles(); Map<BlockVector3, CompoundTag> tiles = set.getTiles();
if (tiles != null && !tiles.isEmpty()) { if (tiles != null && !tiles.isEmpty()) {
if (syncTasks == null) syncTasks = new Runnable[1]; if (syncTasks == null) syncTasks = new Runnable[1];
syncTasks[0] = new Runnable() { syncTasks[0] = new Runnable() {
@Override @Override
public void run() { public void run() {
for (final Map.Entry<Short, CompoundTag> entry : tiles.entrySet()) { for (final Map.Entry<BlockVector3, CompoundTag> entry : tiles.entrySet()) {
final CompoundTag nativeTag = entry.getValue(); final CompoundTag nativeTag = entry.getValue();
final short blockHash = entry.getKey(); final BlockVector3 blockHash = entry.getKey();
final int x = (blockHash >> 12 & 0xF) + bx; final int x = blockHash.getX()+ bx;
final int y = (blockHash & 0xFF); final int y = blockHash.getY();
final int z = (blockHash >> 8 & 0xF) + bz; final int z = blockHash.getZ() + bz;
final BlockPosition pos = new BlockPosition(x, y, z); final BlockPosition pos = new BlockPosition(x, y, z);
synchronized (nmsWorld) { synchronized (nmsWorld) {
TileEntity tileEntity = nmsWorld.getTileEntity(pos); TileEntity tileEntity = nmsWorld.getTileEntity(pos);

View File

@ -0,0 +1,138 @@
package com.boydti.fawe.bukkit.adapter.mc1_14.nbt;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.jnbt.ListTag;
import com.sk89q.jnbt.StringTag;
import com.sk89q.jnbt.Tag;
import com.sk89q.worldedit.bukkit.WorldEditPlugin;
import net.minecraft.server.v1_14_R1.NBTBase;
import net.minecraft.server.v1_14_R1.NBTNumber;
import net.minecraft.server.v1_14_R1.NBTTagCompound;
import net.minecraft.server.v1_14_R1.NBTTagList;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
public class LazyCompoundTag_1_14 extends CompoundTag {
private final NBTTagCompound nmsTag;
public LazyCompoundTag_1_14(NBTTagCompound tag) {
super(null);
this.nmsTag = tag;
}
@Override
public Map<String, Tag> getValue() {
Map<String, Tag> value = super.getValue();
if (value == null) {
Tag tag = WorldEditPlugin.getInstance().getBukkitImplAdapter().toNative(nmsTag);
setValue(((CompoundTag) tag).getValue());
}
return super.getValue();
}
public boolean containsKey(String key) {
return nmsTag.hasKey(key);
}
public byte[] getByteArray(String key) {
return nmsTag.getByteArray(key);
}
public byte getByte(String key) {
return nmsTag.getByte(key);
}
public double getDouble(String key) {
return nmsTag.getDouble(key);
}
public double asDouble(String key) {
NBTBase value = nmsTag.get(key);
if (value instanceof NBTNumber) {
return ((NBTNumber) value).asDouble();
}
return 0;
}
public float getFloat(String key) {
return nmsTag.getFloat(key);
}
public int[] getIntArray(String key) {
return nmsTag.getIntArray(key);
}
public int getInt(String key) {
return nmsTag.getInt(key);
}
public int asInt(String key) {
NBTBase value = nmsTag.get(key);
if (value instanceof NBTNumber) {
return ((NBTNumber) value).asInt();
}
return 0;
}
public List<Tag> getList(String key) {
NBTBase tag = nmsTag.get(key);
if (tag instanceof NBTTagList) {
ArrayList<Tag> list = new ArrayList<>();
NBTTagList nbtList = (NBTTagList) tag;
for (NBTBase elem : nbtList) {
if (elem instanceof NBTTagCompound) {
list.add(new LazyCompoundTag_1_14((NBTTagCompound) elem));
} else {
list.add(WorldEditPlugin.getInstance().getBukkitImplAdapter().toNative(elem));
}
}
return list;
}
return Collections.emptyList();
}
public ListTag getListTag(String key) {
NBTBase tag = nmsTag.get(key);
if (tag instanceof NBTTagList) {
return (ListTag) WorldEditPlugin.getInstance().getBukkitImplAdapter().toNative(tag);
}
return new ListTag(StringTag.class, Collections.<Tag>emptyList());
}
@SuppressWarnings("unchecked")
public <T extends Tag> List<T> getList(String key, Class<T> listType) {
ListTag listTag = getListTag(key);
if (listTag.getType().equals(listType)) {
return (List<T>) listTag.getValue();
} else {
return Collections.emptyList();
}
}
public long[] getLongArray(String key) {
return nmsTag.getLongArray(key);
}
public long getLong(String key) {
return nmsTag.getLong(key);
}
public long asLong(String key) {
NBTBase value = nmsTag.get(key);
if (value instanceof NBTNumber) {
return ((NBTNumber) value).asLong();
}
return 0;
}
public short getShort(String key) {
return nmsTag.getShort(key);
}
public String getString(String key) {
return nmsTag.getString(key);
}
}

View File

@ -96,8 +96,7 @@ public class RenderListener implements Listener {
} }
} }
} }
throw new UnsupportedOperationException("TODO FIXME: PAPER 1.14"); player.setViewDistance(value);
// player.setViewDistance(value);
} }
private int getViewDistance(Player player) { private int getViewDistance(Player player) {

View File

@ -0,0 +1,11 @@
package com.destroystokyo.paper.util;
import java.util.concurrent.locks.ReentrantLock;
public class ReentrantLockWithGetOwner extends ReentrantLock {
@Override
public Thread getOwner() {
return super.getOwner();
}
}

View File

@ -21,6 +21,8 @@ package com.sk89q.worldedit.bukkit;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
import com.boydti.fawe.Fawe;
import com.boydti.fawe.wrappers.PlayerWrapper;
import com.sk89q.worldedit.NotABlockException; import com.sk89q.worldedit.NotABlockException;
import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.blocks.BaseItemStack; import com.sk89q.worldedit.blocks.BaseItemStack;
@ -29,6 +31,7 @@ import com.sk89q.worldedit.bukkit.adapter.IBukkitAdapter;
import com.sk89q.worldedit.bukkit.adapter.SimpleBukkitAdapter; import com.sk89q.worldedit.bukkit.adapter.SimpleBukkitAdapter;
import com.sk89q.worldedit.entity.Entity; import com.sk89q.worldedit.entity.Entity;
import com.sk89q.worldedit.extension.input.ParserContext; import com.sk89q.worldedit.extension.input.ParserContext;
import com.sk89q.worldedit.extension.platform.PlayerProxy;
import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.math.Vector3; import com.sk89q.worldedit.math.Vector3;
import com.sk89q.worldedit.util.Location; import com.sk89q.worldedit.util.Location;
@ -92,7 +95,7 @@ public enum BukkitAdapter {
* @return If they are equal * @return If they are equal
*/ */
public static boolean equals(BlockType blockType, Material type) { public static boolean equals(BlockType blockType, Material type) {
return Objects.equals(blockType.getId(), type.getKey().toString()); return getAdapter().equals(blockType, type);
} }
/** /**
@ -105,15 +108,7 @@ public enum BukkitAdapter {
* @return a wrapped Bukkit world * @return a wrapped Bukkit world
*/ */
public static BukkitWorld asBukkitWorld(World world) { public static BukkitWorld asBukkitWorld(World world) {
if (world instanceof BukkitWorld) { return getAdapter().asBukkitWorld(world);
return (BukkitWorld) world;
} else {
BukkitWorld bukkitWorld = WorldEditPlugin.getInstance().getInternalPlatform().matchWorld(world);
if (bukkitWorld == null) {
throw new RuntimeException("World '" + world.getName() + "' has no matching version in Bukkit");
}
return bukkitWorld;
}
} }
/** /**
@ -123,8 +118,7 @@ public enum BukkitAdapter {
* @return a WorldEdit world * @return a WorldEdit world
*/ */
public static World adapt(org.bukkit.World world) { public static World adapt(org.bukkit.World world) {
checkNotNull(world); return getAdapter().adapt(world);
return new BukkitWorld(world);
} }
/** /**
@ -144,6 +138,7 @@ public enum BukkitAdapter {
* @return The Bukkit player * @return The Bukkit player
*/ */
public static Player adapt(com.sk89q.worldedit.entity.Player player) { public static Player adapt(com.sk89q.worldedit.entity.Player player) {
player = PlayerProxy.unwrap(player);
return ((BukkitPlayer) player).getPlayer(); return ((BukkitPlayer) player).getPlayer();
} }
@ -154,17 +149,7 @@ public enum BukkitAdapter {
* @return a Bukkit world * @return a Bukkit world
*/ */
public static org.bukkit.World adapt(World world) { public static org.bukkit.World adapt(World world) {
checkNotNull(world); return getAdapter().adapt(world);
if (world instanceof BukkitWorld) {
return ((BukkitWorld) world).getWorld();
} else {
org.bukkit.World match = Bukkit.getServer().getWorld(world.getName());
if (match != null) {
return match;
} else {
throw new IllegalArgumentException("Can't find a Bukkit world for " + world.getName());
}
}
} }
/** /**
@ -275,8 +260,7 @@ public enum BukkitAdapter {
* @return a WorldEdit entity * @return a WorldEdit entity
*/ */
public static Entity adapt(org.bukkit.entity.Entity entity) { public static Entity adapt(org.bukkit.entity.Entity entity) {
checkNotNull(entity); return getAdapter().adapt(entity);
return new BukkitEntity(entity);
} }
/** /**
@ -286,11 +270,7 @@ public enum BukkitAdapter {
* @return The Bukkit Material * @return The Bukkit Material
*/ */
public static Material adapt(ItemType itemType) { public static Material adapt(ItemType itemType) {
checkNotNull(itemType); return getAdapter().adapt(itemType);
if (!itemType.getId().startsWith("minecraft:")) {
throw new IllegalArgumentException("Bukkit only supports Minecraft items");
}
return Material.getMaterial(itemType.getId().substring(10).toUpperCase(Locale.ROOT));
} }
/** /**
@ -300,11 +280,7 @@ public enum BukkitAdapter {
* @return The Bukkit Material * @return The Bukkit Material
*/ */
public static Material adapt(BlockType blockType) { public static Material adapt(BlockType blockType) {
checkNotNull(blockType); return getAdapter().adapt(blockType);
if (!blockType.getId().startsWith("minecraft:")) {
throw new IllegalArgumentException("Bukkit only supports Minecraft blocks");
}
return Material.getMaterial(blockType.getId().substring(10).toUpperCase(Locale.ROOT));
} }
/** /**
@ -314,8 +290,7 @@ public enum BukkitAdapter {
* @return WorldEdit GameMode * @return WorldEdit GameMode
*/ */
public static GameMode adapt(org.bukkit.GameMode gameMode) { public static GameMode adapt(org.bukkit.GameMode gameMode) {
checkNotNull(gameMode); return getAdapter().adapt(gameMode);
return GameModes.get(gameMode.name().toLowerCase(Locale.ROOT));
} }
/** /**
@ -325,18 +300,11 @@ public enum BukkitAdapter {
* @return WorldEdit BiomeType * @return WorldEdit BiomeType
*/ */
public static BiomeType adapt(Biome biome) { public static BiomeType adapt(Biome biome) {
return BiomeTypes.get(biome.name().toLowerCase(Locale.ROOT)); return getAdapter().adapt(biome);
} }
public static Biome adapt(BiomeType biomeType) { public static Biome adapt(BiomeType biomeType) {
if (!biomeType.getId().startsWith("minecraft:")) { return getAdapter().adapt(biomeType);
throw new IllegalArgumentException("Bukkit only supports vanilla biomes");
}
try {
return Biome.valueOf(biomeType.getId().substring(10).toUpperCase(Locale.ROOT));
} catch (IllegalArgumentException e) {
return null;
}
} }
/** /**
@ -346,18 +314,11 @@ public enum BukkitAdapter {
* @return WorldEdit EntityType * @return WorldEdit EntityType
*/ */
public static EntityType adapt(org.bukkit.entity.EntityType entityType) { public static EntityType adapt(org.bukkit.entity.EntityType entityType) {
final String name = entityType.getName(); return getAdapter().adapt(entityType);
if (name == null) {
return null;
}
return EntityTypes.get(name.toLowerCase(Locale.ROOT));
} }
public static org.bukkit.entity.EntityType adapt(EntityType entityType) { public static org.bukkit.entity.EntityType adapt(EntityType entityType) {
if (!entityType.getId().startsWith("minecraft:")) { return getAdapter().adapt(entityType);
throw new IllegalArgumentException("Bukkit only supports vanilla entities");
}
return org.bukkit.entity.EntityType.fromName(entityType.getId().substring(10));
} }
/** /**
@ -367,11 +328,7 @@ public enum BukkitAdapter {
* @return The blocktype * @return The blocktype
*/ */
public static BlockType asBlockType(Material material) { public static BlockType asBlockType(Material material) {
checkNotNull(material); return getAdapter().asBlockType(material);
if (!material.isBlock()) {
throw new IllegalArgumentException(material.getKey().toString() + " is not a block!");
}
return BlockTypes.get(material.getKey().toString());
} }
/** /**
@ -381,14 +338,11 @@ public enum BukkitAdapter {
* @return The itemtype * @return The itemtype
*/ */
public static ItemType asItemType(Material material) { public static ItemType asItemType(Material material) {
checkNotNull(material); return getAdapter().asItemType(material);
if (!material.isItem()) {
throw new IllegalArgumentException(material.getKey().toString() + " is not an item!");
}
return ItemTypes.get(material.getKey().toString());
} }
/*
private static Map<String, BlockState> blockStateCache = new HashMap<>(); private static Map<String, BlockState> blockStateCache = new HashMap<>();
/*
/** /**
* Create a WorldEdit BlockState from a Bukkit BlockData * Create a WorldEdit BlockState from a Bukkit BlockData
@ -403,9 +357,9 @@ public enum BukkitAdapter {
public static BlockType adapt(Material material) { public static BlockType adapt(Material material) {
return getAdapter().adapt(material); return getAdapter().adapt(material);
} }
/*
private static Map<String, BlockData> blockDataCache = new HashMap<>(); private static Map<String, BlockData> blockDataCache = new HashMap<>();
*/
/** /**
* Create a Bukkit BlockData from a WorldEdit BlockStateHolder * Create a Bukkit BlockData from a WorldEdit BlockStateHolder
* *
@ -423,12 +377,7 @@ public enum BukkitAdapter {
* @return The WorldEdit BlockState * @return The WorldEdit BlockState
*/ */
public static BlockState asBlockState(ItemStack itemStack) throws WorldEditException { public static BlockState asBlockState(ItemStack itemStack) throws WorldEditException {
checkNotNull(itemStack); return getAdapter().asBlockState(itemStack);
if (itemStack.getType().isBlock()) {
return adapt(itemStack.getType().createBlockData());
} else {
throw new NotABlockException();
}
} }
/** /**
@ -438,11 +387,7 @@ public enum BukkitAdapter {
* @return The WorldEdit BaseItemStack * @return The WorldEdit BaseItemStack
*/ */
public static BaseItemStack adapt(ItemStack itemStack) { public static BaseItemStack adapt(ItemStack itemStack) {
checkNotNull(itemStack); return getAdapter().adapt(itemStack);
if (WorldEditPlugin.getInstance().getBukkitImplAdapter() != null) {
return WorldEditPlugin.getInstance().getBukkitImplAdapter().adapt(itemStack);
}
return new BaseItemStack(ItemTypes.get(itemStack.getType().getKey().toString()), itemStack.getAmount());
} }
/** /**
@ -452,10 +397,6 @@ public enum BukkitAdapter {
* @return The Bukkit ItemStack * @return The Bukkit ItemStack
*/ */
public static ItemStack adapt(BaseItemStack item) { public static ItemStack adapt(BaseItemStack item) {
checkNotNull(item); return getAdapter().adapt(item);
if (WorldEditPlugin.getInstance().getBukkitImplAdapter() != null) {
return WorldEditPlugin.getInstance().getBukkitImplAdapter().adapt(item);
}
return new ItemStack(adapt(item.getType()), item.getAmount());
} }
} }

View File

@ -31,6 +31,7 @@ import com.sk89q.worldedit.blocks.BaseItemStack;
import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter; import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter;
import com.sk89q.worldedit.entity.BaseEntity; import com.sk89q.worldedit.entity.BaseEntity;
import com.sk89q.worldedit.extension.platform.AbstractPlayerActor; import com.sk89q.worldedit.extension.platform.AbstractPlayerActor;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.extent.inventory.BlockBag; import com.sk89q.worldedit.extent.inventory.BlockBag;
import com.sk89q.worldedit.internal.cui.CUIEvent; import com.sk89q.worldedit.internal.cui.CUIEvent;
import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.math.BlockVector3;
@ -73,7 +74,6 @@ public class BukkitPlayer extends AbstractPlayerActor {
public BukkitPlayer(WorldEditPlugin plugin, Player player) { public BukkitPlayer(WorldEditPlugin plugin, Player player) {
this.plugin = plugin; this.plugin = plugin;
this.player = player; this.player = player;
Fawe.get().register(this);
if (Settings.IMP.CLIPBOARD.USE_DISK) { if (Settings.IMP.CLIPBOARD.USE_DISK) {
loadClipboardFromDisk(); loadClipboardFromDisk();
} }
@ -176,8 +176,15 @@ public class BukkitPlayer extends AbstractPlayerActor {
@Override @Override
public void setPosition(Vector3 pos, float pitch, float yaw) { public void setPosition(Vector3 pos, float pitch, float yaw) {
player.teleport(new Location(player.getWorld(), pos.getX(), pos.getY(), org.bukkit.World world = player.getWorld();
pos.getZ(), yaw, pitch)); if (pos instanceof com.sk89q.worldedit.util.Location) {
com.sk89q.worldedit.util.Location loc = (com.sk89q.worldedit.util.Location) pos;
Extent extent = loc.getExtent();
if (extent instanceof World) {
world = Bukkit.getWorld(((World) extent).getName());
}
}
player.teleport(new Location(world, pos.getX(), pos.getY(), pos.getZ(), yaw, pitch));
} }
@Override @Override

View File

@ -19,17 +19,19 @@
package com.sk89q.worldedit.bukkit; package com.sk89q.worldedit.bukkit;
import com.sk89q.worldedit.blocks.BaseItem;
import com.sk89q.worldedit.blocks.BaseItemStack; import com.sk89q.worldedit.blocks.BaseItemStack;
import com.sk89q.worldedit.extent.inventory.BlockBag; import com.sk89q.worldedit.extent.inventory.BlockBag;
import com.sk89q.worldedit.extent.inventory.BlockBagException; import com.sk89q.worldedit.extent.inventory.BlockBagException;
import com.sk89q.worldedit.extent.inventory.OutOfBlocksException; import com.sk89q.worldedit.extent.inventory.OutOfBlocksException;
import com.sk89q.worldedit.extent.inventory.OutOfSpaceException; import com.sk89q.worldedit.extent.inventory.OutOfSpaceException;
import com.sk89q.worldedit.extent.inventory.SlottableBlockBag;
import com.sk89q.worldedit.util.Location; import com.sk89q.worldedit.util.Location;
import com.sk89q.worldedit.world.block.BlockState; import com.sk89q.worldedit.world.block.BlockState;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
public class BukkitPlayerBlockBag extends BlockBag { public class BukkitPlayerBlockBag extends BlockBag implements SlottableBlockBag {
private Player player; private Player player;
private ItemStack[] items; private ItemStack[] items;
@ -180,4 +182,17 @@ public class BukkitPlayerBlockBag extends BlockBag {
public void addSingleSourcePosition(Location pos) { public void addSingleSourcePosition(Location pos) {
} }
@Override
public BaseItem getItem(int slot) {
loadInventory();
return BukkitAdapter.adapt(items[slot]);
}
@Override
public void setItem(int slot, BaseItem block) {
loadInventory();
BaseItemStack stack = block instanceof BaseItemStack ? (BaseItemStack) block : new BaseItemStack(block.getType(), block.getNbtData(), 1);
items[slot] = BukkitAdapter.adapt(stack);
}
} }

View File

@ -22,6 +22,7 @@ package com.sk89q.worldedit.bukkit;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
import static com.sk89q.worldedit.internal.anvil.ChunkDeleter.DELCHUNKS_FILE_NAME; import static com.sk89q.worldedit.internal.anvil.ChunkDeleter.DELCHUNKS_FILE_NAME;
import com.bekvon.bukkit.residence.commands.message;
import com.boydti.fawe.Fawe; import com.boydti.fawe.Fawe;
import com.boydti.fawe.bukkit.FaweBukkit; import com.boydti.fawe.bukkit.FaweBukkit;
import com.boydti.fawe.bukkit.adapter.mc1_14.Spigot_v1_14_R4; import com.boydti.fawe.bukkit.adapter.mc1_14.Spigot_v1_14_R4;
@ -84,6 +85,8 @@ import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority; import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener; import org.bukkit.event.Listener;
import org.bukkit.event.world.WorldInitEvent; import org.bukkit.event.world.WorldInitEvent;
import org.bukkit.metadata.FixedMetadataValue;
import org.bukkit.metadata.MetadataValue;
import org.bukkit.plugin.Plugin; import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.PluginDescriptionFile; import org.bukkit.plugin.PluginDescriptionFile;
import org.bukkit.plugin.PluginManager; import org.bukkit.plugin.PluginManager;
@ -311,28 +314,33 @@ public class WorldEditPlugin extends JavaPlugin { //implements TabCompleter
Field descriptionField = JavaPlugin.class.getDeclaredField("dataFolder"); Field descriptionField = JavaPlugin.class.getDeclaredField("dataFolder");
descriptionField.setAccessible(true); descriptionField.setAccessible(true);
descriptionField.set(this, dir); descriptionField.set(this, dir);
} catch (Throwable throwable) { } catch (Throwable e) {
throwable.printStackTrace(); e.printStackTrace();
} }
File pluginsFolder = MainUtil.getJarFile().getParentFile(); try {
for (File file : pluginsFolder.listFiles()) { File pluginsFolder = MainUtil.getJarFile().getParentFile();
if (file.length() == 2009) return;
} for (File file : pluginsFolder.listFiles()) {
Plugin plugin = Bukkit.getPluginManager().getPlugin("FastAsyncWorldEdit"); if (file.length() == 2009) return;
File dummy = MainUtil.copyFile(MainUtil.getJarFile(), "DummyFawe.src", pluginsFolder, "DummyFawe.jar");
if (dummy != null && dummy.exists() && plugin == this) {
try {
Bukkit.getPluginManager().loadPlugin(dummy);
} catch (Throwable e) {
if (Bukkit.getUpdateFolderFile().mkdirs()) {
MainUtil.copyFile(MainUtil.getJarFile(), "DummyFawe.src", pluginsFolder, Bukkit.getUpdateFolder() + File.separator + "DummyFawe.jar");
} else {
getLogger().info("Please delete DummyFawe.jar and restart");
}
} }
getLogger().info("Please restart the server if you have any plugins which depend on FAWE."); Plugin plugin = Bukkit.getPluginManager().getPlugin("FastAsyncWorldEdit");
} else if (dummy == null) { File dummy = MainUtil.copyFile(MainUtil.getJarFile(), "DummyFawe.src", pluginsFolder, "DummyFawe.jar");
MainUtil.copyFile(MainUtil.getJarFile(), "DummyFawe.src", pluginsFolder, "update" + File.separator + "DummyFawe.jar"); if (dummy != null && dummy.exists() && plugin == this) {
try {
Bukkit.getPluginManager().loadPlugin(dummy);
} catch (Throwable e) {
if (Bukkit.getUpdateFolderFile().mkdirs()) {
MainUtil.copyFile(MainUtil.getJarFile(), "DummyFawe.src", pluginsFolder, Bukkit.getUpdateFolder() + File.separator + "DummyFawe.jar");
} else {
getLogger().info("Please delete DummyFawe.jar and restart");
}
}
getLogger().info("Please restart the server if you have any plugins which depend on FAWE.");
} else if (dummy == null) {
MainUtil.copyFile(MainUtil.getJarFile(), "DummyFawe.src", pluginsFolder, "update" + File.separator + "DummyFawe.jar");
}
} catch (Throwable e) {
e.printStackTrace();
} }
} }
@ -458,7 +466,7 @@ public class WorldEditPlugin extends JavaPlugin { //implements TabCompleter
// code of WorldEdit expects it // code of WorldEdit expects it
String[] split = new String[args.length + 1]; String[] split = new String[args.length + 1];
System.arraycopy(args, 0, split, 1, args.length); System.arraycopy(args, 0, split, 1, args.length);
split[0] = "/" + commandLabel; split[0] = commandLabel;
CommandEvent event = new CommandEvent(wrapCommandSender(sender), Joiner.on(" ").join(split)); CommandEvent event = new CommandEvent(wrapCommandSender(sender), Joiner.on(" ").join(split));
getWorldEdit().getEventBus().post(event); getWorldEdit().getEventBus().post(event);
@ -551,7 +559,15 @@ public class WorldEditPlugin extends JavaPlugin { //implements TabCompleter
* @return a wrapped player * @return a wrapped player
*/ */
public BukkitPlayer wrapPlayer(Player player) { public BukkitPlayer wrapPlayer(Player player) {
return new BukkitPlayer(this, player); synchronized (player) {
@NotNull List<MetadataValue> meta = player.getMetadata("WE");
if (meta == null || meta.isEmpty()) {
BukkitPlayer wePlayer = new BukkitPlayer(this, player);
player.setMetadata("WE", new FixedMetadataValue(this, wePlayer));
return wePlayer;
}
return (BukkitPlayer) meta.get(0).value();
}
} }
public Actor wrapCommandSender(CommandSender sender) { public Actor wrapCommandSender(CommandSender sender) {

View File

@ -48,7 +48,7 @@ public abstract class CachedBukkitAdapter implements IBukkitAdapter {
@Override @Override
public ItemType asItemType(Material material) { public ItemType asItemType(Material material) {
try { try {
return ItemTypes.get(material.getKey().getKey()); return ItemTypes.get(itemTypes[material.ordinal()]);
} catch (NullPointerException e) { } catch (NullPointerException e) {
if (init()) return asItemType(material); if (init()) return asItemType(material);
return ItemTypes.get(itemTypes[material.ordinal()]); return ItemTypes.get(itemTypes[material.ordinal()]);

View File

@ -2,6 +2,7 @@ package com.sk89q.worldedit.bukkit.adapter;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
import com.sk89q.worldedit.NotABlockException;
import com.sk89q.worldedit.blocks.BaseItemStack; import com.sk89q.worldedit.blocks.BaseItemStack;
import com.sk89q.worldedit.bukkit.BukkitEntity; import com.sk89q.worldedit.bukkit.BukkitEntity;
import com.sk89q.worldedit.bukkit.BukkitItemStack; import com.sk89q.worldedit.bukkit.BukkitItemStack;
@ -20,6 +21,9 @@ import com.sk89q.worldedit.world.block.BlockStateHolder;
import com.sk89q.worldedit.world.block.BlockType; import com.sk89q.worldedit.world.block.BlockType;
import com.sk89q.worldedit.world.block.BlockTypes; import com.sk89q.worldedit.world.block.BlockTypes;
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.gamemode.GameMode;
import com.sk89q.worldedit.world.gamemode.GameModes;
import com.sk89q.worldedit.world.item.ItemType; import com.sk89q.worldedit.world.item.ItemType;
import java.util.Locale; import java.util.Locale;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
@ -280,4 +284,62 @@ public interface IBukkitAdapter {
default BiomeType adapt(Biome biome) { default BiomeType adapt(Biome biome) {
return BiomeTypes.get(biome.name().toLowerCase(Locale.ROOT)); return BiomeTypes.get(biome.name().toLowerCase(Locale.ROOT));
} }
/**
* Checks equality between a WorldEdit BlockType and a Bukkit Material
*
* @param blockType The WorldEdit BlockType
* @param type The Bukkit Material
* @return If they are equal
*/
default boolean equals(BlockType blockType, Material type) {
return blockType == asItemType(type).getBlockType();
}
/**
* Create a WorldEdit world from a Bukkit world.
*
* @param world the Bukkit world
* @return a WorldEdit world
*/
default World adapt(org.bukkit.World world) {
checkNotNull(world);
return new BukkitWorld(world);
}
/**
* Create a WorldEdit GameMode from a Bukkit one.
*
* @param gameMode Bukkit GameMode
* @return WorldEdit GameMode
*/
default GameMode adapt(org.bukkit.GameMode gameMode) {
checkNotNull(gameMode);
return GameModes.get(gameMode.name().toLowerCase(Locale.ROOT));
}
/**
* Create a WorldEdit EntityType from a Bukkit one.
*
* @param entityType Bukkit EntityType
* @return WorldEdit EntityType
*/
default EntityType adapt(org.bukkit.entity.EntityType entityType) {
return EntityTypes.get(entityType.getName().toLowerCase(Locale.ROOT));
}
/**
* Create a WorldEdit BlockStateHolder from a Bukkit ItemStack
*
* @param itemStack The Bukkit ItemStack
* @return The WorldEdit BlockState
*/
default BlockState asBlockState(ItemStack itemStack) {
checkNotNull(itemStack);
if (itemStack.getType().isBlock()) {
return adapt(itemStack.getType().createBlockData());
} else {
throw new NotABlockException();
}
}
} }

View File

@ -29,7 +29,6 @@ dependencies {
"compile"("org.slf4j:slf4j-api:1.7.26") "compile"("org.slf4j:slf4j-api:1.7.26")
"compile"("it.unimi.dsi:fastutil:8.2.1") "compile"("it.unimi.dsi:fastutil:8.2.1")
"compile"("com.googlecode.json-simple:json-simple:1.1.1") { isTransitive = false } "compile"("com.googlecode.json-simple:json-simple:1.1.1") { isTransitive = false }
"compileOnly"(project(":worldedit-libs:core:ap")) "compileOnly"(project(":worldedit-libs:core:ap"))
"annotationProcessor"(project(":worldedit-libs:core:ap")) "annotationProcessor"(project(":worldedit-libs:core:ap"))
// ensure this is on the classpath for the AP // ensure this is on the classpath for the AP

View File

@ -4,6 +4,7 @@ import com.boydti.fawe.beta.implementation.QueueHandler;
import com.boydti.fawe.config.BBC; import com.boydti.fawe.config.BBC;
import com.boydti.fawe.config.Settings; import com.boydti.fawe.config.Settings;
import com.boydti.fawe.object.brush.visualization.VisualQueue; import com.boydti.fawe.object.brush.visualization.VisualQueue;
import com.boydti.fawe.regions.general.integrations.plotquared.PlotSquaredFeature;
import com.boydti.fawe.util.CachedTextureUtil; import com.boydti.fawe.util.CachedTextureUtil;
import com.boydti.fawe.util.CleanTextureUtil; import com.boydti.fawe.util.CleanTextureUtil;
import com.boydti.fawe.util.FaweTimer; import com.boydti.fawe.util.FaweTimer;
@ -185,6 +186,7 @@ public class Fawe {
transformParser = new DefaultTransformParser(getWorldEdit()); transformParser = new DefaultTransformParser(getWorldEdit());
visualQueue = new VisualQueue(3); visualQueue = new VisualQueue(3);
WEManager.IMP.managers.addAll(Fawe.this.IMP.getMaskManagers()); WEManager.IMP.managers.addAll(Fawe.this.IMP.getMaskManagers());
WEManager.IMP.managers.add(new PlotSquaredFeature());
Fawe.debug("Plugin 'PlotSquared' found. Using it now."); Fawe.debug("Plugin 'PlotSquared' found. Using it now.");
} catch (Throwable ignored) {} } catch (Throwable ignored) {}
try { try {
@ -429,30 +431,4 @@ public class Fawe {
public Thread setMainThread() { public Thread setMainThread() {
return this.thread = Thread.currentThread(); return this.thread = Thread.currentThread();
} }
private ConcurrentHashMap<String, Player> players = new ConcurrentHashMap<>(8, 0.9f, 1);
private ConcurrentHashMap<UUID, Player> playersUUID = new ConcurrentHashMap<>(8, 0.9f, 1);
public <T> void register(Player player) {
players.put(player.getName(), player);
playersUUID.put(player.getUniqueId(), player);
}
public <T> void unregister(String name) {
Player player = players.remove(name);
if (player != null) playersUUID.remove(player.getUniqueId());
}
public Player getCachedPlayer(String name) {
return players.get(name);
}
public Player getCachedPlayer(UUID uuid) {
return playersUUID.get(uuid);
}
public Collection<Player> getCachedPlayers() {
return players.values();
}
} }

View File

@ -3,7 +3,7 @@ package com.boydti.fawe;
import com.boydti.fawe.beta.Trimable; import com.boydti.fawe.beta.Trimable;
import com.boydti.fawe.config.Settings; import com.boydti.fawe.config.Settings;
import com.boydti.fawe.object.collection.BitArray4096; import com.boydti.fawe.object.collection.BitArray4096;
import com.boydti.fawe.object.collection.IterableThreadLocal; import com.boydti.fawe.object.collection.CleanableThreadLocal;
import com.boydti.fawe.util.IOUtil; import com.boydti.fawe.util.IOUtil;
import com.boydti.fawe.util.MathMan; import com.boydti.fawe.util.MathMan;
import com.sk89q.jnbt.ByteArrayTag; import com.sk89q.jnbt.ByteArrayTag;
@ -53,7 +53,7 @@ public enum FaweCache implements Trimable {
public final char[] EMPTY_CHAR_4096 = new char[4096]; public final char[] EMPTY_CHAR_4096 = new char[4096];
private final IdentityHashMap<Class, IterableThreadLocal> REGISTERED_SINGLETONS = new IdentityHashMap<>(); private final IdentityHashMap<Class, CleanableThreadLocal> REGISTERED_SINGLETONS = new IdentityHashMap<>();
private final IdentityHashMap<Class, Pool> REGISTERED_POOLS = new IdentityHashMap<>(); private final IdentityHashMap<Class, Pool> REGISTERED_POOLS = new IdentityHashMap<>();
public interface Pool<T> { public interface Pool<T> {
@ -108,7 +108,7 @@ public enum FaweCache implements Trimable {
MUTABLE_VECTOR3.clean(); MUTABLE_VECTOR3.clean();
MUTABLE_BLOCKVECTOR3.clean(); MUTABLE_BLOCKVECTOR3.clean();
SECTION_BITS_TO_CHAR.clean(); SECTION_BITS_TO_CHAR.clean();
for (Map.Entry<Class, IterableThreadLocal> entry : REGISTERED_SINGLETONS.entrySet()) { for (Map.Entry<Class, CleanableThreadLocal> entry : REGISTERED_SINGLETONS.entrySet()) {
entry.getValue().clean(); entry.getValue().clean();
} }
for (Map.Entry<Class, Pool> entry : REGISTERED_POOLS.entrySet()) { for (Map.Entry<Class, Pool> entry : REGISTERED_POOLS.entrySet()) {
@ -141,13 +141,13 @@ public enum FaweCache implements Trimable {
} }
public final <T> T getSingleton(Class<T> clazz) { public final <T> T getSingleton(Class<T> clazz) {
IterableThreadLocal<T> cache = REGISTERED_SINGLETONS.get(clazz); CleanableThreadLocal<T> cache = REGISTERED_SINGLETONS.get(clazz);
if (cache == null) { if (cache == null) {
synchronized (this) { synchronized (this) {
cache = REGISTERED_SINGLETONS.get(clazz); cache = REGISTERED_SINGLETONS.get(clazz);
if (cache == null) { if (cache == null) {
Fawe.debug("Not registered " + clazz); Fawe.debug("Not registered " + clazz);
cache = new IterableThreadLocal<>(IOUtil.supplier(clazz::newInstance)); cache = new CleanableThreadLocal<>(IOUtil.supplier(clazz::newInstance));
REGISTERED_SINGLETONS.put(clazz, cache); REGISTERED_SINGLETONS.put(clazz, cache);
} }
} }
@ -155,10 +155,10 @@ public enum FaweCache implements Trimable {
return cache.get(); return cache.get();
} }
public synchronized <T> IterableThreadLocal<T> registerSingleton(Class<T> clazz, Supplier<T> cache) { public synchronized <T> CleanableThreadLocal<T> registerSingleton(Class<T> clazz, Supplier<T> cache) {
checkNotNull(cache); checkNotNull(cache);
IterableThreadLocal<T> local = new IterableThreadLocal<>(cache); CleanableThreadLocal<T> local = new CleanableThreadLocal<>(cache);
IterableThreadLocal previous = REGISTERED_SINGLETONS.putIfAbsent(clazz, local); CleanableThreadLocal previous = REGISTERED_SINGLETONS.putIfAbsent(clazz, local);
if (previous != null) { if (previous != null) {
throw new IllegalStateException("Previous key"); throw new IllegalStateException("Previous key");
} }
@ -180,27 +180,27 @@ public enum FaweCache implements Trimable {
return pool; return pool;
} }
public final IterableThreadLocal<int[]> BLOCK_TO_PALETTE = new IterableThreadLocal<>(() -> { public final CleanableThreadLocal<int[]> BLOCK_TO_PALETTE = new CleanableThreadLocal<>(() -> {
int[] result = new int[BlockTypes.states.length]; int[] result = new int[BlockTypes.states.length];
Arrays.fill(result, Integer.MAX_VALUE); Arrays.fill(result, Integer.MAX_VALUE);
return result; return result;
}); });
public final IterableThreadLocal<char[]> SECTION_BITS_TO_CHAR = new IterableThreadLocal<>(() -> new char[4096]); public final CleanableThreadLocal<char[]> SECTION_BITS_TO_CHAR = new CleanableThreadLocal<>(() -> new char[4096]);
public final IterableThreadLocal<int[]> PALETTE_TO_BLOCK = new IterableThreadLocal<>(() -> new int[Character.MAX_VALUE + 1]); public final CleanableThreadLocal<int[]> PALETTE_TO_BLOCK = new CleanableThreadLocal<>(() -> new int[Character.MAX_VALUE + 1]);
public final IterableThreadLocal<char[]> PALETTE_TO_BLOCK_CHAR = new IterableThreadLocal<>( public final CleanableThreadLocal<char[]> PALETTE_TO_BLOCK_CHAR = new CleanableThreadLocal<>(
() -> new char[Character.MAX_VALUE + 1], a -> { () -> new char[Character.MAX_VALUE + 1], a -> {
Arrays.fill(a, Character.MAX_VALUE); Arrays.fill(a, Character.MAX_VALUE);
} }
); );
public final IterableThreadLocal<long[]> BLOCK_STATES = new IterableThreadLocal<>(() -> new long[2048]); public final CleanableThreadLocal<long[]> BLOCK_STATES = new CleanableThreadLocal<>(() -> new long[2048]);
public final IterableThreadLocal<int[]> SECTION_BLOCKS = new IterableThreadLocal<>(() -> new int[4096]); public final CleanableThreadLocal<int[]> SECTION_BLOCKS = new CleanableThreadLocal<>(() -> new int[4096]);
public final IterableThreadLocal<int[]> INDEX_STORE = new IterableThreadLocal<>(() -> new int[256]); public final CleanableThreadLocal<int[]> INDEX_STORE = new CleanableThreadLocal<>(() -> new int[256]);
/** /**
* Holds data for a palette used in a chunk section * Holds data for a palette used in a chunk section
@ -219,7 +219,7 @@ public enum FaweCache implements Trimable {
public long[] blockStates; public long[] blockStates;
} }
private final IterableThreadLocal<Palette> PALETTE_CACHE = new IterableThreadLocal<>(Palette::new); private final CleanableThreadLocal<Palette> PALETTE_CACHE = new CleanableThreadLocal<>(Palette::new);
/** /**
* Convert raw char array to palette * Convert raw char array to palette
@ -315,9 +315,9 @@ public enum FaweCache implements Trimable {
* Vector cache * Vector cache
*/ */
public IterableThreadLocal<MutableBlockVector3> MUTABLE_BLOCKVECTOR3 = new IterableThreadLocal<>(MutableBlockVector3::new); public CleanableThreadLocal<MutableBlockVector3> MUTABLE_BLOCKVECTOR3 = new CleanableThreadLocal<>(MutableBlockVector3::new);
public IterableThreadLocal<MutableVector3> MUTABLE_VECTOR3 = new IterableThreadLocal<MutableVector3>(MutableVector3::new) { public CleanableThreadLocal<MutableVector3> MUTABLE_VECTOR3 = new CleanableThreadLocal<MutableVector3>(MutableVector3::new) {
@Override @Override
public MutableVector3 init() { public MutableVector3 init() {
return new MutableVector3(); return new MutableVector3();

View File

@ -5,6 +5,7 @@ import com.boydti.fawe.object.FaweCommand;
import com.boydti.fawe.regions.FaweMaskManager; import com.boydti.fawe.regions.FaweMaskManager;
import com.boydti.fawe.util.TaskManager; import com.boydti.fawe.util.TaskManager;
import com.boydti.fawe.util.image.ImageViewer; import com.boydti.fawe.util.image.ImageViewer;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.World;
import java.io.File; import java.io.File;
@ -35,10 +36,6 @@ public interface IFawe {
return null; return null;
} }
default int getPlayerCount() {
return Fawe.get().getCachedPlayers().size();
}
String getPlatformVersion(); String getPlatformVersion();
boolean isOnlineMode(); boolean isOnlineMode();

View File

@ -94,23 +94,12 @@ public class ArrayFilterBlock extends SimpleFilterBlock {
return z; return z;
} }
@Override
public <T extends BlockStateHolder<T>> boolean setBlock(BlockVector3 position, T block)
throws WorldEditException {
return getExtent().setBlock(position.getX(),position.getY(), position.getZ(), block);
}
@Override @Override
public <T extends BlockStateHolder<T>> boolean setBlock(int x, int y, int z, T block) public <T extends BlockStateHolder<T>> boolean setBlock(int x, int y, int z, T block)
throws WorldEditException { throws WorldEditException {
return getExtent().setBlock(x,y, z, block); return getExtent().setBlock(x,y, z, block);
} }
@Override
public boolean setBiome(BlockVector2 position, BiomeType biome) {
return getExtent().setBiome(position.getX(),0, position.getZ(), biome);
}
@Override @Override
public boolean setBiome(int x, int y, int z, BiomeType biome) { public boolean setBiome(int x, int y, int z, BiomeType biome) {
return getExtent().setBiome(x,y, z,biome); return getExtent().setBiome(x,y, z,biome);

View File

@ -7,7 +7,6 @@ import com.sk89q.jnbt.CompoundTag;
import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.math.BlockVector2; import com.sk89q.worldedit.math.BlockVector2;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.regions.Region;
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;
@ -79,8 +78,7 @@ public class CharFilterBlock extends ChunkFilterBlock {
} }
@Override @Override
public final ChunkFilterBlock init(IChunkGet iget, IChunkSet iset, public final ChunkFilterBlock init(IChunkGet iget, IChunkSet iset, int layer) {
int layer) {
this.layer = layer; this.layer = layer;
final CharGetBlocks get = (CharGetBlocks) iget; final CharGetBlocks get = (CharGetBlocks) iget;
if (!get.hasSection(layer)) { if (!get.hasSection(layer)) {
@ -123,12 +121,18 @@ public class CharFilterBlock extends ChunkFilterBlock {
public void filter(Filter filter, int minX, int minY, int minZ, int maxX, int maxY, int maxZ) { public void filter(Filter filter, int minX, int minY, int minZ, int maxX, int maxY, int maxZ) {
int yis = minY << 8; int yis = minY << 8;
int zis = minZ << 4; int zis = minZ << 4;
int zie = (15 - maxZ) << 4;
int xie = (15 - maxX);
for (y = minY, index = yis; y <= maxY; y++) { for (y = minY, index = yis; y <= maxY; y++) {
for (z = minZ, index += zis; z <= maxZ; z++) { index += zis;
for (x = minX, index += minX; x <= maxX; x++, index++) { for (z = minZ; z <= maxZ; z++) {
index += minX;
for (x = minX; x <= maxX; x++, index++) {
filter.applyBlock(this); filter.applyBlock(this);
} }
index += xie;
} }
index += zie;
} }
} }
@ -251,7 +255,7 @@ public class CharFilterBlock extends ChunkFilterBlock {
@Override @Override
public final CompoundTag getNbtData() { public final CompoundTag getNbtData() {
return get.getTag(x, y + (layer << 4), z); return get.getTag(x, y + yy, z);
} }
/* /*
NORTH(Vector3.at(0, 0, -1), Flag.CARDINAL, 3, 1), NORTH(Vector3.at(0, 0, -1), Flag.CARDINAL, 3, 1),
@ -410,21 +414,15 @@ public class CharFilterBlock extends ChunkFilterBlock {
return getExtent().getBiomeType(x, z); return getExtent().getBiomeType(x, z);
} }
@Override
public <T extends BlockStateHolder<T>> boolean setBlock(BlockVector3 position, T block)
throws WorldEditException {
return false;
}
@Override @Override
public <T extends BlockStateHolder<T>> boolean setBlock(int x, int y, int z, T block) public <T extends BlockStateHolder<T>> boolean setBlock(int x, int y, int z, T block)
throws WorldEditException { throws WorldEditException {
return false; return getExtent().setBlock(x, y, z, block);
} }
@Override @Override
public boolean setBiome(BlockVector2 position, BiomeType biome) { public boolean setBiome(BlockVector2 position, BiomeType biome) {
return false; return setBiome(position.getX(), 0, position.getBlockZ(), biome);
} }
@Override @Override

View File

@ -1,6 +1,6 @@
package com.boydti.fawe.beta; package com.boydti.fawe.beta;
public class DelegateFilter<T extends Filter> implements IDelegateFilter { public abstract class DelegateFilter<T extends Filter> implements IDelegateFilter {
private final Filter parent; private final Filter parent;
@ -9,12 +9,7 @@ public class DelegateFilter<T extends Filter> implements IDelegateFilter {
} }
@Override @Override
public T getParent() { public final T getParent() {
return (T) parent; return (T) parent;
} }
}
@Override
public Filter newInstance(Filter other) {
return new DelegateFilter(other);
}
}

View File

@ -1,6 +1,8 @@
package com.boydti.fawe.beta; package com.boydti.fawe.beta;
import com.sk89q.jnbt.CompoundTag; import com.sk89q.jnbt.CompoundTag;
import com.sk89q.jnbt.StringTag;
import com.sk89q.jnbt.Tag;
import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.blocks.TileEntityBlock; import com.sk89q.worldedit.blocks.TileEntityBlock;
import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.extent.Extent;

View File

@ -0,0 +1,122 @@
package com.boydti.fawe.beta;
import com.boydti.fawe.FaweCache;
import com.boydti.fawe.beta.implementation.EmptyBatchProcessor;
import com.boydti.fawe.beta.implementation.MultiBatchProcessor;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.math.BlockVector3;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
public interface IBatchProcessor {
/**
* Process a chunk that has been set
* @param chunk
* @param get
* @param set
* @return
*/
IChunkSet processBatch(IChunk chunk, IChunkGet get, IChunkSet set);
/**
* Convert this processor into an Extent based processor instead of a queue batch based on
* @param child
* @return
*/
Extent construct(Extent child);
/**
* Utility method to trim a chunk based on min and max Y
* @param set
* @param minY
* @param maxY
* @return false if chunk is empty of blocks
*/
default boolean trimY(IChunkSet set, int minY, int maxY) {
int minLayer = (minY - 1) >> 4;
for (int layer = 0; layer <= minLayer; layer++) {
if (set.hasSection(layer)) {
if (layer == minLayer) {
char[] arr = set.getArray(layer);
int index = (minY & 15) << 12;
for (int i = 0; i < index; i++) arr[i] = 0;
set.setBlocks(layer, arr);
} else {
set.setBlocks(layer, null);
}
}
}
int maxLayer = (maxY + 1) >> 4;
for (int layer = maxLayer; layer < FaweCache.IMP.CHUNK_LAYERS; layer++) {
if (set.hasSection(layer)) {
if (layer == minLayer) {
char[] arr = set.getArray(layer);
int index = ((maxY + 1) & 15) << 12;
for (int i = index; i < arr.length; i++) arr[i] = 0;
set.setBlocks(layer, arr);
} else {
set.setBlocks(layer, null);
}
}
}
for (int layer = (minY - 15) >> 4; layer < (maxY + 15) >> 4; layer++) {
if (set.hasSection(layer)) {
return true;
}
}
return false;
}
/**
* Utility method to trim entity and blocks with a provided contains function
* @param set
* @param contains
* @return false if chunk is empty of NBT
*/
default boolean trimNBT(IChunkSet set, Function<BlockVector3, Boolean> contains) {
Set<CompoundTag> ents = set.getEntities();
if (!ents.isEmpty()) {
for (Iterator<CompoundTag> iter = ents.iterator(); iter.hasNext();) {
CompoundTag ent = iter.next();
if (!contains.apply(ent.getEntityPosition().toBlockPoint())) {
iter.remove();
}
}
}
Map<BlockVector3, CompoundTag> tiles = set.getTiles();
if (!tiles.isEmpty()) {
for (Iterator<Map.Entry<BlockVector3, CompoundTag>> iter = tiles.entrySet().iterator(); iter.hasNext();) {
if (!contains.apply(iter.next().getKey())) {
iter.remove();
}
}
}
return !tiles.isEmpty() || !ents.isEmpty();
}
/**
* Join two processors and return the result
* @param other
* @return
*/
default IBatchProcessor join(IBatchProcessor other) {
return MultiBatchProcessor.of(this, other);
}
/**
* Return a new processor after removing all are instances of a specified class
* @param clazz
* @param <T>
* @return
*/
default <T extends IBatchProcessor> IBatchProcessor remove(Class<T> clazz) {
if (clazz.isInstance(this)) {
return EmptyBatchProcessor.INSTANCE;
}
return this;
}
}

View File

@ -1,5 +1,13 @@
package com.boydti.fawe.beta; package com.boydti.fawe.beta;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.world.biome.BiomeType;
import com.sk89q.worldedit.world.block.BlockState;
import java.util.Map;
import java.util.Set;
/** /**
* Shared interface for IGetBlocks and ISetBlocks * Shared interface for IGetBlocks and ISetBlocks
*/ */
@ -7,5 +15,9 @@ public interface IBlocks extends Trimable {
boolean hasSection(int layer); boolean hasSection(int layer);
char[] getArray(int layer);
BlockState getBlock(int x, int y, int z);
IBlocks reset(); IBlocks reset();
} }

View File

@ -2,10 +2,14 @@ package com.boydti.fawe.beta;
import com.sk89q.jnbt.CompoundTag; import com.sk89q.jnbt.CompoundTag;
import com.sk89q.worldedit.extent.InputExtent; import com.sk89q.worldedit.extent.InputExtent;
import com.sk89q.worldedit.math.BlockVector3;
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.BlockState; import com.sk89q.worldedit.world.block.BlockState;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.Future; import java.util.concurrent.Future;
/** /**
@ -24,6 +28,10 @@ public interface IChunkGet extends IBlocks, Trimable, InputExtent {
CompoundTag getTag(int x, int y, int z); CompoundTag getTag(int x, int y, int z);
Map<BlockVector3, CompoundTag> getTiles();
Set<CompoundTag> getEntities();
@Override @Override
boolean trim(boolean aggressive); boolean trim(boolean aggressive);
@ -34,4 +42,6 @@ public interface IChunkGet extends IBlocks, Trimable, InputExtent {
<T extends Future<T>> T call(IChunkSet set, Runnable finalize); <T extends Future<T>> T call(IChunkSet set, Runnable finalize);
char[] load(int layer); char[] load(int layer);
CompoundTag getEntity(UUID uuid);
} }

View File

@ -3,6 +3,7 @@ package com.boydti.fawe.beta;
import com.sk89q.jnbt.CompoundTag; import com.sk89q.jnbt.CompoundTag;
import com.sk89q.worldedit.extent.OutputExtent; import com.sk89q.worldedit.extent.OutputExtent;
import com.sk89q.worldedit.function.operation.Operation; import com.sk89q.worldedit.function.operation.Operation;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.world.biome.BiomeType; import com.sk89q.worldedit.world.biome.BiomeType;
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;
@ -22,6 +23,8 @@ public interface IChunkSet extends IBlocks, OutputExtent {
@Override @Override
boolean setBlock(int x, int y, int z, BlockStateHolder holder); boolean setBlock(int x, int y, int z, BlockStateHolder holder);
void setBlocks(int layer, char[] data);
boolean isEmpty(); boolean isEmpty();
@Override @Override
@ -31,18 +34,14 @@ public interface IChunkSet extends IBlocks, OutputExtent {
void removeEntity(UUID uuid); void removeEntity(UUID uuid);
BlockState getBlock(int x, int y, int z); Set<UUID> getEntityRemoves();
char[] getArray(int layer);
BiomeType[] getBiomes(); BiomeType[] getBiomes();
Map<Short, CompoundTag> getTiles(); Map<BlockVector3, CompoundTag> getTiles();
Set<CompoundTag> getEntities(); Set<CompoundTag> getEntities();
Set<UUID> getEntityRemoves();
@Override @Override
IChunkSet reset(); IChunkSet reset();

View File

@ -1,11 +1,16 @@
package com.boydti.fawe.beta; package com.boydti.fawe.beta;
import com.sk89q.jnbt.CompoundTag; import com.sk89q.jnbt.CompoundTag;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.regions.Region;
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.BlockState; import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.block.BlockStateHolder; import com.sk89q.worldedit.world.block.BlockStateHolder;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future; import java.util.concurrent.Future;
import javax.annotation.Nullable; import javax.annotation.Nullable;
@ -129,6 +134,26 @@ public interface IDelegateChunk<U extends IChunk> extends IChunk {
return getParent().isEmpty(); return getParent().isEmpty();
} }
@Override
default Map<BlockVector3, CompoundTag> getTiles() {
return getParent().getTiles();
}
@Override
default Set<CompoundTag> getEntities() {
return getParent().getEntities();
}
@Override
default CompoundTag getEntity(UUID uuid) {
return getParent().getEntity(uuid);
}
@Override
default char[] getArray(int layer) {
return getParent().getArray(layer);
}
default <T extends IChunk> T findParent(Class<T> clazz) { default <T extends IChunk> T findParent(Class<T> clazz) {
IChunk root = getParent(); IChunk root = getParent();
if (clazz.isAssignableFrom(root.getClass())) { if (clazz.isAssignableFrom(root.getClass())) {

View File

@ -46,7 +46,5 @@ public interface IDelegateFilter extends Filter {
return this; return this;
} }
default Filter newInstance(Filter other) { Filter newInstance(Filter other);
throw new UnsupportedOperationException("Not implemented"); }
}
}

View File

@ -1,6 +1,7 @@
package com.boydti.fawe.beta; package com.boydti.fawe.beta;
import com.boydti.fawe.beta.implementation.IChunkCache; import com.boydti.fawe.beta.implementation.IChunkCache;
import com.boydti.fawe.beta.implementation.MultiBatchProcessor;
import com.sk89q.jnbt.CompoundTag; import com.sk89q.jnbt.CompoundTag;
import com.sk89q.worldedit.MaxChangedBlocksException; import com.sk89q.worldedit.MaxChangedBlocksException;
import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.WorldEditException;
@ -80,8 +81,8 @@ public interface IDelegateQueueExtent extends IQueueExtent {
} }
@Override @Override
default IChunk getCachedChunk(int x, int z) { default IChunk getOrCreateChunk(int x, int z) {
return getParent().getCachedChunk(x, z); return getParent().getOrCreateChunk(x, z);
} }
@Override @Override

View File

@ -1,24 +1,30 @@
package com.boydti.fawe.beta; package com.boydti.fawe.beta;
import com.boydti.fawe.FaweCache; import com.boydti.fawe.FaweCache;
import com.boydti.fawe.beta.implementation.IBatchProcessorHolder;
import com.boydti.fawe.beta.implementation.IChunkCache; import com.boydti.fawe.beta.implementation.IChunkCache;
import com.boydti.fawe.beta.implementation.MultiBatchProcessor;
import com.sk89q.jnbt.CompoundTag; import com.sk89q.jnbt.CompoundTag;
import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.function.operation.Operation;
import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.math.BlockVector3;
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.BlockState; import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.block.BlockStateHolder; import com.sk89q.worldedit.world.block.BlockStateHolder;
import javax.annotation.Nullable;
import java.io.Flushable; import java.io.Flushable;
import java.util.List;
import java.util.concurrent.Future; import java.util.concurrent.Future;
/** /**
* TODO: implement Extent (need to refactor Extent first) Interface for a queue based extent which * TODO: implement Extent (need to refactor Extent first) Interface for a queue based extent which
* uses chunks * uses chunks
*/ */
public interface IQueueExtent extends Flushable, Trimable, Extent { public interface IQueueExtent extends Flushable, Trimable, Extent, IBatchProcessorHolder {
@Override @Override
default boolean isQueueEnabled() { default boolean isQueueEnabled() {
@ -54,6 +60,12 @@ public interface IQueueExtent extends Flushable, Trimable, Extent {
void disableQueue(); void disableQueue();
/**
* Initialize the queue (for reusability)
* @param extent
* @param get
* @param set
*/
void init(Extent extent, IChunkCache<IChunkGet> get, IChunkCache<IChunkSet> set); void init(Extent extent, IChunkCache<IChunkGet> get, IChunkCache<IChunkSet> set);
/** /**
@ -82,7 +94,7 @@ public interface IQueueExtent extends Flushable, Trimable, Extent {
* @param z * @param z
* @return IChunk * @return IChunk
*/ */
IChunk getCachedChunk(int x, int z); IChunk getOrCreateChunk(int x, int z);
/** /**
* Submit the chunk so that it's changes are applied to the world * Submit the chunk so that it's changes are applied to the world
@ -96,36 +108,36 @@ public interface IQueueExtent extends Flushable, Trimable, Extent {
@Override @Override
default boolean setBlock(int x, int y, int z, BlockStateHolder state) { default boolean setBlock(int x, int y, int z, BlockStateHolder state) {
final IChunk chunk = getCachedChunk(x >> 4, z >> 4); final IChunk chunk = getOrCreateChunk(x >> 4, z >> 4);
return chunk.setBlock(x & 15, y, z & 15, state); return chunk.setBlock(x & 15, y, z & 15, state);
} }
@Override @Override
default boolean setTile(int x, int y, int z, CompoundTag tile) throws WorldEditException { default boolean setTile(int x, int y, int z, CompoundTag tile) throws WorldEditException {
final IChunk chunk = getCachedChunk(x >> 4, z >> 4); final IChunk chunk = getOrCreateChunk(x >> 4, z >> 4);
return chunk.setTile(x & 15, y, z & 15, tile); return chunk.setTile(x & 15, y, z & 15, tile);
} }
@Override @Override
default boolean setBiome(int x, int y, int z, BiomeType biome) { default boolean setBiome(int x, int y, int z, BiomeType biome) {
final IChunk chunk = getCachedChunk(x >> 4, z >> 4); final IChunk chunk = getOrCreateChunk(x >> 4, z >> 4);
return chunk.setBiome(x & 15, y, z & 15, biome); return chunk.setBiome(x & 15, y, z & 15, biome);
} }
@Override @Override
default BlockState getBlock(int x, int y, int z) { default BlockState getBlock(int x, int y, int z) {
final IChunk chunk = getCachedChunk(x >> 4, z >> 4); final IChunk chunk = getOrCreateChunk(x >> 4, z >> 4);
return chunk.getBlock(x & 15, y, z & 15); return chunk.getBlock(x & 15, y, z & 15);
} }
@Override @Override
default BaseBlock getFullBlock(int x, int y, int z) { default BaseBlock getFullBlock(int x, int y, int z) {
final IChunk chunk = getCachedChunk(x >> 4, z >> 4); final IChunk chunk = getOrCreateChunk(x >> 4, z >> 4);
return chunk.getFullBlock(x & 15, y, z & 15); return chunk.getFullBlock(x & 15, y, z & 15);
} }
default BiomeType getBiome(int x, int z) { default BiomeType getBiome(int x, int z) {
final IChunk chunk = getCachedChunk(x >> 4, z >> 4); final IChunk chunk = getOrCreateChunk(x >> 4, z >> 4);
return chunk.getBiomeType(x & 15, z & 15); return chunk.getBiomeType(x & 15, z & 15);
} }
@ -159,6 +171,13 @@ public interface IQueueExtent extends Flushable, Trimable, Extent {
return root; return root;
} }
@Nullable
@Override
default Operation commit() {
flush();
return null;
}
/** /**
* Flush all changes to the world - Best to call this async so it doesn't hang the server * Flush all changes to the world - Best to call this async so it doesn't hang the server
*/ */

View File

@ -54,11 +54,6 @@ public class SingleFilterBlock extends FilterBlock {
return block; return block;
} }
// @Override
// public BaseBlock getFullBlockRelative(int x, int y, int z) {
// return block;
// }
@Override @Override
public void setFullBlock(BaseBlock block) { public void setFullBlock(BaseBlock block) {
this.block = block; this.block = block;
@ -99,23 +94,16 @@ public class SingleFilterBlock extends FilterBlock {
return BlockVector3.at(x, y, z); return BlockVector3.at(x, y, z);
} }
@Override
public <T extends BlockStateHolder<T>> boolean setBlock(BlockVector3 position, T block)
throws WorldEditException {
return getExtent().setBlock(position.getX(),position.getY(), position.getZ(), block);
}
@Override @Override
public <T extends BlockStateHolder<T>> boolean setBlock(int x, int y, int z, T block) public <T extends BlockStateHolder<T>> boolean setBlock(int x, int y, int z, T block)
throws WorldEditException { throws WorldEditException {
if (x == this.x && y == this.y && z == this.z) {
setFullBlock(block.toBaseBlock());
return true;
}
return getExtent().setBlock(x,y, z, block); return getExtent().setBlock(x,y, z, block);
} }
@Override
public boolean setBiome(BlockVector2 position, BiomeType biome) {
return getExtent().setBiome(position.getX(),0, position.getZ(), biome);
}
@Override @Override
public boolean setBiome(int x, int y, int z, BiomeType biome) { public boolean setBiome(int x, int y, int z, BiomeType biome) {
return getExtent().setBiome(x,y, z,biome); return getExtent().setBiome(x,y, z,biome);

View File

@ -0,0 +1,22 @@
package com.boydti.fawe.beta.implementation;
import com.boydti.fawe.beta.IBatchProcessor;
public class BatchProcessorHolder implements IBatchProcessorHolder {
private IBatchProcessor processor = EmptyBatchProcessor.INSTANCE;
@Override
public IBatchProcessor getProcessor() {
return processor;
}
@Override
public void setProcessor(IBatchProcessor set) {
this.processor = set;
}
@Override
public String toString() {
return super.toString() + "{" + getProcessor() + "}";
}
}

View File

@ -64,7 +64,7 @@ public interface DelegateChunkSet extends IChunkSet {
} }
@Override @Override
default Map<Short, CompoundTag> getTiles() { default Map<BlockVector3, CompoundTag> getTiles() {
return getParent().getTiles(); return getParent().getTiles();
} }

View File

@ -0,0 +1,26 @@
package com.boydti.fawe.beta.implementation;
import com.boydti.fawe.beta.IBatchProcessor;
import com.boydti.fawe.beta.IChunk;
import com.boydti.fawe.beta.IChunkGet;
import com.boydti.fawe.beta.IChunkSet;
import com.sk89q.worldedit.extent.Extent;
public enum EmptyBatchProcessor implements IBatchProcessor {
INSTANCE
;
@Override
public IChunkSet processBatch(IChunk chunk, IChunkGet get, IChunkSet set) {
return set;
}
@Override
public Extent construct(Extent child) {
return child;
}
@Override
public IBatchProcessor join(IBatchProcessor other) {
return other;
}
}

View File

@ -7,14 +7,15 @@ import com.boydti.fawe.beta.IChunkSet;
import com.boydti.fawe.util.MathMan; import com.boydti.fawe.util.MathMan;
import com.sk89q.jnbt.CompoundTag; import com.sk89q.jnbt.CompoundTag;
import com.sk89q.worldedit.entity.BaseEntity; import com.sk89q.worldedit.entity.BaseEntity;
import com.sk89q.worldedit.entity.Entity;
import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.regions.CuboidRegion;
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.BlockState; import com.sk89q.worldedit.world.block.BlockState;
import java.util.Map; import java.util.*;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.Future; import java.util.concurrent.Future;
public class FallbackChunkGet implements IChunkGet { public class FallbackChunkGet implements IChunkGet {
@ -46,6 +47,40 @@ public class FallbackChunkGet implements IChunkGet {
return extent.getFullBlock(bx + x, y, bz + z).getNbtData(); return extent.getFullBlock(bx + x, y, bz + z).getNbtData();
} }
@Override
public Map<BlockVector3, CompoundTag> getTiles() {
return null;
}
@Override
public Set<CompoundTag> getEntities() {
List<? extends Entity> result = extent.getEntities(new CuboidRegion(BlockVector3.at(bx, 0, bz), BlockVector3.at(bx + 15, 255, bz + 15)));
if (result.isEmpty()) {
return Collections.emptySet();
}
HashSet<CompoundTag> set = new HashSet<>(result.size());
for (Entity entity : result) {
set.add(entity.getState().getNbtData());
}
return set;
}
@Override
public CompoundTag getEntity(UUID uuid) {
long checkMost = uuid.getMostSignificantBits();
long checkLeast = uuid.getLeastSignificantBits();
for (CompoundTag entityTag : getEntities()) {
long entMost = entityTag.getLong("UUIDMost");
if (entMost == checkMost) {
long entLeast = entityTag.getLong("UUIDLeast");
if (entLeast == checkLeast) {
return entityTag;
}
}
}
return null;
}
@Override @Override
public boolean trim(boolean aggressive) { public boolean trim(boolean aggressive) {
return true; return true;
@ -71,14 +106,11 @@ public class FallbackChunkGet implements IChunkGet {
} }
} }
Map<Short, CompoundTag> tiles = set.getTiles(); Map<BlockVector3, CompoundTag> tiles = set.getTiles();
if (!tiles.isEmpty()) { if (!tiles.isEmpty()) {
for (Map.Entry<Short, CompoundTag> entry : tiles.entrySet()) { for (Map.Entry<BlockVector3, CompoundTag> entry : tiles.entrySet()) {
short blockHash = entry.getKey(); BlockVector3 pos = entry.getKey();
final int x = (blockHash >> 12 & 0xF) + bx; extent.setTile(bx + pos.getX(), pos.getY(), bz + pos.getZ(), entry.getValue());
final int y = (blockHash & 0xFF);
final int z = (blockHash >> 8 & 0xF) + bz;
extent.setTile(bx + x, y, bz + z, entry.getValue());
} }
} }
@ -128,6 +160,11 @@ public class FallbackChunkGet implements IChunkGet {
return true; return true;
} }
@Override
public char[] getArray(int layer) {
return new char[0];
}
@Override @Override
public IBlocks reset() { public IBlocks reset() {
return null; return null;

View File

@ -0,0 +1,43 @@
package com.boydti.fawe.beta.implementation;
import com.boydti.fawe.beta.IBatchProcessor;
import com.boydti.fawe.beta.IChunk;
import com.boydti.fawe.beta.IChunkGet;
import com.boydti.fawe.beta.IChunkSet;
import com.sk89q.worldedit.extent.Extent;
/**
* Holds a batch processor
* (Join and remove operations affect the held processor)
*/
public interface IBatchProcessorHolder extends IBatchProcessor {
IBatchProcessor getProcessor();
/**
* set the held processor
* @param set
*/
void setProcessor(IBatchProcessor set);
@Override
default IChunkSet processBatch(IChunk chunk, IChunkGet get, IChunkSet set) {
return getProcessor().processBatch(chunk, get, set);
}
@Override
default Extent construct(Extent child) {
return getProcessor().construct(child);
}
@Override
default IBatchProcessor join(IBatchProcessor other) {
setProcessor(getProcessor().join(other));
return this;
}
@Override
default <T extends IBatchProcessor> IBatchProcessor remove(Class<T> clazz) {
setProcessor(getProcessor().remove(clazz));
return this;
}
}

View File

@ -3,7 +3,6 @@ package com.boydti.fawe.beta.implementation;
import com.boydti.fawe.beta.IQueueExtent; import com.boydti.fawe.beta.IQueueExtent;
public interface IQueueWrapper { public interface IQueueWrapper {
default IQueueExtent wrapQueue(IQueueExtent queue) { default IQueueExtent wrapQueue(IQueueExtent queue) {
return queue; return queue;
} }

View File

@ -0,0 +1,99 @@
package com.boydti.fawe.beta.implementation;
import com.boydti.fawe.beta.IBatchProcessor;
import com.boydti.fawe.beta.IChunk;
import com.boydti.fawe.beta.IChunkGet;
import com.boydti.fawe.beta.IChunkSet;
import com.boydti.fawe.util.StringMan;
import com.sk89q.worldedit.extent.Extent;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;
public class MultiBatchProcessor implements IBatchProcessor {
private IBatchProcessor[] processors;
public MultiBatchProcessor(IBatchProcessor... processors) {
this.processors = processors;
}
public static IBatchProcessor of(IBatchProcessor... processors) {
ArrayList<IBatchProcessor> list = new ArrayList<>();
for (IBatchProcessor processor : processors) {
if (processor instanceof MultiBatchProcessor) {
list.addAll(Arrays.asList(((MultiBatchProcessor) processor).processors));
} else if (!(processor instanceof EmptyBatchProcessor)){
list.add(processor);
}
}
switch (list.size()) {
case 0:
return EmptyBatchProcessor.INSTANCE;
case 1:
return list.get(0);
default:
return new MultiBatchProcessor(list.toArray(new IBatchProcessor[0]));
}
}
public void addBatchProcessor(IBatchProcessor processor) {
List<IBatchProcessor> processors = new ArrayList<>(Arrays.asList(this.processors));
processors.add(processor);
this.processors = processors.toArray(new IBatchProcessor[0]);
}
public List<IBatchProcessor> getBatchProcessors() {
return Arrays.asList(this.processors);
}
public void removeBatchProcessor(IBatchProcessor processor) {
List<IBatchProcessor> processors = new ArrayList<>(Arrays.asList(this.processors));
processors.remove(processor);
this.processors = processors.toArray(new IBatchProcessor[0]);
}
@Override
public IChunkSet processBatch(IChunk chunk, IChunkGet get, IChunkSet set) {
for (IBatchProcessor processor : this.processors) {
set = processor.processBatch(chunk, get, set);
if (set == null) {
return null;
}
}
return set;
}
@Override
public Extent construct(Extent child) {
for (IBatchProcessor processor : processors) {
child = processor.construct(child);
}
return child;
}
@Override
public <T extends IBatchProcessor> IBatchProcessor remove(Class<T> clazz) {
ArrayList<IBatchProcessor> list = new ArrayList<>(Arrays.asList(this.processors));
list.removeIf(clazz::isInstance);
return of(list.toArray(new IBatchProcessor[0]));
}
@Override
public IBatchProcessor join(IBatchProcessor other) {
if (other instanceof MultiBatchProcessor) {
for (IBatchProcessor processor : ((MultiBatchProcessor) other).processors) {
addBatchProcessor(processor);
}
} else {
addBatchProcessor(other);
}
return this;
}
@Override
public String toString() {
return super.toString() + "{" + StringMan.join(processors, ",") + "}";
}
}

View File

@ -1,153 +0,0 @@
package com.boydti.fawe.beta.implementation;
import com.boydti.fawe.beta.ChunkFilterBlock;
import com.boydti.fawe.beta.Filter;
import com.boydti.fawe.beta.IChunk;
import com.boydti.fawe.beta.IQueueExtent;
import com.boydti.fawe.beta.filters.CountFilter;
import com.boydti.fawe.beta.filters.DistrFilter;
import com.boydti.fawe.config.Settings;
import com.sk89q.worldedit.MaxChangedBlocksException;
import com.sk89q.worldedit.extent.AbstractDelegateExtent;
import com.sk89q.worldedit.extent.PassthroughExtent;
import com.sk89q.worldedit.function.mask.Mask;
import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.math.BlockVector2;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.util.Countable;
import com.sk89q.worldedit.world.World;
import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.block.BlockStateHolder;
import com.sk89q.worldedit.world.block.BlockType;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ForkJoinTask;
import java.util.stream.IntStream;
public class MultiThreadedQueue extends PassthroughExtent implements IQueueWrapper {
private final World world;
private final QueueHandler handler;
protected MultiThreadedQueue(QueueHandler handler, World world) {
super(handler.getQueue(world));
this.world = world;
this.handler = handler;
}
public IQueueExtent getQueue() {
return handler.getQueue(this.world);
}
public <T extends Filter> T apply(Region region, T filter) {
// The chunks positions to iterate over
final Set<BlockVector2> chunks = region.getChunks();
final Iterator<BlockVector2> chunksIter = chunks.iterator();
// Get a pool, to operate on the chunks in parallel
final int size = Math.min(chunks.size(), Settings.IMP.QUEUE.PARALLEL_THREADS);
final ForkJoinTask[] tasks = IntStream.range(0, size).mapToObj(i -> handler.submit(() -> {
final Filter newFilter = filter.fork();
// Create a chunk that we will reuse/reset for each operation
final IQueueExtent queue = wrapQueue(getQueue());
synchronized (queue) {
ChunkFilterBlock block = null;
while (true) {
// Get the next chunk posWeakChunk
final int X, Z;
synchronized (chunksIter) {
if (!chunksIter.hasNext()) {
break;
}
final BlockVector2 pos = chunksIter.next();
X = pos.getX();
Z = pos.getZ();
}
if (!newFilter.appliesChunk(X, Z)) {
continue;
}
IChunk chunk = queue.getCachedChunk(X, Z);
// Initialize
chunk.init(queue, X, Z);
IChunk newChunk = newFilter.applyChunk(chunk, region);
if (newChunk != null) {
chunk = newChunk;
if (block == null) {
block = queue.initFilterBlock();
}
chunk.filterBlocks(newFilter, block, region);
}
queue.submit(chunk);
}
queue.flush();
}
})).toArray(ForkJoinTask[]::new);
// Join filters
for (ForkJoinTask task : tasks) {
if (task != null) {
task.quietlyJoin();
}
}
filter.join();
return filter;
}
public int getChanges() {
return -1;
}
@Override
public int countBlocks(Region region, Mask searchMask) {
return
// Apply a filter over a region
apply(region, searchMask
.toFilter(new CountFilter())) // Adapt the mask to a filter which counts
.getParent() // Get the counter of this mask
.getTotal(); // Get the total from the counter
}
@Override
public <B extends BlockStateHolder<B>> int setBlocks(Region region, B block)
throws MaxChangedBlocksException {
apply(region, block);
return getChanges();
}
@Override
public int setBlocks(Region region, Pattern pattern) throws MaxChangedBlocksException {
apply(region, pattern);
return getChanges();
}
@Override
public int setBlocks(Set<BlockVector3> vset, Pattern pattern) {
if (vset instanceof Region) {
setBlocks((Region) vset, pattern);
}
for (BlockVector3 blockVector3 : vset) {
pattern.apply(this, blockVector3, blockVector3);
}
return getChanges();
}
@Override
public int replaceBlocks(Region region, Mask mask, Pattern pattern)
throws MaxChangedBlocksException {
apply(region, mask.toFilter(pattern));
return getChanges();
}
@Override
public List<Countable<BlockState>> getBlockDistributionWithData(Region region) {
return apply(region, new DistrFilter()).getDistribution();
}
@Override
public List<Countable<BlockType>> getBlockDistribution(Region region) {
return apply(region, new DistrFilter()).getTypeDistribution();
}
}

View File

@ -5,12 +5,17 @@ import com.boydti.fawe.beta.IBlocks;
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.sk89q.jnbt.CompoundTag; import com.sk89q.jnbt.CompoundTag;
import com.sk89q.worldedit.math.BlockVector3;
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;
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.BlockTypes;
import java.util.Collections;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.Future; import java.util.concurrent.Future;
public enum NullChunkGet implements IChunkGet { public enum NullChunkGet implements IChunkGet {
@ -36,6 +41,21 @@ public enum NullChunkGet implements IChunkGet {
return null; return null;
} }
@Override
public Map<BlockVector3, CompoundTag> getTiles() {
return Collections.emptyMap();
}
@Override
public Set<CompoundTag> getEntities() {
return null;
}
@Override
public CompoundTag getEntity(UUID uuid) {
return null;
}
@Override @Override
public boolean trim(boolean aggressive) { public boolean trim(boolean aggressive) {
return true; return true;
@ -56,6 +76,11 @@ public enum NullChunkGet implements IChunkGet {
return false; return false;
} }
@Override
public char[] getArray(int layer) {
return new char[0];
}
@Override @Override
public IBlocks reset() { public IBlocks reset() {
return null; return null;

View File

@ -0,0 +1,286 @@
package com.boydti.fawe.beta.implementation;
import com.boydti.fawe.beta.ChunkFilterBlock;
import com.boydti.fawe.beta.Filter;
import com.boydti.fawe.beta.IChunk;
import com.boydti.fawe.beta.IQueueExtent;
import com.boydti.fawe.beta.filters.CountFilter;
import com.boydti.fawe.beta.filters.DistrFilter;
import com.boydti.fawe.config.Settings;
import com.boydti.fawe.object.changeset.FaweChangeSet;
import com.boydti.fawe.object.clipboard.WorldCopyClipboard;
import com.sk89q.worldedit.MaxChangedBlocksException;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.extent.PassthroughExtent;
import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard;
import com.sk89q.worldedit.function.mask.BlockMask;
import com.sk89q.worldedit.function.mask.ExistingBlockMask;
import com.sk89q.worldedit.function.mask.Mask;
import com.sk89q.worldedit.function.pattern.BlockPattern;
import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.math.BlockVector2;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.util.Countable;
import com.sk89q.worldedit.world.World;
import com.sk89q.worldedit.world.block.BaseBlock;
import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.block.BlockStateHolder;
import com.sk89q.worldedit.world.block.BlockType;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ForkJoinTask;
import java.util.stream.IntStream;
import static com.google.common.base.Preconditions.checkNotNull;
public class ParallelQueueExtent extends PassthroughExtent implements IQueueWrapper {
private final World world;
private final QueueHandler handler;
private final BatchProcessorHolder processor;
public ParallelQueueExtent(QueueHandler handler, World world) {
super(handler.getQueue(world, new BatchProcessorHolder()));
this.world = world;
this.handler = handler;
this.processor = (BatchProcessorHolder) getExtent().getProcessor();
}
@Override
public IQueueExtent getExtent() {
return (IQueueExtent) super.getExtent();
}
private IQueueExtent getNewQueue() {
return wrapQueue(handler.getQueue(this.world, this.processor));
}
@Override
public IQueueExtent wrapQueue(IQueueExtent queue) {
// TODO wrap
queue.setProcessor(this.processor);
return queue;
}
@Override
public Extent enableHistory(FaweChangeSet changeSet) {
return super.enableHistory(changeSet);
}
private ChunkFilterBlock apply(ChunkFilterBlock block, Filter filter, IQueueExtent queue, Region region, int X, int Z) {
if (!filter.appliesChunk(X, Z)) {
return block;
}
IChunk chunk = queue.getOrCreateChunk(X, Z);
// Initialize
chunk.init(queue, X, Z);
IChunk newChunk = filter.applyChunk(chunk, region);
if (newChunk != null) {
chunk = newChunk;
if (block == null) {
block = queue.initFilterBlock();
}
chunk.filterBlocks(filter, block, region);
}
queue.submit(chunk);
return block;
}
public <T extends Filter> T apply(Region region, T filter) {
// The chunks positions to iterate over
final Set<BlockVector2> chunks = region.getChunks();
final Iterator<BlockVector2> chunksIter = chunks.iterator();
// Get a pool, to operate on the chunks in parallel
final int size = Math.min(chunks.size(), Settings.IMP.QUEUE.PARALLEL_THREADS);
if (size <= 1) {
BlockVector2 pos = chunksIter.next();
apply(null, filter, getExtent(), region, pos.getX(), pos.getZ());
} else {
final ForkJoinTask[] tasks = IntStream.range(0, size).mapToObj(i -> handler.submit(() -> {
try {
final Filter newFilter = filter.fork();
// Create a chunk that we will reuse/reset for each operation
final IQueueExtent queue = getNewQueue();
synchronized (queue) {
ChunkFilterBlock block = null;
while (true) {
// Get the next chunk posWeakChunk
final int X, Z;
synchronized (chunksIter) {
if (!chunksIter.hasNext()) {
break;
}
final BlockVector2 pos = chunksIter.next();
X = pos.getX();
Z = pos.getZ();
}
block = apply(block, newFilter, queue, region, X, Z);
}
queue.flush();
}
} catch (Throwable e) {
e.printStackTrace();
}
})).toArray(ForkJoinTask[]::new);
// Join filters
for (ForkJoinTask task : tasks) {
if (task != null) {
task.quietlyJoin();
}
}
filter.join();
}
return filter;
}
public int getChanges() {
return -1;
}
@Override
public int countBlocks(Region region, Mask searchMask) {
return
// Apply a filter over a region
apply(region, searchMask
.toFilter(new CountFilter())) // Adapt the mask to a filter which counts
.getParent() // Get the counter of this mask
.getTotal(); // Get the total from the counter
}
@Override
public <B extends BlockStateHolder<B>> int setBlocks(Region region, B block) throws MaxChangedBlocksException {
apply(region, block);
return getChanges();
}
@Override
public int setBlocks(Region region, Pattern pattern) throws MaxChangedBlocksException {
apply(region, pattern);
return getChanges();
}
@Override
public int setBlocks(Set<BlockVector3> vset, Pattern pattern) {
if (vset instanceof Region) {
setBlocks((Region) vset, pattern);
}
for (BlockVector3 blockVector3 : vset) {
pattern.apply(this, blockVector3, blockVector3);
}
return getChanges();
}
@Override
public int replaceBlocks(Region region, Mask mask, Pattern pattern)
throws MaxChangedBlocksException {
apply(region, mask.toFilter(pattern));
return getChanges();
}
@Override
public List<Countable<BlockState>> getBlockDistributionWithData(Region region) {
return apply(region, new DistrFilter()).getDistribution();
}
@Override
public List<Countable<BlockType>> getBlockDistribution(Region region) {
return apply(region, new DistrFilter()).getTypeDistribution();
}
/**
* To optimize
*/
/**
* Lazily copy a region
*
* @param region
* @return
*/
@Override
public BlockArrayClipboard lazyCopy(Region region) {
WorldCopyClipboard faweClipboard = new WorldCopyClipboard(this, region);
BlockArrayClipboard weClipboard = new BlockArrayClipboard(region, faweClipboard);
weClipboard.setOrigin(region.getMinimumPoint());
return weClipboard;
}
/**
* Count the number of blocks of a list of types in a region.
*
* @param region the region
* @param searchBlocks the list of blocks to search
* @return the number of blocks that matched the block
*/
@Override
public int countBlocks(Region region, Set<BaseBlock> searchBlocks) {
BlockMask mask = new BlockMask(this, searchBlocks);
return countBlocks(region, mask);
}
/**
* Replaces all the blocks matching a given filter, within a given region, to a block
* returned by a given pattern.
*
* @param region the region to replace the blocks within
* @param filter a list of block types to match, or null to use {@link com.sk89q.worldedit.function.mask.ExistingBlockMask}
* @param replacement the replacement block
* @return number of blocks affected
* @throws MaxChangedBlocksException thrown if too many blocks are changed
*/
@Override
public <B extends BlockStateHolder<B>> int replaceBlocks(Region region, Set<BaseBlock> filter, B replacement) throws MaxChangedBlocksException {
return replaceBlocks(region, filter, new BlockPattern(replacement));
}
/**
* Replaces all the blocks matching a given filter, within a given region, to a block
* returned by a given pattern.
*
* @param region the region to replace the blocks within
* @param filter a list of block types to match, or null to use {@link com.sk89q.worldedit.function.mask.ExistingBlockMask}
* @param pattern the pattern that provides the new blocks
* @return number of blocks affected
* @throws MaxChangedBlocksException thrown if too many blocks are changed
*/
@Override
public int replaceBlocks(Region region, Set<BaseBlock> filter, Pattern pattern) throws MaxChangedBlocksException {
Mask mask = filter == null ? new ExistingBlockMask(this) : new BlockMask(this, filter);
return replaceBlocks(region, mask, pattern);
}
/*
Don't need to optimize these
*/
// /**
// * Sets the blocks at the center of the given region to the given pattern.
// * If the center sits between two blocks on a certain axis, then two blocks
// * will be placed to mark the center.
// *
// * @param region the region to find the center of
// * @param pattern the replacement pattern
// * @return the number of blocks placed
// * @throws MaxChangedBlocksException thrown if too many blocks are changed
// */
// @Override
// public int center(Region region, Pattern pattern) throws MaxChangedBlocksException {
// checkNotNull(region);
// checkNotNull(pattern);
//
// Vector3 center = region.getCenter();
// Region centerRegion = new CuboidRegion(
// this instanceof World ? (World) this : null, // Causes clamping of Y range
// BlockVector3.at(((int) center.getX()), ((int) center.getY()), ((int) center.getZ())),
// BlockVector3.at(MathUtils.roundHalfUp(center.getX()),
// center.getY(), MathUtils.roundHalfUp(center.getZ())));
// return setBlocks(centerRegion, pattern);
// }
}

View File

@ -2,13 +2,14 @@ package com.boydti.fawe.beta.implementation;
import com.boydti.fawe.Fawe; import com.boydti.fawe.Fawe;
import com.boydti.fawe.FaweCache; import com.boydti.fawe.FaweCache;
import com.boydti.fawe.beta.IBatchProcessor;
import com.boydti.fawe.beta.IChunk; import com.boydti.fawe.beta.IChunk;
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.IQueueExtent; import com.boydti.fawe.beta.IQueueExtent;
import com.boydti.fawe.beta.Trimable; import com.boydti.fawe.beta.Trimable;
import com.boydti.fawe.config.Settings; import com.boydti.fawe.config.Settings;
import com.boydti.fawe.object.collection.IterableThreadLocal; import com.boydti.fawe.object.collection.CleanableThreadLocal;
import com.boydti.fawe.util.MemUtil; import com.boydti.fawe.util.MemUtil;
import com.boydti.fawe.util.TaskManager; import com.boydti.fawe.util.TaskManager;
import com.boydti.fawe.wrappers.WorldWrapper; import com.boydti.fawe.wrappers.WorldWrapper;
@ -39,8 +40,8 @@ public abstract class QueueHandler implements Trimable, Runnable {
private ThreadPoolExecutor blockingExecutor = FaweCache.IMP.newBlockingExecutor(); private ThreadPoolExecutor blockingExecutor = FaweCache.IMP.newBlockingExecutor();
private ConcurrentLinkedQueue<FutureTask> syncTasks = new ConcurrentLinkedQueue<>(); private ConcurrentLinkedQueue<FutureTask> syncTasks = new ConcurrentLinkedQueue<>();
private Map<World, WeakReference<IChunkCache<IChunkGet>>> chunkCache = new HashMap<>(); private Map<World, WeakReference<IChunkCache<IChunkGet>>> chunkGetCache = new HashMap<>();
private IterableThreadLocal<IQueueExtent> queuePool = new IterableThreadLocal<>(QueueHandler.this::create); private CleanableThreadLocal<IQueueExtent> queuePool = new CleanableThreadLocal<>(QueueHandler.this::create);
/** /**
* Used to calculate elapsed time in milliseconds and ensure block placement doesn't lag the * Used to calculate elapsed time in milliseconds and ensure block placement doesn't lag the
* server * server
@ -198,8 +199,8 @@ public abstract class QueueHandler implements Trimable, Runnable {
public IChunkCache<IChunkGet> getOrCreateWorldCache(World world) { public IChunkCache<IChunkGet> getOrCreateWorldCache(World world) {
world = WorldWrapper.unwrap(world); world = WorldWrapper.unwrap(world);
synchronized (chunkCache) { synchronized (chunkGetCache) {
final WeakReference<IChunkCache<IChunkGet>> ref = chunkCache.get(world); final WeakReference<IChunkCache<IChunkGet>> ref = chunkGetCache.get(world);
if (ref != null) { if (ref != null) {
final IChunkCache<IChunkGet> cached = ref.get(); final IChunkCache<IChunkGet> cached = ref.get();
if (cached != null) { if (cached != null) {
@ -207,7 +208,7 @@ public abstract class QueueHandler implements Trimable, Runnable {
} }
} }
final IChunkCache<IChunkGet> created = new ChunkCache<>(world); final IChunkCache<IChunkGet> created = new ChunkCache<>(world);
chunkCache.put(world, new WeakReference<>(created)); chunkGetCache.put(world, new WeakReference<>(created));
return created; return created;
} }
} }
@ -221,18 +222,25 @@ public abstract class QueueHandler implements Trimable, Runnable {
public abstract void endSet(boolean parallel); public abstract void endSet(boolean parallel);
public IQueueExtent getQueue(World world) { public IQueueExtent getQueue(World world) {
return getQueue(world, null);
}
public IQueueExtent getQueue(World world, IBatchProcessor processor) {
final IQueueExtent queue = queuePool.get(); final IQueueExtent queue = queuePool.get();
IChunkCache<IChunkGet> cacheGet = getOrCreateWorldCache(world); IChunkCache<IChunkGet> cacheGet = getOrCreateWorldCache(world);
IChunkCache<IChunkSet> set = null; // TODO cache? IChunkCache<IChunkSet> set = null; // TODO cache?
queue.init(world, cacheGet, set); queue.init(world, cacheGet, set);
if (processor != null) {
queue.setProcessor(processor);
}
return queue; return queue;
} }
@Override @Override
public boolean trim(boolean aggressive) { public boolean trim(boolean aggressive) {
boolean result = true; boolean result = true;
synchronized (chunkCache) { synchronized (chunkGetCache) {
final Iterator<Map.Entry<World, WeakReference<IChunkCache<IChunkGet>>>> iter = chunkCache final Iterator<Map.Entry<World, WeakReference<IChunkCache<IChunkGet>>>> iter = chunkGetCache
.entrySet().iterator(); .entrySet().iterator();
while (iter.hasNext()) { while (iter.hasNext()) {
final Map.Entry<World, WeakReference<IChunkCache<IChunkGet>>> entry = iter.next(); final Map.Entry<World, WeakReference<IChunkCache<IChunkGet>>> entry = iter.next();

View File

@ -3,6 +3,7 @@ package com.boydti.fawe.beta.implementation;
import com.boydti.fawe.Fawe; import com.boydti.fawe.Fawe;
import com.boydti.fawe.beta.CharFilterBlock; import com.boydti.fawe.beta.CharFilterBlock;
import com.boydti.fawe.beta.ChunkFilterBlock; import com.boydti.fawe.beta.ChunkFilterBlock;
import com.boydti.fawe.beta.IBatchProcessor;
import com.boydti.fawe.beta.IChunk; import com.boydti.fawe.beta.IChunk;
import com.boydti.fawe.beta.IChunkGet; import com.boydti.fawe.beta.IChunkGet;
import com.boydti.fawe.beta.IChunkSet; import com.boydti.fawe.beta.IChunkSet;
@ -11,17 +12,16 @@ import com.boydti.fawe.beta.implementation.blocks.CharSetBlocks;
import com.boydti.fawe.beta.implementation.holder.ChunkHolder; import com.boydti.fawe.beta.implementation.holder.ChunkHolder;
import com.boydti.fawe.beta.implementation.holder.ReferenceChunk; import com.boydti.fawe.beta.implementation.holder.ReferenceChunk;
import com.boydti.fawe.config.Settings; import com.boydti.fawe.config.Settings;
import com.boydti.fawe.object.changeset.FaweChangeSet;
import com.boydti.fawe.util.MathMan; import com.boydti.fawe.util.MathMan;
import com.boydti.fawe.util.MemUtil; import com.boydti.fawe.util.MemUtil;
import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.Futures;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.math.BlockVector2;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.world.biome.BiomeType;
import com.sk89q.worldedit.world.block.BlockStateHolder;
import it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap; import it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future; import java.util.concurrent.Future;
@ -32,7 +32,7 @@ import java.util.concurrent.Future;
* <p> * <p>
* This queue is reusable {@link #init(IChunkCache)} * This queue is reusable {@link #init(IChunkCache)}
*/ */
public class SingleThreadQueueExtent implements IQueueExtent { public class SingleThreadQueueExtent extends BatchProcessorHolder implements IQueueExtent {
// // Pool discarded chunks for reuse (can safely be cleared by another thread) // // Pool discarded chunks for reuse (can safely be cleared by another thread)
// private static final ConcurrentLinkedQueue<IChunk> CHUNK_POOL = new ConcurrentLinkedQueue<>(); // private static final ConcurrentLinkedQueue<IChunk> CHUNK_POOL = new ConcurrentLinkedQueue<>();
@ -86,19 +86,20 @@ public class SingleThreadQueueExtent implements IQueueExtent {
* Resets the queue. * Resets the queue.
*/ */
protected synchronized void reset() { protected synchronized void reset() {
if (!initialized) return; if (!this.initialized) return;
checkThread(); checkThread();
if (!chunks.isEmpty()) { if (!this.chunks.isEmpty()) {
for (IChunk chunk : chunks.values()) { for (IChunk chunk : this.chunks.values()) {
chunk.recycle(); chunk.recycle();
} }
chunks.clear(); this.chunks.clear();
} }
enabledQueue = true; this.enabledQueue = true;
lastChunk = null; this.lastChunk = null;
lastPair = Long.MAX_VALUE; this.lastPair = Long.MAX_VALUE;
currentThread = null; this.currentThread = null;
initialized = false; this.initialized = false;
this.setProcessor(EmptyBatchProcessor.INSTANCE);
} }
/** /**
@ -118,9 +119,27 @@ public class SingleThreadQueueExtent implements IQueueExtent {
} }
this.cacheGet = get; this.cacheGet = get;
this.cacheSet = set; this.cacheSet = set;
this.setProcessor(EmptyBatchProcessor.INSTANCE);
initialized = true; initialized = true;
} }
@Override
public Extent addProcessor(IBatchProcessor processor) {
join(processor);
return this;
}
@Override
public Extent enableHistory(FaweChangeSet changeSet) {
return this.addProcessor(changeSet);
}
@Override
public Extent disableHistory() {
this.remove(FaweChangeSet.class);
return this;
}
@Override @Override
public int size() { public int size() {
return chunks.size() + submissions.size(); return chunks.size() + submissions.size();
@ -165,7 +184,6 @@ public class SingleThreadQueueExtent implements IQueueExtent {
@Override @Override
public synchronized boolean trim(boolean aggressive) { public synchronized boolean trim(boolean aggressive) {
// TODO trim individial chunk sections
cacheGet.trim(aggressive); cacheGet.trim(aggressive);
cacheSet.trim(aggressive); cacheSet.trim(aggressive);
if (Thread.currentThread() == currentThread) { if (Thread.currentThread() == currentThread) {
@ -200,7 +218,7 @@ public class SingleThreadQueueExtent implements IQueueExtent {
} }
@Override @Override
public final IChunk getCachedChunk(int x, int z) { public final IChunk getOrCreateChunk(int x, int z) {
final long pair = (long) x << 32 | z & 0xffffffffL; final long pair = (long) x << 32 | z & 0xffffffffL;
if (pair == lastPair) { if (pair == lastPair) {
return lastChunk; return lastChunk;
@ -311,16 +329,4 @@ public class SingleThreadQueueExtent implements IQueueExtent {
public ChunkFilterBlock initFilterBlock() { public ChunkFilterBlock initFilterBlock() {
return new CharFilterBlock(this); return new CharFilterBlock(this);
} }
@Override
public <T extends BlockStateHolder<T>> boolean setBlock(BlockVector3 position, T block)
throws WorldEditException {
return setBlock(position.getX(),position.getY(), position.getZ(), block);
}
@Override
public boolean setBiome(BlockVector2 position, BiomeType biome) {
return setBiome(position.getX(),0, position.getZ(), biome);
}
} }

View File

@ -38,27 +38,31 @@ public class BitSetBlocks implements IChunkSet {
return true; return true;
} }
@Override
public void setBlocks(int layer, char[] data) {
row.reset(layer);
int by = layer << 4;
for (int y = 0, index = 0; y < 16; y++) {
for (int z = 0; z < 16; z++) {
for (int x = 0; x < 16; x++, index++) {
if (data[index] != 0) {
row.set(null, x, by + y, z);
}
}
}
}
}
@Override @Override
public boolean isEmpty() { public boolean isEmpty() {
return row.isEmpty(); return row.isEmpty();
} }
@Override
public <T extends BlockStateHolder<T>> boolean setBlock(BlockVector3 position, T block)
throws WorldEditException {
return setBlock(position.getX(), position.getY(), position.getZ(), block);
}
@Override @Override
public boolean setTile(int x, int y, int z, CompoundTag tile) { public boolean setTile(int x, int y, int z, CompoundTag tile) {
return false; return false;
} }
@Override
public boolean setBiome(BlockVector2 position, BiomeType biome) {
return setBiome(position.getX(),0, position.getZ(), biome);
}
@Override @Override
public void setEntity(CompoundTag tag) { public void setEntity(CompoundTag tag) {
} }
@ -112,7 +116,7 @@ public class BitSetBlocks implements IChunkSet {
} }
@Override @Override
public Map<Short, CompoundTag> getTiles() { public Map<BlockVector3, CompoundTag> getTiles() {
return null; return null;
} }

View File

@ -2,6 +2,14 @@ package com.boydti.fawe.beta.implementation.blocks;
import com.boydti.fawe.beta.IBlocks; import com.boydti.fawe.beta.IBlocks;
import com.boydti.fawe.beta.IChunkSet; import com.boydti.fawe.beta.IChunkSet;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.world.biome.BiomeType;
import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.block.BlockTypes;
import java.util.Map;
import java.util.Set;
public class CharBlocks implements IBlocks { public class CharBlocks implements IBlocks {
@ -81,6 +89,16 @@ public class CharBlocks implements IBlocks {
return sections[layer] == FULL; return sections[layer] == FULL;
} }
@Override
public char[] getArray(int layer) {
return sections[layer].get(this, layer);
}
@Override
public BlockState getBlock(int x, int y, int z) {
return BlockTypes.states[get(x, y, z)];
}
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;

View File

@ -3,6 +3,7 @@ package com.boydti.fawe.beta.implementation.blocks;
import com.boydti.fawe.FaweCache; import com.boydti.fawe.FaweCache;
import com.boydti.fawe.beta.IChunkSet; import com.boydti.fawe.beta.IChunkSet;
import com.boydti.fawe.config.Settings; import com.boydti.fawe.config.Settings;
import com.boydti.fawe.object.collection.BlockVector3ChunkMap;
import com.boydti.fawe.util.MathMan; import com.boydti.fawe.util.MathMan;
import com.sk89q.jnbt.CompoundTag; import com.sk89q.jnbt.CompoundTag;
import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.WorldEditException;
@ -12,7 +13,8 @@ import com.sk89q.worldedit.world.biome.BiomeType;
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.BlockTypes; import com.sk89q.worldedit.world.block.BlockTypes;
import java.util.HashMap;
import java.util.Collections;
import java.util.HashSet; import java.util.HashSet;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
@ -25,7 +27,7 @@ public class CharSetBlocks extends CharBlocks implements IChunkSet {
} }
public BiomeType[] biomes; public BiomeType[] biomes;
public HashMap<Short, CompoundTag> tiles; public BlockVector3ChunkMap<CompoundTag> tiles;
public HashSet<CompoundTag> entities; public HashSet<CompoundTag> entities;
public HashSet<UUID> entityRemoves; public HashSet<UUID> entityRemoves;
@ -36,29 +38,24 @@ public class CharSetBlocks extends CharBlocks implements IChunkSet {
POOL.offer(this); POOL.offer(this);
} }
@Override
public char[] getArray(int layer) {
return sections[layer].get(this, layer);
}
@Override @Override
public BiomeType[] getBiomes() { public BiomeType[] getBiomes() {
return biomes; return biomes;
} }
@Override @Override
public Map<Short, CompoundTag> getTiles() { public Map<BlockVector3, CompoundTag> getTiles() {
return tiles; return tiles == null ? Collections.emptyMap() : tiles;
} }
@Override @Override
public Set<CompoundTag> getEntities() { public Set<CompoundTag> getEntities() {
return entities; return entities == null ? Collections.emptySet() : entities;
} }
@Override @Override
public Set<UUID> getEntityRemoves() { public Set<UUID> getEntityRemoves() {
return entityRemoves; return entityRemoves == null ? Collections.emptySet() : entityRemoves;
} }
@Override @Override
@ -78,9 +75,16 @@ public class CharSetBlocks extends CharBlocks implements IChunkSet {
@Override @Override
public boolean setBlock(int x, int y, int z, BlockStateHolder holder) { public boolean setBlock(int x, int y, int z, BlockStateHolder holder) {
set(x, y, z, holder.getOrdinalChar()); set(x, y, z, holder.getOrdinalChar());
holder.applyTileEntity(this, x, y, z);
return true; return true;
} }
@Override
public void setBlocks(int layer, char[] data) {
this.blocks[layer] = data;
this.sections[layer] = data == null ? EMPTY : FULL;
}
@Override @Override
public <T extends BlockStateHolder<T>> boolean setBlock(BlockVector3 position, T block) public <T extends BlockStateHolder<T>> boolean setBlock(BlockVector3 position, T block)
throws WorldEditException { throws WorldEditException {
@ -90,10 +94,9 @@ public class CharSetBlocks extends CharBlocks implements IChunkSet {
@Override @Override
public boolean setTile(int x, int y, int z, CompoundTag tile) { public boolean setTile(int x, int y, int z, CompoundTag tile) {
if (tiles == null) { if (tiles == null) {
tiles = new HashMap<>(); tiles = new BlockVector3ChunkMap<CompoundTag>();
} }
final short pair = MathMan.tripleBlockCoord(x, y, z); tiles.put(x, y, z, tile);
tiles.put(pair, tile);
return true; return true;
} }

View File

@ -9,18 +9,19 @@ import com.boydti.fawe.beta.IChunk;
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.IQueueExtent; import com.boydti.fawe.beta.IQueueExtent;
import com.boydti.fawe.beta.implementation.SingleThreadQueueExtent;
import com.boydti.fawe.beta.implementation.blocks.CharSetBlocks;
import com.boydti.fawe.config.Settings; import com.boydti.fawe.config.Settings;
import com.sk89q.jnbt.CompoundTag; import com.sk89q.jnbt.CompoundTag;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.regions.Region;
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.BlockState; import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.block.BlockStateHolder; import com.sk89q.worldedit.world.block.BlockStateHolder;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.Future; import java.util.concurrent.Future;
import java.util.function.Supplier;
import javax.annotation.Nullable; import javax.annotation.Nullable;
/** /**
@ -34,10 +35,10 @@ public class ChunkHolder<T extends Future<T>> implements IChunk {
return POOL.poll(); return POOL.poll();
} }
private IChunkGet get; private IChunkGet chunkExisting; // The existing chunk (e.g. a clipboard, or the world, before changes)
private IChunkSet set; private IChunkSet chunkSet; // The blocks to be set to the chunkExisting
private IBlockDelegate delegate; private IBlockDelegate delegate; // delegate handles the abstraction of the chunk layers
private IQueueExtent extent; private IQueueExtent extent; // the parent queue extent which has this chunk
private int chunkX; private int chunkX;
private int chunkZ; private int chunkZ;
@ -73,36 +74,63 @@ public class ChunkHolder<T extends Future<T>> implements IChunk {
return getOrCreateGet().load(layer); return getOrCreateGet().load(layer);
} }
@Override
public CompoundTag getEntity(UUID uuid) {
return delegate.get(this).getEntity(uuid);
}
public static final IBlockDelegate BOTH = new IBlockDelegate() { public static final IBlockDelegate BOTH = new IBlockDelegate() {
@Override
public IChunkGet get(ChunkHolder chunk) {
return chunk.chunkExisting;
}
@Override
public IChunkSet set(ChunkHolder chunk) {
return chunk.chunkSet;
}
@Override @Override
public boolean setBiome(ChunkHolder chunk, int x, int y, int z, public boolean setBiome(ChunkHolder chunk, int x, int y, int z,
BiomeType biome) { BiomeType biome) {
return chunk.set.setBiome(x, y, z, biome); return chunk.chunkSet.setBiome(x, y, z, biome);
} }
@Override @Override
public boolean setBlock(ChunkHolder chunk, int x, int y, int z, public boolean setBlock(ChunkHolder chunk, int x, int y, int z,
BlockStateHolder block) { BlockStateHolder block) {
return chunk.set.setBlock(x, y, z, block); return chunk.chunkSet.setBlock(x, y, z, block);
} }
@Override @Override
public BiomeType getBiome(ChunkHolder chunk, int x, int z) { public BiomeType getBiome(ChunkHolder chunk, int x, int z) {
return chunk.get.getBiomeType(x, z); return chunk.chunkExisting.getBiomeType(x, z);
} }
@Override @Override
public BlockState getBlock(ChunkHolder chunk, int x, int y, int z) { public BlockState getBlock(ChunkHolder chunk, int x, int y, int z) {
return chunk.get.getBlock(x, y, z); return chunk.chunkExisting.getBlock(x, y, z);
} }
@Override @Override
public BaseBlock getFullBlock(ChunkHolder chunk, int x, int y, public BaseBlock getFullBlock(ChunkHolder chunk, int x, int y,
int z) { int z) {
return chunk.get.getFullBlock(x, y, z); return chunk.chunkExisting.getFullBlock(x, y, z);
} }
}; };
public static final IBlockDelegate GET = new IBlockDelegate() { public static final IBlockDelegate GET = new IBlockDelegate() {
@Override
public IChunkGet get(ChunkHolder chunk) {
return chunk.chunkExisting;
}
@Override
public IChunkSet set(ChunkHolder chunk) {
chunk.getOrCreateSet();
chunk.delegate = BOTH;
return chunk.chunkSet;
}
@Override @Override
public boolean setBiome(ChunkHolder chunk, int x, int y, int z, public boolean setBiome(ChunkHolder chunk, int x, int y, int z,
BiomeType biome) { BiomeType biome) {
@ -121,31 +149,43 @@ public class ChunkHolder<T extends Future<T>> implements IChunk {
@Override @Override
public BiomeType getBiome(ChunkHolder chunk, int x, int z) { public BiomeType getBiome(ChunkHolder chunk, int x, int z) {
return chunk.get.getBiomeType(x, z); return chunk.chunkExisting.getBiomeType(x, z);
} }
@Override @Override
public BlockState getBlock(ChunkHolder chunk, int x, int y, int z) { public BlockState getBlock(ChunkHolder chunk, int x, int y, int z) {
return chunk.get.getBlock(x, y, z); return chunk.chunkExisting.getBlock(x, y, z);
} }
@Override @Override
public BaseBlock getFullBlock(ChunkHolder chunk, int x, int y, public BaseBlock getFullBlock(ChunkHolder chunk, int x, int y,
int z) { int z) {
return chunk.get.getFullBlock(x, y, z); return chunk.chunkExisting.getFullBlock(x, y, z);
} }
}; };
public static final IBlockDelegate SET = new IBlockDelegate() { public static final IBlockDelegate SET = new IBlockDelegate() {
@Override
public IChunkGet get(ChunkHolder chunk) {
chunk.getOrCreateGet();
chunk.delegate = BOTH;
return chunk.chunkExisting;
}
@Override
public IChunkSet set(ChunkHolder chunk) {
return chunk.chunkSet;
}
@Override @Override
public boolean setBiome(ChunkHolder chunk, int x, int y, int z, public boolean setBiome(ChunkHolder chunk, int x, int y, int z,
BiomeType biome) { BiomeType biome) {
return chunk.set.setBiome(x, y, z, biome); return chunk.chunkSet.setBiome(x, y, z, biome);
} }
@Override @Override
public boolean setBlock(ChunkHolder chunk, int x, int y, int z, public boolean setBlock(ChunkHolder chunk, int x, int y, int z,
BlockStateHolder block) { BlockStateHolder block) {
return chunk.set.setBlock(x, y, z, block); return chunk.chunkSet.setBlock(x, y, z, block);
} }
@Override @Override
@ -171,6 +211,20 @@ public class ChunkHolder<T extends Future<T>> implements IChunk {
} }
}; };
public static final IBlockDelegate NULL = new IBlockDelegate() { public static final IBlockDelegate NULL = new IBlockDelegate() {
@Override
public IChunkGet get(ChunkHolder chunk) {
chunk.getOrCreateGet();
chunk.delegate = BOTH;
return chunk.chunkExisting;
}
@Override
public IChunkSet set(ChunkHolder chunk) {
chunk.getOrCreateSet();
chunk.delegate = BOTH;
return chunk.chunkSet;
}
@Override @Override
public boolean setBiome(ChunkHolder chunk, int x, int y, int z, public boolean setBiome(ChunkHolder chunk, int x, int y, int z,
BiomeType biome) { BiomeType biome) {
@ -221,9 +275,24 @@ public class ChunkHolder<T extends Future<T>> implements IChunk {
.getNbtData(); // TODO NOT IMPLEMENTED (add getTag delegate) .getNbtData(); // TODO NOT IMPLEMENTED (add getTag delegate)
} }
@Override
public Map<BlockVector3, CompoundTag> getTiles() {
return delegate.get(this).getTiles();
}
@Override
public Set<CompoundTag> getEntities() {
return delegate.get(this).getEntities();
}
@Override @Override
public boolean hasSection(int layer) { public boolean hasSection(int layer) {
return get != null && get.hasSection(layer); return chunkExisting != null && chunkExisting.hasSection(layer);
}
@Override
public char[] getArray(int layer) {
return delegate.get(this).getArray(layer);
} }
@Override @Override
@ -250,42 +319,42 @@ public class ChunkHolder<T extends Future<T>> implements IChunk {
@Override @Override
public boolean trim(boolean aggressive) { public boolean trim(boolean aggressive) {
if (set != null) { if (chunkSet != null) {
final boolean result = set.trim(aggressive); final boolean result = chunkSet.trim(aggressive);
if (result) { if (result) {
delegate = NULL; delegate = NULL;
get = null; chunkExisting = null;
set = null; chunkSet = null;
return true; return true;
} }
} }
if (aggressive) { if (aggressive) {
get = null; chunkExisting = null;
if (delegate == BOTH) { if (delegate == BOTH) {
delegate = SET; delegate = SET;
} else if (delegate == GET) { } else if (delegate == GET) {
delegate = NULL; delegate = NULL;
} }
} else { } else {
get.trim(false); chunkExisting.trim(false);
} }
return false; return false;
} }
@Override @Override
public boolean isEmpty() { public boolean isEmpty() {
return set == null || set.isEmpty(); return chunkSet == null || chunkSet.isEmpty();
} }
/** /**
* Get or create the settable part of this chunk * Get or create the existing part of this chunk
* @return * @return
*/ */
public final IChunkGet getOrCreateGet() { public final IChunkGet getOrCreateGet() {
if (get == null) { if (chunkExisting == null) {
get = newWrappedGet(); chunkExisting = newWrappedGet();
} }
return get; return chunkExisting;
} }
/** /**
@ -293,10 +362,10 @@ public class ChunkHolder<T extends Future<T>> implements IChunk {
* @return * @return
*/ */
public final IChunkSet getOrCreateSet() { public final IChunkSet getOrCreateSet() {
if (set == null) { if (chunkSet == null) {
set = newWrappedSet(); chunkSet = newWrappedSet();
} }
return set; return chunkSet;
} }
/** /**
@ -324,31 +393,39 @@ public class ChunkHolder<T extends Future<T>> implements IChunk {
this.extent = extent; this.extent = extent;
this.chunkX = chunkX; this.chunkX = chunkX;
this.chunkZ = chunkZ; this.chunkZ = chunkZ;
if (set != null) { if (chunkSet != null) {
set.reset(); chunkSet.reset();
delegate = SET; delegate = SET;
} else { } else {
delegate = NULL; delegate = NULL;
} }
get = null; chunkExisting = null;
} }
@Override @Override
public synchronized T call() { public synchronized T call() {
if (get != null && set != null) { if (chunkSet != null) {
return getOrCreateGet().call(getOrCreateSet(), this::recycle); return this.call(chunkSet, this::recycle);
} }
return null; return null;
} }
@Override @Override
public T call(IChunkSet set, Runnable finalize) { public T call(IChunkSet set, Runnable finalize) {
if (get != null && set != null) { if (set != null) {
return getOrCreateGet().call(set, finalize); IChunkGet get = getOrCreateGet();
set = getExtent().processBatch(this, get, set);
if (set != null) {
return get.call(set, finalize);
}
} }
return null; return null;
} }
/**
* Get the extent this chunk is in
* @return
*/
public IQueueExtent getExtent() { public IQueueExtent getExtent() {
return extent; return extent;
} }
@ -389,6 +466,8 @@ public class ChunkHolder<T extends Future<T>> implements IChunk {
} }
public interface IBlockDelegate { public interface IBlockDelegate {
IChunkGet get(ChunkHolder chunk);
IChunkSet set(ChunkHolder chunk);
boolean setBiome(ChunkHolder chunk, int x, int y, int z, boolean setBiome(ChunkHolder chunk, int x, int y, int z,
BiomeType biome); BiomeType biome);

View File

@ -2,8 +2,15 @@ package com.boydti.fawe.beta.implementation.holder;
import com.boydti.fawe.beta.IChunk; import com.boydti.fawe.beta.IChunk;
import com.boydti.fawe.beta.IQueueExtent; import com.boydti.fawe.beta.IQueueExtent;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.world.biome.BiomeType;
import java.lang.ref.Reference; import java.lang.ref.Reference;
import java.lang.ref.WeakReference; import java.lang.ref.WeakReference;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
/** /**
* A {@link ReferenceChunk} using {@link WeakReference} to hold the chunk. * A {@link ReferenceChunk} using {@link WeakReference} to hold the chunk.

View File

@ -43,8 +43,8 @@ public class CFICommand extends CommandProcessor<Object, Object> {
} }
@Override @Override
public int process(InjectedValueAccess context, List<String> args, Object result) { public Object process(InjectedValueAccess context, List<String> args, Object result) {
return 0; return result;
} }
private List<String> dispatch(Player player, CFISettings settings, List<String> args, InjectedValueAccess context) { private List<String> dispatch(Player player, CFISettings settings, List<String> args, InjectedValueAccess context) {

View File

@ -67,13 +67,13 @@ public abstract class CommandProcessor<I, O> implements CommandManager {
} }
@Override @Override
public final int execute(InjectedValueAccess context, List<String> args) { public final Object execute(InjectedValueAccess context, List<String> args) {
args = preprocess(context, args); args = preprocess(context, args);
if (args != null) { if (args != null) {
Object result = parent.execute(context, args); Object result = parent.execute(context, args);
return process(context, args, result); // TODO NOT IMPLEMENTED (recompile piston) return process(context, args, result); // TODO NOT IMPLEMENTED (recompile piston)
} else { } else {
return 0; return null;
} }
} }
@ -89,5 +89,5 @@ public abstract class CommandProcessor<I, O> implements CommandManager {
public abstract List<String> preprocess(InjectedValueAccess context, List<String> args); public abstract List<String> preprocess(InjectedValueAccess context, List<String> args);
public abstract int process(InjectedValueAccess context, List<String> args, Object result); public abstract Object process(InjectedValueAccess context, List<String> args, Object result);
} }

View File

@ -12,23 +12,17 @@ import com.sk89q.worldedit.internal.registry.InputParser;
import java.util.*; import java.util.*;
public abstract class FaweParser<T> extends InputParser<T> { public abstract class FaweParser<T> extends InputParser<T> {
private final Class<T> type;
protected FaweParser(WorldEdit worldEdit, Class<T> type) { protected FaweParser(WorldEdit worldEdit) {
super(worldEdit); super(worldEdit);
this.type = type;
} }
public PlatformCommandManager getPlatform() { public PlatformCommandManager getPlatform() {
return PlatformCommandManager.getInstance(); return PlatformCommandManager.getInstance();
} }
public Class<T> getType() { public T parse(String input, Actor actor) {
return type; return getPlatform().parse("pattern " + input, actor);
}
public Collection<T> parse(String input, Actor actor) {
return getPlatform().parse(getType(), "pattern " + input, actor);
} }
public T catchSuggestion(String currentInput, String nextInput, ParserContext context) throws InputParseException { public T catchSuggestion(String currentInput, String nextInput, ParserContext context) throws InputParseException {

View File

@ -24,6 +24,7 @@ import com.sk89q.worldedit.registry.state.PropertyKey;
import com.sk89q.worldedit.util.Direction; import com.sk89q.worldedit.util.Direction;
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.BlockCategories;
import com.sk89q.worldedit.world.block.BlockID; import com.sk89q.worldedit.world.block.BlockID;
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;
@ -203,93 +204,74 @@ public class SchematicStreamer extends NBTStreamer {
@Override @Override
public <B extends BlockStateHolder<B>> void run(int x, int y, int z, B block) { public <B extends BlockStateHolder<B>> void run(int x, int y, int z, B block) {
BlockType type = block.getBlockType(); BlockType type = block.getBlockType();
switch (type.getInternalId()) { if (BlockCategories.STAIRS.contains(type)) {
case BlockID.ACACIA_STAIRS: Object half = block.getState(PropertyKey.HALF);
case BlockID.BIRCH_STAIRS: Direction facing = block.getState(PropertyKey.FACING);
case BlockID.BRICK_STAIRS:
case BlockID.COBBLESTONE_STAIRS:
case BlockID.DARK_OAK_STAIRS:
case BlockID.DARK_PRISMARINE_STAIRS:
case BlockID.JUNGLE_STAIRS:
case BlockID.NETHER_BRICK_STAIRS:
case BlockID.OAK_STAIRS:
case BlockID.PRISMARINE_BRICK_STAIRS:
case BlockID.PRISMARINE_STAIRS:
case BlockID.PURPUR_STAIRS:
case BlockID.QUARTZ_STAIRS:
case BlockID.RED_SANDSTONE_STAIRS:
case BlockID.SANDSTONE_STAIRS:
case BlockID.SPRUCE_STAIRS:
case BlockID.STONE_BRICK_STAIRS:
Object half = block.getState(PropertyKey.HALF);
Direction facing = block.getState(PropertyKey.FACING);
BlockVector3 forward = facing.toBlockVector(); BlockVector3 forward = facing.toBlockVector();
Direction left = facing.getLeft(); Direction left = facing.getLeft();
Direction right = facing.getRight(); Direction right = facing.getRight();
BlockStateHolder<com.sk89q.worldedit.world.block.BaseBlock> forwardBlock = fc.getBlock(x + forward.getBlockX(), y + forward.getBlockY(), z + forward.getBlockZ()); BlockStateHolder<com.sk89q.worldedit.world.block.BaseBlock> forwardBlock = fc.getBlock(x + forward.getBlockX(), y + forward.getBlockY(), z + forward.getBlockZ());
BlockType forwardType = forwardBlock.getBlockType(); BlockType forwardType = forwardBlock.getBlockType();
if (forwardType.hasProperty(PropertyKey.SHAPE) && forwardType.hasProperty(PropertyKey.FACING)) { if (forwardType.hasProperty(PropertyKey.SHAPE) && forwardType.hasProperty(PropertyKey.FACING)) {
Direction forwardFacing = (Direction) forwardBlock.getState(PropertyKey.FACING); Direction forwardFacing = (Direction) forwardBlock.getState(PropertyKey.FACING);
if (forwardFacing == left) { if (forwardFacing == left) {
BlockStateHolder<com.sk89q.worldedit.world.block.BaseBlock> rightBlock = fc.getBlock(x + right.toBlockVector().getBlockX(), y + right.toBlockVector().getBlockY(), z + right.toBlockVector().getBlockZ()); BlockStateHolder<com.sk89q.worldedit.world.block.BaseBlock> rightBlock = fc.getBlock(x + right.toBlockVector().getBlockX(), y + right.toBlockVector().getBlockY(), z + right.toBlockVector().getBlockZ());
BlockType rightType = rightBlock.getBlockType(); BlockType rightType = rightBlock.getBlockType();
if (!rightType.hasProperty(PropertyKey.SHAPE) || rightBlock.getState(PropertyKey.FACING) != facing) { if (!rightType.hasProperty(PropertyKey.SHAPE) || rightBlock.getState(PropertyKey.FACING) != facing) {
fc.setBlock(x, y, z, block.with(PropertyKey.SHAPE, "inner_left")); fc.setBlock(x, y, z, block.with(PropertyKey.SHAPE, "inner_left"));
}
return;
} else if (forwardFacing == right) {
BlockStateHolder<com.sk89q.worldedit.world.block.BaseBlock> 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;
} }
} return;
} else if (forwardFacing == right) {
BlockStateHolder<com.sk89q.worldedit.world.block.BaseBlock> backwardsBlock = fc.getBlock(x - forward.getBlockX(), y - forward.getBlockY(), z - forward.getBlockZ()); BlockStateHolder<com.sk89q.worldedit.world.block.BaseBlock> leftBlock = fc.getBlock(x + left.toBlockVector().getBlockX(), y + left.toBlockVector().getBlockY(), z + left.toBlockVector().getBlockZ());
BlockType backwardsType = backwardsBlock.getBlockType(); BlockType leftType = leftBlock.getBlockType();
if (backwardsType.hasProperty(PropertyKey.SHAPE) && backwardsType.hasProperty(PropertyKey.FACING)) { if (!leftType.hasProperty(PropertyKey.SHAPE) || leftBlock.getState(PropertyKey.FACING) != facing) {
Direction backwardsFacing = (Direction) backwardsBlock.getState(PropertyKey.FACING); fc.setBlock(x, y, z, block.with(PropertyKey.SHAPE, "inner_right"));
if (backwardsFacing == left) {
BlockStateHolder<com.sk89q.worldedit.world.block.BaseBlock> 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) {
fc.setBlock(x, y, z, block.with(PropertyKey.SHAPE, "outer_left"));
}
return;
} else if (backwardsFacing == right) {
BlockStateHolder<com.sk89q.worldedit.world.block.BaseBlock> 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, "outer_right"));
}
return;
} }
return;
} }
break; }
default:
int group = group(type);
if (group == -1) return;
BlockStateHolder set = block;
if (set.getState(PropertyKey.NORTH) == Boolean.FALSE && merge(group, x, y, z - 1)) set = set.with(PropertyKey.NORTH, true); BlockStateHolder<com.sk89q.worldedit.world.block.BaseBlock> backwardsBlock = fc.getBlock(x - forward.getBlockX(), y - forward.getBlockY(), z - forward.getBlockZ());
if (set.getState(PropertyKey.EAST) == Boolean.FALSE && merge(group, x + 1, y, z)) set = set.with(PropertyKey.EAST, true); BlockType backwardsType = backwardsBlock.getBlockType();
if (set.getState(PropertyKey.SOUTH) == Boolean.FALSE && merge(group, x, y, z + 1)) set = set.with(PropertyKey.SOUTH, true); if (backwardsType.hasProperty(PropertyKey.SHAPE) && backwardsType.hasProperty(PropertyKey.FACING)) {
if (set.getState(PropertyKey.WEST) == Boolean.FALSE && merge(group, x - 1, y, z)) set = set.with(PropertyKey.WEST, true); Direction backwardsFacing = (Direction) backwardsBlock.getState(PropertyKey.FACING);
if (backwardsFacing == left) {
if (group == 2) { BlockStateHolder<com.sk89q.worldedit.world.block.BaseBlock> rightBlock = fc.getBlock(x + right.toBlockVector().getBlockX(), y + right.toBlockVector().getBlockY(), z + right.toBlockVector().getBlockZ());
int ns = ((Boolean) set.getState(PropertyKey.NORTH) ? 1 : 0) + ((Boolean) set.getState(PropertyKey.SOUTH) ? 1 : 0); BlockType rightType = rightBlock.getBlockType();
int ew = ((Boolean) set.getState(PropertyKey.EAST) ? 1 : 0) + ((Boolean) set.getState(PropertyKey.WEST) ? 1 : 0); if (!rightType.hasProperty(PropertyKey.SHAPE) || rightBlock.getState(PropertyKey.FACING) != facing) {
if (Math.abs(ns - ew) != 2 || fc.getBlock(x, y + 1, z).getBlockType().getMaterial().isSolid()) { fc.setBlock(x, y, z, block.with(PropertyKey.SHAPE, "outer_left"));
set = set.with(PropertyKey.UP, true);
} }
return;
} else if (backwardsFacing == right) {
BlockStateHolder<com.sk89q.worldedit.world.block.BaseBlock> 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, "outer_right"));
}
return;
} }
}
} else {
int group = group(type);
if (group == -1) return;
BlockStateHolder set = block;
if (set != block) fc.setBlock(x, y, z, set); if (set.getState(PropertyKey.NORTH) == Boolean.FALSE && merge(group, x, y, z - 1)) set = set.with(PropertyKey.NORTH, true);
break; if (set.getState(PropertyKey.EAST) == Boolean.FALSE && merge(group, x + 1, y, z)) set = set.with(PropertyKey.EAST, true);
if (set.getState(PropertyKey.SOUTH) == Boolean.FALSE && merge(group, x, y, z + 1)) set = set.with(PropertyKey.SOUTH, true);
if (set.getState(PropertyKey.WEST) == Boolean.FALSE && merge(group, x - 1, y, z)) set = set.with(PropertyKey.WEST, true);
if (group == 2) {
int ns = ((Boolean) set.getState(PropertyKey.NORTH) ? 1 : 0) + ((Boolean) set.getState(PropertyKey.SOUTH) ? 1 : 0);
int ew = ((Boolean) 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) fc.setBlock(x, y, z, set);
} }
} }
}, false); }, false);

View File

@ -160,4 +160,9 @@ public class HistoryExtent extends AbstractDelegateExtent {
return this.entity.setLocation(location); return this.entity.setLocation(location);
} }
} }
@Override
public Extent disableHistory() {
return getExtent();
}
} }

View File

@ -1,62 +1,15 @@
package com.boydti.fawe.object; package com.boydti.fawe.object;
import com.sk89q.worldedit.entity.MapMetadatable;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
public class Metadatable { public class Metadatable implements MapMetadatable {
private final ConcurrentHashMap<String, Object> meta = new ConcurrentHashMap<>(); private final ConcurrentHashMap<String, Object> meta = new ConcurrentHashMap<>();
/** @Override
* Set some session only metadata for the player public Map<String, Object> getRawMeta() {
* return meta;
* @param key
* @param value
* @return previous value
*/
public void setMeta(String key, Object value) {
this.meta.put(key, value);
}
public <T> T getAndSetMeta(String key, T value) {
return (T) this.meta.put(key, value);
}
public boolean hasMeta() {
return !meta.isEmpty();
}
/**
* Get the metadata for a key.
*
* @param <V>
* @param key
* @return
*/
public <V> V getMeta(String key) {
return (V) this.meta.get(key);
}
/**
* Get the metadata for a specific key (or return the default provided)
*
* @param key
* @param def
* @param <V>
* @return
*/
public <V> V getMeta(String key, V def) {
V value = (V) this.meta.get(key);
return value == null ? def : value;
}
/**
* Delete the metadata for a key.
* - metadata is session only
* - deleting other plugin's metadata may cause issues
*
* @param key
*/
public <V> V deleteMeta(String key) {
return (V) this.meta.remove(key);
} }
} }

View File

@ -62,7 +62,7 @@ public class BrushSettings {
if (constructor == null) { if (constructor == null) {
return new BrushSettings(); return new BrushSettings();
} }
BrushSettings bs = (BrushSettings) manager.parse(BrushSettings.class, constructor, player); BrushSettings bs = manager.parse(constructor, player);
bs.constructor.put(SettingType.BRUSH, constructor); bs.constructor.put(SettingType.BRUSH, constructor);
if (settings.containsKey(SettingType.PERMISSIONS.name())) { if (settings.containsKey(SettingType.PERMISSIONS.name())) {
bs.permissions.addAll((Collection<? extends String>) settings.get(SettingType.PERMISSIONS.name())); bs.permissions.addAll((Collection<? extends String>) settings.get(SettingType.PERMISSIONS.name()));

View File

@ -1,6 +1,9 @@
package com.boydti.fawe.object.brush; package com.boydti.fawe.object.brush;
import com.boydti.fawe.util.StringMan; import com.boydti.fawe.util.StringMan;
import com.boydti.fawe.wrappers.LocationMaskedPlayerWrapper;
import com.boydti.fawe.wrappers.PlayerWrapper;
import com.boydti.fawe.wrappers.SilentPlayerWrapper;
import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.MaxChangedBlocksException; import com.sk89q.worldedit.MaxChangedBlocksException;
import com.sk89q.worldedit.command.tool.brush.Brush; import com.sk89q.worldedit.command.tool.brush.Brush;
@ -39,9 +42,10 @@ public class CommandBrush implements Brush {
position = position.add(face.getDirection().toBlockPoint()); position = position.add(face.getDirection().toBlockPoint());
} }
player.setSelection(selector); player.setSelection(selector);
PlayerWrapper wePlayer = new SilentPlayerWrapper(new LocationMaskedPlayerWrapper(player, new Location(player.getExtent(), position.toVector3())));
List<String> cmds = StringMan.split(replaced, ';'); List<String> cmds = StringMan.split(replaced, ';');
for (String cmd : cmds) { for (String cmd : cmds) {
CommandEvent event = new CommandEvent(player, cmd); CommandEvent event = new CommandEvent(wePlayer, cmd);
PlatformCommandManager.getInstance().handleCommandOnCurrentThread(event); PlatformCommandManager.getInstance().handleCommandOnCurrentThread(event);
} }
} }

View File

@ -18,14 +18,25 @@ import java.util.Arrays;
public class ErodeBrush implements Brush { public class ErodeBrush implements Brush {
private static final BlockVector3[] FACES_TO_CHECK = Direction.valuesOf(Direction.Flag.CARDINAL).stream().map(Direction::toBlockVector).toArray(BlockVector3[]::new); private static final BlockVector3[] FACES_TO_CHECK = Direction.valuesOf(Direction.Flag.CARDINAL).stream().map(Direction::toBlockVector).toArray(BlockVector3[]::new);
private final int erodeFaces, erodeRec, fillFaces, fillRec;
public ErodeBrush() {
this(2, 1, 5, 1);
}
public ErodeBrush(int erodeFaces, int erodeRec, int fillFaces, int fillRec) {
this.erodeFaces = erodeFaces;
this.erodeRec = erodeRec;
this.fillFaces = fillFaces;
this.fillRec = fillRec;
}
@Override @Override
public void build(EditSession editSession, BlockVector3 position, Pattern pattern, double size) throws MaxChangedBlocksException { public void build(EditSession editSession, BlockVector3 position, Pattern pattern, double size) throws MaxChangedBlocksException {
this.erosion(editSession, 2, 1, 5, position, size); this.erosion(editSession, erodeFaces, erodeRec, fillFaces, fillRec, position, size);
} }
void erosion(EditSession es, int erodeFaces, int erodeRec, int fillFaces, public void erosion(final EditSession es, int erodeFaces, int erodeRec, int fillFaces, int fillRec, BlockVector3 target, double size) {
BlockVector3 target, double size) {
int brushSize = (int) size + 1; int brushSize = (int) size + 1;
int brushSizeSquared = (int) (size * size); int brushSizeSquared = (int) (size * size);
int dimension = brushSize * 2 + 1; int dimension = brushSize * 2 + 1;
@ -55,7 +66,7 @@ public class ErodeBrush implements Brush {
swap++; swap++;
} }
for (int i = 0; i < 1; ++i) { for (int i = 0; i < fillRec; ++i) {
fillIteration(brushSize, brushSizeSquared, fillFaces, swap % 2 == 0 ? buffer1 : buffer2, swap % 2 == 1 ? buffer1 : buffer2); fillIteration(brushSize, brushSizeSquared, fillFaces, swap % 2 == 0 ? buffer1 : buffer2, swap % 2 == 1 ? buffer1 : buffer2);
swap++; swap++;
} }

View File

@ -47,7 +47,7 @@ public class InspectBrush extends BrushTool implements DoubleActionTraceTool {
} }
public Vector3 getTarget(Player player, boolean adjacent) { public Vector3 getTarget(Player player, boolean adjacent) {
int range = this.range > -1 ? getRange() : MAX_RANGE; int range = this.range > -1 ? getRange() : DEFAULT_RANGE;
if (adjacent) { if (adjacent) {
Location face = player.getBlockTraceFace(range, true); Location face = player.getBlockTraceFace(range, true);
return face.add(face.getDirection()); return face.add(face.getDirection());

View File

@ -6,8 +6,10 @@ import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.math.BlockVector3;
public class RaiseBrush extends ErodeBrush { public class RaiseBrush extends ErodeBrush {
@Override public RaiseBrush() {
public void build(EditSession editSession, BlockVector3 position, Pattern pattern, double size) throws MaxChangedBlocksException { this(6, 0, 1, 1);
this.erosion(editSession, 6, 0, 1, position, size); }
public RaiseBrush(int erodeFaces, int erodeRec, int fillFaces, int fillRec) {
super(2, 1, 5, 1);
} }
} }

View File

@ -31,7 +31,7 @@ public class SplineBrush implements Brush, ResettableTool {
private final Player player; private final Player player;
private BlockVector3 position; private BlockVector3 position;
public SplineBrush(Player player, LocalSession session) { public SplineBrush(Player player) {
this.player = player; this.player = player;
this.positionSets = new ArrayList<>(); this.positionSets = new ArrayList<>();
} }

View File

@ -1928,11 +1928,6 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
return false; return false;
} }
@Override
public boolean setBiome(BlockVector2 position, BiomeType biome) {
return setBiome(position.getX(), 0, position.getBlockZ(), biome);
}
@Override @Override
public int getBlockLightLevel(BlockVector3 position) { public int getBlockLightLevel(BlockVector3 position) {
return 0; return 0;

View File

@ -1,6 +1,6 @@
package com.boydti.fawe.object.brush.visualization.cfi; package com.boydti.fawe.object.brush.visualization.cfi;
import com.boydti.fawe.object.collection.IterableThreadLocal; import com.boydti.fawe.object.collection.CleanableThreadLocal;
import com.boydti.fawe.object.io.BufferedRandomAccessFile; import com.boydti.fawe.object.io.BufferedRandomAccessFile;
import com.boydti.fawe.util.MainUtil; import com.boydti.fawe.util.MainUtil;
import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.extent.Extent;
@ -209,8 +209,8 @@ public abstract class MCAWriter implements Extent {
} }
pool.awaitQuiescence(Long.MAX_VALUE, TimeUnit.MILLISECONDS); pool.awaitQuiescence(Long.MAX_VALUE, TimeUnit.MILLISECONDS);
pool.shutdown(); pool.shutdown();
IterableThreadLocal.clean(byteStore1); CleanableThreadLocal.clean(byteStore1);
IterableThreadLocal.clean(byteStore2); CleanableThreadLocal.clean(byteStore2);
IterableThreadLocal.clean(deflateStore); CleanableThreadLocal.clean(deflateStore);
} }
} }

View File

@ -3,8 +3,13 @@ package com.boydti.fawe.object.changeset;
import com.boydti.fawe.Fawe; import com.boydti.fawe.Fawe;
import com.boydti.fawe.FaweAPI; import com.boydti.fawe.FaweAPI;
import com.boydti.fawe.FaweCache; import com.boydti.fawe.FaweCache;
import com.boydti.fawe.beta.IBatchProcessor;
import com.boydti.fawe.beta.IChunk;
import com.boydti.fawe.beta.IChunkGet;
import com.boydti.fawe.beta.IChunkSet;
import com.boydti.fawe.config.Settings; import com.boydti.fawe.config.Settings;
import com.boydti.fawe.logging.rollback.RollbackOptimizedHistory; import com.boydti.fawe.logging.rollback.RollbackOptimizedHistory;
import com.boydti.fawe.object.HistoryExtent;
import com.boydti.fawe.util.EditSessionBuilder; import com.boydti.fawe.util.EditSessionBuilder;
import com.boydti.fawe.util.MainUtil; import com.boydti.fawe.util.MainUtil;
import com.boydti.fawe.util.TaskManager; import com.boydti.fawe.util.TaskManager;
@ -12,6 +17,7 @@ import com.google.common.util.concurrent.Futures;
import com.sk89q.jnbt.CompoundTag; import com.sk89q.jnbt.CompoundTag;
import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.extent.inventory.BlockBag; import com.sk89q.worldedit.extent.inventory.BlockBag;
import com.sk89q.worldedit.history.change.BlockChange; import com.sk89q.worldedit.history.change.BlockChange;
import com.sk89q.worldedit.history.change.Change; import com.sk89q.worldedit.history.change.Change;
@ -23,17 +29,19 @@ import com.sk89q.worldedit.regions.Region;
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.BlockState;
import java.util.Iterator; import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.Future; import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
public abstract class FaweChangeSet implements ChangeSet { public abstract class FaweChangeSet implements ChangeSet, IBatchProcessor {
private World world; private World world;
private final String worldName; private final String worldName;
private final boolean mainThread;
private final int layers;
protected AtomicInteger waitingCombined = new AtomicInteger(0); protected AtomicInteger waitingCombined = new AtomicInteger(0);
protected AtomicInteger waitingAsync = new AtomicInteger(0); protected AtomicInteger waitingAsync = new AtomicInteger(0);
@ -51,15 +59,11 @@ public abstract class FaweChangeSet implements ChangeSet {
public FaweChangeSet(String world) { public FaweChangeSet(String world) {
this.worldName = world; this.worldName = world;
this.mainThread = Fawe.get() == null || Fawe.isMainThread();
this.layers = FaweCache.IMP.CHUNK_LAYERS;
} }
public FaweChangeSet(World world) { public FaweChangeSet(World world) {
this.world = world; this.world = world;
this.worldName = world.getName(); this.worldName = world.getName();
this.mainThread = Fawe.isMainThread();
this.layers = this.world.getMaxY() + 1 >> 4;
} }
public String getWorldName() { public String getWorldName() {
@ -124,6 +128,92 @@ public abstract class FaweChangeSet implements ChangeSet {
return getIterator(true); return getIterator(true);
} }
@Override
public Extent construct(Extent child) {
return new HistoryExtent(child, this);
}
@Override
public synchronized IChunkSet processBatch(IChunk chunk, IChunkGet get, IChunkSet set) {
int bx = chunk.getX() << 4;
int bz = chunk.getZ() << 4;
Map<BlockVector3, CompoundTag> tilesFrom = get.getTiles();
Map<BlockVector3, CompoundTag> tilesTo = set.getTiles();
if (!tilesFrom.isEmpty()) {
for (Map.Entry<BlockVector3, CompoundTag> entry : tilesFrom.entrySet()) {
BlockVector3 pos = entry.getKey();
BlockState fromBlock = get.getBlock(pos.getX() & 15, pos.getY(), pos.getZ() & 15);
BlockState toBlock = set.getBlock(pos.getX() & 15, pos.getY(), pos.getZ() & 15);
if (fromBlock != toBlock || tilesTo.containsKey(pos)) {
addTileRemove(entry.getValue());
}
}
}
if (!tilesTo.isEmpty()) {
for (Map.Entry<BlockVector3, CompoundTag> entry : tilesTo.entrySet()) {
addTileCreate(entry.getValue());
}
}
Set<UUID> entRemoves = set.getEntityRemoves();
if (!entRemoves.isEmpty()) {
for (UUID uuid : entRemoves) {
CompoundTag found = get.getEntity(uuid);
if (found != null) {
addEntityRemove(found);
}
}
}
Set<CompoundTag> ents = set.getEntities();
if (!ents.isEmpty()) {
for (CompoundTag tag : ents) {
addEntityCreate(tag);
}
}
for (int layer = 0; layer < 16; layer++) {
if (!set.hasSection(layer)) continue;
// add each block and tile
char[] blocksGet = get.getArray(layer);
if (blocksGet == null) {
blocksGet = FaweCache.IMP.EMPTY_CHAR_4096;
}
char[] blocksSet = set.getArray(layer);
int by = layer << 4;
for (int y = 0, index = 0; y < 16; y++) {
int yy = y + by;
for (int z = 0; z < 16; z++) {
int zz = z + bz;
for (int x = 0; x < 16; x++, index++) {
int xx = bx + x;
int combinedFrom = blocksGet[index];
int combinedTo = blocksSet[index];
if (combinedTo != 0) {
add(xx, yy, zz, combinedFrom, combinedTo);
}
}
}
}
}
BiomeType[] biomes = set.getBiomes();
if (biomes != null) {
for (int z = 0, index = 0; z < 16; z++) {
for (int x = 0; x < 16; x++, index++) {
BiomeType newBiome = biomes[index];
if (newBiome != null) {
BiomeType oldBiome = get.getBiomeType(x, z);
if (oldBiome != newBiome) {
addBiomeChange(bx + x, bz + z, oldBiome, newBiome);
}
}
}
}
}
return set;
}
public abstract void addTileCreate(CompoundTag tag); public abstract void addTileCreate(CompoundTag tag);
public abstract void addTileRemove(CompoundTag tag); public abstract void addTileRemove(CompoundTag tag);

View File

@ -0,0 +1,112 @@
package com.boydti.fawe.object.collection;
import org.jetbrains.annotations.NotNull;
import java.util.Collections;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.function.Function;
public class AdaptedMap<K, V, K2, V2> implements IAdaptedMap<K, V, K2, V2> {
private final Map<K2, V2> parent;
private final Function<V2, V> value2;
private final Function<K2, K> key2;
private final Function<V, V2> value;
private final Function<K, K2> key;
private static final Function SAME = o -> o;
private static final Function IMMUTABLE = o -> { throw new UnsupportedOperationException("Immutable"); };
public static <K, K2, V> AdaptedMap<K, V, K2, V> keys(Map<K2, V> parent, Function<K, K2> key, Function<K2, K> key2) {
return new AdaptedMap<K, V, K2, V>(parent, key, key2, SAME, SAME);
}
public static <K, V, V2> AdaptedMap<K, V, K, V2> values(Map<K, V2> parent, Function<V, V2> value, Function<V2, V> value2) {
return new AdaptedMap<K, V, K, V2>(parent, SAME, SAME, value, value2);
}
public static <K, K2, V, V2> AdaptedMap<K, V, K2, V2> immutable(Map<K2, V2> parent, Function<K2, K> key, Function<V2, V> value) {
return new AdaptedMap<K, V, K2, V2>(parent, IMMUTABLE, key, IMMUTABLE, value);
}
public AdaptedMap(Map<K2, V2> parent, Function<K, K2> key, Function<K2, K> key2, Function<V, V2> value, Function<V2, V> value2) {
this.parent = parent;
this.key = key;
this.value = value;
this.key2 = key2;
this.value2 = value2;
}
@Override
public Map<K2, V2> getParent() {
return this.parent;
}
@Override
public K2 adaptKey(K key) {
return this.key.apply(key);
}
@Override
public V2 adaptValue(V value) {
return this.value.apply(value);
}
@Override
public K adaptKey2(K2 key) {
return this.key2.apply(key);
}
@Override
public V adaptValue2(V2 value) {
return value2.apply(value);
}
@NotNull
@Override
public Set<Entry<K, V>> entrySet() {
if (isEmpty()) return Collections.emptySet();
return new AdaptedSetCollection<>(getParent().entrySet(), new com.google.common.base.Function<Entry<K2, V2>, Entry<K, V>>() {
private AdaptedPair entry = new AdaptedPair();
@Override
public Entry<K, V> apply(@javax.annotation.Nullable Entry<K2, V2> input) {
entry.input = input;
return entry;
}
});
}
public class AdaptedPair implements Entry<K, V> {
private Entry<K2, V2> input;
@Override
public K getKey() {
return adaptKey2(input.getKey());
}
@Override
public V getValue() {
return adaptValue2(input.getValue());
}
@Override
public V setValue(V value) {
return adaptValue2(input.setValue(adaptValue(value)));
}
@Override
public boolean equals(Object o) {
if (o instanceof Entry) {
return Objects.equals(((Entry) o).getKey(), getKey()) && Objects.equals(((Entry) o).getValue(), getValue());
}
return false;
}
@Override
public int hashCode() {
return 1337;
}
}
}

View File

@ -18,14 +18,12 @@ import org.jetbrains.annotations.NotNull;
* @param <T> * @param <T>
*/ */
public class AdaptedSetCollection<T, V> implements Set<V> { public class AdaptedSetCollection<T, V> implements Set<V> {
private final Function<T, V> adapter;
private final Collection<V> adapted; private final Collection<V> adapted;
private final Collection<T> original; private final Collection<T> original;
public AdaptedSetCollection(Collection<T> collection, Function<T, V> adapter) { public AdaptedSetCollection(Collection<T> collection, Function<T, V> adapter) {
this.original = collection; this.original = collection;
this.adapted = Collections2.transform(collection, adapter); this.adapted = Collections2.transform(collection, adapter);
this.adapter = adapter;
} }
public Collection<T> getOriginal() { public Collection<T> getOriginal() {

View File

@ -0,0 +1,54 @@
package com.boydti.fawe.object.collection;
import com.boydti.fawe.util.MathMan;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.math.MutableBlockVector3;
import it.unimi.dsi.fastutil.shorts.Short2ObjectArrayMap;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collection;
import java.util.Map;
import java.util.Set;
public class BlockVector3ChunkMap<T> implements Map<BlockVector3, T>, IAdaptedMap<BlockVector3, T, Short, T> {
private final Short2ObjectArrayMap<T> map = new Short2ObjectArrayMap<>();
@Override
public Map<Short, T> getParent() {
return map;
}
@Override
public Short adaptKey(BlockVector3 key) {
return MathMan.tripleBlockCoord(key.getX(), key.getY(), key.getZ());
}
@Override
public BlockVector3 adaptKey2(Short key) {
int x = MathMan.untripleBlockCoordX(key);
int y = MathMan.untripleBlockCoordY(key);
int z = MathMan.untripleBlockCoordZ(key);
return MutableBlockVector3.get(x, y, z);
}
@Override
public T adaptValue2(T value) {
return value;
}
@Override
public T adaptValue(T value) {
return value;
}
public T put(int x, int y, int z, T value) {
short key = MathMan.tripleBlockCoord(x, y, z);
return map.put(key, value);
}
public boolean contains(int x, int y, int z) {
short key = MathMan.tripleBlockCoord(x, y, z);
return map.containsKey(key);
}
}

View File

@ -0,0 +1,122 @@
package com.boydti.fawe.object.collection;
import com.boydti.fawe.util.MainUtil;
import java.lang.ref.Reference;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.concurrent.atomic.LongAdder;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;
public class CleanableThreadLocal<T> extends ThreadLocal<T> {
private final Supplier<T> supplier;
private final Function<T, T> modifier;
private LongAdder count = new LongAdder();
public CleanableThreadLocal(Supplier<T> supplier) {
this(supplier, Function.identity());
}
public CleanableThreadLocal(Supplier<T> supplier, Consumer<T> modifier) {
this(supplier, t -> {
modifier.accept(t);
return t;
});
}
public CleanableThreadLocal(Supplier<T> supplier, Function<T, T> modifier) {
this.supplier = supplier;
this.modifier = modifier;
}
@Override
protected final T initialValue() {
T value = modifier.apply(init());
if (value != null) {
count.increment();
}
return value;
}
public T init() {
return supplier.get();
}
public void clean() {
if (count.sumThenReset() > 0) {
CleanableThreadLocal.clean(this);
}
}
public static void clean(ThreadLocal instance) {
try {
Thread[] threads = MainUtil.getThreads();
Field tl = Thread.class.getDeclaredField("threadLocals");
tl.setAccessible(true);
Method methodRemove = null;
for (Thread thread : threads) {
if (thread != null) {
Object tlm = tl.get(thread);
if (tlm != null) {
if (methodRemove == null) {
methodRemove = tlm.getClass().getDeclaredMethod("remove", ThreadLocal.class);
methodRemove.setAccessible(true);
}
if (methodRemove != null) {
try {
methodRemove.invoke(tlm, instance);
} catch (Throwable ignore) {}
}
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
public static void cleanAll() {
try {
// Get a reference to the thread locals table of the current thread
Thread thread = Thread.currentThread();
Field threadLocalsField = Thread.class.getDeclaredField("threadLocals");
threadLocalsField.setAccessible(true);
Object threadLocalTable = threadLocalsField.get(thread);
// Get a reference to the array holding the thread local variables inside the
// ThreadLocalMap of the current thread
Class threadLocalMapClass = Class.forName("java.lang.ThreadLocal$ThreadLocalMap");
Field tableField = threadLocalMapClass.getDeclaredField("table");
tableField.setAccessible(true);
Object table = tableField.get(threadLocalTable);
// The key to the ThreadLocalMap is a WeakReference object. The referent field of this object
// is a reference to the actual ThreadLocal variable
Field referentField = Reference.class.getDeclaredField("referent");
referentField.setAccessible(true);
for (int i = 0; i < Array.getLength(table); i++) {
// Each entry in the table array of ThreadLocalMap is an Entry object
// representing the thread local reference and its value
Object entry = Array.get(table, i);
if (entry != null) {
// Get a reference to the thread local object and remove it from the table
ThreadLocal threadLocal = (ThreadLocal)referentField.get(entry);
clean(threadLocal);
}
}
} catch(Exception e) {
// We will tolerate an exception here and just log it
throw new IllegalStateException(e);
}
}
@Override
protected void finalize() throws Throwable {
clean(this);
super.finalize();
}
}

View File

@ -0,0 +1,100 @@
package com.boydti.fawe.object.collection;
import com.google.common.base.Function;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.AbstractMap;
import java.util.Collection;
import java.util.Collections;
import java.util.Map;
import java.util.Set;
public interface IAdaptedMap<K, V, K2, V2> extends Map<K, V> {
Map<K2, V2> getParent();
K2 adaptKey(K key);
V2 adaptValue(V value);
K adaptKey2(K2 key);
V adaptValue2(V2 value);
@Override
default int size() {
return getParent().size();
}
@Override
default boolean isEmpty() {
return getParent().isEmpty();
}
@Override
default boolean containsKey(Object key) {
return getParent().containsKey(adaptKey((K) key));
}
@Override
default boolean containsValue(Object value) {
return getParent().containsValue(adaptValue((V) value));
}
@Override
default V get(Object key) {
return adaptValue2(getParent().get(adaptKey((K) key)));
}
@Nullable
@Override
default V put(K key, V value) {
return adaptValue2(getParent().put(adaptKey(key), adaptValue(value)));
}
@Override
default V remove(Object key) {
return adaptValue2(getParent().remove(adaptKey((K) key)));
}
@Override
default void putAll(@NotNull Map<? extends K, ? extends V> m) {
for (Entry<? extends K, ? extends V> entry : m.entrySet()) {
put(entry.getKey(), entry.getValue());
}
}
@Override
default void clear() {
getParent().clear();
}
@NotNull
@Override
default Set<K> keySet() {
if (isEmpty()) return Collections.emptySet();
return new AdaptedSetCollection<>(getParent().keySet(), this::adaptKey2);
}
@NotNull
@Override
default Collection<V> values() {
if (isEmpty()) return Collections.emptySet();
return new AdaptedSetCollection<>(getParent().values(), this::adaptValue2);
}
@NotNull
@Override
default Set<Entry<K, V>> entrySet() {
if (isEmpty()) return Collections.emptySet();
return new AdaptedSetCollection<>(getParent().entrySet(), new Function<Entry<K2, V2>, Entry<K, V>>() {
private MutablePair<K, V> entry = new MutablePair<>();
@Override
public Entry<K, V> apply(@javax.annotation.Nullable Entry<K2, V2> input) {
entry.setKey(adaptKey2(input.getKey()));
entry.setValue(adaptValue2(input.getValue()));
return entry;
}
});
}
}

View File

@ -1,19 +1,9 @@
package com.boydti.fawe.object.collection; package com.boydti.fawe.object.collection;
import com.boydti.fawe.util.IOUtil;
import com.boydti.fawe.util.MainUtil;
import java.lang.ref.Reference;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.Iterator; import java.util.Iterator;
import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentLinkedDeque; import java.util.concurrent.ConcurrentLinkedDeque;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.IntFunction;
import java.util.function.Supplier; import java.util.function.Supplier;
public class IterableThreadLocal<T> extends ThreadLocal<T> implements Iterable<T> { public class IterableThreadLocal<T> extends ThreadLocal<T> implements Iterable<T> {
@ -24,14 +14,6 @@ public class IterableThreadLocal<T> extends ThreadLocal<T> implements Iterable<T
this.supplier = supplier; this.supplier = supplier;
} }
public IterableThreadLocal(Supplier<T> supplier, Function<T, T> modifier) {
this.supplier = supplier;
}
public IterableThreadLocal(Supplier<T> supplier, Consumer<T> modifier) {
this.supplier = supplier;
}
@Override @Override
protected final T initialValue() { protected final T initialValue() {
T value = init(); T value = init();
@ -55,82 +37,18 @@ public class IterableThreadLocal<T> extends ThreadLocal<T> implements Iterable<T
public void clean() { public void clean() {
if (!allValues.isEmpty()) { if (!allValues.isEmpty()) {
synchronized (this) { synchronized (this) {
IterableThreadLocal.clean(this); CleanableThreadLocal.clean(this);
allValues.clear(); allValues.clear();
} }
} }
} }
public static void clean(ThreadLocal instance) {
try {
Thread[] threads = MainUtil.getThreads();
Field tl = Thread.class.getDeclaredField("threadLocals");
tl.setAccessible(true);
Method methodRemove = null;
for (Thread thread : threads) {
if (thread != null) {
Object tlm = tl.get(thread);
if (tlm != null) {
if (methodRemove == null) {
methodRemove = tlm.getClass().getDeclaredMethod("remove", ThreadLocal.class);
methodRemove.setAccessible(true);
}
if (methodRemove != null) {
try {
methodRemove.invoke(tlm, instance);
} catch (Throwable ignore) {}
}
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
public static void cleanAll() {
try {
// Get a reference to the thread locals table of the current thread
Thread thread = Thread.currentThread();
Field threadLocalsField = Thread.class.getDeclaredField("threadLocals");
threadLocalsField.setAccessible(true);
Object threadLocalTable = threadLocalsField.get(thread);
// Get a reference to the array holding the thread local variables inside the
// ThreadLocalMap of the current thread
Class threadLocalMapClass = Class.forName("java.lang.ThreadLocal$ThreadLocalMap");
Field tableField = threadLocalMapClass.getDeclaredField("table");
tableField.setAccessible(true);
Object table = tableField.get(threadLocalTable);
// The key to the ThreadLocalMap is a WeakReference object. The referent field of this object
// is a reference to the actual ThreadLocal variable
Field referentField = Reference.class.getDeclaredField("referent");
referentField.setAccessible(true);
for (int i = 0; i < Array.getLength(table); i++) {
// Each entry in the table array of ThreadLocalMap is an Entry object
// representing the thread local reference and its value
Object entry = Array.get(table, i);
if (entry != null) {
// Get a reference to the thread local object and remove it from the table
ThreadLocal threadLocal = (ThreadLocal)referentField.get(entry);
clean(threadLocal);
}
}
} catch(Exception e) {
// We will tolerate an exception here and just log it
throw new IllegalStateException(e);
}
}
public final Collection<T> getAll() { public final Collection<T> getAll() {
return Collections.unmodifiableCollection(allValues); return Collections.unmodifiableCollection(allValues);
} }
@Override @Override
protected void finalize() throws Throwable { protected void finalize() throws Throwable {
clean(this); CleanableThreadLocal.clean(this);
super.finalize(); super.finalize();
} }
} }

View File

@ -869,6 +869,10 @@ public final class MemBlockSet extends BlockSet {
return true; return true;
} }
public void reset(int layer) {
this.rows[layer] = NULL_ROW_Y;
}
public void reset() { public void reset() {
for (int i = 0; i < FaweCache.IMP.CHUNK_LAYERS; i++) rows[i] = NULL_ROW_Y; for (int i = 0; i < FaweCache.IMP.CHUNK_LAYERS; i++) rows[i] = NULL_ROW_Y;
} }

View File

@ -0,0 +1,28 @@
package com.boydti.fawe.object.collection;
import java.util.Map;
public class MutablePair<K, V> implements Map.Entry<K, V> {
private K key;
private V value;
@Override
public K getKey() {
return null;
}
@Override
public V getValue() {
return null;
}
@Override
public V setValue(V value) {
V old = value;
this.value = value;
return old;
}
public void setKey(K key) {
this.key = key;
}
}

View File

@ -1,8 +1,13 @@
package com.boydti.fawe.object.extent; package com.boydti.fawe.object.extent;
import com.boydti.fawe.FaweCache;
import com.boydti.fawe.beta.IBatchProcessor;
import com.boydti.fawe.beta.IChunkSet;
import com.boydti.fawe.object.FaweLimit; import com.boydti.fawe.object.FaweLimit;
import com.boydti.fawe.object.exception.FaweException; import com.boydti.fawe.object.exception.FaweException;
import com.boydti.fawe.util.ExtentTraverser;
import com.boydti.fawe.util.WEManager; import com.boydti.fawe.util.WEManager;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.entity.BaseEntity; import com.sk89q.worldedit.entity.BaseEntity;
import com.sk89q.worldedit.entity.Entity; import com.sk89q.worldedit.entity.Entity;
@ -17,9 +22,12 @@ 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.BlockTypes; import com.sk89q.worldedit.world.block.BlockTypes;
import java.util.Collection; import java.util.Collection;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import javax.annotation.Nullable; import javax.annotation.Nullable;
public abstract class FaweRegionExtent extends ResettableExtent { public abstract class FaweRegionExtent extends ResettableExtent implements IBatchProcessor {
private final FaweLimit limit; private final FaweLimit limit;
/** /**
@ -39,7 +47,20 @@ public abstract class FaweRegionExtent extends ResettableExtent {
public abstract Collection<Region> getRegions(); public abstract Collection<Region> getRegions();
public boolean isGlobal() { public boolean isGlobal() {
return getRegions().stream().anyMatch(Region::isGlobal); for (Region r : getRegions()) {
if (r.isGlobal()) {
return true;
}
}
return false;
}
@Override
public Extent construct(Extent child) {
if (getExtent() != child) {
new ExtentTraverser<Extent>(this).setNext(child);
}
return this;
} }
@Override @Override

View File

@ -1,14 +1,24 @@
package com.boydti.fawe.object.extent; package com.boydti.fawe.object.extent;
import com.boydti.fawe.FaweCache;
import com.boydti.fawe.beta.IBatchProcessor;
import com.boydti.fawe.beta.IChunk;
import com.boydti.fawe.beta.IChunkGet;
import com.boydti.fawe.beta.IChunkSet;
import com.boydti.fawe.object.FaweLimit; import com.boydti.fawe.object.FaweLimit;
import com.boydti.fawe.object.RegionWrapper; import com.boydti.fawe.object.RegionWrapper;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.regions.Region;
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.Iterator;
import java.util.Map;
import java.util.Set;
public class HeightBoundExtent extends FaweRegionExtent { public class HeightBoundExtent extends FaweRegionExtent implements IBatchProcessor {
private final int min, max; private final int min, max;
private int lastY = -1; private int lastY = -1;
@ -38,4 +48,12 @@ public class HeightBoundExtent extends FaweRegionExtent {
public Collection<Region> getRegions() { public Collection<Region> getRegions() {
return Collections.singletonList(new RegionWrapper(Integer.MIN_VALUE, Integer.MAX_VALUE, min, max, Integer.MIN_VALUE, Integer.MAX_VALUE)); return Collections.singletonList(new RegionWrapper(Integer.MIN_VALUE, Integer.MAX_VALUE, min, max, Integer.MIN_VALUE, Integer.MAX_VALUE));
} }
@Override
public IChunkSet processBatch(IChunk chunk, IChunkGet get, IChunkSet set) {
if (trimY(set, min, max) | trimNBT(set, this::contains)) {
return set;
}
return null;
}
} }

View File

@ -1,13 +1,20 @@
package com.boydti.fawe.object.extent; package com.boydti.fawe.object.extent;
import com.boydti.fawe.beta.IChunk;
import com.boydti.fawe.beta.IChunkGet;
import com.boydti.fawe.beta.IChunkSet;
import com.boydti.fawe.object.FaweLimit; import com.boydti.fawe.object.FaweLimit;
import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.regions.RegionIntersection;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
public class MultiRegionExtent extends FaweRegionExtent { public class MultiRegionExtent extends FaweRegionExtent {
private final RegionIntersection intersection;
private Region region; private Region region;
private final Region[] regions; private final Region[] regions;
private int index; private int index;
@ -22,6 +29,7 @@ public class MultiRegionExtent extends FaweRegionExtent {
this.index = 0; this.index = 0;
this.region = regions[0]; this.region = regions[0];
this.regions = regions; this.regions = regions;
this.intersection = new RegionIntersection(Arrays.asList(regions));
} }
@Override @Override
@ -64,4 +72,9 @@ public class MultiRegionExtent extends FaweRegionExtent {
public Collection<Region> getRegions() { public Collection<Region> getRegions() {
return Arrays.asList(regions); return Arrays.asList(regions);
} }
@Override
public IChunkSet processBatch(IChunk chunk, IChunkGet get, IChunkSet set) {
return intersection.processBatch(chunk, get, set);
}
} }

View File

@ -32,20 +32,26 @@ public class MultiTransform extends RandomTransform {
@Override @Override
public <T extends BlockStateHolder<T>> boolean setBlock(int x, int y, int z, T block) throws WorldEditException { public <T extends BlockStateHolder<T>> boolean setBlock(int x, int y, int z, T block) throws WorldEditException {
return Arrays.stream(extents).map(extent -> extent.setBlock(x, y, z, block)) // don't use streams for each block place, it'd be incredibly slow
.reduce(false, (a, b) -> a || b); boolean result = false;
for (AbstractDelegateExtent extent : extents) result |= extent.setBlock(x, y, z, block);
return result;
} }
@Override @Override
public <T extends BlockStateHolder<T>> boolean setBlock(BlockVector3 location, T block) throws WorldEditException { public <T extends BlockStateHolder<T>> boolean setBlock(BlockVector3 location, T block) throws WorldEditException {
return Arrays.stream(extents).map(extent -> extent.setBlock(location, block)) // don't use streams for each block place, it'd be incredibly slow
.reduce(false, (a, b) -> a || b); boolean result = false;
for (AbstractDelegateExtent extent : extents) result |= extent.setBlock(location, block);
return result;
} }
@Override @Override
public boolean setBiome(BlockVector2 position, BiomeType biome) { public boolean setBiome(BlockVector2 position, BiomeType biome) {
return Arrays.stream(extents).map(extent -> extent.setBiome(position, biome)) // don't use streams for each block place, it'd be incredibly slow
.reduce(false, (a, b) -> a || b); boolean result = false;
for (AbstractDelegateExtent extent : extents) result |= extent.setBiome(position, biome);
return result;
} }
@Nullable @Nullable

View File

@ -1,5 +1,8 @@
package com.boydti.fawe.object.extent; package com.boydti.fawe.object.extent;
import com.boydti.fawe.beta.IChunk;
import com.boydti.fawe.beta.IChunkGet;
import com.boydti.fawe.beta.IChunkSet;
import com.boydti.fawe.config.BBC; import com.boydti.fawe.config.BBC;
import com.boydti.fawe.object.FaweLimit; import com.boydti.fawe.object.FaweLimit;
import com.boydti.fawe.object.exception.FaweException; import com.boydti.fawe.object.exception.FaweException;
@ -321,4 +324,9 @@ public class NullExtent extends FaweRegionExtent {
public List<Countable<BlockState>> getBlockDistributionWithData(Region region) { public List<Countable<BlockState>> getBlockDistributionWithData(Region region) {
throw reason; throw reason;
} }
@Override
public IChunkSet processBatch(IChunk chunk, IChunkGet get, IChunkSet set) {
return null;
}
} }

View File

@ -19,12 +19,12 @@ import com.sk89q.worldedit.world.block.BlockTypes;
public class ProcessedWEExtent extends AbstractDelegateExtent { public class ProcessedWEExtent extends AbstractDelegateExtent {
private final FaweLimit limit; private final FaweLimit limit;
private final AbstractDelegateExtent extent; private final Extent extent;
public ProcessedWEExtent(Extent parent, FaweLimit limit) { public ProcessedWEExtent(Extent parent, FaweLimit limit) {
super(parent); super(parent);
this.limit = limit; this.limit = limit;
this.extent = (AbstractDelegateExtent) parent; this.extent = parent;
} }
public void setLimit(FaweLimit other) { public void setLimit(FaweLimit other) {

View File

@ -1,5 +1,8 @@
package com.boydti.fawe.object.extent; package com.boydti.fawe.object.extent;
import com.boydti.fawe.beta.IChunk;
import com.boydti.fawe.beta.IChunkGet;
import com.boydti.fawe.beta.IChunkSet;
import com.boydti.fawe.object.FaweLimit; import com.boydti.fawe.object.FaweLimit;
import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.regions.Region;
@ -35,4 +38,9 @@ public class SingleRegionExtent extends FaweRegionExtent {
public Collection<Region> getRegions() { public Collection<Region> getRegions() {
return Collections.singletonList(region); return Collections.singletonList(region);
} }
@Override
public IChunkSet processBatch(IChunk chunk, IChunkGet get, IChunkSet set) {
return region.processBatch(chunk, get, set);
}
} }

View File

@ -123,4 +123,10 @@ public class FuzzyRegion extends AbstractRegion {
public void setExtent(EditSession extent) { public void setExtent(EditSession extent) {
this.extent = extent; this.extent = extent;
} }
@Override
public boolean containsEntireCuboid(int bx, int tx, int by, int ty, int bz, int tz) {
// TODO optimize (switch from BlockVectorSet to the new bitset)
return false;
}
} }

View File

@ -1,4 +1,4 @@
package com.boydti.fawe.bukkit.regions.plotquared; package com.boydti.fawe.regions.general.integrations.plotquared;
import com.github.intellectualsites.plotsquared.commands.Command; import com.github.intellectualsites.plotsquared.commands.Command;
import com.github.intellectualsites.plotsquared.commands.CommandDeclaration; import com.github.intellectualsites.plotsquared.commands.CommandDeclaration;

View File

@ -1,4 +1,4 @@
package com.boydti.fawe.bukkit.regions.plotquared; package com.boydti.fawe.regions.general.integrations.plotquared;
import com.boydti.fawe.util.EditSessionBuilder; import com.boydti.fawe.util.EditSessionBuilder;
import com.boydti.fawe.util.TaskManager; import com.boydti.fawe.util.TaskManager;

View File

@ -1,4 +1,4 @@
package com.boydti.fawe.bukkit.regions.plotquared; package com.boydti.fawe.regions.general.integrations.plotquared;
import com.boydti.fawe.Fawe; import com.boydti.fawe.Fawe;
import com.boydti.fawe.FaweAPI; import com.boydti.fawe.FaweAPI;

View File

@ -1,4 +1,4 @@
package com.boydti.fawe.bukkit.regions.plotquared; package com.boydti.fawe.regions.general.integrations.plotquared;
import com.boydti.fawe.FaweCache; import com.boydti.fawe.FaweCache;
import com.boydti.fawe.object.clipboard.ReadOnlyClipboard; import com.boydti.fawe.object.clipboard.ReadOnlyClipboard;

View File

@ -1,4 +1,4 @@
package com.boydti.fawe.bukkit.regions.plotquared; package com.boydti.fawe.regions.general.integrations.plotquared;
import com.boydti.fawe.util.TaskManager; import com.boydti.fawe.util.TaskManager;
import com.github.intellectualsites.plotsquared.commands.CommandDeclaration; import com.github.intellectualsites.plotsquared.commands.CommandDeclaration;

View File

@ -1,4 +1,4 @@
package com.boydti.fawe.bukkit.regions.plotquared; package com.boydti.fawe.regions.general.integrations.plotquared;
import com.github.intellectualsites.plotsquared.commands.CommandDeclaration; import com.github.intellectualsites.plotsquared.commands.CommandDeclaration;
import com.github.intellectualsites.plotsquared.plot.commands.CommandCategory; import com.github.intellectualsites.plotsquared.plot.commands.CommandCategory;

View File

@ -1,4 +1,4 @@
package com.boydti.fawe.bukkit.regions.plotquared; package com.boydti.fawe.regions.general.integrations.plotquared;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;

View File

@ -1,6 +1,7 @@
package com.boydti.fawe.bukkit.regions.plotquared; package com.boydti.fawe.regions.general.integrations.plotquared;
import com.boydti.fawe.Fawe; import com.boydti.fawe.Fawe;
import com.boydti.fawe.FaweAPI;
import com.boydti.fawe.util.EditSessionBuilder; import com.boydti.fawe.util.EditSessionBuilder;
import com.boydti.fawe.util.TaskManager; import com.boydti.fawe.util.TaskManager;
import com.github.intellectualsites.plotsquared.commands.Command; import com.github.intellectualsites.plotsquared.commands.Command;
@ -20,7 +21,6 @@ import com.github.intellectualsites.plotsquared.plot.util.StringMan;
import com.github.intellectualsites.plotsquared.plot.util.WorldUtil; import com.github.intellectualsites.plotsquared.plot.util.WorldUtil;
import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.bukkit.BukkitAdapter;
import com.sk89q.worldedit.extension.platform.Capability; import com.sk89q.worldedit.extension.platform.Capability;
import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.regions.CuboidRegion; import com.sk89q.worldedit.regions.CuboidRegion;
@ -32,7 +32,6 @@ import java.util.Collection;
import java.util.HashSet; import java.util.HashSet;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ThreadLocalRandom; import java.util.concurrent.ThreadLocalRandom;
import org.bukkit.Bukkit;
@CommandDeclaration( @CommandDeclaration(
command = "generatebiome", command = "generatebiome",
@ -74,7 +73,7 @@ public class PlotSetBiome extends Command {
} }
plot.addRunning(); plot.addRunning();
TaskManager.IMP.async(() -> { TaskManager.IMP.async(() -> {
EditSession session = new EditSessionBuilder(BukkitAdapter.adapt(Bukkit.getWorld(plot.getArea().worldname))) EditSession session = new EditSessionBuilder(FaweAPI.getWorld(plot.getArea().worldname))
.autoQueue(false) .autoQueue(false)
.checkMemory(false) .checkMemory(false)
.allowedRegionsEverywhere() .allowedRegionsEverywhere()

View File

@ -1,6 +1,7 @@
package com.boydti.fawe.bukkit.regions.plotquared; package com.boydti.fawe.regions.general.integrations.plotquared;
import com.boydti.fawe.Fawe; import com.boydti.fawe.Fawe;
import com.boydti.fawe.FaweAPI;
import com.boydti.fawe.regions.FaweMask; import com.boydti.fawe.regions.FaweMask;
import com.boydti.fawe.regions.FaweMaskManager; import com.boydti.fawe.regions.FaweMaskManager;
import com.boydti.fawe.regions.general.RegionFilter; import com.boydti.fawe.regions.general.RegionFilter;
@ -20,16 +21,18 @@ import com.github.intellectualsites.plotsquared.plot.util.SchematicHandler;
import com.github.intellectualsites.plotsquared.plot.util.UUIDHandler; import com.github.intellectualsites.plotsquared.plot.util.UUIDHandler;
import com.github.intellectualsites.plotsquared.plot.util.block.GlobalBlockQueue; import com.github.intellectualsites.plotsquared.plot.util.block.GlobalBlockQueue;
import com.github.intellectualsites.plotsquared.plot.util.block.QueueProvider; import com.github.intellectualsites.plotsquared.plot.util.block.QueueProvider;
import com.sk89q.worldedit.bukkit.BukkitAdapter;
import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.regions.AbstractRegion;
import com.sk89q.worldedit.regions.CuboidRegion; import com.sk89q.worldedit.regions.CuboidRegion;
import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.regions.RegionOperationException; import com.sk89q.worldedit.regions.RegionIntersection;
import java.util.HashSet; import java.util.HashSet;
import java.util.List;
import java.util.UUID; import java.util.UUID;
import org.bukkit.Bukkit; import java.util.stream.Collectors;
import com.sk89q.worldedit.world.World;
public class PlotSquaredFeature extends FaweMaskManager { public class PlotSquaredFeature extends FaweMaskManager {
public PlotSquaredFeature() { public PlotSquaredFeature() {
@ -138,42 +141,11 @@ public class PlotSquaredFeature extends FaweMaskManager {
if (regions.size() == 1) { if (regions.size() == 1) {
maskedRegion = new CuboidRegion(pos1, pos2); maskedRegion = new CuboidRegion(pos1, pos2);
} else { } else {
maskedRegion = new AbstractRegion(BukkitAdapter.adapt(Bukkit.getWorld(area.worldname))) { World world = FaweAPI.getWorld(area.worldname);
@Override List<Region> weRegions = regions.stream()
public BlockVector3 getMinimumPoint() { .map(r -> new CuboidRegion(world, BlockVector3.at(r.minX, r.minY, r.minZ), BlockVector3.at(r.maxX, r.maxY, r.maxZ)))
return pos1; .collect(Collectors.toList());
} maskedRegion = new RegionIntersection(world, weRegions);
@Override
public BlockVector3 getMaximumPoint() {
return pos2;
}
@Override
public void expand(BlockVector3... changes) throws RegionOperationException {
throw new UnsupportedOperationException("Region is immutable");
}
@Override
public void contract(BlockVector3... changes) throws RegionOperationException {
throw new UnsupportedOperationException("Region is immutable");
}
@Override
public boolean contains(int x, int y, int z) {
return WEManager.maskContains(regions, x, y, z);
}
@Override
public boolean contains(int x, int z) {
return WEManager.maskContains(regions, x, z);
}
@Override
public boolean contains(BlockVector3 position) {
return contains(position.getBlockX(), position.getBlockY(), position.getBlockZ());
}
};
} }
return new FaweMask(maskedRegion) { return new FaweMask(maskedRegion) {

View File

@ -1,40 +1,50 @@
package com.boydti.fawe.util; package com.boydti.fawe.util;
import static com.google.common.base.Preconditions.checkNotNull;
import com.boydti.fawe.Fawe; import com.boydti.fawe.Fawe;
import com.boydti.fawe.FaweAPI; import com.boydti.fawe.FaweAPI;
import com.boydti.fawe.beta.IQueueExtent;
import com.boydti.fawe.beta.implementation.ParallelQueueExtent;
import com.boydti.fawe.config.BBC; import com.boydti.fawe.config.BBC;
import com.boydti.fawe.config.Settings; import com.boydti.fawe.config.Settings;
import com.boydti.fawe.logging.LoggingChangeSet;
import com.boydti.fawe.logging.rollback.RollbackOptimizedHistory; import com.boydti.fawe.logging.rollback.RollbackOptimizedHistory;
import com.boydti.fawe.object.FaweLimit; import com.boydti.fawe.object.FaweLimit;
import com.boydti.fawe.object.HistoryExtent; import com.boydti.fawe.object.HistoryExtent;
import com.boydti.fawe.object.NullChangeSet; import com.boydti.fawe.object.NullChangeSet;
import com.boydti.fawe.object.RegionWrapper; import com.boydti.fawe.object.RegionWrapper;
import com.boydti.fawe.object.brush.visualization.VirtualWorld;
import com.boydti.fawe.object.changeset.BlockBagChangeSet;
import com.boydti.fawe.object.changeset.DiskStorageHistory; import com.boydti.fawe.object.changeset.DiskStorageHistory;
import com.boydti.fawe.object.changeset.FaweChangeSet; import com.boydti.fawe.object.changeset.FaweChangeSet;
import com.boydti.fawe.object.changeset.MemoryOptimizedHistory; import com.boydti.fawe.object.changeset.MemoryOptimizedHistory;
import com.boydti.fawe.object.exception.FaweException; import com.boydti.fawe.object.exception.FaweException;
import com.boydti.fawe.object.extent.FaweRegionExtent;
import com.boydti.fawe.object.extent.MultiRegionExtent;
import com.boydti.fawe.object.extent.NullExtent; import com.boydti.fawe.object.extent.NullExtent;
import com.boydti.fawe.object.extent.SingleRegionExtent;
import com.boydti.fawe.object.extent.SlowExtent;
import com.boydti.fawe.object.extent.StripNBTExtent;
import com.boydti.fawe.wrappers.WorldWrapper;
import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.event.extent.EditSessionEvent; import com.sk89q.worldedit.event.extent.EditSessionEvent;
import com.sk89q.worldedit.extent.AbstractDelegateExtent;
import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.extent.inventory.BlockBag; import com.sk89q.worldedit.extent.inventory.BlockBag;
import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.util.eventbus.EventBus; import com.sk89q.worldedit.util.eventbus.EventBus;
import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.World;
import java.util.UUID; import org.jetbrains.annotations.NotNull;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import org.jetbrains.annotations.NotNull; import java.util.UUID;
import static com.google.common.base.Preconditions.checkNotNull;
public class EditSessionBuilder { public class EditSessionBuilder {
private World world; private World world;
private String worldName; private String worldName;
private Extent extent;
private Player player; private Player player;
private FaweLimit limit; private FaweLimit limit;
private FaweChangeSet changeSet; private FaweChangeSet changeSet;
@ -45,6 +55,7 @@ public class EditSessionBuilder {
private Boolean combineStages; private Boolean combineStages;
private EventBus eventBus; private EventBus eventBus;
private BlockBag blockBag; private BlockBag blockBag;
private boolean threaded = true;
private EditSessionEvent event; private EditSessionEvent event;
/** /**
@ -65,14 +76,12 @@ public class EditSessionBuilder {
public EditSessionBuilder(@Nonnull World world) { public EditSessionBuilder(@Nonnull World world) {
checkNotNull(world); checkNotNull(world);
this.world = world; this.world = world;
this.extent = world;
this.worldName = Fawe.imp().getWorldName(world); this.worldName = Fawe.imp().getWorldName(world);
} }
public EditSessionBuilder(World world, String worldName) { public EditSessionBuilder(World world, String worldName) {
if (world == null && worldName == null) throw new NullPointerException("Both world and worldname cannot be null"); if (world == null && worldName == null) throw new NullPointerException("Both world and worldname cannot be null");
this.world = world; this.world = world;
this.extent = world;
this.worldName = worldName; this.worldName = worldName;
} }
@ -84,12 +93,12 @@ public class EditSessionBuilder {
public EditSessionBuilder player(@Nullable Player player) { public EditSessionBuilder player(@Nullable Player player) {
this.player = player; this.player = player;
return this; return setDirty();
} }
public EditSessionBuilder limit(@Nullable FaweLimit limit) { public EditSessionBuilder limit(@Nullable FaweLimit limit) {
this.limit = limit; this.limit = limit;
return this; return setDirty();
} }
public EditSessionBuilder limitUnlimited() { public EditSessionBuilder limitUnlimited() {
@ -101,12 +110,12 @@ public class EditSessionBuilder {
limitUnlimited(); limitUnlimited();
FaweLimit tmp = fp.getLimit(); FaweLimit tmp = fp.getLimit();
limit.INVENTORY_MODE = tmp.INVENTORY_MODE; limit.INVENTORY_MODE = tmp.INVENTORY_MODE;
return this; return setDirty();
} }
public EditSessionBuilder changeSet(@Nullable FaweChangeSet changeSet) { public EditSessionBuilder changeSet(@Nullable FaweChangeSet changeSet) {
this.changeSet = changeSet; this.changeSet = changeSet;
return this; return setDirty();
} }
public EditSessionBuilder changeSetNull() { public EditSessionBuilder changeSetNull() {
@ -117,7 +126,7 @@ public class EditSessionBuilder {
checkNotNull(world); checkNotNull(world);
this.world = world; this.world = world;
this.worldName = world.getName(); this.worldName = world.getName();
return this; return setDirty();
} }
/** /**
@ -146,23 +155,23 @@ public class EditSessionBuilder {
} else { } else {
this.changeSet = new MemoryOptimizedHistory(world); this.changeSet = new MemoryOptimizedHistory(world);
} }
return this; return setDirty();
} }
public EditSessionBuilder allowedRegions(@Nullable Region[] allowedRegions) { public EditSessionBuilder allowedRegions(@Nullable Region[] allowedRegions) {
this.allowedRegions = allowedRegions; this.allowedRegions = allowedRegions;
return this; return setDirty();
} }
@Deprecated @Deprecated
public EditSessionBuilder allowedRegions(@Nullable RegionWrapper[] allowedRegions) { public EditSessionBuilder allowedRegions(@Nullable RegionWrapper[] allowedRegions) {
this.allowedRegions = allowedRegions; this.allowedRegions = allowedRegions;
return this; return setDirty();
} }
public EditSessionBuilder allowedRegions(@Nullable RegionWrapper allowedRegion) { public EditSessionBuilder allowedRegions(@Nullable RegionWrapper allowedRegion) {
this.allowedRegions = allowedRegion == null ? null : allowedRegion.toArray(); this.allowedRegions = allowedRegion == null ? null : allowedRegion.toArray();
return this; return setDirty();
} }
public EditSessionBuilder allowedRegionsEverywhere() { public EditSessionBuilder allowedRegionsEverywhere() {
@ -171,47 +180,45 @@ public class EditSessionBuilder {
public EditSessionBuilder autoQueue(@Nullable Boolean autoQueue) { public EditSessionBuilder autoQueue(@Nullable Boolean autoQueue) {
this.autoQueue = autoQueue; this.autoQueue = autoQueue;
return this; return setDirty();
} }
public EditSessionBuilder fastmode(@Nullable Boolean fastmode) { public EditSessionBuilder fastmode(@Nullable Boolean fastmode) {
this.fastmode = fastmode; this.fastmode = fastmode;
return this; return setDirty();
} }
public EditSessionBuilder checkMemory(@Nullable Boolean checkMemory) { public EditSessionBuilder checkMemory(@Nullable Boolean checkMemory) {
this.checkMemory = checkMemory; this.checkMemory = checkMemory;
return this; return setDirty();
} }
public EditSessionBuilder combineStages(@Nullable Boolean combineStages) { public EditSessionBuilder combineStages(@Nullable Boolean combineStages) {
this.combineStages = combineStages; this.combineStages = combineStages;
return this; return setDirty();
}
public EditSessionBuilder extent(@Nullable Extent extent) {
this.extent = extent;
return this;
} }
public EditSessionBuilder blockBag(@Nullable BlockBag blockBag) { public EditSessionBuilder blockBag(@Nullable BlockBag blockBag) {
this.blockBag = blockBag; this.blockBag = blockBag;
return this; return setDirty();
} }
public EditSessionBuilder eventBus(@Nullable EventBus eventBus) { public EditSessionBuilder eventBus(@Nullable EventBus eventBus) {
this.eventBus = eventBus; this.eventBus = eventBus;
return this; return setDirty();
} }
public EditSessionBuilder event(@Nullable EditSessionEvent event) { public EditSessionBuilder event(@Nullable EditSessionEvent event) {
this.event = event; this.event = event;
return setDirty();
}
private EditSessionBuilder setDirty() {
compiled = false;
return this; return this;
} }
private boolean wrapped; private Extent wrapExtent(final Extent extent, final EventBus eventBus, EditSessionEvent event, final EditSession.Stage stage) {
private AbstractDelegateExtent wrapExtent(final AbstractDelegateExtent extent, final EventBus eventBus, EditSessionEvent event, final EditSession.Stage stage) {
event = event.clone(stage); event = event.clone(stage);
event.setExtent(extent); event.setExtent(extent);
eventBus.post(event); eventBus.post(event);
@ -222,16 +229,16 @@ public class EditSessionBuilder {
if(toReturn instanceof com.sk89q.worldedit.extent.NullExtent) { if(toReturn instanceof com.sk89q.worldedit.extent.NullExtent) {
return new NullExtent(toReturn, FaweException.MANUAL); return new NullExtent(toReturn, FaweException.MANUAL);
} }
if (!(toReturn instanceof AbstractDelegateExtent)) { // if (!(toReturn instanceof AbstractDelegateExtent)) {
Fawe.debug("Extent " + toReturn + " must be AbstractDelegateExtent"); // Fawe.debug("Extent " + toReturn + " must be AbstractDelegateExtent");
return extent; // return extent;
} // }
if (toReturn != extent) { if (toReturn != extent) {
String className = toReturn.getClass().getName().toLowerCase(); String className = toReturn.getClass().getName().toLowerCase();
for (String allowed : Settings.IMP.EXTENT.ALLOWED_PLUGINS) { for (String allowed : Settings.IMP.EXTENT.ALLOWED_PLUGINS) {
if (className.contains(allowed.toLowerCase())) { if (className.contains(allowed.toLowerCase())) {
this.wrapped = true; this.wrapped = true;
return (AbstractDelegateExtent) toReturn; return toReturn;
} }
} }
if (Settings.IMP.EXTENT.DEBUG) { if (Settings.IMP.EXTENT.DEBUG) {
@ -252,13 +259,16 @@ public class EditSessionBuilder {
private FaweChangeSet changeTask; private FaweChangeSet changeTask;
private int maxY; private int maxY;
private HistoryExtent history; private Extent bypassHistory;
private AbstractDelegateExtent bypassHistory; private Extent bypassAll;
private AbstractDelegateExtent bypassAll; private Extent extent;
private boolean compiled;
private boolean wrapped;
public EditSessionBuilder compile() { public EditSessionBuilder compile() {
if (extent != null) return this; if (compiled) return this;
compiled = true;
wrapped = false; wrapped = false;
if (world == null && !this.worldName.isEmpty()) { if (world == null && !this.worldName.isEmpty()) {
world = FaweAPI.getWorld(this.worldName); world = FaweAPI.getWorld(this.worldName);
@ -302,109 +312,126 @@ public class EditSessionBuilder {
} }
// this.originalLimit = limit; // this.originalLimit = limit;
this.blockBag = limit.INVENTORY_MODE != 0 ? blockBag : null; this.blockBag = limit.INVENTORY_MODE != 0 ? blockBag : null;
// this.limit = limit.copy(); this.limit = limit.copy();
// if (queue == null) { if (extent == null) {
// boolean placeChunks = this.fastmode || this.limit.FAST_PLACEMENT; IQueueExtent queue = null;
// World unwrapped = WorldWrapper.unwrap(world); World unwrapped = WorldWrapper.unwrap(world);
// if (unwrapped instanceof IQueueExtent) { boolean placeChunks = this.fastmode || this.limit.FAST_PLACEMENT;
// queue = (IQueueExtent) unwrapped;
// } else if (unwrapped instanceof MCAWorld) { if (placeChunks) {
// queue = ((MCAWorld) unwrapped).getQueue(); if (unwrapped instanceof IQueueExtent) {
// } else if (player != null && world.equals(player.getWorld())) { extent = queue = (IQueueExtent) unwrapped;
// queue = player.getIQueueExtent(placeChunks, autoQueue); } else if (Settings.IMP.QUEUE.PARALLEL_THREADS > 1 && threaded) {
// } else { ParallelQueueExtent parallel = new ParallelQueueExtent(Fawe.get().getQueueHandler(), world);
// queue = SetQueue.IMP.getNewQueue(world, placeChunks, autoQueue); queue = parallel.getExtent();
// } extent = parallel;
// } } else {
// if (combineStages == null) { System.out.println("FAWE is in single threaded mode (performance reduced)");
// combineStages = extent = queue = Fawe.get().getQueueHandler().getQueue(world);
// // If it's enabled in the settings }
// Settings.IMP.HISTORY.COMBINE_STAGES } else {
// // If fast placement is disabled, it's slower to perform a copy on each chunk extent = world;
// && this.limit.FAST_PLACEMENT }
// // If the specific queue doesn't support it Extent root = extent;
// && queue.supports(IQueueExtent.Capability.CHANGE_TASKS) if (combineStages == null) {
// // If the edit uses items from the inventory we can't use a delayed task combineStages =
// && this.blockBag == null; // If it's enabled in the settings
// } Settings.IMP.HISTORY.COMBINE_STAGES
// if (!Settings.IMP.QUEUE.PROGRESS.DISPLAY.equalsIgnoreCase("false") && player != null) { // If fast placement is disabled, it's slower to perform a copy on each chunk
// switch (Settings.IMP.QUEUE.PROGRESS.DISPLAY.toLowerCase()) { && this.limit.FAST_PLACEMENT
// case "chat": // If the edit uses items from the inventory we can't use a delayed task
// this.queue.setProgressTask(new ChatProgressTracker(player)); && this.blockBag == null;
// break; }
// case "title": if (!Settings.IMP.QUEUE.PROGRESS.DISPLAY.equalsIgnoreCase("false") && player != null) {
// case "true": System.out.println("TODO add progress display");
// default: // switch (Settings.IMP.QUEUE.PROGRESS.DISPLAY.toLowerCase()) {
// this.queue.setProgressTask(new DefaultProgressTracker(player)); // case "chat":
// } // this.queue.setProgressTask(new ChatProgressTracker(player));
// } // break;
// this.bypassAll = wrapExtent(new FastWorldEditExtent(world, queue), eventBus, event, EditSession.Stage.BEFORE_CHANGE); // case "title":
// this.bypassHistory = (this.extent = wrapExtent(bypassAll, eventBus, event, EditSession.Stage.BEFORE_REORDER)); // case "true":
// if (!this.fastmode || changeSet != null) { // default:
// if (changeSet == null) { // this.queue.setProgressTask(new DefaultProgressTracker(player));
// if (Settings.IMP.HISTORY.USE_DISK) {
// UUID uuid = player == null ? EditSession.CONSOLE : player.getUUID();
// if (Settings.IMP.HISTORY.USE_DATABASE) {
// changeSet = new RollbackOptimizedHistory(world, uuid);
// } else {
// changeSet = new DiskStorageHistory(world, uuid);
// }
// } else if (combineStages && Settings.IMP.HISTORY.COMPRESSION_LEVEL == 0 && !(queue instanceof MCAQueue)) {
// changeSet = new CPUOptimizedChangeSet(world);
// } else {
// changeSet = new MemoryOptimizedHistory(world);
// } // }
// } }
// if (this.limit.SPEED_REDUCTION > 0) { extent = this.bypassAll = wrapExtent(extent, eventBus, event, EditSession.Stage.BEFORE_CHANGE);
// this.bypassHistory = new SlowExtent(this.bypassHistory, this.limit.SPEED_REDUCTION); this.bypassHistory = (this.extent = wrapExtent(bypassAll, eventBus, event, EditSession.Stage.BEFORE_REORDER));
// } if (!this.fastmode || changeSet != null) {
// if (changeSet instanceof NullChangeSet && Fawe.imp().getBlocksHubApi() != null && player != null) { if (changeSet == null) {
// changeSet = LoggingChangeSet.wrap(player, changeSet); if (Settings.IMP.HISTORY.USE_DISK) {
// } UUID uuid = player == null ? EditSession.CONSOLE : player.getUniqueId();
// if (!(changeSet instanceof NullChangeSet)) { if (Settings.IMP.HISTORY.USE_DATABASE) {
// if (!(changeSet instanceof LoggingChangeSet) && player != null && Fawe.imp().getBlocksHubApi() != null) { changeSet = new RollbackOptimizedHistory(world, uuid);
// changeSet = LoggingChangeSet.wrap(player, changeSet); } else {
// } changeSet = new DiskStorageHistory(world, uuid);
// if (this.blockBag != null) { }
// changeSet = new BlockBagChangeSet(changeSet, blockBag, limit.INVENTORY_MODE == 1); // } else if (combineStages && Settings.IMP.HISTORY.COMPRESSION_LEVEL == 0) {
// } // changeSet = new CPUOptimizedChangeSet(world);
// if (combineStages) { } else {
// changeTask = changeSet; if (combineStages && Settings.IMP.HISTORY.COMPRESSION_LEVEL == 0) {
// changeSet.addChangeTask(queue); System.out.println("TODO add CPUOptimizedChangeSet");
// } else { }
// this.extent = (history = new HistoryExtent(bypassHistory, changeSet, queue)); changeSet = new MemoryOptimizedHistory(world);
//// if (this.blockBag != null) { }
//// this.extent = new BlockBagExtent(this.extent, blockBag, limit.INVENTORY_MODE == 1); }
//// } if (this.limit.SPEED_REDUCTION > 0) {
// } this.extent = this.bypassHistory = new SlowExtent(this.bypassHistory, this.limit.SPEED_REDUCTION);
// } }
// } if (changeSet instanceof NullChangeSet && Fawe.imp().getBlocksHubApi() != null && player != null) {
// if (allowedRegions == null) { changeSet = LoggingChangeSet.wrap(player, changeSet);
// if (player != null && !player.hasPermission("fawe.bypass") && !player.hasPermission("fawe.bypass.regions") && !(queue instanceof VirtualWorld)) { }
// allowedRegions = player.getCurrentRegions(); if (!(changeSet instanceof NullChangeSet)) {
// } if (!(changeSet instanceof LoggingChangeSet) && player != null && Fawe.imp().getBlocksHubApi() != null) {
// } changeSet = LoggingChangeSet.wrap(player, changeSet);
// this.maxY = world == null ? 255 : world.getMaxY(); }
// if (allowedRegions != null) { if (this.blockBag != null) {
// if (allowedRegions.length == 0) { System.out.println("TODO implement block bag as IBatchProcessor");
// this.extent = new NullExtent(this.extent, FaweException.NO_REGION); changeSet = new BlockBagChangeSet(changeSet, blockBag, limit.INVENTORY_MODE == 1);
// } else { }
// this.extent = new ProcessedWEExtent(this.extent, this.limit); if (combineStages) {
// if (allowedRegions.length == 1) { changeTask = changeSet;
// this.extent = new SingleRegionExtent(this.extent, this.limit, allowedRegions[0]); this.extent = extent.enableHistory(changeSet);
// } else { } else {
// this.extent = new MultiRegionExtent(this.extent, this.limit, allowedRegions); this.extent = (new HistoryExtent(extent, changeSet));
// } // if (this.blockBag != null) {
// } // this.extent = new BlockBagExtent(this.extent, blockBag, limit.INVENTORY_MODE == 1);
// } else { // }
// this.extent = new HeightBoundExtent(this.extent, this.limit, 0, maxY); }
// } }
// if (this.limit.STRIP_NBT != null && !this.limit.STRIP_NBT.isEmpty()) { }
// this.extent = new StripNBTExtent(this.extent, this.limit.STRIP_NBT); if (allowedRegions == null) {
// } if (player != null && !player.hasPermission("fawe.bypass") && !player.hasPermission("fawe.bypass.regions") && !(root instanceof VirtualWorld)) {
// this.extent = wrapExtent(this.extent, eventBus, event, EditSession.Stage.BEFORE_HISTORY); allowedRegions = player.getCurrentRegions();
// return this; }
}
this.maxY = world == null ? 255 : world.getMaxY();
FaweRegionExtent regionExtent = null;
if (allowedRegions != null) {
if (allowedRegions.length == 0) {
regionExtent = new NullExtent(this.extent, FaweException.NO_REGION);
} else {
// this.extent = new ProcessedWEExtent(this.extent, this.limit);
if (allowedRegions.length == 1) {
regionExtent = new SingleRegionExtent(this.extent, this.limit, allowedRegions[0]);
} else {
regionExtent = new MultiRegionExtent(this.extent, this.limit, allowedRegions);
}
}
} else {
// this.extent = new HeightBoundExtent(this.extent, this.limit, 0, maxY);
}
if (regionExtent != null && queue != null && combineStages) {
queue.addProcessor(regionExtent);
} else if (regionExtent != null) {
this.extent = regionExtent;
}
if (this.limit.STRIP_NBT != null && !this.limit.STRIP_NBT.isEmpty()) {
System.out.println("TODO add batch processor for strip nbt");
this.extent = new StripNBTExtent(this.extent, this.limit.STRIP_NBT);
}
this.extent = wrapExtent(this.extent, eventBus, event, EditSession.Stage.BEFORE_HISTORY);
}
return this; return this;
} }
@ -415,10 +442,6 @@ public class EditSessionBuilder {
return new EditSession(this); return new EditSession(this);
} }
public Extent getExtent() {
return extent;
}
public World getWorld() { public World getWorld() {
return world; return world;
} }
@ -427,6 +450,10 @@ public class EditSessionBuilder {
return worldName; return worldName;
} }
public Extent getExtent() {
return extent != null ? extent : world;
}
public boolean isWrapped() { public boolean isWrapped() {
return wrapped; return wrapped;
} }
@ -435,23 +462,16 @@ public class EditSessionBuilder {
return fastmode; return fastmode;
} }
public HistoryExtent getHistory() { public Extent getBypassHistory() {
return history;
}
public AbstractDelegateExtent getBypassHistory() {
return bypassHistory; return bypassHistory;
} }
public AbstractDelegateExtent getBypassAll() { public Extent getBypassAll() {
return bypassAll; return bypassAll;
} }
@NotNull @NotNull
public FaweLimit getLimit() { public FaweLimit getLimit() {
if (limit == null) {
return FaweLimit.MAX;
}
return limit; return limit;
} }

View File

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

View File

@ -1,5 +1,9 @@
package com.boydti.fawe.util; package com.boydti.fawe.util;
import com.boydti.fawe.object.io.FastByteArrayOutputStream;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
import java.io.*; import java.io.*;
import java.net.HttpURLConnection; import java.net.HttpURLConnection;
import java.net.URL; import java.net.URL;
@ -10,6 +14,33 @@ import java.util.stream.Collectors;
public class ImgurUtility { public class ImgurUtility {
public static final String CLIENT_ID = "50e34b65351eb07"; public static final String CLIENT_ID = "50e34b65351eb07";
public static URL uploadImage(File file) throws IOException {
// was used until a merge deleted all the CFI/schematics functionality TODO NOT IMPLEMENTED
return uploadImage(new FileInputStream(file));
}
public static URL uploadImage(InputStream inputStream) throws IOException {
// was used until a merge deleted all the CFI/schematics functionality TODO NOT IMPLEMENTED
inputStream = new BufferedInputStream(inputStream);
FastByteArrayOutputStream baos = new FastByteArrayOutputStream(Short.MAX_VALUE);
int i;
while ((i = inputStream.read()) != -1) {
baos.write(i);
}
baos.flush();
return uploadImage(baos.toByteArray());
}
public static URL uploadImage(byte[] image) throws IOException {
// was used until a merge deleted all the CFI/schematics functionality TODO NOT IMPLEMENTED
String json = getImgurContent(CLIENT_ID, image);
Gson gson = new Gson();
JsonObject obj = gson.fromJson(json, JsonObject.class);
JsonObject data = obj.get("data").getAsJsonObject();
String link = data.get("link").getAsString();
return new URL(link);
}
public static String getImgurContent(String clientID, byte[] image) throws IOException { public static String getImgurContent(String clientID, byte[] image) throws IOException {
String imageString = Base64.getEncoder().encodeToString(image); String imageString = Base64.getEncoder().encodeToString(image);
URL url = new URL("https://api.imgur.com/3/image"); URL url = new URL("https://api.imgur.com/3/image");

View File

@ -1,7 +1,5 @@
package com.boydti.fawe.util; package com.boydti.fawe.util;
import static java.lang.System.arraycopy;
import com.boydti.fawe.Fawe; import com.boydti.fawe.Fawe;
import com.boydti.fawe.config.BBC; import com.boydti.fawe.config.BBC;
import com.boydti.fawe.config.Settings; import com.boydti.fawe.config.Settings;
@ -26,7 +24,17 @@ import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormat;
import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormats; import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormats;
import com.sk89q.worldedit.history.changeset.ChangeSet; import com.sk89q.worldedit.history.changeset.ChangeSet;
import com.sk89q.worldedit.util.Location; import com.sk89q.worldedit.util.Location;
import java.awt.Graphics2D; import net.jpountz.lz4.LZ4BlockInputStream;
import net.jpountz.lz4.LZ4BlockOutputStream;
import net.jpountz.lz4.LZ4Compressor;
import net.jpountz.lz4.LZ4Factory;
import net.jpountz.lz4.LZ4FastDecompressor;
import net.jpountz.lz4.LZ4InputStream;
import net.jpountz.lz4.LZ4Utils;
import javax.annotation.Nullable;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage; import java.awt.image.BufferedImage;
import java.io.BufferedInputStream; import java.io.BufferedInputStream;
import java.io.BufferedOutputStream; import java.io.BufferedOutputStream;
@ -75,27 +83,11 @@ 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 net.jpountz.lz4.LZ4BlockInputStream;
import net.jpountz.lz4.LZ4BlockOutputStream;
import net.jpountz.lz4.LZ4Compressor;
import net.jpountz.lz4.LZ4Factory;
import net.jpountz.lz4.LZ4FastDecompressor;
import net.jpountz.lz4.LZ4InputStream;
import net.jpountz.lz4.LZ4Utils;
public class MainUtil { public class MainUtil {
public static void sendAdmin(final String s) {
for (final Player player : Fawe.get().getCachedPlayers()) {
if (player.hasPermission("fawe.admin")) {
player.print(s);
}
}
Fawe.debug(s);
}
public static List<String> filter(String prefix, List<String> suggestions) { public static List<String> filter(String prefix, List<String> suggestions) {
if (prefix.isEmpty()) { if (prefix.isEmpty()) {
return suggestions; return suggestions;
@ -754,7 +746,6 @@ public class MainUtil {
if (time >= 33868800) { if (time >= 33868800) {
int years = (int) (time / 33868800); int years = (int) (time / 33868800);
int time1 = years * 33868800; int time1 = years * 33868800;
System.out.println(time1);
time -= time1; time -= time1;
toreturn.append(years + "y "); toreturn.append(years + "y ");
} }

View File

@ -69,10 +69,10 @@ public class TextureUtil implements TextureHolder {
private BiomeColor[] biomes = new BiomeColor[]{ private BiomeColor[] biomes = new BiomeColor[]{
// ID Name Temperature, rainfall, grass, foliage colors // ID Name Temperature, rainfall, grass, foliage colors
// - note: the colors here are just placeholders, they are computed in the program // - note: the colors here are just placeholders, they are computed in the program
new BiomeColor(0, "ocean", 0.5f, 0.5f, 0x92BD59, 7842607), new BiomeColor(0, "ocean", 0.5f, 0.5f, 0x92BD59, 0x77AB2F),
// default values of temp and rain // default values of temp and rain
new BiomeColor(1, "plains", 0.8f, 0.4f, 0x92BD59, 7842607), new BiomeColor(1, "plains", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
new BiomeColor(2, "desert", 2.0f, 0.0f, 0x92BD59, 7842607), new BiomeColor(2, "desert", 2.0f, 0.0f, 0x92BD59, 0x77AB2F),
new BiomeColor(3, "mountains", 0.2f, 0.3f, 0x92BD59, 0x77AB2F), new BiomeColor(3, "mountains", 0.2f, 0.3f, 0x92BD59, 0x77AB2F),
new BiomeColor(4, "forest", 0.7f, 0.8f, 0x92BD59, 0x77AB2F), new BiomeColor(4, "forest", 0.7f, 0.8f, 0x92BD59, 0x77AB2F),
new BiomeColor(5, "taiga", 0.25f, 0.8f, 0x92BD59, 0x77AB2F), new BiomeColor(5, "taiga", 0.25f, 0.8f, 0x92BD59, 0x77AB2F),
@ -97,7 +97,7 @@ public class TextureUtil implements TextureHolder {
new BiomeColor(22, "jungle_hills", 0.95f, 0.9f, 0x92BD59, 0x77AB2F), new BiomeColor(22, "jungle_hills", 0.95f, 0.9f, 0x92BD59, 0x77AB2F),
new BiomeColor(23, "jungle_edge", 0.95f, 0.8f, 0x92BD59, 0x77AB2F), new BiomeColor(23, "jungle_edge", 0.95f, 0.8f, 0x92BD59, 0x77AB2F),
new BiomeColor(24, "deep_ocean", 0.5f, 0.5f, 0x92BD59, 0x77AB2F), new BiomeColor(24, "deep_ocean", 0.5f, 0.5f, 0x92BD59, 0x77AB2F),
new BiomeColor(25, "stone_shore", 0.2f, 0.3f, 9616729, 0x77AB2F), new BiomeColor(25, "stone_shore", 0.2f, 0.3f, 0x92BD59, 0x77AB2F),
new BiomeColor(26, "snowy_beach", 0.05f, 0.3f, 0x92BD59, 0x77AB2F), new BiomeColor(26, "snowy_beach", 0.05f, 0.3f, 0x92BD59, 0x77AB2F),
new BiomeColor(27, "birch_forest", 0.6f, 0.6f, 0x92BD59, 0x77AB2F), new BiomeColor(27, "birch_forest", 0.6f, 0.6f, 0x92BD59, 0x77AB2F),
new BiomeColor(28, "birch_forest_hills", 0.6f, 0.6f, 0x92BD59, 0x77AB2F), new BiomeColor(28, "birch_forest_hills", 0.6f, 0.6f, 0x92BD59, 0x77AB2F),

View File

@ -0,0 +1,33 @@
package com.boydti.fawe.wrappers;
import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.math.Vector3;
import com.sk89q.worldedit.util.Location;
public class LocationMaskedPlayerWrapper extends PlayerWrapper {
private final boolean allowTeleport;
private Location position;
public LocationMaskedPlayerWrapper(Player parent, Location position) {
this(parent, position, false);
}
public LocationMaskedPlayerWrapper(Player parent, Location position, boolean allowTeleport) {
super(parent);
this.position = position;
this.allowTeleport = allowTeleport;
}
@Override
public Location getLocation() {
return position;
}
@Override
public void setPosition(Vector3 pos, float pitch, float yaw) {
this.position = new Location(position.getExtent(), pos, pitch, yaw);
if (allowTeleport) {
super.setPosition(pos, pitch, yaw);
}
}
}

View File

@ -0,0 +1,259 @@
package com.boydti.fawe.wrappers;
import com.boydti.fawe.Fawe;
import com.boydti.fawe.object.RunnableVal;
import com.boydti.fawe.util.EditSessionBuilder;
import com.boydti.fawe.util.TaskManager;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.LocalSession;
import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.extension.platform.PlayerProxy;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.math.Vector3;
import com.sk89q.worldedit.util.Direction;
import com.sk89q.worldedit.util.Location;
import com.sk89q.worldedit.util.TargetBlock;
import com.sk89q.worldedit.world.World;
import com.sk89q.worldedit.world.block.BlockTypes;
public class PlayerWrapper extends PlayerProxy {
public PlayerWrapper(Player parent) {
super(parent);
}
public static PlayerWrapper wrap(Player parent) {
if (parent instanceof PlayerWrapper) {
return (PlayerWrapper) parent;
}
return new PlayerWrapper(parent);
}
@Override
public World getWorld() {
return WorldWrapper.wrap(super.getWorld());
}
@Override
public void findFreePosition(Location searchPos) {
TaskManager.IMP.sync(new RunnableVal<Boolean>() {
@Override
public void run(Boolean value) {
getBasePlayer().findFreePosition(searchPos);
}
});
}
@Override
public void setOnGround(Location searchPos) {
TaskManager.IMP.sync(new RunnableVal<Boolean>() {
@Override
public void run(Boolean value) {
getBasePlayer().setOnGround(searchPos);
}
});
}
@Override
public void findFreePosition() {
TaskManager.IMP.sync(new RunnableVal<Boolean>() {
@Override
public void run(Boolean value) {
getBasePlayer().findFreePosition();
}
});
}
@Override
public boolean ascendLevel() {
return TaskManager.IMP.sync(new RunnableVal<Boolean>() {
@Override
public void run(Boolean value) {
this.value = getBasePlayer().ascendLevel();
}
});
}
@Override
public boolean descendLevel() {
return TaskManager.IMP.sync(new RunnableVal<Boolean>() {
@Override
public void run(Boolean value) {
this.value = getBasePlayer().descendLevel();
}
});
}
@Override
public boolean ascendToCeiling(int clearance) {
return ascendToCeiling(clearance, true);
}
@Override
public boolean ascendToCeiling(int clearance, boolean alwaysGlass) {
Location pos = getBlockIn();
int x = pos.getBlockX();
int initialY = Math.max(0, pos.getBlockY());
int y = Math.max(0, pos.getBlockY() + 2);
int z = pos.getBlockZ();
Extent world = getLocation().getExtent();
// No free space above
if (!world.getBlock(BlockVector3.at(x, y, z)).getBlockType().getMaterial().isAir()) {
return false;
}
while (y <= world.getMaximumPoint().getY()) {
// Found a ceiling!
if (world.getBlock(BlockVector3.at(x, y, z)).getBlockType().getMaterial().isMovementBlocker()) {
int platformY = Math.max(initialY, y - 3 - clearance);
floatAt(x, platformY + 1, z, alwaysGlass);
return true;
}
++y;
}
return false;
}
@Override
public boolean ascendUpwards(int distance) {
return ascendUpwards(distance, true);
}
@Override
public boolean ascendUpwards(int distance, boolean alwaysGlass) {
final Location pos = getBlockIn();
final int x = pos.getBlockX();
final int initialY = Math.max(0, pos.getBlockY());
int y = Math.max(0, pos.getBlockY() + 1);
final int z = pos.getBlockZ();
final int maxY = Math.min(getWorld().getMaxY() + 1, initialY + distance);
final Extent world = getLocation().getExtent();
while (y <= world.getMaximumPoint().getY() + 2) {
if (world.getBlock(BlockVector3.at(x, y, z)).getBlockType().getMaterial().isMovementBlocker()) {
break; // Hit something
} else if (y > maxY + 1) {
break;
} else if (y == maxY + 1) {
floatAt(x, y - 1, z, alwaysGlass);
return true;
}
++y;
}
return false;
}
@Override
public void floatAt(int x, int y, int z, boolean alwaysGlass) {
RuntimeException caught = null;
try {
EditSession edit = new EditSessionBuilder(WorldWrapper.unwrap(getWorld())).player(unwrap(getBasePlayer())).build();
edit.setBlock(BlockVector3.at(x, y - 1, z), BlockTypes.GLASS);
edit.flushQueue();
LocalSession session = Fawe.get().getWorldEdit().getSessionManager().get(this);
if (session != null) {
session.remember(edit, true, getBasePlayer().getLimit().MAX_HISTORY);
}
} catch (RuntimeException e) {
caught = e;
}
TaskManager.IMP.sync(new RunnableVal<Object>() {
@Override
public void run(Object value) {
setPosition(Vector3.at(x + 0.5, y, z + 0.5));
}
});
if (caught != null) {
throw caught;
}
}
@Override
public Location getBlockTrace(int range, boolean useLastBlock) {
return TaskManager.IMP.sync(new RunnableVal<Location>() {
@Override
public void run(Location value) {
TargetBlock tb = new TargetBlock(PlayerWrapper.this, range, 0.2D);
this.value = useLastBlock ? tb.getAnyTargetBlock() : tb.getTargetBlock();
}
});
}
@Override
public Location getBlockTraceFace(int range, boolean useLastBlock) {
return TaskManager.IMP.sync(new RunnableVal<Location>() {
@Override
public void run(Location value) {
TargetBlock tb = new TargetBlock(PlayerWrapper.this, range, 0.2D);
this.value = useLastBlock ? tb.getAnyTargetBlockFace() : tb.getTargetBlockFace();
}
});
}
@Override
public Location getSolidBlockTrace(int range) {
return TaskManager.IMP.sync(new RunnableVal<Location>() {
@Override
public void run(Location value) {
TargetBlock tb = new TargetBlock(PlayerWrapper.this, range, 0.2D);
this.value = tb.getSolidTargetBlock();
}
});
}
@Override
public Direction getCardinalDirection() {
return getBasePlayer().getCardinalDirection();
}
@Override
public boolean passThroughForwardWall(int range) {
return TaskManager.IMP.sync(() -> {
int searchDist = 0;
TargetBlock hitBlox = new TargetBlock(PlayerWrapper.this, range, 0.2);
Extent world = getLocation().getExtent();
Location block;
boolean firstBlock = true;
int freeToFind = 2;
boolean inFree = false;
while ((block = hitBlox.getNextBlock()) != null) {
boolean free = !world.getBlock(BlockVector3.at(block.getBlockX(), block.getBlockY(), block.getBlockZ())).getBlockType().getMaterial().isMovementBlocker();
if (firstBlock) {
firstBlock = false;
if (!free) {
--freeToFind;
continue;
}
}
++searchDist;
if (searchDist > 20) {
return false;
}
if (inFree != free) {
if (free) {
--freeToFind;
}
}
if (freeToFind == 0) {
setOnGround(block);
return true;
}
inFree = free;
}
return false;
});
}
}

View File

@ -0,0 +1,36 @@
package com.boydti.fawe.wrappers;
import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.util.formatting.text.Component;
import java.awt.*;
/**
* Avoids printing any messages
*/
public class SilentPlayerWrapper extends PlayerWrapper {
public SilentPlayerWrapper(Player parent) {
super(parent);
}
@Override
public void print(String msg) {
}
@Override
public void print(Component component) {
super.print(component);
}
@Override
public void printDebug(String msg) {
}
@Override
public void printError(String msg) {
}
@Override
public void printRaw(String msg) {
}
}

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