1
All checks were successful
ci/woodpecker/push/my-first-workflow Pipeline was successful

This commit is contained in:
昔念
2026-02-12 12:43:28 +08:00
parent d0cf598ced
commit 2f756c77bb
9 changed files with 128 additions and 18 deletions

View File

@@ -58,14 +58,14 @@ func (s *Server) OnClose(c gnet.Conn, err error) (action gnet.Action) {
if t, ok := c.Context().(*player.ClientData); ok { if t, ok := c.Context().(*player.ClientData); ok {
if t.Player != nil { if t.Player != nil {
if t.Player.Info != nil { if t.Player.Info != nil {
cool.Logger.Error(context.TODO(), "OnClose 错误:", t.Player.Info.UserID, err) cool.Logger.Error(context.TODO(), "OnClose 错误:", cool.Config.ServerInfo.OnlineID, t.Player.Info.UserID, err)
t.Player.Service.Info.Save(*t.Player.Info) t.Player.Service.Info.Save(*t.Player.Info)
} }
} }
} else { } else {
cool.Logger.Error(context.TODO(), "OnClose 错误:", err) cool.Logger.Error(context.TODO(), "OnClose 错误:", cool.Config.ServerInfo.OnlineID, err)
} }
@@ -132,7 +132,7 @@ func (s *Server) OnTraffic(c gnet.Conn) (action gnet.Action) {
if t, ok := c.Context().(*player.ClientData); ok { if t, ok := c.Context().(*player.ClientData); ok {
if t.Player != nil { if t.Player != nil {
if t.Player.Info != nil { if t.Player.Info != nil {
cool.Logger.Error(context.TODO(), "OnTraffic 错误:", t.Player.Info.UserID, err) cool.Logger.Error(context.TODO(), "OnTraffic 错误:", cool.Config.ServerInfo.OnlineID, t.Player.Info.UserID, err)
t.Player.Service.Info.Save(*t.Player.Info) t.Player.Service.Info.Save(*t.Player.Info)
} }

45
help/三主宠查询.sql Normal file
View File

@@ -0,0 +1,45 @@
-- 删除每个多余精灵组中除了最早创建的其余记录
WITH pet_group_mapping AS (
SELECT
id,
player_id,
-- 核心修正PARTITION BY中直接写分组逻辑
ROW_NUMBER() OVER (
PARTITION BY
player_id,
CASE -- 3个一组的分组逻辑
WHEN (data->>'ID')::INT BETWEEN 1 AND 3 THEN 'group_1_3'
WHEN (data->>'ID')::INT BETWEEN 4 AND 6 THEN 'group_4_6'
WHEN (data->>'ID')::INT BETWEEN 7 AND 9 THEN 'group_7_9'
WHEN (data->>'ID')::INT BETWEEN 301 AND 303 THEN 'group_301_303'
WHEN (data->>'ID')::INT BETWEEN 304 AND 306 THEN 'group_304_306'
WHEN (data->>'ID')::INT BETWEEN 307 AND 309 THEN 'group_307_309'
END
ORDER BY "createTime" ASC
) AS rn,
-- 定义pet_group用于筛选多余组
CASE
WHEN (data->>'ID')::INT BETWEEN 1 AND 3 THEN 'group_1_3'
WHEN (data->>'ID')::INT BETWEEN 4 AND 6 THEN 'group_4_6'
WHEN (data->>'ID')::INT BETWEEN 7 AND 9 THEN 'group_7_9'
WHEN (data->>'ID')::INT BETWEEN 301 AND 303 THEN 'group_301_303'
WHEN (data->>'ID')::INT BETWEEN 304 AND 306 THEN 'group_304_306'
WHEN (data->>'ID')::INT BETWEEN 307 AND 309 THEN 'group_307_309'
END AS pet_group
FROM "player_pet"
WHERE deleted_at IS NULL
),
excess_groups AS (
SELECT player_id, pet_group
FROM pet_group_mapping
WHERE pet_group IS NOT NULL
GROUP BY player_id, pet_group
HAVING COUNT(*) > 1
)
DELETE FROM "player_pet"
WHERE id IN (
SELECT pgm.id
FROM pet_group_mapping pgm
INNER JOIN excess_groups eg ON pgm.player_id = eg.player_id AND pgm.pet_group = eg.pet_group
WHERE pgm.rn > 1
);

View File

@@ -1,11 +1,50 @@
SELECT -- 验证查询宠物ID为273/274玩家拥有2条且非最早创建的记录只查不删
player_id, WITH player_pet_ranked AS (
COUNT(*) AS pet_count SELECT
FROM id, -- 记录主键ID
"player_pet" player_id,
WHERE (data->>'ID')::INT AS pet_id, -- 便于核对宠物ID
(data->>'ID')::INT IN (273, 274) -- 适配JSONB的data字段取id并转整型 "createTime",
GROUP BY ROW_NUMBER() OVER (
player_id PARTITION BY player_id
HAVING ORDER BY "createTime" ASC
COUNT(*) >= 2; -- 筛选出拥有273/274宠物的玩家可根据需求调整为>=2同时拥有两者 ) AS rn
FROM "player_pet"
WHERE (data->>'ID')::INT IN (273, 274) -- 改为273或274
)
SELECT *
FROM player_pet_ranked
WHERE rn > 1 -- rn>1是要删除的记录
AND player_id IN (
SELECT player_id
FROM player_pet_ranked
GROUP BY player_id
HAVING COUNT(*) >= 2
);
-- 核心删除保留每个玩家下273/274宠物中createTime最早的那条删除其余
WITH player_pet_ranked AS (
SELECT
id, -- 必须取主键ID用于精准删除
player_id,
ROW_NUMBER() OVER (
PARTITION BY player_id
ORDER BY "createTime" ASC
) AS rn
FROM "player_pet"
WHERE (data->>'ID')::INT IN (273, 274) -- 关键修改70273,274
)
DELETE FROM "player_pet"
WHERE id IN (
SELECT id
FROM player_pet_ranked
WHERE rn > 1 -- 删除非最早的记录
AND player_id IN (
SELECT player_id
FROM player_pet_ranked
GROUP BY player_id
HAVING COUNT(*) >= 2 -- 仅处理拥有2条273/274宠物的玩家
)
);

View File

@@ -31,7 +31,7 @@ func (h Controller) GetPetInfo(
return nil, errorcode.ErrorCodes.ErrPokemonNotExists return nil, errorcode.ErrorCodes.ErrPokemonNotExists
} }
result = &pet.OutInfo{ result = &pet.OutInfo{
PetInfo: player.Service.Pet.PetInfo_One(data.CatchTime).Data, PetInfo: ret.Data,
} }
return result, 0 return result, 0
} }

View File

@@ -182,6 +182,9 @@ func (ctl Controller) GetHatchPet(
// TODO: 实现获得孵化精灵的具体逻辑,这里暂时返回默认值 // TODO: 实现获得孵化精灵的具体逻辑,这里暂时返回默认值
r := playerObj.Service.Egg.GetEgg() r := playerObj.Service.Egg.GetEgg()
if r == nil {
return nil, errorcode.ErrorCodes.ErrSystemError
}
playerObj.Service.Pet.PetAdd(r) playerObj.Service.Pet.PetAdd(r)
result.PetID = r.ID result.PetID = r.ID

View File

@@ -27,6 +27,9 @@ func (h Controller) GetUserSimInfo(data *user.SimUserInfoInboundInfo, player *pl
func (h Controller) GetUserMoreInfo(data *user.MoreUserInfoInboundInfo, player *player.Player) (result *user.MoreUserInfoOutboundInfo, err errorcode.ErrorCode) { func (h Controller) GetUserMoreInfo(data *user.MoreUserInfoInboundInfo, player *player.Player) (result *user.MoreUserInfoOutboundInfo, err errorcode.ErrorCode) {
result = &user.MoreUserInfoOutboundInfo{} result = &user.MoreUserInfoOutboundInfo{}
info := player.Service.Info.Person(data.UserId) info := player.Service.Info.Person(data.UserId)
if info == nil {
return nil, errorcode.ErrorCode(errorcode.ErrorCodes.ErrSystemError)
}
copier.CopyWithOption(result, info.Data, copier.Option{IgnoreEmpty: true, DeepCopy: true}) copier.CopyWithOption(result, info.Data, copier.Option{IgnoreEmpty: true, DeepCopy: true})
//todo 待实现 //todo 待实现

View File

@@ -52,9 +52,9 @@ func (h *ClientData) OnEvent(data common.TomeeHeader) {
// 1. 打印错误信息 // 1. 打印错误信息
if h.Player != nil { if h.Player != nil {
if h.Player.Info != nil { if h.Player.Info != nil {
cool.Logger.Error(context.TODO(), "panic 错误:", h.Player.Info.UserID, err) cool.Logger.Error(context.TODO(), "panic 错误:", cool.Config.ServerInfo.OnlineID, h.Player.Info.UserID, err)
} else { } else {
cool.Logger.Error(context.TODO(), "panic 错误:", err) cool.Logger.Error(context.TODO(), "panic 错误:", cool.Config.ServerInfo.OnlineID, err)
} }

View File

@@ -29,7 +29,26 @@ func (p *Player) Save() {
p.Info.OnlineTime = p.Info.OnlineTime + (newtime-int64(p.Logintime))/60 //每次退出时候保存已经在线的分钟数 p.Info.OnlineTime = p.Info.OnlineTime + (newtime-int64(p.Logintime))/60 //每次退出时候保存已经在线的分钟数
if p.FightC != nil { if p.FightC != nil {
defer p.FightC.Over(p, info.BattleOverReason.PlayerOffline) //玩家逃跑,但是不能锁线程 //ov := make(chan struct{})
go func() {
defer func() {
if err := recover(); err != nil { // 恢复 panicerr 为 panic 错误值
// 1. 打印错误信息
cool.Logger.Error(context.TODO(), "panic 错误:", err)
}
}()
p.FightC.Over(p, info.BattleOverReason.PlayerOffline) //玩家逃跑,但是不能锁线程
}()
//<-ov
select {
case <-p.FightC.GetOverChan(): //等待结束
case <-time.After(time.Second * 5): //等待5秒
cool.Logger.Error(context.TODO(), "战斗崩溃", p.Info.UserID)
}
} }
p.IsLogin = false p.IsLogin = false

View File

@@ -191,6 +191,7 @@ func (s *InfoService) Save(data model.PlayerInfo) {
tt.Data = data tt.Data = data
_, err := m.Save(tt) _, err := m.Save(tt)
if err != nil { if err != nil {
//todo 待实现兜底保存,现在有可能出错
panic(err) panic(err)
} }