Fixes for melee attack sync.

This commit is contained in:
genxium 2022-11-24 19:45:48 +08:00
parent 2290c57c1c
commit 04de4666d5
13 changed files with 271 additions and 238 deletions

View File

@ -150,11 +150,6 @@ type Room struct {
Index int Index int
RenderFrameId int32 RenderFrameId int32
CurDynamicsRenderFrameId int32 // [WARNING] The dynamics of backend is ALWAYS MOVING FORWARD BY ALL-CONFIRMED INPUTFRAMES (either by upsync or forced), i.e. no rollback CurDynamicsRenderFrameId int32 // [WARNING] The dynamics of backend is ALWAYS MOVING FORWARD BY ALL-CONFIRMED INPUTFRAMES (either by upsync or forced), i.e. no rollback
ServerFps int32
BattleDurationFrames int32
BattleDurationNanos int64
InputFrameUpsyncDelayTolerance int32
MaxChasingRenderFramesPerUpdate int32
EffectivePlayerCount int32 EffectivePlayerCount int32
DismissalWaitGroup sync.WaitGroup DismissalWaitGroup sync.WaitGroup
Barriers map[int32]*Barrier Barriers map[int32]*Barrier
@ -164,17 +159,15 @@ type Room struct {
LastAllConfirmedInputFrameId int32 LastAllConfirmedInputFrameId int32
LastAllConfirmedInputFrameIdWithChange int32 LastAllConfirmedInputFrameIdWithChange int32
LastAllConfirmedInputList []uint64 LastAllConfirmedInputList []uint64
InputDelayFrames int32 // in the count of render frames
NstDelayFrames int32 // network-single-trip delay in the count of render frames, proposed to be (InputDelayFrames >> 1) because we expect a round-trip delay to be exactly "InputDelayFrames"
InputScaleFrames uint32 // inputDelayedAndScaledFrameId = ((originalFrameId - InputDelayFrames) >> InputScaleFrames)
JoinIndexBooleanArr []bool JoinIndexBooleanArr []bool
BackendDynamicsEnabled bool BackendDynamicsEnabled bool
LastRenderFrameIdTriggeredAt int64 LastRenderFrameIdTriggeredAt int64
PlayerDefaultSpeed int32 PlayerDefaultSpeed int32
BulletBattleLocalIdCounter int32 BulletBattleLocalIdCounter int32
BattleColliderInfo // Compositing to send centralized magic numbers dilutedRollbackEstimatedDtNanos int64
BattleColliderInfo // Compositing to send centralized magic numbers
} }
func (pR *Room) updateScore() { func (pR *Room) updateScore() {
@ -377,8 +370,6 @@ func (pR *Room) StartBattle() {
return return
} }
// Always instantiates a new channel and let the old one die out due to not being retained by any root reference.
nanosPerFrame := 1000000000 / int64(pR.ServerFps)
pR.RenderFrameId = 0 pR.RenderFrameId = 0
// Initialize the "collisionSys" as well as "RenderFrameBuffer" // Initialize the "collisionSys" as well as "RenderFrameBuffer"
@ -418,7 +409,7 @@ func (pR *Room) StartBattle() {
stCalculation := utils.UnixtimeNano() stCalculation := utils.UnixtimeNano()
elapsedNanosSinceLastFrameIdTriggered := stCalculation - pR.LastRenderFrameIdTriggeredAt elapsedNanosSinceLastFrameIdTriggered := stCalculation - pR.LastRenderFrameIdTriggeredAt
if elapsedNanosSinceLastFrameIdTriggered < pR.RollbackEstimatedDtNanos { if elapsedNanosSinceLastFrameIdTriggered < pR.dilutedRollbackEstimatedDtNanos {
Logger.Debug(fmt.Sprintf("Avoiding too fast frame@roomId=%v, renderFrameId=%v: elapsedNanosSinceLastFrameIdTriggered=%v", pR.Id, pR.RenderFrameId, elapsedNanosSinceLastFrameIdTriggered)) Logger.Debug(fmt.Sprintf("Avoiding too fast frame@roomId=%v, renderFrameId=%v: elapsedNanosSinceLastFrameIdTriggered=%v", pR.Id, pR.RenderFrameId, elapsedNanosSinceLastFrameIdTriggered))
continue continue
} }
@ -580,10 +571,10 @@ func (pR *Room) StartBattle() {
pR.RenderFrameId++ pR.RenderFrameId++
elapsedInCalculation := (utils.UnixtimeNano() - stCalculation) elapsedInCalculation := (utils.UnixtimeNano() - stCalculation)
if elapsedInCalculation > nanosPerFrame { if elapsedInCalculation > pR.dilutedRollbackEstimatedDtNanos {
Logger.Warn(fmt.Sprintf("SLOW FRAME! Elapsed time statistics: roomId=%v, room.RenderFrameId=%v, elapsedInCalculation=%v ns, dynamicsDuration=%v ns, expected nanosPerFrame=%v", pR.Id, pR.RenderFrameId, elapsedInCalculation, dynamicsDuration, nanosPerFrame)) Logger.Warn(fmt.Sprintf("SLOW FRAME! Elapsed time statistics: roomId=%v, room.RenderFrameId=%v, elapsedInCalculation=%v ns, dynamicsDuration=%v ns, dilutedRollbackEstimatedDtNanos=%v", pR.Id, pR.RenderFrameId, elapsedInCalculation, dynamicsDuration, pR.dilutedRollbackEstimatedDtNanos))
} }
time.Sleep(time.Duration(nanosPerFrame - elapsedInCalculation)) time.Sleep(time.Duration(pR.dilutedRollbackEstimatedDtNanos - elapsedInCalculation))
} }
} }
@ -783,7 +774,7 @@ func (pR *Room) OnDismissed() {
pR.PlayerSignalToCloseDict = make(map[int32]SignalToCloseConnCbType) pR.PlayerSignalToCloseDict = make(map[int32]SignalToCloseConnCbType)
pR.JoinIndexBooleanArr = make([]bool, pR.Capacity) pR.JoinIndexBooleanArr = make([]bool, pR.Capacity)
pR.Barriers = make(map[int32]*Barrier) pR.Barriers = make(map[int32]*Barrier)
pR.RenderCacheSize = 512 pR.RenderCacheSize = 1024
pR.RenderFrameBuffer = NewRingBuffer(pR.RenderCacheSize) pR.RenderFrameBuffer = NewRingBuffer(pR.RenderCacheSize)
pR.DiscreteInputsBuffer = sync.Map{} pR.DiscreteInputsBuffer = sync.Map{}
pR.InputsBuffer = NewRingBuffer((pR.RenderCacheSize >> 2) + 1) pR.InputsBuffer = NewRingBuffer((pR.RenderCacheSize >> 2) + 1)
@ -800,6 +791,8 @@ func (pR *Room) OnDismissed() {
pR.ServerFps = 60 pR.ServerFps = 60
pR.RollbackEstimatedDtMillis = 16.667 // Use fixed-and-low-precision to mitigate the inconsistent floating-point-number issue between Golang and JavaScript pR.RollbackEstimatedDtMillis = 16.667 // Use fixed-and-low-precision to mitigate the inconsistent floating-point-number issue between Golang and JavaScript
pR.RollbackEstimatedDtNanos = 16666666 // A little smaller than the actual per frame time, just for preventing FAST FRAME pR.RollbackEstimatedDtNanos = 16666666 // A little smaller than the actual per frame time, just for preventing FAST FRAME
dilutionFactor := 8
pR.dilutedRollbackEstimatedDtNanos = int64(16666666 * (dilutionFactor) / (dilutionFactor - 1)) // [WARNING] Only used in controlling "battleMainLoop" to be keep a frame rate lower than that of the frontends, such that upon resync(i.e. BackendDynamicsEnabled=true), the frontends would have bigger chances to keep up with or even surpass the backend calculation
pR.BattleDurationFrames = 30 * pR.ServerFps pR.BattleDurationFrames = 30 * pR.ServerFps
pR.BattleDurationNanos = int64(pR.BattleDurationFrames) * (pR.RollbackEstimatedDtNanos + 1) pR.BattleDurationNanos = int64(pR.BattleDurationFrames) * (pR.RollbackEstimatedDtNanos + 1)
pR.InputFrameUpsyncDelayTolerance = 2 pR.InputFrameUpsyncDelayTolerance = 2
@ -807,32 +800,30 @@ func (pR *Room) OnDismissed() {
pR.BackendDynamicsEnabled = true // [WARNING] When "false", recovery upon reconnection wouldn't work! pR.BackendDynamicsEnabled = true // [WARNING] When "false", recovery upon reconnection wouldn't work!
punchSkillId := int32(1) punchSkillId := int32(1)
if _, existent := pR.MeleeSkillConfig[punchSkillId]; !existent { pR.MeleeSkillConfig = make(map[int32]*MeleeBullet, 0)
pR.MeleeSkillConfig = make(map[int32]*MeleeBullet, 0) pR.MeleeSkillConfig[punchSkillId] = &MeleeBullet{
pR.MeleeSkillConfig[punchSkillId] = &MeleeBullet{ // for offender
// for offender StartupFrames: int32(18),
StartupFrames: int32(18), ActiveFrames: int32(42),
ActiveFrames: int32(42), RecoveryFrames: int32(61), // usually but not always "startupFrames+activeFrames", I hereby set it to be 1 frame more than the actual animation to avoid critical transition, i.e. when the animation is 1 frame from ending but "rdfPlayer.framesToRecover" is already counted 0 and the player triggers an other same attack, making an effective bullet trigger but no animation is played due to same animName is still playing
RecoveryFrames: int32(61), // usually but not always "startupFrames+activeFrames", I hereby set it to be 1 frame more than the actual animation to avoid critical transition, i.e. when the animation is 1 frame from ending but "rdfPlayer.framesToRecover" is already counted 0 and the player triggers an other same attack, making an effective bullet trigger but no animation is played due to same animName is still playing RecoveryFramesOnBlock: int32(61),
RecoveryFramesOnBlock: int32(61), RecoveryFramesOnHit: int32(61),
RecoveryFramesOnHit: int32(61), Moveforward: &Vec2D{
Moveforward: &Vec2D{ X: 0,
X: 0, Y: 0,
Y: 0, },
}, HitboxOffset: float64(12.0), // should be about the radius of the PlayerCollider
HitboxOffset: float64(12.0), // should be about the radius of the PlayerCollider HitboxSize: &Vec2D{
HitboxSize: &Vec2D{ X: float64(45.0),
X: float64(45.0), Y: float64(32.0),
Y: float64(32.0), },
},
// for defender // for defender
HitStunFrames: int32(18), HitStunFrames: int32(18),
BlockStunFrames: int32(9), BlockStunFrames: int32(9),
Pushback: float64(22.0), Pushback: float64(22.0),
ReleaseTriggerType: int32(1), // 1: rising-edge, 2: falling-edge ReleaseTriggerType: int32(1), // 1: rising-edge, 2: falling-edge
Damage: int32(5), Damage: int32(5),
}
} }
pR.ChooseStage() pR.ChooseStage()
@ -1078,7 +1069,7 @@ func (pR *Room) prefabInputFrameDownsync(inputFrameId int32) *InputFrameDownsync
prevInputFrameDownsync := tmp.(*InputFrameDownsync) prevInputFrameDownsync := tmp.(*InputFrameDownsync)
currInputList := make([]uint64, pR.Capacity) // Would be a clone of the values currInputList := make([]uint64, pR.Capacity) // Would be a clone of the values
for i, _ := range currInputList { for i, _ := range currInputList {
currInputList[i] = (prevInputFrameDownsync.InputList[i] & uint64(15)) // Don't predict attack input currInputList[i] = (prevInputFrameDownsync.InputList[i] & uint64(15)) // Don't predict attack input!
} }
currInputFrameDownsync = &InputFrameDownsync{ currInputFrameDownsync = &InputFrameDownsync{
InputFrameId: inputFrameId, InputFrameId: inputFrameId,
@ -1098,7 +1089,7 @@ func (pR *Room) markConfirmationIfApplicable() {
for inputFrameId := inputFrameId1; inputFrameId < pR.InputsBuffer.EdFrameId; inputFrameId++ { for inputFrameId := inputFrameId1; inputFrameId < pR.InputsBuffer.EdFrameId; inputFrameId++ {
tmp := pR.InputsBuffer.GetByFrameId(inputFrameId) tmp := pR.InputsBuffer.GetByFrameId(inputFrameId)
if nil == tmp { if nil == tmp {
panic(fmt.Sprintf("inputFrameId=%v doesn't exist for roomId=%v, this is abnormal because the server should prefab inputFrameDownsync in a most advanced pace, check the prefab logic! InputsBuffer=%v", inputFrameId, pR.Id, pR.InputsBufferString(false))) panic(fmt.Sprintf("inputFrameId=%v doesn't exist for roomId=%v, this is abnormal because the server should prefab inputFrameDownsync in a most advanced pace, check the prefab logic (Or maybe you're having a 'Room.RenderCacheSize' too small)! InputsBuffer=%v", inputFrameId, pR.Id, pR.InputsBufferString(false)))
} }
inputFrameDownsync := tmp.(*InputFrameDownsync) inputFrameDownsync := tmp.(*InputFrameDownsync)
for _, player := range pR.Players { for _, player := range pR.Players {
@ -1334,6 +1325,9 @@ func (pR *Room) applyInputFrameDownsyncDynamicsOnSingleRenderFrame(delayedInputF
playerCollider.Y += bulletPushbacks[joinIndex-1].Y playerCollider.Y += bulletPushbacks[joinIndex-1].Y
// Update in the collision system // Update in the collision system
playerCollider.Update() playerCollider.Update()
if 0 != bulletPushbacks[joinIndex-1].X || 0 != bulletPushbacks[joinIndex-1].Y {
Logger.Info(fmt.Sprintf("roomId=%v, playerId=%v is pushed back by (%.2f, %.2f) by bullet impacts, now its framesToRecover is %d at currRenderFrame.id=%v", pR.Id, playerId, bulletPushbacks[joinIndex-1].X, bulletPushbacks[joinIndex-1].Y, thatPlayerInNextFrame.FramesToRecover, currRenderFrame.Id))
}
continue continue
} }
currPlayerDownsync := currRenderFrame.Players[playerId] currPlayerDownsync := currRenderFrame.Players[playerId]

View File

@ -822,21 +822,22 @@ type BattleColliderInfo struct {
IntervalToPing int32 `protobuf:"varint,8,opt,name=intervalToPing,proto3" json:"intervalToPing,omitempty"` IntervalToPing int32 `protobuf:"varint,8,opt,name=intervalToPing,proto3" json:"intervalToPing,omitempty"`
WillKickIfInactiveFor int32 `protobuf:"varint,9,opt,name=willKickIfInactiveFor,proto3" json:"willKickIfInactiveFor,omitempty"` WillKickIfInactiveFor int32 `protobuf:"varint,9,opt,name=willKickIfInactiveFor,proto3" json:"willKickIfInactiveFor,omitempty"`
BoundRoomId int32 `protobuf:"varint,10,opt,name=boundRoomId,proto3" json:"boundRoomId,omitempty"` BoundRoomId int32 `protobuf:"varint,10,opt,name=boundRoomId,proto3" json:"boundRoomId,omitempty"`
BattleDurationNanos int64 `protobuf:"varint,11,opt,name=battleDurationNanos,proto3" json:"battleDurationNanos,omitempty"` BattleDurationFrames int32 `protobuf:"varint,12,opt,name=battleDurationFrames,proto3" json:"battleDurationFrames,omitempty"`
ServerFps int32 `protobuf:"varint,12,opt,name=serverFps,proto3" json:"serverFps,omitempty"` BattleDurationNanos int64 `protobuf:"varint,13,opt,name=battleDurationNanos,proto3" json:"battleDurationNanos,omitempty"`
InputDelayFrames int32 `protobuf:"varint,13,opt,name=inputDelayFrames,proto3" json:"inputDelayFrames,omitempty"` ServerFps int32 `protobuf:"varint,14,opt,name=serverFps,proto3" json:"serverFps,omitempty"`
InputScaleFrames uint32 `protobuf:"varint,14,opt,name=inputScaleFrames,proto3" json:"inputScaleFrames,omitempty"` InputDelayFrames int32 `protobuf:"varint,15,opt,name=inputDelayFrames,proto3" json:"inputDelayFrames,omitempty"` // in the count of render frames
NstDelayFrames int32 `protobuf:"varint,15,opt,name=nstDelayFrames,proto3" json:"nstDelayFrames,omitempty"` InputScaleFrames uint32 `protobuf:"varint,16,opt,name=inputScaleFrames,proto3" json:"inputScaleFrames,omitempty"` // inputDelayedAndScaledFrameId = ((originalFrameId - InputDelayFrames) >> InputScaleFrames)
InputFrameUpsyncDelayTolerance int32 `protobuf:"varint,16,opt,name=inputFrameUpsyncDelayTolerance,proto3" json:"inputFrameUpsyncDelayTolerance,omitempty"` NstDelayFrames int32 `protobuf:"varint,17,opt,name=nstDelayFrames,proto3" json:"nstDelayFrames,omitempty"` // network-single-trip delay in the count of render frames, proposed to be (InputDelayFrames >> 1) because we expect a round-trip delay to be exactly "InputDelayFrames"
MaxChasingRenderFramesPerUpdate int32 `protobuf:"varint,17,opt,name=maxChasingRenderFramesPerUpdate,proto3" json:"maxChasingRenderFramesPerUpdate,omitempty"` InputFrameUpsyncDelayTolerance int32 `protobuf:"varint,18,opt,name=inputFrameUpsyncDelayTolerance,proto3" json:"inputFrameUpsyncDelayTolerance,omitempty"`
PlayerBattleState int32 `protobuf:"varint,18,opt,name=playerBattleState,proto3" json:"playerBattleState,omitempty"` MaxChasingRenderFramesPerUpdate int32 `protobuf:"varint,19,opt,name=maxChasingRenderFramesPerUpdate,proto3" json:"maxChasingRenderFramesPerUpdate,omitempty"`
RollbackEstimatedDtMillis float64 `protobuf:"fixed64,19,opt,name=rollbackEstimatedDtMillis,proto3" json:"rollbackEstimatedDtMillis,omitempty"` PlayerBattleState int32 `protobuf:"varint,20,opt,name=playerBattleState,proto3" json:"playerBattleState,omitempty"`
RollbackEstimatedDtNanos int64 `protobuf:"varint,20,opt,name=rollbackEstimatedDtNanos,proto3" json:"rollbackEstimatedDtNanos,omitempty"` RollbackEstimatedDtMillis float64 `protobuf:"fixed64,21,opt,name=rollbackEstimatedDtMillis,proto3" json:"rollbackEstimatedDtMillis,omitempty"`
WorldToVirtualGridRatio float64 `protobuf:"fixed64,21,opt,name=worldToVirtualGridRatio,proto3" json:"worldToVirtualGridRatio,omitempty"` RollbackEstimatedDtNanos int64 `protobuf:"varint,22,opt,name=rollbackEstimatedDtNanos,proto3" json:"rollbackEstimatedDtNanos,omitempty"`
VirtualGridToWorldRatio float64 `protobuf:"fixed64,22,opt,name=virtualGridToWorldRatio,proto3" json:"virtualGridToWorldRatio,omitempty"` WorldToVirtualGridRatio float64 `protobuf:"fixed64,23,opt,name=worldToVirtualGridRatio,proto3" json:"worldToVirtualGridRatio,omitempty"`
SpAtkLookupFrames int32 `protobuf:"varint,23,opt,name=spAtkLookupFrames,proto3" json:"spAtkLookupFrames,omitempty"` VirtualGridToWorldRatio float64 `protobuf:"fixed64,24,opt,name=virtualGridToWorldRatio,proto3" json:"virtualGridToWorldRatio,omitempty"`
RenderCacheSize int32 `protobuf:"varint,24,opt,name=renderCacheSize,proto3" json:"renderCacheSize,omitempty"` SpAtkLookupFrames int32 `protobuf:"varint,25,opt,name=spAtkLookupFrames,proto3" json:"spAtkLookupFrames,omitempty"`
MeleeSkillConfig map[int32]*MeleeBullet `protobuf:"bytes,25,rep,name=meleeSkillConfig,proto3" json:"meleeSkillConfig,omitempty" protobuf_key:"varint,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` // skillId -> skill RenderCacheSize int32 `protobuf:"varint,26,opt,name=renderCacheSize,proto3" json:"renderCacheSize,omitempty"`
MeleeSkillConfig map[int32]*MeleeBullet `protobuf:"bytes,27,rep,name=meleeSkillConfig,proto3" json:"meleeSkillConfig,omitempty" protobuf_key:"varint,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` // skillId -> skill
} }
func (x *BattleColliderInfo) Reset() { func (x *BattleColliderInfo) Reset() {
@ -941,6 +942,13 @@ func (x *BattleColliderInfo) GetBoundRoomId() int32 {
return 0 return 0
} }
func (x *BattleColliderInfo) GetBattleDurationFrames() int32 {
if x != nil {
return x.BattleDurationFrames
}
return 0
}
func (x *BattleColliderInfo) GetBattleDurationNanos() int64 { func (x *BattleColliderInfo) GetBattleDurationNanos() int64 {
if x != nil { if x != nil {
return x.BattleDurationNanos return x.BattleDurationNanos
@ -1263,7 +1271,7 @@ var file_room_downsync_frame_proto_rawDesc = []byte{
0x65, 0x72, 0x4a, 0x6f, 0x69, 0x6e, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x2a, 0x0a, 0x10, 0x6f, 0x65, 0x72, 0x4a, 0x6f, 0x69, 0x6e, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x2a, 0x0a, 0x10, 0x6f,
0x66, 0x66, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x50, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x49, 0x64, 0x18, 0x66, 0x66, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x50, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x49, 0x64, 0x18,
0x11, 0x20, 0x01, 0x28, 0x05, 0x52, 0x10, 0x6f, 0x66, 0x66, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x50, 0x11, 0x20, 0x01, 0x28, 0x05, 0x52, 0x10, 0x6f, 0x66, 0x66, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x50,
0x6c, 0x61, 0x79, 0x65, 0x72, 0x49, 0x64, 0x22, 0xe4, 0x0c, 0x0a, 0x12, 0x42, 0x61, 0x74, 0x74, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x49, 0x64, 0x22, 0x98, 0x0d, 0x0a, 0x12, 0x42, 0x61, 0x74, 0x74,
0x6c, 0x65, 0x43, 0x6f, 0x6c, 0x6c, 0x69, 0x64, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x1c, 0x6c, 0x65, 0x43, 0x6f, 0x6c, 0x6c, 0x69, 0x64, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x1c,
0x0a, 0x09, 0x73, 0x74, 0x61, 0x67, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0a, 0x09, 0x73, 0x74, 0x61, 0x67, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28,
0x09, 0x52, 0x09, 0x73, 0x74, 0x61, 0x67, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x5f, 0x0a, 0x11, 0x09, 0x52, 0x09, 0x73, 0x74, 0x61, 0x67, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x5f, 0x0a, 0x11,
@ -1296,96 +1304,99 @@ var file_room_downsync_frame_proto_rawDesc = []byte{
0x05, 0x52, 0x15, 0x77, 0x69, 0x6c, 0x6c, 0x4b, 0x69, 0x63, 0x6b, 0x49, 0x66, 0x49, 0x6e, 0x61, 0x05, 0x52, 0x15, 0x77, 0x69, 0x6c, 0x6c, 0x4b, 0x69, 0x63, 0x6b, 0x49, 0x66, 0x49, 0x6e, 0x61,
0x63, 0x74, 0x69, 0x76, 0x65, 0x46, 0x6f, 0x72, 0x12, 0x20, 0x0a, 0x0b, 0x62, 0x6f, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x76, 0x65, 0x46, 0x6f, 0x72, 0x12, 0x20, 0x0a, 0x0b, 0x62, 0x6f, 0x75, 0x6e,
0x64, 0x52, 0x6f, 0x6f, 0x6d, 0x49, 0x64, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0b, 0x62, 0x64, 0x52, 0x6f, 0x6f, 0x6d, 0x49, 0x64, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0b, 0x62,
0x6f, 0x75, 0x6e, 0x64, 0x52, 0x6f, 0x6f, 0x6d, 0x49, 0x64, 0x12, 0x30, 0x0a, 0x13, 0x62, 0x61, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x6f, 0x6f, 0x6d, 0x49, 0x64, 0x12, 0x32, 0x0a, 0x14, 0x62, 0x61,
0x74, 0x74, 0x6c, 0x65, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4e, 0x61, 0x6e, 0x6f, 0x74, 0x74, 0x6c, 0x65, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x46, 0x72, 0x61, 0x6d,
0x73, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x03, 0x52, 0x13, 0x62, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x44, 0x65, 0x73, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x05, 0x52, 0x14, 0x62, 0x61, 0x74, 0x74, 0x6c, 0x65,
0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4e, 0x61, 0x6e, 0x6f, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x12, 0x30,
0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x46, 0x70, 0x73, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0a, 0x13, 0x62, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e,
0x09, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x46, 0x70, 0x73, 0x12, 0x2a, 0x0a, 0x10, 0x69, 0x6e, 0x4e, 0x61, 0x6e, 0x6f, 0x73, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x03, 0x52, 0x13, 0x62, 0x61, 0x74,
0x70, 0x75, 0x74, 0x44, 0x65, 0x6c, 0x61, 0x79, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x0d, 0x74, 0x6c, 0x65, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4e, 0x61, 0x6e, 0x6f, 0x73,
0x20, 0x01, 0x28, 0x05, 0x52, 0x10, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x44, 0x65, 0x6c, 0x61, 0x79, 0x12, 0x1c, 0x0a, 0x09, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x46, 0x70, 0x73, 0x18, 0x0e, 0x20,
0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x12, 0x2a, 0x0a, 0x10, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x53, 0x01, 0x28, 0x05, 0x52, 0x09, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x46, 0x70, 0x73, 0x12, 0x2a,
0x63, 0x61, 0x6c, 0x65, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x0d, 0x0a, 0x10, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x44, 0x65, 0x6c, 0x61, 0x79, 0x46, 0x72, 0x61, 0x6d,
0x52, 0x10, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x53, 0x63, 0x61, 0x6c, 0x65, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x05, 0x52, 0x10, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x44,
0x65, 0x73, 0x12, 0x26, 0x0a, 0x0e, 0x6e, 0x73, 0x74, 0x44, 0x65, 0x6c, 0x61, 0x79, 0x46, 0x72, 0x65, 0x6c, 0x61, 0x79, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x12, 0x2a, 0x0a, 0x10, 0x69, 0x6e,
0x61, 0x6d, 0x65, 0x73, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0e, 0x6e, 0x73, 0x74, 0x44, 0x70, 0x75, 0x74, 0x53, 0x63, 0x61, 0x6c, 0x65, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x10,
0x65, 0x6c, 0x61, 0x79, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x12, 0x46, 0x0a, 0x1e, 0x69, 0x6e, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x10, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x53, 0x63, 0x61, 0x6c, 0x65,
0x70, 0x75, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x55, 0x70, 0x73, 0x79, 0x6e, 0x63, 0x44, 0x65, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x12, 0x26, 0x0a, 0x0e, 0x6e, 0x73, 0x74, 0x44, 0x65, 0x6c,
0x6c, 0x61, 0x79, 0x54, 0x6f, 0x6c, 0x65, 0x72, 0x61, 0x6e, 0x63, 0x65, 0x18, 0x10, 0x20, 0x01, 0x61, 0x79, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x11, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0e,
0x28, 0x05, 0x52, 0x1e, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x55, 0x70, 0x6e, 0x73, 0x74, 0x44, 0x65, 0x6c, 0x61, 0x79, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x12, 0x46,
0x73, 0x79, 0x6e, 0x63, 0x44, 0x65, 0x6c, 0x61, 0x79, 0x54, 0x6f, 0x6c, 0x65, 0x72, 0x61, 0x6e, 0x0a, 0x1e, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x55, 0x70, 0x73, 0x79,
0x63, 0x65, 0x12, 0x48, 0x0a, 0x1f, 0x6d, 0x61, 0x78, 0x43, 0x68, 0x61, 0x73, 0x69, 0x6e, 0x67, 0x6e, 0x63, 0x44, 0x65, 0x6c, 0x61, 0x79, 0x54, 0x6f, 0x6c, 0x65, 0x72, 0x61, 0x6e, 0x63, 0x65,
0x52, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x50, 0x65, 0x72, 0x55, 0x18, 0x12, 0x20, 0x01, 0x28, 0x05, 0x52, 0x1e, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x46, 0x72, 0x61,
0x70, 0x64, 0x61, 0x74, 0x65, 0x18, 0x11, 0x20, 0x01, 0x28, 0x05, 0x52, 0x1f, 0x6d, 0x61, 0x78, 0x6d, 0x65, 0x55, 0x70, 0x73, 0x79, 0x6e, 0x63, 0x44, 0x65, 0x6c, 0x61, 0x79, 0x54, 0x6f, 0x6c,
0x43, 0x68, 0x61, 0x73, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x46, 0x72, 0x61, 0x65, 0x72, 0x61, 0x6e, 0x63, 0x65, 0x12, 0x48, 0x0a, 0x1f, 0x6d, 0x61, 0x78, 0x43, 0x68, 0x61,
0x6d, 0x65, 0x73, 0x50, 0x65, 0x72, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x12, 0x2c, 0x0a, 0x11, 0x73, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73,
0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x42, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x53, 0x74, 0x61, 0x74, 0x50, 0x65, 0x72, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x18, 0x13, 0x20, 0x01, 0x28, 0x05, 0x52,
0x65, 0x18, 0x12, 0x20, 0x01, 0x28, 0x05, 0x52, 0x11, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x42, 0x1f, 0x6d, 0x61, 0x78, 0x43, 0x68, 0x61, 0x73, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x6e, 0x64, 0x65,
0x61, 0x74, 0x74, 0x6c, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x3c, 0x0a, 0x19, 0x72, 0x6f, 0x72, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x50, 0x65, 0x72, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65,
0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x45, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x64, 0x44, 0x12, 0x2c, 0x0a, 0x11, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x42, 0x61, 0x74, 0x74, 0x6c, 0x65,
0x74, 0x4d, 0x69, 0x6c, 0x6c, 0x69, 0x73, 0x18, 0x13, 0x20, 0x01, 0x28, 0x01, 0x52, 0x19, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x18, 0x14, 0x20, 0x01, 0x28, 0x05, 0x52, 0x11, 0x70, 0x6c, 0x61,
0x6f, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x45, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x64, 0x79, 0x65, 0x72, 0x42, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x3c,
0x44, 0x74, 0x4d, 0x69, 0x6c, 0x6c, 0x69, 0x73, 0x12, 0x3a, 0x0a, 0x18, 0x72, 0x6f, 0x6c, 0x6c, 0x0a, 0x19, 0x72, 0x6f, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x45, 0x73, 0x74, 0x69, 0x6d, 0x61,
0x62, 0x61, 0x63, 0x6b, 0x45, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x64, 0x44, 0x74, 0x4e, 0x74, 0x65, 0x64, 0x44, 0x74, 0x4d, 0x69, 0x6c, 0x6c, 0x69, 0x73, 0x18, 0x15, 0x20, 0x01, 0x28,
0x61, 0x6e, 0x6f, 0x73, 0x18, 0x14, 0x20, 0x01, 0x28, 0x03, 0x52, 0x18, 0x72, 0x6f, 0x6c, 0x6c, 0x01, 0x52, 0x19, 0x72, 0x6f, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x45, 0x73, 0x74, 0x69, 0x6d,
0x62, 0x61, 0x63, 0x6b, 0x45, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x64, 0x44, 0x74, 0x4e, 0x61, 0x74, 0x65, 0x64, 0x44, 0x74, 0x4d, 0x69, 0x6c, 0x6c, 0x69, 0x73, 0x12, 0x3a, 0x0a, 0x18,
0x61, 0x6e, 0x6f, 0x73, 0x12, 0x38, 0x0a, 0x17, 0x77, 0x6f, 0x72, 0x6c, 0x64, 0x54, 0x6f, 0x56, 0x72, 0x6f, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x45, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65,
0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x47, 0x72, 0x69, 0x64, 0x52, 0x61, 0x74, 0x69, 0x6f, 0x18, 0x64, 0x44, 0x74, 0x4e, 0x61, 0x6e, 0x6f, 0x73, 0x18, 0x16, 0x20, 0x01, 0x28, 0x03, 0x52, 0x18,
0x15, 0x20, 0x01, 0x28, 0x01, 0x52, 0x17, 0x77, 0x6f, 0x72, 0x6c, 0x64, 0x54, 0x6f, 0x56, 0x69, 0x72, 0x6f, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x45, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65,
0x72, 0x74, 0x75, 0x61, 0x6c, 0x47, 0x72, 0x69, 0x64, 0x52, 0x61, 0x74, 0x69, 0x6f, 0x12, 0x38, 0x64, 0x44, 0x74, 0x4e, 0x61, 0x6e, 0x6f, 0x73, 0x12, 0x38, 0x0a, 0x17, 0x77, 0x6f, 0x72, 0x6c,
0x0a, 0x17, 0x76, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x47, 0x72, 0x69, 0x64, 0x54, 0x6f, 0x57, 0x64, 0x54, 0x6f, 0x56, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x47, 0x72, 0x69, 0x64, 0x52, 0x61,
0x6f, 0x72, 0x6c, 0x64, 0x52, 0x61, 0x74, 0x69, 0x6f, 0x18, 0x16, 0x20, 0x01, 0x28, 0x01, 0x52, 0x74, 0x69, 0x6f, 0x18, 0x17, 0x20, 0x01, 0x28, 0x01, 0x52, 0x17, 0x77, 0x6f, 0x72, 0x6c, 0x64,
0x17, 0x76, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x47, 0x72, 0x69, 0x64, 0x54, 0x6f, 0x57, 0x6f, 0x54, 0x6f, 0x56, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x47, 0x72, 0x69, 0x64, 0x52, 0x61, 0x74,
0x72, 0x6c, 0x64, 0x52, 0x61, 0x74, 0x69, 0x6f, 0x12, 0x2c, 0x0a, 0x11, 0x73, 0x70, 0x41, 0x74, 0x69, 0x6f, 0x12, 0x38, 0x0a, 0x17, 0x76, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x47, 0x72, 0x69,
0x6b, 0x4c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x17, 0x20, 0x64, 0x54, 0x6f, 0x57, 0x6f, 0x72, 0x6c, 0x64, 0x52, 0x61, 0x74, 0x69, 0x6f, 0x18, 0x18, 0x20,
0x01, 0x28, 0x05, 0x52, 0x11, 0x73, 0x70, 0x41, 0x74, 0x6b, 0x4c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x01, 0x28, 0x01, 0x52, 0x17, 0x76, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x47, 0x72, 0x69, 0x64,
0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x12, 0x28, 0x0a, 0x0f, 0x72, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x54, 0x6f, 0x57, 0x6f, 0x72, 0x6c, 0x64, 0x52, 0x61, 0x74, 0x69, 0x6f, 0x12, 0x2c, 0x0a, 0x11,
0x43, 0x61, 0x63, 0x68, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x18, 0x18, 0x20, 0x01, 0x28, 0x05, 0x52, 0x73, 0x70, 0x41, 0x74, 0x6b, 0x4c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x46, 0x72, 0x61, 0x6d, 0x65,
0x0f, 0x72, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x43, 0x61, 0x63, 0x68, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x73, 0x18, 0x19, 0x20, 0x01, 0x28, 0x05, 0x52, 0x11, 0x73, 0x70, 0x41, 0x74, 0x6b, 0x4c, 0x6f,
0x12, 0x5c, 0x0a, 0x10, 0x6d, 0x65, 0x6c, 0x65, 0x65, 0x53, 0x6b, 0x69, 0x6c, 0x6c, 0x43, 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x12, 0x28, 0x0a, 0x0f, 0x72, 0x65,
0x6e, 0x66, 0x69, 0x67, 0x18, 0x19, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x70, 0x72, 0x6f, 0x6e, 0x64, 0x65, 0x72, 0x43, 0x61, 0x63, 0x68, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x18, 0x1a, 0x20,
0x74, 0x6f, 0x73, 0x2e, 0x42, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x43, 0x6f, 0x6c, 0x6c, 0x69, 0x64, 0x01, 0x28, 0x05, 0x52, 0x0f, 0x72, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x43, 0x61, 0x63, 0x68, 0x65,
0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x2e, 0x4d, 0x65, 0x6c, 0x65, 0x65, 0x53, 0x6b, 0x69, 0x6c, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x5c, 0x0a, 0x10, 0x6d, 0x65, 0x6c, 0x65, 0x65, 0x53, 0x6b, 0x69,
0x6c, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x10, 0x6d, 0x65, 0x6c, 0x6c, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x1b, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x30,
0x6c, 0x65, 0x65, 0x53, 0x6b, 0x69, 0x6c, 0x6c, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x1a, 0x5d, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x42, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x43, 0x6f,
0x0a, 0x16, 0x53, 0x74, 0x72, 0x54, 0x6f, 0x56, 0x65, 0x63, 0x32, 0x44, 0x4c, 0x69, 0x73, 0x74, 0x6c, 0x6c, 0x69, 0x64, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x2e, 0x4d, 0x65, 0x6c, 0x65, 0x65,
0x4d, 0x61, 0x70, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x53, 0x6b, 0x69, 0x6c, 0x6c, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x45, 0x6e, 0x74, 0x72, 0x79,
0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x2d, 0x0a, 0x05, 0x76, 0x61, 0x52, 0x10, 0x6d, 0x65, 0x6c, 0x65, 0x65, 0x53, 0x6b, 0x69, 0x6c, 0x6c, 0x43, 0x6f, 0x6e, 0x66,
0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x73, 0x68, 0x61, 0x72, 0x69, 0x67, 0x1a, 0x5d, 0x0a, 0x16, 0x53, 0x74, 0x72, 0x54, 0x6f, 0x56, 0x65, 0x63, 0x32, 0x44,
0x65, 0x64, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x56, 0x65, 0x63, 0x32, 0x44, 0x4c, 0x69, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x61, 0x70, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03,
0x73, 0x74, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x65, 0x0a, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x2d,
0x1a, 0x53, 0x74, 0x72, 0x54, 0x6f, 0x50, 0x6f, 0x6c, 0x79, 0x67, 0x6f, 0x6e, 0x32, 0x44, 0x4c, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e,
0x69, 0x73, 0x74, 0x4d, 0x61, 0x70, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x73, 0x68, 0x61, 0x72, 0x65, 0x64, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x56, 0x65, 0x63,
0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x31, 0x0a, 0x32, 0x44, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38,
0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x73, 0x01, 0x1a, 0x65, 0x0a, 0x1a, 0x53, 0x74, 0x72, 0x54, 0x6f, 0x50, 0x6f, 0x6c, 0x79, 0x67, 0x6f,
0x68, 0x61, 0x72, 0x65, 0x64, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x50, 0x6f, 0x6c, 0x79, 0x6e, 0x32, 0x44, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x61, 0x70, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12,
0x67, 0x6f, 0x6e, 0x32, 0x44, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65,
0x3a, 0x02, 0x38, 0x01, 0x1a, 0x58, 0x0a, 0x15, 0x4d, 0x65, 0x6c, 0x65, 0x65, 0x53, 0x6b, 0x69, 0x79, 0x12, 0x31, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b,
0x6c, 0x6c, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x32, 0x1b, 0x2e, 0x73, 0x68, 0x61, 0x72, 0x65, 0x64, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e,
0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x50, 0x6f, 0x6c, 0x79, 0x67, 0x6f, 0x6e, 0x32, 0x44, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x05, 0x76,
0x29, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x58, 0x0a, 0x15, 0x4d, 0x65, 0x6c, 0x65,
0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x4d, 0x65, 0x6c, 0x65, 0x65, 0x42, 0x75, 0x6c, 0x65, 0x53, 0x6b, 0x69, 0x6c, 0x6c, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x45, 0x6e, 0x74, 0x72,
0x6c, 0x65, 0x74, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x9a, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x03,
0x02, 0x0a, 0x11, 0x52, 0x6f, 0x6f, 0x6d, 0x44, 0x6f, 0x77, 0x6e, 0x73, 0x79, 0x6e, 0x63, 0x46, 0x6b, 0x65, 0x79, 0x12, 0x29, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01,
0x72, 0x61, 0x6d, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x4d, 0x65, 0x6c, 0x65,
0x52, 0x02, 0x69, 0x64, 0x12, 0x40, 0x0a, 0x07, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x73, 0x18, 0x65, 0x42, 0x75, 0x6c, 0x6c, 0x65, 0x74, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02,
0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x52, 0x38, 0x01, 0x22, 0x9a, 0x02, 0x0a, 0x11, 0x52, 0x6f, 0x6f, 0x6d, 0x44, 0x6f, 0x77, 0x6e, 0x73,
0x6f, 0x6f, 0x6d, 0x44, 0x6f, 0x77, 0x6e, 0x73, 0x79, 0x6e, 0x63, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x79, 0x6e, 0x63, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01,
0x2e, 0x50, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x07, 0x70, 0x20, 0x01, 0x28, 0x05, 0x52, 0x02, 0x69, 0x64, 0x12, 0x40, 0x0a, 0x07, 0x70, 0x6c, 0x61, 0x79,
0x6c, 0x61, 0x79, 0x65, 0x72, 0x73, 0x12, 0x26, 0x0a, 0x0e, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x64, 0x65, 0x72, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x70, 0x72, 0x6f, 0x74,
0x6f, 0x77, 0x6e, 0x4e, 0x61, 0x6e, 0x6f, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, 0x6f, 0x73, 0x2e, 0x52, 0x6f, 0x6f, 0x6d, 0x44, 0x6f, 0x77, 0x6e, 0x73, 0x79, 0x6e, 0x63, 0x46,
0x63, 0x6f, 0x75, 0x6e, 0x74, 0x64, 0x6f, 0x77, 0x6e, 0x4e, 0x61, 0x6e, 0x6f, 0x73, 0x12, 0x37, 0x72, 0x61, 0x6d, 0x65, 0x2e, 0x50, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x73, 0x45, 0x6e, 0x74, 0x72,
0x0a, 0x0c, 0x6d, 0x65, 0x6c, 0x65, 0x65, 0x42, 0x75, 0x6c, 0x6c, 0x65, 0x74, 0x73, 0x18, 0x04, 0x79, 0x52, 0x07, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x73, 0x12, 0x26, 0x0a, 0x0e, 0x63, 0x6f,
0x20, 0x03, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x4d, 0x65, 0x75, 0x6e, 0x74, 0x64, 0x6f, 0x77, 0x6e, 0x4e, 0x61, 0x6e, 0x6f, 0x73, 0x18, 0x03, 0x20, 0x01,
0x6c, 0x65, 0x65, 0x42, 0x75, 0x6c, 0x6c, 0x65, 0x74, 0x52, 0x0c, 0x6d, 0x65, 0x6c, 0x65, 0x65, 0x28, 0x03, 0x52, 0x0e, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x64, 0x6f, 0x77, 0x6e, 0x4e, 0x61, 0x6e,
0x42, 0x75, 0x6c, 0x6c, 0x65, 0x74, 0x73, 0x1a, 0x52, 0x0a, 0x0c, 0x50, 0x6c, 0x61, 0x79, 0x65, 0x6f, 0x73, 0x12, 0x37, 0x0a, 0x0c, 0x6d, 0x65, 0x6c, 0x65, 0x65, 0x42, 0x75, 0x6c, 0x6c, 0x65,
0x72, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x74, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
0x20, 0x01, 0x28, 0x05, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x2c, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x73, 0x2e, 0x4d, 0x65, 0x6c, 0x65, 0x65, 0x42, 0x75, 0x6c, 0x6c, 0x65, 0x74, 0x52, 0x0c, 0x6d,
0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x65, 0x6c, 0x65, 0x65, 0x42, 0x75, 0x6c, 0x6c, 0x65, 0x74, 0x73, 0x1a, 0x52, 0x0a, 0x0c, 0x50,
0x73, 0x2e, 0x50, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x44, 0x6f, 0x77, 0x6e, 0x73, 0x79, 0x6e, 0x63, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b,
0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x42, 0x13, 0x5a, 0x11, 0x62, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x2c, 0x0a,
0x61, 0x74, 0x74, 0x6c, 0x65, 0x5f, 0x73, 0x72, 0x76, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x70,
0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x50, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x44, 0x6f, 0x77, 0x6e,
0x73, 0x79, 0x6e, 0x63, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x42,
0x13, 0x5a, 0x11, 0x62, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x5f, 0x73, 0x72, 0x76, 0x2f, 0x70, 0x72,
0x6f, 0x74, 0x6f, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
} }
var ( var (

View File

@ -272,6 +272,7 @@ func Serve(c *gin.Context) {
SpAtkLookupFrames: pRoom.SpAtkLookupFrames, SpAtkLookupFrames: pRoom.SpAtkLookupFrames,
RenderCacheSize: pRoom.RenderCacheSize, RenderCacheSize: pRoom.RenderCacheSize,
MeleeSkillConfig: pRoom.MeleeSkillConfig,
} }
resp := &pb.WsResp{ resp := &pb.WsResp{

File diff suppressed because one or more lines are too long

View File

@ -1,7 +1,7 @@
{ {
"ver": "1.0.0", "ver": "1.0.0",
"uuid": "2f5ba371-9006-4e2d-8dd4-df91fcea1df2", "uuid": "e9e703e9-3589-4713-b889-28b23406d220",
"atlasJson": "{\"SubTexture\":[{\"y\":50,\"frameX\":-2,\"frameY\":-2,\"width\":19,\"frameWidth\":23,\"height\":19,\"name\":\"biu\",\"frameHeight\":22,\"x\":1},{\"width\":9,\"y\":50,\"height\":14,\"name\":\"rightArm\",\"x\":42},{\"y\":34,\"frameX\":-6,\"frameY\":0,\"width\":20,\"frameWidth\":29,\"height\":32,\"name\":\"yinmoqe00\",\"frameHeight\":32,\"x\":88},{\"y\":1,\"frameX\":0,\"frameY\":0,\"width\":33,\"frameWidth\":34,\"height\":39,\"name\":\"body\",\"frameHeight\":41,\"x\":53},{\"width\":9,\"y\":56,\"height\":13,\"name\":\"rightShoulder\",\"x\":74},{\"y\":50,\"frameX\":0,\"frameY\":0,\"width\":18,\"frameWidth\":19,\"height\":17,\"name\":\"rightFrontArm\",\"frameHeight\":18,\"x\":22},{\"width\":14,\"y\":50,\"height\":14,\"name\":\"rightHand\",\"x\":110},{\"width\":12,\"y\":42,\"height\":12,\"name\":\"leftArm\",\"x\":74},{\"width\":13,\"y\":66,\"height\":12,\"name\":\"leftShoulder\",\"x\":110},{\"y\":42,\"frameX\":-1,\"frameY\":0,\"width\":19,\"frameWidth\":20,\"height\":21,\"name\":\"leftFrontArm\",\"frameHeight\":21,\"x\":53},{\"width\":50,\"y\":1,\"height\":47,\"name\":\"head2\",\"x\":1},{\"y\":1,\"frameX\":-1,\"frameY\":0,\"width\":32,\"frameWidth\":33,\"height\":31,\"name\":\"head\",\"frameHeight\":32,\"x\":88},{\"width\":16,\"y\":34,\"height\":14,\"name\":\"leftHand\",\"x\":110},{\"y\":1,\"frameX\":-2,\"frameY\":-3,\"width\":2,\"frameWidth\":8,\"height\":2,\"name\":\"huomiao01\",\"frameHeight\":8,\"x\":122}],\"width\":128,\"height\":128,\"name\":\"SoldierWaterGhost\",\"imagePath\":\"SoldierWaterGhost_tex.png\"}", "atlasJson": "{\"SubTexture\":[{\"y\":50,\"frameX\":-2,\"frameY\":-2,\"width\":19,\"frameWidth\":23,\"height\":19,\"name\":\"biu\",\"frameHeight\":22,\"x\":1},{\"width\":9,\"y\":50,\"height\":14,\"name\":\"rightArm\",\"x\":42},{\"y\":34,\"frameX\":-6,\"frameY\":0,\"width\":20,\"frameWidth\":29,\"height\":32,\"name\":\"yinmoqe00\",\"frameHeight\":32,\"x\":88},{\"y\":1,\"frameX\":0,\"frameY\":0,\"width\":33,\"frameWidth\":34,\"height\":39,\"name\":\"body\",\"frameHeight\":41,\"x\":53},{\"width\":9,\"y\":56,\"height\":13,\"name\":\"rightShoulder\",\"x\":74},{\"y\":50,\"frameX\":0,\"frameY\":0,\"width\":18,\"frameWidth\":19,\"height\":17,\"name\":\"rightFrontArm\",\"frameHeight\":18,\"x\":22},{\"width\":14,\"y\":50,\"height\":14,\"name\":\"rightHand\",\"x\":110},{\"width\":12,\"y\":42,\"height\":12,\"name\":\"leftArm\",\"x\":74},{\"width\":13,\"y\":66,\"height\":12,\"name\":\"leftShoulder\",\"x\":110},{\"y\":42,\"frameX\":-1,\"frameY\":0,\"width\":19,\"frameWidth\":20,\"height\":21,\"name\":\"leftFrontArm\",\"frameHeight\":21,\"x\":53},{\"width\":50,\"y\":1,\"height\":47,\"name\":\"head2\",\"x\":1},{\"y\":1,\"frameX\":-1,\"frameY\":0,\"width\":32,\"frameWidth\":33,\"height\":31,\"name\":\"head\",\"frameHeight\":32,\"x\":88},{\"width\":16,\"y\":34,\"height\":14,\"name\":\"leftHand\",\"x\":110},{\"y\":1,\"frameX\":-2,\"frameY\":-3,\"width\":2,\"frameWidth\":8,\"height\":2,\"name\":\"huomiao01\",\"frameHeight\":8,\"x\":122}],\"width\":128,\"height\":128,\"name\":\"SoldierWaterGhost\",\"imagePath\":\"SoldierWaterGhost_tex.png\"}",
"texture": "62ea1a78-b096-4b8c-afb4-8edd4be142f7", "texture": "def168c3-3f07-43f9-a460-36b397c70a57",
"subMetas": {} "subMetas": {}
} }

View File

@ -1,6 +1,6 @@
{ {
"ver": "2.3.3", "ver": "2.3.3",
"uuid": "62ea1a78-b096-4b8c-afb4-8edd4be142f7", "uuid": "def168c3-3f07-43f9-a460-36b397c70a57",
"type": "sprite", "type": "sprite",
"wrapMode": "clamp", "wrapMode": "clamp",
"filterMode": "bilinear", "filterMode": "bilinear",
@ -11,8 +11,8 @@
"subMetas": { "subMetas": {
"SoldierWaterGhost_tex": { "SoldierWaterGhost_tex": {
"ver": "1.0.4", "ver": "1.0.4",
"uuid": "e7b96c0e-a9b8-40eb-8568-73bd2803cd31", "uuid": "52fb0606-bbea-433c-803b-bf5ce936a0df",
"rawTextureUuid": "62ea1a78-b096-4b8c-afb4-8edd4be142f7", "rawTextureUuid": "def168c3-3f07-43f9-a460-36b397c70a57",
"trimType": "auto", "trimType": "auto",
"trimThreshold": 1, "trimThreshold": 1,
"rotated": false, "rotated": false,

View File

@ -108,24 +108,25 @@ message BattleColliderInfo {
int32 intervalToPing = 8; int32 intervalToPing = 8;
int32 willKickIfInactiveFor = 9; int32 willKickIfInactiveFor = 9;
int32 boundRoomId = 10; int32 boundRoomId = 10;
int64 battleDurationNanos = 11; int32 battleDurationFrames = 12;
int32 serverFps = 12; int64 battleDurationNanos = 13;
int32 inputDelayFrames = 13; int32 serverFps = 14;
uint32 inputScaleFrames = 14; int32 inputDelayFrames = 15; // in the count of render frames
int32 nstDelayFrames = 15; uint32 inputScaleFrames = 16; // inputDelayedAndScaledFrameId = ((originalFrameId - InputDelayFrames) >> InputScaleFrames)
int32 inputFrameUpsyncDelayTolerance = 16; int32 nstDelayFrames = 17; // network-single-trip delay in the count of render frames, proposed to be (InputDelayFrames >> 1) because we expect a round-trip delay to be exactly "InputDelayFrames"
int32 maxChasingRenderFramesPerUpdate = 17; int32 inputFrameUpsyncDelayTolerance = 18;
int32 playerBattleState = 18; int32 maxChasingRenderFramesPerUpdate = 19;
double rollbackEstimatedDtMillis = 19; int32 playerBattleState = 20;
int64 rollbackEstimatedDtNanos = 20; double rollbackEstimatedDtMillis = 21;
int64 rollbackEstimatedDtNanos = 22;
double worldToVirtualGridRatio = 21; double worldToVirtualGridRatio = 23;
double virtualGridToWorldRatio = 22; double virtualGridToWorldRatio = 24;
int32 spAtkLookupFrames = 23; int32 spAtkLookupFrames = 25;
int32 renderCacheSize = 24; int32 renderCacheSize = 26;
map<int32, MeleeBullet> meleeSkillConfig = 25; // skillId -> skill map<int32, MeleeBullet> meleeSkillConfig = 27; // skillId -> skill
} }
message RoomDownsyncFrame { message RoomDownsyncFrame {

View File

@ -860,7 +860,7 @@
"_cacheMode": 0, "_cacheMode": 0,
"playTimes": -1, "playTimes": -1,
"premultipliedAlpha": false, "premultipliedAlpha": false,
"_armatureKey": "73b7e7d4-6ad0-41ea-9d17-1104c463aad2#2f5ba371-9006-4e2d-8dd4-df91fcea1df2", "_armatureKey": "a9d7bbc2-134b-4eb4-ba16-6541f3e51e06#e9e703e9-3589-4713-b889-28b23406d220",
"_accTime": 0, "_accTime": 0,
"_playCount": 0, "_playCount": 0,
"_frameCache": null, "_frameCache": null,
@ -868,10 +868,10 @@
"_playing": false, "_playing": false,
"_armatureCache": null, "_armatureCache": null,
"_N$dragonAsset": { "_N$dragonAsset": {
"__uuid__": "73b7e7d4-6ad0-41ea-9d17-1104c463aad2" "__uuid__": "a9d7bbc2-134b-4eb4-ba16-6541f3e51e06"
}, },
"_N$dragonAtlasAsset": { "_N$dragonAtlasAsset": {
"__uuid__": "2f5ba371-9006-4e2d-8dd4-df91fcea1df2" "__uuid__": "e9e703e9-3589-4713-b889-28b23406d220"
}, },
"_N$_defaultArmatureIndex": 0, "_N$_defaultArmatureIndex": 0,
"_N$_animationIndex": 8, "_N$_animationIndex": 8,

View File

@ -440,7 +440,7 @@
"array": [ "array": [
0, 0,
0, 0,
210.23252687912068, 216.50635094610968,
0, 0,
0, 0,
0, 0,

View File

@ -454,7 +454,7 @@
"array": [ "array": [
0, 0,
0, 0,
210.23252687912068, 216.50635094610968,
0, 0,
0, 0,
0, 0,

View File

@ -991,7 +991,7 @@ cc.Class({
const lastAllConfirmedInputFrame = self.recentInputCache.getByFrameId(self.lastAllConfirmedInputFrameId); const lastAllConfirmedInputFrame = self.recentInputCache.getByFrameId(self.lastAllConfirmedInputFrameId);
for (let i = 0; i < inputFrameDownsync.inputList.length; ++i) { for (let i = 0; i < inputFrameDownsync.inputList.length; ++i) {
if (i == self.selfPlayerInfo.joinIndex - 1) continue; if (i == self.selfPlayerInfo.joinIndex - 1) continue;
inputFrameDownsync.inputList[i] = lastAllConfirmedInputFrame.inputList[i]; inputFrameDownsync.inputList[i] = (lastAllConfirmedInputFrame.inputList[i] & 15); // Don't predict attack input!
} }
} }
@ -1141,7 +1141,7 @@ cc.Class({
playerCollider.x += bulletPushbacks[joinIndex - 1][0]; playerCollider.x += bulletPushbacks[joinIndex - 1][0];
playerCollider.y += bulletPushbacks[joinIndex - 1][1]; playerCollider.y += bulletPushbacks[joinIndex - 1][1];
if (0 != bulletPushbacks[joinIndex - 1][0] || 0 != bulletPushbacks[joinIndex - 1][1]) { if (0 != bulletPushbacks[joinIndex - 1][0] || 0 != bulletPushbacks[joinIndex - 1][1]) {
console.log(`playerId=${playerId}, joinIndex=${joinIndex} is pushbacked back by ${bulletPushbacks[joinIndex - 1]} by bullet impacts, now its framesToRecover is ${currPlayerDownsync.framesToRecover}`); console.log(`playerId=${playerId}, joinIndex=${joinIndex} is pushbacked back by ${bulletPushbacks[joinIndex - 1]} by bullet impacts, now its framesToRecover is ${thatPlayerInNextFrame.framesToRecover}`);
} }
continue; continue;
} }
@ -1154,14 +1154,16 @@ cc.Class({
if (1 == decodedInput.btnALevel && 0 == prevBtnALevel) { if (1 == decodedInput.btnALevel && 0 == prevBtnALevel) {
// console.log(`playerId=${playerId} triggered a rising-edge of btnA at renderFrame.id=${currRenderFrame.id}, delayedInputFrame.id=${delayedInputFrame.inputFrameId}`); // console.log(`playerId=${playerId} triggered a rising-edge of btnA at renderFrame.id=${currRenderFrame.id}, delayedInputFrame.id=${delayedInputFrame.inputFrameId}`);
if (self.bulletTriggerEnabled) { if (self.bulletTriggerEnabled) {
thatPlayerInNextFrame.framesToRecover = window.PunchAtkConfig.recoveryFrames; const punchSkillId = 1;
const punch = window.pb.protos.MeleeBullet.create(window.PunchAtkConfig); const punch = window.pb.protos.MeleeBullet.create(self.meleeSkillConfig[punchSkillId]);
thatPlayerInNextFrame.framesToRecover = punch.recoveryFrames;
punch.battleLocalId = self.bulletBattleLocalIdCounter++; punch.battleLocalId = self.bulletBattleLocalIdCounter++;
punch.offenderJoinIndex = joinIndex; punch.offenderJoinIndex = joinIndex;
punch.offenderPlayerId = playerId; punch.offenderPlayerId = playerId;
punch.originatedRenderFrameId = currRenderFrame.id; punch.originatedRenderFrameId = currRenderFrame.id;
toRet.meleeBullets.push(punch); toRet.meleeBullets.push(punch);
console.log(`A rising-edge of meleeBullet is created at renderFrame.id=${currRenderFrame.id}, delayedInputFrame.id=${delayedInputFrame.inputFrameId}: ${self._stringifyRecentInputCache(true)}`); // console.log(`A rising-edge of meleeBullet is created at renderFrame.id=${currRenderFrame.id}, delayedInputFrame.id=${delayedInputFrame.inputFrameId}: ${self._stringifyRecentInputCache(true)}`);
// console.log(`A rising-edge of meleeBullet is created at renderFrame.id=${currRenderFrame.id}, delayedInputFrame.id=${delayedInputFrame.inputFrameId}`);
thatPlayerInNextFrame.characterState = window.ATK_CHARACTER_STATE.Atk1[0]; thatPlayerInNextFrame.characterState = window.ATK_CHARACTER_STATE.Atk1[0];
} }

View File

@ -3,31 +3,6 @@ i18n.init(window.language); // languageID should be equal to the one we input in
const OnlineMap = require('./Map'); const OnlineMap = require('./Map');
window.PunchAtkConfig = {
// for offender
startupFrames: 18,
activeFrames: 42,
recoveryFrames: 61, // usually but not always "startupFrames+activeFrames", I hereby set it to be 1 frame more than the actual animation to avoid critical transition, i.e. when the animation is 1 frame from ending but "rdfPlayer.framesToRecover" is already counted 0 and the player triggers an other same attack, making an effective bullet trigger but no animation is played due to same animName is still playing
recoveryFramesOnBlock: 61,
recoveryFramesOnHit: 61,
moveforward: {
x: 0,
y: 0,
},
hitboxOffset: 12.0, // should be about the radius of the PlayerCollider
hitboxSize: {
x: 45.0,
y: 32.0,
},
// for defender
hitStunFrames: 18,
blockStunFrames: 9,
pushback: 22.0,
releaseTriggerType: 1, // 1: rising-edge, 2: falling-edge
damage: 5
};
cc.Class({ cc.Class({
extends: OnlineMap, extends: OnlineMap,
@ -64,6 +39,32 @@ cc.Class({
self.worldToVirtualGridRatio = 1000; self.worldToVirtualGridRatio = 1000;
self.virtualGridToWorldRatio = 1.0 / self.worldToVirtualGridRatio; self.virtualGridToWorldRatio = 1.0 / self.worldToVirtualGridRatio;
self.meleeSkillConfig = {
1: {
// for offender
startupFrames: 18,
activeFrames: 42,
recoveryFrames: 61, // usually but not always "startupFrames+activeFrames", I hereby set it to be 1 frame more than the actual animation to avoid critical transition, i.e. when the animation is 1 frame from ending but "rdfPlayer.framesToRecover" is already counted 0 and the player triggers an other same attack, making an effective bullet trigger but no animation is played due to same animName is still playing
recoveryFramesOnBlock: 61,
recoveryFramesOnHit: 61,
moveforward: {
x: 0,
y: 0,
},
hitboxOffset: 12.0, // should be about the radius of the PlayerCollider
hitboxSize: {
x: 45.0,
y: 32.0,
},
// for defender
hitStunFrames: 18,
blockStunFrames: 9,
pushback: 22.0,
releaseTriggerType: 1, // 1: rising-edge, 2: falling-edge
damage: 5
}
};
const tiledMapIns = self.node.getComponent(cc.TiledMap); const tiledMapIns = self.node.getComponent(cc.TiledMap);

View File

@ -4151,6 +4151,7 @@ $root.protos = (function() {
* @property {number|null} [intervalToPing] BattleColliderInfo intervalToPing * @property {number|null} [intervalToPing] BattleColliderInfo intervalToPing
* @property {number|null} [willKickIfInactiveFor] BattleColliderInfo willKickIfInactiveFor * @property {number|null} [willKickIfInactiveFor] BattleColliderInfo willKickIfInactiveFor
* @property {number|null} [boundRoomId] BattleColliderInfo boundRoomId * @property {number|null} [boundRoomId] BattleColliderInfo boundRoomId
* @property {number|null} [battleDurationFrames] BattleColliderInfo battleDurationFrames
* @property {number|Long|null} [battleDurationNanos] BattleColliderInfo battleDurationNanos * @property {number|Long|null} [battleDurationNanos] BattleColliderInfo battleDurationNanos
* @property {number|null} [serverFps] BattleColliderInfo serverFps * @property {number|null} [serverFps] BattleColliderInfo serverFps
* @property {number|null} [inputDelayFrames] BattleColliderInfo inputDelayFrames * @property {number|null} [inputDelayFrames] BattleColliderInfo inputDelayFrames
@ -4266,6 +4267,14 @@ $root.protos = (function() {
*/ */
BattleColliderInfo.prototype.boundRoomId = 0; BattleColliderInfo.prototype.boundRoomId = 0;
/**
* BattleColliderInfo battleDurationFrames.
* @member {number} battleDurationFrames
* @memberof protos.BattleColliderInfo
* @instance
*/
BattleColliderInfo.prototype.battleDurationFrames = 0;
/** /**
* BattleColliderInfo battleDurationNanos. * BattleColliderInfo battleDurationNanos.
* @member {number|Long} battleDurationNanos * @member {number|Long} battleDurationNanos
@ -4436,37 +4445,39 @@ $root.protos = (function() {
writer.uint32(/* id 9, wireType 0 =*/72).int32(message.willKickIfInactiveFor); writer.uint32(/* id 9, wireType 0 =*/72).int32(message.willKickIfInactiveFor);
if (message.boundRoomId != null && Object.hasOwnProperty.call(message, "boundRoomId")) if (message.boundRoomId != null && Object.hasOwnProperty.call(message, "boundRoomId"))
writer.uint32(/* id 10, wireType 0 =*/80).int32(message.boundRoomId); writer.uint32(/* id 10, wireType 0 =*/80).int32(message.boundRoomId);
if (message.battleDurationFrames != null && Object.hasOwnProperty.call(message, "battleDurationFrames"))
writer.uint32(/* id 12, wireType 0 =*/96).int32(message.battleDurationFrames);
if (message.battleDurationNanos != null && Object.hasOwnProperty.call(message, "battleDurationNanos")) if (message.battleDurationNanos != null && Object.hasOwnProperty.call(message, "battleDurationNanos"))
writer.uint32(/* id 11, wireType 0 =*/88).int64(message.battleDurationNanos); writer.uint32(/* id 13, wireType 0 =*/104).int64(message.battleDurationNanos);
if (message.serverFps != null && Object.hasOwnProperty.call(message, "serverFps")) if (message.serverFps != null && Object.hasOwnProperty.call(message, "serverFps"))
writer.uint32(/* id 12, wireType 0 =*/96).int32(message.serverFps); writer.uint32(/* id 14, wireType 0 =*/112).int32(message.serverFps);
if (message.inputDelayFrames != null && Object.hasOwnProperty.call(message, "inputDelayFrames")) if (message.inputDelayFrames != null && Object.hasOwnProperty.call(message, "inputDelayFrames"))
writer.uint32(/* id 13, wireType 0 =*/104).int32(message.inputDelayFrames); writer.uint32(/* id 15, wireType 0 =*/120).int32(message.inputDelayFrames);
if (message.inputScaleFrames != null && Object.hasOwnProperty.call(message, "inputScaleFrames")) if (message.inputScaleFrames != null && Object.hasOwnProperty.call(message, "inputScaleFrames"))
writer.uint32(/* id 14, wireType 0 =*/112).uint32(message.inputScaleFrames); writer.uint32(/* id 16, wireType 0 =*/128).uint32(message.inputScaleFrames);
if (message.nstDelayFrames != null && Object.hasOwnProperty.call(message, "nstDelayFrames")) if (message.nstDelayFrames != null && Object.hasOwnProperty.call(message, "nstDelayFrames"))
writer.uint32(/* id 15, wireType 0 =*/120).int32(message.nstDelayFrames); writer.uint32(/* id 17, wireType 0 =*/136).int32(message.nstDelayFrames);
if (message.inputFrameUpsyncDelayTolerance != null && Object.hasOwnProperty.call(message, "inputFrameUpsyncDelayTolerance")) if (message.inputFrameUpsyncDelayTolerance != null && Object.hasOwnProperty.call(message, "inputFrameUpsyncDelayTolerance"))
writer.uint32(/* id 16, wireType 0 =*/128).int32(message.inputFrameUpsyncDelayTolerance); writer.uint32(/* id 18, wireType 0 =*/144).int32(message.inputFrameUpsyncDelayTolerance);
if (message.maxChasingRenderFramesPerUpdate != null && Object.hasOwnProperty.call(message, "maxChasingRenderFramesPerUpdate")) if (message.maxChasingRenderFramesPerUpdate != null && Object.hasOwnProperty.call(message, "maxChasingRenderFramesPerUpdate"))
writer.uint32(/* id 17, wireType 0 =*/136).int32(message.maxChasingRenderFramesPerUpdate); writer.uint32(/* id 19, wireType 0 =*/152).int32(message.maxChasingRenderFramesPerUpdate);
if (message.playerBattleState != null && Object.hasOwnProperty.call(message, "playerBattleState")) if (message.playerBattleState != null && Object.hasOwnProperty.call(message, "playerBattleState"))
writer.uint32(/* id 18, wireType 0 =*/144).int32(message.playerBattleState); writer.uint32(/* id 20, wireType 0 =*/160).int32(message.playerBattleState);
if (message.rollbackEstimatedDtMillis != null && Object.hasOwnProperty.call(message, "rollbackEstimatedDtMillis")) if (message.rollbackEstimatedDtMillis != null && Object.hasOwnProperty.call(message, "rollbackEstimatedDtMillis"))
writer.uint32(/* id 19, wireType 1 =*/153).double(message.rollbackEstimatedDtMillis); writer.uint32(/* id 21, wireType 1 =*/169).double(message.rollbackEstimatedDtMillis);
if (message.rollbackEstimatedDtNanos != null && Object.hasOwnProperty.call(message, "rollbackEstimatedDtNanos")) if (message.rollbackEstimatedDtNanos != null && Object.hasOwnProperty.call(message, "rollbackEstimatedDtNanos"))
writer.uint32(/* id 20, wireType 0 =*/160).int64(message.rollbackEstimatedDtNanos); writer.uint32(/* id 22, wireType 0 =*/176).int64(message.rollbackEstimatedDtNanos);
if (message.worldToVirtualGridRatio != null && Object.hasOwnProperty.call(message, "worldToVirtualGridRatio")) if (message.worldToVirtualGridRatio != null && Object.hasOwnProperty.call(message, "worldToVirtualGridRatio"))
writer.uint32(/* id 21, wireType 1 =*/169).double(message.worldToVirtualGridRatio); writer.uint32(/* id 23, wireType 1 =*/185).double(message.worldToVirtualGridRatio);
if (message.virtualGridToWorldRatio != null && Object.hasOwnProperty.call(message, "virtualGridToWorldRatio")) if (message.virtualGridToWorldRatio != null && Object.hasOwnProperty.call(message, "virtualGridToWorldRatio"))
writer.uint32(/* id 22, wireType 1 =*/177).double(message.virtualGridToWorldRatio); writer.uint32(/* id 24, wireType 1 =*/193).double(message.virtualGridToWorldRatio);
if (message.spAtkLookupFrames != null && Object.hasOwnProperty.call(message, "spAtkLookupFrames")) if (message.spAtkLookupFrames != null && Object.hasOwnProperty.call(message, "spAtkLookupFrames"))
writer.uint32(/* id 23, wireType 0 =*/184).int32(message.spAtkLookupFrames); writer.uint32(/* id 25, wireType 0 =*/200).int32(message.spAtkLookupFrames);
if (message.renderCacheSize != null && Object.hasOwnProperty.call(message, "renderCacheSize")) if (message.renderCacheSize != null && Object.hasOwnProperty.call(message, "renderCacheSize"))
writer.uint32(/* id 24, wireType 0 =*/192).int32(message.renderCacheSize); writer.uint32(/* id 26, wireType 0 =*/208).int32(message.renderCacheSize);
if (message.meleeSkillConfig != null && Object.hasOwnProperty.call(message, "meleeSkillConfig")) if (message.meleeSkillConfig != null && Object.hasOwnProperty.call(message, "meleeSkillConfig"))
for (var keys = Object.keys(message.meleeSkillConfig), i = 0; i < keys.length; ++i) { for (var keys = Object.keys(message.meleeSkillConfig), i = 0; i < keys.length; ++i) {
writer.uint32(/* id 25, wireType 2 =*/202).fork().uint32(/* id 1, wireType 0 =*/8).int32(keys[i]); writer.uint32(/* id 27, wireType 2 =*/218).fork().uint32(/* id 1, wireType 0 =*/8).int32(keys[i]);
$root.protos.MeleeBullet.encode(message.meleeSkillConfig[keys[i]], writer.uint32(/* id 2, wireType 2 =*/18).fork()).ldelim().ldelim(); $root.protos.MeleeBullet.encode(message.meleeSkillConfig[keys[i]], writer.uint32(/* id 2, wireType 2 =*/18).fork()).ldelim().ldelim();
} }
return writer; return writer;
@ -4581,63 +4592,67 @@ $root.protos = (function() {
message.boundRoomId = reader.int32(); message.boundRoomId = reader.int32();
break; break;
} }
case 11: {
message.battleDurationNanos = reader.int64();
break;
}
case 12: { case 12: {
message.serverFps = reader.int32(); message.battleDurationFrames = reader.int32();
break; break;
} }
case 13: { case 13: {
message.inputDelayFrames = reader.int32(); message.battleDurationNanos = reader.int64();
break; break;
} }
case 14: { case 14: {
message.inputScaleFrames = reader.uint32(); message.serverFps = reader.int32();
break; break;
} }
case 15: { case 15: {
message.nstDelayFrames = reader.int32(); message.inputDelayFrames = reader.int32();
break; break;
} }
case 16: { case 16: {
message.inputFrameUpsyncDelayTolerance = reader.int32(); message.inputScaleFrames = reader.uint32();
break; break;
} }
case 17: { case 17: {
message.maxChasingRenderFramesPerUpdate = reader.int32(); message.nstDelayFrames = reader.int32();
break; break;
} }
case 18: { case 18: {
message.playerBattleState = reader.int32(); message.inputFrameUpsyncDelayTolerance = reader.int32();
break; break;
} }
case 19: { case 19: {
message.rollbackEstimatedDtMillis = reader.double(); message.maxChasingRenderFramesPerUpdate = reader.int32();
break; break;
} }
case 20: { case 20: {
message.rollbackEstimatedDtNanos = reader.int64(); message.playerBattleState = reader.int32();
break; break;
} }
case 21: { case 21: {
message.worldToVirtualGridRatio = reader.double(); message.rollbackEstimatedDtMillis = reader.double();
break; break;
} }
case 22: { case 22: {
message.virtualGridToWorldRatio = reader.double(); message.rollbackEstimatedDtNanos = reader.int64();
break; break;
} }
case 23: { case 23: {
message.spAtkLookupFrames = reader.int32(); message.worldToVirtualGridRatio = reader.double();
break; break;
} }
case 24: { case 24: {
message.renderCacheSize = reader.int32(); message.virtualGridToWorldRatio = reader.double();
break; break;
} }
case 25: { case 25: {
message.spAtkLookupFrames = reader.int32();
break;
}
case 26: {
message.renderCacheSize = reader.int32();
break;
}
case 27: {
if (message.meleeSkillConfig === $util.emptyObject) if (message.meleeSkillConfig === $util.emptyObject)
message.meleeSkillConfig = {}; message.meleeSkillConfig = {};
var end2 = reader.uint32() + reader.pos; var end2 = reader.uint32() + reader.pos;
@ -4739,6 +4754,9 @@ $root.protos = (function() {
if (message.boundRoomId != null && message.hasOwnProperty("boundRoomId")) if (message.boundRoomId != null && message.hasOwnProperty("boundRoomId"))
if (!$util.isInteger(message.boundRoomId)) if (!$util.isInteger(message.boundRoomId))
return "boundRoomId: integer expected"; return "boundRoomId: integer expected";
if (message.battleDurationFrames != null && message.hasOwnProperty("battleDurationFrames"))
if (!$util.isInteger(message.battleDurationFrames))
return "battleDurationFrames: integer expected";
if (message.battleDurationNanos != null && message.hasOwnProperty("battleDurationNanos")) if (message.battleDurationNanos != null && message.hasOwnProperty("battleDurationNanos"))
if (!$util.isInteger(message.battleDurationNanos) && !(message.battleDurationNanos && $util.isInteger(message.battleDurationNanos.low) && $util.isInteger(message.battleDurationNanos.high))) if (!$util.isInteger(message.battleDurationNanos) && !(message.battleDurationNanos && $util.isInteger(message.battleDurationNanos.low) && $util.isInteger(message.battleDurationNanos.high)))
return "battleDurationNanos: integer|Long expected"; return "battleDurationNanos: integer|Long expected";
@ -4846,6 +4864,8 @@ $root.protos = (function() {
message.willKickIfInactiveFor = object.willKickIfInactiveFor | 0; message.willKickIfInactiveFor = object.willKickIfInactiveFor | 0;
if (object.boundRoomId != null) if (object.boundRoomId != null)
message.boundRoomId = object.boundRoomId | 0; message.boundRoomId = object.boundRoomId | 0;
if (object.battleDurationFrames != null)
message.battleDurationFrames = object.battleDurationFrames | 0;
if (object.battleDurationNanos != null) if (object.battleDurationNanos != null)
if ($util.Long) if ($util.Long)
(message.battleDurationNanos = $util.Long.fromValue(object.battleDurationNanos)).unsigned = false; (message.battleDurationNanos = $util.Long.fromValue(object.battleDurationNanos)).unsigned = false;
@ -4928,6 +4948,7 @@ $root.protos = (function() {
object.intervalToPing = 0; object.intervalToPing = 0;
object.willKickIfInactiveFor = 0; object.willKickIfInactiveFor = 0;
object.boundRoomId = 0; object.boundRoomId = 0;
object.battleDurationFrames = 0;
if ($util.Long) { if ($util.Long) {
var long = new $util.Long(0, 0, false); var long = new $util.Long(0, 0, false);
object.battleDurationNanos = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long; object.battleDurationNanos = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
@ -4978,6 +4999,8 @@ $root.protos = (function() {
object.willKickIfInactiveFor = message.willKickIfInactiveFor; object.willKickIfInactiveFor = message.willKickIfInactiveFor;
if (message.boundRoomId != null && message.hasOwnProperty("boundRoomId")) if (message.boundRoomId != null && message.hasOwnProperty("boundRoomId"))
object.boundRoomId = message.boundRoomId; object.boundRoomId = message.boundRoomId;
if (message.battleDurationFrames != null && message.hasOwnProperty("battleDurationFrames"))
object.battleDurationFrames = message.battleDurationFrames;
if (message.battleDurationNanos != null && message.hasOwnProperty("battleDurationNanos")) if (message.battleDurationNanos != null && message.hasOwnProperty("battleDurationNanos"))
if (typeof message.battleDurationNanos === "number") if (typeof message.battleDurationNanos === "number")
object.battleDurationNanos = options.longs === String ? String(message.battleDurationNanos) : message.battleDurationNanos; object.battleDurationNanos = options.longs === String ? String(message.battleDurationNanos) : message.battleDurationNanos;