Revert "Revert matt's changes"

This reverts commit bfcc6184ad.
This commit is contained in:
IronApollo 2020-06-13 14:41:36 -04:00
parent bfcc6184ad
commit 238c56a3c6
75 changed files with 980 additions and 687 deletions

View File

@ -7,7 +7,7 @@ New contributions must be licensed under:
GNU LESSER GENERAL PUBLIC LICENSE GNU LESSER GENERAL PUBLIC LICENSE
Version 3, 29 June 2007 Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/> Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed. of this license document, but changing it is not allowed.
@ -180,7 +180,7 @@ WorldEdit as a whole is licensed under:
GNU GENERAL PUBLIC LICENSE GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007 Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/> Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed. of this license document, but changing it is not allowed.

View File

@ -1,8 +1,8 @@
import org.gradle.api.Project import org.gradle.api.Project
object Versions { object Versions {
const val TEXT = "3.0.3" const val TEXT = "3.0.4"
const val TEXT_EXTRAS = "3.0.3" const val TEXT_EXTRAS = "3.0.5"
const val PISTON = "0.5.5" const val PISTON = "0.5.5"
const val AUTO_VALUE = "1.7" const val AUTO_VALUE = "1.7"
const val JUNIT = "5.6.1" const val JUNIT = "5.6.1"

View File

@ -73,6 +73,7 @@
<allow pkg="org.spongepowered.api" /> <allow pkg="org.spongepowered.api" />
<allow pkg="com.mojang.brigadier" /> <allow pkg="com.mojang.brigadier" />
<allow pkg="com.mojang.datafixers" /> <allow pkg="com.mojang.datafixers" />
<allow pkg="org.apache.commons" />
</subpackage> </subpackage>
<subpackage name="fabric"> <subpackage name="fabric">

View File

@ -128,6 +128,7 @@ public class BukkitGetBlocks_1_14 extends CharGetBlocks {
public int getSkyLight(int x, int y, int z) { public int getSkyLight(int x, int y, int z) {
int layer = y >> 4; int layer = y >> 4;
if (skyLight[layer] == null) { if (skyLight[layer] == null) {
//getDataLayerData
skyLight[layer] = world.getChunkProvider().getLightEngine().a(EnumSkyBlock.SKY).a(SectionPosition.a(nmsChunk.getPos(), layer)); skyLight[layer] = world.getChunkProvider().getLightEngine().a(EnumSkyBlock.SKY).a(SectionPosition.a(nmsChunk.getPos(), layer));
} }
long l = BlockPosition.a(x, y, z); long l = BlockPosition.a(x, y, z);
@ -138,6 +139,7 @@ public class BukkitGetBlocks_1_14 extends CharGetBlocks {
public int getEmmittedLight(int x, int y, int z) { public int getEmmittedLight(int x, int y, int z) {
int layer = y >> 4; int layer = y >> 4;
if (blockLight[layer] == null) { if (blockLight[layer] == null) {
//getDataLayerData
blockLight[layer] = world.getChunkProvider().getLightEngine().a(EnumSkyBlock.BLOCK).a(SectionPosition.a(nmsChunk.getPos(), layer)); blockLight[layer] = world.getChunkProvider().getLightEngine().a(EnumSkyBlock.BLOCK).a(SectionPosition.a(nmsChunk.getPos(), layer));
} }
long l = BlockPosition.a(x, y, z); long l = BlockPosition.a(x, y, z);

View File

@ -20,11 +20,6 @@
package com.sk89q.bukkit.util; package com.sk89q.bukkit.util;
import com.sk89q.util.ReflectionUtil; import com.sk89q.util.ReflectionUtil;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.command.Command; import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor; import org.bukkit.command.CommandExecutor;
@ -33,6 +28,12 @@ import org.bukkit.command.PluginIdentifiableCommand;
import org.bukkit.command.SimpleCommandMap; import org.bukkit.command.SimpleCommandMap;
import org.bukkit.plugin.Plugin; import org.bukkit.plugin.Plugin;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
public class CommandRegistration { public class CommandRegistration {
static { static {
@ -61,6 +62,7 @@ public class CommandRegistration {
} }
return null; return null;
} }
public boolean register(List<CommandInfo> registered) { public boolean register(List<CommandInfo> registered) {
CommandMap commandMap = getCommandMap(); CommandMap commandMap = getCommandMap();
if (registered == null || commandMap == null) { if (registered == null || commandMap == null) {
@ -82,12 +84,13 @@ public class CommandRegistration {
if (fallbackCommands != null) { if (fallbackCommands != null) {
return fallbackCommands; return fallbackCommands;
} }
CommandMap commandMap = ReflectionUtil.getField(plugin.getServer().getPluginManager(), "commandMap"); CommandMap commandMap = ReflectionUtil.getField(plugin.getServer().getPluginManager(), "commandMap");
if (commandMap == null) { if (commandMap == null) {
Bukkit.getServer().getLogger().severe(plugin.getDescription().getName() + Bukkit.getServer().getLogger().severe(plugin.getDescription().getName() +
": Could not retrieve server CommandMap, using fallback instead!"); ": Could not retrieve server CommandMap, using fallback instead!");
fallbackCommands = commandMap = new SimpleCommandMap(Bukkit.getServer()); fallbackCommands = commandMap = new SimpleCommandMap(Bukkit.getServer());
Bukkit.getServer().getPluginManager().registerEvents(new FallbackRegistrationListener(fallbackCommands), plugin); Bukkit.getServer().getPluginManager().registerEvents(new FallbackRegistrationListener(fallbackCommands), plugin);
} else { } else {
serverCommandMap = commandMap; serverCommandMap = commandMap;
} }

View File

@ -31,7 +31,7 @@ import java.nio.charset.StandardCharsets;
*/ */
public class CUIChannelListener implements PluginMessageListener { public class CUIChannelListener implements PluginMessageListener {
public static final Charset UTF_8_CHARSET = Charset.forName("UTF-8"); public static final Charset UTF_8_CHARSET = StandardCharsets.UTF_8;
private final WorldEditPlugin plugin; private final WorldEditPlugin plugin;
public CUIChannelListener(WorldEditPlugin plugin) { public CUIChannelListener(WorldEditPlugin plugin) {

View File

@ -117,27 +117,6 @@ public class FaweAPI {
// return parser != null; // return parser != null;
// } // }
public static <T> T getParser(Class<T> parserClass) {
try {
Field field = AbstractFactory.class.getDeclaredField("parsers");
field.setAccessible(true);
ArrayList<InputParser> parsers = new ArrayList<>();
parsers.addAll((List<InputParser>) field.get(WorldEdit.getInstance().getMaskFactory()));
parsers.addAll((List<InputParser>) field.get(WorldEdit.getInstance().getBlockFactory()));
parsers.addAll((List<InputParser>) field.get(WorldEdit.getInstance().getItemFactory()));
parsers.addAll((List<InputParser>) field.get(WorldEdit.getInstance().getPatternFactory()));
for (InputParser parser : parsers) {
if (parserClass.isAssignableFrom(parser.getClass())) {
return (T) parser;
}
}
return null;
} catch (Throwable e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
/** /**
* You can either use a IQueueExtent or an EditSession to change blocks<br> * You can either use a IQueueExtent or an EditSession to change blocks<br>
* - The IQueueExtent skips a bit of overhead so it's marginally faster<br> * - The IQueueExtent skips a bit of overhead so it's marginally faster<br>

View File

@ -50,7 +50,7 @@ public class AsyncPreloader implements Preloader, Runnable {
MutablePair<World, Set<BlockVector2>> existing = cancelAndGet(player); MutablePair<World, Set<BlockVector2>> existing = cancelAndGet(player);
try { try {
Region region = session.getSelection(world); Region region = session.getSelection(world);
if (!(region instanceof CuboidRegion) || region.getArea() > 50466816) { if (!(region instanceof CuboidRegion) || region.getVolume() > 50466816) {
// TOO LARGE or NOT CUBOID // TOO LARGE or NOT CUBOID
return; return;
} }

View File

@ -428,7 +428,7 @@ public class NMSRelighter implements Relighter {
} }
} }
for (int y = 255; y > 0; y--) { for (int y = 255; y > 0; y--) {
for (RelightSkyEntry chunk : chunks) { // Propogate skylight for (RelightSkyEntry chunk : chunks) { // Propagate skylight
int layer = y >> 4; int layer = y >> 4;
byte[] mask = chunk.mask; byte[] mask = chunk.mask;
if ((y & 15) == 15 && chunk.fix[layer] != SkipReason.NONE) { if ((y & 15) == 15 && chunk.fix[layer] != SkipReason.NONE) {
@ -596,7 +596,7 @@ public class NMSRelighter implements Relighter {
} }
} }
private class RelightSkyEntry implements Comparable { private class RelightSkyEntry implements Comparable<RelightSkyEntry> {
public final int x; public final int x;
public final int z; public final int z;
public final byte[] mask; public final byte[] mask;
@ -625,18 +625,17 @@ public class NMSRelighter implements Relighter {
} }
@Override @Override
public int compareTo(Object o) { public int compareTo(RelightSkyEntry o) {
RelightSkyEntry other = (RelightSkyEntry) o; if (o.x < x) {
if (other.x < x) {
return 1; return 1;
} }
if (other.x > x) { if (o.x > x) {
return -1; return -1;
} }
if (other.z < z) { if (o.z < z) {
return 1; return 1;
} }
if (other.z > z) { if (o.z > z) {
return -1; return -1;
} }
return 0; return 0;

View File

@ -52,7 +52,7 @@ public class LimitExtent extends PassthroughExtent {
@Override @Override
public List<? extends Entity> getEntities(Region region) { public List<? extends Entity> getEntities(Region region) {
limit.THROW_MAX_CHECKS(region.getArea()); limit.THROW_MAX_CHECKS(region.getVolume());
try { try {
return getExtent().getEntities(region); return getExtent().getEntities(region);
} catch (FaweException e) { } catch (FaweException e) {
@ -223,8 +223,8 @@ public class LimitExtent extends PassthroughExtent {
@Override @Override
public void addCaves(Region region) throws WorldEditException { public void addCaves(Region region) throws WorldEditException {
limit.THROW_MAX_CHECKS(region.getArea()); limit.THROW_MAX_CHECKS(region.getVolume());
limit.THROW_MAX_CHANGES(region.getArea()); limit.THROW_MAX_CHANGES(region.getVolume());
try { try {
getExtent().addCaves(region); getExtent().addCaves(region);
} catch (FaweException e) { } catch (FaweException e) {
@ -236,8 +236,8 @@ public class LimitExtent extends PassthroughExtent {
@Override @Override
public void generate(Region region, GenBase gen) throws WorldEditException { public void generate(Region region, GenBase gen) throws WorldEditException {
limit.THROW_MAX_CHECKS(region.getArea()); limit.THROW_MAX_CHECKS(region.getVolume());
limit.THROW_MAX_CHANGES(region.getArea()); limit.THROW_MAX_CHANGES(region.getVolume());
try { try {
getExtent().generate(region, gen); getExtent().generate(region, gen);
} catch (FaweException e) { } catch (FaweException e) {
@ -249,8 +249,8 @@ public class LimitExtent extends PassthroughExtent {
@Override @Override
public void addSchems(Region region, Mask mask, List<ClipboardHolder> clipboards, int rarity, boolean rotate) throws WorldEditException { public void addSchems(Region region, Mask mask, List<ClipboardHolder> clipboards, int rarity, boolean rotate) throws WorldEditException {
limit.THROW_MAX_CHECKS(region.getArea()); limit.THROW_MAX_CHECKS(region.getVolume());
limit.THROW_MAX_CHANGES(region.getArea()); limit.THROW_MAX_CHANGES(region.getVolume());
try { try {
getExtent().addSchems(region, mask, clipboards, rarity, rotate); getExtent().addSchems(region, mask, clipboards, rarity, rotate);
} catch (FaweException e) { } catch (FaweException e) {
@ -262,8 +262,8 @@ public class LimitExtent extends PassthroughExtent {
@Override @Override
public void spawnResource(Region region, Resource gen, int rarity, int frequency) throws WorldEditException { public void spawnResource(Region region, Resource gen, int rarity, int frequency) throws WorldEditException {
limit.THROW_MAX_CHECKS(region.getArea()); limit.THROW_MAX_CHECKS(region.getVolume());
limit.THROW_MAX_CHANGES(region.getArea()); limit.THROW_MAX_CHANGES(region.getVolume());
try { try {
getExtent().spawnResource(region, gen, rarity, frequency); getExtent().spawnResource(region, gen, rarity, frequency);
} catch (FaweException e) { } catch (FaweException e) {
@ -275,8 +275,8 @@ public class LimitExtent extends PassthroughExtent {
@Override @Override
public void addOre(Region region, Mask mask, Pattern material, int size, int frequency, int rarity, int minY, int maxY) throws WorldEditException { 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.getArea()); limit.THROW_MAX_CHECKS(region.getVolume());
limit.THROW_MAX_CHANGES(region.getArea()); limit.THROW_MAX_CHANGES(region.getVolume());
try { try {
getExtent().addOre(region, mask, material, size, frequency, rarity, minY, maxY); getExtent().addOre(region, mask, material, size, frequency, rarity, minY, maxY);
} catch (FaweException e) { } catch (FaweException e) {
@ -288,8 +288,8 @@ public class LimitExtent extends PassthroughExtent {
@Override @Override
public void addOres(Region region, Mask mask) throws WorldEditException { public void addOres(Region region, Mask mask) throws WorldEditException {
limit.THROW_MAX_CHECKS(region.getArea()); limit.THROW_MAX_CHECKS(region.getVolume());
limit.THROW_MAX_CHANGES(region.getArea()); limit.THROW_MAX_CHANGES(region.getVolume());
try { try {
getExtent().addOres(region, mask); getExtent().addOres(region, mask);
} catch (FaweException e) { } catch (FaweException e) {
@ -301,7 +301,7 @@ public class LimitExtent extends PassthroughExtent {
@Override @Override
public List<Countable<BlockType>> getBlockDistribution(Region region) { public List<Countable<BlockType>> getBlockDistribution(Region region) {
limit.THROW_MAX_CHECKS(region.getArea()); limit.THROW_MAX_CHECKS(region.getVolume());
try { try {
return getExtent().getBlockDistribution(region); return getExtent().getBlockDistribution(region);
} catch (FaweException e) { } catch (FaweException e) {
@ -314,7 +314,7 @@ public class LimitExtent extends PassthroughExtent {
@Override @Override
public List<Countable<BlockState>> getBlockDistributionWithData(Region region) { public List<Countable<BlockState>> getBlockDistributionWithData(Region region) {
limit.THROW_MAX_CHECKS(region.getArea()); limit.THROW_MAX_CHECKS(region.getVolume());
try { try {
return getExtent().getBlockDistributionWithData(region); return getExtent().getBlockDistributionWithData(region);
} catch (FaweException e) { } catch (FaweException e) {
@ -327,7 +327,7 @@ public class LimitExtent extends PassthroughExtent {
@Override @Override
public int countBlocks(Region region, Set<BaseBlock> searchBlocks) { public int countBlocks(Region region, Set<BaseBlock> searchBlocks) {
limit.THROW_MAX_CHECKS(region.getArea()); limit.THROW_MAX_CHECKS(region.getVolume());
try { try {
return getExtent().countBlocks(region, searchBlocks); return getExtent().countBlocks(region, searchBlocks);
} catch (FaweException e) { } catch (FaweException e) {
@ -340,7 +340,7 @@ public class LimitExtent extends PassthroughExtent {
@Override @Override
public int countBlocks(Region region, Mask searchMask) { public int countBlocks(Region region, Mask searchMask) {
limit.THROW_MAX_CHECKS(region.getArea()); limit.THROW_MAX_CHECKS(region.getVolume());
try { try {
return getExtent().countBlocks(region, searchMask); return getExtent().countBlocks(region, searchMask);
} catch (FaweException e) { } catch (FaweException e) {
@ -353,7 +353,7 @@ public class LimitExtent extends PassthroughExtent {
@Override @Override
public <B extends BlockStateHolder<B>> int setBlocks(Region region, B block) throws MaxChangedBlocksException { public <B extends BlockStateHolder<B>> int setBlocks(Region region, B block) throws MaxChangedBlocksException {
limit.THROW_MAX_CHANGES(region.getArea()); limit.THROW_MAX_CHANGES(region.getVolume());
try { try {
return getExtent().setBlocks(region, block); return getExtent().setBlocks(region, block);
} catch (FaweException e) { } catch (FaweException e) {
@ -366,7 +366,7 @@ public class LimitExtent extends PassthroughExtent {
@Override @Override
public int setBlocks(Region region, Pattern pattern) throws MaxChangedBlocksException { public int setBlocks(Region region, Pattern pattern) throws MaxChangedBlocksException {
limit.THROW_MAX_CHANGES(region.getArea()); limit.THROW_MAX_CHANGES(region.getVolume());
try { try {
return getExtent().setBlocks(region, pattern); return getExtent().setBlocks(region, pattern);
} catch (FaweException e) { } catch (FaweException e) {
@ -379,8 +379,8 @@ public class LimitExtent extends PassthroughExtent {
@Override @Override
public <B extends BlockStateHolder<B>> int replaceBlocks(Region region, Set<BaseBlock> filter, B replacement) throws MaxChangedBlocksException { public <B extends BlockStateHolder<B>> int replaceBlocks(Region region, Set<BaseBlock> filter, B replacement) throws MaxChangedBlocksException {
limit.THROW_MAX_CHECKS(region.getArea()); limit.THROW_MAX_CHECKS(region.getVolume());
limit.THROW_MAX_CHANGES(region.getArea()); limit.THROW_MAX_CHANGES(region.getVolume());
try { try {
return getExtent().replaceBlocks(region, filter, replacement); return getExtent().replaceBlocks(region, filter, replacement);
} catch (FaweException e) { } catch (FaweException e) {
@ -393,8 +393,8 @@ public class LimitExtent extends PassthroughExtent {
@Override @Override
public int replaceBlocks(Region region, Set<BaseBlock> filter, Pattern pattern) throws MaxChangedBlocksException { public int replaceBlocks(Region region, Set<BaseBlock> filter, Pattern pattern) throws MaxChangedBlocksException {
limit.THROW_MAX_CHECKS(region.getArea()); limit.THROW_MAX_CHECKS(region.getVolume());
limit.THROW_MAX_CHANGES(region.getArea()); limit.THROW_MAX_CHANGES(region.getVolume());
try { try {
return getExtent().replaceBlocks(region, filter, pattern); return getExtent().replaceBlocks(region, filter, pattern);
} catch (FaweException e) { } catch (FaweException e) {
@ -407,8 +407,8 @@ public class LimitExtent extends PassthroughExtent {
@Override @Override
public int replaceBlocks(Region region, Mask mask, Pattern pattern) throws MaxChangedBlocksException { public int replaceBlocks(Region region, Mask mask, Pattern pattern) throws MaxChangedBlocksException {
limit.THROW_MAX_CHECKS(region.getArea()); limit.THROW_MAX_CHECKS(region.getVolume());
limit.THROW_MAX_CHANGES(region.getArea()); limit.THROW_MAX_CHANGES(region.getVolume());
try { try {
return getExtent().replaceBlocks(region, mask, pattern); return getExtent().replaceBlocks(region, mask, pattern);
} catch (FaweException e) { } catch (FaweException e) {
@ -421,8 +421,8 @@ public class LimitExtent extends PassthroughExtent {
@Override @Override
public int center(Region region, Pattern pattern) throws MaxChangedBlocksException { public int center(Region region, Pattern pattern) throws MaxChangedBlocksException {
limit.THROW_MAX_CHECKS(region.getArea()); limit.THROW_MAX_CHECKS(region.getVolume());
limit.THROW_MAX_CHANGES(region.getArea()); limit.THROW_MAX_CHANGES(region.getVolume());
try { try {
return getExtent().center(region, pattern); return getExtent().center(region, pattern);
} catch (FaweException e) { } catch (FaweException e) {
@ -448,8 +448,8 @@ public class LimitExtent extends PassthroughExtent {
@Override @Override
public <T extends Filter> T apply(Region region, T filter, boolean full) { public <T extends Filter> T apply(Region region, T filter, boolean full) {
limit.THROW_MAX_CHECKS(region.getArea()); limit.THROW_MAX_CHECKS(region.getVolume());
limit.THROW_MAX_CHANGES(region.getArea()); limit.THROW_MAX_CHANGES(region.getVolume());
try { try {
return getExtent().apply(region, filter, full); return getExtent().apply(region, filter, full);
} catch (FaweException e) { } catch (FaweException e) {

View File

@ -151,10 +151,6 @@ public abstract class QueueHandler implements Trimable, Runnable {
return forkJoinPoolPrimary.submit(call); return forkJoinPoolPrimary.submit(call);
} }
public <T> Future<T> sync(Runnable run, T value) {
return sync(run, value, syncTasks);
}
public <T> Future<T> sync(Runnable run) { public <T> Future<T> sync(Runnable run) {
return sync(run, syncTasks); return sync(run, syncTasks);
} }

View File

@ -1,22 +1,3 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.boydti.fawe.function.mask; package com.boydti.fawe.function.mask;
import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.extent.Extent;

View File

@ -1,22 +1,3 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.boydti.fawe.function.mask; package com.boydti.fawe.function.mask;
import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.extent.Extent;

View File

@ -9,6 +9,10 @@ public class XAxisMask extends AbstractMask implements ResettableMask {
private transient int layer = -1; private transient int layer = -1;
public XAxisMask(Extent extent) {
}
@Override @Override
public boolean test(Extent extent, BlockVector3 vector) { public boolean test(Extent extent, BlockVector3 vector) {
if (layer == -1) { if (layer == -1) {

View File

@ -9,6 +9,9 @@ public class YAxisMask extends AbstractMask implements ResettableMask {
private transient int layer = -1; private transient int layer = -1;
public YAxisMask(Extent extent) {
}
@Override @Override
public boolean test(Extent extent, BlockVector3 vector) { public boolean test(Extent extent, BlockVector3 vector) {
if (layer == -1) { if (layer == -1) {

View File

@ -9,6 +9,9 @@ public class ZAxisMask extends AbstractMask implements ResettableMask {
private transient int layer = -1; private transient int layer = -1;
public ZAxisMask(Extent extent) {
}
@Override @Override
public boolean test(Extent extent, BlockVector3 vector) { public boolean test(Extent extent, BlockVector3 vector) {
if (layer == -1) { if (layer == -1) {

View File

@ -162,6 +162,9 @@ public class FaweLimit {
public void THROW_MAX_CHANGES(int amt) { public void THROW_MAX_CHANGES(int amt) {
if ((MAX_CHANGES -= amt) <= 0) throw FaweCache.MAX_CHANGES; if ((MAX_CHANGES -= amt) <= 0) throw FaweCache.MAX_CHANGES;
} }
public void THROW_MAX_CHANGES(long amt) {
if ((MAX_CHANGES -= amt) <= 0) throw FaweCache.MAX_CHANGES;
}
public void THROW_MAX_FAILS(int amt) { public void THROW_MAX_FAILS(int amt) {
if ((MAX_FAILS -= amt) <= 0) throw FaweCache.MAX_CHECKS; if ((MAX_FAILS -= amt) <= 0) throw FaweCache.MAX_CHECKS;
@ -171,6 +174,10 @@ public class FaweLimit {
if ((MAX_CHECKS -= amt) <= 0) throw FaweCache.MAX_CHECKS; if ((MAX_CHECKS -= amt) <= 0) throw FaweCache.MAX_CHECKS;
} }
public void THROW_MAX_CHECKS(long amt) {
if ((MAX_CHECKS -= amt) <= 0) throw FaweCache.MAX_CHECKS;
}
public void THROW_MAX_ITERATIONS(int amt) { public void THROW_MAX_ITERATIONS(int amt) {
if ((MAX_ITERATIONS -= amt) <= 0) throw FaweCache.MAX_ITERATIONS; if ((MAX_ITERATIONS -= amt) <= 0) throw FaweCache.MAX_ITERATIONS;
} }

View File

@ -2,9 +2,9 @@ package com.boydti.fawe.object;
public final class IntTriple { public final class IntTriple {
public int x; private final int x;
public int y; private final int y;
public int z; private final int z;
public IntTriple(int x, int y, int z) { public IntTriple(int x, int y, int z) {
this.x = x; this.x = x;

View File

@ -1,8 +0,0 @@
package com.boydti.fawe.object;
import java.util.function.Supplier;
public interface Lazy<T> extends Supplier<T> {
Supplier<T> init();
public default T get() { return init().get(); }
}

View File

@ -1,33 +0,0 @@
package com.boydti.fawe.object;
import java.util.function.BiConsumer;
public abstract class RunnableVal2<T, U> implements Runnable, BiConsumer<T, U> {
public T value1;
public U value2;
public RunnableVal2() {
}
public RunnableVal2(T value1, U value2) {
this.value1 = value1;
this.value2 = value2;
}
@Override
public void run() {
run(this.value1, this.value2);
}
public abstract void run(T value1, U value2);
public RunnableVal2<T, U> runAndGet(T value1, U value2) {
run(value1, value2);
return this;
}
@Override
public void accept(T t, U u) {
run(t, u);
}
}

View File

@ -93,7 +93,7 @@ public class CPUOptimizedClipboard extends LinearClipboard {
} }
for (Map.Entry<IntTriple, CompoundTag> entry : nbtMapLoc.entrySet()) { for (Map.Entry<IntTriple, CompoundTag> entry : nbtMapLoc.entrySet()) {
IntTriple key = entry.getKey(); IntTriple key = entry.getKey();
setTile(getIndex(key.x, key.y, key.z), entry.getValue()); setTile(getIndex(key.getX(), key.getY(), key.getZ()), entry.getValue());
} }
nbtMapLoc.clear(); nbtMapLoc.clear();
} }

View File

@ -324,7 +324,7 @@ public class DiskOptimizedClipboard extends LinearClipboard implements Closeable
nbt = null; nbt = null;
for (Map.Entry<IntTriple, CompoundTag> entry : nbtMap.entrySet()) { for (Map.Entry<IntTriple, CompoundTag> entry : nbtMap.entrySet()) {
IntTriple key = entry.getKey(); IntTriple key = entry.getKey();
int index = getIndex(key.x, key.y, key.z); int index = getIndex(key.getX(), key.getY(), key.getZ());
if (index == i) { if (index == i) {
nbt = entry.getValue(); nbt = entry.getValue();
break; break;

View File

@ -200,7 +200,7 @@ public class MemoryOptimizedClipboard extends LinearClipboard {
nbt = null; nbt = null;
for (Map.Entry<IntTriple, CompoundTag> entry : nbtMap.entrySet()) { for (Map.Entry<IntTriple, CompoundTag> entry : nbtMap.entrySet()) {
IntTriple trio = entry.getKey(); IntTriple trio = entry.getKey();
int index = getIndex(trio.x, trio.y, trio.z); int index = getIndex(trio.getX(), trio.getY(), trio.getZ());
if (index == i) { if (index == i) {
nbt = entry.getValue(); nbt = entry.getValue();
break; break;

View File

@ -1,6 +1,7 @@
package com.boydti.fawe.object.mask; package com.boydti.fawe.object.mask;
import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.function.mask.AbstractExtentMask;
import com.sk89q.worldedit.function.mask.AbstractMask; import com.sk89q.worldedit.function.mask.AbstractMask;
import com.sk89q.worldedit.function.mask.Mask; import com.sk89q.worldedit.function.mask.Mask;
import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.math.BlockVector3;
@ -14,7 +15,7 @@ public class AdjacentAnyMask extends AbstractMask implements ResettableMask {
private final CachedMask mask; private final CachedMask mask;
private final MutableBlockVector3 mutable; private final MutableBlockVector3 mutable;
public AdjacentAnyMask(Mask mask) { public AdjacentAnyMask(AbstractExtentMask mask) {
this.mask = CachedMask.cache(mask); this.mask = CachedMask.cache(mask);
mutable = new MutableBlockVector3(); mutable = new MutableBlockVector3();
} }

View File

@ -1,6 +1,7 @@
package com.boydti.fawe.object.mask; package com.boydti.fawe.object.mask;
import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.function.mask.AbstractExtentMask;
import com.sk89q.worldedit.function.mask.BlockMaskBuilder; import com.sk89q.worldedit.function.mask.BlockMaskBuilder;
import com.sk89q.worldedit.function.mask.Mask; import com.sk89q.worldedit.function.mask.Mask;
import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.math.BlockVector3;
@ -11,7 +12,7 @@ public class SurfaceMask extends AdjacentAnyMask {
super(getMask(extent)); super(getMask(extent));
} }
public static Mask getMask(Extent extent) { public static AbstractExtentMask getMask(Extent extent) {
return new BlockMaskBuilder() return new BlockMaskBuilder()
.addTypes(BlockTypes.AIR, BlockTypes.CAVE_AIR, BlockTypes.VOID_AIR) .addTypes(BlockTypes.AIR, BlockTypes.CAVE_AIR, BlockTypes.VOID_AIR)
.addAll(b -> !b.getMaterial().isMovementBlocker()) .addAll(b -> !b.getMaterial().isMovementBlocker())

View File

@ -87,14 +87,12 @@ public class FuzzyRegionSelector extends PassthroughExtent implements RegionSele
@Override @Override
public void explainPrimarySelection(Actor actor, LocalSession session, BlockVector3 position) { public void explainPrimarySelection(Actor actor, LocalSession session, BlockVector3 position) {
int size = this.region.getArea(); player.print(Caption.of("fawe.worldedit.selector.selector.fuzzy.pos1", position, "(" + region.getVolume() + ")"));
player.print(Caption.of("fawe.worldedit.selector.selector.fuzzy.pos1", position, "(" + region.getArea() + ")"));
} }
@Override @Override
public void explainSecondarySelection(Actor actor, LocalSession session, BlockVector3 position) { public void explainSecondarySelection(Actor actor, LocalSession session, BlockVector3 position) {
int size = this.region.getArea(); player.print(Caption.of("fawe.worldedit.selector.selector.fuzzy.pos2", position, "(" + region.getVolume() + ")"));
player.print(Caption.of("fawe.worldedit.selector.selector.fuzzy.pos2", position, "(" + region.getArea() + ")"));
} }
@Override @Override

View File

@ -99,8 +99,8 @@ public abstract class DFSVisitor implements Operation {
// mutable2.mutY(from.getY() + direction.y); // mutable2.mutY(from.getY() + direction.y);
// mutable2.mutZ(from.getZ() + direction.z); // mutable2.mutZ(from.getZ() + direction.z);
BlockVector3 bv2 = BlockVector3 BlockVector3 bv2 = BlockVector3
.at(from.getX() + direction.x, from.getY() + direction.y, .at(from.getX() + direction.getX(), from.getY() + direction.getY(),
from.getZ() + direction.z); from.getZ() + direction.getZ());
if (isVisitable(bv, bv2)) { if (isVisitable(bv, bv2)) {
Node adjacent = new Node(bv2.getBlockX(), bv2.getBlockY(), bv2.getBlockZ()); Node adjacent = new Node(bv2.getBlockX(), bv2.getBlockY(), bv2.getBlockZ());
if (!adjacent.equals(current.from)) { if (!adjacent.equals(current.from)) {

View File

@ -5,29 +5,17 @@ import com.boydti.fawe.FaweCache;
import com.boydti.fawe.beta.IBatchProcessor; import com.boydti.fawe.beta.IBatchProcessor;
import com.boydti.fawe.beta.IQueueChunk; import com.boydti.fawe.beta.IQueueChunk;
import com.boydti.fawe.beta.IQueueExtent; import com.boydti.fawe.beta.IQueueExtent;
import com.boydti.fawe.beta.implementation.lighting.NMSRelighter;
import com.boydti.fawe.beta.implementation.lighting.NullRelighter;
import com.boydti.fawe.beta.implementation.lighting.Relighter;
import com.boydti.fawe.beta.implementation.processors.LimitProcessor; import com.boydti.fawe.beta.implementation.processors.LimitProcessor;
import com.boydti.fawe.beta.implementation.queue.ParallelQueueExtent; import com.boydti.fawe.beta.implementation.queue.ParallelQueueExtent;
import com.boydti.fawe.config.Settings; import com.boydti.fawe.config.Settings;
import com.boydti.fawe.logging.rollback.RollbackOptimizedHistory; import com.boydti.fawe.logging.rollback.RollbackOptimizedHistory;
import com.boydti.fawe.object.FaweLimit; import com.boydti.fawe.object.*;
import com.boydti.fawe.object.HistoryExtent;
import com.boydti.fawe.object.NullChangeSet;
import com.boydti.fawe.object.RegionWrapper;
import com.boydti.fawe.object.RelightMode;
import com.boydti.fawe.object.brush.visualization.VirtualWorld; import com.boydti.fawe.object.brush.visualization.VirtualWorld;
import com.boydti.fawe.object.changeset.AbstractChangeSet; import com.boydti.fawe.object.changeset.AbstractChangeSet;
import com.boydti.fawe.object.changeset.BlockBagChangeSet; import com.boydti.fawe.object.changeset.BlockBagChangeSet;
import com.boydti.fawe.object.changeset.DiskStorageHistory; import com.boydti.fawe.object.changeset.DiskStorageHistory;
import com.boydti.fawe.object.changeset.MemoryOptimizedHistory; import com.boydti.fawe.object.changeset.MemoryOptimizedHistory;
import com.boydti.fawe.object.extent.FaweRegionExtent; import com.boydti.fawe.object.extent.*;
import com.boydti.fawe.object.extent.MultiRegionExtent;
import com.boydti.fawe.object.extent.NullExtent;
import com.boydti.fawe.object.extent.SingleRegionExtent;
import com.boydti.fawe.object.extent.SlowExtent;
import com.boydti.fawe.object.extent.StripNBTExtent;
import com.boydti.fawe.wrappers.WorldWrapper; import com.boydti.fawe.wrappers.WorldWrapper;
import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.WorldEdit;

View File

@ -4,6 +4,7 @@ import com.sk89q.worldedit.extent.AbstractDelegateExtent;
import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.extent.Extent;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
public class ExtentTraverser<T extends Extent> { public class ExtentTraverser<T extends Extent> {
@ -48,21 +49,8 @@ public class ExtentTraverser<T extends Extent> {
return last; return last;
} }
public boolean insert(T extent) {
try {
Field field = AbstractDelegateExtent.class.getDeclaredField("extent");
field.setAccessible(true);
field.set(extent, field.get(root));
field.set(root, extent);
return true;
} catch (Throwable e) {
e.printStackTrace();
return false;
}
}
public <U> U findAndGet(Class<U> clazz) { public <U> U findAndGet(Class<U> clazz) {
ExtentTraverser<Extent> traverser = find( clazz); ExtentTraverser<Extent> traverser = find(clazz);
return (traverser != null) ? (U) traverser.get() : null; return (traverser != null) ? (U) traverser.get() : null;
} }

View File

@ -1,92 +1,51 @@
package com.boydti.fawe.util; package com.boydti.fawe.util;
import static java.lang.System.arraycopy;
import static org.slf4j.LoggerFactory.getLogger;
import com.boydti.fawe.Fawe; import com.boydti.fawe.Fawe;
import com.sk89q.worldedit.util.formatting.text.Component;
import com.sk89q.worldedit.util.formatting.text.TranslatableComponent;
import com.boydti.fawe.config.Settings; import com.boydti.fawe.config.Settings;
import com.boydti.fawe.object.FaweInputStream; import com.boydti.fawe.object.FaweInputStream;
import com.boydti.fawe.object.FaweOutputStream; import com.boydti.fawe.object.FaweOutputStream;
import com.boydti.fawe.object.RegionWrapper; import com.boydti.fawe.object.RegionWrapper;
import com.boydti.fawe.object.RunnableVal; import com.boydti.fawe.object.RunnableVal;
import com.boydti.fawe.object.RunnableVal2;
import com.boydti.fawe.object.changeset.FaweStreamChangeSet; import com.boydti.fawe.object.changeset.FaweStreamChangeSet;
import com.boydti.fawe.object.io.AbstractDelegateOutputStream; import com.boydti.fawe.object.io.AbstractDelegateOutputStream;
import com.github.luben.zstd.ZstdInputStream; import com.github.luben.zstd.ZstdInputStream;
import com.github.luben.zstd.ZstdOutputStream; import com.github.luben.zstd.ZstdOutputStream;
import com.sk89q.jnbt.CompoundTag; import com.sk89q.jnbt.*;
import com.sk89q.jnbt.DoubleTag;
import com.sk89q.jnbt.IntTag;
import com.sk89q.jnbt.ListTag;
import com.sk89q.jnbt.StringTag;
import com.sk89q.jnbt.Tag;
import com.sk89q.worldedit.entity.Entity; import com.sk89q.worldedit.entity.Entity;
import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormat; import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormat;
import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormats; import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormats;
import com.sk89q.worldedit.history.changeset.ChangeSet; import com.sk89q.worldedit.history.changeset.ChangeSet;
import com.sk89q.worldedit.util.Location; import com.sk89q.worldedit.util.Location;
import java.awt.Graphics2D; import com.sk89q.worldedit.util.formatting.text.Component;
import com.sk89q.worldedit.util.formatting.text.TranslatableComponent;
import it.unimi.dsi.fastutil.io.FastBufferedInputStream;
import net.jpountz.lz4.*;
import org.jetbrains.annotations.NotNull;
import javax.annotation.Nullable;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage; import java.awt.image.BufferedImage;
import java.io.BufferedOutputStream; import java.io.*;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.lang.reflect.Array; import java.lang.reflect.Array;
import java.net.HttpURLConnection; import java.net.*;
import java.net.MalformedURLException;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLConnection;
import java.nio.channels.Channels; import java.nio.channels.Channels;
import java.nio.channels.FileChannel; import java.nio.channels.FileChannel;
import java.nio.channels.ReadableByteChannel; import java.nio.channels.ReadableByteChannel;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.nio.file.FileVisitResult; import java.nio.file.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.StandardCopyOption;
import java.nio.file.attribute.BasicFileAttributes; import java.nio.file.attribute.BasicFileAttributes;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.*;
import java.util.Scanner;
import java.util.UUID;
import java.util.concurrent.ForkJoinPool; import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicLong;
import java.util.function.BiConsumer;
import java.util.function.Consumer; import java.util.function.Consumer;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import java.util.zip.DataFormatException; import java.util.zip.*;
import java.util.zip.Deflater;
import java.util.zip.GZIPInputStream;
import java.util.zip.Inflater;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import javax.annotation.Nullable;
import javax.imageio.ImageIO;
import it.unimi.dsi.fastutil.io.FastBufferedInputStream; import static java.lang.System.arraycopy;
import net.jpountz.lz4.LZ4BlockInputStream; import static org.slf4j.LoggerFactory.getLogger;
import net.jpountz.lz4.LZ4BlockOutputStream;
import net.jpountz.lz4.LZ4Compressor;
import net.jpountz.lz4.LZ4Factory;
import net.jpountz.lz4.LZ4FastDecompressor;
import net.jpountz.lz4.LZ4InputStream;
import net.jpountz.lz4.LZ4Utils;
import org.jetbrains.annotations.NotNull;
public class MainUtil { public class MainUtil {
@ -112,22 +71,22 @@ public class MainUtil {
public static long getTotalSize(Path path) { public static long getTotalSize(Path path) {
final AtomicLong size = new AtomicLong(0); final AtomicLong size = new AtomicLong(0);
traverse(path, new RunnableVal2<Path, BasicFileAttributes>() { traverse(path, new RunnableVal<BasicFileAttributes>() {
@Override @Override
public void run(Path path, BasicFileAttributes attrs) { public void run(BasicFileAttributes attrs) {
size.addAndGet(attrs.size()); size.addAndGet(attrs.size());
} }
}); });
return size.get(); return size.get();
} }
public static void traverse(Path path, final BiConsumer<Path, BasicFileAttributes> onEach) { public static void traverse(Path path, final Consumer<BasicFileAttributes> onEach) {
try { try {
Files.walkFileTree(path, new SimpleFileVisitor<Path>() { Files.walkFileTree(path, new SimpleFileVisitor<Path>() {
@Override @Override
public FileVisitResult public FileVisitResult
visitFile(Path file, BasicFileAttributes attrs) { visitFile(Path file, BasicFileAttributes attrs) {
onEach.accept(file, attrs); onEach.accept(attrs);
return FileVisitResult.CONTINUE; return FileVisitResult.CONTINUE;
} }
@ -169,7 +128,7 @@ public class MainUtil {
return out.toString(); return out.toString();
} }
public static void forEachFile(Path path, final RunnableVal2<Path, BasicFileAttributes> onEach, Comparator<File> comparator) { public static void forEachFile(Path path, final RunnableVal<BasicFileAttributes> onEach, Comparator<File> comparator) {
File dir = path.toFile(); File dir = path.toFile();
if (!dir.exists()) return; if (!dir.exists()) return;
File[] files = path.toFile().listFiles(); File[] files = path.toFile().listFiles();
@ -178,7 +137,7 @@ public class MainUtil {
Path filePath = file.toPath(); Path filePath = file.toPath();
try { try {
BasicFileAttributes attr = Files.readAttributes(filePath, BasicFileAttributes.class); BasicFileAttributes attr = Files.readAttributes(filePath, BasicFileAttributes.class);
onEach.run(file.toPath(), attr); onEach.run(attr);
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); e.printStackTrace();
} }

View File

@ -4,6 +4,8 @@ import com.boydti.fawe.object.mask.ResettableMask;
import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.function.mask.AbstractExtentMask; import com.sk89q.worldedit.function.mask.AbstractExtentMask;
import com.sk89q.worldedit.function.mask.Mask; import com.sk89q.worldedit.function.mask.Mask;
import com.sk89q.worldedit.function.mask.MaskIntersection;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.util.Collection; import java.util.Collection;
@ -38,6 +40,18 @@ public class MaskTraverser {
} catch (NoSuchFieldException | IllegalAccessException ignored) { } catch (NoSuchFieldException | IllegalAccessException ignored) {
} }
} }
if (mask instanceof MaskIntersection) {
MaskIntersection mask1 = (MaskIntersection) mask;
try {
Field field = mask1.getClass().getDeclaredField("masks");
field.setAccessible(true);
Collection<Mask> masks = (Collection<Mask>) field.get(mask);
for (Mask next : masks) {
reset(next, newExtent);
}
} catch (NoSuchFieldException | IllegalAccessException ignored) {
}
}
try { try {
Field field = current.getDeclaredField("mask"); Field field = current.getDeclaredField("mask");
field.setAccessible(true); field.setAccessible(true);

View File

@ -1,27 +0,0 @@
package com.boydti.fawe.util;
import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.regions.Region;
import java.util.Iterator;
import java.util.concurrent.ConcurrentLinkedQueue;
public class RegionCacheUtil {
public RegionCacheUtil() {
}
public void cache(Region region) {
Iterator<BlockVector3> iter = region.iterator();
}
public void run() {
TaskManager.IMP.async(new Runnable() {
@Override
public void run() {
}
});
}
}

View File

@ -33,15 +33,9 @@ public class WEManager {
public void cancelEditSafe(AbstractDelegateExtent parent, FaweException reason) throws FaweException { public void cancelEditSafe(AbstractDelegateExtent parent, FaweException reason) throws FaweException {
log.warn("CancelEditSafe was hit. Please ignore this message."); log.warn("CancelEditSafe was hit. Please ignore this message.");
try { Extent currentExtent = parent.getExtent();
final Field field = AbstractDelegateExtent.class.getDeclaredField("extent"); if (!(currentExtent instanceof NullExtent)) {
field.setAccessible(true); parent.extent = new NullExtent(parent.extent, reason);
Extent currentExtent = parent.getExtent();
if (!(currentExtent instanceof NullExtent)) {
field.set(parent, new NullExtent((Extent) field.get(parent), reason));
}
} catch (Exception e) {
e.printStackTrace();
} }
throw reason; throw reason;
} }

View File

@ -1102,7 +1102,7 @@ public class EditSession extends PassthroughExtent implements AutoCloseable {
* @param radius the radius of the spherical area to fill * @param radius the radius of the spherical area to fill
* @param depth the maximum depth, starting from the origin * @param depth the maximum depth, starting from the origin
* @param direction the direction to fill * @param direction the direction to fill
* @return number of blocks affected * @return the number of blocks affected
* @throws MaxChangedBlocksException thrown if too many blocks are changed * @throws MaxChangedBlocksException thrown if too many blocks are changed
*/ */
public int fillDirection(final BlockVector3 origin, final Pattern pattern, final double radius, final int depth, BlockVector3 direction) throws MaxChangedBlocksException { public int fillDirection(final BlockVector3 origin, final Pattern pattern, final double radius, final int depth, BlockVector3 direction) throws MaxChangedBlocksException {
@ -1181,7 +1181,7 @@ public class EditSession extends PassthroughExtent implements AutoCloseable {
visitor.visit(origin); visitor.visit(origin);
// Execute // Execute
Operations.completeBlindly(visitor); Operations.completeLegacy(visitor);
return this.changes = visitor.getAffected(); return this.changes = visitor.getAffected();
} }
@ -2185,12 +2185,13 @@ public class EditSession extends PassthroughExtent implements AutoCloseable {
* *
* @param position a position * @param position a position
* @param radius a radius * @param radius a radius
* @param onlyNormalDirt only affect normal dirt (data value 0) * @param onlyNormalDirt only affect normal dirt (all default properties)
* @return number of blocks affected * @return number of blocks affected
* @throws MaxChangedBlocksException thrown if too many blocks are changed * @throws MaxChangedBlocksException thrown if too many blocks are changed
*/ */
@Deprecated
public int green(BlockVector3 position, double radius, boolean onlyNormalDirt) public int green(BlockVector3 position, double radius, boolean onlyNormalDirt)
throws MaxChangedBlocksException { throws MaxChangedBlocksException {
final double radiusSq = radius * radius; final double radiusSq = radius * radius;
final int ox = position.getBlockX(); final int ox = position.getBlockX();
@ -2257,7 +2258,7 @@ public class EditSession extends PassthroughExtent implements AutoCloseable {
GroundFunction ground = new GroundFunction(new ExistingBlockMask(this), generator); GroundFunction ground = new GroundFunction(new ExistingBlockMask(this), generator);
LayerVisitor visitor = new LayerVisitor(region, minimumBlockY(region), maximumBlockY(region), ground); LayerVisitor visitor = new LayerVisitor(region, minimumBlockY(region), maximumBlockY(region), ground);
visitor.setMask(new NoiseFilter2D(new RandomNoise(), density)); visitor.setMask(new NoiseFilter2D(new RandomNoise(), density));
Operations.completeBlindly(visitor); Operations.completeLegacy(visitor);
return this.changes = ground.getAffected(); return this.changes = ground.getAffected();
} }
@ -2403,11 +2404,42 @@ public class EditSession extends PassthroughExtent implements AutoCloseable {
return changed; return changed;
} }
/**
* Deforms the region by a given expression. A deform provides a block's x, y, and z coordinates (possibly scaled)
* to an expression, and then sets the block to the block given by the resulting values of the variables, if they
* have changed.
*
* @param region the region to deform
* @param zero the origin of the coordinate system
* @param unit the scale of the coordinate system
* @param expressionString the expression to evaluate for each block
*
* @return number of blocks changed
*
* @throws ExpressionException thrown on invalid expression input
* @throws MaxChangedBlocksException thrown if too many blocks are changed
*/
public int deformRegion(final Region region, final Vector3 zero, final Vector3 unit, final String expressionString) public int deformRegion(final Region region, final Vector3 zero, final Vector3 unit, final String expressionString)
throws ExpressionException, MaxChangedBlocksException { throws ExpressionException, MaxChangedBlocksException {
return deformRegion(region, zero, unit, expressionString, WorldEdit.getInstance().getConfiguration().calculationTimeout); return deformRegion(region, zero, unit, expressionString, WorldEdit.getInstance().getConfiguration().calculationTimeout);
} }
/**
* Deforms the region by a given expression. A deform provides a block's x, y, and z coordinates (possibly scaled)
* to an expression, and then sets the block to the block given by the resulting values of the variables, if they
* have changed.
*
* @param region the region to deform
* @param zero the origin of the coordinate system
* @param unit the scale of the coordinate system
* @param expressionString the expression to evaluate for each block
* @param timeout maximum time for the expression to evaluate for each block. -1 for unlimited.
*
* @return number of blocks changed
*
* @throws ExpressionException thrown on invalid expression input
* @throws MaxChangedBlocksException thrown if too many blocks are changed
*/
public int deformRegion(final Region region, final Vector3 zero, final Vector3 unit, final String expressionString, public int deformRegion(final Region region, final Vector3 zero, final Vector3 unit, final String expressionString,
final int timeout) throws ExpressionException, MaxChangedBlocksException { final int timeout) throws ExpressionException, MaxChangedBlocksException {
final Expression expression = Expression.compile(expressionString, "x", "y", "z"); final Expression expression = Expression.compile(expressionString, "x", "y", "z");
@ -2425,7 +2457,6 @@ public class EditSession extends PassthroughExtent implements AutoCloseable {
final Vector3 zero2 = zero.add(0.5, 0.5, 0.5); final Vector3 zero2 = zero.add(0.5, 0.5, 0.5);
RegionVisitor visitor = new RegionVisitor(region, new RegionFunction() { RegionVisitor visitor = new RegionVisitor(region, new RegionFunction() {
private final MutableBlockVector3 mutable = new MutableBlockVector3();
@Override @Override
public boolean apply(BlockVector3 position) throws WorldEditException { public boolean apply(BlockVector3 position) throws WorldEditException {

View File

@ -176,7 +176,7 @@ public class ClipboardCommands {
lazyClipboard.setOrigin(session.getPlacementPosition(actor)); lazyClipboard.setOrigin(session.getPlacementPosition(actor));
session.setClipboard(new ClipboardHolder(lazyClipboard)); session.setClipboard(new ClipboardHolder(lazyClipboard));
actor.print(Caption.of("fawe.worldedit.copy.command.copy" , region.getArea())); actor.print(Caption.of("fawe.worldedit.copy.command.copy" , region.getVolume()));
} }
// @Command( // @Command(

View File

@ -104,14 +104,14 @@ public class ExpandCommands {
private static void expandVert(LocalSession session, Actor actor, World world) throws IncompleteRegionException { private static void expandVert(LocalSession session, Actor actor, World world) throws IncompleteRegionException {
Region region = session.getSelection(world); Region region = session.getSelection(world);
try { try {
int oldSize = region.getArea(); long oldSize = region.getVolume();
region.expand( region.expand(
BlockVector3.at(0, (world.getMaxY() + 1), 0), BlockVector3.at(0, (world.getMaxY() + 1), 0),
BlockVector3.at(0, -(world.getMaxY() + 1), 0)); BlockVector3.at(0, -(world.getMaxY() + 1), 0));
session.getRegionSelector(world).learnChanges(); session.getRegionSelector(world).learnChanges();
int newSize = region.getArea(); long newSize = region.getVolume();
session.getRegionSelector(world).explainRegionAdjust(actor, session); session.getRegionSelector(world).explainRegionAdjust(actor, session);
int changeSize = newSize - oldSize; long changeSize = newSize - oldSize;
actor.printInfo( actor.printInfo(
TranslatableComponent.of("worldedit.expand.expanded.vert", TextComponent.of(changeSize)) TranslatableComponent.of("worldedit.expand.expanded.vert", TextComponent.of(changeSize))
); );
@ -134,7 +134,7 @@ public class ExpandCommands {
@MultiDirection @MultiDirection
List<BlockVector3> direction) throws WorldEditException { List<BlockVector3> direction) throws WorldEditException {
Region region = session.getSelection(world); Region region = session.getSelection(world);
int oldSize = region.getArea(); long oldSize = region.getVolume();
if (reverseAmount == 0) { if (reverseAmount == 0) {
for (BlockVector3 dir : direction) { for (BlockVector3 dir : direction) {
@ -147,11 +147,11 @@ public class ExpandCommands {
} }
session.getRegionSelector(world).learnChanges(); session.getRegionSelector(world).learnChanges();
int newSize = region.getArea(); long newSize = region.getVolume();
session.getRegionSelector(world).explainRegionAdjust(actor, session); session.getRegionSelector(world).explainRegionAdjust(actor, session);
int changeSize = newSize - oldSize; long changeSize = newSize - oldSize;
actor.printInfo(TranslatableComponent.of("worldedit.expand.expanded", TextComponent.of(changeSize))); actor.printInfo(TranslatableComponent.of("worldedit.expand.expanded", TextComponent.of(changeSize)));
} }

View File

@ -7,10 +7,7 @@
//import com.boydti.fawe.object.mask.BiomeMask; //import com.boydti.fawe.object.mask.BiomeMask;
//import com.boydti.fawe.object.mask.BlockLightMask; //import com.boydti.fawe.object.mask.BlockLightMask;
//import com.boydti.fawe.object.mask.BrightnessMask; //import com.boydti.fawe.object.mask.BrightnessMask;
//import com.boydti.fawe.object.mask.DataMask;
//import com.boydti.fawe.object.mask.ExtremaMask; //import com.boydti.fawe.object.mask.ExtremaMask;
//import com.boydti.fawe.object.mask.IdDataMask;
//import com.boydti.fawe.object.mask.IdMask;
//import com.boydti.fawe.object.mask.LightMask; //import com.boydti.fawe.object.mask.LightMask;
//import com.boydti.fawe.object.mask.OpacityMask; //import com.boydti.fawe.object.mask.OpacityMask;
//import com.boydti.fawe.object.mask.ROCAngleMask; //import com.boydti.fawe.object.mask.ROCAngleMask;
@ -171,22 +168,6 @@
// } // }
// //
// @Command( // @Command(
// name = "#id",
// desc = "Restrict to initial id"
// )
// public Mask id(Extent extent) {
// return new IdMask(extent);
// }
//
// @Command(
// name = "#data",
// desc = "Restrict to initial data"
// )
// public Mask data(Extent extent) {
// return new DataMask(extent);
// }
//
// @Command(
// name = "#iddata", // name = "#iddata",
// desc = "Restrict to initial block id and data" // desc = "Restrict to initial block id and data"
// ) // )

View File

@ -205,7 +205,7 @@ public class RegionCommands {
desc = "Set block lighting in a selection" desc = "Set block lighting in a selection"
) )
@CommandPermissions("worldedit.light.set") @CommandPermissions("worldedit.light.set")
public void setlighting(Player player, EditSession editSession, @Selection Region region, @Range(from = 0, to = 15) int value) { public void setlighting(Player player, EditSession editSession, @Selection Region region) {
player.print(TextComponent.of("Temporarily not working")); player.print(TextComponent.of("Temporarily not working"));
} }
@ -214,7 +214,7 @@ public class RegionCommands {
desc = "Set sky lighting in a selection" desc = "Set sky lighting in a selection"
) )
@CommandPermissions("worldedit.light.set") @CommandPermissions("worldedit.light.set")
public void setskylighting(Player player, @Selection Region region, @Range(from = 0, to= 15) int value) { public void setskylighting(Player player, @Selection Region region) {
player.printInfo(TextComponent.of("Temporarily not working")); player.printInfo(TextComponent.of("Temporarily not working"));
} }

View File

@ -339,7 +339,7 @@ public class SelectionCommands {
List<BlockVector3> direction) throws WorldEditException { List<BlockVector3> direction) throws WorldEditException {
try { try {
Region region = session.getSelection(world); Region region = session.getSelection(world);
int oldSize = region.getArea(); long oldSize = region.getVolume();
if (reverseAmount == 0) { if (reverseAmount == 0) {
for (BlockVector3 dir : direction) { for (BlockVector3 dir : direction) {
region.contract(dir.multiply(amount)); region.contract(dir.multiply(amount));
@ -350,7 +350,7 @@ public class SelectionCommands {
} }
} }
session.getRegionSelector(world).learnChanges(); session.getRegionSelector(world).learnChanges();
int newSize = region.getArea(); long newSize = region.getVolume();
session.getRegionSelector(world).explainRegionAdjust(actor, session); session.getRegionSelector(world).explainRegionAdjust(actor, session);
@ -501,7 +501,7 @@ public class SelectionCommands {
actor.printInfo(TranslatableComponent.of("worldedit.size.size", TextComponent.of(size.toString()))); actor.printInfo(TranslatableComponent.of("worldedit.size.size", TextComponent.of(size.toString())));
actor.printInfo(TranslatableComponent.of("worldedit.size.distance", TextComponent.of(region.getMaximumPoint().distance(region.getMinimumPoint())))); actor.printInfo(TranslatableComponent.of("worldedit.size.distance", TextComponent.of(region.getMaximumPoint().distance(region.getMinimumPoint()))));
actor.printInfo(TranslatableComponent.of("worldedit.size.blocks", TextComponent.of(region.getArea()))); actor.printInfo(TranslatableComponent.of("worldedit.size.blocks", TextComponent.of(region.getVolume())));
} }
@Command( @Command(

View File

@ -20,22 +20,7 @@
package com.sk89q.worldedit.extension.factory; package com.sk89q.worldedit.extension.factory;
import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.extension.factory.parser.mask.AirMaskParser; import com.sk89q.worldedit.extension.factory.parser.mask.*;
import com.sk89q.worldedit.extension.factory.parser.mask.BiomeMaskParser;
import com.sk89q.worldedit.extension.factory.parser.mask.BlockCategoryMaskParser;
import com.sk89q.worldedit.extension.factory.parser.mask.BlockStateMaskParser;
import com.sk89q.worldedit.extension.factory.parser.mask.BlocksMaskParser;
import com.sk89q.worldedit.extension.factory.parser.mask.ExistingMaskParser;
import com.sk89q.worldedit.extension.factory.parser.mask.ExpressionMaskParser;
import com.sk89q.worldedit.extension.factory.parser.mask.FalseMaskParser;
import com.sk89q.worldedit.extension.factory.parser.mask.LazyRegionMaskParser;
import com.sk89q.worldedit.extension.factory.parser.mask.LiquidMaskParser;
import com.sk89q.worldedit.extension.factory.parser.mask.NegateMaskParser;
import com.sk89q.worldedit.extension.factory.parser.mask.NoiseMaskParser;
import com.sk89q.worldedit.extension.factory.parser.mask.OffsetMaskParser;
import com.sk89q.worldedit.extension.factory.parser.mask.RegionMaskParser;
import com.sk89q.worldedit.extension.factory.parser.mask.SolidMaskParser;
import com.sk89q.worldedit.extension.factory.parser.mask.TrueMaskParser;
import com.sk89q.worldedit.extension.input.InputParseException; import com.sk89q.worldedit.extension.input.InputParseException;
import com.sk89q.worldedit.extension.input.NoMatchException; import com.sk89q.worldedit.extension.input.NoMatchException;
import com.sk89q.worldedit.extension.input.ParserContext; import com.sk89q.worldedit.extension.input.ParserContext;
@ -81,6 +66,9 @@ public final class MaskFactory extends AbstractFactory<Mask> {
register(new TrueMaskParser(worldEdit)); register(new TrueMaskParser(worldEdit));
register(new AirMaskParser(worldEdit)); register(new AirMaskParser(worldEdit));
register(new LiquidMaskParser(worldEdit)); register(new LiquidMaskParser(worldEdit));
register(new XAxisMaskParser(worldEdit));
register(new YAxisMaskParser(worldEdit));
register(new ZAxisMaskParser(worldEdit));
} }

View File

@ -1,22 +1,3 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.extension.factory.parser.mask; package com.sk89q.worldedit.extension.factory.parser.mask;
import com.boydti.fawe.function.mask.AirMask; import com.boydti.fawe.function.mask.AirMask;

View File

@ -1,22 +1,3 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.extension.factory.parser.mask; package com.sk89q.worldedit.extension.factory.parser.mask;
import com.boydti.fawe.function.mask.LiquidMask; import com.boydti.fawe.function.mask.LiquidMask;

View File

@ -0,0 +1,48 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.extension.factory.parser.mask;
import com.boydti.fawe.function.mask.XAxisMask;
import com.google.common.collect.ImmutableList;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.extension.input.ParserContext;
import com.sk89q.worldedit.function.mask.Mask;
import com.sk89q.worldedit.internal.registry.SimpleInputParser;
import java.util.List;
public class XAxisMaskParser extends SimpleInputParser<Mask> {
private final List<String> aliases = ImmutableList.of("#xaxis");
public XAxisMaskParser(WorldEdit worldEdit) {
super(worldEdit);
}
@Override
public List<String> getMatchedAliases() {
return aliases;
}
@Override
public Mask parseFromSimpleInput(String input, ParserContext context) {
return new XAxisMask(context.getExtent());
}
}

View File

@ -0,0 +1,49 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.extension.factory.parser.mask;
import com.boydti.fawe.function.mask.XAxisMask;
import com.boydti.fawe.function.mask.YAxisMask;
import com.google.common.collect.ImmutableList;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.extension.input.ParserContext;
import com.sk89q.worldedit.function.mask.Mask;
import com.sk89q.worldedit.internal.registry.SimpleInputParser;
import java.util.List;
public class YAxisMaskParser extends SimpleInputParser<Mask> {
private final List<String> aliases = ImmutableList.of("#yaxis");
public YAxisMaskParser(WorldEdit worldEdit) {
super(worldEdit);
}
@Override
public List<String> getMatchedAliases() {
return aliases;
}
@Override
public Mask parseFromSimpleInput(String input, ParserContext context) {
return new YAxisMask(context.getExtent());
}
}

View File

@ -0,0 +1,49 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.extension.factory.parser.mask;
import com.boydti.fawe.function.mask.XAxisMask;
import com.boydti.fawe.function.mask.ZAxisMask;
import com.google.common.collect.ImmutableList;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.extension.input.ParserContext;
import com.sk89q.worldedit.function.mask.Mask;
import com.sk89q.worldedit.internal.registry.SimpleInputParser;
import java.util.List;
public class ZAxisMaskParser extends SimpleInputParser<Mask> {
private final List<String> aliases = ImmutableList.of("#zaxis");
public ZAxisMaskParser(WorldEdit worldEdit) {
super(worldEdit);
}
@Override
public List<String> getMatchedAliases() {
return aliases;
}
@Override
public Mask parseFromSimpleInput(String input, ParserContext context) {
return new ZAxisMask(context.getExtent());
}
}

View File

@ -19,7 +19,6 @@
package com.sk89q.worldedit.extension.platform; package com.sk89q.worldedit.extension.platform;
import com.boydti.fawe.config.Caption;
import com.boydti.fawe.object.task.AsyncNotifyQueue; import com.boydti.fawe.object.task.AsyncNotifyQueue;
import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.EditSession;
@ -701,10 +700,10 @@ public abstract class AbstractPlayerActor implements Actor, Player, Cloneable {
* @return * @return
*/ */
public Region getLargestRegion() { public Region getLargestRegion() {
int area = 0; long area = 0;
Region max = null; Region max = null;
for (Region region : this.getCurrentRegions()) { for (Region region : this.getCurrentRegions()) {
final int tmp = region.getArea(); final long tmp = region.getVolume();
if (tmp > area) { if (tmp > area) {
area = tmp; area = tmp;
max = region; max = region;

View File

@ -59,7 +59,8 @@ public class AbstractDelegateExtent implements Extent {
private static final Logger logger = LoggerFactory.getLogger(AbstractDelegateExtent.class); private static final Logger logger = LoggerFactory.getLogger(AbstractDelegateExtent.class);
private final Extent extent; //Not safe for public usage
public Extent extent;
/** /**
* Create a new instance. * Create a new instance.

View File

@ -27,8 +27,9 @@ public class SelectionPoint2DEvent implements CUIEvent {
protected final int id; protected final int id;
protected final int blockX; protected final int blockX;
protected final int blockZ; protected final int blockZ;
protected final int area; protected final long area;
@Deprecated
public SelectionPoint2DEvent(int id, BlockVector2 pos, int area) { public SelectionPoint2DEvent(int id, BlockVector2 pos, int area) {
this.id = id; this.id = id;
this.blockX = pos.getX(); this.blockX = pos.getX();
@ -36,6 +37,7 @@ public class SelectionPoint2DEvent implements CUIEvent {
this.area = area; this.area = area;
} }
@Deprecated
public SelectionPoint2DEvent(int id, BlockVector3 pos, int area) { public SelectionPoint2DEvent(int id, BlockVector3 pos, int area) {
this.id = id; this.id = id;
this.blockX = pos.getX(); this.blockX = pos.getX();
@ -43,6 +45,20 @@ public class SelectionPoint2DEvent implements CUIEvent {
this.area = area; this.area = area;
} }
public SelectionPoint2DEvent(int id, BlockVector2 pos, long area) {
this.id = id;
this.blockX = pos.getX();
this.blockZ = pos.getZ();
this.area = area;
}
public SelectionPoint2DEvent(int id, BlockVector3 pos, long area) {
this.id = id;
this.blockX = pos.getX();
this.blockZ = pos.getZ();
this.area = area;
}
@Override @Override
public String getTypeId() { public String getTypeId() {
return "p2"; return "p2";

View File

@ -25,14 +25,21 @@ public class SelectionPointEvent implements CUIEvent {
protected final int id; protected final int id;
protected final BlockVector3 pos; protected final BlockVector3 pos;
protected final int area; protected final long area;
@Deprecated
public SelectionPointEvent(int id, BlockVector3 pos, int area) { public SelectionPointEvent(int id, BlockVector3 pos, int area) {
this.id = id; this.id = id;
this.pos = pos; this.pos = pos;
this.area = area; this.area = area;
} }
public SelectionPointEvent(int id, BlockVector3 pos, long area) {
this.id = id;
this.pos = pos;
this.area = area;
}
@Override @Override
public String getTypeId() { public String getTypeId() {
return "p"; return "p";

View File

@ -20,6 +20,7 @@
package com.sk89q.worldedit.regions; package com.sk89q.worldedit.regions;
import com.boydti.fawe.object.collection.BlockVectorSet; import com.boydti.fawe.object.collection.BlockVectorSet;
import com.google.common.primitives.Longs;
import com.sk89q.worldedit.math.BlockVector2; import com.sk89q.worldedit.math.BlockVector2;
import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.math.Vector3; import com.sk89q.worldedit.math.Vector3;
@ -44,7 +45,7 @@ public abstract class AbstractRegion extends AbstractSet<BlockVector3> implement
@Override @Override
public int size() { public int size() {
return getArea(); return com.google.common.primitives.Ints.saturatedCast(getVolume());
} }
@Override @Override
@ -106,19 +107,14 @@ public abstract class AbstractRegion extends AbstractSet<BlockVector3> implement
return points; return points;
} }
/**
* Get the number of blocks in the region.
*
* @return number of blocks
*/
@Override @Override
public int getArea() { public long getVolume() {
BlockVector3 min = getMinimumPoint(); BlockVector3 min = getMinimumPoint();
BlockVector3 max = getMaximumPoint(); BlockVector3 max = getMaximumPoint();
return (max.getX() - min.getX() + 1) * return (max.getX() - min.getX() + 1L) *
(max.getY() - min.getY() + 1) * (max.getY() - min.getY() + 1L) *
(max.getZ() - min.getZ() + 1); (max.getZ() - min.getZ() + 1L);
} }
/** /**
@ -218,7 +214,7 @@ public abstract class AbstractRegion extends AbstractSet<BlockVector3> implement
int result = worldHash ^ (worldHash >>> 32); int result = worldHash ^ (worldHash >>> 32);
result = 31 * result + this.getMinimumPoint().hashCode(); result = 31 * result + this.getMinimumPoint().hashCode();
result = 31 * result + this.getMaximumPoint().hashCode(); result = 31 * result + this.getMaximumPoint().hashCode();
result = 31 * result + this.getArea(); result = (int) (31 * result + this.getVolume());
return result; return result;
} }
@ -239,7 +235,7 @@ public abstract class AbstractRegion extends AbstractSet<BlockVector3> implement
if(this.getWorld().equals(region.getWorld()) if(this.getWorld().equals(region.getWorld())
&& this.getMinimumPoint().equals(region.getMinimumPoint()) && this.getMinimumPoint().equals(region.getMinimumPoint())
&& this.getMaximumPoint().equals(region.getMaximumPoint()) && this.getMaximumPoint().equals(region.getMaximumPoint())
&& this.getArea() == region.getArea()){ && this.getVolume() == region.getVolume()){
return true; return true;
} }
return false; return false;

View File

@ -35,6 +35,9 @@ import com.sk89q.worldedit.math.geom.Polygons;
import com.sk89q.worldedit.regions.iterator.FlatRegion3DIterator; import com.sk89q.worldedit.regions.iterator.FlatRegion3DIterator;
import com.sk89q.worldedit.regions.iterator.FlatRegionIterator; import com.sk89q.worldedit.regions.iterator.FlatRegionIterator;
import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.World;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
@ -196,9 +199,16 @@ public class CylinderRegion extends AbstractRegion implements FlatRegion {
return minY; return minY;
} }
private static final BigDecimal PI = BigDecimal.valueOf(Math.PI);
@Override @Override
public int getArea() { public long getVolume() {
return (int) Math.floor(radius.getX() * radius.getZ() * Math.PI * getHeight()); return BigDecimal.valueOf(radius.getX())
.multiply(BigDecimal.valueOf(radius.getZ()))
.multiply(PI)
.multiply(BigDecimal.valueOf(getHeight()))
.setScale(0, RoundingMode.FLOOR)
.longValue();
} }
@Override @Override

View File

@ -32,6 +32,8 @@ import com.sk89q.worldedit.math.Vector3;
import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.World;
import com.sk89q.worldedit.world.storage.ChunkStore; import com.sk89q.worldedit.world.storage.ChunkStore;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.HashSet; import java.util.HashSet;
import java.util.Set; import java.util.Set;
@ -68,7 +70,7 @@ public class EllipsoidRegion extends AbstractRegion {
/** /**
* Construct a new instance of this ellipsoid region. * Construct a new instance of this ellipsoid region.
* *
* @param world the world * @param world the world
* @param center the center * @param center the center
* @param radius the radius * @param radius the radius
*/ */
@ -92,10 +94,16 @@ public class EllipsoidRegion extends AbstractRegion {
return center.toVector3().add(getRadius()).toBlockPoint(); return center.toVector3().add(getRadius()).toBlockPoint();
} }
private static final BigDecimal ELLIPSOID_BASE_MULTIPLIER = BigDecimal.valueOf((4.0 / 3.0) * Math.PI);
@Override @Override
public int getArea() { public long getVolume() {
return (int) Math return ELLIPSOID_BASE_MULTIPLIER
.floor((4.0 / 3.0) * Math.PI * radius.getX() * radius.getY() * radius.getZ()); .multiply(BigDecimal.valueOf(radius.getX()))
.multiply(BigDecimal.valueOf(radius.getY()))
.multiply(BigDecimal.valueOf(radius.getZ()))
.setScale(0, RoundingMode.FLOOR)
.longValue();
} }
@Override @Override
@ -118,7 +126,7 @@ public class EllipsoidRegion extends AbstractRegion {
if ((diff.getBlockX() & 1) + (diff.getBlockY() & 1) + (diff.getBlockZ() & 1) != 0) { if ((diff.getBlockX() & 1) + (diff.getBlockY() & 1) + (diff.getBlockZ() & 1) != 0) {
throw new RegionOperationException( throw new RegionOperationException(
"Ellipsoid changes must be even for each dimensions."); "Ellipsoid changes must be even for each dimensions.");
} }
return diff.divide(2).floor(); return diff.divide(2).floor();

View File

@ -53,7 +53,7 @@ public class NullRegion implements Region {
} }
@Override @Override
public int getArea() { public long getVolume() {
return 0; return 0;
} }

View File

@ -25,6 +25,8 @@ import com.sk89q.worldedit.regions.iterator.FlatRegion3DIterator;
import com.sk89q.worldedit.regions.iterator.FlatRegionIterator; import com.sk89q.worldedit.regions.iterator.FlatRegionIterator;
import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.World;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.Iterator; import java.util.Iterator;
@ -197,18 +199,22 @@ public class Polygonal2DRegion extends AbstractRegion implements FlatRegion {
} }
@Override @Override
public int getArea() { public long getVolume() {
double area = 0; long area = 0;
int i, j = points.size() - 1; int i, j = points.size() - 1;
for (i = 0; i < points.size(); ++i) { for (i = 0; i < points.size(); ++i) {
area += (points.get(j).getBlockX() + points.get(i).getBlockX()) long x = points.get(j).getBlockX() + points.get(i).getBlockX();
* (points.get(j).getBlockZ() - points.get(i).getBlockZ()); long z = points.get(j).getBlockZ() - points.get(i).getBlockZ();
area += x * z;
j = i; j = i;
} }
return (int) Math.floor(Math.abs(area * 0.5) return BigDecimal.valueOf(area)
* (maxY - minY + 1)); .multiply(BigDecimal.valueOf(0.5))
.abs()
.setScale(0, RoundingMode.FLOOR)
.longValue() * (maxY - minY + 1);
} }
@Override @Override

View File

@ -32,8 +32,10 @@ import com.sk89q.worldedit.math.BlockVector2;
import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.math.Vector3; import com.sk89q.worldedit.math.Vector3;
import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.World;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import javax.annotation.Nullable; import javax.annotation.Nullable;
/** /**
@ -74,14 +76,40 @@ public interface Region extends Iterable<BlockVector3>, Cloneable, IBatchProcess
* Get the number of blocks in the region. * Get the number of blocks in the region.
* *
* @return number of blocks * @return number of blocks
* @deprecated use {@link Region#getVolume()} to prevent overflows
*/ */
@Deprecated
default int getArea() { default int getArea() {
return (int) getVolume();
}
/**
* Get the number of blocks in the region.
*
* <p>Note: This method <b>must</b> be overridden.</p>
*
* @return number of blocks
*/
default long getVolume() {
// TODO Remove default status when getArea is removed.
try {
if (getClass().getMethod("getArea").getDeclaringClass().equals(Region.class)) {
throw new IllegalStateException("Class " + getClass().getName() + " must override getVolume.");
}
} catch (NoSuchMethodException e) {
throw new AssertionError(e);
}
return getArea();
}
/* FAWE code for getArea() before merge:
default int getArea() {
BlockVector3 min = getMinimumPoint(); BlockVector3 min = getMinimumPoint();
BlockVector3 max = getMaximumPoint(); BlockVector3 max = getMaximumPoint();
return (max.getX() - min.getX() + 1) * (max.getY() - min.getY() + 1) * (max.getZ() - min.getZ() + 1); return (max.getX() - min.getX() + 1) * (max.getY() - min.getY() + 1) * (max.getZ() - min.getZ() + 1);
} }
*/
/** /**
* Get X-size. * Get X-size.
* *

View File

@ -135,8 +135,31 @@ public interface RegionSelector {
* Get the number of blocks inside the region. * Get the number of blocks inside the region.
* *
* @return number of blocks, or -1 if undefined * @return number of blocks, or -1 if undefined
* @deprecated use {@link RegionSelector#getVolume()}
*/ */
int getArea(); @Deprecated
default int getArea() {
return (int) getVolume();
}
/**
* Get the number of blocks inside the region.
*
* <p>Note: This method <b>must</b> be overridden.</p>
*
* @return number of blocks, or -1 if undefined
*/
default long getVolume() {
// TODO Remove default once getArea is removed
try {
if (getClass().getMethod("getArea").getDeclaringClass().equals(RegionSelector.class)) {
throw new IllegalStateException("Class " + getClass().getName() + " must override getVolume.");
}
} catch (NoSuchMethodException e) {
throw new AssertionError(e);
}
return getArea();
}
/** /**
* Update the selector with changes to the region. * Update the selector with changes to the region.

View File

@ -113,8 +113,8 @@ public class TransformRegion extends AbstractRegion {
} }
@Override @Override
public int getArea() { public long getVolume() {
return region.getArea(); // Cannot transform this return region.getVolume(); // Cannot transform this
} }
@Override @Override

View File

@ -170,8 +170,8 @@ public class ConvexPolyhedralRegionSelector implements RegionSelector, CUIRegion
} }
@Override @Override
public int getArea() { public long getVolume() {
return region.getArea(); return region.getVolume();
} }
@Override @Override
@ -250,7 +250,7 @@ public class ConvexPolyhedralRegionSelector implements RegionSelector, CUIRegion
int lastVertexId = -1; int lastVertexId = -1;
for (BlockVector3 vertex : vertices) { for (BlockVector3 vertex : vertices) {
vertexIds.put(vertex, ++lastVertexId); vertexIds.put(vertex, ++lastVertexId);
session.dispatchCUIEvent(player, new SelectionPointEvent(lastVertexId, vertex, getArea())); session.dispatchCUIEvent(player, new SelectionPointEvent(lastVertexId, vertex, getVolume()));
} }
for (Triangle triangle : triangles) { for (Triangle triangle : triangles) {
@ -273,8 +273,8 @@ public class ConvexPolyhedralRegionSelector implements RegionSelector, CUIRegion
checkNotNull(session); checkNotNull(session);
if (isDefined()) { if (isDefined()) {
session.dispatchCUIEvent(player, new SelectionPointEvent(0, region.getMinimumPoint(), getArea())); session.dispatchCUIEvent(player, new SelectionPointEvent(0, region.getMinimumPoint(), getVolume()));
session.dispatchCUIEvent(player, new SelectionPointEvent(1, region.getMaximumPoint(), getArea())); session.dispatchCUIEvent(player, new SelectionPointEvent(1, region.getMaximumPoint(), getVolume()));
} }
} }

View File

@ -161,13 +161,13 @@ public class CuboidRegionSelector implements RegionSelector, CUIRegion {
player.printInfo(TranslatableComponent.of( player.printInfo(TranslatableComponent.of(
"worldedit.selection.cuboid.explain.primary-area", "worldedit.selection.cuboid.explain.primary-area",
TextComponent.of(position1.toString()), TextComponent.of(position1.toString()),
TextComponent.of(region.getArea()) TextComponent.of(region.getVolume())
)); ));
} else if (position1 != null) { } else if (position1 != null) {
player.printInfo(TranslatableComponent.of("worldedit.selection.cuboid.explain.primary", TextComponent.of(position1.toString()))); player.printInfo(TranslatableComponent.of("worldedit.selection.cuboid.explain.primary", TextComponent.of(position1.toString())));
} }
session.dispatchCUIEvent(player, new SelectionPointEvent(0, pos, getArea())); session.dispatchCUIEvent(player, new SelectionPointEvent(0, pos, getVolume()));
} }
@Override @Override
@ -180,13 +180,13 @@ public class CuboidRegionSelector implements RegionSelector, CUIRegion {
player.printInfo(TranslatableComponent.of( player.printInfo(TranslatableComponent.of(
"worldedit.selection.cuboid.explain.secondary-area", "worldedit.selection.cuboid.explain.secondary-area",
TextComponent.of(position2.toString()), TextComponent.of(position2.toString()),
TextComponent.of(region.getArea()) TextComponent.of(region.getVolume())
)); ));
} else if (position2 != null) { } else if (position2 != null) {
player.printInfo(TranslatableComponent.of("worldedit.selection.cuboid.explain.secondary", TextComponent.of(position2.toString()))); player.printInfo(TranslatableComponent.of("worldedit.selection.cuboid.explain.secondary", TextComponent.of(position2.toString())));
} }
session.dispatchCUIEvent(player, new SelectionPointEvent(1, pos, getArea())); session.dispatchCUIEvent(player, new SelectionPointEvent(1, pos, getVolume()));
} }
@Override @Override
@ -197,11 +197,11 @@ public class CuboidRegionSelector implements RegionSelector, CUIRegion {
session.dispatchCUIEvent(player, new SelectionShapeEvent(getTypeID())); session.dispatchCUIEvent(player, new SelectionShapeEvent(getTypeID()));
if (position1 != null) { if (position1 != null) {
session.dispatchCUIEvent(player, new SelectionPointEvent(0, position1, getArea())); session.dispatchCUIEvent(player, new SelectionPointEvent(0, position1, getVolume()));
} }
if (position2 != null) { if (position2 != null) {
session.dispatchCUIEvent(player, new SelectionPointEvent(1, position2, getArea())); session.dispatchCUIEvent(player, new SelectionPointEvent(1, position2, getVolume()));
} }
} }
@ -268,7 +268,7 @@ public class CuboidRegionSelector implements RegionSelector, CUIRegion {
} }
@Override @Override
public int getArea() { public long getVolume() {
if (position1 == null) { if (position1 == null) {
return -1; return -1;
} }
@ -277,17 +277,17 @@ public class CuboidRegionSelector implements RegionSelector, CUIRegion {
return -1; return -1;
} }
return region.getArea(); return region.getVolume();
} }
@Override @Override
public void describeCUI(LocalSession session, Actor player) { public void describeCUI(LocalSession session, Actor player) {
if (position1 != null) { if (position1 != null) {
session.dispatchCUIEvent(player, new SelectionPointEvent(0, position1, getArea())); session.dispatchCUIEvent(player, new SelectionPointEvent(0, position1, getVolume()));
} }
if (position2 != null) { if (position2 != null) {
session.dispatchCUIEvent(player, new SelectionPointEvent(1, position2, getArea())); session.dispatchCUIEvent(player, new SelectionPointEvent(1, position2, getVolume()));
} }
} }

View File

@ -188,7 +188,7 @@ public class CylinderRegionSelector implements RegionSelector, CUIRegion {
"worldedit.selection.cylinder.explain.secondary", "worldedit.selection.cylinder.explain.secondary",
TextComponent.of(NUMBER_FORMAT.format(region.getRadius().getX())), TextComponent.of(NUMBER_FORMAT.format(region.getRadius().getX())),
TextComponent.of(NUMBER_FORMAT.format(region.getRadius().getZ())), TextComponent.of(NUMBER_FORMAT.format(region.getRadius().getZ())),
TextComponent.of(region.getArea()) TextComponent.of(region.getVolume())
)); ));
} else { } else {
player.printError(TranslatableComponent.of("worldedit.selection.cylinder.explain.secondary-missing")); player.printError(TranslatableComponent.of("worldedit.selection.cylinder.explain.secondary-missing"));
@ -260,8 +260,8 @@ public class CylinderRegionSelector implements RegionSelector, CUIRegion {
} }
@Override @Override
public int getArea() { public long getVolume() {
return region.getArea(); return region.getVolume();
} }
@Override @Override
@ -273,8 +273,8 @@ public class CylinderRegionSelector implements RegionSelector, CUIRegion {
@Override @Override
public void describeLegacyCUI(LocalSession session, Actor player) { public void describeLegacyCUI(LocalSession session, Actor player) {
if (isDefined()) { if (isDefined()) {
session.dispatchCUIEvent(player, new SelectionPointEvent(0, region.getMinimumPoint(), getArea())); session.dispatchCUIEvent(player, new SelectionPointEvent(0, region.getMinimumPoint(), getVolume()));
session.dispatchCUIEvent(player, new SelectionPointEvent(1, region.getMaximumPoint(), getArea())); session.dispatchCUIEvent(player, new SelectionPointEvent(1, region.getMaximumPoint(), getVolume()));
} }
} }

View File

@ -151,7 +151,7 @@ public class EllipsoidRegionSelector implements RegionSelector, CUIRegion {
player.printInfo(TranslatableComponent.of( player.printInfo(TranslatableComponent.of(
"worldedit.selection.ellipsoid.explain.primary-area", "worldedit.selection.ellipsoid.explain.primary-area",
TextComponent.of(region.getCenter().toString()), TextComponent.of(region.getCenter().toString()),
TextComponent.of(region.getArea()) TextComponent.of(region.getVolume())
)); ));
} else { } else {
player.printInfo(TranslatableComponent.of( player.printInfo(TranslatableComponent.of(
@ -169,7 +169,7 @@ public class EllipsoidRegionSelector implements RegionSelector, CUIRegion {
player.printInfo(TranslatableComponent.of( player.printInfo(TranslatableComponent.of(
"worldedit.selection.ellipsoid.explain.secondary-area", "worldedit.selection.ellipsoid.explain.secondary-area",
TextComponent.of(region.getRadius().toString()), TextComponent.of(region.getRadius().toString()),
TextComponent.of(region.getArea()) TextComponent.of(region.getVolume())
)); ));
} else { } else {
player.printInfo(TranslatableComponent.of( player.printInfo(TranslatableComponent.of(
@ -238,8 +238,8 @@ public class EllipsoidRegionSelector implements RegionSelector, CUIRegion {
} }
@Override @Override
public int getArea() { public long getVolume() {
return region.getArea(); return region.getVolume();
} }
@Override @Override
@ -250,8 +250,8 @@ public class EllipsoidRegionSelector implements RegionSelector, CUIRegion {
@Override @Override
public void describeLegacyCUI(LocalSession session, Actor player) { public void describeLegacyCUI(LocalSession session, Actor player) {
session.dispatchCUIEvent(player, new SelectionPointEvent(0, region.getMinimumPoint(), getArea())); session.dispatchCUIEvent(player, new SelectionPointEvent(0, region.getMinimumPoint(), getVolume()));
session.dispatchCUIEvent(player, new SelectionPointEvent(1, region.getMaximumPoint(), getArea())); session.dispatchCUIEvent(player, new SelectionPointEvent(1, region.getMaximumPoint(), getVolume()));
} }
@Override @Override

View File

@ -134,7 +134,7 @@ public class ExtendingCuboidRegionSelector extends CuboidRegionSelector {
player.printInfo(TranslatableComponent.of( player.printInfo(TranslatableComponent.of(
"worldedit.selection.extend.explain.primary", "worldedit.selection.extend.explain.primary",
TextComponent.of(pos.toString()), TextComponent.of(pos.toString()),
TextComponent.of(region.getArea()) TextComponent.of(region.getVolume())
)); ));
explainRegionAdjust(player, session); explainRegionAdjust(player, session);
@ -145,7 +145,7 @@ public class ExtendingCuboidRegionSelector extends CuboidRegionSelector {
player.printInfo(TranslatableComponent.of( player.printInfo(TranslatableComponent.of(
"worldedit.selection.extend.explain.secondary", "worldedit.selection.extend.explain.secondary",
TextComponent.of(pos.toString()), TextComponent.of(pos.toString()),
TextComponent.of(region.getArea()) TextComponent.of(region.getVolume())
)); ));
explainRegionAdjust(player, session); explainRegionAdjust(player, session);

View File

@ -174,7 +174,7 @@ public class Polygonal2DRegionSelector implements RegionSelector, CUIRegion {
player.printInfo(TranslatableComponent.of("worldedit.selection.polygon2d.explain.primary", TextComponent.of(pos.toString()))); player.printInfo(TranslatableComponent.of("worldedit.selection.polygon2d.explain.primary", TextComponent.of(pos.toString())));
session.dispatchCUIEvent(player, new SelectionShapeEvent(getTypeID())); session.dispatchCUIEvent(player, new SelectionShapeEvent(getTypeID()));
session.dispatchCUIEvent(player, new SelectionPoint2DEvent(0, pos, getArea())); session.dispatchCUIEvent(player, new SelectionPoint2DEvent(0, pos, getVolume()));
session.dispatchCUIEvent(player, new SelectionMinMaxEvent(region.getMinimumY(), region.getMaximumY())); session.dispatchCUIEvent(player, new SelectionMinMaxEvent(region.getMinimumY(), region.getMaximumY()));
} }
@ -186,7 +186,7 @@ public class Polygonal2DRegionSelector implements RegionSelector, CUIRegion {
TextComponent.of(pos.toString()) TextComponent.of(pos.toString())
)); ));
session.dispatchCUIEvent(player, new SelectionPoint2DEvent(region.size() - 1, pos, getArea())); session.dispatchCUIEvent(player, new SelectionPoint2DEvent(region.size() - 1, pos, getVolume()));
session.dispatchCUIEvent(player, new SelectionMinMaxEvent(region.getMinimumY(), region.getMaximumY())); session.dispatchCUIEvent(player, new SelectionMinMaxEvent(region.getMinimumY(), region.getMaximumY()));
} }
@ -247,8 +247,8 @@ public class Polygonal2DRegionSelector implements RegionSelector, CUIRegion {
} }
@Override @Override
public int getArea() { public long getVolume() {
return region.getArea(); return region.getVolume();
} }
/** /**
@ -264,7 +264,7 @@ public class Polygonal2DRegionSelector implements RegionSelector, CUIRegion {
public void describeCUI(LocalSession session, Actor player) { public void describeCUI(LocalSession session, Actor player) {
final List<BlockVector2> points = region.getPoints(); final List<BlockVector2> points = region.getPoints();
for (int id = 0; id < points.size(); id++) { for (int id = 0; id < points.size(); id++) {
session.dispatchCUIEvent(player, new SelectionPoint2DEvent(id, points.get(id), getArea())); session.dispatchCUIEvent(player, new SelectionPoint2DEvent(id, points.get(id), getVolume()));
} }
session.dispatchCUIEvent(player, new SelectionMinMaxEvent(region.getMinimumY(), region.getMaximumY())); session.dispatchCUIEvent(player, new SelectionMinMaxEvent(region.getMinimumY(), region.getMaximumY()));

View File

@ -93,7 +93,7 @@ public class SphereRegionSelector extends EllipsoidRegionSelector {
player.printInfo(TranslatableComponent.of( player.printInfo(TranslatableComponent.of(
"worldedit.selection.sphere.explain.secondary-defined", "worldedit.selection.sphere.explain.secondary-defined",
TextComponent.of(region.getRadius().getX()), TextComponent.of(region.getRadius().getX()),
TextComponent.of(region.getArea()) TextComponent.of(region.getVolume())
)); ));
} else { } else {
player.printInfo(TranslatableComponent.of("worldedit.selection.sphere.explain.secondary", TextComponent.of(region.getRadius().getX()))); player.printInfo(TranslatableComponent.of("worldedit.selection.sphere.explain.secondary", TextComponent.of(region.getRadius().getX())));

View File

@ -78,8 +78,8 @@ public class RequestSelection implements Region {
} }
@Override @Override
public int getArea() { public long getVolume() {
return getRegion().getArea(); return getRegion().getVolume();
} }
@Override @Override

View File

@ -19,7 +19,6 @@
package com.sk89q.worldedit.util.collection; package com.sk89q.worldedit.util.collection;
import com.google.common.collect.AbstractIterator;
import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BaseBlock;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
@ -36,6 +35,7 @@ import java.util.AbstractSet;
import java.util.Collection; import java.util.Collection;
import java.util.Iterator; import java.util.Iterator;
import java.util.Map; import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Objects; import java.util.Objects;
import java.util.Set; import java.util.Set;
import java.util.function.BiConsumer; import java.util.function.BiConsumer;
@ -43,6 +43,7 @@ import java.util.function.BiFunction;
import java.util.function.Function; import java.util.function.Function;
import java.util.function.Supplier; import java.util.function.Supplier;
import static com.google.common.base.Preconditions.checkState;
import static com.sk89q.worldedit.math.BitMath.fixSign; import static com.sk89q.worldedit.math.BitMath.fixSign;
import static com.sk89q.worldedit.math.BitMath.mask; import static com.sk89q.worldedit.math.BitMath.mask;
@ -51,12 +52,6 @@ import static com.sk89q.worldedit.math.BitMath.mask;
*/ */
public class BlockMap<V> extends AbstractMap<BlockVector3, V> { public class BlockMap<V> extends AbstractMap<BlockVector3, V> {
/* =========================
IF YOU MAKE CHANGES TO THIS CLASS
Re-run BlockMapTest with the blockmap.fulltesting=true system property.
Or just temporarily remove the annotation disabling the related tests.
========================= */
public static <V> BlockMap<V> create() { public static <V> BlockMap<V> create() {
return create(() -> new Int2ObjectOpenHashMap<>(64, 0.9f)); return create(() -> new Int2ObjectOpenHashMap<>(64, 0.9f));
} }
@ -245,26 +240,65 @@ public class BlockMap<V> extends AbstractMap<BlockVector3, V> {
entrySet = es = new AbstractSet<Entry<BlockVector3, V>>() { entrySet = es = new AbstractSet<Entry<BlockVector3, V>>() {
@Override @Override
public Iterator<Entry<BlockVector3, V>> iterator() { public Iterator<Entry<BlockVector3, V>> iterator() {
return new AbstractIterator<Entry<BlockVector3, V>>() { return new Iterator<Entry<BlockVector3,V>>() {
private final ObjectIterator<Long2ObjectMap.Entry<Int2ObjectMap<V>>> primaryIterator private final ObjectIterator<Long2ObjectMap.Entry<Int2ObjectMap<V>>> primaryIterator
= Long2ObjectMaps.fastIterator(maps); = Long2ObjectMaps.fastIterator(maps);
private long currentGroupKey; private Long2ObjectMap.Entry<Int2ObjectMap<V>> currentPrimaryEntry;
private ObjectIterator<Int2ObjectMap.Entry<V>> secondaryIterator; private ObjectIterator<Int2ObjectMap.Entry<V>> secondaryIterator;
private boolean finished;
private LazyEntry next;
@Override @Override
protected Entry<BlockVector3, V> computeNext() { public boolean hasNext() {
if (finished) {
return false;
}
if (next == null) {
LazyEntry proposedNext = computeNext();
if (proposedNext == null) {
finished = true;
return false;
}
next = proposedNext;
}
return true;
}
private LazyEntry computeNext() {
if (secondaryIterator == null || !secondaryIterator.hasNext()) { if (secondaryIterator == null || !secondaryIterator.hasNext()) {
if (!primaryIterator.hasNext()) { if (!primaryIterator.hasNext()) {
return endOfData(); return null;
} }
Long2ObjectMap.Entry<Int2ObjectMap<V>> next = primaryIterator.next(); currentPrimaryEntry = primaryIterator.next();
currentGroupKey = next.getLongKey(); secondaryIterator = Int2ObjectMaps.fastIterator(currentPrimaryEntry.getValue());
secondaryIterator = Int2ObjectMaps.fastIterator(next.getValue()); // be paranoid
checkState(secondaryIterator.hasNext(),
"Should not have an empty map entry, it should have been removed!");
} }
Int2ObjectMap.Entry<V> next = secondaryIterator.next(); Int2ObjectMap.Entry<V> next = secondaryIterator.next();
return new LazyEntry(currentGroupKey, next.getIntKey(), next.getValue()); return new LazyEntry(currentPrimaryEntry.getLongKey(), next.getIntKey(), next.getValue());
}
@Override
public Entry<BlockVector3, V> next() {
if (!hasNext()) {
throw new NoSuchElementException();
}
LazyEntry tmp = next;
next = null;
return tmp;
}
@Override
public void remove() {
secondaryIterator.remove();
// ensure invariants hold
if (currentPrimaryEntry.getValue().isEmpty()) {
// the remove call cleared this map. call remove on the primary iter
primaryIterator.remove();
}
} }
}; };
} }
@ -364,13 +398,14 @@ public class BlockMap<V> extends AbstractMap<BlockVector3, V> {
@Override @Override
public V remove(Object key) { public V remove(Object key) {
BlockVector3 vec = (BlockVector3) key; BlockVector3 vec = (BlockVector3) key;
Int2ObjectMap<V> activeMap = maps.get(toGroupKey(vec)); long groupKey = toGroupKey(vec);
Int2ObjectMap<V> activeMap = maps.get(groupKey);
if (activeMap == null) { if (activeMap == null) {
return null; return null;
} }
V removed = activeMap.remove(toInnerKey(vec)); V removed = activeMap.remove(toInnerKey(vec));
if (activeMap.isEmpty()) { if (activeMap.isEmpty()) {
maps.remove(toGroupKey(vec)); maps.remove(groupKey);
} }
return removed; return removed;
} }
@ -429,7 +464,9 @@ public class BlockMap<V> extends AbstractMap<BlockVector3, V> {
} }
if (o instanceof BlockMap) { if (o instanceof BlockMap) {
// optimize by skipping entry translations: // optimize by skipping entry translations:
return maps.equals(((BlockMap) o).maps); @SuppressWarnings("unchecked")
BlockMap<V> other = (BlockMap<V>) o;
return maps.equals(other.maps);
} }
return super.equals(o); return super.equals(o);
} }

View File

@ -91,6 +91,7 @@ class Int2BaseBlockMap extends AbstractInt2ObjectMap<BaseBlock> {
= Int2IntMaps.fastIterator(commonMap); = Int2IntMaps.fastIterator(commonMap);
private final ObjectIterator<Entry<BaseBlock>> uncommonIter private final ObjectIterator<Entry<BaseBlock>> uncommonIter
= Int2ObjectMaps.fastIterator(uncommonMap); = Int2ObjectMaps.fastIterator(uncommonMap);
private boolean lastNextFromCommon = false;
@Override @Override
public boolean hasNext() { public boolean hasNext() {
@ -101,15 +102,26 @@ class Int2BaseBlockMap extends AbstractInt2ObjectMap<BaseBlock> {
public Entry<BaseBlock> next() { public Entry<BaseBlock> next() {
if (commonIter.hasNext()) { if (commonIter.hasNext()) {
Int2IntMap.Entry e = commonIter.next(); Int2IntMap.Entry e = commonIter.next();
lastNextFromCommon = true;
return new BasicEntry<>( return new BasicEntry<>(
e.getIntKey(), assumeAsBlock(e.getIntValue()) e.getIntKey(), assumeAsBlock(e.getIntValue())
); );
} }
if (uncommonIter.hasNext()) { if (uncommonIter.hasNext()) {
lastNextFromCommon = false;
return uncommonIter.next(); return uncommonIter.next();
} }
throw new NoSuchElementException(); throw new NoSuchElementException();
} }
@Override
public void remove() {
if (lastNextFromCommon) {
commonIter.remove();
} else {
uncommonIter.remove();
}
}
}; };
} }

View File

@ -30,49 +30,54 @@ import java.util.Iterator;
class VectorPositionList implements PositionList { class VectorPositionList implements PositionList {
private final IntList delegate = new IntArrayList(); private final IntList delegateX = new IntArrayList();
private final IntList delegateY = new IntArrayList();
private final IntList delegateZ = new IntArrayList();
@Override @Override
public BlockVector3 get(int index) { public BlockVector3 get(int index) {
int ri = index * 3;
return BlockVector3.at( return BlockVector3.at(
delegate.getInt(ri), delegateX.getInt(index),
delegate.getInt(ri + 1), delegateY.getInt(index),
delegate.getInt(ri + 2)); delegateZ.getInt(index));
} }
@Override @Override
public void add(BlockVector3 vector) { public void add(BlockVector3 vector) {
delegate.add(vector.getX()); delegateX.add(vector.getX());
delegate.add(vector.getY()); delegateY.add(vector.getY());
delegate.add(vector.getZ()); delegateZ.add(vector.getZ());
} }
@Override @Override
public int size() { public int size() {
return delegate.size(); return delegateX.size();
} }
@Override @Override
public void clear() { public void clear() {
delegate.clear(); delegateX.clear();
delegateY.clear();
delegateZ.clear();
} }
@Override @Override
public Iterator<BlockVector3> iterator() { public Iterator<BlockVector3> iterator() {
return new AbstractIterator<BlockVector3>() { return new AbstractIterator<BlockVector3>() {
private final IntIterator iterator = delegate.iterator(); private final IntIterator iteratorX = delegateX.iterator();
private final IntIterator iteratorY = delegateY.iterator();
private final IntIterator iteratorZ = delegateZ.iterator();
@Override @Override
protected BlockVector3 computeNext() { protected BlockVector3 computeNext() {
if (!iterator.hasNext()) { if (!iteratorX.hasNext()) {
return endOfData(); return endOfData();
} }
return BlockVector3.at( return BlockVector3.at(
iterator.nextInt(), iteratorX.nextInt(),
iterator.nextInt(), iteratorY.nextInt(),
iterator.nextInt()); iteratorZ.nextInt());
} }
}; };
} }
@ -81,17 +86,19 @@ class VectorPositionList implements PositionList {
public Iterator<BlockVector3> reverseIterator() { public Iterator<BlockVector3> reverseIterator() {
return new AbstractIterator<BlockVector3>() { return new AbstractIterator<BlockVector3>() {
private final IntListIterator iterator = delegate.listIterator(delegate.size()); private final IntListIterator iteratorX = delegateX.listIterator(delegateX.size());
private final IntListIterator iteratorY = delegateY.listIterator(delegateY.size());
private final IntListIterator iteratorZ = delegateZ.listIterator(delegateZ.size());
@Override @Override
protected BlockVector3 computeNext() { protected BlockVector3 computeNext() {
if (!iterator.hasPrevious()) { if (!iteratorX.hasPrevious()) {
return endOfData(); return endOfData();
} }
return BlockVector3.at( return BlockVector3.at(
iterator.previousInt(), iteratorX.previousInt(),
iterator.previousInt(), iteratorY.previousInt(),
iterator.previousInt()); iteratorZ.previousInt());
} }
}; };
} }

View File

@ -31,13 +31,7 @@ public class TaskStateComparator implements Comparator<Task<?>> {
public int compare(com.sk89q.worldedit.util.task.Task<?> o1, Task<?> o2) { public int compare(com.sk89q.worldedit.util.task.Task<?> o1, Task<?> o2) {
int ordinal1 = o1.getState().ordinal(); int ordinal1 = o1.getState().ordinal();
int ordinal2 = o2.getState().ordinal(); int ordinal2 = o2.getState().ordinal();
if (ordinal1 < ordinal2) { return Integer.compare(ordinal1, ordinal2);
return -1;
} else if (ordinal1 > ordinal2) {
return 1;
} else {
return 0;
}
} }
} }

View File

@ -0,0 +1,36 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.math;
import com.sk89q.worldedit.util.test.VariedVectors;
import org.junit.jupiter.api.DisplayName;
import static org.junit.jupiter.api.Assertions.assertEquals;
@DisplayName("A 3D block vector")
public class BlockVector3Test {
@VariedVectors.Test(capToVanilla = true, divisionsXZ = 50, divisionsY = 50)
@DisplayName("survives a round-trip through long-packing")
void longPackingRoundTrip(BlockVector3 vec) {
assertEquals(vec, BlockVector3.fromLongPackedForm(vec.toLongPackedForm()));
}
}

View File

@ -1,133 +0,0 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.util;
import com.google.common.collect.AbstractIterator;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Streams;
import com.sk89q.worldedit.math.BlockVector3;
import org.junit.jupiter.api.extension.ExtensionContext;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.ArgumentsProvider;
import org.junit.jupiter.params.provider.ArgumentsSource;
import org.junit.jupiter.params.support.AnnotationConsumer;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.Iterator;
import java.util.Set;
import java.util.stream.Stream;
/**
* Argument provider for various vectors.
*/
public final class VariedVectorsProvider implements ArgumentsProvider, AnnotationConsumer<VariedVectorsProvider.Test> {
@Target({ ElementType.ANNOTATION_TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@ArgumentsSource(VariedVectorsProvider.class)
@ParameterizedTest(name = ParameterizedTest.ARGUMENTS_PLACEHOLDER)
public @interface Test {
/**
* If {@code true}, provide a non-matching vector from
* the existing vectors set as well. This will nearly
* square the number of tests executed, since it will
* test <em>every</em> non-matching vector.
*/
boolean provideNonMatching() default false;
}
private static final int WORLD_XZ_MINMAX = 30_000_000;
private static final long WORLD_Y_MAX = Integer.MAX_VALUE;
private static final long WORLD_Y_MIN = Integer.MIN_VALUE;
// For better coverage assurance, increase these values for a local Gradle run.
// Don't do it for IntelliJ, it'll probably run out of memory.
private static final int DIVISIONS_XZ = Integer.getInteger("variedvecs.divisions.xz", 5);
private static final int DIVISIONS_Y = Integer.getInteger("variedvecs.divisions.y", 5);
private static final int XZ_STEP = (WORLD_XZ_MINMAX * 2) / DIVISIONS_XZ;
private static final long Y_STEP = (WORLD_Y_MAX * 2) / DIVISIONS_Y;
private static final Set<BlockVector3> ALWAYS_INCLUDE =
ImmutableSet.of(BlockVector3.ZERO, BlockVector3.ONE,
BlockVector3.at(-WORLD_XZ_MINMAX, 0, -WORLD_XZ_MINMAX),
BlockVector3.at(WORLD_XZ_MINMAX, 0, WORLD_XZ_MINMAX),
BlockVector3.at(-WORLD_XZ_MINMAX, WORLD_Y_MAX, -WORLD_XZ_MINMAX),
BlockVector3.at(WORLD_XZ_MINMAX, WORLD_Y_MAX, WORLD_XZ_MINMAX));
private boolean provideNonMatching;
@Override
public void accept(Test test) {
provideNonMatching = test.provideNonMatching();
}
@Override
public Stream<? extends Arguments> provideArguments(ExtensionContext context) {
if (provideNonMatching) {
return makeVectorsStream()
.flatMap(vec -> makeVectorsStream().filter(v -> !v.equals(vec))
.map(v -> Arguments.of(vec, v)));
}
return makeVectorsStream().map(Arguments::of);
}
public static Stream<BlockVector3> makeVectorsStream() {
return Stream.concat(
ALWAYS_INCLUDE.stream(),
Streams.stream(generateVectors()).filter(v -> !ALWAYS_INCLUDE.contains(v))
);
}
private static Iterator<BlockVector3> generateVectors() {
return new AbstractIterator<BlockVector3>() {
private int x = -WORLD_XZ_MINMAX + 1;
private int z = -WORLD_XZ_MINMAX + 1;
private long y = WORLD_Y_MAX;
@Override
protected BlockVector3 computeNext() {
if (x > WORLD_XZ_MINMAX) {
return endOfData();
}
BlockVector3 newVector = BlockVector3.at(x, (int) y, z);
y += Y_STEP;
if (y > WORLD_Y_MAX) {
y = 0;
z += XZ_STEP;
if (z > WORLD_XZ_MINMAX) {
z = -WORLD_XZ_MINMAX;
x += XZ_STEP;
}
}
return newVector;
}
};
}
}

View File

@ -27,7 +27,8 @@ import com.sk89q.worldedit.extension.platform.PlatformManager;
import com.sk89q.worldedit.extension.platform.Preference; import com.sk89q.worldedit.extension.platform.Preference;
import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.registry.Registry; import com.sk89q.worldedit.registry.Registry;
import com.sk89q.worldedit.util.VariedVectorsProvider; import com.sk89q.worldedit.util.test.VariedVectorGenerator;
import com.sk89q.worldedit.util.test.VariedVectors;
import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BaseBlock;
import com.sk89q.worldedit.world.block.BlockType; import com.sk89q.worldedit.world.block.BlockType;
import com.sk89q.worldedit.world.block.BlockTypes; import com.sk89q.worldedit.world.block.BlockTypes;
@ -45,11 +46,11 @@ import org.mockito.MockitoAnnotations;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.util.AbstractMap; import java.util.AbstractMap;
import java.util.Iterator;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.function.BiConsumer; import java.util.function.BiConsumer;
import java.util.function.BiFunction; import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
@ -63,24 +64,23 @@ import static org.junit.jupiter.api.Assumptions.assumeFalse;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.verifyZeroInteractions;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
@DisplayName("An ordered block map") @DisplayName("An ordered block map")
class BlockMapTest { class BlockMapTest {
/* /*
private static Platform mockedPlatform = mock(Platform.class); private static final Platform MOCKED_PLATFORM = mock(Platform.class);
@BeforeAll @BeforeAll
static void setupFakePlatform() { static void setupFakePlatform() {
when(mockedPlatform.getRegistries()).thenReturn(new BundledRegistries() { when(MOCKED_PLATFORM.getRegistries()).thenReturn(new BundledRegistries() {
}); });
when(mockedPlatform.getCapabilities()).thenReturn(ImmutableMap.of( when(MOCKED_PLATFORM.getCapabilities()).thenReturn(ImmutableMap.of(
Capability.WORLD_EDITING, Preference.PREFERRED, Capability.WORLD_EDITING, Preference.PREFERRED,
Capability.GAME_HOOKS, Preference.PREFERRED Capability.GAME_HOOKS, Preference.PREFERRED
)); ));
PlatformManager platformManager = WorldEdit.getInstance().getPlatformManager(); PlatformManager platformManager = WorldEdit.getInstance().getPlatformManager();
platformManager.register(mockedPlatform); platformManager.register(MOCKED_PLATFORM);
registerBlock("minecraft:air"); registerBlock("minecraft:air");
registerBlock("minecraft:oak_wood"); registerBlock("minecraft:oak_wood");
@ -88,7 +88,7 @@ class BlockMapTest {
@AfterAll @AfterAll
static void tearDownFakePlatform() throws Exception { static void tearDownFakePlatform() throws Exception {
WorldEdit.getInstance().getPlatformManager().unregister(mockedPlatform); WorldEdit.getInstance().getPlatformManager().unregister(MOCKED_PLATFORM);
Field map = Registry.class.getDeclaredField("map"); Field map = Registry.class.getDeclaredField("map");
map.setAccessible(true); map.setAccessible(true);
((Map<?, ?>) map.get(BlockType.REGISTRY)).clear(); ((Map<?, ?>) map.get(BlockType.REGISTRY)).clear();
@ -98,8 +98,6 @@ class BlockMapTest {
BlockType.REGISTRY.register(id, new BlockType(id)); BlockType.REGISTRY.register(id, new BlockType(id));
} }
@Mock
private Function<? super BlockVector3, ? extends BaseBlock> function;
@Mock @Mock
private BiFunction<? super BlockVector3, ? super BaseBlock, ? extends BaseBlock> biFunction; private BiFunction<? super BlockVector3, ? super BaseBlock, ? extends BaseBlock> biFunction;
@Mock @Mock
@ -110,7 +108,7 @@ class BlockMapTest {
private final BaseBlock air = checkNotNull(BlockTypes.AIR).getDefaultState().toBaseBlock(); private final BaseBlock air = checkNotNull(BlockTypes.AIR).getDefaultState().toBaseBlock();
private final BaseBlock oakWood = checkNotNull(BlockTypes.OAK_WOOD).getDefaultState().toBaseBlock(); private final BaseBlock oakWood = checkNotNull(BlockTypes.OAK_WOOD).getDefaultState().toBaseBlock();
private BlockMap<BaseBlock> map = BlockMap.createForBaseBlock(); private final BlockMap<BaseBlock> map = BlockMap.createForBaseBlock();
@BeforeEach @BeforeEach
void setUp() { void setUp() {
@ -186,14 +184,14 @@ class BlockMapTest {
@DisplayName("never calls the forEach action") @DisplayName("never calls the forEach action")
void neverCallsForEachAction() { void neverCallsForEachAction() {
map.forEach(biConsumer); map.forEach(biConsumer);
verifyZeroInteractions(biConsumer); verifyNoMoreInteractions(biConsumer);
} }
@Test @Test
@DisplayName("never calls the replaceAll function") @DisplayName("never calls the replaceAll function")
void neverCallsReplaceAllFunction() { void neverCallsReplaceAllFunction() {
map.replaceAll(biFunction); map.replaceAll(biFunction);
verifyZeroInteractions(biFunction); verifyNoMoreInteractions(biFunction);
} }
@Test @Test
@ -254,63 +252,62 @@ class BlockMapTest {
assertEquals(air, map.merge(BlockVector3.ZERO, air, mergeFunction)); assertEquals(air, map.merge(BlockVector3.ZERO, air, mergeFunction));
assertEquals(1, map.size()); assertEquals(1, map.size());
assertEquals(air, map.get(BlockVector3.ZERO)); assertEquals(air, map.get(BlockVector3.ZERO));
verifyZeroInteractions(mergeFunction); verifyNoMoreInteractions(mergeFunction);
} }
} }
@Nested @Nested
@DisplayName("after having an entry added") @DisplayName("after having an entry added")
@EnabledIfSystemProperty(named = "blockmap.fulltesting", matches = "true")
class AfterEntryAdded { class AfterEntryAdded {
// Note: This section of tests would really benefit from // Note: This section of tests would really benefit from
// being able to parameterize classes. It's not part of JUnit // being able to parameterize classes. It's not part of JUnit
// yet though: https://github.com/junit-team/junit5/issues/878 // yet though: https://github.com/junit-team/junit5/issues/878
@VariedVectorsProvider.Test @VariedVectors.Test
@DisplayName("has a size of one") @DisplayName("has a size of one")
void hasSizeOne(BlockVector3 vec) { void hasSizeOne(BlockVector3 vec) {
map.put(vec, air); map.put(vec, air);
assertEquals(1, map.size()); assertEquals(1, map.size());
} }
@VariedVectorsProvider.Test @VariedVectors.Test
@DisplayName("is equal to another map with the same entry") @DisplayName("is equal to another map with the same entry")
void isEqualToSimilarMap(BlockVector3 vec) { void isEqualToSimilarMap(BlockVector3 vec) {
map.put(vec, air); map.put(vec, air);
assertEquals(ImmutableMap.of(vec, air), map); assertEquals(ImmutableMap.of(vec, air), map);
} }
@VariedVectorsProvider.Test(provideNonMatching = true) @VariedVectors.Test(provideNonMatching = true)
@DisplayName("is not equal to another map with a different key") @DisplayName("is not equal to another map with a different key")
void isNotEqualToDifferentKeyMap(BlockVector3 vec, BlockVector3 nonMatch) { void isNotEqualToDifferentKeyMap(BlockVector3 vec, BlockVector3 nonMatch) {
map.put(vec, air); map.put(vec, air);
assertNotEquals(ImmutableMap.of(nonMatch, air), map); assertNotEquals(ImmutableMap.of(nonMatch, air), map);
} }
@VariedVectorsProvider.Test @VariedVectors.Test
@DisplayName("is not equal to another map with a different value") @DisplayName("is not equal to another map with a different value")
void isNotEqualToDifferentValueMap(BlockVector3 vec) { void isNotEqualToDifferentValueMap(BlockVector3 vec) {
map.put(vec, air); map.put(vec, air);
assertNotEquals(ImmutableMap.of(vec, oakWood), map); assertNotEquals(ImmutableMap.of(vec, oakWood), map);
} }
@VariedVectorsProvider.Test @VariedVectors.Test
@DisplayName("is not equal to an empty map") @DisplayName("is not equal to an empty map")
void isNotEqualToEmptyMap(BlockVector3 vec) { void isNotEqualToEmptyMap(BlockVector3 vec) {
map.put(vec, air); map.put(vec, air);
assertNotEquals(ImmutableMap.of(), map); assertNotEquals(ImmutableMap.of(), map);
} }
@VariedVectorsProvider.Test @VariedVectors.Test
@DisplayName("has the same hashCode as another map with the same entry") @DisplayName("has the same hashCode as another map with the same entry")
void isHashCodeEqualToSimilarMap(BlockVector3 vec) { void isHashCodeEqualToSimilarMap(BlockVector3 vec) {
map.put(vec, air); map.put(vec, air);
assertEquals(ImmutableMap.of(vec, air).hashCode(), map.hashCode()); assertEquals(ImmutableMap.of(vec, air).hashCode(), map.hashCode());
} }
@VariedVectorsProvider.Test(provideNonMatching = true) @VariedVectors.Test(provideNonMatching = true)
@DisplayName("has a different hashCode from another map with a different key") @DisplayName("has a different hashCode from another map with a different key")
void isHashCodeNotEqualToDifferentKeyMap(BlockVector3 vec, BlockVector3 nonMatch) { void isHashCodeNotEqualToDifferentKeyMap(BlockVector3 vec, BlockVector3 nonMatch) {
assumeFalse(vec.hashCode() == nonMatch.hashCode(), assumeFalse(vec.hashCode() == nonMatch.hashCode(),
@ -319,35 +316,35 @@ class BlockMapTest {
assertNotEquals(ImmutableMap.of(nonMatch, air).hashCode(), map.hashCode()); assertNotEquals(ImmutableMap.of(nonMatch, air).hashCode(), map.hashCode());
} }
@VariedVectorsProvider.Test @VariedVectors.Test
@DisplayName("has a different hashCode from another map with a different value") @DisplayName("has a different hashCode from another map with a different value")
void isHashCodeNotEqualToDifferentValueMap(BlockVector3 vec) { void isHashCodeNotEqualToDifferentValueMap(BlockVector3 vec) {
map.put(vec, air); map.put(vec, air);
assertNotEquals(ImmutableMap.of(vec, oakWood).hashCode(), map.hashCode()); assertNotEquals(ImmutableMap.of(vec, oakWood).hashCode(), map.hashCode());
} }
@VariedVectorsProvider.Test @VariedVectors.Test
@DisplayName("has a different hashCode from an empty map") @DisplayName("has a different hashCode from an empty map")
void isHashCodeNotEqualToEmptyMap(BlockVector3 vec) { void isHashCodeNotEqualToEmptyMap(BlockVector3 vec) {
map.put(vec, air); map.put(vec, air);
assertNotEquals(ImmutableMap.of().hashCode(), map.hashCode()); assertNotEquals(ImmutableMap.of().hashCode(), map.hashCode());
} }
@VariedVectorsProvider.Test @VariedVectors.Test
@DisplayName("returns value from get") @DisplayName("returns value from get")
void returnsValueFromGet(BlockVector3 vec) { void returnsValueFromGet(BlockVector3 vec) {
map.put(vec, air); map.put(vec, air);
assertEquals(air, map.get(vec)); assertEquals(air, map.get(vec));
} }
@VariedVectorsProvider.Test(provideNonMatching = true) @VariedVectors.Test(provideNonMatching = true)
@DisplayName("returns `null` from get with different key") @DisplayName("returns `null` from get with different key")
void returnsValueFromGet(BlockVector3 vec, BlockVector3 nonMatch) { void returnsValueFromGet(BlockVector3 vec, BlockVector3 nonMatch) {
map.put(vec, air); map.put(vec, air);
assertNotEquals(air, map.get(nonMatch)); assertNotEquals(air, map.get(nonMatch));
} }
@VariedVectorsProvider.Test @VariedVectors.Test
@DisplayName("contains the key") @DisplayName("contains the key")
void containsTheKey(BlockVector3 vec) { void containsTheKey(BlockVector3 vec) {
map.put(vec, air); map.put(vec, air);
@ -356,7 +353,7 @@ class BlockMapTest {
assertTrue(map.containsKey(vec)); assertTrue(map.containsKey(vec));
} }
@VariedVectorsProvider.Test @VariedVectors.Test
@DisplayName("contains the value") @DisplayName("contains the value")
void containsTheValue(BlockVector3 vec) { void containsTheValue(BlockVector3 vec) {
map.put(vec, air); map.put(vec, air);
@ -365,7 +362,7 @@ class BlockMapTest {
assertTrue(map.containsValue(air)); assertTrue(map.containsValue(air));
} }
@VariedVectorsProvider.Test @VariedVectors.Test
@DisplayName("contains the entry") @DisplayName("contains the entry")
void containsTheEntry(BlockVector3 vec) { void containsTheEntry(BlockVector3 vec) {
map.put(vec, air); map.put(vec, air);
@ -373,21 +370,21 @@ class BlockMapTest {
assertEquals(new AbstractMap.SimpleImmutableEntry<>(vec, air), map.entrySet().iterator().next()); assertEquals(new AbstractMap.SimpleImmutableEntry<>(vec, air), map.entrySet().iterator().next());
} }
@VariedVectorsProvider.Test @VariedVectors.Test
@DisplayName("returns the provided value from getOrDefault") @DisplayName("returns the provided value from getOrDefault")
void returnsProvidedFromGetOrDefault(BlockVector3 vec) { void returnsProvidedFromGetOrDefault(BlockVector3 vec) {
map.put(vec, air); map.put(vec, air);
assertEquals(air, map.getOrDefault(vec, oakWood)); assertEquals(air, map.getOrDefault(vec, oakWood));
} }
@VariedVectorsProvider.Test(provideNonMatching = true) @VariedVectors.Test(provideNonMatching = true)
@DisplayName("returns the default value from getOrDefault with a different key") @DisplayName("returns the default value from getOrDefault with a different key")
void returnsDefaultFromGetOrDefaultWrongKey(BlockVector3 vec, BlockVector3 nonMatch) { void returnsDefaultFromGetOrDefaultWrongKey(BlockVector3 vec, BlockVector3 nonMatch) {
map.put(vec, air); map.put(vec, air);
assertEquals(oakWood, map.getOrDefault(nonMatch, oakWood)); assertEquals(oakWood, map.getOrDefault(nonMatch, oakWood));
} }
@VariedVectorsProvider.Test @VariedVectors.Test
@DisplayName("calls the forEach action once") @DisplayName("calls the forEach action once")
void neverCallsForEachAction(BlockVector3 vec) { void neverCallsForEachAction(BlockVector3 vec) {
map.put(vec, air); map.put(vec, air);
@ -396,7 +393,7 @@ class BlockMapTest {
verifyNoMoreInteractions(biConsumer); verifyNoMoreInteractions(biConsumer);
} }
@VariedVectorsProvider.Test @VariedVectors.Test
@DisplayName("replaces value using replaceAll") @DisplayName("replaces value using replaceAll")
void neverCallsReplaceAllFunction(BlockVector3 vec) { void neverCallsReplaceAllFunction(BlockVector3 vec) {
map.put(vec, air); map.put(vec, air);
@ -404,7 +401,7 @@ class BlockMapTest {
assertEquals(oakWood, map.get(vec)); assertEquals(oakWood, map.get(vec));
} }
@VariedVectorsProvider.Test @VariedVectors.Test
@DisplayName("does not insert on `putIfAbsent`") @DisplayName("does not insert on `putIfAbsent`")
void noInsertOnPutIfAbsent(BlockVector3 vec) { void noInsertOnPutIfAbsent(BlockVector3 vec) {
map.put(vec, air); map.put(vec, air);
@ -413,7 +410,7 @@ class BlockMapTest {
assertEquals(air, map.get(vec)); assertEquals(air, map.get(vec));
} }
@VariedVectorsProvider.Test(provideNonMatching = true) @VariedVectors.Test(provideNonMatching = true)
@DisplayName("inserts on `putIfAbsent` to a different key") @DisplayName("inserts on `putIfAbsent` to a different key")
void insertOnPutIfAbsentDifferentKey(BlockVector3 vec, BlockVector3 nonMatch) { void insertOnPutIfAbsentDifferentKey(BlockVector3 vec, BlockVector3 nonMatch) {
map.put(vec, air); map.put(vec, air);
@ -423,7 +420,7 @@ class BlockMapTest {
assertEquals(oakWood, map.get(nonMatch)); assertEquals(oakWood, map.get(nonMatch));
} }
@VariedVectorsProvider.Test @VariedVectors.Test
@DisplayName("remove(key) returns the old value") @DisplayName("remove(key) returns the old value")
void removeKeyReturnsOldValue(BlockVector3 vec) { void removeKeyReturnsOldValue(BlockVector3 vec) {
map.put(vec, air); map.put(vec, air);
@ -431,7 +428,27 @@ class BlockMapTest {
assertEquals(0, map.size()); assertEquals(0, map.size());
} }
@VariedVectorsProvider.Test(provideNonMatching = true) @VariedVectors.Test
@DisplayName("keySet().remove(key) removes the entry from the map")
void keySetRemovePassesThrough(BlockVector3 vec) {
map.put(vec, air);
assertTrue(map.keySet().remove(vec));
assertEquals(0, map.size());
}
@VariedVectors.Test
@DisplayName("entrySet().iterator().remove() removes the entry from the map")
void entrySetIteratorRemovePassesThrough(BlockVector3 vec) {
map.put(vec, air);
Iterator<Map.Entry<BlockVector3, BaseBlock>> iterator = map.entrySet().iterator();
assertTrue(iterator.hasNext());
Map.Entry<BlockVector3, BaseBlock> entry = iterator.next();
assertEquals(entry.getKey(), vec);
iterator.remove();
assertEquals(0, map.size());
}
@VariedVectors.Test(provideNonMatching = true)
@DisplayName("remove(nonMatch) returns null") @DisplayName("remove(nonMatch) returns null")
void removeNonMatchingKeyReturnsNull(BlockVector3 vec, BlockVector3 nonMatch) { void removeNonMatchingKeyReturnsNull(BlockVector3 vec, BlockVector3 nonMatch) {
map.put(vec, air); map.put(vec, air);
@ -439,7 +456,7 @@ class BlockMapTest {
assertEquals(1, map.size()); assertEquals(1, map.size());
} }
@VariedVectorsProvider.Test @VariedVectors.Test
@DisplayName("remove(key, value) returns true") @DisplayName("remove(key, value) returns true")
void removeKeyValueReturnsTrue(BlockVector3 vec) { void removeKeyValueReturnsTrue(BlockVector3 vec) {
map.put(vec, air); map.put(vec, air);
@ -447,7 +464,7 @@ class BlockMapTest {
assertEquals(0, map.size()); assertEquals(0, map.size());
} }
@VariedVectorsProvider.Test @VariedVectors.Test
@DisplayName("remove(key, value) returns false for wrong value") @DisplayName("remove(key, value) returns false for wrong value")
void removeKeyValueReturnsFalseWrongValue(BlockVector3 vec) { void removeKeyValueReturnsFalseWrongValue(BlockVector3 vec) {
map.put(vec, air); map.put(vec, air);
@ -455,7 +472,7 @@ class BlockMapTest {
assertEquals(1, map.size()); assertEquals(1, map.size());
} }
@VariedVectorsProvider.Test @VariedVectors.Test
@DisplayName("replaces value at key") @DisplayName("replaces value at key")
void replacesValueAtKey(BlockVector3 vec) { void replacesValueAtKey(BlockVector3 vec) {
map.put(vec, air); map.put(vec, air);
@ -469,7 +486,7 @@ class BlockMapTest {
assertEquals(air, map.get(vec)); assertEquals(air, map.get(vec));
} }
@VariedVectorsProvider.Test(provideNonMatching = true) @VariedVectors.Test(provideNonMatching = true)
@DisplayName("does not replace value at different key") @DisplayName("does not replace value at different key")
void doesNotReplaceAtDifferentKey(BlockVector3 vec, BlockVector3 nonMatch) { void doesNotReplaceAtDifferentKey(BlockVector3 vec, BlockVector3 nonMatch) {
map.put(vec, air); map.put(vec, air);
@ -483,7 +500,7 @@ class BlockMapTest {
assertEquals(air, map.get(vec)); assertEquals(air, map.get(vec));
} }
@VariedVectorsProvider.Test @VariedVectors.Test
@DisplayName("does not insert on computeIfAbsent") @DisplayName("does not insert on computeIfAbsent")
void doesNotInsertComputeIfAbsent(BlockVector3 vec) { void doesNotInsertComputeIfAbsent(BlockVector3 vec) {
map.put(vec, air); map.put(vec, air);
@ -495,7 +512,7 @@ class BlockMapTest {
assertEquals(air, map.get(vec)); assertEquals(air, map.get(vec));
} }
@VariedVectorsProvider.Test(provideNonMatching = true) @VariedVectors.Test(provideNonMatching = true)
@DisplayName("inserts on computeIfAbsent with different key") @DisplayName("inserts on computeIfAbsent with different key")
void insertsOnComputeIfAbsentDifferentKey(BlockVector3 vec, BlockVector3 nonMatch) { void insertsOnComputeIfAbsentDifferentKey(BlockVector3 vec, BlockVector3 nonMatch) {
map.put(vec, air); map.put(vec, air);
@ -508,7 +525,7 @@ class BlockMapTest {
assertEquals(oakWood, map.get(nonMatch)); assertEquals(oakWood, map.get(nonMatch));
} }
@VariedVectorsProvider.Test @VariedVectors.Test
@DisplayName("replaces on compute") @DisplayName("replaces on compute")
void replaceOnCompute(BlockVector3 vec) { void replaceOnCompute(BlockVector3 vec) {
map.put(vec, air); map.put(vec, air);
@ -523,7 +540,7 @@ class BlockMapTest {
assertEquals(0, map.size()); assertEquals(0, map.size());
} }
@VariedVectorsProvider.Test(provideNonMatching = true) @VariedVectors.Test(provideNonMatching = true)
@DisplayName("inserts on compute with different key") @DisplayName("inserts on compute with different key")
void insertOnComputeDifferentKey(BlockVector3 vec, BlockVector3 nonMatch) { void insertOnComputeDifferentKey(BlockVector3 vec, BlockVector3 nonMatch) {
map.put(vec, air); map.put(vec, air);
@ -540,7 +557,7 @@ class BlockMapTest {
assertEquals(air, map.get(vec)); assertEquals(air, map.get(vec));
} }
@VariedVectorsProvider.Test @VariedVectors.Test
@DisplayName("replaces on computeIfPresent") @DisplayName("replaces on computeIfPresent")
void replacesOnComputeIfPresent(BlockVector3 vec) { void replacesOnComputeIfPresent(BlockVector3 vec) {
map.put(vec, air); map.put(vec, air);
@ -555,7 +572,7 @@ class BlockMapTest {
assertEquals(0, map.size()); assertEquals(0, map.size());
} }
@VariedVectorsProvider.Test @VariedVectors.Test
@DisplayName("inserts on merge, with call to merge function") @DisplayName("inserts on merge, with call to merge function")
void insertsOnMerge(BlockVector3 vec) { void insertsOnMerge(BlockVector3 vec) {
map.put(vec, air); map.put(vec, air);
@ -573,7 +590,9 @@ class BlockMapTest {
@Test @Test
@DisplayName("contains all inserted vectors") @DisplayName("contains all inserted vectors")
void containsAllInsertedVectors() { void containsAllInsertedVectors() {
Set<BlockVector3> allVectors = VariedVectorsProvider.makeVectorsStream().collect(Collectors.toSet()); Set<BlockVector3> allVectors = new VariedVectorGenerator()
.makeVectorsStream()
.collect(Collectors.toSet());
for (BlockVector3 vec : allVectors) { for (BlockVector3 vec : allVectors) {
map.put(vec, air); map.put(vec, air);
} }

View File

@ -0,0 +1,98 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.util.collection;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.util.test.VariedVectors;
import org.junit.jupiter.api.DisplayName;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
abstract class PositionListTest {
static class Long extends PositionListTest {
protected Long() {
super(new LongPositionList());
}
}
static class Vector extends PositionListTest {
protected Vector() {
super(new VectorPositionList());
}
}
private final PositionList positionList;
protected PositionListTest(PositionList positionList) {
this.positionList = positionList;
}
@VariedVectors.Test(capToVanilla = true)
@DisplayName("calling add(vec) increases size by 1")
void addIncreasesSizeByOne(BlockVector3 vec) {
positionList.add(vec);
assertEquals(1, positionList.size());
}
@VariedVectors.Test(capToVanilla = true)
@DisplayName("calling get(0) after add(vec) returns vec")
void canGetVectorAfterAdd(BlockVector3 vec) {
positionList.add(vec);
assertEquals(vec, positionList.get(0));
}
@VariedVectors.Test(capToVanilla = true)
@DisplayName("calling iterator().hasNext() after add(vec) returns true")
void hasNextAfterAdd(BlockVector3 vec) {
positionList.add(vec);
assertTrue(positionList.iterator().hasNext());
}
@VariedVectors.Test(capToVanilla = true)
@DisplayName("calling iterator().next() after add(vec) returns vec")
void nextAfterAdd(BlockVector3 vec) {
positionList.add(vec);
assertEquals(vec, positionList.iterator().next());
}
@VariedVectors.Test(capToVanilla = true)
@DisplayName("calling reverseIterator().hasNext() after add(vec) returns true")
void reverseHasNextAfterAdd(BlockVector3 vec) {
positionList.add(vec);
assertTrue(positionList.reverseIterator().hasNext());
}
@VariedVectors.Test(capToVanilla = true)
@DisplayName("calling reverseIterator().next() after add(vec) returns vec")
void reverseNextAfterAdd(BlockVector3 vec) {
positionList.add(vec);
assertEquals(vec, positionList.reverseIterator().next());
}
@VariedVectors.Test(capToVanilla = true)
@DisplayName("calling clear() after add(vec) makes the size() zero")
void clearAfterAdd(BlockVector3 vec) {
positionList.add(vec);
positionList.clear();
assertEquals(0, positionList.size());
}
}

View File

@ -0,0 +1,100 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.util.test;
import com.google.common.collect.AbstractIterator;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Streams;
import com.sk89q.worldedit.math.BlockVector3;
import java.util.Iterator;
import java.util.Set;
import java.util.stream.Stream;
public class VariedVectorGenerator {
// For better coverage assurance, increase these values for a local Gradle run.
// Don't do it for IntelliJ, it'll probably run out of memory.
private static final int DEFAULT_DIVISIONS_XZ =
Integer.getInteger("variedvecs.divisions.xz", 5);
private static final int DEFAULT_DIVISIONS_Y =
Integer.getInteger("variedvecs.divisions.y", 5);
public final int divisionsXZ;
public final int divisionsY;
public final int maxXZ;
public final long maxY;
public final int xzStep;
public final long yStep;
public final Set<BlockVector3> alwaysInclude;
public VariedVectorGenerator() {
this(false, -1, -1);
}
public VariedVectorGenerator(boolean vanilla, int divisionsXZ, int divisionsY) {
this.divisionsXZ = divisionsXZ == -1 ? DEFAULT_DIVISIONS_XZ : divisionsXZ;
this.divisionsY = divisionsY == -1 ? DEFAULT_DIVISIONS_Y : divisionsY;
maxXZ = 30_000_000;
maxY = vanilla ? 255 : Integer.MAX_VALUE;
xzStep = (maxXZ * 2) / this.divisionsXZ;
yStep = (maxY * 2) / this.divisionsY;
alwaysInclude =
ImmutableSet.of(BlockVector3.ZERO, BlockVector3.ONE,
BlockVector3.at(-maxXZ, 0, -maxXZ),
BlockVector3.at(maxXZ, 0, maxXZ),
BlockVector3.at(-maxXZ, maxY, -maxXZ),
BlockVector3.at(maxXZ, maxY, maxXZ));
}
public Stream<BlockVector3> makeVectorsStream() {
return Stream.concat(
alwaysInclude.stream(),
Streams.stream(generateVectors()).filter(v -> !alwaysInclude.contains(v))
);
}
private Iterator<BlockVector3> generateVectors() {
return new AbstractIterator<BlockVector3>() {
private int x = -maxXZ + 1;
private int z = -maxXZ + 1;
private long y = maxY;
@Override
protected BlockVector3 computeNext() {
if (x > maxXZ) {
return endOfData();
}
BlockVector3 newVector = BlockVector3.at(x, (int) y, z);
y += yStep;
if (y > maxY) {
y = 0;
z += xzStep;
if (z > maxXZ) {
z = -maxXZ;
x += xzStep;
}
}
return newVector;
}
};
}
}

View File

@ -0,0 +1,87 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.util.test;
import org.junit.jupiter.api.extension.ExtensionContext;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.ArgumentsProvider;
import org.junit.jupiter.params.provider.ArgumentsSource;
import org.junit.jupiter.params.support.AnnotationConsumer;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.stream.Stream;
/**
* Argument provider for various vectors.
*/
public final class VariedVectors implements ArgumentsProvider, AnnotationConsumer<VariedVectors.Test> {
@Target({ ElementType.ANNOTATION_TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@ArgumentsSource(VariedVectors.class)
@ParameterizedTest(name = ParameterizedTest.ARGUMENTS_PLACEHOLDER)
public @interface Test {
/**
* If {@code true}, provide a non-matching vector from
* the existing vectors set as well. This will nearly
* square the number of tests executed, since it will
* test <em>every</em> non-matching vector.
*/
boolean provideNonMatching() default false;
/**
* If {@code true}, only provide vectors inside the range of Vanilla MC.
* This caps the Y value to 255.
*/
boolean capToVanilla() default false;
int divisionsXZ() default -1;
int divisionsY() default -1;
}
private boolean provideNonMatching;
private VariedVectorGenerator generator;
@Override
public void accept(Test test) {
provideNonMatching = test.provideNonMatching();
generator = new VariedVectorGenerator(test.capToVanilla(), test.divisionsXZ(), test.divisionsY());
}
@Override
public Stream<? extends Arguments> provideArguments(ExtensionContext context) {
if (provideNonMatching) {
return generator.makeVectorsStream()
.flatMap(vec -> generator.makeVectorsStream().filter(v -> !v.equals(vec))
.map(v -> Arguments.of(vec, v)));
}
return generator.makeVectorsStream().map(Arguments::of);
}
}