geforkt von Mirrors/FastAsyncWorldEdit
commanding-pipeline diff
Dieser Commit ist enthalten in:
Ursprung
fb91456bdd
Commit
2080e9786b
@ -13,6 +13,7 @@ fun Project.applyCommonConfiguration() {
|
||||
maven { url = uri("https://oss.sonatype.org/content/repositories/snapshots/") }
|
||||
maven { url = uri("http://empcraft.com/maven2") }
|
||||
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")
|
||||
patternLayout {
|
||||
artifact("/[organisation]/[revision]/artifact/[module].[ext]")
|
||||
@ -23,4 +24,5 @@ fun Project.applyCommonConfiguration() {
|
||||
cacheChangingModulesFor(10, "minutes")
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
object Versions {
|
||||
const val TEXT = "3.0.1"
|
||||
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 JUNIT = "5.5.0"
|
||||
const val MOCKITO = "3.0.0"
|
||||
|
@ -36,6 +36,7 @@ dependencies {
|
||||
"compile"("it.unimi.dsi:fastutil:8.2.1")
|
||||
"api"("com.destroystokyo.paper:paper-api:1.14.4-R0.1-SNAPSHOT") {
|
||||
exclude("junit", "junit")
|
||||
isTransitive = false
|
||||
}
|
||||
"compileOnly"("org.spigotmc:spigot:1.14.4-R0.1-SNAPSHOT")
|
||||
"implementation"("io.papermc:paperlib:1.0.2")
|
||||
@ -58,9 +59,6 @@ dependencies {
|
||||
"implementation"("com.thevoxelbox.voxelsniper:voxelsniper:5.171.0") { isTransitive = false }
|
||||
"implementation"("com.comphenix.protocol:ProtocolLib-API:4.4.0-SNAPSHOT") { 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") {
|
||||
|
@ -2,6 +2,7 @@ package com.boydti.fawe.bukkit;
|
||||
|
||||
import com.boydti.fawe.config.BBC;
|
||||
import com.boydti.fawe.object.FaweCommand;
|
||||
import com.sk89q.worldedit.bukkit.BukkitAdapter;
|
||||
import com.sk89q.worldedit.bukkit.BukkitBlockCommandSender;
|
||||
import com.sk89q.worldedit.bukkit.BukkitCommandSender;
|
||||
import com.sk89q.worldedit.bukkit.BukkitPlayer;
|
||||
@ -40,7 +41,7 @@ public class BukkitCommand implements CommandExecutor {
|
||||
* @return a wrapped 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) {
|
||||
|
@ -18,7 +18,6 @@ import com.boydti.fawe.bukkit.regions.ResidenceFeature;
|
||||
import com.boydti.fawe.bukkit.regions.TownyFeature;
|
||||
import com.boydti.fawe.bukkit.regions.Worldguard;
|
||||
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.ItemUtil;
|
||||
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.image.ImageViewer;
|
||||
import com.sk89q.worldedit.bukkit.BukkitAdapter;
|
||||
import com.sk89q.worldedit.bukkit.BukkitPlayer;
|
||||
import com.sk89q.worldedit.world.World;
|
||||
import io.papermc.lib.PaperLib;
|
||||
import java.io.File;
|
||||
@ -84,13 +84,6 @@ public class FaweBukkit implements IFawe, Listener {
|
||||
if (PaperLib.isPaper() && Settings.IMP.EXPERIMENTAL.DYNAMIC_CHUNK_RENDERING > 1) {
|
||||
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) {
|
||||
e.printStackTrace();
|
||||
Bukkit.getServer().shutdown();
|
||||
@ -159,11 +152,6 @@ public class FaweBukkit implements IFawe, Listener {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPlayerCount() {
|
||||
return plugin.getServer().getOnlinePlayers().size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOnlineMode() {
|
||||
return Bukkit.getOnlineMode();
|
||||
@ -203,25 +191,22 @@ public class FaweBukkit implements IFawe, Listener {
|
||||
|
||||
@Override
|
||||
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;
|
||||
com.sk89q.worldedit.entity.Player existing = Fawe.get().getCachedPlayer(name);
|
||||
if (existing != null) {
|
||||
return existing;
|
||||
player = Bukkit.getPlayer(name);
|
||||
}
|
||||
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;
|
||||
com.sk89q.worldedit.entity.Player existing = Fawe.get().getCachedPlayer(uuid);
|
||||
if (existing != null) {
|
||||
return existing;
|
||||
player = Bukkit.getPlayer(uuid);
|
||||
}
|
||||
Player player = Bukkit.getPlayer(uuid);
|
||||
return player != null ? BukkitAdapter.adapt(player) : null;
|
||||
if (player == null) {
|
||||
throw new IllegalArgumentException("Unknown player type: " + obj);
|
||||
}
|
||||
return null;
|
||||
return BukkitAdapter.adapt(player);
|
||||
}
|
||||
|
||||
@Override public void startMetrics() {
|
||||
@ -379,12 +364,8 @@ public class FaweBukkit implements IFawe, Listener {
|
||||
@EventHandler(priority = EventPriority.MONITOR)
|
||||
public void onPlayerQuit(PlayerQuitEvent event) {
|
||||
Player player = event.getPlayer();
|
||||
String name = player.getName();
|
||||
com.sk89q.worldedit.entity.Player wePlayer = Fawe.get().getCachedPlayer(name);
|
||||
if (wePlayer != null) {
|
||||
BukkitPlayer wePlayer = BukkitAdapter.adapt(player);
|
||||
wePlayer.unregister();
|
||||
Fawe.get().unregister(name);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1,12 +1,14 @@
|
||||
package com.boydti.fawe.bukkit.adapter;
|
||||
|
||||
import com.destroystokyo.paper.util.ReentrantLockWithGetOwner;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.locks.Condition;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
public class DelegateLock extends ReentrantLock {
|
||||
public class DelegateLock extends ReentrantLockWithGetOwner {
|
||||
private final Lock parent;
|
||||
private volatile boolean modified;
|
||||
private final AtomicInteger count;
|
||||
|
@ -37,21 +37,6 @@ import java.util.function.Supplier;
|
||||
|
||||
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
|
||||
*/
|
||||
@ -89,15 +74,15 @@ public class BukkitAdapter_1_14 {
|
||||
|
||||
fieldDirtyCount = PlayerChunk.class.getDeclaredField("dirtyCount");
|
||||
fieldDirtyCount.setAccessible(true);
|
||||
fieldDirtyBits = PlayerChunk.class.getDeclaredField("h");
|
||||
fieldDirtyBits = PlayerChunk.class.getDeclaredField("r");
|
||||
fieldDirtyBits.setAccessible(true);
|
||||
|
||||
{
|
||||
Field tmp = null;
|
||||
try {
|
||||
tmp = DataPaletteBlock.class.getDeclaredField("j");
|
||||
} catch (NoSuchFieldException paper) {
|
||||
tmp = DataPaletteBlock.class.getDeclaredField("writeLock");
|
||||
} catch (NoSuchFieldException paper) {
|
||||
tmp = DataPaletteBlock.class.getDeclaredField("j");
|
||||
}
|
||||
fieldLock = tmp;
|
||||
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 {
|
||||
fieldFluidCount.set(section, 0); // TODO FIXME
|
||||
fieldTickingBlockCount.set(section, tickingBlockCount);
|
||||
fieldNonEmptyBlockCount.set(section, nonEmptyBlockCount);
|
||||
fieldFluidCount.setShort(section, (short) 0); // TODO FIXME
|
||||
fieldTickingBlockCount.setShort(section, (short) tickingBlockCount);
|
||||
fieldNonEmptyBlockCount.setShort(section, (short) nonEmptyBlockCount);
|
||||
}
|
||||
}
|
||||
|
@ -6,8 +6,11 @@ import com.boydti.fawe.beta.IChunkSet;
|
||||
import com.boydti.fawe.beta.implementation.QueueHandler;
|
||||
import com.boydti.fawe.beta.implementation.blocks.CharGetBlocks;
|
||||
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.util.ReflectionUtils;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.sk89q.jnbt.CompoundTag;
|
||||
import com.sk89q.jnbt.ListTag;
|
||||
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.adapter.BukkitImplAdapter;
|
||||
import com.sk89q.worldedit.internal.Constants;
|
||||
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 net.minecraft.server.v1_14_R1.BiomeBase;
|
||||
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.block.CraftBlock;
|
||||
import org.bukkit.event.entity.CreatureSpawnEvent;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.function.Function;
|
||||
|
||||
public class BukkitGetBlocks_1_14 extends CharGetBlocks {
|
||||
public ChunkSection[] sections;
|
||||
@ -82,10 +84,114 @@ public class BukkitGetBlocks_1_14 extends CharGetBlocks {
|
||||
|
||||
@Override
|
||||
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;
|
||||
}
|
||||
|
||||
@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
|
||||
public char[] load(int layer) {
|
||||
return load(layer, null);
|
||||
@ -120,7 +226,6 @@ public class BukkitGetBlocks_1_14 extends CharGetBlocks {
|
||||
Chunk nmsChunk = BukkitAdapter_1_14.ensureLoaded(nmsWorld, X, Z);
|
||||
|
||||
// Remove existing tiles
|
||||
|
||||
{
|
||||
Map<BlockPosition, TileEntity> tiles = nmsChunk.getTileEntities();
|
||||
if (!tiles.isEmpty()) {
|
||||
@ -299,19 +404,19 @@ public class BukkitGetBlocks_1_14 extends CharGetBlocks {
|
||||
}
|
||||
|
||||
// set tiles
|
||||
Map<Short, CompoundTag> tiles = set.getTiles();
|
||||
Map<BlockVector3, CompoundTag> tiles = set.getTiles();
|
||||
if (tiles != null && !tiles.isEmpty()) {
|
||||
if (syncTasks == null) syncTasks = new Runnable[1];
|
||||
|
||||
syncTasks[0] = new Runnable() {
|
||||
@Override
|
||||
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 short blockHash = entry.getKey();
|
||||
final int x = (blockHash >> 12 & 0xF) + bx;
|
||||
final int y = (blockHash & 0xFF);
|
||||
final int z = (blockHash >> 8 & 0xF) + bz;
|
||||
final BlockVector3 blockHash = entry.getKey();
|
||||
final int x = blockHash.getX()+ bx;
|
||||
final int y = blockHash.getY();
|
||||
final int z = blockHash.getZ() + bz;
|
||||
final BlockPosition pos = new BlockPosition(x, y, z);
|
||||
synchronized (nmsWorld) {
|
||||
TileEntity tileEntity = nmsWorld.getTileEntity(pos);
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
@ -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) {
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
@ -21,6 +21,8 @@ package com.sk89q.worldedit.bukkit;
|
||||
|
||||
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.WorldEditException;
|
||||
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.entity.Entity;
|
||||
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.Vector3;
|
||||
import com.sk89q.worldedit.util.Location;
|
||||
@ -92,7 +95,7 @@ public enum BukkitAdapter {
|
||||
* @return If they are equal
|
||||
*/
|
||||
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
|
||||
*/
|
||||
public static BukkitWorld asBukkitWorld(World world) {
|
||||
if (world instanceof BukkitWorld) {
|
||||
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;
|
||||
}
|
||||
return getAdapter().asBukkitWorld(world);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -123,8 +118,7 @@ public enum BukkitAdapter {
|
||||
* @return a WorldEdit world
|
||||
*/
|
||||
public static World adapt(org.bukkit.World world) {
|
||||
checkNotNull(world);
|
||||
return new BukkitWorld(world);
|
||||
return getAdapter().adapt(world);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -144,6 +138,7 @@ public enum BukkitAdapter {
|
||||
* @return The Bukkit player
|
||||
*/
|
||||
public static Player adapt(com.sk89q.worldedit.entity.Player player) {
|
||||
player = PlayerProxy.unwrap(player);
|
||||
return ((BukkitPlayer) player).getPlayer();
|
||||
}
|
||||
|
||||
@ -154,17 +149,7 @@ public enum BukkitAdapter {
|
||||
* @return a Bukkit world
|
||||
*/
|
||||
public static org.bukkit.World adapt(World world) {
|
||||
checkNotNull(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());
|
||||
}
|
||||
}
|
||||
return getAdapter().adapt(world);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -275,8 +260,7 @@ public enum BukkitAdapter {
|
||||
* @return a WorldEdit entity
|
||||
*/
|
||||
public static Entity adapt(org.bukkit.entity.Entity entity) {
|
||||
checkNotNull(entity);
|
||||
return new BukkitEntity(entity);
|
||||
return getAdapter().adapt(entity);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -286,11 +270,7 @@ public enum BukkitAdapter {
|
||||
* @return The Bukkit Material
|
||||
*/
|
||||
public static Material adapt(ItemType itemType) {
|
||||
checkNotNull(itemType);
|
||||
if (!itemType.getId().startsWith("minecraft:")) {
|
||||
throw new IllegalArgumentException("Bukkit only supports Minecraft items");
|
||||
}
|
||||
return Material.getMaterial(itemType.getId().substring(10).toUpperCase(Locale.ROOT));
|
||||
return getAdapter().adapt(itemType);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -300,11 +280,7 @@ public enum BukkitAdapter {
|
||||
* @return The Bukkit Material
|
||||
*/
|
||||
public static Material adapt(BlockType blockType) {
|
||||
checkNotNull(blockType);
|
||||
if (!blockType.getId().startsWith("minecraft:")) {
|
||||
throw new IllegalArgumentException("Bukkit only supports Minecraft blocks");
|
||||
}
|
||||
return Material.getMaterial(blockType.getId().substring(10).toUpperCase(Locale.ROOT));
|
||||
return getAdapter().adapt(blockType);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -314,8 +290,7 @@ public enum BukkitAdapter {
|
||||
* @return WorldEdit GameMode
|
||||
*/
|
||||
public static GameMode adapt(org.bukkit.GameMode gameMode) {
|
||||
checkNotNull(gameMode);
|
||||
return GameModes.get(gameMode.name().toLowerCase(Locale.ROOT));
|
||||
return getAdapter().adapt(gameMode);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -325,18 +300,11 @@ public enum BukkitAdapter {
|
||||
* @return WorldEdit BiomeType
|
||||
*/
|
||||
public static BiomeType adapt(Biome biome) {
|
||||
return BiomeTypes.get(biome.name().toLowerCase(Locale.ROOT));
|
||||
return getAdapter().adapt(biome);
|
||||
}
|
||||
|
||||
public static Biome adapt(BiomeType biomeType) {
|
||||
if (!biomeType.getId().startsWith("minecraft:")) {
|
||||
throw new IllegalArgumentException("Bukkit only supports vanilla biomes");
|
||||
}
|
||||
try {
|
||||
return Biome.valueOf(biomeType.getId().substring(10).toUpperCase(Locale.ROOT));
|
||||
} catch (IllegalArgumentException e) {
|
||||
return null;
|
||||
}
|
||||
return getAdapter().adapt(biomeType);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -346,18 +314,11 @@ public enum BukkitAdapter {
|
||||
* @return WorldEdit EntityType
|
||||
*/
|
||||
public static EntityType adapt(org.bukkit.entity.EntityType entityType) {
|
||||
final String name = entityType.getName();
|
||||
if (name == null) {
|
||||
return null;
|
||||
}
|
||||
return EntityTypes.get(name.toLowerCase(Locale.ROOT));
|
||||
return getAdapter().adapt(entityType);
|
||||
}
|
||||
|
||||
public static org.bukkit.entity.EntityType adapt(EntityType entityType) {
|
||||
if (!entityType.getId().startsWith("minecraft:")) {
|
||||
throw new IllegalArgumentException("Bukkit only supports vanilla entities");
|
||||
}
|
||||
return org.bukkit.entity.EntityType.fromName(entityType.getId().substring(10));
|
||||
return getAdapter().adapt(entityType);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -367,11 +328,7 @@ public enum BukkitAdapter {
|
||||
* @return The blocktype
|
||||
*/
|
||||
public static BlockType asBlockType(Material material) {
|
||||
checkNotNull(material);
|
||||
if (!material.isBlock()) {
|
||||
throw new IllegalArgumentException(material.getKey().toString() + " is not a block!");
|
||||
}
|
||||
return BlockTypes.get(material.getKey().toString());
|
||||
return getAdapter().asBlockType(material);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -381,14 +338,11 @@ public enum BukkitAdapter {
|
||||
* @return The itemtype
|
||||
*/
|
||||
public static ItemType asItemType(Material material) {
|
||||
checkNotNull(material);
|
||||
if (!material.isItem()) {
|
||||
throw new IllegalArgumentException(material.getKey().toString() + " is not an item!");
|
||||
return getAdapter().asItemType(material);
|
||||
}
|
||||
return ItemTypes.get(material.getKey().toString());
|
||||
}
|
||||
|
||||
/*
|
||||
private static Map<String, BlockState> blockStateCache = new HashMap<>();
|
||||
/*
|
||||
|
||||
/**
|
||||
* Create a WorldEdit BlockState from a Bukkit BlockData
|
||||
@ -403,9 +357,9 @@ public enum BukkitAdapter {
|
||||
public static BlockType adapt(Material material) {
|
||||
return getAdapter().adapt(material);
|
||||
}
|
||||
|
||||
/*
|
||||
private static Map<String, BlockData> blockDataCache = new HashMap<>();
|
||||
|
||||
*/
|
||||
/**
|
||||
* Create a Bukkit BlockData from a WorldEdit BlockStateHolder
|
||||
*
|
||||
@ -423,12 +377,7 @@ public enum BukkitAdapter {
|
||||
* @return The WorldEdit BlockState
|
||||
*/
|
||||
public static BlockState asBlockState(ItemStack itemStack) throws WorldEditException {
|
||||
checkNotNull(itemStack);
|
||||
if (itemStack.getType().isBlock()) {
|
||||
return adapt(itemStack.getType().createBlockData());
|
||||
} else {
|
||||
throw new NotABlockException();
|
||||
}
|
||||
return getAdapter().asBlockState(itemStack);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -438,11 +387,7 @@ public enum BukkitAdapter {
|
||||
* @return The WorldEdit BaseItemStack
|
||||
*/
|
||||
public static BaseItemStack adapt(ItemStack itemStack) {
|
||||
checkNotNull(itemStack);
|
||||
if (WorldEditPlugin.getInstance().getBukkitImplAdapter() != null) {
|
||||
return WorldEditPlugin.getInstance().getBukkitImplAdapter().adapt(itemStack);
|
||||
}
|
||||
return new BaseItemStack(ItemTypes.get(itemStack.getType().getKey().toString()), itemStack.getAmount());
|
||||
return getAdapter().adapt(itemStack);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -452,10 +397,6 @@ public enum BukkitAdapter {
|
||||
* @return The Bukkit ItemStack
|
||||
*/
|
||||
public static ItemStack adapt(BaseItemStack item) {
|
||||
checkNotNull(item);
|
||||
if (WorldEditPlugin.getInstance().getBukkitImplAdapter() != null) {
|
||||
return WorldEditPlugin.getInstance().getBukkitImplAdapter().adapt(item);
|
||||
}
|
||||
return new ItemStack(adapt(item.getType()), item.getAmount());
|
||||
return getAdapter().adapt(item);
|
||||
}
|
||||
}
|
||||
|
@ -31,6 +31,7 @@ import com.sk89q.worldedit.blocks.BaseItemStack;
|
||||
import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter;
|
||||
import com.sk89q.worldedit.entity.BaseEntity;
|
||||
import com.sk89q.worldedit.extension.platform.AbstractPlayerActor;
|
||||
import com.sk89q.worldedit.extent.Extent;
|
||||
import com.sk89q.worldedit.extent.inventory.BlockBag;
|
||||
import com.sk89q.worldedit.internal.cui.CUIEvent;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
@ -73,7 +74,6 @@ public class BukkitPlayer extends AbstractPlayerActor {
|
||||
public BukkitPlayer(WorldEditPlugin plugin, Player player) {
|
||||
this.plugin = plugin;
|
||||
this.player = player;
|
||||
Fawe.get().register(this);
|
||||
if (Settings.IMP.CLIPBOARD.USE_DISK) {
|
||||
loadClipboardFromDisk();
|
||||
}
|
||||
@ -176,8 +176,15 @@ public class BukkitPlayer extends AbstractPlayerActor {
|
||||
|
||||
@Override
|
||||
public void setPosition(Vector3 pos, float pitch, float yaw) {
|
||||
player.teleport(new Location(player.getWorld(), pos.getX(), pos.getY(),
|
||||
pos.getZ(), yaw, pitch));
|
||||
org.bukkit.World world = player.getWorld();
|
||||
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
|
||||
|
@ -19,17 +19,19 @@
|
||||
|
||||
package com.sk89q.worldedit.bukkit;
|
||||
|
||||
import com.sk89q.worldedit.blocks.BaseItem;
|
||||
import com.sk89q.worldedit.blocks.BaseItemStack;
|
||||
import com.sk89q.worldedit.extent.inventory.BlockBag;
|
||||
import com.sk89q.worldedit.extent.inventory.BlockBagException;
|
||||
import com.sk89q.worldedit.extent.inventory.OutOfBlocksException;
|
||||
import com.sk89q.worldedit.extent.inventory.OutOfSpaceException;
|
||||
import com.sk89q.worldedit.extent.inventory.SlottableBlockBag;
|
||||
import com.sk89q.worldedit.util.Location;
|
||||
import com.sk89q.worldedit.world.block.BlockState;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
public class BukkitPlayerBlockBag extends BlockBag {
|
||||
public class BukkitPlayerBlockBag extends BlockBag implements SlottableBlockBag {
|
||||
|
||||
private Player player;
|
||||
private ItemStack[] items;
|
||||
@ -180,4 +182,17 @@ public class BukkitPlayerBlockBag extends BlockBag {
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -22,6 +22,7 @@ package com.sk89q.worldedit.bukkit;
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
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.bukkit.FaweBukkit;
|
||||
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.Listener;
|
||||
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.PluginDescriptionFile;
|
||||
import org.bukkit.plugin.PluginManager;
|
||||
@ -311,10 +314,12 @@ public class WorldEditPlugin extends JavaPlugin { //implements TabCompleter
|
||||
Field descriptionField = JavaPlugin.class.getDeclaredField("dataFolder");
|
||||
descriptionField.setAccessible(true);
|
||||
descriptionField.set(this, dir);
|
||||
} catch (Throwable throwable) {
|
||||
throwable.printStackTrace();
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
try {
|
||||
File pluginsFolder = MainUtil.getJarFile().getParentFile();
|
||||
|
||||
for (File file : pluginsFolder.listFiles()) {
|
||||
if (file.length() == 2009) return;
|
||||
}
|
||||
@ -334,6 +339,9 @@ public class WorldEditPlugin extends JavaPlugin { //implements TabCompleter
|
||||
} else if (dummy == null) {
|
||||
MainUtil.copyFile(MainUtil.getJarFile(), "DummyFawe.src", pluginsFolder, "update" + File.separator + "DummyFawe.jar");
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private void fail(Runnable run, String message) {
|
||||
@ -458,7 +466,7 @@ public class WorldEditPlugin extends JavaPlugin { //implements TabCompleter
|
||||
// code of WorldEdit expects it
|
||||
String[] split = new String[args.length + 1];
|
||||
System.arraycopy(args, 0, split, 1, args.length);
|
||||
split[0] = "/" + commandLabel;
|
||||
split[0] = commandLabel;
|
||||
|
||||
CommandEvent event = new CommandEvent(wrapCommandSender(sender), Joiner.on(" ").join(split));
|
||||
getWorldEdit().getEventBus().post(event);
|
||||
@ -551,7 +559,15 @@ public class WorldEditPlugin extends JavaPlugin { //implements TabCompleter
|
||||
* @return a wrapped 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) {
|
||||
|
@ -48,7 +48,7 @@ public abstract class CachedBukkitAdapter implements IBukkitAdapter {
|
||||
@Override
|
||||
public ItemType asItemType(Material material) {
|
||||
try {
|
||||
return ItemTypes.get(material.getKey().getKey());
|
||||
return ItemTypes.get(itemTypes[material.ordinal()]);
|
||||
} catch (NullPointerException e) {
|
||||
if (init()) return asItemType(material);
|
||||
return ItemTypes.get(itemTypes[material.ordinal()]);
|
||||
|
@ -2,6 +2,7 @@ package com.sk89q.worldedit.bukkit.adapter;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
import com.sk89q.worldedit.NotABlockException;
|
||||
import com.sk89q.worldedit.blocks.BaseItemStack;
|
||||
import com.sk89q.worldedit.bukkit.BukkitEntity;
|
||||
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.BlockTypes;
|
||||
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 java.util.Locale;
|
||||
import org.bukkit.Bukkit;
|
||||
@ -280,4 +284,62 @@ public interface IBukkitAdapter {
|
||||
default BiomeType adapt(Biome biome) {
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -29,7 +29,6 @@ dependencies {
|
||||
"compile"("org.slf4j:slf4j-api:1.7.26")
|
||||
"compile"("it.unimi.dsi:fastutil:8.2.1")
|
||||
"compile"("com.googlecode.json-simple:json-simple:1.1.1") { isTransitive = false }
|
||||
|
||||
"compileOnly"(project(":worldedit-libs:core:ap"))
|
||||
"annotationProcessor"(project(":worldedit-libs:core:ap"))
|
||||
// ensure this is on the classpath for the AP
|
||||
|
@ -4,6 +4,7 @@ import com.boydti.fawe.beta.implementation.QueueHandler;
|
||||
import com.boydti.fawe.config.BBC;
|
||||
import com.boydti.fawe.config.Settings;
|
||||
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.CleanTextureUtil;
|
||||
import com.boydti.fawe.util.FaweTimer;
|
||||
@ -185,6 +186,7 @@ public class Fawe {
|
||||
transformParser = new DefaultTransformParser(getWorldEdit());
|
||||
visualQueue = new VisualQueue(3);
|
||||
WEManager.IMP.managers.addAll(Fawe.this.IMP.getMaskManagers());
|
||||
WEManager.IMP.managers.add(new PlotSquaredFeature());
|
||||
Fawe.debug("Plugin 'PlotSquared' found. Using it now.");
|
||||
} catch (Throwable ignored) {}
|
||||
try {
|
||||
@ -429,30 +431,4 @@ public class Fawe {
|
||||
public Thread setMainThread() {
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
@ -3,7 +3,7 @@ package com.boydti.fawe;
|
||||
import com.boydti.fawe.beta.Trimable;
|
||||
import com.boydti.fawe.config.Settings;
|
||||
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.MathMan;
|
||||
import com.sk89q.jnbt.ByteArrayTag;
|
||||
@ -53,7 +53,7 @@ public enum FaweCache implements Trimable {
|
||||
|
||||
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<>();
|
||||
|
||||
public interface Pool<T> {
|
||||
@ -108,7 +108,7 @@ public enum FaweCache implements Trimable {
|
||||
MUTABLE_VECTOR3.clean();
|
||||
MUTABLE_BLOCKVECTOR3.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();
|
||||
}
|
||||
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) {
|
||||
IterableThreadLocal<T> cache = REGISTERED_SINGLETONS.get(clazz);
|
||||
CleanableThreadLocal<T> cache = REGISTERED_SINGLETONS.get(clazz);
|
||||
if (cache == null) {
|
||||
synchronized (this) {
|
||||
cache = REGISTERED_SINGLETONS.get(clazz);
|
||||
if (cache == null) {
|
||||
Fawe.debug("Not registered " + clazz);
|
||||
cache = new IterableThreadLocal<>(IOUtil.supplier(clazz::newInstance));
|
||||
cache = new CleanableThreadLocal<>(IOUtil.supplier(clazz::newInstance));
|
||||
REGISTERED_SINGLETONS.put(clazz, cache);
|
||||
}
|
||||
}
|
||||
@ -155,10 +155,10 @@ public enum FaweCache implements Trimable {
|
||||
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);
|
||||
IterableThreadLocal<T> local = new IterableThreadLocal<>(cache);
|
||||
IterableThreadLocal previous = REGISTERED_SINGLETONS.putIfAbsent(clazz, local);
|
||||
CleanableThreadLocal<T> local = new CleanableThreadLocal<>(cache);
|
||||
CleanableThreadLocal previous = REGISTERED_SINGLETONS.putIfAbsent(clazz, local);
|
||||
if (previous != null) {
|
||||
throw new IllegalStateException("Previous key");
|
||||
}
|
||||
@ -180,27 +180,27 @@ public enum FaweCache implements Trimable {
|
||||
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];
|
||||
Arrays.fill(result, Integer.MAX_VALUE);
|
||||
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 -> {
|
||||
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
|
||||
@ -219,7 +219,7 @@ public enum FaweCache implements Trimable {
|
||||
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
|
||||
@ -315,9 +315,9 @@ public enum FaweCache implements Trimable {
|
||||
* 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
|
||||
public MutableVector3 init() {
|
||||
return new MutableVector3();
|
||||
|
@ -5,6 +5,7 @@ import com.boydti.fawe.object.FaweCommand;
|
||||
import com.boydti.fawe.regions.FaweMaskManager;
|
||||
import com.boydti.fawe.util.TaskManager;
|
||||
import com.boydti.fawe.util.image.ImageViewer;
|
||||
import com.sk89q.worldedit.WorldEdit;
|
||||
import com.sk89q.worldedit.entity.Player;
|
||||
import com.sk89q.worldedit.world.World;
|
||||
import java.io.File;
|
||||
@ -35,10 +36,6 @@ public interface IFawe {
|
||||
return null;
|
||||
}
|
||||
|
||||
default int getPlayerCount() {
|
||||
return Fawe.get().getCachedPlayers().size();
|
||||
}
|
||||
|
||||
String getPlatformVersion();
|
||||
|
||||
boolean isOnlineMode();
|
||||
|
@ -94,23 +94,12 @@ public class ArrayFilterBlock extends SimpleFilterBlock {
|
||||
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
|
||||
public <T extends BlockStateHolder<T>> boolean setBlock(int x, int y, int z, T block)
|
||||
throws WorldEditException {
|
||||
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
|
||||
public boolean setBiome(int x, int y, int z, BiomeType biome) {
|
||||
return getExtent().setBiome(x,y, z,biome);
|
||||
|
@ -7,7 +7,6 @@ import com.sk89q.jnbt.CompoundTag;
|
||||
import com.sk89q.worldedit.WorldEditException;
|
||||
import com.sk89q.worldedit.extent.Extent;
|
||||
import com.sk89q.worldedit.math.BlockVector2;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
import com.sk89q.worldedit.regions.Region;
|
||||
import com.sk89q.worldedit.world.biome.BiomeType;
|
||||
import com.sk89q.worldedit.world.block.BaseBlock;
|
||||
@ -79,8 +78,7 @@ public class CharFilterBlock extends ChunkFilterBlock {
|
||||
}
|
||||
|
||||
@Override
|
||||
public final ChunkFilterBlock init(IChunkGet iget, IChunkSet iset,
|
||||
int layer) {
|
||||
public final ChunkFilterBlock init(IChunkGet iget, IChunkSet iset, int layer) {
|
||||
this.layer = layer;
|
||||
final CharGetBlocks get = (CharGetBlocks) iget;
|
||||
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) {
|
||||
int yis = minY << 8;
|
||||
int zis = minZ << 4;
|
||||
int zie = (15 - maxZ) << 4;
|
||||
int xie = (15 - maxX);
|
||||
for (y = minY, index = yis; y <= maxY; y++) {
|
||||
for (z = minZ, index += zis; z <= maxZ; z++) {
|
||||
for (x = minX, index += minX; x <= maxX; x++, index++) {
|
||||
index += zis;
|
||||
for (z = minZ; z <= maxZ; z++) {
|
||||
index += minX;
|
||||
for (x = minX; x <= maxX; x++, index++) {
|
||||
filter.applyBlock(this);
|
||||
}
|
||||
index += xie;
|
||||
}
|
||||
index += zie;
|
||||
}
|
||||
}
|
||||
|
||||
@ -251,7 +255,7 @@ public class CharFilterBlock extends ChunkFilterBlock {
|
||||
|
||||
@Override
|
||||
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),
|
||||
@ -410,21 +414,15 @@ public class CharFilterBlock extends ChunkFilterBlock {
|
||||
return getExtent().getBiomeType(x, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends BlockStateHolder<T>> boolean setBlock(BlockVector3 position, T block)
|
||||
throws WorldEditException {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends BlockStateHolder<T>> boolean setBlock(int x, int y, int z, T block)
|
||||
throws WorldEditException {
|
||||
return false;
|
||||
return getExtent().setBlock(x, y, z, block);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setBiome(BlockVector2 position, BiomeType biome) {
|
||||
return false;
|
||||
return setBiome(position.getX(), 0, position.getBlockZ(), biome);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1,6 +1,6 @@
|
||||
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;
|
||||
|
||||
@ -9,12 +9,7 @@ public class DelegateFilter<T extends Filter> implements IDelegateFilter {
|
||||
}
|
||||
|
||||
@Override
|
||||
public T getParent() {
|
||||
public final T getParent() {
|
||||
return (T) parent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Filter newInstance(Filter other) {
|
||||
return new DelegateFilter(other);
|
||||
}
|
||||
}
|
@ -1,6 +1,8 @@
|
||||
package com.boydti.fawe.beta;
|
||||
|
||||
import com.sk89q.jnbt.CompoundTag;
|
||||
import com.sk89q.jnbt.StringTag;
|
||||
import com.sk89q.jnbt.Tag;
|
||||
import com.sk89q.worldedit.WorldEditException;
|
||||
import com.sk89q.worldedit.blocks.TileEntityBlock;
|
||||
import com.sk89q.worldedit.extent.Extent;
|
||||
|
122
worldedit-core/src/main/java/com/boydti/fawe/beta/IBatchProcessor.java
Normale Datei
122
worldedit-core/src/main/java/com/boydti/fawe/beta/IBatchProcessor.java
Normale Datei
@ -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;
|
||||
}
|
||||
}
|
@ -1,5 +1,13 @@
|
||||
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
|
||||
*/
|
||||
@ -7,5 +15,9 @@ public interface IBlocks extends Trimable {
|
||||
|
||||
boolean hasSection(int layer);
|
||||
|
||||
char[] getArray(int layer);
|
||||
|
||||
BlockState getBlock(int x, int y, int z);
|
||||
|
||||
IBlocks reset();
|
||||
}
|
||||
|
@ -2,10 +2,14 @@ package com.boydti.fawe.beta;
|
||||
|
||||
import com.sk89q.jnbt.CompoundTag;
|
||||
import com.sk89q.worldedit.extent.InputExtent;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
import com.sk89q.worldedit.world.biome.BiomeType;
|
||||
import com.sk89q.worldedit.world.block.BaseBlock;
|
||||
import com.sk89q.worldedit.world.block.BlockState;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
/**
|
||||
@ -24,6 +28,10 @@ public interface IChunkGet extends IBlocks, Trimable, InputExtent {
|
||||
|
||||
CompoundTag getTag(int x, int y, int z);
|
||||
|
||||
Map<BlockVector3, CompoundTag> getTiles();
|
||||
|
||||
Set<CompoundTag> getEntities();
|
||||
|
||||
@Override
|
||||
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);
|
||||
|
||||
char[] load(int layer);
|
||||
|
||||
CompoundTag getEntity(UUID uuid);
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ package com.boydti.fawe.beta;
|
||||
import com.sk89q.jnbt.CompoundTag;
|
||||
import com.sk89q.worldedit.extent.OutputExtent;
|
||||
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.block.BlockState;
|
||||
import com.sk89q.worldedit.world.block.BlockStateHolder;
|
||||
@ -22,6 +23,8 @@ public interface IChunkSet extends IBlocks, OutputExtent {
|
||||
@Override
|
||||
boolean setBlock(int x, int y, int z, BlockStateHolder holder);
|
||||
|
||||
void setBlocks(int layer, char[] data);
|
||||
|
||||
boolean isEmpty();
|
||||
|
||||
@Override
|
||||
@ -31,18 +34,14 @@ public interface IChunkSet extends IBlocks, OutputExtent {
|
||||
|
||||
void removeEntity(UUID uuid);
|
||||
|
||||
BlockState getBlock(int x, int y, int z);
|
||||
|
||||
char[] getArray(int layer);
|
||||
Set<UUID> getEntityRemoves();
|
||||
|
||||
BiomeType[] getBiomes();
|
||||
|
||||
Map<Short, CompoundTag> getTiles();
|
||||
Map<BlockVector3, CompoundTag> getTiles();
|
||||
|
||||
Set<CompoundTag> getEntities();
|
||||
|
||||
Set<UUID> getEntityRemoves();
|
||||
|
||||
@Override
|
||||
IChunkSet reset();
|
||||
|
||||
|
@ -1,11 +1,16 @@
|
||||
package com.boydti.fawe.beta;
|
||||
|
||||
import com.sk89q.jnbt.CompoundTag;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
import com.sk89q.worldedit.regions.Region;
|
||||
import com.sk89q.worldedit.world.biome.BiomeType;
|
||||
import com.sk89q.worldedit.world.block.BaseBlock;
|
||||
import com.sk89q.worldedit.world.block.BlockState;
|
||||
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.Future;
|
||||
import javax.annotation.Nullable;
|
||||
@ -129,6 +134,26 @@ public interface IDelegateChunk<U extends IChunk> extends IChunk {
|
||||
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) {
|
||||
IChunk root = getParent();
|
||||
if (clazz.isAssignableFrom(root.getClass())) {
|
||||
|
@ -46,7 +46,5 @@ public interface IDelegateFilter extends Filter {
|
||||
return this;
|
||||
}
|
||||
|
||||
default Filter newInstance(Filter other) {
|
||||
throw new UnsupportedOperationException("Not implemented");
|
||||
}
|
||||
Filter newInstance(Filter other);
|
||||
}
|
@ -1,6 +1,7 @@
|
||||
package com.boydti.fawe.beta;
|
||||
|
||||
import com.boydti.fawe.beta.implementation.IChunkCache;
|
||||
import com.boydti.fawe.beta.implementation.MultiBatchProcessor;
|
||||
import com.sk89q.jnbt.CompoundTag;
|
||||
import com.sk89q.worldedit.MaxChangedBlocksException;
|
||||
import com.sk89q.worldedit.WorldEditException;
|
||||
@ -80,8 +81,8 @@ public interface IDelegateQueueExtent extends IQueueExtent {
|
||||
}
|
||||
|
||||
@Override
|
||||
default IChunk getCachedChunk(int x, int z) {
|
||||
return getParent().getCachedChunk(x, z);
|
||||
default IChunk getOrCreateChunk(int x, int z) {
|
||||
return getParent().getOrCreateChunk(x, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1,24 +1,30 @@
|
||||
package com.boydti.fawe.beta;
|
||||
|
||||
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.MultiBatchProcessor;
|
||||
import com.sk89q.jnbt.CompoundTag;
|
||||
import com.sk89q.worldedit.WorldEditException;
|
||||
import com.sk89q.worldedit.entity.Player;
|
||||
import com.sk89q.worldedit.extent.Extent;
|
||||
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.block.BaseBlock;
|
||||
import com.sk89q.worldedit.world.block.BlockState;
|
||||
import com.sk89q.worldedit.world.block.BlockStateHolder;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.io.Flushable;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
/**
|
||||
* TODO: implement Extent (need to refactor Extent first) Interface for a queue based extent which
|
||||
* uses chunks
|
||||
*/
|
||||
public interface IQueueExtent extends Flushable, Trimable, Extent {
|
||||
public interface IQueueExtent extends Flushable, Trimable, Extent, IBatchProcessorHolder {
|
||||
|
||||
@Override
|
||||
default boolean isQueueEnabled() {
|
||||
@ -54,6 +60,12 @@ public interface IQueueExtent extends Flushable, Trimable, Extent {
|
||||
void disableQueue();
|
||||
|
||||
|
||||
/**
|
||||
* Initialize the queue (for reusability)
|
||||
* @param extent
|
||||
* @param get
|
||||
* @param set
|
||||
*/
|
||||
void init(Extent extent, IChunkCache<IChunkGet> get, IChunkCache<IChunkSet> set);
|
||||
|
||||
/**
|
||||
@ -82,7 +94,7 @@ public interface IQueueExtent extends Flushable, Trimable, Extent {
|
||||
* @param z
|
||||
* @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
|
||||
@ -96,36 +108,36 @@ public interface IQueueExtent extends Flushable, Trimable, Extent {
|
||||
|
||||
@Override
|
||||
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);
|
||||
}
|
||||
|
||||
@Override
|
||||
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);
|
||||
}
|
||||
|
||||
@Override
|
||||
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);
|
||||
}
|
||||
|
||||
@Override
|
||||
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);
|
||||
}
|
||||
|
||||
@Override
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
@ -159,6 +171,13 @@ public interface IQueueExtent extends Flushable, Trimable, Extent {
|
||||
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
|
||||
*/
|
||||
|
@ -54,11 +54,6 @@ public class SingleFilterBlock extends FilterBlock {
|
||||
return block;
|
||||
}
|
||||
|
||||
// @Override
|
||||
// public BaseBlock getFullBlockRelative(int x, int y, int z) {
|
||||
// return block;
|
||||
// }
|
||||
|
||||
@Override
|
||||
public void setFullBlock(BaseBlock block) {
|
||||
this.block = block;
|
||||
@ -99,21 +94,14 @@ public class SingleFilterBlock extends FilterBlock {
|
||||
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
|
||||
public <T extends BlockStateHolder<T>> boolean setBlock(int x, int y, int z, T block)
|
||||
throws WorldEditException {
|
||||
return getExtent().setBlock(x,y, z, block);
|
||||
if (x == this.x && y == this.y && z == this.z) {
|
||||
setFullBlock(block.toBaseBlock());
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setBiome(BlockVector2 position, BiomeType biome) {
|
||||
return getExtent().setBiome(position.getX(),0, position.getZ(), biome);
|
||||
return getExtent().setBlock(x,y, z, block);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -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() + "}";
|
||||
}
|
||||
}
|
@ -64,7 +64,7 @@ public interface DelegateChunkSet extends IChunkSet {
|
||||
}
|
||||
|
||||
@Override
|
||||
default Map<Short, CompoundTag> getTiles() {
|
||||
default Map<BlockVector3, CompoundTag> getTiles() {
|
||||
return getParent().getTiles();
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
@ -7,14 +7,15 @@ import com.boydti.fawe.beta.IChunkSet;
|
||||
import com.boydti.fawe.util.MathMan;
|
||||
import com.sk89q.jnbt.CompoundTag;
|
||||
import com.sk89q.worldedit.entity.BaseEntity;
|
||||
import com.sk89q.worldedit.entity.Entity;
|
||||
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.block.BaseBlock;
|
||||
import com.sk89q.worldedit.world.block.BlockState;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
public class FallbackChunkGet implements IChunkGet {
|
||||
@ -46,6 +47,40 @@ public class FallbackChunkGet implements IChunkGet {
|
||||
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
|
||||
public boolean trim(boolean aggressive) {
|
||||
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()) {
|
||||
for (Map.Entry<Short, CompoundTag> entry : tiles.entrySet()) {
|
||||
short blockHash = entry.getKey();
|
||||
final int x = (blockHash >> 12 & 0xF) + bx;
|
||||
final int y = (blockHash & 0xFF);
|
||||
final int z = (blockHash >> 8 & 0xF) + bz;
|
||||
extent.setTile(bx + x, y, bz + z, entry.getValue());
|
||||
for (Map.Entry<BlockVector3, CompoundTag> entry : tiles.entrySet()) {
|
||||
BlockVector3 pos = entry.getKey();
|
||||
extent.setTile(bx + pos.getX(), pos.getY(), bz + pos.getZ(), entry.getValue());
|
||||
}
|
||||
|
||||
}
|
||||
@ -128,6 +160,11 @@ public class FallbackChunkGet implements IChunkGet {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public char[] getArray(int layer) {
|
||||
return new char[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
public IBlocks reset() {
|
||||
return null;
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
@ -3,7 +3,6 @@ package com.boydti.fawe.beta.implementation;
|
||||
import com.boydti.fawe.beta.IQueueExtent;
|
||||
|
||||
public interface IQueueWrapper {
|
||||
|
||||
default IQueueExtent wrapQueue(IQueueExtent queue) {
|
||||
return queue;
|
||||
}
|
||||
|
@ -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, ",") + "}";
|
||||
}
|
||||
}
|
@ -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();
|
||||
}
|
||||
}
|
@ -5,12 +5,17 @@ import com.boydti.fawe.beta.IBlocks;
|
||||
import com.boydti.fawe.beta.IChunkGet;
|
||||
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.biome.BiomeTypes;
|
||||
import com.sk89q.worldedit.world.block.BaseBlock;
|
||||
import com.sk89q.worldedit.world.block.BlockState;
|
||||
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;
|
||||
|
||||
public enum NullChunkGet implements IChunkGet {
|
||||
@ -36,6 +41,21 @@ public enum NullChunkGet implements IChunkGet {
|
||||
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
|
||||
public boolean trim(boolean aggressive) {
|
||||
return true;
|
||||
@ -56,6 +76,11 @@ public enum NullChunkGet implements IChunkGet {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public char[] getArray(int layer) {
|
||||
return new char[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
public IBlocks reset() {
|
||||
return null;
|
||||
|
@ -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);
|
||||
// }
|
||||
}
|
@ -2,13 +2,14 @@ package com.boydti.fawe.beta.implementation;
|
||||
|
||||
import com.boydti.fawe.Fawe;
|
||||
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.beta.IQueueExtent;
|
||||
import com.boydti.fawe.beta.Trimable;
|
||||
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.TaskManager;
|
||||
import com.boydti.fawe.wrappers.WorldWrapper;
|
||||
@ -39,8 +40,8 @@ public abstract class QueueHandler implements Trimable, Runnable {
|
||||
private ThreadPoolExecutor blockingExecutor = FaweCache.IMP.newBlockingExecutor();
|
||||
private ConcurrentLinkedQueue<FutureTask> syncTasks = new ConcurrentLinkedQueue<>();
|
||||
|
||||
private Map<World, WeakReference<IChunkCache<IChunkGet>>> chunkCache = new HashMap<>();
|
||||
private IterableThreadLocal<IQueueExtent> queuePool = new IterableThreadLocal<>(QueueHandler.this::create);
|
||||
private Map<World, WeakReference<IChunkCache<IChunkGet>>> chunkGetCache = new HashMap<>();
|
||||
private CleanableThreadLocal<IQueueExtent> queuePool = new CleanableThreadLocal<>(QueueHandler.this::create);
|
||||
/**
|
||||
* Used to calculate elapsed time in milliseconds and ensure block placement doesn't lag the
|
||||
* server
|
||||
@ -198,8 +199,8 @@ public abstract class QueueHandler implements Trimable, Runnable {
|
||||
public IChunkCache<IChunkGet> getOrCreateWorldCache(World world) {
|
||||
world = WorldWrapper.unwrap(world);
|
||||
|
||||
synchronized (chunkCache) {
|
||||
final WeakReference<IChunkCache<IChunkGet>> ref = chunkCache.get(world);
|
||||
synchronized (chunkGetCache) {
|
||||
final WeakReference<IChunkCache<IChunkGet>> ref = chunkGetCache.get(world);
|
||||
if (ref != null) {
|
||||
final IChunkCache<IChunkGet> cached = ref.get();
|
||||
if (cached != null) {
|
||||
@ -207,7 +208,7 @@ public abstract class QueueHandler implements Trimable, Runnable {
|
||||
}
|
||||
}
|
||||
final IChunkCache<IChunkGet> created = new ChunkCache<>(world);
|
||||
chunkCache.put(world, new WeakReference<>(created));
|
||||
chunkGetCache.put(world, new WeakReference<>(created));
|
||||
return created;
|
||||
}
|
||||
}
|
||||
@ -221,18 +222,25 @@ public abstract class QueueHandler implements Trimable, Runnable {
|
||||
public abstract void endSet(boolean parallel);
|
||||
|
||||
public IQueueExtent getQueue(World world) {
|
||||
return getQueue(world, null);
|
||||
}
|
||||
|
||||
public IQueueExtent getQueue(World world, IBatchProcessor processor) {
|
||||
final IQueueExtent queue = queuePool.get();
|
||||
IChunkCache<IChunkGet> cacheGet = getOrCreateWorldCache(world);
|
||||
IChunkCache<IChunkSet> set = null; // TODO cache?
|
||||
queue.init(world, cacheGet, set);
|
||||
if (processor != null) {
|
||||
queue.setProcessor(processor);
|
||||
}
|
||||
return queue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean trim(boolean aggressive) {
|
||||
boolean result = true;
|
||||
synchronized (chunkCache) {
|
||||
final Iterator<Map.Entry<World, WeakReference<IChunkCache<IChunkGet>>>> iter = chunkCache
|
||||
synchronized (chunkGetCache) {
|
||||
final Iterator<Map.Entry<World, WeakReference<IChunkCache<IChunkGet>>>> iter = chunkGetCache
|
||||
.entrySet().iterator();
|
||||
while (iter.hasNext()) {
|
||||
final Map.Entry<World, WeakReference<IChunkCache<IChunkGet>>> entry = iter.next();
|
||||
|
@ -3,6 +3,7 @@ package com.boydti.fawe.beta.implementation;
|
||||
import com.boydti.fawe.Fawe;
|
||||
import com.boydti.fawe.beta.CharFilterBlock;
|
||||
import com.boydti.fawe.beta.ChunkFilterBlock;
|
||||
import com.boydti.fawe.beta.IBatchProcessor;
|
||||
import com.boydti.fawe.beta.IChunk;
|
||||
import com.boydti.fawe.beta.IChunkGet;
|
||||
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.ReferenceChunk;
|
||||
import com.boydti.fawe.config.Settings;
|
||||
import com.boydti.fawe.object.changeset.FaweChangeSet;
|
||||
import com.boydti.fawe.util.MathMan;
|
||||
import com.boydti.fawe.util.MemUtil;
|
||||
import com.google.common.util.concurrent.Futures;
|
||||
import com.sk89q.worldedit.WorldEditException;
|
||||
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 java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.Future;
|
||||
@ -32,7 +32,7 @@ import java.util.concurrent.Future;
|
||||
* <p>
|
||||
* 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)
|
||||
// private static final ConcurrentLinkedQueue<IChunk> CHUNK_POOL = new ConcurrentLinkedQueue<>();
|
||||
@ -86,19 +86,20 @@ public class SingleThreadQueueExtent implements IQueueExtent {
|
||||
* Resets the queue.
|
||||
*/
|
||||
protected synchronized void reset() {
|
||||
if (!initialized) return;
|
||||
if (!this.initialized) return;
|
||||
checkThread();
|
||||
if (!chunks.isEmpty()) {
|
||||
for (IChunk chunk : chunks.values()) {
|
||||
if (!this.chunks.isEmpty()) {
|
||||
for (IChunk chunk : this.chunks.values()) {
|
||||
chunk.recycle();
|
||||
}
|
||||
chunks.clear();
|
||||
this.chunks.clear();
|
||||
}
|
||||
enabledQueue = true;
|
||||
lastChunk = null;
|
||||
lastPair = Long.MAX_VALUE;
|
||||
currentThread = null;
|
||||
initialized = false;
|
||||
this.enabledQueue = true;
|
||||
this.lastChunk = null;
|
||||
this.lastPair = Long.MAX_VALUE;
|
||||
this.currentThread = null;
|
||||
this.initialized = false;
|
||||
this.setProcessor(EmptyBatchProcessor.INSTANCE);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -118,9 +119,27 @@ public class SingleThreadQueueExtent implements IQueueExtent {
|
||||
}
|
||||
this.cacheGet = get;
|
||||
this.cacheSet = set;
|
||||
this.setProcessor(EmptyBatchProcessor.INSTANCE);
|
||||
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
|
||||
public int size() {
|
||||
return chunks.size() + submissions.size();
|
||||
@ -165,7 +184,6 @@ public class SingleThreadQueueExtent implements IQueueExtent {
|
||||
|
||||
@Override
|
||||
public synchronized boolean trim(boolean aggressive) {
|
||||
// TODO trim individial chunk sections
|
||||
cacheGet.trim(aggressive);
|
||||
cacheSet.trim(aggressive);
|
||||
if (Thread.currentThread() == currentThread) {
|
||||
@ -200,7 +218,7 @@ public class SingleThreadQueueExtent implements IQueueExtent {
|
||||
}
|
||||
|
||||
@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;
|
||||
if (pair == lastPair) {
|
||||
return lastChunk;
|
||||
@ -311,16 +329,4 @@ public class SingleThreadQueueExtent implements IQueueExtent {
|
||||
public ChunkFilterBlock initFilterBlock() {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
@ -38,27 +38,31 @@ public class BitSetBlocks implements IChunkSet {
|
||||
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
|
||||
public boolean 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
|
||||
public boolean setTile(int x, int y, int z, CompoundTag tile) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setBiome(BlockVector2 position, BiomeType biome) {
|
||||
return setBiome(position.getX(),0, position.getZ(), biome);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setEntity(CompoundTag tag) {
|
||||
}
|
||||
@ -112,7 +116,7 @@ public class BitSetBlocks implements IChunkSet {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<Short, CompoundTag> getTiles() {
|
||||
public Map<BlockVector3, CompoundTag> getTiles() {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -2,6 +2,14 @@ package com.boydti.fawe.beta.implementation.blocks;
|
||||
|
||||
import com.boydti.fawe.beta.IBlocks;
|
||||
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 {
|
||||
|
||||
@ -81,6 +89,16 @@ public class CharBlocks implements IBlocks {
|
||||
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) {
|
||||
final int layer = y >> 4;
|
||||
final int index = (y & 15) << 8 | z << 4 | x;
|
||||
|
@ -3,6 +3,7 @@ package com.boydti.fawe.beta.implementation.blocks;
|
||||
import com.boydti.fawe.FaweCache;
|
||||
import com.boydti.fawe.beta.IChunkSet;
|
||||
import com.boydti.fawe.config.Settings;
|
||||
import com.boydti.fawe.object.collection.BlockVector3ChunkMap;
|
||||
import com.boydti.fawe.util.MathMan;
|
||||
import com.sk89q.jnbt.CompoundTag;
|
||||
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.BlockStateHolder;
|
||||
import com.sk89q.worldedit.world.block.BlockTypes;
|
||||
import java.util.HashMap;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
@ -25,7 +27,7 @@ public class CharSetBlocks extends CharBlocks implements IChunkSet {
|
||||
}
|
||||
|
||||
public BiomeType[] biomes;
|
||||
public HashMap<Short, CompoundTag> tiles;
|
||||
public BlockVector3ChunkMap<CompoundTag> tiles;
|
||||
public HashSet<CompoundTag> entities;
|
||||
public HashSet<UUID> entityRemoves;
|
||||
|
||||
@ -36,29 +38,24 @@ public class CharSetBlocks extends CharBlocks implements IChunkSet {
|
||||
POOL.offer(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public char[] getArray(int layer) {
|
||||
return sections[layer].get(this, layer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BiomeType[] getBiomes() {
|
||||
return biomes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<Short, CompoundTag> getTiles() {
|
||||
return tiles;
|
||||
public Map<BlockVector3, CompoundTag> getTiles() {
|
||||
return tiles == null ? Collections.emptyMap() : tiles;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<CompoundTag> getEntities() {
|
||||
return entities;
|
||||
return entities == null ? Collections.emptySet() : entities;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<UUID> getEntityRemoves() {
|
||||
return entityRemoves;
|
||||
return entityRemoves == null ? Collections.emptySet() : entityRemoves;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -78,9 +75,16 @@ public class CharSetBlocks extends CharBlocks implements IChunkSet {
|
||||
@Override
|
||||
public boolean setBlock(int x, int y, int z, BlockStateHolder holder) {
|
||||
set(x, y, z, holder.getOrdinalChar());
|
||||
holder.applyTileEntity(this, x, y, z);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBlocks(int layer, char[] data) {
|
||||
this.blocks[layer] = data;
|
||||
this.sections[layer] = data == null ? EMPTY : FULL;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends BlockStateHolder<T>> boolean setBlock(BlockVector3 position, T block)
|
||||
throws WorldEditException {
|
||||
@ -90,10 +94,9 @@ public class CharSetBlocks extends CharBlocks implements IChunkSet {
|
||||
@Override
|
||||
public boolean setTile(int x, int y, int z, CompoundTag tile) {
|
||||
if (tiles == null) {
|
||||
tiles = new HashMap<>();
|
||||
tiles = new BlockVector3ChunkMap<CompoundTag>();
|
||||
}
|
||||
final short pair = MathMan.tripleBlockCoord(x, y, z);
|
||||
tiles.put(pair, tile);
|
||||
tiles.put(x, y, z, tile);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -9,18 +9,19 @@ import com.boydti.fawe.beta.IChunk;
|
||||
import com.boydti.fawe.beta.IChunkGet;
|
||||
import com.boydti.fawe.beta.IChunkSet;
|
||||
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.sk89q.jnbt.CompoundTag;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
import com.sk89q.worldedit.regions.Region;
|
||||
import com.sk89q.worldedit.world.biome.BiomeType;
|
||||
import com.sk89q.worldedit.world.block.BaseBlock;
|
||||
import com.sk89q.worldedit.world.block.BlockState;
|
||||
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.function.Supplier;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
@ -34,10 +35,10 @@ public class ChunkHolder<T extends Future<T>> implements IChunk {
|
||||
return POOL.poll();
|
||||
}
|
||||
|
||||
private IChunkGet get;
|
||||
private IChunkSet set;
|
||||
private IBlockDelegate delegate;
|
||||
private IQueueExtent extent;
|
||||
private IChunkGet chunkExisting; // The existing chunk (e.g. a clipboard, or the world, before changes)
|
||||
private IChunkSet chunkSet; // The blocks to be set to the chunkExisting
|
||||
private IBlockDelegate delegate; // delegate handles the abstraction of the chunk layers
|
||||
private IQueueExtent extent; // the parent queue extent which has this chunk
|
||||
private int chunkX;
|
||||
private int chunkZ;
|
||||
|
||||
@ -73,36 +74,63 @@ public class ChunkHolder<T extends Future<T>> implements IChunk {
|
||||
return getOrCreateGet().load(layer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompoundTag getEntity(UUID uuid) {
|
||||
return delegate.get(this).getEntity(uuid);
|
||||
}
|
||||
|
||||
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
|
||||
public boolean setBiome(ChunkHolder chunk, int x, int y, int z,
|
||||
BiomeType biome) {
|
||||
return chunk.set.setBiome(x, y, z, biome);
|
||||
return chunk.chunkSet.setBiome(x, y, z, biome);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setBlock(ChunkHolder chunk, int x, int y, int z,
|
||||
BlockStateHolder block) {
|
||||
return chunk.set.setBlock(x, y, z, block);
|
||||
return chunk.chunkSet.setBlock(x, y, z, block);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BiomeType getBiome(ChunkHolder chunk, int x, int z) {
|
||||
return chunk.get.getBiomeType(x, z);
|
||||
return chunk.chunkExisting.getBiomeType(x, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
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
|
||||
public BaseBlock getFullBlock(ChunkHolder chunk, int x, int y,
|
||||
int z) {
|
||||
return chunk.get.getFullBlock(x, y, z);
|
||||
return chunk.chunkExisting.getFullBlock(x, y, z);
|
||||
}
|
||||
};
|
||||
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
|
||||
public boolean setBiome(ChunkHolder chunk, int x, int y, int z,
|
||||
BiomeType biome) {
|
||||
@ -121,31 +149,43 @@ public class ChunkHolder<T extends Future<T>> implements IChunk {
|
||||
|
||||
@Override
|
||||
public BiomeType getBiome(ChunkHolder chunk, int x, int z) {
|
||||
return chunk.get.getBiomeType(x, z);
|
||||
return chunk.chunkExisting.getBiomeType(x, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
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
|
||||
public BaseBlock getFullBlock(ChunkHolder chunk, int x, int y,
|
||||
int z) {
|
||||
return chunk.get.getFullBlock(x, y, z);
|
||||
return chunk.chunkExisting.getFullBlock(x, y, z);
|
||||
}
|
||||
};
|
||||
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
|
||||
public boolean setBiome(ChunkHolder chunk, int x, int y, int z,
|
||||
BiomeType biome) {
|
||||
return chunk.set.setBiome(x, y, z, biome);
|
||||
return chunk.chunkSet.setBiome(x, y, z, biome);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setBlock(ChunkHolder chunk, int x, int y, int z,
|
||||
BlockStateHolder block) {
|
||||
return chunk.set.setBlock(x, y, z, block);
|
||||
return chunk.chunkSet.setBlock(x, y, z, block);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -171,6 +211,20 @@ public class ChunkHolder<T extends Future<T>> implements IChunk {
|
||||
}
|
||||
};
|
||||
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
|
||||
public boolean setBiome(ChunkHolder chunk, int x, int y, int z,
|
||||
BiomeType biome) {
|
||||
@ -221,9 +275,24 @@ public class ChunkHolder<T extends Future<T>> implements IChunk {
|
||||
.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
|
||||
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
|
||||
@ -250,42 +319,42 @@ public class ChunkHolder<T extends Future<T>> implements IChunk {
|
||||
|
||||
@Override
|
||||
public boolean trim(boolean aggressive) {
|
||||
if (set != null) {
|
||||
final boolean result = set.trim(aggressive);
|
||||
if (chunkSet != null) {
|
||||
final boolean result = chunkSet.trim(aggressive);
|
||||
if (result) {
|
||||
delegate = NULL;
|
||||
get = null;
|
||||
set = null;
|
||||
chunkExisting = null;
|
||||
chunkSet = null;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (aggressive) {
|
||||
get = null;
|
||||
chunkExisting = null;
|
||||
if (delegate == BOTH) {
|
||||
delegate = SET;
|
||||
} else if (delegate == GET) {
|
||||
delegate = NULL;
|
||||
}
|
||||
} else {
|
||||
get.trim(false);
|
||||
chunkExisting.trim(false);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
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
|
||||
*/
|
||||
public final IChunkGet getOrCreateGet() {
|
||||
if (get == null) {
|
||||
get = newWrappedGet();
|
||||
if (chunkExisting == null) {
|
||||
chunkExisting = newWrappedGet();
|
||||
}
|
||||
return get;
|
||||
return chunkExisting;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -293,10 +362,10 @@ public class ChunkHolder<T extends Future<T>> implements IChunk {
|
||||
* @return
|
||||
*/
|
||||
public final IChunkSet getOrCreateSet() {
|
||||
if (set == null) {
|
||||
set = newWrappedSet();
|
||||
if (chunkSet == null) {
|
||||
chunkSet = newWrappedSet();
|
||||
}
|
||||
return set;
|
||||
return chunkSet;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -324,31 +393,39 @@ public class ChunkHolder<T extends Future<T>> implements IChunk {
|
||||
this.extent = extent;
|
||||
this.chunkX = chunkX;
|
||||
this.chunkZ = chunkZ;
|
||||
if (set != null) {
|
||||
set.reset();
|
||||
if (chunkSet != null) {
|
||||
chunkSet.reset();
|
||||
delegate = SET;
|
||||
} else {
|
||||
delegate = NULL;
|
||||
}
|
||||
get = null;
|
||||
chunkExisting = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized T call() {
|
||||
if (get != null && set != null) {
|
||||
return getOrCreateGet().call(getOrCreateSet(), this::recycle);
|
||||
if (chunkSet != null) {
|
||||
return this.call(chunkSet, this::recycle);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T call(IChunkSet set, Runnable finalize) {
|
||||
if (get != null && set != null) {
|
||||
return getOrCreateGet().call(set, finalize);
|
||||
if (set != null) {
|
||||
IChunkGet get = getOrCreateGet();
|
||||
set = getExtent().processBatch(this, get, set);
|
||||
if (set != null) {
|
||||
return get.call(set, finalize);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the extent this chunk is in
|
||||
* @return
|
||||
*/
|
||||
public IQueueExtent getExtent() {
|
||||
return extent;
|
||||
}
|
||||
@ -389,6 +466,8 @@ public class ChunkHolder<T extends Future<T>> implements IChunk {
|
||||
}
|
||||
|
||||
public interface IBlockDelegate {
|
||||
IChunkGet get(ChunkHolder chunk);
|
||||
IChunkSet set(ChunkHolder chunk);
|
||||
|
||||
boolean setBiome(ChunkHolder chunk, int x, int y, int z,
|
||||
BiomeType biome);
|
||||
|
@ -2,8 +2,15 @@ package com.boydti.fawe.beta.implementation.holder;
|
||||
|
||||
import com.boydti.fawe.beta.IChunk;
|
||||
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.WeakReference;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* A {@link ReferenceChunk} using {@link WeakReference} to hold the chunk.
|
||||
|
@ -43,8 +43,8 @@ public class CFICommand extends CommandProcessor<Object, Object> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int process(InjectedValueAccess context, List<String> args, Object result) {
|
||||
return 0;
|
||||
public Object process(InjectedValueAccess context, List<String> args, Object result) {
|
||||
return result;
|
||||
}
|
||||
|
||||
private List<String> dispatch(Player player, CFISettings settings, List<String> args, InjectedValueAccess context) {
|
||||
|
@ -67,13 +67,13 @@ public abstract class CommandProcessor<I, O> implements CommandManager {
|
||||
}
|
||||
|
||||
@Override
|
||||
public final int execute(InjectedValueAccess context, List<String> args) {
|
||||
public final Object execute(InjectedValueAccess context, List<String> args) {
|
||||
args = preprocess(context, args);
|
||||
if (args != null) {
|
||||
Object result = parent.execute(context, args);
|
||||
return process(context, args, result); // TODO NOT IMPLEMENTED (recompile piston)
|
||||
} 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 int process(InjectedValueAccess context, List<String> args, Object result);
|
||||
public abstract Object process(InjectedValueAccess context, List<String> args, Object result);
|
||||
}
|
||||
|
@ -12,23 +12,17 @@ import com.sk89q.worldedit.internal.registry.InputParser;
|
||||
import java.util.*;
|
||||
|
||||
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);
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public PlatformCommandManager getPlatform() {
|
||||
return PlatformCommandManager.getInstance();
|
||||
}
|
||||
|
||||
public Class<T> getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public Collection<T> parse(String input, Actor actor) {
|
||||
return getPlatform().parse(getType(), "pattern " + input, actor);
|
||||
public T parse(String input, Actor actor) {
|
||||
return getPlatform().parse("pattern " + input, actor);
|
||||
}
|
||||
|
||||
public T catchSuggestion(String currentInput, String nextInput, ParserContext context) throws InputParseException {
|
||||
|
@ -24,6 +24,7 @@ import com.sk89q.worldedit.registry.state.PropertyKey;
|
||||
import com.sk89q.worldedit.util.Direction;
|
||||
import com.sk89q.worldedit.world.biome.BiomeType;
|
||||
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.BlockStateHolder;
|
||||
import com.sk89q.worldedit.world.block.BlockType;
|
||||
@ -203,24 +204,7 @@ public class SchematicStreamer extends NBTStreamer {
|
||||
@Override
|
||||
public <B extends BlockStateHolder<B>> void run(int x, int y, int z, B block) {
|
||||
BlockType type = block.getBlockType();
|
||||
switch (type.getInternalId()) {
|
||||
case BlockID.ACACIA_STAIRS:
|
||||
case BlockID.BIRCH_STAIRS:
|
||||
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:
|
||||
if (BlockCategories.STAIRS.contains(type)) {
|
||||
Object half = block.getState(PropertyKey.HALF);
|
||||
Direction facing = block.getState(PropertyKey.FACING);
|
||||
|
||||
@ -269,8 +253,7 @@ public class SchematicStreamer extends NBTStreamer {
|
||||
return;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
} else {
|
||||
int group = group(type);
|
||||
if (group == -1) return;
|
||||
BlockStateHolder set = block;
|
||||
@ -289,7 +272,6 @@ public class SchematicStreamer extends NBTStreamer {
|
||||
}
|
||||
|
||||
if (set != block) fc.setBlock(x, y, z, set);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}, false);
|
||||
|
@ -160,4 +160,9 @@ public class HistoryExtent extends AbstractDelegateExtent {
|
||||
return this.entity.setLocation(location);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Extent disableHistory() {
|
||||
return getExtent();
|
||||
}
|
||||
}
|
||||
|
@ -1,62 +1,15 @@
|
||||
package com.boydti.fawe.object;
|
||||
|
||||
import com.sk89q.worldedit.entity.MapMetadatable;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
public class Metadatable {
|
||||
|
||||
public class Metadatable implements MapMetadatable {
|
||||
private final ConcurrentHashMap<String, Object> meta = new ConcurrentHashMap<>();
|
||||
|
||||
/**
|
||||
* Set some session only metadata for the player
|
||||
*
|
||||
* @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);
|
||||
@Override
|
||||
public Map<String, Object> getRawMeta() {
|
||||
return meta;
|
||||
}
|
||||
}
|
||||
|
@ -62,7 +62,7 @@ public class BrushSettings {
|
||||
if (constructor == null) {
|
||||
return new BrushSettings();
|
||||
}
|
||||
BrushSettings bs = (BrushSettings) manager.parse(BrushSettings.class, constructor, player);
|
||||
BrushSettings bs = manager.parse(constructor, player);
|
||||
bs.constructor.put(SettingType.BRUSH, constructor);
|
||||
if (settings.containsKey(SettingType.PERMISSIONS.name())) {
|
||||
bs.permissions.addAll((Collection<? extends String>) settings.get(SettingType.PERMISSIONS.name()));
|
||||
|
@ -1,6 +1,9 @@
|
||||
package com.boydti.fawe.object.brush;
|
||||
|
||||
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.MaxChangedBlocksException;
|
||||
import com.sk89q.worldedit.command.tool.brush.Brush;
|
||||
@ -39,9 +42,10 @@ public class CommandBrush implements Brush {
|
||||
position = position.add(face.getDirection().toBlockPoint());
|
||||
}
|
||||
player.setSelection(selector);
|
||||
PlayerWrapper wePlayer = new SilentPlayerWrapper(new LocationMaskedPlayerWrapper(player, new Location(player.getExtent(), position.toVector3())));
|
||||
List<String> cmds = StringMan.split(replaced, ';');
|
||||
for (String cmd : cmds) {
|
||||
CommandEvent event = new CommandEvent(player, cmd);
|
||||
CommandEvent event = new CommandEvent(wePlayer, cmd);
|
||||
PlatformCommandManager.getInstance().handleCommandOnCurrentThread(event);
|
||||
}
|
||||
}
|
||||
|
@ -18,14 +18,25 @@ import java.util.Arrays;
|
||||
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 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
|
||||
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,
|
||||
BlockVector3 target, double size) {
|
||||
public void erosion(final EditSession es, int erodeFaces, int erodeRec, int fillFaces, int fillRec, BlockVector3 target, double size) {
|
||||
int brushSize = (int) size + 1;
|
||||
int brushSizeSquared = (int) (size * size);
|
||||
int dimension = brushSize * 2 + 1;
|
||||
@ -55,7 +66,7 @@ public class ErodeBrush implements Brush {
|
||||
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);
|
||||
swap++;
|
||||
}
|
||||
|
@ -47,7 +47,7 @@ public class InspectBrush extends BrushTool implements DoubleActionTraceTool {
|
||||
}
|
||||
|
||||
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) {
|
||||
Location face = player.getBlockTraceFace(range, true);
|
||||
return face.add(face.getDirection());
|
||||
|
@ -6,8 +6,10 @@ import com.sk89q.worldedit.function.pattern.Pattern;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
|
||||
public class RaiseBrush extends ErodeBrush {
|
||||
@Override
|
||||
public void build(EditSession editSession, BlockVector3 position, Pattern pattern, double size) throws MaxChangedBlocksException {
|
||||
this.erosion(editSession, 6, 0, 1, position, size);
|
||||
public RaiseBrush() {
|
||||
this(6, 0, 1, 1);
|
||||
}
|
||||
public RaiseBrush(int erodeFaces, int erodeRec, int fillFaces, int fillRec) {
|
||||
super(2, 1, 5, 1);
|
||||
}
|
||||
}
|
||||
|
@ -31,7 +31,7 @@ public class SplineBrush implements Brush, ResettableTool {
|
||||
private final Player player;
|
||||
private BlockVector3 position;
|
||||
|
||||
public SplineBrush(Player player, LocalSession session) {
|
||||
public SplineBrush(Player player) {
|
||||
this.player = player;
|
||||
this.positionSets = new ArrayList<>();
|
||||
}
|
||||
|
@ -1928,11 +1928,6 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setBiome(BlockVector2 position, BiomeType biome) {
|
||||
return setBiome(position.getX(), 0, position.getBlockZ(), biome);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBlockLightLevel(BlockVector3 position) {
|
||||
return 0;
|
||||
|
@ -1,6 +1,6 @@
|
||||
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.util.MainUtil;
|
||||
import com.sk89q.worldedit.extent.Extent;
|
||||
@ -209,8 +209,8 @@ public abstract class MCAWriter implements Extent {
|
||||
}
|
||||
pool.awaitQuiescence(Long.MAX_VALUE, TimeUnit.MILLISECONDS);
|
||||
pool.shutdown();
|
||||
IterableThreadLocal.clean(byteStore1);
|
||||
IterableThreadLocal.clean(byteStore2);
|
||||
IterableThreadLocal.clean(deflateStore);
|
||||
CleanableThreadLocal.clean(byteStore1);
|
||||
CleanableThreadLocal.clean(byteStore2);
|
||||
CleanableThreadLocal.clean(deflateStore);
|
||||
}
|
||||
}
|
||||
|
@ -3,8 +3,13 @@ package com.boydti.fawe.object.changeset;
|
||||
import com.boydti.fawe.Fawe;
|
||||
import com.boydti.fawe.FaweAPI;
|
||||
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.logging.rollback.RollbackOptimizedHistory;
|
||||
import com.boydti.fawe.object.HistoryExtent;
|
||||
import com.boydti.fawe.util.EditSessionBuilder;
|
||||
import com.boydti.fawe.util.MainUtil;
|
||||
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.worldedit.EditSession;
|
||||
import com.sk89q.worldedit.entity.Player;
|
||||
import com.sk89q.worldedit.extent.Extent;
|
||||
import com.sk89q.worldedit.extent.inventory.BlockBag;
|
||||
import com.sk89q.worldedit.history.change.BlockChange;
|
||||
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.biome.BiomeType;
|
||||
import com.sk89q.worldedit.world.block.BaseBlock;
|
||||
import com.sk89q.worldedit.world.block.BlockState;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
public abstract class FaweChangeSet implements ChangeSet {
|
||||
public abstract class FaweChangeSet implements ChangeSet, IBatchProcessor {
|
||||
|
||||
private World world;
|
||||
private final String worldName;
|
||||
private final boolean mainThread;
|
||||
private final int layers;
|
||||
protected AtomicInteger waitingCombined = new AtomicInteger(0);
|
||||
protected AtomicInteger waitingAsync = new AtomicInteger(0);
|
||||
|
||||
@ -51,15 +59,11 @@ public abstract class FaweChangeSet implements ChangeSet {
|
||||
|
||||
public FaweChangeSet(String world) {
|
||||
this.worldName = world;
|
||||
this.mainThread = Fawe.get() == null || Fawe.isMainThread();
|
||||
this.layers = FaweCache.IMP.CHUNK_LAYERS;
|
||||
}
|
||||
|
||||
public FaweChangeSet(World world) {
|
||||
this.world = world;
|
||||
this.worldName = world.getName();
|
||||
this.mainThread = Fawe.isMainThread();
|
||||
this.layers = this.world.getMaxY() + 1 >> 4;
|
||||
}
|
||||
|
||||
public String getWorldName() {
|
||||
@ -124,6 +128,92 @@ public abstract class FaweChangeSet implements ChangeSet {
|
||||
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 addTileRemove(CompoundTag tag);
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
@ -18,14 +18,12 @@ import org.jetbrains.annotations.NotNull;
|
||||
* @param <T>
|
||||
*/
|
||||
public class AdaptedSetCollection<T, V> implements Set<V> {
|
||||
private final Function<T, V> adapter;
|
||||
private final Collection<V> adapted;
|
||||
private final Collection<T> original;
|
||||
|
||||
public AdaptedSetCollection(Collection<T> collection, Function<T, V> adapter) {
|
||||
this.original = collection;
|
||||
this.adapted = Collections2.transform(collection, adapter);
|
||||
this.adapter = adapter;
|
||||
}
|
||||
|
||||
public Collection<T> getOriginal() {
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
@ -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();
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
@ -1,19 +1,9 @@
|
||||
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.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.concurrent.Callable;
|
||||
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;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
public IterableThreadLocal(Supplier<T> supplier, Function<T, T> modifier) {
|
||||
this.supplier = supplier;
|
||||
}
|
||||
|
||||
public IterableThreadLocal(Supplier<T> supplier, Consumer<T> modifier) {
|
||||
this.supplier = supplier;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final T initialValue() {
|
||||
T value = init();
|
||||
@ -55,82 +37,18 @@ public class IterableThreadLocal<T> extends ThreadLocal<T> implements Iterable<T
|
||||
public void clean() {
|
||||
if (!allValues.isEmpty()) {
|
||||
synchronized (this) {
|
||||
IterableThreadLocal.clean(this);
|
||||
CleanableThreadLocal.clean(this);
|
||||
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() {
|
||||
return Collections.unmodifiableCollection(allValues);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void finalize() throws Throwable {
|
||||
clean(this);
|
||||
CleanableThreadLocal.clean(this);
|
||||
super.finalize();
|
||||
}
|
||||
}
|
||||
|
@ -869,6 +869,10 @@ public final class MemBlockSet extends BlockSet {
|
||||
return true;
|
||||
}
|
||||
|
||||
public void reset(int layer) {
|
||||
this.rows[layer] = NULL_ROW_Y;
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
for (int i = 0; i < FaweCache.IMP.CHUNK_LAYERS; i++) rows[i] = NULL_ROW_Y;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
@ -1,8 +1,13 @@
|
||||
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.exception.FaweException;
|
||||
import com.boydti.fawe.util.ExtentTraverser;
|
||||
import com.boydti.fawe.util.WEManager;
|
||||
import com.sk89q.jnbt.CompoundTag;
|
||||
import com.sk89q.worldedit.WorldEditException;
|
||||
import com.sk89q.worldedit.entity.BaseEntity;
|
||||
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.BlockTypes;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public abstract class FaweRegionExtent extends ResettableExtent {
|
||||
public abstract class FaweRegionExtent extends ResettableExtent implements IBatchProcessor {
|
||||
private final FaweLimit limit;
|
||||
|
||||
/**
|
||||
@ -39,7 +47,20 @@ public abstract class FaweRegionExtent extends ResettableExtent {
|
||||
public abstract Collection<Region> getRegions();
|
||||
|
||||
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
|
||||
|
@ -1,14 +1,24 @@
|
||||
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.RegionWrapper;
|
||||
import com.sk89q.jnbt.CompoundTag;
|
||||
import com.sk89q.worldedit.extent.Extent;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
import com.sk89q.worldedit.regions.Region;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
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 int lastY = -1;
|
||||
@ -38,4 +48,12 @@ public class HeightBoundExtent extends FaweRegionExtent {
|
||||
public Collection<Region> getRegions() {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -1,13 +1,20 @@
|
||||
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.sk89q.worldedit.extent.Extent;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
import com.sk89q.worldedit.regions.Region;
|
||||
import com.sk89q.worldedit.regions.RegionIntersection;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
|
||||
public class MultiRegionExtent extends FaweRegionExtent {
|
||||
|
||||
private final RegionIntersection intersection;
|
||||
private Region region;
|
||||
private final Region[] regions;
|
||||
private int index;
|
||||
@ -22,6 +29,7 @@ public class MultiRegionExtent extends FaweRegionExtent {
|
||||
this.index = 0;
|
||||
this.region = regions[0];
|
||||
this.regions = regions;
|
||||
this.intersection = new RegionIntersection(Arrays.asList(regions));
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -64,4 +72,9 @@ public class MultiRegionExtent extends FaweRegionExtent {
|
||||
public Collection<Region> getRegions() {
|
||||
return Arrays.asList(regions);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IChunkSet processBatch(IChunk chunk, IChunkGet get, IChunkSet set) {
|
||||
return intersection.processBatch(chunk, get, set);
|
||||
}
|
||||
}
|
||||
|
@ -32,20 +32,26 @@ public class MultiTransform extends RandomTransform {
|
||||
|
||||
@Override
|
||||
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))
|
||||
.reduce(false, (a, b) -> a || b);
|
||||
// don't use streams for each block place, it'd be incredibly slow
|
||||
boolean result = false;
|
||||
for (AbstractDelegateExtent extent : extents) result |= extent.setBlock(x, y, z, block);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends BlockStateHolder<T>> boolean setBlock(BlockVector3 location, T block) throws WorldEditException {
|
||||
return Arrays.stream(extents).map(extent -> extent.setBlock(location, block))
|
||||
.reduce(false, (a, b) -> a || b);
|
||||
// don't use streams for each block place, it'd be incredibly slow
|
||||
boolean result = false;
|
||||
for (AbstractDelegateExtent extent : extents) result |= extent.setBlock(location, block);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setBiome(BlockVector2 position, BiomeType biome) {
|
||||
return Arrays.stream(extents).map(extent -> extent.setBiome(position, biome))
|
||||
.reduce(false, (a, b) -> a || b);
|
||||
// don't use streams for each block place, it'd be incredibly slow
|
||||
boolean result = false;
|
||||
for (AbstractDelegateExtent extent : extents) result |= extent.setBiome(position, biome);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
@ -1,5 +1,8 @@
|
||||
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.object.FaweLimit;
|
||||
import com.boydti.fawe.object.exception.FaweException;
|
||||
@ -321,4 +324,9 @@ public class NullExtent extends FaweRegionExtent {
|
||||
public List<Countable<BlockState>> getBlockDistributionWithData(Region region) {
|
||||
throw reason;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IChunkSet processBatch(IChunk chunk, IChunkGet get, IChunkSet set) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@ -19,12 +19,12 @@ import com.sk89q.worldedit.world.block.BlockTypes;
|
||||
|
||||
public class ProcessedWEExtent extends AbstractDelegateExtent {
|
||||
private final FaweLimit limit;
|
||||
private final AbstractDelegateExtent extent;
|
||||
private final Extent extent;
|
||||
|
||||
public ProcessedWEExtent(Extent parent, FaweLimit limit) {
|
||||
super(parent);
|
||||
this.limit = limit;
|
||||
this.extent = (AbstractDelegateExtent) parent;
|
||||
this.extent = parent;
|
||||
}
|
||||
|
||||
public void setLimit(FaweLimit other) {
|
||||
|
@ -1,5 +1,8 @@
|
||||
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.sk89q.worldedit.extent.Extent;
|
||||
import com.sk89q.worldedit.regions.Region;
|
||||
@ -35,4 +38,9 @@ public class SingleRegionExtent extends FaweRegionExtent {
|
||||
public Collection<Region> getRegions() {
|
||||
return Collections.singletonList(region);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IChunkSet processBatch(IChunk chunk, IChunkGet get, IChunkSet set) {
|
||||
return region.processBatch(chunk, get, set);
|
||||
}
|
||||
}
|
||||
|
@ -123,4 +123,10 @@ public class FuzzyRegion extends AbstractRegion {
|
||||
public void setExtent(EditSession 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;
|
||||
}
|
||||
}
|
||||
|
@ -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.CommandDeclaration;
|
@ -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.TaskManager;
|
@ -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.FaweAPI;
|
@ -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.object.clipboard.ReadOnlyClipboard;
|
@ -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.github.intellectualsites.plotsquared.commands.CommandDeclaration;
|
@ -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.plot.commands.CommandCategory;
|
@ -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;
|
||||
|
@ -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.FaweAPI;
|
||||
import com.boydti.fawe.util.EditSessionBuilder;
|
||||
import com.boydti.fawe.util.TaskManager;
|
||||
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.sk89q.worldedit.EditSession;
|
||||
import com.sk89q.worldedit.WorldEdit;
|
||||
import com.sk89q.worldedit.bukkit.BukkitAdapter;
|
||||
import com.sk89q.worldedit.extension.platform.Capability;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
import com.sk89q.worldedit.regions.CuboidRegion;
|
||||
@ -32,7 +32,6 @@ import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
import org.bukkit.Bukkit;
|
||||
|
||||
@CommandDeclaration(
|
||||
command = "generatebiome",
|
||||
@ -74,7 +73,7 @@ public class PlotSetBiome extends Command {
|
||||
}
|
||||
plot.addRunning();
|
||||
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)
|
||||
.checkMemory(false)
|
||||
.allowedRegionsEverywhere()
|
@ -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.FaweAPI;
|
||||
import com.boydti.fawe.regions.FaweMask;
|
||||
import com.boydti.fawe.regions.FaweMaskManager;
|
||||
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.block.GlobalBlockQueue;
|
||||
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.math.BlockVector3;
|
||||
import com.sk89q.worldedit.regions.AbstractRegion;
|
||||
import com.sk89q.worldedit.regions.CuboidRegion;
|
||||
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.List;
|
||||
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 PlotSquaredFeature() {
|
||||
@ -138,42 +141,11 @@ public class PlotSquaredFeature extends FaweMaskManager {
|
||||
if (regions.size() == 1) {
|
||||
maskedRegion = new CuboidRegion(pos1, pos2);
|
||||
} else {
|
||||
maskedRegion = new AbstractRegion(BukkitAdapter.adapt(Bukkit.getWorld(area.worldname))) {
|
||||
@Override
|
||||
public BlockVector3 getMinimumPoint() {
|
||||
return pos1;
|
||||
}
|
||||
|
||||
@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());
|
||||
}
|
||||
};
|
||||
World world = FaweAPI.getWorld(area.worldname);
|
||||
List<Region> weRegions = regions.stream()
|
||||
.map(r -> new CuboidRegion(world, BlockVector3.at(r.minX, r.minY, r.minZ), BlockVector3.at(r.maxX, r.maxY, r.maxZ)))
|
||||
.collect(Collectors.toList());
|
||||
maskedRegion = new RegionIntersection(world, weRegions);
|
||||
}
|
||||
|
||||
return new FaweMask(maskedRegion) {
|
@ -1,40 +1,50 @@
|
||||
package com.boydti.fawe.util;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
import com.boydti.fawe.Fawe;
|
||||
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.Settings;
|
||||
import com.boydti.fawe.logging.LoggingChangeSet;
|
||||
import com.boydti.fawe.logging.rollback.RollbackOptimizedHistory;
|
||||
import com.boydti.fawe.object.FaweLimit;
|
||||
import com.boydti.fawe.object.HistoryExtent;
|
||||
import com.boydti.fawe.object.NullChangeSet;
|
||||
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.FaweChangeSet;
|
||||
import com.boydti.fawe.object.changeset.MemoryOptimizedHistory;
|
||||
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.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.WorldEdit;
|
||||
import com.sk89q.worldedit.entity.Player;
|
||||
import com.sk89q.worldedit.event.extent.EditSessionEvent;
|
||||
import com.sk89q.worldedit.extent.AbstractDelegateExtent;
|
||||
import com.sk89q.worldedit.extent.Extent;
|
||||
import com.sk89q.worldedit.extent.inventory.BlockBag;
|
||||
import com.sk89q.worldedit.regions.Region;
|
||||
import com.sk89q.worldedit.util.eventbus.EventBus;
|
||||
import com.sk89q.worldedit.world.World;
|
||||
import java.util.UUID;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import java.util.UUID;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
public class EditSessionBuilder {
|
||||
private World world;
|
||||
private String worldName;
|
||||
private Extent extent;
|
||||
private Player player;
|
||||
private FaweLimit limit;
|
||||
private FaweChangeSet changeSet;
|
||||
@ -45,6 +55,7 @@ public class EditSessionBuilder {
|
||||
private Boolean combineStages;
|
||||
private EventBus eventBus;
|
||||
private BlockBag blockBag;
|
||||
private boolean threaded = true;
|
||||
private EditSessionEvent event;
|
||||
|
||||
/**
|
||||
@ -65,14 +76,12 @@ public class EditSessionBuilder {
|
||||
public EditSessionBuilder(@Nonnull World world) {
|
||||
checkNotNull(world);
|
||||
this.world = world;
|
||||
this.extent = world;
|
||||
this.worldName = Fawe.imp().getWorldName(world);
|
||||
}
|
||||
|
||||
public EditSessionBuilder(World world, String worldName) {
|
||||
if (world == null && worldName == null) throw new NullPointerException("Both world and worldname cannot be null");
|
||||
this.world = world;
|
||||
this.extent = world;
|
||||
this.worldName = worldName;
|
||||
}
|
||||
|
||||
@ -84,12 +93,12 @@ public class EditSessionBuilder {
|
||||
|
||||
public EditSessionBuilder player(@Nullable Player player) {
|
||||
this.player = player;
|
||||
return this;
|
||||
return setDirty();
|
||||
}
|
||||
|
||||
public EditSessionBuilder limit(@Nullable FaweLimit limit) {
|
||||
this.limit = limit;
|
||||
return this;
|
||||
return setDirty();
|
||||
}
|
||||
|
||||
public EditSessionBuilder limitUnlimited() {
|
||||
@ -101,12 +110,12 @@ public class EditSessionBuilder {
|
||||
limitUnlimited();
|
||||
FaweLimit tmp = fp.getLimit();
|
||||
limit.INVENTORY_MODE = tmp.INVENTORY_MODE;
|
||||
return this;
|
||||
return setDirty();
|
||||
}
|
||||
|
||||
public EditSessionBuilder changeSet(@Nullable FaweChangeSet changeSet) {
|
||||
this.changeSet = changeSet;
|
||||
return this;
|
||||
return setDirty();
|
||||
}
|
||||
|
||||
public EditSessionBuilder changeSetNull() {
|
||||
@ -117,7 +126,7 @@ public class EditSessionBuilder {
|
||||
checkNotNull(world);
|
||||
this.world = world;
|
||||
this.worldName = world.getName();
|
||||
return this;
|
||||
return setDirty();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -146,23 +155,23 @@ public class EditSessionBuilder {
|
||||
} else {
|
||||
this.changeSet = new MemoryOptimizedHistory(world);
|
||||
}
|
||||
return this;
|
||||
return setDirty();
|
||||
}
|
||||
|
||||
public EditSessionBuilder allowedRegions(@Nullable Region[] allowedRegions) {
|
||||
this.allowedRegions = allowedRegions;
|
||||
return this;
|
||||
return setDirty();
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public EditSessionBuilder allowedRegions(@Nullable RegionWrapper[] allowedRegions) {
|
||||
this.allowedRegions = allowedRegions;
|
||||
return this;
|
||||
return setDirty();
|
||||
}
|
||||
|
||||
public EditSessionBuilder allowedRegions(@Nullable RegionWrapper allowedRegion) {
|
||||
this.allowedRegions = allowedRegion == null ? null : allowedRegion.toArray();
|
||||
return this;
|
||||
return setDirty();
|
||||
}
|
||||
|
||||
public EditSessionBuilder allowedRegionsEverywhere() {
|
||||
@ -171,47 +180,45 @@ public class EditSessionBuilder {
|
||||
|
||||
public EditSessionBuilder autoQueue(@Nullable Boolean autoQueue) {
|
||||
this.autoQueue = autoQueue;
|
||||
return this;
|
||||
return setDirty();
|
||||
}
|
||||
|
||||
public EditSessionBuilder fastmode(@Nullable Boolean fastmode) {
|
||||
this.fastmode = fastmode;
|
||||
return this;
|
||||
return setDirty();
|
||||
}
|
||||
|
||||
public EditSessionBuilder checkMemory(@Nullable Boolean checkMemory) {
|
||||
this.checkMemory = checkMemory;
|
||||
return this;
|
||||
return setDirty();
|
||||
}
|
||||
|
||||
public EditSessionBuilder combineStages(@Nullable Boolean combineStages) {
|
||||
this.combineStages = combineStages;
|
||||
return this;
|
||||
}
|
||||
|
||||
public EditSessionBuilder extent(@Nullable Extent extent) {
|
||||
this.extent = extent;
|
||||
return this;
|
||||
return setDirty();
|
||||
}
|
||||
|
||||
public EditSessionBuilder blockBag(@Nullable BlockBag blockBag) {
|
||||
this.blockBag = blockBag;
|
||||
return this;
|
||||
return setDirty();
|
||||
}
|
||||
|
||||
public EditSessionBuilder eventBus(@Nullable EventBus eventBus) {
|
||||
this.eventBus = eventBus;
|
||||
return this;
|
||||
return setDirty();
|
||||
}
|
||||
|
||||
public EditSessionBuilder event(@Nullable EditSessionEvent event) {
|
||||
this.event = event;
|
||||
return setDirty();
|
||||
}
|
||||
|
||||
private EditSessionBuilder setDirty() {
|
||||
compiled = false;
|
||||
return this;
|
||||
}
|
||||
|
||||
private boolean wrapped;
|
||||
|
||||
private AbstractDelegateExtent wrapExtent(final AbstractDelegateExtent extent, final EventBus eventBus, EditSessionEvent event, final EditSession.Stage stage) {
|
||||
private Extent wrapExtent(final Extent extent, final EventBus eventBus, EditSessionEvent event, final EditSession.Stage stage) {
|
||||
event = event.clone(stage);
|
||||
event.setExtent(extent);
|
||||
eventBus.post(event);
|
||||
@ -222,16 +229,16 @@ public class EditSessionBuilder {
|
||||
if(toReturn instanceof com.sk89q.worldedit.extent.NullExtent) {
|
||||
return new NullExtent(toReturn, FaweException.MANUAL);
|
||||
}
|
||||
if (!(toReturn instanceof AbstractDelegateExtent)) {
|
||||
Fawe.debug("Extent " + toReturn + " must be AbstractDelegateExtent");
|
||||
return extent;
|
||||
}
|
||||
// if (!(toReturn instanceof AbstractDelegateExtent)) {
|
||||
// Fawe.debug("Extent " + toReturn + " must be AbstractDelegateExtent");
|
||||
// return extent;
|
||||
// }
|
||||
if (toReturn != extent) {
|
||||
String className = toReturn.getClass().getName().toLowerCase();
|
||||
for (String allowed : Settings.IMP.EXTENT.ALLOWED_PLUGINS) {
|
||||
if (className.contains(allowed.toLowerCase())) {
|
||||
this.wrapped = true;
|
||||
return (AbstractDelegateExtent) toReturn;
|
||||
return toReturn;
|
||||
}
|
||||
}
|
||||
if (Settings.IMP.EXTENT.DEBUG) {
|
||||
@ -252,13 +259,16 @@ public class EditSessionBuilder {
|
||||
|
||||
private FaweChangeSet changeTask;
|
||||
private int maxY;
|
||||
private HistoryExtent history;
|
||||
private AbstractDelegateExtent bypassHistory;
|
||||
private AbstractDelegateExtent bypassAll;
|
||||
private Extent bypassHistory;
|
||||
private Extent bypassAll;
|
||||
private Extent extent;
|
||||
private boolean compiled;
|
||||
private boolean wrapped;
|
||||
|
||||
public EditSessionBuilder compile() {
|
||||
if (extent != null) return this;
|
||||
if (compiled) return this;
|
||||
|
||||
compiled = true;
|
||||
wrapped = false;
|
||||
if (world == null && !this.worldName.isEmpty()) {
|
||||
world = FaweAPI.getWorld(this.worldName);
|
||||
@ -302,33 +312,39 @@ public class EditSessionBuilder {
|
||||
}
|
||||
// this.originalLimit = limit;
|
||||
this.blockBag = limit.INVENTORY_MODE != 0 ? blockBag : null;
|
||||
// this.limit = limit.copy();
|
||||
this.limit = limit.copy();
|
||||
|
||||
// if (queue == null) {
|
||||
// boolean placeChunks = this.fastmode || this.limit.FAST_PLACEMENT;
|
||||
// World unwrapped = WorldWrapper.unwrap(world);
|
||||
// if (unwrapped instanceof IQueueExtent) {
|
||||
// queue = (IQueueExtent) unwrapped;
|
||||
// } else if (unwrapped instanceof MCAWorld) {
|
||||
// queue = ((MCAWorld) unwrapped).getQueue();
|
||||
// } else if (player != null && world.equals(player.getWorld())) {
|
||||
// queue = player.getIQueueExtent(placeChunks, autoQueue);
|
||||
// } else {
|
||||
// queue = SetQueue.IMP.getNewQueue(world, placeChunks, autoQueue);
|
||||
// }
|
||||
// }
|
||||
// if (combineStages == null) {
|
||||
// combineStages =
|
||||
// // If it's enabled in the settings
|
||||
// Settings.IMP.HISTORY.COMBINE_STAGES
|
||||
// // If fast placement is disabled, it's slower to perform a copy on each chunk
|
||||
// && this.limit.FAST_PLACEMENT
|
||||
// // If the specific queue doesn't support it
|
||||
// && queue.supports(IQueueExtent.Capability.CHANGE_TASKS)
|
||||
// // If the edit uses items from the inventory we can't use a delayed task
|
||||
// && this.blockBag == null;
|
||||
// }
|
||||
// if (!Settings.IMP.QUEUE.PROGRESS.DISPLAY.equalsIgnoreCase("false") && player != null) {
|
||||
if (extent == null) {
|
||||
IQueueExtent queue = null;
|
||||
World unwrapped = WorldWrapper.unwrap(world);
|
||||
boolean placeChunks = this.fastmode || this.limit.FAST_PLACEMENT;
|
||||
|
||||
if (placeChunks) {
|
||||
if (unwrapped instanceof IQueueExtent) {
|
||||
extent = queue = (IQueueExtent) unwrapped;
|
||||
} else if (Settings.IMP.QUEUE.PARALLEL_THREADS > 1 && threaded) {
|
||||
ParallelQueueExtent parallel = new ParallelQueueExtent(Fawe.get().getQueueHandler(), world);
|
||||
queue = parallel.getExtent();
|
||||
extent = parallel;
|
||||
} else {
|
||||
System.out.println("FAWE is in single threaded mode (performance reduced)");
|
||||
extent = queue = Fawe.get().getQueueHandler().getQueue(world);
|
||||
}
|
||||
} else {
|
||||
extent = world;
|
||||
}
|
||||
Extent root = extent;
|
||||
if (combineStages == null) {
|
||||
combineStages =
|
||||
// If it's enabled in the settings
|
||||
Settings.IMP.HISTORY.COMBINE_STAGES
|
||||
// If fast placement is disabled, it's slower to perform a copy on each chunk
|
||||
&& this.limit.FAST_PLACEMENT
|
||||
// If the edit uses items from the inventory we can't use a delayed task
|
||||
&& this.blockBag == null;
|
||||
}
|
||||
if (!Settings.IMP.QUEUE.PROGRESS.DISPLAY.equalsIgnoreCase("false") && player != null) {
|
||||
System.out.println("TODO add progress display");
|
||||
// switch (Settings.IMP.QUEUE.PROGRESS.DISPLAY.toLowerCase()) {
|
||||
// case "chat":
|
||||
// this.queue.setProgressTask(new ChatProgressTracker(player));
|
||||
@ -338,73 +354,84 @@ public class EditSessionBuilder {
|
||||
// default:
|
||||
// this.queue.setProgressTask(new DefaultProgressTracker(player));
|
||||
// }
|
||||
// }
|
||||
// this.bypassAll = wrapExtent(new FastWorldEditExtent(world, queue), eventBus, event, EditSession.Stage.BEFORE_CHANGE);
|
||||
// this.bypassHistory = (this.extent = wrapExtent(bypassAll, eventBus, event, EditSession.Stage.BEFORE_REORDER));
|
||||
// if (!this.fastmode || changeSet != null) {
|
||||
// if (changeSet == null) {
|
||||
// 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)) {
|
||||
}
|
||||
extent = this.bypassAll = wrapExtent(extent, eventBus, event, EditSession.Stage.BEFORE_CHANGE);
|
||||
this.bypassHistory = (this.extent = wrapExtent(bypassAll, eventBus, event, EditSession.Stage.BEFORE_REORDER));
|
||||
if (!this.fastmode || changeSet != null) {
|
||||
if (changeSet == null) {
|
||||
if (Settings.IMP.HISTORY.USE_DISK) {
|
||||
UUID uuid = player == null ? EditSession.CONSOLE : player.getUniqueId();
|
||||
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) {
|
||||
// changeSet = new CPUOptimizedChangeSet(world);
|
||||
// } else {
|
||||
// changeSet = new MemoryOptimizedHistory(world);
|
||||
// }
|
||||
// }
|
||||
// if (this.limit.SPEED_REDUCTION > 0) {
|
||||
// this.bypassHistory = new SlowExtent(this.bypassHistory, this.limit.SPEED_REDUCTION);
|
||||
// }
|
||||
// if (changeSet instanceof NullChangeSet && Fawe.imp().getBlocksHubApi() != null && player != null) {
|
||||
// changeSet = LoggingChangeSet.wrap(player, changeSet);
|
||||
// }
|
||||
// if (!(changeSet instanceof NullChangeSet)) {
|
||||
// if (!(changeSet instanceof LoggingChangeSet) && player != null && Fawe.imp().getBlocksHubApi() != null) {
|
||||
// changeSet = LoggingChangeSet.wrap(player, changeSet);
|
||||
// }
|
||||
} else {
|
||||
if (combineStages && Settings.IMP.HISTORY.COMPRESSION_LEVEL == 0) {
|
||||
System.out.println("TODO add CPUOptimizedChangeSet");
|
||||
}
|
||||
changeSet = new MemoryOptimizedHistory(world);
|
||||
}
|
||||
}
|
||||
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) {
|
||||
changeSet = LoggingChangeSet.wrap(player, changeSet);
|
||||
}
|
||||
if (!(changeSet instanceof NullChangeSet)) {
|
||||
if (!(changeSet instanceof LoggingChangeSet) && player != null && Fawe.imp().getBlocksHubApi() != null) {
|
||||
changeSet = LoggingChangeSet.wrap(player, changeSet);
|
||||
}
|
||||
if (this.blockBag != null) {
|
||||
System.out.println("TODO implement block bag as IBatchProcessor");
|
||||
changeSet = new BlockBagChangeSet(changeSet, blockBag, limit.INVENTORY_MODE == 1);
|
||||
}
|
||||
if (combineStages) {
|
||||
changeTask = changeSet;
|
||||
this.extent = extent.enableHistory(changeSet);
|
||||
} else {
|
||||
this.extent = (new HistoryExtent(extent, changeSet));
|
||||
// if (this.blockBag != null) {
|
||||
// changeSet = new BlockBagChangeSet(changeSet, blockBag, limit.INVENTORY_MODE == 1);
|
||||
// this.extent = new BlockBagExtent(this.extent, blockBag, limit.INVENTORY_MODE == 1);
|
||||
// }
|
||||
// if (combineStages) {
|
||||
// changeTask = changeSet;
|
||||
// changeSet.addChangeTask(queue);
|
||||
// } else {
|
||||
// this.extent = (history = new HistoryExtent(bypassHistory, changeSet, queue));
|
||||
//// if (this.blockBag != null) {
|
||||
//// this.extent = new BlockBagExtent(this.extent, blockBag, limit.INVENTORY_MODE == 1);
|
||||
//// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// if (allowedRegions == null) {
|
||||
// if (player != null && !player.hasPermission("fawe.bypass") && !player.hasPermission("fawe.bypass.regions") && !(queue instanceof VirtualWorld)) {
|
||||
// allowedRegions = player.getCurrentRegions();
|
||||
// }
|
||||
// }
|
||||
// this.maxY = world == null ? 255 : world.getMaxY();
|
||||
// if (allowedRegions != null) {
|
||||
// if (allowedRegions.length == 0) {
|
||||
// this.extent = new NullExtent(this.extent, FaweException.NO_REGION);
|
||||
// } else {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (allowedRegions == null) {
|
||||
if (player != null && !player.hasPermission("fawe.bypass") && !player.hasPermission("fawe.bypass.regions") && !(root instanceof VirtualWorld)) {
|
||||
allowedRegions = player.getCurrentRegions();
|
||||
}
|
||||
}
|
||||
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) {
|
||||
// this.extent = new SingleRegionExtent(this.extent, this.limit, allowedRegions[0]);
|
||||
// } else {
|
||||
// this.extent = new MultiRegionExtent(this.extent, this.limit, allowedRegions);
|
||||
// }
|
||||
// }
|
||||
// } else {
|
||||
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 (this.limit.STRIP_NBT != null && !this.limit.STRIP_NBT.isEmpty()) {
|
||||
// this.extent = new StripNBTExtent(this.extent, this.limit.STRIP_NBT);
|
||||
// }
|
||||
// this.extent = wrapExtent(this.extent, eventBus, event, EditSession.Stage.BEFORE_HISTORY);
|
||||
// return this;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
@ -415,10 +442,6 @@ public class EditSessionBuilder {
|
||||
return new EditSession(this);
|
||||
}
|
||||
|
||||
public Extent getExtent() {
|
||||
return extent;
|
||||
}
|
||||
|
||||
public World getWorld() {
|
||||
return world;
|
||||
}
|
||||
@ -427,6 +450,10 @@ public class EditSessionBuilder {
|
||||
return worldName;
|
||||
}
|
||||
|
||||
public Extent getExtent() {
|
||||
return extent != null ? extent : world;
|
||||
}
|
||||
|
||||
public boolean isWrapped() {
|
||||
return wrapped;
|
||||
}
|
||||
@ -435,23 +462,16 @@ public class EditSessionBuilder {
|
||||
return fastmode;
|
||||
}
|
||||
|
||||
public HistoryExtent getHistory() {
|
||||
return history;
|
||||
}
|
||||
|
||||
public AbstractDelegateExtent getBypassHistory() {
|
||||
public Extent getBypassHistory() {
|
||||
return bypassHistory;
|
||||
}
|
||||
|
||||
public AbstractDelegateExtent getBypassAll() {
|
||||
public Extent getBypassAll() {
|
||||
return bypassAll;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public FaweLimit getLimit() {
|
||||
if (limit == null) {
|
||||
return FaweLimit.MAX;
|
||||
}
|
||||
return limit;
|
||||
}
|
||||
|
||||
|
@ -41,7 +41,8 @@ public class FaweTimer implements Runnable {
|
||||
if (tick < lastGetTPSTick + tickInterval) {
|
||||
return lastGetTPSValue;
|
||||
}
|
||||
double total = Arrays.stream(history).sum();
|
||||
double total = 0;
|
||||
for (double v : history) total += v;
|
||||
lastGetTPSValue = total / history.length;
|
||||
lastGetTPSTick = tick;
|
||||
return lastGetTPSValue;
|
||||
|
@ -1,5 +1,9 @@
|
||||
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.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
@ -10,6 +14,33 @@ import java.util.stream.Collectors;
|
||||
public class ImgurUtility {
|
||||
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 {
|
||||
String imageString = Base64.getEncoder().encodeToString(image);
|
||||
URL url = new URL("https://api.imgur.com/3/image");
|
||||
|
@ -1,7 +1,5 @@
|
||||
package com.boydti.fawe.util;
|
||||
|
||||
import static java.lang.System.arraycopy;
|
||||
|
||||
import com.boydti.fawe.Fawe;
|
||||
import com.boydti.fawe.config.BBC;
|
||||
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.history.changeset.ChangeSet;
|
||||
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.io.BufferedInputStream;
|
||||
import java.io.BufferedOutputStream;
|
||||
@ -75,27 +83,11 @@ import java.util.zip.GZIPInputStream;
|
||||
import java.util.zip.Inflater;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipInputStream;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.imageio.ImageIO;
|
||||
import 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 static java.lang.System.arraycopy;
|
||||
|
||||
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) {
|
||||
if (prefix.isEmpty()) {
|
||||
return suggestions;
|
||||
@ -754,7 +746,6 @@ public class MainUtil {
|
||||
if (time >= 33868800) {
|
||||
int years = (int) (time / 33868800);
|
||||
int time1 = years * 33868800;
|
||||
System.out.println(time1);
|
||||
time -= time1;
|
||||
toreturn.append(years + "y ");
|
||||
}
|
||||
|
@ -69,10 +69,10 @@ public class TextureUtil implements TextureHolder {
|
||||
private BiomeColor[] biomes = new BiomeColor[]{
|
||||
// ID Name Temperature, rainfall, grass, foliage colors
|
||||
// - 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
|
||||
new BiomeColor(1, "plains", 0.8f, 0.4f, 0x92BD59, 7842607),
|
||||
new BiomeColor(2, "desert", 2.0f, 0.0f, 0x92BD59, 7842607),
|
||||
new BiomeColor(1, "plains", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
|
||||
new BiomeColor(2, "desert", 2.0f, 0.0f, 0x92BD59, 0x77AB2F),
|
||||
new BiomeColor(3, "mountains", 0.2f, 0.3f, 0x92BD59, 0x77AB2F),
|
||||
new BiomeColor(4, "forest", 0.7f, 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(23, "jungle_edge", 0.95f, 0.8f, 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(27, "birch_forest", 0.6f, 0.6f, 0x92BD59, 0x77AB2F),
|
||||
new BiomeColor(28, "birch_forest_hills", 0.6f, 0.6f, 0x92BD59, 0x77AB2F),
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
259
worldedit-core/src/main/java/com/boydti/fawe/wrappers/PlayerWrapper.java
Normale Datei
259
worldedit-core/src/main/java/com/boydti/fawe/wrappers/PlayerWrapper.java
Normale Datei
@ -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;
|
||||
});
|
||||
}
|
||||
}
|
@ -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) {
|
||||
}
|
||||
}
|
Einige Dateien werden nicht angezeigt, da zu viele Dateien in diesem Diff geändert wurden Mehr anzeigen
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren