Skip to content

Commit 24fecf3

Browse files
committed
chore/fix: fix and update snow simulator
1 parent 653cdd4 commit 24fecf3

File tree

2 files changed

+104
-70
lines changed

2 files changed

+104
-70
lines changed

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 & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -31,36 +31,36 @@
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(
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 TRAPDOOR = (EnumProperty) (Property<?>) BlockTypes.OAK_TRAPDOOR.getProperty("half");
43+
private static final BooleanProperty TRAPDOOR_OPEN = (BooleanProperty) (Property<?>) BlockTypes.OAK_TRAPDOOR.getProperty(
4444
"open");
45-
//FAWE end
4645

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();
46+
private static final BlockState ICE = BlockTypes.ICE.getDefaultState();
47+
private static final BlockState SNOW = BlockTypes.SNOW.getDefaultState();
48+
private static final BlockState SNOW_BLOCK = BlockTypes.SNOW_BLOCK.getDefaultState();
5049

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

5457
private final Extent extent;
5558
private final boolean stack;
56-
5759
private int affected;
5860

5961
public SnowSimulator(Extent extent, boolean stack) {
60-
6162
this.extent = extent;
6263
this.stack = stack;
63-
6464
this.affected = 0;
6565
}
6666

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

7171
@Override
7272
public boolean isGround(BlockVector3 position) {
73-
BlockState block = this.extent.getBlock(position);
73+
final BlockState block = this.extent.getBlock(position);
74+
final BlockType blockType = block.getBlockType();
7475

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

8081
// Unless it's water
81-
if (block.getBlockType() == BlockTypes.WATER) {
82+
if (blockType == BlockTypes.WATER) {
8283
return true;
8384
}
8485

8586
// Stop searching when we hit a movement blocker
86-
return block.getBlockType().getMaterial().isMovementBlocker();
87+
return blockType.getMaterial().isMovementBlocker();
8788
}
8889

8990
@Override
@@ -93,18 +94,17 @@ public boolean apply(BlockVector3 position, int depth) throws WorldEditException
9394
return false;
9495
}
9596

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

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

107-
108108
// Can't put snow this far up
109109
if (position.y() == this.extent.getMaximumPoint().y()) {
110110
return false;
@@ -113,57 +113,91 @@ public boolean apply(BlockVector3 position, int depth) throws WorldEditException
113113
BlockVector3 abovePosition = position.add(0, 1, 0);
114114
BlockState above = this.extent.getBlock(abovePosition);
115115

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) {
116+
if (!shouldSnow(block, above)) {
122117
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"))) {
118+
}
119+
120+
// in stack mode, we want to increase existing snow layers
121+
if (stack && above.getBlockType() == BlockTypes.SNOW) {
122+
int layers = above.getState(PROPERTY_SNOW_LAYERS);
123+
// if we would place the last possible layer (in current versions layer 8) we just replace with a snow block and
124+
// set the block beneath snowy (if property is applicable, example would be grass with snow texture on top)
125+
if (layers == MAX_SNOW_LAYER - 1 && !this.extent.setBlock(abovePosition, SNOW_BLOCK)) {
129126
return false;
130-
} else if (type.hasProperty(stair) && block.getState(stair).equalsIgnoreCase("bottom")) {
127+
}
128+
// we've not reached the top snow layer yet, so just add another layer
129+
if (!this.extent.setBlock(abovePosition, above.with(PROPERTY_SNOW_LAYERS, layers + 1))) {
131130
return false;
132-
} else {
131+
}
132+
} else {
133+
if (!this.extent.setBlock(abovePosition, SNOW)) {
133134
return false;
134135
}
135-
//FAWE end
136-
} else if (!BlockCategories.SNOW_LAYER_CAN_SURVIVE_ON.contains(block.getBlockType())) {
136+
}
137+
// set block beneath snow (layers) snowy, if applicable
138+
if (block.getBlockType().hasProperty(SNOWY)) {
139+
this.extent.setBlock(position, block.with(SNOWY, true));
140+
}
141+
this.affected++;
142+
return false;
143+
}
144+
145+
/**
146+
* Check if snow should be placed at {@code above}
147+
*
148+
* @param blockState The block under the snow layer
149+
* @param above The block which will hold the snow layer
150+
* @return if snow should be placed
151+
*/
152+
private boolean shouldSnow(BlockState blockState, BlockState above) {
153+
// simplified net.minecraft.world.level.biome.Biome#shouldSnow
154+
// if the block, where the snow should be actually placed at, is not air or snow (if in stack mode), we can't place
155+
// anything
156+
if (!(above.isAir() || (above.getBlockType() == BlockTypes.SNOW && stack))) {
157+
return false;
158+
}
159+
// net.minecraft.world.level.block.SnowLayerBlock#canSurvive
160+
if (BlockCategories.SNOW_LAYER_CANNOT_SURVIVE_ON.contains(blockState)) {
137161
return false;
138162
}
163+
if (BlockCategories.SNOW_LAYER_CAN_SURVIVE_ON.contains(blockState)) {
164+
return true;
165+
}
166+
BlockType type = blockState.getBlockType();
139167

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-
}
168+
// net.minecraft.world.level.block.Block.isFaceFull (block has 1x1x1 bounding box)
169+
if (type.getMaterial().isFullCube()) {
170+
return true;
171+
}
172+
// if block beneath potential snow layer has snow layers, we can place snow if all possible layers are present.
173+
if (type == BlockTypes.SNOW && blockState.getState(PROPERTY_SNOW_LAYERS) == MAX_SNOW_LAYER) {
174+
return true;
175+
}
176+
// return potential non-full blocks, which could hold snow layers due to block states
177+
// if block is a slab, needs to be on the upper part of the block
178+
if (type.hasProperty(PROPERTY_SLAB)) {
179+
return PROPERTY_VALUE_TOP.equals(blockState.getState(PROPERTY_SLAB));
180+
}
181+
// if block is a trapdoor, the trapdoor must NOT be open
182+
if (type.hasProperty(TRAPDOOR_OPEN) && blockState.getState(TRAPDOOR_OPEN)) {
158183
return false;
159184
}
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++;
185+
// if block is a closed trapdoor, the trapdoor must be aligned at the top part of the block
186+
if (type.hasProperty(TRAPDOOR)) {
187+
return PROPERTY_VALUE_TOP.equals(blockState.getState(TRAPDOOR));
188+
}
189+
// if block is a stair, it must be "bottom" (upside-down)
190+
if (type.hasProperty(PROPERTY_STAIR)) {
191+
return PROPERTY_VALUE_BOTTOM.equals(blockState.getState(PROPERTY_STAIR));
165192
}
166193
return false;
167194
}
168195

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

0 commit comments

Comments
 (0)