Skip to content

Commit ebb1e66

Browse files
committed
Improve BlendBall performance using custom Filter
1 parent 373dfbc commit ebb1e66

File tree

1 file changed

+94
-73
lines changed
  • worldedit-core/src/main/java/com/fastasyncworldedit/core/command/tool/brush

1 file changed

+94
-73
lines changed
Lines changed: 94 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,16 @@
11
package com.fastasyncworldedit.core.command.tool.brush;
22

3+
import com.fastasyncworldedit.core.extent.filter.block.FilterBlock;
34
import com.fastasyncworldedit.core.function.mask.CachedMask;
45
import com.fastasyncworldedit.core.math.MutableBlockVector3;
6+
import com.fastasyncworldedit.core.queue.Filter;
57
import com.sk89q.worldedit.EditSession;
68
import com.sk89q.worldedit.MaxChangedBlocksException;
79
import com.sk89q.worldedit.command.tool.brush.Brush;
10+
import com.sk89q.worldedit.extent.Extent;
811
import com.sk89q.worldedit.function.pattern.Pattern;
912
import com.sk89q.worldedit.math.BlockVector3;
13+
import com.sk89q.worldedit.regions.CuboidRegion;
1014
import com.sk89q.worldedit.world.block.BlockState;
1115
import com.sk89q.worldedit.world.block.BlockTypes;
1216

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

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

59-
int maxY = editSession.getMaxY();
60-
int minY = editSession.getMinY();
66+
editSession.apply(region, new BlendBallFilter((int) brushSizeSquared, tx, ty, tz), true);
67+
}
6168

