* Initial work on 3D biomes. Not implemented for Bukkit, and history is unfinished * Further implement 3D Biomes. It's now usable on Forge/Fabric * Fix a few cases of apply. Gotta fix the deprecated methods at some point * Add Bukkit support * Add clipboard support. Schematics are still not great, but the Sponge schem format doesn't support this yet. * Fix the last of the issues * Fixed up review comments * Fixed review notes * Simplify * max is inclusive * Standardize non-abstract compatibility handling Co-authored-by: Octavia Togami <octavia.togami@gmail.com>
Dieser Commit ist enthalten in:
Ursprung
57d62b0bf5
Commit
f5e36ed8a8
@ -72,11 +72,22 @@ public class BukkitWorld extends AbstractWorld {
|
||||
|
||||
private static final Logger logger = WorldEdit.logger;
|
||||
|
||||
private static final boolean HAS_3D_BIOMES;
|
||||
|
||||
private static final Map<Integer, Effect> effects = new HashMap<>();
|
||||
static {
|
||||
for (Effect effect : Effect.values()) {
|
||||
effects.put(effect.getId(), effect);
|
||||
}
|
||||
|
||||
boolean temp;
|
||||
try {
|
||||
World.class.getMethod("getBiome", int.class, int.class, int.class);
|
||||
temp = true;
|
||||
} catch (NoSuchMethodException e) {
|
||||
temp = false;
|
||||
}
|
||||
HAS_3D_BIOMES = temp;
|
||||
}
|
||||
|
||||
private final WeakReference<World> worldRef;
|
||||
@ -478,14 +489,24 @@ public class BukkitWorld extends AbstractWorld {
|
||||
return false;
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecated")
|
||||
@Override
|
||||
public BiomeType getBiome(BlockVector2 position) {
|
||||
return BukkitAdapter.adapt(getWorld().getBiome(position.getBlockX(), position.getBlockZ()));
|
||||
public BiomeType getBiome(BlockVector3 position) {
|
||||
if (HAS_3D_BIOMES) {
|
||||
return BukkitAdapter.adapt(getWorld().getBiome(position.getBlockX(), position.getBlockY(), position.getBlockZ()));
|
||||
} else {
|
||||
return BukkitAdapter.adapt(getWorld().getBiome(position.getBlockX(), position.getBlockZ()));
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecated")
|
||||
@Override
|
||||
public boolean setBiome(BlockVector2 position, BiomeType biome) {
|
||||
getWorld().setBiome(position.getBlockX(), position.getBlockZ(), BukkitAdapter.adapt(biome));
|
||||
public boolean setBiome(BlockVector3 position, BiomeType biome) {
|
||||
if (HAS_3D_BIOMES) {
|
||||
getWorld().setBiome(position.getBlockX(), position.getBlockY(), position.getBlockZ(), BukkitAdapter.adapt(biome));
|
||||
} else {
|
||||
getWorld().setBiome(position.getBlockX(), position.getBlockZ(), BukkitAdapter.adapt(biome));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -30,7 +30,6 @@ import com.sk89q.worldedit.entity.Entity;
|
||||
import com.sk89q.worldedit.extent.clipboard.Clipboard;
|
||||
import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormats;
|
||||
import com.sk89q.worldedit.extent.clipboard.io.ClipboardWriter;
|
||||
import com.sk89q.worldedit.math.BlockVector2;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
import com.sk89q.worldedit.math.Vector3;
|
||||
import com.sk89q.worldedit.regions.Region;
|
||||
@ -150,12 +149,12 @@ public class ClipboardWorld extends AbstractWorld implements Clipboard, CLIWorld
|
||||
}
|
||||
|
||||
@Override
|
||||
public BiomeType getBiome(BlockVector2 position) {
|
||||
public BiomeType getBiome(BlockVector3 position) {
|
||||
return clipboard.getBiome(position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setBiome(BlockVector2 position, BiomeType biome) {
|
||||
public boolean setBiome(BlockVector3 position, BiomeType biome) {
|
||||
dirty = true;
|
||||
return clipboard.setBiome(position, biome);
|
||||
}
|
||||
|
@ -71,7 +71,6 @@ import com.sk89q.worldedit.function.pattern.Pattern;
|
||||
import com.sk89q.worldedit.function.pattern.WaterloggedRemover;
|
||||
import com.sk89q.worldedit.function.util.RegionOffset;
|
||||
import com.sk89q.worldedit.function.visitor.DownwardVisitor;
|
||||
import com.sk89q.worldedit.function.visitor.FlatRegionVisitor;
|
||||
import com.sk89q.worldedit.function.visitor.LayerVisitor;
|
||||
import com.sk89q.worldedit.function.visitor.NonRisingVisitor;
|
||||
import com.sk89q.worldedit.function.visitor.RecursiveVisitor;
|
||||
@ -83,10 +82,8 @@ import com.sk89q.worldedit.internal.expression.Expression;
|
||||
import com.sk89q.worldedit.internal.expression.ExpressionException;
|
||||
import com.sk89q.worldedit.internal.expression.ExpressionTimeoutException;
|
||||
import com.sk89q.worldedit.internal.expression.LocalSlot.Variable;
|
||||
import com.sk89q.worldedit.math.BlockVector2;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
import com.sk89q.worldedit.math.MathUtils;
|
||||
import com.sk89q.worldedit.math.Vector2;
|
||||
import com.sk89q.worldedit.math.Vector3;
|
||||
import com.sk89q.worldedit.math.interpolation.Interpolation;
|
||||
import com.sk89q.worldedit.math.interpolation.KochanekBartelsInterpolation;
|
||||
@ -609,12 +606,12 @@ public class EditSession implements Extent, AutoCloseable {
|
||||
}
|
||||
|
||||
@Override
|
||||
public BiomeType getBiome(BlockVector2 position) {
|
||||
public BiomeType getBiome(BlockVector3 position) {
|
||||
return bypassNone.getBiome(position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setBiome(BlockVector2 position, BiomeType biome) {
|
||||
public boolean setBiome(BlockVector3 position, BiomeType biome) {
|
||||
return bypassNone.setBiome(position, biome);
|
||||
}
|
||||
|
||||
@ -736,7 +733,7 @@ public class EditSession implements Extent, AutoCloseable {
|
||||
* @throws MaxChangedBlocksException thrown if too many blocks are changed
|
||||
*/
|
||||
public boolean setBlock(BlockVector3 position, Pattern pattern) throws MaxChangedBlocksException {
|
||||
return setBlock(position, pattern.apply(position));
|
||||
return setBlock(position, pattern.applyBlock(position));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1374,7 +1371,7 @@ public class EditSession implements Extent, AutoCloseable {
|
||||
|
||||
if (copyBiomes) {
|
||||
BiomeReplace biomeReplace = new BiomeReplace(this, buffer);
|
||||
FlatRegionVisitor biomeVisitor = new FlatRegionVisitor((FlatRegion) buffer.asRegion(), biomeReplace);
|
||||
RegionVisitor biomeVisitor = new RegionVisitor(buffer.asRegion(), biomeReplace);
|
||||
operation.offer(biomeVisitor);
|
||||
}
|
||||
|
||||
@ -2313,7 +2310,7 @@ public class EditSession implements Extent, AutoCloseable {
|
||||
}
|
||||
}
|
||||
|
||||
if (setBlock(position, pattern.apply(position))) {
|
||||
if (setBlock(position, pattern.applyBlock(position))) {
|
||||
++affected;
|
||||
}
|
||||
}
|
||||
@ -2530,8 +2527,6 @@ public class EditSession implements Extent, AutoCloseable {
|
||||
public int makeBiomeShape(final Region region, final Vector3 zero, final Vector3 unit, final BiomeType biomeType,
|
||||
final String expressionString, final boolean hollow, final int timeout)
|
||||
throws ExpressionException, MaxChangedBlocksException {
|
||||
final Vector2 zero2D = zero.toVector2();
|
||||
final Vector2 unit2D = unit.toVector2();
|
||||
|
||||
final Expression expression = Expression.compile(expressionString, "x", "z");
|
||||
expression.optimize();
|
||||
@ -2543,13 +2538,13 @@ public class EditSession implements Extent, AutoCloseable {
|
||||
final int[] timedOut = {0};
|
||||
final ArbitraryBiomeShape shape = new ArbitraryBiomeShape(region) {
|
||||
@Override
|
||||
protected BiomeType getBiome(int x, int z, BiomeType defaultBiomeType) {
|
||||
final Vector2 current = Vector2.at(x, z);
|
||||
environment.setCurrentBlock(current.toVector3(0));
|
||||
final Vector2 scaled = current.subtract(zero2D).divide(unit2D);
|
||||
protected BiomeType getBiome(int x, int y, int z, BiomeType defaultBiomeType) {
|
||||
final Vector3 current = Vector3.at(x, y, z);
|
||||
environment.setCurrentBlock(current);
|
||||
final Vector3 scaled = current.subtract(zero).divide(unit);
|
||||
|
||||
try {
|
||||
if (expression.evaluate(new double[]{scaled.getX(), scaled.getZ()}, timeout) <= 0) {
|
||||
if (expression.evaluate(new double[]{scaled.getX(), scaled.getY(), scaled.getZ()}, timeout) <= 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -30,19 +30,15 @@ import com.sk89q.worldedit.command.util.WorldEditAsyncCommandBuilder;
|
||||
import com.sk89q.worldedit.entity.Player;
|
||||
import com.sk89q.worldedit.extension.platform.Actor;
|
||||
import com.sk89q.worldedit.extension.platform.Capability;
|
||||
import com.sk89q.worldedit.function.FlatRegionFunction;
|
||||
import com.sk89q.worldedit.function.FlatRegionMaskingFilter;
|
||||
import com.sk89q.worldedit.function.RegionFunction;
|
||||
import com.sk89q.worldedit.function.RegionMaskingFilter;
|
||||
import com.sk89q.worldedit.function.biome.BiomeReplace;
|
||||
import com.sk89q.worldedit.function.mask.Mask;
|
||||
import com.sk89q.worldedit.function.mask.Mask2D;
|
||||
import com.sk89q.worldedit.function.operation.Operations;
|
||||
import com.sk89q.worldedit.function.visitor.FlatRegionVisitor;
|
||||
import com.sk89q.worldedit.math.BlockVector2;
|
||||
import com.sk89q.worldedit.function.visitor.RegionVisitor;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
import com.sk89q.worldedit.regions.CuboidRegion;
|
||||
import com.sk89q.worldedit.regions.FlatRegion;
|
||||
import com.sk89q.worldedit.regions.Region;
|
||||
import com.sk89q.worldedit.regions.Regions;
|
||||
import com.sk89q.worldedit.util.Location;
|
||||
import com.sk89q.worldedit.util.formatting.component.PaginationBox;
|
||||
import com.sk89q.worldedit.util.formatting.component.TextUtils;
|
||||
@ -127,12 +123,12 @@ public class BiomeCommands {
|
||||
return;
|
||||
}
|
||||
|
||||
BiomeType biome = player.getWorld().getBiome(blockPosition.toVector().toBlockPoint().toBlockVector2());
|
||||
BiomeType biome = player.getWorld().getBiome(blockPosition.toVector().toBlockPoint());
|
||||
biomes.add(biome);
|
||||
|
||||
messageKey = "worldedit.biomeinfo.lineofsight";
|
||||
} else if (usePosition) {
|
||||
BiomeType biome = player.getWorld().getBiome(player.getLocation().toVector().toBlockPoint().toBlockVector2());
|
||||
BiomeType biome = player.getWorld().getBiome(player.getLocation().toVector().toBlockPoint());
|
||||
biomes.add(biome);
|
||||
|
||||
messageKey = "worldedit.biomeinfo.position";
|
||||
@ -140,14 +136,8 @@ public class BiomeCommands {
|
||||
World world = player.getWorld();
|
||||
Region region = session.getSelection(world);
|
||||
|
||||
if (region instanceof FlatRegion) {
|
||||
for (BlockVector2 pt : ((FlatRegion) region).asFlatRegion()) {
|
||||
biomes.add(world.getBiome(pt));
|
||||
}
|
||||
} else {
|
||||
for (BlockVector3 pt : region) {
|
||||
biomes.add(world.getBiome(pt.toBlockVector2()));
|
||||
}
|
||||
for (BlockVector3 pt : region) {
|
||||
biomes.add(world.getBiome(pt));
|
||||
}
|
||||
|
||||
messageKey = "worldedit.biomeinfo.selection";
|
||||
@ -175,7 +165,6 @@ public class BiomeCommands {
|
||||
World world = player.getWorld();
|
||||
Region region;
|
||||
Mask mask = editSession.getMask();
|
||||
Mask2D mask2d = mask != null ? mask.toMask2D() : null;
|
||||
|
||||
if (atPosition) {
|
||||
final BlockVector3 pos = player.getLocation().toVector().toBlockPoint();
|
||||
@ -184,11 +173,11 @@ public class BiomeCommands {
|
||||
region = session.getSelection(world);
|
||||
}
|
||||
|
||||
FlatRegionFunction replace = new BiomeReplace(editSession, target);
|
||||
if (mask2d != null) {
|
||||
replace = new FlatRegionMaskingFilter(mask2d, replace);
|
||||
RegionFunction replace = new BiomeReplace(editSession, target);
|
||||
if (mask != null) {
|
||||
replace = new RegionMaskingFilter(mask, replace);
|
||||
}
|
||||
FlatRegionVisitor visitor = new FlatRegionVisitor(Regions.asFlatRegion(region), replace);
|
||||
RegionVisitor visitor = new RegionVisitor(region, replace);
|
||||
Operations.completeLegacy(visitor);
|
||||
|
||||
player.printInfo(TranslatableComponent.of(
|
||||
|
@ -93,7 +93,7 @@ public class FloodFillTool implements BlockTool {
|
||||
visited.add(pos);
|
||||
|
||||
if (editSession.getBlock(pos).getBlockType() == initialType) {
|
||||
editSession.setBlock(pos, pattern.apply(pos));
|
||||
editSession.setBlock(pos, pattern.applyBlock(pos));
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
@ -63,7 +63,7 @@ public class LongRangeBuildTool extends BrushTool implements DoubleActionTraceTo
|
||||
try {
|
||||
editSession.disableBuffering();
|
||||
BlockVector3 blockPoint = pos.toVector().toBlockPoint();
|
||||
BaseBlock applied = secondary.apply(blockPoint);
|
||||
BaseBlock applied = secondary.applyBlock(blockPoint);
|
||||
if (applied.getBlockType().getMaterial().isAir()) {
|
||||
editSession.setBlock(blockPoint, secondary);
|
||||
} else {
|
||||
@ -91,7 +91,7 @@ public class LongRangeBuildTool extends BrushTool implements DoubleActionTraceTo
|
||||
try {
|
||||
editSession.disableBuffering();
|
||||
BlockVector3 blockPoint = pos.toVector().toBlockPoint();
|
||||
BaseBlock applied = primary.apply(blockPoint);
|
||||
BaseBlock applied = primary.applyBlock(blockPoint);
|
||||
if (applied.getBlockType().getMaterial().isAir()) {
|
||||
editSession.setBlock(blockPoint, primary);
|
||||
} else {
|
||||
|
@ -24,9 +24,8 @@ import com.sk89q.worldedit.WorldEdit;
|
||||
import com.sk89q.worldedit.command.util.SuggestionHelper;
|
||||
import com.sk89q.worldedit.extension.input.InputParseException;
|
||||
import com.sk89q.worldedit.extension.input.ParserContext;
|
||||
import com.sk89q.worldedit.function.mask.BiomeMask2D;
|
||||
import com.sk89q.worldedit.function.mask.BiomeMask;
|
||||
import com.sk89q.worldedit.function.mask.Mask;
|
||||
import com.sk89q.worldedit.function.mask.Masks;
|
||||
import com.sk89q.worldedit.internal.registry.InputParser;
|
||||
import com.sk89q.worldedit.world.biome.BiomeType;
|
||||
|
||||
@ -77,6 +76,6 @@ public class BiomeMaskParser extends InputParser<Mask> {
|
||||
biomes.add(biome);
|
||||
}
|
||||
|
||||
return Masks.asMask(new BiomeMask2D(context.getExtent(), biomes));
|
||||
return new BiomeMask(context.getExtent(), biomes);
|
||||
}
|
||||
}
|
||||
|
@ -26,7 +26,6 @@ import com.sk89q.worldedit.entity.BaseEntity;
|
||||
import com.sk89q.worldedit.entity.Entity;
|
||||
import com.sk89q.worldedit.function.operation.Operation;
|
||||
import com.sk89q.worldedit.function.operation.OperationQueue;
|
||||
import com.sk89q.worldedit.math.BlockVector2;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
import com.sk89q.worldedit.regions.Region;
|
||||
import com.sk89q.worldedit.util.Location;
|
||||
@ -97,12 +96,12 @@ public abstract class AbstractDelegateExtent implements Extent {
|
||||
}
|
||||
|
||||
@Override
|
||||
public BiomeType getBiome(BlockVector2 position) {
|
||||
public BiomeType getBiome(BlockVector3 position) {
|
||||
return extent.getBiome(position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setBiome(BlockVector2 position, BiomeType biome) {
|
||||
public boolean setBiome(BlockVector3 position, BiomeType biome) {
|
||||
return extent.setBiome(position, biome);
|
||||
}
|
||||
|
||||
|
@ -24,12 +24,11 @@ import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import com.sk89q.worldedit.WorldEditException;
|
||||
import com.sk89q.worldedit.entity.BaseEntity;
|
||||
import com.sk89q.worldedit.entity.Entity;
|
||||
import com.sk89q.worldedit.history.change.BiomeChange;
|
||||
import com.sk89q.worldedit.history.change.BiomeChange3D;
|
||||
import com.sk89q.worldedit.history.change.BlockChange;
|
||||
import com.sk89q.worldedit.history.change.EntityCreate;
|
||||
import com.sk89q.worldedit.history.change.EntityRemove;
|
||||
import com.sk89q.worldedit.history.changeset.ChangeSet;
|
||||
import com.sk89q.worldedit.math.BlockVector2;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
import com.sk89q.worldedit.regions.Region;
|
||||
import com.sk89q.worldedit.util.Location;
|
||||
@ -69,9 +68,9 @@ public class ChangeSetExtent extends AbstractDelegateExtent {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setBiome(BlockVector2 position, BiomeType biome) {
|
||||
public boolean setBiome(BlockVector3 position, BiomeType biome) {
|
||||
BiomeType previous = getBiome(position);
|
||||
changeSet.add(new BiomeChange(position, previous, biome));
|
||||
changeSet.add(new BiomeChange3D(position, previous, biome));
|
||||
return super.setBiome(position, biome);
|
||||
}
|
||||
|
||||
|
@ -20,6 +20,8 @@
|
||||
package com.sk89q.worldedit.extent;
|
||||
|
||||
import com.sk89q.worldedit.function.pattern.Pattern;
|
||||
import com.sk89q.worldedit.internal.util.DeprecationUtil;
|
||||
import com.sk89q.worldedit.internal.util.NonAbstractForCompatibility;
|
||||
import com.sk89q.worldedit.math.BlockVector2;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
import com.sk89q.worldedit.world.biome.BiomeType;
|
||||
@ -63,7 +65,39 @@ public interface InputExtent {
|
||||
*
|
||||
* @param position the (x, z) location to check the biome at
|
||||
* @return the biome at the location
|
||||
* @deprecated Biomes in Minecraft are 3D now, use {@link InputExtent#getBiome(BlockVector3)}
|
||||
*/
|
||||
BiomeType getBiome(BlockVector2 position);
|
||||
@Deprecated
|
||||
default BiomeType getBiome(BlockVector2 position) {
|
||||
return getBiome(position.toBlockVector3());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the biome at the given location.
|
||||
*
|
||||
* <p>
|
||||
* If there is no biome available, then the ocean biome should be
|
||||
* returned.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* As implementation varies per Minecraft version, this may not exactly get
|
||||
* this positions biome. On versions prior to 1.15, this will get the entire
|
||||
* column. On later versions it will get the 4x4x4 cube's biome.
|
||||
* </p>
|
||||
*
|
||||
* @param position the (x, y, z) location to check the biome at
|
||||
* @return the biome at the location
|
||||
* @apiNote This must be overridden by new subclasses. See {@link NonAbstractForCompatibility}
|
||||
* for details
|
||||
*/
|
||||
@NonAbstractForCompatibility(
|
||||
delegateName = "getBiome",
|
||||
delegateParams = { BlockVector2.class }
|
||||
)
|
||||
default BiomeType getBiome(BlockVector3 position) {
|
||||
DeprecationUtil.checkDelegatingOverride(getClass());
|
||||
|
||||
return getBiome(position.toBlockVector2());
|
||||
}
|
||||
}
|
||||
|
@ -82,7 +82,7 @@ public class NullExtent implements Extent {
|
||||
}
|
||||
|
||||
@Override
|
||||
public BiomeType getBiome(BlockVector2 position) {
|
||||
public BiomeType getBiome(BlockVector3 position) {
|
||||
return BiomeTypes.THE_VOID;
|
||||
}
|
||||
|
||||
@ -92,7 +92,7 @@ public class NullExtent implements Extent {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setBiome(BlockVector2 position, BiomeType biome) {
|
||||
public boolean setBiome(BlockVector3 position, BiomeType biome) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -21,6 +21,8 @@ package com.sk89q.worldedit.extent;
|
||||
|
||||
import com.sk89q.worldedit.WorldEditException;
|
||||
import com.sk89q.worldedit.function.operation.Operation;
|
||||
import com.sk89q.worldedit.internal.util.DeprecationUtil;
|
||||
import com.sk89q.worldedit.internal.util.NonAbstractForCompatibility;
|
||||
import com.sk89q.worldedit.math.BlockVector2;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
import com.sk89q.worldedit.world.biome.BiomeType;
|
||||
@ -58,8 +60,37 @@ public interface OutputExtent {
|
||||
* @param position the (x, z) location to set the biome at
|
||||
* @param biome the biome to set to
|
||||
* @return true if the biome was successfully set (return value may not be accurate)
|
||||
* @deprecated Biomes in Minecraft are 3D now, use {@link OutputExtent#setBiome(BlockVector3, BiomeType)}
|
||||
*/
|
||||
boolean setBiome(BlockVector2 position, BiomeType biome);
|
||||
@Deprecated
|
||||
default boolean setBiome(BlockVector2 position, BiomeType biome) {
|
||||
return setBiome(position.toBlockVector3(), biome);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the biome.
|
||||
*
|
||||
* <p>
|
||||
* As implementation varies per Minecraft version, this may set more than
|
||||
* this position's biome. On versions prior to 1.15, this will set the entire
|
||||
* column. On later versions it will set the 4x4x4 cube.
|
||||
* </p>
|
||||
*
|
||||
* @param position the (x, y, z) location to set the biome at
|
||||
* @param biome the biome to set to
|
||||
* @return true if the biome was successfully set (return value may not be accurate)
|
||||
* @apiNote This must be overridden by new subclasses. See {@link NonAbstractForCompatibility}
|
||||
* for details
|
||||
*/
|
||||
@NonAbstractForCompatibility(
|
||||
delegateName = "setBiome",
|
||||
delegateParams = { BlockVector3.class, BiomeType.class }
|
||||
)
|
||||
default boolean setBiome(BlockVector3 position, BiomeType biome) {
|
||||
DeprecationUtil.checkDelegatingOverride(getClass());
|
||||
|
||||
return setBiome(position.toBlockVector2(), biome);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an {@link Operation} that should be called to tie up loose ends
|
||||
|
@ -25,7 +25,6 @@ import com.sk89q.worldedit.WorldEditException;
|
||||
import com.sk89q.worldedit.extent.AbstractDelegateExtent;
|
||||
import com.sk89q.worldedit.extent.Extent;
|
||||
import com.sk89q.worldedit.function.mask.Mask;
|
||||
import com.sk89q.worldedit.function.mask.Mask2D;
|
||||
import com.sk89q.worldedit.function.mask.Masks;
|
||||
import com.sk89q.worldedit.function.pattern.BiomePattern;
|
||||
import com.sk89q.worldedit.function.pattern.Pattern;
|
||||
@ -43,6 +42,7 @@ import com.sk89q.worldedit.world.block.BlockTypes;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Buffers changes to an {@link Extent} and allows later retrieval for
|
||||
@ -54,13 +54,10 @@ import java.util.Map;
|
||||
public class ForgetfulExtentBuffer extends AbstractDelegateExtent implements Pattern, BiomePattern {
|
||||
|
||||
private final Map<BlockVector3, BaseBlock> buffer = new LinkedHashMap<>();
|
||||
private final Map<BlockVector2, BiomeType> biomeBuffer = new LinkedHashMap<>();
|
||||
private final Map<BlockVector3, BiomeType> biomeBuffer = new LinkedHashMap<>();
|
||||
private final Mask mask;
|
||||
private final Mask2D biomeMask;
|
||||
private BlockVector3 min = null;
|
||||
private BlockVector2 min2d = null;
|
||||
private BlockVector3 max = null;
|
||||
private BlockVector2 max2d = null;
|
||||
|
||||
/**
|
||||
* Create a new extent buffer that will buffer every change.
|
||||
@ -82,25 +79,27 @@ public class ForgetfulExtentBuffer extends AbstractDelegateExtent implements Pat
|
||||
super(delegate);
|
||||
checkNotNull(mask);
|
||||
this.mask = mask;
|
||||
Mask2D bmask = mask.toMask2D();
|
||||
this.biomeMask = bmask == null ? Masks.alwaysTrue2D() : bmask;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <B extends BlockStateHolder<B>> boolean setBlock(BlockVector3 location, B block) throws WorldEditException {
|
||||
private void updateBounds(BlockVector3 position) {
|
||||
// Update minimum
|
||||
if (min == null) {
|
||||
min = location;
|
||||
min = position;
|
||||
} else {
|
||||
min = min.getMinimum(location);
|
||||
min = min.getMinimum(position);
|
||||
}
|
||||
|
||||
// Update maximum
|
||||
if (max == null) {
|
||||
max = location;
|
||||
max = position;
|
||||
} else {
|
||||
max = max.getMaximum(location);
|
||||
max = max.getMaximum(position);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public <B extends BlockStateHolder<B>> boolean setBlock(BlockVector3 location, B block) throws WorldEditException {
|
||||
updateBounds(location);
|
||||
|
||||
if (mask.test(location)) {
|
||||
buffer.put(location, block.toBaseBlock());
|
||||
@ -111,22 +110,10 @@ public class ForgetfulExtentBuffer extends AbstractDelegateExtent implements Pat
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setBiome(BlockVector2 position, BiomeType biome) {
|
||||
// Update minimum
|
||||
if (min2d == null) {
|
||||
min2d = position;
|
||||
} else {
|
||||
min2d = min2d.getMinimum(position);
|
||||
}
|
||||
public boolean setBiome(BlockVector3 position, BiomeType biome) {
|
||||
updateBounds(position);
|
||||
|
||||
// Update maximum
|
||||
if (max2d == null) {
|
||||
max2d = position;
|
||||
} else {
|
||||
max2d = max2d.getMaximum(position);
|
||||
}
|
||||
|
||||
if (biomeMask.test(position)) {
|
||||
if (mask.test(position)) {
|
||||
biomeBuffer.put(position, biome);
|
||||
return true;
|
||||
} else {
|
||||
@ -135,7 +122,7 @@ public class ForgetfulExtentBuffer extends AbstractDelegateExtent implements Pat
|
||||
}
|
||||
|
||||
@Override
|
||||
public BaseBlock apply(BlockVector3 pos) {
|
||||
public BaseBlock applyBlock(BlockVector3 pos) {
|
||||
BaseBlock block = buffer.get(pos);
|
||||
if (block != null) {
|
||||
return block;
|
||||
@ -145,7 +132,7 @@ public class ForgetfulExtentBuffer extends AbstractDelegateExtent implements Pat
|
||||
}
|
||||
|
||||
@Override
|
||||
public BiomeType apply(BlockVector2 pos) {
|
||||
public BiomeType applyBiome(BlockVector3 pos) {
|
||||
BiomeType biome = biomeBuffer.get(pos);
|
||||
if (biome != null) {
|
||||
return biome;
|
||||
@ -193,7 +180,10 @@ public class ForgetfulExtentBuffer extends AbstractDelegateExtent implements Pat
|
||||
|
||||
@Override
|
||||
public Iterable<BlockVector2> asFlatRegion() {
|
||||
return biomeBuffer.keySet();
|
||||
return biomeBuffer.keySet()
|
||||
.stream()
|
||||
.map(BlockVector3::toBlockVector2)
|
||||
.collect(Collectors.toSet());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -25,7 +25,6 @@ import com.sk89q.worldedit.WorldEditException;
|
||||
import com.sk89q.worldedit.entity.BaseEntity;
|
||||
import com.sk89q.worldedit.entity.Entity;
|
||||
import com.sk89q.worldedit.function.operation.Operation;
|
||||
import com.sk89q.worldedit.math.BlockVector2;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
import com.sk89q.worldedit.regions.Region;
|
||||
import com.sk89q.worldedit.util.Location;
|
||||
@ -51,7 +50,7 @@ public class BlockArrayClipboard implements Clipboard {
|
||||
private final Region region;
|
||||
private BlockVector3 origin;
|
||||
private final BaseBlock[][][] blocks;
|
||||
private BiomeType[][] biomes = null;
|
||||
private BiomeType[][][] biomes = null;
|
||||
private final List<ClipboardEntity> entities = new ArrayList<>();
|
||||
|
||||
/**
|
||||
@ -167,11 +166,11 @@ public class BlockArrayClipboard implements Clipboard {
|
||||
}
|
||||
|
||||
@Override
|
||||
public BiomeType getBiome(BlockVector2 position) {
|
||||
public BiomeType getBiome(BlockVector3 position) {
|
||||
if (biomes != null
|
||||
&& position.containedWithin(getMinimumPoint().toBlockVector2(), getMaximumPoint().toBlockVector2())) {
|
||||
BlockVector2 v = position.subtract(region.getMinimumPoint().toBlockVector2());
|
||||
BiomeType biomeType = biomes[v.getBlockX()][v.getBlockZ()];
|
||||
&& position.containedWithin(getMinimumPoint(), getMaximumPoint())) {
|
||||
BlockVector3 v = position.subtract(region.getMinimumPoint());
|
||||
BiomeType biomeType = biomes[v.getBlockX()][v.getBlockY()][v.getBlockZ()];
|
||||
if (biomeType != null) {
|
||||
return biomeType;
|
||||
}
|
||||
@ -181,13 +180,13 @@ public class BlockArrayClipboard implements Clipboard {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setBiome(BlockVector2 position, BiomeType biome) {
|
||||
if (position.containedWithin(getMinimumPoint().toBlockVector2(), getMaximumPoint().toBlockVector2())) {
|
||||
BlockVector2 v = position.subtract(region.getMinimumPoint().toBlockVector2());
|
||||
public boolean setBiome(BlockVector3 position, BiomeType biome) {
|
||||
if (position.containedWithin(getMinimumPoint(), getMaximumPoint())) {
|
||||
BlockVector3 v = position.subtract(region.getMinimumPoint());
|
||||
if (biomes == null) {
|
||||
biomes = new BiomeType[region.getWidth()][region.getLength()];
|
||||
biomes = new BiomeType[region.getWidth()][region.getHeight()][region.getLength()];
|
||||
}
|
||||
biomes[v.getBlockX()][v.getBlockZ()] = biome;
|
||||
biomes[v.getBlockX()][v.getBlockY()][v.getBlockZ()] = biome;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -20,7 +20,6 @@
|
||||
package com.sk89q.worldedit.extent.clipboard;
|
||||
|
||||
import com.sk89q.worldedit.extent.Extent;
|
||||
import com.sk89q.worldedit.math.BlockVector2;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
import com.sk89q.worldedit.regions.Region;
|
||||
|
||||
@ -60,10 +59,9 @@ public interface Clipboard extends Extent {
|
||||
void setOrigin(BlockVector3 origin);
|
||||
|
||||
/**
|
||||
* Returns true if the clipboard has biome data. This can be checked since {@link Extent#getBiome(BlockVector2)}
|
||||
* Returns true if the clipboard has biome data. This can be checked since {@link Extent#getBiome(BlockVector3)}
|
||||
* strongly suggests returning {@link com.sk89q.worldedit.world.biome.BiomeTypes#OCEAN} instead of {@code null}
|
||||
* if biomes aren't present. However, it might not be desired to set areas to ocean if the clipboard is defaulting
|
||||
* to ocean, instead of having biomes explicitly set.
|
||||
* if biomes aren't present.
|
||||
*
|
||||
* @return true if the clipboard has biome data set
|
||||
*/
|
||||
|
@ -39,7 +39,6 @@ import com.sk89q.worldedit.extension.platform.Capability;
|
||||
import com.sk89q.worldedit.extension.platform.Platform;
|
||||
import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard;
|
||||
import com.sk89q.worldedit.extent.clipboard.Clipboard;
|
||||
import com.sk89q.worldedit.math.BlockVector2;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
import com.sk89q.worldedit.regions.CuboidRegion;
|
||||
import com.sk89q.worldedit.regions.Region;
|
||||
@ -337,7 +336,7 @@ public class SpongeSchematicReader extends NBTSchematicReader {
|
||||
int biomeJ = 0;
|
||||
int bVal;
|
||||
int varIntLength;
|
||||
BlockVector2 min = clipboard.getMinimumPoint().toBlockVector2();
|
||||
BlockVector3 min = clipboard.getMinimumPoint();
|
||||
while (biomeJ < biomes.length) {
|
||||
bVal = 0;
|
||||
varIntLength = 0;
|
||||
@ -356,7 +355,9 @@ public class SpongeSchematicReader extends NBTSchematicReader {
|
||||
int z = biomeIndex / width;
|
||||
int x = biomeIndex % width;
|
||||
BiomeType type = palette.get(bVal);
|
||||
clipboard.setBiome(min.add(x, z), type);
|
||||
for (int y = 0; y < clipboard.getRegion().getHeight(); y++) {
|
||||
clipboard.setBiome(min.add(x, y, z), type);
|
||||
}
|
||||
biomeIndex++;
|
||||
}
|
||||
}
|
||||
|
@ -37,7 +37,6 @@ import com.sk89q.worldedit.WorldEdit;
|
||||
import com.sk89q.worldedit.entity.BaseEntity;
|
||||
import com.sk89q.worldedit.extension.platform.Capability;
|
||||
import com.sk89q.worldedit.extent.clipboard.Clipboard;
|
||||
import com.sk89q.worldedit.math.BlockVector2;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
import com.sk89q.worldedit.math.Vector3;
|
||||
import com.sk89q.worldedit.regions.Region;
|
||||
@ -217,7 +216,7 @@ public class SpongeSchematicWriter implements ClipboardWriter {
|
||||
int z0 = min.getBlockZ() + z;
|
||||
for (int x = 0; x < width; x++) {
|
||||
int x0 = min.getBlockX() + x;
|
||||
BlockVector2 pt = BlockVector2.at(x0, z0);
|
||||
BlockVector3 pt = BlockVector3.at(x0, min.getBlockY(), z0);
|
||||
BiomeType biome = clipboard.getBiome(pt);
|
||||
|
||||
String biomeKey = biome.getId();
|
||||
|
@ -71,9 +71,9 @@ public class ChunkLoadingExtent extends AbstractDelegateExtent {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setBiome(BlockVector2 position, BiomeType biome) {
|
||||
public boolean setBiome(BlockVector3 position, BiomeType biome) {
|
||||
if (enabled) {
|
||||
world.checkLoadedChunk(position.toBlockVector3());
|
||||
world.checkLoadedChunk(position);
|
||||
}
|
||||
return super.setBiome(position, biome);
|
||||
}
|
||||
|
@ -25,7 +25,6 @@ import com.sk89q.worldedit.entity.Entity;
|
||||
import com.sk89q.worldedit.extension.platform.Watchdog;
|
||||
import com.sk89q.worldedit.extent.AbstractDelegateExtent;
|
||||
import com.sk89q.worldedit.extent.Extent;
|
||||
import com.sk89q.worldedit.math.BlockVector2;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
import com.sk89q.worldedit.util.Location;
|
||||
import com.sk89q.worldedit.world.biome.BiomeType;
|
||||
@ -88,7 +87,7 @@ public class WatchdogTickingExtent extends AbstractDelegateExtent {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setBiome(BlockVector2 position, BiomeType biome) {
|
||||
public boolean setBiome(BlockVector3 position, BiomeType biome) {
|
||||
onOperation();
|
||||
return super.setBiome(position, biome);
|
||||
}
|
||||
|
@ -24,14 +24,16 @@ import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import com.sk89q.worldedit.WorldEditException;
|
||||
import com.sk89q.worldedit.extent.Extent;
|
||||
import com.sk89q.worldedit.function.FlatRegionFunction;
|
||||
import com.sk89q.worldedit.function.RegionFunction;
|
||||
import com.sk89q.worldedit.function.pattern.BiomePattern;
|
||||
import com.sk89q.worldedit.math.BlockVector2;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
import com.sk89q.worldedit.world.biome.BiomeType;
|
||||
|
||||
/**
|
||||
* Replaces the biome at the locations that this function is applied to.
|
||||
*/
|
||||
public class BiomeReplace implements FlatRegionFunction {
|
||||
public class BiomeReplace implements FlatRegionFunction, RegionFunction {
|
||||
|
||||
private final Extent extent;
|
||||
private BiomePattern biome;
|
||||
@ -60,8 +62,17 @@ public class BiomeReplace implements FlatRegionFunction {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(BlockVector2 position) throws WorldEditException {
|
||||
return extent.setBiome(position, biome.apply(position));
|
||||
public boolean apply(BlockVector3 position) throws WorldEditException {
|
||||
return extent.setBiome(position, biome.applyBiome(position));
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public boolean apply(BlockVector2 position) throws WorldEditException {
|
||||
boolean success = false;
|
||||
for (int y = extent.getMinimumPoint().getY(); y <= extent.getMaximumPoint().getY(); y++) {
|
||||
success |= apply(position.toBlockVector3(y));
|
||||
}
|
||||
return success;
|
||||
}
|
||||
}
|
||||
|
@ -22,7 +22,9 @@ package com.sk89q.worldedit.function.biome;
|
||||
import com.sk89q.worldedit.WorldEditException;
|
||||
import com.sk89q.worldedit.extent.Extent;
|
||||
import com.sk89q.worldedit.function.FlatRegionFunction;
|
||||
import com.sk89q.worldedit.function.RegionFunction;
|
||||
import com.sk89q.worldedit.math.BlockVector2;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
import com.sk89q.worldedit.math.transform.Transform;
|
||||
import com.sk89q.worldedit.world.biome.BiomeType;
|
||||
|
||||
@ -31,12 +33,12 @@ import static com.google.common.base.Preconditions.checkNotNull;
|
||||
/**
|
||||
* Copies the biome from one extent to another.
|
||||
*/
|
||||
public class ExtentBiomeCopy implements FlatRegionFunction {
|
||||
public class ExtentBiomeCopy implements FlatRegionFunction, RegionFunction {
|
||||
|
||||
private final Extent source;
|
||||
private final Extent destination;
|
||||
private final BlockVector2 from;
|
||||
private final BlockVector2 to;
|
||||
private final BlockVector3 from;
|
||||
private final BlockVector3 to;
|
||||
private final Transform transform;
|
||||
|
||||
/**
|
||||
@ -47,8 +49,32 @@ public class ExtentBiomeCopy implements FlatRegionFunction {
|
||||
* @param destination the destination extent
|
||||
* @param to the destination offset
|
||||
* @param transform a transform to apply to positions (after source offset, before destination offset)
|
||||
* @deprecated use {@link ExtentBiomeCopy#ExtentBiomeCopy(Extent, BlockVector3, Extent, BlockVector3, Transform)}
|
||||
*/
|
||||
@Deprecated
|
||||
public ExtentBiomeCopy(Extent source, BlockVector2 from, Extent destination, BlockVector2 to, Transform transform) {
|
||||
checkNotNull(source);
|
||||
checkNotNull(from);
|
||||
checkNotNull(destination);
|
||||
checkNotNull(to);
|
||||
checkNotNull(transform);
|
||||
this.source = source;
|
||||
this.from = from.toBlockVector3();
|
||||
this.destination = destination;
|
||||
this.to = to.toBlockVector3();
|
||||
this.transform = transform;
|
||||
}
|
||||
|
||||
/**
|
||||
* Make a new biome copy.
|
||||
*
|
||||
* @param source the source extent
|
||||
* @param from the source offset
|
||||
* @param destination the destination extent
|
||||
* @param to the destination offset
|
||||
* @param transform a transform to apply to positions (after source offset, before destination offset)
|
||||
*/
|
||||
public ExtentBiomeCopy(Extent source, BlockVector3 from, Extent destination, BlockVector3 to, Transform transform) {
|
||||
checkNotNull(source);
|
||||
checkNotNull(from);
|
||||
checkNotNull(destination);
|
||||
@ -62,11 +88,21 @@ public class ExtentBiomeCopy implements FlatRegionFunction {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(BlockVector2 position) throws WorldEditException {
|
||||
public boolean apply(BlockVector3 position) throws WorldEditException {
|
||||
BiomeType biome = source.getBiome(position);
|
||||
BlockVector2 orig = position.subtract(from);
|
||||
BlockVector2 transformed = transform.apply(orig.toVector3(0)).toVector2().toBlockPoint();
|
||||
BlockVector3 orig = position.subtract(from);
|
||||
BlockVector3 transformed = transform.apply(orig.toVector3()).toBlockPoint();
|
||||
|
||||
return destination.setBiome(transformed.add(to), biome);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public boolean apply(BlockVector2 position) throws WorldEditException {
|
||||
boolean success = false;
|
||||
for (int y = destination.getMinimumPoint().getY(); y <= destination.getMaximumPoint().getY(); y++) {
|
||||
success |= apply(position.toBlockVector3(y));
|
||||
}
|
||||
return success;
|
||||
}
|
||||
}
|
||||
|
@ -50,7 +50,7 @@ public class BlockReplace implements RegionFunction {
|
||||
|
||||
@Override
|
||||
public boolean apply(BlockVector3 position) throws WorldEditException {
|
||||
return extent.setBlock(position, pattern.apply(position));
|
||||
return extent.setBlock(position, pattern.applyBlock(position));
|
||||
}
|
||||
|
||||
}
|
@ -106,10 +106,10 @@ public class FloraGenerator implements RegionFunction {
|
||||
BlockState block = editSession.getBlock(position);
|
||||
|
||||
if (block.getBlockType() == BlockTypes.GRASS_BLOCK) {
|
||||
editSession.setBlock(position.add(0, 1, 0), temperatePattern.apply(position));
|
||||
editSession.setBlock(position.add(0, 1, 0), temperatePattern.applyBlock(position));
|
||||
return true;
|
||||
} else if (block.getBlockType() == BlockTypes.SAND) {
|
||||
editSession.setBlock(position.add(0, 1, 0), desertPattern.apply(position));
|
||||
editSession.setBlock(position.add(0, 1, 0), desertPattern.applyBlock(position));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -114,7 +114,7 @@ public class GardenPatchGenerator implements RegionFunction {
|
||||
setBlockIfAir(editSession, pos.add(1, h, -1), log);
|
||||
affected++;
|
||||
}
|
||||
setBlockIfAir(editSession, p = pos.add(0, 0, -1), plant.apply(p));
|
||||
setBlockIfAir(editSession, p = pos.add(0, 0, -1), plant.applyBlock(p));
|
||||
affected++;
|
||||
break;
|
||||
|
||||
@ -126,7 +126,7 @@ public class GardenPatchGenerator implements RegionFunction {
|
||||
setBlockIfAir(editSession, pos.add(1, h, 0), log);
|
||||
affected++;
|
||||
}
|
||||
setBlockIfAir(editSession, p = pos.add(1, 0, 1), plant.apply(p));
|
||||
setBlockIfAir(editSession, p = pos.add(1, 0, 1), plant.applyBlock(p));
|
||||
affected++;
|
||||
break;
|
||||
|
||||
@ -138,7 +138,7 @@ public class GardenPatchGenerator implements RegionFunction {
|
||||
setBlockIfAir(editSession, pos.add(-1, h, 0), log);
|
||||
affected++;
|
||||
}
|
||||
setBlockIfAir(editSession, p = pos.add(-1, 0, 1), plant.apply(p));
|
||||
setBlockIfAir(editSession, p = pos.add(-1, 0, 1), plant.applyBlock(p));
|
||||
affected++;
|
||||
break;
|
||||
|
||||
@ -150,7 +150,7 @@ public class GardenPatchGenerator implements RegionFunction {
|
||||
setBlockIfAir(editSession, pos.add(-1, h, -1), log);
|
||||
affected++;
|
||||
}
|
||||
setBlockIfAir(editSession, p = pos.add(-1, 0, -1), plant.apply(p));
|
||||
setBlockIfAir(editSession, p = pos.add(-1, 0, -1), plant.applyBlock(p));
|
||||
affected++;
|
||||
break;
|
||||
}
|
||||
|
@ -0,0 +1,106 @@
|
||||
/*
|
||||
* 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.function.mask;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
import com.sk89q.worldedit.extent.Extent;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
import com.sk89q.worldedit.world.biome.BiomeType;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* Tests true if the biome at applied points is the same as the one given.
|
||||
*/
|
||||
public class BiomeMask extends AbstractMask {
|
||||
|
||||
private final Extent extent;
|
||||
private final Set<BiomeType> biomes = new HashSet<>();
|
||||
|
||||
/**
|
||||
* Create a new biome mask.
|
||||
*
|
||||
* @param extent the extent
|
||||
* @param biomes a list of biomes to match
|
||||
*/
|
||||
public BiomeMask(Extent extent, Collection<BiomeType> biomes) {
|
||||
checkNotNull(extent);
|
||||
checkNotNull(biomes);
|
||||
this.extent = extent;
|
||||
this.biomes.addAll(biomes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new biome mask.
|
||||
*
|
||||
* @param extent the extent
|
||||
* @param biome an array of biomes to match
|
||||
*/
|
||||
public BiomeMask(Extent extent, BiomeType... biome) {
|
||||
this(extent, Arrays.asList(checkNotNull(biome)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the given biomes to the list of criteria.
|
||||
*
|
||||
* @param biomes a list of biomes
|
||||
*/
|
||||
public void add(Collection<BiomeType> biomes) {
|
||||
checkNotNull(biomes);
|
||||
this.biomes.addAll(biomes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the given biomes to the list of criteria.
|
||||
*
|
||||
* @param biome an array of biomes
|
||||
*/
|
||||
public void add(BiomeType... biome) {
|
||||
add(Arrays.asList(checkNotNull(biome)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the list of biomes that are tested with.
|
||||
*
|
||||
* @return a list of biomes
|
||||
*/
|
||||
public Collection<BiomeType> getBiomes() {
|
||||
return biomes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean test(BlockVector3 vector) {
|
||||
BiomeType biome = extent.getBiome(vector);
|
||||
return biomes.contains(biome);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Mask2D toMask2D() {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
@ -32,7 +32,10 @@ import java.util.Set;
|
||||
|
||||
/**
|
||||
* Tests true if the biome at applied points is the same as the one given.
|
||||
*
|
||||
* @deprecated use {@link BiomeMask} as biomes are now 3D.
|
||||
*/
|
||||
@Deprecated
|
||||
public class BiomeMask2D extends AbstractMask2D {
|
||||
|
||||
private final Extent extent;
|
||||
|
@ -29,18 +29,14 @@ import com.sk89q.worldedit.entity.Entity;
|
||||
import com.sk89q.worldedit.entity.metadata.EntityProperties;
|
||||
import com.sk89q.worldedit.extent.Extent;
|
||||
import com.sk89q.worldedit.function.CombinedRegionFunction;
|
||||
import com.sk89q.worldedit.function.FlatRegionFunction;
|
||||
import com.sk89q.worldedit.function.FlatRegionMaskingFilter;
|
||||
import com.sk89q.worldedit.function.RegionFunction;
|
||||
import com.sk89q.worldedit.function.RegionMaskingFilter;
|
||||
import com.sk89q.worldedit.function.biome.ExtentBiomeCopy;
|
||||
import com.sk89q.worldedit.function.block.ExtentBlockCopy;
|
||||
import com.sk89q.worldedit.function.entity.ExtentEntityCopy;
|
||||
import com.sk89q.worldedit.function.mask.Mask;
|
||||
import com.sk89q.worldedit.function.mask.Mask2D;
|
||||
import com.sk89q.worldedit.function.mask.Masks;
|
||||
import com.sk89q.worldedit.function.visitor.EntityVisitor;
|
||||
import com.sk89q.worldedit.function.visitor.FlatRegionVisitor;
|
||||
import com.sk89q.worldedit.function.visitor.RegionVisitor;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
import com.sk89q.worldedit.math.transform.Identity;
|
||||
@ -78,7 +74,7 @@ public class ForwardExtentCopy implements Operation {
|
||||
private Transform currentTransform = null;
|
||||
|
||||
private RegionVisitor lastVisitor;
|
||||
private FlatRegionVisitor lastBiomeVisitor;
|
||||
private RegionVisitor lastBiomeVisitor;
|
||||
private EntityVisitor lastEntityVisitor;
|
||||
|
||||
private int affectedBlocks;
|
||||
@ -255,9 +251,6 @@ public class ForwardExtentCopy implements Operation {
|
||||
* @param copyingBiomes true if copying
|
||||
*/
|
||||
public void setCopyingBiomes(boolean copyingBiomes) {
|
||||
if (copyingBiomes && !(region instanceof FlatRegion)) {
|
||||
throw new UnsupportedOperationException("Can't copy biomes from region that doesn't implement FlatRegion");
|
||||
}
|
||||
this.copyingBiomes = copyingBiomes;
|
||||
}
|
||||
|
||||
@ -307,13 +300,12 @@ public class ForwardExtentCopy implements Operation {
|
||||
|
||||
List<Operation> ops = Lists.newArrayList(blockVisitor);
|
||||
|
||||
if (copyingBiomes && region instanceof FlatRegion) { // double-check here even though we checked before
|
||||
ExtentBiomeCopy biomeCopy = new ExtentBiomeCopy(source, from.toBlockVector2(),
|
||||
destination, to.toBlockVector2(), currentTransform);
|
||||
Mask2D biomeMask = sourceMask.toMask2D();
|
||||
FlatRegionFunction biomeFunction = biomeMask == null ? biomeCopy
|
||||
: new FlatRegionMaskingFilter(biomeMask, biomeCopy);
|
||||
FlatRegionVisitor biomeVisitor = new FlatRegionVisitor(((FlatRegion) region), biomeFunction);
|
||||
if (copyingBiomes) {
|
||||
ExtentBiomeCopy biomeCopy = new ExtentBiomeCopy(source, from,
|
||||
destination, to, currentTransform);
|
||||
RegionFunction biomeFunction = sourceFunction == null ? biomeCopy
|
||||
: new RegionMaskingFilter(sourceMask, biomeCopy);
|
||||
RegionVisitor biomeVisitor = new RegionVisitor(region, biomeFunction);
|
||||
ops.add(biomeVisitor);
|
||||
lastBiomeVisitor = biomeVisitor;
|
||||
}
|
||||
|
@ -19,7 +19,10 @@
|
||||
|
||||
package com.sk89q.worldedit.function.pattern;
|
||||
|
||||
import com.sk89q.worldedit.internal.util.DeprecationUtil;
|
||||
import com.sk89q.worldedit.internal.util.NonAbstractForCompatibility;
|
||||
import com.sk89q.worldedit.math.BlockVector2;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
import com.sk89q.worldedit.world.biome.BiomeType;
|
||||
|
||||
/**
|
||||
@ -31,7 +34,29 @@ public interface BiomePattern {
|
||||
* Return a {@link BiomeType} for the given position.
|
||||
*
|
||||
* @param position the position
|
||||
* @return a block
|
||||
* @return a biome
|
||||
* @deprecated use {@link BiomePattern#applyBiome(BlockVector3)}
|
||||
*/
|
||||
BiomeType apply(BlockVector2 position);
|
||||
@Deprecated
|
||||
default BiomeType apply(BlockVector2 position) {
|
||||
return applyBiome(position.toBlockVector3());
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a {@link BiomeType} for the given position.
|
||||
*
|
||||
* @param position the position
|
||||
* @return a biome
|
||||
* @apiNote This must be overridden by new subclasses. See {@link NonAbstractForCompatibility}
|
||||
* for details
|
||||
*/
|
||||
@NonAbstractForCompatibility(
|
||||
delegateName = "apply",
|
||||
delegateParams = { BlockVector2.class }
|
||||
)
|
||||
default BiomeType applyBiome(BlockVector3 position) {
|
||||
DeprecationUtil.checkDelegatingOverride(getClass());
|
||||
|
||||
return apply(position.toBlockVector2());
|
||||
}
|
||||
}
|
||||
|
@ -64,7 +64,7 @@ public class BlockPattern extends AbstractPattern {
|
||||
}
|
||||
|
||||
@Override
|
||||
public BaseBlock apply(BlockVector3 position) {
|
||||
public BaseBlock applyBlock(BlockVector3 position) {
|
||||
return block;
|
||||
}
|
||||
|
||||
|
@ -52,10 +52,10 @@ public class ExtentBufferedCompositePattern extends AbstractExtentPattern {
|
||||
}
|
||||
|
||||
@Override
|
||||
public BaseBlock apply(BlockVector3 position) {
|
||||
public BaseBlock applyBlock(BlockVector3 position) {
|
||||
BaseBlock lastBlock = null;
|
||||
for (Pattern pattern : patterns) {
|
||||
lastBlock = pattern.apply(position);
|
||||
lastBlock = pattern.applyBlock(position);
|
||||
try {
|
||||
getExtent().setBlock(position, lastBlock);
|
||||
} catch (WorldEditException ignored) { // buffer doesn't throw
|
||||
|
@ -19,21 +19,43 @@
|
||||
|
||||
package com.sk89q.worldedit.function.pattern;
|
||||
|
||||
import com.sk89q.worldedit.internal.util.DeprecationUtil;
|
||||
import com.sk89q.worldedit.internal.util.NonAbstractForCompatibility;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
import com.sk89q.worldedit.world.block.BaseBlock;
|
||||
import com.sk89q.worldedit.world.block.BlockStateHolder;
|
||||
|
||||
/**
|
||||
* Returns a {@link BlockStateHolder} for a given position.
|
||||
* Returns a {@link BaseBlock} for a given position.
|
||||
*/
|
||||
public interface Pattern {
|
||||
|
||||
/**
|
||||
* Return a {@link BlockStateHolder} for the given position.
|
||||
* Return a {@link BaseBlock} for the given position.
|
||||
*
|
||||
* @param position the position
|
||||
* @return a block
|
||||
* @deprecated use {@link Pattern#applyBlock(BlockVector3)}
|
||||
*/
|
||||
BaseBlock apply(BlockVector3 position);
|
||||
@Deprecated
|
||||
default BaseBlock apply(BlockVector3 position) {
|
||||
return applyBlock(position);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a {@link BaseBlock} for the given position.
|
||||
*
|
||||
* @param position the position
|
||||
* @return a block
|
||||
* @apiNote This must be overridden by new subclasses. See {@link NonAbstractForCompatibility}
|
||||
* for details
|
||||
*/
|
||||
@NonAbstractForCompatibility(
|
||||
delegateName = "apply",
|
||||
delegateParams = { BlockVector3.class }
|
||||
)
|
||||
default BaseBlock applyBlock(BlockVector3 position) {
|
||||
DeprecationUtil.checkDelegatingOverride(getClass());
|
||||
|
||||
return apply(position);
|
||||
}
|
||||
}
|
||||
|
@ -53,13 +53,13 @@ public class RandomPattern extends AbstractPattern {
|
||||
}
|
||||
|
||||
@Override
|
||||
public BaseBlock apply(BlockVector3 position) {
|
||||
public BaseBlock applyBlock(BlockVector3 position) {
|
||||
double r = random.nextDouble();
|
||||
double offset = 0;
|
||||
|
||||
for (Chance chance : patterns) {
|
||||
if (r <= (offset + chance.getChance()) / max) {
|
||||
return chance.getPattern().apply(position);
|
||||
return chance.getPattern().applyBlock(position);
|
||||
}
|
||||
offset += chance.getChance();
|
||||
}
|
||||
|
@ -39,7 +39,7 @@ public class RandomStatePattern implements Pattern {
|
||||
}
|
||||
|
||||
@Override
|
||||
public BaseBlock apply(BlockVector3 position) {
|
||||
public BaseBlock applyBlock(BlockVector3 position) {
|
||||
return blocks.get(rand.nextInt(blocks.size()));
|
||||
}
|
||||
}
|
||||
|
@ -86,7 +86,7 @@ public class RepeatingExtentPattern extends AbstractExtentPattern {
|
||||
}
|
||||
|
||||
@Override
|
||||
public BaseBlock apply(BlockVector3 position) {
|
||||
public BaseBlock applyBlock(BlockVector3 position) {
|
||||
BlockVector3 base = position.add(offset);
|
||||
int x = Math.abs(base.getBlockX()) % size.getBlockX();
|
||||
int y = Math.abs(base.getBlockY()) % size.getBlockY();
|
||||
|
@ -43,7 +43,7 @@ public class StateApplyingPattern extends AbstractExtentPattern {
|
||||
}
|
||||
|
||||
@Override
|
||||
public BaseBlock apply(BlockVector3 position) {
|
||||
public BaseBlock applyBlock(BlockVector3 position) {
|
||||
BlockState block = getExtent().getBlock(position);
|
||||
for (Entry<Property<Object>, Object> entry : cache
|
||||
.computeIfAbsent(block.getBlockType(), (b -> resolveProperties(states, b))).entrySet()) {
|
||||
|
@ -39,7 +39,7 @@ public class TypeApplyingPattern extends AbstractExtentPattern {
|
||||
}
|
||||
|
||||
@Override
|
||||
public BaseBlock apply(BlockVector3 position) {
|
||||
public BaseBlock applyBlock(BlockVector3 position) {
|
||||
BlockState oldBlock = getExtent().getBlock(position);
|
||||
BlockState newBlock = blockState;
|
||||
for (Entry<Property<?>, Object> entry : oldBlock.getStates().entrySet()) {
|
||||
|
@ -35,7 +35,7 @@ public class WaterloggedRemover extends AbstractExtentPattern {
|
||||
}
|
||||
|
||||
@Override
|
||||
public BaseBlock apply(BlockVector3 position) {
|
||||
public BaseBlock applyBlock(BlockVector3 position) {
|
||||
BaseBlock block = getExtent().getFullBlock(position);
|
||||
@SuppressWarnings("unchecked")
|
||||
Property<Object> prop = (Property<Object>) block.getBlockType().getPropertyMap().getOrDefault("waterlogged", null);
|
||||
|
@ -33,7 +33,9 @@ import com.sk89q.worldedit.world.biome.BiomeType;
|
||||
* <p>This biome change does not have an {@link Extent} assigned to it because
|
||||
* one will be taken from the passed {@link UndoContext}. If the context
|
||||
* does not have an extent (it is null), cryptic errors may occur.</p>
|
||||
* @deprecated use {@link BiomeChange3D}
|
||||
*/
|
||||
@Deprecated
|
||||
public class BiomeChange implements Change {
|
||||
|
||||
private final BlockVector2 position;
|
||||
@ -85,12 +87,12 @@ public class BiomeChange implements Change {
|
||||
|
||||
@Override
|
||||
public void undo(UndoContext context) throws WorldEditException {
|
||||
checkNotNull(context.getExtent()).setBiome(position, previous);
|
||||
checkNotNull(context.getExtent()).setBiome(position.toBlockVector3(), previous);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void redo(UndoContext context) throws WorldEditException {
|
||||
checkNotNull(context.getExtent()).setBiome(position, current);
|
||||
checkNotNull(context.getExtent()).setBiome(position.toBlockVector3(), current);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,96 @@
|
||||
/*
|
||||
* 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.history.change;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
import com.sk89q.worldedit.WorldEditException;
|
||||
import com.sk89q.worldedit.extent.Extent;
|
||||
import com.sk89q.worldedit.history.UndoContext;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
import com.sk89q.worldedit.world.biome.BiomeType;
|
||||
|
||||
/**
|
||||
* Represents a biome change that may be undone or replayed.
|
||||
*
|
||||
* <p>This biome change does not have an {@link Extent} assigned to it because
|
||||
* one will be taken from the passed {@link UndoContext}. If the context
|
||||
* does not have an extent (it is null), cryptic errors may occur.</p>
|
||||
*/
|
||||
public class BiomeChange3D implements Change {
|
||||
|
||||
private final BlockVector3 position;
|
||||
private final BiomeType previous;
|
||||
private final BiomeType current;
|
||||
|
||||
/**
|
||||
* Create a new biome change.
|
||||
*
|
||||
* @param position the position
|
||||
* @param previous the previous biome
|
||||
* @param current the current biome
|
||||
*/
|
||||
public BiomeChange3D(BlockVector3 position, BiomeType previous, BiomeType current) {
|
||||
checkNotNull(position);
|
||||
checkNotNull(previous);
|
||||
checkNotNull(current);
|
||||
this.position = position;
|
||||
this.previous = previous;
|
||||
this.current = current;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the position.
|
||||
*
|
||||
* @return the position
|
||||
*/
|
||||
public BlockVector3 getPosition() {
|
||||
return position;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the previous biome.
|
||||
*
|
||||
* @return the previous biome
|
||||
*/
|
||||
public BiomeType getPrevious() {
|
||||
return previous;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current biome.
|
||||
*
|
||||
* @return the current biome
|
||||
*/
|
||||
public BiomeType getCurrent() {
|
||||
return current;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void undo(UndoContext context) throws WorldEditException {
|
||||
checkNotNull(context.getExtent()).setBiome(position, previous);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void redo(UndoContext context) throws WorldEditException {
|
||||
checkNotNull(context.getExtent()).setBiome(position, current);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,97 @@
|
||||
/*
|
||||
* 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.internal.util;
|
||||
|
||||
import com.google.common.base.Joiner;
|
||||
import com.google.common.base.Throwables;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public class DeprecationUtil {
|
||||
|
||||
private DeprecationUtil() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify that one of the two functions is overridden. Caller method must be the new method,
|
||||
* annotated with {@link NonAbstractForCompatibility}.
|
||||
*
|
||||
* @param implementingClass the result of calling {@link Object#getClass()}
|
||||
*/
|
||||
public static void checkDelegatingOverride(Class<?> implementingClass) {
|
||||
// pull the information about the caller
|
||||
StackTraceElement caller = Throwables.lazyStackTrace(new Throwable()).get(1);
|
||||
// find the matching caller method
|
||||
Method callingMethod = getCallingMethod(caller);
|
||||
NonAbstractForCompatibility annotation =
|
||||
callingMethod.getAnnotation(NonAbstractForCompatibility.class);
|
||||
// get the deprecated method
|
||||
Method deprecatedMethod;
|
||||
try {
|
||||
deprecatedMethod = implementingClass.getMethod(
|
||||
annotation.delegateName(), annotation.delegateParams()
|
||||
);
|
||||
} catch (NoSuchMethodException e) {
|
||||
throw new AssertionError(
|
||||
"Missing method referenced by " + NonAbstractForCompatibility.class, e
|
||||
);
|
||||
}
|
||||
// Check if the deprecated method was overridden. If the declaring class is the caller's
|
||||
// class, then it wasn't. That means that the caller method (i.e. the new method) should be
|
||||
// overridden by the implementing class.
|
||||
// There's no need to check if the new method has been overridden, since the only other
|
||||
// way this could be reached is if someone calls `super.xyz`, which they have no reason to.
|
||||
if (deprecatedMethod.getDeclaringClass().getName().equals(caller.getClassName())) {
|
||||
throw new IllegalStateException("Class " + implementingClass.getName()
|
||||
+ " must override " + methodToString(callingMethod));
|
||||
}
|
||||
}
|
||||
|
||||
private static Method getCallingMethod(StackTraceElement callerInfo) {
|
||||
Method[] declaredMethods;
|
||||
try {
|
||||
declaredMethods = Class.forName(callerInfo.getClassName()).getDeclaredMethods();
|
||||
} catch (ClassNotFoundException e) {
|
||||
throw new AssertionError("Caller class missing?", e);
|
||||
}
|
||||
for (Method declaredMethod : declaredMethods) {
|
||||
if (declaredMethod.isAnnotationPresent(NonAbstractForCompatibility.class) &&
|
||||
declaredMethod.getName().equals(callerInfo.getMethodName())) {
|
||||
return declaredMethod;
|
||||
}
|
||||
}
|
||||
throw new IllegalStateException("Failed to find caller method " +
|
||||
callerInfo.getMethodName() + " annotated with " + NonAbstractForCompatibility.class);
|
||||
}
|
||||
|
||||
private static String methodToString(Method method) {
|
||||
StringBuilder builder = new StringBuilder(method.getDeclaringClass().getCanonicalName())
|
||||
.append('.')
|
||||
.append(method.getName())
|
||||
.append('(');
|
||||
Joiner.on(", ").appendTo(builder, Stream.of(method.getParameterTypes())
|
||||
.map(Class::getSimpleName)
|
||||
.iterator());
|
||||
builder.append(')');
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,57 @@
|
||||
/*
|
||||
* 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.internal.util;
|
||||
|
||||
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;
|
||||
|
||||
/**
|
||||
* The annotated method is only non-{@code abstract} for compatibility with old subclasses,
|
||||
* and will be made {@code abstract} in the next major version of WorldEdit.
|
||||
*
|
||||
* <p>
|
||||
* Any new subclasses <em>must</em> override the annotated method, failing to do so will result in
|
||||
* an exception at runtime.
|
||||
* </p>
|
||||
*/
|
||||
@Documented
|
||||
@Target(ElementType.METHOD)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface NonAbstractForCompatibility {
|
||||
|
||||
// Note that this annotation only functions properly if no other method in the same class
|
||||
// shares the name of the annotated function AND is also annotated with this annotation.
|
||||
// Otherwise, we cannot uniquely determine the calling method via reflection hacks.
|
||||
// This could be changed, but it's not currently necessary.
|
||||
|
||||
/**
|
||||
* The name of the method delegated to by the annotated method.
|
||||
*/
|
||||
String delegateName();
|
||||
|
||||
/**
|
||||
* The parameter types of the method delegated to by the annotated method.
|
||||
*/
|
||||
Class<?>[] delegateParams();
|
||||
|
||||
}
|
@ -19,9 +19,11 @@
|
||||
|
||||
package com.sk89q.worldedit.regions;
|
||||
|
||||
import com.sk89q.worldedit.internal.util.NonAbstractForCompatibility;
|
||||
import com.sk89q.worldedit.math.BlockVector2;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
import com.sk89q.worldedit.math.Vector3;
|
||||
import com.sk89q.worldedit.internal.util.DeprecationUtil;
|
||||
import com.sk89q.worldedit.world.World;
|
||||
|
||||
import java.util.List;
|
||||
@ -71,19 +73,17 @@ public interface Region extends Iterable<BlockVector3>, Cloneable {
|
||||
/**
|
||||
* Get the number of blocks in the region.
|
||||
*
|
||||
* <p>Note: This method <b>must</b> be overridden.</p>
|
||||
*
|
||||
* @return number of blocks
|
||||
* @apiNote This must be overridden by new subclasses. See {@link NonAbstractForCompatibility}
|
||||
* for details
|
||||
*/
|
||||
@NonAbstractForCompatibility(
|
||||
delegateName = "getArea",
|
||||
delegateParams = {}
|
||||
)
|
||||
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);
|
||||
}
|
||||
DeprecationUtil.checkDelegatingOverride(getClass());
|
||||
|
||||
return getArea();
|
||||
}
|
||||
|
||||
|
@ -23,6 +23,8 @@ import com.google.common.collect.Lists;
|
||||
import com.sk89q.worldedit.IncompleteRegionException;
|
||||
import com.sk89q.worldedit.LocalSession;
|
||||
import com.sk89q.worldedit.extension.platform.Actor;
|
||||
import com.sk89q.worldedit.internal.util.DeprecationUtil;
|
||||
import com.sk89q.worldedit.internal.util.NonAbstractForCompatibility;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
import com.sk89q.worldedit.regions.selector.limit.SelectorLimits;
|
||||
import com.sk89q.worldedit.util.formatting.text.Component;
|
||||
@ -30,11 +32,10 @@ import com.sk89q.worldedit.util.formatting.text.TextComponent;
|
||||
import com.sk89q.worldedit.util.formatting.text.format.TextColor;
|
||||
import com.sk89q.worldedit.world.World;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* Region selectors create {@link Region}s from a series of "selected points."
|
||||
* They are used, for example, to allow users to create a {@link CuboidRegion}
|
||||
@ -144,19 +145,17 @@ public interface RegionSelector {
|
||||
/**
|
||||
* 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
|
||||
* @apiNote This must be overridden by new subclasses. See {@link NonAbstractForCompatibility}
|
||||
* for details
|
||||
*/
|
||||
@NonAbstractForCompatibility(
|
||||
delegateName = "getArea",
|
||||
delegateParams = {}
|
||||
)
|
||||
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);
|
||||
}
|
||||
DeprecationUtil.checkDelegatingOverride(getClass());
|
||||
|
||||
return getArea();
|
||||
}
|
||||
|
||||
|
@ -20,9 +20,7 @@
|
||||
package com.sk89q.worldedit.regions.shape;
|
||||
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
import com.sk89q.worldedit.math.BlockVector2;
|
||||
import com.sk89q.worldedit.regions.CuboidRegion;
|
||||
import com.sk89q.worldedit.regions.FlatRegion;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
import com.sk89q.worldedit.regions.Region;
|
||||
import com.sk89q.worldedit.world.biome.BiomeType;
|
||||
import com.sk89q.worldedit.world.biome.BiomeTypes;
|
||||
@ -33,36 +31,34 @@ import com.sk89q.worldedit.world.biome.BiomeTypes;
|
||||
*/
|
||||
public abstract class ArbitraryBiomeShape {
|
||||
|
||||
private final FlatRegion extent;
|
||||
private int cacheOffsetX;
|
||||
private int cacheOffsetZ;
|
||||
private final Region extent;
|
||||
private final int cacheOffsetX;
|
||||
private final int cacheOffsetY;
|
||||
private final int cacheOffsetZ;
|
||||
@SuppressWarnings("FieldCanBeLocal")
|
||||
private int cacheSizeX;
|
||||
private int cacheSizeZ;
|
||||
private final int cacheSizeX;
|
||||
private final int cacheSizeY;
|
||||
private final int cacheSizeZ;
|
||||
|
||||
public ArbitraryBiomeShape(Region extent) {
|
||||
if (extent instanceof FlatRegion) {
|
||||
this.extent = (FlatRegion) extent;
|
||||
}
|
||||
else {
|
||||
// TODO: polygonize
|
||||
this.extent = new CuboidRegion(extent.getWorld(), extent.getMinimumPoint(), extent.getMaximumPoint());
|
||||
}
|
||||
this.extent = extent;
|
||||
|
||||
BlockVector2 min = extent.getMinimumPoint().toBlockVector2();
|
||||
BlockVector2 max = extent.getMaximumPoint().toBlockVector2();
|
||||
BlockVector3 min = extent.getMinimumPoint();
|
||||
BlockVector3 max = extent.getMaximumPoint();
|
||||
|
||||
cacheOffsetX = min.getBlockX() - 1;
|
||||
cacheOffsetY = min.getBlockY() - 1;
|
||||
cacheOffsetZ = min.getBlockZ() - 1;
|
||||
|
||||
cacheSizeX = max.getX() - cacheOffsetX + 2;
|
||||
cacheSizeY = max.getY() - cacheOffsetY + 2;
|
||||
cacheSizeZ = max.getZ() - cacheOffsetZ + 2;
|
||||
|
||||
cache = new BiomeType[cacheSizeX * cacheSizeZ];
|
||||
cache = new BiomeType[cacheSizeX * cacheSizeY * cacheSizeZ];
|
||||
}
|
||||
|
||||
protected Iterable<BlockVector2> getExtent() {
|
||||
return extent.asFlatRegion();
|
||||
protected Iterable<BlockVector3> getExtent() {
|
||||
return extent;
|
||||
}
|
||||
|
||||
|
||||
@ -82,17 +78,17 @@ public abstract class ArbitraryBiomeShape {
|
||||
* @param defaultBaseBiome The default biome for the current column.
|
||||
* @return material to place or null to not place anything.
|
||||
*/
|
||||
protected abstract BiomeType getBiome(int x, int z, BiomeType defaultBaseBiome);
|
||||
protected abstract BiomeType getBiome(int x, int y, int z, BiomeType defaultBaseBiome);
|
||||
|
||||
private BiomeType getBiomeCached(int x, int z, BiomeType baseBiome) {
|
||||
final int index = (z - cacheOffsetZ) + (x - cacheOffsetX) * cacheSizeZ;
|
||||
private BiomeType getBiomeCached(int x, int y, int z, BiomeType baseBiome) {
|
||||
final int index = (y - cacheOffsetY) + (z - cacheOffsetZ) * cacheSizeY + (x - cacheOffsetX) * cacheSizeY * cacheSizeZ;
|
||||
|
||||
final BiomeType cacheEntry = cache[index];
|
||||
if (cacheEntry == null) {// unknown, fetch material
|
||||
final BiomeType material = getBiome(x, z, baseBiome);
|
||||
final BiomeType material = getBiome(x, y, z, baseBiome);
|
||||
if (material == null) {
|
||||
// outside
|
||||
cache[index] = BiomeTypes.THE_VOID;
|
||||
cache[index] = null;
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -100,21 +96,16 @@ public abstract class ArbitraryBiomeShape {
|
||||
return material;
|
||||
}
|
||||
|
||||
if (cacheEntry == BiomeTypes.THE_VOID) {
|
||||
// outside
|
||||
return null;
|
||||
}
|
||||
|
||||
return cacheEntry;
|
||||
}
|
||||
|
||||
private boolean isInsideCached(int x, int z, BiomeType baseBiome) {
|
||||
final int index = (z - cacheOffsetZ) + (x - cacheOffsetX) * cacheSizeZ;
|
||||
private boolean isInsideCached(int x, int y, int z, BiomeType baseBiome) {
|
||||
final int index = (y - cacheOffsetY) + (z - cacheOffsetZ) * cacheSizeY + (x - cacheOffsetX) * cacheSizeY * cacheSizeZ;
|
||||
|
||||
final BiomeType cacheEntry = cache[index];
|
||||
if (cacheEntry == null) {
|
||||
// unknown block, meaning they must be outside the extent at this stage, but might still be inside the shape
|
||||
return getBiomeCached(x, z, baseBiome) != null;
|
||||
return getBiomeCached(x, y, z, baseBiome) != null;
|
||||
}
|
||||
|
||||
return cacheEntry != BiomeTypes.THE_VOID;
|
||||
@ -131,12 +122,13 @@ public abstract class ArbitraryBiomeShape {
|
||||
public int generate(EditSession editSession, BiomeType baseBiome, boolean hollow) {
|
||||
int affected = 0;
|
||||
|
||||
for (BlockVector2 position : getExtent()) {
|
||||
for (BlockVector3 position : getExtent()) {
|
||||
int x = position.getBlockX();
|
||||
int y = position.getBlockY();
|
||||
int z = position.getBlockZ();
|
||||
|
||||
if (!hollow) {
|
||||
final BiomeType material = getBiome(x, z, baseBiome);
|
||||
final BiomeType material = getBiome(x, y, z, baseBiome);
|
||||
if (material != null && material != BiomeTypes.THE_VOID) {
|
||||
editSession.getWorld().setBiome(position, material);
|
||||
++affected;
|
||||
@ -145,26 +137,34 @@ public abstract class ArbitraryBiomeShape {
|
||||
continue;
|
||||
}
|
||||
|
||||
final BiomeType material = getBiomeCached(x, z, baseBiome);
|
||||
final BiomeType material = getBiomeCached(x, y, z, baseBiome);
|
||||
if (material == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
boolean draw = false;
|
||||
do {
|
||||
if (!isInsideCached(x + 1, z, baseBiome)) {
|
||||
if (!isInsideCached(x + 1, y, z, material)) {
|
||||
draw = true;
|
||||
break;
|
||||
}
|
||||
if (!isInsideCached(x - 1, z, baseBiome)) {
|
||||
if (!isInsideCached(x - 1, y, z, material)) {
|
||||
draw = true;
|
||||
break;
|
||||
}
|
||||
if (!isInsideCached(x, z + 1, baseBiome)) {
|
||||
if (!isInsideCached(x, y, z + 1, material)) {
|
||||
draw = true;
|
||||
break;
|
||||
}
|
||||
if (!isInsideCached(x, z - 1, baseBiome)) {
|
||||
if (!isInsideCached(x, y, z - 1, material)) {
|
||||
draw = true;
|
||||
break;
|
||||
}
|
||||
if (!isInsideCached(x, y + 1, z, material)) {
|
||||
draw = true;
|
||||
break;
|
||||
}
|
||||
if (!isInsideCached(x, y - 1, z, material)) {
|
||||
draw = true;
|
||||
break;
|
||||
}
|
||||
|
@ -99,7 +99,7 @@ public abstract class ArbitraryShape {
|
||||
int z = position.getBlockZ();
|
||||
|
||||
if (!hollow) {
|
||||
BaseBlock material = getMaterial(x, y, z, pattern.apply(position));
|
||||
BaseBlock material = getMaterial(x, y, z, pattern.applyBlock(position));
|
||||
if (material != null && editSession.setBlock(position, material)) {
|
||||
++affected;
|
||||
}
|
||||
@ -107,7 +107,7 @@ public abstract class ArbitraryShape {
|
||||
continue;
|
||||
}
|
||||
|
||||
BaseBlock material = getMaterial(x, y, z, pattern.apply(position));
|
||||
BaseBlock material = getMaterial(x, y, z, pattern.applyBlock(position));
|
||||
if (material == null) {
|
||||
final int index = (y - cacheOffsetY) + (z - cacheOffsetZ) * cacheSizeY + (x - cacheOffsetX) * cacheSizeY * cacheSizeZ;
|
||||
cache[index] = -1;
|
||||
@ -159,7 +159,7 @@ public abstract class ArbitraryShape {
|
||||
|
||||
switch (cache[index]) {
|
||||
case 0:
|
||||
BaseBlock mat = getMaterial(x, y, z, pattern.apply(BlockVector3.at(x, y, z)));
|
||||
BaseBlock mat = getMaterial(x, y, z, pattern.applyBlock(BlockVector3.at(x, y, z)));
|
||||
if (mat == null) {
|
||||
cache[index] = -1;
|
||||
return false;
|
||||
|
@ -86,7 +86,7 @@ public class RequestExtent implements Extent {
|
||||
}
|
||||
|
||||
@Override
|
||||
public BiomeType getBiome(BlockVector2 position) {
|
||||
public BiomeType getBiome(BlockVector3 position) {
|
||||
return getExtent().getBiome(position);
|
||||
}
|
||||
|
||||
@ -96,7 +96,7 @@ public class RequestExtent implements Extent {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setBiome(BlockVector2 position, BiomeType biome) {
|
||||
public boolean setBiome(BlockVector3 position, BiomeType biome) {
|
||||
return getExtent().setBiome(position, biome);
|
||||
}
|
||||
|
||||
|
@ -92,12 +92,12 @@ public class NullWorld extends AbstractWorld {
|
||||
}
|
||||
|
||||
@Override
|
||||
public BiomeType getBiome(BlockVector2 position) {
|
||||
public BiomeType getBiome(BlockVector3 position) {
|
||||
return BiomeTypes.THE_VOID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setBiome(BlockVector2 position, BiomeType biome) {
|
||||
public boolean setBiome(BlockVector3 position, BiomeType biome) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -20,7 +20,7 @@
|
||||
package com.sk89q.worldedit.world.biome;
|
||||
|
||||
import com.sk89q.worldedit.function.pattern.BiomePattern;
|
||||
import com.sk89q.worldedit.math.BlockVector2;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
import com.sk89q.worldedit.registry.Keyed;
|
||||
import com.sk89q.worldedit.registry.NamespacedRegistry;
|
||||
|
||||
@ -63,7 +63,7 @@ public class BiomeType implements Keyed, BiomePattern {
|
||||
}
|
||||
|
||||
@Override
|
||||
public BiomeType apply(BlockVector2 position) {
|
||||
public BiomeType applyBiome(BlockVector3 position) {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
@ -92,7 +92,7 @@ public interface BlockStateHolder<B extends BlockStateHolder<B>> extends Pattern
|
||||
BaseBlock toBaseBlock(CompoundTag compoundTag);
|
||||
|
||||
@Override
|
||||
default BaseBlock apply(BlockVector3 position) {
|
||||
default BaseBlock applyBlock(BlockVector3 position) {
|
||||
return toBaseBlock();
|
||||
}
|
||||
|
||||
|
@ -29,7 +29,7 @@
|
||||
"worldedit.brush.operation.equip": "Set brush to {0}.",
|
||||
"worldedit.brush.none.equip": "Brush unbound from your current item.",
|
||||
|
||||
"worldedit.setbiome.changed": "Biomes were changed in {0} columns. You may have to rejoin your game (or close and reopen your world) to see a change.",
|
||||
"worldedit.setbiome.changed": "Biomes were changed for approximately {0} blocks. You may have to rejoin your game (or close and reopen your world) to see a change.",
|
||||
|
||||
"worldedit.drawsel.disabled": "Server CUI disabled.",
|
||||
"worldedit.drawsel.enabled": "Server CUI enabled. This only supports cuboid regions, with a maximum size of 32x32x32.",
|
||||
|
@ -0,0 +1,88 @@
|
||||
/*
|
||||
* 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.internal.util;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
public class DeprecationUtilTest {
|
||||
|
||||
public interface ModifiedApi {
|
||||
@Deprecated
|
||||
default boolean oldApi() {
|
||||
return newApi();
|
||||
}
|
||||
|
||||
@NonAbstractForCompatibility(
|
||||
delegateName = "oldApi",
|
||||
delegateParams = {}
|
||||
)
|
||||
default boolean newApi() {
|
||||
DeprecationUtil.checkDelegatingOverride(getClass());
|
||||
return oldApi();
|
||||
}
|
||||
}
|
||||
|
||||
public static class OldImpl implements ModifiedApi {
|
||||
@SuppressWarnings("deprecation")
|
||||
@Override
|
||||
public boolean oldApi() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static class NewImpl implements ModifiedApi {
|
||||
@Override
|
||||
public boolean newApi() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public static class NewBadImpl implements ModifiedApi {
|
||||
}
|
||||
|
||||
@Test
|
||||
void oldImpl() {
|
||||
assertFalse(new OldImpl().oldApi());
|
||||
assertFalse(new OldImpl().newApi());
|
||||
}
|
||||
|
||||
@Test
|
||||
void newImpl() {
|
||||
assertTrue(new NewImpl().oldApi());
|
||||
assertTrue(new NewImpl().newApi());
|
||||
}
|
||||
|
||||
@Test
|
||||
void newBadImpl() {
|
||||
// regardless of which method is called, the message is the same
|
||||
Exception ex = assertThrows(IllegalStateException.class, new NewBadImpl()::oldApi);
|
||||
assertTrue(ex.getMessage().contains("must override"));
|
||||
assertTrue(ex.getMessage().contains("ModifiedApi.newApi()"));
|
||||
|
||||
ex = assertThrows(IllegalStateException.class, new NewBadImpl()::newApi);
|
||||
assertTrue(ex.getMessage().contains("must override"));
|
||||
assertTrue(ex.getMessage().contains("ModifiedApi.newApi()"));
|
||||
}
|
||||
|
||||
}
|
@ -202,15 +202,15 @@ public class FabricWorld extends AbstractWorld {
|
||||
}
|
||||
|
||||
@Override
|
||||
public BiomeType getBiome(BlockVector2 position) {
|
||||
public BiomeType getBiome(BlockVector3 position) {
|
||||
checkNotNull(position);
|
||||
Chunk chunk = getWorld().getChunk(position.getX() >> 4, position.getZ() >> 4);
|
||||
BiomeArray biomeArray = checkNotNull(chunk.getBiomeArray());
|
||||
return FabricAdapter.adapt(biomeArray.getBiomeForNoiseGen(position.getX() >> 2, 0, position.getZ() >> 2));
|
||||
return FabricAdapter.adapt(biomeArray.getBiomeForNoiseGen(position.getX() >> 2, position.getY() >> 2, position.getZ() >> 2));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setBiome(BlockVector2 position, BiomeType biome) {
|
||||
public boolean setBiome(BlockVector3 position, BiomeType biome) {
|
||||
checkNotNull(position);
|
||||
checkNotNull(biome);
|
||||
|
||||
@ -219,10 +219,7 @@ public class FabricWorld extends AbstractWorld {
|
||||
return false;
|
||||
}
|
||||
MutableBiomeArray biomeArray = MutableBiomeArray.inject(checkNotNull(chunk.getBiomeArray()));
|
||||
// Temporary, while biome setting is 2D only
|
||||
for (int i = 0; i <= getMaxY(); i++) {
|
||||
biomeArray.setBiome(position.getX(), i, position.getZ(), FabricAdapter.adapt(biome));
|
||||
}
|
||||
biomeArray.setBiome(position.getX(), position.getY(), position.getZ(), FabricAdapter.adapt(biome));
|
||||
chunk.setShouldSave(true);
|
||||
return true;
|
||||
}
|
||||
|
@ -201,16 +201,16 @@ public class ForgeWorld extends AbstractWorld {
|
||||
}
|
||||
|
||||
@Override
|
||||
public BiomeType getBiome(BlockVector2 position) {
|
||||
public BiomeType getBiome(BlockVector3 position) {
|
||||
checkNotNull(position);
|
||||
|
||||
IChunk chunk = getWorld().getChunk(position.getBlockX() >> 4, position.getBlockZ() >> 4);
|
||||
BiomeContainer biomes = checkNotNull(chunk.getBiomes());
|
||||
return ForgeAdapter.adapt(biomes.getNoiseBiome(position.getX() >> 2, 0, position.getZ() >> 2));
|
||||
return ForgeAdapter.adapt(biomes.getNoiseBiome(position.getX() >> 2, position.getY() >> 2, position.getZ() >> 2));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setBiome(BlockVector2 position, BiomeType biome) {
|
||||
public boolean setBiome(BlockVector3 position, BiomeType biome) {
|
||||
checkNotNull(position);
|
||||
checkNotNull(biome);
|
||||
|
||||
@ -219,11 +219,8 @@ public class ForgeWorld extends AbstractWorld {
|
||||
if (chunk == null || container == null) {
|
||||
return false;
|
||||
}
|
||||
// Temporary, while biome setting is 2D only
|
||||
for (int i = 0; i <= getMaxY(); i++) {
|
||||
int idx = BiomeMath.computeBiomeIndex(position.getX(), i, position.getZ());
|
||||
container.biomes[idx] = ForgeAdapter.adapt(biome);
|
||||
}
|
||||
int idx = BiomeMath.computeBiomeIndex(position.getX(), position.getY(), position.getZ());
|
||||
container.biomes[idx] = ForgeAdapter.adapt(biome);
|
||||
chunk.setModified(true);
|
||||
return true;
|
||||
}
|
||||
|
@ -205,17 +205,17 @@ public abstract class SpongeWorld extends AbstractWorld {
|
||||
}
|
||||
|
||||
@Override
|
||||
public BiomeType getBiome(BlockVector2 position) {
|
||||
public BiomeType getBiome(BlockVector3 position) {
|
||||
checkNotNull(position);
|
||||
return SpongeAdapter.adapt(getWorld().getBiome(position.getBlockX(), 0, position.getBlockZ()));
|
||||
return SpongeAdapter.adapt(getWorld().getBiome(position.getBlockX(), position.getBlockY(), position.getBlockZ()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setBiome(BlockVector2 position, BiomeType biome) {
|
||||
public boolean setBiome(BlockVector3 position, BiomeType biome) {
|
||||
checkNotNull(position);
|
||||
checkNotNull(biome);
|
||||
|
||||
getWorld().setBiome(position.getBlockX(), 0, position.getBlockZ(), SpongeAdapter.adapt(biome));
|
||||
getWorld().setBiome(position.getBlockX(), position.getY(), position.getBlockZ(), SpongeAdapter.adapt(biome));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren