Files
hk4e/gs/game/tick_manager.go
huangxiaolei 7384fca483 优化代码
2022-12-05 23:05:57 +08:00

342 lines
12 KiB
Go

package game
import (
"time"
"hk4e/gs/constant"
"hk4e/gs/model"
"hk4e/pkg/logger"
"hk4e/pkg/random"
"hk4e/protocol/cmd"
"hk4e/protocol/proto"
)
// 游戏服务器定时帧管理器
type TickManager struct {
ticker *time.Ticker
tickCount uint64
}
func NewTickManager() (r *TickManager) {
r = new(TickManager)
r.ticker = time.NewTicker(time.Millisecond * 100)
logger.LOG.Info("game server tick start at: %v", time.Now().UnixMilli())
return r
}
func (t *TickManager) OnGameServerTick() {
t.tickCount++
now := time.Now().UnixMilli()
t.onTick100MilliSecond(now)
if t.tickCount%2 == 0 {
t.onTick200MilliSecond(now)
}
if t.tickCount%(10*1) == 0 {
t.onTickSecond(now)
}
if t.tickCount%(10*5) == 0 {
t.onTick5Second(now)
}
if t.tickCount%(10*10) == 0 {
t.onTick10Second(now)
}
if t.tickCount%(10*60) == 0 {
t.onTickMinute(now)
}
if t.tickCount%(10*60*10) == 0 {
t.onTick10Minute(now)
}
if t.tickCount%(10*3600) == 0 {
t.onTickHour(now)
}
if t.tickCount%(10*3600*24) == 0 {
t.onTickDay(now)
}
if t.tickCount%(10*3600*24*7) == 0 {
t.onTickWeek(now)
}
}
func (t *TickManager) onTickWeek(now int64) {
logger.LOG.Info("on tick week, time: %v", now)
}
func (t *TickManager) onTickDay(now int64) {
logger.LOG.Info("on tick day, time: %v", now)
}
func (t *TickManager) onTickHour(now int64) {
logger.LOG.Info("on tick hour, time: %v", now)
}
func (t *TickManager) onTick10Minute(now int64) {
for _, world := range WORLD_MANAGER.worldMap {
for _, player := range world.playerMap {
// 蓝球粉球
GAME_MANAGER.AddUserItem(player.PlayerID, []*UserItem{{ItemId: 223, ChangeCount: 1}}, true, 0)
GAME_MANAGER.AddUserItem(player.PlayerID, []*UserItem{{ItemId: 224, ChangeCount: 1}}, true, 0)
}
}
}
func (t *TickManager) onTickMinute(now int64) {
//t.gameManager.ServerAnnounceNotify(100, "test123")
for _, world := range WORLD_MANAGER.worldMap {
for _, player := range world.playerMap {
// 随机物品
allItemDataConfig := GAME_MANAGER.GetAllItemDataConfig()
count := random.GetRandomInt32(0, 4)
i := int32(0)
for itemId := range allItemDataConfig {
itemDataConfig, ok := allItemDataConfig[itemId]
if !ok {
logger.LOG.Error("config is nil, itemId: %v", itemId)
return
}
// TODO 3.0.0REL版本中 发送某些无效家具 可能会导致客户端背包家具界面卡死
if itemDataConfig.ItemEnumType == constant.ItemTypeConst.ITEM_FURNITURE {
continue
}
num := random.GetRandomInt32(1, 9)
GAME_MANAGER.AddUserItem(player.PlayerID, []*UserItem{{ItemId: uint32(itemId), ChangeCount: uint32(num)}}, true, 0)
i++
if i > count {
break
}
}
GAME_MANAGER.AddUserItem(player.PlayerID, []*UserItem{{ItemId: 102, ChangeCount: 30}}, true, 0)
GAME_MANAGER.AddUserItem(player.PlayerID, []*UserItem{{ItemId: 201, ChangeCount: 10}}, true, 0)
GAME_MANAGER.AddUserItem(player.PlayerID, []*UserItem{{ItemId: 202, ChangeCount: 100}}, true, 0)
GAME_MANAGER.AddUserItem(player.PlayerID, []*UserItem{{ItemId: 203, ChangeCount: 10}}, true, 0)
}
}
}
func (t *TickManager) onTick10Second(now int64) {
for _, world := range WORLD_MANAGER.worldMap {
for _, scene := range world.sceneMap {
for _, player := range scene.playerMap {
// PacketSceneTimeNotify
sceneTimeNotify := new(proto.SceneTimeNotify)
sceneTimeNotify.SceneId = player.SceneId
sceneTimeNotify.SceneTime = uint64(scene.GetSceneTime())
GAME_MANAGER.SendMsg(cmd.SceneTimeNotify, player.PlayerID, player.ClientSeq, sceneTimeNotify)
}
}
if !world.IsBigWorld() && (world.multiplayer || !world.owner.Pause) {
// 刷怪
scene := world.GetSceneById(3)
monsterEntityCount := 0
for _, entity := range scene.entityMap {
if entity.entityType == uint32(proto.ProtEntityType_PROT_ENTITY_TYPE_MONSTER) {
monsterEntityCount++
}
}
if monsterEntityCount < 30 {
monsterEntityId := t.createMonster(scene)
bigWorldOwner := USER_MANAGER.GetOnlineUser(1)
GAME_MANAGER.AddSceneEntityNotify(bigWorldOwner, proto.VisionType_VISION_TYPE_BORN, []uint32{monsterEntityId}, true)
}
}
for _, player := range world.playerMap {
if world.multiplayer || !world.owner.Pause {
// 改面板
team := player.TeamConfig.GetActiveTeam()
for _, avatarId := range team.AvatarIdList {
if avatarId == 0 {
break
}
avatar := player.AvatarMap[avatarId]
avatar.FightPropMap[uint32(constant.FightPropertyConst.FIGHT_PROP_CUR_ATTACK)] = 1000000
avatar.FightPropMap[uint32(constant.FightPropertyConst.FIGHT_PROP_CRITICAL)] = 1.0
GAME_MANAGER.UpdateUserAvatarFightProp(player.PlayerID, avatarId)
}
}
}
}
}
func (t *TickManager) onTick5Second(now int64) {
for _, world := range WORLD_MANAGER.worldMap {
if world.IsBigWorld() {
for applyUid := range world.owner.CoopApplyMap {
GAME_MANAGER.UserDealEnterWorld(world.owner, applyUid, true)
}
}
for _, player := range world.playerMap {
if world.multiplayer {
// 多人世界其他玩家的坐标位置广播
// PacketWorldPlayerLocationNotify
worldPlayerLocationNotify := new(proto.WorldPlayerLocationNotify)
for _, worldPlayer := range world.playerMap {
playerWorldLocationInfo := &proto.PlayerWorldLocationInfo{
SceneId: worldPlayer.SceneId,
PlayerLoc: &proto.PlayerLocationInfo{
Uid: worldPlayer.PlayerID,
Pos: &proto.Vector{
X: float32(worldPlayer.Pos.X),
Y: float32(worldPlayer.Pos.Y),
Z: float32(worldPlayer.Pos.Z),
},
Rot: &proto.Vector{
X: float32(worldPlayer.Rot.X),
Y: float32(worldPlayer.Rot.Y),
Z: float32(worldPlayer.Rot.Z),
},
},
}
worldPlayerLocationNotify.PlayerWorldLocList = append(worldPlayerLocationNotify.PlayerWorldLocList, playerWorldLocationInfo)
}
GAME_MANAGER.SendMsg(cmd.WorldPlayerLocationNotify, player.PlayerID, 0, worldPlayerLocationNotify)
// PacketScenePlayerLocationNotify
scene := world.GetSceneById(player.SceneId)
scenePlayerLocationNotify := new(proto.ScenePlayerLocationNotify)
scenePlayerLocationNotify.SceneId = player.SceneId
for _, scenePlayer := range scene.playerMap {
playerLocationInfo := &proto.PlayerLocationInfo{
Uid: scenePlayer.PlayerID,
Pos: &proto.Vector{
X: float32(scenePlayer.Pos.X),
Y: float32(scenePlayer.Pos.Y),
Z: float32(scenePlayer.Pos.Z),
},
Rot: &proto.Vector{
X: float32(scenePlayer.Rot.X),
Y: float32(scenePlayer.Rot.Y),
Z: float32(scenePlayer.Rot.Z),
},
}
scenePlayerLocationNotify.PlayerLocList = append(scenePlayerLocationNotify.PlayerLocList, playerLocationInfo)
}
GAME_MANAGER.SendMsg(cmd.ScenePlayerLocationNotify, player.PlayerID, 0, scenePlayerLocationNotify)
}
}
}
}
func (t *TickManager) onTickSecond(now int64) {
for _, world := range WORLD_MANAGER.worldMap {
for _, player := range world.playerMap {
// 世界里所有玩家的网络延迟广播
// PacketWorldPlayerRTTNotify
worldPlayerRTTNotify := new(proto.WorldPlayerRTTNotify)
worldPlayerRTTNotify.PlayerRttList = make([]*proto.PlayerRTTInfo, 0)
for _, worldPlayer := range world.playerMap {
playerRTTInfo := &proto.PlayerRTTInfo{Uid: worldPlayer.PlayerID, Rtt: worldPlayer.ClientRTT}
worldPlayerRTTNotify.PlayerRttList = append(worldPlayerRTTNotify.PlayerRttList, playerRTTInfo)
}
GAME_MANAGER.SendMsg(cmd.WorldPlayerRTTNotify, player.PlayerID, 0, worldPlayerRTTNotify)
}
}
}
func (t *TickManager) onTick200MilliSecond(now int64) {
// 耐力消耗
for _, world := range WORLD_MANAGER.worldMap {
for _, player := range world.playerMap {
GAME_MANAGER.StaminaHandler(player)
}
}
}
func (t *TickManager) onTick100MilliSecond(now int64) {
//// 伤害处理和转发
//for _, world := range t.gameManager.worldManager.worldMap {
// for _, scene := range world.sceneMap {
// scene.AttackHandler(t.gameManager)
// }
//}
// 服务器控制的模拟AI移动
//bigWorldOwner := t.gameManager.userManager.GetOnlineUser(1)
//bigWorld := t.gameManager.worldManager.GetBigWorld()
//bigWorldScene := bigWorld.GetSceneById(3)
//
//if len(bigWorldScene.playerMap) < 2 {
// return
//}
//if t.gameManager.worldManager.worldStatic.aiMoveCurrIndex >= len(t.gameManager.worldManager.worldStatic.aiMoveVectorList)-1 {
// return
//}
//t.gameManager.worldManager.worldStatic.aiMoveCurrIndex++
//
//entityMoveInfo := new(proto.EntityMoveInfo)
//activeAvatarId := bigWorldOwner.TeamConfig.GetActiveAvatarId()
//playerTeamEntity := bigWorldScene.GetPlayerTeamEntity(bigWorldOwner.PlayerID)
//entityMoveInfo.EntityId = playerTeamEntity.avatarEntityMap[activeAvatarId]
//entityMoveInfo.SceneTime = uint32(bigWorldScene.GetSceneTime())
//entityMoveInfo.ReliableSeq = uint32(bigWorldScene.GetSceneTime() / 100 * 100)
//entityMoveInfo.IsReliable = true
//oldPos := model.Vector{
// X: bigWorldOwner.Pos.X,
// Y: bigWorldOwner.Pos.Y,
// Z: bigWorldOwner.Pos.Z,
//}
//newPos := t.gameManager.worldManager.worldStatic.aiMoveVectorList[t.gameManager.worldManager.worldStatic.aiMoveCurrIndex]
//rotY := math.Atan2(newPos.X-oldPos.X, newPos.Z-oldPos.Z) / math.Pi * 180.0
//if rotY < 0.0 {
// rotY += 360.0
//}
//entityMoveInfo.MotionInfo = &proto.MotionInfo{
// Pos: &proto.Vector{
// X: float32(newPos.X),
// Y: float32(newPos.Y),
// Z: float32(newPos.Z),
// },
// Rot: &proto.Vector{
// X: 0.0,
// Y: float32(rotY),
// Z: 0.0,
// },
// Speed: &proto.Vector{
// X: float32((newPos.X - oldPos.X) * 10.0),
// Y: float32((newPos.Y - oldPos.Y) * 10.0),
// Z: float32((newPos.Z - oldPos.Z) * 10.0),
// },
// State: proto.MotionState_MOTION_STATE_RUN,
// RefPos: new(proto.Vector),
//}
//data, err := pb.Marshal(entityMoveInfo)
//if err != nil {
// logger.LOG.Error("build combat invocations entity move info error: %v", err)
// return
//}
//combatInvocationsNotify := new(proto.CombatInvocationsNotify)
//combatInvocationsNotify.InvokeList = []*proto.CombatInvokeEntry{{
// CombatData: data,
// ForwardType: proto.ForwardType_FORWARD_TYPE_TO_ALL_EXCEPT_CUR,
// ArgumentType: proto.CombatTypeArgument_COMBAT_TYPE_ARGUMENT_ENTITY_MOVE,
//}}
//t.gameManager.CombatInvocationsNotify(bigWorldOwner.PlayerID, bigWorldOwner, 0, combatInvocationsNotify)
}
func (t *TickManager) createMonster(scene *Scene) uint32 {
pos := &model.Vector{
X: 2747,
Y: 194,
Z: -1719,
}
fpm := map[uint32]float32{
uint32(constant.FightPropertyConst.FIGHT_PROP_CUR_HP): float32(72.91699),
uint32(constant.FightPropertyConst.FIGHT_PROP_PHYSICAL_SUB_HURT): float32(0.1),
uint32(constant.FightPropertyConst.FIGHT_PROP_CUR_DEFENSE): float32(505.0),
uint32(constant.FightPropertyConst.FIGHT_PROP_CUR_ATTACK): float32(45.679916),
uint32(constant.FightPropertyConst.FIGHT_PROP_ICE_SUB_HURT): float32(0.1),
uint32(constant.FightPropertyConst.FIGHT_PROP_BASE_ATTACK): float32(45.679916),
uint32(constant.FightPropertyConst.FIGHT_PROP_MAX_HP): float32(72.91699),
uint32(constant.FightPropertyConst.FIGHT_PROP_FIRE_SUB_HURT): float32(0.1),
uint32(constant.FightPropertyConst.FIGHT_PROP_ELEC_SUB_HURT): float32(0.1),
uint32(constant.FightPropertyConst.FIGHT_PROP_WIND_SUB_HURT): float32(0.1),
uint32(constant.FightPropertyConst.FIGHT_PROP_ROCK_SUB_HURT): float32(0.1),
uint32(constant.FightPropertyConst.FIGHT_PROP_GRASS_SUB_HURT): float32(0.1),
uint32(constant.FightPropertyConst.FIGHT_PROP_WATER_SUB_HURT): float32(0.1),
uint32(constant.FightPropertyConst.FIGHT_PROP_BASE_HP): float32(72.91699),
uint32(constant.FightPropertyConst.FIGHT_PROP_BASE_DEFENSE): float32(505.0),
}
entityId := scene.CreateEntityMonster(pos, 1, fpm)
return entityId
}