205 行
6.2 KiB
Go
205 行
6.2 KiB
Go
// Package modules - NPC势力关系系统模块
|
|
// 对齐GDD-32 NPC与势力关系系统设计
|
|
package modules
|
|
|
|
import (
|
|
"context"
|
|
"database/sql"
|
|
"encoding/json"
|
|
"time"
|
|
|
|
"github.com/heroiclabs/nakama-common/runtime"
|
|
)
|
|
|
|
// RegisterNPCFaction 注册NPC势力相关 RPC。
|
|
func RegisterNPCFaction(initializer runtime.Initializer) error {
|
|
rpcs := map[string]func(runtime.Initializer) 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)
|
|
}
|