"refactor(socket): 添加玩家断开连接时的登录状态标记并优化刷怪逻辑"
This commit is contained in:
@@ -1,360 +0,0 @@
|
||||
package entity
|
||||
|
||||
// import (
|
||||
// "context"
|
||||
// "database/sql"
|
||||
// "errors"
|
||||
// "fmt"
|
||||
// "log"
|
||||
// "sync"
|
||||
// "time"
|
||||
|
||||
// )
|
||||
|
||||
// // Server 游戏服务器核心类,管理玩家、星球和游戏逻辑
|
||||
// type Server struct {
|
||||
// players map[int64]*entity.Player
|
||||
// planets map[int64]*planet.Planet
|
||||
// mutex sync.RWMutex
|
||||
// gameRepo repo.GameResourceRepo
|
||||
// serverRepo repo.ServerRepo
|
||||
// accountRepo repo.AccountRepo
|
||||
// playerInfoRepo repo.PlayerInfoRepo
|
||||
// playerItemRepo repo.PlayerItemInfoRepo
|
||||
// petRepo repo.PetRepo
|
||||
// }
|
||||
|
||||
// // NewServer 创建新的游戏服务器实例
|
||||
// func NewServer(
|
||||
// gameRepo repo.GameResourceRepo,
|
||||
// serverRepo repo.ServerRepo,
|
||||
// accountRepo repo.AccountRepo,
|
||||
// playerInfoRepo repo.PlayerInfoRepo,
|
||||
// playerItemRepo repo.PlayerItemInfoRepo,
|
||||
// petRepo repo.PetRepo,
|
||||
// ) *Server {
|
||||
// s := &Server{
|
||||
// players: make(map[int64]*entity.Player),
|
||||
// planets: make(map[int64]*planet.Planet),
|
||||
// gameRepo: gameRepo,
|
||||
// serverRepo: serverRepo,
|
||||
// accountRepo: accountRepo,
|
||||
// playerInfoRepo: playerInfoRepo,
|
||||
// playerItemRepo: playerItemRepo,
|
||||
// petRepo: petRepo,
|
||||
// }
|
||||
// s.initializePlanets()
|
||||
// return s
|
||||
// }
|
||||
|
||||
// // initializePlanets 初始化所有星球
|
||||
// func (s *Server) initializePlanets() {
|
||||
// maps := s.gameRepo.GetAllMaps()
|
||||
// for _, config := range maps {
|
||||
// planet := s.generatePlanet(config)
|
||||
// s.planets[planet.GetId()] = planet
|
||||
// }
|
||||
// }
|
||||
|
||||
// // generatePlanet 根据地图配置生成星球
|
||||
// func (s *Server) generatePlanet(config *mapInfo.MapXmlModel) *planet.Planet {
|
||||
// entries := config.GetEntries()
|
||||
// positions := make(map[int64]structs.Point)
|
||||
|
||||
// if len(entries) == 0 {
|
||||
// positions = make(map[int64]structs.Point)
|
||||
// } else {
|
||||
// for _, entry := range entries {
|
||||
// positions[entry.GetFromMap()] = s.generatePoint(entry)
|
||||
// }
|
||||
// }
|
||||
|
||||
// return planet.NewPlanet(
|
||||
// s,
|
||||
// int64(config.GetId()),
|
||||
// config.GetName(),
|
||||
// structs.Point{X: config.GetX(), Y: config.GetY()},
|
||||
// positions,
|
||||
// s.gameRepo.CanMapRefresh(config.GetId()),
|
||||
// )
|
||||
// }
|
||||
|
||||
// // generatePoint 从入口配置生成点坐标
|
||||
// func (s *Server) generatePoint(xml *mapInfo.EntryXmlModel) structs.Point {
|
||||
// return structs.Point{X: xml.GetPosX(), Y: xml.GetPosY()}
|
||||
// }
|
||||
|
||||
// // GetPlayer 获取玩家信息
|
||||
// func (s *Server) GetPlayer(accountID int64) (*entity.Player, error) {
|
||||
// s.mutex.RLock()
|
||||
// defer s.mutex.RUnlock()
|
||||
|
||||
// player, exists := s.players[accountID]
|
||||
// if !exists {
|
||||
// return nil, errors.New("玩家不存在")
|
||||
// }
|
||||
// return player, nil
|
||||
// }
|
||||
|
||||
// // GetPlanet 获取星球信息
|
||||
// func (s *Server) GetPlanet(planetID int64) (*planet.Planet, error) {
|
||||
// s.mutex.RLock()
|
||||
// defer s.mutex.RUnlock()
|
||||
|
||||
// planet, exists := s.planets[planetID]
|
||||
// if !exists {
|
||||
// return nil, errors.New("星球不存在")
|
||||
// }
|
||||
// return planet, nil
|
||||
// }
|
||||
|
||||
// // GetDefaultPlanet 获取默认星球
|
||||
// func (s *Server) GetDefaultPlanet() (*planet.Planet, error) {
|
||||
// s.mutex.RLock()
|
||||
// defer s.mutex.RUnlock()
|
||||
|
||||
// planet, exists := s.planets[1] // 假设1是默认星球ID
|
||||
// if !exists {
|
||||
// return nil, errors.New("未找到默认星球")
|
||||
// }
|
||||
// return planet, nil
|
||||
// }
|
||||
|
||||
// // PlayerEnter 玩家加入服务器
|
||||
// func (s *Server) PlayerEnter(player *entity.Player) {
|
||||
// s.mutex.Lock()
|
||||
// defer s.mutex.Unlock()
|
||||
|
||||
// s.players[player.GetAccountID()] = player
|
||||
// }
|
||||
|
||||
// // PlayerOffline 玩家离线处理
|
||||
// func (s *Server) PlayerOffline(player *entity.Player) {
|
||||
// s.mutex.Lock()
|
||||
// defer s.mutex.Unlock()
|
||||
|
||||
// // 清理缓存会话数据
|
||||
// if err := s.accountRepo.RemoveSessionID(player.GetSessionID()); err != nil {
|
||||
// log.Printf("清除会话ID失败: %v", err)
|
||||
// }
|
||||
|
||||
// // 清理登录绑定服务器
|
||||
// if err := s.serverRepo.CancelRecordAccount(player.GetAccountID()); err != nil {
|
||||
// log.Printf("取消账号绑定失败: %v", err)
|
||||
// }
|
||||
|
||||
// // 从玩家列表中移除
|
||||
// delete(s.players, player.GetAccountID())
|
||||
// }
|
||||
|
||||
// // BroadcastMessage 广播消息给所有在线玩家
|
||||
// func (s *Server) BroadcastMessage(message *net.OutboundMessage) {
|
||||
// s.mutex.RLock()
|
||||
// defer s.mutex.RUnlock()
|
||||
|
||||
// for _, player := range s.players {
|
||||
// if player.IsOnline() {
|
||||
// player.SendMessage(message)
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// // BroadcastMessageWithFilter 按条件广播消息给在线玩家
|
||||
// func (s *Server) BroadcastMessageWithFilter(message *net.OutboundMessage, filter func(*entity.Player) bool) {
|
||||
// s.mutex.RLock()
|
||||
// defer s.mutex.RUnlock()
|
||||
|
||||
// for _, player := range s.players {
|
||||
// if player.IsOnline() && filter(player) {
|
||||
// player.SendMessage(message)
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// // GeneratePetEntity 生成宠物实体
|
||||
// func (s *Server) GeneratePetEntity(
|
||||
// playerID int64,
|
||||
// petTypeID int,
|
||||
// individualValue int16,
|
||||
// nature int,
|
||||
// abilityTypeEnum int,
|
||||
// isShiny bool,
|
||||
// level int,
|
||||
// ) (*pet.PetEntity, error) {
|
||||
// if level < 1 || level > 100 {
|
||||
// return nil, fmt.Errorf("精灵等级必须在1到100之间, level: %d", level)
|
||||
// }
|
||||
|
||||
// petInfo, err := s.gameRepo.GetMonsterByID(petTypeID)
|
||||
// if err != nil {
|
||||
// return nil, fmt.Errorf("无效的精灵ID, pet_id: %d, 错误: %v", petTypeID, err)
|
||||
// }
|
||||
|
||||
// firstSkillInfo, err := s.gameRepo.GetPetFirstSkillID(petTypeID, level)
|
||||
// if err != nil {
|
||||
// return nil, fmt.Errorf("精灵没有初始技能, pet_id: %d, 错误: %v", petTypeID, err)
|
||||
// }
|
||||
|
||||
// zero := int16(0)
|
||||
|
||||
// pet := pet.NewPetEntityBuilder()
|
||||
// .WithAsset(petInfo)
|
||||
// .WithLevelToExp(s.gameRepo.GetLevelToExp())
|
||||
// .WithPlayerID(playerID)
|
||||
// .WithCapturePlayerID(playerID)
|
||||
// .WithCaptureTime(time.Now().Unix())
|
||||
// .WithCaptureMap(0) // 假设0是默认地图ID
|
||||
// .WithCaptureRect(0) // 假设0是默认区域
|
||||
// .WithCaptureLevel(level)
|
||||
// .WithIndividualValue(individualValue)
|
||||
// .WithNature(nature)
|
||||
// .WithAbilityTypeEnum(abilityTypeEnum)
|
||||
// .WithIsShiny(isShiny)
|
||||
// .WithLevel(level)
|
||||
// .WithCurrentExp(0)
|
||||
// .WithEvHp(zero)
|
||||
// .WithEvAttack(zero)
|
||||
// .WithEvDefense(zero)
|
||||
// .WithEvSpecialAttack(zero)
|
||||
// .WithEvSpecialDefense(zero)
|
||||
// .WithEvSpeed(zero)
|
||||
// .WithSkill1ID(firstSkillInfo[0].GetId())
|
||||
// .WithSkill1Pp(firstSkillInfo[0].GetMaxPp())
|
||||
// .WithSkill2ID(firstSkillInfo[1].GetId())
|
||||
// .WithSkill2Pp(firstSkillInfo[1].GetMaxPp())
|
||||
// .WithSkill3ID(firstSkillInfo[2].GetId())
|
||||
// .WithSkill3Pp(firstSkillInfo[2].GetMaxPp())
|
||||
// .WithSkill4ID(firstSkillInfo[3].GetId())
|
||||
// .WithSkill4Pp(firstSkillInfo[3].GetMaxPp())
|
||||
// .WithIndividualGuarantee(0)
|
||||
// .WithNatureGuarantee(0)
|
||||
// .Build()
|
||||
|
||||
// if err := s.CalculatePetPanel(pet); err != nil {
|
||||
// return nil, err
|
||||
// }
|
||||
|
||||
// return pet, nil
|
||||
// }
|
||||
|
||||
// // CalculatePetPanel 计算宠物面板属性
|
||||
// func (s *Server) CalculatePetPanel(petEntity *pet.PetEntity) error {
|
||||
// natureInfo, err := s.gameRepo.GetNatureInfoByID(petEntity.GetNature())
|
||||
// if err != nil {
|
||||
// return fmt.Errorf("无效的性格ID, nature: %d, 错误: %v", petEntity.GetNature(), err)
|
||||
// }
|
||||
|
||||
// hp := util.CalculatePetHPPanelSize(
|
||||
// petEntity.GetAsset().GetHp(),
|
||||
// petEntity.GetIndividualValue(),
|
||||
// petEntity.GetLevel(),
|
||||
// petEntity.GetEvHp(),
|
||||
// )
|
||||
|
||||
// attack := util.CalculatePetPanelSize(
|
||||
// petEntity.GetAsset().GetAtk(),
|
||||
// petEntity.GetIndividualValue(),
|
||||
// petEntity.GetLevel(),
|
||||
// petEntity.GetEvHp(),
|
||||
// natureInfo.GetAttackCorrect(),
|
||||
// )
|
||||
|
||||
// defense := util.CalculatePetPanelSize(
|
||||
// petEntity.GetAsset().GetDef(),
|
||||
// petEntity.GetIndividualValue(),
|
||||
// petEntity.GetLevel(),
|
||||
// petEntity.GetEvHp(),
|
||||
// natureInfo.GetDefenseCorrect(),
|
||||
// )
|
||||
|
||||
// specialAttack := util.CalculatePetPanelSize(
|
||||
// petEntity.GetAsset().GetSpAtk(),
|
||||
// petEntity.GetIndividualValue(),
|
||||
// petEntity.GetLevel(),
|
||||
// petEntity.GetEvHp(),
|
||||
// natureInfo.GetSaCorrect(),
|
||||
// )
|
||||
|
||||
// specialDefense := util.CalculatePetPanelSize(
|
||||
// petEntity.GetAsset().GetSpDef(),
|
||||
// petEntity.GetIndividualValue(),
|
||||
// petEntity.GetLevel(),
|
||||
// petEntity.GetEvHp(),
|
||||
// natureInfo.GetSdCorrect(),
|
||||
// )
|
||||
|
||||
// speed := util.CalculatePetPanelSize(
|
||||
// petEntity.GetAsset().GetSpd(),
|
||||
// petEntity.GetIndividualValue(),
|
||||
// petEntity.GetLevel(),
|
||||
// petEntity.GetEvHp(),
|
||||
// natureInfo.GetSpeedCorrect(),
|
||||
// )
|
||||
|
||||
// petEntity.SetMaxHp(hp)
|
||||
// petEntity.SetCurrentHp(hp)
|
||||
// petEntity.SetAttack(attack)
|
||||
// petEntity.SetDefense(defense)
|
||||
// petEntity.SetSpecialAttack(specialAttack)
|
||||
// petEntity.SetSpecialDefense(specialDefense)
|
||||
// petEntity.SetSpeed(speed)
|
||||
|
||||
// return nil
|
||||
// }
|
||||
|
||||
// // SavePlayer 保存玩家信息到数据库
|
||||
// func (s *Server) SavePlayer(player *entity.Player) (bool, error) {
|
||||
// ctx := context.Background()
|
||||
// tx, err := s.playerInfoRepo.BeginTransaction(ctx)
|
||||
// if err != nil {
|
||||
// return false, fmt.Errorf("开始事务失败: %v", err)
|
||||
// }
|
||||
// defer func() {
|
||||
// if r := recover(); r != nil {
|
||||
// tx.Rollback()
|
||||
// log.Printf("保存玩家时发生panic: %v", r)
|
||||
// } else if err != nil {
|
||||
// tx.Rollback()
|
||||
// } else {
|
||||
// tx.Commit()
|
||||
// }
|
||||
// }()
|
||||
|
||||
// playerID := player.GetGameID()
|
||||
// pets := player.GetPetBag().GetUsedPets()
|
||||
// items := player.GetItemBag().GetItems()
|
||||
|
||||
// // 保存玩家信息
|
||||
// if err := s.playerInfoRepo.Save(ctx, tx, player); err != nil {
|
||||
// return false, fmt.Errorf("保存玩家信息失败: %v", err)
|
||||
// }
|
||||
|
||||
// // 保存精灵信息
|
||||
// if err := s.petRepo.SaveAll(ctx, tx, playerID, pets); err != nil {
|
||||
// return false, fmt.Errorf("保存精灵信息失败: %v", err)
|
||||
// }
|
||||
|
||||
// // 保存玩家背包信息
|
||||
// if err := s.playerItemRepo.SaveAll(ctx, tx, playerID, items); err != nil {
|
||||
// return false, fmt.Errorf("保存背包信息失败: %v", err)
|
||||
// }
|
||||
|
||||
// return true, nil
|
||||
// }
|
||||
|
||||
// // Destroy 销毁服务器,清理资源
|
||||
// func (s *Server) Destroy() error {
|
||||
// // 保存所有玩家数据
|
||||
// s.mutex.RLock()
|
||||
// for _, player := range s.players {
|
||||
// go func(p *entity.Player) {
|
||||
// if _, err := s.SavePlayer(p); err != nil {
|
||||
// log.Printf("保存玩家 %d 数据失败: %v", p.GetAccountID(), err)
|
||||
// }
|
||||
// }(player)
|
||||
// }
|
||||
// s.mutex.RUnlock()
|
||||
|
||||
// log.Println("Destroying server ...")
|
||||
// return nil
|
||||
// }
|
||||
@@ -50,6 +50,7 @@ func (s *Server) OnClose(c gnet.Conn, _ error) (action gnet.Action) {
|
||||
t := v.GetPlayer()
|
||||
if t != nil {
|
||||
glog.Debug(context.Background(), t.UserID, "断开连接")
|
||||
t.IsLogin = false
|
||||
cool.Mainplayer.Delete(t.UserID)
|
||||
share.ShareManager.DeleteUserOnline(t.UserID) //设置用户登录服务器
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@ func (h *Controller) MapEnter(data *maps.InInfo, c *entity.Player) (result *maps
|
||||
case <-ticker.C:
|
||||
// 刷新当前地图的怪物
|
||||
if !c.IsFighting && c.MapId != 0 {
|
||||
spawnMonsters(currentMap, c)
|
||||
spawnMonsters(c)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -85,28 +85,58 @@ func (h *Controller) MapList(data *maps.ListMapPlayerInboundInfo, c *entity.Play
|
||||
}
|
||||
|
||||
// 刷怪具体实现
|
||||
func spawnMonsters(mapID int, c *entity.Player) {
|
||||
func spawnMonsters(c *entity.Player) {
|
||||
// 获取当前地图的怪物配置
|
||||
|
||||
if mservice.NewMonsterService().GetId(c.MapId) == 0 {
|
||||
if c == nil || mservice.NewMonsterService().GetId(c.MapId) == 0 { //用户离线
|
||||
return
|
||||
}
|
||||
if !c.IsLogin {
|
||||
defer func() {
|
||||
|
||||
if c.StopChan != nil {
|
||||
close(c.StopChan)
|
||||
c.StopChan = nil
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
// 创建数据包
|
||||
tt := handler.NewTomeeHeader(2004, c.UserID)
|
||||
t1 := genMonster(c.MapId)
|
||||
|
||||
c.SendPack(tt.Pack(&t1))
|
||||
}
|
||||
|
||||
func genMonster(id uint32) maps.OgreInfo {
|
||||
// 设置怪物信息
|
||||
t1 := maps.OgreInfo{}
|
||||
//copy(t1.Data[:], monsterConfig) // 使用地图对应的怪物配置
|
||||
var localMenu = make([]int, 0)
|
||||
for i := 7; i <= 448; i++ {
|
||||
if bitsCount(i) == 3 {
|
||||
localMenu = append(localMenu, i)
|
||||
}
|
||||
}
|
||||
|
||||
for i := 0; i < 3; i++ {
|
||||
|
||||
ttt := maps.OgrePetInfo{}
|
||||
ttt.Id = mservice.NewMonsterService().GetId(c.MapId)
|
||||
ttt.Id = mservice.NewMonsterService().GetId(id)
|
||||
|
||||
ttt.Shiny = uint32(i + 1)
|
||||
//t1.Data[i] = mservice.NewMonsterService().GetId(c.MapId)
|
||||
t1.Data[i] = ttt
|
||||
}
|
||||
// 发送数据包
|
||||
c.SendPack(tt.Pack(&t1))
|
||||
|
||||
return t1
|
||||
}
|
||||
|
||||
// 计算整数的二进制1的个数(对应Java的Integer.bitCount)
|
||||
func bitsCount(n int) int {
|
||||
count := 0
|
||||
for n > 0 {
|
||||
count += n & 1
|
||||
n >>= 1
|
||||
}
|
||||
return count
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user