geforkt von Mirrors/FastAsyncWorldEdit
Improve performance of various commands/actions
- Add chunk preloading to RegionVisitor if supplied with a suitable Extent - Where extents are used in masks, set EditSession as the extent as they are otherwise initialised with WorldWrapper that is very slow - Fixes #1073
Dieser Commit ist enthalten in:
Ursprung
f2ee2248e0
Commit
3b4beba7d6
@ -1242,7 +1242,7 @@ public class EditSession extends PassthroughExtent implements AutoCloseable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
});
|
}, this);
|
||||||
Operations.completeBlindly(visitor);
|
Operations.completeBlindly(visitor);
|
||||||
return this.changes;
|
return this.changes;
|
||||||
}
|
}
|
||||||
@ -2783,7 +2783,7 @@ public class EditSession extends PassthroughExtent implements AutoCloseable {
|
|||||||
} catch (EvaluationException e) {
|
} catch (EvaluationException e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
});
|
}, this);
|
||||||
Operations.completeBlindly(visitor);
|
Operations.completeBlindly(visitor);
|
||||||
changes += visitor.getAffected();
|
changes += visitor.getAffected();
|
||||||
return changes;
|
return changes;
|
||||||
|
@ -177,7 +177,9 @@ public class BiomeCommands {
|
|||||||
if (mask != null) {
|
if (mask != null) {
|
||||||
replace = new RegionMaskingFilter(editSession, mask, replace);
|
replace = new RegionMaskingFilter(editSession, mask, replace);
|
||||||
}
|
}
|
||||||
RegionVisitor visitor = new RegionVisitor(region, replace);
|
//FAWE start > add extent to RegionVisitor to allow chunk preloading
|
||||||
|
RegionVisitor visitor = new RegionVisitor(region, replace, editSession);
|
||||||
|
//FAWE end
|
||||||
Operations.completeLegacy(visitor);
|
Operations.completeLegacy(visitor);
|
||||||
|
|
||||||
player.print(Caption.of(
|
player.print(Caption.of(
|
||||||
|
@ -35,6 +35,7 @@ import com.sk89q.worldedit.command.util.annotation.Confirm;
|
|||||||
import com.sk89q.worldedit.entity.Player;
|
import com.sk89q.worldedit.entity.Player;
|
||||||
import com.sk89q.worldedit.extension.platform.Actor;
|
import com.sk89q.worldedit.extension.platform.Actor;
|
||||||
import com.fastasyncworldedit.core.function.generator.CavesGen;
|
import com.fastasyncworldedit.core.function.generator.CavesGen;
|
||||||
|
import com.sk89q.worldedit.function.mask.AbstractExtentMask;
|
||||||
import com.sk89q.worldedit.function.mask.Mask;
|
import com.sk89q.worldedit.function.mask.Mask;
|
||||||
import com.sk89q.worldedit.function.operation.Operations;
|
import com.sk89q.worldedit.function.operation.Operations;
|
||||||
import com.sk89q.worldedit.function.pattern.Pattern;
|
import com.sk89q.worldedit.function.pattern.Pattern;
|
||||||
@ -467,6 +468,9 @@ public class GenerationCommands {
|
|||||||
@Logging(PLACEMENT)
|
@Logging(PLACEMENT)
|
||||||
@Confirm(Confirm.Processor.REGION)
|
@Confirm(Confirm.Processor.REGION)
|
||||||
public void ores(Actor actor, LocalSession session, EditSession editSession, @Selection Region region, @Arg(desc = "Mask") Mask mask) throws WorldEditException {
|
public void ores(Actor actor, LocalSession session, EditSession editSession, @Selection Region region, @Arg(desc = "Mask") Mask mask) throws WorldEditException {
|
||||||
|
if (mask instanceof AbstractExtentMask) {
|
||||||
|
((AbstractExtentMask) mask).setExtent(editSession);
|
||||||
|
}
|
||||||
editSession.addOres(region, mask);
|
editSession.addOres(region, mask);
|
||||||
actor.print(Caption.of("fawe.worldedit.visitor.visitor.block", editSession.getBlockChangeCount()));
|
actor.print(Caption.of("fawe.worldedit.visitor.visitor.block", editSession.getBlockChangeCount()));
|
||||||
}
|
}
|
||||||
@ -516,7 +520,7 @@ public class GenerationCommands {
|
|||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
});
|
}, editSession);
|
||||||
Operations.completeBlindly(visitor);
|
Operations.completeBlindly(visitor);
|
||||||
actor.print(Caption.of("fawe.worldedit.visitor.visitor.block", editSession.getBlockChangeCount()));
|
actor.print(Caption.of("fawe.worldedit.visitor.visitor.block", editSession.getBlockChangeCount()));
|
||||||
}
|
}
|
||||||
@ -536,6 +540,9 @@ public class GenerationCommands {
|
|||||||
@Arg(desc = "Ore vein rarity (% chance each attempt is placed)", def = "100") @Range(from = 0, to = 100) int rarity,
|
@Arg(desc = "Ore vein rarity (% chance each attempt is placed)", def = "100") @Range(from = 0, to = 100) int rarity,
|
||||||
@Arg(desc = "Ore vein min y", def = "0") @Range(from = 0, to = 255) int minY,
|
@Arg(desc = "Ore vein min y", def = "0") @Range(from = 0, to = 255) int minY,
|
||||||
@Arg(desc = "Ore vein max y", def = "63") @Range(from = 0, to = 255) int maxY) throws WorldEditException {
|
@Arg(desc = "Ore vein max y", def = "63") @Range(from = 0, to = 255) int maxY) throws WorldEditException {
|
||||||
|
if (mask instanceof AbstractExtentMask) {
|
||||||
|
((AbstractExtentMask) mask).setExtent(editSession);
|
||||||
|
}
|
||||||
editSession.addOre(region, mask, material, size, freq, rarity, minY, maxY);
|
editSession.addOre(region, mask, material, size, freq, rarity, minY, maxY);
|
||||||
actor.print(Caption.of("fawe.worldedit.visitor.visitor.block", editSession.getBlockChangeCount()));
|
actor.print(Caption.of("fawe.worldedit.visitor.visitor.block", editSession.getBlockChangeCount()));
|
||||||
}
|
}
|
||||||
|
@ -299,6 +299,10 @@ public class RegionCommands {
|
|||||||
Pattern to) throws WorldEditException {
|
Pattern to) throws WorldEditException {
|
||||||
if (from == null) {
|
if (from == null) {
|
||||||
from = new ExistingBlockMask(editSession);
|
from = new ExistingBlockMask(editSession);
|
||||||
|
//FAWE start > the mask will have been initialised with a WorldWrapper extent (very bad/slow
|
||||||
|
} else if (from instanceof AbstractExtentMask) {
|
||||||
|
((AbstractExtentMask) from).setExtent(editSession);
|
||||||
|
//FAWE end
|
||||||
}
|
}
|
||||||
if (from instanceof AbstractExtentMask) {
|
if (from instanceof AbstractExtentMask) {
|
||||||
((AbstractExtentMask) from).setExtent(editSession);
|
((AbstractExtentMask) from).setExtent(editSession);
|
||||||
@ -422,6 +426,11 @@ public class RegionCommands {
|
|||||||
Mask mask,
|
Mask mask,
|
||||||
@Switch(name = 's', desc = "The flag makes it only consider snow")
|
@Switch(name = 's', desc = "The flag makes it only consider snow")
|
||||||
boolean snow) throws WorldEditException {
|
boolean snow) throws WorldEditException {
|
||||||
|
//FAWE start > the mask will have been initialised with a WorldWrapper extent (very bad/slow)
|
||||||
|
if (mask instanceof AbstractExtentMask) {
|
||||||
|
((AbstractExtentMask) mask).setExtent(editSession);
|
||||||
|
}
|
||||||
|
//FAWE end
|
||||||
BlockVector3 min = region.getMinimumPoint();
|
BlockVector3 min = region.getMinimumPoint();
|
||||||
BlockVector3 max = region.getMaximumPoint();
|
BlockVector3 max = region.getMaximumPoint();
|
||||||
long volume = (((long) max.getX() - (long) min.getX() + 1) * ((long) max.getY() - (long) min.getY() + 1) * ((long) max.getZ() - (long) min.getZ() + 1));
|
long volume = (((long) max.getX() - (long) min.getX() + 1) * ((long) max.getY() - (long) min.getY() + 1) * ((long) max.getZ() - (long) min.getZ() + 1));
|
||||||
@ -502,7 +511,11 @@ public class RegionCommands {
|
|||||||
@ArgFlag(name = 'm', desc = "Set the include mask, non-matching blocks become air")
|
@ArgFlag(name = 'm', desc = "Set the include mask, non-matching blocks become air")
|
||||||
Mask mask) throws WorldEditException {
|
Mask mask) throws WorldEditException {
|
||||||
checkCommandArgument(count >= 1, "Count must be >= 1");
|
checkCommandArgument(count >= 1, "Count must be >= 1");
|
||||||
|
//FAWE start > the mask will have been initialised with a WorldWrapper extent (very bad/slow)
|
||||||
|
if (mask instanceof AbstractExtentMask) {
|
||||||
|
((AbstractExtentMask) mask).setExtent(editSession);
|
||||||
|
}
|
||||||
|
//FAWE end
|
||||||
Mask combinedMask;
|
Mask combinedMask;
|
||||||
if (ignoreAirBlocks) {
|
if (ignoreAirBlocks) {
|
||||||
if (mask == null) {
|
if (mask == null) {
|
||||||
@ -573,7 +586,11 @@ public class RegionCommands {
|
|||||||
boolean copyBiomes,
|
boolean copyBiomes,
|
||||||
@ArgFlag(name = 'm', desc = "Set the include mask, non-matching blocks become air")
|
@ArgFlag(name = 'm', desc = "Set the include mask, non-matching blocks become air")
|
||||||
Mask mask) throws WorldEditException {
|
Mask mask) throws WorldEditException {
|
||||||
|
//FAWE start > the mask will have been initialised with a WorldWrapper extent (very bad/slow)
|
||||||
|
if (mask instanceof AbstractExtentMask) {
|
||||||
|
((AbstractExtentMask) mask).setExtent(editSession);
|
||||||
|
}
|
||||||
|
//FAWE end
|
||||||
Mask combinedMask;
|
Mask combinedMask;
|
||||||
if (ignoreAirBlocks) {
|
if (ignoreAirBlocks) {
|
||||||
if (mask == null) {
|
if (mask == null) {
|
||||||
@ -731,7 +748,18 @@ public class RegionCommands {
|
|||||||
@ArgFlag(name = 'm', desc = "Mask to hollow with")
|
@ArgFlag(name = 'm', desc = "Mask to hollow with")
|
||||||
Mask mask) throws WorldEditException {
|
Mask mask) throws WorldEditException {
|
||||||
checkCommandArgument(thickness >= 0, "Thickness must be >= 0");
|
checkCommandArgument(thickness >= 0, "Thickness must be >= 0");
|
||||||
Mask finalMask = mask == null ? new SolidBlockMask(editSession) : mask;
|
|
||||||
|
//FAWE start > the mask will have been initialised with a WorldWrapper extent (very bad/slow)
|
||||||
|
Mask finalMask;
|
||||||
|
if (mask != null) {
|
||||||
|
if (mask instanceof AbstractExtentMask) {
|
||||||
|
((AbstractExtentMask) mask).setExtent(editSession);
|
||||||
|
}
|
||||||
|
finalMask = mask;
|
||||||
|
} else {
|
||||||
|
finalMask = new SolidBlockMask(editSession);
|
||||||
|
}
|
||||||
|
//FAWE end
|
||||||
|
|
||||||
int affected = editSession.hollowOutRegion(region, thickness, pattern, finalMask);
|
int affected = editSession.hollowOutRegion(region, thickness, pattern, finalMask);
|
||||||
actor.print(Caption.of("worldedit.hollow.changed", TextComponent.of(affected)));
|
actor.print(Caption.of("worldedit.hollow.changed", TextComponent.of(affected)));
|
||||||
|
@ -42,6 +42,7 @@ import com.sk89q.worldedit.extension.platform.Locatable;
|
|||||||
import com.sk89q.worldedit.extension.platform.permission.ActorSelectorLimits;
|
import com.sk89q.worldedit.extension.platform.permission.ActorSelectorLimits;
|
||||||
import com.sk89q.worldedit.extent.clipboard.Clipboard;
|
import com.sk89q.worldedit.extent.clipboard.Clipboard;
|
||||||
import com.sk89q.worldedit.function.block.BlockDistributionCounter;
|
import com.sk89q.worldedit.function.block.BlockDistributionCounter;
|
||||||
|
import com.sk89q.worldedit.function.mask.AbstractExtentMask;
|
||||||
import com.sk89q.worldedit.function.mask.Mask;
|
import com.sk89q.worldedit.function.mask.Mask;
|
||||||
import com.sk89q.worldedit.function.operation.Operations;
|
import com.sk89q.worldedit.function.operation.Operations;
|
||||||
import com.sk89q.worldedit.function.visitor.RegionVisitor;
|
import com.sk89q.worldedit.function.visitor.RegionVisitor;
|
||||||
@ -534,6 +535,11 @@ public class SelectionCommands {
|
|||||||
public int count(Actor actor, World world, LocalSession session, EditSession editSession,
|
public int count(Actor actor, World world, LocalSession session, EditSession editSession,
|
||||||
@Arg(desc = "The mask of blocks to match")
|
@Arg(desc = "The mask of blocks to match")
|
||||||
Mask mask) throws WorldEditException {
|
Mask mask) throws WorldEditException {
|
||||||
|
//FAWE start > the mask will have been initialised with a WorldWrapper extent (very bad/slow)
|
||||||
|
if (mask instanceof AbstractExtentMask) {
|
||||||
|
((AbstractExtentMask) mask).setExtent(editSession);
|
||||||
|
}
|
||||||
|
//FAWE end
|
||||||
int count = editSession.countBlocks(session.getSelection(world), mask);
|
int count = editSession.countBlocks(session.getSelection(world), mask);
|
||||||
actor.print(Caption.of("worldedit.count.counted", TextComponent.of(count)));
|
actor.print(Caption.of("worldedit.count.counted", TextComponent.of(count)));
|
||||||
return count;
|
return count;
|
||||||
@ -545,6 +551,9 @@ public class SelectionCommands {
|
|||||||
)
|
)
|
||||||
@CommandPermissions("worldedit.analysis.distr")
|
@CommandPermissions("worldedit.analysis.distr")
|
||||||
public void distr(Actor actor, World world, LocalSession session,
|
public void distr(Actor actor, World world, LocalSession session,
|
||||||
|
//FAWE start > add extent to RegionVisitor to allow chunk preloading
|
||||||
|
EditSession editSession,
|
||||||
|
//FAWE end
|
||||||
@Switch(name = 'c', desc = "Get the distribution of the clipboard instead")
|
@Switch(name = 'c', desc = "Get the distribution of the clipboard instead")
|
||||||
boolean clipboardDistr,
|
boolean clipboardDistr,
|
||||||
@Switch(name = 'd', desc = "Separate blocks by state")
|
@Switch(name = 'd', desc = "Separate blocks by state")
|
||||||
@ -557,14 +566,14 @@ public class SelectionCommands {
|
|||||||
if (clipboardDistr) {
|
if (clipboardDistr) {
|
||||||
Clipboard clipboard = session.getClipboard().getClipboard(); // throws if missing
|
Clipboard clipboard = session.getClipboard().getClipboard(); // throws if missing
|
||||||
BlockDistributionCounter count = new BlockDistributionCounter(clipboard, separateStates);
|
BlockDistributionCounter count = new BlockDistributionCounter(clipboard, separateStates);
|
||||||
RegionVisitor visitor = new RegionVisitor(clipboard.getRegion(), count);
|
//FAWE start > add extent to RegionVisitor to allow chunk preloading
|
||||||
|
RegionVisitor visitor = new RegionVisitor(clipboard.getRegion(), count, editSession);
|
||||||
|
//FAWE end
|
||||||
Operations.completeBlindly(visitor);
|
Operations.completeBlindly(visitor);
|
||||||
distribution = count.getDistribution();
|
distribution = count.getDistribution();
|
||||||
} else {
|
} else {
|
||||||
try (EditSession editSession = session.createEditSession(actor)) {
|
|
||||||
distribution = editSession.getBlockDistribution(session.getSelection(world), separateStates);
|
distribution = editSession.getBlockDistribution(session.getSelection(world), separateStates);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
session.setLastDistribution(distribution);
|
session.setLastDistribution(distribution);
|
||||||
page = 1;
|
page = 1;
|
||||||
} else {
|
} else {
|
||||||
|
@ -49,6 +49,7 @@ import com.sk89q.worldedit.extension.platform.Actor;
|
|||||||
import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormat;
|
import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormat;
|
||||||
import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormats;
|
import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormats;
|
||||||
import com.sk89q.worldedit.function.EntityFunction;
|
import com.sk89q.worldedit.function.EntityFunction;
|
||||||
|
import com.sk89q.worldedit.function.mask.AbstractExtentMask;
|
||||||
import com.sk89q.worldedit.function.mask.BlockTypeMask;
|
import com.sk89q.worldedit.function.mask.BlockTypeMask;
|
||||||
import com.sk89q.worldedit.function.mask.ExistingBlockMask;
|
import com.sk89q.worldedit.function.mask.ExistingBlockMask;
|
||||||
import com.sk89q.worldedit.function.mask.Mask;
|
import com.sk89q.worldedit.function.mask.Mask;
|
||||||
@ -424,6 +425,11 @@ public class UtilityCommands {
|
|||||||
Mask mask,
|
Mask mask,
|
||||||
@Arg(desc = "The radius of the square to remove from", def = "50")
|
@Arg(desc = "The radius of the square to remove from", def = "50")
|
||||||
int radius) throws WorldEditException {
|
int radius) throws WorldEditException {
|
||||||
|
//FAWE start > the mask will have been initialised with a WorldWrapper extent (very bad/slow)
|
||||||
|
if (mask instanceof AbstractExtentMask) {
|
||||||
|
((AbstractExtentMask) mask).setExtent(editSession);
|
||||||
|
}
|
||||||
|
//FAWE end
|
||||||
radius = Math.max(1, radius);
|
radius = Math.max(1, radius);
|
||||||
we.checkMaxRadius(radius);
|
we.checkMaxRadius(radius);
|
||||||
|
|
||||||
@ -446,6 +452,11 @@ public class UtilityCommands {
|
|||||||
Mask from,
|
Mask from,
|
||||||
@Arg(desc = "The pattern of blocks to replace with")
|
@Arg(desc = "The pattern of blocks to replace with")
|
||||||
Pattern to) throws WorldEditException {
|
Pattern to) throws WorldEditException {
|
||||||
|
//FAWE start > the mask will have been initialised with a WorldWrapper extent (very bad/slow)
|
||||||
|
if (from instanceof AbstractExtentMask) {
|
||||||
|
((AbstractExtentMask) from).setExtent(editSession);
|
||||||
|
}
|
||||||
|
//FAWE end
|
||||||
radius = Math.max(1, radius);
|
radius = Math.max(1, radius);
|
||||||
we.checkMaxRadius(radius);
|
we.checkMaxRadius(radius);
|
||||||
|
|
||||||
|
@ -549,7 +549,9 @@ public interface Extent extends InputExtent, OutputExtent {
|
|||||||
* @return the number of blocks that matched the mask
|
* @return the number of blocks that matched the mask
|
||||||
*/
|
*/
|
||||||
default int countBlocks(Region region, Mask searchMask) {
|
default int countBlocks(Region region, Mask searchMask) {
|
||||||
RegionVisitor visitor = new RegionVisitor(region, searchMask::test);
|
//FAWE start > use slightly more performant RegionVisitor
|
||||||
|
RegionVisitor visitor = new RegionVisitor(region, searchMask::test, this);
|
||||||
|
//FAWE end
|
||||||
Operations.completeBlindly(visitor);
|
Operations.completeBlindly(visitor);
|
||||||
return visitor.getAffected();
|
return visitor.getAffected();
|
||||||
}
|
}
|
||||||
@ -648,7 +650,9 @@ public interface Extent extends InputExtent, OutputExtent {
|
|||||||
|
|
||||||
BlockReplace replace = new BlockReplace(this, pattern);
|
BlockReplace replace = new BlockReplace(this, pattern);
|
||||||
RegionMaskingFilter filter = new RegionMaskingFilter(this, mask, replace);
|
RegionMaskingFilter filter = new RegionMaskingFilter(this, mask, replace);
|
||||||
RegionVisitor visitor = new RegionVisitor(region, filter);
|
//FAWE start > add extent to RegionVisitor to allow chunk preloading
|
||||||
|
RegionVisitor visitor = new RegionVisitor(region, filter, this);
|
||||||
|
//FAWE end
|
||||||
Operations.completeLegacy(visitor);
|
Operations.completeLegacy(visitor);
|
||||||
return visitor.getAffected();
|
return visitor.getAffected();
|
||||||
}
|
}
|
||||||
|
@ -55,7 +55,9 @@ public class Apply implements Contextual<Operation> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Operation createFromContext(EditContext context) {
|
public Operation createFromContext(EditContext context) {
|
||||||
return new RegionVisitor(firstNonNull(context.getRegion(), region), function.createFromContext(context));
|
//FAWE start > add extent to RegionVisitor to allow chunk preloading
|
||||||
|
return new RegionVisitor(firstNonNull(context.getRegion(), region), function.createFromContext(context), context.getDestination());
|
||||||
|
//FAWE end
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -48,7 +48,9 @@ public class ApplyRegion implements Contextual<Operation> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Operation createFromContext(EditContext context) {
|
public Operation createFromContext(EditContext context) {
|
||||||
return new RegionVisitor(firstNonNull(context.getRegion(), region), function.createFromContext(context));
|
//FAWE start > add extent to RegionVisitor to allow chunk preloading
|
||||||
|
return new RegionVisitor(firstNonNull(context.getRegion(), region), function.createFromContext(context), context.getDestination());
|
||||||
|
//FAWE end
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -19,9 +19,19 @@
|
|||||||
|
|
||||||
package com.sk89q.worldedit.function.visitor;
|
package com.sk89q.worldedit.function.visitor;
|
||||||
|
|
||||||
|
import com.fastasyncworldedit.core.Fawe;
|
||||||
import com.fastasyncworldedit.core.configuration.Caption;
|
import com.fastasyncworldedit.core.configuration.Caption;
|
||||||
|
import com.fastasyncworldedit.core.configuration.Settings;
|
||||||
|
import com.fastasyncworldedit.core.internal.exception.FaweException;
|
||||||
|
import com.fastasyncworldedit.core.queue.implementation.ParallelQueueExtent;
|
||||||
|
import com.fastasyncworldedit.core.queue.implementation.SingleThreadQueueExtent;
|
||||||
|
import com.fastasyncworldedit.core.queue.implementation.chunk.ChunkHolder;
|
||||||
|
import com.fastasyncworldedit.core.util.ExtentTraverser;
|
||||||
|
import com.fastasyncworldedit.core.util.MemUtil;
|
||||||
|
import com.fastasyncworldedit.core.util.TaskManager;
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
import com.sk89q.worldedit.WorldEditException;
|
import com.sk89q.worldedit.WorldEditException;
|
||||||
|
import com.sk89q.worldedit.extent.Extent;
|
||||||
import com.sk89q.worldedit.function.RegionFunction;
|
import com.sk89q.worldedit.function.RegionFunction;
|
||||||
import com.sk89q.worldedit.function.operation.Operation;
|
import com.sk89q.worldedit.function.operation.Operation;
|
||||||
import com.sk89q.worldedit.function.operation.RunContext;
|
import com.sk89q.worldedit.function.operation.RunContext;
|
||||||
@ -29,25 +39,45 @@ import com.sk89q.worldedit.math.BlockVector3;
|
|||||||
import com.sk89q.worldedit.regions.Region;
|
import com.sk89q.worldedit.regions.Region;
|
||||||
import com.sk89q.worldedit.util.formatting.text.Component;
|
import com.sk89q.worldedit.util.formatting.text.Component;
|
||||||
import com.sk89q.worldedit.util.formatting.text.TextComponent;
|
import com.sk89q.worldedit.util.formatting.text.TextComponent;
|
||||||
|
import java.util.Iterator;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Utility class to apply region functions to {@link com.sk89q.worldedit.regions.Region}.
|
* Utility class to apply region functions to {@link com.sk89q.worldedit.regions.Region}.
|
||||||
|
*
|
||||||
* @deprecated - FAWE deprecation: Let the queue iterate, not the region function which lacks any kind of optimizations / parallelism
|
* @deprecated - FAWE deprecation: Let the queue iterate, not the region function which lacks any kind of optimizations / parallelism
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated public class RegionVisitor implements Operation {
|
||||||
public class RegionVisitor implements Operation {
|
|
||||||
|
|
||||||
|
public final Iterable<? extends BlockVector3> iterable;
|
||||||
private final Region region;
|
private final Region region;
|
||||||
private final RegionFunction function;
|
private final RegionFunction function;
|
||||||
private int affected = 0;
|
private int affected = 0;
|
||||||
|
private SingleThreadQueueExtent singleQueue;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @deprecated Use other constructors which will preload chunks during iteration
|
* @deprecated Use other constructors which will preload chunks during iteration
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated public RegionVisitor(Region region, RegionFunction function) {
|
||||||
public RegionVisitor(Region region, RegionFunction function) {
|
this(region, function, null);
|
||||||
this.region = region;
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allows for preloading chunks, and non-specific "regions" to be visited.
|
||||||
|
*
|
||||||
|
* @param iterable Can be supplied as a region, or a raw iterator
|
||||||
|
* @param function The function to be applied to each BlockVector3 iterated over
|
||||||
|
* @param extent Supplied editsession/extent to attempt to extract {@link SingleThreadQueueExtent} from
|
||||||
|
*/
|
||||||
|
public RegionVisitor(Iterable<BlockVector3> iterable, RegionFunction function, Extent extent) {
|
||||||
|
region = iterable instanceof Region ? (Region) iterable : null;
|
||||||
|
this.iterable = iterable;
|
||||||
this.function = function;
|
this.function = function;
|
||||||
|
if (extent != null) {
|
||||||
|
ExtentTraverser<ParallelQueueExtent> queueTraverser = new ExtentTraverser<>(extent).find(ParallelQueueExtent.class);
|
||||||
|
this.singleQueue = queueTraverser != null ? (SingleThreadQueueExtent) queueTraverser.get().getExtent() : null;
|
||||||
|
} else {
|
||||||
|
this.singleQueue = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -59,27 +89,132 @@ public class RegionVisitor implements Operation {
|
|||||||
return affected;
|
return affected;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override public Operation resume(RunContext run) throws WorldEditException {
|
||||||
public Operation resume(RunContext run) throws WorldEditException {
|
//FAWE start > allow chunk preloading
|
||||||
|
if (singleQueue != null && Settings.IMP.QUEUE.PRELOAD_CHUNKS > 1) {
|
||||||
|
/*
|
||||||
|
* The following is done to reduce iteration cost
|
||||||
|
* - Preload chunks just in time
|
||||||
|
* - Only check every 16th block for potential chunk loads
|
||||||
|
* - Stop iteration on exception instead of hasNext
|
||||||
|
* - Do not calculate the stacktrace as it is expensive
|
||||||
|
*/
|
||||||
|
Iterator<? extends BlockVector3> trailIter = iterable.iterator();
|
||||||
|
Iterator<? extends BlockVector3> leadIter = iterable.iterator();
|
||||||
|
int lastTrailChunkX = Integer.MIN_VALUE;
|
||||||
|
int lastTrailChunkZ = Integer.MIN_VALUE;
|
||||||
|
int lastLeadChunkX = Integer.MIN_VALUE;
|
||||||
|
int lastLeadChunkZ = Integer.MIN_VALUE;
|
||||||
|
int loadingTarget = Settings.IMP.QUEUE.PRELOAD_CHUNKS;
|
||||||
|
try {
|
||||||
|
for (; ; ) {
|
||||||
|
BlockVector3 pt = trailIter.next();
|
||||||
|
apply(pt);
|
||||||
|
int cx = pt.getBlockX() >> 4;
|
||||||
|
int cz = pt.getBlockZ() >> 4;
|
||||||
|
if (cx != lastTrailChunkX || cz != lastTrailChunkZ) {
|
||||||
|
lastTrailChunkX = cx;
|
||||||
|
lastTrailChunkZ = cz;
|
||||||
|
int amount;
|
||||||
|
if (lastLeadChunkX == Integer.MIN_VALUE) {
|
||||||
|
lastLeadChunkX = cx;
|
||||||
|
lastLeadChunkZ = cz;
|
||||||
|
amount = loadingTarget;
|
||||||
|
} else {
|
||||||
|
amount = 1;
|
||||||
|
}
|
||||||
|
for (int count = 0; count < amount; ) {
|
||||||
|
BlockVector3 v = leadIter.next();
|
||||||
|
int vcx = v.getBlockX() >> 4;
|
||||||
|
int vcz = v.getBlockZ() >> 4;
|
||||||
|
if (vcx != lastLeadChunkX || vcz != lastLeadChunkZ) {
|
||||||
|
lastLeadChunkX = vcx;
|
||||||
|
lastLeadChunkZ = vcz;
|
||||||
|
queueChunkLoad(vcx, vcz);
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
// Skip the next 15 blocks
|
||||||
|
leadIter.next();
|
||||||
|
leadIter.next();
|
||||||
|
leadIter.next();
|
||||||
|
leadIter.next();
|
||||||
|
leadIter.next();
|
||||||
|
leadIter.next();
|
||||||
|
leadIter.next();
|
||||||
|
leadIter.next();
|
||||||
|
leadIter.next();
|
||||||
|
leadIter.next();
|
||||||
|
leadIter.next();
|
||||||
|
leadIter.next();
|
||||||
|
leadIter.next();
|
||||||
|
leadIter.next();
|
||||||
|
leadIter.next();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
apply(trailIter.next());
|
||||||
|
apply(trailIter.next());
|
||||||
|
apply(trailIter.next());
|
||||||
|
apply(trailIter.next());
|
||||||
|
apply(trailIter.next());
|
||||||
|
apply(trailIter.next());
|
||||||
|
apply(trailIter.next());
|
||||||
|
apply(trailIter.next());
|
||||||
|
apply(trailIter.next());
|
||||||
|
apply(trailIter.next());
|
||||||
|
apply(trailIter.next());
|
||||||
|
apply(trailIter.next());
|
||||||
|
apply(trailIter.next());
|
||||||
|
apply(trailIter.next());
|
||||||
|
apply(trailIter.next());
|
||||||
|
}
|
||||||
|
} catch (FaweException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
} catch (Throwable ignore) {
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
for (; ; ) {
|
||||||
|
apply(trailIter.next());
|
||||||
|
apply(trailIter.next());
|
||||||
|
}
|
||||||
|
} catch (FaweException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
} catch (Throwable ignore) {
|
||||||
|
}
|
||||||
|
} else {
|
||||||
for (BlockVector3 pt : region) {
|
for (BlockVector3 pt : region) {
|
||||||
|
apply(pt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//FAWE end
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
//FAWE start > extract methods for slightly clean resume method
|
||||||
|
private void apply(BlockVector3 pt) throws WorldEditException {
|
||||||
if (function.apply(pt)) {
|
if (function.apply(pt)) {
|
||||||
affected++;
|
affected++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void queueChunkLoad(int cx, int cz) {
|
||||||
|
TaskManager.IMP.sync(() -> {
|
||||||
|
boolean lowMem = MemUtil.isMemoryLimited();
|
||||||
|
if (!singleQueue.isQueueEnabled() || (!(lowMem && singleQueue.size() > Settings.IMP.QUEUE.PARALLEL_THREADS + 8)
|
||||||
|
&& singleQueue.size() < Settings.IMP.QUEUE.TARGET_SIZE && Fawe.get().getQueueHandler().isUnderutilized())) {
|
||||||
|
//The GET chunk is what will take longest.
|
||||||
|
((ChunkHolder)singleQueue.getOrCreateChunk(cx, cz)).getOrCreateGet();
|
||||||
|
}
|
||||||
return null;
|
return null;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
//FAWE end
|
||||||
|
|
||||||
|
@Override public void cancel() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override public Iterable<Component> getStatusMessages() {
|
||||||
public void cancel() {
|
return ImmutableList.of(Caption.of("worldedit.operation.affected.block", TextComponent.of(getAffected())));
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Iterable<Component> getStatusMessages() {
|
|
||||||
return ImmutableList.of(Caption.of(
|
|
||||||
"worldedit.operation.affected.block",
|
|
||||||
TextComponent.of(getAffected())
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren