Skip to content

Commit

Permalink
fix: customblock and item
Browse files Browse the repository at this point in the history
  • Loading branch information
CoolLoong committed Feb 11, 2024
1 parent 409d6ed commit c0c2183
Show file tree
Hide file tree
Showing 5 changed files with 78 additions and 70 deletions.
17 changes: 7 additions & 10 deletions src/main/java/cn/nukkit/block/Block.java
Original file line number Diff line number Diff line change
Expand Up @@ -1288,10 +1288,6 @@ public static void registerBlockImplementation(int blockId, @NotNull Class<? ext
Level.setCanRandomTick(blockId, receivesRandomTick);
}

//自定义方块id从1000开始,按照FNV1 64bit计算hash值升序排序
@PowerNukkitXOnly
private static int nextBlockId = 1000;

@PowerNukkitXOnly
@Since("1.19.62-r1")
private final static SortedMap<String, CustomBlock> SORTED_CUSTOM_BLOCK = new TreeMap<>(MinecraftNamespaceComparator::compareFNV);
Expand Down Expand Up @@ -1354,19 +1350,19 @@ public static OK<?> registerCustomBlock(@NotNull Map<String, Class<? extends Cus
public static void initCustomBlock() {
if (!SORTED_CUSTOM_BLOCK.isEmpty()) {
for (var entry : SORTED_CUSTOM_BLOCK.entrySet()) {
CUSTOM_BLOCK_ID_MAP.put(entry.getKey(), nextBlockId);//自定义方块标识符->自定义方块id
ID_TO_CUSTOM_BLOCK.put(nextBlockId, entry.getValue());//自定义方块id->自定义方块
int runtimeId = CustomBlockDefinition.getRuntimeId(entry.getKey());
CUSTOM_BLOCK_ID_MAP.put(entry.getKey(), runtimeId);//自定义方块标识符->自定义方块id
ID_TO_CUSTOM_BLOCK.put(runtimeId, entry.getValue());//自定义方块id->自定义方块
CUSTOM_BLOCK_DEFINITIONS.add(entry.getValue().getDefinition());//行为包数据
++nextBlockId;
}
var blocks = ID_TO_CUSTOM_BLOCK.values().stream().toList();
var result = BlockStateRegistry.registerCustomBlockState(blocks);//注册方块state
if (!result.ok()) {
throw new CustomBlockStateRegisterException("Register CustomBlock state error, please check all your CustomBlock plugins,contact the plugin author! Error:", result.getError());
}
RuntimeItems.getRuntimeMapping().registerCustomBlock(blocks);//注册物品
blocks.stream().filter( CustomBlock::shouldBeRegisteredInCreative ).forEach(
b -> Item.addCreativeItem(b.toItem())
blocks.stream().filter(CustomBlock::shouldBeRegisteredInCreative).forEach(
b -> Item.addCreativeItem(b.toItem())
);//注册创造栏物品
}
}
Expand All @@ -1383,7 +1379,7 @@ public static void deleteAllCustomBlock() {
ID_TO_CUSTOM_BLOCK.clear();
CUSTOM_BLOCK_ID_MAP.clear();
CUSTOM_BLOCK_DEFINITIONS.clear();
nextBlockId = 1000;
CustomBlockDefinition.deleteAllCustomBlock();
}

@PowerNukkitXOnly
Expand Down Expand Up @@ -3080,6 +3076,7 @@ public int hashCode() {
public long computeUnsignedBlockStateHash() {
return Integer.toUnsignedLong(computeBlockStateHash());
}

@PowerNukkitXOnly
@Since("1.20.10-r2")
public boolean isFertilizable() {
Expand Down
7 changes: 2 additions & 5 deletions src/main/java/cn/nukkit/block/customblock/CustomBlock.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,9 @@
@Since("1.6.0.0-PNX")
public interface CustomBlock {
/**
* 覆写该方法设置自定义方块的摩擦因数。<br>
* 警告:如果你想要让玩家在你的自定义方块上的摩擦不同,请覆写{@link CustomBlockDefinition.Builder#clientFriction(float)}方法。
* 覆写该方法设置自定义方块的摩擦因数。
* <p>
* {@code @Override} this method to set the friction factor of the custom block.<br>
* Warning: If you want to make the friction of the player on your custom block different,
* please override the {@link CustomBlockDefinition.Builder#clientFriction(float)} method.
* {@code @Override} this method to set the friction factor of the custom block.
*/
double getFrictionFactor();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,14 @@
import cn.nukkit.math.Vector3f;
import cn.nukkit.nbt.tag.*;
import com.google.common.base.Preconditions;
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Locale;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Consumer;

/**
Expand All @@ -26,7 +28,20 @@
@PowerNukkitXOnly
@Since("1.19.31-r1")
public record CustomBlockDefinition(String identifier, CompoundTag nbt) {
private static final Object2IntOpenHashMap<String> INTERNAL_ALLOCATION_ID_MAP = new Object2IntOpenHashMap<>();
private static final AtomicInteger CUSTOM_BLOCK_RUNTIMEID = new AtomicInteger(10000);

public int getRuntimeId() {
return CustomBlockDefinition.INTERNAL_ALLOCATION_ID_MAP.getInt(identifier);
}

public static int getRuntimeId(String identifier) {
return CustomBlockDefinition.INTERNAL_ALLOCATION_ID_MAP.getInt(identifier);
}

public static void deleteAllCustomBlock() {
CustomBlockDefinition.INTERNAL_ALLOCATION_ID_MAP.clear();
}

public static CustomBlockDefinition.Builder builder(CustomBlock customBlock, String texture) {
return builder(customBlock, Materials.builder().any(Materials.RenderMethod.OPAQUE, texture), BlockCreativeCategory.CONSTRUCTION);
Expand Down Expand Up @@ -62,12 +77,12 @@ public static class Builder {
protected Builder(CustomBlock customBlock, Materials materials, BlockCreativeCategory blockCreativeCategory) {
this.identifier = customBlock.getNamespaceId();
this.customBlock = customBlock;

var b = (Block) customBlock;
var components = this.nbt.getCompound("components");

//设置一些与PNX内部对应的方块属性
components.putCompound("minecraft:friction", new CompoundTag()
.putFloat("value", (float) (1 - Block.DEFAULT_FRICTION_FACTOR)))
.putFloat("value", (float) Math.min(0.9, Math.max(0, b.getFrictionFactor()))))
.putCompound("minecraft:destructible_by_explosion", new CompoundTag()
.putInt("explosion_resistance", (int) customBlock.getResistance()))
.putCompound("minecraft:light_dampening", new CompoundTag()
Expand All @@ -79,22 +94,40 @@ protected Builder(CustomBlock customBlock, Materials materials, BlockCreativeCat
//设置材质
components.putCompound("minecraft:material_instances", new CompoundTag()
.putCompound("mappings", new CompoundTag())
.putCompound("materials", materials.toCompoundTag()));
.putCompound("materials", new CompoundTag()));

//默认单位立方体方块
components.putCompound("minecraft:unit_cube", new CompoundTag());
//设置默认单位立方体方块的几何模型
components.putCompound("minecraft:geometry", new CompoundTag()
.putString("identifier", "minecraft:geometry.full_block")
.putString("culling", "")
.putCompound("bone_visibility", new CompoundTag())
);

//设置方块在创造栏的分类
this.nbt.putCompound("menu_category", new CompoundTag()
.putString("category", blockCreativeCategory.name().toLowerCase(Locale.ENGLISH))
.putString("group", ItemCreativeGroup.NONE.getGroupName()));
//molang版本
this.nbt.putInt("molangVersion", 6);
this.nbt.putInt("molangVersion", 9);

//设置方块的properties
var propertiesNBT = getPropertiesNBT();
if (propertiesNBT != null) {
propertiesNBT.setName("properties");
nbt.putList(propertiesNBT);
nbt.putList("properties", propertiesNBT);
}

int block_id;
if (!INTERNAL_ALLOCATION_ID_MAP.containsKey(identifier)) {
while (INTERNAL_ALLOCATION_ID_MAP.containsValue(block_id = CUSTOM_BLOCK_RUNTIMEID.getAndIncrement())) {
}
INTERNAL_ALLOCATION_ID_MAP.put(identifier, block_id);
} else {
block_id = INTERNAL_ALLOCATION_ID_MAP.getInt(identifier);
}
nbt.putCompound("vanilla_block_data", new CompoundTag().putInt("block_id", block_id)
/*.putString("material", "")*/); //todo Figure what is dirt, maybe that corresponds to https://wiki.bedrock.dev/documentation/materials.html
}

/**
Expand Down Expand Up @@ -282,19 +315,6 @@ public Builder blockTags(String... tag) {
return this;
}

/**
* 客户端摩擦系数,用于控制玩家在自定义方块上行走的速度,值越大,移动越快。
* <p>
* the client friction, which is used to control the speed at which the player walks on the custom block.The larger the value, the faster the movement.
*/
@Since("1.20.0-r2")
public Builder clientFriction(float friction) {
this.nbt.getCompound("components")
.putCompound("minecraft:friction", new CompoundTag()
.putFloat("value", friction));
return this;
}

/**
* PNX无法准确提供三个以上属性方块的属性解析,如果出现地图异常,请制作一个该方块相同属性的行为包,利用proxypass和bds抓包获取准确的属性解析。
* <p>
Expand All @@ -318,8 +338,8 @@ private ListTag<CompoundTag> getPropertiesNBT() {
if (each.getProperty() instanceof BooleanBlockProperty booleanBlockProperty) {
nbtList.add(new CompoundTag().putString("name", booleanBlockProperty.getName())
.putList(new ListTag<>("enum")
.add(new IntTag("", 0))
.add(new IntTag("", 1))));
.add(new ByteTag("", 0))
.add(new ByteTag("", 1))));
} else if (each.getProperty() instanceof IntBlockProperty intBlockProperty) {
var enumList = new ListTag<IntTag>("enum");
for (int i = intBlockProperty.getMinValue(); i <= intBlockProperty.getMaxValue(); i++) {
Expand All @@ -344,8 +364,8 @@ private ListTag<CompoundTag> getPropertiesNBT() {
} else {
nbtList.add(new CompoundTag().putString("name", arrayBlockProperty.getName())
.putList(new ListTag<>("enum")
.add(new IntTag("", 0))
.add(new IntTag("", 1))));
.add(new ByteTag("", 0))
.add(new ByteTag("", 1))));
}
} else {
var enumList = new ListTag<StringTag>("enum");
Expand Down
21 changes: 15 additions & 6 deletions src/main/java/cn/nukkit/block/customblock/data/Geometry.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
@Since("1.19.80-r1")
public class Geometry implements NBTData {
private final String geometryName;
private String culling = "";
private final Map<String, String> boneVisibilities = new LinkedHashMap<>();

public Geometry(@NotNull String name) {
Expand All @@ -29,7 +30,7 @@ public Geometry(@NotNull String name) {
public Geometry boneVisibility(@NotNull String boneName, boolean isVisibility) {
Preconditions.checkNotNull(boneName);
Preconditions.checkArgument(!boneName.isBlank());
this.boneVisibilities.put(boneName, isVisibility ? "true" : "false");
this.boneVisibilities.put(boneName, isVisibility ? "1.000000" : "0.000000");
return this;
}

Expand All @@ -45,18 +46,26 @@ public Geometry boneVisibility(@NotNull String boneName, String condition) {
return this;
}

public Geometry culling(@NotNull String cullingName) {
Preconditions.checkNotNull(cullingName);
this.culling = cullingName;
return this;
}


@Override
public CompoundTag toCompoundTag() {
var boneVisibility = new CompoundTag();
for (var entry : boneVisibilities.entrySet()) {
boneVisibility.putString(entry.getKey(), entry.getValue());
boneVisibility.putCompound(entry.getKey(), new CompoundTag()
.putString("expression", entry.getValue())
.putInt("version", 1)
);
}
CompoundTag compoundTag = new CompoundTag("minecraft:geometry")
CompoundTag compoundTag = new CompoundTag()
.putString("identifier", geometryName)
.putByte("legacyBlockLightAbsorption", 0)
.putByte("legacyTopRotation", 0);
if (boneVisibilities.size() > 0) {
.putString("culling", culling);
if (!boneVisibilities.isEmpty()) {
compoundTag.putCompound("bone_visibility", boneVisibility);
}
return compoundTag;
Expand Down
Loading

0 comments on commit c0c2183

Please sign in to comment.