package model import ( "rocommon/util" "roserver/baseserver/aoi" "roserver/baseserver/model" "roserver/serverproto" ) type MapRole struct { uid uint64 cliID model.ClientID //gate selfObj *aoi.AoiObject pos serverproto.Position targetPos serverproto.Position ownerUid uint64 isHide bool unitType int32 aoiMap *AoiMap //测试发送全量移动数据 bTestSend bool showInfo *serverproto.PlayerShowInfo IsMaster bool } func newMapRole(uid uint64, position *serverproto.Position, aoiMap *AoiMap, ownerUid uint64) *MapRole { mapRole := &MapRole{ uid: uid, ownerUid: ownerUid, selfObj: nil, bTestSend: false, aoiMap: aoiMap, showInfo: &serverproto.PlayerShowInfo{}, } mapRole.pos = *position return mapRole } func (this *MapRole) isSummon() bool { return this.ownerUid > 0 } //todo // gate消息需要合并 func (this *MapRole) syncSurrounding() { //ghost只更新坐标位置,不发送消息 if !this.IsMaster { return } //通知其他玩家 enterOtherNtfMsg := &serverproto.SCPlayerEnterNtf{} enterOtherNtfMsg.Players = append(enterOtherNtfMsg.Players, &serverproto.Player{Uid: this.uid, Pos: &serverproto.Position{X: this.pos.X, Y: this.pos.Y, Z: this.pos.Z}, UType: this.unitType}) //通知自己 enterSelfNtfMsg := &serverproto.SCPlayerEnterNtf{} var serverUidList = map[string][]uint64{} //通知别的玩家显示当前玩家 for _, data := range this.selfObj.AoiInfo.EnterSet.List() { if data.(uint64) == this.uid { continue } otherRole := this.aoiMap.getPlayer(data.(uint64)) if otherRole == nil { continue } //判断当前别的玩家的移动列表中的人数是否超过上限 if !otherRole.selfObj.AoiInfo.MoveNoNtfSet.Has(this.uid) && !otherRole.isSummon() { //todo...这边可以对相同的消息做缓存处理 //todo... 如果otherRole在同一个gate可以通过压缩的方式来提升效率 //otherRole.SendGate(enterOtherNtfMsg) //添加到同服务器列表中 serviceID := otherRole.cliID.ServiceID serverUidList[serviceID] = append(serverUidList[serviceID], otherRole.cliID.SessID) if len(serverUidList[serviceID]) >= MAX_SEND_NUM { this.SendGate(enterOtherNtfMsg, serverUidList[serviceID], true) serverUidList[serviceID] = []uint64{} } } //判断召唤物对自己是否可见 if otherRole.isHide { if otherRole.ownerUid == this.uid { enterSelfNtfMsg.Players = append(enterSelfNtfMsg.Players, &serverproto.Player{ Uid: otherRole.uid, Pos: &otherRole.pos, UType: otherRole.unitType, }) } } else { enterSelfNtfMsg.Players = append(enterSelfNtfMsg.Players, &serverproto.Player{ Uid: otherRole.uid, Pos: &otherRole.pos, UType: otherRole.unitType, }) } //通知自己显示别的玩家 if len(enterSelfNtfMsg.Players) >= MAX_SEND_NUM { this.SendGate(enterSelfNtfMsg, nil, true) enterSelfNtfMsg.Players = enterSelfNtfMsg.Players[0:0] } } //剩余未发送部分处理 for key, _ := range serverUidList { if len(serverUidList[key]) > 0 && key != "" { SendGate(key, enterOtherNtfMsg, serverUidList[key], true) } } //通知自己显示别的玩家 if len(enterSelfNtfMsg.Players) > 0 { this.SendGate(enterSelfNtfMsg, nil, true) } } func (this *MapRole) summonSyncSurrounding() { //通知其他玩家 enterOtherNtfMsg := &serverproto.SCPlayerEnterNtf{} enterOtherNtfMsg.Players = append(enterOtherNtfMsg.Players, &serverproto.Player{Uid: this.uid, Pos: &serverproto.Position{X: this.pos.X, Y: this.pos.Y, Z: this.pos.Z}, UType: this.unitType}) var serverUidList = map[string][]uint64{} //通知别的玩家显示当前玩家 for _, data := range this.selfObj.AoiInfo.MoveSet.List() { if data.(uint64) == this.uid { continue } otherRole := this.aoiMap.getPlayer(data.(uint64)) if otherRole == nil { continue } //判断当前别的玩家的移动列表中的人数是否超过上限 if !otherRole.selfObj.AoiInfo.MoveNoNtfSet.Has(this.uid) && !otherRole.isSummon() { //todo...这边可以对相同的消息做缓存处理 //todo... 如果otherRole在同一个gate可以通过压缩的方式来提升效率 //otherRole.SendGate(enterOtherNtfMsg) //添加到同服务器列表中 serviceID := otherRole.cliID.ServiceID serverUidList[serviceID] = append(serverUidList[serviceID], otherRole.cliID.SessID) if len(serverUidList[serviceID]) >= MAX_SEND_NUM { this.SendGate(enterOtherNtfMsg, serverUidList[serviceID], true) serverUidList[serviceID] = []uint64{} } } } //剩余未发送部分处理 for key, _ := range serverUidList { if len(serverUidList[key]) > 0 && key != "" { SendGate(key, enterOtherNtfMsg, serverUidList[key], true) } } } //可见状态变更处理 func (this *MapRole) summonVisibleSyncSurrounding() { //通知其他玩家 var ntfMsg interface{} = nil if this.isHide { ntfMsg = &serverproto.SCPlayerLeaveNtf{} ntfMsg.(*serverproto.SCPlayerLeaveNtf).Players = append(ntfMsg.(*serverproto.SCPlayerLeaveNtf).Players, &serverproto.Player{Uid: this.uid, Pos: &serverproto.Position{X: this.pos.X, Y: this.pos.Y, Z: this.pos.Z}, UType: this.unitType}) } else { ntfMsg = &serverproto.SCPlayerEnterNtf{} ntfMsg.(*serverproto.SCPlayerEnterNtf).Players = append(ntfMsg.(*serverproto.SCPlayerEnterNtf).Players, &serverproto.Player{Uid: this.uid, Pos: &serverproto.Position{X: this.pos.X, Y: this.pos.Y, Z: this.pos.Z}, UType: this.unitType}) } var serverUidList = map[string][]uint64{} //通知别的玩家显示当前玩家 for _, data := range this.selfObj.AoiInfo.MoveSet.List() { if data.(uint64) == this.uid { continue } otherRole := this.aoiMap.getPlayer(data.(uint64)) if otherRole == nil || otherRole.isSummon() { continue } if this.isHide { } //这边可以对相同的消息做缓存处理 //如果otherRole在同一个gate可以通过压缩的方式来提升效率 //otherRole.SendGate(enterOtherNtfMsg) //添加到同服务器列表中 serviceID := otherRole.cliID.ServiceID serverUidList[serviceID] = append(serverUidList[serviceID], otherRole.cliID.SessID) if len(serverUidList[serviceID]) >= MAX_SEND_NUM { this.SendGate(ntfMsg, serverUidList[serviceID], true) serverUidList[serviceID] = []uint64{} } } //剩余未发送部分处理 for key, _ := range serverUidList { if len(serverUidList[key]) > 0 && key != "" { SendGate(key, ntfMsg, serverUidList[key], true) } } } func (this *MapRole) playerMove(pos *serverproto.Position) { updateObj, ret := this.aoiMap.aoi.Update(this.uid, *this.aoiMap.aoi.AoiArea, pos.X, pos.Y, this.IsMaster) if updateObj == nil { return } this.pos = *pos //只处理master if !this.IsMaster { return } //只发送移动信息 if !ret { //MoveOnlySet处理 this.playerMoveNtf() } else { //enter处理 this.syncSurrounding() //位置同步信息 //MoveOnlySet处理 this.playerMoveNtf() //LeaveSet处理 //通知离开视野的玩家 this.playerLeaveNtf() } } func (this *MapRole) playerMoveNtf() { //MoveOnlySet处理 //位置同步信息 syncOtherNtfMsg := &serverproto.SCSyncPlayersNtf{} syncOtherNtfMsg.Players = append(syncOtherNtfMsg.Players, &serverproto.Player{Uid: this.uid, Pos: &serverproto.Position{X: this.pos.X, Y: this.pos.Y, Z: this.pos.Z}, UType: this.unitType}) var serverUidList = map[string][]uint64{} for _, data := range this.selfObj.AoiInfo.MoveOnlySet.List() { otherRole := this.aoiMap.getPlayer(data.(uint64)) //移动消息 不发送给召唤物 if otherRole.isSummon() { continue } if otherRole != nil && !otherRole.selfObj.AoiInfo.MoveNoNtfSet.Has(this.uid) { serviceID := otherRole.cliID.ServiceID if _, ok := serverUidList[serviceID]; ok { serverUidList[serviceID] = append(serverUidList[serviceID], otherRole.cliID.SessID) } else { serverUidList[serviceID] = []uint64{otherRole.cliID.SessID} } if len(serverUidList[serviceID]) >= MAX_SEND_NUM { SendGate(serviceID, syncOtherNtfMsg, serverUidList[serviceID], true) serverUidList[serviceID] = []uint64{} } } } //剩余未发送部分处理 for key, _ := range serverUidList { if len(serverUidList[key]) > 0 && key != "" { SendGate(key, syncOtherNtfMsg, serverUidList[key], true) serverUidList[key] = serverUidList[key][0:0] } } } func (this *MapRole) playerLeaveNtf() { //LeaveSet处理 //通知离开视野的玩家 leaveSelfNtfMsg := &serverproto.SCPlayerLeaveNtf{} leaveOtherNtfMsg := &serverproto.SCPlayerLeaveNtf{} leaveOtherNtfMsg.Players = append(leaveOtherNtfMsg.Players, &serverproto.Player{Uid: this.uid, Pos: &serverproto.Position{X: this.pos.X, Y: this.pos.Y, Z: this.pos.Z}, UType: this.unitType}) var serverLeaveUidList = map[string][]uint64{} for _, data := range this.selfObj.AoiInfo.LeaveSet.List() { otherRole := this.aoiMap.getPlayer(data.(uint64)) if otherRole != nil { //移除别的玩家中移动队列中的自己(否则可能会导致发送多次离开消息) //1.别人通知自己离开视野 2.自己通知该玩家离开视野 if otherRole.selfObj.AoiInfo.MoveNoNtfSet.Has(this.uid) { otherRole.selfObj.AoiInfo.MoveNoNtfSet.Remove(this.uid) } else { serviceID := otherRole.cliID.ServiceID if _, ok := serverLeaveUidList[serviceID]; ok { serverLeaveUidList[serviceID] = append(serverLeaveUidList[serviceID], otherRole.cliID.SessID) } else { serverLeaveUidList[serviceID] = []uint64{otherRole.cliID.SessID} } if len(serverLeaveUidList[serviceID]) >= MAX_SEND_NUM { SendGate(serviceID, leaveOtherNtfMsg, serverLeaveUidList[serviceID], false) serverLeaveUidList[serviceID] = []uint64{} } } otherRole.selfObj.AoiInfo.MoveSet.Remove(this.uid) if this.selfObj.AoiInfo.MoveNoNtfSet.Has(otherRole.uid) { this.selfObj.AoiInfo.MoveSet.Remove(otherRole.uid) this.selfObj.AoiInfo.MoveNoNtfSet.Remove(otherRole.uid) } leaveSelfNtfMsg.Players = append(leaveSelfNtfMsg.Players, &serverproto.Player{Uid: otherRole.uid, UType: otherRole.unitType}) if len(leaveSelfNtfMsg.Players) >= MAX_SEND_NUM { this.SendGate(leaveSelfNtfMsg, nil, true) leaveSelfNtfMsg.Players = leaveSelfNtfMsg.Players[0:0] } } } //剩余未发送部分处理 for key, _ := range serverLeaveUidList { if len(serverLeaveUidList[key]) > 0 && key != "" { SendGate(key, leaveOtherNtfMsg, serverLeaveUidList[key], true) } } //发送给自己有别的玩家离开自己的视野 if len(leaveSelfNtfMsg.Players) > 0 { this.SendGate(leaveSelfNtfMsg, nil, true) } } func (this *MapRole) playerLeave() bool { this.bTestSend = false util.DebugF("playerLeave uid=%v", this.uid) leaveNtfMsg := &serverproto.SCPlayerLeaveNtf{} leaveNtfMsg.Players = append(leaveNtfMsg.Players, &serverproto.Player{ Uid: this.uid, Pos: &this.pos, UType: this.unitType, }) //通知自己离开地图 this.SendGate(leaveNtfMsg, nil, true) leaveList := this.aoiMap.aoi.LeaveNode(this.uid) if leaveList == nil || len(leaveList) <= 0 { return true } util.DebugF("playerLeave uid=%v leaveNotifyList=%v", this.uid, leaveList) //通知其他玩家 for _, data := range leaveList { otherRole := this.aoiMap.getPlayer(data.(uint64)) if otherRole != nil && otherRole.unitType != int32(UnityType_Boss) { otherRole.selfObj.AoiInfo.MoveSet.Remove(this.uid) otherRole.selfObj.AoiInfo.MoveOnlySet.Remove(this.uid) this.selfObj.AoiInfo.MoveNoNtfSet.Remove(otherRole.uid) if this.IsMaster { otherRole.SendGate(leaveNtfMsg, nil, true) } } } return true } //视野范围内玩家操作通知(avatar,action) func (this *MapRole) playerViewNtf(ntfMsg interface{}) { var serverUidList = map[string][]uint64{} for _, data := range this.selfObj.AoiInfo.MoveSet.List() { otherRole := this.aoiMap.getPlayer(data.(uint64)) if otherRole != nil && !otherRole.selfObj.AoiInfo.MoveNoNtfSet.Has(this.uid) { serviceID := otherRole.cliID.ServiceID if _, ok := serverUidList[serviceID]; ok { serverUidList[serviceID] = append(serverUidList[serviceID], otherRole.cliID.SessID) } else { serverUidList[serviceID] = []uint64{otherRole.cliID.SessID} } if len(serverUidList[serviceID]) >= MAX_SEND_NUM { SendGate(serviceID, ntfMsg, serverUidList[serviceID], true) serverUidList[serviceID] = []uint64{} } } } //剩余未发送部分处理 for key, _ := range serverUidList { if len(serverUidList[key]) > 0 && key != "" { SendGate(key, ntfMsg, serverUidList[key], true) serverUidList[key] = serverUidList[key][0:0] } } util.DebugF("showChange MoveSet=%v", this.selfObj.AoiInfo.MoveSet.List()) } func (this *MapRole) showChange(info *serverproto.PlayerShowInfo) bool { if info == nil { return false } if info.NickName != "" { this.showInfo.NickName = info.NickName } if info.FashionData != nil { this.showInfo.FashionData = info.FashionData } //MoveSet处理 //地图形象显示变更通知 changeNtfMsg := &serverproto.SCMapOtherPlayersInfoNtf{} changeNtfMsg.InfoList = append(changeNtfMsg.InfoList, info) this.playerViewNtf(changeNtfMsg) return true } func (this *MapRole) mapDoDoAction(actionId int32, pos *serverproto.Position) bool { actionNtfMsg := &serverproto.SCPlayerActionNtf{ ActionId: actionId, Uid: this.uid, Pos: pos, } this.playerViewNtf(actionNtfMsg) return true } func (this *MapRole) TestUpdate() { if this.bTestSend { this.TestSyncAllPlayer() } } func (this *MapRole) TestSyncAllPlayer() { //todo... // for test testNtfMsg := &serverproto.SCGMSyncAllPlayerNtf{} this.SendGate(testNtfMsg, nil, true) return for _, data := range this.aoiMap.aoi.GetAllNode() { if data == nil || data.Id == this.uid { continue } tempPos := this.aoiMap.getPlayer(data.Id).pos testNtfMsg.Players = append(testNtfMsg.Players, &serverproto.Player{ Uid: data.Id, Pos: &tempPos, }) if len(testNtfMsg.Players) >= MAX_SEND_NUM { this.SendGate(testNtfMsg, nil, true) testNtfMsg.Players = testNtfMsg.Players[0:0] } } if len(testNtfMsg.Players) > 0 { this.SendGate(testNtfMsg, nil, true) } }