mirror of
https://github.com/boy0001/FastAsyncWorldedit.git
synced 2025-01-06 08:28:14 +01:00
Anvil undo/region restrictions
This commit is contained in:
parent
d37e44e395
commit
7359100159
@ -107,9 +107,9 @@ public class BukkitQueue_All extends BukkitQueue_0<ChunkSnapshot, ChunkSnapshot,
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean setMCA(int mcaX, int mcaZ, RegionWrapper allowed, Runnable whileLocked, boolean load) {
|
public boolean setMCA(int mcaX, int mcaZ, RegionWrapper allowed, Runnable whileLocked, boolean saveChunks, boolean load) {
|
||||||
if (classRegionFileCache == null) {
|
if (classRegionFileCache == null) {
|
||||||
return super.setMCA(mcaX, mcaZ, allowed, whileLocked, load);
|
return super.setMCA(mcaX, mcaZ, allowed, whileLocked, saveChunks, load);
|
||||||
}
|
}
|
||||||
TaskManager.IMP.sync(new RunnableVal<Boolean>() {
|
TaskManager.IMP.sync(new RunnableVal<Boolean>() {
|
||||||
@Override
|
@Override
|
||||||
@ -134,7 +134,7 @@ public class BukkitQueue_All extends BukkitQueue_0<ChunkSnapshot, ChunkSnapshot,
|
|||||||
int cz = chunk.getZ();
|
int cz = chunk.getZ();
|
||||||
if (cx >= bcx && cx <= tcx && cz >= bcz && cz <= tcz) {
|
if (cx >= bcx && cx <= tcx && cz >= bcz && cz <= tcz) {
|
||||||
Object nmsChunk = methodGetHandleChunk.invoke(chunk);
|
Object nmsChunk = methodGetHandleChunk.invoke(chunk);
|
||||||
boolean mustSave = (boolean) methodNeedsSaving.invoke(nmsChunk, false);
|
boolean mustSave = saveChunks && (boolean) methodNeedsSaving.invoke(nmsChunk, false);
|
||||||
chunk.unload(mustSave, false);
|
chunk.unload(mustSave, false);
|
||||||
if (unloaded == null) unloaded = new ArrayDeque<Chunk>();
|
if (unloaded == null) unloaded = new ArrayDeque<Chunk>();
|
||||||
unloaded.add(chunk);
|
unloaded.add(chunk);
|
||||||
|
@ -402,7 +402,7 @@ public class BukkitQueue_1_10 extends BukkitQueue_0<net.minecraft.server.v1_10_R
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean setMCA(final int mcaX, final int mcaZ, final RegionWrapper allowed, final Runnable whileLocked, final boolean load) {
|
public boolean setMCA(final int mcaX, final int mcaZ, final RegionWrapper allowed, final Runnable whileLocked, final boolean saveChunks, final boolean load) {
|
||||||
TaskManager.IMP.sync(new RunnableVal<Boolean>() {
|
TaskManager.IMP.sync(new RunnableVal<Boolean>() {
|
||||||
@Override
|
@Override
|
||||||
public void run(Boolean value) {
|
public void run(Boolean value) {
|
||||||
@ -423,7 +423,7 @@ public class BukkitQueue_1_10 extends BukkitQueue_0<net.minecraft.server.v1_10_R
|
|||||||
boolean isIn = allowed.isInChunk(chunk.locX, chunk.locZ);
|
boolean isIn = allowed.isInChunk(chunk.locX, chunk.locZ);
|
||||||
if (isIn) {
|
if (isIn) {
|
||||||
if (!load) {
|
if (!load) {
|
||||||
if (chunk.a(false)) {
|
if (saveChunks && chunk.a(false)) {
|
||||||
mustSave = true;
|
mustSave = true;
|
||||||
provider.saveChunk(chunk);
|
provider.saveChunk(chunk);
|
||||||
provider.saveChunkNOP(chunk);
|
provider.saveChunkNOP(chunk);
|
||||||
@ -431,7 +431,7 @@ public class BukkitQueue_1_10 extends BukkitQueue_0<net.minecraft.server.v1_10_R
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
iter.remove();
|
iter.remove();
|
||||||
boolean save = chunk.a(false);
|
boolean save = saveChunks && chunk.a(false);
|
||||||
mustSave |= save;
|
mustSave |= save;
|
||||||
if (save) {
|
if (save) {
|
||||||
provider.unload(chunk);
|
provider.unload(chunk);
|
||||||
|
@ -260,7 +260,7 @@ public class BukkitQueue_1_11 extends BukkitQueue_0<net.minecraft.server.v1_11_R
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean setMCA(final int mcaX, final int mcaZ, final RegionWrapper allowed, final Runnable whileLocked, final boolean load) {
|
public boolean setMCA(final int mcaX, final int mcaZ, final RegionWrapper allowed, final Runnable whileLocked, final boolean saveChunks, final boolean load) {
|
||||||
TaskManager.IMP.sync(new RunnableVal<Boolean>() {
|
TaskManager.IMP.sync(new RunnableVal<Boolean>() {
|
||||||
@Override
|
@Override
|
||||||
public void run(Boolean value) {
|
public void run(Boolean value) {
|
||||||
@ -281,7 +281,7 @@ public class BukkitQueue_1_11 extends BukkitQueue_0<net.minecraft.server.v1_11_R
|
|||||||
boolean isIn = allowed.isInChunk(chunk.locX, chunk.locZ);
|
boolean isIn = allowed.isInChunk(chunk.locX, chunk.locZ);
|
||||||
if (isIn) {
|
if (isIn) {
|
||||||
if (!load) {
|
if (!load) {
|
||||||
if (chunk.a(false)) {
|
if (saveChunks && chunk.a(false)) {
|
||||||
mustSave = true;
|
mustSave = true;
|
||||||
provider.saveChunk(chunk);
|
provider.saveChunk(chunk);
|
||||||
provider.saveChunkNOP(chunk);
|
provider.saveChunkNOP(chunk);
|
||||||
@ -289,7 +289,7 @@ public class BukkitQueue_1_11 extends BukkitQueue_0<net.minecraft.server.v1_11_R
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
iter.remove();
|
iter.remove();
|
||||||
boolean save = chunk.a(false);
|
boolean save = saveChunks && chunk.a(false);
|
||||||
mustSave |= save;
|
mustSave |= save;
|
||||||
provider.unloadChunk(chunk, save);
|
provider.unloadChunk(chunk, save);
|
||||||
if (chunksUnloaded == null) {
|
if (chunksUnloaded == null) {
|
||||||
|
@ -14,6 +14,7 @@ import com.boydti.fawe.object.visitor.FaweChunkVisitor;
|
|||||||
import com.boydti.fawe.util.MainUtil;
|
import com.boydti.fawe.util.MainUtil;
|
||||||
import com.boydti.fawe.util.MathMan;
|
import com.boydti.fawe.util.MathMan;
|
||||||
import com.boydti.fawe.util.ReflectionUtils;
|
import com.boydti.fawe.util.ReflectionUtils;
|
||||||
|
import com.boydti.fawe.util.SetQueue;
|
||||||
import com.boydti.fawe.util.TaskManager;
|
import com.boydti.fawe.util.TaskManager;
|
||||||
import com.sk89q.jnbt.CompoundTag;
|
import com.sk89q.jnbt.CompoundTag;
|
||||||
import com.sk89q.jnbt.StringTag;
|
import com.sk89q.jnbt.StringTag;
|
||||||
@ -293,7 +294,7 @@ public class BukkitQueue_1_12 extends BukkitQueue_0<net.minecraft.server.v1_12_R
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean setMCA(final int mcaX, final int mcaZ, final RegionWrapper allowed, final Runnable whileLocked, final boolean load) {
|
public boolean setMCA(final int mcaX, final int mcaZ, final RegionWrapper allowed, final Runnable whileLocked, final boolean saveChunks, final boolean load) {
|
||||||
TaskManager.IMP.sync(new RunnableVal<Boolean>() {
|
TaskManager.IMP.sync(new RunnableVal<Boolean>() {
|
||||||
@Override
|
@Override
|
||||||
public void run(Boolean value) {
|
public void run(Boolean value) {
|
||||||
@ -314,11 +315,11 @@ public class BukkitQueue_1_12 extends BukkitQueue_0<net.minecraft.server.v1_12_R
|
|||||||
boolean isIn = allowed.isInChunk(chunk.locX, chunk.locZ);
|
boolean isIn = allowed.isInChunk(chunk.locX, chunk.locZ);
|
||||||
if (isIn) {
|
if (isIn) {
|
||||||
if (!load) {
|
if (!load) {
|
||||||
mustSave |= save(chunk, provider);
|
mustSave |= saveChunks && save(chunk, provider);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
iter.remove();
|
iter.remove();
|
||||||
boolean save = chunk.a(false);
|
boolean save = saveChunks && chunk.a(false);
|
||||||
mustSave |= save;
|
mustSave |= save;
|
||||||
provider.unloadChunk(chunk, save);
|
provider.unloadChunk(chunk, save);
|
||||||
if (chunksUnloaded == null) {
|
if (chunksUnloaded == null) {
|
||||||
@ -334,7 +335,9 @@ public class BukkitQueue_1_12 extends BukkitQueue_0<net.minecraft.server.v1_12_R
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (mustSave) provider.c(); // TODO only the necessary chunks
|
if (mustSave) {
|
||||||
|
provider.c(); // TODO only the necessary chunks
|
||||||
|
}
|
||||||
|
|
||||||
File unloadedRegion = null;
|
File unloadedRegion = null;
|
||||||
if (load && !RegionFileCache.a.isEmpty()) {
|
if (load && !RegionFileCache.a.isEmpty()) {
|
||||||
@ -378,9 +381,9 @@ public class BukkitQueue_1_12 extends BukkitQueue_0<net.minecraft.server.v1_12_R
|
|||||||
if (arr[z]) {
|
if (arr[z]) {
|
||||||
int cx = bx + x;
|
int cx = bx + x;
|
||||||
int cz = bz + z;
|
int cz = bz + z;
|
||||||
TaskManager.IMP.sync(new RunnableVal<Object>() {
|
SetQueue.IMP.addTask(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run(Object value1) {
|
public void run() {
|
||||||
net.minecraft.server.v1_12_R1.Chunk chunk = provider.getChunkAt(cx, cz, null, false);
|
net.minecraft.server.v1_12_R1.Chunk chunk = provider.getChunkAt(cx, cz, null, false);
|
||||||
if (chunk != null) {
|
if (chunk != null) {
|
||||||
PlayerChunk pc = getPlayerChunk(nmsWorld, cx, cz);
|
PlayerChunk pc = getPlayerChunk(nmsWorld, cx, cz);
|
||||||
|
@ -130,7 +130,7 @@ public class BukkitQueue17 extends BukkitQueue_0<net.minecraft.server.v1_7_R4.Ch
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean setMCA(final int mcaX, final int mcaZ, final RegionWrapper allowed, final Runnable whileLocked, final boolean load) {
|
public boolean setMCA(final int mcaX, final int mcaZ, final RegionWrapper allowed, final Runnable whileLocked, boolean saveChunks, final boolean load) {
|
||||||
TaskManager.IMP.sync(new RunnableVal<Boolean>() {
|
TaskManager.IMP.sync(new RunnableVal<Boolean>() {
|
||||||
@Override
|
@Override
|
||||||
public void run(Boolean value) {
|
public void run(Boolean value) {
|
||||||
@ -151,7 +151,7 @@ public class BukkitQueue17 extends BukkitQueue_0<net.minecraft.server.v1_7_R4.Ch
|
|||||||
boolean isIn = allowed.isInChunk(chunk.locX, chunk.locZ);
|
boolean isIn = allowed.isInChunk(chunk.locX, chunk.locZ);
|
||||||
if (isIn) {
|
if (isIn) {
|
||||||
if (!load) {
|
if (!load) {
|
||||||
if (chunk.a(false)) {
|
if (saveChunks && chunk.a(false)) {
|
||||||
mustSave = true;
|
mustSave = true;
|
||||||
provider.saveChunk(chunk);
|
provider.saveChunk(chunk);
|
||||||
provider.saveChunkNOP(chunk);
|
provider.saveChunkNOP(chunk);
|
||||||
@ -159,7 +159,7 @@ public class BukkitQueue17 extends BukkitQueue_0<net.minecraft.server.v1_7_R4.Ch
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
iter.remove();
|
iter.remove();
|
||||||
boolean save = chunk.a(false);
|
boolean save = saveChunks && chunk.a(false);
|
||||||
mustSave |= save;
|
mustSave |= save;
|
||||||
chunk.bukkitChunk.unload(save, false);
|
chunk.bukkitChunk.unload(save, false);
|
||||||
if (chunksUnloaded == null) {
|
if (chunksUnloaded == null) {
|
||||||
|
@ -9,6 +9,7 @@ import com.boydti.fawe.object.RunnableVal;
|
|||||||
import com.boydti.fawe.util.MainUtil;
|
import com.boydti.fawe.util.MainUtil;
|
||||||
import com.boydti.fawe.util.MathMan;
|
import com.boydti.fawe.util.MathMan;
|
||||||
import com.boydti.fawe.util.ReflectionUtils;
|
import com.boydti.fawe.util.ReflectionUtils;
|
||||||
|
import com.boydti.fawe.util.SetQueue;
|
||||||
import com.boydti.fawe.util.TaskManager;
|
import com.boydti.fawe.util.TaskManager;
|
||||||
import com.sk89q.jnbt.CompoundTag;
|
import com.sk89q.jnbt.CompoundTag;
|
||||||
import com.sk89q.jnbt.StringTag;
|
import com.sk89q.jnbt.StringTag;
|
||||||
@ -128,7 +129,7 @@ public class BukkitQueue18R3 extends BukkitQueue_0<net.minecraft.server.v1_8_R3.
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean setMCA(final int mcaX, final int mcaZ, final RegionWrapper allowed, final Runnable whileLocked, final boolean load) {
|
public boolean setMCA(final int mcaX, final int mcaZ, final RegionWrapper allowed, final Runnable whileLocked, final boolean saveChunks, final boolean load) {
|
||||||
TaskManager.IMP.sync(new RunnableVal<Boolean>() {
|
TaskManager.IMP.sync(new RunnableVal<Boolean>() {
|
||||||
@Override
|
@Override
|
||||||
public void run(Boolean value) {
|
public void run(Boolean value) {
|
||||||
@ -149,7 +150,7 @@ public class BukkitQueue18R3 extends BukkitQueue_0<net.minecraft.server.v1_8_R3.
|
|||||||
boolean isIn = allowed.isInChunk(chunk.locX, chunk.locZ);
|
boolean isIn = allowed.isInChunk(chunk.locX, chunk.locZ);
|
||||||
if (isIn) {
|
if (isIn) {
|
||||||
if (!load) {
|
if (!load) {
|
||||||
if (chunk.a(false)) {
|
if (saveChunks && chunk.a(false)) {
|
||||||
mustSave = true;
|
mustSave = true;
|
||||||
provider.saveChunk(chunk);
|
provider.saveChunk(chunk);
|
||||||
provider.saveChunkNOP(chunk);
|
provider.saveChunkNOP(chunk);
|
||||||
@ -157,7 +158,7 @@ public class BukkitQueue18R3 extends BukkitQueue_0<net.minecraft.server.v1_8_R3.
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
iter.remove();
|
iter.remove();
|
||||||
boolean save = chunk.a(false);
|
boolean save = saveChunks && chunk.a(false);
|
||||||
mustSave |= save;
|
mustSave |= save;
|
||||||
chunk.bukkitChunk.unload(save, false);
|
chunk.bukkitChunk.unload(save, false);
|
||||||
if (chunksUnloaded == null) {
|
if (chunksUnloaded == null) {
|
||||||
@ -217,9 +218,9 @@ public class BukkitQueue18R3 extends BukkitQueue_0<net.minecraft.server.v1_8_R3.
|
|||||||
if (arr[z]) {
|
if (arr[z]) {
|
||||||
int cx = bx + x;
|
int cx = bx + x;
|
||||||
int cz = bz + z;
|
int cz = bz + z;
|
||||||
TaskManager.IMP.sync(new RunnableVal<Object>() {
|
SetQueue.IMP.addTask(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run(Object value1) {
|
public void run() {
|
||||||
net.minecraft.server.v1_8_R3.Chunk chunk = provider.getChunkAt(cx, cz, null);
|
net.minecraft.server.v1_8_R3.Chunk chunk = provider.getChunkAt(cx, cz, null);
|
||||||
if (chunk != null) {
|
if (chunk != null) {
|
||||||
if (nmsWorld.getPlayerChunkMap().isChunkInUse(cx, cz)) {
|
if (nmsWorld.getPlayerChunkMap().isChunkInUse(cx, cz)) {
|
||||||
|
@ -263,7 +263,7 @@ public class BukkitQueue_1_9_R1 extends BukkitQueue_0<net.minecraft.server.v1_9_
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean setMCA(final int mcaX, final int mcaZ, final RegionWrapper allowed, final Runnable whileLocked, final boolean load) {
|
public boolean setMCA(final int mcaX, final int mcaZ, final RegionWrapper allowed, final Runnable whileLocked, boolean saveChunks, final boolean load) {
|
||||||
TaskManager.IMP.sync(new RunnableVal<Boolean>() {
|
TaskManager.IMP.sync(new RunnableVal<Boolean>() {
|
||||||
@Override
|
@Override
|
||||||
public void run(Boolean value) {
|
public void run(Boolean value) {
|
||||||
@ -284,7 +284,7 @@ public class BukkitQueue_1_9_R1 extends BukkitQueue_0<net.minecraft.server.v1_9_
|
|||||||
boolean isIn = allowed.isInChunk(chunk.locX, chunk.locZ);
|
boolean isIn = allowed.isInChunk(chunk.locX, chunk.locZ);
|
||||||
if (isIn) {
|
if (isIn) {
|
||||||
if (!load) {
|
if (!load) {
|
||||||
if (chunk.a(false)) {
|
if (saveChunks && chunk.a(false)) {
|
||||||
mustSave = true;
|
mustSave = true;
|
||||||
provider.saveChunk(chunk);
|
provider.saveChunk(chunk);
|
||||||
provider.saveChunkNOP(chunk);
|
provider.saveChunkNOP(chunk);
|
||||||
@ -292,7 +292,7 @@ public class BukkitQueue_1_9_R1 extends BukkitQueue_0<net.minecraft.server.v1_9_
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
iter.remove();
|
iter.remove();
|
||||||
boolean save = chunk.a(false);
|
boolean save = saveChunks && chunk.a(false);
|
||||||
mustSave |= save;
|
mustSave |= save;
|
||||||
if (save) {
|
if (save) {
|
||||||
provider.unload(chunk);
|
provider.unload(chunk);
|
||||||
|
@ -23,11 +23,15 @@ import com.boydti.fawe.object.FawePlayer;
|
|||||||
import com.boydti.fawe.object.FaweQueue;
|
import com.boydti.fawe.object.FaweQueue;
|
||||||
import com.boydti.fawe.object.RegionWrapper;
|
import com.boydti.fawe.object.RegionWrapper;
|
||||||
import com.boydti.fawe.object.RunnableVal4;
|
import com.boydti.fawe.object.RunnableVal4;
|
||||||
|
import com.boydti.fawe.object.changeset.AnvilHistory;
|
||||||
import com.boydti.fawe.object.clipboard.ClipboardRemapper;
|
import com.boydti.fawe.object.clipboard.ClipboardRemapper;
|
||||||
|
import com.boydti.fawe.object.exception.FaweException;
|
||||||
import com.boydti.fawe.object.mask.FaweBlockMatcher;
|
import com.boydti.fawe.object.mask.FaweBlockMatcher;
|
||||||
|
import com.boydti.fawe.regions.FaweMaskManager;
|
||||||
import com.boydti.fawe.util.MainUtil;
|
import com.boydti.fawe.util.MainUtil;
|
||||||
import com.boydti.fawe.util.SetQueue;
|
import com.boydti.fawe.util.SetQueue;
|
||||||
import com.boydti.fawe.util.StringMan;
|
import com.boydti.fawe.util.StringMan;
|
||||||
|
import com.boydti.fawe.util.WEManager;
|
||||||
import com.sk89q.minecraft.util.commands.Command;
|
import com.sk89q.minecraft.util.commands.Command;
|
||||||
import com.sk89q.minecraft.util.commands.CommandPermissions;
|
import com.sk89q.minecraft.util.commands.CommandPermissions;
|
||||||
import com.sk89q.worldedit.EditSession;
|
import com.sk89q.worldedit.EditSession;
|
||||||
@ -48,8 +52,10 @@ import com.sk89q.worldedit.util.command.parametric.Optional;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.RandomAccessFile;
|
import java.io.RandomAccessFile;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
@ -122,7 +128,23 @@ public class AnvilCommands {
|
|||||||
String worldName = Fawe.imp().getWorldName(editSession.getWorld());
|
String worldName = Fawe.imp().getWorldName(editSession.getWorld());
|
||||||
FaweQueue tmp = SetQueue.IMP.getNewQueue(worldName, true, false);
|
FaweQueue tmp = SetQueue.IMP.getNewQueue(worldName, true, false);
|
||||||
MCAQueue queue = new MCAQueue(tmp);
|
MCAQueue queue = new MCAQueue(tmp);
|
||||||
|
FawePlayer<Object> fp = FawePlayer.wrap(player);
|
||||||
|
LocalSession session = fp.getSession();
|
||||||
|
if (session == null || session.hasFastMode()) {
|
||||||
queue.filterCopy(filter, wrappedRegion);
|
queue.filterCopy(filter, wrappedRegion);
|
||||||
|
} else {
|
||||||
|
RegionWrapper[] allowed = WEManager.IMP.getMask(fp, FaweMaskManager.MaskType.OWNER);
|
||||||
|
HashSet<RegionWrapper> allowedSet = new HashSet<>(Arrays.asList(allowed));
|
||||||
|
RegionWrapper wrappedSelection = new RegionWrapper(selection.getMinimumPoint(), selection.getMaximumPoint());
|
||||||
|
if (allowed.length == 0) {
|
||||||
|
throw new FaweException(BBC.WORLDEDIT_CANCEL_REASON_NO_REGION);
|
||||||
|
} else if (!WEManager.IMP.regionContains(wrappedSelection, allowedSet)) {
|
||||||
|
throw new FaweException(BBC.WORLDEDIT_CANCEL_REASON_MAX_FAILS);
|
||||||
|
}
|
||||||
|
AnvilHistory history = new AnvilHistory(worldName, player.getUniqueId());
|
||||||
|
queue.filterCopy(filter, wrappedRegion, history);
|
||||||
|
session.remember(player, editSession.getWorld(), history, fp.getLimit());
|
||||||
|
}
|
||||||
return filter;
|
return filter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,6 +5,8 @@ import com.boydti.fawe.example.CharFaweChunk;
|
|||||||
import com.boydti.fawe.example.NMSMappedFaweQueue;
|
import com.boydti.fawe.example.NMSMappedFaweQueue;
|
||||||
import com.boydti.fawe.example.NullFaweChunk;
|
import com.boydti.fawe.example.NullFaweChunk;
|
||||||
import com.boydti.fawe.jnbt.anvil.filters.DelegateMCAFilter;
|
import com.boydti.fawe.jnbt.anvil.filters.DelegateMCAFilter;
|
||||||
|
import com.boydti.fawe.jnbt.anvil.history.IAnvilHistory;
|
||||||
|
import com.boydti.fawe.jnbt.anvil.history.NullAnvilHistory;
|
||||||
import com.boydti.fawe.object.FaweChunk;
|
import com.boydti.fawe.object.FaweChunk;
|
||||||
import com.boydti.fawe.object.FawePlayer;
|
import com.boydti.fawe.object.FawePlayer;
|
||||||
import com.boydti.fawe.object.FaweQueue;
|
import com.boydti.fawe.object.FaweQueue;
|
||||||
@ -147,9 +149,9 @@ public class MCAQueue extends NMSMappedFaweQueue<FaweQueue, FaweChunk, FaweChunk
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean setMCA(int mcaX, int mcaZ, RegionWrapper region, Runnable whileLocked, boolean unload) {
|
public boolean setMCA(int mcaX, int mcaZ, RegionWrapper region, Runnable whileLocked, boolean save, boolean unload) {
|
||||||
if (parent != null) return parent.setMCA(mcaX, mcaZ, region, whileLocked, unload);
|
if (parent != null) return parent.setMCA(mcaX, mcaZ, region, whileLocked, save, unload);
|
||||||
return super.setMCA(mcaX, mcaZ, region, whileLocked, unload);
|
return super.setMCA(mcaX, mcaZ, region, whileLocked, save, unload);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void pasteRegion(MCAQueue from, final RegionWrapper regionFrom, Vector offset) throws IOException {
|
public void pasteRegion(MCAQueue from, final RegionWrapper regionFrom, Vector offset) throws IOException {
|
||||||
@ -279,27 +281,30 @@ public class MCAQueue extends NMSMappedFaweQueue<FaweQueue, FaweChunk, FaweChunk
|
|||||||
from.clear();
|
from.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void performCopy(MCAFile original, MCAFile copy, RegionWrapper region, ForkJoinPool pool) {
|
private void performCopy(MCAFile original, MCAFile copy, RegionWrapper region, IAnvilHistory task, ForkJoinPool pool) {
|
||||||
original.clear();
|
original.clear();
|
||||||
File originalFile = original.getFile();
|
File originalFile = original.getFile();
|
||||||
File copyFile = copy.getFile();
|
File copyFile = copy.getFile();
|
||||||
if (copy.isModified()) {
|
if (copy.isModified()) {
|
||||||
if (copy.isDeleted()) {
|
if (copy.isDeleted()) {
|
||||||
if (originalFile.delete()) return;
|
if (task.addFileChange(originalFile)) return;
|
||||||
setMCA(original.getX(), original.getZ(), region, () -> originalFile.delete(), true);
|
setMCA(original.getX(), original.getZ(), region, () -> task.addFileChange(originalFile), true, true);
|
||||||
return;
|
return;
|
||||||
} else if (copyFile.exists()) {
|
} else if (copyFile.exists()) {
|
||||||
try {
|
// If the task is the normal delete task, we can do a normal file move
|
||||||
copy.close(pool);
|
copy.close(pool);
|
||||||
|
if (task.getClass() == NullAnvilHistory.class) {
|
||||||
|
try {
|
||||||
Files.move(copyFile.toPath(), originalFile.toPath(), StandardCopyOption.ATOMIC_MOVE);
|
Files.move(copyFile.toPath(), originalFile.toPath(), StandardCopyOption.ATOMIC_MOVE);
|
||||||
} catch (IOException e) {
|
return;
|
||||||
|
} catch (IOException ignore) {}
|
||||||
|
}
|
||||||
setMCA(original.getX(), original.getZ(), region, () -> {
|
setMCA(original.getX(), original.getZ(), region, () -> {
|
||||||
originalFile.delete();
|
task.addFileChange(originalFile);
|
||||||
if (!copyFile.renameTo(originalFile)) {
|
if (!copyFile.renameTo(originalFile)) {
|
||||||
Fawe.debug("Failed to copy (2)");
|
Fawe.debug("Failed to copy (2)");
|
||||||
}
|
}
|
||||||
}, true);
|
}, true, true);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
copy.clear();
|
copy.clear();
|
||||||
@ -307,6 +312,11 @@ public class MCAQueue extends NMSMappedFaweQueue<FaweQueue, FaweChunk, FaweChunk
|
|||||||
}
|
}
|
||||||
|
|
||||||
public <G, T extends MCAFilter<G>> T filterCopy(final T filter, RegionWrapper region) {
|
public <G, T extends MCAFilter<G>> T filterCopy(final T filter, RegionWrapper region) {
|
||||||
|
return filterCopy(filter, region, new NullAnvilHistory());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public <G, T extends MCAFilter<G>> T filterCopy(final T filter, RegionWrapper region, IAnvilHistory task) {
|
||||||
DelegateMCAFilter<G> delegate = new DelegateMCAFilter<G>(filter) {
|
DelegateMCAFilter<G> delegate = new DelegateMCAFilter<G>(filter) {
|
||||||
MCAFile original;
|
MCAFile original;
|
||||||
MCAFile copy;
|
MCAFile copy;
|
||||||
@ -330,11 +340,11 @@ public class MCAQueue extends NMSMappedFaweQueue<FaweQueue, FaweChunk, FaweChunk
|
|||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}, false);
|
}, true, false);
|
||||||
this.copy = new MCAFile(original.getParent(), copyDest);
|
this.copy = new MCAFile(original.getParent(), copyDest);
|
||||||
MCAFile result = filter.applyFile(copy);
|
MCAFile result = filter.applyFile(copy);
|
||||||
if (result == null) {
|
if (result == null) {
|
||||||
performCopy(original, copy, region, pool);
|
performCopy(original, copy, region, task, pool);
|
||||||
}
|
}
|
||||||
if (result == null || !copy.getFile().equals(result.getFile())) {
|
if (result == null || !copy.getFile().equals(result.getFile())) {
|
||||||
copy.clear();
|
copy.clear();
|
||||||
@ -345,7 +355,7 @@ public class MCAQueue extends NMSMappedFaweQueue<FaweQueue, FaweChunk, FaweChunk
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void finishFile(MCAFile newRegion, G cache) {
|
public void finishFile(MCAFile newRegion, G cache) {
|
||||||
performCopy(original, newRegion, region, pool);
|
performCopy(original, newRegion, region, task, pool);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
if (region == RegionWrapper.GLOBAL()) {
|
if (region == RegionWrapper.GLOBAL()) {
|
||||||
|
@ -51,7 +51,7 @@ public class MCAQueueMap implements IFaweQueueMap {
|
|||||||
lastFile = tmp = mcaFileMap.get(pair);
|
lastFile = tmp = mcaFileMap.get(pair);
|
||||||
if (lastFile == null) {
|
if (lastFile == null) {
|
||||||
try {
|
try {
|
||||||
queue.setMCA(lastFileX, lastFileZ, RegionWrapper.GLOBAL(), null, false);
|
queue.setMCA(lastFileX, lastFileZ, RegionWrapper.GLOBAL(), null, true, false);
|
||||||
lastFile = tmp = new MCAFile(queue, lastFileX, lastFileZ);
|
lastFile = tmp = new MCAFile(queue, lastFileX, lastFileZ);
|
||||||
} catch (FaweException.FaweChunkLoadException ignore) {
|
} catch (FaweException.FaweChunkLoadException ignore) {
|
||||||
lastFile = null;
|
lastFile = null;
|
||||||
@ -184,7 +184,7 @@ public class MCAQueueMap implements IFaweQueueMap {
|
|||||||
public void run() {
|
public void run() {
|
||||||
file.close(SetQueue.IMP.getForkJoinPool());
|
file.close(SetQueue.IMP.getForkJoinPool());
|
||||||
}
|
}
|
||||||
}, true);
|
}, true, true);
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,9 @@
|
|||||||
|
package com.boydti.fawe.jnbt.anvil.history;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
|
||||||
|
public interface IAnvilHistory {
|
||||||
|
default boolean addFileChange(File originalMCAFile) {
|
||||||
|
return originalMCAFile.delete();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,4 @@
|
|||||||
|
package com.boydti.fawe.jnbt.anvil.history;
|
||||||
|
|
||||||
|
public class NullAnvilHistory implements IAnvilHistory {
|
||||||
|
}
|
@ -289,7 +289,7 @@ public abstract class FaweQueue implements HasFaweQueue, Extent {
|
|||||||
|
|
||||||
public abstract Collection<FaweChunk> getFaweChunks();
|
public abstract Collection<FaweChunk> getFaweChunks();
|
||||||
|
|
||||||
public boolean setMCA(int mcaX, int mcaZ, RegionWrapper region, Runnable whileLocked, boolean load) {
|
public boolean setMCA(int mcaX, int mcaZ, RegionWrapper region, Runnable whileLocked, boolean save, boolean load) {
|
||||||
if (whileLocked != null) whileLocked.run();
|
if (whileLocked != null) whileLocked.run();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,105 @@
|
|||||||
|
package com.boydti.fawe.object.changeset;
|
||||||
|
|
||||||
|
import com.boydti.fawe.Fawe;
|
||||||
|
import com.boydti.fawe.config.Settings;
|
||||||
|
import com.boydti.fawe.jnbt.anvil.history.IAnvilHistory;
|
||||||
|
import com.boydti.fawe.util.MainUtil;
|
||||||
|
import com.google.common.base.Function;
|
||||||
|
import com.google.common.collect.Iterators;
|
||||||
|
import com.sk89q.jnbt.CompoundTag;
|
||||||
|
import com.sk89q.worldedit.history.change.Change;
|
||||||
|
import com.sk89q.worldedit.world.biome.BaseBiome;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
import java.nio.file.StandardCopyOption;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.UUID;
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
public class AnvilHistory extends FaweChangeSet implements IAnvilHistory {
|
||||||
|
private final File folder;
|
||||||
|
private int size;
|
||||||
|
|
||||||
|
public AnvilHistory(String world, File folder) {
|
||||||
|
super(world);
|
||||||
|
this.folder = folder;
|
||||||
|
size = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AnvilHistory(String world, UUID uuid) {
|
||||||
|
super(world);
|
||||||
|
File history = MainUtil.getFile(Fawe.imp().getDirectory(), Settings.IMP.PATHS.HISTORY + File.separator + world + File.separator + uuid);
|
||||||
|
File destFolder = new File(history, Integer.toString(MainUtil.getMaxFileId(history)));
|
||||||
|
if (!destFolder.exists()) {
|
||||||
|
destFolder.mkdirs();
|
||||||
|
}
|
||||||
|
this.folder = destFolder;
|
||||||
|
this.size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean addFileChange(File originalMCAFile) {
|
||||||
|
try {
|
||||||
|
Files.move(originalMCAFile.toPath(), Paths.get(folder.getPath(), originalMCAFile.getName()), StandardCopyOption.ATOMIC_MOVE);
|
||||||
|
if (size != -1) size++;
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
originalMCAFile.delete();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void add(int x, int y, int z, int combinedFrom, int combinedTo) {
|
||||||
|
throw new UnsupportedOperationException("Only anvil operations are supported");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addTileCreate(CompoundTag tag) {
|
||||||
|
throw new UnsupportedOperationException("Only anvil operations are supported");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addTileRemove(CompoundTag tag) {
|
||||||
|
throw new UnsupportedOperationException("Only anvil operations are supported");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addEntityRemove(CompoundTag tag) {
|
||||||
|
throw new UnsupportedOperationException("Only anvil operations are supported");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addEntityCreate(CompoundTag tag) {
|
||||||
|
throw new UnsupportedOperationException("Only anvil operations are supported");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addBiomeChange(int x, int z, BaseBiome from, BaseBiome to) {
|
||||||
|
throw new UnsupportedOperationException("Only anvil operations are supported");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Iterator<Change> getIterator(boolean redo) {
|
||||||
|
if (redo) throw new UnsupportedOperationException("Only undo operations are supported");
|
||||||
|
List<File> files = Arrays.asList(folder.listFiles());
|
||||||
|
final MutableAnvilChange change = new MutableAnvilChange();
|
||||||
|
return Iterators.transform(files.iterator(), new Function<File, MutableAnvilChange>() {
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public MutableAnvilChange apply(@Nullable File input) {
|
||||||
|
change.setSource(input.toPath());
|
||||||
|
return change;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int size() {
|
||||||
|
return size == -1 ? folder.listFiles().length : size;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,71 @@
|
|||||||
|
package com.boydti.fawe.object.changeset;
|
||||||
|
|
||||||
|
import com.boydti.fawe.Fawe;
|
||||||
|
import com.boydti.fawe.object.FaweQueue;
|
||||||
|
import com.boydti.fawe.object.HasFaweQueue;
|
||||||
|
import com.boydti.fawe.object.RegionWrapper;
|
||||||
|
import com.boydti.fawe.util.ExtentTraverser;
|
||||||
|
import com.boydti.fawe.util.MainUtil;
|
||||||
|
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.io.IOException;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.nio.file.StandardCopyOption;
|
||||||
|
|
||||||
|
public class MutableAnvilChange implements Change {
|
||||||
|
private Path source;
|
||||||
|
private Path destDir;
|
||||||
|
|
||||||
|
public void setSource(Path source) {
|
||||||
|
this.source = source;
|
||||||
|
}
|
||||||
|
|
||||||
|
private FaweQueue queue;
|
||||||
|
private boolean checkedQueue;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void undo(UndoContext context) throws WorldEditException {
|
||||||
|
if (queue != null) {
|
||||||
|
perform(queue);
|
||||||
|
}
|
||||||
|
if (!checkedQueue) {
|
||||||
|
checkedQueue = true;
|
||||||
|
Extent extent = context.getExtent();
|
||||||
|
ExtentTraverser found = new ExtentTraverser(extent).find(HasFaweQueue.class);
|
||||||
|
if (found != null) {
|
||||||
|
queue = ((HasFaweQueue) found.get()).getQueue();
|
||||||
|
destDir = queue.getSaveFolder().toPath();
|
||||||
|
perform(queue);
|
||||||
|
} else {
|
||||||
|
Fawe.debug("FAWE does not support: " + extent + " for " + getClass() + " (bug Empire92)");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void perform(FaweQueue queue) {
|
||||||
|
Path dest = destDir.resolve(source.getFileName());
|
||||||
|
try {
|
||||||
|
Files.move(source, dest, StandardCopyOption.ATOMIC_MOVE);
|
||||||
|
} catch (IOException ignore) {
|
||||||
|
int[] coords = MainUtil.regionNameToCoords(source.toString());
|
||||||
|
queue.setMCA(coords[0], coords[1], RegionWrapper.GLOBAL(), new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
try {
|
||||||
|
Files.move(source, dest, StandardCopyOption.ATOMIC_MOVE);
|
||||||
|
} catch (IOException e1) {
|
||||||
|
e1.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, false, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void redo(UndoContext context) throws WorldEditException {
|
||||||
|
throw new UnsupportedOperationException("Redo not supported");
|
||||||
|
}
|
||||||
|
}
|
@ -47,8 +47,8 @@ public class DelegateFaweQueue extends FaweQueue {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean setMCA(int mcaX, int mcaZ, RegionWrapper region, Runnable whileLocked, boolean load) {
|
public boolean setMCA(int mcaX, int mcaZ, RegionWrapper region, Runnable whileLocked, boolean save, boolean load) {
|
||||||
return parent.setMCA(mcaX, mcaZ, region, whileLocked, load);
|
return parent.setMCA(mcaX, mcaZ, region, whileLocked, save, load);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -30,6 +30,7 @@ import java.io.BufferedInputStream;
|
|||||||
import java.io.BufferedOutputStream;
|
import java.io.BufferedOutputStream;
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.io.FileFilter;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@ -61,7 +62,6 @@ import java.util.List;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
|
||||||
import java.util.concurrent.atomic.AtomicLong;
|
import java.util.concurrent.atomic.AtomicLong;
|
||||||
import java.util.zip.DataFormatException;
|
import java.util.zip.DataFormatException;
|
||||||
import java.util.zip.Deflater;
|
import java.util.zip.Deflater;
|
||||||
@ -220,27 +220,23 @@ public class MainUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static int getMaxFileId(File folder) {
|
public static int getMaxFileId(File folder) {
|
||||||
final AtomicInteger max = new AtomicInteger();
|
final int[] max = new int[1];
|
||||||
if (folder.exists()) {
|
folder.listFiles(new FileFilter() {
|
||||||
MainUtil.traverse(folder.toPath(), new RunnableVal2<Path, BasicFileAttributes>() {
|
|
||||||
@Override
|
@Override
|
||||||
public void run(Path path, BasicFileAttributes attr) {
|
public boolean accept(File pathname) {
|
||||||
try {
|
String name = pathname.getName();
|
||||||
String file = path.getFileName().toString();
|
Integer val = null;
|
||||||
int index = file.indexOf('.');
|
if (pathname.isDirectory()) {
|
||||||
if (index == -1) {
|
val = StringMan.toInteger(name, 0, name.length());
|
||||||
return;
|
} else {
|
||||||
}
|
int i = name.lastIndexOf('.');
|
||||||
int id = Integer.parseInt(file.substring(0, index));
|
if (i != -1) val = StringMan.toInteger(name, 0, i);
|
||||||
if (id > max.get()) {
|
|
||||||
max.set(id);
|
|
||||||
}
|
|
||||||
} catch (NumberFormatException ignore) {
|
|
||||||
}
|
}
|
||||||
|
if (val != null && val > max[0]) max[0] = val;
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
return max[0] + 1;
|
||||||
return max.get() + 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static File getFile(File base, String path) {
|
public static File getFile(File base, String path) {
|
||||||
|
@ -80,7 +80,31 @@ public class SetQueue {
|
|||||||
public void run() {
|
public void run() {
|
||||||
try {
|
try {
|
||||||
long now = System.currentTimeMillis();
|
long now = System.currentTimeMillis();
|
||||||
|
boolean empty = (inactiveQueues.isEmpty() && activeQueues.isEmpty());
|
||||||
|
boolean emptyTasks = tasks.isEmpty();
|
||||||
|
if (emptyTasks && empty) {
|
||||||
|
last = now;
|
||||||
|
runEmptyTasks();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
targetTPS = 18 - Math.max(Settings.IMP.QUEUE.EXTRA_TIME_MS * 0.05, 0);
|
targetTPS = 18 - Math.max(Settings.IMP.QUEUE.EXTRA_TIME_MS * 0.05, 0);
|
||||||
|
|
||||||
|
long diff = (50 + SetQueue.this.last) - (SetQueue.this.last = now);
|
||||||
|
long absDiff = Math.abs(diff);
|
||||||
|
if (diff == 0) {
|
||||||
|
allocate = Math.min(50, allocate + 1);
|
||||||
|
} else if (diff < 0) {
|
||||||
|
allocate = Math.max(5, allocate + diff);
|
||||||
|
} else if (!Fawe.get().getTimer().isAbove(targetTPS)) {
|
||||||
|
allocate = Math.max(5, allocate - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
long currentAllocate = allocate - absDiff;
|
||||||
|
|
||||||
|
if (!emptyTasks) {
|
||||||
|
long taskAllocate = empty ? currentAllocate : currentAllocate >> 1;
|
||||||
|
long used = 0;
|
||||||
do {
|
do {
|
||||||
Runnable task = tasks.poll();
|
Runnable task = tasks.poll();
|
||||||
if (task != null) {
|
if (task != null) {
|
||||||
@ -88,16 +112,18 @@ public class SetQueue {
|
|||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} while (Fawe.get().getTimer().isAbove(targetTPS));
|
} while ((used = System.currentTimeMillis() - now) < taskAllocate);
|
||||||
if (inactiveQueues.isEmpty() && activeQueues.isEmpty()) {
|
currentAllocate -= used;
|
||||||
last = lastSuccess = now;
|
}
|
||||||
|
|
||||||
|
if (empty) {
|
||||||
runEmptyTasks();
|
runEmptyTasks();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!MemUtil.isMemoryFree()) {
|
if (!MemUtil.isMemoryFree()) {
|
||||||
final int mem = MemUtil.calculateMemory();
|
final int mem = MemUtil.calculateMemory();
|
||||||
if (mem != Integer.MAX_VALUE) {
|
if (mem != Integer.MAX_VALUE) {
|
||||||
last = now;
|
|
||||||
allocate = Math.max(5, allocate - 1);
|
allocate = Math.max(5, allocate - 1);
|
||||||
if ((mem <= 1) && Settings.IMP.PREVENT_CRASHES) {
|
if ((mem <= 1) && Settings.IMP.PREVENT_CRASHES) {
|
||||||
for (FaweQueue queue : getAllQueues()) {
|
for (FaweQueue queue : getAllQueues()) {
|
||||||
@ -113,27 +139,13 @@ public class SetQueue {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
FaweQueue queue = getNextQueue();
|
FaweQueue queue = getNextQueue();
|
||||||
if (queue == null) {
|
if (queue == null) {
|
||||||
last = now;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!Fawe.get().getTimer().isAbove(targetTPS)) {
|
|
||||||
allocate = Math.max(5, allocate - 1);
|
long time = Settings.IMP.QUEUE.EXTRA_TIME_MS + currentAllocate - System.currentTimeMillis() + now;
|
||||||
last = now;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (Thread.currentThread() != Fawe.get().getMainThread()) {
|
|
||||||
throw new IllegalStateException("This shouldn't be possible for placement to occur off the main thread");
|
|
||||||
}
|
|
||||||
long diff = (50 + SetQueue.this.last) - (SetQueue.this.last = now);
|
|
||||||
long absDiff = Math.abs(diff);
|
|
||||||
if (diff == 0) {
|
|
||||||
allocate = Math.min(50, allocate + 1);
|
|
||||||
} else if (diff < 0) {
|
|
||||||
allocate = Math.max(5, allocate + diff);
|
|
||||||
}
|
|
||||||
long time = Settings.IMP.QUEUE.EXTRA_TIME_MS + allocate - absDiff - System.currentTimeMillis() + now;
|
|
||||||
// Disable the async catcher as it can't discern async vs parallel
|
// Disable the async catcher as it can't discern async vs parallel
|
||||||
boolean parallel = Settings.IMP.QUEUE.PARALLEL_THREADS > 1;
|
boolean parallel = Settings.IMP.QUEUE.PARALLEL_THREADS > 1;
|
||||||
queue.startSet(parallel);
|
queue.startSet(parallel);
|
||||||
|
@ -313,6 +313,37 @@ public class StringMan {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Integer toInteger(String string, int start, int end) {
|
||||||
|
int value = 0;
|
||||||
|
char char0 = string.charAt(0);
|
||||||
|
boolean negative;
|
||||||
|
if (char0 == '-') {
|
||||||
|
negative = true;
|
||||||
|
start++;
|
||||||
|
}
|
||||||
|
else negative = false;
|
||||||
|
for (int i = start; i < end; i++) {
|
||||||
|
char c = string.charAt(i);
|
||||||
|
switch (c) {
|
||||||
|
case '0':
|
||||||
|
case '1':
|
||||||
|
case '2':
|
||||||
|
case '3':
|
||||||
|
case '4':
|
||||||
|
case '5':
|
||||||
|
case '6':
|
||||||
|
case '7':
|
||||||
|
case '8':
|
||||||
|
case '9':
|
||||||
|
value = value * 10 + c - '0';
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return negative ? -value : value;
|
||||||
|
}
|
||||||
|
|
||||||
public static String join(final int[] array, final String delimiter) {
|
public static String join(final int[] array, final String delimiter) {
|
||||||
final Integer[] wrapped = new Integer[array.length];
|
final Integer[] wrapped = new Integer[array.length];
|
||||||
for (int i = 0; i < array.length; i++) {
|
for (int i = 0; i < array.length; i++) {
|
||||||
|
@ -208,7 +208,7 @@ public class PlayerWrapper extends AbstractPlayerActor {
|
|||||||
edit.flushQueue();
|
edit.flushQueue();
|
||||||
LocalSession session = Fawe.get().getWorldEdit().getSession(this);
|
LocalSession session = Fawe.get().getWorldEdit().getSession(this);
|
||||||
if (session != null) {
|
if (session != null) {
|
||||||
session.remember(edit, true, false, FawePlayer.wrap(this).getLimit().MAX_HISTORY);
|
session.remember(edit, true, FawePlayer.wrap(this).getLimit().MAX_HISTORY);
|
||||||
}
|
}
|
||||||
} catch (RuntimeException e) {
|
} catch (RuntimeException e) {
|
||||||
caught = e;
|
caught = e;
|
||||||
|
@ -2934,7 +2934,7 @@ public class EditSession extends AbstractWorld implements HasFaweQueue, Lighting
|
|||||||
int yv = (int) (y.getValue() * unit.getY() + zero2.getY());
|
int yv = (int) (y.getValue() * unit.getY() + zero2.getY());
|
||||||
int zv = (int) (z.getValue() * unit.getZ() + zero2.getZ());
|
int zv = (int) (z.getValue() * unit.getZ() + zero2.getZ());
|
||||||
// read block from world
|
// read block from world
|
||||||
BaseBlock material = getLazyBlock(xv, yv, zv);
|
BaseBlock material = FaweCache.CACHE_BLOCK[queue.getCombinedId4DataDebug(xv, yv, zv, 0, EditSession.this)];
|
||||||
// queue operation
|
// queue operation
|
||||||
return setBlockFast(position, material);
|
return setBlockFast(position, material);
|
||||||
} catch (EvaluationException e) {
|
} catch (EvaluationException e) {
|
||||||
|
@ -23,14 +23,17 @@ import com.boydti.fawe.Fawe;
|
|||||||
import com.boydti.fawe.FaweCache;
|
import com.boydti.fawe.FaweCache;
|
||||||
import com.boydti.fawe.config.Settings;
|
import com.boydti.fawe.config.Settings;
|
||||||
import com.boydti.fawe.object.FaweInputStream;
|
import com.boydti.fawe.object.FaweInputStream;
|
||||||
|
import com.boydti.fawe.object.FaweLimit;
|
||||||
import com.boydti.fawe.object.FaweOutputStream;
|
import com.boydti.fawe.object.FaweOutputStream;
|
||||||
import com.boydti.fawe.object.FawePlayer;
|
import com.boydti.fawe.object.FawePlayer;
|
||||||
import com.boydti.fawe.object.RunnableVal2;
|
import com.boydti.fawe.object.changeset.AnvilHistory;
|
||||||
import com.boydti.fawe.object.changeset.DiskStorageHistory;
|
import com.boydti.fawe.object.changeset.DiskStorageHistory;
|
||||||
import com.boydti.fawe.object.changeset.FaweChangeSet;
|
import com.boydti.fawe.object.changeset.FaweChangeSet;
|
||||||
|
import com.boydti.fawe.object.collection.SparseBitSet;
|
||||||
import com.boydti.fawe.object.extent.ResettableExtent;
|
import com.boydti.fawe.object.extent.ResettableExtent;
|
||||||
import com.boydti.fawe.util.EditSessionBuilder;
|
import com.boydti.fawe.util.EditSessionBuilder;
|
||||||
import com.boydti.fawe.util.MainUtil;
|
import com.boydti.fawe.util.MainUtil;
|
||||||
|
import com.boydti.fawe.util.StringMan;
|
||||||
import com.boydti.fawe.wrappers.WorldWrapper;
|
import com.boydti.fawe.wrappers.WorldWrapper;
|
||||||
import com.sk89q.jchronic.Chronic;
|
import com.sk89q.jchronic.Chronic;
|
||||||
import com.sk89q.jchronic.Options;
|
import com.sk89q.jchronic.Options;
|
||||||
@ -47,6 +50,7 @@ import com.sk89q.worldedit.extension.platform.Actor;
|
|||||||
import com.sk89q.worldedit.extent.inventory.BlockBag;
|
import com.sk89q.worldedit.extent.inventory.BlockBag;
|
||||||
import com.sk89q.worldedit.function.mask.Mask;
|
import com.sk89q.worldedit.function.mask.Mask;
|
||||||
import com.sk89q.worldedit.function.mask.Masks;
|
import com.sk89q.worldedit.function.mask.Masks;
|
||||||
|
import com.sk89q.worldedit.history.changeset.ChangeSet;
|
||||||
import com.sk89q.worldedit.internal.cui.CUIEvent;
|
import com.sk89q.worldedit.internal.cui.CUIEvent;
|
||||||
import com.sk89q.worldedit.internal.cui.CUIRegion;
|
import com.sk89q.worldedit.internal.cui.CUIRegion;
|
||||||
import com.sk89q.worldedit.internal.cui.SelectionShapeEvent;
|
import com.sk89q.worldedit.internal.cui.SelectionShapeEvent;
|
||||||
@ -63,11 +67,6 @@ import java.io.FileFilter;
|
|||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.file.Files;
|
|
||||||
import java.nio.file.Path;
|
|
||||||
import java.nio.file.attribute.BasicFileAttributes;
|
|
||||||
import java.util.ArrayDeque;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Calendar;
|
import java.util.Calendar;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
@ -78,9 +77,7 @@ import java.util.Map;
|
|||||||
import java.util.TimeZone;
|
import java.util.TimeZone;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
import java.util.concurrent.atomic.AtomicLong;
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import javax.swing.filechooser.FileNameExtensionFilter;
|
|
||||||
|
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
@ -207,84 +204,35 @@ public class LocalSession {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean loadHistoryChangeSets(UUID uuid, World world) {
|
private boolean loadHistoryChangeSets(UUID uuid, World world) {
|
||||||
final List<Integer> editIds = new ArrayList<>();
|
SparseBitSet set = new SparseBitSet();
|
||||||
final File folder = MainUtil.getFile(Fawe.imp().getDirectory(), Settings.IMP.PATHS.HISTORY + File.separator + Fawe.imp().getWorldName(world) + File.separator + uuid);
|
final File folder = MainUtil.getFile(Fawe.imp().getDirectory(), Settings.IMP.PATHS.HISTORY + File.separator + Fawe.imp().getWorldName(world) + File.separator + uuid);
|
||||||
if (folder.isDirectory()) {
|
if (folder.isDirectory()) {
|
||||||
final FileNameExtensionFilter filter = new FileNameExtensionFilter("BlockData files", "bd");
|
|
||||||
folder.listFiles(new FileFilter() {
|
folder.listFiles(new FileFilter() {
|
||||||
@Override
|
@Override
|
||||||
public boolean accept(File pathname) {
|
public boolean accept(File pathname) {
|
||||||
String name = pathname.getName();
|
String name = pathname.getName();
|
||||||
|
Integer val = null;
|
||||||
|
if (pathname.isDirectory()) {
|
||||||
|
val = StringMan.toInteger(name, 0, name.length());
|
||||||
|
|
||||||
|
} else {
|
||||||
int i = name.lastIndexOf('.');
|
int i = name.lastIndexOf('.');
|
||||||
if ((name.length() == i + 3) && (name.charAt(i + 1) == 'b' && name.charAt(i + 2) == 'd')) {
|
if (i != -1) val = StringMan.toInteger(name, 0, i);
|
||||||
int index = Integer.parseInt(name.substring(0, i));
|
|
||||||
editIds.add(index);
|
|
||||||
}
|
}
|
||||||
|
if (val != null) set.set(val);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (editIds.size() > 0) {
|
if (!set.isEmpty()) {
|
||||||
historySize = MainUtil.getTotalSize(folder.toPath());
|
historySize = MainUtil.getTotalSize(folder.toPath());
|
||||||
Collections.sort(editIds);
|
for (int index = set.nextSetBit(0); index != -1; index = set.nextSetBit(index + 1)) {
|
||||||
for (int index : editIds) {
|
|
||||||
history.add(index);
|
history.add(index);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
historySize = 0;
|
historySize = 0;
|
||||||
}
|
}
|
||||||
return editIds.size() > 0;
|
return !set.isEmpty();
|
||||||
}
|
|
||||||
|
|
||||||
@Deprecated
|
|
||||||
private void deleteOldFiles(UUID uuid, World world, long maxBytes) throws IOException {
|
|
||||||
final File folder = MainUtil.getFile(Fawe.imp().getDirectory(), Settings.IMP.PATHS.HISTORY + File.separator + Fawe.imp().getWorldName(world) + File.separator + uuid);
|
|
||||||
|
|
||||||
final ArrayList<Integer> ids = new ArrayList<Integer>();
|
|
||||||
final HashMap<Integer, ArrayDeque<Path>> paths = new HashMap<>();
|
|
||||||
final HashMap<Integer, AtomicLong> sizes = new HashMap<>();
|
|
||||||
final AtomicLong totalSize = new AtomicLong();
|
|
||||||
|
|
||||||
MainUtil.traverse(folder.toPath(), new RunnableVal2<Path, BasicFileAttributes>() {
|
|
||||||
@Override
|
|
||||||
public void run(Path path, BasicFileAttributes attr) {
|
|
||||||
try {
|
|
||||||
String file = path.getFileName().toString();
|
|
||||||
int index = file.indexOf('.');
|
|
||||||
if (index == -1) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
int id = Integer.parseInt(file.substring(0, index));
|
|
||||||
long size = attr.size();
|
|
||||||
totalSize.addAndGet(size);
|
|
||||||
ArrayDeque<Path> existingPaths = paths.get(id);
|
|
||||||
if (existingPaths == null) {
|
|
||||||
existingPaths = new ArrayDeque<Path>();
|
|
||||||
paths.put(id, existingPaths);
|
|
||||||
}
|
|
||||||
existingPaths.add(path);
|
|
||||||
AtomicLong existingSize = sizes.get(id);
|
|
||||||
if (existingSize == null) {
|
|
||||||
existingSize = new AtomicLong();
|
|
||||||
sizes.put(id, existingSize);
|
|
||||||
}
|
|
||||||
existingSize.addAndGet(size);
|
|
||||||
} catch (NumberFormatException ignore) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
if (totalSize.get() < maxBytes) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Collections.sort(ids);
|
|
||||||
long total = totalSize.get();
|
|
||||||
for (int i = 0; i < ids.size() && total > maxBytes; i++) {
|
|
||||||
int id = ids.get(i);
|
|
||||||
for (Path path : paths.get(id)) {
|
|
||||||
Files.delete(path);
|
|
||||||
}
|
|
||||||
total -= sizes.get(id).get();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void loadHistoryNegativeIndex(UUID uuid, World world) {
|
private void loadHistoryNegativeIndex(UUID uuid, World world) {
|
||||||
@ -414,7 +362,7 @@ public class LocalSession {
|
|||||||
public void remember(EditSession editSession) {
|
public void remember(EditSession editSession) {
|
||||||
FawePlayer fp = editSession.getPlayer();
|
FawePlayer fp = editSession.getPlayer();
|
||||||
int limit = fp == null ? Integer.MAX_VALUE : fp.getLimit().MAX_HISTORY;
|
int limit = fp == null ? Integer.MAX_VALUE : fp.getLimit().MAX_HISTORY;
|
||||||
remember(editSession, true, false, limit);
|
remember(editSession, true, limit);
|
||||||
}
|
}
|
||||||
|
|
||||||
private FaweChangeSet getChangeSet(Object o) {
|
private FaweChangeSet getChangeSet(Object o) {
|
||||||
@ -424,12 +372,62 @@ public class LocalSession {
|
|||||||
return cs;
|
return cs;
|
||||||
}
|
}
|
||||||
if (o instanceof Integer) {
|
if (o instanceof Integer) {
|
||||||
|
File folder = MainUtil.getFile(Fawe.imp().getDirectory(), Settings.IMP.PATHS.HISTORY + File.separator + Fawe.imp().getWorldName(currentWorld) + File.separator + uuid);
|
||||||
|
File specific = new File(folder, o.toString());
|
||||||
|
if (specific.isDirectory()) {
|
||||||
|
return new AnvilHistory(Fawe.imp().getWorldName(currentWorld), specific);
|
||||||
|
} else {
|
||||||
return new DiskStorageHistory(currentWorld, this.uuid, (Integer) o);
|
return new DiskStorageHistory(currentWorld, this.uuid, (Integer) o);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized void remember(final EditSession editSession, final boolean append, final boolean sendMessage, int limitMb) {
|
public synchronized void remember(Player player, World world, ChangeSet changeSet, FaweLimit limit) {
|
||||||
|
if (Settings.IMP.HISTORY.USE_DISK) {
|
||||||
|
LocalSession.MAX_HISTORY_SIZE = Integer.MAX_VALUE;
|
||||||
|
}
|
||||||
|
if (changeSet.size() == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
loadSessionHistoryFromDisk(player.getUniqueId(), world);
|
||||||
|
if (changeSet instanceof FaweChangeSet) {
|
||||||
|
int size = getHistoryNegativeIndex();
|
||||||
|
ListIterator<Object> iter = history.listIterator();
|
||||||
|
int i = 0;
|
||||||
|
int cutoffIndex = history.size() - getHistoryNegativeIndex();
|
||||||
|
while (iter.hasNext()) {
|
||||||
|
Object item = iter.next();
|
||||||
|
if (++i > cutoffIndex) {
|
||||||
|
FaweChangeSet oldChangeSet;
|
||||||
|
if (item instanceof FaweChangeSet) {
|
||||||
|
oldChangeSet = (FaweChangeSet) item;
|
||||||
|
} else {
|
||||||
|
oldChangeSet = getChangeSet(item);
|
||||||
|
}
|
||||||
|
historySize -= MainUtil.getSize(oldChangeSet);
|
||||||
|
iter.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
historySize += MainUtil.getSize(changeSet);
|
||||||
|
history.add(changeSet);
|
||||||
|
if (getHistoryNegativeIndex() != 0) {
|
||||||
|
setDirty();
|
||||||
|
historyNegativeIndex = 0;
|
||||||
|
}
|
||||||
|
if (limit != null) {
|
||||||
|
int limitMb = limit.MAX_HISTORY;
|
||||||
|
while (((!Settings.IMP.HISTORY.USE_DISK && history.size() > MAX_HISTORY_SIZE) || (historySize >> 20) > limitMb) && history.size() > 1) {
|
||||||
|
FaweChangeSet item = (FaweChangeSet) history.remove(0);
|
||||||
|
item.delete();
|
||||||
|
long size = MainUtil.getSize(item);
|
||||||
|
historySize -= size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void remember(final EditSession editSession, final boolean append, int limitMb) {
|
||||||
if (Settings.IMP.HISTORY.USE_DISK) {
|
if (Settings.IMP.HISTORY.USE_DISK) {
|
||||||
LocalSession.MAX_HISTORY_SIZE = Integer.MAX_VALUE;
|
LocalSession.MAX_HISTORY_SIZE = Integer.MAX_VALUE;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user