Sign-Post

路牌方块(注册名 signposts:signPost)。放置后高 2 格,下半格存储传送目标坐标,上半格只负责视觉。配合 魔法路牌标记 刻写铭文后,会作为 signPost 类型的全局标记出现在 Antique Atlas 中,点击即可传送。

基本信息

属性 值
注册名 signposts:signPost
内部名 signPost(GameRegistry.registerBlock(signPostBlock, "signPost"))
材质 Material.plants
TileEntity SignPostTileEntity(注册名 signPostTileEntity)
硬度 2.0
爆炸抗性 6.0
挖掘等级 2,工具 axe
脚步声 Block.soundTypeWood
碰撞箱 0.4, 0, 0.4 ~ 0.6, 1, 0.6
亮度 0(未调用 setLightLevel)
方块容器 isBlockContainer = true
物品形态 无(见下方「方块形态」)

合成配方

矿石字典配方(ShapedOreRecipe):

   .WS      W = 任意 plankWood(任意木材木板)
   .WS      S = 原版告示牌
   .W.

即 2 任意木板 + 1 告示牌竖排,产出 1 个路牌。plankWood 走 ore dict,因此所有原版木板变种都可用。

metadata / 方块状态

只有 5 个 metadata 值,语义分为两类:

meta 含义 isBottom 由谁设置
0 下半格,面朝南(realY -= 0.13,旋转 180°) true onBlockPlacedBy
1 下半格,面朝东(realX -= 0.13,旋转 90°) true onBlockPlacedBy
2 下半格,面朝北(realY += 0.13,旋转 0°) true onBlockPlacedBy
3 下半格,面朝西(realX += 0.13,旋转 270°) true onBlockPlacedBy
4 上半格(自动生成),无渲染 false onBlockPlaced

朝向换算在 onBlockPlacedBy 中由放置者 yaw 计算:rotation = floor(placer.rotationYaw * 4.0F / 360.0F + 0.5) & 3,再经 switch 映射 0→meta 2、1→meta 3、2→meta 0、3→meta 1,最后 setBlockMetadataWithNotify(..., 2)。

摆放要求

  • canPlaceBlockAt:当前位置与 y+1 位置都必须是 isReplaceable,因此只能贴地或贴已有可替换方块。
  • onBlockPlaced:放置下半格时自动在 y+1 写一个 meta 4 的同种方块(flags = 2,触发客户端更新),所以任何时候都是 2 格高。
  • onBlockPlaced 开头 if (meta >= 4) return 4; —— meta 4(即上半格)被再次放置时直接返回 4,不会再往上叠第三格,形成高度上限 2。

交互

全部逻辑包在 world.isRemote 内(纯客户端),onBlockActivated 恒返回 false:

手持 / 状态 行为
手持 魔法路牌标记 且 markerId == 0 打开铭文输入界面(proxy.openSignPostLabelGui),跳转坐标固定为「玩家当前 X / floor(posY - 1) / 玩家当前 Z」
手持魔法路牌标记且 markerId != 0 什么也不做(return false)
手持 Antique Atlas 若 markerId != 0,打开地图界面,支付处理器键为 signposts
快捷栏(槽位 8→1)存在 Atlas 且 markerId != 0 同上;注意循环为 for (int j = 8; j > 0; j--),跳过槽位 0
上述条件都不满足 无反应

破坏行为(breakBlock)

if (meta == 4) {
  world.setBlockToAir(x, y - 1, z);   // 拆上半格 → 连带拆掉下半格
} else {
  SignPostsMod.removeJumpTarget(x, y, z, world);  // 删除全局标记 + 映射
  world.setBlockToAir(x, y + 1, z);   // 拆下半格 → 连带拆掉上半格
}
world.removeTileEntity(x, y, z);

所以拆任一半都会连带拆掉另一半;拆下半格时才会清除 Atlas 标记。

方块形态

源码中没有 ItemBlock、getDrops、LootTable 或 dropItem 的任何实现(已 grep 确认),GameRegistry.registerBlock 也没有传 ItemBlock。因此:

  • 路牌没有物品形态,不能放进背包或物品栏;
  • 破坏时不掉落任何东西;
  • 无法被 /give 或创意模式物品栏取用,只能靠 ShapedOreRecipe 合成后直接放置。

NBT 字段(SignPostTileEntity)

字段 类型 写入条件 含义
isBottom boolean 总是 是否为下半格(= meta != 4)
jumpX double 仅 isBottom == true 传送目标 X(玩家坐标,浮点)
jumpY double 仅 isBottom == true 传送目标 Y
jumpZ double 仅 isBottom == true 传送目标 Z
markerId int 仅 isBottom == true 对应的 Antique Atlas 全局标记 ID,0 表示未刻写

写入位置:setAsJumpLocation(x, y, z, markerId) 先通过 getBottom() 定位到下半格写入四个字段,再 worldObj.markBlockForUpdate(...)。上半格的 getJumpX/Y/Z()、getMarkerId() 全部委托给 getBottom(),后者在 isBottom == false 时取 worldObj.getTileEntity(xCoord, yCoord - 1, zCoord)。

同步走原版 S35PacketUpdateTileEntity(getDescriptionPacket 用 action id 1 + 完整 NBT,onDataPacket 反过来 readFromNBT)。

⚠️ public String text 字段是唯一不参与 NBT 的数据:源码里没有任何 data.setString("text", ...),因此它纯客户端、不随存档与区块同步,也不会在标记被改名后更新。

贴图与渲染

  • 方块贴图 signposts:sign_post_top,getIcon 对侧面(side > 1)返回 Blocks.log.getIcon(side, 0),即侧面看起来像原版木头、顶底面用本模组贴图。
  • 文字渲染由 SignPostRenderer extends TileEntitySignRenderer 负责,getRenderType() 返回 0(普通模型)。
  • 渲染时 meta >= 4 直接 return(上半格不渲染文字),下半格按 meta 做 0.13 的水平/垂直偏移并旋转 0/90/180/270°。
  • 缩放常量 scale = 0.6666667F,用 ModelSign 并隐藏 signStick,绑定原版 textures/entity/sign.png。
  • 文字取自 Atlas 标记而非 NBT:当 signTe.text == null 且 markerId != 0 时,用 AntiqueAtlasMod.globalMarkersData.getData().getMarkerByID(id) 取 marker.getLocalizedLabel() 赋给 signTe.text;只有 text != null 的分支才真正调用 FontRenderer.drawString。因此新刻写的路牌要等下一次渲染才显示文字。

相关条目