睡袋(Sleeping Bag)

基本信息

属性 值
类 ru.npo6ka.sleepingbag.items.ItemSleepingBag
modid sleepingbag
注册名 sleepingbag:sleepingBag(GameRegistry.registerItem(sleepingBagItem, "sleepingBag"))
本地化键 item.sleepingBag.name → 英文 Sleeping Bag / 俄文 Спальный мешок
物品贴图 assets/sleepingbag/textures/items/sleeping_bag.png
最大堆叠 1(setMaxStackSize(1))
耐久度 无(源码未调用 setMaxDamage/setUndamageable,也不会损毁)
附魔适用 否(推断:源码未覆写 getItemEnchantability() / isValidEnchant(),沿用原版 Item 默认值 0)
创造标签 CreativeTabs.tabDecorations
染色变体 无(全 mod 只有这一个物品,无 metadata 变体系统)

功能

把一个睡袋铺成两格高的「平铺床」,之后在该睡袋上过夜可以直接把出生点设到这里(详见个人重生点条目)。核心差异有三点:

  1. 睡袋不占床的空间高度——碰撞箱只有 0.25 格,可以紧贴机器 / 墙壁铺一整排
  2. 睡袋可以被收起来带走——睡醒离开时若背包有空位会自动把睡袋收回(见方块页「拆袋回收」)
  3. 睡袋不会污染服务器战点——出生点存在每个玩家自己的内存数据里(见个人重生点条目)

使用方式

使用方式 触发条件 使用效果 条件 / 限制
快捷栏右键(对空) onItemRightClick 以玩家自身所在格为脚部放置整对睡袋 服务端执行;下方必须是实心顶面
右键点击方块顶面 onItemUse,仅 side == 1 先 y++,以点击位置的上一格为脚部放置 点侧面 / 底面无效
睡醒时自动回收 睡袋方块的 setBedOccupied 背包有空槽时睡袋收回;创造模式直接消失 背包全满则退回正常破坏掉落

onItemRightClick 直接返回原 ItemStack,不做数量检查;真正扣数量发生在 setBlockSleepingBag 末尾的 --itemstack.stackSize。

放置判定

setSleepingBag 的完整判定顺序:

  1. world.isRemote → 直接返回(客户端不做事)
  2. canPlayerSetBad(x, y, z):player.canPlayerEdit(x, y, z, 1, itemstack) 且 world.isAirBlock(x, y, z)
  3. World.doesBlockHaveSolidTopSurface(world, x, y - 1, z):正下方必须有实心顶面
  4. 朝向 dir = MathHelper.floor_double(player.rotationYaw * 4.0f / 360.0f + 0.5) & 0x3
    • dir == 0 → 偏移 (0, -1);dir == 1 → (+1, 0);dir == 2 → (0, +1);dir == 3 → (-1, 0)
  5. 四向搜索(按此顺序尝试「第二个格子」是否可放):
    1. 面向方向
    2. 面向的反方向
    3. 若面向在 Z 轴 → (+1, 0),再试 (-1, 0)
    4. 若面向在 X 轴 → (0, +1),再试 (0, -1)
  6. 全部失败 → 返回 false,睡袋不消耗

setBlockSleepingBag 由实际采用的偏移反推 dir(offsetZ == 1 → 0、offsetX == -1 → 1、offsetZ == -1 → 2、offsetX == 1 → 3),然后:

world.setBlock(x,            y, z,            block, dir,     3)   // 脚部
world.setBlock(x + offsetX,  y, z + offsetZ,  block, dir + 8, 3)   // 头部(+8 标记位)

放置后的二次校验(会回滚)

setBlockSleepingBag 在放完两格后调用 canPlayerSleep,不通过就把两格都 setBlockToAir 并返回 false(睡袋不扣数量)。校验条件:

条件 失败时
玩家未在睡觉、实体存活、所在维度是地表维度(provider.isSurfaceWorld()) 静默失败
非白天(isDaytime() 为真时) 提示 tile.bed.noSleep
目标方块是 BlockSleepingBag 静默失败
距离:` posX - x
以睡袋为中心的 18×10×18 包围盒(x±9、y±5、z±9)内没有 EntityMob 提示 tile.bed.notSafe

合成配方

有形状合成(工作台)。⚠️ 只有 Loader.isModLoaded("dreamcraft") == false 时才注册——装了 DreamCraft 的整合包里这条配方不存在。

   ┌───┬───┬───┐
   │   │   │   │   ← 空
   ├───┼───┼───┤
   │ 毛│ 毛│ 毛│   '#' = Blocks.wool ×1
   ├───┼───┼───┤
   │ 地│ 地│ 地│   'c' = Blocks.carpet ×1
   └───┴───┴───┘
产出:1 × 睡袋

毛毯与地毯都用 OreDictionary.WILDCARD_VALUE(meta 32767),所以任意颜色的毛 + 任意颜色的地毯都能做出来——这是全 mod 唯一与「颜色」沾边的地方:合成接受任意颜色,但产出的睡袋不带颜色信息。

数值

属性 值
消耗数量 每次成功放置 1 个(--itemstack.stackSize)
最大堆叠 1
睡眠距离容差 X/Z ±3.0、Y ±2.0
敌对生物排除范围 X/Z ±9.0、Y ±5.0(EntityMob 包围盒)
朝向搜索候选数 4

已知问题 / 限制

  • public static final String TAG_POSITION = "player_pos_sleaping_bag" 声明了但全代码库无人引用;配套的 ExtendedPlayer.saveNBTData / loadNBTData 是空方法,所以睡袋位置不会写进玩家存档,登出或重启后丢失
  • field_149981_a = {{0,1},{-1,0},{0,-1},{1,0}} 是本类自己的一份方向偏移表副本(与 BlockBed 的同名字段取值一致),不是引用父类字段

相关条目