睡袋(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 变体系统) |
功能
把一个睡袋铺成两格高的「平铺床」,之后在该睡袋上过夜可以直接把出生点设到这里(详见个人重生点条目)。核心差异有三点:
- 睡袋不占床的空间高度——碰撞箱只有 0.25 格,可以紧贴机器 / 墙壁铺一整排
- 睡袋可以被收起来带走——睡醒离开时若背包有空位会自动把睡袋收回(见方块页「拆袋回收」)
- 睡袋不会污染服务器战点——出生点存在每个玩家自己的内存数据里(见个人重生点条目)
使用方式
| 使用方式 | 触发条件 | 使用效果 | 条件 / 限制 |
|---|---|---|---|
| 快捷栏右键(对空) | onItemRightClick |
以玩家自身所在格为脚部放置整对睡袋 | 服务端执行;下方必须是实心顶面 |
| 右键点击方块顶面 | onItemUse,仅 side == 1 |
先 y++,以点击位置的上一格为脚部放置 |
点侧面 / 底面无效 |
| 睡醒时自动回收 | 睡袋方块的 setBedOccupied |
背包有空槽时睡袋收回;创造模式直接消失 | 背包全满则退回正常破坏掉落 |
onItemRightClick 直接返回原 ItemStack,不做数量检查;真正扣数量发生在 setBlockSleepingBag 末尾的 --itemstack.stackSize。
放置判定
setSleepingBag 的完整判定顺序:
world.isRemote→ 直接返回(客户端不做事)canPlayerSetBad(x, y, z):player.canPlayerEdit(x, y, z, 1, itemstack)且world.isAirBlock(x, y, z)World.doesBlockHaveSolidTopSurface(world, x, y - 1, z):正下方必须有实心顶面- 朝向
dir = MathHelper.floor_double(player.rotationYaw * 4.0f / 360.0f + 0.5) & 0x3dir == 0→ 偏移(0, -1);dir == 1→(+1, 0);dir == 2→(0, +1);dir == 3→(-1, 0)
- 四向搜索(按此顺序尝试「第二个格子」是否可放):
- 面向方向
- 面向的反方向
- 若面向在 Z 轴 →
(+1, 0),再试(-1, 0) - 若面向在 X 轴 →
(0, +1),再试(0, -1)
- 全部失败 → 返回
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的同名字段取值一致),不是引用父类字段
相关条目
- 睡袋方块(Sleeping Bag Block) - 被本物品放置的成对方块
- 个人重生点与睡眠状态机 - 放置时写入的坐标与唤醒流程