// Package modules - NPC势力关系系统模块 // 对齐GDD-32 NPC与势力关系系统设计 package modules import ( "context" "database/sql" "encoding/json" "github.com/heroiclabs/nakama-common/runtime" ) // RegisterNPCFaction 注册NPC势力相关 RPC。 func RegisterNPCFaction(initializer runtime.Initializer) error { rpcs := map[string]func(context.Context, runtime.Logger, *sql.DB, runtime.NakamaModule, string) (string, error){ "NPCFactionService/GetFactionInfo": getFactionInfo, "NPCFactionService/GetNPCRelations": getNPCRelations, "NPCFactionService/ChangeRelation": changeRelation, "NPCFactionService/GetFactionShop": getFactionShop, } for path, fn := range rpcs { if err := initializer.RegisterRpc(path, fn); err != nil { return err } } return nil } type getFactionInfoReq struct { FactionID string `json:"faction_id"` } type getNPCRelationsReq struct { CharacterID string `json:"character_id"` FactionID string `json:"faction_id"` } type changeRelationReq struct { CharacterID string `json:"character_id"` FactionID string `json:"faction_id"` Delta int32 `json:"delta"` // 正数=友好,负数=敌对 Reason string `json:"reason"` } type getFactionShopReq struct { FactionID string `json:"faction_id"` CharacterID string `json:"character_id"` } type factionInfoData struct { ID string `json:"id"` Name string `json:"name"` Alignment string `json:"alignment"` // tian/hongyouming/neutral Description string `json:"description"` NPCCount int32 `json:"npc_count"` Reputation interface{} `json:"reputation"` } type npcRelationData struct { NPCID string `json:"npc_id"` NPCName string `json:"npc_name"` Relation string `json:"relation"` // friendly/neutral/hostile/enemy Reputation int32 `json:"reputation"` Dialogue string `json:"dialogue"` Available bool `json:"available"` } type factionShopItem struct { ItemID string `json:"item_id"` ItemName string `json:"item_name"` Price float64 `json:"price"` Currency string `json:"currency"` RequiredRep int32 `json:"required_reputation"` Stock int32 `json:"stock"` } // 势力配置 var factionConfig = map[string]factionInfoData{ "tian ting": { ID: "tian_ting", Name: "天庭", Alignment: "tian", Description: "天道秩序的维护者,神族主导", NPCCount: 50, }, "xian men": { ID: "xian_men", Name: "仙门联盟", Alignment: "tian", Description: "人族修仙门派联盟", NPCCount: 100, }, "sheng dian": { ID: "sheng_dian", Name: "圣殿", Alignment: "tian", Description: "天使裔的神圣组织", NPCCount: 30, }, "yao zu lian meng": { ID: "yao_zu_lian_meng", Name: "妖族联盟", Alignment: "hongyouming", Description: "各妖族部落联合", NPCCount: 80, }, "long gong": { ID: "long_gong", Name: "龙宫", Alignment: "hongyouming", Description: "龙族的海底王国", NPCCount: 20, }, "you ming jie": { ID: "you_ming_jie", Name: "幽冥界", Alignment: "youming", Description: "鬼族、冥族的死亡国度", NPCCount: 60, }, "mo yu": { ID: "mo_yu", Name: "魔域", Alignment: "youming", Description: "魔族的黑暗领地", NPCCount: 40, }, "jiu ri jiao tuan": { ID: "jiu_ri_jiao_tuan", Name: "旧日教团", Alignment: "youming", Description: "深潜裔的旧神信仰组织", NPCCount: 15, }, } func getFactionInfo(ctx context.Context, logger runtime.Logger, db *sql.DB, nk runtime.NakamaModule, payload string) (string, error) { traceID := newTraceID() var req getFactionInfoReq if err := json.Unmarshal([]byte(payload), &req); err != nil { return errResp(2001, "invalid payload", traceID) } faction, ok := factionConfig[req.FactionID] if !ok { return errResp(8701, "faction not found", traceID) } return okResp(faction, traceID) } func getNPCRelations(ctx context.Context, logger runtime.Logger, db *sql.DB, nk runtime.NakamaModule, payload string) (string, error) { traceID := newTraceID() uid := userIDFromCtx(ctx) if uid == "" { return errResp(1001, "missing token", traceID) } var req getNPCRelationsReq if err := json.Unmarshal([]byte(payload), &req); err != nil { return errResp(2001, "invalid payload", traceID) } // 模拟NPC关系数据 relations := []npcRelationData{ {NPCID: "npc_elder", NPCName: "长老", Relation: "neutral", Reputation: 0, Available: true}, {NPCID: "npc_merchant", NPCName: "商人", Relation: "neutral", Reputation: 0, Available: true}, {NPCID: "npc_guard", NPCName: "守卫", Relation: "neutral", Reputation: 0, Available: true}, } return okResp(map[string]interface{}{ "faction_id": req.FactionID, "relations": relations, "count": len(relations), }, traceID) } func changeRelation(ctx context.Context, logger runtime.Logger, db *sql.DB, nk runtime.NakamaModule, payload string) (string, error) { traceID := newTraceID() uid := userIDFromCtx(ctx) if uid == "" { return errResp(1001, "missing token", traceID) } var req changeRelationReq if err := json.Unmarshal([]byte(payload), &req); err != nil { return errResp(2001, "invalid payload", traceID) } // 更新关系值 logger.Info("Change relation: char=%s faction=%s delta=%d reason=%s", req.CharacterID, req.FactionID, req.Delta, req.Reason) return okResp(map[string]interface{}{ "success": true, "faction_id": req.FactionID, "delta": req.Delta, "message": "关系已更新", }, traceID) } func getFactionShop(ctx context.Context, logger runtime.Logger, db *sql.DB, nk runtime.NakamaModule, payload string) (string, error) { traceID := newTraceID() uid := userIDFromCtx(ctx) if uid == "" { return errResp(1001, "missing token", traceID) } var req getFactionShopReq if err := json.Unmarshal([]byte(payload), &req); err != nil { return errResp(2001, "invalid payload", traceID) } // 模拟商店物品 shopItems := []factionShopItem{ {ItemID: "pill_huiqi", ItemName: "回气丹", Price: 100, Currency: "copper", RequiredRep: 0, Stock: 10}, {ItemID: "material_xuantie", ItemName: "玄铁", Price: 500, Currency: "copper", RequiredRep: 100, Stock: 5}, {ItemID: "manual_yellow", ItemName: "黄品功法", Price: 50, Currency: "spirit_stone_low", RequiredRep: 500, Stock: 1}, } return okResp(map[string]interface{}{ "faction_id": req.FactionID, "items": shopItems, "count": len(shopItems), }, traceID) }