Files
ngzz-mc/internal/entity/villager.go

103 lines
2.9 KiB
Go
Raw Normal View History

// 村民建造子系统:程序化房屋蓝图 + 逐块建造队列(村民系统.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) }