Minor inventory + queue management changes

This commit is contained in:
Jesse Boyd 2016-10-17 18:04:33 +11:00
parent 135d936825
commit 295aad0f2f
No known key found for this signature in database
GPG Key ID: 59F1DE6293AF6E1F
17 changed files with 374 additions and 115 deletions

View File

@ -17,7 +17,6 @@ import org.bukkit.block.Block;
public class BukkitQueue_All extends BukkitQueue_0<Chunk, Chunk, Chunk> {
public static int ALLOCATE;
public static double TPS_TARGET = 18.5;
private static int LIGHT_MASK = 0x739C0;
public BukkitQueue_All(com.sk89q.worldedit.world.World world) {

View File

@ -51,6 +51,7 @@ import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard;
import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormat;
import com.sk89q.worldedit.extent.clipboard.io.SchematicReader;
import com.sk89q.worldedit.extent.clipboard.io.SchematicWriter;
import com.sk89q.worldedit.extent.inventory.BlockBagExtent;
import com.sk89q.worldedit.extent.transform.BlockTransformExtent;
import com.sk89q.worldedit.function.entity.ExtentEntityCopy;
import com.sk89q.worldedit.function.mask.BlockMask;
@ -389,6 +390,7 @@ public class Fawe {
// Extents
BlockTransformExtent.inject(); // Fix for cache not being mutable
AbstractDelegateExtent.inject(); // Optimizations
BlockBagExtent.inject(); // Fixes + Optimizations
// Vector
Vector.inject(); // Optimizations
// Pattern

View File

@ -16,6 +16,7 @@ import com.sk89q.jnbt.StringTag;
import com.sk89q.jnbt.Tag;
import com.sk89q.worldedit.CuboidClipboard;
import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.blocks.BaseItem;
import com.sk89q.worldedit.world.registry.BundledBlockData;
import java.awt.Color;
import java.lang.reflect.Field;
@ -65,6 +66,8 @@ public class FaweCache {
*/
public final static BaseBlock[] CACHE_BLOCK = new BaseBlock[Character.MAX_VALUE + 1];
public final static BaseItem[] CACHE_ITEM = new BaseItem[Character.MAX_VALUE + 1];
/**
* Faster than java random (since it just needs to look random)
*/
@ -83,6 +86,10 @@ public class FaweCache {
return CACHE_BLOCK[(id << 4) + data];
}
public static final BaseItem getItem(int id, int data) {
return CACHE_ITEM[(id << 4) + data];
}
/**
* Get the combined data for a block
* @param id
@ -174,6 +181,23 @@ public class FaweCache {
return true;
}
};
CACHE_ITEM[i] = new BaseItem(id, (short) data) {
@Override
public void setData(short data) {
throw new IllegalStateException("Cannot set data");
}
@Override
public void setDamage(short data) {
throw new IllegalStateException("Cannot set data");
}
@Override
public void setType(int id) {
throw new IllegalStateException("Cannot set id");
}
};
}
CACHE_COLOR[getCombined(0, 0)] = new Color(128, 128, 128); //Air

View File

@ -169,6 +169,7 @@ public enum BBC {
"Error"),
WORLDEDIT_SOME_FAILS("&c%s0 blocks weren't placed because they were outside your allowed region.", "Error"),
WORLDEDIT_SOME_FAILS_BLOCKBAG("&cMissing blocks: %s0", "Error"),
WORLDEDIT_CANCEL_COUNT("&cCancelled %s0 edits.", "Cancel"),
WORLDEDIT_CANCEL_REASON("&cYour WorldEdit action was cancelled:&7 %s0&c.", "Cancel"),

View File

@ -3,17 +3,14 @@ package com.boydti.fawe.logging;
import com.boydti.fawe.Fawe;
import com.boydti.fawe.FaweCache;
import com.boydti.fawe.object.FawePlayer;
import com.boydti.fawe.object.changeset.AbstractDelegateChangeSet;
import com.boydti.fawe.object.changeset.FaweChangeSet;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.worldedit.extent.inventory.BlockBag;
import com.sk89q.worldedit.history.change.Change;
import java.util.Iterator;
import org.bukkit.entity.Player;
import org.primesoft.blockshub.IBlocksHubApi;
import org.primesoft.blockshub.api.IPlayer;
import org.primesoft.blockshub.api.IWorld;
public class LoggingChangeSet extends FaweChangeSet {
public class LoggingChangeSet extends AbstractDelegateChangeSet {
private static boolean initialized = false;
@ -30,8 +27,6 @@ public class LoggingChangeSet extends FaweChangeSet {
public static IBlocksHubApi api;
private final FaweChangeSet parent;
private final MutableVector loc;
private final IPlayer player;
private final IWorld world;
@ -39,8 +34,7 @@ public class LoggingChangeSet extends FaweChangeSet {
private final MutableBlockData newBlock;
private LoggingChangeSet(FawePlayer player, FaweChangeSet parent) {
super(parent.getWorld());
this.parent = parent;
super(parent);
this.world = api.getWorld(player.getLocation().world);
this.loc = new MutableVector();
this.oldBlock = new MutableBlockData();
@ -48,11 +42,6 @@ public class LoggingChangeSet extends FaweChangeSet {
this.player = api.getPlayer(player.getUUID());
}
@Override
public boolean flush() {
return parent.flush();
}
@Override
public void add(int x, int y, int z, int combinedId4DataFrom, int combinedId4DataTo) {
// Mutable (avoids object creation)
@ -67,39 +56,4 @@ public class LoggingChangeSet extends FaweChangeSet {
api.logBlock(loc, player, world, oldBlock, newBlock);
parent.add(x, y, z, combinedId4DataFrom, combinedId4DataTo);
}
@Override
public void addTileCreate(CompoundTag tag) {
parent.addTileCreate(tag);
}
@Override
public void addTileRemove(CompoundTag tag) {
parent.addTileRemove(tag);
}
@Override
public void addEntityRemove(CompoundTag tag) {
parent.addEntityRemove(tag);
}
@Override
public void addEntityCreate(CompoundTag tag) {
parent.addEntityCreate(tag);
}
@Override
public Iterator<Change> getIterator(BlockBag blockBag, int mode, boolean redo) {
return parent.getIterator(blockBag, mode, redo);
}
@Override
public Iterator<Change> getIterator(boolean undo) {
return parent.getIterator(undo);
}
@Override
public int size() {
return parent.size();
}
}

View File

@ -2,6 +2,7 @@ package com.boydti.fawe.object;
import com.boydti.fawe.FaweCache;
import com.boydti.fawe.object.changeset.FaweChangeSet;
import com.boydti.fawe.object.exception.FaweException;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.Vector;
@ -67,20 +68,24 @@ public class HistoryExtent extends AbstractDelegateExtent {
return false;
}
}
if (!FaweCache.hasNBT(id)) {
if (FaweCache.hasNBT(block.getId())) {
this.changeSet.add(x, y, z, combined, block);
try {
if (!FaweCache.hasNBT(id)) {
if (FaweCache.hasNBT(block.getId())) {
this.changeSet.add(x, y, z, combined, block);
} else {
this.changeSet.add(x, y, z, combined, (block.getId() << 4) + block.getData());
}
} else {
this.changeSet.add(x, y, z, combined, (block.getId() << 4) + block.getData());
}
} else {
try {
CompoundTag tag = queue.getTileEntity(x, y, z);
this.changeSet.add(x, y, z, new BaseBlock(id, combined & 0xF, tag), block);
} catch (Throwable e) {
e.printStackTrace();
this.changeSet.add(x, y, z, combined, block);
try {
CompoundTag tag = queue.getTileEntity(x, y, z);
this.changeSet.add(x, y, z, new BaseBlock(id, combined & 0xF, tag), block);
} catch (Throwable e) {
e.printStackTrace();
this.changeSet.add(x, y, z, combined, block);
}
}
} catch (FaweException ignore) {
return false;
}
return extent.setBlock(x, y, z, block);
}

View File

@ -60,24 +60,24 @@ public class MutableFullBlockChange implements Change {
public void perform(FaweQueue queue) {
int idFrom = FaweCache.getId(from);
int dataFrom = FaweCache.getData(from);
if (blockBag != null) {
if (allowFetch && idFrom != 0) {
try {
blockBag.fetchPlacedBlock(idFrom, dataFrom);
} catch (BlockBagException e) {
return;
}
}
int idTo = FaweCache.getId(to);
int dataTo = FaweCache.getData(to);
if (allowStore && idTo != 0) {
try {
blockBag.storeDroppedBlock(idTo, dataTo);
} catch (BlockBagException ignored) {
if (idFrom != idTo) {
if (allowFetch && from != 0) {
try {
blockBag.fetchPlacedBlock(idFrom, FaweCache.getData(from));
} catch (BlockBagException e) {
return;
}
}
if (allowStore && to != 0) {
try {
blockBag.storeDroppedBlock(idTo, FaweCache.getData(to));
} catch (BlockBagException ignored) {
}
}
}
}
queue.setBlock(x, y, z, idFrom, dataFrom);
queue.setBlock(x, y, z, idFrom, FaweCache.getData(from));
}
}

View File

@ -0,0 +1,148 @@
package com.boydti.fawe.object.changeset;
import com.boydti.fawe.object.FawePlayer;
import com.boydti.fawe.object.FaweQueue;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.extent.inventory.BlockBag;
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.world.World;
import java.util.Iterator;
import java.util.UUID;
public class AbstractDelegateChangeSet extends FaweChangeSet {
public final FaweChangeSet parent;
public AbstractDelegateChangeSet(FaweChangeSet parent) {
super(parent.getWorld());
this.parent = parent;
}
public final FaweChangeSet getParent() {
return parent;
}
public static FaweChangeSet getDefaultChangeSet(World world, UUID uuid) {
return FaweChangeSet.getDefaultChangeSet(world, uuid);
}
@Override
public World getWorld() {
return parent.getWorld();
}
@Override
public boolean flushAsync() {
return parent.flushAsync();
}
@Override
public boolean flush() {
return parent.flush();
}
@Override
public void add(int x, int y, int z, int combinedFrom, int combinedTo) {
parent.add(x, y, z, combinedFrom, combinedTo);
}
@Override
public Iterator<Change> backwardIterator() {
return parent.backwardIterator();
}
@Override
public Iterator<Change> forwardIterator() {
return parent.forwardIterator();
}
@Override
public int size() {
return parent.size();
}
@Override
public void addTileCreate(CompoundTag tag) {
parent.addTileCreate(tag);
}
@Override
public void addTileRemove(CompoundTag tag) {
parent.addTileRemove(tag);
}
@Override
public void addEntityRemove(CompoundTag tag) {
parent.addEntityRemove(tag);
}
@Override
public void addEntityCreate(CompoundTag tag) {
parent.addEntityCreate(tag);
}
@Override
public Iterator<Change> getIterator(BlockBag blockBag, int mode, boolean redo) {
return parent.getIterator(blockBag, mode, redo);
}
@Override
public Iterator<Change> getIterator(boolean redo) {
return parent.getIterator(redo);
}
@Override
public void delete() {
parent.delete();
}
@Override
public EditSession toEditSession(FawePlayer player) {
return parent.toEditSession(player);
}
@Override
public void add(EntityCreate change) {
parent.add(change);
}
@Override
public void add(EntityRemove change) {
parent.add(change);
}
@Override
public void add(Change change) {
parent.add(change);
}
@Override
public void add(BlockChange change) {
parent.add(change);
}
@Override
public void add(Vector loc, BaseBlock from, BaseBlock to) {
parent.add(loc, from, to);
}
@Override
public void add(int x, int y, int z, BaseBlock from, BaseBlock to) {
parent.add(x, y, z, from, to);
}
@Override
public void add(int x, int y, int z, int combinedFrom, BaseBlock to) {
parent.add(x, y, z, combinedFrom, to);
}
@Override
public void addChangeTask(FaweQueue queue) {
parent.addChangeTask(queue);
}
}

View File

@ -0,0 +1,96 @@
package com.boydti.fawe.object.changeset;
import com.boydti.fawe.FaweCache;
import com.boydti.fawe.object.exception.FaweException;
import com.boydti.fawe.util.ReflectionUtils;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.jnbt.Tag;
import com.sk89q.worldedit.extent.inventory.BlockBag;
import com.sk89q.worldedit.extent.inventory.BlockBagException;
import com.sk89q.worldedit.extent.inventory.UnplaceableBlockException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import javax.annotation.Nullable;
public class BlockBagChangeSet extends AbstractDelegateChangeSet {
private final boolean mine;
private int[] missingBlocks = new int[Character.MAX_VALUE + 1];
private BlockBag blockBag;
public BlockBagChangeSet(FaweChangeSet parent, BlockBag blockBag, boolean mine) {
super(parent);
this.blockBag = blockBag;
this.mine = mine;
}
/**
* Get the block bag.
*
* @return a block bag, which may be null if none is used
*/
public @Nullable
BlockBag getBlockBag() {
return blockBag;
}
/**
* Set the block bag.
*
* @param blockBag a block bag, which may be null if none is used
*/
public void setBlockBag(@Nullable BlockBag blockBag) {
this.blockBag = blockBag;
}
/**
* Gets the list of missing blocks and clears the list for the next
* operation.
*
* @return a map of missing blocks
*/
public Map<Integer, Integer> popMissing() {
HashMap<Integer, Integer> map = new HashMap<>();
for (int i = 0; i < missingBlocks.length; i++) {
int count = missingBlocks[i];
if (count > 0) {
map.put(i, count);
}
}
Arrays.fill(missingBlocks, 0);
return map;
}
@Override
public void add(int x, int y, int z, int combinedFrom, int combinedTo) {
if (combinedTo != 0) {
try {
blockBag.fetchPlacedBlock(FaweCache.getId(combinedTo), FaweCache.getData(combinedTo));
} catch (UnplaceableBlockException e) {
throw new FaweException.FaweBlockBagException();
} catch (BlockBagException e) {
missingBlocks[combinedTo]++;
throw new FaweException.FaweBlockBagException();
}
}
if (mine) {
if (combinedFrom != 0) {
try {
blockBag.storeDroppedBlock(FaweCache.getId(combinedFrom), FaweCache.getData(combinedFrom));
} catch (BlockBagException ignored) {}
}
}
super.add(x, y, z, combinedFrom, combinedTo);
}
@Override
public void addTileCreate(CompoundTag nbt) {
if (nbt.containsKey("items")) {
Map<String, Tag> map = ReflectionUtils.getMap(nbt.getValue());
map.remove("items");
}
super.addTileCreate(nbt);
}
}

View File

@ -94,7 +94,9 @@ public abstract class FaweChangeSet implements ChangeSet {
public abstract void addTileRemove(CompoundTag tag);
public abstract void addEntityRemove(CompoundTag tag);
public abstract void addEntityCreate(CompoundTag tag);
public abstract Iterator<Change> getIterator(BlockBag blockBag, int mode, boolean redo);
public Iterator<Change> getIterator(BlockBag blockBag, int mode, boolean redo) {
return getIterator(redo);
}
public abstract Iterator<Change> getIterator(boolean redo);
public void delete() {};

View File

@ -35,6 +35,12 @@ public class FaweException extends RuntimeException {
}
}
public static class FaweBlockBagException extends FaweException {
public FaweBlockBagException() {
super(BBC.WORLDEDIT_SOME_FAILS_BLOCKBAG);
}
}
/**
* Faster exception throwing if you don't fill the stacktrace
* @return

View File

@ -5,9 +5,11 @@ import java.io.OutputStream;
import java.io.RandomAccessFile;
import java.io.Writer;
import java.util.ArrayDeque;
import java.util.Arrays;
import java.util.Iterator;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorCompletionService;
import java.util.concurrent.ForkJoinPool;
/**
@ -101,44 +103,25 @@ public class FastByteArrayOutputStream extends OutputStream {
return data;
}
public byte[] toByteArray() {
byte[] data = new byte[getSize()];
// Check if we have a list of buffers
int pos = 0;
if (buffers != null) {
for (byte[] bytes : buffers) {
System.arraycopy(bytes, 0, data, pos, bytes.length);
pos += bytes.length;
}
}
// write the internal buffer directly
System.arraycopy(buffer, 0, data, pos, index);
return data;
}
public String toString() {
return new String(toByteArray());
}
@Override
public void write(byte[] b) throws IOException {
if (b.length > blockSize) {
if (index > 0) {
byte[] buf2 = new byte[index];
System.arraycopy(buffer, 0, buf2, 0, index);
buffer = buf2;
addBuffer();
public void write(byte[] b) throws IOException {
if (b.length > blockSize) {
if (index > 0) {
byte[] buf2 = new byte[index];
System.arraycopy(buffer, 0, buf2, 0, index);
buffer = buf2;
addBuffer();
}
size += b.length;
buffers.addLast(b);
} else {
write(b, 0, b.length);
}
size += b.length;
buffers.addLast(b);
} else {
write(b, 0, b.length);
}
}
public void write(int datum) {
if (index == blockSize) {

View File

@ -61,6 +61,9 @@ public class FaweTimer implements Runnable {
private long skipTick = 0;
public boolean isAbove(double tps) {
if (tps <= 0) {
return true;
}
if (skip > 0) {
if (skipTick != tick) {
skip--;

View File

@ -60,7 +60,8 @@ public class SetQueue {
@Override
public void run() {
try {
while (!tasks.isEmpty() && Fawe.get().getTimer().isAbove(18.5)) {
double targetTPS = 18 - Math.max(Settings.QUEUE.EXTRA_TIME_MS * 0.05, 0);
while (!tasks.isEmpty() && Fawe.get().getTimer().isAbove(targetTPS)) {
tasks.poll().run();
}
if (inactiveQueues.isEmpty() && activeQueues.isEmpty()) {
@ -86,7 +87,7 @@ public class SetQueue {
}
}
FaweQueue queue = getNextQueue();
if (queue == null || !Fawe.get().getTimer().isAbove(18.5)) {
if (queue == null || !Fawe.get().getTimer().isAbove(targetTPS)) {
return;
}
if (Thread.currentThread() != Fawe.get().getMainThread()) {

View File

@ -36,6 +36,7 @@ import com.boydti.fawe.object.HistoryExtent;
import com.boydti.fawe.object.NullChangeSet;
import com.boydti.fawe.object.RegionWrapper;
import com.boydti.fawe.object.RunnableVal;
import com.boydti.fawe.object.changeset.BlockBagChangeSet;
import com.boydti.fawe.object.changeset.CPUOptimizedChangeSet;
import com.boydti.fawe.object.changeset.DiskStorageHistory;
import com.boydti.fawe.object.changeset.FaweChangeSet;
@ -70,7 +71,6 @@ import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.extent.MaskingExtent;
import com.sk89q.worldedit.extent.buffer.ForgetfulExtentBuffer;
import com.sk89q.worldedit.extent.inventory.BlockBag;
import com.sk89q.worldedit.extent.inventory.BlockBagExtent;
import com.sk89q.worldedit.extent.world.SurvivalModeExtent;
import com.sk89q.worldedit.function.GroundFunction;
import com.sk89q.worldedit.function.RegionMaskingFilter;
@ -285,9 +285,6 @@ public class EditSession extends AbstractWorld implements HasFaweQueue {
this.bypassAll = wrapExtent(new FastWorldEditExtent(world, queue), bus, event, Stage.BEFORE_CHANGE);
this.bypassHistory = (this.extent = wrapExtent(bypassAll, bus, event, Stage.BEFORE_REORDER));
if (!fastmode) {
if (this.blockBag != null && limit.INVENTORY_MODE > 0) {
this.bypassHistory = new BlockBagExtent(this.bypassHistory, this.blockBag, limit.INVENTORY_MODE == 1);
}
if (limit.SPEED_REDUCTION > 0) {
this.bypassHistory = new SlowExtent(this.bypassHistory, limit.SPEED_REDUCTION);
}
@ -295,6 +292,9 @@ public class EditSession extends AbstractWorld implements HasFaweQueue {
if (player != null && Fawe.imp().getBlocksHubApi() != null) {
changeSet = LoggingChangeSet.wrap(player, changeSet);
}
if (this.blockBag != null && limit.INVENTORY_MODE > 0) {
changeSet = new BlockBagChangeSet(changeSet, blockBag, limit.INVENTORY_MODE == 1);
}
if (combineStages) {
changeTask = changeSet;
changeSet.addChangeTask(queue);
@ -728,6 +728,37 @@ public class EditSession extends AbstractWorld implements HasFaweQueue {
* @return a map of missing blocks
*/
public Map<Integer, Integer> popMissingBlocks() {
ChangeSet changeSet = getChangeSet();
if (changeSet instanceof BlockBagChangeSet) {
BlockBagChangeSet bbcs = (BlockBagChangeSet) changeSet;
BlockBag bag = bbcs.getBlockBag();
if (bag != null) {
bag.flushChanges();
Map<Integer, Integer> missingBlocks = ((BlockBagChangeSet) changeSet).popMissing();
if (!missingBlocks.isEmpty()) {
StringBuilder str = new StringBuilder();
int size = missingBlocks.size();
int i = 0;
for (Map.Entry<Integer, Integer> entry : missingBlocks.entrySet()) {
int combined = entry.getKey();
int id = FaweCache.getId(combined);
int data = FaweCache.getData(combined);
int amount = entry.getValue();
BlockType type = BlockType.fromID(id);
str.append((type != null ? type.getName() : "" + id))
.append((data != 0 ? ":" + data : ""))
.append((amount != 1 ? "x" + amount : ""));
++i;
if (i != size) {
str.append(", ");
}
}
BBC.WORLDEDIT_SOME_FAILS_BLOCKBAG.send(player, str.toString());
}
}
}
return new HashMap<>();
}

View File

@ -1,5 +1,6 @@
package com.sk89q.worldedit.extent.inventory;
import com.boydti.fawe.FaweCache;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.WorldEditException;
@ -108,4 +109,8 @@ public class BlockBagExtent extends AbstractDelegateExtent {
}
return super.setBlock(position, block);
}
public static Class<?> inject() {
return BlockBagExtent.class;
}
}

View File

@ -28,7 +28,6 @@ public class NukkitQueue extends NMSMappedFaweQueue<Level, BaseFullChunk, BaseFu
private Level world;
public static int ALLOCATE;
public static double TPS_TARGET = 18.5;
private static int LIGHT_MASK = 0x739C0;
public NukkitQueue(FaweNukkit fn, World world) {