62-
MutableBlockVector3 mutable = new MutableBlockVector3();
63-
for (int x = -outsetSize; x <= outsetSize; x++) {
64-
int x0 = x + tx;
65-
int xx = x * x;
66-
for (int y = -outsetSize; y <= outsetSize; y++) {
67-
int y0 = y + ty;
68-
if (y0 + 1 < minY || y0 - 1 > maxY) {
69-
continue;
70-
}
71-
int yy = y * y;
72-
int xxyy = xx + yy;
73-
if (xxyy >= brushSizeSquared) {
74-
continue;
75-
}
76-
for (int z = -outsetSize; z <= outsetSize; z++) {
77-
int z0 = z + tz;
78-
if (xxyy + z * z >= brushSizeSquared || maskFails(editSession, mutable.setComponents(x0, y0, z0))) {
79-
continue;
80-
}
81-
int highest = 1, currentBlockFrequency = 1;
82-
BlockState currentState = editSession.getBlock(x0, y0, z0);
83-
BlockState highestState = currentState;
84-
int currentStateID = currentState.getInternalBlockTypeId();
85-
Arrays.fill(frequency, 0);
86-
int air = 0;
87-
int total = 26;
88-
boolean tie = false;
89-
for (int ox = -1; ox <= 1; ox++) {
90-
for (int oz = -1; oz <= 1; oz++) {
91-
for (int oy = -1; oy <= 1; oy++) {
92-
if (ox == 0 && oy == 0 && oz == 0) {
93-
continue;
94-
} else if (oy + y0 < minY || oy + y0 > maxY) {
95-
total--;
96-
continue;
97-
}
98-
boolean masked = maskFails(editSession, mutable.setComponents(x0 + ox, y0 + oy, z0 + oz));
99-
BlockState state = masked ? AIR : editSession.getBlock(x0 + ox, y0 + oy, z0 + oz);
100-
if (state.getBlockType().getMaterial().isAir()) {
101-
air++;
102-
}
103-
int internalID = state.getInternalBlockTypeId();
104-
int count = frequency[internalID];
105-
if (internalID == currentStateID) {
106-
currentBlockFrequency++;
107-
}
108-
count++;
109-
if (count - highest >= minFreqDiff) {
110-
highest = count;
111-
highestState = state;
112-
tie = false;
113-
} else if (count == highest) {
114-
tie = true;
115-
}
116-
frequency[internalID] = count;
117-
}
69+
private boolean maskFails(Extent extent, BlockVector3 pos) {
70+
return mask != null && !mask.test(extent, pos);
71+
}
72+
73+
private class BlendBallFilter implements Filter {
74+
private final int[] frequency = new int[BlockTypes.size()];
75+
private final MutableBlockVector3 mutable = new MutableBlockVector3();
76+
private final int brushSizeSquared;
77+
private final int xo;
78+
private final int yo;
79+
private final int zo;
80+
81+
private BlendBallFilter(final int brushSizeSquared, final int xo, final int yo, final int zo) {
82+
this.brushSizeSquared = brushSizeSquared;
83+
this.xo = xo;
84+
this.yo = yo;
85+
this.zo = zo;
86+
}
87+
88+
@Override
89+
public void applyBlock(final FilterBlock block) {
90+
final Extent extent = block.getExtent();
91+
final int xr = block.x();
92+
final int yr = block.y();
93+
final int zr = block.z();
94+
int x = xr - this.xo;
95+
int y = yr - this.yo;
96+
int z = zr - this.zo;
97+
if (x * x + y * y + z * z >= brushSizeSquared || maskFails(extent, block)) {
98+
return;
99+
}
100+
int maxY = extent.getMaxY();
101+
int minY = extent.getMinY();
102+
int highest = 1, currentBlockFrequency = 1;
103+
BlockState currentState = block.getBlock();
104+
BlockState highestState = currentState;
105+
int currentStateID = currentState.getInternalBlockTypeId();
106+
Arrays.fill(frequency, 0);
107+
int air = 0;
108+
int total = 26;
109+
boolean tie = false;
110+
for (int ox = -1; ox <= 1; ox++) {
111+
for (int oz = -1; oz <= 1; oz++) {
112+
for (int oy = -1; oy <= 1; oy++) {
113+
if (ox == 0 && oy == 0 && oz == 0) {
114+
continue;
115+
} else if (oy + yr < minY || oy + yr > maxY) {
116+
total--;
117+
continue;
118118
}
119-
}
120-
if (onlyAir) {
121-
if (air * 2 - total >= minFreqDiff) {
122-
if (!currentState.isAir()) {
123-
editSession.setBlock(x0, y0, z0, AIR);
124-
}
125-
} else if (currentState.isAir() && total - 2 * air >= minFreqDiff) {
126-
editSession.setBlock(x0, y0, z0, highestState);
119+
boolean masked = maskFails(extent, mutable.setComponents(xr + ox, yr + oy, zr + oz));
120+
BlockState state = masked ? AIR : block.getBlock(xr + ox, yr + oy, zr + oz);
121+
if (state.getBlockType().getMaterial().isAir()) {
122+
air++;
123+
}
124+
int internalID = state.getInternalBlockTypeId();
125+
int count = frequency[internalID];
126+
if (internalID == currentStateID) {
127+
currentBlockFrequency++;
128+
}
129+
count++;
130+
if (count - highest >= minFreqDiff) {
131+
highest = count;
132+
highestState = state;
133+
tie = false;
134+
} else if (count == highest) {
135+
tie = true;
127136
}
128-
continue;
137+
frequency[internalID] = count;
129138
}
130-
if (highest - currentBlockFrequency >= minFreqDiff && !tie && currentState != highestState) {
131-
editSession.setBlock(x0, y0, z0, highestState);
139+
}
140+
}
141+
if (onlyAir) {
142+
if (air * 2 - total >= minFreqDiff) {
143+
if (!currentState.isAir()) {
144+
block.setBlock(AIR);
132145
}
146+
} else if (currentState.isAir() && total - 2 * air >= minFreqDiff) {
147+
block.setBlock(highestState);
133148
}
149+
return;
150+
}
151+
if (highest - currentBlockFrequency >= minFreqDiff && !tie && currentState != highestState) {
152+
block.setBlock(highestState);
134153
}
135154
}
136-
}
137155

138-
private boolean maskFails(EditSession editSession, MutableBlockVector3 mutable) {
139-
return mask != null && !mask.test(editSession, mutable);
156+
@Override
157+
public Filter fork() {
158+
return new BlendBallFilter(brushSizeSquared, xo, yo, zo);
159+
}
160+
140161
}
141162

142163
}

0 commit comments

Comments
 (0)