Various
fix pom combine stages work on efficient handling tiles / entities in changeset other minor restructuring (Currently only stable for bukkit 1.8 with Settings.COMBINE_HISTORY_STAGE=true)
This commit is contained in:
parent
71da20c6c4
commit
1d5765e8cc
@ -12,6 +12,7 @@ dependencies {
|
||||
compile 'com.palmergames.bukkit:towny:0.84.0.9'
|
||||
compile 'com.worldcretornica:plotme_core:0.16.3'
|
||||
compile 'junit:junit:4.11'
|
||||
compile 'com.sk89q.worldedit:worldedit-bukkit:6.1.1-SNAPSHOT'
|
||||
}
|
||||
|
||||
processResources {
|
||||
|
@ -5,7 +5,7 @@ import com.boydti.fawe.util.FaweQueue;
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
public abstract class BukkitMain extends JavaPlugin {
|
||||
public abstract class ABukkitMain extends JavaPlugin {
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
@ -43,7 +43,7 @@ import org.bukkit.plugin.Plugin;
|
||||
|
||||
public class FaweBukkit implements IFawe, Listener {
|
||||
|
||||
private final BukkitMain plugin;
|
||||
private final ABukkitMain plugin;
|
||||
private VaultUtil vault;
|
||||
private WorldEditPlugin worldedit;
|
||||
|
||||
@ -58,7 +58,7 @@ public class FaweBukkit implements IFawe, Listener {
|
||||
return this.worldedit;
|
||||
}
|
||||
|
||||
public FaweBukkit(BukkitMain plugin) {
|
||||
public FaweBukkit(ABukkitMain plugin) {
|
||||
this.plugin = plugin;
|
||||
try {
|
||||
Bukkit.getPluginManager().registerEvents(this, plugin);
|
||||
@ -203,7 +203,7 @@ public class FaweBukkit implements IFawe, Listener {
|
||||
return new BukkitQueue_All(world);
|
||||
}
|
||||
|
||||
public BukkitMain getPlugin() {
|
||||
public ABukkitMain getPlugin() {
|
||||
return plugin;
|
||||
}
|
||||
|
||||
|
@ -2,8 +2,7 @@ package com.boydti.fawe.bukkit.logging;
|
||||
|
||||
import com.boydti.fawe.object.FawePlayer;
|
||||
import com.boydti.fawe.object.changeset.FaweChangeSet;
|
||||
import com.sk89q.worldedit.Vector;
|
||||
import com.sk89q.worldedit.blocks.BaseBlock;
|
||||
import com.sk89q.jnbt.CompoundTag;
|
||||
import com.sk89q.worldedit.history.change.Change;
|
||||
import java.util.Iterator;
|
||||
import org.PrimeSoft.blocksHub.IBlocksHubApi;
|
||||
@ -11,7 +10,7 @@ import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public class LoggingChangeSet implements FaweChangeSet {
|
||||
public class LoggingChangeSet extends FaweChangeSet {
|
||||
|
||||
private final FaweChangeSet parent;
|
||||
private final IBlocksHubApi api;
|
||||
@ -32,29 +31,6 @@ public class LoggingChangeSet implements FaweChangeSet {
|
||||
return parent.flush();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCompressedSize() {
|
||||
return parent.getCompressedSize();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void add(Vector location, BaseBlock from, BaseBlock to) {
|
||||
loc.setX(location.getX());
|
||||
loc.setY(location.getY());
|
||||
loc.setZ(location.getZ());
|
||||
api.logBlock(name, world, loc, from.getId(), (byte) from.getData(), to.getId(), (byte) to.getData());
|
||||
parent.add(location, from, to);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void add(int x, int y, int z, int combinedId4DataFrom, BaseBlock to) {
|
||||
loc.setX(x);
|
||||
loc.setY(y);
|
||||
loc.setZ(z);
|
||||
api.logBlock(name, world, loc, combinedId4DataFrom >> 4, (byte) (combinedId4DataFrom & 0xF), to.getId(), (byte) to.getData());
|
||||
parent.add(x, y, z, combinedId4DataFrom, to);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void add(int x, int y, int z, int combinedId4DataFrom, int combinedId4DataTo) {
|
||||
loc.setX(x);
|
||||
@ -65,18 +41,28 @@ public class LoggingChangeSet implements FaweChangeSet {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void add(Change change) {
|
||||
parent.add(change);
|
||||
public void addTileCreate(CompoundTag tag) {
|
||||
parent.addTileCreate(tag);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<Change> backwardIterator() {
|
||||
return parent.backwardIterator();
|
||||
public void addTileRemove(CompoundTag tag) {
|
||||
parent.addTileRemove(tag);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<Change> forwardIterator() {
|
||||
return parent.forwardIterator();
|
||||
public void addEntityRemove(CompoundTag tag) {
|
||||
parent.addEntityRemove(tag);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addEntityCreate(CompoundTag tag) {
|
||||
parent.addEntityCreate(tag);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<Change> getIterator(boolean undo) {
|
||||
return parent.getIterator(undo);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -4,9 +4,12 @@ import com.boydti.fawe.FaweCache;
|
||||
import com.boydti.fawe.example.CharFaweChunk;
|
||||
import com.boydti.fawe.example.NMSMappedFaweQueue;
|
||||
import com.boydti.fawe.object.FaweChunk;
|
||||
import com.boydti.fawe.object.RunnableVal;
|
||||
import com.sk89q.worldedit.LocalWorld;
|
||||
import com.sk89q.worldedit.Vector2D;
|
||||
import com.sk89q.worldedit.bukkit.BukkitUtil;
|
||||
import com.sk89q.worldedit.bukkit.WorldEditPlugin;
|
||||
import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter;
|
||||
import com.sk89q.worldedit.world.biome.BaseBiome;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
@ -18,8 +21,32 @@ import org.bukkit.block.Block;
|
||||
|
||||
public abstract class BukkitQueue_0<CHUNK, CHUNKSECTIONS, SECTION> extends NMSMappedFaweQueue<World, CHUNK, CHUNKSECTIONS, SECTION> {
|
||||
|
||||
public final BukkitImplAdapter adapter;
|
||||
public Method methodToNative;
|
||||
public Method methodFromNative;
|
||||
|
||||
public BukkitQueue_0(final String world) {
|
||||
super(world);
|
||||
try {
|
||||
WorldEditPlugin instance = (WorldEditPlugin) Bukkit.getPluginManager().getPlugin("WorldEdit");
|
||||
Field fieldAdapter = WorldEditPlugin.class.getDeclaredField("bukkitAdapter");
|
||||
fieldAdapter.setAccessible(true);
|
||||
this.adapter = (BukkitImplAdapter) fieldAdapter.get(instance);
|
||||
for (Method method : adapter.getClass().getDeclaredMethods()) {
|
||||
switch (method.getName()) {
|
||||
case "toNative":
|
||||
methodToNative = method;
|
||||
methodToNative.setAccessible(true);
|
||||
break;
|
||||
case "fromNative":
|
||||
methodFromNative = method;
|
||||
methodFromNative.setAccessible(true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -85,8 +112,11 @@ public abstract class BukkitQueue_0<CHUNK, CHUNKSECTIONS, SECTION> extends NMSMa
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setComponents(FaweChunk fc) {
|
||||
public boolean setComponents(FaweChunk fc, RunnableVal<FaweChunk> changeTask) {
|
||||
try {
|
||||
// TODO track stage
|
||||
// TODO set task
|
||||
|
||||
final CharFaweChunk<Chunk> fs = ((CharFaweChunk<Chunk>) fc);
|
||||
final Chunk chunk = fs.getChunk();
|
||||
chunk.load(true);
|
||||
|
@ -24,15 +24,15 @@ public class ChunkListener implements Listener {
|
||||
}, 1);
|
||||
}
|
||||
|
||||
private int physicsLimit = Settings.PHYSICS_PER_TICK;
|
||||
private int itemLimit = Settings.ITEMS_PER_TICK;
|
||||
private int physicsLimit = Integer.MAX_VALUE;
|
||||
private int itemLimit = Integer.MAX_VALUE;
|
||||
public static boolean physicsFreeze = false;
|
||||
|
||||
@EventHandler(priority = EventPriority.LOWEST)
|
||||
public void onPhysics(BlockPhysicsEvent event) {
|
||||
if (physicsFreeze) {
|
||||
event.setCancelled(true);
|
||||
} else if (--physicsLimit < 0) {
|
||||
} else if (physicsLimit-- < 0) {
|
||||
physicsFreeze = true;
|
||||
}
|
||||
}
|
||||
@ -41,7 +41,7 @@ public class ChunkListener implements Listener {
|
||||
public void onItemSpawn(ItemSpawnEvent event) {
|
||||
if (physicsFreeze) {
|
||||
event.setCancelled(true);
|
||||
} else if (--itemLimit < 0) {
|
||||
} else if (itemLimit-- < 0) {
|
||||
physicsFreeze = true;
|
||||
}
|
||||
}
|
||||
|
@ -1,43 +0,0 @@
|
||||
name: FastAsyncWorldEdit
|
||||
main: com.boydti.fawe.bukkit.FaweBukkit
|
||||
version: 3.4.3
|
||||
description: Fast Async WorldEdit plugin
|
||||
authors: [Empire92]
|
||||
loadbefore: [WorldEdit]
|
||||
load: STARTUP
|
||||
database: false
|
||||
#softdepend: [WorldGuard, PlotSquared, MCore, Factions, GriefPrevention, Residence, Towny, PlotMe, PreciousStones]
|
||||
commands:
|
||||
wea:
|
||||
description: (FAWE) Bypass WorldEdit processing and area restrictions
|
||||
aliases: [weanywhere,worldeditanywhere,/wea,/weanywhere,/worldeditanywhere]
|
||||
usage: "Vault is required for the toggle. Optionally, you can set the permission fawe.bypass"
|
||||
fixlighting:
|
||||
description: (FAWE) Fix the lighting in your current chunk
|
||||
aliases: [/fixlighting]
|
||||
stream:
|
||||
description: (FAWE) Stream a schematic into the world
|
||||
aliases: [/stream]
|
||||
fawe:
|
||||
description: (FAWE) Reload the plugin
|
||||
aliases: [/fawe,/fawereload]
|
||||
wrg:
|
||||
description: (FAWE) Select your current WorldEdit Region.
|
||||
aliases: [/wrg,wer,/wer,worldeditregion,/worldeditregion,/region]
|
||||
frb:
|
||||
description: (FAWE) Rollback an edit
|
||||
aliases: [fawerollback,fawerb,/uu,/rb,/frb,/fawerollback,/fawerb]
|
||||
fcancel:
|
||||
description: (FAWE) Cancel your edit
|
||||
aliases: [fawecancel,/fcancel,/cancel,/fawecancel]
|
||||
permissions:
|
||||
fawe.bypass:
|
||||
default: false
|
||||
fawe.admin:
|
||||
default: false
|
||||
fawe.stream:
|
||||
default: false
|
||||
fawe.fixlighting:
|
||||
default: false
|
||||
fawe.reload:
|
||||
default: false
|
@ -1,11 +1,12 @@
|
||||
package com.boydti.fawe.bukkit.v1_8;
|
||||
|
||||
import com.boydti.fawe.bukkit.BukkitMain;
|
||||
import com.boydti.fawe.bukkit.ABukkitMain;
|
||||
import com.boydti.fawe.bukkit.v0.BukkitQueue_0;
|
||||
import com.boydti.fawe.bukkit.v1_8.BukkitQueue18R3;
|
||||
import com.boydti.fawe.object.EditSessionWrapper;
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
|
||||
public class BukkitMain_1_8 extends BukkitMain {
|
||||
public class BukkitMain_18 extends ABukkitMain {
|
||||
@Override
|
||||
public BukkitQueue_0 getQueue(String world) {
|
||||
return new BukkitQueue18R3(world);
|
@ -5,11 +5,21 @@ import com.boydti.fawe.FaweCache;
|
||||
import com.boydti.fawe.bukkit.BukkitPlayer;
|
||||
import com.boydti.fawe.bukkit.v0.BukkitQueue_0;
|
||||
import com.boydti.fawe.example.CharFaweChunk;
|
||||
import com.boydti.fawe.object.BytePair;
|
||||
import com.boydti.fawe.object.FaweChunk;
|
||||
import com.boydti.fawe.object.FaweLocation;
|
||||
import com.boydti.fawe.object.FawePlayer;
|
||||
import com.boydti.fawe.object.PseudoRandom;
|
||||
import com.boydti.fawe.object.RunnableVal;
|
||||
import com.boydti.fawe.util.MathMan;
|
||||
import com.boydti.fawe.util.ReflectionUtils;
|
||||
import com.sk89q.jnbt.CompoundTag;
|
||||
import com.sk89q.jnbt.ListTag;
|
||||
import com.sk89q.jnbt.StringTag;
|
||||
import com.sk89q.jnbt.Tag;
|
||||
import com.sk89q.worldedit.internal.Constants;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
@ -17,6 +27,10 @@ import java.util.Set;
|
||||
import net.minecraft.server.v1_8_R3.BlockPosition;
|
||||
import net.minecraft.server.v1_8_R3.ChunkCoordIntPair;
|
||||
import net.minecraft.server.v1_8_R3.ChunkSection;
|
||||
import net.minecraft.server.v1_8_R3.Entity;
|
||||
import net.minecraft.server.v1_8_R3.EntityTypes;
|
||||
import net.minecraft.server.v1_8_R3.NBTTagCompound;
|
||||
import net.minecraft.server.v1_8_R3.NBTTagInt;
|
||||
import net.minecraft.server.v1_8_R3.PacketPlayOutMapChunk;
|
||||
import net.minecraft.server.v1_8_R3.PlayerConnection;
|
||||
import net.minecraft.server.v1_8_R3.TileEntity;
|
||||
@ -26,6 +40,7 @@ import org.bukkit.Material;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.craftbukkit.v1_8_R3.CraftChunk;
|
||||
import org.bukkit.craftbukkit.v1_8_R3.entity.CraftPlayer;
|
||||
import org.bukkit.event.entity.CreatureSpawnEvent;
|
||||
|
||||
public class BukkitQueue18R3 extends BukkitQueue_0<Chunk, ChunkSection[], char[]> {
|
||||
|
||||
@ -81,7 +96,7 @@ public class BukkitQueue18R3 extends BukkitQueue_0<Chunk, ChunkSection[], char[]
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setComponents(FaweChunk fc) {
|
||||
public boolean setComponents(FaweChunk fc, RunnableVal<FaweChunk> changeTask) {
|
||||
CharFaweChunk<Chunk> fs = (CharFaweChunk<Chunk>) fc;
|
||||
CraftChunk chunk = (CraftChunk) fs.getChunk();
|
||||
net.minecraft.server.v1_8_R3.Chunk nmsChunk = chunk.getHandle();
|
||||
@ -92,6 +107,55 @@ public class BukkitQueue18R3 extends BukkitQueue_0<Chunk, ChunkSection[], char[]
|
||||
ChunkSection[] sections = nmsChunk.getSections();
|
||||
Map<BlockPosition, TileEntity> tiles = nmsChunk.getTileEntities();
|
||||
Collection<net.minecraft.server.v1_8_R3.Entity>[] entities = nmsChunk.getEntitySlices();
|
||||
|
||||
// Run change task if applicable
|
||||
if (changeTask != null) {
|
||||
CharFaweChunk previous = (CharFaweChunk) getChunk(fc.getX(), fc.getZ());
|
||||
char[][] idPrevious = new char[16][];
|
||||
for (int layer = 0; layer < sections.length; layer++) {
|
||||
if (fs.getCount(layer) != 0) {
|
||||
ChunkSection section = sections[layer];
|
||||
if (section != null) {
|
||||
idPrevious[layer] = section.getIdArray().clone();
|
||||
}
|
||||
}
|
||||
}
|
||||
previous.ids = idPrevious;
|
||||
for (Map.Entry<BlockPosition, TileEntity> entry : tiles.entrySet()) {
|
||||
TileEntity tile = entry.getValue();
|
||||
NBTTagCompound tag = new NBTTagCompound();
|
||||
tile.b(tag); // ReadTileIntoTag
|
||||
BlockPosition pos = entry.getKey();
|
||||
CompoundTag nativeTag = (CompoundTag) methodToNative.invoke(adapter, tag);
|
||||
previous.setTile(pos.getX(), pos.getY(), pos.getZ(), nativeTag);
|
||||
}
|
||||
for (Collection<Entity> entityList : entities) {
|
||||
for (Entity ent : entityList) {
|
||||
int x = ((int) Math.round(ent.locX) & 15);
|
||||
int z = ((int) Math.round(ent.locZ) & 15);
|
||||
int y = (int) Math.round(ent.locY);
|
||||
int i = FaweCache.CACHE_I[y][x][z];
|
||||
char[] array = fs.getIdArray(i);
|
||||
if (array == null) {
|
||||
continue;
|
||||
}
|
||||
int j = FaweCache.CACHE_J[y][x][z];
|
||||
if (array[j] != 0) {
|
||||
String id = EntityTypes.b(ent);
|
||||
if (id != null) {
|
||||
NBTTagCompound tag = new NBTTagCompound();
|
||||
ent.e(tag);
|
||||
CompoundTag nativeTag = (CompoundTag) methodToNative.invoke(adapter, tag);
|
||||
Map<String, Tag> map = ReflectionUtils.getMap(nativeTag.getValue());
|
||||
map.put("Id", new StringTag(id));
|
||||
previous.setEntity(nativeTag);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
changeTask.run(previous);
|
||||
}
|
||||
|
||||
// Trim tiles
|
||||
Set<Map.Entry<BlockPosition, TileEntity>> entryset = tiles.entrySet();
|
||||
Iterator<Map.Entry<BlockPosition, TileEntity>> iterator = entryset.iterator();
|
||||
@ -102,22 +166,41 @@ public class BukkitQueue18R3 extends BukkitQueue_0<Chunk, ChunkSection[], char[]
|
||||
int ly = pos.getY();
|
||||
int lz = pos.getZ() & 15;
|
||||
int j = FaweCache.CACHE_I[ly][lx][lz];
|
||||
int k = FaweCache.CACHE_J[ly][lx][lz];
|
||||
char[] array = fs.getIdArray(j);
|
||||
if (array == null) {
|
||||
continue;
|
||||
}
|
||||
int k = FaweCache.CACHE_J[ly][lx][lz];
|
||||
if (array[k] != 0) {
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
// Trim entities
|
||||
// Remove entities
|
||||
for (int i = 0; i < 16; i++) {
|
||||
if ((entities[i] != null) && (fs.getCount(i) >= 4096)) {
|
||||
int count = fs.getCount(i);
|
||||
if (count == 0) {
|
||||
continue;
|
||||
} else if (count >= 4096) {
|
||||
entities[i].clear();
|
||||
} else {
|
||||
char[] array = fs.getIdArray(i);
|
||||
Collection<Entity> ents = new ArrayList<>(entities[i]);
|
||||
for (Entity entity : ents) {
|
||||
int x = ((int) Math.round(entity.locX) & 15);
|
||||
int z = ((int) Math.round(entity.locZ) & 15);
|
||||
int y = (int) Math.round(entity.locY);
|
||||
if (array == null) {
|
||||
continue;
|
||||
}
|
||||
int j = FaweCache.CACHE_J[y][x][z];
|
||||
if (array[j] != 0) {
|
||||
nmsWorld.removeEntity(entity);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Efficiently merge sections
|
||||
|
||||
// Set blocks
|
||||
for (int j = 0; j < sections.length; j++) {
|
||||
if (fs.getCount(j) == 0) {
|
||||
continue;
|
||||
@ -142,8 +225,8 @@ public class BukkitQueue18R3 extends BukkitQueue_0<Chunk, ChunkSection[], char[]
|
||||
case 1:
|
||||
if (currentArray[k] > 1) {
|
||||
solid++;
|
||||
currentArray[k] = 0;
|
||||
}
|
||||
currentArray[k] = 0;
|
||||
continue;
|
||||
default:
|
||||
solid++;
|
||||
@ -153,25 +236,75 @@ public class BukkitQueue18R3 extends BukkitQueue_0<Chunk, ChunkSection[], char[]
|
||||
}
|
||||
setCount(0, solid, section);
|
||||
}
|
||||
// // Clear
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
int[][] biomes = fs.biomes;
|
||||
if (biomes != null) {
|
||||
for (int x = 0; x < 16; x++) {
|
||||
int[] array = biomes[x];
|
||||
if (array == null) {
|
||||
continue;
|
||||
}
|
||||
for (int z = 0; z < 16; z++) {
|
||||
int biome = array[z];
|
||||
if (biome == 0) {
|
||||
|
||||
// Set biomes
|
||||
int[][] biomes = fs.biomes;
|
||||
if (biomes != null) {
|
||||
for (int x = 0; x < 16; x++) {
|
||||
int[] array = biomes[x];
|
||||
if (array == null) {
|
||||
continue;
|
||||
}
|
||||
nmsChunk.getBiomeIndex()[((z & 0xF) << 4 | x & 0xF)] = (byte) biome;
|
||||
for (int z = 0; z < 16; z++) {
|
||||
int biome = array[z];
|
||||
if (biome == 0) {
|
||||
continue;
|
||||
}
|
||||
nmsChunk.getBiomeIndex()[((z & 0xF) << 4 | x & 0xF)] = (byte) biome;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Set tiles
|
||||
Map<BytePair, CompoundTag> tilesToSpawn = fs.getTiles();
|
||||
BlockPosition.MutableBlockPosition mutablePos = new BlockPosition.MutableBlockPosition(0, 0, 0);
|
||||
int bx = fs.getX() << 4;
|
||||
int bz = fs.getZ() << 4;
|
||||
|
||||
for (Map.Entry<BytePair, CompoundTag> entry : tilesToSpawn.entrySet()) {
|
||||
CompoundTag nativeTag = entry.getValue();
|
||||
BytePair pair = entry.getKey();
|
||||
mutablePos.c(MathMan.unpair16x(pair.pair[0]) + bx, pair.pair[1] & 0xFF, MathMan.unpair16y(pair.pair[0]) + bz); // Set pos
|
||||
TileEntity tileEntity = nmsWorld.getTileEntity(mutablePos);
|
||||
if (tileEntity != null) {
|
||||
NBTTagCompound tag = (NBTTagCompound) methodFromNative.invoke(adapter, nativeTag);
|
||||
tag.set("x", new NBTTagInt(mutablePos.getX()));
|
||||
tag.set("y", new NBTTagInt(mutablePos.getY()));
|
||||
tag.set("z", new NBTTagInt(mutablePos.getZ()));
|
||||
tileEntity.a(tag); // ReadTagIntoTile
|
||||
}
|
||||
}
|
||||
// Set entities
|
||||
Set<CompoundTag> entitiesToSpawn = fs.getEntities();
|
||||
for (CompoundTag nativeTag : entitiesToSpawn) {
|
||||
Map<String, Tag> entityTagMap = nativeTag.getValue();
|
||||
StringTag idTag = (StringTag) entityTagMap.get("Id");
|
||||
ListTag posTag = (ListTag) entityTagMap.get("Pos");
|
||||
ListTag rotTag = (ListTag) entityTagMap.get("Rotation");
|
||||
if (idTag == null || posTag == null || rotTag == null) {
|
||||
Fawe.debug("Unknown entity tag: " + nativeTag);
|
||||
continue;
|
||||
}
|
||||
double x = posTag.getDouble(0);
|
||||
double y = posTag.getDouble(1);
|
||||
double z = posTag.getDouble(2);
|
||||
float yaw = rotTag.getFloat(0);
|
||||
float pitch = rotTag.getFloat(1);
|
||||
String id = idTag.getValue();
|
||||
Entity entity = EntityTypes.createEntityByName(id, nmsWorld);
|
||||
if (entity != null) {
|
||||
if (nativeTag != null) {
|
||||
NBTTagCompound tag = (NBTTagCompound)methodFromNative.invoke(adapter, nativeTag);
|
||||
for (String name : Constants.NO_COPY_ENTITY_NBT_FIELDS) {
|
||||
tag.remove(name);
|
||||
}
|
||||
entity.f(tag);
|
||||
}
|
||||
entity.setLocation(x, y, z, yaw, pitch);
|
||||
nmsWorld.addEntity(entity, CreatureSpawnEvent.SpawnReason.CUSTOM);
|
||||
}
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
sendChunk(fc);
|
||||
return true;
|
||||
|
@ -1,5 +1,5 @@
|
||||
name: FastAsyncWorldEdit
|
||||
main: com.boydti.fawe.bukkit.v1_8.BukkitMain_1_8
|
||||
main: com.boydti.fawe.bukkit.v1_8.BukkitMain_18
|
||||
version: 3.4.3
|
||||
description: Fast Async WorldEdit plugin
|
||||
authors: [Empire92]
|
||||
|
@ -1,11 +1,12 @@
|
||||
package com.boydti.fawe.bukkit.v1_9;
|
||||
|
||||
import com.boydti.fawe.bukkit.BukkitMain;
|
||||
import com.boydti.fawe.bukkit.ABukkitMain;
|
||||
import com.boydti.fawe.bukkit.v0.BukkitQueue_0;
|
||||
import com.boydti.fawe.bukkit.v1_9.BukkitQueue_1_9_R1;
|
||||
import com.boydti.fawe.object.EditSessionWrapper;
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
|
||||
public class BukkitMain_1_9 extends BukkitMain {
|
||||
public class BukkitMain_19 extends ABukkitMain {
|
||||
@Override
|
||||
public BukkitQueue_0 getQueue(String world) {
|
||||
return new BukkitQueue_1_9_R1(world);
|
@ -8,6 +8,7 @@ import com.boydti.fawe.object.FaweChunk;
|
||||
import com.boydti.fawe.object.FawePlayer;
|
||||
import com.boydti.fawe.object.IntegerPair;
|
||||
import com.boydti.fawe.object.PseudoRandom;
|
||||
import com.boydti.fawe.object.RunnableVal;
|
||||
import com.boydti.fawe.util.MemUtil;
|
||||
import com.sk89q.worldedit.LocalSession;
|
||||
import java.lang.reflect.Constructor;
|
||||
@ -248,7 +249,12 @@ public class BukkitQueue_1_9_R1 extends BukkitQueue_0<Chunk, ChunkSection[], Dat
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setComponents(final FaweChunk pc) {
|
||||
public boolean setComponents(final FaweChunk pc, RunnableVal<FaweChunk> changeTask) {
|
||||
// TODO change task
|
||||
{
|
||||
// blah, stuff
|
||||
}
|
||||
|
||||
final BukkitChunk_1_9 fs = (BukkitChunk_1_9) pc;
|
||||
final Chunk chunk = (Chunk) fs.getChunk();
|
||||
final World world = chunk.getWorld();
|
||||
|
@ -1,5 +1,5 @@
|
||||
name: FastAsyncWorldEdit
|
||||
main: com.boydti.fawe.bukkit.v1_9.BukkitMain_1_9
|
||||
main: com.boydti.fawe.bukkit.v1_9.BukkitMain_19
|
||||
version: 3.4.3
|
||||
description: Fast Async WorldEdit plugin
|
||||
authors: [Empire92]
|
||||
|
@ -11,7 +11,6 @@ import com.boydti.fawe.config.BBC;
|
||||
import com.boydti.fawe.config.Settings;
|
||||
import com.boydti.fawe.object.FawePlayer;
|
||||
import com.boydti.fawe.regions.general.PlotSquaredFeature;
|
||||
import com.boydti.fawe.util.Lag;
|
||||
import com.boydti.fawe.util.MainUtil;
|
||||
import com.boydti.fawe.util.MemUtil;
|
||||
import com.boydti.fawe.util.TaskManager;
|
||||
@ -191,10 +190,6 @@ public class Fawe {
|
||||
*/
|
||||
this.setupInjector();
|
||||
this.setupMemoryListener();
|
||||
|
||||
// Lag
|
||||
final Lag lag = new Lag();
|
||||
TaskManager.IMP.repeat(lag, 100);
|
||||
}
|
||||
|
||||
private void setupEvents() {
|
||||
@ -336,28 +331,38 @@ public class Fawe {
|
||||
if (Settings.MEM_FREE < 1) {
|
||||
return;
|
||||
}
|
||||
final MemoryMXBean memBean = ManagementFactory.getMemoryMXBean();
|
||||
final NotificationEmitter ne = (NotificationEmitter) memBean;
|
||||
try {
|
||||
final MemoryMXBean memBean = ManagementFactory.getMemoryMXBean();
|
||||
final NotificationEmitter ne = (NotificationEmitter) memBean;
|
||||
|
||||
ne.addNotificationListener(new NotificationListener() {
|
||||
@Override
|
||||
public void handleNotification(final Notification notification, final Object handback) {
|
||||
MemUtil.memoryLimitedTask();
|
||||
}
|
||||
}, null, null);
|
||||
|
||||
final List<MemoryPoolMXBean> memPools = ManagementFactory.getMemoryPoolMXBeans();
|
||||
for (final MemoryPoolMXBean mp : memPools) {
|
||||
if (mp.isUsageThresholdSupported()) {
|
||||
final MemoryUsage mu = mp.getUsage();
|
||||
final long max = mu.getMax();
|
||||
if (max < 0) {
|
||||
continue;
|
||||
ne.addNotificationListener(new NotificationListener() {
|
||||
@Override
|
||||
public void handleNotification(final Notification notification, final Object handback) {
|
||||
MemUtil.memoryLimitedTask();
|
||||
}
|
||||
final long alert = (max * Settings.MEM_FREE) / 100;
|
||||
mp.setUsageThreshold(alert);
|
||||
}, null, null);
|
||||
|
||||
final List<MemoryPoolMXBean> memPools = ManagementFactory.getMemoryPoolMXBeans();
|
||||
for (final MemoryPoolMXBean mp : memPools) {
|
||||
if (mp.isUsageThresholdSupported()) {
|
||||
final MemoryUsage mu = mp.getUsage();
|
||||
final long max = mu.getMax();
|
||||
if (max < 0) {
|
||||
continue;
|
||||
}
|
||||
final long alert = (max * Settings.MEM_FREE) / 100;
|
||||
mp.setUsageThreshold(alert);
|
||||
|
||||
}
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
debug("====== MEMORY LISTENER ERROR ======");
|
||||
e.printStackTrace();
|
||||
debug("===================================");
|
||||
debug("FAWE needs access to the JVM memory system:");
|
||||
debug(" - Change your Java security settings");
|
||||
debug(" - Disable this with `max-memory-percent: -1`");
|
||||
debug("===================================");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -37,8 +37,10 @@ public class Settings {
|
||||
public static int UNSAFE_PARALLEL_THREADS = 1;
|
||||
public static boolean FIX_ALL_LIGHTING = true;
|
||||
public static boolean ASYNC_LIGHTING = true;
|
||||
public static int PHYSICS_PER_TICK = 1337;
|
||||
public static int ITEMS_PER_TICK = 1337;
|
||||
public static int PHYSICS_PER_TICK = 500000;
|
||||
public static int ITEMS_PER_TICK = 50000;
|
||||
|
||||
public static boolean COMBINE_HISTORY_STAGE = true;
|
||||
|
||||
public static HashMap<String, FaweLimit> limits;
|
||||
|
||||
@ -103,6 +105,9 @@ public class Settings {
|
||||
options.put("extent.debug", EXTENT_DEBUG);
|
||||
options.put("metrics", METRICS);
|
||||
|
||||
if (config.getInt("tick-limiter.physics") == 1337) {
|
||||
config.set("tick-limiter.physics", PHYSICS_PER_TICK);
|
||||
}
|
||||
options.put("tick-limiter.physics", PHYSICS_PER_TICK);
|
||||
options.put("tick-limiter.items", ITEMS_PER_TICK);
|
||||
|
||||
|
@ -1,11 +1,18 @@
|
||||
package com.boydti.fawe.example;
|
||||
|
||||
import com.boydti.fawe.FaweCache;
|
||||
import com.boydti.fawe.object.BytePair;
|
||||
import com.boydti.fawe.object.FaweChunk;
|
||||
import com.boydti.fawe.util.FaweQueue;
|
||||
import com.boydti.fawe.util.MainUtil;
|
||||
import com.boydti.fawe.util.MathMan;
|
||||
import com.sk89q.jnbt.CompoundTag;
|
||||
import com.sk89q.worldedit.world.biome.BaseBiome;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
public abstract class CharFaweChunk<T> extends FaweChunk<T> {
|
||||
|
||||
@ -112,6 +119,50 @@ public abstract class CharFaweChunk<T> extends FaweChunk<T> {
|
||||
return this.biomes;
|
||||
}
|
||||
|
||||
public HashMap<BytePair, CompoundTag> tiles;
|
||||
|
||||
@Override
|
||||
public void setTile(int x, int y, int z, CompoundTag tile) {
|
||||
if (tiles == null) {
|
||||
tiles = new HashMap<>();
|
||||
}
|
||||
byte i = MathMan.pair16((byte) x, (byte) z);
|
||||
byte j = (byte) y;
|
||||
BytePair pair = new BytePair(i, j);
|
||||
tiles.put(pair, tile);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompoundTag getTile(int x, int y, int z) {
|
||||
if (tiles == null) {
|
||||
return null;
|
||||
}
|
||||
byte i = MathMan.pair16((byte) x, (byte) z);
|
||||
byte j = (byte) y;
|
||||
BytePair pair = new BytePair(i, j);
|
||||
return tiles.get(pair);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<BytePair, CompoundTag> getTiles() {
|
||||
return tiles == null ? new HashMap<BytePair, CompoundTag>() : tiles;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<CompoundTag> getEntities() {
|
||||
return entities == null ? new HashSet<CompoundTag>() : entities;
|
||||
}
|
||||
|
||||
public HashSet<CompoundTag> entities;
|
||||
|
||||
@Override
|
||||
public void setEntity(CompoundTag tag) {
|
||||
if (entities == null) {
|
||||
entities = new HashSet<>();
|
||||
}
|
||||
entities.add(tag);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBlock(final int x, final int y, final int z, final int id, byte data) {
|
||||
final int i = FaweCache.CACHE_I[y][x][z];
|
||||
|
@ -1,254 +0,0 @@
|
||||
package com.boydti.fawe.example;
|
||||
|
||||
import com.boydti.fawe.FaweCache;
|
||||
import com.boydti.fawe.object.FaweChunk;
|
||||
import com.boydti.fawe.util.FaweQueue;
|
||||
import com.boydti.fawe.util.MainUtil;
|
||||
import com.sk89q.worldedit.world.biome.BaseBiome;
|
||||
import java.util.Arrays;
|
||||
|
||||
public abstract class IntFaweChunk<T> extends FaweChunk<T> {
|
||||
|
||||
private int[][] ids;
|
||||
|
||||
private short[] count;
|
||||
private short[] air;
|
||||
private short[] relight;
|
||||
private int[][] biomes;
|
||||
|
||||
private T chunk;
|
||||
|
||||
/**
|
||||
* A FaweSections object represents a chunk and the blocks that you wish to change in it.
|
||||
*
|
||||
* @param parent
|
||||
* @param x
|
||||
* @param z
|
||||
*/
|
||||
public IntFaweChunk(FaweQueue parent, int x, int z) {
|
||||
super(parent, x, z);
|
||||
this.ids = new int[16][];
|
||||
this.count = new short[16];
|
||||
this.air = new short[16];
|
||||
this.relight = new short[16];
|
||||
}
|
||||
|
||||
@Override
|
||||
public T getChunk() {
|
||||
if (this.chunk == null) {
|
||||
this.chunk = getNewChunk();
|
||||
}
|
||||
return this.chunk;
|
||||
}
|
||||
|
||||
public abstract T getNewChunk();
|
||||
|
||||
@Override
|
||||
public void setLoc(final FaweQueue parent, int x, int z) {
|
||||
super.setLoc(parent, x, z);
|
||||
this.chunk = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of block changes in a specified section
|
||||
* @param i
|
||||
* @return
|
||||
*/
|
||||
public int getCount(final int i) {
|
||||
return this.count[i];
|
||||
}
|
||||
|
||||
public int getAir(final int i) {
|
||||
return this.air[i];
|
||||
}
|
||||
|
||||
public void setCount(final int i, final short value) {
|
||||
this.count[i] = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of block changes in a specified section
|
||||
* @param i
|
||||
* @return
|
||||
*/
|
||||
public int getRelight(final int i) {
|
||||
return this.relight[i];
|
||||
}
|
||||
|
||||
public int getTotalCount() {
|
||||
int total = 0;
|
||||
for (int i = 0; i < 16; i++) {
|
||||
total += this.count[i];
|
||||
}
|
||||
return total;
|
||||
}
|
||||
|
||||
public int getTotalRelight() {
|
||||
if ((this.getTotalCount() == 0) && (this.biomes == null)) {
|
||||
Arrays.fill(this.count, (short) 1);
|
||||
Arrays.fill(this.relight, Short.MAX_VALUE);
|
||||
return Short.MAX_VALUE;
|
||||
}
|
||||
int total = 0;
|
||||
for (int i = 0; i < 16; i++) {
|
||||
total += this.relight[i];
|
||||
}
|
||||
return total;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the raw data for a section
|
||||
* @param i
|
||||
* @return
|
||||
*/
|
||||
public int[] getIdArray(final int i) {
|
||||
return this.ids[i];
|
||||
}
|
||||
|
||||
public int[][] getIdArrays() {
|
||||
return this.ids;
|
||||
}
|
||||
|
||||
public int[][] getBiomeArray() {
|
||||
return this.biomes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBlock(final int x, final int y, final int z, final int id, byte data) {
|
||||
final int i = FaweCache.CACHE_I[y][x][z];
|
||||
final int j = FaweCache.CACHE_J[y][x][z];
|
||||
int[] vs = this.ids[i];
|
||||
if (vs == null) {
|
||||
vs = this.ids[i] = new int[4096];
|
||||
this.count[i]++;
|
||||
} else if (vs[j] == 0) {
|
||||
this.count[i]++;
|
||||
}
|
||||
switch (id) {
|
||||
case 0:
|
||||
this.air[i]++;
|
||||
vs[j] = -1;
|
||||
return;
|
||||
case 10:
|
||||
case 11:
|
||||
case 39:
|
||||
case 40:
|
||||
case 51:
|
||||
case 74:
|
||||
case 89:
|
||||
case 122:
|
||||
case 124:
|
||||
case 138:
|
||||
case 169:
|
||||
this.relight[i]++;
|
||||
case 2:
|
||||
case 4:
|
||||
case 13:
|
||||
case 14:
|
||||
case 15:
|
||||
case 20:
|
||||
case 21:
|
||||
case 22:
|
||||
case 30:
|
||||
case 32:
|
||||
case 37:
|
||||
case 41:
|
||||
case 42:
|
||||
case 45:
|
||||
case 46:
|
||||
case 47:
|
||||
case 48:
|
||||
case 49:
|
||||
case 56:
|
||||
case 57:
|
||||
case 58:
|
||||
case 60:
|
||||
case 7:
|
||||
case 8:
|
||||
case 9:
|
||||
case 73:
|
||||
case 78:
|
||||
case 79:
|
||||
case 80:
|
||||
case 81:
|
||||
case 82:
|
||||
case 83:
|
||||
case 85:
|
||||
case 87:
|
||||
case 88:
|
||||
case 101:
|
||||
case 102:
|
||||
case 103:
|
||||
case 110:
|
||||
case 112:
|
||||
case 113:
|
||||
case 121:
|
||||
case 129:
|
||||
case 133:
|
||||
case 165:
|
||||
case 166:
|
||||
case 170:
|
||||
case 172:
|
||||
case 173:
|
||||
case 174:
|
||||
case 181:
|
||||
case 182:
|
||||
case 188:
|
||||
case 189:
|
||||
case 190:
|
||||
case 191:
|
||||
case 192:
|
||||
vs[j] = (id);
|
||||
return;
|
||||
case 130:
|
||||
case 50:
|
||||
case 76:
|
||||
case 62:
|
||||
this.relight[i]++;
|
||||
case 54:
|
||||
case 146:
|
||||
case 61:
|
||||
case 65:
|
||||
case 68:
|
||||
// if (data < 2) {
|
||||
// data = 2;
|
||||
// }
|
||||
default:
|
||||
vs[j] = id + (data << 12);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBiome(final int x, final int z, final BaseBiome biome) {
|
||||
if (this.biomes == null) {
|
||||
this.biomes = new int[16][];
|
||||
}
|
||||
int[] index = this.biomes[x];
|
||||
if (index == null) {
|
||||
index = this.biomes[x] = new int[16];
|
||||
}
|
||||
index[z] = biome.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public IntFaweChunk<T> copy(boolean shallow) {
|
||||
IntFaweChunk<T> copy = (IntFaweChunk<T>) getParent().getChunk(getX(), getZ());
|
||||
if (shallow) {
|
||||
copy.ids = ids;
|
||||
copy.air = air;
|
||||
copy.biomes = biomes;
|
||||
copy.chunk = chunk;
|
||||
copy.count = count;
|
||||
copy.relight = relight;
|
||||
} else {
|
||||
copy.ids = (int[][]) MainUtil.copyNd(ids);
|
||||
copy.air = air.clone();
|
||||
copy.biomes = biomes.clone();
|
||||
copy.chunk = chunk;
|
||||
copy.count = count.clone();
|
||||
copy.relight = relight.clone();
|
||||
}
|
||||
return copy;
|
||||
}
|
||||
}
|
@ -7,8 +7,11 @@ import com.boydti.fawe.object.IntegerPair;
|
||||
import com.boydti.fawe.object.RunnableVal;
|
||||
import com.boydti.fawe.object.exception.FaweException;
|
||||
import com.boydti.fawe.util.FaweQueue;
|
||||
import com.boydti.fawe.util.SetQueue;
|
||||
import com.boydti.fawe.util.TaskManager;
|
||||
import com.sk89q.jnbt.CompoundTag;
|
||||
import com.sk89q.worldedit.world.biome.BaseBiome;
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
@ -23,6 +26,7 @@ public abstract class MappedFaweQueue<WORLD, CHUNK, SECTION> extends FaweQueue {
|
||||
*/
|
||||
private ConcurrentHashMap<Long, FaweChunk> blocks = new ConcurrentHashMap<>();
|
||||
private LinkedBlockingDeque<FaweChunk> chunks = new LinkedBlockingDeque<>();
|
||||
private ArrayDeque<Runnable> tasks = new ArrayDeque<>();
|
||||
|
||||
@Override
|
||||
public void optimize() {
|
||||
@ -46,6 +50,11 @@ public abstract class MappedFaweQueue<WORLD, CHUNK, SECTION> extends FaweQueue {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addNotifyTask(Runnable runnable) {
|
||||
this.tasks.add(runnable);
|
||||
}
|
||||
|
||||
public MappedFaweQueue(final String world) {
|
||||
super(world);
|
||||
}
|
||||
@ -58,7 +67,7 @@ public abstract class MappedFaweQueue<WORLD, CHUNK, SECTION> extends FaweQueue {
|
||||
|
||||
public abstract void sendChunk(FaweChunk chunk);
|
||||
|
||||
public abstract boolean setComponents(FaweChunk fc);
|
||||
public abstract boolean setComponents(FaweChunk fc, RunnableVal<FaweChunk> changeTask);
|
||||
|
||||
@Override
|
||||
public abstract FaweChunk getChunk(int x, int z);
|
||||
@ -88,12 +97,12 @@ public abstract class MappedFaweQueue<WORLD, CHUNK, SECTION> extends FaweQueue {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addTask(int x, int z, Runnable runnable) {
|
||||
public void addNotifyTask(int x, int z, Runnable runnable) {
|
||||
long pair = (long) (x) << 32 | (z) & 0xFFFFFFFFL;
|
||||
FaweChunk result = this.blocks.get(pair);
|
||||
if (result == null) {
|
||||
result = this.getChunk(x, z);
|
||||
result.addTask(runnable);
|
||||
result.addNotifyTask(runnable);
|
||||
FaweChunk previous = this.blocks.put(pair, result);
|
||||
if (previous == null) {
|
||||
chunks.add(result);
|
||||
@ -102,9 +111,11 @@ public abstract class MappedFaweQueue<WORLD, CHUNK, SECTION> extends FaweQueue {
|
||||
this.blocks.put(pair, previous);
|
||||
result = previous;
|
||||
}
|
||||
result.addTask(runnable);
|
||||
result.addNotifyTask(runnable);
|
||||
}
|
||||
|
||||
|
||||
|
||||
private FaweChunk lastWrappedChunk;
|
||||
private int lastX = Integer.MIN_VALUE;
|
||||
private int lastZ = Integer.MIN_VALUE;
|
||||
@ -137,6 +148,60 @@ public abstract class MappedFaweQueue<WORLD, CHUNK, SECTION> extends FaweQueue {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTile(int x, int y, int z, CompoundTag tag) {
|
||||
if ((y > 255) || (y < 0)) {
|
||||
return;
|
||||
}
|
||||
int cx = x >> 4;
|
||||
int cz = z >> 4;
|
||||
if (cx != lastX || cz != lastZ) {
|
||||
lastX = cx;
|
||||
lastZ = cz;
|
||||
long pair = (long) (cx) << 32 | (cz) & 0xFFFFFFFFL;
|
||||
lastWrappedChunk = this.blocks.get(pair);
|
||||
if (lastWrappedChunk == null) {
|
||||
lastWrappedChunk = this.getChunk(x >> 4, z >> 4);
|
||||
lastWrappedChunk.setTile(x & 15, y, z & 15, tag);
|
||||
FaweChunk previous = this.blocks.put(pair, lastWrappedChunk);
|
||||
if (previous == null) {
|
||||
chunks.add(lastWrappedChunk);
|
||||
return;
|
||||
}
|
||||
this.blocks.put(pair, previous);
|
||||
lastWrappedChunk = previous;
|
||||
}
|
||||
}
|
||||
lastWrappedChunk.setTile(x & 15, y, z & 15, tag);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setEntity(int x, int y, int z, CompoundTag tag) {
|
||||
if ((y > 255) || (y < 0)) {
|
||||
return;
|
||||
}
|
||||
int cx = x >> 4;
|
||||
int cz = z >> 4;
|
||||
if (cx != lastX || cz != lastZ) {
|
||||
lastX = cx;
|
||||
lastZ = cz;
|
||||
long pair = (long) (cx) << 32 | (cz) & 0xFFFFFFFFL;
|
||||
lastWrappedChunk = this.blocks.get(pair);
|
||||
if (lastWrappedChunk == null) {
|
||||
lastWrappedChunk = this.getChunk(x >> 4, z >> 4);
|
||||
lastWrappedChunk.setEntity(tag);
|
||||
FaweChunk previous = this.blocks.put(pair, lastWrappedChunk);
|
||||
if (previous == null) {
|
||||
chunks.add(lastWrappedChunk);
|
||||
return;
|
||||
}
|
||||
this.blocks.put(pair, previous);
|
||||
lastWrappedChunk = previous;
|
||||
}
|
||||
}
|
||||
lastWrappedChunk.setEntity(tag);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setBiome(int x, int z, BaseBiome biome) {
|
||||
long pair = (long) (x >> 4) << 32 | (z >> 4) & 0xFFFFFFFFL;
|
||||
@ -177,22 +242,41 @@ public abstract class MappedFaweQueue<WORLD, CHUNK, SECTION> extends FaweQueue {
|
||||
return null;
|
||||
}
|
||||
|
||||
public void runTasks() {
|
||||
for (Runnable run : tasks) {
|
||||
run.run();
|
||||
}
|
||||
tasks.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
if (chunks.size() == 0 && SetQueue.IMP.isStage(this, SetQueue.QueueStage.ACTIVE)) {
|
||||
runTasks();
|
||||
}
|
||||
return chunks.size();
|
||||
}
|
||||
|
||||
private LinkedBlockingDeque<FaweChunk> toUpdate = new LinkedBlockingDeque<>();
|
||||
|
||||
public boolean execute(FaweChunk fc) {
|
||||
public boolean execute(final FaweChunk fc) {
|
||||
if (fc == null) {
|
||||
return false;
|
||||
}
|
||||
// Set blocks / entities / biome
|
||||
if (!this.setComponents(fc)) {
|
||||
if (getChangeTask() != null) {
|
||||
if (!this.setComponents(fc, new RunnableVal<FaweChunk>() {
|
||||
@Override
|
||||
public void run(FaweChunk before) {
|
||||
getChangeTask().run(before, fc);
|
||||
}
|
||||
})) {
|
||||
return false;
|
||||
}
|
||||
} else if (!this.setComponents(fc, null)) {
|
||||
return false;
|
||||
}
|
||||
fc.executeTasks();
|
||||
fc.executeNotifyTasks();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -31,9 +31,6 @@ public abstract class NMSMappedFaweQueue<WORLD, CHUNK, CHUNKSECTION, SECTION> ex
|
||||
|
||||
public abstract void refreshChunk(WORLD world, CHUNK chunk);
|
||||
|
||||
@Override
|
||||
public abstract boolean setComponents(FaweChunk fc);
|
||||
|
||||
@Override
|
||||
public abstract boolean fixLighting(FaweChunk fc, boolean fixAll);
|
||||
}
|
||||
|
33
core/src/main/java/com/boydti/fawe/object/BytePair.java
Normal file
33
core/src/main/java/com/boydti/fawe/object/BytePair.java
Normal file
@ -0,0 +1,33 @@
|
||||
package com.boydti.fawe.object;
|
||||
|
||||
public class BytePair {
|
||||
public byte[] pair;
|
||||
|
||||
public BytePair(final byte x, final byte z) {
|
||||
this.pair = new byte[] { x, z};
|
||||
}
|
||||
|
||||
int hash;
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return pair[0] + (pair[1] << 8);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return pair[0] + "," + pair[1];
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(final Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if ((obj == null) || (this.hashCode() != obj.hashCode()) || (this.getClass() != obj.getClass())) {
|
||||
return false;
|
||||
}
|
||||
final BytePair other = (BytePair) obj;
|
||||
return pair[0] == other.pair[0] && pair[1] == other.pair[1];
|
||||
}
|
||||
}
|
@ -2,8 +2,11 @@ package com.boydti.fawe.object;
|
||||
|
||||
import com.boydti.fawe.config.Settings;
|
||||
import com.boydti.fawe.util.FaweQueue;
|
||||
import com.sk89q.jnbt.CompoundTag;
|
||||
import com.sk89q.worldedit.world.biome.BaseBiome;
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
public abstract class FaweChunk<T> {
|
||||
|
||||
@ -56,6 +59,8 @@ public abstract class FaweChunk<T> {
|
||||
parent.fixLighting(this, Settings.FIX_ALL_LIGHTING);
|
||||
}
|
||||
|
||||
public abstract char[][] getIdArrays();
|
||||
|
||||
/**
|
||||
* Fill this chunk with a block
|
||||
* @param id
|
||||
@ -86,13 +91,17 @@ public abstract class FaweChunk<T> {
|
||||
}
|
||||
}
|
||||
|
||||
public void addTask(Runnable run) {
|
||||
public void addNotifyTask(Runnable run) {
|
||||
if (run != null) {
|
||||
tasks.add(run);
|
||||
}
|
||||
}
|
||||
|
||||
public void executeTasks() {
|
||||
|
||||
public boolean hasNotifyTasks() {
|
||||
return tasks.size() > 0;
|
||||
}
|
||||
|
||||
public void executeNotifyTasks() {
|
||||
for (Runnable task : tasks) {
|
||||
task.run();
|
||||
}
|
||||
@ -101,8 +110,18 @@ public abstract class FaweChunk<T> {
|
||||
|
||||
public abstract T getChunk();
|
||||
|
||||
public abstract void setTile(int x, int y, int z, CompoundTag tile);
|
||||
|
||||
public abstract void setEntity(CompoundTag entity);
|
||||
|
||||
public abstract void setBlock(final int x, final int y, final int z, final int id, final byte data);
|
||||
|
||||
public abstract CompoundTag getTile(int x, int y, int z);
|
||||
|
||||
public abstract Set<CompoundTag> getEntities();
|
||||
|
||||
public abstract Map<BytePair, CompoundTag> getTiles();
|
||||
|
||||
public abstract void setBiome(final int x, final int z, final BaseBiome biome);
|
||||
|
||||
public void optimize() {}
|
||||
|
@ -5,6 +5,7 @@ import com.boydti.fawe.FaweAPI;
|
||||
import com.boydti.fawe.config.BBC;
|
||||
import com.boydti.fawe.config.Settings;
|
||||
import com.boydti.fawe.object.changeset.DiskStorageHistory;
|
||||
import com.boydti.fawe.object.changeset.FaweStreamChangeSet;
|
||||
import com.boydti.fawe.object.clipboard.DiskOptimizedClipboard;
|
||||
import com.boydti.fawe.util.TaskManager;
|
||||
import com.boydti.fawe.util.WEManager;
|
||||
@ -169,7 +170,7 @@ public abstract class FawePlayer<T> {
|
||||
Collections.sort(editIds);
|
||||
for (int i = editIds.size() - 1; i >= 0; i--) {
|
||||
int index = editIds.get(i);
|
||||
DiskStorageHistory set = new DiskStorageHistory(world, uuid, index);
|
||||
FaweStreamChangeSet set = new DiskStorageHistory(world, uuid, index);
|
||||
EditSession edit = set.toEditSession(getPlayer());
|
||||
if (world.equals(getWorld())) {
|
||||
session.remember(edit, false);
|
||||
|
@ -41,9 +41,9 @@ public class HistoryExtent extends AbstractDelegateExtent {
|
||||
*/
|
||||
public HistoryExtent(final EditSession session, FaweLimit limit, final Extent extent, final FaweChangeSet changeSet, FaweQueue queue) {
|
||||
super(extent);
|
||||
checkNotNull(changeSet);
|
||||
this.limit = limit;
|
||||
this.queue = queue;
|
||||
checkNotNull(changeSet);
|
||||
this.changeSet = changeSet;
|
||||
this.session = session;
|
||||
}
|
||||
|
@ -1,48 +1,49 @@
|
||||
package com.boydti.fawe.object;
|
||||
|
||||
import com.boydti.fawe.object.changeset.FaweChangeSet;
|
||||
import com.sk89q.worldedit.Vector;
|
||||
import com.sk89q.worldedit.blocks.BaseBlock;
|
||||
import com.sk89q.jnbt.CompoundTag;
|
||||
import com.sk89q.worldedit.history.change.Change;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
|
||||
public class NullChangeSet implements FaweChangeSet {
|
||||
|
||||
@Override
|
||||
public void add(Change change) {}
|
||||
|
||||
@Override
|
||||
public Iterator<Change> backwardIterator() {
|
||||
return new ArrayList<Change>().iterator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<Change> forwardIterator() {
|
||||
return new ArrayList<Change>().iterator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public class NullChangeSet extends FaweChangeSet {
|
||||
@Override
|
||||
public boolean flush() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCompressedSize() {
|
||||
return 0;
|
||||
public void add(int x, int y, int z, int combinedFrom, int combinedTo) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void add(Vector location, BaseBlock from, BaseBlock to) {}
|
||||
public void addTileCreate(CompoundTag tag) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void add(int x, int y, int z, int combinedId4DataFrom, BaseBlock to) {}
|
||||
public void addTileRemove(CompoundTag tag) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void add(int x, int y, int z, int combinedId4DataFrom, int combinedId4DataTo) {}
|
||||
public void addEntityRemove(CompoundTag tag) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addEntityCreate(CompoundTag tag) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<Change> getIterator(boolean undo) {
|
||||
return new ArrayList<Change>().iterator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,46 @@
|
||||
package com.boydti.fawe.object.change;
|
||||
|
||||
import com.boydti.fawe.Fawe;
|
||||
import com.boydti.fawe.object.extent.FastWorldEditExtent;
|
||||
import com.sk89q.worldedit.WorldEditException;
|
||||
import com.sk89q.worldedit.extent.Extent;
|
||||
import com.sk89q.worldedit.history.UndoContext;
|
||||
import com.sk89q.worldedit.history.change.Change;
|
||||
|
||||
public class MutableBlockChange implements Change {
|
||||
|
||||
public int z;
|
||||
public int y;
|
||||
public int x;
|
||||
public short id;
|
||||
public byte data;
|
||||
|
||||
|
||||
public MutableBlockChange(int x, int y, int z, short id, byte data) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
this.id = id;
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void undo(UndoContext context) throws WorldEditException {
|
||||
create(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void redo(UndoContext context) throws WorldEditException {
|
||||
create(context);
|
||||
}
|
||||
|
||||
public void create(UndoContext context) {
|
||||
Extent extent = context.getExtent();
|
||||
if (extent.getClass() == FastWorldEditExtent.class) {
|
||||
FastWorldEditExtent fwee = (FastWorldEditExtent) extent;
|
||||
fwee.getQueue().setBlock(x, y, z, id, data);
|
||||
} else {
|
||||
Fawe.debug("FAWE doesn't support: " + extent + " for " + getClass() + " (bug Empire92)");
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,53 @@
|
||||
package com.boydti.fawe.object.change;
|
||||
|
||||
import com.boydti.fawe.Fawe;
|
||||
import com.boydti.fawe.object.extent.FastWorldEditExtent;
|
||||
import com.sk89q.jnbt.CompoundTag;
|
||||
import com.sk89q.jnbt.DoubleTag;
|
||||
import com.sk89q.jnbt.Tag;
|
||||
import com.sk89q.worldedit.WorldEditException;
|
||||
import com.sk89q.worldedit.extent.Extent;
|
||||
import com.sk89q.worldedit.history.UndoContext;
|
||||
import com.sk89q.worldedit.history.change.Change;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class MutableEntityChange implements Change {
|
||||
|
||||
public CompoundTag tag;
|
||||
public boolean create;
|
||||
|
||||
public MutableEntityChange(CompoundTag tag, boolean create) {
|
||||
this.tag = tag;
|
||||
this.create = create;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void undo(UndoContext context) throws WorldEditException {
|
||||
if (!create) {
|
||||
create(context);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void redo(UndoContext context) throws WorldEditException {
|
||||
if (create) {
|
||||
create(context);
|
||||
}
|
||||
}
|
||||
|
||||
public void create(UndoContext context) {
|
||||
Extent extent = context.getExtent();
|
||||
if (extent.getClass() == FastWorldEditExtent.class) {
|
||||
FastWorldEditExtent fwee = (FastWorldEditExtent) extent;
|
||||
Map<String, Tag> map = tag.getValue();
|
||||
List<DoubleTag> pos = (List<DoubleTag>) map.get("Pos").getValue();
|
||||
int x = (int) Math.round(pos.get(0).getValue());
|
||||
int y = (int) Math.round(pos.get(1).getValue());
|
||||
int z = (int) Math.round(pos.get(2).getValue());
|
||||
fwee.getQueue().setEntity(x, y, z, tag);
|
||||
} else {
|
||||
Fawe.debug("FAWE doesn't support: " + context + " for " + getClass() + " (bug Empire92)");
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,51 @@
|
||||
package com.boydti.fawe.object.change;
|
||||
|
||||
import com.boydti.fawe.Fawe;
|
||||
import com.boydti.fawe.object.extent.FastWorldEditExtent;
|
||||
import com.sk89q.jnbt.CompoundTag;
|
||||
import com.sk89q.jnbt.IntTag;
|
||||
import com.sk89q.jnbt.Tag;
|
||||
import com.sk89q.worldedit.WorldEditException;
|
||||
import com.sk89q.worldedit.extent.Extent;
|
||||
import com.sk89q.worldedit.history.UndoContext;
|
||||
import com.sk89q.worldedit.history.change.Change;
|
||||
import java.util.Map;
|
||||
|
||||
public class MutableTileChange implements Change {
|
||||
|
||||
public CompoundTag tag;
|
||||
public boolean create;
|
||||
|
||||
public MutableTileChange(CompoundTag tag, boolean create) {
|
||||
this.tag = tag;
|
||||
this.create = create;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void undo(UndoContext context) throws WorldEditException {
|
||||
if (!create) {
|
||||
create(context);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void redo(UndoContext context) throws WorldEditException {
|
||||
if (create) {
|
||||
create(context);
|
||||
}
|
||||
}
|
||||
|
||||
public void create(UndoContext context) {
|
||||
Extent extent = context.getExtent();
|
||||
if (extent.getClass() == FastWorldEditExtent.class) {
|
||||
FastWorldEditExtent fwee = (FastWorldEditExtent) extent;
|
||||
Map<String, Tag> map = tag.getValue();
|
||||
int x = ((IntTag) map.get("x")).getValue();
|
||||
int y = ((IntTag) map.get("y")).getValue();
|
||||
int z = ((IntTag) map.get("z")).getValue();
|
||||
fwee.getQueue().setTile(x, y, z, tag);
|
||||
} else {
|
||||
Fawe.debug("FAWE doesn't support: " + context + " for " + getClass());
|
||||
}
|
||||
}
|
||||
}
|
@ -1,30 +1,11 @@
|
||||
package com.boydti.fawe.object.changeset;
|
||||
|
||||
import com.boydti.fawe.Fawe;
|
||||
import com.boydti.fawe.FaweCache;
|
||||
import com.boydti.fawe.config.Settings;
|
||||
import com.boydti.fawe.object.IntegerPair;
|
||||
import com.boydti.fawe.object.RegionWrapper;
|
||||
import com.boydti.fawe.util.MainUtil;
|
||||
import com.boydti.fawe.util.ReflectionUtils;
|
||||
import com.sk89q.jnbt.CompoundTag;
|
||||
import com.sk89q.jnbt.IntTag;
|
||||
import com.sk89q.jnbt.NBTInputStream;
|
||||
import com.sk89q.jnbt.NBTOutputStream;
|
||||
import com.sk89q.jnbt.NamedTag;
|
||||
import com.sk89q.jnbt.Tag;
|
||||
import com.sk89q.worldedit.BlockVector;
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
import com.sk89q.worldedit.EditSessionFactory;
|
||||
import com.sk89q.worldedit.Vector;
|
||||
import com.sk89q.worldedit.WorldEdit;
|
||||
import com.sk89q.worldedit.blocks.BaseBlock;
|
||||
import com.sk89q.worldedit.entity.Player;
|
||||
import com.sk89q.worldedit.history.change.BlockChange;
|
||||
import com.sk89q.worldedit.history.change.Change;
|
||||
import com.sk89q.worldedit.history.change.EntityCreate;
|
||||
import com.sk89q.worldedit.history.change.EntityRemove;
|
||||
import com.sk89q.worldedit.history.changeset.ChangeSet;
|
||||
import com.sk89q.worldedit.world.World;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
@ -32,18 +13,14 @@ import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.zip.GZIPInputStream;
|
||||
import java.util.zip.GZIPOutputStream;
|
||||
import net.jpountz.lz4.LZ4Compressor;
|
||||
import net.jpountz.lz4.LZ4Factory;
|
||||
import net.jpountz.lz4.LZ4InputStream;
|
||||
import net.jpountz.lz4.LZ4OutputStream;
|
||||
|
||||
/**
|
||||
* Store the change on disk
|
||||
@ -52,7 +29,7 @@ import net.jpountz.lz4.LZ4OutputStream;
|
||||
* - Minimal memory usage
|
||||
* - Slow
|
||||
*/
|
||||
public class DiskStorageHistory implements ChangeSet, FaweChangeSet {
|
||||
public class DiskStorageHistory extends FaweStreamChangeSet {
|
||||
|
||||
private UUID uuid;
|
||||
private File bdFile;
|
||||
@ -60,7 +37,12 @@ public class DiskStorageHistory implements ChangeSet, FaweChangeSet {
|
||||
private File nbttFile;
|
||||
private File entfFile;
|
||||
private File enttFile;
|
||||
|
||||
|
||||
/**
|
||||
* Summary of this change (not accurate for larger edits)
|
||||
*/
|
||||
private DiskStorageSummary summary;
|
||||
|
||||
/*
|
||||
* Block data
|
||||
*
|
||||
@ -80,22 +62,15 @@ public class DiskStorageHistory implements ChangeSet, FaweChangeSet {
|
||||
// NBT To
|
||||
private NBTOutputStream osNBTT;
|
||||
private GZIPOutputStream osNBTTG;
|
||||
private AtomicInteger osNBTTI;
|
||||
|
||||
// Entity From
|
||||
private NBTOutputStream osENTF;
|
||||
private GZIPOutputStream osENTFG;
|
||||
private AtomicInteger osENTFI;
|
||||
|
||||
// Entity To
|
||||
private NBTOutputStream osENTT;
|
||||
private GZIPOutputStream osENTTG;
|
||||
private AtomicInteger osENTTI;
|
||||
|
||||
private int ox;
|
||||
private int oz;
|
||||
// Entity Create From
|
||||
private NBTOutputStream osENTCF;
|
||||
private GZIPOutputStream osENTCFG;
|
||||
|
||||
// Entity Create To
|
||||
private NBTOutputStream osENTCT;
|
||||
private GZIPOutputStream osENTCTG;
|
||||
|
||||
private int size;
|
||||
private World world;
|
||||
|
||||
public void deleteFiles() {
|
||||
@ -148,23 +123,6 @@ public class DiskStorageHistory implements ChangeSet, FaweChangeSet {
|
||||
return bdFile;
|
||||
}
|
||||
|
||||
public EditSession toEditSession(Player player) {
|
||||
EditSessionFactory factory = WorldEdit.getInstance().getEditSessionFactory();
|
||||
EditSession edit = factory.getEditSession(world, -1, null, player);
|
||||
edit.setChangeSet(this);
|
||||
edit.dequeue();
|
||||
return edit;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void add(Change change) {
|
||||
if ((change instanceof BlockChange)) {
|
||||
add((BlockChange) change);
|
||||
} else {
|
||||
Fawe.debug("Does not support " + change + " yet! (Please bug Empire92)");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean flush() {
|
||||
boolean flushed = false;
|
||||
@ -201,123 +159,63 @@ public class DiskStorageHistory implements ChangeSet, FaweChangeSet {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void add(int x, int y, int z, int combinedFrom, int combinedTo) {
|
||||
size++;
|
||||
try {
|
||||
OutputStream stream = getBAOS(x, y, z);
|
||||
//x
|
||||
x-=ox;
|
||||
stream.write((x) & 0xff);
|
||||
stream.write(((x) >> 8) & 0xff);
|
||||
//z
|
||||
z-=oz;
|
||||
stream.write((z) & 0xff);
|
||||
stream.write(((z) >> 8) & 0xff);
|
||||
//y
|
||||
stream.write((byte) y);
|
||||
//from
|
||||
stream.write((combinedFrom) & 0xff);
|
||||
stream.write(((combinedFrom) >> 8) & 0xff);
|
||||
//to
|
||||
stream.write((combinedTo) & 0xff);
|
||||
stream.write(((combinedTo) >> 8) & 0xff);
|
||||
}
|
||||
catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void add(int x, int y, int z, int combinedId4DataFrom, BaseBlock to) {
|
||||
int idTo = to.getId();
|
||||
int combinedTo = (FaweCache.hasData(idTo) ? ((idTo << 4) + to.getData()) : (idTo << 4));
|
||||
CompoundTag nbtTo = FaweCache.hasNBT(idTo) ? to.getNbtData() : null;
|
||||
add(x, y, z, combinedId4DataFrom, combinedTo);
|
||||
if (nbtTo != null && MainUtil.isValidTag(nbtTo)) {
|
||||
try {
|
||||
Map<String, Tag> value = ReflectionUtils.getMap(nbtTo.getValue());
|
||||
value.put("x", new IntTag(x));
|
||||
value.put("y", new IntTag(y));
|
||||
value.put("z", new IntTag(z));
|
||||
NBTOutputStream nbtos = getNBTTOS(x, y, z);
|
||||
nbtos.writeNamedTag(osNBTTI.getAndIncrement() + "", nbtTo);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void add(Vector loc, BaseBlock from, BaseBlock to) {
|
||||
int x = loc.getBlockX();
|
||||
int y = loc.getBlockY();
|
||||
int z = loc.getBlockZ();
|
||||
try {
|
||||
int idfrom = from.getId();
|
||||
int combinedFrom = (FaweCache.hasData(idfrom) ? ((idfrom << 4) + from.getData()) : (idfrom << 4));
|
||||
CompoundTag nbtFrom = FaweCache.hasNBT(idfrom) ? from.getNbtData() : null;
|
||||
|
||||
if (nbtFrom != null && MainUtil.isValidTag(nbtFrom)) {
|
||||
Map<String, Tag> value = ReflectionUtils.getMap(nbtFrom.getValue());
|
||||
value.put("x", new IntTag(x));
|
||||
value.put("y", new IntTag(y));
|
||||
value.put("z", new IntTag(z));
|
||||
NBTOutputStream nbtos = getNBTFOS(x, y, z);
|
||||
nbtos.writeNamedTag(osNBTFI.getAndIncrement() + "", nbtFrom);
|
||||
}
|
||||
add(x, y, z, combinedFrom, to);
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void add(EntityCreate change) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
public void add(EntityRemove change) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
public void add(BlockChange change) {
|
||||
try {
|
||||
BlockVector loc = change.getPosition();
|
||||
BaseBlock from = change.getPrevious();
|
||||
BaseBlock to = change.getCurrent();
|
||||
add(loc, from, to);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private OutputStream getBAOS(int x, int y, int z) throws IOException {
|
||||
public OutputStream getBlockOS(int x, int y, int z) throws IOException {
|
||||
if (osBD != null) {
|
||||
return osBD;
|
||||
}
|
||||
bdFile.getParentFile().mkdirs();
|
||||
bdFile.createNewFile();
|
||||
FileOutputStream stream = new FileOutputStream(bdFile);
|
||||
LZ4Factory factory = LZ4Factory.fastestInstance();
|
||||
LZ4Compressor compressor = factory.fastCompressor();
|
||||
osBD = new LZ4OutputStream(stream, Settings.BUFFER_SIZE, factory.fastCompressor());
|
||||
if (Settings.COMPRESSION_LEVEL > 0) {
|
||||
osBD = new LZ4OutputStream(osBD, Settings.BUFFER_SIZE, factory.highCompressor());
|
||||
}
|
||||
ox = x;
|
||||
oz = z;
|
||||
osBD.write((byte) (ox >> 24));
|
||||
osBD.write((byte) (ox >> 16));
|
||||
osBD.write((byte) (ox >> 8));
|
||||
osBD.write((byte) (ox));
|
||||
osBD.write((byte) (oz >> 24));
|
||||
osBD.write((byte) (oz >> 16));
|
||||
osBD.write((byte) (oz >> 8));
|
||||
osBD.write((byte) (oz));
|
||||
osBD = getCompressedOS(new FileOutputStream(bdFile));
|
||||
setOrigin(x, z);
|
||||
osBD.write((byte) (x >> 24));
|
||||
osBD.write((byte) (x >> 16));
|
||||
osBD.write((byte) (x >> 8));
|
||||
osBD.write((byte) (x));
|
||||
osBD.write((byte) (z >> 24));
|
||||
osBD.write((byte) (z >> 16));
|
||||
osBD.write((byte) (z >> 8));
|
||||
osBD.write((byte) (z));
|
||||
return osBD;
|
||||
}
|
||||
|
||||
private NBTOutputStream getNBTFOS(int x, int y, int z) throws IOException {
|
||||
|
||||
@Override
|
||||
public NBTOutputStream getEntityCreateOS() throws IOException {
|
||||
if (osENTCT != null) {
|
||||
return osENTCT;
|
||||
}
|
||||
enttFile.getParentFile().mkdirs();
|
||||
enttFile.createNewFile();
|
||||
osENTCTG = new GZIPOutputStream(new FileOutputStream(enttFile), true);
|
||||
osENTCT = new NBTOutputStream(osENTCTG);
|
||||
return osENTCT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NBTOutputStream getEntityRemoveOS() throws IOException {
|
||||
if (osENTCF != null) {
|
||||
return osENTCF;
|
||||
}
|
||||
entfFile.getParentFile().mkdirs();
|
||||
entfFile.createNewFile();
|
||||
osENTCFG = new GZIPOutputStream(new FileOutputStream(entfFile), true);
|
||||
osENTCF = new NBTOutputStream(osENTCFG);
|
||||
return osENTCF;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NBTOutputStream getTileCreateOS() throws IOException {
|
||||
if (osNBTT != null) {
|
||||
return osNBTT;
|
||||
}
|
||||
nbttFile.getParentFile().mkdirs();
|
||||
nbttFile.createNewFile();
|
||||
osNBTTG = new GZIPOutputStream(new FileOutputStream(nbttFile), true);
|
||||
osNBTT = new NBTOutputStream(osNBTTG);
|
||||
return osNBTT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NBTOutputStream getTileRemoveOS() throws IOException {
|
||||
if (osNBTF != null) {
|
||||
return osNBTF;
|
||||
}
|
||||
@ -328,51 +226,58 @@ public class DiskStorageHistory implements ChangeSet, FaweChangeSet {
|
||||
osNBTFI = new AtomicInteger();
|
||||
return osNBTF;
|
||||
}
|
||||
|
||||
private NBTOutputStream getNBTTOS(int x, int y, int z) throws IOException {
|
||||
if (osNBTT != null) {
|
||||
return osNBTT;
|
||||
|
||||
@Override
|
||||
public InputStream getBlockIS() throws IOException {
|
||||
if (!bdFile.exists()) {
|
||||
return null;
|
||||
}
|
||||
nbttFile.getParentFile().mkdirs();
|
||||
nbttFile.createNewFile();
|
||||
osNBTTG = new GZIPOutputStream(new FileOutputStream(nbttFile), true);
|
||||
osNBTT = new NBTOutputStream(osNBTTG);
|
||||
osNBTTI = new AtomicInteger();
|
||||
return osNBTT;
|
||||
InputStream is = getCompressedIS(new FileInputStream(bdFile));
|
||||
int x = ((is.read() << 24) + (is.read() << 16) + (is.read() << 8) + (is.read() << 0));
|
||||
int z = ((is.read() << 24) + (is.read() << 16) + (is.read() << 8) + (is.read() << 0));
|
||||
setOrigin(x, z);
|
||||
return is;
|
||||
}
|
||||
|
||||
private NBTOutputStream getENTFOS(int x, int y, int z) throws IOException {
|
||||
if (osNBTF != null) {
|
||||
return osNBTF;
|
||||
@Override
|
||||
public NBTInputStream getEntityCreateIS() throws IOException {
|
||||
if (!enttFile.exists()) {
|
||||
return null;
|
||||
}
|
||||
entfFile.getParentFile().mkdirs();
|
||||
entfFile.createNewFile();
|
||||
osENTFG = new GZIPOutputStream(new FileOutputStream(entfFile), true);
|
||||
osENTF = new NBTOutputStream(osENTFG);
|
||||
osENTFI = new AtomicInteger();
|
||||
return osENTF;
|
||||
}
|
||||
|
||||
private NBTOutputStream getENTTOS(int x, int y, int z) throws IOException {
|
||||
if (osENTT != null) {
|
||||
return osENTT;
|
||||
}
|
||||
enttFile.getParentFile().mkdirs();
|
||||
enttFile.createNewFile();
|
||||
osENTTG = new GZIPOutputStream(new FileOutputStream(enttFile), true);
|
||||
osENTT = new NBTOutputStream(osENTTG);
|
||||
osENTTI = new AtomicInteger();
|
||||
return osENTT;
|
||||
return new NBTInputStream(getCompressedIS(new FileInputStream(enttFile)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public NBTInputStream getEntityRemoveIS() throws IOException {
|
||||
if (!entfFile.exists()) {
|
||||
return null;
|
||||
}
|
||||
return new NBTInputStream(getCompressedIS(new FileInputStream(entfFile)));
|
||||
}
|
||||
|
||||
private DiskStorageSummary summary;
|
||||
@Override
|
||||
public NBTInputStream getTileCreateIS() throws IOException {
|
||||
if (!nbttFile.exists()) {
|
||||
return null;
|
||||
}
|
||||
return new NBTInputStream(getCompressedIS(new FileInputStream(nbttFile)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public NBTInputStream getTileRemoveIS() throws IOException {
|
||||
if (!nbtfFile.exists()) {
|
||||
return null;
|
||||
}
|
||||
return new NBTInputStream(getCompressedIS(new FileInputStream(nbtfFile)));
|
||||
}
|
||||
|
||||
public DiskStorageSummary summarize(RegionWrapper requiredRegion, boolean shallow) {
|
||||
if (summary != null) {
|
||||
return summary;
|
||||
}
|
||||
if (bdFile.exists()) {
|
||||
int ox = getOriginX();
|
||||
int oz = getOriginZ();
|
||||
if ((ox != 0 || oz != 0) && !requiredRegion.isIn(ox, oz)) {
|
||||
return summary = new DiskStorageSummary(ox, oz);
|
||||
}
|
||||
@ -387,6 +292,7 @@ public class DiskStorageHistory implements ChangeSet, FaweChangeSet {
|
||||
}
|
||||
ox = ((gis.read() << 24) + (gis.read() << 16) + (gis.read() << 8) + (gis.read() << 0));
|
||||
oz = ((gis.read() << 24) + (gis.read() << 16) + (gis.read() << 8) + (gis.read() << 0));
|
||||
setOrigin(ox, oz);
|
||||
summary = new DiskStorageSummary(ox, oz);
|
||||
if (!requiredRegion.isIn(ox, oz)) {
|
||||
fis.close();
|
||||
@ -415,6 +321,8 @@ public class DiskStorageHistory implements ChangeSet, FaweChangeSet {
|
||||
}
|
||||
|
||||
public IntegerPair readHeader() {
|
||||
int ox = getOriginX();
|
||||
int oz = getOriginZ();
|
||||
if (ox == 0 && oz == 0 && bdFile.exists()) {
|
||||
try {
|
||||
FileInputStream fis = new FileInputStream(bdFile);
|
||||
@ -428,6 +336,7 @@ public class DiskStorageHistory implements ChangeSet, FaweChangeSet {
|
||||
}
|
||||
ox = ((gis.read() << 24) + (gis.read() << 16) + (gis.read() << 8) + (gis.read() << 0));
|
||||
oz = ((gis.read() << 24) + (gis.read() << 16) + (gis.read() << 8) + (gis.read() << 0));
|
||||
setOrigin(ox, oz);
|
||||
fis.close();
|
||||
gis.close();
|
||||
} catch (IOException e) {
|
||||
@ -437,129 +346,6 @@ public class DiskStorageHistory implements ChangeSet, FaweChangeSet {
|
||||
return new IntegerPair(ox, oz);
|
||||
}
|
||||
|
||||
@SuppressWarnings("resource")
|
||||
public Iterator<Change> getIterator(final boolean dir) {
|
||||
flush();
|
||||
try {
|
||||
if (bdFile.exists()) {
|
||||
final NBTInputStream nbtf = nbtfFile.exists() ? new NBTInputStream(new GZIPInputStream(new FileInputStream(nbtfFile))) : null;
|
||||
final NBTInputStream nbtt = nbttFile.exists() ? new NBTInputStream(new GZIPInputStream(new FileInputStream(nbttFile))) : null;
|
||||
|
||||
FileInputStream fis = new FileInputStream(bdFile);
|
||||
LZ4Factory factory = LZ4Factory.fastestInstance();
|
||||
LZ4Compressor compressor = factory.fastCompressor();
|
||||
final InputStream gis;
|
||||
if (Settings.COMPRESSION_LEVEL > 0) {
|
||||
gis = new LZ4InputStream(new LZ4InputStream(fis));
|
||||
} else {
|
||||
gis = new LZ4InputStream(fis);
|
||||
}
|
||||
ox = ((gis.read() << 24) + (gis.read() << 16) + (gis.read() << 8) + (gis.read() << 0));
|
||||
oz = ((gis.read() << 24) + (gis.read() << 16) + (gis.read() << 8) + (gis.read() << 0));
|
||||
return new Iterator<Change>() {
|
||||
|
||||
private CompoundTag lastFrom = read(nbtf);
|
||||
private CompoundTag lastTo = read(nbtt);
|
||||
private Change last = read();
|
||||
|
||||
public CompoundTag read(NBTInputStream stream) {
|
||||
if (stream != null) {
|
||||
try {
|
||||
NamedTag nt = stream.readNamedTag();
|
||||
return nt != null ? ((CompoundTag) nt.getTag()) : null;
|
||||
} catch (IOException ignore) {}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public Change read() {
|
||||
try {
|
||||
int x = ((byte) gis.read() & 0xFF) + ((byte) gis.read() << 8) + ox;
|
||||
int z = ((byte) gis.read() & 0xFF) + ((byte) gis.read() << 8) + oz;
|
||||
int y = gis.read() & 0xff;
|
||||
int from1 = gis.read();
|
||||
int from2 = gis.read();
|
||||
BaseBlock from = FaweCache.getBlock(((from2 << 4) + (from1 >> 4)), (from1 & 0xf));
|
||||
if (lastFrom != null && FaweCache.hasNBT(from.getId())) {
|
||||
Map<String, Tag> t = lastFrom.getValue();
|
||||
if (((IntTag) t.get("x")).getValue() == x && ((IntTag) t.get("z")).getValue() == z && ((IntTag) t.get("y")).getValue() == y) {
|
||||
from = new BaseBlock(from.getId(), from.getData());
|
||||
from.setNbtData(lastFrom);
|
||||
lastFrom = read(nbtf);
|
||||
}
|
||||
}
|
||||
int to1 = gis.read();
|
||||
int to2 = gis.read();
|
||||
BaseBlock to = FaweCache.getBlock(((to2 << 4) + (to1 >> 4)), (to1 & 0xf));
|
||||
if (lastTo != null && FaweCache.hasNBT(to.getId())) {
|
||||
Map<String, Tag> t = lastTo.getValue();
|
||||
if (((IntTag) t.get("x")).getValue() == x && ((IntTag) t.get("z")).getValue() == z && ((IntTag) t.get("y")).getValue() == y) {
|
||||
to = new BaseBlock(to.getId(), to.getData());
|
||||
to.setNbtData(lastTo);
|
||||
lastTo = read(nbtt);
|
||||
}
|
||||
}
|
||||
BlockVector position = new BlockVector(x, y, z);
|
||||
return dir ? new BlockChange(position, to, from) : new BlockChange(position, from, to);
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
if (last != null) {
|
||||
return true;
|
||||
}
|
||||
try {
|
||||
gis.close();
|
||||
if (nbtf != null) {
|
||||
nbtf.close();
|
||||
}
|
||||
if (nbtt != null) {
|
||||
nbtt.close();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Change next() {
|
||||
Change tmp = last;
|
||||
last = read();
|
||||
return tmp;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
throw new IllegalArgumentException("CANNOT REMOVE");
|
||||
}
|
||||
};
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return new ArrayList<Change>().iterator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<Change> backwardIterator() {
|
||||
return getIterator(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<Change> forwardIterator() {
|
||||
return getIterator(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
flush();
|
||||
return size;
|
||||
}
|
||||
|
||||
public static class DiskStorageSummary {
|
||||
|
||||
private final int z;
|
||||
|
@ -1,17 +1,222 @@
|
||||
package com.boydti.fawe.object.changeset;
|
||||
|
||||
import com.boydti.fawe.Fawe;
|
||||
import com.boydti.fawe.FaweCache;
|
||||
import com.boydti.fawe.object.BytePair;
|
||||
import com.boydti.fawe.object.FaweChunk;
|
||||
import com.boydti.fawe.object.RunnableVal2;
|
||||
import com.boydti.fawe.util.FaweQueue;
|
||||
import com.boydti.fawe.util.MainUtil;
|
||||
import com.sk89q.jnbt.CompoundTag;
|
||||
import com.sk89q.worldedit.BlockVector;
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
import com.sk89q.worldedit.EditSessionFactory;
|
||||
import com.sk89q.worldedit.Vector;
|
||||
import com.sk89q.worldedit.WorldEdit;
|
||||
import com.sk89q.worldedit.blocks.BaseBlock;
|
||||
import com.sk89q.worldedit.entity.Player;
|
||||
import com.sk89q.worldedit.history.change.BlockChange;
|
||||
import com.sk89q.worldedit.history.change.Change;
|
||||
import com.sk89q.worldedit.history.change.EntityCreate;
|
||||
import com.sk89q.worldedit.history.change.EntityRemove;
|
||||
import com.sk89q.worldedit.history.changeset.ChangeSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
public interface FaweChangeSet extends ChangeSet {
|
||||
boolean flush();
|
||||
public abstract class FaweChangeSet implements ChangeSet {
|
||||
public abstract boolean flush();
|
||||
|
||||
int getCompressedSize();
|
||||
public abstract void add(int x, int y, int z, int combinedFrom, int combinedTo);
|
||||
|
||||
void add(Vector location, BaseBlock from, BaseBlock to);
|
||||
@Override
|
||||
public Iterator<Change> backwardIterator() {
|
||||
return getIterator(false);
|
||||
}
|
||||
|
||||
void add(int x, int y, int z, int combinedId4DataFrom, BaseBlock to);
|
||||
@Override
|
||||
public Iterator<Change> forwardIterator() {
|
||||
return getIterator(true);
|
||||
}
|
||||
|
||||
void add(int x, int y, int z, int combinedId4DataFrom, int combinedId4DataTo);
|
||||
public abstract void addTileCreate(CompoundTag tag);
|
||||
public abstract void addTileRemove(CompoundTag tag);
|
||||
public abstract void addEntityRemove(CompoundTag tag);
|
||||
public abstract void addEntityCreate(CompoundTag tag);
|
||||
public abstract Iterator<Change> getIterator(boolean redo);
|
||||
|
||||
public EditSession toEditSession(Player player) {
|
||||
EditSessionFactory factory = WorldEdit.getInstance().getEditSessionFactory();
|
||||
EditSession edit = factory.getEditSession(player.getWorld(), -1, null, player);
|
||||
edit.setChangeSet(this);
|
||||
edit.dequeue();
|
||||
return edit;
|
||||
}
|
||||
|
||||
public void add(EntityCreate change) {
|
||||
CompoundTag tag = change.state.getNbtData();
|
||||
MainUtil.setEntityInfo(tag, change.entity);
|
||||
addEntityCreate(tag);
|
||||
}
|
||||
|
||||
public void add(EntityRemove change) {
|
||||
CompoundTag tag = change.state.getNbtData();
|
||||
MainUtil.setEntityInfo(tag, change.entity);
|
||||
addEntityRemove(tag);
|
||||
}
|
||||
|
||||
public void add(Change change) {
|
||||
if (change.getClass() == BlockChange.class) {
|
||||
add((BlockChange) change);
|
||||
} else if (change.getClass() == EntityCreate.class) {
|
||||
add((EntityCreate) change);
|
||||
} else if (change.getClass() == EntityRemove.class) {
|
||||
add((EntityRemove) change);
|
||||
} else {
|
||||
Fawe.debug("Unknown change: " + change.getClass());
|
||||
}
|
||||
}
|
||||
|
||||
public void add(BlockChange change) {
|
||||
try {
|
||||
BlockVector loc = change.getPosition();
|
||||
BaseBlock from = change.getPrevious();
|
||||
BaseBlock to = change.getCurrent();
|
||||
add(loc, from, to);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void add(Vector loc, BaseBlock from, BaseBlock to) {
|
||||
int x = loc.getBlockX();
|
||||
int y = loc.getBlockY();
|
||||
int z = loc.getBlockZ();
|
||||
add(x, y, z, from, to);
|
||||
}
|
||||
|
||||
public void add(int x, int y, int z, BaseBlock from, BaseBlock to) {
|
||||
try {
|
||||
if (from.hasNbtData()) {
|
||||
CompoundTag nbt = from.getNbtData();
|
||||
MainUtil.setPosition(nbt, x, y, z);
|
||||
addTileRemove(nbt);
|
||||
}
|
||||
if (to.hasNbtData()) {
|
||||
CompoundTag nbt = to.getNbtData();
|
||||
MainUtil.setPosition(nbt, x, y, z);
|
||||
addTileRemove(nbt);
|
||||
}
|
||||
int combinedFrom = (from.getId() << 4) + from.getData();
|
||||
int combinedTo = (to.getId() << 4) + to.getData();
|
||||
add(x, y, z, combinedFrom, combinedTo);
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void add(int x, int y, int z, int combinedFrom, BaseBlock to) {
|
||||
try {
|
||||
if (to.hasNbtData()) {
|
||||
CompoundTag nbt = to.getNbtData();
|
||||
MainUtil.setPosition(nbt, x, y, z);
|
||||
addTileRemove(nbt);
|
||||
}
|
||||
int combinedTo = (to.getId() << 4) + to.getData();
|
||||
add(x, y, z, combinedFrom, combinedTo);
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void addChangeTask(FaweQueue queue) {
|
||||
queue.setChangeTask(new RunnableVal2<FaweChunk, FaweChunk>() {
|
||||
@Override
|
||||
public void run(final FaweChunk previous, FaweChunk next) {
|
||||
/**
|
||||
* TODO cache NBT
|
||||
* - Counter variable for nbt changes
|
||||
* - Record biome changes
|
||||
*/
|
||||
int cx = previous.getX();
|
||||
int cz = previous.getZ();
|
||||
int bx = cx << 4;
|
||||
int bz = cz << 4;
|
||||
|
||||
// Biome changes
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
|
||||
// Block changes
|
||||
{
|
||||
// Current blocks
|
||||
char[][] currentIds = next.getIdArrays();
|
||||
// Previous blocks in modified sections (i.e. we skip sections that weren't modified)
|
||||
char[][] previousIds = previous.getIdArrays();
|
||||
for (int layer = 0; layer < currentIds.length; layer++) {
|
||||
char[] currentLayer = currentIds[layer];
|
||||
char[] previousLayer = previousIds[layer];
|
||||
if (currentLayer == null) {
|
||||
continue;
|
||||
}
|
||||
int startY = layer << 4;
|
||||
for (int y = 0; y < 16; y++) {
|
||||
short[][] i1 = FaweCache.CACHE_J[y];
|
||||
int yy = y + startY;
|
||||
for (int x = 0; x < 16; x++) {
|
||||
int xx = x + bx;
|
||||
short[] i2 = i1[x];
|
||||
for (int z = 0; z < 16; z++) {
|
||||
int zz = z + bz;
|
||||
int index = i2[z];
|
||||
int combinedIdCurrent = currentLayer[index];
|
||||
switch (combinedIdCurrent) {
|
||||
case 0:
|
||||
continue;
|
||||
case 1:
|
||||
combinedIdCurrent = 0;
|
||||
default:
|
||||
char combinedIdPrevious = previousLayer != null ? previousLayer[index] : 0;
|
||||
if (combinedIdCurrent != combinedIdPrevious) {
|
||||
add(xx, yy, zz, combinedIdPrevious, combinedIdCurrent);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Tile changes
|
||||
{
|
||||
// Tiles created
|
||||
Map<BytePair, CompoundTag> tiles = next.getTiles();
|
||||
for (Map.Entry<BytePair, CompoundTag> entry : tiles.entrySet()) {
|
||||
addTileCreate(entry.getValue());
|
||||
}
|
||||
// Tiles removed
|
||||
tiles = previous.getTiles();
|
||||
for (Map.Entry<BytePair, CompoundTag> entry : tiles.entrySet()) {
|
||||
addTileRemove(entry.getValue());
|
||||
}
|
||||
}
|
||||
// Entity changes
|
||||
{
|
||||
// Entities created
|
||||
Set<CompoundTag> entities = next.getEntities();
|
||||
for (CompoundTag entityTag : entities) {
|
||||
addEntityCreate(entityTag);
|
||||
}
|
||||
// Entities removed
|
||||
entities = previous.getEntities();
|
||||
for (CompoundTag entityTag : entities) {
|
||||
addEntityRemove(entityTag);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,363 @@
|
||||
package com.boydti.fawe.object.changeset;
|
||||
|
||||
import com.boydti.fawe.config.Settings;
|
||||
import com.boydti.fawe.object.change.MutableBlockChange;
|
||||
import com.boydti.fawe.object.change.MutableEntityChange;
|
||||
import com.boydti.fawe.object.change.MutableTileChange;
|
||||
import com.google.common.collect.Iterators;
|
||||
import com.sk89q.jnbt.CompoundTag;
|
||||
import com.sk89q.jnbt.NBTInputStream;
|
||||
import com.sk89q.jnbt.NBTOutputStream;
|
||||
import com.sk89q.worldedit.history.change.Change;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import net.jpountz.lz4.LZ4Compressor;
|
||||
import net.jpountz.lz4.LZ4Factory;
|
||||
import net.jpountz.lz4.LZ4InputStream;
|
||||
import net.jpountz.lz4.LZ4OutputStream;
|
||||
|
||||
public abstract class FaweStreamChangeSet extends FaweChangeSet {
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
System.out.println("SIZE: " + blockSize);
|
||||
// Flush so we can accurately get the size
|
||||
flush();
|
||||
return blockSize;
|
||||
}
|
||||
|
||||
public abstract int getCompressedSize();
|
||||
|
||||
public abstract OutputStream getBlockOS(int x, int y, int z) throws IOException;
|
||||
public abstract NBTOutputStream getEntityCreateOS() throws IOException;
|
||||
public abstract NBTOutputStream getEntityRemoveOS() throws IOException;
|
||||
public abstract NBTOutputStream getTileCreateOS() throws IOException;
|
||||
public abstract NBTOutputStream getTileRemoveOS() throws IOException;
|
||||
|
||||
public abstract InputStream getBlockIS() throws IOException;
|
||||
public abstract NBTInputStream getEntityCreateIS() throws IOException;
|
||||
public abstract NBTInputStream getEntityRemoveIS() throws IOException;
|
||||
public abstract NBTInputStream getTileCreateIS() throws IOException;
|
||||
public abstract NBTInputStream getTileRemoveIS() throws IOException;
|
||||
|
||||
public int blockSize;
|
||||
public int entityCreateSize;
|
||||
public int entityRemoveSize;
|
||||
public int tileCreateSize;
|
||||
public int tileRemoveSize;
|
||||
|
||||
private int originX;
|
||||
private int originZ;
|
||||
|
||||
public void setOrigin(int x, int z) {
|
||||
originX = x;
|
||||
originZ = z;
|
||||
}
|
||||
|
||||
public int getOriginX() {
|
||||
return originX;
|
||||
}
|
||||
|
||||
public int getOriginZ() {
|
||||
return originZ;
|
||||
}
|
||||
|
||||
public InputStream getCompressedIS(InputStream is) {
|
||||
if (Settings.COMPRESSION_LEVEL > 0) {
|
||||
is = new LZ4InputStream(new LZ4InputStream(is));
|
||||
} else {
|
||||
is = new LZ4InputStream(is);
|
||||
}
|
||||
return is;
|
||||
}
|
||||
|
||||
public OutputStream getCompressedOS(OutputStream os) throws IOException {
|
||||
LZ4Factory factory = LZ4Factory.fastestInstance();
|
||||
LZ4Compressor compressor = factory.fastCompressor();
|
||||
os = new LZ4OutputStream(os, Settings.BUFFER_SIZE, factory.fastCompressor());
|
||||
if (Settings.COMPRESSION_LEVEL > 0) {
|
||||
os = new LZ4OutputStream(os, Settings.BUFFER_SIZE, factory.highCompressor());
|
||||
}
|
||||
return os;
|
||||
}
|
||||
|
||||
public void add(int x, int y, int z, int combinedFrom, int combinedTo) {
|
||||
blockSize++;
|
||||
try {
|
||||
OutputStream stream = getBlockOS(x, y, z);
|
||||
//x
|
||||
x-=originX;
|
||||
stream.write((x) & 0xff);
|
||||
stream.write(((x) >> 8) & 0xff);
|
||||
//z
|
||||
z-=originZ;
|
||||
stream.write((z) & 0xff);
|
||||
stream.write(((z) >> 8) & 0xff);
|
||||
//y
|
||||
stream.write((byte) y);
|
||||
//from
|
||||
stream.write((combinedFrom) & 0xff);
|
||||
stream.write(((combinedFrom) >> 8) & 0xff);
|
||||
//to
|
||||
stream.write((combinedTo) & 0xff);
|
||||
stream.write(((combinedTo) >> 8) & 0xff);
|
||||
}
|
||||
catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void addTileCreate(CompoundTag tag) {
|
||||
if (tag == null) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
NBTOutputStream nbtos = getTileCreateOS();
|
||||
nbtos.writeNamedTag(tileCreateSize++ + "", tag);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void addTileRemove(CompoundTag tag) {
|
||||
if (tag == null) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
NBTOutputStream nbtos = getTileRemoveOS();
|
||||
nbtos.writeNamedTag(tileRemoveSize++ + "", tag);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void addEntityRemove(CompoundTag tag) {
|
||||
if (tag == null) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
NBTOutputStream nbtos = getEntityRemoveOS();
|
||||
nbtos.writeNamedTag(entityRemoveSize++ + "", tag);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void addEntityCreate(CompoundTag tag) {
|
||||
if (tag == null) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
NBTOutputStream nbtos = getEntityCreateOS();
|
||||
nbtos.writeNamedTag(entityCreateSize++ + "", tag);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public Iterator<MutableBlockChange> getBlockIterator(final boolean dir) throws IOException {
|
||||
final InputStream is = getBlockIS();
|
||||
if (is == null) {
|
||||
return new ArrayList<MutableBlockChange>().iterator();
|
||||
}
|
||||
final MutableBlockChange change = new MutableBlockChange(0, 0, 0, (short) 0, (byte) 0);
|
||||
return new Iterator<MutableBlockChange>() {
|
||||
private MutableBlockChange last = read();
|
||||
public MutableBlockChange read() {
|
||||
try {
|
||||
int read0 = is.read();
|
||||
if (read0 == -1) {
|
||||
return null;
|
||||
}
|
||||
System.out.println("r0: " + read0);
|
||||
int x = ((byte) read0 & 0xFF) + ((byte) is.read() << 8) + originX;
|
||||
int z = ((byte) is.read() & 0xFF) + ((byte) is.read() << 8) + originZ;
|
||||
int y = is.read() & 0xff;
|
||||
change.x = x;
|
||||
change.y = y;
|
||||
change.z = z;
|
||||
if (dir) {
|
||||
is.skip(2);
|
||||
int to1 = is.read();
|
||||
int to2 = is.read();
|
||||
change.id = (short) ((to2 << 4) + (to1 >> 4));
|
||||
change.data = (byte) (to1 & 0xf);
|
||||
} else {
|
||||
int from1 = is.read();
|
||||
int from2 = is.read();
|
||||
is.skip(2);
|
||||
change.id = (short) ((from2 << 4) + (from1 >> 4));
|
||||
change.data = (byte) (from1 & 0xf);
|
||||
}
|
||||
System.out.println("CHANGE: " + change.id);
|
||||
return change;
|
||||
} catch (Exception ignoreEOF) {
|
||||
ignoreEOF.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
if (last == null) {
|
||||
last = read();
|
||||
}
|
||||
if (last != null) {
|
||||
System.out.println("HAS NEXT!");
|
||||
return true;
|
||||
}
|
||||
System.out.println("NO NEXT");
|
||||
try {
|
||||
is.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MutableBlockChange next() {
|
||||
MutableBlockChange tmp = last;
|
||||
last = null;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
throw new IllegalArgumentException("CANNOT REMOVE");
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public Iterator<MutableEntityChange> getEntityIterator(final NBTInputStream is, final boolean create, final boolean dir) {
|
||||
if (is == null) {
|
||||
return new ArrayList<MutableEntityChange>().iterator();
|
||||
}
|
||||
final MutableEntityChange change = new MutableEntityChange(null, create);
|
||||
try {
|
||||
return new Iterator<MutableEntityChange>() {
|
||||
private CompoundTag last = read();
|
||||
|
||||
public CompoundTag read() {
|
||||
try {
|
||||
return (CompoundTag) is.readNamedTag().getTag();
|
||||
} catch (Exception ignoreEOS) {}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
if (last == null) {
|
||||
last = read();
|
||||
}
|
||||
if (last != null) {
|
||||
return true;
|
||||
}
|
||||
try {
|
||||
is.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MutableEntityChange next() {
|
||||
change.tag = last;
|
||||
last = null;
|
||||
return change;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
throw new IllegalArgumentException("CANNOT REMOVE");
|
||||
}
|
||||
};
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public Iterator<MutableTileChange> getTileIterator(final NBTInputStream is, final boolean create, final boolean dir) {
|
||||
if (is == null) {
|
||||
return new ArrayList<MutableTileChange>().iterator();
|
||||
}
|
||||
final MutableTileChange change = new MutableTileChange(null, create);
|
||||
try {
|
||||
return new Iterator<MutableTileChange>() {
|
||||
private CompoundTag last = read();
|
||||
|
||||
public CompoundTag read() {
|
||||
try {
|
||||
return (CompoundTag) is.readNamedTag().getTag();
|
||||
} catch (Exception ignoreEOS) {}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
if (last == null) {
|
||||
last = read();
|
||||
}
|
||||
if (last != null) {
|
||||
return true;
|
||||
}
|
||||
try {
|
||||
is.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MutableTileChange next() {
|
||||
change.tag = last;
|
||||
last = null;
|
||||
return change;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
throw new IllegalArgumentException("CANNOT REMOVE");
|
||||
}
|
||||
};
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public Iterator<Change> getIterator(final boolean dir) {
|
||||
System.out.println("GET ITERATOR: " + dir);
|
||||
flush();
|
||||
try {
|
||||
Iterator<MutableTileChange> tileCreate = getTileIterator(getTileCreateIS(), true, dir);
|
||||
Iterator<MutableTileChange> tileRemove = getTileIterator(getTileRemoveIS(), false, dir);
|
||||
|
||||
Iterator<MutableEntityChange> entityCreate = getEntityIterator(getEntityCreateIS(), true, dir);
|
||||
Iterator<MutableEntityChange> entityRemove = getEntityIterator(getEntityRemoveIS(), false, dir);
|
||||
|
||||
Iterator<MutableBlockChange> blockChange = getBlockIterator(dir);
|
||||
|
||||
return Iterators.concat(tileCreate, tileRemove, entityCreate, entityRemove, blockChange);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return new ArrayList<Change>().iterator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<Change> backwardIterator() {
|
||||
return getIterator(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<Change> forwardIterator() {
|
||||
return getIterator(true);
|
||||
}
|
||||
}
|
@ -1,29 +1,14 @@
|
||||
package com.boydti.fawe.object.changeset;
|
||||
|
||||
import com.boydti.fawe.FaweCache;
|
||||
import com.boydti.fawe.config.Settings;
|
||||
import com.boydti.fawe.object.io.FastByteArrayOutputStream;
|
||||
import com.boydti.fawe.util.MainUtil;
|
||||
import com.boydti.fawe.util.ReflectionUtils;
|
||||
import com.google.common.collect.Iterators;
|
||||
import com.sk89q.jnbt.CompoundTag;
|
||||
import com.sk89q.jnbt.IntTag;
|
||||
import com.sk89q.jnbt.Tag;
|
||||
import com.sk89q.worldedit.BlockVector;
|
||||
import com.sk89q.worldedit.Vector;
|
||||
import com.sk89q.worldedit.blocks.BaseBlock;
|
||||
import com.sk89q.jnbt.NBTInputStream;
|
||||
import com.sk89q.jnbt.NBTOutputStream;
|
||||
import com.sk89q.worldedit.extension.platform.Actor;
|
||||
import com.sk89q.worldedit.history.change.BlockChange;
|
||||
import com.sk89q.worldedit.history.change.Change;
|
||||
import com.sk89q.worldedit.history.changeset.ChangeSet;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import net.jpountz.lz4.LZ4Factory;
|
||||
import net.jpountz.lz4.LZ4InputStream;
|
||||
import net.jpountz.lz4.LZ4OutputStream;
|
||||
@ -34,250 +19,14 @@ import net.jpountz.lz4.LZ4OutputStream;
|
||||
* - High CPU usage
|
||||
* - Low memory usage
|
||||
*/
|
||||
public class MemoryOptimizedHistory implements ChangeSet, FaweChangeSet {
|
||||
public class MemoryOptimizedHistory extends FaweStreamChangeSet {
|
||||
|
||||
private final Actor actor;
|
||||
private ArrayDeque<CompoundTag> fromTags;
|
||||
private ArrayDeque<CompoundTag> toTags;
|
||||
|
||||
private byte[] ids;
|
||||
private Object lock;
|
||||
private int decompressedLength;
|
||||
|
||||
private FastByteArrayOutputStream idsStream;
|
||||
private OutputStream idsStreamZip;
|
||||
|
||||
private ArrayDeque<Change> entities;
|
||||
|
||||
int ox;
|
||||
int oz;
|
||||
|
||||
private int size;
|
||||
|
||||
public MemoryOptimizedHistory(Actor actor) {
|
||||
this.actor = actor;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void add(int x, int y, int z, int combinedFrom, int combinedTo) {
|
||||
size++;
|
||||
try {
|
||||
OutputStream stream = getBAOS(x, y, z);
|
||||
//x
|
||||
x -= ox;
|
||||
z -= oz;
|
||||
stream.write((x & 0xff));
|
||||
stream.write(((x >> 8) & 0xff));
|
||||
//z
|
||||
stream.write((z & 0xff));
|
||||
stream.write( ((z >> 8) & 0xff));
|
||||
//y
|
||||
stream.write((byte) y);
|
||||
//from
|
||||
stream.write((combinedFrom) & 0xff);
|
||||
stream.write(((combinedFrom) >> 8) & 0xff);
|
||||
//to
|
||||
stream.write((combinedTo) & 0xff);
|
||||
stream.write(((combinedTo) >> 8) & 0xff);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void add(int x, int y, int z, int combinedId4DataFrom, BaseBlock to) {
|
||||
int idTo = to.getId();
|
||||
int combinedTo = (FaweCache.hasData(idTo) ? ((idTo << 4) + to.getData()) : (idTo << 4));
|
||||
CompoundTag nbtTo = FaweCache.hasNBT(idTo) ? to.getNbtData() : null;
|
||||
add(x, y, z, combinedId4DataFrom, combinedTo);
|
||||
if (nbtTo != null && MainUtil.isValidTag(nbtTo)) {
|
||||
Map<String, Tag> value = ReflectionUtils.getMap(nbtTo.getValue());
|
||||
value.put("x", new IntTag(x));
|
||||
value.put("y", new IntTag(y));
|
||||
value.put("z", new IntTag(z));
|
||||
if (toTags == null) {
|
||||
toTags = new ArrayDeque<>();
|
||||
}
|
||||
toTags.add(nbtTo);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void add(Vector loc, BaseBlock from, BaseBlock to) {
|
||||
try {
|
||||
int x = loc.getBlockX();
|
||||
int y = loc.getBlockY();
|
||||
int z = loc.getBlockZ();
|
||||
|
||||
int idfrom = from.getId();
|
||||
int combinedFrom = (FaweCache.hasData(idfrom) ? ((idfrom << 4) + from.getData()) : (idfrom << 4));
|
||||
CompoundTag nbtFrom = FaweCache.hasNBT(idfrom) ? from.getNbtData() : null;
|
||||
if (nbtFrom != null && MainUtil.isValidTag(nbtFrom)) {
|
||||
Map<String, Tag> value = ReflectionUtils.getMap(nbtFrom.getValue());
|
||||
value.put("x", new IntTag(x));
|
||||
value.put("y", new IntTag(y));
|
||||
value.put("z", new IntTag(z));
|
||||
if (fromTags == null) {
|
||||
fromTags = new ArrayDeque<>();
|
||||
}
|
||||
fromTags.add(nbtFrom);
|
||||
}
|
||||
add(x, y, z, combinedFrom, to);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void add(Change arg) {
|
||||
if ((arg instanceof BlockChange)) {
|
||||
BlockChange change = (BlockChange) arg;
|
||||
BlockVector loc = change.getPosition();
|
||||
BaseBlock from = change.getPrevious();
|
||||
BaseBlock to = change.getCurrent();
|
||||
add(loc, from, to);
|
||||
} else {
|
||||
if (entities == null) {
|
||||
entities = new ArrayDeque<>();
|
||||
}
|
||||
entities.add(arg);
|
||||
}
|
||||
}
|
||||
|
||||
private OutputStream getBAOS(int x, int y, int z) throws IOException {
|
||||
if (idsStreamZip != null) {
|
||||
return idsStreamZip;
|
||||
}
|
||||
LZ4Factory factory = LZ4Factory.fastestInstance();
|
||||
idsStream = new FastByteArrayOutputStream(Settings.BUFFER_SIZE);
|
||||
idsStreamZip = new LZ4OutputStream(idsStream, Settings.BUFFER_SIZE, factory.fastCompressor());
|
||||
if (Settings.COMPRESSION_LEVEL > 0) {
|
||||
idsStreamZip = new LZ4OutputStream(idsStreamZip, Settings.BUFFER_SIZE, factory.highCompressor());
|
||||
}
|
||||
ox = x;
|
||||
oz = z;
|
||||
return idsStreamZip;
|
||||
}
|
||||
|
||||
@SuppressWarnings("resource")
|
||||
public Iterator<Change> getIterator(final boolean dir) {
|
||||
flush();
|
||||
if (lock != null) {
|
||||
try {
|
||||
lock.wait();
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
try {
|
||||
Iterator<Change> idsIterator;
|
||||
Iterator<Change> entsIterator = entities != null ? entities.iterator() : new ArrayList().iterator();
|
||||
if (ids == null) {
|
||||
idsIterator = new ArrayList().iterator();
|
||||
} else {
|
||||
ByteArrayInputStream bais = new ByteArrayInputStream(ids);
|
||||
final InputStream gis;
|
||||
if (Settings.COMPRESSION_LEVEL > 0) {
|
||||
gis = new LZ4InputStream(new LZ4InputStream(bais));
|
||||
} else {
|
||||
gis = new LZ4InputStream(bais);
|
||||
}
|
||||
idsIterator = new Iterator<Change>() {
|
||||
private final Iterator<CompoundTag> lastFromIter = fromTags != null ? fromTags.iterator() : null;
|
||||
private final Iterator<CompoundTag> lastToIter = toTags != null ? toTags.iterator() : null;
|
||||
private CompoundTag lastFrom = read(lastFromIter);
|
||||
private CompoundTag lastTo = read(lastToIter);
|
||||
private Change last = read();
|
||||
|
||||
public CompoundTag read(Iterator<CompoundTag> tags) {
|
||||
if (tags != null && tags.hasNext()) {
|
||||
return tags.next();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public Change read() {
|
||||
try {
|
||||
int x = ((byte) gis.read() & 0xFF) + ((byte) gis.read() << 8) + ox;
|
||||
int z = ((byte) gis.read() & 0xFF) + ((byte) gis.read() << 8) + oz;
|
||||
int y = gis.read() & 0xff;
|
||||
int from1 = gis.read();
|
||||
int from2 = gis.read();
|
||||
BaseBlock from = FaweCache.getBlock(((from2 << 4) + (from1 >> 4)), (from1 & 0xf));
|
||||
if (lastFrom != null && FaweCache.hasNBT(from.getId())) {
|
||||
Map<String, Tag> t = lastFrom.getValue();
|
||||
if (((IntTag) t.get("x")).getValue() == x && ((IntTag) t.get("z")).getValue() == z && ((IntTag) t.get("y")).getValue() == y) {
|
||||
from = new BaseBlock(from.getId(), from.getData());
|
||||
from.setNbtData(lastFrom);
|
||||
lastFrom = read(lastFromIter);
|
||||
}
|
||||
}
|
||||
int to1 = gis.read();
|
||||
int to2 = gis.read();
|
||||
BaseBlock to = FaweCache.getBlock(((to2 << 4) + (to1 >> 4)), (to1 & 0xf));
|
||||
if (lastTo != null && FaweCache.hasNBT(to.getId())) {
|
||||
Map<String, Tag> t = lastTo.getValue();
|
||||
if (((IntTag) t.get("x")).getValue() == x && ((IntTag) t.get("z")).getValue() == z && ((IntTag) t.get("y")).getValue() == y) {
|
||||
to = new BaseBlock(to.getId(), to.getData());
|
||||
to.setNbtData(lastTo);
|
||||
lastTo = read(lastToIter);
|
||||
}
|
||||
}
|
||||
BlockVector position = new BlockVector(x, y, z);
|
||||
return dir ? new BlockChange(position, to, from) : new BlockChange(position, from, to);
|
||||
} catch (Exception ignore) {}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
if (last != null) {
|
||||
return true;
|
||||
}
|
||||
try {
|
||||
gis.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Change next() {
|
||||
Change tmp = last;
|
||||
last = read();
|
||||
return tmp;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
throw new IllegalArgumentException("CANNOT REMOVE");
|
||||
}
|
||||
};
|
||||
}
|
||||
return Iterators.concat(idsIterator, entsIterator);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return new ArrayList<Change>().iterator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<Change> backwardIterator() {
|
||||
return getIterator(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<Change> forwardIterator() {
|
||||
return getIterator(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean flush() {
|
||||
if (idsStreamZip != null) {
|
||||
@ -285,7 +34,7 @@ public class MemoryOptimizedHistory implements ChangeSet, FaweChangeSet {
|
||||
idsStream.flush();
|
||||
idsStreamZip.flush();
|
||||
idsStreamZip.close();
|
||||
ids = idsStream.toByteArray();
|
||||
ids = idsStream.toByteArray(true);
|
||||
idsStream = null;
|
||||
idsStreamZip = null;
|
||||
} catch (IOException e) {
|
||||
@ -301,4 +50,75 @@ public class MemoryOptimizedHistory implements ChangeSet, FaweChangeSet {
|
||||
return ids == null ? 0 : ids.length;
|
||||
}
|
||||
|
||||
private byte[] ids;
|
||||
private FastByteArrayOutputStream idsStream;
|
||||
private OutputStream idsStreamZip;
|
||||
|
||||
@Override
|
||||
public OutputStream getBlockOS(int x, int y, int z) throws IOException {
|
||||
if (idsStreamZip != null) {
|
||||
return idsStreamZip;
|
||||
}
|
||||
LZ4Factory factory = LZ4Factory.fastestInstance();
|
||||
idsStream = new FastByteArrayOutputStream(Settings.BUFFER_SIZE);
|
||||
idsStreamZip = new LZ4OutputStream(idsStream, Settings.BUFFER_SIZE, factory.fastCompressor());
|
||||
if (Settings.COMPRESSION_LEVEL > 0) {
|
||||
idsStreamZip = new LZ4OutputStream(idsStreamZip, Settings.BUFFER_SIZE, factory.highCompressor());
|
||||
}
|
||||
setOrigin(x, z);
|
||||
return idsStreamZip;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NBTOutputStream getEntityCreateOS() throws IOException {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NBTOutputStream getEntityRemoveOS() throws IOException {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NBTOutputStream getTileCreateOS() throws IOException {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NBTOutputStream getTileRemoveOS() throws IOException {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream getBlockIS() {
|
||||
if (ids == null) {
|
||||
return null;
|
||||
}
|
||||
InputStream is = new ByteArrayInputStream(ids);
|
||||
is = new LZ4InputStream(is);
|
||||
if (Settings.COMPRESSION_LEVEL > 0) {
|
||||
is = new LZ4InputStream(is);
|
||||
}
|
||||
return is;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NBTInputStream getEntityCreateIS() throws IOException {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NBTInputStream getEntityRemoveIS() throws IOException {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NBTInputStream getTileCreateIS() throws IOException {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NBTInputStream getTileRemoveIS() throws IOException {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@ -3,7 +3,12 @@ package com.boydti.fawe.object.extent;
|
||||
import com.boydti.fawe.FaweCache;
|
||||
import com.boydti.fawe.util.FaweQueue;
|
||||
import com.boydti.fawe.util.MainUtil;
|
||||
import com.boydti.fawe.util.TaskManager;
|
||||
import com.boydti.fawe.util.ReflectionUtils;
|
||||
import com.sk89q.jnbt.CompoundTag;
|
||||
import com.sk89q.jnbt.DoubleTag;
|
||||
import com.sk89q.jnbt.ListTag;
|
||||
import com.sk89q.jnbt.StringTag;
|
||||
import com.sk89q.jnbt.Tag;
|
||||
import com.sk89q.worldedit.BlockVector;
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
import com.sk89q.worldedit.Vector;
|
||||
@ -18,6 +23,7 @@ import com.sk89q.worldedit.util.Location;
|
||||
import com.sk89q.worldedit.world.World;
|
||||
import com.sk89q.worldedit.world.biome.BaseBiome;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class FastWorldEditExtent extends AbstractDelegateExtent {
|
||||
|
||||
@ -28,15 +34,24 @@ public class FastWorldEditExtent extends AbstractDelegateExtent {
|
||||
this.queue = queue;
|
||||
}
|
||||
|
||||
public FaweQueue getQueue() {
|
||||
return queue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Entity createEntity(final Location location, final BaseEntity entity) {
|
||||
public Entity createEntity(final Location loc, final BaseEntity entity) {
|
||||
if (entity != null) {
|
||||
TaskManager.IMP.task(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
FastWorldEditExtent.super.createEntity(location, entity);
|
||||
}
|
||||
});
|
||||
CompoundTag tag = entity.getNbtData();
|
||||
Map<String, Tag> map = ReflectionUtils.getMap(tag.getValue());
|
||||
map.put("Id", new StringTag(entity.getTypeId()));
|
||||
ListTag pos = (ListTag) map.get("Pos");
|
||||
if (pos != null) {
|
||||
List<Tag> posList = ReflectionUtils.getList(pos.getValue());
|
||||
posList.set(0, new DoubleTag(loc.getX()));
|
||||
posList.set(1, new DoubleTag(loc.getY()));
|
||||
posList.set(2, new DoubleTag(loc.getZ()));
|
||||
}
|
||||
queue.setEntity(loc.getBlockX(), loc.getBlockY(), loc.getBlockZ(), tag);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@ -138,89 +153,10 @@ public class FastWorldEditExtent extends AbstractDelegateExtent {
|
||||
case 151:
|
||||
case 178: {
|
||||
if (block.hasNbtData()) {
|
||||
final Vector loc = new Vector(location.x, location.y, location.z);
|
||||
queue.addTask(x >> 4, z >> 4, new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
FastWorldEditExtent.super.setBlock(loc, block);
|
||||
} catch (WorldEditException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
});
|
||||
return true;
|
||||
CompoundTag nbt = block.getNbtData();
|
||||
queue.setTile(x, y, z, nbt);
|
||||
}
|
||||
queue.setBlock(x, y, z, id, FaweCache.hasData(id) ? (byte) block.getData() : 0);
|
||||
return true;
|
||||
}
|
||||
case 0:
|
||||
case 2:
|
||||
case 4:
|
||||
case 13:
|
||||
case 14:
|
||||
case 15:
|
||||
case 20:
|
||||
case 21:
|
||||
case 22:
|
||||
case 30:
|
||||
case 32:
|
||||
case 37:
|
||||
case 39:
|
||||
case 40:
|
||||
case 41:
|
||||
case 42:
|
||||
case 45:
|
||||
case 46:
|
||||
case 47:
|
||||
case 48:
|
||||
case 49:
|
||||
case 51:
|
||||
case 56:
|
||||
case 57:
|
||||
case 58:
|
||||
case 60:
|
||||
case 7:
|
||||
case 8:
|
||||
case 9:
|
||||
case 10:
|
||||
case 11:
|
||||
case 73:
|
||||
case 74:
|
||||
case 78:
|
||||
case 79:
|
||||
case 80:
|
||||
case 81:
|
||||
case 82:
|
||||
case 83:
|
||||
case 85:
|
||||
case 87:
|
||||
case 88:
|
||||
case 101:
|
||||
case 102:
|
||||
case 103:
|
||||
case 110:
|
||||
case 112:
|
||||
case 113:
|
||||
case 121:
|
||||
case 122:
|
||||
case 129:
|
||||
case 133:
|
||||
case 165:
|
||||
case 166:
|
||||
case 169:
|
||||
case 170:
|
||||
case 172:
|
||||
case 173:
|
||||
case 174:
|
||||
case 181:
|
||||
case 182:
|
||||
case 188:
|
||||
case 189:
|
||||
case 190:
|
||||
case 191:
|
||||
case 192: {
|
||||
queue.setBlock(x, y, z, id, (byte) 0);
|
||||
queue.setBlock(x, y, z, id, (byte) block.getData());
|
||||
return true;
|
||||
}
|
||||
default: {
|
||||
|
@ -73,16 +73,23 @@ public class FastByteArrayOutputStream extends OutputStream {
|
||||
}
|
||||
|
||||
public byte[] toByteArray() {
|
||||
return toByteArray(false);
|
||||
}
|
||||
|
||||
public byte[] toByteArray(boolean delete) {
|
||||
byte[] data = new byte[getSize()];
|
||||
|
||||
// Check if we have a list of buffers
|
||||
int pos = 0;
|
||||
|
||||
buffer = null;
|
||||
if (buffers != null) {
|
||||
Iterator iter = buffers.iterator();
|
||||
|
||||
while (iter.hasNext()) {
|
||||
byte[] bytes = (byte[])iter.next();
|
||||
if (delete) {
|
||||
iter.remove();
|
||||
}
|
||||
System.arraycopy(bytes, 0, data, pos, blockSize);
|
||||
pos += blockSize;
|
||||
}
|
||||
|
@ -3,7 +3,9 @@ package com.boydti.fawe.util;
|
||||
import com.boydti.fawe.Fawe;
|
||||
import com.boydti.fawe.config.BBC;
|
||||
import com.boydti.fawe.object.FaweChunk;
|
||||
import com.boydti.fawe.object.RunnableVal2;
|
||||
import com.boydti.fawe.object.exception.FaweException;
|
||||
import com.sk89q.jnbt.CompoundTag;
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
import com.sk89q.worldedit.world.biome.BaseBiome;
|
||||
import java.util.HashSet;
|
||||
@ -15,6 +17,7 @@ public abstract class FaweQueue {
|
||||
public final String world;
|
||||
public LinkedBlockingDeque<EditSession> sessions;
|
||||
public long modified = System.currentTimeMillis();
|
||||
public RunnableVal2<FaweChunk, FaweChunk> changeTask;
|
||||
|
||||
public FaweQueue(String world) {
|
||||
this.world = world;
|
||||
@ -34,10 +37,22 @@ public abstract class FaweQueue {
|
||||
return sessions == null ? new HashSet<EditSession>() : new HashSet<>(sessions);
|
||||
}
|
||||
|
||||
public void setChangeTask(RunnableVal2<FaweChunk, FaweChunk> changeTask) {
|
||||
this.changeTask = changeTask;
|
||||
}
|
||||
|
||||
public RunnableVal2<FaweChunk, FaweChunk> getChangeTask() {
|
||||
return changeTask;
|
||||
}
|
||||
|
||||
public void optimize() {}
|
||||
|
||||
public abstract boolean setBlock(final int x, final int y, final int z, final short id, final byte data);
|
||||
|
||||
public abstract void setTile(int x, int y, int z, CompoundTag tag);
|
||||
|
||||
public abstract void setEntity(int x, int y, int z, CompoundTag tag);
|
||||
|
||||
public abstract boolean setBiome(final int x, final int z, final BaseBiome biome);
|
||||
|
||||
public abstract FaweChunk<?> getChunk(int x, int z);
|
||||
@ -88,7 +103,9 @@ public abstract class FaweQueue {
|
||||
*/
|
||||
public abstract void clear();
|
||||
|
||||
public abstract void addTask(int x, int z, Runnable runnable);
|
||||
public abstract void addNotifyTask(int x, int z, Runnable runnable);
|
||||
|
||||
public abstract void addNotifyTask(Runnable runnable);
|
||||
|
||||
public abstract int getCombinedId4Data(int x, int y, int z) throws FaweException.FaweChunkLoadException;
|
||||
|
||||
|
@ -1,81 +0,0 @@
|
||||
package com.boydti.fawe.util;
|
||||
|
||||
/**
|
||||
* TPS and Lag Checker.
|
||||
*/
|
||||
public class Lag implements Runnable {
|
||||
/**
|
||||
* Ticks
|
||||
*/
|
||||
public static final long[] T = new long[600];
|
||||
/**
|
||||
* Tick count
|
||||
*/
|
||||
public static int TC = 0;
|
||||
/**
|
||||
* something :_:
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public static long LT = 0L;
|
||||
|
||||
/**
|
||||
* Get the server TPS
|
||||
*
|
||||
* @return server tick per second
|
||||
*/
|
||||
public static double getTPS() {
|
||||
return Math.round(getTPS(100)) > 20.0D ? 20.0D : Math.round(getTPS(100));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the tick per second (measured in $ticks)
|
||||
*
|
||||
* @param ticks Ticks
|
||||
*
|
||||
* @return ticks per second
|
||||
*/
|
||||
public static double getTPS(final int ticks) {
|
||||
if (TC < ticks) {
|
||||
return 20.0D;
|
||||
}
|
||||
final int t = (TC - 1 - ticks) % T.length;
|
||||
final long e = System.currentTimeMillis() - T[t];
|
||||
return ticks / (e / 1000.0D);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get number of ticks since
|
||||
*
|
||||
* @param tI Ticks <
|
||||
*
|
||||
* @return number of ticks since $tI
|
||||
*/
|
||||
public static long getElapsed(final int tI) {
|
||||
final long t = T[tI % T.length];
|
||||
return System.currentTimeMillis() - t;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get lag percentage
|
||||
*
|
||||
* @return lag percentage
|
||||
*/
|
||||
public static double getPercentage() {
|
||||
return Math.round((1.0D - (Lag.getTPS() / 20.0D)) * 100.0D);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get TPS percentage (of 20)
|
||||
*
|
||||
* @return TPS percentage
|
||||
*/
|
||||
public static double getFullPercentage() {
|
||||
return getTPS() * 5.0D;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
T[TC % T.length] = System.currentTimeMillis();
|
||||
TC++;
|
||||
}
|
||||
}
|
@ -5,14 +5,20 @@ import com.boydti.fawe.config.BBC;
|
||||
import com.boydti.fawe.object.FawePlayer;
|
||||
import com.boydti.fawe.object.RegionWrapper;
|
||||
import com.boydti.fawe.object.RunnableVal;
|
||||
import com.boydti.fawe.object.changeset.FaweChangeSet;
|
||||
import com.boydti.fawe.object.changeset.FaweStreamChangeSet;
|
||||
import com.sk89q.jnbt.CompoundTag;
|
||||
import com.sk89q.jnbt.DoubleTag;
|
||||
import com.sk89q.jnbt.EndTag;
|
||||
import com.sk89q.jnbt.IntTag;
|
||||
import com.sk89q.jnbt.ListTag;
|
||||
import com.sk89q.jnbt.StringTag;
|
||||
import com.sk89q.jnbt.Tag;
|
||||
import com.sk89q.worldedit.entity.Entity;
|
||||
import com.sk89q.worldedit.extension.platform.Actor;
|
||||
import com.sk89q.worldedit.util.Location;
|
||||
import java.io.File;
|
||||
import java.lang.reflect.Array;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
@ -39,7 +45,27 @@ public class MainUtil {
|
||||
Fawe.debug(s);
|
||||
}
|
||||
|
||||
public static void sendCompressedMessage(FaweChangeSet set, Actor actor)
|
||||
public static void setPosition(CompoundTag tag, int x, int y, int z) {
|
||||
Map<String, Tag> value = ReflectionUtils.getMap(tag.getValue());
|
||||
value.put("x", new IntTag(x));
|
||||
value.put("y", new IntTag(y));
|
||||
value.put("z", new IntTag(z));
|
||||
}
|
||||
|
||||
public static void setEntityInfo(CompoundTag tag, Entity entity) {
|
||||
Map<String, Tag> map = ReflectionUtils.getMap(tag.getValue());
|
||||
map.put("Id", new StringTag(entity.getState().getTypeId()));
|
||||
ListTag pos = (ListTag) map.get("Pos");
|
||||
if (pos != null) {
|
||||
Location loc = entity.getLocation();
|
||||
List<Tag> posList = ReflectionUtils.getList(pos.getValue());
|
||||
posList.set(0, new DoubleTag(loc.getX()));
|
||||
posList.set(1, new DoubleTag(loc.getY()));
|
||||
posList.set(2, new DoubleTag(loc.getZ()));
|
||||
}
|
||||
}
|
||||
|
||||
public static void sendCompressedMessage(FaweStreamChangeSet set, Actor actor)
|
||||
{
|
||||
try {
|
||||
int elements = set.size();
|
||||
|
@ -43,6 +43,18 @@ public class MathMan {
|
||||
253, 254, 254, 255
|
||||
};
|
||||
|
||||
public static byte pair16(byte x, byte y) {
|
||||
return (byte) (x + (y << 4));
|
||||
}
|
||||
|
||||
public static byte unpair16x(byte value) {
|
||||
return (byte) (value & 0xF);
|
||||
}
|
||||
|
||||
public static byte unpair16y(byte value) {
|
||||
return (byte) ((value >> 4) & 0xF);
|
||||
}
|
||||
|
||||
public static int sqrt(int x) {
|
||||
int xn;
|
||||
|
||||
|
@ -57,18 +57,30 @@ public class ReflectionUtils {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static <T, V> Map<T, V> getMap(Map<T, V> map) {
|
||||
try {
|
||||
Class<? extends Map> clazz = map.getClass();
|
||||
Field m = clazz.getDeclaredField("m");
|
||||
m.setAccessible(true);
|
||||
return (Map<T, V>) m.get(map);
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
return map;
|
||||
}
|
||||
|
||||
public static <T, V> Map<T, V> getMap(Map<T, V> map) {
|
||||
try {
|
||||
Class<? extends Map> clazz = map.getClass();
|
||||
Field m = clazz.getDeclaredField("m");
|
||||
m.setAccessible(true);
|
||||
return (Map<T, V>) m.get(map);
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
return map;
|
||||
}
|
||||
}
|
||||
|
||||
public static <T> List<T> getList(List<T> list) {
|
||||
try {
|
||||
Class<? extends List> clazz = (Class<? extends List>) Class.forName("java.util.Collections$UnmodifiableList");
|
||||
Field m = clazz.getDeclaredField("list");
|
||||
m.setAccessible(true);
|
||||
return (List<T>) m.get(list);
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
return list;
|
||||
}
|
||||
}
|
||||
|
||||
public static Class<?> getNmsClass(final String name) {
|
||||
final String className = "net.minecraft.server." + getVersion() + "." + name;
|
||||
|
@ -15,6 +15,10 @@ public class SetQueue {
|
||||
*/
|
||||
public static final SetQueue IMP = new SetQueue();
|
||||
|
||||
public static enum QueueStage {
|
||||
INACTIVE, ACTIVE, NONE;
|
||||
}
|
||||
|
||||
public final LinkedBlockingDeque<FaweQueue> activeQueues;
|
||||
public final LinkedBlockingDeque<FaweQueue> inactiveQueues;
|
||||
|
||||
@ -113,6 +117,27 @@ public class SetQueue {
|
||||
}, 1);
|
||||
}
|
||||
|
||||
public QueueStage getStage(FaweQueue queue) {
|
||||
if (activeQueues.contains(queue)) {
|
||||
return QueueStage.ACTIVE;
|
||||
} else if (inactiveQueues.contains(queue)) {
|
||||
return QueueStage.INACTIVE;
|
||||
}
|
||||
return QueueStage.NONE;
|
||||
}
|
||||
|
||||
public boolean isStage(FaweQueue queue, QueueStage stage) {
|
||||
switch (stage) {
|
||||
case ACTIVE:
|
||||
return activeQueues.contains(queue);
|
||||
case INACTIVE:
|
||||
return inactiveQueues.contains(queue);
|
||||
case NONE:
|
||||
return !activeQueues.contains(queue) && !inactiveQueues.contains(queue);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void enqueue(FaweQueue queue) {
|
||||
inactiveQueues.remove(queue);
|
||||
if (queue.size() > 0 && !activeQueues.contains(queue)) {
|
||||
|
@ -304,7 +304,7 @@ public class WorldWrapper extends AbstractWorld {
|
||||
try {
|
||||
final BaseBlock block = getBlock(loc);
|
||||
final Vector v = new Vector(loc.x, loc.y, loc.z);
|
||||
queue.addTask(cx, cz, new Runnable() {
|
||||
queue.addNotifyTask(cx, cz, new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
|
@ -327,7 +327,11 @@ public class EditSession implements Extent {
|
||||
|
||||
// History
|
||||
this.changeSet = Settings.STORE_HISTORY_ON_DISK ? new DiskStorageHistory(world, actor.getUniqueId()) : new MemoryOptimizedHistory(actor);
|
||||
extent = this.wrapper.getHistoryExtent(this, limit, extent, this.changeSet, queue, fp);
|
||||
if (Settings.COMBINE_HISTORY_STAGE) {
|
||||
changeSet.addChangeTask(queue);
|
||||
} else {
|
||||
extent = this.wrapper.getHistoryExtent(this, limit, extent, this.changeSet, queue, fp);
|
||||
}
|
||||
|
||||
// Region restrictions if mask is not null
|
||||
if (mask != null) {
|
||||
@ -875,7 +879,7 @@ public class EditSession implements Extent {
|
||||
editSession.flushQueue();
|
||||
}
|
||||
}, true);
|
||||
editSession.changes = changes;
|
||||
editSession.changes = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -892,7 +896,7 @@ public class EditSession implements Extent {
|
||||
editSession.flushQueue();
|
||||
}
|
||||
}, true);
|
||||
editSession.changes = changes;
|
||||
editSession.changes = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -19,7 +19,9 @@
|
||||
|
||||
package com.sk89q.worldedit;
|
||||
|
||||
import com.boydti.fawe.config.Settings;
|
||||
import com.boydti.fawe.object.changeset.FaweChangeSet;
|
||||
import com.boydti.fawe.object.changeset.FaweStreamChangeSet;
|
||||
import com.boydti.fawe.object.clipboard.DiskOptimizedClipboard;
|
||||
import com.boydti.fawe.util.FaweQueue;
|
||||
import com.boydti.fawe.util.MainUtil;
|
||||
@ -80,7 +82,7 @@ public class LocalSession {
|
||||
private transient RegionSelector selector = new CuboidRegionSelector();
|
||||
private transient boolean placeAtPos1 = false;
|
||||
private transient List<EditSession> history = Collections.synchronizedList(new LinkedList<EditSession>());
|
||||
private transient int historyPointer = 0;
|
||||
private transient volatile int historyPointer = 0;
|
||||
private transient ClipboardHolder clipboard;
|
||||
private transient boolean toolControl = true;
|
||||
private transient boolean superPickaxe = false;
|
||||
@ -200,7 +202,7 @@ public class LocalSession {
|
||||
remember(editSession, true);
|
||||
}
|
||||
|
||||
public void remember(EditSession editSession, boolean append) {
|
||||
public void remember(final EditSession editSession, final boolean append) {
|
||||
// Enqueue it
|
||||
if (editSession.getQueue() != null) {
|
||||
FaweQueue queue = editSession.getQueue();
|
||||
@ -217,12 +219,25 @@ public class LocalSession {
|
||||
history.remove(historyPointer);
|
||||
}
|
||||
ChangeSet set = editSession.getChangeSet();
|
||||
if (set instanceof FaweChangeSet) {
|
||||
FaweChangeSet fcs = (FaweChangeSet) set;
|
||||
if (fcs.flush() && append) {
|
||||
MainUtil.sendCompressedMessage(fcs, editSession.actor);
|
||||
if (set instanceof FaweStreamChangeSet) {
|
||||
final FaweStreamChangeSet fcs = (FaweStreamChangeSet) set;
|
||||
if (Settings.COMBINE_HISTORY_STAGE) {
|
||||
editSession.getQueue().addNotifyTask(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (fcs.flush() && append) {
|
||||
MainUtil.sendCompressedMessage(fcs, editSession.actor);
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
if (fcs.flush() && append) {
|
||||
MainUtil.sendCompressedMessage(fcs, editSession.actor);
|
||||
}
|
||||
}
|
||||
|
||||
} else if (set instanceof FaweChangeSet) {
|
||||
((FaweChangeSet) set).flush();
|
||||
}
|
||||
if (append) {
|
||||
history.add(editSession);
|
||||
@ -232,7 +247,7 @@ public class LocalSession {
|
||||
while (history.size() > MAX_HISTORY_SIZE) {
|
||||
history.remove(0);
|
||||
}
|
||||
historyPointer = history.size();
|
||||
historyPointer = append ? history.size() : historyPointer + 1;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -263,6 +278,7 @@ public class LocalSession {
|
||||
newEditSession.enableQueue();
|
||||
newEditSession.setFastMode(fastMode);
|
||||
editSession.undo(newEditSession);
|
||||
System.out.println("UNDO: " + historyPointer + " | " + history.size());
|
||||
return editSession;
|
||||
} else {
|
||||
historyPointer = 0;
|
||||
@ -290,6 +306,7 @@ public class LocalSession {
|
||||
*/
|
||||
public EditSession redo(@Nullable BlockBag newBlockBag, Player player) {
|
||||
checkNotNull(player);
|
||||
System.out.println("CHECK REDO: " + historyPointer + " | " + history.size());
|
||||
if (historyPointer < history.size()) {
|
||||
EditSession editSession = history.get(historyPointer);
|
||||
EditSession newEditSession = WorldEdit.getInstance().getEditSessionFactory()
|
||||
@ -298,7 +315,10 @@ public class LocalSession {
|
||||
newEditSession.setFastMode(fastMode);
|
||||
editSession.redo(newEditSession);
|
||||
++historyPointer;
|
||||
System.out.println("CAN REDO");
|
||||
return editSession;
|
||||
} else {
|
||||
System.out.println("POINTER");
|
||||
}
|
||||
|
||||
return null;
|
||||
|
@ -224,6 +224,7 @@ public final class CommandManager {
|
||||
TaskManager.IMP.async(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
System.out.println("COMMAND START!");
|
||||
final Actor actor = platformManager.createProxyActor(event.getActor());
|
||||
String[] split = commandDetection(event.getArguments().split(" "));
|
||||
|
||||
@ -284,6 +285,7 @@ public final class CommandManager {
|
||||
log.log(Level.SEVERE, "An unknown error occurred", e);
|
||||
}
|
||||
} finally {
|
||||
System.out.println("DONE!");
|
||||
if (fp != null) {
|
||||
fp.deleteMeta("fawe_action");
|
||||
}
|
||||
|
@ -62,7 +62,6 @@ public class ChangeSetExecutor implements Operation {
|
||||
|
||||
@Override
|
||||
public Operation resume(RunContext run) throws WorldEditException {
|
||||
int size = 0;
|
||||
if (type == Type.UNDO) {
|
||||
while (iterator.hasNext()) {
|
||||
iterator.next().undo(context);
|
||||
|
144
pom.xml
144
pom.xml
@ -12,53 +12,94 @@
|
||||
<name>FastAsyncWorldEdit</name>
|
||||
<packaging>jar</packaging>
|
||||
<build>
|
||||
<finalName>FastAsyncWorldEdit-Bukkit-${project.version}</finalName>
|
||||
<sourceDirectory>Bukkit/src/main/java</sourceDirectory>
|
||||
<finalName>FastAsyncWorldEdit-UBER-${project.version}</finalName>
|
||||
<sourceDirectory>core/src/main/java</sourceDirectory>
|
||||
<resources>
|
||||
<resource>
|
||||
<filtering>true</filtering>
|
||||
<includes>
|
||||
<include>**/*.*</include>
|
||||
</includes>
|
||||
<directory>bukkit/src/main/resources/</directory>
|
||||
</resource>
|
||||
<resource>
|
||||
<filtering>false</filtering>
|
||||
<includes>
|
||||
<include>**/*.*</include>
|
||||
</includes>
|
||||
<directory>core/src/main/resources/</directory>
|
||||
</resource>
|
||||
<resource>
|
||||
<filtering>false</filtering>
|
||||
<includes>
|
||||
<include>**/*.*</include>
|
||||
</includes>
|
||||
<directory>bukkit19/src/main/resources/</directory>
|
||||
</resource>
|
||||
<resource>
|
||||
<filtering>false</filtering>
|
||||
<includes>
|
||||
<include>**/*.*</include>
|
||||
</includes>
|
||||
<directory>bukkit18/src/main/resources/</directory>
|
||||
</resource>
|
||||
</resources>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>2.3.2</version>
|
||||
<configuration>
|
||||
<excludes>
|
||||
<exclude>**/forge/src/main/**/*.*</exclude>
|
||||
</excludes>
|
||||
<source>1.7</source>
|
||||
<target>1.7</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>build-helper-maven-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>generate-sources</phase>
|
||||
<goals>
|
||||
<goal>add-source</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<sources>
|
||||
<source>core/src/main/java</source>
|
||||
</sources>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-jar-plugin</artifactId>
|
||||
<version>2.6</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>jar</goal>
|
||||
</goals>
|
||||
<id>Bukkit19</id>
|
||||
<configuration>
|
||||
<finalName>FastAsyncWorldEdit-Bukkit19-${project.version}</finalName>
|
||||
<excludes>
|
||||
<exclude>**/forge180/src/main/**/*.*</exclude>
|
||||
<exclude>**/forge1710/src/main/**/*.*</exclude>
|
||||
<exclude>com/boydti/fawe/bukkit/v1_8/**/*.*</exclude>
|
||||
</excludes>
|
||||
</configuration>
|
||||
</execution>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>jar</goal>
|
||||
</goals>
|
||||
<id>Bukkit18</id>
|
||||
<configuration>
|
||||
<finalName>FastAsyncWorldEdit-Bukkit18-${project.version}</finalName>
|
||||
<excludes>
|
||||
<exclude>**/forge180/src/main/**/*.*</exclude>
|
||||
<exclude>**/forge1710/src/main/**/*.*</exclude>
|
||||
<exclude>com/boydti/fawe/bukkit/v1_9/**/*.*</exclude>
|
||||
</excludes>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>2.3.2</version>
|
||||
<configuration>
|
||||
<source>1.7</source>
|
||||
<target>1.7</target>
|
||||
<excludes>
|
||||
<exclude>**/forge180/src/main/**/*.*</exclude>
|
||||
<exclude>**/forge1710/src/main/**/*.*</exclude>
|
||||
</excludes>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>build-helper-maven-plugin</artifactId>
|
||||
<version>1.7</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>add-source</id>
|
||||
<phase>generate-sources</phase>
|
||||
<goals>
|
||||
<goal>add-source</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<sources>
|
||||
<source>bukkit0/src/main/java</source>
|
||||
<source>bukkit18/src/main/java</source>
|
||||
<source>bukkit19/src/main/java</source>
|
||||
</sources>
|
||||
<compilerArgument>-proc:none</compilerArgument>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
<repositories>
|
||||
@ -114,6 +155,16 @@
|
||||
<artifactId>bukkit</artifactId>
|
||||
<version>1.9-R0.1-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.bukkit.craftbukkit.v1_8</groupId>
|
||||
<artifactId>craftbukkitv1_8</artifactId>
|
||||
<version>1.8.9</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.bukkit.craftbukkit</groupId>
|
||||
<artifactId>CraftBukkit</artifactId>
|
||||
<version>1.9.2</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.PrimeSoft</groupId>
|
||||
<artifactId>blockshub</artifactId>
|
||||
@ -129,6 +180,11 @@
|
||||
<artifactId>factions</artifactId>
|
||||
<version>1.6.9.5</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.factionsone</groupId>
|
||||
<artifactId>FactionsOne</artifactId>
|
||||
<version>1.2.2</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>me.ryanhamshire</groupId>
|
||||
<artifactId>GriefPrevention</artifactId>
|
||||
|
Loading…
Reference in New Issue
Block a user