Skip to content

Commit 4d321df

Browse files
authored
Merge pull request #13 from PowerNukkitX/master
pnx
2 parents 9d78d70 + 857bb4a commit 4d321df

File tree

6 files changed

+131
-24
lines changed

6 files changed

+131
-24
lines changed

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

Lines changed: 44 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -381,17 +381,19 @@ public boolean canBeReplaced() {
381381
public boolean hasFreeSpaceAbove() {
382382
Block above = this.up();
383383

384-
if (above.isAir()) {
384+
if (above instanceof BlockSlab slab) {
385+
return slab.isOnTop();
386+
}
387+
388+
if (above.isTransparent()) {
385389
return true;
386390
}
387391

388392
AxisAlignedBB box = above.getCollisionBoundingBox();
389393
if (box != null) {
390394
double minY = box.getMinY();
391395
double relativeMinY = minY - above.getY();
392-
boolean allowed = relativeMinY >= 0.5;
393-
394-
return allowed;
396+
return relativeMinY >= 0.5;
395397
}
396398

397399
return false;
@@ -593,10 +595,48 @@ public BlockState getBlockState() {
593595
return blockstate;
594596
}
595597

598+
/**
599+
* @deprecated Use {@link #hasTag(String)} instead.
600+
*/
601+
@Deprecated
596602
public boolean is(final String blockTag) {
597603
return BlockTags.getTagSet(this.getId()).contains(blockTag);
598604
}
599605

606+
/**
607+
* @return if block has a string tag
608+
*/
609+
public boolean hasTag(final String blockTag) {
610+
CustomBlockDefinition def = getCustomDefinition();
611+
if (def != null) {
612+
CompoundTag nbt = def.nbt();
613+
if (nbt.contains("blockTags")) {
614+
ListTag<StringTag> tagList = nbt.getList("blockTags", StringTag.class);
615+
return tagList.getAll().contains(new StringTag(blockTag));
616+
}
617+
}
618+
619+
return BlockTags.getTagSet(this.getId()).contains(blockTag);
620+
}
621+
622+
/**
623+
* @return list of tags for the block
624+
*/
625+
public String[] getTags() {
626+
CustomBlockDefinition def = getCustomDefinition();
627+
if (def != null) {
628+
CompoundTag nbt = def.nbt();
629+
if (nbt.contains("blockTags")) {
630+
ListTag<StringTag> tagList = nbt.getList("blockTags", StringTag.class);
631+
return tagList.getAll().stream()
632+
.map(tag -> tag.data)
633+
.toArray(String[]::new);
634+
}
635+
}
636+
637+
return BlockTags.getTagSet(this.getId()).toArray(new String[0]);
638+
}
639+
600640
public <DATATYPE, PROPERTY extends BlockPropertyType<DATATYPE>> DATATYPE getPropertyValue(PROPERTY p) {
601641
return blockstate.getPropertyValue(p);
602642
}

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

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -211,15 +211,28 @@ public boolean onBreak(Item item) {
211211

212212
@Override
213213
public boolean onActivate(@NotNull Item item, Player player, BlockFace blockFace, float fx, float fy, float fz) {
214-
if(isNotActivate(player)) return false;
214+
if (isNotActivate(player)) return false;
215215
Item itemInHand = player.getInventory().getItemInHand();
216216
if (player.isSneaking() && !(itemInHand.isTool() || itemInHand.isNull())) return false;
217217

218+
// Check itself if can be opened
218219
if (!this.hasFreeSpaceAbove()) {
219220
return false;
220221
}
221222

222223
BlockEntityChest chest = getOrCreateBlockEntity();
224+
225+
// If paired, check if the pair can be opened
226+
if (chest.isPaired()) {
227+
BlockEntityChest pair = chest.getPair();
228+
if (pair != null) {
229+
Block pairedBlock = pair.getBlock();
230+
if (!pairedBlock.hasFreeSpaceAbove()) {
231+
return false;
232+
}
233+
}
234+
}
235+
223236
if (chest.namedTag.contains("Lock") && chest.namedTag.get("Lock") instanceof StringTag
224237
&& !chest.namedTag.getString("Lock").equals(item.getCustomName())) {
225238
return false;

src/main/java/cn/nukkit/inventory/fake/FakeInventory.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,15 @@
2929
import java.util.List;
3030
import java.util.Map;
3131
import java.util.Optional;
32+
import java.util.function.Consumer;
3233

3334
public class FakeInventory extends BaseInventory implements InputInventory {
3435
private final Map<Integer, ItemHandler> handlers = new HashMap<>();
3536
private final FakeBlock fakeBlock;
3637
private final FakeInventoryType fakeInventoryType;
3738
private String title;
3839
private ItemHandler defaultItemHandler;
40+
private Consumer<Player> onCloseHandler;
3941

4042
public FakeInventory(FakeInventoryType fakeInventoryType) {
4143
this(fakeInventoryType, fakeInventoryType.name());
@@ -135,6 +137,10 @@ public void onClose(Player player) {
135137
}, 5);
136138
super.onClose(player);
137139
player.setFakeInventoryOpen(false);
140+
141+
if (this.onCloseHandler != null) {
142+
this.onCloseHandler.accept(player);
143+
}
138144
}
139145

140146
public String getTitle() {
@@ -153,6 +159,10 @@ public void setDefaultItemHandler(ItemHandler defaultItemHandler) {
153159
this.defaultItemHandler = defaultItemHandler;
154160
}
155161

162+
public void setOnCloseHandler(Consumer<Player> onCloseHandler) {
163+
this.onCloseHandler = onCloseHandler;
164+
}
165+
156166
@ApiStatus.Internal
157167
public void handle(ItemStackRequestActionEvent event) {
158168
ItemStackRequestAction action = event.getAction();

src/main/java/cn/nukkit/item/customitem/CustomItemDefinition.java

Lines changed: 34 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -327,17 +327,19 @@ public SimpleBuilder useModifiers(float movementModifier, float useDuration) {
327327
*/
328328
public SimpleBuilder blockPlacer(String blockId, String... useOn) {
329329
ListTag<CompoundTag> useOnList = new ListTag<>();
330-
for (String s : useOn) {
331-
useOnList.add(new CompoundTag()
330+
if (useOn != null && useOn.length > 0) {
331+
for (String s : useOn) {
332+
useOnList.add(new CompoundTag()
332333
.putString("name", s)
333334
.putCompound("states", new CompoundTag())
334335
.putString("tags", ""));
336+
}
335337
}
336338

337339
CompoundTag blockPlacer = new CompoundTag()
338-
.putString("block", blockId)
339-
.putBoolean("canUseBlockAsIcon", true)
340-
.putList("use_on", useOnList);
340+
.putString("block", blockId)
341+
.putBoolean("canUseBlockAsIcon", true)
342+
.putList("use_on", useOnList);
341343

342344
CompoundTag components = nbt.getCompound("components");
343345
if (!nbt.contains("components")) {
@@ -373,7 +375,7 @@ protected CustomItemDefinition calculateID() {
373375
CompoundTag components = nbt.getCompound("components");
374376
CompoundTag itemProps = ensureItemProperties();
375377

376-
if (texture != null && !texture.isBlank() && !components.contains("minecraft:block_placer")) {
378+
if (texture != null && !texture.isBlank()) {
377379
itemProps.putCompound("minecraft:icon", new CompoundTag()
378380
.putCompound("textures", new CompoundTag().putString("default", texture)));
379381
}
@@ -851,6 +853,32 @@ private EdibleBuilder(ItemCustomFood item) {
851853
}
852854
}
853855

856+
public record BlockPlacerData(String blockId, List<String> useOn) {}
857+
@Nullable
858+
public BlockPlacerData getBlockPlacerData() {
859+
CompoundTag components = nbt.getCompound("components");
860+
if (!components.contains("minecraft:block_placer")) {
861+
return null;
862+
}
863+
864+
CompoundTag placer = components.getCompound("minecraft:block_placer");
865+
String blockId = placer.getString("block");
866+
List<String> useOnList = new ArrayList<>();
867+
868+
ListTag<CompoundTag> useOnTag = placer.getList("use_on", CompoundTag.class);
869+
if (useOnTag != null && useOnTag.size() > 0) {
870+
for (int i = 0; i < useOnTag.size(); i++) {
871+
CompoundTag entry = useOnTag.get(i);
872+
String useOnName = entry.getString("name");
873+
if (!useOnName.isEmpty()) {
874+
useOnList.add(useOnName);
875+
}
876+
}
877+
}
878+
879+
return new BlockPlacerData(blockId, useOnList);
880+
}
881+
854882
// HELPER FUNCTION TO TROUBLESHOOTING THE ITEM NBT FORMAT
855883
public CompoundTag getNbt() {
856884
return this.nbt;
Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
package cn.nukkit.item.customitem;
22

3+
import cn.nukkit.block.Block;
34
import cn.nukkit.item.Item;
5+
import cn.nukkit.item.customitem.CustomItemDefinition.BlockPlacerData;
6+
7+
import javax.annotation.Nullable;
48
import org.jetbrains.annotations.NotNull;
59

610

711
/**
8-
* 继承这个类实现自定义物品,重写{@link Item}中的方法控制方块属性
9-
* <p>
1012
* Inherit this class to implement a custom item, override the methods in the {@link Item} to control the feature of the item.
1113
*
1214
* @author lt_name
@@ -17,8 +19,6 @@ public ItemCustom(@NotNull String id) {
1719
}
1820

1921
/**
20-
* 该方法设置自定义物品的定义
21-
* <p>
2222
* This method sets the definition of custom item
2323
*/
2424
public abstract CustomItemDefinition getDefinition();
@@ -27,4 +27,10 @@ public ItemCustom(@NotNull String id) {
2727
public ItemCustom clone() {
2828
return (ItemCustom) super.clone();
2929
}
30+
31+
@Nullable
32+
public Block getBlockPlacerTargetBlock() {
33+
BlockPlacerData data = this.getDefinition().getBlockPlacerData();
34+
return data != null ? Block.get(data.blockId()) : null;
35+
}
3036
}

src/main/java/cn/nukkit/level/Level.java

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
import cn.nukkit.inventory.BlockInventoryHolder;
3737
import cn.nukkit.item.Item;
3838
import cn.nukkit.item.ItemBucket;
39+
import cn.nukkit.item.customitem.ItemCustom;
3940
import cn.nukkit.item.enchantment.Enchantment;
4041
import cn.nukkit.level.format.ChunkSection;
4142
import cn.nukkit.level.format.ChunkState;
@@ -2814,33 +2815,42 @@ public Item useItemOn(Vector3 vector, Item item, BlockFace face, UseItemData dat
28142815

28152816
private Block beforePlaceBlock(Item item, BlockFace face, float fx, float fy, float fz, Player player, boolean playSound, Block block, Block target) {
28162817
Block hand;
2818+
28172819
if (item.canBePlaced()) {
28182820
hand = item.getBlock();
28192821
hand.position(block);
2822+
} else if (item instanceof ItemCustom customItem) {
2823+
Block blockToPlace = customItem.getBlockPlacerTargetBlock();
2824+
if (blockToPlace == null || blockToPlace.isAir()) return null;
2825+
hand = blockToPlace;
2826+
hand.position(block);
28202827
} else {
28212828
return null;
28222829
}
2823-
if (
2824-
!(block.canBeReplaced() ||
2825-
(hand instanceof BlockSlab && hand.getId().equals(block.getId())) ||
2826-
hand instanceof BlockCandle//Special for candles
2827-
)
2828-
) {
2830+
2831+
// Check for valid placement conditions
2832+
if (!(block.canBeReplaced() ||
2833+
(hand instanceof BlockSlab && hand.getId().equals(block.getId())) ||
2834+
hand instanceof BlockCandle)) {
28292835
return null;
28302836
}
28312837

2832-
//处理放置梯子,我们应该提前给hand设置方向,这样后面计算是否碰撞实体才准确
2838+
// To place the ladder, we should set the direction of the hand in advance so that the calculation of whether it
2839+
// collides with the entity can be accurate.
28332840
if (hand instanceof BlockLadder) {
28342841
if (target instanceof BlockLadder) {
28352842
hand.setPropertyValue(CommonBlockProperties.FACING_DIRECTION, face.getOpposite().getIndex());
2836-
} else hand.setPropertyValue(CommonBlockProperties.FACING_DIRECTION, face.getIndex());
2843+
} else {
2844+
hand.setPropertyValue(CommonBlockProperties.FACING_DIRECTION, face.getIndex());
2845+
}
28372846
}
28382847

2839-
//cause bug (eg: frog_spawn) (and I don't know what this is for)
2848+
// cause bug (eg: frog_spawn) (and I don't know what this is for)
28402849
if (!(hand instanceof BlockFrogSpawn) && target.canBeReplaced()) {
28412850
block = target;
28422851
hand.position(block);
28432852
}
2853+
28442854
return hand;
28452855
}
28462856

0 commit comments

Comments
 (0)