一些检测仍在等待运行
Docs Build / build-and-deploy (push) Waiting to run
- 移除 ConfigManager 配置管理器类 - 移除 GameManager 全局单例管理器类 - 移除 NetworkManager 网络连接管理器类 - 移除 CharacterData 和 ItemData 数据模型类 - 移除 BagScene、BattleScene、LobbyScene 等场景脚本 - 移除 EncounterBubble 和 EventFeedPanel UI组件脚本 - 更新代理邀请文档中的服务器连接方式 - 更新同步状态表格中的代理任务分配信息 - 添加 MiMo 任务完成总结和审查修复记录
263 行
7.5 KiB
Go
263 行
7.5 KiB
Go
package modules
|
|
|
|
import (
|
|
"context"
|
|
"database/sql"
|
|
"encoding/json"
|
|
"fmt"
|
|
"math/rand"
|
|
|
|
"github.com/heroiclabs/nakama-common/runtime"
|
|
)
|
|
|
|
// RegisterManual 注册功法相关 RPC。
|
|
func RegisterManual(initializer runtime.Initializer) error {
|
|
if err := initializer.RegisterRpc("ManualService/ListManuals", listManuals); err != nil {
|
|
return err
|
|
}
|
|
if err := initializer.RegisterRpc("ManualService/UpgradeManual", upgradeManual); err != nil {
|
|
return err
|
|
}
|
|
if err := initializer.RegisterRpc("ManualService/SetBuffingManual", setBuffingManual); err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
type manualListReq struct {
|
|
CharacterID string `json:"character_id"`
|
|
IsBuffing bool `json:"is_buffing"`
|
|
Page int32 `json:"page"`
|
|
PageSize int32 `json:"page_size"`
|
|
}
|
|
|
|
type upgradeManualReq struct {
|
|
CharacterID string `json:"character_id"`
|
|
ManualInstanceID string `json:"manual_instance_id"`
|
|
Materials []materialCostReq `json:"materials"`
|
|
UseInsightItem bool `json:"use_insight_item"`
|
|
IdempotencyKey string `json:"idempotency_key"`
|
|
}
|
|
|
|
type buffManualReq struct {
|
|
CharacterID string `json:"character_id"`
|
|
ManualInstanceID string `json:"manual_instance_id"`
|
|
SlotIndex int32 `json:"slot_index"`
|
|
UnsetOthers bool `json:"unset_others"`
|
|
}
|
|
|
|
type manualItemData struct {
|
|
ManualInstanceID string `json:"manual_instance_id"`
|
|
ManualID string `json:"manual_id"`
|
|
Name string `json:"name"`
|
|
Category string `json:"category"`
|
|
Domain string `json:"domain"`
|
|
Element string `json:"element"`
|
|
InstanceData interface{} `json:"instance_data"`
|
|
IsBuffing bool `json:"is_buffing"`
|
|
CreatedAt string `json:"created_at"`
|
|
}
|
|
|
|
type manualListData struct {
|
|
Total int32 `json:"total"`
|
|
List []manualItemData `json:"list"`
|
|
}
|
|
|
|
type manualUpgradeData struct {
|
|
ManualInstanceID string `json:"manual_instance_id"`
|
|
OldLayer int32 `json:"old_layer"`
|
|
NewLayer int32 `json:"new_layer"`
|
|
Success bool `json:"success"`
|
|
ProficiencyLeft int32 `json:"proficiency_left"`
|
|
UnlockedSkill interface{} `json:"unlocked_skill"`
|
|
}
|
|
|
|
type buffSlotData struct {
|
|
SlotIndex int32 `json:"slot_index"`
|
|
ManualInstanceID string `json:"manual_instance_id"`
|
|
BuffSpeedBonus float64 `json:"buff_speed_bonus"`
|
|
BreakinUntil string `json:"breakin_until"`
|
|
}
|
|
|
|
func listManuals(ctx context.Context, logger runtime.Logger, db *sql.DB, nk runtime.NakamaModule, payload string) (string, error) {
|
|
traceID := newTraceID()
|
|
var req manualListReq
|
|
if err := json.Unmarshal([]byte(payload), &req); err != nil {
|
|
return errResp(5001, "invalid payload", traceID)
|
|
}
|
|
|
|
if req.Page < 1 {
|
|
req.Page = 1
|
|
}
|
|
if req.PageSize < 1 || req.PageSize > 50 {
|
|
req.PageSize = 20
|
|
}
|
|
offset := (req.Page - 1) * req.PageSize
|
|
|
|
// 查询功法列表
|
|
query := `
|
|
SELECT cm.id, cm.manual_id, m.name, m.category, m.domain, m.element,
|
|
cm.instance_data, cm.is_buffing, cm.created_at::text
|
|
FROM character_manuals cm
|
|
JOIN manuals m ON cm.manual_id = m.id
|
|
WHERE cm.character_id = $1
|
|
`
|
|
args := []interface{}{req.CharacterID}
|
|
|
|
if req.IsBuffing {
|
|
query += " AND cm.is_buffing = true"
|
|
}
|
|
|
|
query += " ORDER BY cm.created_at DESC LIMIT $2 OFFSET $3"
|
|
args = append(args, req.PageSize, offset)
|
|
|
|
rows, err := db.QueryContext(ctx, query, args...)
|
|
if err != nil {
|
|
logger.Error("list manuals failed: %v", err)
|
|
return errResp(9002, "internal error", traceID)
|
|
}
|
|
defer rows.Close()
|
|
|
|
var manuals []manualItemData
|
|
for rows.Next() {
|
|
var m manualItemData
|
|
if err := rows.Scan(
|
|
&m.ManualInstanceID, &m.ManualID, &m.Name, &m.Category,
|
|
&m.Domain, &m.Element, &m.InstanceData, &m.IsBuffing, &m.CreatedAt,
|
|
); err != nil {
|
|
continue
|
|
}
|
|
manuals = append(manuals, m)
|
|
}
|
|
|
|
// 查询总数
|
|
var total int32
|
|
err = db.QueryRowContext(ctx, `
|
|
SELECT COUNT(*) FROM character_manuals WHERE character_id = $1
|
|
`, req.CharacterID).Scan(&total)
|
|
if err != nil {
|
|
total = 0
|
|
}
|
|
|
|
return okResp(manualListData{Total: total, List: manuals}, traceID)
|
|
}
|
|
|
|
func upgradeManual(ctx context.Context, logger runtime.Logger, db *sql.DB, nk runtime.NakamaModule, payload string) (string, error) {
|
|
traceID := newTraceID()
|
|
var req upgradeManualReq
|
|
if err := json.Unmarshal([]byte(payload), &req); err != nil {
|
|
return errResp(5002, "invalid payload", traceID)
|
|
}
|
|
|
|
// 查询功法信息
|
|
var currentLayer int32
|
|
var maxLayer int32
|
|
err := db.QueryRowContext(ctx, `
|
|
SELECT cm.instance_data->>'current_layer', m.max_layers
|
|
FROM character_manuals cm
|
|
JOIN manuals m ON cm.manual_id = m.id
|
|
WHERE cm.id = $1 AND cm.character_id = $2
|
|
`, req.ManualInstanceID, req.CharacterID).Scan(¤tLayer, &maxLayer)
|
|
if err != nil {
|
|
return errResp(5003, "manual not found", traceID)
|
|
}
|
|
|
|
// 检查层数上限
|
|
if currentLayer >= maxLayer {
|
|
return errResp(5004, "already at max layer", traceID)
|
|
}
|
|
|
|
// 检查熟练度
|
|
var proficiency int32
|
|
err = db.QueryRowContext(ctx, `
|
|
SELECT COALESCE((instance_data->>'proficiency')::int, 0)
|
|
FROM character_manuals WHERE id = $1
|
|
`, req.ManualInstanceID).Scan(&proficiency)
|
|
if err != nil {
|
|
proficiency = 0
|
|
}
|
|
|
|
requiredProficiency := currentLayer * 100
|
|
if proficiency < requiredProficiency {
|
|
return errResp(5005, "insufficient proficiency", traceID)
|
|
}
|
|
|
|
// 计算成功率
|
|
successRate := 0.85
|
|
if currentLayer >= 5 {
|
|
successRate -= float64(currentLayer-4) * 0.05
|
|
}
|
|
|
|
// 判定成功/失败
|
|
success := rand.Float64() < successRate
|
|
|
|
var newLayer int32
|
|
if success {
|
|
newLayer = currentLayer + 1
|
|
// 更新功法层数和熟练度
|
|
_, err = db.ExecContext(ctx, `
|
|
UPDATE character_manuals
|
|
SET instance_data = jsonb_set(
|
|
instance_data,
|
|
'{current_layer}',
|
|
$1::jsonb
|
|
),
|
|
updated_at = NOW()
|
|
WHERE id = $2
|
|
`, fmt.Sprintf("%d", newLayer), req.ManualInstanceID)
|
|
if err != nil {
|
|
logger.Error("upgrade manual failed: %v", err)
|
|
return errResp(9002, "internal error", traceID)
|
|
}
|
|
}
|
|
|
|
logger.Info("ManualService/UpgradeManual: manual=%s success=%v", req.ManualInstanceID, success)
|
|
return okResp(manualUpgradeData{
|
|
ManualInstanceID: req.ManualInstanceID,
|
|
OldLayer: currentLayer,
|
|
NewLayer: newLayer,
|
|
Success: success,
|
|
}, traceID)
|
|
}
|
|
|
|
func setBuffingManual(ctx context.Context, logger runtime.Logger, db *sql.DB, nk runtime.NakamaModule, payload string) (string, error) {
|
|
traceID := newTraceID()
|
|
var req buffManualReq
|
|
if err := json.Unmarshal([]byte(payload), &req); err != nil {
|
|
return errResp(5006, "invalid payload", traceID)
|
|
}
|
|
|
|
// 查询功法信息
|
|
var isBuffing bool
|
|
err := db.QueryRowContext(ctx, `
|
|
SELECT is_buffing FROM character_manuals
|
|
WHERE id = $1 AND character_id = $2
|
|
`, req.ManualInstanceID, req.CharacterID).Scan(&isBuffing)
|
|
if err != nil {
|
|
return errResp(5003, "manual not found", traceID)
|
|
}
|
|
|
|
// 检查是否已在加持状态
|
|
if isBuffing {
|
|
return errResp(5007, "already buffing", traceID)
|
|
}
|
|
|
|
// 更新加持状态
|
|
_, err = db.ExecContext(ctx, `
|
|
UPDATE character_manuals
|
|
SET is_buffing = true, updated_at = NOW()
|
|
WHERE id = $1 AND character_id = $2
|
|
`, req.ManualInstanceID, req.CharacterID)
|
|
if err != nil {
|
|
logger.Error("set buffing manual failed: %v", err)
|
|
return errResp(9002, "internal error", traceID)
|
|
}
|
|
|
|
logger.Info("ManualService/SetBuffingManual success: manual=%s", req.ManualInstanceID)
|
|
return okResp(buffSlotData{
|
|
SlotIndex: req.SlotIndex,
|
|
ManualInstanceID: req.ManualInstanceID,
|
|
BuffSpeedBonus: 0.08,
|
|
}, traceID)
|
|
}
|