Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
package com.fastasyncworldedit.core.command.tool.brush;

import com.fastasyncworldedit.core.extent.filter.block.FilterBlock;
import com.fastasyncworldedit.core.function.mask.CachedMask;
import com.fastasyncworldedit.core.math.MutableBlockVector3;
import com.fastasyncworldedit.core.queue.Filter;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.MaxChangedBlocksException;
import com.sk89q.worldedit.command.tool.brush.Brush;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.regions.CuboidRegion;
import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.block.BlockTypes;

Expand Down Expand Up @@ -54,89 +58,106 @@ public void build(EditSession editSession, BlockVector3 position, Pattern patter
int ty = position.y();
int tz = position.z();

int[] frequency = new int[BlockTypes.size()];
final CuboidRegion region = new CuboidRegion(
BlockVector3.at(tx - outsetSize, ty - outsetSize, tz - outsetSize),
BlockVector3.at(tx + outsetSize, ty + outsetSize, tz + outsetSize)
);

int maxY = editSession.getMaxY();
int minY = editSession.getMinY();
editSession.apply(region, new BlendBallFilter((int) brushSizeSquared, tx, ty, tz), true);
}

MutableBlockVector3 mutable = new MutableBlockVector3();
for (int x = -outsetSize; x <= outsetSize; x++) {
int x0 = x + tx;
int xx = x * x;
for (int y = -outsetSize; y <= outsetSize; y++) {
int y0 = y + ty;
if (y0 + 1 < minY || y0 - 1 > maxY) {
continue;
}
int yy = y * y;
int xxyy = xx + yy;
if (xxyy >= brushSizeSquared) {
continue;
}
for (int z = -outsetSize; z <= outsetSize; z++) {
int z0 = z + tz;
if (xxyy + z * z >= brushSizeSquared || maskFails(editSession, mutable.setComponents(x0, y0, z0))) {
continue;
}
int highest = 1, currentBlockFrequency = 1;
BlockState currentState = editSession.getBlock(x0, y0, z0);
BlockState highestState = currentState;
int currentStateID = currentState.getInternalBlockTypeId();
Arrays.fill(frequency, 0);
int air = 0;
int total = 26;
boolean tie = false;
for (int ox = -1; ox <= 1; ox++) {
for (int oz = -1; oz <= 1; oz++) {
for (int oy = -1; oy <= 1; oy++) {
if (ox == 0 && oy == 0 && oz == 0) {
continue;
} else if (oy + y0 < minY || oy + y0 > maxY) {
total--;
continue;
}
boolean masked = maskFails(editSession, mutable.setComponents(x0 + ox, y0 + oy, z0 + oz));
BlockState state = masked ? AIR : editSession.getBlock(x0 + ox, y0 + oy, z0 + oz);
if (state.getBlockType().getMaterial().isAir()) {
air++;
}
int internalID = state.getInternalBlockTypeId();
int count = frequency[internalID];
if (internalID == currentStateID) {
currentBlockFrequency++;
}
count++;
if (count - highest >= minFreqDiff) {
highest = count;
highestState = state;
tie = false;
} else if (count == highest) {
tie = true;
}
frequency[internalID] = count;
}
private boolean maskFails(Extent extent, BlockVector3 pos) {
return mask != null && !mask.test(extent, pos);
}

private class BlendBallFilter implements Filter {
private final int[] frequency = new int[BlockTypes.size()];
private final MutableBlockVector3 mutable = new MutableBlockVector3();
private final int brushSizeSquared;
private final int centerX;
private final int centerY;
private final int centerZ;

private BlendBallFilter(final int brushSizeSquared, final int centerX, final int centerY, final int centerZ) {
this.brushSizeSquared = brushSizeSquared;
this.centerX = centerX;
this.centerY = centerY;
this.centerZ = centerZ;
}

@Override
public void applyBlock(final FilterBlock block) {
final Extent extent = block.getExtent();
final int gx = block.x();
final int gy = block.y();
final int gz = block.z();
int dx = gx - this.centerX;
int dy = gy - this.centerY;
int dz = gz - this.centerZ;
if (dx * dx + dy * dy + dz * dz >= brushSizeSquared || maskFails(extent, block)) {
return;
}
int maxY = extent.getMaxY();
int minY = extent.getMinY();
int highest = 1, currentBlockFrequency = 1;
BlockState currentState = block.getBlock();
BlockState highestState = currentState;
int currentStateID = currentState.getInternalBlockTypeId();
Arrays.fill(frequency, 0);
int air = 0;
int total = 26;
boolean tie = false;
for (int ox = -1; ox <= 1; ox++) {
for (int oz = -1; oz <= 1; oz++) {
for (int oy = -1; oy <= 1; oy++) {
if (ox == 0 && oy == 0 && oz == 0) {
continue;
} else if (oy + gy < minY || oy + gy > maxY) {
total--;
continue;
}
}
if (onlyAir) {
if (air * 2 - total >= minFreqDiff) {
if (!currentState.isAir()) {
editSession.setBlock(x0, y0, z0, AIR);
}
} else if (currentState.isAir() && total - 2 * air >= minFreqDiff) {
editSession.setBlock(x0, y0, z0, highestState);
boolean masked = maskFails(extent, mutable.setComponents(gx + ox, gy + oy, gz + oz));
BlockState state = masked ? AIR : block.getBlock(gx + ox, gy + oy, gz + oz);
if (state.getBlockType().getMaterial().isAir()) {
air++;
}
int internalID = state.getInternalBlockTypeId();
int count = frequency[internalID];
if (internalID == currentStateID) {
currentBlockFrequency++;
}
count++;
if (count - highest >= minFreqDiff) {
highest = count;
highestState = state;
tie = false;
} else if (count == highest) {
tie = true;
}
continue;
frequency[internalID] = count;
}
if (highest - currentBlockFrequency >= minFreqDiff && !tie && currentState != highestState) {
editSession.setBlock(x0, y0, z0, highestState);
}
}
if (onlyAir) {
if (air * 2 - total >= minFreqDiff) {
if (!currentState.isAir()) {
block.setBlock(AIR);
}
} else if (currentState.isAir() && total - 2 * air >= minFreqDiff) {
block.setBlock(highestState);
}
return;
}
if (highest - currentBlockFrequency >= minFreqDiff && !tie && currentState != highestState) {
block.setBlock(highestState);
}
}
}

private boolean maskFails(EditSession editSession, MutableBlockVector3 mutable) {
return mask != null && !mask.test(editSession, mutable);
@Override
public Filter fork() {
return new BlendBallFilter(brushSizeSquared, centerX, centerY, centerZ);
}

}

}
Loading