Minor updates.

This commit is contained in:
genxium 2022-10-01 23:54:48 +08:00
parent 2264c0d362
commit f3a576ba13
8 changed files with 159 additions and 262 deletions

View File

@ -30,14 +30,15 @@ const (
DOWNSYNC_MSG_ACT_INPUT_BATCH = int32(2) DOWNSYNC_MSG_ACT_INPUT_BATCH = int32(2)
DOWNSYNC_MSG_ACT_ROOM_FRAME = int32(3) DOWNSYNC_MSG_ACT_ROOM_FRAME = int32(3)
DOWNSYNC_MSG_ACT_FORCED_RESYNC = int32(4) DOWNSYNC_MSG_ACT_FORCED_RESYNC = int32(4)
DOWNSYNC_MSG_ACT_BATTLE_READY_TO_START = int32(-1)
DOWNSYNC_MSG_ACT_BATTLE_START = int32(0)
DOWNSYNC_MSG_ACT_PLAYER_ADDED_AND_ACKED = int32(-98)
DOWNSYNC_MSG_ACT_PLAYER_READDED_AND_ACKED = int32(-97)
) )
const ( const (
MAGIC_ROOM_DOWNSYNC_FRAME_ID_BATTLE_READY_TO_START = -1
MAGIC_ROOM_DOWNSYNC_FRAME_ID_BATTLE_START = 0
MAGIC_ROOM_DOWNSYNC_FRAME_ID_PLAYER_ADDED_AND_ACKED = -98
MAGIC_ROOM_DOWNSYNC_FRAME_ID_PLAYER_READDED_AND_ACKED = -97
MAGIC_JOIN_INDEX_DEFAULT = 0 MAGIC_JOIN_INDEX_DEFAULT = 0
MAGIC_JOIN_INDEX_INVALID = -1 MAGIC_JOIN_INDEX_INVALID = -1
) )
@ -380,9 +381,7 @@ func (pR *Room) StartBattle() {
pR.CurDynamicsRenderFrameId = 0 pR.CurDynamicsRenderFrameId = 0
kickoffFrame := &pb.RoomDownsyncFrame{ kickoffFrame := &pb.RoomDownsyncFrame{
Id: pR.RenderFrameId, Id: pR.RenderFrameId,
RefFrameId: MAGIC_ROOM_DOWNSYNC_FRAME_ID_BATTLE_START, // Legacy frontend codes need this special "refFrameId" to remove the "3-2-1-countdown" logo
Players: toPbPlayers(pR.Players), Players: toPbPlayers(pR.Players),
SentAt: utils.UnixtimeMilli(),
CountdownNanos: pR.BattleDurationNanos, CountdownNanos: pR.BattleDurationNanos,
} }
pR.RenderFrameBuffer.Put(kickoffFrame) pR.RenderFrameBuffer.Put(kickoffFrame)
@ -433,6 +432,10 @@ func (pR *Room) StartBattle() {
dynamicsStartedAt := utils.UnixtimeNano() dynamicsStartedAt := utils.UnixtimeNano()
// Apply "all-confirmed inputFrames" to move forward "pR.CurDynamicsRenderFrameId" // Apply "all-confirmed inputFrames" to move forward "pR.CurDynamicsRenderFrameId"
nextDynamicsRenderFrameId := pR.ConvertToLastUsedRenderFrameId(pR.LastAllConfirmedInputFrameId, pR.InputDelayFrames) nextDynamicsRenderFrameId := pR.ConvertToLastUsedRenderFrameId(pR.LastAllConfirmedInputFrameId, pR.InputDelayFrames)
if nextDynamicsRenderFrameId > pR.RenderFrameId {
// [WARNING] DON'T apply dynamics too fast, otherwise upon DOWNSYNC_MSG_ACT_FORCED_RESYNC the frontend would resync itself to a "too advanced frontend.renderFrameId", and then start upsyncing "too advanced inputFrameId".
nextDynamicsRenderFrameId = pR.RenderFrameId
}
Logger.Debug(fmt.Sprintf("roomId=%v, room.RenderFrameId=%v, LastAllConfirmedInputFrameId=%v, InputDelayFrames=%v, nextDynamicsRenderFrameId=%v", pR.Id, pR.RenderFrameId, pR.LastAllConfirmedInputFrameId, pR.InputDelayFrames, nextDynamicsRenderFrameId)) Logger.Debug(fmt.Sprintf("roomId=%v, room.RenderFrameId=%v, LastAllConfirmedInputFrameId=%v, InputDelayFrames=%v, nextDynamicsRenderFrameId=%v", pR.Id, pR.RenderFrameId, pR.LastAllConfirmedInputFrameId, pR.InputDelayFrames, nextDynamicsRenderFrameId))
pR.applyInputFrameDownsyncDynamics(pR.CurDynamicsRenderFrameId, nextDynamicsRenderFrameId) pR.applyInputFrameDownsyncDynamics(pR.CurDynamicsRenderFrameId, nextDynamicsRenderFrameId)
dynamicsDuration = utils.UnixtimeNano() - dynamicsStartedAt dynamicsDuration = utils.UnixtimeNano() - dynamicsStartedAt
@ -446,7 +449,7 @@ func (pR *Room) StartBattle() {
} }
if 0 == pR.RenderFrameId { if 0 == pR.RenderFrameId {
kickoffFrame := pR.RenderFrameBuffer.GetByFrameId(0).(*pb.RoomDownsyncFrame) kickoffFrame := pR.RenderFrameBuffer.GetByFrameId(0).(*pb.RoomDownsyncFrame)
pR.sendSafely(kickoffFrame, nil, DOWNSYNC_MSG_ACT_ROOM_FRAME, playerId) pR.sendSafely(kickoffFrame, nil, DOWNSYNC_MSG_ACT_BATTLE_START, playerId)
} else { } else {
// [WARNING] Websocket is TCP-based, thus no need to re-send a previously sent inputFrame to a same player! // [WARNING] Websocket is TCP-based, thus no need to re-send a previously sent inputFrame to a same player!
toSendInputFrames := make([]*pb.InputFrameDownsync, 0, pR.AllPlayerInputsBuffer.Cnt) toSendInputFrames := make([]*pb.InputFrameDownsync, 0, pR.AllPlayerInputsBuffer.Cnt)
@ -484,10 +487,10 @@ func (pR *Room) StartBattle() {
continue continue
} }
pR.sendSafely(nil, toSendInputFrames, DOWNSYNC_MSG_ACT_INPUT_BATCH, playerId) pR.sendSafely(nil, toSendInputFrames, DOWNSYNC_MSG_ACT_INPUT_BATCH, playerId)
if -1 != debugSendingInputFrameId {
Logger.Info("inputFrame lifecycle#4[sent]:", zap.Any("roomId", pR.Id), zap.Any("playerId", playerId), zap.Any("playerAckingInputFrameId", player.AckingInputFrameId), zap.Any("inputFrameId", debugSendingInputFrameId), zap.Any("AllPlayerInputsBuffer", pR.AllPlayerInputsBufferString(false)))
}
} }
if -1 != debugSendingInputFrameId {
Logger.Info("inputFrame lifecycle#4[sent]:", zap.Any("roomId", pR.Id), zap.Any("playerId", playerId), zap.Any("playerAckingInputFrameId", player.AckingInputFrameId), zap.Any("inputFrameId", debugSendingInputFrameId), zap.Any("AllPlayerInputsBuffer", pR.AllPlayerInputsBufferString(false)))
}
atomic.StoreInt32(&(pR.Players[playerId].LastSentInputFrameId), candidateToSendInputFrameId-1) atomic.StoreInt32(&(pR.Players[playerId].LastSentInputFrameId), candidateToSendInputFrameId-1)
} }
} }
@ -557,7 +560,7 @@ func (pR *Room) OnBattleCmdReceived(pReq *pb.WsReq) {
encodedInput := pR.EncodeUpsyncCmd(inputFrameUpsync) encodedInput := pR.EncodeUpsyncCmd(inputFrameUpsync)
if clientInputFrameId >= pR.AllPlayerInputsBuffer.EdFrameId { if clientInputFrameId >= pR.AllPlayerInputsBuffer.EdFrameId {
Logger.Warn(fmt.Sprintf("inputFrame too advanced! is the player cheating?: roomId=%v, playerId=%v, clientInputFrameId=%v, AllPlayerInputsBuffer=%v", pR.Id, playerId, clientInputFrameId, pR.AllPlayerInputsBufferString(false))) Logger.Warn(fmt.Sprintf("inputFrame too advanced! is the player cheating? roomId=%v, playerId=%v, clientInputFrameId=%v, AllPlayerInputsBuffer=%v", pR.Id, playerId, clientInputFrameId, pR.AllPlayerInputsBufferString(false)))
return return
} }
tmp2 := pR.AllPlayerInputsBuffer.GetByFrameId(clientInputFrameId) tmp2 := pR.AllPlayerInputsBuffer.GetByFrameId(clientInputFrameId)
@ -597,8 +600,8 @@ func (pR *Room) OnBattleCmdReceived(pReq *pb.WsReq) {
func (pR *Room) onInputFrameDownsyncAllConfirmed(inputFrameDownsync *pb.InputFrameDownsync, playerId int32) { func (pR *Room) onInputFrameDownsyncAllConfirmed(inputFrameDownsync *pb.InputFrameDownsync, playerId int32) {
inputFrameId := inputFrameDownsync.InputFrameId inputFrameId := inputFrameDownsync.InputFrameId
if -1 == pR.LastAllConfirmedInputFrameIdWithChange || false == pR.equalInputLists(inputFrameDownsync.InputList, pR.LastAllConfirmedInputList) { if -1 == pR.LastAllConfirmedInputFrameIdWithChange || false == pR.equalInputLists(inputFrameDownsync.InputList, pR.LastAllConfirmedInputList) {
atomic.StoreInt32(&(pR.LastAllConfirmedInputFrameIdWithChange), inputFrameId) // [WARNING] Different from the CAS in "battleMainLoop", it's safe to just update "pR.LastAllConfirmedInputFrameIdWithChange" here, because only monotonic increment is possible here! Logger.Info(fmt.Sprintf("Key inputFrame change: roomId=%v, playerId=%v, newInputFrameId=%v, lastInputFrameId=%v, newInputList=%v, lastInputList=%v, AllPlayerInputsBuffer=%v", pR.Id, playerId, inputFrameId, pR.LastAllConfirmedInputFrameId, inputFrameDownsync.InputList, pR.LastAllConfirmedInputList, pR.AllPlayerInputsBufferString(false)))
Logger.Info(fmt.Sprintf("Key inputFrame change: roomId=%v, playerId=%v, inputFrameId=%v, lastInputFrameId=%v, newInputList=%v, lastInputList=%v, AllPlayerInputsBuffer=%v", pR.Id, playerId, inputFrameId, pR.LastAllConfirmedInputFrameId, inputFrameDownsync.InputList, pR.LastAllConfirmedInputList, pR.AllPlayerInputsBufferString(false))) atomic.StoreInt32(&(pR.LastAllConfirmedInputFrameIdWithChange), inputFrameId)
} }
atomic.StoreInt32(&(pR.LastAllConfirmedInputFrameId), inputFrameId) // [WARNING] It's IMPORTANT that "pR.LastAllConfirmedInputFrameId" is NOT NECESSARILY CONSECUTIVE, i.e. if one of the players disconnects and reconnects within a considerable amount of frame delays! atomic.StoreInt32(&(pR.LastAllConfirmedInputFrameId), inputFrameId) // [WARNING] It's IMPORTANT that "pR.LastAllConfirmedInputFrameId" is NOT NECESSARILY CONSECUTIVE, i.e. if one of the players disconnects and reconnects within a considerable amount of frame delays!
for i, v := range inputFrameDownsync.InputList { for i, v := range inputFrameDownsync.InputList {
@ -636,9 +639,7 @@ func (pR *Room) StopBattleForSettlement() {
for playerId, _ := range pR.Players { for playerId, _ := range pR.Players {
assembledFrame := pb.RoomDownsyncFrame{ assembledFrame := pb.RoomDownsyncFrame{
Id: pR.RenderFrameId, Id: pR.RenderFrameId,
RefFrameId: pR.RenderFrameId, // Hardcoded for now.
Players: toPbPlayers(pR.Players), Players: toPbPlayers(pR.Players),
SentAt: utils.UnixtimeMilli(),
CountdownNanos: -1, // TODO: Replace this magic constant! CountdownNanos: -1, // TODO: Replace this magic constant!
} }
pR.sendSafely(&assembledFrame, nil, DOWNSYNC_MSG_ACT_ROOM_FRAME, playerId) pR.sendSafely(&assembledFrame, nil, DOWNSYNC_MSG_ACT_ROOM_FRAME, playerId)
@ -673,18 +674,16 @@ func (pR *Room) onBattlePrepare(cb BattleStartCbType) {
} }
} }
battleReadyToStartFrame := pb.RoomDownsyncFrame{ battleReadyToStartFrame := &pb.RoomDownsyncFrame{
Id: pR.RenderFrameId, Id: DOWNSYNC_MSG_ACT_BATTLE_READY_TO_START,
Players: toPbPlayers(pR.Players), Players: toPbPlayers(pR.Players),
SentAt: utils.UnixtimeMilli(),
RefFrameId: MAGIC_ROOM_DOWNSYNC_FRAME_ID_BATTLE_READY_TO_START,
PlayerMetas: playerMetas, PlayerMetas: playerMetas,
CountdownNanos: pR.BattleDurationNanos, CountdownNanos: pR.BattleDurationNanos,
} }
Logger.Info("Sending out frame for RoomBattleState.PREPARE ", zap.Any("battleReadyToStartFrame", battleReadyToStartFrame)) Logger.Info("Sending out frame for RoomBattleState.PREPARE ", zap.Any("battleReadyToStartFrame", battleReadyToStartFrame))
for _, player := range pR.Players { for _, player := range pR.Players {
pR.sendSafely(&battleReadyToStartFrame, nil, DOWNSYNC_MSG_ACT_ROOM_FRAME, player.Id) pR.sendSafely(battleReadyToStartFrame, nil, DOWNSYNC_MSG_ACT_BATTLE_READY_TO_START, player.Id)
} }
battlePreparationNanos := int64(6000000000) battlePreparationNanos := int64(6000000000)
@ -902,58 +901,53 @@ func (pR *Room) onPlayerReAdded(playerId int32) {
} }
func (pR *Room) OnPlayerBattleColliderAcked(playerId int32) bool { func (pR *Room) OnPlayerBattleColliderAcked(playerId int32) bool {
pPlayer, ok := pR.Players[playerId] targetPlayer, ok := pR.Players[playerId]
if false == ok { if false == ok {
return false return false
} }
playerMetas := make(map[int32]*pb.PlayerMeta, 0) playerMetas := make(map[int32]*pb.PlayerMeta, 0)
for _, player := range pR.Players { for _, eachPlayer := range pR.Players {
playerMetas[player.Id] = &pb.PlayerMeta{ playerMetas[eachPlayer.Id] = &pb.PlayerMeta{
Id: player.Id, Id: eachPlayer.Id,
Name: player.Name, Name: eachPlayer.Name,
DisplayName: player.DisplayName, DisplayName: eachPlayer.DisplayName,
Avatar: player.Avatar, Avatar: eachPlayer.Avatar,
JoinIndex: player.JoinIndex, JoinIndex: eachPlayer.JoinIndex,
} }
} }
var playerAckedFrame pb.RoomDownsyncFrame // Broadcast added or readded player info to all players in the same room
for _, eachPlayer := range pR.Players {
switch pPlayer.BattleState {
case PlayerBattleStateIns.ADDED_PENDING_BATTLE_COLLIDER_ACK:
playerAckedFrame = pb.RoomDownsyncFrame{
Id: pR.RenderFrameId,
Players: toPbPlayers(pR.Players),
SentAt: utils.UnixtimeMilli(),
RefFrameId: MAGIC_ROOM_DOWNSYNC_FRAME_ID_PLAYER_ADDED_AND_ACKED,
PlayerMetas: playerMetas,
}
case PlayerBattleStateIns.READDED_PENDING_BATTLE_COLLIDER_ACK:
playerAckedFrame = pb.RoomDownsyncFrame{
Id: pR.RenderFrameId,
Players: toPbPlayers(pR.Players),
SentAt: utils.UnixtimeMilli(),
RefFrameId: MAGIC_ROOM_DOWNSYNC_FRAME_ID_PLAYER_READDED_AND_ACKED,
PlayerMetas: playerMetas,
}
default:
}
for _, player := range pR.Players {
/* /*
[WARNING] [WARNING]
This `playerAckedFrame` is the first ever "RoomDownsyncFrame" for every "PersistentSessionClient on the frontend", and it goes right after each "BattleColliderInfo". This `playerAckedFrame` is the first ever "RoomDownsyncFrame" for every "PersistentSessionClient on the frontend", and it goes right after each "BattleColliderInfo".
By making use of the sequential nature of each ws session, all later "RoomDownsyncFrame"s generated after `pRoom.StartBattle()` will be put behind this `playerAckedFrame`. By making use of the sequential nature of each ws session, all later "RoomDownsyncFrame"s generated after `pRoom.StartBattle()` will be put behind this `playerAckedFrame`.
*/ */
pR.sendSafely(&playerAckedFrame, nil, DOWNSYNC_MSG_ACT_ROOM_FRAME, player.Id) switch targetPlayer.BattleState {
case PlayerBattleStateIns.ADDED_PENDING_BATTLE_COLLIDER_ACK:
playerAckedFrame := &pb.RoomDownsyncFrame{
Id: pR.RenderFrameId,
Players: toPbPlayers(pR.Players),
PlayerMetas: playerMetas,
}
pR.sendSafely(playerAckedFrame, nil, DOWNSYNC_MSG_ACT_PLAYER_ADDED_AND_ACKED, eachPlayer.Id)
case PlayerBattleStateIns.READDED_PENDING_BATTLE_COLLIDER_ACK:
playerAckedFrame := &pb.RoomDownsyncFrame{
Id: pR.RenderFrameId,
Players: toPbPlayers(pR.Players),
PlayerMetas: playerMetas,
}
pR.sendSafely(playerAckedFrame, nil, DOWNSYNC_MSG_ACT_PLAYER_READDED_AND_ACKED, eachPlayer.Id)
default:
}
} }
pPlayer.BattleState = PlayerBattleStateIns.ACTIVE targetPlayer.BattleState = PlayerBattleStateIns.ACTIVE
Logger.Info("OnPlayerBattleColliderAcked", zap.Any("roomId", pR.Id), zap.Any("roomState", pR.State), zap.Any("playerId", playerId), zap.Any("capacity", pR.Capacity), zap.Any("len(players)", len(pR.Players))) Logger.Info(fmt.Sprintf("OnPlayerBattleColliderAcked: roomId=%v, roomState=%v, targetPlayerId=%v, capacity=%v, EffectivePlayerCount=%v", pR.Id, pR.State, targetPlayer.Id, pR.Capacity, pR.EffectivePlayerCount))
if pR.Capacity == len(pR.Players) { if pR.Capacity == int(pR.EffectivePlayerCount) {
allAcked := true allAcked := true
for _, p := range pR.Players { for _, p := range pR.Players {
if PlayerBattleStateIns.ACTIVE != p.BattleState { if PlayerBattleStateIns.ACTIVE != p.BattleState {
@ -1122,9 +1116,7 @@ func (pR *Room) applyInputFrameDownsyncDynamics(fromRenderFrameId int32, toRende
newRenderFrame := pb.RoomDownsyncFrame{ newRenderFrame := pb.RoomDownsyncFrame{
Id: collisionSysRenderFrameId + 1, Id: collisionSysRenderFrameId + 1,
RefFrameId: collisionSysRenderFrameId,
Players: toPbPlayers(pR.Players), Players: toPbPlayers(pR.Players),
SentAt: utils.UnixtimeMilli(),
CountdownNanos: (pR.BattleDurationNanos - int64(collisionSysRenderFrameId)*int64(pR.RollbackEstimatedDt*1000000000)), CountdownNanos: (pR.BattleDurationNanos - int64(collisionSysRenderFrameId)*int64(pR.RollbackEstimatedDt*1000000000)),
} }
pR.RenderFrameBuffer.Put(&newRenderFrame) pR.RenderFrameBuffer.Put(&newRenderFrame)

View File

@ -767,11 +767,9 @@ type RoomDownsyncFrame struct {
unknownFields protoimpl.UnknownFields unknownFields protoimpl.UnknownFields
Id int32 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"` Id int32 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"`
RefFrameId int32 `protobuf:"varint,2,opt,name=refFrameId,proto3" json:"refFrameId,omitempty"` Players map[int32]*Player `protobuf:"bytes,2,rep,name=players,proto3" json:"players,omitempty" protobuf_key:"varint,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
Players map[int32]*Player `protobuf:"bytes,3,rep,name=players,proto3" json:"players,omitempty" protobuf_key:"varint,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` CountdownNanos int64 `protobuf:"varint,3,opt,name=countdownNanos,proto3" json:"countdownNanos,omitempty"`
SentAt int64 `protobuf:"varint,4,opt,name=sentAt,proto3" json:"sentAt,omitempty"` PlayerMetas map[int32]*PlayerMeta `protobuf:"bytes,4,rep,name=playerMetas,proto3" json:"playerMetas,omitempty" protobuf_key:"varint,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
CountdownNanos int64 `protobuf:"varint,5,opt,name=countdownNanos,proto3" json:"countdownNanos,omitempty"`
PlayerMetas map[int32]*PlayerMeta `protobuf:"bytes,6,rep,name=playerMetas,proto3" json:"playerMetas,omitempty" protobuf_key:"varint,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
} }
func (x *RoomDownsyncFrame) Reset() { func (x *RoomDownsyncFrame) Reset() {
@ -813,13 +811,6 @@ func (x *RoomDownsyncFrame) GetId() int32 {
return 0 return 0
} }
func (x *RoomDownsyncFrame) GetRefFrameId() int32 {
if x != nil {
return x.RefFrameId
}
return 0
}
func (x *RoomDownsyncFrame) GetPlayers() map[int32]*Player { func (x *RoomDownsyncFrame) GetPlayers() map[int32]*Player {
if x != nil { if x != nil {
return x.Players return x.Players
@ -827,13 +818,6 @@ func (x *RoomDownsyncFrame) GetPlayers() map[int32]*Player {
return nil return nil
} }
func (x *RoomDownsyncFrame) GetSentAt() int64 {
if x != nil {
return x.SentAt
}
return 0
}
func (x *RoomDownsyncFrame) GetCountdownNanos() int64 { func (x *RoomDownsyncFrame) GetCountdownNanos() int64 {
if x != nil { if x != nil {
return x.CountdownNanos return x.CountdownNanos
@ -1155,77 +1139,73 @@ var file_room_downsync_frame_proto_rawDesc = []byte{
0x48, 0x65, 0x61, 0x72, 0x74, 0x62, 0x65, 0x61, 0x74, 0x55, 0x70, 0x73, 0x79, 0x6e, 0x63, 0x12, 0x48, 0x65, 0x61, 0x72, 0x74, 0x62, 0x65, 0x61, 0x74, 0x55, 0x70, 0x73, 0x79, 0x6e, 0x63, 0x12,
0x28, 0x0a, 0x0f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x28, 0x0a, 0x0f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61,
0x6d, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x6d, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74,
0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x22, 0xd7, 0x03, 0x0a, 0x11, 0x52, 0x6f, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x22, 0x9f, 0x03, 0x0a, 0x11, 0x52, 0x6f,
0x6f, 0x6d, 0x44, 0x6f, 0x77, 0x6e, 0x73, 0x79, 0x6e, 0x63, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x12, 0x6f, 0x6d, 0x44, 0x6f, 0x77, 0x6e, 0x73, 0x79, 0x6e, 0x63, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x12,
0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x02, 0x69, 0x64, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x02, 0x69, 0x64, 0x12,
0x1e, 0x0a, 0x0a, 0x72, 0x65, 0x66, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x49, 0x64, 0x18, 0x02, 0x20, 0x49, 0x0a, 0x07, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b,
0x01, 0x28, 0x05, 0x52, 0x0a, 0x72, 0x65, 0x66, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x49, 0x64, 0x12,
0x49, 0x0a, 0x07, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b,
0x32, 0x2f, 0x2e, 0x74, 0x72, 0x65, 0x61, 0x73, 0x75, 0x72, 0x65, 0x68, 0x75, 0x6e, 0x74, 0x65, 0x32, 0x2f, 0x2e, 0x74, 0x72, 0x65, 0x61, 0x73, 0x75, 0x72, 0x65, 0x68, 0x75, 0x6e, 0x74, 0x65,
0x72, 0x78, 0x2e, 0x52, 0x6f, 0x6f, 0x6d, 0x44, 0x6f, 0x77, 0x6e, 0x73, 0x79, 0x6e, 0x63, 0x46, 0x72, 0x78, 0x2e, 0x52, 0x6f, 0x6f, 0x6d, 0x44, 0x6f, 0x77, 0x6e, 0x73, 0x79, 0x6e, 0x63, 0x46,
0x72, 0x61, 0x6d, 0x65, 0x2e, 0x50, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x72, 0x61, 0x6d, 0x65, 0x2e, 0x50, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x73, 0x45, 0x6e, 0x74, 0x72,
0x79, 0x52, 0x07, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x65, 0x79, 0x52, 0x07, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x73, 0x12, 0x26, 0x0a, 0x0e, 0x63, 0x6f,
0x6e, 0x74, 0x41, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x73, 0x65, 0x6e, 0x74, 0x75, 0x6e, 0x74, 0x64, 0x6f, 0x77, 0x6e, 0x4e, 0x61, 0x6e, 0x6f, 0x73, 0x18, 0x03, 0x20, 0x01,
0x41, 0x74, 0x12, 0x26, 0x0a, 0x0e, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x64, 0x6f, 0x77, 0x6e, 0x4e, 0x28, 0x03, 0x52, 0x0e, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x64, 0x6f, 0x77, 0x6e, 0x4e, 0x61, 0x6e,
0x61, 0x6e, 0x6f, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, 0x63, 0x6f, 0x75, 0x6e, 0x6f, 0x73, 0x12, 0x55, 0x0a, 0x0b, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x4d, 0x65, 0x74, 0x61,
0x74, 0x64, 0x6f, 0x77, 0x6e, 0x4e, 0x61, 0x6e, 0x6f, 0x73, 0x12, 0x55, 0x0a, 0x0b, 0x70, 0x6c, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x33, 0x2e, 0x74, 0x72, 0x65, 0x61, 0x73, 0x75,
0x61, 0x79, 0x65, 0x72, 0x4d, 0x65, 0x74, 0x61, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x72, 0x65, 0x68, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x78, 0x2e, 0x52, 0x6f, 0x6f, 0x6d, 0x44, 0x6f,
0x33, 0x2e, 0x74, 0x72, 0x65, 0x61, 0x73, 0x75, 0x72, 0x65, 0x68, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x77, 0x6e, 0x73, 0x79, 0x6e, 0x63, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x2e, 0x50, 0x6c, 0x61, 0x79,
0x78, 0x2e, 0x52, 0x6f, 0x6f, 0x6d, 0x44, 0x6f, 0x77, 0x6e, 0x73, 0x79, 0x6e, 0x63, 0x46, 0x72, 0x65, 0x72, 0x4d, 0x65, 0x74, 0x61, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0b, 0x70, 0x6c,
0x61, 0x6d, 0x65, 0x2e, 0x50, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x4d, 0x65, 0x74, 0x61, 0x73, 0x45, 0x61, 0x79, 0x65, 0x72, 0x4d, 0x65, 0x74, 0x61, 0x73, 0x1a, 0x53, 0x0a, 0x0c, 0x50, 0x6c, 0x61,
0x6e, 0x74, 0x72, 0x79, 0x52, 0x0b, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x4d, 0x65, 0x74, 0x61, 0x79, 0x65, 0x72, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79,
0x73, 0x1a, 0x53, 0x0a, 0x0c, 0x50, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x2d, 0x0a, 0x05, 0x76,
0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x03, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x74, 0x72, 0x65,
0x6b, 0x65, 0x79, 0x12, 0x2d, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x61, 0x73, 0x75, 0x72, 0x65, 0x68, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x78, 0x2e, 0x50, 0x6c, 0x61,
0x28, 0x0b, 0x32, 0x17, 0x2e, 0x74, 0x72, 0x65, 0x61, 0x73, 0x75, 0x72, 0x65, 0x68, 0x75, 0x6e, 0x79, 0x65, 0x72, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x5b,
0x74, 0x65, 0x72, 0x78, 0x2e, 0x50, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x0a, 0x10, 0x50, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x4d, 0x65, 0x74, 0x61, 0x73, 0x45, 0x6e, 0x74,
0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x5b, 0x0a, 0x10, 0x50, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52,
0x4d, 0x65, 0x74, 0x61, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x31, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20,
0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x31, 0x0a, 0x05, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x74, 0x72, 0x65, 0x61, 0x73, 0x75, 0x72, 0x65, 0x68, 0x75,
0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x74, 0x72, 0x6e, 0x74, 0x65, 0x72, 0x78, 0x2e, 0x50, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x4d, 0x65, 0x74, 0x61,
0x65, 0x61, 0x73, 0x75, 0x72, 0x65, 0x68, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x78, 0x2e, 0x50, 0x6c, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xca, 0x02, 0x0a, 0x05,
0x61, 0x79, 0x65, 0x72, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x57, 0x73, 0x52, 0x65, 0x71, 0x12, 0x14, 0x0a, 0x05, 0x6d, 0x73, 0x67, 0x49, 0x64, 0x18, 0x01,
0x02, 0x38, 0x01, 0x22, 0xca, 0x02, 0x0a, 0x05, 0x57, 0x73, 0x52, 0x65, 0x71, 0x12, 0x14, 0x0a, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x6d, 0x73, 0x67, 0x49, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x70,
0x05, 0x6d, 0x73, 0x67, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x6d, 0x73, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x49, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x70,
0x67, 0x49, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x49, 0x64, 0x18, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x49, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x61, 0x63, 0x74, 0x18, 0x03,
0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x49, 0x64, 0x12, 0x20, 0x01, 0x28, 0x05, 0x52, 0x03, 0x61, 0x63, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x6a, 0x6f, 0x69,
0x10, 0x0a, 0x03, 0x61, 0x63, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x03, 0x61, 0x63, 0x6e, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x6a, 0x6f,
0x74, 0x12, 0x1c, 0x0a, 0x09, 0x6a, 0x6f, 0x69, 0x6e, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x04, 0x69, 0x6e, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x24, 0x0a, 0x0d, 0x61, 0x63, 0x6b, 0x69, 0x6e,
0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x6a, 0x6f, 0x69, 0x6e, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x67, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x49, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0d,
0x24, 0x0a, 0x0d, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x49, 0x64, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x49, 0x64, 0x12, 0x2e, 0x0a,
0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0d, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x46, 0x72, 0x12, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x46, 0x72, 0x61, 0x6d,
0x61, 0x6d, 0x65, 0x49, 0x64, 0x12, 0x2e, 0x0a, 0x12, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x49, 0x65, 0x49, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x05, 0x52, 0x12, 0x61, 0x63, 0x6b, 0x69, 0x6e,
0x6e, 0x70, 0x75, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x49, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x67, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x49, 0x64, 0x12, 0x57, 0x0a,
0x05, 0x52, 0x12, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x46, 0x72, 0x15, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x55, 0x70, 0x73, 0x79, 0x6e,
0x61, 0x6d, 0x65, 0x49, 0x64, 0x12, 0x57, 0x0a, 0x15, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x46, 0x72, 0x63, 0x42, 0x61, 0x74, 0x63, 0x68, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x74,
0x61, 0x6d, 0x65, 0x55, 0x70, 0x73, 0x79, 0x6e, 0x63, 0x42, 0x61, 0x74, 0x63, 0x68, 0x18, 0x07, 0x72, 0x65, 0x61, 0x73, 0x75, 0x72, 0x65, 0x68, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x78, 0x2e, 0x49,
0x20, 0x03, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x74, 0x72, 0x65, 0x61, 0x73, 0x75, 0x72, 0x65, 0x68, 0x6e, 0x70, 0x75, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x55, 0x70, 0x73, 0x79, 0x6e, 0x63, 0x52,
0x75, 0x6e, 0x74, 0x65, 0x72, 0x78, 0x2e, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x15, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x55, 0x70, 0x73, 0x79, 0x6e,
0x65, 0x55, 0x70, 0x73, 0x79, 0x6e, 0x63, 0x52, 0x15, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x46, 0x72, 0x63, 0x42, 0x61, 0x74, 0x63, 0x68, 0x12, 0x30, 0x0a, 0x02, 0x68, 0x62, 0x18, 0x08, 0x20, 0x01,
0x61, 0x6d, 0x65, 0x55, 0x70, 0x73, 0x79, 0x6e, 0x63, 0x42, 0x61, 0x74, 0x63, 0x68, 0x12, 0x30, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x74, 0x72, 0x65, 0x61, 0x73, 0x75, 0x72, 0x65, 0x68, 0x75, 0x6e,
0x0a, 0x02, 0x68, 0x62, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x74, 0x72, 0x65, 0x74, 0x65, 0x72, 0x78, 0x2e, 0x48, 0x65, 0x61, 0x72, 0x74, 0x62, 0x65, 0x61, 0x74, 0x55, 0x70,
0x61, 0x73, 0x75, 0x72, 0x65, 0x68, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x78, 0x2e, 0x48, 0x65, 0x61, 0x73, 0x79, 0x6e, 0x63, 0x52, 0x02, 0x68, 0x62, 0x22, 0xa4, 0x02, 0x0a, 0x06, 0x57, 0x73, 0x52,
0x72, 0x74, 0x62, 0x65, 0x61, 0x74, 0x55, 0x70, 0x73, 0x79, 0x6e, 0x63, 0x52, 0x02, 0x68, 0x62, 0x65, 0x73, 0x70, 0x12, 0x10, 0x0a, 0x03, 0x72, 0x65, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05,
0x22, 0xa4, 0x02, 0x0a, 0x06, 0x57, 0x73, 0x52, 0x65, 0x73, 0x70, 0x12, 0x10, 0x0a, 0x03, 0x72, 0x52, 0x03, 0x72, 0x65, 0x74, 0x12, 0x20, 0x0a, 0x0b, 0x65, 0x63, 0x68, 0x6f, 0x65, 0x64, 0x4d,
0x65, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x03, 0x72, 0x65, 0x74, 0x12, 0x20, 0x0a, 0x73, 0x67, 0x49, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0b, 0x65, 0x63, 0x68, 0x6f,
0x0b, 0x65, 0x63, 0x68, 0x6f, 0x65, 0x64, 0x4d, 0x73, 0x67, 0x49, 0x64, 0x18, 0x02, 0x20, 0x01, 0x65, 0x64, 0x4d, 0x73, 0x67, 0x49, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x61, 0x63, 0x74, 0x18, 0x03,
0x28, 0x05, 0x52, 0x0b, 0x65, 0x63, 0x68, 0x6f, 0x65, 0x64, 0x4d, 0x73, 0x67, 0x49, 0x64, 0x12, 0x20, 0x01, 0x28, 0x05, 0x52, 0x03, 0x61, 0x63, 0x74, 0x12, 0x34, 0x0a, 0x03, 0x72, 0x64, 0x66,
0x10, 0x0a, 0x03, 0x61, 0x63, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x03, 0x61, 0x63, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x74, 0x72, 0x65, 0x61, 0x73, 0x75, 0x72,
0x74, 0x12, 0x34, 0x0a, 0x03, 0x72, 0x64, 0x66, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x65, 0x68, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x78, 0x2e, 0x52, 0x6f, 0x6f, 0x6d, 0x44, 0x6f, 0x77,
0x2e, 0x74, 0x72, 0x65, 0x61, 0x73, 0x75, 0x72, 0x65, 0x68, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x78, 0x6e, 0x73, 0x79, 0x6e, 0x63, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x52, 0x03, 0x72, 0x64, 0x66, 0x12,
0x2e, 0x52, 0x6f, 0x6f, 0x6d, 0x44, 0x6f, 0x77, 0x6e, 0x73, 0x79, 0x6e, 0x63, 0x46, 0x72, 0x61, 0x5d, 0x0a, 0x17, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x44, 0x6f, 0x77,
0x6d, 0x65, 0x52, 0x03, 0x72, 0x64, 0x66, 0x12, 0x5d, 0x0a, 0x17, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x6e, 0x73, 0x79, 0x6e, 0x63, 0x42, 0x61, 0x74, 0x63, 0x68, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b,
0x46, 0x72, 0x61, 0x6d, 0x65, 0x44, 0x6f, 0x77, 0x6e, 0x73, 0x79, 0x6e, 0x63, 0x42, 0x61, 0x74, 0x32, 0x23, 0x2e, 0x74, 0x72, 0x65, 0x61, 0x73, 0x75, 0x72, 0x65, 0x68, 0x75, 0x6e, 0x74, 0x65,
0x63, 0x68, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x74, 0x72, 0x65, 0x61, 0x73, 0x72, 0x78, 0x2e, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x44, 0x6f, 0x77,
0x75, 0x72, 0x65, 0x68, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x78, 0x2e, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x6e, 0x73, 0x79, 0x6e, 0x63, 0x52, 0x17, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x46, 0x72, 0x61, 0x6d,
0x46, 0x72, 0x61, 0x6d, 0x65, 0x44, 0x6f, 0x77, 0x6e, 0x73, 0x79, 0x6e, 0x63, 0x52, 0x17, 0x69, 0x65, 0x44, 0x6f, 0x77, 0x6e, 0x73, 0x79, 0x6e, 0x63, 0x42, 0x61, 0x74, 0x63, 0x68, 0x12, 0x3f,
0x6e, 0x70, 0x75, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x44, 0x6f, 0x77, 0x6e, 0x73, 0x79, 0x6e, 0x0a, 0x08, 0x62, 0x63, 0x69, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b,
0x63, 0x42, 0x61, 0x74, 0x63, 0x68, 0x12, 0x3f, 0x0a, 0x08, 0x62, 0x63, 0x69, 0x46, 0x72, 0x61, 0x32, 0x23, 0x2e, 0x74, 0x72, 0x65, 0x61, 0x73, 0x75, 0x72, 0x65, 0x68, 0x75, 0x6e, 0x74, 0x65,
0x6d, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x74, 0x72, 0x65, 0x61, 0x73, 0x72, 0x78, 0x2e, 0x42, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x43, 0x6f, 0x6c, 0x6c, 0x69, 0x64, 0x65,
0x75, 0x72, 0x65, 0x68, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x78, 0x2e, 0x42, 0x61, 0x74, 0x74, 0x6c, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x08, 0x62, 0x63, 0x69, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x42,
0x65, 0x43, 0x6f, 0x6c, 0x6c, 0x69, 0x64, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x08, 0x62, 0x03, 0x5a, 0x01, 0x2e, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
0x63, 0x69, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x42, 0x03, 0x5a, 0x01, 0x2e, 0x62, 0x06, 0x70, 0x72,
0x6f, 0x74, 0x6f, 0x33,
} }
var ( var (

View File

@ -29,23 +29,6 @@ var constants = {
BGM: "BGM" BGM: "BGM"
} }
}, },
PLAYER_NAME: {
1: "Merdan",
2: "Monroe",
},
SOCKET_EVENT: {
CONTROL: "control",
SYNC: "sync",
LOGIN: "login",
CREATE: "create"
},
WECHAT: {
AUTHORIZE_PATH: "/connect/oauth2/authorize",
REDIRECT_RUI_KEY: "redirect_uri=",
RESPONSE_TYPE: "response_type=code",
SCOPE: "scope=snsapi_userinfo",
FIN: "#wechat_redirect"
},
ROUTE_PATH: (_ROUTE_PATH = { ROUTE_PATH: (_ROUTE_PATH = {
PLAYER: "/player", PLAYER: "/player",
JSCONFIG: "/jsconfig", JSCONFIG: "/jsconfig",
@ -61,8 +44,6 @@ var constants = {
LIST: "/list", LIST: "/list",
READ: "/read", READ: "/read",
PROFILE: "/profile", PROFILE: "/profile",
WECHAT: "/wechat",
WECHATGAME: "/wechatGame",
FETCH: "/fetch", FETCH: "/fetch",
}, _defineProperty(_ROUTE_PATH, "LOGIN", "/login"), _defineProperty(_ROUTE_PATH, "RET_CODE", "/retCode"), _defineProperty(_ROUTE_PATH, "REGEX", "/regex"), _defineProperty(_ROUTE_PATH, "SMS_CAPTCHA", "/SmsCaptcha"), _defineProperty(_ROUTE_PATH, "GET", "/get"), _ROUTE_PATH), }, _defineProperty(_ROUTE_PATH, "LOGIN", "/login"), _defineProperty(_ROUTE_PATH, "RET_CODE", "/retCode"), _defineProperty(_ROUTE_PATH, "REGEX", "/regex"), _defineProperty(_ROUTE_PATH, "SMS_CAPTCHA", "/SmsCaptcha"), _defineProperty(_ROUTE_PATH, "GET", "/get"), _ROUTE_PATH),
REQUEST_QUERY: { REQUEST_QUERY: {
@ -138,7 +119,6 @@ var constants = {
INCORRECT_PHONE_NUMBER: '手机号不正确', INCORRECT_PHONE_NUMBER: '手机号不正确',
LOG_OUT: '您已在其他地方登陆', LOG_OUT: '您已在其他地方登陆',
GAME_OVER: '游戏结束,您的得分是', GAME_OVER: '游戏结束,您的得分是',
WECHAT_LOGIN_FAILS: "微信登录失败",
}, },
CONFIRM_BUTTON_LABEL: { CONFIRM_BUTTON_LABEL: {
RESTART: '重新开始' RESTART: '重新开始'

View File

@ -78,11 +78,9 @@ message HeartbeatUpsync {
message RoomDownsyncFrame { message RoomDownsyncFrame {
int32 id = 1; int32 id = 1;
int32 refFrameId = 2; map<int32, Player> players = 2;
map<int32, Player> players = 3; int64 countdownNanos = 3;
int64 sentAt = 4; map<int32, PlayerMeta> playerMetas = 4;
int64 countdownNanos = 5;
map<int32, PlayerMeta> playerMetas = 6;
} }
message WsReq { message WsReq {

View File

@ -440,7 +440,7 @@
"array": [ "array": [
0, 0,
0, 0,
209.73151519075364, 210.43837950571782,
0, 0,
0, 0,
0, 0,

View File

@ -18,11 +18,8 @@ window.ALL_BATTLE_STATES = {
}; };
window.MAGIC_ROOM_DOWNSYNC_FRAME_ID = { window.MAGIC_ROOM_DOWNSYNC_FRAME_ID = {
PLAYER_ADDED_AND_ACKED: -98,
PLAYER_READDED_AND_ACKED: -97,
BATTLE_READY_TO_START: -1, BATTLE_READY_TO_START: -1,
BATTLE_START: 0, BATTLE_START: 0
}; };
cc.Class({ cc.Class({
@ -124,9 +121,13 @@ cc.Class({
type: cc.Float, type: cc.Float,
default: 1.0/60 default: 1.0/60
}, },
perFrameDtMaxTolerance: { rollbackEstimatedDtMillis: {
type: cc.Float, type: cc.Float,
default: 1.0/600 default: 1000.0/60
},
rollbackEstimatedDtToleranceMillis: {
type: cc.Float,
default: 1.0/60
}, },
maxChasingRenderFramesPerUpdate: { maxChasingRenderFramesPerUpdate: {
type: cc.Integer, type: cc.Integer,
@ -353,7 +354,7 @@ cc.Class({
self.lastAllConfirmedInputFrameId = -1; self.lastAllConfirmedInputFrameId = -1;
self.chaserRenderFrameId = -1; // at any moment, "lastAllConfirmedRenderFrameId <= chaserRenderFrameId <= renderFrameId", but "chaserRenderFrameId" would fluctuate according to "handleInputFrameDownsyncBatch" self.chaserRenderFrameId = -1; // at any moment, "lastAllConfirmedRenderFrameId <= chaserRenderFrameId <= renderFrameId", but "chaserRenderFrameId" would fluctuate according to "handleInputFrameDownsyncBatch"
self.inputDelayFrames = 8; self.inputDelayFrames = 4;
self.inputScaleFrames = 2; self.inputScaleFrames = 2;
self.lastUpsyncInputFrameId = -1; self.lastUpsyncInputFrameId = -1;
self.inputFrameUpsyncDelayTolerance = 2; self.inputFrameUpsyncDelayTolerance = 2;
@ -547,34 +548,24 @@ cc.Class({
self._inputControlEnabled = false; self._inputControlEnabled = false;
let findingPlayerScriptIns = self.findingPlayerNode.getComponent("FindingPlayer"); let findingPlayerScriptIns = self.findingPlayerNode.getComponent("FindingPlayer");
window.handleRoomDownsyncFrame = function(rdf) { window.handlePlayerAdded = function(rdf) {
if (ALL_BATTLE_STATES.WAITING != self.battleState // Update the "finding player" GUI and show it if not previously present
&& ALL_BATTLE_STATES.IN_BATTLE != self.battleState if (!self.findingPlayerNode.parent) {
&& ALL_BATTLE_STATES.IN_SETTLEMENT != self.battleState) { self.showPopupInCanvas(self.findingPlayerNode);
return;
} }
findingPlayerScriptIns.updatePlayersInfo(rdf.playerMetas);
};
window.handleRoomDownsyncFrame = function(rdf) {
const frameId = rdf.id; const frameId = rdf.id;
// Right upon establishment of the "PersistentSessionClient", we should receive an initial signal "BattleColliderInfo" earlier than any "RoomDownsyncFrame" containing "PlayerMeta" data. // Right upon establishment of the "PersistentSessionClient", we should receive an initial signal "BattleColliderInfo" earlier than any "RoomDownsyncFrame" containing "PlayerMeta" data.
const refFrameId = rdf.refFrameId; switch (frameId) {
switch (refFrameId) {
case window.MAGIC_ROOM_DOWNSYNC_FRAME_ID.PLAYER_ADDED_AND_ACKED:
// Update the "finding player" GUI and show it if not previously present
if (!self.findingPlayerNode.parent) {
self.showPopupInCanvas(self.findingPlayerNode);
}
findingPlayerScriptIns.updatePlayersInfo(rdf.playerMetas);
return;
case window.MAGIC_ROOM_DOWNSYNC_FRAME_ID.BATTLE_READY_TO_START: case window.MAGIC_ROOM_DOWNSYNC_FRAME_ID.BATTLE_READY_TO_START:
self.onBattleReadyToStart(rdf.playerMetas, false); self.onBattleReadyToStart(rdf.playerMetas, false);
return; return;
case window.MAGIC_ROOM_DOWNSYNC_FRAME_ID.BATTLE_START: case window.MAGIC_ROOM_DOWNSYNC_FRAME_ID.BATTLE_START:
self.onBattleStartedOrResynced(rdf); self.onBattleStartedOrResynced(rdf);
return; return;
case window.MAGIC_ROOM_DOWNSYNC_FRAME_ID.PLAYER_READDED_AND_ACKED:
self.onBattleReadyToStart(rdf.playerMetas, true);
self.onBattleStartedOrResynced(rdf);
return;
} }
// TODO: Inject a NetworkDoctor as introduced in https://app.yinxiang.com/shard/s61/nl/13267014/5c575124-01db-419b-9c02-ec81f78c6ddc/. // TODO: Inject a NetworkDoctor as introduced in https://app.yinxiang.com/shard/s61/nl/13267014/5c575124-01db-419b-9c02-ec81f78c6ddc/.
@ -728,6 +719,7 @@ cc.Class({
self.applyRoomDownsyncFrameDynamics(rdf); self.applyRoomDownsyncFrameDynamics(rdf);
self._dumpToRenderCache(rdf); self._dumpToRenderCache(rdf);
self.battleState = ALL_BATTLE_STATES.IN_BATTLE; // Starts the increment of "self.renderFrameId" in "self.update(dt)" self.battleState = ALL_BATTLE_STATES.IN_BATTLE; // Starts the increment of "self.renderFrameId" in "self.update(dt)"
self.lastRenderFrameIdTriggeredAt = performance.now();
if (null != window.boundRoomId) { if (null != window.boundRoomId) {
self.boundRoomIdLabel.string = window.boundRoomId; self.boundRoomIdLabel.string = window.boundRoomId;
} }
@ -791,8 +783,9 @@ cc.Class({
update(dt) { update(dt) {
const self = this; const self = this;
if (ALL_BATTLE_STATES.IN_BATTLE == self.battleState) { if (ALL_BATTLE_STATES.IN_BATTLE == self.battleState) {
if (dt < self.rollbackEstimatedDt-self.perFrameDtMaxTolerance) { const elapsedMillisSinceLastFrameIdTriggered = performance.now() - self.lastRenderFrameIdTriggeredAt;
console.warn("Avoiding too fast frame@renderFrameId=", self.renderFrameId, ": dt=", dt); if (elapsedMillisSinceLastFrameIdTriggered < (self.rollbackEstimatedDtMillis)) {
// console.debug("Avoiding too fast frame@renderFrameId=", self.renderFrameId, ": elapsedMillisSinceLastFrameIdTriggered=", elapsedMillisSinceLastFrameIdTriggered);
return; return;
} }
try { try {
@ -842,6 +835,7 @@ cc.Class({
self.countdownLabel.string = countdownSeconds; self.countdownLabel.string = countdownSeconds;
} }
++self.renderFrameId; // [WARNING] It's important to increment the renderFrameId AFTER all the operations above!!! ++self.renderFrameId; // [WARNING] It's important to increment the renderFrameId AFTER all the operations above!!!
self.lastRenderFrameIdTriggeredAt = performance.now();
} }
} }
}, },

View File

@ -2,11 +2,16 @@ window.UPSYNC_MSG_ACT_HB_PING = 1;
window.UPSYNC_MSG_ACT_PLAYER_CMD = 2; window.UPSYNC_MSG_ACT_PLAYER_CMD = 2;
window.UPSYNC_MSG_ACT_PLAYER_COLLIDER_ACK = 3; window.UPSYNC_MSG_ACT_PLAYER_COLLIDER_ACK = 3;
window.DOWNSYNC_MSG_ACT_PLAYER_ADDED_AND_ACKED = -98;
window.DOWNSYNC_MSG_ACT_PLAYER_READDED_AND_ACKED = -97;
window.DOWNSYNC_MSG_ACT_BATTLE_READY_TO_START = -1;
window.DOWNSYNC_MSG_ACT_BATTLE_START = 0;
window.DOWNSYNC_MSG_ACT_HB_REQ = 1; window.DOWNSYNC_MSG_ACT_HB_REQ = 1;
window.DOWNSYNC_MSG_ACT_INPUT_BATCH = 2; window.DOWNSYNC_MSG_ACT_INPUT_BATCH = 2;
window.DOWNSYNC_MSG_ACT_ROOM_FRAME = 3; window.DOWNSYNC_MSG_ACT_ROOM_FRAME = 3;
window.DOWNSYNC_MSG_ACT_FORCED_RESYNC = 4; window.DOWNSYNC_MSG_ACT_FORCED_RESYNC = 4;
window.sendSafely = function(msgStr) { window.sendSafely = function(msgStr) {
/** /**
* - "If the data can't be sent (for example, because it needs to be buffered but the buffer is full), the socket is closed automatically." * - "If the data can't be sent (for example, because it needs to be buffered but the buffer is full), the socket is closed automatically."
@ -154,6 +159,14 @@ window.initPersistentSessionClient = function(onopenCb, expectedRoomId) {
case window.DOWNSYNC_MSG_ACT_HB_REQ: case window.DOWNSYNC_MSG_ACT_HB_REQ:
window.handleHbRequirements(resp); // 获取boundRoomId并存储到localStorage window.handleHbRequirements(resp); // 获取boundRoomId并存储到localStorage
break; break;
case window.DOWNSYNC_MSG_ACT_PLAYER_ADDED_AND_ACKED:
window.handlePlayerAdded(resp.rdf);
break;
case window.DOWNSYNC_MSG_ACT_PLAYER_READDED_AND_ACKED:
// Deliberately left blank for now
break;
case window.DOWNSYNC_MSG_ACT_BATTLE_READY_TO_START:
case window.DOWNSYNC_MSG_ACT_BATTLE_START:
case window.DOWNSYNC_MSG_ACT_ROOM_FRAME: case window.DOWNSYNC_MSG_ACT_ROOM_FRAME:
if (window.handleRoomDownsyncFrame) { if (window.handleRoomDownsyncFrame) {
window.handleRoomDownsyncFrame(resp.rdf); window.handleRoomDownsyncFrame(resp.rdf);
@ -166,7 +179,7 @@ window.initPersistentSessionClient = function(onopenCb, expectedRoomId) {
break; break;
case window.DOWNSYNC_MSG_ACT_FORCED_RESYNC: case window.DOWNSYNC_MSG_ACT_FORCED_RESYNC:
if (window.handleInputFrameDownsyncBatch && window.handleRoomDownsyncFrame) { if (window.handleInputFrameDownsyncBatch && window.handleRoomDownsyncFrame) {
console.warn("GOT forced resync:", resp); console.warn("Got forced resync:", resp.toString(), " @localRenderFrameId=", mapIns.renderFrameId, ", @localRecentInputCache=", mapIns._stringifyRecentInputCache(false));
// The following order of execution is important, because "handleInputFrameDownsyncBatch" is only available when state is IN_BATTLE // The following order of execution is important, because "handleInputFrameDownsyncBatch" is only available when state is IN_BATTLE
window.handleRoomDownsyncFrame(resp.rdf); window.handleRoomDownsyncFrame(resp.rdf);
window.handleInputFrameDownsyncBatch(resp.inputFrameDownsyncBatch); window.handleInputFrameDownsyncBatch(resp.inputFrameDownsyncBatch);

View File

@ -3131,9 +3131,7 @@ $root.treasurehunterx = (function() {
* @memberof treasurehunterx * @memberof treasurehunterx
* @interface IRoomDownsyncFrame * @interface IRoomDownsyncFrame
* @property {number|null} [id] RoomDownsyncFrame id * @property {number|null} [id] RoomDownsyncFrame id
* @property {number|null} [refFrameId] RoomDownsyncFrame refFrameId
* @property {Object.<string,treasurehunterx.Player>|null} [players] RoomDownsyncFrame players * @property {Object.<string,treasurehunterx.Player>|null} [players] RoomDownsyncFrame players
* @property {number|Long|null} [sentAt] RoomDownsyncFrame sentAt
* @property {number|Long|null} [countdownNanos] RoomDownsyncFrame countdownNanos * @property {number|Long|null} [countdownNanos] RoomDownsyncFrame countdownNanos
* @property {Object.<string,treasurehunterx.PlayerMeta>|null} [playerMetas] RoomDownsyncFrame playerMetas * @property {Object.<string,treasurehunterx.PlayerMeta>|null} [playerMetas] RoomDownsyncFrame playerMetas
*/ */
@ -3163,14 +3161,6 @@ $root.treasurehunterx = (function() {
*/ */
RoomDownsyncFrame.prototype.id = 0; RoomDownsyncFrame.prototype.id = 0;
/**
* RoomDownsyncFrame refFrameId.
* @member {number} refFrameId
* @memberof treasurehunterx.RoomDownsyncFrame
* @instance
*/
RoomDownsyncFrame.prototype.refFrameId = 0;
/** /**
* RoomDownsyncFrame players. * RoomDownsyncFrame players.
* @member {Object.<string,treasurehunterx.Player>} players * @member {Object.<string,treasurehunterx.Player>} players
@ -3179,14 +3169,6 @@ $root.treasurehunterx = (function() {
*/ */
RoomDownsyncFrame.prototype.players = $util.emptyObject; RoomDownsyncFrame.prototype.players = $util.emptyObject;
/**
* RoomDownsyncFrame sentAt.
* @member {number|Long} sentAt
* @memberof treasurehunterx.RoomDownsyncFrame
* @instance
*/
RoomDownsyncFrame.prototype.sentAt = $util.Long ? $util.Long.fromBits(0,0,false) : 0;
/** /**
* RoomDownsyncFrame countdownNanos. * RoomDownsyncFrame countdownNanos.
* @member {number|Long} countdownNanos * @member {number|Long} countdownNanos
@ -3229,20 +3211,16 @@ $root.treasurehunterx = (function() {
writer = $Writer.create(); writer = $Writer.create();
if (message.id != null && Object.hasOwnProperty.call(message, "id")) if (message.id != null && Object.hasOwnProperty.call(message, "id"))
writer.uint32(/* id 1, wireType 0 =*/8).int32(message.id); writer.uint32(/* id 1, wireType 0 =*/8).int32(message.id);
if (message.refFrameId != null && Object.hasOwnProperty.call(message, "refFrameId"))
writer.uint32(/* id 2, wireType 0 =*/16).int32(message.refFrameId);
if (message.players != null && Object.hasOwnProperty.call(message, "players")) if (message.players != null && Object.hasOwnProperty.call(message, "players"))
for (var keys = Object.keys(message.players), i = 0; i < keys.length; ++i) { for (var keys = Object.keys(message.players), i = 0; i < keys.length; ++i) {
writer.uint32(/* id 3, wireType 2 =*/26).fork().uint32(/* id 1, wireType 0 =*/8).int32(keys[i]); writer.uint32(/* id 2, wireType 2 =*/18).fork().uint32(/* id 1, wireType 0 =*/8).int32(keys[i]);
$root.treasurehunterx.Player.encode(message.players[keys[i]], writer.uint32(/* id 2, wireType 2 =*/18).fork()).ldelim().ldelim(); $root.treasurehunterx.Player.encode(message.players[keys[i]], writer.uint32(/* id 2, wireType 2 =*/18).fork()).ldelim().ldelim();
} }
if (message.sentAt != null && Object.hasOwnProperty.call(message, "sentAt"))
writer.uint32(/* id 4, wireType 0 =*/32).int64(message.sentAt);
if (message.countdownNanos != null && Object.hasOwnProperty.call(message, "countdownNanos")) if (message.countdownNanos != null && Object.hasOwnProperty.call(message, "countdownNanos"))
writer.uint32(/* id 5, wireType 0 =*/40).int64(message.countdownNanos); writer.uint32(/* id 3, wireType 0 =*/24).int64(message.countdownNanos);
if (message.playerMetas != null && Object.hasOwnProperty.call(message, "playerMetas")) if (message.playerMetas != null && Object.hasOwnProperty.call(message, "playerMetas"))
for (var keys = Object.keys(message.playerMetas), i = 0; i < keys.length; ++i) { for (var keys = Object.keys(message.playerMetas), i = 0; i < keys.length; ++i) {
writer.uint32(/* id 6, wireType 2 =*/50).fork().uint32(/* id 1, wireType 0 =*/8).int32(keys[i]); writer.uint32(/* id 4, wireType 2 =*/34).fork().uint32(/* id 1, wireType 0 =*/8).int32(keys[i]);
$root.treasurehunterx.PlayerMeta.encode(message.playerMetas[keys[i]], writer.uint32(/* id 2, wireType 2 =*/18).fork()).ldelim().ldelim(); $root.treasurehunterx.PlayerMeta.encode(message.playerMetas[keys[i]], writer.uint32(/* id 2, wireType 2 =*/18).fork()).ldelim().ldelim();
} }
return writer; return writer;
@ -3284,10 +3262,6 @@ $root.treasurehunterx = (function() {
break; break;
} }
case 2: { case 2: {
message.refFrameId = reader.int32();
break;
}
case 3: {
if (message.players === $util.emptyObject) if (message.players === $util.emptyObject)
message.players = {}; message.players = {};
var end2 = reader.uint32() + reader.pos; var end2 = reader.uint32() + reader.pos;
@ -3310,15 +3284,11 @@ $root.treasurehunterx = (function() {
message.players[key] = value; message.players[key] = value;
break; break;
} }
case 4: { case 3: {
message.sentAt = reader.int64();
break;
}
case 5: {
message.countdownNanos = reader.int64(); message.countdownNanos = reader.int64();
break; break;
} }
case 6: { case 4: {
if (message.playerMetas === $util.emptyObject) if (message.playerMetas === $util.emptyObject)
message.playerMetas = {}; message.playerMetas = {};
var end2 = reader.uint32() + reader.pos; var end2 = reader.uint32() + reader.pos;
@ -3379,9 +3349,6 @@ $root.treasurehunterx = (function() {
if (message.id != null && message.hasOwnProperty("id")) if (message.id != null && message.hasOwnProperty("id"))
if (!$util.isInteger(message.id)) if (!$util.isInteger(message.id))
return "id: integer expected"; return "id: integer expected";
if (message.refFrameId != null && message.hasOwnProperty("refFrameId"))
if (!$util.isInteger(message.refFrameId))
return "refFrameId: integer expected";
if (message.players != null && message.hasOwnProperty("players")) { if (message.players != null && message.hasOwnProperty("players")) {
if (!$util.isObject(message.players)) if (!$util.isObject(message.players))
return "players: object expected"; return "players: object expected";
@ -3396,9 +3363,6 @@ $root.treasurehunterx = (function() {
} }
} }
} }
if (message.sentAt != null && message.hasOwnProperty("sentAt"))
if (!$util.isInteger(message.sentAt) && !(message.sentAt && $util.isInteger(message.sentAt.low) && $util.isInteger(message.sentAt.high)))
return "sentAt: integer|Long expected";
if (message.countdownNanos != null && message.hasOwnProperty("countdownNanos")) if (message.countdownNanos != null && message.hasOwnProperty("countdownNanos"))
if (!$util.isInteger(message.countdownNanos) && !(message.countdownNanos && $util.isInteger(message.countdownNanos.low) && $util.isInteger(message.countdownNanos.high))) if (!$util.isInteger(message.countdownNanos) && !(message.countdownNanos && $util.isInteger(message.countdownNanos.low) && $util.isInteger(message.countdownNanos.high)))
return "countdownNanos: integer|Long expected"; return "countdownNanos: integer|Long expected";
@ -3433,8 +3397,6 @@ $root.treasurehunterx = (function() {
var message = new $root.treasurehunterx.RoomDownsyncFrame(); var message = new $root.treasurehunterx.RoomDownsyncFrame();
if (object.id != null) if (object.id != null)
message.id = object.id | 0; message.id = object.id | 0;
if (object.refFrameId != null)
message.refFrameId = object.refFrameId | 0;
if (object.players) { if (object.players) {
if (typeof object.players !== "object") if (typeof object.players !== "object")
throw TypeError(".treasurehunterx.RoomDownsyncFrame.players: object expected"); throw TypeError(".treasurehunterx.RoomDownsyncFrame.players: object expected");
@ -3445,15 +3407,6 @@ $root.treasurehunterx = (function() {
message.players[keys[i]] = $root.treasurehunterx.Player.fromObject(object.players[keys[i]]); message.players[keys[i]] = $root.treasurehunterx.Player.fromObject(object.players[keys[i]]);
} }
} }
if (object.sentAt != null)
if ($util.Long)
(message.sentAt = $util.Long.fromValue(object.sentAt)).unsigned = false;
else if (typeof object.sentAt === "string")
message.sentAt = parseInt(object.sentAt, 10);
else if (typeof object.sentAt === "number")
message.sentAt = object.sentAt;
else if (typeof object.sentAt === "object")
message.sentAt = new $util.LongBits(object.sentAt.low >>> 0, object.sentAt.high >>> 0).toNumber();
if (object.countdownNanos != null) if (object.countdownNanos != null)
if ($util.Long) if ($util.Long)
(message.countdownNanos = $util.Long.fromValue(object.countdownNanos)).unsigned = false; (message.countdownNanos = $util.Long.fromValue(object.countdownNanos)).unsigned = false;
@ -3495,12 +3448,6 @@ $root.treasurehunterx = (function() {
} }
if (options.defaults) { if (options.defaults) {
object.id = 0; object.id = 0;
object.refFrameId = 0;
if ($util.Long) {
var long = new $util.Long(0, 0, false);
object.sentAt = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
} else
object.sentAt = options.longs === String ? "0" : 0;
if ($util.Long) { if ($util.Long) {
var long = new $util.Long(0, 0, false); var long = new $util.Long(0, 0, false);
object.countdownNanos = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long; object.countdownNanos = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
@ -3509,19 +3456,12 @@ $root.treasurehunterx = (function() {
} }
if (message.id != null && message.hasOwnProperty("id")) if (message.id != null && message.hasOwnProperty("id"))
object.id = message.id; object.id = message.id;
if (message.refFrameId != null && message.hasOwnProperty("refFrameId"))
object.refFrameId = message.refFrameId;
var keys2; var keys2;
if (message.players && (keys2 = Object.keys(message.players)).length) { if (message.players && (keys2 = Object.keys(message.players)).length) {
object.players = {}; object.players = {};
for (var j = 0; j < keys2.length; ++j) for (var j = 0; j < keys2.length; ++j)
object.players[keys2[j]] = $root.treasurehunterx.Player.toObject(message.players[keys2[j]], options); object.players[keys2[j]] = $root.treasurehunterx.Player.toObject(message.players[keys2[j]], options);
} }
if (message.sentAt != null && message.hasOwnProperty("sentAt"))
if (typeof message.sentAt === "number")
object.sentAt = options.longs === String ? String(message.sentAt) : message.sentAt;
else
object.sentAt = options.longs === String ? $util.Long.prototype.toString.call(message.sentAt) : options.longs === Number ? new $util.LongBits(message.sentAt.low >>> 0, message.sentAt.high >>> 0).toNumber() : message.sentAt;
if (message.countdownNanos != null && message.hasOwnProperty("countdownNanos")) if (message.countdownNanos != null && message.hasOwnProperty("countdownNanos"))
if (typeof message.countdownNanos === "number") if (typeof message.countdownNanos === "number")
object.countdownNanos = options.longs === String ? String(message.countdownNanos) : message.countdownNanos; object.countdownNanos = options.longs === String ? String(message.countdownNanos) : message.countdownNanos;