// 村民建造子系统:程序化房屋蓝图 + 逐块建造队列(村民系统.md §6 特色功能)。 package entity import ( "mc/internal/block" ) // Villager 村民附加数据(村民系统.md §3–§6)。 type Villager struct { Profession uint8 // 0 农民 1 建造者 2 铁匠 3 商人 Home [3]int32 // 建造队列(村民系统.md §6.3:按顺序逐块放置) BuildQueue []BuildTask } // BuildTask 一个建造任务(建造顺序已定)。 type BuildTask struct { X, Y, Z int32 BlockID uint16 Meta uint8 Order uint32 // 地基 → 墙 → 门 → 屋顶 → 火把 } // Blueprint 程序化房屋蓝图(村民系统.md §6.2): // 矩形地基 W×D、墙高 3、门朝 +x、平顶、四角火把;确定性(seed 派生尺寸)。 func Blueprint(origin [3]int32, seed uint64) []BuildTask { w := 5 + int(seed%3) // 5–7 d := 4 + int(seed%3) // 4–6 wall := uint16(8) // oak_planks(与 assets/config/blocks.json 一致) door := uint16(0) // 门后置:先留空 roof := uint16(8) torch := uint16(17) var tasks []BuildTask order := uint32(0) add := func(x, y, z int32, id uint16, o uint32) { tasks = append(tasks, BuildTask{X: x, Y: y, Z: z, BlockID: id, Order: o}) } ox, oy, oz := origin[0], origin[1], origin[2] // 1) 地基(order 0) for x := 0; x < w; x++ { for z := 0; z < d; z++ { add(ox+int32(x), oy, oz+int32(z), wall, order) } } order++ // 2) 墙(order 1–2,高 3;门位置留空) for y := 1; y <= 2; y++ { for x := 0; x < w; x++ { for z := 0; z < d; z++ { edge := x == 0 || x == w-1 || z == 0 || z == d-1 if !edge { continue } if y == 1 && x == 0 && z == d/2 { continue // 门洞 } add(ox+int32(x), oy+int32(y), oz+int32(z), wall, order) } } order++ } // 3) 屋顶(order 3,平顶 + 一圈外沿) for x := -1; x <= w; x++ { for z := -1; z <= d; z++ { edge := x == -1 || x == w || z == -1 || z == d add(ox+int32(x), oy+3, oz+int32(z), roof, order+uint32(boolToInt(edge))) } } order += 2 // 4) 火把(order 5,四角) for _, c := range [4][2]int{{0, 0}, {w - 1, 0}, {0, d - 1}, {w - 1, d - 1}} { add(ox+int32(c[0]), oy+2, oz+int32(c[1]), torch, order) } _ = door return tasks } // boolToInt bool → int。 func boolToInt(b bool) int { if b { return 1 } return 0 } // BuildTick 建造者村民执行建造队列:每 tick 1–2 块(村民系统.md §6.3 防瞬建突兀)。 // place:放置回调(世界层 SetBlock);返回剩余任务数。 func (v *Villager) BuildTick(place func(x, y, z int32, id uint16, meta uint8) bool) int { n := 0 for len(v.BuildQueue) > 0 && n < 2 { t := v.BuildQueue[0] v.BuildQueue = v.BuildQueue[1:] if place(t.X, t.Y, t.Z, t.BlockID, t.Meta) { n++ } } return len(v.BuildQueue) } // 方块状态工具(避免测试重复导入)。 func stateOf(id uint16, meta uint8) block.State { return block.NewState(id, meta) }