feat: 新增PVP匹配队列分组和暗黑门关卡前置检查
All checks were successful
ci/woodpecker/push/my-first-workflow Pipeline was successful
All checks were successful
ci/woodpecker/push/my-first-workflow Pipeline was successful
This commit is contained in:
@@ -21,17 +21,25 @@ type PVPMatchJoinPayload struct {
|
||||
Nick string `json:"nick"`
|
||||
FightMode uint32 `json:"fightMode"`
|
||||
Status uint32 `json:"status"`
|
||||
IsVip uint32 `json:"isVip"`
|
||||
IsDebug uint8 `json:"isDebug"`
|
||||
CatchTimes []uint32 `json:"catchTimes"`
|
||||
}
|
||||
|
||||
type pvpMatchQueueKey struct {
|
||||
FightMode uint32
|
||||
IsVip uint32
|
||||
IsDebug uint8
|
||||
}
|
||||
|
||||
type pvpMatchCoordinator struct {
|
||||
mu sync.Mutex
|
||||
queues map[uint32][]pvpwire.QueuePlayerSnapshot
|
||||
queues map[pvpMatchQueueKey][]pvpwire.QueuePlayerSnapshot
|
||||
lastSeen map[uint32]time.Time
|
||||
}
|
||||
|
||||
var defaultPVPMatchCoordinator = &pvpMatchCoordinator{
|
||||
queues: make(map[uint32][]pvpwire.QueuePlayerSnapshot),
|
||||
queues: make(map[pvpMatchQueueKey][]pvpwire.QueuePlayerSnapshot),
|
||||
lastSeen: make(map[uint32]time.Time),
|
||||
}
|
||||
|
||||
@@ -51,6 +59,8 @@ func (m *pvpMatchCoordinator) JoinOrUpdate(payload PVPMatchJoinPayload) error {
|
||||
Nick: payload.Nick,
|
||||
FightMode: payload.FightMode,
|
||||
Status: payload.Status,
|
||||
IsVip: payload.IsVip,
|
||||
IsDebug: payload.IsDebug,
|
||||
JoinedAtUnix: now.Unix(),
|
||||
CatchTimes: append([]uint32(nil), payload.CatchTimes...),
|
||||
}
|
||||
@@ -62,11 +72,12 @@ func (m *pvpMatchCoordinator) JoinOrUpdate(payload PVPMatchJoinPayload) error {
|
||||
m.removeUserLocked(payload.UserID)
|
||||
m.lastSeen[payload.UserID] = now
|
||||
|
||||
queue := m.queues[payload.FightMode]
|
||||
queueKey := newPVPMatchQueueKey(player)
|
||||
queue := m.queues[queueKey]
|
||||
if len(queue) > 0 {
|
||||
host := queue[0]
|
||||
queue = queue[1:]
|
||||
m.queues[payload.FightMode] = queue
|
||||
m.queues[queueKey] = queue
|
||||
delete(m.lastSeen, host.UserID)
|
||||
delete(m.lastSeen, payload.UserID)
|
||||
|
||||
@@ -79,7 +90,7 @@ func (m *pvpMatchCoordinator) JoinOrUpdate(payload PVPMatchJoinPayload) error {
|
||||
}
|
||||
match = &result
|
||||
} else {
|
||||
m.queues[payload.FightMode] = append(queue, player)
|
||||
m.queues[queueKey] = append(queue, player)
|
||||
}
|
||||
m.mu.Unlock()
|
||||
|
||||
@@ -109,7 +120,7 @@ func (m *pvpMatchCoordinator) Cancel(userID uint32) {
|
||||
}
|
||||
|
||||
func (m *pvpMatchCoordinator) pruneExpiredLocked(now time.Time) {
|
||||
for mode, queue := range m.queues {
|
||||
for key, queue := range m.queues {
|
||||
next := make([]pvpwire.QueuePlayerSnapshot, 0, len(queue))
|
||||
for _, queued := range queue {
|
||||
last := m.lastSeen[queued.UserID]
|
||||
@@ -119,12 +130,12 @@ func (m *pvpMatchCoordinator) pruneExpiredLocked(now time.Time) {
|
||||
}
|
||||
next = append(next, queued)
|
||||
}
|
||||
m.queues[mode] = next
|
||||
m.queues[key] = next
|
||||
}
|
||||
}
|
||||
|
||||
func (m *pvpMatchCoordinator) removeUserLocked(userID uint32) {
|
||||
for mode, queue := range m.queues {
|
||||
for key, queue := range m.queues {
|
||||
next := make([]pvpwire.QueuePlayerSnapshot, 0, len(queue))
|
||||
for _, queued := range queue {
|
||||
if queued.UserID == userID {
|
||||
@@ -132,7 +143,15 @@ func (m *pvpMatchCoordinator) removeUserLocked(userID uint32) {
|
||||
}
|
||||
next = append(next, queued)
|
||||
}
|
||||
m.queues[mode] = next
|
||||
m.queues[key] = next
|
||||
}
|
||||
}
|
||||
|
||||
func newPVPMatchQueueKey(player pvpwire.QueuePlayerSnapshot) pvpMatchQueueKey {
|
||||
return pvpMatchQueueKey{
|
||||
FightMode: player.FightMode,
|
||||
IsVip: player.IsVip,
|
||||
IsDebug: player.IsDebug,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ package controller
|
||||
import (
|
||||
"blazing/common/rpc"
|
||||
"blazing/common/socket/errorcode"
|
||||
"blazing/cool"
|
||||
"blazing/logic/service/common"
|
||||
"blazing/logic/service/fight"
|
||||
"blazing/logic/service/fight/pvp"
|
||||
@@ -37,6 +38,8 @@ func (h Controller) JoINtop(data *PetTOPLEVELnboundInfo, c *player.Player) (resu
|
||||
Nick: c.Info.Nick,
|
||||
FightMode: fightMode,
|
||||
Status: status,
|
||||
IsVip: cool.Config.ServerInfo.IsVip,
|
||||
IsDebug: cool.Config.ServerInfo.IsDebug,
|
||||
CatchTimes: pvp.AvailableCatchTimes(c.GetPetInfo(0)),
|
||||
}
|
||||
if callErr := Maincontroller.RPCClient.MatchJoinOrUpdate(joinPayload); callErr != nil {
|
||||
|
||||
@@ -59,9 +59,15 @@ type session struct {
|
||||
banPickDeadline time.Time
|
||||
}
|
||||
|
||||
type queueKey struct {
|
||||
FightMode uint32
|
||||
IsVip uint32
|
||||
IsDebug uint8
|
||||
}
|
||||
|
||||
type manager struct {
|
||||
mu sync.RWMutex
|
||||
queues map[uint32][]pvpwire.QueuePlayerSnapshot
|
||||
queues map[queueKey][]pvpwire.QueuePlayerSnapshot
|
||||
lastSeen map[uint32]time.Time
|
||||
localQueues map[uint32]*localQueueTicket
|
||||
sessions map[string]*session
|
||||
@@ -69,7 +75,7 @@ type manager struct {
|
||||
}
|
||||
|
||||
var defaultManager = &manager{
|
||||
queues: make(map[uint32][]pvpwire.QueuePlayerSnapshot),
|
||||
queues: make(map[queueKey][]pvpwire.QueuePlayerSnapshot),
|
||||
lastSeen: make(map[uint32]time.Time),
|
||||
localQueues: make(map[uint32]*localQueueTicket),
|
||||
sessions: make(map[string]*session),
|
||||
@@ -222,6 +228,8 @@ func (m *manager) queueHeartbeatLoop(p *player.Player, ticket *localQueueTicket)
|
||||
Nick: p.Info.Nick,
|
||||
FightMode: ticket.fightMode,
|
||||
Status: ticket.status,
|
||||
IsVip: cool.Config.ServerInfo.IsVip,
|
||||
IsDebug: cool.Config.ServerInfo.IsDebug,
|
||||
JoinedAtUnix: time.Now().Unix(),
|
||||
CatchTimes: filterAvailableCatchTimes(p.GetPetInfo(0)),
|
||||
},
|
||||
@@ -254,12 +262,13 @@ func (m *manager) handleQueueJoin(payload pvpwire.QueueJoinPayload) {
|
||||
m.pruneExpiredQueueLocked(now)
|
||||
playerInfo := payload.Player
|
||||
m.lastSeen[playerInfo.UserID] = now
|
||||
queue := m.queues[playerInfo.FightMode]
|
||||
queueBucket := newQueueKey(playerInfo)
|
||||
queue := m.queues[queueBucket]
|
||||
|
||||
for idx, queued := range queue {
|
||||
if queued.UserID == playerInfo.UserID {
|
||||
queue[idx] = playerInfo
|
||||
m.queues[playerInfo.FightMode] = queue
|
||||
m.queues[queueBucket] = queue
|
||||
return
|
||||
}
|
||||
}
|
||||
@@ -267,7 +276,7 @@ func (m *manager) handleQueueJoin(payload pvpwire.QueueJoinPayload) {
|
||||
if len(queue) > 0 {
|
||||
host := queue[0]
|
||||
queue = queue[1:]
|
||||
m.queues[playerInfo.FightMode] = queue
|
||||
m.queues[queueBucket] = queue
|
||||
delete(m.lastSeen, host.UserID)
|
||||
delete(m.lastSeen, playerInfo.UserID)
|
||||
|
||||
@@ -286,7 +295,7 @@ func (m *manager) handleQueueJoin(payload pvpwire.QueueJoinPayload) {
|
||||
return
|
||||
}
|
||||
|
||||
m.queues[playerInfo.FightMode] = append(queue, playerInfo)
|
||||
m.queues[queueBucket] = append(queue, playerInfo)
|
||||
}
|
||||
|
||||
func (m *manager) handleQueueCancel(payload pvpwire.QueueCancelPayload) {
|
||||
@@ -294,7 +303,7 @@ func (m *manager) handleQueueCancel(payload pvpwire.QueueCancelPayload) {
|
||||
defer m.mu.Unlock()
|
||||
|
||||
delete(m.lastSeen, payload.UserID)
|
||||
for mode, queue := range m.queues {
|
||||
for key, queue := range m.queues {
|
||||
next := make([]pvpwire.QueuePlayerSnapshot, 0, len(queue))
|
||||
for _, queued := range queue {
|
||||
if queued.UserID == payload.UserID {
|
||||
@@ -302,7 +311,7 @@ func (m *manager) handleQueueCancel(payload pvpwire.QueueCancelPayload) {
|
||||
}
|
||||
next = append(next, queued)
|
||||
}
|
||||
m.queues[mode] = next
|
||||
m.queues[key] = next
|
||||
}
|
||||
}
|
||||
|
||||
@@ -547,7 +556,7 @@ func (m *manager) closeSession(sessionID, reason string) {
|
||||
}
|
||||
|
||||
func (m *manager) pruneExpiredQueueLocked(now time.Time) {
|
||||
for mode, queue := range m.queues {
|
||||
for key, queue := range m.queues {
|
||||
next := make([]pvpwire.QueuePlayerSnapshot, 0, len(queue))
|
||||
for _, queued := range queue {
|
||||
last := m.lastSeen[queued.UserID]
|
||||
@@ -557,7 +566,15 @@ func (m *manager) pruneExpiredQueueLocked(now time.Time) {
|
||||
}
|
||||
next = append(next, queued)
|
||||
}
|
||||
m.queues[mode] = next
|
||||
m.queues[key] = next
|
||||
}
|
||||
}
|
||||
|
||||
func newQueueKey(player pvpwire.QueuePlayerSnapshot) queueKey {
|
||||
return queueKey{
|
||||
FightMode: player.FightMode,
|
||||
IsVip: player.IsVip,
|
||||
IsDebug: player.IsDebug,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -50,6 +50,8 @@ type QueuePlayerSnapshot struct {
|
||||
Nick string `json:"nick"`
|
||||
FightMode uint32 `json:"fightMode"`
|
||||
Status uint32 `json:"status"`
|
||||
IsVip uint32 `json:"isVip"`
|
||||
IsDebug uint8 `json:"isDebug"`
|
||||
JoinedAtUnix int64 `json:"joinedAtUnix"`
|
||||
CatchTimes []uint32 `json:"catchTimes"`
|
||||
}
|
||||
|
||||
@@ -72,6 +72,19 @@ func (s *TowerService) Boss(towerLevel ...uint32) []model.BaseTowerConfig {
|
||||
return config
|
||||
}
|
||||
|
||||
func (s *TowerService) EnabledLevels() []uint32 {
|
||||
var config []model.BaseTowerConfig
|
||||
dbm_enable(s.Model).OrderAsc("tower_level").Cache(gdb.CacheOption{
|
||||
Force: false,
|
||||
}).Scan(&config)
|
||||
|
||||
levels := make([]uint32, 0, len(config))
|
||||
for _, item := range config {
|
||||
levels = append(levels, item.TowerLevel)
|
||||
}
|
||||
return levels
|
||||
}
|
||||
|
||||
func NewTower1Service() *TowerService {
|
||||
return NewTowerService(TowerType1)
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package service
|
||||
|
||||
import (
|
||||
"blazing/cool"
|
||||
configservice "blazing/modules/config/service"
|
||||
"blazing/modules/player/model"
|
||||
"errors"
|
||||
"strings"
|
||||
@@ -27,6 +28,19 @@ func (s *TaskService) ShopRequirementError() error {
|
||||
return errors.New("请先完成试炼任务50")
|
||||
}
|
||||
|
||||
var darkTask *model.Task
|
||||
s.dbm(s.Model).Where("task_id", 110).Scan(&darkTask)
|
||||
darkTaskBits := bitset32.New(0)
|
||||
if darkTask != nil {
|
||||
darkTaskBits = bitset32.From(darkTask.Data)
|
||||
}
|
||||
|
||||
for _, level := range configservice.NewTower110Service().EnabledLevels() {
|
||||
if !darkTaskBits.Test(uint(level)) {
|
||||
return errors.New("请先完成暗黑门全部已开放关卡")
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user