载具创建交互初步

This commit is contained in:
UnKownOwO
2022-12-14 23:21:19 +08:00
parent 5dd722d389
commit 3a2b82585f
5 changed files with 305 additions and 41 deletions

View File

@@ -37,7 +37,7 @@ func (r *RouteManager) doRoute(cmdId uint16, userId uint32, clientSeq uint32, pa
if player == nil {
logger.LOG.Error("player is nil, uid: %v", userId)
// 临时为了调试便捷搞的重连 生产环境请务必去除 不然新用户会一直重连不能进入
//GAME_MANAGER.ReconnectPlayer(userId)
// GAME_MANAGER.ReconnectPlayer(userId)
return
}
player.ClientSeq = clientSeq
@@ -112,6 +112,8 @@ func (r *RouteManager) InitRoute() {
r.registerRouter(cmd.EvtEntityRenderersChangedNotify, GAME_MANAGER.EvtEntityRenderersChangedNotify)
r.registerRouter(cmd.EvtCreateGadgetNotify, GAME_MANAGER.EvtCreateGadgetNotify)
r.registerRouter(cmd.EvtDestroyGadgetNotify, GAME_MANAGER.EvtDestroyGadgetNotify)
r.registerRouter(cmd.CreateVehicleReq, GAME_MANAGER.CreateVehicleReq)
r.registerRouter(cmd.VehicleInteractReq, GAME_MANAGER.VehicleInteractReq)
}
func (r *RouteManager) RouteHandle(netMsg *cmd.NetMsg) {

View File

@@ -440,9 +440,9 @@ func (g *GameManager) AddSceneEntityNotify(player *model.Player, visionType prot
scene := world.GetSceneById(player.SceneId)
entityList := make([]*proto.SceneEntityInfo, 0)
for _, entityId := range entityIdList {
entity := scene.entityMap[entityId]
if entity == nil {
logger.LOG.Error("get entity is nil, entityId: %v", entityId)
entity, ok := scene.entityMap[entityId]
if !ok {
// logger.LOG.Error("get entity is nil, entityId: %v", entityId)
continue
}
switch entity.entityType {
@@ -527,16 +527,17 @@ func (g *GameManager) PacketSceneEntityInfoAvatar(scene *Scene, player *model.Pl
if entity == nil {
return new(proto.SceneEntityInfo)
}
pos := &proto.Vector{
X: float32(entity.pos.X),
Y: float32(entity.pos.Y),
Z: float32(entity.pos.Z),
}
worldAvatar := scene.world.GetWorldAvatarByEntityId(entity.id)
sceneEntityInfo := &proto.SceneEntityInfo{
EntityType: proto.ProtEntityType_PROT_ENTITY_TYPE_AVATAR,
EntityId: entity.id,
MotionInfo: &proto.MotionInfo{
Pos: &proto.Vector{
X: float32(entity.pos.X),
Y: float32(entity.pos.Y),
Z: float32(entity.pos.Z),
},
Pos: pos,
Rot: &proto.Vector{
X: float32(entity.rot.X),
Y: float32(entity.rot.Y),
@@ -569,9 +570,9 @@ func (g *GameManager) PacketSceneEntityInfoAvatar(scene *Scene, player *model.Pl
RendererChangedInfo: new(proto.EntityRendererChangedInfo),
AiInfo: &proto.SceneEntityAiInfo{
IsAiOpen: true,
BornPos: new(proto.Vector),
BornPos: pos,
},
BornPos: new(proto.Vector),
BornPos: pos,
},
LastMoveSceneTimeMs: entity.lastMoveSceneTimeMs,
LastMoveReliableSeq: entity.lastMoveReliableSeq,
@@ -632,15 +633,16 @@ func (g *GameManager) PacketSceneEntityInfoGadget(scene *Scene, entityId uint32)
if entity == nil {
return new(proto.SceneEntityInfo)
}
pos := &proto.Vector{
X: float32(entity.pos.X),
Y: float32(entity.pos.Y),
Z: float32(entity.pos.Z),
}
sceneEntityInfo := &proto.SceneEntityInfo{
EntityType: proto.ProtEntityType_PROT_ENTITY_TYPE_GADGET,
EntityId: entity.id,
MotionInfo: &proto.MotionInfo{
Pos: &proto.Vector{
X: float32(entity.pos.X),
Y: float32(entity.pos.Y),
Z: float32(entity.pos.Z),
},
Pos: pos,
Rot: &proto.Vector{
X: float32(entity.rot.X),
Y: float32(entity.rot.Y),
@@ -663,19 +665,23 @@ func (g *GameManager) PacketSceneEntityInfoGadget(scene *Scene, entityId uint32)
RendererChangedInfo: new(proto.EntityRendererChangedInfo),
AiInfo: &proto.SceneEntityAiInfo{
IsAiOpen: true,
BornPos: new(proto.Vector),
BornPos: pos,
},
BornPos: new(proto.Vector),
BornPos: pos,
},
}
switch entity.gadgetEntity.gadgetType {
case GADGET_TYPE_CLIENT:
sceneEntityInfo.Entity = &proto.SceneEntityInfo_Gadget{
Gadget: g.PacketSceneGadgetInfoAbility(entity.gadgetEntity),
Gadget: g.PacketSceneGadgetInfoAbility(entity.gadgetEntity.gadgetClientEntity),
}
case GADGET_TYPE_GATHER:
sceneEntityInfo.Entity = &proto.SceneEntityInfo_Gadget{
Gadget: g.PacketSceneGadgetInfoGather(entity.gadgetEntity),
Gadget: g.PacketSceneGadgetInfoGather(entity.gadgetEntity.gadgetGatherEntity),
}
case GADGET_TYPE_VEHICLE:
sceneEntityInfo.Entity = &proto.SceneEntityInfo_Gadget{
Gadget: g.PacketSceneGadgetInfoVehicle(entity.gadgetEntity.gadgetVehicleEntity),
}
default:
break
@@ -731,8 +737,28 @@ func (g *GameManager) PacketSceneMonsterInfo() *proto.SceneMonsterInfo {
return sceneMonsterInfo
}
func (g *GameManager) PacketSceneGadgetInfoGather(gadgetEntity *GadgetEntity) *proto.SceneGadgetInfo {
gather := gdc.CONF.GatherDataMap[int32(gadgetEntity.gatherId)]
func (g *GameManager) PacketSceneGadgetInfoVehicle(gadgetVehicleEntity *GadgetVehicleEntity) *proto.SceneGadgetInfo {
sceneGadgetInfo := &proto.SceneGadgetInfo{
GadgetId: gadgetVehicleEntity.vehicleId,
AuthorityPeerId: WORLD_MANAGER.GetWorldByID(gadgetVehicleEntity.owner.WorldId).GetPlayerPeerId(gadgetVehicleEntity.owner),
IsEnableInteract: true,
Content: &proto.SceneGadgetInfo_VehicleInfo{
VehicleInfo: &proto.VehicleInfo{
MemberList: make([]*proto.VehicleMember, 0, len(gadgetVehicleEntity.memberMap)),
OwnerUid: gadgetVehicleEntity.owner.PlayerID,
CurStamina: gadgetVehicleEntity.curStamina,
},
},
}
return sceneGadgetInfo
}
func (g *GameManager) PacketSceneGadgetInfoGather(gadgetGatherEntity *GadgetGatherEntity) *proto.SceneGadgetInfo {
gather, ok := gdc.CONF.GatherDataMap[int32(gadgetGatherEntity.gatherId)]
if !ok {
logger.LOG.Error("gather data error, gatherId: %v", gadgetGatherEntity.gatherId)
return new(proto.SceneGadgetInfo)
}
sceneGadgetInfo := &proto.SceneGadgetInfo{
GadgetId: uint32(gather.GadgetId),
//GroupId: 133003011,
@@ -750,21 +776,21 @@ func (g *GameManager) PacketSceneGadgetInfoGather(gadgetEntity *GadgetEntity) *p
return sceneGadgetInfo
}
func (g *GameManager) PacketSceneGadgetInfoAbility(gadgetEntity *GadgetEntity) *proto.SceneGadgetInfo {
func (g *GameManager) PacketSceneGadgetInfoAbility(gadgetClientEntity *GadgetClientEntity) *proto.SceneGadgetInfo {
sceneGadgetInfo := &proto.SceneGadgetInfo{
GadgetId: gadgetEntity.configId,
OwnerEntityId: gadgetEntity.ownerEntityId,
GadgetId: gadgetClientEntity.configId,
OwnerEntityId: gadgetClientEntity.ownerEntityId,
AuthorityPeerId: 1,
IsEnableInteract: true,
Content: &proto.SceneGadgetInfo_ClientGadget{
ClientGadget: &proto.ClientGadgetInfo{
CampId: gadgetEntity.campId,
CampType: gadgetEntity.campType,
OwnerEntityId: gadgetEntity.ownerEntityId,
TargetEntityId: gadgetEntity.targetEntityId,
CampId: gadgetClientEntity.campId,
CampType: gadgetClientEntity.campType,
OwnerEntityId: gadgetClientEntity.ownerEntityId,
TargetEntityId: gadgetClientEntity.targetEntityId,
},
},
PropOwnerEntityId: gadgetEntity.propOwnerEntityId,
PropOwnerEntityId: gadgetClientEntity.propOwnerEntityId,
}
return sceneGadgetInfo
}

170
gs/game/user_vehicle.go Normal file
View File

@@ -0,0 +1,170 @@
package game
import (
pb "google.golang.org/protobuf/proto"
"hk4e/gs/model"
"hk4e/pkg/logger"
"hk4e/protocol/cmd"
"hk4e/protocol/proto"
)
// CreateVehicleReq 创建载具
func (g *GameManager) CreateVehicleReq(player *model.Player, payloadMsg pb.Message) {
req := payloadMsg.(*proto.CreateVehicleReq)
world := WORLD_MANAGER.GetWorldByID(player.WorldId)
scene := world.GetSceneById(player.SceneId)
// TODO req.ScenePointId 验证浪船锚点是否已解锁
// 清除已创建的载具
for _, id := range scene.GetEntityIdList() {
entity := scene.GetEntity(id)
// 判断实体类型是否为载具
if entity.entityType != uint32(proto.ProtEntityType_PROT_ENTITY_TYPE_GADGET) || entity.gadgetEntity.gadgetType != GADGET_TYPE_VEHICLE {
continue
}
// 确保载具Id为将要创建的 (每种载具允许存在1个)
if entity.gadgetEntity.gadgetVehicleEntity.vehicleId != req.VehicleId {
continue
}
// 该载具是否为此玩家的
if entity.gadgetEntity.gadgetVehicleEntity.owner != player {
continue
}
// 现行角色Guid
avatar, ok := player.AvatarMap[player.TeamConfig.GetActiveAvatarId()]
if !ok {
logger.LOG.Error("avatar is nil, avatarId: %v", player.TeamConfig.GetActiveAvatarId())
g.CommonRetError(cmd.CreateVehicleRsp, player, &proto.CreateVehicleRsp{})
return
}
// 确保玩家正在载具中
if g.IsPlayerInVehicle(player, entity.gadgetEntity.gadgetVehicleEntity) {
// 离开载具
g.ExitVehicle(player, entity, avatar.Guid)
}
// TODO 删除实体 需要杀死实体 暂时实体模块还没写这个
// scene.DestroyEntity(entity.id)
}
// 创建载具实体
pos := &model.Vector{X: float64(req.Pos.X), Y: float64(req.Pos.Y), Z: float64(req.Pos.Z)}
rot := &model.Vector{X: float64(req.Rot.X), Y: float64(req.Rot.Y), Z: float64(req.Rot.Z)}
entityId := scene.CreateEntityGadgetVehicle(player.PlayerID, pos, rot, req.VehicleId)
if entityId == 0 {
logger.LOG.Error("vehicle entityId is 0, uid: %v", player.PlayerID)
g.CommonRetError(cmd.CreateVehicleRsp, player, &proto.CreateVehicleRsp{})
return
}
GAME_MANAGER.AddSceneEntityNotify(player, proto.VisionType_VISION_TYPE_BORN, []uint32{entityId}, true, false)
createVehicleRsp := &proto.CreateVehicleRsp{
VehicleId: req.VehicleId,
EntityId: entityId,
}
g.SendMsg(cmd.CreateVehicleRsp, player.PlayerID, player.ClientSeq, createVehicleRsp)
}
// IsPlayerInVehicle 判断玩家是否在载具中
func (g *GameManager) IsPlayerInVehicle(player *model.Player, gadgetVehicleEntity *GadgetVehicleEntity) bool {
for _, p := range gadgetVehicleEntity.memberMap {
if p == player {
return true
}
}
return false
}
// EnterVehicle 进入载具
func (g *GameManager) EnterVehicle(player *model.Player, entity *Entity, avatarGuid uint64) {
// 玩家是否已进入载具
if g.IsPlayerInVehicle(player, entity.gadgetEntity.gadgetVehicleEntity) {
logger.LOG.Error("vehicle has equal player, uid: %v", player.PlayerID)
g.CommonRetError(cmd.VehicleInteractRsp, player, &proto.VehicleInteractRsp{})
return
}
// 找出载具空闲的位置
pos := uint32(0)
for entity.gadgetEntity.gadgetVehicleEntity.memberMap[pos] != nil {
pos++
}
// 载具成员记录玩家
entity.gadgetEntity.gadgetVehicleEntity.memberMap[pos] = player
vehicleInteractRsp := &proto.VehicleInteractRsp{
InteractType: proto.VehicleInteractType_VEHICLE_INTERACT_TYPE_IN,
Member: &proto.VehicleMember{
Uid: player.PlayerID,
AvatarGuid: avatarGuid,
Pos: pos, // 应该是多人坐船时的位置?
},
EntityId: entity.id,
}
g.SendMsg(cmd.VehicleInteractRsp, player.PlayerID, player.ClientSeq, vehicleInteractRsp)
}
// ExitVehicle 离开载具
func (g *GameManager) ExitVehicle(player *model.Player, entity *Entity, avatarGuid uint64) {
// 玩家是否进入载具
if !g.IsPlayerInVehicle(player, entity.gadgetEntity.gadgetVehicleEntity) {
logger.LOG.Error("vehicle not has player, uid: %v", player.PlayerID)
g.SendMsg(cmd.VehicleInteractRsp, player.PlayerID, player.ClientSeq, &proto.VehicleInteractRsp{Retcode: int32(proto.Retcode_RET_NOT_IN_VEHICLE)})
return
}
// 载具成员删除玩家
var memberPos uint32
for pos, p := range entity.gadgetEntity.gadgetVehicleEntity.memberMap {
if p == player {
memberPos = pos
delete(entity.gadgetEntity.gadgetVehicleEntity.memberMap, pos)
}
}
vehicleInteractRsp := &proto.VehicleInteractRsp{
InteractType: proto.VehicleInteractType_VEHICLE_INTERACT_TYPE_OUT,
Member: &proto.VehicleMember{
Uid: player.PlayerID,
AvatarGuid: avatarGuid,
Pos: memberPos, // 应该是多人坐船时的位置?
},
EntityId: entity.id,
}
g.SendMsg(cmd.VehicleInteractRsp, player.PlayerID, player.ClientSeq, vehicleInteractRsp)
}
// VehicleInteractReq 载具交互
func (g *GameManager) VehicleInteractReq(player *model.Player, payloadMsg pb.Message) {
req := payloadMsg.(*proto.VehicleInteractReq)
// 获取载具实体
world := WORLD_MANAGER.GetWorldByID(player.WorldId)
entity := world.GetSceneById(player.SceneId).GetEntity(req.EntityId)
if entity == nil {
logger.LOG.Error("vehicle entity is nil, entityId: %v", req.EntityId)
g.CommonRetError(cmd.VehicleInteractRsp, player, &proto.VehicleInteractRsp{})
return
}
// 判断实体类型是否为载具
if entity.entityType != uint32(proto.ProtEntityType_PROT_ENTITY_TYPE_GADGET) || entity.gadgetEntity.gadgetType != GADGET_TYPE_VEHICLE {
logger.LOG.Error("vehicle entity error, entityType: %v", entity.entityType)
g.SendMsg(cmd.VehicleInteractRsp, player.PlayerID, player.ClientSeq, &proto.VehicleInteractRsp{Retcode: int32(proto.Retcode_RET_GADGET_NOT_VEHICLE)})
return
}
// 现行角色Guid
avatar, ok := player.AvatarMap[player.TeamConfig.GetActiveAvatarId()]
if !ok {
logger.LOG.Error("avatar is nil, avatarId: %v", player.TeamConfig.GetActiveAvatarId())
g.CommonRetError(cmd.VehicleInteractRsp, player, &proto.VehicleInteractRsp{})
return
}
switch req.InteractType {
case proto.VehicleInteractType_VEHICLE_INTERACT_TYPE_IN:
// 进入载具
g.EnterVehicle(player, entity, avatar.Guid)
case proto.VehicleInteractType_VEHICLE_INTERACT_TYPE_OUT:
// 离开载具
g.ExitVehicle(player, entity, avatar.Guid)
}
}

View File

@@ -1,6 +1,7 @@
package game
import (
"hk4e/pkg/logger"
"math"
"time"
@@ -520,11 +521,10 @@ type MonsterEntity struct {
const (
GADGET_TYPE_CLIENT = iota
GADGET_TYPE_GATHER
GADGET_TYPE_VEHICLE // 载具
)
type GadgetEntity struct {
gadgetType int
gatherId uint32
type GadgetClientEntity struct {
configId uint32
campId uint32
campType uint32
@@ -533,6 +533,24 @@ type GadgetEntity struct {
propOwnerEntityId uint32
}
type GadgetGatherEntity struct {
gatherId uint32
}
type GadgetVehicleEntity struct {
vehicleId uint32
owner *model.Player
curStamina float32
memberMap map[uint32]*model.Player // uint32 = pos
}
type GadgetEntity struct {
gadgetType int
gadgetClientEntity *GadgetClientEntity
gadgetGatherEntity *GadgetGatherEntity
gadgetVehicleEntity *GadgetVehicleEntity
}
// 场景实体数据结构
type Entity struct {
@@ -662,13 +680,15 @@ func (s *Scene) ClientCreateEntityGadget(pos, rot *model.Vector, entityId uint32
entityType: uint32(proto.ProtEntityType_PROT_ENTITY_TYPE_GADGET),
level: 0,
gadgetEntity: &GadgetEntity{
gadgetType: GADGET_TYPE_CLIENT,
configId: configId,
campId: campId,
campType: campType,
ownerEntityId: ownerEntityId,
targetEntityId: targetEntityId,
propOwnerEntityId: propOwnerEntityId,
gadgetType: GADGET_TYPE_CLIENT,
gadgetClientEntity: &GadgetClientEntity{
configId: configId,
campId: campId,
campType: campType,
ownerEntityId: ownerEntityId,
targetEntityId: targetEntityId,
propOwnerEntityId: propOwnerEntityId,
},
},
}
s.entityMap[entity.id] = entity
@@ -694,7 +714,47 @@ func (s *Scene) CreateEntityGadget(pos *model.Vector, gatherId uint32) uint32 {
level: 0,
gadgetEntity: &GadgetEntity{
gadgetType: GADGET_TYPE_GATHER,
gatherId: gatherId,
gadgetGatherEntity: &GadgetGatherEntity{
gatherId: gatherId,
},
},
}
s.entityMap[entity.id] = entity
s.world.aoiManager.AddEntityIdToGridByPos(entity.id, float32(entity.pos.X), float32(entity.pos.Y), float32(entity.pos.Z))
return entity.id
}
func (s *Scene) CreateEntityGadgetVehicle(uid uint32, pos, rot *model.Vector, vehicleId uint32) uint32 {
player := USER_MANAGER.GetOnlineUser(uid)
if player == nil {
logger.LOG.Error("player is nil, uid: %v", uid)
return 0
}
entityId := s.world.GetNextWorldEntityId(constant.EntityIdTypeConst.GADGET)
entity := &Entity{
id: entityId,
scene: s,
pos: pos,
rot: rot,
moveState: uint16(proto.MotionState_MOTION_STATE_NONE),
lastMoveSceneTimeMs: 0,
lastMoveReliableSeq: 0,
fightProp: map[uint32]float32{
// TODO 以后使用配置表
uint32(constant.FightPropertyConst.FIGHT_PROP_CUR_HP): 114514,
uint32(constant.FightPropertyConst.FIGHT_PROP_MAX_HP): 114514,
uint32(constant.FightPropertyConst.FIGHT_PROP_BASE_HP): float32(1),
},
entityType: uint32(proto.ProtEntityType_PROT_ENTITY_TYPE_GADGET),
level: 0,
gadgetEntity: &GadgetEntity{
gadgetType: GADGET_TYPE_VEHICLE,
gadgetVehicleEntity: &GadgetVehicleEntity{
vehicleId: vehicleId,
owner: player,
curStamina: 240, // TODO 应该也能在配置表找到
memberMap: make(map[uint32]*model.Player),
},
},
}
s.entityMap[entity.id] = entity

View File

@@ -230,6 +230,12 @@ func (c *CmdProtoMap) registerAllMessage() {
c.registerMessage(McoinExchangeHcoinReq, &proto.McoinExchangeHcoinReq{}) // 结晶换原石请求
c.registerMessage(McoinExchangeHcoinRsp, &proto.McoinExchangeHcoinRsp{}) // 结晶换原石响应
// 载具
c.registerMessage(CreateVehicleReq, &proto.CreateVehicleReq{}) // 创建载具请求
c.registerMessage(CreateVehicleRsp, &proto.CreateVehicleRsp{}) // 创建载具响应
c.registerMessage(VehicleInteractReq, &proto.VehicleInteractReq{}) // 载具交互请求
c.registerMessage(VehicleInteractRsp, &proto.VehicleInteractRsp{}) // 载具交互响应
// 乱七八糟
c.registerMessage(MarkMapReq, &proto.MarkMapReq{}) // 标记地图请求
c.registerMessage(TowerAllDataReq, &proto.TowerAllDataReq{}) // 深渊数据请求