Skip to content

Commit b548219

Browse files
Fix //snow (#3019)
* chore: update isFullCube to actually check for shape not occlusion * chore/fix: fix and update snow simulator * chore: consistent property field naming
1 parent 6d44537 commit b548219

File tree

7 files changed

+109
-76
lines changed

7 files changed

+109
-76
lines changed

worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/PaperweightBlockMaterial.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ public boolean isAir() {
7070

7171
@Override
7272
public boolean isFullCube() {
73-
return craftMaterial.isOccluding();
73+
return Block.isShapeFullBlock(blockState.getShape(EmptyBlockGetter.INSTANCE, BlockPos.ZERO));
7474
}
7575

7676
@Override

worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R3/PaperweightBlockMaterial.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ public boolean isAir() {
6161

6262
@Override
6363
public boolean isFullCube() {
64-
return craftMaterial.isOccluding();
64+
return Block.isShapeFullBlock(blockState.getShape(EmptyBlockGetter.INSTANCE, BlockPos.ZERO));
6565
}
6666

6767
@Override

worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R4/PaperweightBlockMaterial.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ public boolean isAir() {
6161

6262
@Override
6363
public boolean isFullCube() {
64-
return craftMaterial.isOccluding();
64+
return Block.isShapeFullBlock(blockState.getShape(EmptyBlockGetter.INSTANCE, BlockPos.ZERO));
6565
}
6666

6767
@Override

worldedit-bukkit/adapters/adapter-1_21/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_21_R1/PaperweightBlockMaterial.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ public boolean isAir() {
6161

6262
@Override
6363
public boolean isFullCube() {
64-
return craftMaterial.isOccluding();
64+
return Block.isShapeFullBlock(blockState.getShape(EmptyBlockGetter.INSTANCE, BlockPos.ZERO));
6565
}
6666

6767
@Override

worldedit-bukkit/adapters/adapter-1_21_3/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_21_3/PaperweightBlockMaterial.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ public boolean isAir() {
6161

6262
@Override
6363
public boolean isFullCube() {
64-
return craftMaterial.isOccluding();
64+
return Block.isShapeFullBlock(blockState.getShape(EmptyBlockGetter.INSTANCE, BlockPos.ZERO));
6565
}
6666

6767
@Override

worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,7 @@
170170

171171
import static com.google.common.base.Preconditions.checkArgument;
172172
import static com.google.common.base.Preconditions.checkNotNull;
173-
import static com.sk89q.worldedit.function.block.SnowSimulator.snowy;
173+
import static com.sk89q.worldedit.function.block.SnowSimulator.SNOWY;
174174
import static com.sk89q.worldedit.regions.Regions.asFlatRegion;
175175
import static com.sk89q.worldedit.regions.Regions.maximumBlockY;
176176
import static com.sk89q.worldedit.regions.Regions.minimumBlockY;
@@ -2788,8 +2788,8 @@ public int thaw(BlockVector3 position, double radius, int height)
27882788
if (setBlock(mutable, air)) {
27892789
if (y > getMinY()) {
27902790
BlockState block = getBlock(mutable2);
2791-
if (block.getBlockType().hasProperty(snowy)) {
2792-
if (setBlock(mutable2, block.with(snowy, false))) {
2791+
if (block.getBlockType().hasProperty(SNOWY)) {
2792+
if (setBlock(mutable2, block.with(SNOWY, false))) {
27932793
affected++;
27942794
}
27952795
}

worldedit-core/src/main/java/com/sk89q/worldedit/function/block/SnowSimulator.java

Lines changed: 101 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -31,36 +31,35 @@
3131
import com.sk89q.worldedit.world.block.BlockType;
3232
import com.sk89q.worldedit.world.block.BlockTypes;
3333

34-
import java.util.Locale;
34+
import java.util.Comparator;
3535

36+
//FAWE start - rewrite simulator
3637
public class SnowSimulator implements LayerFunction {
3738

38-
//FAWE start
39-
public static final BooleanProperty snowy = (BooleanProperty) (Property<?>) BlockTypes.GRASS_BLOCK.getProperty("snowy");
40-
private static final EnumProperty slab = (EnumProperty) (Property<?>) BlockTypes.SANDSTONE_SLAB.getProperty("type");
41-
private static final EnumProperty stair = (EnumProperty) (Property<?>) BlockTypes.SANDSTONE_STAIRS.getProperty("half");
42-
private static final EnumProperty trapdoor = (EnumProperty) (Property<?>) BlockTypes.ACACIA_TRAPDOOR.getProperty("half");
43-
private static final BooleanProperty trapdoorOpen = (BooleanProperty) (Property<?>) BlockTypes.ACACIA_TRAPDOOR.getProperty(
44-
"open");
45-
//FAWE end
39+
public static final BooleanProperty SNOWY = (BooleanProperty) (Property<?>) BlockTypes.GRASS_BLOCK.getProperty("snowy");
40+
private static final EnumProperty PROPERTY_SLAB = (EnumProperty) (Property<?>) BlockTypes.OAK_SLAB.getProperty("type");
41+
private static final EnumProperty PROPERTY_STAIR = (EnumProperty) (Property<?>) BlockTypes.OAK_STAIRS.getProperty("half");
42+
private static final EnumProperty PROPERTY_TRAPDOOR = (EnumProperty) (Property<?>) BlockTypes.OAK_TRAPDOOR.getProperty("half");
43+
private static final BooleanProperty PROPERTY_TRAPDOOR_OPEN = (BooleanProperty) (Property<?>) BlockTypes.OAK_TRAPDOOR.getProperty("open");
4644

47-
private final BlockState ice = BlockTypes.ICE.getDefaultState();
48-
private final BlockState snow = BlockTypes.SNOW.getDefaultState();
49-
private final BlockState snowBlock = BlockTypes.SNOW_BLOCK.getDefaultState();
45+
private static final BlockState ICE = BlockTypes.ICE.getDefaultState();
46+
private static final BlockState SNOW = BlockTypes.SNOW.getDefaultState();
47+
private static final BlockState SNOW_BLOCK = BlockTypes.SNOW_BLOCK.getDefaultState();
5048

51-
private final Property<Integer> snowLayersProperty = BlockTypes.SNOW.getProperty("layers");
52-
private final Property<Integer> waterLevelProperty = BlockTypes.WATER.getProperty("level");
49+
private static final Property<Integer> PROPERTY_SNOW_LAYERS = BlockTypes.SNOW.getProperty("layers");
50+
private static final Property<Integer> PROPERTY_WATER_LEVEL = BlockTypes.WATER.getProperty("level");
51+
52+
private static final String PROPERTY_VALUE_TOP = "top";
53+
private static final String PROPERTY_VALUE_BOTTOM = "bottom";
54+
private static final int MAX_SNOW_LAYER = PROPERTY_SNOW_LAYERS.getValues().stream().max(Comparator.naturalOrder()).orElse(8);
5355

5456
private final Extent extent;
5557
private final boolean stack;
56-
5758
private int affected;
5859

5960
public SnowSimulator(Extent extent, boolean stack) {
60-
6161
this.extent = extent;
6262
this.stack = stack;
63-
6463
this.affected = 0;
6564
}
6665

@@ -70,20 +69,21 @@ public int getAffected() {
7069

7170
@Override
7271
public boolean isGround(BlockVector3 position) {
73-
BlockState block = this.extent.getBlock(position);
72+
final BlockState block = this.extent.getBlock(position);
73+
final BlockType blockType = block.getBlockType();
7474

75-
// We're returning the first block we can place *on top of*
76-
if (block.getBlockType().getMaterial().isAir() || (stack && block.getBlockType() == BlockTypes.SNOW)) {
75+
// We're returning the first block we can (potentially) place *on top of*
76+
if (blockType.getMaterial().isAir() || (stack && blockType == BlockTypes.SNOW)) {
7777
return false;
7878
}
7979

8080
// Unless it's water
81-
if (block.getBlockType() == BlockTypes.WATER) {
81+
if (blockType == BlockTypes.WATER) {
8282
return true;
8383
}
8484

8585
// Stop searching when we hit a movement blocker
86-
return block.getBlockType().getMaterial().isMovementBlocker();
86+
return blockType.getMaterial().isMovementBlocker();
8787
}
8888

8989
@Override
@@ -93,18 +93,17 @@ public boolean apply(BlockVector3 position, int depth) throws WorldEditException
9393
return false;
9494
}
9595

96-
BlockState block = this.extent.getBlock(position);
96+
final BlockState block = this.extent.getBlock(position);
97+
final BlockType blockType = block.getBlockType();
9798

98-
if (block.getBlockType() == BlockTypes.WATER) {
99-
if (block.getState(waterLevelProperty) == 0) {
100-
if (this.extent.setBlock(position, ice)) {
101-
affected++;
102-
}
99+
// If affected block is water, replace with ice
100+
if (blockType == BlockTypes.WATER) {
101+
if (shouldFreeze(position, block) && this.extent.setBlock(position.x(), position.y(), position.z(), ICE)) {
102+
affected++;
103103
}
104104
return false;
105105
}
106106

107-
108107
// Can't put snow this far up
109108
if (position.y() == this.extent.getMaximumPoint().y()) {
110109
return false;
@@ -113,57 +112,91 @@ public boolean apply(BlockVector3 position, int depth) throws WorldEditException
113112
BlockVector3 abovePosition = position.add(0, 1, 0);
114113
BlockState above = this.extent.getBlock(abovePosition);
115114

116-
// Can only replace air (or snow in stack mode)
117-
if (!above.getBlockType().getMaterial().isAir() && (!stack || above.getBlockType() != BlockTypes.SNOW)) {
118-
return false;
119-
//FAWE start
120-
} else if (!block.getBlockType().id().toLowerCase(Locale.ROOT).contains("ice") && this.extent.getEmittedLight(
121-
abovePosition) > 10) {
115+
if (!shouldSnow(block, above)) {
122116
return false;
123-
} else if (!block.getBlockType().getMaterial().isFullCube()) {
124-
BlockType type = block.getBlockType();
125-
if (type.hasProperty(slab) && block.getState(slab).equalsIgnoreCase("bottom")) {
126-
return false;
127-
} else if ((type.hasProperty(trapdoorOpen) && block.getState(trapdoorOpen)) ||
128-
(type.hasProperty(trapdoor) && block.getState(trapdoor).equalsIgnoreCase("bottom"))) {
117+
}
118+
119+
// in stack mode, we want to increase existing snow layers
120+
if (stack && above.getBlockType() == BlockTypes.SNOW) {
121+
int layers = above.getState(PROPERTY_SNOW_LAYERS);
122+
// if we would place the last possible layer (in current versions layer 8) we just replace with a snow block and
123+
// set the block beneath snowy (if property is applicable, example would be grass with snow texture on top)
124+
if (layers == MAX_SNOW_LAYER - 1 && !this.extent.setBlock(abovePosition, SNOW_BLOCK)) {
129125
return false;
130-
} else if (type.hasProperty(stair) && block.getState(stair).equalsIgnoreCase("bottom")) {
126+
}
127+
// we've not reached the top snow layer yet, so just add another layer
128+
if (!this.extent.setBlock(abovePosition, above.with(PROPERTY_SNOW_LAYERS, layers + 1))) {
131129
return false;
132-
} else {
130+
}
131+
} else {
132+
if (!this.extent.setBlock(abovePosition, SNOW)) {
133133
return false;
134134
}
135-
//FAWE end
136-
} else if (!BlockCategories.SNOW_LAYER_CAN_SURVIVE_ON.contains(block.getBlockType())) {
135+
}
136+
// set block beneath snow (layers) snowy, if applicable
137+
if (block.getBlockType().hasProperty(SNOWY)) {
138+
this.extent.setBlock(position, block.with(SNOWY, true));
139+
}
140+
this.affected++;
141+
return false;
142+
}
143+
144+
/**
145+
* Check if snow should be placed at {@code above}
146+
*
147+
* @param blockState The block under the snow layer
148+
* @param above The block which will hold the snow layer
149+
* @return if snow should be placed
150+
*/
151+
private boolean shouldSnow(BlockState blockState, BlockState above) {
152+
// simplified net.minecraft.world.level.biome.Biome#shouldSnow
153+
// if the block, where the snow should be actually placed at, is not air or snow (if in stack mode), we can't place
154+
// anything
155+
if (!(above.isAir() || (above.getBlockType() == BlockTypes.SNOW && stack))) {
156+
return false;
157+
}
158+
// net.minecraft.world.level.block.SnowLayerBlock#canSurvive
159+
if (BlockCategories.SNOW_LAYER_CANNOT_SURVIVE_ON.contains(blockState)) {
137160
return false;
138161
}
162+
if (BlockCategories.SNOW_LAYER_CAN_SURVIVE_ON.contains(blockState)) {
163+
return true;
164+
}
165+
BlockType type = blockState.getBlockType();
139166

140-
if (stack && above.getBlockType() == BlockTypes.SNOW) {
141-
int currentHeight = above.getState(snowLayersProperty);
142-
// We've hit the highest layer (If it doesn't contain current + 2 it means it's 1 away from full)
143-
if (!snowLayersProperty.getValues().contains(currentHeight + 2)) {
144-
if (this.extent.setBlock(abovePosition, snowBlock)) {
145-
if (block.getBlockType().hasProperty(snowy)) {
146-
this.extent.setBlock(position, block.with(snowy, true));
147-
}
148-
this.affected++;
149-
}
150-
} else {
151-
if (this.extent.setBlock(abovePosition, above.with(snowLayersProperty, currentHeight + 1))) {
152-
if (block.getBlockType().hasProperty(snowy)) {
153-
this.extent.setBlock(position, block.with(snowy, true));
154-
}
155-
this.affected++;
156-
}
157-
}
167+
// net.minecraft.world.level.block.Block.isFaceFull (block has 1x1x1 bounding box)
168+
if (type.getMaterial().isFullCube()) {
169+
return true;
170+
}
171+
// if block beneath potential snow layer has snow layers, we can place snow if all possible layers are present.
172+
if (type == BlockTypes.SNOW && blockState.getState(PROPERTY_SNOW_LAYERS) == MAX_SNOW_LAYER) {
173+
return true;
174+
}
175+
// return potential non-full blocks, which could hold snow layers due to block states
176+
// if block is a slab, needs to be on the upper part of the block
177+
if (type.hasProperty(PROPERTY_SLAB)) {
178+
return PROPERTY_VALUE_TOP.equals(blockState.getState(PROPERTY_SLAB));
179+
}
180+
// if block is a trapdoor, the trapdoor must NOT be open
181+
if (type.hasProperty(PROPERTY_TRAPDOOR_OPEN) && blockState.getState(PROPERTY_TRAPDOOR_OPEN)) {
158182
return false;
159183
}
160-
if (this.extent.setBlock(abovePosition, snow)) {
161-
if (block.getBlockType().hasProperty(snowy)) {
162-
this.extent.setBlock(position, block.with(snowy, true));
163-
}
164-
this.affected++;
184+
// if block is a closed trapdoor, the trapdoor must be aligned at the top part of the block
185+
if (type.hasProperty(PROPERTY_TRAPDOOR)) {
186+
return PROPERTY_VALUE_TOP.equals(blockState.getState(PROPERTY_TRAPDOOR));
187+
}
188+
// if block is a stair, it must be "bottom" (upside-down)
189+
if (type.hasProperty(PROPERTY_STAIR)) {
190+
return PROPERTY_VALUE_BOTTOM.equals(blockState.getState(PROPERTY_STAIR));
165191
}
166192
return false;
167193
}
168194

195+
// net.minecraft.world.level.biome.Biome#shouldFreeze
196+
private boolean shouldFreeze(BlockVector3 position, BlockState blockState) {
197+
return blockState.getBlockType() == BlockTypes.WATER &&
198+
blockState.getState(PROPERTY_WATER_LEVEL) == 0 &&
199+
this.extent.getEmittedLight(position) < 10;
200+
}
201+
169202
}

0 commit comments

Comments
 (0)