Skip to content

Commit 3d37f42

Browse files
CloudburstMC#1070 Fixes double plant not stacking up after bonemealing from different heights
1 parent b4cab97 commit 3d37f42

File tree

6 files changed

+214
-55
lines changed

6 files changed

+214
-55
lines changed

src/main/java/cn/nukkit/block/BlockDoor.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import java.util.List;
3131

3232
import static cn.nukkit.blockproperty.CommonBlockProperties.OPEN;
33+
import static cn.nukkit.blockproperty.CommonBlockProperties.UPPER_BLOCK;
3334

3435
/**
3536
* @author MagicDroidX (Nukkit Project)
@@ -44,7 +45,6 @@ public abstract class BlockDoor extends BlockTransparentMeta implements Redstone
4445
// and gives the vanilla behavior; no idea how to make this better :d
4546
private static final List<Location> manualOverrides = new ArrayList<>();
4647

47-
public static final BooleanBlockProperty UPPER_BLOCK = new BooleanBlockProperty("upper_block_bit", false);
4848
public static final BooleanBlockProperty DOOR_HINGE = new BooleanBlockProperty("door_hinge_bit", false);
4949
public static final BlockProperty<BlockFace> DOOR_DIRECTION = new ArrayBlockProperty<>("direction", false, new BlockFace[]{
5050
BlockFace.EAST, BlockFace.SOUTH,

src/main/java/cn/nukkit/block/BlockDoublePlant.java

Lines changed: 99 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,15 @@
11
package cn.nukkit.block;
22

33
import cn.nukkit.Player;
4+
import cn.nukkit.api.DeprecationDetails;
45
import cn.nukkit.api.PowerNukkitDifference;
6+
import cn.nukkit.api.PowerNukkitOnly;
7+
import cn.nukkit.api.Since;
8+
import cn.nukkit.blockproperty.ArrayBlockProperty;
9+
import cn.nukkit.blockproperty.BlockProperties;
10+
import cn.nukkit.blockproperty.value.DoublePlantType;
511
import cn.nukkit.item.Item;
6-
import cn.nukkit.item.ItemSeedsWheat;
12+
import cn.nukkit.item.ItemID;
713
import cn.nukkit.level.Level;
814
import cn.nukkit.level.particle.BoneMealParticle;
915
import cn.nukkit.math.BlockFace;
@@ -12,28 +18,45 @@
1218
import javax.annotation.Nonnull;
1319
import java.util.concurrent.ThreadLocalRandom;
1420

21+
import static cn.nukkit.blockproperty.CommonBlockProperties.UPPER_BLOCK;
22+
1523
/**
1624
* @author xtypr
1725
* @since 2015/11/23
1826
*/
1927
public class BlockDoublePlant extends BlockFlowable {
28+
@PowerNukkitOnly
29+
@Since("1.4.0.0-PN")
30+
public static final ArrayBlockProperty<DoublePlantType> DOUBLE_PLANT_TYPE = new ArrayBlockProperty<>(
31+
"double_plant_type", true, DoublePlantType.class
32+
);
33+
34+
@PowerNukkitOnly
35+
@Since("1.4.0.0-PN")
36+
public static final BlockProperties PROPERTIES = new BlockProperties(DOUBLE_PLANT_TYPE, UPPER_BLOCK);
37+
38+
@Deprecated @DeprecationDetails(since = "1.4.0.0-PN", by = "PowerNukkit", replaceWith = "DoublePlantType.SUNFLOWER",
39+
reason = "Magic values may change in future without backward compatibility.")
2040
public static final int SUNFLOWER = 0;
41+
@Deprecated @DeprecationDetails(since = "1.4.0.0-PN", by = "PowerNukkit", replaceWith = "DoublePlantType.LILAC",
42+
reason = "Magic values may change in future without backward compatibility.")
2143
public static final int LILAC = 1;
44+
@Deprecated @DeprecationDetails(since = "1.4.0.0-PN", by = "PowerNukkit", replaceWith = "DoublePlantType.TALL_GRASS",
45+
reason = "Magic values may change in future without backward compatibility.")
2246
public static final int TALL_GRASS = 2;
47+
@Deprecated @DeprecationDetails(since = "1.4.0.0-PN", by = "PowerNukkit", replaceWith = "DoublePlantType.LARGE_FERN",
48+
reason = "Magic values may change in future without backward compatibility.")
2349
public static final int LARGE_FERN = 3;
50+
@Deprecated @DeprecationDetails(since = "1.4.0.0-PN", by = "PowerNukkit", replaceWith = "DoublePlantType.ROSE_BUSH",
51+
reason = "Magic values may change in future without backward compatibility.")
2452
public static final int ROSE_BUSH = 4;
53+
@Deprecated @DeprecationDetails(since = "1.4.0.0-PN", by = "PowerNukkit", replaceWith = "DoublePlantType.PEONY",
54+
reason = "Magic values may change in future without backward compatibility.")
2555
public static final int PEONY = 5;
56+
@Deprecated @DeprecationDetails(since = "1.4.0.0-PN", by = "PowerNukkit", replaceWith = "CommonBlockProperties.UPPER_BLOCK",
57+
reason = "Magic values may change in future without backward compatibility.")
2658
public static final int TOP_HALF_BITMASK = 0x8;
2759

28-
private static final String[] NAMES = new String[]{
29-
"Sunflower",
30-
"Lilac",
31-
"Double Tallgrass",
32-
"Large Fern",
33-
"Rose Bush",
34-
"Peony"
35-
};
36-
3760
public BlockDoublePlant() {
3861
this(0);
3962
}
@@ -47,22 +70,54 @@ public int getId() {
4770
return DOUBLE_PLANT;
4871
}
4972

73+
@Since("1.4.0.0-PN")
74+
@PowerNukkitOnly
75+
@Nonnull
76+
@Override
77+
public BlockProperties getProperties() {
78+
return PROPERTIES;
79+
}
80+
81+
@PowerNukkitOnly
82+
@Since("1.4.0.0-PN")
83+
@Nonnull
84+
public DoublePlantType getDoublePlantType() {
85+
return getPropertyValue(DOUBLE_PLANT_TYPE);
86+
}
87+
88+
@PowerNukkitOnly
89+
@Since("1.4.0.0-PN")
90+
public void setDoublePlantType(@Nonnull DoublePlantType type) {
91+
setPropertyValue(DOUBLE_PLANT_TYPE, type);
92+
}
93+
94+
@PowerNukkitOnly
95+
@Since("1.4.0.0-PN")
96+
public boolean isTopHalf() {
97+
return getBooleanValue(UPPER_BLOCK);
98+
}
99+
100+
@PowerNukkitOnly
101+
@Since("1.4.0.0-PN")
102+
public void setTopHalf(boolean topHalf) {
103+
setBooleanValue(UPPER_BLOCK, topHalf);
104+
}
105+
50106
@Override
51107
public boolean canBeReplaced() {
52-
int damage = this.getDamage() & 0x7;
53-
return damage == TALL_GRASS || damage == LARGE_FERN;
108+
return getDoublePlantType().isReplaceable();
54109
}
55110

56111
@Override
57112
public String getName() {
58-
return NAMES[this.getDamage() > 5 ? 0 : this.getDamage()];
113+
return getDoublePlantType().getEnglishName();
59114
}
60115

61116
@PowerNukkitDifference(since = "1.4.0.0-PN", info = "Bottom part will break if the supporting block is invalid on normal update")
62117
@Override
63118
public int onUpdate(int type) {
64119
if (type == Level.BLOCK_UPDATE_NORMAL) {
65-
if ((this.getDamage() & TOP_HALF_BITMASK) == TOP_HALF_BITMASK) {
120+
if (isTopHalf()) {
66121
// Top
67122
if (this.down().getId() != DOUBLE_PLANT) {
68123
this.getLevel().setBlock(this, Block.get(BlockID.AIR), false, true);
@@ -84,8 +139,12 @@ public boolean place(@Nonnull Item item, @Nonnull Block block, @Nonnull Block ta
84139
Block up = up();
85140

86141
if (up.getId() == AIR && isSupportValid(down())) {
142+
setTopHalf(false);
87143
this.getLevel().setBlock(block, this, true, false); // If we update the bottom half, it will drop the item because there isn't a flower block above
88-
this.getLevel().setBlock(up, Block.get(BlockID.DOUBLE_PLANT, getDamage() ^ TOP_HALF_BITMASK), true, true);
144+
145+
setTopHalf(true);
146+
this.getLevel().setBlock(up, this, true, true);
147+
this.getLevel().updateAround(this);
89148
return true;
90149
}
91150

@@ -106,7 +165,7 @@ private boolean isSupportValid(Block support) {
106165
public boolean onBreak(Item item) {
107166
Block down = down();
108167

109-
if ((this.getDamage() & TOP_HALF_BITMASK) == TOP_HALF_BITMASK) { // Top half
168+
if (isTopHalf()) { // Top half
110169
this.getLevel().useBreakOn(down);
111170
} else {
112171
this.getLevel().setBlock(this, Block.get(BlockID.AIR), true, true);
@@ -117,38 +176,38 @@ public boolean onBreak(Item item) {
117176

118177
@Override
119178
public Item[] getDrops(Item item) {
120-
if ((this.getDamage() & TOP_HALF_BITMASK) != TOP_HALF_BITMASK) {
121-
switch (this.getDamage() & 0x07) {
122-
case TALL_GRASS:
123-
case LARGE_FERN:
124-
boolean dropSeeds = ThreadLocalRandom.current().nextInt(10) == 0;
125-
if (item.isShears()) {
126-
//todo enchantment
127-
if (dropSeeds) {
128-
return new Item[]{
129-
new ItemSeedsWheat(0, 1),
130-
toItem()
131-
};
132-
} else {
133-
return new Item[]{
134-
toItem()
135-
};
136-
}
137-
}
179+
if (isTopHalf()){
180+
return Item.EMPTY_ARRAY;
181+
}
138182

183+
switch (getDoublePlantType()) {
184+
case TALL_GRASS:
185+
case LARGE_FERN:
186+
boolean dropSeeds = ThreadLocalRandom.current().nextInt(10) == 0;
187+
if (item.isShears()) {
188+
//todo enchantment
139189
if (dropSeeds) {
140190
return new Item[]{
141-
new ItemSeedsWheat()
191+
Item.get(ItemID.WHEAT_SEEDS),
192+
toItem()
142193
};
143194
} else {
144-
return Item.EMPTY_ARRAY;
195+
return new Item[]{
196+
toItem()
197+
};
145198
}
146-
}
199+
}
147200

148-
return new Item[]{toItem()};
201+
if (dropSeeds) {
202+
return new Item[]{
203+
Item.get(ItemID.WHEAT_SEEDS)
204+
};
205+
} else {
206+
return Item.EMPTY_ARRAY;
207+
}
149208
}
150209

151-
return Item.EMPTY_ARRAY;
210+
return new Item[]{toItem()};
152211
}
153212

154213
@Override
@@ -164,7 +223,7 @@ public boolean canBeActivated() {
164223
@Override
165224
public boolean onActivate(@Nonnull Item item, Player player) {
166225
if (item.isFertilizer()) { //Bone meal
167-
switch (this.getDamage() & 0x07) {
226+
switch (getDoublePlantType()) {
168227
case SUNFLOWER:
169228
case LILAC:
170229
case ROSE_BUSH:

src/main/java/cn/nukkit/block/BlockTallGrass.java

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import cn.nukkit.Player;
44
import cn.nukkit.api.PowerNukkitDifference;
5+
import cn.nukkit.blockproperty.value.DoublePlantType;
56
import cn.nukkit.item.Item;
67
import cn.nukkit.item.ItemID;
78
import cn.nukkit.item.ItemTool;
@@ -92,29 +93,36 @@ public boolean onActivate(@Nonnull Item item, Player player) {
9293
Block up = this.up();
9394

9495
if (up.getId() == AIR) {
95-
int meta;
96+
DoublePlantType type;
9697

9798
switch (this.getDamage()) {
9899
case 0:
99100
case 1:
100-
meta = BlockDoublePlant.TALL_GRASS;
101+
type = DoublePlantType.TALL_GRASS;
101102
break;
102103
case 2:
103104
case 3:
104-
meta = BlockDoublePlant.LARGE_FERN;
105+
type = DoublePlantType.LARGE_FERN;
105106
break;
106107
default:
107-
meta = -1;
108+
type = null;
108109
}
109110

110-
if (meta != -1) {
111-
if (player != null && (player.gamemode & 0x01) == 0) {
111+
if (type != null) {
112+
if (player != null && !player.isCreative()) {
112113
item.count--;
113114
}
114115

116+
BlockDoublePlant doublePlant = (BlockDoublePlant) Block.get(BlockID.DOUBLE_PLANT);
117+
doublePlant.setDoublePlantType(type);
118+
doublePlant.setTopHalf(false);
119+
115120
this.level.addParticle(new BoneMealParticle(this));
116-
this.level.setBlock(this, get(DOUBLE_PLANT, meta), true, false);
117-
this.level.setBlock(up, get(DOUBLE_PLANT, meta ^ BlockDoublePlant.TOP_HALF_BITMASK), true);
121+
this.level.setBlock(this, doublePlant, true, false);
122+
123+
doublePlant.setTopHalf(true);
124+
this.level.setBlock(up, doublePlant, true);
125+
this.level.updateAround(this);
118126
}
119127
}
120128

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,72 @@
11
package cn.nukkit.blockproperty;
22

3+
import cn.nukkit.api.PowerNukkitOnly;
4+
import cn.nukkit.api.Since;
35
import cn.nukkit.block.Block;
46
import cn.nukkit.math.BlockFace;
57

8+
@PowerNukkitOnly
9+
@Since("1.4.0.0-PN")
610
public final class CommonBlockProperties {
11+
@PowerNukkitOnly
12+
@Since("1.4.0.0-PN")
713
public static final String LEGACY_PROPERTY_NAME = "nukkit-legacy";
814

15+
@PowerNukkitOnly
16+
@Since("1.4.0.0-PN")
917
public static final BlockProperties EMPTY_PROPERTIES = new BlockProperties();
18+
@PowerNukkitOnly
19+
@Since("1.4.0.0-PN")
1020
public static final BlockProperties LEGACY_PROPERTIES = new BlockProperties(new IntBlockProperty(LEGACY_PROPERTY_NAME, true, Block.DATA_MASK));
21+
@PowerNukkitOnly
22+
@Since("1.4.0.0-PN")
1123
public static final BlockProperties LEGACY_BIG_PROPERTIES = new BlockProperties(new UnsignedIntBlockProperty(LEGACY_PROPERTY_NAME, true, 0xFFFFFFFF));
1224

25+
@PowerNukkitOnly
26+
@Since("1.4.0.0-PN")
1327
public static final BooleanBlockProperty OPEN = new BooleanBlockProperty("open_bit", false);
28+
@PowerNukkitOnly
29+
@Since("1.4.0.0-PN")
1430
public static final BooleanBlockProperty TOGGLE = new BooleanBlockProperty("toggle_bit", false);
31+
@PowerNukkitOnly
32+
@Since("1.4.0.0-PN")
1533
public static final IntBlockProperty REDSTONE_SIGNAL = new IntBlockProperty("redstone_signal", false, 15);
34+
@PowerNukkitOnly
35+
@Since("1.4.0.0-PN")
36+
public static final BooleanBlockProperty UPPER_BLOCK = new BooleanBlockProperty("upper_block_bit", false);
1637

38+
@PowerNukkitOnly
39+
@Since("1.4.0.0-PN")
1740
public static final BlockProperty<BlockFace> FACING_DIRECTION = new ArrayBlockProperty<>("facing_direction", false, new BlockFace[] {
1841
// Index based
1942
BlockFace.DOWN, BlockFace.UP,
2043
BlockFace.NORTH, BlockFace.SOUTH,
2144
BlockFace.WEST, BlockFace.EAST,
2245
}).ordinal(true);
23-
46+
47+
@PowerNukkitOnly
48+
@Since("1.4.0.0-PN")
2449
public static final BlockProperty<BlockFace> DIRECTION = new ArrayBlockProperty<>("direction", false, new BlockFace[]{
2550
// Horizontal-index based
2651
BlockFace.SOUTH, BlockFace.WEST,
2752
BlockFace.NORTH, BlockFace.EAST,
2853
}).ordinal(true);
29-
54+
55+
@PowerNukkitOnly
56+
@Since("1.4.0.0-PN")
3057
public static final BlockProperty<BlockFace.Axis> PILLAR_AXIS = new ArrayBlockProperty<>("pillar_axis", false, new BlockFace.Axis[]{
3158
BlockFace.Axis.Y, BlockFace.Axis.X, BlockFace.Axis.Z
3259
});
33-
60+
61+
@PowerNukkitOnly
62+
@Since("1.4.0.0-PN")
3463
public static final IntBlockProperty DEPRECATED = new IntBlockProperty("deprecated", false, 3);
3564

3665
private CommonBlockProperties() {
3766
throw new UnsupportedOperationException("This is a utility class and cannot be instantiated");
3867
}
39-
68+
69+
@PowerNukkitOnly
70+
@Since("1.4.0.0-PN")
4071
public static final BooleanBlockProperty POWERED = new BooleanBlockProperty("powered_bit", false);
4172
}

0 commit comments

Comments
 (0)