// Package modules - 怪物生成引擎模块 // 对齐GDD-19 怪物图鉴与生成引擎 package modules import ( "context" "database/sql" "encoding/json" "math/rand" "time" "github.com/heroiclabs/nakama-common/runtime" ) // RegisterMonster 注册怪物相关 RPC。 func RegisterMonster(initializer runtime.Initializer) error { rpcs := map[string]func(runtime.Initializer) error{ "MonsterService/GetMonsterInfo": getMonsterInfo, "MonsterService/GetMonsterList": getMonsterList, "MonsterService/GetMonsterDrops": getMonsterDrops, } for path, fn := range rpcs { if err := initializer.RegisterRpc(path, fn); err != nil { return err } } return nil } type getMonsterInfoReq struct { MonsterID string `json:"monster_id"` } type getMonsterListReq struct { WorldTier int32 `json:"world_tier"` MonsterType string `json:"monster_type"` // wild/elite/boss Page int32 `json:"page"` PageSize int32 `json:"page_size"` } type getMonsterDropsReq struct { MonsterID string `json:"monster_id"` } type monsterInfoData struct { ID string `json:"id"` Name string `json:"name"` MonsterType string `json:"monster_type"` // wild/elite/boss WorldTier int32 `json:"world_tier"` RealmTier int32 `json:"realm_tier"` HP int32 `json:"hp"` Attack int32 `json:"attack"` Defense int32 `json:"defense"` Elements interface{} `json:"elements"` Drops interface{} `json:"drops"` SpawnRate float64 `json:"spawn_rate"` IsAggressive bool `json:"is_aggressive"` } type monsterDropData struct { ItemID string `json:"item_id"` ItemName string `json:"item_name"` DropRate float64 `json:"drop_rate"` MinQuantity int32 `json:"min_quantity"` MaxQuantity int32 `json:"max_quantity"` } // 怪物模板配置 var monsterTemplates = map[string]monsterInfoData{ "wild_boar": { ID: "wild_boar", Name: "野猪", MonsterType: "wild", WorldTier: 1, RealmTier: 1, HP: 100, Attack: 8, Defense: 3, Elements: []string{"none"}, SpawnRate: 0.8, IsAggressive: false, }, "wolf": { ID: "wolf", Name: "灰狼", MonsterType: "wild", WorldTier: 1, RealmTier: 1, HP: 120, Attack: 12, Defense: 5, Elements: []string{"none"}, SpawnRate: 0.7, IsAggressive: true, }, "forest_troll": { ID: "forest_troll", Name: "森林巨魔", MonsterType: "elite", WorldTier: 2, RealmTier: 2, HP: 500, Attack: 35, Defense: 20, Elements: []string{"wood"}, SpawnRate: 0.3, IsAggressive: true, }, "fire_spirit": { ID: "fire_spirit", Name: "火焰精灵", MonsterType: "elite", WorldTier: 3, RealmTier: 3, HP: 800, Attack: 55, Defense: 30, Elements: []string{"fire"}, SpawnRate: 0.2, IsAggressive: true, }, "ancient_dragon": { ID: "ancient_dragon", Name: "远古巨龙", MonsterType: "boss", WorldTier: 5, RealmTier: 6, HP: 50000, Attack: 500, Defense: 300, Elements: []string{"fire", "lightning"}, SpawnRate: 0.01, IsAggressive: true, }, "chaos_guardian": { ID: "chaos_guardian", Name: "混沌守卫", MonsterType: "boss", WorldTier: 6, RealmTier: 8, HP: 200000, Attack: 2000, Defense: 1500, Elements: []string{"chaos"}, SpawnRate: 0.005, IsAggressive: true, }, } func getMonsterInfo(ctx context.Context, logger runtime.Logger, db *sql.DB, nk runtime.NakamaModule, payload string) (string, error) { traceID := newTraceID() var req getMonsterInfoReq if err := json.Unmarshal([]byte(payload), &req); err != nil { return errResp(2001, "invalid payload", traceID) } monster, ok := monsterTemplates[req.MonsterID] if !ok { return errResp(8501, "monster not found", traceID) } return okResp(monster, traceID) } func getMonsterList(ctx context.Context, logger runtime.Logger, db *sql.DB, nk runtime.NakamaModule, payload string) (string, error) { traceID := newTraceID() var req getMonsterListReq if err := json.Unmarshal([]byte(payload), &req); err != nil { return errResp(2001, "invalid payload", traceID) } if req.Page < 1 { req.Page = 1 } if req.PageSize < 1 || req.PageSize > 50 { req.PageSize = 20 } // 筛选怪物 var monsters []monsterInfoData for _, m := range monsterTemplates { if m.WorldTier == req.WorldTier { if req.MonsterType == "" || m.MonsterType == req.MonsterType { monsters = append(monsters, m) } } } // 分页 start := (req.Page - 1) * req.PageSize end := start + req.PageSize if start > len(monsters) { monsters = []monsterInfoData{} } else if end > len(monsters) { monsters = monsters[start:] } else { monsters = monsters[start:end] } return okResp(map[string]interface{}{ "monsters": monsters, "count": len(monsters), "page": req.Page, }, traceID) } func getMonsterDrops(ctx context.Context, logger runtime.Logger, db *sql.DB, nk runtime.NakamaModule, payload string) (string, error) { traceID := newTraceID() var req getMonsterDropsReq if err := json.Unmarshal([]byte(payload), &req); err != nil { return errResp(2001, "invalid payload", traceID) } // 模拟掉落表 drops := []monsterDropData{ {ItemID: "material_hide", ItemName: "兽皮", DropRate: 0.8, MinQuantity: 1, MaxQuantity: 3}, {ItemID: "material_bone", ItemName: "兽骨", DropRate: 0.6, MinQuantity: 1, MaxQuantity: 2}, {ItemID: "material_fang", ItemName: "兽牙", DropRate: 0.3, MinQuantity: 1, MaxQuantity: 1}, } return okResp(map[string]interface{}{ "monster_id": req.MonsterID, "drops": drops, }, traceID) }