lawless/server/modules/npc_faction.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)
}