191 行
6.4 KiB
Go
191 行
6.4 KiB
Go
// Package modules - 成就图鉴系统模块
|
|
// 对齐GDD-30 成就里程碑与图鉴系统设计
|
|
package modules
|
|
|
|
import (
|
|
"context"
|
|
"database/sql"
|
|
"encoding/json"
|
|
"time"
|
|
|
|
"github.com/heroiclabs/nakama-common/runtime"
|
|
)
|
|
|
|
// RegisterAchievement 注册成就相关 RPC。
|
|
func RegisterAchievement(initializer runtime.Initializer) error {
|
|
rpcs := map[string]func(runtime.Initializer) error{
|
|
"AchievementService/GetAchievements": getAchievements,
|
|
"AchievementService/ClaimAchievement": claimAchievement,
|
|
"AchievementService/GetCollection": getCollection,
|
|
"AchievementService/GetMilestones": getMilestones,
|
|
}
|
|
for path, fn := range rpcs {
|
|
if err := initializer.RegisterRpc(path, fn); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
type getAchievementsReq struct {
|
|
CharacterID string `json:"character_id"`
|
|
Category string `json:"category"` // combat/exploration/crafting/social/special
|
|
}
|
|
|
|
type claimAchievementReq struct {
|
|
AchievementID string `json:"achievement_id"`
|
|
}
|
|
|
|
type getCollectionReq struct {
|
|
CharacterID string `json:"character_id"`
|
|
CollectionType string `json:"collection_type"` // skill/artifact/manual/monster
|
|
}
|
|
|
|
type getMilestonesReq struct {
|
|
CharacterID string `json:"character_id"`
|
|
}
|
|
|
|
type achievementData struct {
|
|
ID string `json:"id"`
|
|
Name string `json:"name"`
|
|
Description string `json:"description"`
|
|
Category string `json:"category"`
|
|
Progress int32 `json:"progress"`
|
|
Target int32 `json:"target"`
|
|
IsCompleted bool `json:"is_completed"`
|
|
IsClaimed bool `json:"is_claimed"`
|
|
Reward interface{} `json:"reward"`
|
|
UnlockedAt *time.Time `json:"unlocked_at"`
|
|
}
|
|
|
|
type collectionData struct {
|
|
Type string `json:"type"`
|
|
TotalItems int32 `json:"total_items"`
|
|
Collected int32 `json:"collected"`
|
|
CompletionRate float64 `json:"completion_rate"`
|
|
Items interface{} `json:"items"`
|
|
}
|
|
|
|
type milestoneData struct {
|
|
ID string `json:"id"`
|
|
Name string `json:"name"`
|
|
Description string `json:"description"`
|
|
Target int32 `json:"target"`
|
|
Current int32 `json:"current"`
|
|
IsCompleted bool `json:"is_completed"`
|
|
Reward interface{} `json:"reward"`
|
|
}
|
|
|
|
// 成就模板配置
|
|
var achievementTemplates = []achievementData{
|
|
{ID: "first_kill", Name: "初出茅庐", Description: "击杀第一个怪物", Category: "combat", Target: 1},
|
|
{ID: "kill_100", Name: "百战老兵", Description: "击杀100个怪物", Category: "combat", Target: 100},
|
|
{ID: "kill_1000", Name: "千人斩", Description: "击杀1000个怪物", Category: "combat", Target: 1000},
|
|
{ID: "realm_reach_3", Name: "金丹大道", Description: "达到金丹期", Category: "exploration", Target: 3},
|
|
{ID: "realm_reach_5", Name: "化神飞升", Description: "达到化神期", Category: "exploration", Target: 5},
|
|
{ID: "craft_10", Name: "炼丹新手", Description: "成功炼制10颗丹药", Category: "crafting", Target: 10},
|
|
{ID: "craft_100", Name: "炼丹大师", Description: "成功炼制100颗丹药", Category: "crafting", Target: 100},
|
|
{ID: "friend_10", Name: "广交好友", Description: "添加10个好友", Category: "social", Target: 10},
|
|
{ID: "join_guild", Name: "宗门弟子", Description: "加入一个宗门", Category: "social", Target: 1},
|
|
{ID: "collect_50", Name: "收藏家", Description: "收集50个不同技能", Category: "special", Target: 50},
|
|
}
|
|
|
|
// 里程碑配置
|
|
var milestoneTemplates = []milestoneData{
|
|
{ID: "ms_realm_3", Name: "筑基有成", Description: "达到筑基期", Target: 2},
|
|
{ID: "ms_realm_5", Name: "元婴大能", Description: "达到元婴期", Target: 4},
|
|
{ID: "ms_realm_7", Name: "大乘圆满", Description: "达到大乘期", Target: 7},
|
|
{ID: "ms_kill_10000", Name: "万军取首", Description: "击杀10000个怪物", Target: 10000},
|
|
{ID: "ms_craft_500", Name: "炼丹宗师", Description: "成功炼制500颗丹药", Target: 500},
|
|
}
|
|
|
|
func getAchievements(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 getAchievementsReq
|
|
if err := json.Unmarshal([]byte(payload), &req); err != nil {
|
|
return errResp(2001, "invalid payload", traceID)
|
|
}
|
|
|
|
// 筛选成就
|
|
var achievements []achievementData
|
|
for _, a := range achievementTemplates {
|
|
if req.Category == "" || a.Category == req.Category {
|
|
achievements = append(achievements, a)
|
|
}
|
|
}
|
|
|
|
return okResp(map[string]interface{}{
|
|
"achievements": achievements,
|
|
"count": len(achievements),
|
|
}, traceID)
|
|
}
|
|
|
|
func claimAchievement(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 claimAchievementReq
|
|
if err := json.Unmarshal([]byte(payload), &req); err != nil {
|
|
return errResp(2001, "invalid payload", traceID)
|
|
}
|
|
|
|
// 领取成就奖励(简化版)
|
|
logger.Info("Claim achievement: achievement=%s", req.AchievementID)
|
|
|
|
return okResp(map[string]interface{}{
|
|
"success": true,
|
|
"achievement_id": req.AchievementID,
|
|
"message": "成就奖励已领取",
|
|
}, traceID)
|
|
}
|
|
|
|
func getCollection(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 getCollectionReq
|
|
if err := json.Unmarshal([]byte(payload), &req); err != nil {
|
|
return errResp(2001, "invalid payload", traceID)
|
|
}
|
|
|
|
// 模拟图鉴数据
|
|
collection := collectionData{
|
|
Type: req.CollectionType,
|
|
TotalItems: 100,
|
|
Collected: 0,
|
|
CompletionRate: 0,
|
|
Items: []interface{}{},
|
|
}
|
|
|
|
return okResp(collection, traceID)
|
|
}
|
|
|
|
func getMilestones(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 getMilestonesReq
|
|
if err := json.Unmarshal([]byte(payload), &req); err != nil {
|
|
return errResp(2001, "invalid payload", traceID)
|
|
}
|
|
|
|
return okResp(map[string]interface{}{
|
|
"milestones": milestoneTemplates,
|
|
"count": len(milestoneTemplates),
|
|
}, traceID)
|
|
}
|