墙面标识

基本信息

属性 值
实现类 modernmarkings.blocks.MarkingWall(继承 BlockBase)
方块数 83
注册位置 modernmarkings.init.ModBlocks 的 new MarkingWall(...) 静态字段
材质 Material.carpet
碰撞 无(getCollisionBoundingBoxFromPool 返回全 0 包围盒)
厚度 0.01(setBlockBoundsBasedOnState)
渲染 自定义 ISimpleBlockRendering(renderMarkingWallID)
参考实现 注释指明参照原版 BlockSign 的贴附逻辑

83 个方块涵盖工厂安全标识:电压等级牌、危险符号、编号、方向箭头、字母。

分类统计

类别 数量 成员示例
字母 A–Z 26 wall_marking_letter_a … wall_marking_letter_z
电压等级 18 voltage_eu / voltage_ev / voltage_fe / voltage_hv / voltage_iv / voltage_luv / voltage_lv / voltage_max / voltage_mv / voltage_pert / voltage_rf / voltage_uev / voltage_uhv / voltage_uiv / voltage_umv / voltage_uv / voltage_uxv / voltage_zpm
数字 15 number_0 … number_9 + number_no / number_numero / number_dash / number_comma / number_period
危险符号 14 symbol_chemical / symbol_electric / symbol_fire / symbol_fluid / symbol_frost / symbol_gears / symbol_laser / symbol_magic / symbol_mob / symbol_pinch / symbol_production / symbol_radiation / symbol_radiation_2 / symbol_storage
危险线 2 hazardline_left / hazardline_right
出口 1 wall_marking_exit
单位牌 1 unit
急救 1 first_aid
灭火器 1 fire_extinguisher
警告 1 warning_danger
箭头 2 arrowleft / arrowright
菱形危险 1 hazard_diamond

合计 83。

[!NOTE] 18 个电压等级覆盖 GT 电力体系的 EU 到 ZPM 全套(voltage_luv 是 LuV 而非 voltage_lv 的误写——两者都存在,luv 是小写 u 的正确拼写)。

放置:只能贴侧壁

onBlockPlaced 显式拒绝上下表面:

if (side != 0 && side != 1) {   // 0 = DOWN, 1 = UP
    return side;
}
return getDirectionFromPlacedPlayer(world, x, y, z);

即点顶面/底面时直接返回原 side(放置失败),只有 4 个侧面才继续。方向不看点击的面,而是用最近玩家的朝向决定贴附哪一面:

getDirectionFromPlacedPlayer 取 world.getClosestPlayer(x, y, z, -1),把 rotationYaw 折成 4 个 rotation,返回值直接是 ForgeDirection 的序号:2 = 北、3 = 南、4 = 西、5 = 东。

[!WARNING] 源码缺陷 MarkingWall.java:44-45 的 getClosestPlayer(x, y, z, -1) 可能返回 null(半径 -1 表示不限距离,周围 7×7×7 无玩家时即为 null),紧接着 player.rotationYaw 会抛 NullPointerException。该方法被 onBlockPlaced(第 40 行)和 canPlaceBlockAt(第 150 行)调用,两处都没有做 null 检查。实际触发需要在无玩家的位置对方块交互。

canPlaceBlockAt 随后校验目标那一面确实是实心的:world.isSideSolid(x + dir.offsetX, y, z + dir.offsetZ, dir, false)。

元数据与包围盒

setBlockBoundsBasedOnState 按 meta 把方块压成 0.01 厚的薄片,紧贴对应墙面:

meta 朝向 min/max
2 北 z ∈ [1 - 0.01, 1]
3 南 z ∈ [0, 0.01]
4 西 x ∈ [1 - 0.01, 1]
5 东 x ∈ [0, 0.01]
其它 兜底 整格 0,0,0 – 1,1,1

getSelectedBoundingBoxFromPool 读世界元数据返回同样的薄片 AABB,让选中框也跟着贴到墙上。

依赖方块变化:正反面不对称

onNeighborBlockChange 判定支撑时多了 .getOpposite():

ForgeDirection dir = ForgeDirection.getOrientation(meta).getOpposite();

而 canPlaceBlockAt 用的是不带 getOpposite 的方向。源码里作者自己留了注释:

// I have no idea why .getOpposite is required here when it's not in canPlaceBlockAt, but it works like this

结果是:放置时校验的是正面所依附的墙是否实心,拆除时校验的却是背面的墙。两侧的判定条件并不一致。

判定失败时同样 setBlockToAir + dropBlockAsItem,即标识掉落为物品并消失。

相关条目