|
1 | 1 | package com.fastasyncworldedit.core.command.tool.brush; |
2 | 2 |
|
| 3 | +import com.fastasyncworldedit.core.extent.filter.block.FilterBlock; |
3 | 4 | import com.fastasyncworldedit.core.function.mask.CachedMask; |
4 | 5 | import com.fastasyncworldedit.core.math.MutableBlockVector3; |
| 6 | +import com.fastasyncworldedit.core.queue.Filter; |
5 | 7 | import com.sk89q.worldedit.EditSession; |
6 | 8 | import com.sk89q.worldedit.MaxChangedBlocksException; |
7 | 9 | import com.sk89q.worldedit.command.tool.brush.Brush; |
| 10 | +import com.sk89q.worldedit.extent.Extent; |
8 | 11 | import com.sk89q.worldedit.function.pattern.Pattern; |
9 | 12 | import com.sk89q.worldedit.math.BlockVector3; |
| 13 | +import com.sk89q.worldedit.regions.CuboidRegion; |
10 | 14 | import com.sk89q.worldedit.world.block.BlockState; |
11 | 15 | import com.sk89q.worldedit.world.block.BlockTypes; |
12 | 16 |
|
@@ -54,89 +58,106 @@ public void build(EditSession editSession, BlockVector3 position, Pattern patter |
54 | 58 | int ty = position.y(); |
55 | 59 | int tz = position.z(); |
56 | 60 |
|
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 | + ); |
58 | 65 |
|
59 | | - int maxY = editSession.getMaxY(); |
60 | | - int minY = editSession.getMinY(); |
| 66 | + editSession.apply(region, new BlendBallFilter((int) brushSizeSquared, tx, ty, tz), true); |
| 67 | + } |
61 | 68 |
|
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; |
118 | 118 | } |
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; |
127 | 136 | } |
128 | | - continue; |
| 137 | + frequency[internalID] = count; |
129 | 138 | } |
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); |
132 | 145 | } |
| 146 | + } else if (currentState.isAir() && total - 2 * air >= minFreqDiff) { |
| 147 | + block.setBlock(highestState); |
133 | 148 | } |
| 149 | + return; |
| 150 | + } |
| 151 | + if (highest - currentBlockFrequency >= minFreqDiff && !tie && currentState != highestState) { |
| 152 | + block.setBlock(highestState); |
134 | 153 | } |
135 | 154 | } |
136 | | - } |
137 | 155 |
|
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 | + |
140 | 161 | } |
141 | 162 |
|
142 | 163 | } |
0 commit comments