2024-10-15 18:22:59 -05:00
205 changed files with 3688 additions and 3318 deletions

View File

@ -365,6 +365,18 @@ public class Fawe {
Settings.settings().QUEUE.PARALLEL_THREADS
);
}
if (Settings.settings().HISTORY.DELETE_DISK_ON_LOGOUT && Settings.settings().HISTORY.USE_DATABASE) {
LOGGER.warn("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
LOGGER.warn("!!! !!!");
LOGGER.warn("!!! Using history database whilst deleting disk history! !!!");
LOGGER.warn("!!! You will not be able to rollback edits after a user logs !!!");
LOGGER.warn("!!! out, recommended to disable delete-disk-on-logout if you !!!");
LOGGER.warn("!!! you want to have full history rollback functionality. !!!");
LOGGER.warn("!!! Disable use-database if you do not need to have rollback !!!");
LOGGER.warn("!!! functionality and wish to disable this warning. !!!");
LOGGER.warn("!!! !!!");
LOGGER.warn("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
}
try {
byte[] in = new byte[0];
byte[] compressed = LZ4Factory.fastestJavaInstance().fastCompressor().compress(in);

View File

@ -192,17 +192,22 @@ public enum FaweCache implements Trimable {
Type.OUTSIDE_REGION
);
public static final FaweException MAX_CHECKS = new FaweException(
Caption.of("fawe.cancel.reason.max" + ".checks"),
Caption.of("fawe.cancel.reason.max.checks"),
Type.MAX_CHECKS,
true
);
public static final FaweException MAX_FAILS = new FaweException(
Caption.of("fawe.cancel.reason.max.fails"),
Type.MAX_CHECKS,
true
);
public static final FaweException MAX_CHANGES = new FaweException(
Caption.of("fawe.cancel.reason.max" + ".changes"),
Caption.of("fawe.cancel.reason.max.changes"),
Type.MAX_CHANGES,
false
);
public static final FaweException LOW_MEMORY = new FaweException(
Caption.of("fawe.cancel.reason.low" + ".memory"),
Caption.of("fawe.cancel.reason.low.memory"),
Type.LOW_MEMORY,
false
);

View File

@ -123,29 +123,31 @@ public class Settings extends Config {
limit.MAX_ACTIONS,
newLimit.MAX_ACTIONS != -1 ? newLimit.MAX_ACTIONS : Integer.MAX_VALUE
);
limit.MAX_CHANGES = Math.max(
limit.MAX_CHANGES,
limit.MAX_CHANGES.set(Math.max(
limit.MAX_CHANGES.get(),
newLimit.MAX_CHANGES != -1 ? newLimit.MAX_CHANGES : Long.MAX_VALUE
);
limit.MAX_BLOCKSTATES = Math.max(
limit.MAX_BLOCKSTATES,
));
limit.MAX_BLOCKSTATES.set(Math.max(
limit.MAX_BLOCKSTATES.get(),
newLimit.MAX_BLOCKSTATES != -1 ? newLimit.MAX_BLOCKSTATES : Integer.MAX_VALUE
);
limit.MAX_CHECKS = Math.max(
limit.MAX_CHECKS,
));
limit.MAX_CHECKS.set(Math.max(
limit.MAX_CHECKS.get(),
newLimit.MAX_CHECKS != -1 ? newLimit.MAX_CHECKS : Long.MAX_VALUE
);
limit.MAX_ENTITIES = Math.max(
limit.MAX_ENTITIES,
));
limit.MAX_ENTITIES.set(Math.max(
limit.MAX_ENTITIES.get(),
newLimit.MAX_ENTITIES != -1 ? newLimit.MAX_ENTITIES : Integer.MAX_VALUE
);
limit.MAX_FAILS = Math.max(limit.MAX_FAILS, newLimit.MAX_FAILS != -1 ? newLimit.MAX_FAILS : Integer.MAX_VALUE);
limit.MAX_ITERATIONS = Math.max(
limit.MAX_ITERATIONS, newLimit.MAX_ITERATIONS != -1 ? newLimit.MAX_ITERATIONS : Integer.MAX_VALUE);
limit.MAX_RADIUS = Math.max(
limit.MAX_RADIUS,
newLimit.MAX_RADIUS != -1 ? newLimit.MAX_RADIUS : Integer.MAX_VALUE
);
));
limit.MAX_FAILS.set(Math.max(
limit.MAX_FAILS.get(),
newLimit.MAX_FAILS != -1 ? newLimit.MAX_FAILS : Integer.MAX_VALUE
));
limit.MAX_ITERATIONS.set(Math.max(
limit.MAX_ITERATIONS.get(),
newLimit.MAX_ITERATIONS != -1 ? newLimit.MAX_ITERATIONS : Integer.MAX_VALUE
));
limit.MAX_RADIUS = Math.max(limit.MAX_RADIUS, newLimit.MAX_RADIUS != -1 ? newLimit.MAX_RADIUS : Integer.MAX_VALUE);
limit.MAX_SUPER_PICKAXE_SIZE = Math.max(
limit.MAX_SUPER_PICKAXE_SIZE,
newLimit.MAX_SUPER_PICKAXE_SIZE != -1 ? newLimit.MAX_SUPER_PICKAXE_SIZE : Integer.MAX_VALUE
@ -622,6 +624,13 @@ public class Settings extends Config {
})
public static class EXPERIMENTAL {
@Comment({
"Undo operation batch size",
" - The size defines the number of changes read at once.",
" - Larger numbers might reduce overhead but increase latency for edits with only few changes.",
" - 0 means undo operations are not batched."})
public int UNDO_BATCH_SIZE = 128;
@Comment({
"[UNSAFE] Directly modify the region files. (OBSOLETE - USE ANVIL COMMANDS)",
" - IMPROPER USE CAN CAUSE WORLD CORRUPTION!",
@ -668,6 +677,11 @@ public class Settings extends Config {
})
public boolean ALLOW_TICK_FLUIDS = false;
@Comment({
"Whether FAWE should use the incubator Vector API to accelerate some operations"
})
public boolean USE_VECTOR_API = false;
}
@Comment({"Web/HTTP connection related settings"})

View File

@ -19,9 +19,9 @@ public class AdjacentMaskParser extends RichParser<Mask> {
}
@Override
protected Stream<String> getSuggestions(String argumentInput, int index) {
protected Stream<String> getSuggestions(String argumentInput, int index, ParserContext context) {
if (index == 0) {
return worldEdit.getMaskFactory().getSuggestions(argumentInput).stream();
return worldEdit.getMaskFactory().getSuggestions(argumentInput, context).stream();
} else if (index == 1 || index == 2) {
return SuggestionHelper.suggestPositiveDoubles(argumentInput);
}

View File

@ -22,7 +22,7 @@ public class AngleMaskParser extends RichParser<Mask> {
}
@Override
protected Stream<String> getSuggestions(String argumentInput, int index) {
protected Stream<String> getSuggestions(String argumentInput, int index, ParserContext context) {
if (index == 0 || index == 1) {
return SuggestionHelper.suggestPositiveDoubles(argumentInput).flatMap(s -> Stream.of(s, s + "d"));
} else if (index > 1 && index <= 1 + flags.length) {

View File

@ -18,9 +18,9 @@ public class BesideMaskParser extends RichParser<Mask> {
}
@Override
protected Stream<String> getSuggestions(final String argumentInput, final int index) {
protected Stream<String> getSuggestions(final String argumentInput, final int index, ParserContext context) {
if (index == 0) {
return worldEdit.getMaskFactory().getSuggestions(argumentInput).stream();
return worldEdit.getMaskFactory().getSuggestions(argumentInput, context).stream();
} else if (index == 1 || index == 2) {
return SuggestionHelper.suggestPositiveDoubles(argumentInput);
}

View File

@ -22,7 +22,7 @@ public class ExtremaMaskParser extends RichParser<Mask> {
}
@Override
protected Stream<String> getSuggestions(String argumentInput, int index) {
protected Stream<String> getSuggestions(String argumentInput, int index, ParserContext context) {
if (index == 0 || index == 1) {
return SuggestionHelper.suggestPositiveDoubles(argumentInput).flatMap(s -> Stream.of(s, s + "d"));
} else if (index > 1 && index <= 1 + flags.length) {

View File

@ -22,7 +22,7 @@ public class ROCAngleMaskParser extends RichParser<Mask> {
}
@Override
protected Stream<String> getSuggestions(String argumentInput, int index) {
protected Stream<String> getSuggestions(String argumentInput, int index, ParserContext context) {
if (index == 0 || index == 1) {
return SuggestionHelper.suggestPositiveDoubles(argumentInput).flatMap(s -> Stream.of(s, s + "d"));
} else if (index > 1 && index <= 1 + flags.length) {

View File

@ -18,7 +18,7 @@ public class RadiusMaskParser extends RichParser<Mask> {
}
@Override
protected Stream<String> getSuggestions(String argumentInput, int index) {
protected Stream<String> getSuggestions(String argumentInput, int index, ParserContext context) {
if (index == 0 || index == 1) {
return SuggestionHelper.suggestPositiveIntegers(argumentInput);
}

View File

@ -24,12 +24,12 @@ public class RichOffsetMaskParser extends RichParser<Mask> {
}
@Override
protected Stream<String> getSuggestions(String argumentInput, int index) {
protected Stream<String> getSuggestions(String argumentInput, int index, ParserContext context) {
if (index < 3) {
return SuggestionHelper.suggestPositiveIntegers(argumentInput);
}
if (index == 3) {
return worldEdit.getMaskFactory().getSuggestions(argumentInput).stream();
return worldEdit.getMaskFactory().getSuggestions(argumentInput, context).stream();
}
return Stream.empty();
}

View File

@ -20,7 +20,7 @@ public class SimplexMaskParser extends RichParser<Mask> {
}
@Override
protected Stream<String> getSuggestions(String argumentInput, int index) {
protected Stream<String> getSuggestions(String argumentInput, int index, ParserContext context) {
if (index < 3) {
return SuggestionHelper.suggestPositiveDoubles(argumentInput);
}

View File

@ -23,7 +23,7 @@ public class SurfaceAngleMaskParser extends RichParser<Mask> {
}
@Override
protected Stream<String> getSuggestions(String argumentInput, int index) {
protected Stream<String> getSuggestions(String argumentInput, int index, ParserContext context) {
if (index <= 2) {
return SuggestionHelper.suggestPositiveDoubles(argumentInput);
}

View File

@ -25,7 +25,7 @@ public class AngleColorPatternParser extends RichParser<Pattern> {
}
@Override
public Stream<String> getSuggestions(String argumentInput, int index) {
public Stream<String> getSuggestions(String argumentInput, int index, ParserContext context) {
if (index != 0) {
return Stream.empty();
}

View File

@ -25,7 +25,7 @@ public class AverageColorPatternParser extends RichParser<Pattern> {
}
@Override
public Stream<String> getSuggestions(String argumentInput, int index) {
public Stream<String> getSuggestions(String argumentInput, int index, ParserContext context) {
if (index > 4) {
return Stream.empty();
}

View File

@ -54,7 +54,7 @@ public class BiomePatternParser extends RichParser<Pattern> {
}
@Override
protected Stream<String> getSuggestions(String argumentInput, int index) {
protected Stream<String> getSuggestions(String argumentInput, int index, ParserContext context) {
if (index == 0) {
return BiomeType.REGISTRY.getSuggestions(argumentInput);
}

View File

@ -26,9 +26,9 @@ public class BufferedPattern2DParser extends RichParser<Pattern> {
}
@Override
protected Stream<String> getSuggestions(String argumentInput, int index) {
protected Stream<String> getSuggestions(String argumentInput, int index, ParserContext context) {
if (index == 0) {
return this.worldEdit.getPatternFactory().getSuggestions(argumentInput).stream();
return this.worldEdit.getPatternFactory().getSuggestions(argumentInput, context).stream();
}
return Stream.empty();
}

View File

@ -26,9 +26,9 @@ public class BufferedPatternParser extends RichParser<Pattern> {
}
@Override
protected Stream<String> getSuggestions(String argumentInput, int index) {
protected Stream<String> getSuggestions(String argumentInput, int index, ParserContext context) {
if (index == 0) {
return this.worldEdit.getPatternFactory().getSuggestions(argumentInput).stream();
return this.worldEdit.getPatternFactory().getSuggestions(argumentInput, context).stream();
}
return Stream.empty();
}

View File

@ -26,7 +26,7 @@ public class ColorPatternParser extends RichParser<Pattern> {
}
@Override
public Stream<String> getSuggestions(String argumentInput, int index) {
public Stream<String> getSuggestions(String argumentInput, int index, ParserContext context) {
if (index > 4) {
return Stream.empty();
}

View File

@ -25,7 +25,7 @@ public class DesaturatePatternParser extends RichParser<Pattern> {
}
@Override
public Stream<String> getSuggestions(String argumentInput, int index) {
public Stream<String> getSuggestions(String argumentInput, int index, ParserContext context) {
if (index == 0) {
return SuggestionHelper.suggestPositiveDoubles(argumentInput);
}

View File

@ -28,9 +28,9 @@ public class Linear2DPatternParser extends RichParser<Pattern> {
}
@Override
protected Stream<String> getSuggestions(String argumentInput, int index) {
protected Stream<String> getSuggestions(String argumentInput, int index, ParserContext context) {
return switch (index) {
case 0 -> this.worldEdit.getPatternFactory().getSuggestions(argumentInput).stream();
case 0 -> this.worldEdit.getPatternFactory().getSuggestions(argumentInput, context).stream();
case 1, 2 -> SuggestionHelper.suggestPositiveIntegers(argumentInput);
default -> Stream.empty();
};

View File

@ -28,9 +28,9 @@ public class Linear3DPatternParser extends RichParser<Pattern> {
}
@Override
protected Stream<String> getSuggestions(String argumentInput, int index) {
protected Stream<String> getSuggestions(String argumentInput, int index, ParserContext context) {
return switch (index) {
case 0 -> this.worldEdit.getPatternFactory().getSuggestions(argumentInput).stream();
case 0 -> this.worldEdit.getPatternFactory().getSuggestions(argumentInput, context).stream();
case 1, 2, 3 -> SuggestionHelper.suggestPositiveIntegers(argumentInput);
default -> Stream.empty();
};

View File

@ -28,9 +28,9 @@ public class LinearPatternParser extends RichParser<Pattern> {
}
@Override
protected Stream<String> getSuggestions(String argumentInput, int index) {
protected Stream<String> getSuggestions(String argumentInput, int index, ParserContext context) {
return switch (index) {
case 0 -> this.worldEdit.getPatternFactory().getSuggestions(argumentInput).stream();
case 0 -> this.worldEdit.getPatternFactory().getSuggestions(argumentInput, context).stream();
case 1, 2, 3 -> SuggestionHelper.suggestPositiveIntegers(argumentInput);
default -> Stream.empty();
};

View File

@ -25,10 +25,10 @@ public class MaskedPatternParser extends RichParser<Pattern> {
}
@Override
protected Stream<String> getSuggestions(String argumentInput, int index) {
protected Stream<String> getSuggestions(String argumentInput, int index, ParserContext context) {
return switch (index) {
case 0 -> this.worldEdit.getMaskFactory().getSuggestions(argumentInput).stream();
case 1, 2 -> this.worldEdit.getPatternFactory().getSuggestions(argumentInput).stream();
case 0 -> this.worldEdit.getMaskFactory().getSuggestions(argumentInput, context).stream();
case 1, 2 -> this.worldEdit.getPatternFactory().getSuggestions(argumentInput, context).stream();
default -> Stream.empty();
};
}

View File

@ -24,9 +24,9 @@ public class NoXPatternParser extends RichParser<Pattern> {
}
@Override
public Stream<String> getSuggestions(String argumentInput, int index) {
public Stream<String> getSuggestions(String argumentInput, int index, ParserContext context) {
if (index == 0) {
return this.worldEdit.getPatternFactory().getSuggestions(argumentInput).stream();
return this.worldEdit.getPatternFactory().getSuggestions(argumentInput, context).stream();
}
return Stream.empty();
}

View File

@ -24,9 +24,9 @@ public class NoYPatternParser extends RichParser<Pattern> {
}
@Override
public Stream<String> getSuggestions(String argumentInput, int index) {
public Stream<String> getSuggestions(String argumentInput, int index, ParserContext context) {
if (index == 0) {
return this.worldEdit.getPatternFactory().getSuggestions(argumentInput).stream();
return this.worldEdit.getPatternFactory().getSuggestions(argumentInput, context).stream();
}
return Stream.empty();
}

View File

@ -24,9 +24,9 @@ public class NoZPatternParser extends RichParser<Pattern> {
}
@Override
public Stream<String> getSuggestions(String argumentInput, int index) {
public Stream<String> getSuggestions(String argumentInput, int index, ParserContext context) {
if (index == 0) {
return this.worldEdit.getPatternFactory().getSuggestions(argumentInput).stream();
return this.worldEdit.getPatternFactory().getSuggestions(argumentInput, context).stream();
}
return Stream.empty();
}

View File

@ -36,12 +36,12 @@ public abstract class NoisePatternParser extends RichParser<Pattern> {
}
@Override
protected Stream<String> getSuggestions(String argumentInput, int index) {
protected Stream<String> getSuggestions(String argumentInput, int index, ParserContext context) {
if (index == 0) {
return SuggestionHelper.suggestPositiveDoubles(argumentInput);
}
if (index == 1) {
return worldEdit.getPatternFactory().getSuggestions(argumentInput).stream();
return worldEdit.getPatternFactory().getSuggestions(argumentInput, context).stream();
}
return Stream.empty();
}

View File

@ -25,9 +25,9 @@ public class OffsetPatternParser extends RichParser<Pattern> {
}
@Override
protected Stream<String> getSuggestions(String argumentInput, int index) {
protected Stream<String> getSuggestions(String argumentInput, int index, ParserContext context) {
return switch (index) {
case 0 -> this.worldEdit.getPatternFactory().getSuggestions(argumentInput).stream();
case 0 -> this.worldEdit.getPatternFactory().getSuggestions(argumentInput, context).stream();
case 1, 2, 3 -> SuggestionHelper.suggestPositiveIntegers(argumentInput);
default -> Stream.empty();
};

View File

@ -4,6 +4,7 @@ import com.fastasyncworldedit.core.configuration.Caption;
import com.fastasyncworldedit.core.extension.factory.parser.RichParser;
import com.fastasyncworldedit.core.extent.clipboard.MultiClipboardHolder;
import com.fastasyncworldedit.core.function.pattern.RandomFullClipboardPattern;
import com.google.common.base.Function;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.command.util.SuggestionHelper;
import com.sk89q.worldedit.extension.input.InputParseException;
@ -33,7 +34,7 @@ public class RandomFullClipboardPatternParser extends RichParser<Pattern> {
}
@Override
protected Stream<String> getSuggestions(String argumentInput, int index) {
protected Stream<String> getSuggestions(String argumentInput, int index, ParserContext context) {
switch (index) {
case 0:
if (argumentInput.equals("#") || argumentInput.equals("#c")) {

View File

@ -25,9 +25,9 @@ public class RandomOffsetPatternParser extends RichParser<Pattern> {
}
@Override
protected Stream<String> getSuggestions(String argumentInput, int index) {
protected Stream<String> getSuggestions(String argumentInput, int index, ParserContext context) {
return switch (index) {
case 0 -> this.worldEdit.getPatternFactory().getSuggestions(argumentInput).stream();
case 0 -> this.worldEdit.getPatternFactory().getSuggestions(argumentInput, context).stream();
case 1, 2, 3 -> SuggestionHelper.suggestPositiveIntegers(argumentInput);
default -> Stream.empty();
};

View File

@ -24,9 +24,9 @@ public class RelativePatternParser extends RichParser<Pattern> {
}
@Override
public Stream<String> getSuggestions(String argumentInput, int index) {
public Stream<String> getSuggestions(String argumentInput, int index, ParserContext context) {
if (index == 0) {
return this.worldEdit.getPatternFactory().getSuggestions(argumentInput).stream();
return this.worldEdit.getPatternFactory().getSuggestions(argumentInput, context).stream();
}
return Stream.empty();
}

View File

@ -25,7 +25,7 @@ public class SaturatePatternParser extends RichParser<Pattern> {
}
@Override
public Stream<String> getSuggestions(String argumentInput, int index) {
public Stream<String> getSuggestions(String argumentInput, int index, ParserContext context) {
if (index > 3) {
return Stream.empty();
}

View File

@ -25,9 +25,9 @@ public class SolidRandomOffsetPatternParser extends RichParser<Pattern> {
}
@Override
protected Stream<String> getSuggestions(String argumentInput, int index) {
protected Stream<String> getSuggestions(String argumentInput, int index, ParserContext context) {
return switch (index) {
case 0 -> this.worldEdit.getPatternFactory().getSuggestions(argumentInput).stream();
case 0 -> this.worldEdit.getPatternFactory().getSuggestions(argumentInput, context).stream();
case 1, 2, 3 -> SuggestionHelper.suggestPositiveIntegers(argumentInput);
default -> Stream.empty();
};

View File

@ -25,9 +25,9 @@ public class SurfaceRandomOffsetPatternParser extends RichParser<Pattern> {
}
@Override
protected Stream<String> getSuggestions(String argumentInput, int index) {
protected Stream<String> getSuggestions(String argumentInput, int index, ParserContext context) {
return switch (index) {
case 0 -> this.worldEdit.getPatternFactory().getSuggestions(argumentInput).stream();
case 0 -> this.worldEdit.getPatternFactory().getSuggestions(argumentInput, context).stream();
case 1 -> SuggestionHelper.suggestPositiveIntegers(argumentInput);
default -> Stream.empty();
};

View File

@ -28,7 +28,7 @@ public class TypeSwapPatternParser extends RichParser<Pattern> {
}
@Override
public Stream<String> getSuggestions(String argumentInput, int index) {
public Stream<String> getSuggestions(String argumentInput, int index, ParserContext context) {
if (index > 2) {
return Stream.empty();
}

View File

@ -23,9 +23,9 @@ public class Linear3DTransformParser extends RichParser<ResettableExtent> {
}
@Override
protected Stream<String> getSuggestions(String argumentInput, int index) {
protected Stream<String> getSuggestions(String argumentInput, int index, ParserContext context) {
if (index == 0) {
return worldEdit.getTransformFactory().getSuggestions(argumentInput).stream();
return worldEdit.getTransformFactory().getSuggestions(argumentInput, context).stream();
}
return Stream.empty();
}

View File

@ -23,9 +23,9 @@ public class LinearTransformParser extends RichParser<ResettableExtent> {
}
@Override
protected Stream<String> getSuggestions(String argumentInput, int index) {
protected Stream<String> getSuggestions(String argumentInput, int index, ParserContext context) {
if (index == 0) {
return worldEdit.getTransformFactory().getSuggestions(argumentInput).stream();
return worldEdit.getTransformFactory().getSuggestions(argumentInput, context).stream();
}
return Stream.empty();
}

View File

@ -26,11 +26,11 @@ public class OffsetTransformParser extends RichParser<ResettableExtent> {
}
@Override
protected Stream<String> getSuggestions(String argumentInput, int index) {
protected Stream<String> getSuggestions(String argumentInput, int index, ParserContext context) {
if (index < 3) {
return SuggestionHelper.suggestPositiveIntegers(argumentInput);
} else if (index == 3) {
return worldEdit.getTransformFactory().getSuggestions(argumentInput).stream();
return worldEdit.getTransformFactory().getSuggestions(argumentInput, context).stream();
}
return Stream.empty();
}

View File

@ -24,11 +24,11 @@ public class PatternTransformParser extends RichParser<ResettableExtent> {
}
@Override
protected Stream<String> getSuggestions(String argumentInput, int index) {
protected Stream<String> getSuggestions(String argumentInput, int index, ParserContext context) {
if (index == 0) {
return worldEdit.getPatternFactory().getSuggestions(argumentInput).stream();
return worldEdit.getPatternFactory().getSuggestions(argumentInput, context).stream();
} else if (index == 1) {
return worldEdit.getTransformFactory().getSuggestions(argumentInput).stream();
return worldEdit.getTransformFactory().getSuggestions(argumentInput, context).stream();
}
return Stream.empty();
}

View File

@ -25,12 +25,12 @@ public class RotateTransformParser extends RichParser<ResettableExtent> {
}
@Override
protected Stream<String> getSuggestions(String argumentInput, int index) {
protected Stream<String> getSuggestions(String argumentInput, int index, ParserContext context) {
if (index < 3) {
return SuggestionHelper.suggestPositiveDoubles(argumentInput);
}
if (index == 3) {
return worldEdit.getTransformFactory().getSuggestions(argumentInput).stream();
return worldEdit.getTransformFactory().getSuggestions(argumentInput, context).stream();
}
return Stream.empty();
}

View File

@ -24,11 +24,11 @@ public class ScaleTransformParser extends RichParser<ResettableExtent> {
}
@Override
protected Stream<String> getSuggestions(String argumentInput, int index) {
protected Stream<String> getSuggestions(String argumentInput, int index, ParserContext context) {
if (index < 3) {
return SuggestionHelper.suggestPositiveDoubles(argumentInput);
} else if (index == 3) {
return worldEdit.getTransformFactory().getSuggestions(argumentInput).stream();
return worldEdit.getTransformFactory().getSuggestions(argumentInput, context).stream();
}
return Stream.empty();
}

View File

@ -24,11 +24,11 @@ public class SpreadTransformParser extends RichParser<ResettableExtent> {
}
@Override
protected Stream<String> getSuggestions(String argumentInput, int index) {
protected Stream<String> getSuggestions(String argumentInput, int index, ParserContext context) {
if (index < 3) {
return SuggestionHelper.suggestPositiveIntegers(argumentInput);
} else if (index == 3) {
return worldEdit.getTransformFactory().getSuggestions(argumentInput).stream();
return worldEdit.getTransformFactory().getSuggestions(argumentInput, context).stream();
}
return Stream.empty();
}

View File

@ -0,0 +1,7 @@
package com.fastasyncworldedit.core.extension.platform.binding;
import com.sk89q.worldedit.EditSession;
public record EditSessionHolder(EditSession session) {
}

View File

@ -3,7 +3,11 @@ package com.fastasyncworldedit.core.extension.platform.binding;
import com.fastasyncworldedit.core.configuration.Caption;
import com.fastasyncworldedit.core.database.DBHandler;
import com.fastasyncworldedit.core.database.RollbackDatabase;
import com.fastasyncworldedit.core.extent.LimitExtent;
import com.fastasyncworldedit.core.extent.processor.ExtentBatchProcessorHolder;
import com.fastasyncworldedit.core.internal.exception.FaweException;
import com.fastasyncworldedit.core.regions.FaweMaskManager;
import com.fastasyncworldedit.core.util.ExtentTraverser;
import com.fastasyncworldedit.core.util.TextureUtil;
import com.fastasyncworldedit.core.util.image.ImageUtil;
import com.sk89q.worldedit.EditSession;
@ -11,6 +15,7 @@ import com.sk89q.worldedit.LocalSession;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.command.argument.Arguments;
import com.sk89q.worldedit.command.util.annotation.AllowedRegion;
import com.sk89q.worldedit.command.util.annotation.SynchronousSettingExpected;
import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.extension.input.InputParseException;
import com.sk89q.worldedit.extension.platform.Actor;
@ -25,6 +30,7 @@ import org.enginehub.piston.inject.Key;
import org.enginehub.piston.util.ValueProvider;
import java.awt.image.BufferedImage;
import java.lang.reflect.Method;
import java.net.URI;
import java.util.Optional;
@ -52,11 +58,33 @@ public class ProvideBindings extends Bindings {
@Binding
public EditSession editSession(LocalSession localSession, Actor actor, InjectedValueAccess context) {
Method commandMethod =
context.injectedValue(Key.of(InjectedValueStore.class)).get().injectedValue(Key.of(Method.class)).get();
Arguments arguments = context.injectedValue(Key.of(Arguments.class)).orElse(null);
String command = arguments == null ? null : arguments.get();
EditSession editSession = localSession.createEditSession(actor, command);
editSession.enableStandardMode();
Request.request().setEditSession(editSession);
boolean synchronousSetting = commandMethod.getAnnotation(SynchronousSettingExpected.class) != null;
EditSessionHolder holder = context.injectedValue(Key.of(EditSessionHolder.class)).orElse(null);
EditSession editSession = holder != null ? holder.session() : null;
if (editSession == null) {
editSession = localSession.createEditSession(actor, command);
editSession.enableStandardMode();
} else {
LimitExtent limitExtent = new ExtentTraverser<>(editSession).findAndGet(LimitExtent.class);
if (limitExtent != null) {
limitExtent.setProcessing(!synchronousSetting);
if (!synchronousSetting) {
ExtentBatchProcessorHolder processorHolder = new ExtentTraverser<>(editSession).findAndGet(
ExtentBatchProcessorHolder.class);
if (processorHolder != null) {
processorHolder.addProcessor(limitExtent);
} else {
throw new FaweException(Caption.of("fawe.error.no-process-non-synchronous-edit"));
}
}
}
Request.request().setEditSession(editSession);
}
return editSession;
}

View File

@ -2,6 +2,7 @@ package com.fastasyncworldedit.core.extent;
import com.fastasyncworldedit.core.history.changeset.AbstractChangeSet;
import com.fastasyncworldedit.core.math.MutableBlockVector3;
import com.fastasyncworldedit.core.nbt.FaweCompoundTag;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.entity.BaseEntity;
import com.sk89q.worldedit.entity.Entity;
@ -74,7 +75,7 @@ public class HistoryExtent extends AbstractDelegateExtent {
public Entity createEntity(Location location, BaseEntity state) {
final Entity entity = super.createEntity(location, state);
if (state != null) {
this.changeSet.addEntityCreate(state.getNbtData());
this.changeSet.addEntityCreate(FaweCompoundTag.of(state.getNbt()));
}
return entity;
}
@ -84,7 +85,7 @@ public class HistoryExtent extends AbstractDelegateExtent {
public Entity createEntity(Location location, BaseEntity state, UUID uuid) {
final Entity entity = super.createEntity(location, state, uuid);
if (state != null) {
this.changeSet.addEntityCreate(state.getNbtData());
this.changeSet.addEntityCreate(FaweCompoundTag.of(state.getNbt()));
}
return entity;
}
@ -154,11 +155,10 @@ public class HistoryExtent extends AbstractDelegateExtent {
@Override
public boolean remove() {
final Location location = this.entity.getLocation();
final BaseEntity state = this.entity.getState();
final boolean success = this.entity.remove();
if (state != null && success) {
HistoryExtent.this.changeSet.addEntityRemove(state.getNbtData());
HistoryExtent.this.changeSet.addEntityRemove(FaweCompoundTag.of(state.getNbt()));
}
return success;
}

View File

@ -1,11 +1,15 @@
package com.fastasyncworldedit.core.extent;
import com.fastasyncworldedit.core.extent.filter.block.ExtentFilterBlock;
import com.fastasyncworldedit.core.function.generator.GenBase;
import com.fastasyncworldedit.core.function.generator.Resource;
import com.fastasyncworldedit.core.extent.processor.ProcessorScope;
import com.fastasyncworldedit.core.internal.exception.FaweException;
import com.fastasyncworldedit.core.limit.FaweLimit;
import com.fastasyncworldedit.core.queue.Filter;
import com.fastasyncworldedit.core.queue.IBatchProcessor;
import com.fastasyncworldedit.core.queue.IChunk;
import com.fastasyncworldedit.core.queue.IChunkGet;
import com.fastasyncworldedit.core.queue.IChunkSet;
import com.fastasyncworldedit.core.util.ExtentTraverser;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.worldedit.MaxChangedBlocksException;
import com.sk89q.worldedit.WorldEditException;
@ -17,7 +21,6 @@ import com.sk89q.worldedit.function.mask.Mask;
import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.session.ClipboardHolder;
import com.sk89q.worldedit.util.Countable;
import com.sk89q.worldedit.util.Location;
import com.sk89q.worldedit.util.formatting.text.Component;
@ -37,18 +40,22 @@ import java.util.Set;
import java.util.UUID;
import java.util.function.Consumer;
public class LimitExtent extends AbstractDelegateExtent {
public class LimitExtent extends AbstractDelegateExtent implements IBatchProcessor {
private final FaweLimit limit;
private final boolean[] faweExceptionReasonsUsed = new boolean[FaweException.Type.values().length];
private final Consumer<Component> onErrorMessage;
private final int chunk_size;
private boolean processing;
/**
* Create a new instance.
*
* @param extent the extent
* @param limit the limit
* @deprecated Use {@link LimitExtent#LimitExtent(Extent, FaweLimit, Consumer, boolean)}
*/
@Deprecated(forRemoval = true, since = "TODO")
public LimitExtent(Extent extent, FaweLimit limit) {
this(extent, limit, c -> {
});
@ -60,11 +67,33 @@ public class LimitExtent extends AbstractDelegateExtent {
* @param extent the extent
* @param limit the limit
* @param onErrorMessage consumer to handle a component generated by exceptions
* @deprecated Use {@link LimitExtent#LimitExtent(Extent, FaweLimit, Consumer, boolean)}
*/
@Deprecated(forRemoval = true, since = "TODO")
public LimitExtent(Extent extent, FaweLimit limit, Consumer<Component> onErrorMessage) {
this(extent, limit, onErrorMessage, false);
}
/**
* Create a new instance.
*
* @param extent the extent
* @param limit the limit
* @param onErrorMessage consumer to handle a component generated by exceptions
* @param processing if this limit extent is expected to be processing
* @since TODO
*/
public LimitExtent(
Extent extent,
FaweLimit limit,
Consumer<Component> onErrorMessage,
boolean processing
) {
super(extent);
this.limit = limit;
this.onErrorMessage = onErrorMessage;
this.chunk_size = 16 * 16 * (extent.getMaxY() - extent.getMinY());
this.processing = processing;
}
private void handleException(FaweException e) {
@ -81,7 +110,7 @@ public class LimitExtent extends AbstractDelegateExtent {
public List<? extends Entity> getEntities(Region region) {
limit.THROW_MAX_CHECKS(region.getVolume());
try {
return super.getEntities(region);
return extent.getEntities(region);
} catch (FaweException e) {
handleException(e);
return Collections.emptyList();
@ -92,7 +121,7 @@ public class LimitExtent extends AbstractDelegateExtent {
public List<? extends Entity> getEntities() {
limit.THROW_MAX_CHECKS();
try {
return super.getEntities();
return extent.getEntities();
} catch (FaweException e) {
handleException(e);
return Collections.emptyList();
@ -105,7 +134,7 @@ public class LimitExtent extends AbstractDelegateExtent {
limit.THROW_MAX_CHANGES();
limit.THROW_MAX_ENTITIES();
try {
return super.createEntity(location, entity);
return extent.createEntity(location, entity);
} catch (FaweException e) {
handleException(e);
return null;
@ -118,7 +147,7 @@ public class LimitExtent extends AbstractDelegateExtent {
limit.THROW_MAX_CHANGES();
limit.THROW_MAX_ENTITIES();
try {
return super.createEntity(location, entity, uuid);
return extent.createEntity(location, entity, uuid);
} catch (FaweException e) {
handleException(e);
return null;
@ -130,7 +159,7 @@ public class LimitExtent extends AbstractDelegateExtent {
limit.THROW_MAX_CHANGES();
limit.THROW_MAX_ENTITIES();
try {
super.removeEntity(x, y, z, uuid);
extent.removeEntity(x, y, z, uuid);
} catch (FaweException e) {
handleException(e);
}
@ -138,9 +167,9 @@ public class LimitExtent extends AbstractDelegateExtent {
@Override
public boolean regenerateChunk(int x, int z, @Nullable BiomeType type, @Nullable Long seed) {
limit.THROW_MAX_CHANGES(Character.MAX_VALUE);
limit.THROW_MAX_CHANGES(chunk_size);
try {
return super.regenerateChunk(x, z, type, seed);
return extent.regenerateChunk(x, z, type, seed);
} catch (FaweException e) {
handleException(e);
return false;
@ -151,7 +180,7 @@ public class LimitExtent extends AbstractDelegateExtent {
public int getHighestTerrainBlock(int x, int z, int minY, int maxY) {
limit.THROW_MAX_CHECKS(maxY - minY + 1);
try {
return super.getHighestTerrainBlock(x, z, minY, maxY);
return extent.getHighestTerrainBlock(x, z, minY, maxY);
} catch (FaweException e) {
handleException(e);
return minY;
@ -162,7 +191,7 @@ public class LimitExtent extends AbstractDelegateExtent {
public int getHighestTerrainBlock(int x, int z, int minY, int maxY, Mask filter) {
limit.THROW_MAX_CHECKS(maxY - minY + 1);
try {
return super.getHighestTerrainBlock(x, z, minY, maxY, filter);
return extent.getHighestTerrainBlock(x, z, minY, maxY, filter);
} catch (FaweException e) {
handleException(e);
return minY;
@ -173,7 +202,7 @@ public class LimitExtent extends AbstractDelegateExtent {
public int getNearestSurfaceLayer(int x, int z, int y, int minY, int maxY) {
limit.THROW_MAX_CHECKS(maxY - minY + 1);
try {
return super.getNearestSurfaceLayer(x, z, y, minY, maxY);
return extent.getNearestSurfaceLayer(x, z, y, minY, maxY);
} catch (FaweException e) {
handleException(e);
return minY;
@ -184,7 +213,7 @@ public class LimitExtent extends AbstractDelegateExtent {
public int getNearestSurfaceTerrainBlock(int x, int z, int y, int minY, int maxY, boolean ignoreAir) {
limit.THROW_MAX_CHECKS(maxY - minY + 1);
try {
return super.getNearestSurfaceTerrainBlock(x, z, y, minY, maxY, ignoreAir);
return extent.getNearestSurfaceTerrainBlock(x, z, y, minY, maxY, ignoreAir);
} catch (FaweException e) {
handleException(e);
return minY;
@ -195,7 +224,7 @@ public class LimitExtent extends AbstractDelegateExtent {
public int getNearestSurfaceTerrainBlock(int x, int z, int y, int minY, int maxY) {
limit.THROW_MAX_CHECKS(maxY - minY + 1);
try {
return super.getNearestSurfaceTerrainBlock(x, z, y, minY, maxY);
return extent.getNearestSurfaceTerrainBlock(x, z, y, minY, maxY);
} catch (FaweException e) {
handleException(e);
return minY;
@ -206,7 +235,7 @@ public class LimitExtent extends AbstractDelegateExtent {
public int getNearestSurfaceTerrainBlock(int x, int z, int y, int minY, int maxY, int failedMin, int failedMax) {
limit.THROW_MAX_CHECKS(maxY - minY + 1);
try {
return super.getNearestSurfaceTerrainBlock(x, z, y, minY, maxY, failedMin, failedMax);
return extent.getNearestSurfaceTerrainBlock(x, z, y, minY, maxY, failedMin, failedMax);
} catch (FaweException e) {
handleException(e);
return minY;
@ -217,7 +246,7 @@ public class LimitExtent extends AbstractDelegateExtent {
public int getNearestSurfaceTerrainBlock(int x, int z, int y, int minY, int maxY, int failedMin, int failedMax, Mask mask) {
limit.THROW_MAX_CHECKS(maxY - minY + 1);
try {
return super.getNearestSurfaceTerrainBlock(x, z, y, minY, maxY, failedMin, failedMax, mask);
return extent.getNearestSurfaceTerrainBlock(x, z, y, minY, maxY, failedMin, failedMax, mask);
} catch (FaweException e) {
handleException(e);
return minY;
@ -237,91 +266,47 @@ public class LimitExtent extends AbstractDelegateExtent {
) {
limit.THROW_MAX_CHECKS(maxY - minY + 1);
try {
return super.getNearestSurfaceTerrainBlock(x, z, y, minY, maxY, failedMin, failedMax, ignoreAir);
return extent.getNearestSurfaceTerrainBlock(x, z, y, minY, maxY, failedMin, failedMax, ignoreAir);
} catch (FaweException e) {
handleException(e);
return minY;
}
}
@Override
public void addCaves(Region region) throws WorldEditException {
limit.THROW_MAX_CHECKS(region.getVolume());
limit.THROW_MAX_CHANGES(region.getVolume());
super.addCaves(region);
}
@Override
public void generate(Region region, GenBase gen) throws WorldEditException {
limit.THROW_MAX_CHECKS(region.getVolume());
limit.THROW_MAX_CHANGES(region.getVolume());
super.generate(region, gen);
}
@Override
public void addSchems(Region region, Mask mask, List<ClipboardHolder> clipboards, int rarity, boolean rotate) throws
WorldEditException {
limit.THROW_MAX_CHECKS(region.getVolume());
limit.THROW_MAX_CHANGES(region.getVolume());
super.addSchems(region, mask, clipboards, rarity, rotate);
}
@Override
public void spawnResource(Region region, Resource gen, int rarity, int frequency) throws WorldEditException {
limit.THROW_MAX_CHECKS(region.getVolume());
limit.THROW_MAX_CHANGES(region.getVolume());
super.spawnResource(region, gen, rarity, frequency);
}
@Override
public void addOre(Region region, Mask mask, Pattern material, int size, int frequency, int rarity, int minY, int maxY) throws
WorldEditException {
limit.THROW_MAX_CHECKS(region.getVolume());
limit.THROW_MAX_CHANGES(region.getVolume());
super.addOre(region, mask, material, size, frequency, rarity, minY, maxY);
}
@Override
public void addOres(Region region, Mask mask) throws WorldEditException {
limit.THROW_MAX_CHECKS(region.getVolume());
limit.THROW_MAX_CHANGES(region.getVolume());
super.addOres(region, mask);
}
@Override
public List<Countable<BlockType>> getBlockDistribution(Region region) {
limit.THROW_MAX_CHECKS(region.getVolume());
return super.getBlockDistribution(region);
return extent.getBlockDistribution(region);
}
@Override
public List<Countable<BlockState>> getBlockDistributionWithData(Region region) {
limit.THROW_MAX_CHECKS(region.getVolume());
return super.getBlockDistributionWithData(region);
return extent.getBlockDistributionWithData(region);
}
@Override
public int countBlocks(Region region, Set<BaseBlock> searchBlocks) {
limit.THROW_MAX_CHECKS(region.getVolume());
return super.countBlocks(region, searchBlocks);
return extent.countBlocks(region, searchBlocks);
}
@Override
public int countBlocks(Region region, Mask searchMask) {
limit.THROW_MAX_CHECKS(region.getVolume());
return super.countBlocks(region, searchMask);
return extent.countBlocks(region, searchMask);
}
@Override
public <B extends BlockStateHolder<B>> int setBlocks(Region region, B block) throws MaxChangedBlocksException {
limit.THROW_MAX_CHANGES(region.getVolume());
return super.setBlocks(region, block);
return extent.setBlocks(region, block);
}
@Override
public int setBlocks(Region region, Pattern pattern) throws MaxChangedBlocksException {
limit.THROW_MAX_CHANGES(region.getVolume());
return super.setBlocks(region, pattern);
return extent.setBlocks(region, pattern);
}
@Override
@ -329,41 +314,34 @@ public class LimitExtent extends AbstractDelegateExtent {
MaxChangedBlocksException {
limit.THROW_MAX_CHECKS(region.getVolume());
limit.THROW_MAX_CHANGES(region.getVolume());
return super.replaceBlocks(region, filter, replacement);
return extent.replaceBlocks(region, filter, replacement);
}
@Override
public int replaceBlocks(Region region, Set<BaseBlock> filter, Pattern pattern) throws MaxChangedBlocksException {
limit.THROW_MAX_CHECKS(region.getVolume());
limit.THROW_MAX_CHANGES(region.getVolume());
return super.replaceBlocks(region, filter, pattern);
return extent.replaceBlocks(region, filter, pattern);
}
@Override
public int replaceBlocks(Region region, Mask mask, Pattern pattern) throws MaxChangedBlocksException {
limit.THROW_MAX_CHECKS(region.getVolume());
limit.THROW_MAX_CHANGES(region.getVolume());
return super.replaceBlocks(region, mask, pattern);
}
@Override
public int center(Region region, Pattern pattern) throws MaxChangedBlocksException {
limit.THROW_MAX_CHECKS(region.getVolume());
limit.THROW_MAX_CHANGES(region.getVolume());
return super.center(region, pattern);
return extent.replaceBlocks(region, mask, pattern);
}
@Override
public int setBlocks(Set<BlockVector3> vset, Pattern pattern) {
limit.THROW_MAX_CHANGES(vset.size());
return super.setBlocks(vset, pattern);
return extent.setBlocks(vset, pattern);
}
@Override
public <T extends Filter> T apply(Region region, T filter, boolean full) {
limit.THROW_MAX_CHECKS(region.getVolume());
limit.THROW_MAX_CHANGES(region.getVolume());
return super.apply(region, filter, full);
return extent.apply(region, filter, full);
}
@Override
@ -393,14 +371,14 @@ public class LimitExtent extends AbstractDelegateExtent {
}
limit.THROW_MAX_CHECKS(size);
limit.THROW_MAX_CHANGES(size);
return super.apply(positions, filter);
return extent.apply(positions, filter);
}
@Override
public BlockState getBlock(BlockVector3 position) {
limit.THROW_MAX_CHECKS();
try {
return super.getBlock(position);
return extent.getBlock(position);
} catch (FaweException e) {
handleException(e);
return BlockTypes.AIR.getDefaultState();
@ -411,7 +389,7 @@ public class LimitExtent extends AbstractDelegateExtent {
public BlockState getBlock(int x, int y, int z) {
limit.THROW_MAX_CHECKS();
try {
return super.getBlock(x, y, z);
return extent.getBlock(x, y, z);
} catch (FaweException e) {
handleException(e);
return BlockTypes.AIR.getDefaultState();
@ -422,7 +400,7 @@ public class LimitExtent extends AbstractDelegateExtent {
public BaseBlock getFullBlock(BlockVector3 position) {
limit.THROW_MAX_CHECKS();
try {
return super.getFullBlock(position);
return extent.getFullBlock(position);
} catch (FaweException e) {
handleException(e);
return BlockTypes.AIR.getDefaultState().toBaseBlock();
@ -433,7 +411,7 @@ public class LimitExtent extends AbstractDelegateExtent {
public BaseBlock getFullBlock(int x, int y, int z) {
limit.THROW_MAX_CHECKS();
try {
return super.getFullBlock(x, y, z);
return extent.getFullBlock(x, y, z);
} catch (FaweException e) {
handleException(e);
return BlockTypes.AIR.getDefaultState().toBaseBlock();
@ -444,7 +422,7 @@ public class LimitExtent extends AbstractDelegateExtent {
public BiomeType getBiome(BlockVector3 position) {
limit.THROW_MAX_CHECKS();
try {
return super.getBiome(position);
return extent.getBiome(position);
} catch (FaweException e) {
handleException(e);
return BiomeTypes.FOREST;
@ -455,7 +433,7 @@ public class LimitExtent extends AbstractDelegateExtent {
public BiomeType getBiomeType(int x, int y, int z) {
limit.THROW_MAX_CHECKS();
try {
return super.getBiomeType(x, y, z);
return extent.getBiomeType(x, y, z);
} catch (FaweException e) {
handleException(e);
return BiomeTypes.FOREST;
@ -470,7 +448,7 @@ public class LimitExtent extends AbstractDelegateExtent {
limit.THROW_MAX_BLOCKSTATES();
}
try {
return super.setBlock(position, block);
return extent.setBlock(position, block);
} catch (FaweException e) {
handleException(e);
return false;
@ -484,7 +462,7 @@ public class LimitExtent extends AbstractDelegateExtent {
limit.THROW_MAX_BLOCKSTATES();
}
try {
return super.setBlock(x, y, z, block);
return extent.setBlock(x, y, z, block);
} catch (FaweException e) {
handleException(e);
return false;
@ -494,9 +472,9 @@ public class LimitExtent extends AbstractDelegateExtent {
@Override
public boolean setTile(int x, int y, int z, CompoundTag tile) throws WorldEditException {
limit.THROW_MAX_CHANGES();
limit.MAX_BLOCKSTATES();
limit.THROW_MAX_BLOCKSTATES();
try {
return super.setTile(x, y, z, tile);
return extent.setTile(x, y, z, tile);
} catch (FaweException e) {
handleException(e);
return false;
@ -507,7 +485,7 @@ public class LimitExtent extends AbstractDelegateExtent {
public boolean setBiome(BlockVector3 position, BiomeType biome) {
limit.THROW_MAX_CHANGES();
try {
return super.setBiome(position, biome);
return extent.setBiome(position, biome);
} catch (FaweException e) {
handleException(e);
return false;
@ -518,11 +496,41 @@ public class LimitExtent extends AbstractDelegateExtent {
public boolean setBiome(int x, int y, int z, BiomeType biome) {
limit.THROW_MAX_CHANGES();
try {
return super.setBiome(x, y, z, biome);
return extent.setBiome(x, y, z, biome);
} catch (FaweException e) {
handleException(e);
return false;
}
}
public void setProcessing(boolean processing) {
this.processing = processing;
}
@Override
public IChunkSet processSet(IChunk chunk, IChunkGet get, IChunkSet set) {
if (!processing) {
return set;
}
int tiles = set.tiles().size();
int ents = set.entities().size() + set.getEntityRemoves().size();
limit.THROW_MAX_CHANGES(tiles + ents);
limit.THROW_MAX_BLOCKSTATES(tiles);
limit.THROW_MAX_ENTITIES(ents);
return set;
}
@Override
public Extent construct(final Extent child) {
if (extent != child) {
new ExtentTraverser<Extent>(this).setNext(child);
}
return this;
}
@Override
public ProcessorScope getScope() {
return ProcessorScope.READING_SET_BLOCKS;
}
}

View File

@ -2,14 +2,12 @@ package com.fastasyncworldedit.core.extent;
import com.fastasyncworldedit.core.extent.processor.ProcessorScope;
import com.fastasyncworldedit.core.math.BlockVector3ChunkMap;
import com.fastasyncworldedit.core.nbt.FaweCompoundTag;
import com.fastasyncworldedit.core.queue.IBatchProcessor;
import com.fastasyncworldedit.core.queue.IChunk;
import com.fastasyncworldedit.core.queue.IChunkGet;
import com.fastasyncworldedit.core.queue.IChunkSet;
import com.fastasyncworldedit.core.util.ExtentTraverser;
import com.google.common.collect.ImmutableMap;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.jnbt.Tag;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.entity.BaseEntity;
import com.sk89q.worldedit.entity.Entity;
@ -20,16 +18,17 @@ import com.sk89q.worldedit.util.Location;
import com.sk89q.worldedit.world.NbtValued;
import com.sk89q.worldedit.world.block.BaseBlock;
import com.sk89q.worldedit.world.block.BlockStateHolder;
import org.enginehub.linbus.tree.LinCompoundTag;
import org.enginehub.linbus.tree.LinTag;
import javax.annotation.Nullable;
import java.util.HashMap;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.stream.Collectors;
public class StripNBTExtent extends AbstractDelegateExtent implements IBatchProcessor {
@ -75,79 +74,82 @@ public class StripNBTExtent extends AbstractDelegateExtent implements IBatchProc
if (!(block instanceof BaseBlock localBlock)) {
return block;
}
if (!localBlock.hasNbtData()) {
final LinCompoundTag nbt = localBlock.getNbt();
if (nbt == null) {
return block;
}
CompoundTag nbt = localBlock.getNbtData();
Map<String, Tag<?, ?>> value = new HashMap<>(nbt.getValue());
LinCompoundTag.Builder nbtBuilder = nbt.toBuilder();
for (String key : strip) {
value.remove(key);
nbtBuilder.remove(key);
}
return (B) localBlock.toBaseBlock(new CompoundTag(value));
return (B) localBlock.toBaseBlock(nbtBuilder.build());
}
public <T extends NbtValued> T stripEntityNBT(T entity) {
if (!entity.hasNbtData()) {
LinCompoundTag nbt = entity.getNbt();
if (nbt == null) {
return entity;
}
CompoundTag nbt = entity.getNbtData();
Map<String, Tag<?, ?>> value = new HashMap<>(nbt.getValue());
LinCompoundTag.Builder nbtBuilder = nbt.toBuilder();
for (String key : strip) {
value.remove(key);
nbtBuilder.remove(key);
}
entity.setNbtData(new CompoundTag(value));
entity.setNbt(nbtBuilder.build());
return entity;
}
@Override
public IChunkSet processSet(final IChunk chunk, final IChunkGet get, final IChunkSet set) {
Map<BlockVector3, CompoundTag> tiles = set.getTiles();
Set<CompoundTag> entities = set.getEntities();
Map<BlockVector3, FaweCompoundTag> tiles = set.tiles();
Collection<FaweCompoundTag> entities = set.entities();
if (tiles.isEmpty() && entities.isEmpty()) {
return set;
}
boolean isBv3ChunkMap = tiles instanceof BlockVector3ChunkMap;
for (final Map.Entry<BlockVector3, CompoundTag> entry : tiles.entrySet()) {
ImmutableMap.Builder<String, Tag<?, ?>> map = ImmutableMap.builder();
final AtomicBoolean isStripped = new AtomicBoolean(false);
entry.getValue().getValue().forEach((k, v) -> {
if (strip.contains(k.toLowerCase())) {
isStripped.set(true);
} else {
map.put(k, v);
}
});
if (isStripped.get()) {
for (final var entry : tiles.entrySet()) {
FaweCompoundTag original = entry.getValue();
FaweCompoundTag result = stripNbt(original);
if (original != result) {
if (isBv3ChunkMap) {
// Replace existing value with stripped value
tiles.put(entry.getKey(), new CompoundTag(map.build()));
tiles.put(entry.getKey(), result);
} else {
entry.setValue(new CompoundTag(map.build()));
entry.setValue(result);
}
}
}
Set<CompoundTag> stripped = new HashSet<>();
Iterator<CompoundTag> iterator = entities.iterator();
Set<FaweCompoundTag> stripped = new HashSet<>();
Iterator<FaweCompoundTag> iterator = entities.iterator();
while (iterator.hasNext()) {
CompoundTag entity = iterator.next();
ImmutableMap.Builder<String, Tag<?, ?>> map = ImmutableMap.builder();
final AtomicBoolean isStripped = new AtomicBoolean(false);
entity.getValue().forEach((k, v) -> {
if (strip.contains(k.toUpperCase(Locale.ROOT))) {
isStripped.set(true);
} else {
map.put(k, v);
}
});
if (isStripped.get()) {
FaweCompoundTag original = iterator.next();
FaweCompoundTag result = stripNbt(original);
if (original != result) {
iterator.remove();
stripped.add(new CompoundTag(map.build()));
stripped.add(result);
}
}
set.getEntities().addAll(stripped);
// this relies on entities.addAll(...) not throwing an exception if empty+unmodifiable (=> stripped is empty too)
entities.addAll(stripped);
return set;
}
private FaweCompoundTag stripNbt(
FaweCompoundTag compoundTag
) {
LinCompoundTag.Builder builder = LinCompoundTag.builder();
boolean stripped = false;
for (var entry : compoundTag.linTag().value().entrySet()) {
String k = entry.getKey();
LinTag<?> v = entry.getValue();
if (strip.contains(k.toLowerCase(Locale.ROOT))) {
stripped = true;
} else {
builder.put(k, v);
}
}
return stripped ? FaweCompoundTag.of(builder.build()) : compoundTag;
}
@Nullable
@Override
public Extent construct(final Extent child) {

View File

@ -2,9 +2,11 @@ package com.fastasyncworldedit.core.extent.clipboard;
import com.fastasyncworldedit.core.jnbt.streamer.IntValueReader;
import com.fastasyncworldedit.core.math.IntTriple;
import com.fastasyncworldedit.core.nbt.FaweCompoundTag;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.jnbt.IntTag;
import com.sk89q.jnbt.Tag;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.world.biome.BiomeType;
@ -175,6 +177,12 @@ public class CPUOptimizedClipboard extends LinearClipboard {
return true;
}
@Override
public boolean tile(final int x, final int y, final int z, final FaweCompoundTag tile) throws WorldEditException {
// TODO replace
return setTile(x, y, z, new CompoundTag(tile.linTag()));
}
private boolean setTile(int index, CompoundTag tag) {
final Map<String, Tag<?, ?>> values = new HashMap<>(tag.getValue());
values.remove("x");

View File

@ -6,15 +6,18 @@ import com.fastasyncworldedit.core.internal.exception.FaweClipboardVersionMismat
import com.fastasyncworldedit.core.internal.io.ByteBufferInputStream;
import com.fastasyncworldedit.core.jnbt.streamer.IntValueReader;
import com.fastasyncworldedit.core.math.IntTriple;
import com.fastasyncworldedit.core.nbt.FaweCompoundTag;
import com.fastasyncworldedit.core.util.MainUtil;
import com.fastasyncworldedit.core.util.NbtUtils;
import com.fastasyncworldedit.core.util.ReflectionUtils;
import com.google.common.collect.Collections2;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.jnbt.DoubleTag;
import com.sk89q.jnbt.IntTag;
import com.sk89q.jnbt.ListTag;
import com.sk89q.jnbt.NBTInputStream;
import com.sk89q.jnbt.NBTOutputStream;
import com.sk89q.jnbt.Tag;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.entity.BaseEntity;
import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard;
import com.sk89q.worldedit.internal.util.LogManagerCompat;
@ -28,6 +31,8 @@ import com.sk89q.worldedit.world.block.BlockStateHolder;
import com.sk89q.worldedit.world.block.BlockTypes;
import com.sk89q.worldedit.world.block.BlockTypesCache;
import org.apache.logging.log4j.Logger;
import org.enginehub.linbus.tree.LinCompoundTag;
import org.enginehub.linbus.tree.LinTagType;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
@ -64,7 +69,7 @@ public class DiskOptimizedClipboard extends LinearClipboard {
private static final int VERSION_2_HEADER_SIZE = 27; // Header size of "version 2" i.e. when NBT/entities could be saved
private static final Map<String, LockHolder> LOCK_HOLDER_CACHE = new ConcurrentHashMap<>();
private final HashMap<IntTriple, CompoundTag> nbtMap;
private final HashMap<IntTriple, FaweCompoundTag> nbtMap;
private final File file;
private final int headerSize;
@ -248,12 +253,12 @@ public class DiskOptimizedClipboard extends LinearClipboard {
try (NBTInputStream nbtIS = new NBTInputStream(MainUtil.getCompressedIS(new ByteBufferInputStream(tmp)))) {
Iterator<CompoundTag> iter = nbtIS.toIterator();
while (nbtCount > 0 && iter.hasNext()) { // TileEntities are stored "before" entities
CompoundTag tag = iter.next();
int x = tag.getInt("x");
int y = tag.getInt("y");
int z = tag.getInt("z");
LinCompoundTag tag = iter.next().toLinTag();
int x = tag.getTag("x", LinTagType.intTag()).valueAsInt();
int y = tag.getTag("y", LinTagType.intTag()).valueAsInt();
int z = tag.getTag("z", LinTagType.intTag()).valueAsInt();
IntTriple pos = new IntTriple(x, y, z);
nbtMap.put(pos, tag);
nbtMap.put(pos, FaweCompoundTag.of(tag));
nbtCount--;
}
while (entitiesCount > 0 && iter.hasNext()) {
@ -559,8 +564,8 @@ public class DiskOptimizedClipboard extends LinearClipboard {
))) {
if (!nbtMap.isEmpty()) {
try {
for (CompoundTag tag : nbtMap.values()) {
nbtOS.writeTag(tag);
for (FaweCompoundTag tag : nbtMap.values()) {
nbtOS.writeTag(new CompoundTag(tag.linTag()));
}
} catch (IOException e) {
e.printStackTrace();
@ -638,7 +643,7 @@ public class DiskOptimizedClipboard extends LinearClipboard {
@Override
public Collection<CompoundTag> getTileEntities() {
return nbtMap.values();
return Collections2.transform(nbtMap.values(), fct -> new CompoundTag(fct.linTag()));
}
public int getIndex(int x, int y, int z) {
@ -656,10 +661,10 @@ public class DiskOptimizedClipboard extends LinearClipboard {
private BaseBlock toBaseBlock(BlockState state, int i) {
if (state.getMaterial().hasContainer() && !nbtMap.isEmpty()) {
CompoundTag nbt;
FaweCompoundTag nbt;
if (nbtMap.size() < 4) {
nbt = null;
for (Map.Entry<IntTriple, CompoundTag> entry : nbtMap.entrySet()) {
for (Map.Entry<IntTriple, FaweCompoundTag> entry : nbtMap.entrySet()) {
IntTriple key = entry.getKey();
int index = getIndex(key.x(), key.y(), key.z());
if (index == i) {
@ -674,15 +679,15 @@ public class DiskOptimizedClipboard extends LinearClipboard {
int x = newI - z * getWidth();
nbt = nbtMap.get(new IntTriple(x, y, z));
}
return state.toBaseBlock(nbt);
return state.toBaseBlock(nbt == null ? null : nbt.linTag());
}
return state.toBaseBlock();
}
private BaseBlock toBaseBlock(BlockState state, int x, int y, int z) {
if (state.getMaterial().hasContainer() && !nbtMap.isEmpty()) {
CompoundTag nbt = nbtMap.get(new IntTriple(x, y, z));
return state.toBaseBlock(nbt);
FaweCompoundTag nbt = nbtMap.get(new IntTriple(x, y, z));
return state.toBaseBlock(nbt == null ? null : nbt.linTag());
}
return state.toBaseBlock();
}
@ -709,12 +714,8 @@ public class DiskOptimizedClipboard extends LinearClipboard {
}
@Override
public boolean setTile(int x, int y, int z, CompoundTag tag) {
final Map<String, Tag<?, ?>> values = new HashMap<>(tag.getValue());
values.put("x", new IntTag(x));
values.put("y", new IntTag(y));
values.put("z", new IntTag(z));
nbtMap.put(new IntTriple(x, y, z), new CompoundTag(values));
public boolean tile(final int x, final int y, final int z, final FaweCompoundTag tile) throws WorldEditException {
nbtMap.put(new IntTriple(x, y, z), NbtUtils.withPosition(tile, x, y, z));
return true;
}

View File

@ -1,7 +1,7 @@
package com.fastasyncworldedit.core.extent.clipboard;
import com.fastasyncworldedit.core.extent.processor.heightmap.HeightMapType;
import com.sk89q.jnbt.CompoundTag;
import com.fastasyncworldedit.core.nbt.FaweCompoundTag;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.entity.Entity;
import com.sk89q.worldedit.extent.clipboard.Clipboard;
@ -84,7 +84,8 @@ public final class EmptyClipboard implements Clipboard {
return false;
}
public boolean setTile(int x, int y, int z, @Nonnull CompoundTag tile) throws WorldEditException {
@Override
public boolean tile(final int x, final int y, final int z, final FaweCompoundTag tile) throws WorldEditException {
return false;
}

View File

@ -57,6 +57,10 @@ public abstract class LinearClipboard extends SimpleClipboard {
*/
public abstract void streamBiomes(IntValueReader task);
/**
* @deprecated will be removed as it is unused and uses outdated types
*/
@Deprecated(forRemoval = true, since = "TODO")
public abstract Collection<CompoundTag> getTileEntities();
@Override

View File

@ -3,10 +3,12 @@ package com.fastasyncworldedit.core.extent.clipboard;
import com.fastasyncworldedit.core.configuration.Settings;
import com.fastasyncworldedit.core.jnbt.streamer.IntValueReader;
import com.fastasyncworldedit.core.math.IntTriple;
import com.fastasyncworldedit.core.nbt.FaweCompoundTag;
import com.fastasyncworldedit.core.util.MainUtil;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.jnbt.IntTag;
import com.sk89q.jnbt.Tag;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.world.biome.BiomeType;
@ -262,6 +264,12 @@ public class MemoryOptimizedClipboard extends LinearClipboard {
return true;
}
@Override
public boolean tile(final int x, final int y, final int z, final FaweCompoundTag tile) throws WorldEditException {
// TODO replace
return setTile(x, y, z, new CompoundTag(tile.linTag()));
}
@Override
public <B extends BlockStateHolder<B>> boolean setBlock(int x, int y, int z, B block) {
return setBlock(getIndex(x, y, z), block);

View File

@ -1,7 +1,7 @@
package com.fastasyncworldedit.core.extent.clipboard;
import com.fastasyncworldedit.core.Fawe;
import com.sk89q.jnbt.CompoundTag;
import com.fastasyncworldedit.core.nbt.FaweCompoundTag;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.entity.BaseEntity;
import com.sk89q.worldedit.entity.Entity;
@ -106,7 +106,7 @@ public abstract class ReadOnlyClipboard extends SimpleClipboard {
}
@Override
public boolean setTile(int x, int y, int z, CompoundTag tag) {
public boolean tile(int x, int y, int z, FaweCompoundTag tag) {
throw new UnsupportedOperationException("Clipboard is immutable");
}

View File

@ -58,6 +58,9 @@ public class ResizableClipboardBuilder extends MemoryOptimizedHistory {
}
public Clipboard build() {
if (longSize() == 0) {
return EmptyClipboard.getInstance();
}
BlockVector3 pos1 = BlockVector3.at(minX, minY, minZ);
BlockVector3 pos2 = BlockVector3.at(maxX, maxY, maxZ);
CuboidRegion region = new CuboidRegion(pos1, pos2);

View File

@ -5,6 +5,7 @@ import com.fastasyncworldedit.core.extent.clipboard.SimpleClipboard;
import com.fastasyncworldedit.core.internal.io.ResettableFileInputStream;
import com.fastasyncworldedit.core.internal.io.VarIntStreamIterator;
import com.fastasyncworldedit.core.math.MutableBlockVector3;
import com.fastasyncworldedit.core.nbt.FaweCompoundTag;
import com.fastasyncworldedit.core.util.IOUtil;
import com.fastasyncworldedit.core.util.MathMan;
import com.sk89q.jnbt.CompoundTag;
@ -40,6 +41,8 @@ import org.apache.logging.log4j.Logger;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.enginehub.linbus.tree.LinCompoundTag;
import org.enginehub.linbus.tree.LinIntArrayTag;
import org.enginehub.linbus.tree.LinTagType;
import org.jetbrains.annotations.ApiStatus;
import java.io.BufferedInputStream;
@ -87,6 +90,7 @@ public class FastSchematicReaderV3 implements ClipboardReader {
private VersionedDataFixer dataFixer;
private BlockVector3 offset;
private BlockVector3 origin = BlockVector3.ZERO;
private BlockState[] blockPalette;
private BiomeType[] biomePalette;
private int dataVersion = -1;
@ -136,6 +140,24 @@ public class FastSchematicReaderV3 implements ClipboardReader {
this.dataVersion = this.dataInputStream.readInt();
this.dataFixer = ReaderUtil.getVersionedDataFixer(this.dataVersion, platform, platform.getDataVersion());
}
case "Metadata" -> {
LinCompoundTag metadataCompoundTag =
(LinCompoundTag) this.nbtInputStream.readTagPayload(NBTConstants.TYPE_COMPOUND, 0).toLinTag();
LinCompoundTag worldEditTag = metadataCompoundTag.findTag("WorldEdit", LinTagType.compoundTag());
if (worldEditTag != null) { // allowed to be optional
LinIntArrayTag originTag = worldEditTag.findTag("Origin", LinTagType.intArrayTag());
if (originTag != null) { // allowed to be optional
int[] parts = originTag.value();
if (parts.length != 3) {
throw new IOException("`Metadata > WorldEdit > Origin` int array length is invalid.");
}
this.origin = BlockVector3.at(parts[0], parts[1], parts[2]);
}
}
}
case "Offset" -> {
this.dataInputStream.skipNBytes(4); // Array Length field (4 byte int)
this.offset = BlockVector3.at(
@ -172,7 +194,7 @@ public class FastSchematicReaderV3 implements ClipboardReader {
clipboard.setOrigin(this.offset.multiply(-1));
if (clipboard instanceof SimpleClipboard simpleClipboard && !this.offset.equals(BlockVector3.ZERO)) {
clipboard = new BlockArrayClipboard(simpleClipboard, this.offset);
clipboard = new BlockArrayClipboard(simpleClipboard, this.offset.add(this.origin));
}
return clipboard;
}
@ -626,12 +648,11 @@ public class FastSchematicReaderV3 implements ClipboardReader {
}
private EntityTransformer provideTileEntityTransformer(Clipboard clipboard) {
//noinspection deprecation
return (x, y, z, id, tag) -> clipboard.setTile(
return (x, y, z, id, tag) -> clipboard.tile(
MathMan.roundInt(x + clipboard.getMinimumPoint().x()),
MathMan.roundInt(y + clipboard.getMinimumPoint().y()),
MathMan.roundInt(z + clipboard.getMinimumPoint().z()),
new CompoundTag(tag)
FaweCompoundTag.of(tag)
);
}

View File

@ -1,8 +1,10 @@
package com.fastasyncworldedit.core.extent.filter;
import com.fastasyncworldedit.core.extent.filter.block.FilterBlock;
import com.fastasyncworldedit.core.internal.simd.VectorizedFilter;
import jdk.incubator.vector.ShortVector;
public class CountFilter extends ForkedFilter<CountFilter> {
public class CountFilter extends ForkedFilter<CountFilter> implements VectorizedFilter {
private int total;
@ -33,4 +35,10 @@ public class CountFilter extends ForkedFilter<CountFilter> {
return total;
}
@Override
public ShortVector applyVector(final ShortVector get, final ShortVector set) {
total += set.length();
return set;
}
}

View File

@ -1,37 +1,92 @@
package com.fastasyncworldedit.core.extent.filter;
import com.fastasyncworldedit.core.extent.filter.block.DelegateFilter;
import com.fastasyncworldedit.core.extent.filter.block.FilterBlock;
import com.fastasyncworldedit.core.internal.simd.VectorizedFilter;
import com.fastasyncworldedit.core.queue.Filter;
import com.fastasyncworldedit.core.queue.IChunk;
import com.sk89q.worldedit.regions.Region;
import jdk.incubator.vector.ShortVector;
import org.jetbrains.annotations.Nullable;
/**
* Filter which links two Filters together for single-filter-input operations.
* Filter which links two Filters together for single-filter-input operations. Left filter is operated first.
*
* @param <T> Parent which extends Filter
* @param <S> Child which extends Filter
* @param <L> Left filter
* @param <R> Right filter
*/
public final class LinkedFilter<T extends Filter, S extends Filter> extends DelegateFilter<T> {
public sealed class LinkedFilter<L extends Filter, R extends Filter> implements Filter {
private final S child;
private final L left;
private final R right;
public LinkedFilter(T parent, S child) {
super(parent);
this.child = child;
public LinkedFilter(L left, R right) {
this.left = left;
this.right = right;
}
public S getChild() {
return this.child;
@SuppressWarnings({"unchecked", "rawtypes"}) // we defeated the type system
public static <L extends Filter, R extends Filter> LinkedFilter<? extends L, ? extends R> of(L left, R right) {
if (left instanceof VectorizedFilter l && right instanceof VectorizedFilter r) {
return new VectorizedLinkedFilter(l, r);
}
return new LinkedFilter<>(left, right);
}
public L getLeft() {
return this.left;
}
public R getRight() {
return this.right;
}
@Override
public <T extends IChunk> T applyChunk(T chunk, @Nullable Region region) {
chunk = getLeft().applyChunk(chunk, region);
return getRight().applyChunk(chunk, region);
}
@Override
public void applyBlock(FilterBlock block) {
this.getParent().applyBlock(block);
this.getChild().applyBlock(block);
getLeft().applyBlock(block);
getRight().applyBlock(block);
}
@Override
public LinkedFilter<LinkedFilter<T, S>, Filter> newInstance(Filter other) {
return new LinkedFilter<>(this, other);
public void finishChunk(IChunk chunk) {
getLeft().finishChunk(chunk);
getRight().finishChunk(chunk);
}
@Override
public Filter fork() {
return new LinkedFilter<>(getLeft().fork(), getRight().fork());
}
@Override
public void join() {
getLeft().join();
getRight().join();
}
private final static class VectorizedLinkedFilter<L extends VectorizedFilter, R extends VectorizedFilter>
extends LinkedFilter<L, R> implements VectorizedFilter {
public VectorizedLinkedFilter(final L left, final R right) {
super(left, right);
}
@Override
public ShortVector applyVector(final ShortVector get, final ShortVector set) {
ShortVector res = getLeft().applyVector(get, set);
return getRight().applyVector(get, res);
}
@Override
public Filter fork() {
return new VectorizedLinkedFilter<>((L) getLeft().fork(), (R) getRight().fork());
}
}
}

View File

@ -2,10 +2,17 @@ package com.fastasyncworldedit.core.extent.filter;
import com.fastasyncworldedit.core.extent.filter.block.DelegateFilter;
import com.fastasyncworldedit.core.extent.filter.block.FilterBlock;
import com.fastasyncworldedit.core.internal.simd.SimdSupport;
import com.fastasyncworldedit.core.internal.simd.VectorizedFilter;
import com.fastasyncworldedit.core.internal.simd.VectorizedMask;
import com.fastasyncworldedit.core.queue.Filter;
import com.sk89q.worldedit.function.mask.AbstractExtentMask;
import com.sk89q.worldedit.function.mask.Mask;
import jdk.incubator.vector.ShortVector;
import jdk.incubator.vector.VectorMask;
import jdk.incubator.vector.VectorOperators;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicInteger;
/**
@ -15,8 +22,8 @@ import java.util.concurrent.atomic.AtomicInteger;
*/
public class MaskFilter<T extends Filter> extends DelegateFilter<T> {
private final Mask mask;
private final AtomicInteger changes;
final Mask mask;
final AtomicInteger changes;
public MaskFilter(T other, Mask root) {
this(other, root, new AtomicInteger());
@ -60,4 +67,45 @@ public class MaskFilter<T extends Filter> extends DelegateFilter<T> {
return new MaskFilter<>(getParent().fork(), mask.copy(), changes);
}
public static class VectorizedMaskFilter<T extends VectorizedFilter> extends MaskFilter<T> implements VectorizedFilter {
private final VectorizedMask vectorizedMask;
public VectorizedMaskFilter(final T other, final Mask root) {
super(other, root);
this.vectorizedMask = Objects.requireNonNull(SimdSupport.vectorizedTargetMask(root), "invalid vectorizable mask");
}
public VectorizedMaskFilter(final T other, final Mask root, AtomicInteger changes) {
super(other, root, changes);
this.vectorizedMask = Objects.requireNonNull(SimdSupport.vectorizedTargetMask(root), "invalid vectorizable mask");
}
@Override
public ShortVector applyVector(final ShortVector get, final ShortVector set) {
final T parent = getParent();
VectorMask<Short> masked = vectorizedMask.compareVector(set, get);
ShortVector res = parent.applyVector(get, set);
res = set.blend(res, masked);
VectorMask<Short> changed = res.compare(VectorOperators.NE, set);
changes.getAndAdd(changed.trueCount());
return res;
}
@Override
public MaskFilter<?> newInstance(final Filter other) {
if (other instanceof VectorizedFilter o) {
return new VectorizedMaskFilter<>(o, mask);
}
return super.newInstance(other);
}
@SuppressWarnings("unchecked")
@Override
public Filter fork() {
return new VectorizedMaskFilter<>((T) getParent().fork(), mask.copy(), changes);
}
}
}

View File

@ -1,5 +1,6 @@
package com.fastasyncworldedit.core.extent.filter.block;
import com.fastasyncworldedit.core.nbt.FaweCompoundTag;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.extent.Extent;
@ -105,6 +106,11 @@ public class ArrayFilterBlock extends AbstractExtentFilterBlock {
return getExtent().setBlock(x, y, z, block);
}
@Override
public boolean tile(final int x, final int y, final int z, final FaweCompoundTag tile) throws WorldEditException {
return false; // class is unused + deprecated, do not care about impl
}
@Override
public boolean setBiome(int x, int y, int z, BiomeType biome) {
return getExtent().setBiome(x, y, z, biome);

View File

@ -1,6 +1,7 @@
package com.fastasyncworldedit.core.extent.filter.block;
import com.fastasyncworldedit.core.FaweCache;
import com.fastasyncworldedit.core.nbt.FaweCompoundTag;
import com.fastasyncworldedit.core.queue.Filter;
import com.fastasyncworldedit.core.queue.FilterBlockMask;
import com.fastasyncworldedit.core.queue.IBlocks;
@ -8,11 +9,11 @@ import com.fastasyncworldedit.core.queue.IChunkGet;
import com.fastasyncworldedit.core.queue.IChunkSet;
import com.fastasyncworldedit.core.queue.implementation.Flood;
import com.fastasyncworldedit.core.queue.implementation.blocks.CharGetBlocks;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.util.concurrency.LazyReference;
import com.sk89q.worldedit.world.biome.BiomeType;
import com.sk89q.worldedit.world.block.BaseBlock;
import com.sk89q.worldedit.world.block.BlockState;
@ -20,12 +21,15 @@ import com.sk89q.worldedit.world.block.BlockStateHolder;
import com.sk89q.worldedit.world.block.BlockTypes;
import com.sk89q.worldedit.world.block.BlockTypesCache;
import com.sk89q.worldedit.world.registry.BlockMaterial;
import org.enginehub.linbus.tree.LinCompoundTag;
import org.jetbrains.annotations.ApiStatus;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import static com.sk89q.worldedit.world.block.BlockTypesCache.states;
@ApiStatus.NonExtendable
public class CharFilterBlock extends ChunkFilterBlock {
private static final SetDelegate FULL = (block, value) -> block.setArr[block.index] = value;
@ -35,10 +39,10 @@ public class CharFilterBlock extends ChunkFilterBlock {
private int minLayer;
private CharGetBlocks get;
private IChunkSet set;
private char[] getArr;
protected char[] getArr;
@Nullable
private char[] setArr;
private SetDelegate delegate;
protected char[] setArr;
protected SetDelegate delegate;
// local
private int layer;
private int index;
@ -169,7 +173,7 @@ public class CharFilterBlock extends ChunkFilterBlock {
}
@Override
public synchronized final void filter(Filter filter) {
public synchronized void filter(Filter filter) {
for (y = 0, index = 0; y < 16; y++) {
for (z = 0; z < 16; z++) {
for (x = 0; x < 16; x++, index++) {
@ -259,8 +263,8 @@ public class CharFilterBlock extends ChunkFilterBlock {
final BlockState state = getBlock();
final BlockMaterial material = state.getMaterial();
if (material.hasContainer()) {
final CompoundTag tag = get.getTile(x, y + yy, z);
return state.toBaseBlock(tag);
final FaweCompoundTag tag = get.tile(x, y + yy, z);
return state.toBaseBlock(tag == null ? null : tag.linTag());
}
return state.toBaseBlock();
}
@ -268,16 +272,28 @@ public class CharFilterBlock extends ChunkFilterBlock {
@Override
public void setFullBlock(BaseBlock block) {
delegate.set(this, block.getOrdinalChar());
final CompoundTag nbt = block.getNbtData();
final LazyReference<LinCompoundTag> nbt = block.getNbtReference();
if (nbt != null) { // TODO optimize check via ImmutableBaseBlock
set.setTile(x, yy + y, z, nbt);
set.tile(x, yy + y, z, FaweCompoundTag.of(nbt));
}
}
@Override
public final CompoundTag getNbtData() {
return get.getTile(x, y + yy, z);
public @Nullable LinCompoundTag getNbt() {
final FaweCompoundTag tile = get.tile(x, y + yy, z);
if (tile == null) {
return null;
}
return tile.linTag();
}
@Override
public void setNbt(@Nullable final LinCompoundTag nbtData) {
if (nbtData != null) {
set.tile(x, y + yy, z, FaweCompoundTag.of(nbtData));
}
}
/*
NORTH(Vector3.at(0, 0, -1), Flag.CARDINAL, 3, 1),
EAST(Vector3.at(1, 0, 0), Flag.CARDINAL, 0, 2),
@ -286,9 +302,9 @@ public class CharFilterBlock extends ChunkFilterBlock {
*/
@Override
public void setNbtData(CompoundTag tag) {
if (tag != null) {
set.setTile(x, y + yy, z, tag);
public void setNbtReference(@Nullable final LazyReference<LinCompoundTag> nbtData) {
if (nbtData != null) {
set.tile(x, y + yy, z, FaweCompoundTag.of(nbtData));
}
}
@ -380,7 +396,7 @@ public class CharFilterBlock extends ChunkFilterBlock {
}
//Set delegate
private SetDelegate initSet() {
protected final SetDelegate initSet() {
setArr = set.load(layer);
return delegate = FULL;
}
@ -412,7 +428,8 @@ public class CharFilterBlock extends ChunkFilterBlock {
return getExtent().setBiome(x, y, z, biome);
}
private interface SetDelegate {
@ApiStatus.Internal
protected interface SetDelegate {
void set(@Nonnull CharFilterBlock block, char value);

View File

@ -83,12 +83,20 @@ public abstract class ChunkFilterBlock extends AbstractExtentFilterBlock {
/**
* Filter a chunk with a region / filter.
*/
public synchronized final IChunkSet filter(IChunk chunk, IChunkGet get, IChunkSet set, Filter filter, Region region, boolean full) {
public synchronized final IChunkSet filter(
IChunk chunk,
IChunkGet get,
IChunkSet set,
Filter filter,
Region region,
boolean full
) {
if (region != null) {
region.filter(chunk, filter, this, get, set, full);
} else {
for (int layer = get.getMinSectionPosition(); layer <= get.getMaxSectionPosition(); layer++) {
if ((!full && !get.hasSection(layer)) || !filter.appliesLayer(chunk, layer)) {
//if ((!full && !get.hasSection(layer)) || !filter.appliesLayer(chunk, layer)) {
if (!full && !get.hasSection(layer)) {
continue;
}
initLayer(get, set, layer);

View File

@ -1,5 +1,6 @@
package com.fastasyncworldedit.core.extent.filter.block;
import com.fastasyncworldedit.core.nbt.FaweCompoundTag;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.blocks.TileEntityBlock;
@ -35,17 +36,6 @@ public abstract class FilterBlock extends BlockVector3 implements Extent, TileEn
public abstract BiomeType getBiome();
@Override
public abstract CompoundTag getNbtData();
@Override
public abstract void setNbtData(@Nullable CompoundTag nbtData);
@Override
public boolean hasNbtData() {
return getNbtData() != null;
}
@Override
public BlockVector3 getMinimumPoint() {
return getExtent().getMinimumPoint();
@ -61,10 +51,9 @@ public abstract class FilterBlock extends BlockVector3 implements Extent, TileEn
return getExtent().getBlock(x, y, z);
}
@Override
public boolean setTile(int x, int y, int z, CompoundTag tile) throws WorldEditException {
return getExtent().setTile(x, y, z, tile);
public boolean tile(final int x, final int y, final int z, final FaweCompoundTag tile) throws WorldEditException {
return getExtent().tile(x, y, z, tile);
}
@Override

View File

@ -26,7 +26,7 @@ public abstract class ABlockMask extends AbstractExtentMask {
@Override
public boolean test(BlockVector3 vector) {
return test(getExtent().getBlock(vector));
return test(vector.getBlock(getExtent()));
}
public abstract boolean test(BlockState state);

View File

@ -16,9 +16,9 @@ public class DataMask extends AbstractExtentMask implements ResettableMask {
@Override
public boolean test(BlockVector3 vector) {
if (data != -1) {
return getExtent().getBlock(vector).getInternalPropertiesId() == data;
return vector.getBlock(getExtent()).getInternalPropertiesId() == data;
} else {
data = getExtent().getBlock(vector).getInternalPropertiesId();
data = vector.getBlock(getExtent()).getInternalPropertiesId();
return true;
}
}

View File

@ -24,7 +24,9 @@ public class IdMask extends AbstractExtentMask implements ResettableMask {
@Override
public boolean test(BlockVector3 vector) {
return test(getExtent(), vector);
int blockID = vector.getBlock(getExtent()).getInternalBlockTypeId();
int testId = id.compareAndExchange(-1, blockID);
return blockID == testId || testId == -1;
}
@Override

View File

@ -30,7 +30,7 @@ public class SingleBlockStateMask extends ABlockMask {
@Override
public boolean test(BlockVector3 vector) {
int test = getExtent().getBlock(vector).getOrdinal();
int test = vector.getBlock(getExtent()).getOrdinal();
return ordinal == test || isAir && test == 0;
}

View File

@ -40,7 +40,7 @@ public class SplatterBrushMask extends AbstractExtentMask {
double dist = vector.distanceSq(position);
synchronized (placed) {
if (dist < size2 && !placed.contains(vector) && ThreadLocalRandom.current().nextInt(5) < 2 && surface.test(vector)) {
placed.add(vector);
placed.add(vector.toImmutable());
return true;
}
}

View File

@ -0,0 +1,65 @@
package com.fastasyncworldedit.core.history.change;
import com.sk89q.worldedit.history.change.Change;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* @since 2.11.2
*/
@ApiStatus.Internal
public interface ChangePopulator<C extends Change> {
static <C extends Change> ChangePopulator<C> empty() {
class Empty implements ChangePopulator<C> {
private static final Empty EMPTY = new Empty();
@Override
public @NotNull C create() {
throw new UnsupportedOperationException("empty");
}
@Override
public @Nullable C populate(@NotNull final C change) {
return null;
}
@Override
public @Nullable C updateOrCreate(@Nullable final Change change) {
return null;
}
@Override
public boolean accepts(final Change change) {
return false;
}
}
return Empty.EMPTY;
}
@SuppressWarnings("unchecked")
default @NotNull C update(@Nullable Change before) {
if (accepts(before)) {
return (C) before;
}
return create();
}
@NotNull
C create();
@Nullable
default C updateOrCreate(@Nullable Change change) {
C u = update(change);
return populate(u);
}
@Nullable
C populate(@NotNull C change);
@Contract("null->false")
boolean accepts(Change change);
}

View File

@ -4,11 +4,12 @@ import com.fastasyncworldedit.core.Fawe;
import com.fastasyncworldedit.core.FaweCache;
import com.fastasyncworldedit.core.extent.HistoryExtent;
import com.fastasyncworldedit.core.extent.processor.ProcessorScope;
import com.fastasyncworldedit.core.nbt.FaweCompoundTag;
import com.fastasyncworldedit.core.queue.IBatchProcessor;
import com.fastasyncworldedit.core.queue.IChunk;
import com.fastasyncworldedit.core.queue.IChunkGet;
import com.fastasyncworldedit.core.queue.IChunkSet;
import com.fastasyncworldedit.core.util.MainUtil;
import com.fastasyncworldedit.core.util.NbtUtils;
import com.fastasyncworldedit.core.util.TaskManager;
import com.google.common.util.concurrent.Futures;
import com.sk89q.jnbt.CompoundTag;
@ -32,8 +33,12 @@ import com.sk89q.worldedit.world.block.BaseBlock;
import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.block.BlockTypesCache;
import org.apache.logging.log4j.Logger;
import org.enginehub.linbus.tree.LinCompoundTag;
import org.jetbrains.annotations.ApiStatus;
import javax.annotation.Nonnull;
import java.io.IOException;
import java.util.Collection;
import java.util.Iterator;
import java.util.Map;
import java.util.Objects;
@ -122,37 +127,38 @@ public abstract class AbstractChangeSet implements ChangeSet, IBatchProcessor {
int bx = chunk.getX() << 4;
int bz = chunk.getZ() << 4;
Map<BlockVector3, CompoundTag> tilesFrom = get.getTiles();
Map<BlockVector3, CompoundTag> tilesTo = set.getTiles();
Map<BlockVector3, FaweCompoundTag> tilesFrom = get.tiles();
Map<BlockVector3, FaweCompoundTag> tilesTo = set.tiles();
if (!tilesFrom.isEmpty()) {
for (Map.Entry<BlockVector3, CompoundTag> entry : tilesFrom.entrySet()) {
for (Map.Entry<BlockVector3, FaweCompoundTag> entry : tilesFrom.entrySet()) {
BlockVector3 pos = entry.getKey();
BlockState fromBlock = get.getBlock(pos.x() & 15, pos.y(), pos.z() & 15);
BlockState toBlock = set.getBlock(pos.x() & 15, pos.y(), pos.z() & 15);
if (fromBlock != toBlock || tilesTo.containsKey(pos)) {
addTileRemove(MainUtil.setPosition(entry.getValue(), entry.getKey().x(), entry.getKey().y(),
entry.getKey().z()));
addTileRemove(NbtUtils.withPosition(entry.getValue(), entry.getKey().x(), entry.getKey().y(),
entry.getKey().z()
));
}
}
}
if (!tilesTo.isEmpty()) {
for (Map.Entry<BlockVector3, CompoundTag> entry : tilesTo.entrySet()) {
for (Map.Entry<BlockVector3, FaweCompoundTag> entry : tilesTo.entrySet()) {
BlockVector3 pos = entry.getKey();
addTileCreate(MainUtil.setPosition(entry.getValue(), pos.x() + bx, pos.y(), pos.z() + bz));
addTileCreate(NbtUtils.withPosition(entry.getValue(), pos.x() + bx, pos.y(), pos.z() + bz));
}
}
Set<UUID> entRemoves = set.getEntityRemoves();
if (!entRemoves.isEmpty()) {
for (UUID uuid : entRemoves) {
CompoundTag found = get.getEntity(uuid);
FaweCompoundTag found = get.entity(uuid);
if (found != null) {
addEntityRemove(found);
}
}
}
Set<CompoundTag> ents = set.getEntities();
Collection<FaweCompoundTag> ents = set.entities();
if (!ents.isEmpty()) {
for (CompoundTag tag : ents) {
for (FaweCompoundTag tag : ents) {
addEntityCreate(tag);
}
}
@ -203,9 +209,9 @@ public abstract class AbstractChangeSet implements ChangeSet, IBatchProcessor {
BiomeType[] biomeSection = biomes[layer - set.getMinSectionPosition()];
int index = 0;
int yy = layer << 4;
for (int y = 0; y < 16; y+= 4) {
for (int z = 0; z < 16; z+= 4) {
for (int x = 0; x < 16; x+= 4, index++) {
for (int y = 0; y < 16; y += 4) {
for (int z = 0; z < 16; z += 4) {
for (int x = 0; x < 16; x += 4, index++) {
BiomeType newBiome = biomeSection[index];
if (newBiome != null) {
BiomeType oldBiome = get.getBiomeType(x, yy + y, z);
@ -236,13 +242,62 @@ public abstract class AbstractChangeSet implements ChangeSet, IBatchProcessor {
return ProcessorScope.READING_SET_BLOCKS;
}
public abstract void addTileCreate(CompoundTag tag);
@Deprecated(forRemoval = true, since = "2.11.2")
public void addTileCreate(CompoundTag tag) {
addTileCreate(adapt(tag));
}
public abstract void addTileRemove(CompoundTag tag);
@SuppressWarnings({"deprecation"})
private static @Nonnull FaweCompoundTag adapt(CompoundTag tag) {
return FaweCompoundTag.of(tag.toLinTag());
}
public abstract void addEntityRemove(CompoundTag tag);
/**
* Creates a tile/block entity create change to this change set.
*
* @param tag the tile/block entity to add.
* @since 2.11.2
*/
public abstract void addTileCreate(FaweCompoundTag tag);
public abstract void addEntityCreate(CompoundTag tag);
@Deprecated(forRemoval = true, since = "2.11.2")
public void addTileRemove(CompoundTag tag) {
addTileRemove(adapt(tag));
}
/**
* Creates a tile/block entity remove change to this change set.
*
* @param tag the tile/block entity to remove.
* @since 2.11.2
*/
public abstract void addTileRemove(FaweCompoundTag tag);
@Deprecated(forRemoval = true, since = "2.11.2")
public void addEntityRemove(CompoundTag tag) {
addEntityRemove(adapt(tag));
}
/**
* Creates an entity remove change to this change set.
*
* @param tag the entity to remove.
* @since 2.11.2
*/
public abstract void addEntityRemove(FaweCompoundTag tag);
@Deprecated(forRemoval = true, since = "2.11.2")
public void addEntityCreate(CompoundTag tag) {
addEntityCreate(adapt(tag));
}
/**
* Creates an entity create change to this change set.
*
* @param tag the entity to add.
* @since 2.11.2
*/
public abstract void addEntityCreate(FaweCompoundTag tag);
public abstract void addBiomeChange(int x, int y, int z, BiomeType from, BiomeType to);
@ -250,6 +305,13 @@ public abstract class AbstractChangeSet implements ChangeSet, IBatchProcessor {
return getIterator(redo);
}
/**
* {@return a coordinator to exchange sets of changes between a producer and a consumer}
* @since 2.11.2
*/
@ApiStatus.Internal
public abstract ChangeExchangeCoordinator getCoordinatedChanges(BlockBag blockBag, int mode, boolean dir);
public abstract Iterator<Change> getIterator(boolean redo);
public EditSession toEditSession(Actor actor) {
@ -272,13 +334,15 @@ public abstract class AbstractChangeSet implements ChangeSet, IBatchProcessor {
}
public void add(EntityCreate change) {
CompoundTag tag = change.state.getNbtData();
addEntityCreate(MainUtil.setEntityInfo(tag, change.getEntity()));
LinCompoundTag tag = change.state.getNbt();
assert tag != null;
addEntityCreate(FaweCompoundTag.of(NbtUtils.withEntityInfo(tag, change.getEntity())));
}
public void add(EntityRemove change) {
CompoundTag tag = change.state.getNbtData();
addEntityRemove(MainUtil.setEntityInfo(tag, change.getEntity()));
LinCompoundTag tag = change.state.getNbt();
assert tag != null;
addEntityRemove(FaweCompoundTag.of(NbtUtils.withEntityInfo(tag, change.getEntity())));
}
@Override
@ -296,9 +360,9 @@ public abstract class AbstractChangeSet implements ChangeSet, IBatchProcessor {
public void add(BlockChange change) {
try {
BlockVector3 loc = change.getPosition();
BlockVector3 loc = change.position();
BaseBlock from = change.previous();
BaseBlock to = change.getCurrent();
BaseBlock to = change.current();
add(loc, from, to);
} catch (Exception e) {
LOGGER.catching(e);
@ -318,31 +382,28 @@ public abstract class AbstractChangeSet implements ChangeSet, IBatchProcessor {
public void add(int x, int y, int z, BaseBlock from, BaseBlock to) {
try {
if (from.hasNbtData()) {
CompoundTag nbt = from.getNbtData();
assert nbt != null;
addTileRemove(MainUtil.setPosition(nbt, x, y, z));
LinCompoundTag nbt = from.getNbt();
if (nbt != null) {
addTileRemove(FaweCompoundTag.of(NbtUtils.withPosition(nbt, x, y, z)));
}
if (to.hasNbtData()) {
CompoundTag nbt = to.getNbtData();
assert nbt != null;
addTileCreate(MainUtil.setPosition(nbt, x, y, z));
nbt = to.getNbt();
if (nbt != null) {
addTileCreate(FaweCompoundTag.of(NbtUtils.withPosition(nbt, x, y, z)));
}
int combinedFrom = from.getOrdinal();
int combinedTo = to.getOrdinal();
add(x, y, z, combinedFrom, combinedTo);
} catch (Exception e) {
e.printStackTrace();
LOGGER.catching(e);
}
}
public void add(int x, int y, int z, int combinedFrom, BaseBlock to) {
try {
if (to.hasNbtData()) {
CompoundTag nbt = to.getNbtData();
assert nbt != null;
addTileCreate(MainUtil.setPosition(nbt, x, y, z));
LinCompoundTag nbt = to.getNbt();
if (nbt != null) {
addTileCreate(FaweCompoundTag.of(NbtUtils.withPosition(nbt, x, y, z)));
}
int combinedTo = to.getInternalId();
add(x, y, z, combinedFrom, combinedTo);

View File

@ -1,6 +1,6 @@
package com.fastasyncworldedit.core.history.changeset;
import com.sk89q.jnbt.CompoundTag;
import com.fastasyncworldedit.core.nbt.FaweCompoundTag;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.extension.platform.Actor;
import com.sk89q.worldedit.extent.inventory.BlockBag;
@ -46,26 +46,6 @@ public class AbstractDelegateChangeSet extends AbstractChangeSet {
parent.flush();
}
@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 void addBiomeChange(int x, int y, int z, BiomeType from, BiomeType to) {
parent.addBiomeChange(x, y, z, from, to);
@ -76,6 +56,11 @@ public class AbstractDelegateChangeSet extends AbstractChangeSet {
return parent.getIterator(blockBag, mode, redo);
}
@Override
public ChangeExchangeCoordinator getCoordinatedChanges(final BlockBag blockBag, final int mode, final boolean dir) {
return parent.getCoordinatedChanges(blockBag, mode, dir);
}
@Override
public Iterator<Change> getIterator(boolean redo) {
return parent.getIterator(redo);
@ -141,6 +126,26 @@ public class AbstractDelegateChangeSet extends AbstractChangeSet {
return parent.forwardIterator();
}
@Override
public void addTileCreate(final FaweCompoundTag tag) {
parent.addTileCreate(tag);
}
@Override
public void addTileRemove(final FaweCompoundTag tag) {
parent.addTileRemove(tag);
}
@Override
public void addEntityRemove(final FaweCompoundTag tag) {
parent.addEntityRemove(tag);
}
@Override
public void addEntityCreate(final FaweCompoundTag tag) {
parent.addEntityCreate(tag);
}
@Override
public void close() throws IOException {
parent.close();

View File

@ -1,8 +1,6 @@
package com.fastasyncworldedit.core.history.changeset;
import com.fastasyncworldedit.core.FaweCache;
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;
@ -109,13 +107,4 @@ public class BlockBagChangeSet extends AbstractDelegateChangeSet {
super.add(x, y, z, combinedFrom, combinedTo);
}
@Override
public void addTileCreate(CompoundTag nbt) {
if (nbt.containsKey("items")) {
Map<String, Tag<?, ?>> map = new HashMap<>(nbt.getValue());
map.remove("items");
}
super.addTileCreate(nbt);
}
}

View File

@ -0,0 +1,53 @@
package com.fastasyncworldedit.core.history.changeset;
import com.sk89q.worldedit.history.change.Change;
import org.jetbrains.annotations.ApiStatus;
import java.util.concurrent.Exchanger;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.function.BiConsumer;
/**
* @since 2.11.2
*/
@ApiStatus.Internal
public class ChangeExchangeCoordinator implements AutoCloseable {
private static final Thread.Builder.OfVirtual UNDO_VIRTUAL_THREAD_BUILDER = Thread.ofVirtual()
.name("FAWE undo", 0);
private final Exchanger<Change[]> exchanger;
private final BiConsumer<Exchanger<Change[]>, Change[]> runnerTask;
private boolean started = false;
private Thread runner;
public ChangeExchangeCoordinator(BiConsumer<Exchanger<Change[]>, Change[]> runner) {
this.runnerTask = runner;
this.exchanger = new Exchanger<>();
}
public Change[] take(Change[] consumed) {
if (!this.started) {
this.started = true;
final int length = consumed.length;
this.runner = UNDO_VIRTUAL_THREAD_BUILDER
.start(() -> this.runnerTask.accept(this.exchanger, new Change[length]));
}
try {
// Allow a reasonable timeout in case of weirdness
return exchanger.exchange(consumed, 30, TimeUnit.SECONDS);
} catch (InterruptedException | TimeoutException e) {
this.runner.interrupt();
Thread.currentThread().interrupt();
return null;
}
}
@Override
public void close() {
if (this.runner != null) {
this.runner.interrupt();
}
}
}

View File

@ -1,6 +1,7 @@
package com.fastasyncworldedit.core.history.changeset;
import com.fastasyncworldedit.core.configuration.Settings;
import com.fastasyncworldedit.core.history.change.ChangePopulator;
import com.fastasyncworldedit.core.history.change.MutableBiomeChange;
import com.fastasyncworldedit.core.history.change.MutableBlockChange;
import com.fastasyncworldedit.core.history.change.MutableEntityChange;
@ -9,6 +10,7 @@ import com.fastasyncworldedit.core.history.change.MutableTileChange;
import com.fastasyncworldedit.core.internal.exception.FaweSmallEditUnsupportedException;
import com.fastasyncworldedit.core.internal.io.FaweInputStream;
import com.fastasyncworldedit.core.internal.io.FaweOutputStream;
import com.fastasyncworldedit.core.nbt.FaweCompoundTag;
import com.fastasyncworldedit.core.util.MainUtil;
import com.fastasyncworldedit.core.util.MathMan;
import com.sk89q.jnbt.CompoundTag;
@ -20,15 +22,22 @@ import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.world.World;
import com.sk89q.worldedit.world.biome.BiomeType;
import com.sk89q.worldedit.world.block.BlockTypes;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.EOFException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayDeque;
import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.Queue;
import java.util.concurrent.Exchanger;
import java.util.function.BiConsumer;
/**
* FAWE stream ChangeSet offering support for extended-height worlds
@ -390,56 +399,44 @@ public abstract class FaweStreamChangeSet extends AbstractChangeSet {
}
@Override
public void addTileCreate(CompoundTag tag) {
if (tag == null) {
return;
}
public void addTileCreate(final FaweCompoundTag tag) {
blockSize++;
try {
NBTOutputStream nbtos = getTileCreateOS();
nbtos.writeTag(tag);
nbtos.writeTag(new CompoundTag(tag.linTag()));
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void addTileRemove(CompoundTag tag) {
if (tag == null) {
return;
}
public void addTileRemove(final FaweCompoundTag tag) {
blockSize++;
try {
NBTOutputStream nbtos = getTileRemoveOS();
nbtos.writeTag(tag);
nbtos.writeTag(new CompoundTag(tag.linTag()));
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void addEntityRemove(CompoundTag tag) {
if (tag == null) {
return;
}
public void addEntityRemove(final FaweCompoundTag tag) {
blockSize++;
try {
NBTOutputStream nbtos = getEntityRemoveOS();
nbtos.writeTag(tag);
nbtos.writeTag(new CompoundTag(tag.linTag()));
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void addEntityCreate(CompoundTag tag) {
if (tag == null) {
return;
}
public void addEntityCreate(final FaweCompoundTag tag) {
blockSize++;
try {
NBTOutputStream nbtos = getEntityCreateOS();
nbtos.writeTag(tag);
nbtos.writeTag(new CompoundTag(tag.linTag()));
} catch (IOException e) {
e.printStackTrace();
}
@ -711,6 +708,284 @@ public abstract class FaweStreamChangeSet extends AbstractChangeSet {
}
}
@Override
public ChangeExchangeCoordinator getCoordinatedChanges(BlockBag blockBag, int mode, boolean dir) {
try {
return coordinatedChanges(blockBag, mode, dir);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
private ChangeExchangeCoordinator coordinatedChanges(final BlockBag blockBag, final int mode, boolean dir) throws IOException {
close();
var tileCreate = tileChangePopulator(getTileCreateIS(), true);
var tileRemove = tileChangePopulator(getTileRemoveIS(), false);
var entityCreate = entityChangePopulator(getEntityCreateIS(), true);
var entityRemove = entityChangePopulator(getEntityRemoveIS(), false);
var blockChange = blockBag != null && mode > 0 ? fullBlockChangePopulator(blockBag, mode, dir) : blockChangePopulator(dir);
var biomeChange = biomeChangePopulator(dir);
Queue<ChangePopulator<?>> populators = new ArrayDeque<>(List.of(
tileCreate,
tileRemove,
entityCreate,
entityRemove,
blockChange,
biomeChange
));
BiConsumer<Exchanger<Change[]>, Change[]> task = (exchanger, array) -> {
while (fillArray(array, populators)) {
try {
array = exchanger.exchange(array);
} catch (InterruptedException e) {
return;
}
}
};
return new ChangeExchangeCoordinator(task);
}
private boolean fillArray(Change[] changes, Queue<ChangePopulator<?>> populators) {
ChangePopulator<?> populator = populators.peek();
if (populator == null) {
return false;
}
for (int i = 0; i < changes.length; i++) {
Change change = changes[i];
do {
change = populator.updateOrCreate(change);
if (change == null) {
populators.remove();
populator = populators.peek();
if (populator == null) {
changes[i] = null; // mark end
return true; // still needs to consume the elements of the current round
}
} else {
break;
}
} while (true);
changes[i] = change;
}
return true;
}
private static abstract class CompoundTagPopulator<C extends Change> implements ChangePopulator<C> {
private final NBTInputStream inputStream;
private CompoundTagPopulator(final NBTInputStream stream) {
inputStream = stream;
}
@Override
public @Nullable C populate(final @NotNull C change) {
try {
write(change, (CompoundTag) inputStream.readTag());
return change;
} catch (Exception ignored) {
}
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
protected abstract void write(C change, CompoundTag tag);
}
private ChangePopulator<MutableTileChange> tileChangePopulator(NBTInputStream is, boolean create) {
if (is == null) {
return ChangePopulator.empty();
}
class Populator extends CompoundTagPopulator<MutableTileChange> {
private Populator() {
super(is);
}
@Override
public @NotNull MutableTileChange create() {
return new MutableTileChange(null, create);
}
@Override
protected void write(final MutableTileChange change, final CompoundTag tag) {
change.tag = tag;
}
@Override
public boolean accepts(final Change change) {
return change instanceof MutableTileChange;
}
}
return new Populator();
}
private ChangePopulator<MutableEntityChange> entityChangePopulator(NBTInputStream is, boolean create) {
if (is == null) {
return ChangePopulator.empty();
}
class Populator extends CompoundTagPopulator<MutableEntityChange> {
private Populator() {
super(is);
}
@Override
public @NotNull MutableEntityChange create() {
return new MutableEntityChange(null, create);
}
@Override
protected void write(final MutableEntityChange change, final CompoundTag tag) {
change.tag = tag;
}
@Override
public boolean accepts(final Change change) {
return change instanceof MutableTileChange;
}
}
return new Populator();
}
private ChangePopulator<MutableFullBlockChange> fullBlockChangePopulator(BlockBag blockBag, int mode, boolean dir) throws
IOException {
final FaweInputStream is = getBlockIS();
if (is == null) {
return ChangePopulator.empty();
}
class Populator implements ChangePopulator<MutableFullBlockChange> {
@Override
public @NotNull MutableFullBlockChange create() {
return new MutableFullBlockChange(blockBag, mode, dir);
}
@Override
public @Nullable MutableFullBlockChange populate(@NotNull final MutableFullBlockChange change) {
try {
change.x = posDel.readX(is) + originX;
change.y = posDel.readY(is);
change.z = posDel.readZ(is) + originZ;
idDel.readCombined(is, change);
return change;
} catch (EOFException ignored) {
} catch (Exception e) {
e.printStackTrace();
}
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
@Override
public boolean accepts(final Change change) {
return change instanceof MutableFullBlockChange;
}
}
return new Populator();
}
private ChangePopulator<MutableBlockChange> blockChangePopulator(boolean dir) throws IOException {
final FaweInputStream is = getBlockIS();
if (is == null) {
return ChangePopulator.empty();
}
class Populator implements ChangePopulator<MutableBlockChange> {
@Override
public @NotNull MutableBlockChange create() {
return new MutableBlockChange(0, 0, 0, BlockTypes.AIR.getInternalId());
}
@Override
public @Nullable MutableBlockChange populate(@NotNull final MutableBlockChange change) {
try {
change.x = posDel.readX(is) + originX;
change.y = posDel.readY(is);
change.z = posDel.readZ(is) + originZ;
idDel.readCombined(is, change, dir);
return change;
} catch (EOFException ignored) {
} catch (Exception e) {
e.printStackTrace();
}
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
@Override
public boolean accepts(final Change change) {
return change instanceof MutableBlockChange;
}
}
return new Populator();
}
private ChangePopulator<MutableBiomeChange> biomeChangePopulator(boolean dir) throws IOException {
final FaweInputStream is = getBiomeIS();
if (is == null) {
return ChangePopulator.empty();
}
class Populator implements ChangePopulator<MutableBiomeChange> {
@Override
public @NotNull MutableBiomeChange create() {
return new MutableBiomeChange();
}
@Override
public @Nullable MutableBiomeChange populate(@NotNull final MutableBiomeChange change) {
try {
int int1 = is.read();
if (int1 != -1) {
int x = ((int1 << 24) + (is.read() << 16) + (is.read() << 8) + is.read()) << 2;
int z = ((is.read() << 24) + (is.read() << 16) + (is.read() << 8) + is.read()) << 2;
int y = (is.read() - 128) << 2;
int from = is.readVarInt();
int to = is.readVarInt();
change.setBiome(x, y, z, from, to);
return change;
}
} catch (EOFException ignored) {
} catch (Exception e) {
e.printStackTrace();
}
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
@Override
public boolean accepts(final Change change) {
return change instanceof MutableBiomeChange;
}
}
return new Populator();
}
@Override
public Iterator<Change> getIterator(final boolean dir) {
try {

View File

@ -1,6 +1,6 @@
package com.fastasyncworldedit.core.history.changeset;
import com.sk89q.jnbt.CompoundTag;
import com.fastasyncworldedit.core.nbt.FaweCompoundTag;
import com.sk89q.worldedit.extent.inventory.BlockBag;
import com.sk89q.worldedit.history.change.Change;
import com.sk89q.worldedit.world.World;
@ -25,22 +25,22 @@ public class NullChangeSet extends AbstractChangeSet {
}
@Override
public final void addTileCreate(CompoundTag tag) {
public void addTileCreate(final FaweCompoundTag tag) {
}
@Override
public final void addTileRemove(CompoundTag tag) {
public void addTileRemove(final FaweCompoundTag tag) {
}
@Override
public final void addEntityRemove(CompoundTag tag) {
public void addEntityRemove(final FaweCompoundTag tag) {
}
@Override
public final void addEntityCreate(CompoundTag tag) {
public void addEntityCreate(final FaweCompoundTag tag) {
}
@ -54,6 +54,17 @@ public class NullChangeSet extends AbstractChangeSet {
return getIterator(redo);
}
@Override
public ChangeExchangeCoordinator getCoordinatedChanges(final BlockBag blockBag, final int mode, final boolean dir) {
return new ChangeExchangeCoordinator(((exchanger, changes) -> {
try {
exchanger.exchange(null);
} catch (InterruptedException ignored) {
Thread.currentThread().interrupt();
}
}));
}
@Override
public final Iterator<Change> getIterator(boolean undo) {
return Collections.emptyIterator();

View File

@ -0,0 +1,115 @@
package com.fastasyncworldedit.core.internal.simd;
import com.fastasyncworldedit.core.configuration.Settings;
import com.fastasyncworldedit.core.extent.filter.block.DelegateFilter;
import com.fastasyncworldedit.core.function.mask.InverseMask;
import com.fastasyncworldedit.core.function.mask.SingleBlockStateMask;
import com.fastasyncworldedit.core.queue.Filter;
import com.sk89q.worldedit.function.mask.ExistingBlockMask;
import com.sk89q.worldedit.function.mask.InverseSingleBlockStateMask;
import com.sk89q.worldedit.function.mask.Mask;
import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.internal.util.LogManagerCompat;
import com.sk89q.worldedit.world.block.BaseBlock;
import com.sk89q.worldedit.world.block.BlockStateHolder;
import com.sk89q.worldedit.world.block.BlockTypesCache;
import jdk.incubator.vector.ShortVector;
import jdk.incubator.vector.VectorOperators;
import javax.annotation.Nullable;
public class SimdSupport {
private static final boolean VECTOR_API_PRESENT;
static {
boolean vectorApiPresent = false;
try {
Class.forName("jdk.incubator.vector.Vector");
vectorApiPresent = true;
} catch (ClassNotFoundException ignored) {
}
VECTOR_API_PRESENT = vectorApiPresent;
if (!VECTOR_API_PRESENT && Settings.settings().EXPERIMENTAL.USE_VECTOR_API) {
LogManagerCompat.getLogger()
.warn("FAWE use-vector-api is enabled but --add-modules=jdk.incubator.vector is not set.");
}
}
public static boolean useVectorApi() {
return VECTOR_API_PRESENT && Settings.settings().EXPERIMENTAL.USE_VECTOR_API;
}
public static @Nullable VectorizedMask vectorizedTargetMask(Mask mask) {
if (!useVectorApi()) {
return null;
}
return switch (mask) {
case SingleBlockStateMask single -> vectorizedTargetMask(single.getBlockState().getOrdinalChar());
case InverseSingleBlockStateMask inverse -> vectorizedTargetMaskInverse(inverse.getBlockState().getOrdinalChar());
case ExistingBlockMask ignored -> vectorizedTargetMaskNonAir();
case InverseMask inverse -> {
final VectorizedMask base = vectorizedTargetMask(inverse.inverse());
if (base == null) {
yield null;
}
yield (set, get) -> base.compareVector(set, get).not();
}
default -> null;
};
}
private static VectorizedMask vectorizedTargetMaskNonAir() {
// everything > VOID_AIR is not air
return (set, get) -> get.compare(VectorOperators.UNSIGNED_GT, BlockTypesCache.ReservedIDs.VOID_AIR);
}
private static VectorizedMask vectorizedTargetMask(char ordinal) {
return (set, get) -> get.compare(VectorOperators.EQ, (short) ordinal);
}
private static VectorizedMask vectorizedTargetMaskInverse(char ordinal) {
return (set, get) -> get.compare(VectorOperators.NE, (short) ordinal);
}
public static @Nullable VectorizedFilter vectorizedPattern(Pattern pattern) {
if (!useVectorApi()) {
return null;
}
return switch (pattern) {
case BaseBlock block -> {
if (block.getNbtReference() == null) {
yield new VectorizedPattern<>(block, block.getOrdinalChar());
}
yield null;
}
case BlockStateHolder<?> blockStateHolder -> new VectorizedPattern<>(
blockStateHolder,
blockStateHolder.getOrdinalChar()
);
default -> null;
};
}
private static final class VectorizedPattern<T extends Filter> extends DelegateFilter<T> implements VectorizedFilter {
private final char ordinal;
public VectorizedPattern(final T parent, char ordinal) {
super(parent);
this.ordinal = ordinal;
}
@Override
public ShortVector applyVector(final ShortVector get, final ShortVector set) {
return ShortVector.broadcast(ShortVector.SPECIES_PREFERRED, ordinal);
}
@Override
public Filter newInstance(final Filter other) {
return new VectorizedPattern<>(other, ordinal);
}
}
}

View File

@ -0,0 +1,33 @@
package com.fastasyncworldedit.core.internal.simd;
import com.fastasyncworldedit.core.extent.filter.block.CharFilterBlock;
import com.fastasyncworldedit.core.queue.Filter;
import com.sk89q.worldedit.extent.Extent;
import jdk.incubator.vector.ShortVector;
import jdk.incubator.vector.VectorSpecies;
public class VectorizedCharFilterBlock extends CharFilterBlock {
public VectorizedCharFilterBlock(final Extent extent) {
super(extent);
}
@Override
public synchronized void filter(final Filter filter) {
if (!(filter instanceof VectorizedFilter vecFilter)) {
throw new IllegalStateException("Unexpected VectorizedCharFilterBlock " + filter);
}
final VectorSpecies<Short> species = ShortVector.SPECIES_PREFERRED;
initSet(); // set array is null before
char[] setArr = this.setArr;
assert setArr != null;
char[] getArr = this.getArr;
// assume setArr.length == getArr.length == 4096
for (int i = 0; i < 4096; i += species.length()) {
ShortVector set = ShortVector.fromCharArray(species, setArr, i);
ShortVector get = ShortVector.fromCharArray(species, getArr, i);
ShortVector res = vecFilter.applyVector(get, set);
res.intoCharArray(setArr, i);
}
}
}

View File

@ -0,0 +1,8 @@
package com.fastasyncworldedit.core.internal.simd;
import com.fastasyncworldedit.core.queue.Filter;
import jdk.incubator.vector.ShortVector;
public interface VectorizedFilter extends Filter {
ShortVector applyVector(ShortVector get, ShortVector set);
}

View File

@ -0,0 +1,40 @@
package com.fastasyncworldedit.core.internal.simd;
import com.fastasyncworldedit.core.queue.IChunk;
import com.fastasyncworldedit.core.queue.IChunkGet;
import com.fastasyncworldedit.core.queue.IChunkSet;
import jdk.incubator.vector.ShortVector;
import jdk.incubator.vector.VectorMask;
import jdk.incubator.vector.VectorSpecies;
public interface VectorizedMask {
default void processChunks(IChunk chunk, IChunkGet get, IChunkSet set) {
for (int layer = get.getMinSectionPosition(); layer <= get.getMaxSectionPosition(); layer++) {
final char[] sectionSet = set.loadIfPresent(layer);
if (sectionSet == null) {
continue;
}
final char[] sectionGet = get.load(layer);
processSection(layer, sectionSet, sectionGet);
}
}
default void processSection(int layer, char[] set, char[] get) {
final VectorSpecies<Short> species = ShortVector.SPECIES_PREFERRED;
// assume that set.length % species.elementSize() == 0
for (int i = 0; i < set.length; i += species.length()) {
ShortVector vectorSet = ShortVector.fromCharArray(species, set, i);
ShortVector vectorGet = ShortVector.fromCharArray(species, get, i);
vectorSet = processVector(vectorSet, vectorGet);
vectorSet.intoCharArray(set, i);
}
}
default ShortVector processVector(ShortVector set, ShortVector get) {
return set.blend(0, compareVector(set, get).not());
}
VectorMask<Short> compareVector(ShortVector set, ShortVector get);
}

View File

@ -5,16 +5,18 @@ import com.fastasyncworldedit.core.configuration.Settings;
import java.util.Collections;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
public class FaweLimit {
public int MAX_ACTIONS = 0;
public long MAX_CHANGES = 0;
public int MAX_FAILS = 0;
public long MAX_CHECKS = 0;
public int MAX_ITERATIONS = 0;
public int MAX_BLOCKSTATES = 0;
public int MAX_ENTITIES = 0;
public AtomicLong MAX_CHANGES = new AtomicLong();
public AtomicInteger MAX_FAILS = new AtomicInteger();
public AtomicLong MAX_CHECKS = new AtomicLong();
public AtomicInteger MAX_ITERATIONS = new AtomicInteger();
public AtomicInteger MAX_BLOCKSTATES = new AtomicInteger();
public AtomicInteger MAX_ENTITIES = new AtomicInteger();
public int MAX_HISTORY = 0;
public int SCHEM_FILE_SIZE_LIMIT = 0;
public int SCHEM_FILE_NUM_LIMIT = 0;
@ -112,12 +114,12 @@ public class FaweLimit {
MAX.SPEED_REDUCTION = 0;
MAX.INVENTORY_MODE = 0;
MAX.MAX_ACTIONS = 1;
MAX.MAX_CHANGES = Long.MAX_VALUE;
MAX.MAX_FAILS = Integer.MAX_VALUE;
MAX.MAX_CHECKS = Long.MAX_VALUE;
MAX.MAX_ITERATIONS = Integer.MAX_VALUE;
MAX.MAX_BLOCKSTATES = Integer.MAX_VALUE;
MAX.MAX_ENTITIES = Integer.MAX_VALUE;
MAX.MAX_CHANGES = new AtomicLong(Long.MAX_VALUE);
MAX.MAX_FAILS = new AtomicInteger(Integer.MAX_VALUE);
MAX.MAX_CHECKS = new AtomicLong(Long.MAX_VALUE);
MAX.MAX_ITERATIONS = new AtomicInteger(Integer.MAX_VALUE);
MAX.MAX_BLOCKSTATES = new AtomicInteger(Integer.MAX_VALUE);
MAX.MAX_ENTITIES = new AtomicInteger(Integer.MAX_VALUE);
MAX.MAX_HISTORY = Integer.MAX_VALUE;
MAX.SCHEM_FILE_NUM_LIMIT = Integer.MAX_VALUE;
MAX.SCHEM_FILE_SIZE_LIMIT = Integer.MAX_VALUE;
@ -138,120 +140,144 @@ public class FaweLimit {
}
public boolean MAX_CHANGES() {
return MAX_CHANGES-- > 0;
return MAX_CHANGES.decrementAndGet() < 0;
}
public boolean MAX_FAILS() {
return MAX_FAILS-- > 0;
return MAX_FAILS.decrementAndGet() < 0;
}
public boolean MAX_CHECKS() {
return MAX_CHECKS-- > 0;
return MAX_CHECKS.decrementAndGet() < 0;
}
public boolean MAX_ITERATIONS() {
return MAX_ITERATIONS-- > 0;
return MAX_ITERATIONS.decrementAndGet() < 0;
}
public boolean MAX_BLOCKSTATES() {
return MAX_BLOCKSTATES-- > 0;
return MAX_BLOCKSTATES.decrementAndGet() < 0;
}
public boolean MAX_ENTITIES() {
return MAX_ENTITIES-- > 0;
return MAX_ENTITIES.decrementAndGet() < 0;
}
public void THROW_MAX_CHANGES() {
if (MAX_CHANGES-- <= 0) {
if (MAX_CHANGES.decrementAndGet() < 0) {
throw FaweCache.MAX_CHANGES;
}
}
public void THROW_MAX_FAILS() {
if (MAX_FAILS-- <= 0) {
throw FaweCache.MAX_CHECKS;
if (MAX_FAILS.decrementAndGet() < 0) {
throw FaweCache.MAX_FAILS;
}
}
public void THROW_MAX_CHECKS() {
if (MAX_CHECKS-- <= 0) {
if (MAX_CHECKS.decrementAndGet() < 0) {
throw FaweCache.MAX_CHECKS;
}
}
public void THROW_MAX_ITERATIONS() {
if (MAX_ITERATIONS-- <= 0) {
if (MAX_ITERATIONS.decrementAndGet() < 0) {
throw FaweCache.MAX_ITERATIONS;
}
}
public void THROW_MAX_BLOCKSTATES() {
if (MAX_BLOCKSTATES-- <= 0) {
if (MAX_BLOCKSTATES.decrementAndGet() < 0) {
throw FaweCache.MAX_TILES;
}
}
public void THROW_MAX_ENTITIES() {
if (MAX_ENTITIES-- <= 0) {
if (MAX_ENTITIES.decrementAndGet() < 0) {
throw FaweCache.MAX_ENTITIES;
}
}
public void THROW_MAX_CHANGES(int amt) {
if ((MAX_CHANGES -= amt) <= 0) {
if (amt == 0) {
return;
}
if (MAX_CHANGES.addAndGet(-amt) < 0) {
throw FaweCache.MAX_CHANGES;
}
}
public void THROW_MAX_CHANGES(long amt) {
if ((MAX_CHANGES -= amt) <= 0) {
if (amt == 0) {
return;
}
if (MAX_CHANGES.addAndGet(-amt) < 0) {
throw FaweCache.MAX_CHANGES;
}
}
public void THROW_MAX_FAILS(int amt) {
if ((MAX_FAILS -= amt) <= 0) {
throw FaweCache.MAX_CHECKS;
if (amt == 0) {
return;
}
if (MAX_FAILS.addAndGet(-amt) < 0) {
throw FaweCache.MAX_FAILS;
}
}
public void THROW_MAX_CHECKS(int amt) {
if ((MAX_CHECKS -= amt) <= 0) {
if (amt == 0) {
return;
}
if (MAX_CHECKS.addAndGet(-amt) < 0) {
throw FaweCache.MAX_CHECKS;
}
}
public void THROW_MAX_CHECKS(long amt) {
if ((MAX_CHECKS -= amt) <= 0) {
if (amt == 0) {
return;
}
if (MAX_CHECKS.addAndGet(-amt) < 0) {
throw FaweCache.MAX_CHECKS;
}
}
public void THROW_MAX_ITERATIONS(int amt) {
if ((MAX_ITERATIONS -= amt) <= 0) {
if (amt == 0) {
return;
}
if (MAX_ITERATIONS.addAndGet(-amt) < 0) {
throw FaweCache.MAX_ITERATIONS;
}
}
public void THROW_MAX_BLOCKSTATES(int amt) {
if ((MAX_BLOCKSTATES -= amt) <= 0) {
if (amt == 0) {
return;
}
if (MAX_BLOCKSTATES.addAndGet(-amt) < 0) {
throw FaweCache.MAX_TILES;
}
}
public void THROW_MAX_ENTITIES(int amt) {
if ((MAX_ENTITIES -= amt) <= 0) {
if (amt == 0) {
return;
}
if (MAX_ENTITIES.addAndGet(-amt) < 0) {
throw FaweCache.MAX_ENTITIES;
}
}
public boolean isUnlimited() {
return MAX_CHANGES == Long.MAX_VALUE
&& MAX_FAILS == Integer.MAX_VALUE
&& MAX_CHECKS == Long.MAX_VALUE
&& MAX_ITERATIONS == Integer.MAX_VALUE
&& MAX_BLOCKSTATES == Integer.MAX_VALUE
&& MAX_ENTITIES == Integer.MAX_VALUE
return MAX_CHANGES.get() == Long.MAX_VALUE
&& MAX_FAILS.get() == Integer.MAX_VALUE
&& MAX_CHECKS.get() == Long.MAX_VALUE
&& MAX_ITERATIONS.get() == Integer.MAX_VALUE
&& MAX_BLOCKSTATES.get() == Integer.MAX_VALUE
&& MAX_ENTITIES.get() == Integer.MAX_VALUE
&& MAX_HISTORY == Integer.MAX_VALUE
&& SCHEM_FILE_SIZE_LIMIT == Integer.MAX_VALUE
&& SCHEM_FILE_NUM_LIMIT == Integer.MAX_VALUE
@ -270,14 +296,30 @@ public class FaweLimit {
&& MAX_BUTCHER_RADIUS == Integer.MAX_VALUE;
}
/**
* Get an {@link FaweLimit} representing the amount of a limit used from a given "original" limit
*
* @since TODO
*/
public FaweLimit getLimitUsed(FaweLimit originalLimit) {
FaweLimit newLimit = new FaweLimit();
newLimit.MAX_CHANGES = new AtomicLong(originalLimit.MAX_CHANGES.get() - this.MAX_CHANGES.get());
newLimit.MAX_FAILS = new AtomicInteger(originalLimit.MAX_FAILS.get() - this.MAX_FAILS.get());
newLimit.MAX_CHECKS = new AtomicLong(originalLimit.MAX_CHECKS.get() - this.MAX_CHECKS.get());
newLimit.MAX_ITERATIONS = new AtomicInteger(originalLimit.MAX_ITERATIONS.get() - this.MAX_ITERATIONS.get());
newLimit.MAX_BLOCKSTATES = new AtomicInteger(originalLimit.MAX_BLOCKSTATES.get() - this.MAX_BLOCKSTATES.get());
newLimit.MAX_ENTITIES = new AtomicInteger(originalLimit.MAX_ENTITIES.get() - this.MAX_ENTITIES.get());
return newLimit;
}
public void set(FaweLimit limit) {
MAX_ACTIONS = limit.MAX_ACTIONS;
MAX_CHANGES = limit.MAX_CHANGES;
MAX_BLOCKSTATES = limit.MAX_BLOCKSTATES;
MAX_CHECKS = limit.MAX_CHECKS;
MAX_ENTITIES = limit.MAX_ENTITIES;
MAX_FAILS = limit.MAX_FAILS;
MAX_ITERATIONS = limit.MAX_ITERATIONS;
MAX_CHANGES.set(limit.MAX_CHANGES.get());
MAX_FAILS.set(limit.MAX_FAILS.get());
MAX_CHECKS.set(limit.MAX_CHECKS.get());
MAX_ITERATIONS.set(limit.MAX_ITERATIONS.get());
MAX_BLOCKSTATES.set(limit.MAX_BLOCKSTATES.get());
MAX_ENTITIES.set(limit.MAX_ENTITIES.get());
MAX_HISTORY = limit.MAX_HISTORY;
SCHEM_FILE_NUM_LIMIT = limit.SCHEM_FILE_NUM_LIMIT;
SCHEM_FILE_SIZE_LIMIT = limit.SCHEM_FILE_SIZE_LIMIT;

View File

@ -4,7 +4,9 @@ public record IntPair(int x, int z) {
@Override
public int hashCode() {
return (x << 16) | (z & 0xFFFF);
int i = 1664525 * x + 1013904223;
int j = 1664525 * (z ^ -559038737) + 1013904223;
return i ^ j;
}
@Override

View File

@ -0,0 +1,7 @@
package com.fastasyncworldedit.core.nbt;
import org.enginehub.linbus.tree.LinCompoundTag;
record EagerFaweCompoundTag(LinCompoundTag linTag) implements FaweCompoundTag {
}

View File

@ -0,0 +1,44 @@
package com.fastasyncworldedit.core.nbt;
import com.google.common.base.Supplier;
import com.google.common.base.Suppliers;
import com.sk89q.worldedit.util.concurrency.LazyReference;
import org.enginehub.linbus.tree.LinCompoundTag;
/**
* A wrapper around compound tags, potentially lazily transformed.
* @since 2.11.2
*/
public sealed interface FaweCompoundTag permits EagerFaweCompoundTag, LazyFaweCompoundTag {
/**
* {@return a lazy compound component backed by a lazy reference}
* @param lazyReference the lazy reference to the actual compound tag
*/
static FaweCompoundTag of(LazyReference<? extends LinCompoundTag> lazyReference) {
return new LazyFaweCompoundTag(lazyReference::getValue);
}
/**
* {@return a lazy compound component backed by a supplier}
* Invocations to the supplier are memoized.
* @param supplier the supplier for the actual compound tag
*/
static FaweCompoundTag of(Supplier<? extends LinCompoundTag> supplier) {
return new LazyFaweCompoundTag(Suppliers.memoize(supplier));
}
/**
* {@return a direct reference tho the given compound tag}
* @param linCompoundTag the tag to wrap
*/
static FaweCompoundTag of(LinCompoundTag linCompoundTag) {
return new EagerFaweCompoundTag(linCompoundTag);
}
/**
* {@return the underlying tag}
*/
LinCompoundTag linTag();
}

View File

@ -0,0 +1,14 @@
package com.fastasyncworldedit.core.nbt;
import org.enginehub.linbus.tree.LinCompoundTag;
import java.util.function.Supplier;
record LazyFaweCompoundTag(Supplier<? extends LinCompoundTag> linTagSupplier) implements FaweCompoundTag {
@Override
public LinCompoundTag linTag() {
return this.linTagSupplier().get();
}
}

View File

@ -3,6 +3,7 @@ package com.fastasyncworldedit.core.queue;
import com.fastasyncworldedit.core.extent.filter.block.FilterBlock;
import com.sk89q.worldedit.regions.Region;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
/**
@ -10,30 +11,29 @@ import javax.annotation.Nullable;
*/
public interface Filter {
/**
* Checks whether a chunk should be read.
*
* @param chunkX the x coordinate in the chunk
* @param chunkZ the z coordinate in the chunk
*/
default boolean appliesChunk(
int chunkX,
int chunkZ
) {
return true;
}
// /**
// * Checks whether a chunk should be read.
// *
// * @param chunkX the x coordinate in the chunk
// * @param chunkZ the z coordinate in the chunk
// */
// default boolean appliesChunk(
// int chunkX,
// int chunkZ
// ) {
// return true;
// }
/**
* Do something with the IChunk<br> - Return null if you don't want to filter blocks<br> -
* Return the chunk if you do want to filter blocks<br>
* Do something with the IChunk<br>
*/
default <T extends IChunk> T applyChunk(T chunk, @Nullable Region region) {
default @Nonnull <T extends IChunk> T applyChunk(T chunk, @Nullable Region region) {
return chunk;
}
default boolean appliesLayer(IChunk chunk, int layer) {
return true;
}
// default boolean appliesLayer(IChunk chunk, int layer) {
// return true;
// }
/**
* Make changes to the block here<br> - e.g., block.setId(...)<br> - Note: Performance is

View File

@ -3,15 +3,16 @@ package com.fastasyncworldedit.core.queue;
import com.fastasyncworldedit.core.extent.processor.EmptyBatchProcessor;
import com.fastasyncworldedit.core.extent.processor.MultiBatchProcessor;
import com.fastasyncworldedit.core.extent.processor.ProcessorScope;
import com.sk89q.jnbt.CompoundTag;
import com.fastasyncworldedit.core.nbt.FaweCompoundTag;
import com.fastasyncworldedit.core.util.NbtUtils;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.world.block.BlockTypesCache;
import javax.annotation.Nullable;
import java.util.Collection;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Future;
import java.util.function.Function;
@ -50,7 +51,7 @@ public interface IBatchProcessor {
}
/**
* Convert this processor into an Extent based processor instead of a queue batch based on.
* Convert this processor into an Extent based processor instead of a queue batch based one.
*/
@Nullable
Extent construct(Extent child);
@ -62,40 +63,41 @@ public interface IBatchProcessor {
* @return false if chunk is empty of blocks
*/
default boolean trimY(IChunkSet set, int minY, int maxY, final boolean keepInsideRange) {
int minLayer = (minY - 1) >> 4;
int maxLayer = (maxY + 1) >> 4;
int minLayer = minY >> 4;
int maxLayer = maxY >> 4;
if (keepInsideRange) {
for (int layer = set.getMinSectionPosition(); layer <= minLayer; layer++) {
if (set.hasSection(layer)) {
if (layer == minLayer) {
char[] arr = set.loadIfPresent(layer);
if (arr != null) {
int index = (minY & 15) << 8;
for (int i = 0; i < index; i++) {
arr[i] = BlockTypesCache.ReservedIDs.__RESERVED__;
}
set.setBlocks(layer, arr);
}
} else {
set.setBlocks(layer, null);
for (int layer = set.getMinSectionPosition(); layer <= set.getMaxSectionPosition(); layer++) {
if (!set.hasSection(layer)) {
continue;
}
// wipe all data from chunk layers above or below the max / min layer
if (layer < minLayer || layer > maxLayer) {
set.setBlocks(layer, null);
continue;
}
// if chunk layer / section is fully enclosed by minY to maxY, keep as is
if (layer > minLayer && layer < maxLayer) {
continue;
}
char[] blocks = set.loadIfPresent(layer);
if (blocks == null) {
continue;
}
// When on the minimum layer (as defined by minY), remove blocks up to minY (exclusive)
if (layer == minLayer) {
int index = (minY & 15) << 8;
for (int i = 0; i < index; i++) {
blocks[i] = BlockTypesCache.ReservedIDs.__RESERVED__;
}
}
}
for (int layer = maxLayer; layer <= set.getMaxSectionPosition(); layer++) {
if (set.hasSection(layer)) {
if (layer == maxLayer) {
char[] arr = set.loadIfPresent(layer);
if (arr != null) {
int index = ((maxY + 1) & 15) << 8;
for (int i = index; i < arr.length; i++) {
arr[i] = BlockTypesCache.ReservedIDs.__RESERVED__;
}
set.setBlocks(layer, arr);
}
} else {
set.setBlocks(layer, null);
// When on the maximum layer (as defined by maxY), remove blocks above maxY (exclusive)
if (layer == maxLayer) {
int index = ((maxY & 15) + 1) << 8;
for (int i = index; i < blocks.length; i++) {
blocks[i] = BlockTypesCache.ReservedIDs.__RESERVED__;
}
}
set.setBlocks(layer, blocks);
}
try {
int layer = (minY - 15) >> 4;
@ -155,11 +157,11 @@ public interface IBatchProcessor {
*/
@Deprecated(forRemoval = true, since = "2.8.4")
default boolean trimNBT(IChunkSet set, Function<BlockVector3, Boolean> contains) {
Set<CompoundTag> ents = set.getEntities();
Collection<FaweCompoundTag> ents = set.entities();
if (!ents.isEmpty()) {
ents.removeIf(ent -> !contains.apply(ent.getEntityPosition().toBlockPoint()));
ents.removeIf(ent -> !contains.apply(NbtUtils.entityPosition(ent).toBlockPoint()));
}
Map<BlockVector3, CompoundTag> tiles = set.getTiles();
Map<BlockVector3, FaweCompoundTag> tiles = set.tiles();
if (!tiles.isEmpty()) {
tiles.entrySet().removeIf(blockVector3CompoundTagEntry -> !contains
.apply(blockVector3CompoundTagEntry.getKey()));
@ -176,11 +178,11 @@ public interface IBatchProcessor {
default boolean trimNBT(
IChunkSet set, Function<BlockVector3, Boolean> containsEntity, Function<BlockVector3, Boolean> containsTile
) {
Set<CompoundTag> ents = set.getEntities();
Collection<FaweCompoundTag> ents = set.entities();
if (!ents.isEmpty()) {
ents.removeIf(ent -> !containsEntity.apply(ent.getEntityPosition().toBlockPoint()));
ents.removeIf(ent -> !containsEntity.apply(NbtUtils.entityPosition(ent).toBlockPoint()));
}
Map<BlockVector3, CompoundTag> tiles = set.getTiles();
Map<BlockVector3, FaweCompoundTag> tiles = set.tiles();
if (!tiles.isEmpty()) {
tiles.entrySet().removeIf(blockVector3CompoundTagEntry -> !containsTile.apply(blockVector3CompoundTagEntry.getKey()));
}

View File

@ -3,6 +3,8 @@ package com.fastasyncworldedit.core.queue;
import com.fastasyncworldedit.core.FaweCache;
import com.fastasyncworldedit.core.internal.io.FastByteArrayOutputStream;
import com.fastasyncworldedit.core.internal.io.FaweOutputStream;
import com.fastasyncworldedit.core.nbt.FaweCompoundTag;
import com.fastasyncworldedit.core.util.collection.AdaptedMap;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.extension.platform.Capability;
@ -12,10 +14,13 @@ import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.block.BlockTypesCache;
import com.sk89q.worldedit.world.registry.BlockRegistry;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.io.IOException;
import java.util.Collection;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
/**
@ -54,11 +59,38 @@ public interface IBlocks extends Trimable {
BlockState getBlock(int x, int y, int z);
Map<BlockVector3, CompoundTag> getTiles();
@Deprecated(forRemoval = true, since = "2.11.2")
default Map<BlockVector3, CompoundTag> getTiles() {
return AdaptedMap.values(tiles(), ct -> FaweCompoundTag.of(ct.toLinTag()), IBlocks::toCompoundTag);
}
CompoundTag getTile(int x, int y, int z);
Map<BlockVector3, FaweCompoundTag> tiles();
Set<CompoundTag> getEntities();
@Deprecated(forRemoval = true, since = "2.11.2")
default CompoundTag getTile(int x, int y, int z) {
final FaweCompoundTag tile = tile(x, y, z);
if (tile == null) {
return null;
}
return toCompoundTag(tile);
}
@SuppressWarnings({"deprecation"})
private static @Nonnull CompoundTag toCompoundTag(FaweCompoundTag tile) {
return new CompoundTag(tile.linTag());
}
@Nullable
FaweCompoundTag tile(int x, int y, int z);
@Deprecated(forRemoval = true, since = "2.11.2")
default Set<CompoundTag> getEntities() {
return entities().stream()
.map(IBlocks::toCompoundTag)
.collect(Collectors.toSet());
}
Collection<FaweCompoundTag> entities();
BiomeType getBiomeType(int x, int y, int z);

View File

@ -1,11 +1,7 @@
package com.fastasyncworldedit.core.queue;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.jnbt.DoubleTag;
import com.sk89q.jnbt.ListTag;
import com.sk89q.jnbt.NBTUtils;
import com.sk89q.jnbt.StringTag;
import com.sk89q.jnbt.Tag;
import com.fastasyncworldedit.core.nbt.FaweCompoundTag;
import com.fastasyncworldedit.core.util.NbtUtils;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.entity.BaseEntity;
import com.sk89q.worldedit.entity.Entity;
@ -16,6 +12,12 @@ import com.sk89q.worldedit.world.biome.BiomeType;
import com.sk89q.worldedit.world.block.BaseBlock;
import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.block.BlockStateHolder;
import org.enginehub.linbus.tree.LinCompoundTag;
import org.enginehub.linbus.tree.LinDoubleTag;
import org.enginehub.linbus.tree.LinListTag;
import org.enginehub.linbus.tree.LinStringTag;
import org.enginehub.linbus.tree.LinTag;
import org.enginehub.linbus.tree.LinTagType;
import java.util.ArrayList;
import java.util.HashMap;
@ -39,9 +41,9 @@ public interface IChunkExtent<T extends IChunk> extends Extent {
}
@Override
default boolean setTile(int x, int y, int z, CompoundTag tile) throws WorldEditException {
default boolean tile(int x, int y, int z, FaweCompoundTag tile) throws WorldEditException {
final IChunk chunk = getOrCreateChunk(x >> 4, z >> 4);
return chunk.setTile(x & 15, y, z & 15, tile);
return chunk.tile(x & 15, y, z & 15, tile);
}
@Override
@ -124,19 +126,19 @@ public interface IChunkExtent<T extends IChunk> extends Extent {
@Override
default Entity createEntity(Location location, BaseEntity entity, UUID uuid) {
final IChunk chunk = getOrCreateChunk(location.getBlockX() >> 4, location.getBlockZ() >> 4);
Map<String, Tag<?, ?>> map = new HashMap<>(entity.getNbtData().getValue()); //do not modify original entity data
map.put("Id", new StringTag(entity.getType().getName()));
Map<String, LinTag<?>> map = new HashMap<>(entity.getNbt().value()); //do not modify original entity data
map.put("Id", LinStringTag.of(entity.getType().getName()));
//Set pos
List<DoubleTag> posList = new ArrayList<>();
posList.add(new DoubleTag(location.x()));
posList.add(new DoubleTag(location.y()));
posList.add(new DoubleTag(location.z()));
map.put("Pos", new ListTag(DoubleTag.class, posList));
List<LinDoubleTag> posList = new ArrayList<>();
posList.add(LinDoubleTag.of(location.x()));
posList.add(LinDoubleTag.of(location.y()));
posList.add(LinDoubleTag.of(location.z()));
map.put("Pos", LinListTag.of(LinTagType.doubleTag(), posList));
NBTUtils.addUUIDToMap(map, uuid);
NbtUtils.addUUIDToMap(map, uuid);
chunk.setEntity(new CompoundTag(map));
chunk.entity(FaweCompoundTag.of(LinCompoundTag.of(map)));
return new IChunkEntity(this, location, uuid, entity);
}

View File

@ -1,6 +1,7 @@
package com.fastasyncworldedit.core.queue;
import com.fastasyncworldedit.core.extent.processor.heightmap.HeightMapType;
import com.fastasyncworldedit.core.nbt.FaweCompoundTag;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.worldedit.extent.InputExtent;
import com.sk89q.worldedit.math.BlockVector3;
@ -46,7 +47,26 @@ public interface IChunkGet extends IBlocks, Trimable, InputExtent, ITileInput {
<T extends Future<T>> T call(IChunkSet set, Runnable finalize);
CompoundTag getEntity(UUID uuid);
@Deprecated(forRemoval = true, since = "2.11.2")
default CompoundTag getEntity(UUID uuid) {
final FaweCompoundTag entity = entity(uuid);
if (entity == null) {
return null;
}
return new CompoundTag(entity.linTag());
}
/**
* {@return the compound tag describing the entity with the given UUID, if any}
* @param uuid the uuid of the entity
*/
@Nullable FaweCompoundTag entity(UUID uuid);
@Override
@Deprecated(forRemoval = true, since = "2.11.2")
default CompoundTag getTile(int x, int y, int z) {
return IBlocks.super.getTile(x, y, z);
}
boolean isCreateCopy();

View File

@ -1,7 +1,9 @@
package com.fastasyncworldedit.core.queue;
import com.fastasyncworldedit.core.extent.processor.heightmap.HeightMapType;
import com.fastasyncworldedit.core.nbt.FaweCompoundTag;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.extent.OutputExtent;
import com.sk89q.worldedit.function.operation.Operation;
import com.sk89q.worldedit.math.BlockVector3;
@ -36,7 +38,12 @@ public interface IChunkSet extends IBlocks, OutputExtent {
boolean isEmpty();
@Override
boolean setTile(int x, int y, int z, CompoundTag tile);
@Deprecated(forRemoval = true, since = "2.11.2")
default boolean setTile(int x, int y, int z, CompoundTag tile) throws WorldEditException {
return tile(x, y, z, FaweCompoundTag.of(tile.toLinTag()));
}
boolean tile(int x, int y, int z, FaweCompoundTag tag);
@Override
void setBlockLight(int x, int y, int z, int value);
@ -53,7 +60,12 @@ public interface IChunkSet extends IBlocks, OutputExtent {
void setFullBright(int layer);
void setEntity(CompoundTag tag);
@Deprecated(forRemoval = true, since = "2.11.2")
default void setEntity(CompoundTag tag) {
entity(FaweCompoundTag.of(tag::toLinTag));
}
void entity(FaweCompoundTag tag);
void removeEntity(UUID uuid);

View File

@ -9,21 +9,11 @@ public interface IDelegateFilter extends Filter {
Filter getParent();
@Override
default boolean appliesChunk(int chunkX, int chunkZ) {
return getParent().appliesChunk(chunkX, chunkZ);
}
@Override
default <V extends IChunk> V applyChunk(V chunk, @Nullable Region region) {
return getParent().applyChunk(chunk, region);
}
@Override
default boolean appliesLayer(IChunk chunk, int layer) {
return getParent().appliesLayer(chunk, layer);
}
@Override
default void applyBlock(FilterBlock block) {
getParent().applyBlock(block);

View File

@ -2,6 +2,9 @@ package com.fastasyncworldedit.core.queue;
import com.fastasyncworldedit.core.extent.filter.block.ChunkFilterBlock;
import com.fastasyncworldedit.core.extent.processor.IBatchProcessorHolder;
import com.fastasyncworldedit.core.internal.simd.SimdSupport;
import com.fastasyncworldedit.core.internal.simd.VectorizedCharFilterBlock;
import com.fastasyncworldedit.core.internal.simd.VectorizedFilter;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.function.operation.Operation;
import com.sk89q.worldedit.math.BlockVector2;
@ -137,16 +140,20 @@ public interface IQueueExtent<T extends IChunk> extends Flushable, Trimable, ICh
int chunkZ,
boolean full
) {
if (!filter.appliesChunk(chunkX, chunkZ)) {
return block;
}
// if (!filter.appliesChunk(chunkX, chunkZ)) {
// return block;
// }
T chunk = this.getOrCreateChunk(chunkX, chunkZ);
T newChunk = filter.applyChunk(chunk, region);
if (newChunk != null) {
chunk = newChunk;
if (block == null) {
block = this.createFilterBlock();
if (SimdSupport.useVectorApi() && filter instanceof VectorizedFilter) {
block = new VectorizedCharFilterBlock(this);
} else {
block = this.createFilterBlock();
}
}
block.initChunk(chunkX, chunkZ);
chunk.filterBlocks(filter, block, region, full);

View File

@ -2,6 +2,7 @@ package com.fastasyncworldedit.core.queue;
import com.sk89q.jnbt.CompoundTag;
@Deprecated(forRemoval = true, since = "2.11.2")
public interface ITileInput {
CompoundTag getTile(int x, int y, int z);

View File

@ -14,6 +14,8 @@ import com.fastasyncworldedit.core.extent.processor.BatchProcessorHolder;
import com.fastasyncworldedit.core.extent.processor.MultiBatchProcessor;
import com.fastasyncworldedit.core.function.mask.BlockMaskBuilder;
import com.fastasyncworldedit.core.internal.exception.FaweException;
import com.fastasyncworldedit.core.internal.simd.SimdSupport;
import com.fastasyncworldedit.core.internal.simd.VectorizedFilter;
import com.fastasyncworldedit.core.queue.Filter;
import com.fastasyncworldedit.core.queue.IQueueChunk;
import com.fastasyncworldedit.core.queue.IQueueExtent;
@ -28,7 +30,6 @@ import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.internal.util.LogManagerCompat;
import com.sk89q.worldedit.math.BlockVector2;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.regions.CuboidRegion;
import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.util.Countable;
import com.sk89q.worldedit.world.World;
@ -223,7 +224,9 @@ public class ParallelQueueExtent extends PassthroughExtent {
@Override
public int setBlocks(Region region, Pattern pattern) throws MaxChangedBlocksException {
return this.changes = apply(region, new LinkedFilter<>(pattern, new CountFilter()), true).getChild().getTotal();
VectorizedFilter vectorizedPattern = SimdSupport.vectorizedPattern(pattern);
var filter = LinkedFilter.of(vectorizedPattern == null ? pattern : vectorizedPattern, new CountFilter());
return this.changes = apply(region, filter, true).getRight().getTotal();
}
@Override

View File

@ -2,9 +2,9 @@ package com.fastasyncworldedit.core.queue.implementation.blocks;
import com.fastasyncworldedit.core.FaweCache;
import com.fastasyncworldedit.core.extent.processor.heightmap.HeightMapType;
import com.fastasyncworldedit.core.nbt.FaweCompoundTag;
import com.fastasyncworldedit.core.queue.IChunkSet;
import com.fastasyncworldedit.core.util.collection.MemBlockSet;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.world.biome.BiomeType;
import com.sk89q.worldedit.world.block.BlockState;
@ -13,6 +13,7 @@ import com.sk89q.worldedit.world.block.BlockTypesCache;
import javax.annotation.Nullable;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Map;
import java.util.Set;
@ -74,7 +75,7 @@ public class BitSetBlocks implements IChunkSet {
}
@Override
public boolean setTile(int x, int y, int z, CompoundTag tile) {
public boolean tile(final int x, final int y, final int z, final FaweCompoundTag tag) {
return false;
}
@ -107,7 +108,7 @@ public class BitSetBlocks implements IChunkSet {
}
@Override
public void setEntity(CompoundTag tag) {
public void entity(final FaweCompoundTag tag) {
}
@Override
@ -181,18 +182,18 @@ public class BitSetBlocks implements IChunkSet {
}
@Override
public Map<BlockVector3, CompoundTag> getTiles() {
public Map<BlockVector3, FaweCompoundTag> tiles() {
return Collections.emptyMap();
}
@Override
public CompoundTag getTile(int x, int y, int z) {
public @Nullable FaweCompoundTag tile(final int x, final int y, final int z) {
return null;
}
@Override
public Set<CompoundTag> getEntities() {
return Collections.emptySet();
public Collection<FaweCompoundTag> entities() {
return Collections.emptyList();
}
@Override

View File

@ -1,5 +1,6 @@
package com.fastasyncworldedit.core.queue.implementation.blocks;
import com.fastasyncworldedit.core.queue.IBlocks;
import com.fastasyncworldedit.core.queue.IChunkGet;
import com.fastasyncworldedit.core.queue.IChunkSet;
import com.sk89q.worldedit.world.block.BaseBlock;
@ -20,7 +21,7 @@ public abstract class CharGetBlocks extends CharBlocks implements IChunkGet {
@Override
public BaseBlock getFullBlock(int x, int y, int z) {
BlockState state = BlockTypesCache.states[get(x, y, z)];
return state.toBaseBlock(this, x, y, z);
return state.toBaseBlock((IBlocks) this, x, y, z);
}
@Override

View File

@ -4,16 +4,18 @@ import com.fastasyncworldedit.core.FaweCache;
import com.fastasyncworldedit.core.configuration.Settings;
import com.fastasyncworldedit.core.extent.processor.heightmap.HeightMapType;
import com.fastasyncworldedit.core.math.BlockVector3ChunkMap;
import com.fastasyncworldedit.core.nbt.FaweCompoundTag;
import com.fastasyncworldedit.core.queue.IChunkSet;
import com.fastasyncworldedit.core.queue.Pool;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.world.biome.BiomeType;
import com.sk89q.worldedit.world.block.BlockStateHolder;
import com.sk89q.worldedit.world.block.BlockTypesCache;
import javax.annotation.Nullable;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.EnumMap;
import java.util.HashSet;
@ -36,8 +38,8 @@ public class CharSetBlocks extends CharBlocks implements IChunkSet {
public BiomeType[][] biomes;
public char[][] light;
public char[][] skyLight;
public BlockVector3ChunkMap<CompoundTag> tiles;
public HashSet<CompoundTag> entities;
public BlockVector3ChunkMap<FaweCompoundTag> tiles;
public HashSet<FaweCompoundTag> entities;
public HashSet<UUID> entityRemoves;
public EnumMap<HeightMapType, int[]> heightMaps;
private boolean fastMode = false;
@ -71,17 +73,17 @@ public class CharSetBlocks extends CharBlocks implements IChunkSet {
}
@Override
public Map<BlockVector3, CompoundTag> getTiles() {
public Map<BlockVector3, FaweCompoundTag> tiles() {
return tiles == null ? Collections.emptyMap() : tiles;
}
@Override
public CompoundTag getTile(int x, int y, int z) {
public @Nullable FaweCompoundTag tile(final int x, final int y, final int z) {
return tiles == null ? null : tiles.get(x, y, z);
}
@Override
public Set<CompoundTag> getEntities() {
public Collection<FaweCompoundTag> entities() {
return entities == null ? Collections.emptySet() : entities;
}
@ -132,12 +134,12 @@ public class CharSetBlocks extends CharBlocks implements IChunkSet {
}
@Override
public boolean setTile(int x, int y, int z, CompoundTag tile) {
public boolean tile(final int x, final int y, final int z, final FaweCompoundTag tag) {
if (tiles == null) {
tiles = new BlockVector3ChunkMap<>();
}
updateSectionIndexRange(y >> 4);
tiles.put(x, y, z, tile);
tiles.put(x, y, z, tag);
return true;
}
@ -259,7 +261,7 @@ public class CharSetBlocks extends CharBlocks implements IChunkSet {
}
@Override
public void setEntity(CompoundTag tag) {
public void entity(final FaweCompoundTag tag) {
if (entities == null) {
entities = new HashSet<>();
}

View File

@ -2,10 +2,10 @@ package com.fastasyncworldedit.core.queue.implementation.blocks;
import com.fastasyncworldedit.core.FaweCache;
import com.fastasyncworldedit.core.extent.processor.heightmap.HeightMapType;
import com.fastasyncworldedit.core.nbt.FaweCompoundTag;
import com.fastasyncworldedit.core.queue.IBlocks;
import com.fastasyncworldedit.core.queue.IChunkGet;
import com.fastasyncworldedit.core.queue.IChunkSet;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.world.biome.BiomeType;
import com.sk89q.worldedit.world.biome.BiomeTypes;
@ -15,9 +15,9 @@ import com.sk89q.worldedit.world.block.BlockTypes;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.Collection;
import java.util.Collections;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.Future;
@ -48,24 +48,19 @@ public final class NullChunkGet implements IChunkGet {
return BlockTypes.AIR.getDefaultState();
}
@Nonnull
public Map<BlockVector3, CompoundTag> getTiles() {
@Override
public Map<BlockVector3, FaweCompoundTag> tiles() {
return Collections.emptyMap();
}
@Nullable
public CompoundTag getTile(int x, int y, int z) {
@Override
public @Nullable FaweCompoundTag tile(final int x, final int y, final int z) {
return null;
}
@Nullable
public Set<CompoundTag> getEntities() {
return null;
}
@Nullable
public CompoundTag getEntity(@Nonnull UUID uuid) {
return null;
@Override
public Collection<FaweCompoundTag> entities() {
return Collections.emptyList();
}
@Override
@ -123,6 +118,11 @@ public final class NullChunkGet implements IChunkGet {
return null;
}
@Override
public @Nullable FaweCompoundTag entity(final UUID uuid) {
return null;
}
@Nonnull
public char[] load(int layer) {
return FaweCache.INSTANCE.EMPTY_CHAR_4096;

View File

@ -4,9 +4,9 @@ import com.fastasyncworldedit.core.Fawe;
import com.fastasyncworldedit.core.FaweCache;
import com.fastasyncworldedit.core.extent.processor.heightmap.HeightMapType;
import com.fastasyncworldedit.core.math.BlockVector3ChunkMap;
import com.fastasyncworldedit.core.nbt.FaweCompoundTag;
import com.fastasyncworldedit.core.queue.IBlocks;
import com.fastasyncworldedit.core.queue.IChunkSet;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.worldedit.internal.util.LogManagerCompat;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.world.biome.BiomeType;
@ -17,6 +17,7 @@ import org.apache.logging.log4j.Logger;
import org.jetbrains.annotations.Nullable;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.EnumMap;
import java.util.HashMap;
@ -44,8 +45,8 @@ public class ThreadUnsafeCharBlocks implements IChunkSet, IBlocks {
private BiomeType[][] biomes;
private char[][] light;
private char[][] skyLight;
private BlockVector3ChunkMap<CompoundTag> tiles;
private HashSet<CompoundTag> entities;
private BlockVector3ChunkMap<FaweCompoundTag> tiles;
private HashSet<FaweCompoundTag> entities;
private HashSet<UUID> entityRemoves;
private Map<HeightMapType, int[]> heightMaps;
private boolean fastMode;
@ -64,8 +65,8 @@ public class ThreadUnsafeCharBlocks implements IChunkSet, IBlocks {
int sectionCount,
char[][] light,
char[][] skyLight,
BlockVector3ChunkMap<CompoundTag> tiles,
HashSet<CompoundTag> entities,
BlockVector3ChunkMap<FaweCompoundTag> tiles,
HashSet<FaweCompoundTag> entities,
HashSet<UUID> entityRemoves,
Map<HeightMapType, int[]> heightMaps,
char defaultOrdinal,
@ -116,18 +117,18 @@ public class ThreadUnsafeCharBlocks implements IChunkSet, IBlocks {
}
@Override
public Map<BlockVector3, CompoundTag> getTiles() {
public Map<BlockVector3, FaweCompoundTag> tiles() {
return tiles == null ? Collections.emptyMap() : tiles;
}
@Override
public CompoundTag getTile(int x, int y, int z) {
public @Nullable FaweCompoundTag tile(final int x, final int y, final int z) {
return tiles == null ? null : tiles.get(x, y, z);
}
@Override
public Set<CompoundTag> getEntities() {
return entities == null ? Collections.emptySet() : entities;
public Collection<FaweCompoundTag> entities() {
return entities == null ? Collections.emptyList() : entities;
}
@Override
@ -268,12 +269,12 @@ public class ThreadUnsafeCharBlocks implements IChunkSet, IBlocks {
}
@Override
public boolean setTile(int x, int y, int z, CompoundTag tile) {
public boolean tile(final int x, final int y, final int z, final FaweCompoundTag tag) {
updateSectionIndexRange(y >> 4);
if (tiles == null) {
tiles = new BlockVector3ChunkMap<>();
}
tiles.put(x, y, z, tile);
tiles.put(x, y, z, tag);
return true;
}
@ -358,7 +359,7 @@ public class ThreadUnsafeCharBlocks implements IChunkSet, IBlocks {
}
@Override
public void setEntity(CompoundTag tag) {
public void entity(final FaweCompoundTag tag) {
if (entities == null) {
entities = new HashSet<>();
}

View File

@ -3,6 +3,7 @@ package com.fastasyncworldedit.core.queue.implementation.chunk;
import com.fastasyncworldedit.core.extent.filter.block.ChunkFilterBlock;
import com.fastasyncworldedit.core.extent.processor.EmptyBatchProcessor;
import com.fastasyncworldedit.core.extent.processor.heightmap.HeightMapType;
import com.fastasyncworldedit.core.nbt.FaweCompoundTag;
import com.fastasyncworldedit.core.queue.Filter;
import com.fastasyncworldedit.core.queue.IChunk;
import com.fastasyncworldedit.core.queue.IChunkGet;
@ -11,7 +12,6 @@ import com.fastasyncworldedit.core.queue.IQueueChunk;
import com.fastasyncworldedit.core.queue.IQueueExtent;
import com.fastasyncworldedit.core.queue.implementation.ParallelQueueExtent;
import com.fastasyncworldedit.core.util.MemUtil;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.worldedit.internal.util.LogManagerCompat;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.regions.Region;
@ -22,6 +22,7 @@ import com.sk89q.worldedit.world.block.BlockStateHolder;
import org.apache.logging.log4j.Logger;
import javax.annotation.Nullable;
import java.util.Collection;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
@ -76,18 +77,8 @@ public class ChunkHolder<T extends Future<T>> implements IQueueChunk<T> {
}
@Override
public boolean setTile(int x, int y, int z, CompoundTag tag) {
return delegate.set(this).setTile(x, y, z, tag);
}
@Override
public CompoundTag getTile(int x, int y, int z) {
return delegate.set(this).getTile(x, y, z);
}
@Override
public void setEntity(CompoundTag tag) {
delegate.set(this).setEntity(tag);
public void entity(final FaweCompoundTag tag) {
delegate.set(this).entity(tag);
}
@Override
@ -163,11 +154,6 @@ public class ChunkHolder<T extends Future<T>> implements IQueueChunk<T> {
return isInit;
}
@Override
public CompoundTag getEntity(UUID uuid) {
return delegate.get(this).getEntity(uuid);
}
@Override
public int setCreateCopy(boolean createCopy) {
this.createCopy = createCopy;
@ -879,16 +865,6 @@ public class ChunkHolder<T extends Future<T>> implements IQueueChunk<T> {
}
};
@Override
public Map<BlockVector3, CompoundTag> getTiles() {
return delegate.get(this).getTiles();
}
@Override
public Set<CompoundTag> getEntities() {
return delegate.get(this).getEntities();
}
@Override
public boolean hasSection(int layer) {
return chunkExisting != null && chunkExisting.hasSection(layer);
@ -946,6 +922,11 @@ public class ChunkHolder<T extends Future<T>> implements IQueueChunk<T> {
return chunkSet == null || chunkSet.isEmpty();
}
@Override
public boolean tile(final int x, final int y, final int z, final FaweCompoundTag tag) {
return false;
}
/**
* Get or create the existing part of this chunk.
*/
@ -1093,6 +1074,21 @@ public class ChunkHolder<T extends Future<T>> implements IQueueChunk<T> {
return delegate.getBlock(this, x, y, z);
}
@Override
public Map<BlockVector3, FaweCompoundTag> tiles() {
return delegate.get(this).tiles();
}
@Override
public @Nullable FaweCompoundTag tile(final int x, final int y, final int z) {
return delegate.get(this).tile(x, y, z);
}
@Override
public Collection<FaweCompoundTag> entities() {
return delegate.get(this).entities();
}
@Override
public BaseBlock getFullBlock(int x, int y, int z) {
return delegate.getFullBlock(this, x, y, z);
@ -1158,6 +1154,11 @@ public class ChunkHolder<T extends Future<T>> implements IQueueChunk<T> {
return delegate.getHeightMap(this, type);
}
@Override
public @Nullable FaweCompoundTag entity(final UUID uuid) {
return delegate.get(this).entity(uuid);
}
public interface IBlockDelegate {
<C extends Future<C>> IChunkGet get(ChunkHolder<C> chunk);

View File

@ -2,10 +2,10 @@ package com.fastasyncworldedit.core.queue.implementation.chunk;
import com.fastasyncworldedit.core.extent.filter.block.ChunkFilterBlock;
import com.fastasyncworldedit.core.extent.processor.heightmap.HeightMapType;
import com.fastasyncworldedit.core.nbt.FaweCompoundTag;
import com.fastasyncworldedit.core.queue.Filter;
import com.fastasyncworldedit.core.queue.IChunkSet;
import com.fastasyncworldedit.core.queue.IQueueChunk;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.world.biome.BiomeType;
@ -16,6 +16,7 @@ import com.sk89q.worldedit.world.block.BlockTypes;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.Collection;
import java.util.Collections;
import java.util.Map;
import java.util.Set;
@ -53,13 +54,11 @@ public final class NullChunk implements IQueueChunk {
return false;
}
public boolean setTile(int x, int y, int z, @Nonnull CompoundTag tag) {
@Override
public boolean tile(final int x, final int y, final int z, final FaweCompoundTag tag) {
return false;
}
public void setEntity(@Nonnull CompoundTag tag) {
}
public void removeEntity(@Nonnull UUID uuid) {
}
@ -112,6 +111,10 @@ public final class NullChunk implements IQueueChunk {
public void setFullBright(int layer) {
}
@Override
public void entity(final FaweCompoundTag tag) {
}
public void removeSectionLighting(int layer, boolean sky) {
}
@ -147,25 +150,26 @@ public final class NullChunk implements IQueueChunk {
return BlockTypes.__RESERVED__.getDefaultState();
}
@Override
public Map<BlockVector3, FaweCompoundTag> tiles() {
return Collections.emptyMap();
}
@Override
public @Nullable FaweCompoundTag tile(final int x, final int y, final int z) {
return null;
}
@Override
public Collection<FaweCompoundTag> entities() {
return Collections.emptyList();
}
@Nonnull
public BaseBlock getFullBlock(int x, int y, int z) {
return BlockTypes.__RESERVED__.getDefaultState().toBaseBlock();
}
@Nonnull
public Map<BlockVector3, CompoundTag> getTiles() {
return Collections.emptyMap();
}
@Nullable
public CompoundTag getTile(int x, int y, int z) {
return null;
}
@Nonnull
public Set<CompoundTag> getEntities() {
return Collections.emptySet();
}
@Nullable
public char[] load(int layer) {
@ -178,11 +182,6 @@ public final class NullChunk implements IQueueChunk {
return null;
}
@Nullable
public CompoundTag getEntity(@Nonnull UUID uuid) {
return null;
}
@Override
public int setCreateCopy(boolean createCopy) {
return -1;
@ -230,6 +229,11 @@ public final class NullChunk implements IQueueChunk {
return null;
}
@Override
public @Nullable FaweCompoundTag entity(final UUID uuid) {
return null;
}
public boolean trim(boolean aggressive) {
return true;
}

Some files were not shown because too many files have changed in this diff Show More