Remove hardcoding of world limits (#1199)

* Remove hardcoding of world limits
 - seems to be working fine without the datapack for world height changing
 - particular attention should be given to LocalBlockVectorSet and MathMan changes

* update adapters

* Override getMinY in various classes and ensure selections have a world attached to them

* no message

* Address comments
 - Fix for lighting mode 1

* A few more changes

* Fix LocalBlockVectorSet

* Fix range statement

* Various fixes/comment-addressing
- There's not much point in having a different file name now for history. We've broken it before...
- Fix history read/write
- Fix range on for loops in CharBlocks

* undo bad CharBlocks change

* Fix history y level

* Fix biome history

* Fix lighting

* Fix /up

* Make regen fail not because of these changes

* Fixes for y < 0

* Fix isEmpty where only the uppermost chunksection is edited

* Fix javadocs/FAWE annotations

* Better explain why BiomeMath is removed

* If history task throws an error, it should only be caught and printed if not completing now.

* Min|max world heights for new patterns

* Load biomes from NMS instead of bukkit (#1200)

* Update adapters

* Update adapters

* Don't initialise BlockTypes when biomes aren't set up yet so all BiomeTypes.BIOME are no longer null thanks.

* Address some comments.

* rename layer -> sectionIndex to imply inclusivity

* Javadoctored.

Co-authored-by: NotMyFault <mc.cache@web.de>
Co-authored-by: Hannes Greule <SirYwell@users.noreply.github.com>
This commit is contained in:
dordsor21
2021-08-17 22:13:51 +01:00
committed by GitHub
parent 5b2bd45d86
commit 1d9b1a3d5e
110 changed files with 1489 additions and 677 deletions

View File

@ -1184,6 +1184,16 @@ public class EditSession extends PassthroughExtent implements AutoCloseable {
return getBlockChangeCount();
}
@Override
public BlockVector3 getMinimumPoint() {
return getWorld().getMinimumPoint();
}
@Override
public BlockVector3 getMaximumPoint() {
return getWorld().getMaximumPoint();
}
//FAWE start
public void setSize(int size) {
this.changes = size;
@ -1276,7 +1286,7 @@ public class EditSession extends PassthroughExtent implements AutoCloseable {
public <B extends BlockStateHolder<B>> int fall(final Region region, boolean fullHeight, final B replace) {
FlatRegion flat = asFlatRegion(region);
final int startPerformY = region.getMinimumPoint().getBlockY();
final int startCheckY = fullHeight ? 0 : startPerformY;
final int startCheckY = fullHeight ? getMinY() : startPerformY;
final int endY = region.getMaximumPoint().getBlockY();
RegionVisitor visitor = new RegionVisitor(flat, pos -> {
int x = pos.getX();
@ -1353,7 +1363,7 @@ public class EditSession extends PassthroughExtent implements AutoCloseable {
final BlockReplace replace = new BlockReplace(EditSession.this, pattern);
// Pick how we're going to visit blocks
RecursiveVisitor visitor = new DirectionalVisitor(mask, replace, origin, direction, (int) (radius * 2 + 1));
RecursiveVisitor visitor = new DirectionalVisitor(mask, replace, origin, direction, (int) (radius * 2 + 1), minY, maxY);
// Start at the origin
visitor.visit(origin);
@ -1406,8 +1416,8 @@ public class EditSession extends PassthroughExtent implements AutoCloseable {
Mask mask = new MaskIntersection(
new RegionMask(new EllipsoidRegion(null, origin, Vector3.at(radius, radius, radius))),
new BoundedHeightMask(
Math.max(origin.getBlockY() - depth + 1, getMinimumPoint().getBlockY()),
Math.min(getMaxY(), origin.getBlockY())
Math.max(origin.getBlockY() - depth + 1, minY),
Math.min(maxY, origin.getBlockY())
),
Masks.negate(new ExistingBlockMask(this))
);
@ -1417,11 +1427,11 @@ public class EditSession extends PassthroughExtent implements AutoCloseable {
// Pick how we're going to visit blocks
RecursiveVisitor visitor;
//FAWE start - provide extent for preloading
//FAWE start - provide extent for preloading, min/max y
if (recursive) {
visitor = new RecursiveVisitor(mask, replace, (int) (radius * 2 + 1), this);
visitor = new RecursiveVisitor(mask, replace, (int) (radius * 2 + 1), minY, maxY, this);
} else {
visitor = new DownwardVisitor(mask, replace, origin.getBlockY(), (int) (radius * 2 + 1), this);
visitor = new DownwardVisitor(mask, replace, origin.getBlockY(), (int) (radius * 2 + 1), minY, maxY, this);
}
//FAWE end
@ -1938,7 +1948,7 @@ public class EditSession extends PassthroughExtent implements AutoCloseable {
//FAWE end
}
Mask mask = new MaskIntersection(
new BoundedHeightMask(getWorld().getMinY(), getWorld().getMaxY()),
new BoundedHeightMask(minY, maxY),
new RegionMask(new EllipsoidRegion(null, origin, Vector3.at(radius, radius, radius))),
//FAWE start
liquidMask
@ -1950,8 +1960,8 @@ public class EditSession extends PassthroughExtent implements AutoCloseable {
} else {
replace = new BlockReplace(this, BlockTypes.AIR.getDefaultState());
}
//FAWE start - provide extent for preloading
RecursiveVisitor visitor = new RecursiveVisitor(mask, replace, (int) (radius * 2 + 1), this);
//FAWE start - provide extent for preloading, min/max y
RecursiveVisitor visitor = new RecursiveVisitor(mask, replace, (int) (radius * 2 + 1), minY, maxY, this);
//FAWE end
// Around the origin in a 3x3 block
@ -1989,14 +1999,14 @@ public class EditSession extends PassthroughExtent implements AutoCloseable {
// There are boundaries that the routine needs to stay in
Mask mask = new MaskIntersection(
new BoundedHeightMask(getWorld().getMinY(), Math.min(origin.getBlockY(), getWorld().getMaxY())),
new BoundedHeightMask(minY, Math.min(origin.getBlockY(), maxY)),
new RegionMask(new EllipsoidRegion(null, origin, Vector3.at(radius, radius, radius))),
blockMask
);
BlockReplace replace = new BlockReplace(this, fluid.getDefaultState());
//FAWE start - provide extent for preloading
NonRisingVisitor visitor = new NonRisingVisitor(mask, replace, Integer.MAX_VALUE, this);
//FAWE start - provide extent for preloading, world min/maxY
NonRisingVisitor visitor = new NonRisingVisitor(mask, replace, Integer.MAX_VALUE, minY, maxY, this);
//FAWE end
// Around the origin in a 3x3 block
@ -2411,7 +2421,7 @@ public class EditSession extends PassthroughExtent implements AutoCloseable {
}
}
}
if (y != 0 && (yy = py - y) >= 0) {
if (y != 0 && (yy = py - y) >= minY) {
this.setBlock(px + x, yy, pz + z, block);
if (x != 0) {
this.setBlock(px - x, yy, pz + z, block);
@ -2506,9 +2516,9 @@ public class EditSession extends PassthroughExtent implements AutoCloseable {
BlockState air = BlockTypes.AIR.getDefaultState();
BlockState water = BlockTypes.WATER.getDefaultState();
int centerY = Math.max(getWorld().getMinY(), Math.min(getWorld().getMaxY(), oy));
int minY = Math.max(getWorld().getMinY(), centerY - height);
int maxY = Math.min(getWorld().getMaxY(), centerY + height);
int centerY = Math.max(minY, Math.min(maxY, oy));
int minY = Math.max(this.minY, centerY - height);
int maxY = Math.min(this.maxY, centerY + height);
//FAWE start - mutable
MutableBlockVector3 mutable = new MutableBlockVector3();
@ -2535,8 +2545,9 @@ public class EditSession extends PassthroughExtent implements AutoCloseable {
++affected;
}
} else if (id == BlockTypes.SNOW) {
//FAWE start
if (setBlock(mutable, air)) {
if (y > 0) {
if (y > getMinY()) {
BlockState block = getBlock(mutable2);
if (block.getStates().containsKey(snowy)) {
if (setBlock(mutable2, block.with(snowy, false))) {
@ -2649,9 +2660,9 @@ public class EditSession extends PassthroughExtent implements AutoCloseable {
final BlockState grass = BlockTypes.GRASS_BLOCK.getDefaultState();
final int centerY = Math.max(getWorld().getMinY(), Math.min(getWorld().getMaxY(), oy));
final int minY = Math.max(getWorld().getMinY(), centerY - height);
final int maxY = Math.min(getWorld().getMaxY(), centerY + height);
final int centerY = Math.max(minY, Math.min(maxY, oy));
final int minY = Math.max(this.minY, centerY - height);
final int maxY = Math.min(this.maxY, centerY + height);
//FAWE start - mutable
MutableBlockVector3 mutable = new MutableBlockVector3();
@ -2952,7 +2963,7 @@ public class EditSession extends PassthroughExtent implements AutoCloseable {
int zv = (int) (z.getValue() * unit.getZ() + zero2.getZ());
BlockState get;
if (yv >= 0 && yv < 256) {
if (yv >= minY && yv <= maxY) {
get = getBlock(xv, yv, zv);
} else {
get = BlockTypes.AIR.getDefaultState();
@ -3538,7 +3549,7 @@ public class EditSession extends PassthroughExtent implements AutoCloseable {
int xx = x + bx;
for (int z = 0; z < 16; z++) {
int zz = z + bz;
for (int y = 0; y < maxY + 1; y++) {
for (int y = minY; y < maxY + 1; y++) {
BaseBlock block = getFullBlock(mutable.setComponents(xx, y, zz));
fcs.add(mutable, block, BlockTypes.AIR.getDefaultState().toBaseBlock());
}
@ -3561,7 +3572,7 @@ public class EditSession extends PassthroughExtent implements AutoCloseable {
for (int z = 0; z < 16; z++) {
int zz = z + bz;
mutable.mutZ(zz);
for (int y = 0; y < maxY + 1; y++) {
for (int y = minY; y < maxY + 1; y++) {
mutable.mutY(y);
boolean contains = (fe == null || fe.contains(xx, y, zz)) && region.contains(mutable);
if (contains) {

View File

@ -211,6 +211,13 @@ public class LocalSession implements TextureHolder {
if (defaultSelector != null) {
this.selector = defaultSelector.createSelector();
}
//FAWE start
if (worldOverride != null) {
this.selector.setWorld(worldOverride);
} else {
this.selector.setWorld(currentWorld);
}
//FAWE end
}
//FAWE start

View File

@ -457,6 +457,7 @@ public class BrushCommands {
)
@CommandPermissions("worldedit.brush.stencil")
public void stencilBrush(
Player player,
LocalSession session, InjectedValueAccess context,
@Arg(desc = "Pattern")
Pattern fill,
@ -478,13 +479,15 @@ public class BrushCommands {
worldEdit.checkMaxBrushRadius(radius);
InputStream stream = getHeightmapStream(image);
HeightBrush brush;
int minY = player.getWorld().getMinY();
int maxY = player.getWorld().getMaxY();
try {
brush = new StencilBrush(stream, rotation, yscale, onlyWhite,
"#clipboard".equalsIgnoreCase(image)
? session.getClipboard().getClipboard() : null
? session.getClipboard().getClipboard() : null, minY, maxY
);
} catch (EmptyClipboardException ignored) {
brush = new StencilBrush(stream, rotation, yscale, onlyWhite, null);
brush = new StencilBrush(stream, rotation, yscale, onlyWhite, null, minY, maxY);
}
if (randomRotate) {
brush.setRandomRotate(true);
@ -710,6 +713,7 @@ public class BrushCommands {
)
@CommandPermissions("worldedit.brush.height")
public void heightBrush(
Player player,
LocalSession session,
@Arg(desc = "Expression", def = "5")
Expression radius,
@ -728,7 +732,7 @@ public class BrushCommands {
boolean dontSmooth, InjectedValueAccess context
)
throws WorldEditException, FileNotFoundException {
terrainBrush(session, radius, image, rotation, yscale, false, randomRotate, layers,
terrainBrush(player, session, radius, image, rotation, yscale, false, randomRotate, layers,
!dontSmooth, ScalableHeightMap.Shape.CONE, context
);
}
@ -741,6 +745,7 @@ public class BrushCommands {
)
@CommandPermissions("worldedit.brush.height")
public void cliffBrush(
Player player,
LocalSession session,
@Arg(desc = "Expression", def = "5")
Expression radius,
@ -760,7 +765,7 @@ public class BrushCommands {
boolean dontSmooth, InjectedValueAccess context
)
throws WorldEditException, FileNotFoundException {
terrainBrush(session, radius, image, rotation, yscale, true, randomRotate, layers,
terrainBrush(player, session, radius, image, rotation, yscale, true, randomRotate, layers,
!dontSmooth, ScalableHeightMap.Shape.CYLINDER, context
);
}
@ -775,6 +780,7 @@ public class BrushCommands {
)
@CommandPermissions("worldedit.brush.height")
public void flattenBrush(
Player player,
LocalSession session,
@Arg(desc = "Expression", def = "5")
Expression radius,
@ -794,12 +800,13 @@ public class BrushCommands {
boolean dontSmooth, InjectedValueAccess context
)
throws WorldEditException, FileNotFoundException {
terrainBrush(session, radius, image, rotation, yscale, true, randomRotate, layers,
terrainBrush(player, session, radius, image, rotation, yscale, true, randomRotate, layers,
!dontSmooth, ScalableHeightMap.Shape.CONE, context
);
}
private void terrainBrush(
Player player,
LocalSession session,
Expression radius,
String image,
@ -816,23 +823,25 @@ public class BrushCommands {
worldEdit.checkMaxBrushRadius(radius);
InputStream stream = getHeightmapStream(image);
HeightBrush brush;
int minY = player.getWorld().getMinY();
int maxY = player.getWorld().getMaxY();
if (flat) {
try {
brush = new FlattenBrush(stream, rotation, yscale, layers, smooth,
"#clipboard".equalsIgnoreCase(image)
? session.getClipboard().getClipboard() : null, shape
? session.getClipboard().getClipboard() : null, shape, minY, maxY
);
} catch (EmptyClipboardException ignored) {
brush = new FlattenBrush(stream, rotation, yscale, layers, smooth, null, shape);
brush = new FlattenBrush(stream, rotation, yscale, layers, smooth, null, shape, minY, maxY);
}
} else {
try {
brush = new HeightBrush(stream, rotation, yscale, layers, smooth,
"#clipboard".equalsIgnoreCase(image)
? session.getClipboard().getClipboard() : null
? session.getClipboard().getClipboard() : null, minY, maxY
);
} catch (EmptyClipboardException ignored) {
brush = new HeightBrush(stream, rotation, yscale, layers, smooth, null);
brush = new HeightBrush(stream, rotation, yscale, layers, smooth, null, minY, maxY);
}
}
if (randomRotate) {

View File

@ -635,12 +635,18 @@ public class GenerationCommands {
@Arg(desc = "Ore vein size") @Range(from = 0, to = Integer.MAX_VALUE) int size,
@Arg(desc = "Ore vein frequency (number of times to attempt to place ore)", def = "10") @Range(from = 0, to = Integer.MAX_VALUE) int freq,
@Arg(desc = "Ore vein rarity (% chance each attempt is placed)", def = "100") @Range(from = 0, to = 100) int rarity,
@Arg(desc = "Ore vein min y", def = "0") @Range(from = 0, to = 255) int minY,
@Arg(desc = "Ore vein max y", def = "63") @Range(from = 0, to = 255) int maxY
@Arg(desc = "Ore vein min y", def = "0") int minY,
@Arg(desc = "Ore vein max y", def = "63") int maxY
) throws WorldEditException {
if (mask instanceof AbstractExtentMask) {
((AbstractExtentMask) mask).setExtent(editSession);
}
checkCommandArgument(minY >= editSession.getMinY(), Caption.of("fawe.error.outside-range-lower", "miny",
editSession.getMinY()));
checkCommandArgument(maxY <= editSession.getMaxY(), Caption.of("fawe.error.outside-range-upper", "maxy",
editSession.getMaxY()));
checkCommandArgument(minY < maxY, Caption.of("fawe.error.argument-size-mismatch", "miny",
"maxy"));
editSession.addOre(region, mask, material, size, freq, rarity, minY, maxY);
actor.print(Caption.of("fawe.worldedit.visitor.visitor.block", editSession.getBlockChangeCount()));
}

View File

@ -133,8 +133,8 @@ public class HistorySubCommands {
Location origin = player.getLocation();
BlockVector3 bot = origin.toBlockPoint().subtract(radius, radius, radius);
BlockVector3 top = origin.toBlockPoint().add(radius, radius, radius);
bot = bot.clampY(0, world.getMaxY());
top = top.clampY(0, world.getMaxY());
bot = bot.clampY(world.getMinY(), world.getMaxY());
top = top.clampY(world.getMinY(), world.getMaxY());
// TODO mask the regions bot / top to the bottom and top coord in the allowedRegions
// TODO: then mask the edit to the bot / top
// if (allowedRegions.length != 1 || !allowedRegions[0].isGlobal()) {
@ -196,9 +196,9 @@ public class HistorySubCommands {
.summarize(RegionWrapper.GLOBAL(), false);
if (summary != null) {
rollback.setDimensions(
BlockVector3.at(summary.minX, 0, summary.minZ),
BlockVector3.at(summary.minX, world.getMinY(), summary.minZ),
BlockVector3
.at(summary.maxX, 255, summary.maxZ)
.at(summary.maxX, world.getMaxY(), summary.maxZ)
);
rollback.setTime(historyFile.lastModified());
RollbackDatabase db = DBHandler.IMP
@ -410,8 +410,8 @@ public class HistorySubCommands {
BlockVector3 bot = origin.toBlockPoint().subtract(radius, radius, radius);
BlockVector3 top = origin.toBlockPoint().add(radius, radius, radius);
bot = bot.clampY(0, world.getMaxY());
top = top.clampY(0, world.getMaxY());
bot = bot.clampY(world.getMinY(), world.getMaxY());
top = top.clampY(world.getMinY(), world.getMaxY());
long minTime = System.currentTimeMillis() - timeDiff;
Iterable<Supplier<RollbackOptimizedHistory>> edits = database.getEdits(other, minTime, bot, top, false, false);

View File

@ -363,17 +363,23 @@ public class RegionCommands {
@Selection Region region,
@Arg(name = "pattern", desc = "The pattern of blocks to lay") Pattern patternArg
) throws WorldEditException {
BlockVector3 max = region.getMaximumPoint();
int maxY = max.getBlockY();
//FAWE start - world min/maxY
int maxY = region.getMaximumY();
int minY = region.getMinimumY();
//FAWE end
Iterable<BlockVector2> flat = Regions.asFlatRegion(region).asFlatRegion();
Iterator<BlockVector2> iter = flat.iterator();
int y = 0;
//FAWE start - world min/maxY
int y = minY;
//FAWE end
int affected = 0;
while (iter.hasNext()) {
BlockVector2 pos = iter.next();
int x = pos.getBlockX();
int z = pos.getBlockZ();
y = editSession.getNearestSurfaceTerrainBlock(x, z, y, 0, maxY);
//FAWE start - world min/maxY
y = editSession.getNearestSurfaceTerrainBlock(x, z, y, minY, maxY);
//FAWE end
editSession.setBlock(x, y, z, patternArg);
affected++;
}
@ -856,6 +862,7 @@ public class RegionCommands {
)
@CommandPermissions("worldedit.region.flora")
@Logging(REGION)
@Preload(Preload.PreloadCheck.PRELOAD)
@Confirm(Confirm.Processor.REGION)
public int flora(
Actor actor, EditSession editSession, @Selection Region region,
@ -867,7 +874,7 @@ public class RegionCommands {
FloraGenerator generator = new FloraGenerator(editSession);
GroundFunction ground = new GroundFunction(new ExistingBlockMask(editSession), generator);
//FAWE start - provide extent for preloading
LayerVisitor visitor = new LayerVisitor(asFlatRegion(region), minimumBlockY(region), maximumBlockY(region), ground, editSession);
LayerVisitor visitor = new LayerVisitor(asFlatRegion(region), minimumBlockY(region), maximumBlockY(region), ground);
//FAWE end
visitor.setMask(new NoiseFilter2D(new RandomNoise(), density));
Operations.completeLegacy(visitor);

View File

@ -124,9 +124,9 @@ public class SelectionCommands {
Location pos;
//FAWE start - clamp
if (coordinates != null) {
pos = new Location(world, coordinates.toVector3().clampY(0, world.getMaxY()));
pos = new Location(world, coordinates.toVector3().clampY(world.getMinY(), world.getMaxY()));
} else if (actor instanceof Locatable) {
pos = ((Locatable) actor).getBlockLocation().clampY(0, world.getMaxY());
pos = ((Locatable) actor).getBlockLocation().clampY(world.getMinY(), world.getMaxY());
//FAWE end
} else {
actor.print(Caption.of("worldedit.pos.console-require-coords"));
@ -157,9 +157,9 @@ public class SelectionCommands {
Location pos;
if (coordinates != null) {
//FAWE start - clamp
pos = new Location(world, coordinates.toVector3().clampY(0, world.getMaxY()));
pos = new Location(world, coordinates.toVector3().clampY(world.getMinY(), world.getMaxY()));
} else if (actor instanceof Locatable) {
pos = ((Locatable) actor).getBlockLocation().clampY(0, world.getMaxY());
pos = ((Locatable) actor).getBlockLocation().clampY(world.getMinY(), world.getMaxY());
//Fawe end
} else {
actor.print(Caption.of("worldedit.pos.console-require-coords"));
@ -258,7 +258,7 @@ public class SelectionCommands {
.clampY(minChunkY, maxChunkY);
min = minChunk.shl(CHUNK_SHIFTS, CHUNK_SHIFTS_Y, CHUNK_SHIFTS);
max = maxChunk.shl(CHUNK_SHIFTS, CHUNK_SHIFTS_Y, CHUNK_SHIFTS).add(15, world.getMaxY(), 15);
max = maxChunk.shl(CHUNK_SHIFTS, CHUNK_SHIFTS_Y, CHUNK_SHIFTS).add(15, 255, 15);
actor.print(Caption.of(
"worldedit.chunk.selected-multiple",
@ -286,7 +286,7 @@ public class SelectionCommands {
}
min = minChunk.shl(CHUNK_SHIFTS, CHUNK_SHIFTS_Y, CHUNK_SHIFTS);
max = min.add(15, world.getMaxY(), 15);
max = min.add(15, 255, 15);
actor.print(Caption.of(
"worldedit.chunk.selected",

View File

@ -413,8 +413,8 @@ public class UtilityCommands {
) throws WorldEditException {
size = Math.max(1, size);
we.checkMaxRadius(size);
height = height != null ? Math.min((world.getMaxY() + 1), height + 1) : (world.getMaxY() + 1);
height = height != null ? Math.min((world.getMaxY() - world.getMinY() + 1), height + 1) : (world.getMaxY() - world.getMinY() + 1);
int affected = editSession.removeAbove(session.getPlacementPosition(actor), size, height);
actor.print(Caption.of("worldedit.removeabove.removed", TextComponent.of(affected)));
return affected;
@ -436,8 +436,8 @@ public class UtilityCommands {
) throws WorldEditException {
size = Math.max(1, size);
we.checkMaxRadius(size);
height = height != null ? Math.min((world.getMaxY() + 1), height + 1) : (world.getMaxY() + 1);
height = height != null ? Math.min((world.getMaxY() - world.getMinY() + 1), height + 1) : (world.getMaxY() - world.getMinY() + 1);
int affected = editSession.removeBelow(session.getPlacementPosition(actor), size, height);
actor.print(Caption.of("worldedit.removebelow.removed", TextComponent.of(affected)));
return affected;

View File

@ -388,7 +388,7 @@ public class BrushTool
final int x = loc.getBlockX();
final int z = loc.getBlockZ();
int y;
for (y = height; y > 0; y--) {
for (y = height; y > editSession.getMinY(); y--) {
BlockType block = editSession.getBlockType(x, y, z);
if (block.getMaterial().isMovementBlocker()) {
break;

View File

@ -87,7 +87,8 @@ public class FloodFillTool implements BlockTool {
//FAWE start - Respect masks
Mask mask = initialType.toMask(editSession);
BlockReplace function = new BlockReplace(editSession, pattern);
RecursiveVisitor visitor = new RecursiveVisitor(mask, function, range, editSession);
RecursiveVisitor visitor = new RecursiveVisitor(mask, function, range, editSession.getMinY(),
editSession.getMaxY(), editSession);
visitor.visit(origin);
Operations.completeLegacy(visitor);
//FAWE end

View File

@ -86,7 +86,14 @@ public class RecursivePickaxe implements BlockTool {
final int radius = (int) range;
final BlockReplace replace = new BlockReplace(editSession, (BlockTypes.AIR.getDefaultState()));
editSession.setMask(null);
RecursiveVisitor visitor = new RecursiveVisitor(new IdMask(editSession), replace, radius, editSession);
RecursiveVisitor visitor = new RecursiveVisitor(
new IdMask(editSession),
replace,
radius,
editSession.getMinY(),
editSession.getMaxY(),
editSession
);
//TODO: Fix below
//visitor.visit(pos);
//Operations.completeBlindly(visitor);

View File

@ -39,8 +39,8 @@ public class GravityBrush implements Brush {
MaxChangedBlocksException {
//FAWE start - Ours operates differently to upstream, but does the same
double endY = position.getY() + size;
double startPerformY = Math.max(0, position.getY() - size);
double startCheckY = fullHeight ? 0 : startPerformY;
double startPerformY = Math.max(editSession.getMinY(), position.getY() - size);
double startCheckY = fullHeight ? editSession.getMinY() : startPerformY;
for (double x = position.getX() + size; x > position.getX() - size; --x) {
for (double z = position.getZ() + size; z > position.getZ() - size; --z) {
double freeSpot = startCheckY;

View File

@ -69,7 +69,7 @@ public class OffsetMaskParser extends InputParser<Mask> implements AliasedParser
submask = new ExistingBlockMask(context.requireExtent());
}
//FAWE start - OffsetMask > OffsetsMask
return new OffsetMask(submask, BlockVector3.at(0, firstChar == '>' ? -1 : 1, 0));
return new OffsetMask(submask, BlockVector3.at(0, firstChar == '>' ? -1 : 1, 0), context.getMinY(), context.getMaxY());
//FAWE end
}

View File

@ -23,6 +23,7 @@ import com.fastasyncworldedit.core.configuration.Caption;
import com.sk89q.worldedit.LocalSession;
import com.sk89q.worldedit.extension.factory.MaskFactory;
import com.sk89q.worldedit.extension.platform.Actor;
import com.sk89q.worldedit.extension.platform.Locatable;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.world.World;
import org.enginehub.piston.inject.InjectedValueAccess;
@ -50,6 +51,8 @@ public class ParserContext {
private boolean preferringWildcard;
//Fawe start
private InjectedValueAccess injected;
private int minY = Integer.MIN_VALUE;
private int maxY = Integer.MAX_VALUE;
//FAWE end
/**
@ -270,5 +273,69 @@ public class ParserContext {
public InjectedValueAccess getInjected() {
return injected;
}
/**
* Attempts to resolve the minimum Y value associated with this context or returns 0.
* Caches both min and max y values.
*
* @return Minimum y value (inclusive) or 0
*/
public int getMinY() {
if (minY != Integer.MIN_VALUE) {
return minY;
}
Extent extent = null;
if (actor instanceof Locatable) {
extent = ((Locatable) actor).getExtent();
} else if (world != null) {
extent = world;
} else if (this.extent != null) {
extent = this.extent;
}
if (extent != null) {
minY = extent.getMinY();
maxY = extent.getMaxY();
} else {
minY = 0;
maxY = 255;
}
return minY;
}
/**
* Attempts to resolve the maximum Y value associated with this context or returns 255.
* Caches both min and max y values.
*
* @return Maximum y value (inclusive) or 255
*/
public int getMaxY() {
if (maxY != Integer.MAX_VALUE) {
return maxY;
}
Extent extent = null;
if (actor instanceof Locatable) {
extent = ((Locatable) actor).getExtent();
} else if (world != null) {
extent = world;
} else if (this.extent != null) {
extent = this.extent;
}
if (extent != null) {
minY = extent.getMinY();
maxY = extent.getMaxY();
} else {
minY = 0;
maxY = 255;
}
return maxY;
}
//FAWE end
}

View File

@ -202,6 +202,11 @@ public class AbstractDelegateExtent implements Extent {
return extent.getMaxY();
}
@Override
public int getMinY() {
return extent.getMinY();
}
@Override
public boolean relight(int x, int y, int z) {
return extent.relight(x, y, z);
@ -317,7 +322,7 @@ public class AbstractDelegateExtent implements Extent {
@Override
public <T extends BlockStateHolder<T>> boolean setBlock(
int x, @Range(from = 0, to = 255) int y,
int x, int y,
int z, T block
) throws WorldEditException {
return extent.setBlock(x, y, z, block);

View File

@ -200,9 +200,16 @@ public interface Extent extends InputExtent, OutputExtent {
- TODO: actually optimize these
*/
/**
* Returns the highest solid 'terrain' block.
*
* @param x the X coordinate
* @param z the Z coordinate
* @param minY minimal height
* @param maxY maximal height
* @return height of highest block found or 'minY'
*/
default int getHighestTerrainBlock(final int x, final int z, int minY, int maxY) {
maxY = Math.min(maxY, Math.max(0, maxY));
minY = Math.max(0, minY);
for (int y = maxY; y >= minY; --y) {
BlockState block = getBlock(x, y, z);
if (block.getBlockType().getMaterial().isMovementBlocker()) {
@ -212,9 +219,19 @@ public interface Extent extends InputExtent, OutputExtent {
return minY;
}
/**
* Returns the highest solid 'terrain' block.
*
* @param x the X coordinate
* @param z the Z coordinate
* @param minY minimal height
* @param maxY maximal height
* @param filter a mask of blocks to consider, or null to consider any solid (movement-blocking) block
* @return height of highest block found or 'minY'
*/
default int getHighestTerrainBlock(final int x, final int z, int minY, int maxY, Mask filter) {
maxY = Math.min(maxY, Math.max(0, maxY));
minY = Math.max(0, minY);
maxY = Math.min(maxY, getMaxY());
minY = Math.max(getMinY(), minY);
MutableBlockVector3 mutable = new MutableBlockVector3();
@ -226,6 +243,18 @@ public interface Extent extends InputExtent, OutputExtent {
return minY;
}
/**
* Returns the nearest surface layer (up/down from start)
* <p>
* TODO: Someone understand this..?
*
* @param x x to search from
* @param z y to search from
* @param y z to search from
* @param minY min y to search (inclusive)
* @param maxY max y to search (inclusive)
* @return nearest surface layer
*/
default int getNearestSurfaceLayer(int x, int z, int y, int minY, int maxY) {
int clearanceAbove = maxY - y;
int clearanceBelow = y - minY;
@ -255,7 +284,7 @@ public interface Extent extends InputExtent, OutputExtent {
for (int layer = y - clearance - 1; layer >= minY; layer--) {
block = getBlock(x, layer, z);
if (block.getBlockType().getMaterial().isMovementBlocker() == state) {
return ((layer + offset) << 4) + 0;
return (layer + offset) << 4;
}
data1 = PropertyGroup.LEVEL.get(block);
}
@ -272,18 +301,20 @@ public interface Extent extends InputExtent, OutputExtent {
return (state ? minY : maxY) << 4;
}
default int getNearestSurfaceTerrainBlock(int x, int z, int y, int minY, int maxY, boolean ignoreAir) {
return getNearestSurfaceTerrainBlock(x, z, y, minY, maxY, minY, maxY, ignoreAir);
}
default int getNearestSurfaceTerrainBlock(int x, int z, int y, int minY, int maxY) {
return getNearestSurfaceTerrainBlock(x, z, y, minY, maxY, minY, maxY);
}
default int getNearestSurfaceTerrainBlock(int x, int z, int y, int minY, int maxY, int failedMin, int failedMax) {
return getNearestSurfaceTerrainBlock(x, z, y, minY, maxY, failedMin, failedMax, true);
}
/**
* Gets y value for the nearest block that is considered the surface of the terrain (cave roof/floor, mountain surface,
* etc) where the block conforms to a given mask. Searches in the x,z column given.
*
* @param x column x
* @param z column z
* @param y start y
* @param minY minimum y height to consider. Inclusive.
* @param maxY maximum y height to consider. Inclusive.
* @param failedMin if nothing found, the minimum y value to return if returning min
* @param failedMax if nothing found, the maximum y value to return if returning max
* @param mask mask to test blocks against
* @return The y value of the nearest terrain block
*/
default int getNearestSurfaceTerrainBlock(int x, int z, int y, int minY, int maxY, int failedMin, int failedMax, Mask mask) {
y = Math.max(minY, Math.min(maxY, y));
int clearanceAbove = maxY - y;
@ -320,6 +351,68 @@ public interface Extent extends InputExtent, OutputExtent {
return state ? failedMin : failedMax;
}
/**
* Gets y value for the nearest block that is considered the surface of the terrain (cave roof/floor, mountain surface,
* etc). Searches in the x,z column given.
*
* @param x column x
* @param z column z
* @param y start y
* @param minY minimum y height to consider. Inclusive.
* @param maxY maximum y height to consider. Inclusive.
* @param ignoreAir if air at the final value if no block found should be considered for return, else return -1
* @return The y value of the nearest terrain block
*/
default int getNearestSurfaceTerrainBlock(int x, int z, int y, int minY, int maxY, boolean ignoreAir) {
return getNearestSurfaceTerrainBlock(x, z, y, minY, maxY, minY, maxY, ignoreAir);
}
/**
* Gets y value for the nearest block that is considered the surface of the terrain (cave roof/floor, mountain surface,
* etc). Searches in the x,z column given.
*
* @param x column x
* @param z column z
* @param y start y
* @param minY minimum y height to consider. Inclusive.
* @param maxY maximum y height to consider. Inclusive.
* @return The y value of the nearest terrain block
*/
default int getNearestSurfaceTerrainBlock(int x, int z, int y, int minY, int maxY) {
return getNearestSurfaceTerrainBlock(x, z, y, minY, maxY, minY, maxY);
}
/**
* Gets y value for the nearest block that is considered the surface of the terrain (cave roof/floor, mountain surface,
* etc). Searches in the x,z column given.
*
* @param x column x
* @param z column z
* @param y start y
* @param minY minimum y height to consider. Inclusive.
* @param maxY maximum y height to consider. Inclusive.
* @param failedMin if nothing found, the minimum y value to return if returning min
* @param failedMax if nothing found, the maximum y value to return if returning max
* @return The y value of the nearest terrain block
*/
default int getNearestSurfaceTerrainBlock(int x, int z, int y, int minY, int maxY, int failedMin, int failedMax) {
return getNearestSurfaceTerrainBlock(x, z, y, minY, maxY, failedMin, failedMax, true);
}
/**
* Gets y value for the nearest block that is considered the surface of the terrain (cave roof/floor, mountain surface,
* etc). Searches in the x,z column given.
*
* @param x column x
* @param z column z
* @param y start y
* @param minY minimum y height to consider. Inclusive.
* @param maxY maximum y height to consider. Inclusive.
* @param failedMin if nothing found, the minimum y value to return if returning min
* @param failedMax if nothing found, the maximum y value to return if returning max
* @param ignoreAir if air at the final value if no block found should be considered for return, else return -1
* @return The y value of the nearest terrain block
*/
default int getNearestSurfaceTerrainBlock(
int x,
int z,
@ -367,7 +460,7 @@ public interface Extent extends InputExtent, OutputExtent {
}
}
int result = state ? failedMin : failedMax;
if (result > 0 && !ignoreAir) {
if (result > minY && !ignoreAir) {
block = getBlock(x, result, z);
return block.getBlockType().getMaterial().isAir() ? -1 : result;
}
@ -444,12 +537,13 @@ public interface Extent extends InputExtent, OutputExtent {
spawnResource(region, new OreGen(this, mask, material, size, minY, maxY), rarity, frequency);
}
//TODO: probably update these for 1.18 etc.
default void addOres(Region region, Mask mask) throws WorldEditException {
addOre(region, mask, BlockTypes.DIRT.getDefaultState(), 33, 10, 100, 0, 255);
addOre(region, mask, BlockTypes.GRAVEL.getDefaultState(), 33, 8, 100, 0, 255);
addOre(region, mask, BlockTypes.ANDESITE.getDefaultState(), 33, 10, 100, 0, 79);
addOre(region, mask, BlockTypes.DIORITE.getDefaultState(), 33, 10, 100, 0, 79);
addOre(region, mask, BlockTypes.GRANITE.getDefaultState(), 33, 10, 100, 0, 79);
addOre(region, mask, BlockTypes.DIRT.getDefaultState(), 33, 10, 100, getMinY(), getMaxY());
addOre(region, mask, BlockTypes.GRAVEL.getDefaultState(), 33, 8, 100, getMinY(), getMaxY());
addOre(region, mask, BlockTypes.ANDESITE.getDefaultState(), 33, 10, 100, getMinY(), 79);
addOre(region, mask, BlockTypes.DIORITE.getDefaultState(), 33, 10, 100, getMinY(), 79);
addOre(region, mask, BlockTypes.GRANITE.getDefaultState(), 33, 10, 100, getMinY(), 79);
addOre(region, mask, BlockTypes.COAL_ORE.getDefaultState(), 17, 20, 100, 0, 127);
addOre(region, mask, BlockTypes.IRON_ORE.getDefaultState(), 9, 20, 100, 0, 63);
addOre(region, mask, BlockTypes.GOLD_ORE.getDefaultState(), 9, 2, 100, 0, 31);
@ -556,11 +650,11 @@ public interface Extent extends InputExtent, OutputExtent {
}
default int getMinY() {
return 0;
return getMinimumPoint().getY();
}
default int getMaxY() {
return 255;
return getMaximumPoint().getY();
}
/**

View File

@ -347,7 +347,7 @@ public interface Clipboard extends Extent, Iterable<BlockVector3>, Closeable {
if (!pasteAir && block.getBlockType().getMaterial().isAir()) {
continue;
}
if (pos.getY() < 0) {
if (pos.getY() < extent.getMinY()) {
throw new RuntimeException("Y-Position cannot be less than 0!");
}
extent.setBlock(xx, yy, zz, block);

View File

@ -31,6 +31,10 @@ import static com.google.common.base.Preconditions.checkNotNull;
*/
public class OffsetMask extends AbstractMask {
//FAWE start - ignore resultant position outside world height range
private final int minY;
private final int maxY;
//FAWE end
private Mask mask;
private BlockVector3 offset;
@ -39,12 +43,30 @@ public class OffsetMask extends AbstractMask {
*
* @param mask the mask
* @param offset the offset
* @deprecated use {@link OffsetMask#OffsetMask(Mask, BlockVector3, int, int)}
*/
@Deprecated
public OffsetMask(Mask mask, BlockVector3 offset) {
this(mask, offset, 0, 255);
}
/**
* Create a new instance.
*
* @param mask the mask
* @param offset the offset
* @param minY minimum allowable y value to be set. Inclusive.
* @param maxY maximum allowable y value to be set. Inclusive.
*/
//FAWE start - ignore resultant position outside world height range
public OffsetMask(Mask mask, BlockVector3 offset, int minY, int maxY) {
checkNotNull(mask);
checkNotNull(offset);
this.mask = mask;
this.offset = offset;
this.minY = minY;
this.maxY = maxY;
//FAWE end
}
/**
@ -87,11 +109,13 @@ public class OffsetMask extends AbstractMask {
@Override
public boolean test(BlockVector3 vector) {
//FAWE start - ignore resultant position outside world height range
BlockVector3 testPos = vector.add(offset);
if (testPos.getBlockY() < 0 || testPos.getBlockY() > 255) {
if (testPos.getBlockY() < minY || testPos.getBlockY() > maxY) {
return false;
}
return getMask().test(vector.add(offset));
return getMask().test(testPos);
//FAWE end
}
@Nullable
@ -108,7 +132,7 @@ public class OffsetMask extends AbstractMask {
//FAWE start
@Override
public Mask copy() {
return new OffsetMask(mask.copy(), offset.toImmutable());
return new OffsetMask(mask.copy(), offset.toImmutable(), minY, maxY);
}
//FAWE end

View File

@ -95,6 +95,8 @@ public abstract class BreadthFirstSearch implements Operation {
private BlockVectorSet visited = new BlockVectorSet();
private BlockVector3[] directions;
//FAWE end
protected final int minY;
protected final int maxY;
private int affected = 0;
//FAWE start
private int currentDepth = 0;
@ -107,21 +109,21 @@ public abstract class BreadthFirstSearch implements Operation {
* @param function the function to apply to visited blocks
*/
public BreadthFirstSearch(RegionFunction function) {
//FAWE start
this(function, Integer.MAX_VALUE);
//FAWE end
checkNotNull(function);
//FAWE start - int depth, min/max y
this(function, Integer.MAX_VALUE, 0, 255, null);
}
//FAWE start
//FAWE start - int depth, min/max y, preloading
/**
* Create a new instance.
*
* @param function the function to apply to visited blocks
* @param maxDepth the maximum number of iterations
* @param depth maximum number of iterations
* @param minY minimum allowable y to visit. Inclusive.
* @param maxY maximum allowable y to visit. Inclusive.
*/
public BreadthFirstSearch(RegionFunction function, int maxDepth) {
this(function, maxDepth, null);
public BreadthFirstSearch(RegionFunction function, int depth, int minY, int maxY) {
this(function, depth, minY, maxY, null);
}
/**
@ -129,13 +131,17 @@ public abstract class BreadthFirstSearch implements Operation {
*
* @param function the function to apply to visited blocks
* @param maxDepth the maximum number of iterations
* @param minY minimum y value to visit. Inclusive.
* @param maxY maximum y value to visit. Inclusive.
* @param extent extent to use for preloading
*/
public BreadthFirstSearch(RegionFunction function, int maxDepth, Extent extent) {
public BreadthFirstSearch(RegionFunction function, int maxDepth, int minY, int maxY, Extent extent) {
checkNotNull(function);
this.function = function;
this.directions = DEFAULT_DIRECTIONS;
this.maxDepth = maxDepth;
this.minY = minY;
this.maxY = maxY;
if (extent != null) {
ExtentTraverser<ParallelQueueExtent> queueTraverser = new ExtentTraverser<>(extent).find(ParallelQueueExtent.class);
this.singleQueue = queueTraverser != null ? (SingleThreadQueueExtent) queueTraverser.get().getExtent() : null;
@ -314,7 +320,7 @@ public abstract class BreadthFirstSearch implements Operation {
for (int i = 0, j = 0; i < dirs.length && j < maxBranch; i++) {
BlockVector3 direction = dirs[i];
int y = from.getBlockY() + direction.getY();
if (y < 0 || y >= 256) {
if (y < minY || y > maxY) {
continue;
}
int x = from.getBlockX() + direction.getX();

View File

@ -37,19 +37,22 @@ public class DownwardVisitor extends RecursiveVisitor {
private final int baseY;
//FAWE start
/**
* Create a new visitor.
*
* @param mask the mask
* @param function the function
* @param baseY the base Y
* @deprecated Use {@link DownwardVisitor#DownwardVisitor(Mask, RegionFunction, int, int, int, int)}
*/
@Deprecated
public DownwardVisitor(Mask mask, RegionFunction function, int baseY) {
this(mask, function, baseY, Integer.MAX_VALUE);
//FAWE start - int depth, min/max y
this(mask, function, baseY, Integer.MAX_VALUE, 0, 255, null);
//FAWE end
}
//FAWE start - int depth, min/max y, preloading
/**
* Create a new visitor.
*
@ -57,9 +60,11 @@ public class DownwardVisitor extends RecursiveVisitor {
* @param function the function
* @param baseY the base Y
* @param depth maximum number of iterations
* @param minY minimum allowable y to visit. Inclusive.
* @param maxY maximum allowable y to visit. Inclusive.
*/
public DownwardVisitor(Mask mask, RegionFunction function, int baseY, int depth) {
this (mask, function, baseY, depth, null);
public DownwardVisitor(Mask mask, RegionFunction function, int baseY, int depth, int minY, int maxY) {
this(mask, function, baseY, depth, minY, maxY, null);
}
/**
@ -69,10 +74,12 @@ public class DownwardVisitor extends RecursiveVisitor {
* @param function the function
* @param baseY the base Y
* @param depth maximum number of iterations
* @param minY minimum allowable y to visit. Inclusive.
* @param maxY maximum allowable y to visit. Inclusive.
* @param extent extent for preloading
*/
public DownwardVisitor(Mask mask, RegionFunction function, int baseY, int depth, Extent extent) {
super(mask, function, depth, extent);
public DownwardVisitor(Mask mask, RegionFunction function, int baseY, int depth, int minY, int maxY, Extent extent) {
super(mask, function, depth, minY, maxY, extent);
checkNotNull(mask);
this.baseY = baseY;

View File

@ -29,29 +29,32 @@ import com.sk89q.worldedit.math.BlockVector3;
*/
public class NonRisingVisitor extends RecursiveVisitor {
//FAWE start - max int
/**
* Create a new recursive visitor.
* Create a new resursive visitor.
*
* @param mask the mask
* @param function the function
* @deprecated Use {@link NonRisingVisitor#NonRisingVisitor(Mask, RegionFunction, int, int, int, Extent)}
*/
@Deprecated
public NonRisingVisitor(Mask mask, RegionFunction function) {
this(mask, function, Integer.MAX_VALUE);
//FAWE start - int depth, y min/max
this(mask, function, Integer.MAX_VALUE, 0, 255, null);
//FAWE end
}
//FAWE end
//FAWE start - int depth, preloading
//FAWE start - int depth, preloading, min/max y
/**
* Create a new recursive visitor.
*
* @param mask the mask
* @param function the function
* @param depth the maximum number of iterations
* @param minY minimum allowable y to visit. Inclusive.
* @param maxY maximum allowable y to visit. Inclusive.
*/
public NonRisingVisitor(Mask mask, RegionFunction function, int depth) {
this(mask, function, depth, null);
public NonRisingVisitor(Mask mask, RegionFunction function, int depth, int minY, int maxY) {
this(mask, function, Integer.MAX_VALUE, minY, maxY, null);
}
/**
@ -60,10 +63,12 @@ public class NonRisingVisitor extends RecursiveVisitor {
* @param mask the mask
* @param function the function
* @param depth the maximum number of iterations
* @param minY minimum allowable y to visit. Inclusive.
* @param maxY maximum allowable y to visit. Inclusive.
* @param extent the extent for preloading
*/
public NonRisingVisitor(Mask mask, RegionFunction function, int depth, Extent extent) {
super(mask, function, depth, extent);
public NonRisingVisitor(Mask mask, RegionFunction function, int depth, int minY, int maxY, Extent extent) {
super(mask, function, depth, minY, maxY, extent);
setDirections(
BlockVector3.UNIT_X,
BlockVector3.UNIT_MINUS_X,

View File

@ -34,7 +34,6 @@ public class RecursiveVisitor extends BreadthFirstSearch {
private final Mask mask;
//FAWE start
/**
* Create a new recursive visitor.
*
@ -42,30 +41,37 @@ public class RecursiveVisitor extends BreadthFirstSearch {
* @param function the function
*/
public RecursiveVisitor(Mask mask, RegionFunction function) {
this(mask, function, Integer.MAX_VALUE);
this(mask, function, Integer.MAX_VALUE, 0, 255, null);
//FAWE end
}
//FAWE start - int depth, min/max y
/**
* Create a new recursive visitor.
*
* @param mask the mask
* @param function the function
* @param maxDepth the maximum number of iterations
* @param minY minimum allowable y to visit. Inclusive.
* @param maxY maximum allowable y to visit. Inclusive.
*/
public RecursiveVisitor(Mask mask, RegionFunction function, int maxDepth) {
this(mask, function, maxDepth, null);
public RecursiveVisitor(Mask mask, RegionFunction function, int maxDepth, int minY, int maxY) {
this(mask, function, maxDepth, minY, maxY, null);
}
//FAWE start - int depth, min/max y
/**
* Create a new recursive visitor.
*
* @param mask the mask
* @param function the function
* @param maxDepth the maximum number of iterations
* @param minY minimum allowable y to visit. Inclusive.
* @param maxY maximum allowable y to visit. Inclusive.
* @param extent the extent for preloading
*/
public RecursiveVisitor(Mask mask, RegionFunction function, int maxDepth, Extent extent) {
super(function, maxDepth, extent);
public RecursiveVisitor(Mask mask, RegionFunction function, int maxDepth, int minY, int maxY, Extent extent) {
super(function, maxDepth, minY, maxY, extent);
checkNotNull(mask);
this.mask = mask;
}

View File

@ -19,53 +19,54 @@
package com.sk89q.worldedit.internal.util;
import net.royawesome.jlibnoise.MathHelper;
public class BiomeMath {
// From BiomeArray / BiomeContainer
public static final int HORIZONTAL_SECTION_COUNT = (int) Math.round(Math.log(16.0D) / Math.log(2.0D)) - 2;
public static final int VERTICAL_SECTION_COUNT = (int) Math.round(Math.log(256.0D) / Math.log(2.0D)) - 2;
public static final int HORIZONTAL_BIT_MASK = (1 << HORIZONTAL_SECTION_COUNT) - 1;
public static final int VERTICAL_BIT_MASK = (1 << VERTICAL_SECTION_COUNT) - 1;
//FAWE - Removed because it's unneeded, and it would require effort to have it work with worlds of differing heights across
// different game versions
private BiomeMath() {
}
/**
* Compute the index into the MC biome array, for non-extended-height worlds.
*
* @param x the block x coordinate
* @param y the block y coordinate
* @param z the block z coordinate
* @return the index into the standard MC biome array
*/
public static int computeBiomeIndex(int x, int y, int z) {
int l = (x >> 2) & HORIZONTAL_BIT_MASK;
int m = MathHelper.clamp(y >> 2, 0, VERTICAL_BIT_MASK);
int n = (z >> 2) & HORIZONTAL_BIT_MASK;
return m << HORIZONTAL_SECTION_COUNT + HORIZONTAL_SECTION_COUNT
| n << HORIZONTAL_SECTION_COUNT
| l;
}
/**
* Compute the index into the MC biome array, for extended-height worlds.
*
* @param x the block x coordinate
* @param y the block y coordinate
* @param z the block z coordinate
* @param minY minimum y of the world
* @param maxY maximum y of the world
* @return the index into the standard MC biome array
*/
public static int computeBiomeIndex(int x, int y, int z, int minY, int maxY) {
int l = (x >> 2) & HORIZONTAL_BIT_MASK;
int m = MathHelper.clamp((y >> 2) - minY, 0, maxY);
int n = (z >> 2) & HORIZONTAL_BIT_MASK;
return m << HORIZONTAL_SECTION_COUNT + HORIZONTAL_SECTION_COUNT
| n << HORIZONTAL_SECTION_COUNT
| l;
}
// // From BiomeArray / BiomeContainer
// public static final int HORIZONTAL_SECTION_COUNT = (int) Math.round(Math.log(16.0D) / Math.log(2.0D)) - 2;
// public static final int VERTICAL_SECTION_COUNT = (int) Math.round(Math.log(256.0D) / Math.log(2.0D)) - 2;
// public static final int HORIZONTAL_BIT_MASK = (1 << HORIZONTAL_SECTION_COUNT) - 1;
// public static final int VERTICAL_BIT_MASK = (1 << VERTICAL_SECTION_COUNT) - 1;
//
// private BiomeMath() {
// }
//
// /**
// * Compute the index into the MC biome array, for non-extended-height worlds.
// *
// * @param x the block x coordinate
// * @param y the block y coordinate
// * @param z the block z coordinate
// * @return the index into the standard MC biome array
// */
// public static int computeBiomeIndex(int x, int y, int z) {
// int l = (x >> 2) & HORIZONTAL_BIT_MASK;
// int m = MathHelper.clamp(y >> 2, 0, VERTICAL_BIT_MASK);
// int n = (z >> 2) & HORIZONTAL_BIT_MASK;
// return m << HORIZONTAL_SECTION_COUNT + HORIZONTAL_SECTION_COUNT
// | n << HORIZONTAL_SECTION_COUNT
// | l;
// }
//
// /**
// * Compute the index into the MC biome array, for extended-height worlds.
// *
// * @param x the block x coordinate
// * @param y the block y coordinate
// * @param z the block z coordinate
// * @param minY minimum y of the world
// * @param maxY maximum y of the world
// * @return the index into the standard MC biome array
// */
// public static int computeBiomeIndex(int x, int y, int z, int minY, int maxY) {
// int l = (x >> 2) & HORIZONTAL_BIT_MASK;
// int m = MathHelper.clamp((y >> 2) - minY, 0, maxY);
// int n = (z >> 2) & HORIZONTAL_BIT_MASK;
// return m << HORIZONTAL_SECTION_COUNT + HORIZONTAL_SECTION_COUNT
// | n << HORIZONTAL_SECTION_COUNT
// | l;
// }
}

View File

@ -97,18 +97,18 @@ public class HeightMap {
int bx = min.getBlockX();
int bz = min.getBlockZ();
Iterator<BlockVector2> flat = Regions.asFlatRegion(region).asFlatRegion().iterator();
int layer = 0;
int layer = session.getMinY();
while (flat.hasNext()) {
BlockVector2 pos = flat.next();
int x = pos.getBlockX();
int z = pos.getBlockZ();
layer = session.getNearestSurfaceLayer(x, z, (layer + 7) >> 3, 0, maxY);
layer = session.getNearestSurfaceLayer(x, z, (layer + 7) >> 3, session.getMinY(), maxY);
data[(z - bz) * width + (x - bx)] = layer;
}
} else {
// Store current heightmap data
int index = 0;
int yTmp = 255;
int yTmp = session.getMaxY();
for (int z = 0; z < height; ++z) {
for (int x = 0; x < width; ++x, index++) {
if (mask != null) {
@ -324,7 +324,7 @@ public class HeightMap {
int y0 = newHeight - 1;
for (int setY = y0, getY = curHeight - 1; setY >= curHeight; setY--, getY--) {
BlockState get;
if (getY >= 0 && getY < 256) {
if (getY >= session.getMinY() && getY <= session.getMaxY()) {
get = session.getBlock(xr, getY, zr);
} else {
get = BlockTypes.AIR.getDefaultState();

View File

@ -19,7 +19,6 @@
package com.sk89q.worldedit.regions;
import com.fastasyncworldedit.core.FaweCache;
import com.fastasyncworldedit.core.configuration.Settings;
import com.fastasyncworldedit.core.extent.filter.block.ChunkFilterBlock;
import com.fastasyncworldedit.core.math.BlockVectorSet;
@ -745,7 +744,7 @@ public class CuboidRegion extends AbstractRegion implements FlatRegion {
if (bx >= minX && tx <= maxX && bz >= minZ && tz <= maxZ) {
// contains all X/Z
if (minY <= 0 && maxY >= 255) {
if (minY <= set.getMinSectionIndex() << 4 && maxY >= (set.getMaxSectionIndex() << 4) + 15) {
return set;
}
trimY(set, minY, maxY);
@ -766,7 +765,7 @@ public class CuboidRegion extends AbstractRegion implements FlatRegion {
boolean trimX = lowerX != 0 || upperX != 15;
boolean trimZ = lowerZ != 0 || upperZ != 15;
for (int layer = 0; layer < FaweCache.IMP.CHUNK_LAYERS; layer++) {
for (int layer = get.getMinSectionIndex(); layer < get.getMaxSectionIndex(); layer++) {
if (set.hasSection(layer)) {
char[] arr = set.load(layer);
if (trimX || trimZ) {

View File

@ -244,11 +244,11 @@ public interface Region extends Iterable<BlockVector3>, Cloneable, IBatchProcess
final IChunkSet set,
boolean full
) {
int minSection = Math.max(0, getMinimumY() >> 4);
int maxSection = Math.min(15, getMaximumY() >> 4);
int minSection = Math.max(get.getMinSectionIndex(), getMinimumY() >> 4);
int maxSection = Math.min(get.getMaxSectionIndex(), getMaximumY() >> 4);
block = block.initChunk(chunk.getX(), chunk.getZ());
for (int layer = minSection; layer <= maxSection; layer++) {
if ((!full && !get.hasSection(layer)) || !filter.appliesLayer(chunk, layer)) {
if ((!full && !set.hasSection(layer)) || !filter.appliesLayer(chunk, layer)) {
return;
}
block = block.initLayer(get, set, layer);

View File

@ -178,7 +178,7 @@ public class TargetBlock {
} else {
if (searchForLastBlock) {
lastBlock = getCurrentBlock();
if (lastBlock.getBlockY() <= 0 || lastBlock.getBlockY() >= world.getMaxY()) {
if (lastBlock.getBlockY() <= world.getMinY() || lastBlock.getBlockY() >= world.getMaxY()) {
searchForLastBlock = false;
}
}