Compare commits

...

28 Commits
v0.8 ... v0.9

Author SHA1 Message Date
Wing
c5b26d716e Merge pull request #15 from genxium/jumping_impl
Added jumping sync.
2022-12-15 15:41:57 +08:00
genxium
1e0959c4cf Updated README. 2022-12-15 15:40:08 +08:00
genxium
3e54670a1b Updated ConcerningEdgeCases.md 2022-12-15 15:03:41 +08:00
genxium
b41b86bbd3 Fixes for bullet and anim offset. 2022-12-15 12:43:34 +08:00
genxium
db2bc0e3cd Updated barrier boundaries and player collider paddings to feature almost-all-integer coordinates. 2022-12-15 11:22:17 +08:00
genxium
eedcf5c4dc Temp broken commit. 2022-12-14 23:17:06 +08:00
genxium
c171ebc211 Draft version for jumping with backend sync. 2022-12-13 23:56:56 +08:00
genxium
5a463239bb Temp broken commit, but it's working for OfflineMap. 2022-12-13 16:42:31 +08:00
genxium
5c06cfdbac More preparations on backend to sync jumping. 2022-12-12 19:11:59 +08:00
genxium
7985a242fd Updated OfflineMap position loading. 2022-12-12 16:42:11 +08:00
genxium
bef1df48aa Prepared backend for jumping sync. 2022-12-11 20:09:06 +08:00
genxium
8d989d543a Improved offline map for code abstraction and testing. 2022-12-11 17:26:55 +08:00
genxium
849ce34fe5 Added debug drawing for OfflineMap. 2022-12-11 12:20:42 +08:00
genxium
195a400dc2 Minor fix. 2022-12-10 18:12:20 +08:00
genxium
66dfcaa0f5 Fixes for platform snapping. 2022-12-10 12:47:02 +08:00
genxium
9917a62526 Drafted basic jumping. 2022-12-10 00:07:03 +08:00
genxium
62e50f8b6c Drafted use of gravity. 2022-12-09 17:22:04 +08:00
genxium
dc66be1599 Improved use of backend ConvertToLastUsedRenderFrameId. 2022-12-06 20:56:09 +08:00
genxium
858eba5243 Updated comments. 2022-12-06 13:53:27 +08:00
Wing
d113cffc7d Merge pull request #13 from genxium/downsync-order-preservation
Fixes for downsync order preservation.
2022-12-06 11:54:49 +08:00
genxium
6af9a14be5 Fixes for downsync order preservation. 2022-12-06 11:49:00 +08:00
genxium
e3fe773634 Fixed (refRenderFrameId, snapshotStFrameId) pairing in "markConfirmationIfApplicable". 2022-12-05 21:17:18 +08:00
genxium
17cac19c62 Fix on backend "createInputsBufferSnapshot". 2022-12-05 17:27:44 +08:00
Wing
26bdd41285 Merge pull request #11 from genxium/backend_locking_improvement
Improved backend implementation.
2022-12-05 15:27:30 +08:00
genxium
6bf70463fa Improved backend implementation. 2022-12-05 15:23:56 +08:00
genxium
e3d844abad Improving backend use of room.InputsBufferLock. 2022-12-04 23:37:01 +08:00
genxium
0373665382 Minor updates on ringbuffer and formatting. 2022-12-02 10:20:58 +08:00
genxium
3b0db64792 Updated README. 2022-12-01 15:46:36 +08:00
42 changed files with 4150 additions and 14704 deletions

View File

@@ -1,3 +1,7 @@
# What to be concerned for internet syncing
1. Server received too late (solution: force confirmation)
2. Client received too late (solution: prediction and frame chasing, big impact on user experience because the graphics will be inconsistent if mismatches occur too often)
# Potential avalanche from local lag
Under the current "input delay" algorithm, the lag of a single player would cause all the other players to receive outdated commands, e.g. when at a certain moment
- player#1: renderFrameId = 100, significantly lagged due to local CPU overheated
@@ -7,9 +11,9 @@ Under the current "input delay" algorithm, the lag of a single player would caus
players #2, #3 #4 would receive "outdated(in their subjective feelings) but all-confirmed commands" from then on, thus forced to rollback and chase many frames - the lag due to "large range of frame-chasing" would then further deteriorate the situation - like an avalanche.
In a "no-server & p2p" setup, I couldn't think of a proper way to cope with such edge case. Solely on the frontend we could only mitigate the impact to players #2, #3, #4, e.g. a potential lag due to "large range of frame-chasing" is proactively avoided in `<proj-root>/frontend/assets/scripts/Map.js, function update(dt)`.
In a "no-server & p2p" setup, I couldn't think of a proper way to cope with such edge case. Solely on the frontend we could only mitigate the impact to players #2, #3, #4, e.g. a potential lag due to "large range of frame-chasing" is proactively avoided in `<proj-root>/frontend/assets/scripts/Map.js, function update(dt)`.
However in a "server as authority" setup, the server could force confirming an inputFrame without player#1's upsync, and notify player#1 to apply a "roomDownsyncFrame" as well as drop all its outdated local inputFrames.
To be fair, **a "p2p" setup can reduce round-trip to single-trip**, but w/o a point of authority in such case player#1 needs a way to recognize the slowness (e.g. check the received peer inputs) and ticks faster for a while to catch up; in contrast in a "server as authority" setup, the server could force confirming an inputFrame without player#1's upsync, and notify player#1 to apply a "roomDownsyncFrame" as well as drop all its outdated local inputFrames.
# Start up frames
renderFrameId | generatedInputFrameId | toApplyInputFrameId

View File

@@ -2,11 +2,11 @@
This project is a demo for a websocket-based rollback netcode inspired by [GGPO](https://github.com/pond3r/ggpo/blob/master/doc/README.md).
_(the following gif is sped up to ~1.5x for file size reduction, kindly note that around ~11s countdown, the attack animation is resumed from a partial progress)_
_(the following gif is sped up to ~1.5x for file size reduction, kindly note that animations are resumed from a partial progress)_
![gif_demo](./charts/melee_attack_fractional_anim_resume_spedup.gif)
![gif_demo](./charts/jump_sync_spedup.gif)
Please also checkout [this demo video](https://pan.baidu.com/s/1U1wb7KWyHorZElNWcS5HHA?pwd=30wh) to see how this demo carries out a full 60fps synchronization with the help of _batched input upsync/downsync_ for satisfying network I/O performance.
Please also checkout [this demo video](https://pan.baidu.com/s/1Lmot9cb0pYylfUvC8G4fDg?pwd=ia97) to see how this demo carries out a full 60fps synchronization with the help of _batched input upsync/downsync_ for satisfying network I/O performance.
The video mainly shows the following features.
- The backend receives inputs from frontend peers and broadcasts back for synchronization.

View File

@@ -17,12 +17,16 @@ func toPbPlayers(modelInstances map[int32]*Player, withMetaInfo bool) map[int32]
VirtualGridY: last.VirtualGridY,
DirX: last.DirX,
DirY: last.DirY,
ColliderRadius: last.ColliderRadius,
VelX: last.VelX,
VelY: last.VelY,
Speed: last.Speed,
BattleState: last.BattleState,
CharacterState: last.CharacterState,
InAir: last.InAir,
JoinIndex: last.JoinIndex,
ColliderRadius: last.ColliderRadius,
Score: last.Score,
Removed: last.Removed,
JoinIndex: last.JoinIndex,
}
if withMetaInfo {
toRet[k].Name = last.Name

View File

@@ -13,6 +13,7 @@ import (
type PlayerBattleState struct {
ADDED_PENDING_BATTLE_COLLIDER_ACK int32
READDED_PENDING_BATTLE_COLLIDER_ACK int32
READDED_BATTLE_COLLIDER_ACKED int32
ACTIVE int32
DISCONNECTED int32
LOST int32
@@ -26,11 +27,12 @@ func InitPlayerBattleStateIns() {
PlayerBattleStateIns = PlayerBattleState{
ADDED_PENDING_BATTLE_COLLIDER_ACK: 0,
READDED_PENDING_BATTLE_COLLIDER_ACK: 1,
ACTIVE: 2,
DISCONNECTED: 3,
LOST: 4,
EXPELLED_DURING_GAME: 5,
EXPELLED_IN_DISMISSAL: 6,
READDED_BATTLE_COLLIDER_ACKED: 2,
ACTIVE: 3,
DISCONNECTED: 4,
LOST: 5,
EXPELLED_DURING_GAME: 6,
EXPELLED_IN_DISMISSAL: 7,
}
}

View File

@@ -1,10 +1,5 @@
package models
import (
. "battle_srv/protos"
"sync"
)
type RingBuffer struct {
Ed int32 // write index, open index
St int32 // read index, closed index
@@ -26,7 +21,7 @@ func NewRingBuffer(n int32) *RingBuffer {
}
func (rb *RingBuffer) Put(pItem interface{}) {
for rb.Cnt >= rb.N-1 {
for 0 < rb.Cnt && rb.Cnt >= rb.N {
// Make room for the new element
rb.Pop()
}
@@ -78,47 +73,8 @@ func (rb *RingBuffer) GetByOffset(offsetFromSt int32) interface{} {
}
func (rb *RingBuffer) GetByFrameId(frameId int32) interface{} {
if frameId >= rb.EdFrameId {
if frameId >= rb.EdFrameId || frameId < rb.StFrameId {
return nil
}
return rb.GetByOffset(frameId - rb.StFrameId)
}
func (rb *RingBuffer) cloneInputFrameDownsyncsByFrameIdRange(stFrameId, edFrameId int32, mux *sync.Mutex) (int32, []*InputFrameDownsync) {
dst := make([]*InputFrameDownsync, 0, rb.Cnt)
if nil != mux {
mux.Lock()
defer func() {
mux.Unlock()
}()
}
prevFrameFound := true
j := stFrameId
for j < edFrameId {
tmp := rb.GetByFrameId(j)
if nil == tmp {
if false == prevFrameFound {
// The "id"s are always consecutive
break
} else {
prevFrameFound = false
continue
}
}
foo := tmp.(*InputFrameDownsync)
bar := &InputFrameDownsync{
InputFrameId: foo.InputFrameId,
InputList: make([]uint64, len(foo.InputList)),
ConfirmedList: foo.ConfirmedList,
}
for i, input := range foo.InputList {
bar.InputList[i] = input
}
dst = append(dst, bar)
j++
}
return j, dst
}

File diff suppressed because it is too large Load Diff

View File

@@ -30,21 +30,24 @@ type PlayerDownsync struct {
VirtualGridX int32 `protobuf:"varint,2,opt,name=virtualGridX,proto3" json:"virtualGridX,omitempty"`
VirtualGridY int32 `protobuf:"varint,3,opt,name=virtualGridY,proto3" json:"virtualGridY,omitempty"`
DirX int32 `protobuf:"varint,4,opt,name=dirX,proto3" json:"dirX,omitempty"`
DirY int32 `protobuf:"varint,5,opt,name=dirY,proto3" json:"dirY,omitempty"`
Speed int32 `protobuf:"varint,6,opt,name=speed,proto3" json:"speed,omitempty"` // in terms of virtual grid units
BattleState int32 `protobuf:"varint,7,opt,name=battleState,proto3" json:"battleState,omitempty"`
JoinIndex int32 `protobuf:"varint,8,opt,name=joinIndex,proto3" json:"joinIndex,omitempty"`
ColliderRadius float64 `protobuf:"fixed64,9,opt,name=colliderRadius,proto3" json:"colliderRadius,omitempty"`
Removed bool `protobuf:"varint,10,opt,name=removed,proto3" json:"removed,omitempty"`
Score int32 `protobuf:"varint,11,opt,name=score,proto3" json:"score,omitempty"`
LastMoveGmtMillis int32 `protobuf:"varint,12,opt,name=lastMoveGmtMillis,proto3" json:"lastMoveGmtMillis,omitempty"`
FramesToRecover int32 `protobuf:"varint,13,opt,name=framesToRecover,proto3" json:"framesToRecover,omitempty"`
Hp int32 `protobuf:"varint,14,opt,name=hp,proto3" json:"hp,omitempty"`
MaxHp int32 `protobuf:"varint,15,opt,name=maxHp,proto3" json:"maxHp,omitempty"`
CharacterState int32 `protobuf:"varint,16,opt,name=characterState,proto3" json:"characterState,omitempty"`
Name string `protobuf:"bytes,17,opt,name=name,proto3" json:"name,omitempty"`
DisplayName string `protobuf:"bytes,18,opt,name=displayName,proto3" json:"displayName,omitempty"`
Avatar string `protobuf:"bytes,19,opt,name=avatar,proto3" json:"avatar,omitempty"`
DirY int32 `protobuf:"varint,5,opt,name=dirY,proto3" json:"dirY,omitempty"` // "dirX" and "dirY" determines character facing
VelX int32 `protobuf:"varint,6,opt,name=velX,proto3" json:"velX,omitempty"`
VelY int32 `protobuf:"varint,7,opt,name=velY,proto3" json:"velY,omitempty"` // "velX" and "velY" is used to record the accumulated effect by accelerations (including gravity)
Speed int32 `protobuf:"varint,8,opt,name=speed,proto3" json:"speed,omitempty"` // this is the instantaneous scalar attribute of a character, different from but will be accounted in "velX" and "velY"
BattleState int32 `protobuf:"varint,9,opt,name=battleState,proto3" json:"battleState,omitempty"`
JoinIndex int32 `protobuf:"varint,10,opt,name=joinIndex,proto3" json:"joinIndex,omitempty"`
ColliderRadius float64 `protobuf:"fixed64,11,opt,name=colliderRadius,proto3" json:"colliderRadius,omitempty"`
Removed bool `protobuf:"varint,12,opt,name=removed,proto3" json:"removed,omitempty"`
Score int32 `protobuf:"varint,13,opt,name=score,proto3" json:"score,omitempty"`
LastMoveGmtMillis int32 `protobuf:"varint,14,opt,name=lastMoveGmtMillis,proto3" json:"lastMoveGmtMillis,omitempty"`
FramesToRecover int32 `protobuf:"varint,15,opt,name=framesToRecover,proto3" json:"framesToRecover,omitempty"`
Hp int32 `protobuf:"varint,16,opt,name=hp,proto3" json:"hp,omitempty"`
MaxHp int32 `protobuf:"varint,17,opt,name=maxHp,proto3" json:"maxHp,omitempty"`
CharacterState int32 `protobuf:"varint,18,opt,name=characterState,proto3" json:"characterState,omitempty"`
InAir bool `protobuf:"varint,19,opt,name=inAir,proto3" json:"inAir,omitempty"` // by design a standalone field only inferred by the collision result of "applyInputFrameDownsyncDynamicsOnSingleRenderFrame" instead of "characterState", because we need check the transition for "characterState" from this field, i.e. "inAir (prev -> curr)"
Name string `protobuf:"bytes,20,opt,name=name,proto3" json:"name,omitempty"`
DisplayName string `protobuf:"bytes,21,opt,name=displayName,proto3" json:"displayName,omitempty"`
Avatar string `protobuf:"bytes,22,opt,name=avatar,proto3" json:"avatar,omitempty"`
}
func (x *PlayerDownsync) Reset() {
@@ -114,6 +117,20 @@ func (x *PlayerDownsync) GetDirY() int32 {
return 0
}
func (x *PlayerDownsync) GetVelX() int32 {
if x != nil {
return x.VelX
}
return 0
}
func (x *PlayerDownsync) GetVelY() int32 {
if x != nil {
return x.VelY
}
return 0
}
func (x *PlayerDownsync) GetSpeed() int32 {
if x != nil {
return x.Speed
@@ -191,6 +208,13 @@ func (x *PlayerDownsync) GetCharacterState() int32 {
return 0
}
func (x *PlayerDownsync) GetInAir() bool {
if x != nil {
return x.InAir
}
return false
}
func (x *PlayerDownsync) GetName() string {
if x != nil {
return x.Name
@@ -220,6 +244,7 @@ type InputFrameDecoded struct {
Dx int32 `protobuf:"varint,1,opt,name=dx,proto3" json:"dx,omitempty"`
Dy int32 `protobuf:"varint,2,opt,name=dy,proto3" json:"dy,omitempty"`
BtnALevel int32 `protobuf:"varint,3,opt,name=btnALevel,proto3" json:"btnALevel,omitempty"`
BtnBLevel int32 `protobuf:"varint,4,opt,name=btnBLevel,proto3" json:"btnBLevel,omitempty"`
}
func (x *InputFrameDecoded) Reset() {
@@ -275,6 +300,13 @@ func (x *InputFrameDecoded) GetBtnALevel() int32 {
return 0
}
func (x *InputFrameDecoded) GetBtnBLevel() int32 {
if x != nil {
return x.BtnBLevel
}
return 0
}
type InputFrameUpsync struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
@@ -630,6 +662,69 @@ func (x *WsResp) GetBciFrame() *BattleColliderInfo {
return nil
}
type InputsBufferSnapshot struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
RefRenderFrameId int32 `protobuf:"varint,1,opt,name=refRenderFrameId,proto3" json:"refRenderFrameId,omitempty"`
UnconfirmedMask uint64 `protobuf:"varint,2,opt,name=unconfirmedMask,proto3" json:"unconfirmedMask,omitempty"`
ToSendInputFrameDownsyncs []*InputFrameDownsync `protobuf:"bytes,3,rep,name=toSendInputFrameDownsyncs,proto3" json:"toSendInputFrameDownsyncs,omitempty"`
}
func (x *InputsBufferSnapshot) Reset() {
*x = InputsBufferSnapshot{}
if protoimpl.UnsafeEnabled {
mi := &file_room_downsync_frame_proto_msgTypes[7]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *InputsBufferSnapshot) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*InputsBufferSnapshot) ProtoMessage() {}
func (x *InputsBufferSnapshot) ProtoReflect() protoreflect.Message {
mi := &file_room_downsync_frame_proto_msgTypes[7]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use InputsBufferSnapshot.ProtoReflect.Descriptor instead.
func (*InputsBufferSnapshot) Descriptor() ([]byte, []int) {
return file_room_downsync_frame_proto_rawDescGZIP(), []int{7}
}
func (x *InputsBufferSnapshot) GetRefRenderFrameId() int32 {
if x != nil {
return x.RefRenderFrameId
}
return 0
}
func (x *InputsBufferSnapshot) GetUnconfirmedMask() uint64 {
if x != nil {
return x.UnconfirmedMask
}
return 0
}
func (x *InputsBufferSnapshot) GetToSendInputFrameDownsyncs() []*InputFrameDownsync {
if x != nil {
return x.ToSendInputFrameDownsyncs
}
return nil
}
type MeleeBullet struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
@@ -659,7 +754,7 @@ type MeleeBullet struct {
func (x *MeleeBullet) Reset() {
*x = MeleeBullet{}
if protoimpl.UnsafeEnabled {
mi := &file_room_downsync_frame_proto_msgTypes[7]
mi := &file_room_downsync_frame_proto_msgTypes[8]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -672,7 +767,7 @@ func (x *MeleeBullet) String() string {
func (*MeleeBullet) ProtoMessage() {}
func (x *MeleeBullet) ProtoReflect() protoreflect.Message {
mi := &file_room_downsync_frame_proto_msgTypes[7]
mi := &file_room_downsync_frame_proto_msgTypes[8]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -685,7 +780,7 @@ func (x *MeleeBullet) ProtoReflect() protoreflect.Message {
// Deprecated: Use MeleeBullet.ProtoReflect.Descriptor instead.
func (*MeleeBullet) Descriptor() ([]byte, []int) {
return file_room_downsync_frame_proto_rawDescGZIP(), []int{7}
return file_room_downsync_frame_proto_rawDescGZIP(), []int{8}
}
func (x *MeleeBullet) GetBattleLocalId() int32 {
@@ -838,12 +933,17 @@ type BattleColliderInfo struct {
SpAtkLookupFrames int32 `protobuf:"varint,25,opt,name=spAtkLookupFrames,proto3" json:"spAtkLookupFrames,omitempty"`
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
SnapIntoPlatformOverlap float64 `protobuf:"fixed64,28,opt,name=snapIntoPlatformOverlap,proto3" json:"snapIntoPlatformOverlap,omitempty"`
SnapIntoPlatformThreshold float64 `protobuf:"fixed64,29,opt,name=snapIntoPlatformThreshold,proto3" json:"snapIntoPlatformThreshold,omitempty"`
JumpingInitVelY int32 `protobuf:"varint,30,opt,name=jumpingInitVelY,proto3" json:"jumpingInitVelY,omitempty"`
GravityX int32 `protobuf:"varint,31,opt,name=gravityX,proto3" json:"gravityX,omitempty"`
GravityY int32 `protobuf:"varint,32,opt,name=gravityY,proto3" json:"gravityY,omitempty"`
}
func (x *BattleColliderInfo) Reset() {
*x = BattleColliderInfo{}
if protoimpl.UnsafeEnabled {
mi := &file_room_downsync_frame_proto_msgTypes[8]
mi := &file_room_downsync_frame_proto_msgTypes[9]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -856,7 +956,7 @@ func (x *BattleColliderInfo) String() string {
func (*BattleColliderInfo) ProtoMessage() {}
func (x *BattleColliderInfo) ProtoReflect() protoreflect.Message {
mi := &file_room_downsync_frame_proto_msgTypes[8]
mi := &file_room_downsync_frame_proto_msgTypes[9]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -869,7 +969,7 @@ func (x *BattleColliderInfo) ProtoReflect() protoreflect.Message {
// Deprecated: Use BattleColliderInfo.ProtoReflect.Descriptor instead.
func (*BattleColliderInfo) Descriptor() ([]byte, []int) {
return file_room_downsync_frame_proto_rawDescGZIP(), []int{8}
return file_room_downsync_frame_proto_rawDescGZIP(), []int{9}
}
func (x *BattleColliderInfo) GetStageName() string {
@@ -1054,6 +1154,41 @@ func (x *BattleColliderInfo) GetMeleeSkillConfig() map[int32]*MeleeBullet {
return nil
}
func (x *BattleColliderInfo) GetSnapIntoPlatformOverlap() float64 {
if x != nil {
return x.SnapIntoPlatformOverlap
}
return 0
}
func (x *BattleColliderInfo) GetSnapIntoPlatformThreshold() float64 {
if x != nil {
return x.SnapIntoPlatformThreshold
}
return 0
}
func (x *BattleColliderInfo) GetJumpingInitVelY() int32 {
if x != nil {
return x.JumpingInitVelY
}
return 0
}
func (x *BattleColliderInfo) GetGravityX() int32 {
if x != nil {
return x.GravityX
}
return 0
}
func (x *BattleColliderInfo) GetGravityY() int32 {
if x != nil {
return x.GravityY
}
return 0
}
type RoomDownsyncFrame struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
@@ -1069,7 +1204,7 @@ type RoomDownsyncFrame struct {
func (x *RoomDownsyncFrame) Reset() {
*x = RoomDownsyncFrame{}
if protoimpl.UnsafeEnabled {
mi := &file_room_downsync_frame_proto_msgTypes[9]
mi := &file_room_downsync_frame_proto_msgTypes[10]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -1082,7 +1217,7 @@ func (x *RoomDownsyncFrame) String() string {
func (*RoomDownsyncFrame) ProtoMessage() {}
func (x *RoomDownsyncFrame) ProtoReflect() protoreflect.Message {
mi := &file_room_downsync_frame_proto_msgTypes[9]
mi := &file_room_downsync_frame_proto_msgTypes[10]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -1095,7 +1230,7 @@ func (x *RoomDownsyncFrame) ProtoReflect() protoreflect.Message {
// Deprecated: Use RoomDownsyncFrame.ProtoReflect.Descriptor instead.
func (*RoomDownsyncFrame) Descriptor() ([]byte, []int) {
return file_room_downsync_frame_proto_rawDescGZIP(), []int{9}
return file_room_downsync_frame_proto_rawDescGZIP(), []int{10}
}
func (x *RoomDownsyncFrame) GetId() int32 {
@@ -1139,7 +1274,7 @@ var file_room_downsync_frame_proto_rawDesc = []byte{
0x0a, 0x19, 0x72, 0x6f, 0x6f, 0x6d, 0x5f, 0x64, 0x6f, 0x77, 0x6e, 0x73, 0x79, 0x6e, 0x63, 0x5f,
0x66, 0x72, 0x61, 0x6d, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x06, 0x70, 0x72, 0x6f,
0x74, 0x6f, 0x73, 0x1a, 0x0e, 0x67, 0x65, 0x6f, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x2e, 0x70, 0x72,
0x6f, 0x74, 0x6f, 0x22, 0xb2, 0x04, 0x0a, 0x0e, 0x50, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x44, 0x6f,
0x6f, 0x74, 0x6f, 0x22, 0xf0, 0x04, 0x0a, 0x0e, 0x50, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x44, 0x6f,
0x77, 0x6e, 0x73, 0x79, 0x6e, 0x63, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01,
0x28, 0x05, 0x52, 0x02, 0x69, 0x64, 0x12, 0x22, 0x0a, 0x0c, 0x76, 0x69, 0x72, 0x74, 0x75, 0x61,
0x6c, 0x47, 0x72, 0x69, 0x64, 0x58, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0c, 0x76, 0x69,
@@ -1148,267 +1283,299 @@ var file_room_downsync_frame_proto_rawDesc = []byte{
0x52, 0x0c, 0x76, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x47, 0x72, 0x69, 0x64, 0x59, 0x12, 0x12,
0x0a, 0x04, 0x64, 0x69, 0x72, 0x58, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x64, 0x69,
0x72, 0x58, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x69, 0x72, 0x59, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05,
0x52, 0x04, 0x64, 0x69, 0x72, 0x59, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x70, 0x65, 0x65, 0x64, 0x18,
0x06, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x73, 0x70, 0x65, 0x65, 0x64, 0x12, 0x20, 0x0a, 0x0b,
0x62, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28,
0x05, 0x52, 0x0b, 0x62, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x1c,
0x0a, 0x09, 0x6a, 0x6f, 0x69, 0x6e, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x08, 0x20, 0x01, 0x28,
0x05, 0x52, 0x09, 0x6a, 0x6f, 0x69, 0x6e, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x26, 0x0a, 0x0e,
0x63, 0x6f, 0x6c, 0x6c, 0x69, 0x64, 0x65, 0x72, 0x52, 0x61, 0x64, 0x69, 0x75, 0x73, 0x18, 0x09,
0x20, 0x01, 0x28, 0x01, 0x52, 0x0e, 0x63, 0x6f, 0x6c, 0x6c, 0x69, 0x64, 0x65, 0x72, 0x52, 0x61,
0x64, 0x69, 0x75, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x18,
0x0a, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x12, 0x14,
0x0a, 0x05, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x73,
0x63, 0x6f, 0x72, 0x65, 0x12, 0x2c, 0x0a, 0x11, 0x6c, 0x61, 0x73, 0x74, 0x4d, 0x6f, 0x76, 0x65,
0x47, 0x6d, 0x74, 0x4d, 0x69, 0x6c, 0x6c, 0x69, 0x73, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x05, 0x52,
0x11, 0x6c, 0x61, 0x73, 0x74, 0x4d, 0x6f, 0x76, 0x65, 0x47, 0x6d, 0x74, 0x4d, 0x69, 0x6c, 0x6c,
0x69, 0x73, 0x12, 0x28, 0x0a, 0x0f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x54, 0x6f, 0x52, 0x65,
0x63, 0x6f, 0x76, 0x65, 0x72, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0f, 0x66, 0x72, 0x61,
0x6d, 0x65, 0x73, 0x54, 0x6f, 0x52, 0x65, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x12, 0x0e, 0x0a, 0x02,
0x68, 0x70, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x05, 0x52, 0x02, 0x68, 0x70, 0x12, 0x14, 0x0a, 0x05,
0x6d, 0x61, 0x78, 0x48, 0x70, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x6d, 0x61, 0x78,
0x48, 0x70, 0x12, 0x26, 0x0a, 0x0e, 0x63, 0x68, 0x61, 0x72, 0x61, 0x63, 0x74, 0x65, 0x72, 0x53,
0x74, 0x61, 0x74, 0x65, 0x18, 0x10, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0e, 0x63, 0x68, 0x61, 0x72,
0x61, 0x63, 0x74, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61,
0x6d, 0x65, 0x18, 0x11, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x20,
0x0a, 0x0b, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x12, 0x20,
0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x4e, 0x61, 0x6d, 0x65,
0x12, 0x16, 0x0a, 0x06, 0x61, 0x76, 0x61, 0x74, 0x61, 0x72, 0x18, 0x13, 0x20, 0x01, 0x28, 0x09,
0x52, 0x06, 0x61, 0x76, 0x61, 0x74, 0x61, 0x72, 0x22, 0x51, 0x0a, 0x11, 0x49, 0x6e, 0x70, 0x75,
0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x44, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x12, 0x0e, 0x0a,
0x02, 0x64, 0x78, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x02, 0x64, 0x78, 0x12, 0x0e, 0x0a,
0x02, 0x64, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x02, 0x64, 0x79, 0x12, 0x1c, 0x0a,
0x09, 0x62, 0x74, 0x6e, 0x41, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05,
0x52, 0x09, 0x62, 0x74, 0x6e, 0x41, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x22, 0x50, 0x0a, 0x10, 0x49,
0x6e, 0x70, 0x75, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x55, 0x70, 0x73, 0x79, 0x6e, 0x63, 0x12,
0x52, 0x04, 0x64, 0x69, 0x72, 0x59, 0x12, 0x12, 0x0a, 0x04, 0x76, 0x65, 0x6c, 0x58, 0x18, 0x06,
0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x76, 0x65, 0x6c, 0x58, 0x12, 0x12, 0x0a, 0x04, 0x76, 0x65,
0x6c, 0x59, 0x18, 0x07, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x76, 0x65, 0x6c, 0x59, 0x12, 0x14,
0x0a, 0x05, 0x73, 0x70, 0x65, 0x65, 0x64, 0x18, 0x08, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x73,
0x70, 0x65, 0x65, 0x64, 0x12, 0x20, 0x0a, 0x0b, 0x62, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x53, 0x74,
0x61, 0x74, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0b, 0x62, 0x61, 0x74, 0x74, 0x6c,
0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x6a, 0x6f, 0x69, 0x6e, 0x49, 0x6e,
0x64, 0x65, 0x78, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x6a, 0x6f, 0x69, 0x6e, 0x49,
0x6e, 0x64, 0x65, 0x78, 0x12, 0x26, 0x0a, 0x0e, 0x63, 0x6f, 0x6c, 0x6c, 0x69, 0x64, 0x65, 0x72,
0x52, 0x61, 0x64, 0x69, 0x75, 0x73, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x01, 0x52, 0x0e, 0x63, 0x6f,
0x6c, 0x6c, 0x69, 0x64, 0x65, 0x72, 0x52, 0x61, 0x64, 0x69, 0x75, 0x73, 0x12, 0x18, 0x0a, 0x07,
0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x72,
0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x18,
0x0d, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x12, 0x2c, 0x0a, 0x11,
0x6c, 0x61, 0x73, 0x74, 0x4d, 0x6f, 0x76, 0x65, 0x47, 0x6d, 0x74, 0x4d, 0x69, 0x6c, 0x6c, 0x69,
0x73, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x05, 0x52, 0x11, 0x6c, 0x61, 0x73, 0x74, 0x4d, 0x6f, 0x76,
0x65, 0x47, 0x6d, 0x74, 0x4d, 0x69, 0x6c, 0x6c, 0x69, 0x73, 0x12, 0x28, 0x0a, 0x0f, 0x66, 0x72,
0x61, 0x6d, 0x65, 0x73, 0x54, 0x6f, 0x52, 0x65, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x18, 0x0f, 0x20,
0x01, 0x28, 0x05, 0x52, 0x0f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x54, 0x6f, 0x52, 0x65, 0x63,
0x6f, 0x76, 0x65, 0x72, 0x12, 0x0e, 0x0a, 0x02, 0x68, 0x70, 0x18, 0x10, 0x20, 0x01, 0x28, 0x05,
0x52, 0x02, 0x68, 0x70, 0x12, 0x14, 0x0a, 0x05, 0x6d, 0x61, 0x78, 0x48, 0x70, 0x18, 0x11, 0x20,
0x01, 0x28, 0x05, 0x52, 0x05, 0x6d, 0x61, 0x78, 0x48, 0x70, 0x12, 0x26, 0x0a, 0x0e, 0x63, 0x68,
0x61, 0x72, 0x61, 0x63, 0x74, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x18, 0x12, 0x20, 0x01,
0x28, 0x05, 0x52, 0x0e, 0x63, 0x68, 0x61, 0x72, 0x61, 0x63, 0x74, 0x65, 0x72, 0x53, 0x74, 0x61,
0x74, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x69, 0x6e, 0x41, 0x69, 0x72, 0x18, 0x13, 0x20, 0x01, 0x28,
0x08, 0x52, 0x05, 0x69, 0x6e, 0x41, 0x69, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65,
0x18, 0x14, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x20, 0x0a, 0x0b,
0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x15, 0x20, 0x01, 0x28,
0x09, 0x52, 0x0b, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x16,
0x0a, 0x06, 0x61, 0x76, 0x61, 0x74, 0x61, 0x72, 0x18, 0x16, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06,
0x61, 0x76, 0x61, 0x74, 0x61, 0x72, 0x22, 0x6f, 0x0a, 0x11, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x46,
0x72, 0x61, 0x6d, 0x65, 0x44, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x12, 0x0e, 0x0a, 0x02, 0x64,
0x78, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x02, 0x64, 0x78, 0x12, 0x0e, 0x0a, 0x02, 0x64,
0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x02, 0x64, 0x79, 0x12, 0x1c, 0x0a, 0x09, 0x62,
0x74, 0x6e, 0x41, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09,
0x62, 0x74, 0x6e, 0x41, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x1c, 0x0a, 0x09, 0x62, 0x74, 0x6e,
0x42, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x62, 0x74,
0x6e, 0x42, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x22, 0x50, 0x0a, 0x10, 0x49, 0x6e, 0x70, 0x75, 0x74,
0x46, 0x72, 0x61, 0x6d, 0x65, 0x55, 0x70, 0x73, 0x79, 0x6e, 0x63, 0x12, 0x22, 0x0a, 0x0c, 0x69,
0x6e, 0x70, 0x75, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28,
0x05, 0x52, 0x0c, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x49, 0x64, 0x12,
0x18, 0x0a, 0x07, 0x65, 0x6e, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04,
0x52, 0x07, 0x65, 0x6e, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x22, 0x7c, 0x0a, 0x12, 0x49, 0x6e, 0x70,
0x75, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x44, 0x6f, 0x77, 0x6e, 0x73, 0x79, 0x6e, 0x63, 0x12,
0x22, 0x0a, 0x0c, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x49, 0x64, 0x18,
0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0c, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x46, 0x72, 0x61, 0x6d,
0x65, 0x49, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x18, 0x02,
0x20, 0x01, 0x28, 0x04, 0x52, 0x07, 0x65, 0x6e, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x22, 0x7c, 0x0a,
0x12, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x44, 0x6f, 0x77, 0x6e, 0x73,
0x79, 0x6e, 0x63, 0x12, 0x22, 0x0a, 0x0c, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x46, 0x72, 0x61, 0x6d,
0x65, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0c, 0x69, 0x6e, 0x70, 0x75, 0x74,
0x46, 0x72, 0x61, 0x6d, 0x65, 0x49, 0x64, 0x12, 0x1c, 0x0a, 0x09, 0x69, 0x6e, 0x70, 0x75, 0x74,
0x4c, 0x69, 0x73, 0x74, 0x18, 0x02, 0x20, 0x03, 0x28, 0x04, 0x52, 0x09, 0x69, 0x6e, 0x70, 0x75,
0x74, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x24, 0x0a, 0x0d, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d,
0x65, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0d, 0x63, 0x6f,
0x6e, 0x66, 0x69, 0x72, 0x6d, 0x65, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x22, 0x3b, 0x0a, 0x0f, 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, 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, 0xb8, 0x02, 0x0a, 0x05, 0x57, 0x73, 0x52,
0x65, 0x71, 0x12, 0x14, 0x0a, 0x05, 0x6d, 0x73, 0x67, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28,
0x05, 0x52, 0x05, 0x6d, 0x73, 0x67, 0x49, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x6c, 0x61, 0x79,
0x65, 0x72, 0x49, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x70, 0x6c, 0x61, 0x79,
0x65, 0x72, 0x49, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x61, 0x63, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28,
0x05, 0x52, 0x03, 0x61, 0x63, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x6a, 0x6f, 0x69, 0x6e, 0x49, 0x6e,
0x64, 0x65, 0x78, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x6a, 0x6f, 0x69, 0x6e, 0x49,
0x6e, 0x64, 0x65, 0x78, 0x12, 0x24, 0x0a, 0x0d, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x46, 0x72,
0x61, 0x6d, 0x65, 0x49, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0d, 0x61, 0x63, 0x6b,
0x69, 0x6e, 0x67, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x49, 0x64, 0x12, 0x2e, 0x0a, 0x12, 0x61, 0x63,
0x6b, 0x69, 0x6e, 0x67, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x49, 0x64,
0x18, 0x06, 0x20, 0x01, 0x28, 0x05, 0x52, 0x12, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x49, 0x6e,
0x70, 0x75, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x49, 0x64, 0x12, 0x4e, 0x0a, 0x15, 0x69, 0x6e,
0x70, 0x75, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x55, 0x70, 0x73, 0x79, 0x6e, 0x63, 0x42, 0x61,
0x74, 0x63, 0x68, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x70, 0x72, 0x6f, 0x74,
0x6f, 0x73, 0x2e, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x55, 0x70, 0x73,
0x79, 0x6e, 0x63, 0x52, 0x15, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x55,
0x70, 0x73, 0x79, 0x6e, 0x63, 0x42, 0x61, 0x74, 0x63, 0x68, 0x12, 0x27, 0x0a, 0x02, 0x68, 0x62,
0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e,
0x48, 0x65, 0x61, 0x72, 0x74, 0x62, 0x65, 0x61, 0x74, 0x55, 0x70, 0x73, 0x79, 0x6e, 0x63, 0x52,
0x02, 0x68, 0x62, 0x22, 0x89, 0x02, 0x0a, 0x06, 0x57, 0x73, 0x52, 0x65, 0x73, 0x70, 0x12, 0x10,
0x0a, 0x03, 0x72, 0x65, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x03, 0x72, 0x65, 0x74,
0x12, 0x20, 0x0a, 0x0b, 0x65, 0x63, 0x68, 0x6f, 0x65, 0x64, 0x4d, 0x73, 0x67, 0x49, 0x64, 0x18,
0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0b, 0x65, 0x63, 0x68, 0x6f, 0x65, 0x64, 0x4d, 0x73, 0x67,
0x49, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x61, 0x63, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52,
0x03, 0x61, 0x63, 0x74, 0x12, 0x2b, 0x0a, 0x03, 0x72, 0x64, 0x66, 0x18, 0x04, 0x20, 0x01, 0x28,
0x0b, 0x32, 0x19, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x52, 0x6f, 0x6f, 0x6d, 0x44,
0x6f, 0x77, 0x6e, 0x73, 0x79, 0x6e, 0x63, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x52, 0x03, 0x72, 0x64,
0x66, 0x12, 0x54, 0x0a, 0x17, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x44,
0x6f, 0x77, 0x6e, 0x73, 0x79, 0x6e, 0x63, 0x42, 0x61, 0x74, 0x63, 0x68, 0x18, 0x05, 0x20, 0x03,
0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x49, 0x6e, 0x70, 0x75,
0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x44, 0x6f, 0x77, 0x6e, 0x73, 0x79, 0x6e, 0x63, 0x52, 0x17,
0x69, 0x6e, 0x70, 0x75, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x44, 0x6f, 0x77, 0x6e, 0x73, 0x79,
0x6e, 0x63, 0x42, 0x61, 0x74, 0x63, 0x68, 0x12, 0x36, 0x0a, 0x08, 0x62, 0x63, 0x69, 0x46, 0x72,
0x61, 0x6d, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x74,
0x6f, 0x73, 0x2e, 0x42, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x43, 0x6f, 0x6c, 0x6c, 0x69, 0x64, 0x65,
0x72, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x08, 0x62, 0x63, 0x69, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x22,
0xe5, 0x05, 0x0a, 0x0b, 0x4d, 0x65, 0x6c, 0x65, 0x65, 0x42, 0x75, 0x6c, 0x6c, 0x65, 0x74, 0x12,
0x24, 0x0a, 0x0d, 0x62, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x49, 0x64,
0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0d, 0x62, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x4c, 0x6f,
0x63, 0x61, 0x6c, 0x49, 0x64, 0x12, 0x24, 0x0a, 0x0d, 0x73, 0x74, 0x61, 0x72, 0x74, 0x75, 0x70,
0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0d, 0x73, 0x74,
0x61, 0x72, 0x74, 0x75, 0x70, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x12, 0x22, 0x0a, 0x0c, 0x61,
0x63, 0x74, 0x69, 0x76, 0x65, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28,
0x05, 0x52, 0x0c, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x12,
0x26, 0x0a, 0x0e, 0x72, 0x65, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x46, 0x72, 0x61, 0x6d, 0x65,
0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0e, 0x72, 0x65, 0x63, 0x6f, 0x76, 0x65, 0x72,
0x79, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x12, 0x34, 0x0a, 0x15, 0x72, 0x65, 0x63, 0x6f, 0x76,
0x65, 0x72, 0x79, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x4f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b,
0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x52, 0x15, 0x72, 0x65, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79,
0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x4f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x30, 0x0a,
0x65, 0x49, 0x64, 0x12, 0x1c, 0x0a, 0x09, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x4c, 0x69, 0x73, 0x74,
0x18, 0x02, 0x20, 0x03, 0x28, 0x04, 0x52, 0x09, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x4c, 0x69, 0x73,
0x74, 0x12, 0x24, 0x0a, 0x0d, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d, 0x65, 0x64, 0x4c, 0x69,
0x73, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0d, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x72,
0x6d, 0x65, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x22, 0x3b, 0x0a, 0x0f, 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, 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, 0xb8, 0x02, 0x0a, 0x05, 0x57, 0x73, 0x52, 0x65, 0x71, 0x12, 0x14,
0x0a, 0x05, 0x6d, 0x73, 0x67, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x6d,
0x73, 0x67, 0x49, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x49, 0x64,
0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x49, 0x64,
0x12, 0x10, 0x0a, 0x03, 0x61, 0x63, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x03, 0x61,
0x63, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x6a, 0x6f, 0x69, 0x6e, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x18,
0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x6a, 0x6f, 0x69, 0x6e, 0x49, 0x6e, 0x64, 0x65, 0x78,
0x12, 0x24, 0x0a, 0x0d, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x49,
0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0d, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x46,
0x72, 0x61, 0x6d, 0x65, 0x49, 0x64, 0x12, 0x2e, 0x0a, 0x12, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67,
0x49, 0x6e, 0x70, 0x75, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x49, 0x64, 0x18, 0x06, 0x20, 0x01,
0x28, 0x05, 0x52, 0x12, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x46,
0x72, 0x61, 0x6d, 0x65, 0x49, 0x64, 0x12, 0x4e, 0x0a, 0x15, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x46,
0x72, 0x61, 0x6d, 0x65, 0x55, 0x70, 0x73, 0x79, 0x6e, 0x63, 0x42, 0x61, 0x74, 0x63, 0x68, 0x18,
0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x49,
0x6e, 0x70, 0x75, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x55, 0x70, 0x73, 0x79, 0x6e, 0x63, 0x52,
0x15, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x55, 0x70, 0x73, 0x79, 0x6e,
0x63, 0x42, 0x61, 0x74, 0x63, 0x68, 0x12, 0x27, 0x0a, 0x02, 0x68, 0x62, 0x18, 0x08, 0x20, 0x01,
0x28, 0x0b, 0x32, 0x17, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x48, 0x65, 0x61, 0x72,
0x74, 0x62, 0x65, 0x61, 0x74, 0x55, 0x70, 0x73, 0x79, 0x6e, 0x63, 0x52, 0x02, 0x68, 0x62, 0x22,
0x89, 0x02, 0x0a, 0x06, 0x57, 0x73, 0x52, 0x65, 0x73, 0x70, 0x12, 0x10, 0x0a, 0x03, 0x72, 0x65,
0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x03, 0x72, 0x65, 0x74, 0x12, 0x20, 0x0a, 0x0b,
0x65, 0x63, 0x68, 0x6f, 0x65, 0x64, 0x4d, 0x73, 0x67, 0x49, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28,
0x05, 0x52, 0x0b, 0x65, 0x63, 0x68, 0x6f, 0x65, 0x64, 0x4d, 0x73, 0x67, 0x49, 0x64, 0x12, 0x10,
0x0a, 0x03, 0x61, 0x63, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x03, 0x61, 0x63, 0x74,
0x12, 0x2b, 0x0a, 0x03, 0x72, 0x64, 0x66, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e,
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x52, 0x6f, 0x6f, 0x6d, 0x44, 0x6f, 0x77, 0x6e, 0x73,
0x79, 0x6e, 0x63, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x52, 0x03, 0x72, 0x64, 0x66, 0x12, 0x54, 0x0a,
0x17, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x44, 0x6f, 0x77, 0x6e, 0x73,
0x79, 0x6e, 0x63, 0x42, 0x61, 0x74, 0x63, 0x68, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a,
0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x46, 0x72, 0x61,
0x6d, 0x65, 0x44, 0x6f, 0x77, 0x6e, 0x73, 0x79, 0x6e, 0x63, 0x52, 0x17, 0x69, 0x6e, 0x70, 0x75,
0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x44, 0x6f, 0x77, 0x6e, 0x73, 0x79, 0x6e, 0x63, 0x42, 0x61,
0x74, 0x63, 0x68, 0x12, 0x36, 0x0a, 0x08, 0x62, 0x63, 0x69, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x18,
0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x42,
0x61, 0x74, 0x74, 0x6c, 0x65, 0x43, 0x6f, 0x6c, 0x6c, 0x69, 0x64, 0x65, 0x72, 0x49, 0x6e, 0x66,
0x6f, 0x52, 0x08, 0x62, 0x63, 0x69, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x22, 0xc6, 0x01, 0x0a, 0x14,
0x49, 0x6e, 0x70, 0x75, 0x74, 0x73, 0x42, 0x75, 0x66, 0x66, 0x65, 0x72, 0x53, 0x6e, 0x61, 0x70,
0x73, 0x68, 0x6f, 0x74, 0x12, 0x2a, 0x0a, 0x10, 0x72, 0x65, 0x66, 0x52, 0x65, 0x6e, 0x64, 0x65,
0x72, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x10,
0x72, 0x65, 0x66, 0x52, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x49, 0x64,
0x12, 0x28, 0x0a, 0x0f, 0x75, 0x6e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d, 0x65, 0x64, 0x4d,
0x61, 0x73, 0x6b, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0f, 0x75, 0x6e, 0x63, 0x6f, 0x6e,
0x66, 0x69, 0x72, 0x6d, 0x65, 0x64, 0x4d, 0x61, 0x73, 0x6b, 0x12, 0x58, 0x0a, 0x19, 0x74, 0x6f,
0x53, 0x65, 0x6e, 0x64, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x44, 0x6f,
0x77, 0x6e, 0x73, 0x79, 0x6e, 0x63, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e,
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x46, 0x72, 0x61, 0x6d,
0x65, 0x44, 0x6f, 0x77, 0x6e, 0x73, 0x79, 0x6e, 0x63, 0x52, 0x19, 0x74, 0x6f, 0x53, 0x65, 0x6e,
0x64, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x44, 0x6f, 0x77, 0x6e, 0x73,
0x79, 0x6e, 0x63, 0x73, 0x22, 0xe5, 0x05, 0x0a, 0x0b, 0x4d, 0x65, 0x6c, 0x65, 0x65, 0x42, 0x75,
0x6c, 0x6c, 0x65, 0x74, 0x12, 0x24, 0x0a, 0x0d, 0x62, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x4c, 0x6f,
0x63, 0x61, 0x6c, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0d, 0x62, 0x61, 0x74,
0x74, 0x6c, 0x65, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x49, 0x64, 0x12, 0x24, 0x0a, 0x0d, 0x73, 0x74,
0x61, 0x72, 0x74, 0x75, 0x70, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28,
0x05, 0x52, 0x0d, 0x73, 0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73,
0x12, 0x22, 0x0a, 0x0c, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73,
0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0c, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x46, 0x72,
0x61, 0x6d, 0x65, 0x73, 0x12, 0x26, 0x0a, 0x0e, 0x72, 0x65, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79,
0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0e, 0x72, 0x65,
0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x12, 0x34, 0x0a, 0x15,
0x72, 0x65, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x4f, 0x6e,
0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x52, 0x15, 0x72, 0x65, 0x63,
0x6f, 0x76, 0x65, 0x72, 0x79, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x4f, 0x6e, 0x42, 0x6c, 0x6f,
0x63, 0x6b, 0x12, 0x30, 0x0a, 0x13, 0x72, 0x65, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x46, 0x72,
0x61, 0x6d, 0x65, 0x73, 0x4f, 0x6e, 0x48, 0x69, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x05, 0x52,
0x13, 0x72, 0x65, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x4f,
0x6e, 0x48, 0x69, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x05, 0x52, 0x13, 0x72, 0x65, 0x63, 0x6f,
0x76, 0x65, 0x72, 0x79, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x4f, 0x6e, 0x48, 0x69, 0x74, 0x12,
0x35, 0x0a, 0x0b, 0x6d, 0x6f, 0x76, 0x65, 0x66, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x18, 0x07,
0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x73, 0x68, 0x61, 0x72, 0x65, 0x64, 0x70, 0x72, 0x6f,
0x74, 0x6f, 0x73, 0x2e, 0x56, 0x65, 0x63, 0x32, 0x44, 0x52, 0x0b, 0x6d, 0x6f, 0x76, 0x65, 0x66,
0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x12, 0x22, 0x0a, 0x0c, 0x68, 0x69, 0x74, 0x62, 0x6f, 0x78,
0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x18, 0x08, 0x20, 0x01, 0x28, 0x01, 0x52, 0x0c, 0x68, 0x69,
0x74, 0x62, 0x6f, 0x78, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x12, 0x33, 0x0a, 0x0a, 0x68, 0x69,
0x74, 0x62, 0x6f, 0x78, 0x53, 0x69, 0x7a, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13,
0x2e, 0x73, 0x68, 0x61, 0x72, 0x65, 0x64, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x56, 0x65,
0x63, 0x32, 0x44, 0x52, 0x0a, 0x68, 0x69, 0x74, 0x62, 0x6f, 0x78, 0x53, 0x69, 0x7a, 0x65, 0x12,
0x38, 0x0a, 0x17, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x65, 0x64, 0x52, 0x65, 0x6e,
0x64, 0x65, 0x72, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x49, 0x64, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x05,
0x52, 0x17, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x65, 0x64, 0x52, 0x65, 0x6e, 0x64,
0x65, 0x72, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x49, 0x64, 0x12, 0x24, 0x0a, 0x0d, 0x68, 0x69, 0x74,
0x53, 0x74, 0x75, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x05,
0x52, 0x0d, 0x68, 0x69, 0x74, 0x53, 0x74, 0x75, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x12,
0x28, 0x0a, 0x0f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x53, 0x74, 0x75, 0x6e, 0x46, 0x72, 0x61, 0x6d,
0x65, 0x73, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x53,
0x74, 0x75, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x75, 0x73,
0x68, 0x62, 0x61, 0x63, 0x6b, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x01, 0x52, 0x08, 0x70, 0x75, 0x73,
0x68, 0x62, 0x61, 0x63, 0x6b, 0x12, 0x2e, 0x0a, 0x12, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65,
0x54, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x54, 0x79, 0x70, 0x65, 0x18, 0x0e, 0x20, 0x01, 0x28,
0x05, 0x52, 0x12, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x54, 0x72, 0x69, 0x67, 0x67, 0x65,
0x72, 0x54, 0x79, 0x70, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x64, 0x61, 0x6d, 0x61, 0x67, 0x65, 0x18,
0x0f, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x64, 0x61, 0x6d, 0x61, 0x67, 0x65, 0x12, 0x2c, 0x0a,
0x11, 0x6f, 0x66, 0x66, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x4a, 0x6f, 0x69, 0x6e, 0x49, 0x6e, 0x64,
0x65, 0x78, 0x18, 0x10, 0x20, 0x01, 0x28, 0x05, 0x52, 0x11, 0x6f, 0x66, 0x66, 0x65, 0x6e, 0x64,
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,
0x11, 0x20, 0x01, 0x28, 0x05, 0x52, 0x10, 0x6f, 0x66, 0x66, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x50,
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,
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,
0x73, 0x74, 0x72, 0x54, 0x6f, 0x56, 0x65, 0x63, 0x32, 0x44, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x61,
0x70, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73,
0x2e, 0x42, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x43, 0x6f, 0x6c, 0x6c, 0x69, 0x64, 0x65, 0x72, 0x49,
0x6e, 0x66, 0x6f, 0x2e, 0x53, 0x74, 0x72, 0x54, 0x6f, 0x56, 0x65, 0x63, 0x32, 0x44, 0x4c, 0x69,
0x73, 0x74, 0x4d, 0x61, 0x70, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x11, 0x73, 0x74, 0x72, 0x54,
0x6f, 0x56, 0x65, 0x63, 0x32, 0x44, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x61, 0x70, 0x12, 0x6b, 0x0a,
0x15, 0x73, 0x74, 0x72, 0x54, 0x6f, 0x50, 0x6f, 0x6c, 0x79, 0x67, 0x6f, 0x6e, 0x32, 0x44, 0x4c,
0x69, 0x73, 0x74, 0x4d, 0x61, 0x70, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x35, 0x2e, 0x70,
0x6e, 0x48, 0x69, 0x74, 0x12, 0x35, 0x0a, 0x0b, 0x6d, 0x6f, 0x76, 0x65, 0x66, 0x6f, 0x72, 0x77,
0x61, 0x72, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x73, 0x68, 0x61, 0x72,
0x65, 0x64, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x56, 0x65, 0x63, 0x32, 0x44, 0x52, 0x0b,
0x6d, 0x6f, 0x76, 0x65, 0x66, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x12, 0x22, 0x0a, 0x0c, 0x68,
0x69, 0x74, 0x62, 0x6f, 0x78, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x18, 0x08, 0x20, 0x01, 0x28,
0x01, 0x52, 0x0c, 0x68, 0x69, 0x74, 0x62, 0x6f, 0x78, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x12,
0x33, 0x0a, 0x0a, 0x68, 0x69, 0x74, 0x62, 0x6f, 0x78, 0x53, 0x69, 0x7a, 0x65, 0x18, 0x09, 0x20,
0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x73, 0x68, 0x61, 0x72, 0x65, 0x64, 0x70, 0x72, 0x6f, 0x74,
0x6f, 0x73, 0x2e, 0x56, 0x65, 0x63, 0x32, 0x44, 0x52, 0x0a, 0x68, 0x69, 0x74, 0x62, 0x6f, 0x78,
0x53, 0x69, 0x7a, 0x65, 0x12, 0x38, 0x0a, 0x17, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x74,
0x65, 0x64, 0x52, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x49, 0x64, 0x18,
0x0a, 0x20, 0x01, 0x28, 0x05, 0x52, 0x17, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x65,
0x64, 0x52, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x49, 0x64, 0x12, 0x24,
0x0a, 0x0d, 0x68, 0x69, 0x74, 0x53, 0x74, 0x75, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x18,
0x0b, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0d, 0x68, 0x69, 0x74, 0x53, 0x74, 0x75, 0x6e, 0x46, 0x72,
0x61, 0x6d, 0x65, 0x73, 0x12, 0x28, 0x0a, 0x0f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x53, 0x74, 0x75,
0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0f, 0x62,
0x6c, 0x6f, 0x63, 0x6b, 0x53, 0x74, 0x75, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x12, 0x1a,
0x0a, 0x08, 0x70, 0x75, 0x73, 0x68, 0x62, 0x61, 0x63, 0x6b, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x01,
0x52, 0x08, 0x70, 0x75, 0x73, 0x68, 0x62, 0x61, 0x63, 0x6b, 0x12, 0x2e, 0x0a, 0x12, 0x72, 0x65,
0x6c, 0x65, 0x61, 0x73, 0x65, 0x54, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x54, 0x79, 0x70, 0x65,
0x18, 0x0e, 0x20, 0x01, 0x28, 0x05, 0x52, 0x12, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x54,
0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x54, 0x79, 0x70, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x64, 0x61,
0x6d, 0x61, 0x67, 0x65, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x64, 0x61, 0x6d, 0x61,
0x67, 0x65, 0x12, 0x2c, 0x0a, 0x11, 0x6f, 0x66, 0x66, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x4a, 0x6f,
0x69, 0x6e, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x10, 0x20, 0x01, 0x28, 0x05, 0x52, 0x11, 0x6f,
0x66, 0x66, 0x65, 0x6e, 0x64, 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, 0x11, 0x20, 0x01, 0x28, 0x05, 0x52, 0x10, 0x6f, 0x66, 0x66, 0x65,
0x6e, 0x64, 0x65, 0x72, 0x50, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x49, 0x64, 0x22, 0xf2, 0x0e, 0x0a,
0x12, 0x42, 0x61, 0x74, 0x74, 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, 0x09, 0x52, 0x09, 0x73, 0x74, 0x61, 0x67, 0x65, 0x4e, 0x61, 0x6d,
0x65, 0x12, 0x5f, 0x0a, 0x11, 0x73, 0x74, 0x72, 0x54, 0x6f, 0x56, 0x65, 0x63, 0x32, 0x44, 0x4c,
0x69, 0x73, 0x74, 0x4d, 0x61, 0x70, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x70,
0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x42, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x43, 0x6f, 0x6c, 0x6c,
0x69, 0x64, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x2e, 0x53, 0x74, 0x72, 0x54, 0x6f, 0x50, 0x6f,
0x6c, 0x79, 0x67, 0x6f, 0x6e, 0x32, 0x44, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x61, 0x70, 0x45, 0x6e,
0x74, 0x72, 0x79, 0x52, 0x15, 0x73, 0x74, 0x72, 0x54, 0x6f, 0x50, 0x6f, 0x6c, 0x79, 0x67, 0x6f,
0x6e, 0x32, 0x44, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x61, 0x70, 0x12, 0x26, 0x0a, 0x0e, 0x73, 0x74,
0x61, 0x67, 0x65, 0x44, 0x69, 0x73, 0x63, 0x72, 0x65, 0x74, 0x65, 0x57, 0x18, 0x04, 0x20, 0x01,
0x28, 0x05, 0x52, 0x0e, 0x73, 0x74, 0x61, 0x67, 0x65, 0x44, 0x69, 0x73, 0x63, 0x72, 0x65, 0x74,
0x65, 0x57, 0x12, 0x26, 0x0a, 0x0e, 0x73, 0x74, 0x61, 0x67, 0x65, 0x44, 0x69, 0x73, 0x63, 0x72,
0x65, 0x74, 0x65, 0x48, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0e, 0x73, 0x74, 0x61, 0x67,
0x65, 0x44, 0x69, 0x73, 0x63, 0x72, 0x65, 0x74, 0x65, 0x48, 0x12, 0x1e, 0x0a, 0x0a, 0x73, 0x74,
0x61, 0x67, 0x65, 0x54, 0x69, 0x6c, 0x65, 0x57, 0x18, 0x06, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0a,
0x73, 0x74, 0x61, 0x67, 0x65, 0x54, 0x69, 0x6c, 0x65, 0x57, 0x12, 0x1e, 0x0a, 0x0a, 0x73, 0x74,
0x61, 0x67, 0x65, 0x54, 0x69, 0x6c, 0x65, 0x48, 0x18, 0x07, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0a,
0x73, 0x74, 0x61, 0x67, 0x65, 0x54, 0x69, 0x6c, 0x65, 0x48, 0x12, 0x26, 0x0a, 0x0e, 0x69, 0x6e,
0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x54, 0x6f, 0x50, 0x69, 0x6e, 0x67, 0x18, 0x08, 0x20, 0x01,
0x28, 0x05, 0x52, 0x0e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x54, 0x6f, 0x50, 0x69,
0x6e, 0x67, 0x12, 0x34, 0x0a, 0x15, 0x77, 0x69, 0x6c, 0x6c, 0x4b, 0x69, 0x63, 0x6b, 0x49, 0x66,
0x49, 0x6e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x46, 0x6f, 0x72, 0x18, 0x09, 0x20, 0x01, 0x28,
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,
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, 0x32, 0x0a, 0x14, 0x62, 0x61,
0x74, 0x74, 0x6c, 0x65, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x46, 0x72, 0x61, 0x6d,
0x65, 0x73, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x05, 0x52, 0x14, 0x62, 0x61, 0x74, 0x74, 0x6c, 0x65,
0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x12, 0x30,
0x0a, 0x13, 0x62, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e,
0x4e, 0x61, 0x6e, 0x6f, 0x73, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x03, 0x52, 0x13, 0x62, 0x61, 0x74,
0x74, 0x6c, 0x65, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4e, 0x61, 0x6e, 0x6f, 0x73,
0x12, 0x1c, 0x0a, 0x09, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x46, 0x70, 0x73, 0x18, 0x0e, 0x20,
0x01, 0x28, 0x05, 0x52, 0x09, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x46, 0x70, 0x73, 0x12, 0x2a,
0x0a, 0x10, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x44, 0x65, 0x6c, 0x61, 0x79, 0x46, 0x72, 0x61, 0x6d,
0x65, 0x73, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x05, 0x52, 0x10, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x44,
0x65, 0x6c, 0x61, 0x79, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x12, 0x2a, 0x0a, 0x10, 0x69, 0x6e,
0x70, 0x75, 0x74, 0x53, 0x63, 0x61, 0x6c, 0x65, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x10,
0x20, 0x01, 0x28, 0x0d, 0x52, 0x10, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x53, 0x63, 0x61, 0x6c, 0x65,
0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x12, 0x26, 0x0a, 0x0e, 0x6e, 0x73, 0x74, 0x44, 0x65, 0x6c,
0x61, 0x79, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x11, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0e,
0x6e, 0x73, 0x74, 0x44, 0x65, 0x6c, 0x61, 0x79, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x12, 0x46,
0x0a, 0x1e, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x55, 0x70, 0x73, 0x79,
0x6e, 0x63, 0x44, 0x65, 0x6c, 0x61, 0x79, 0x54, 0x6f, 0x6c, 0x65, 0x72, 0x61, 0x6e, 0x63, 0x65,
0x18, 0x12, 0x20, 0x01, 0x28, 0x05, 0x52, 0x1e, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x46, 0x72, 0x61,
0x6d, 0x65, 0x55, 0x70, 0x73, 0x79, 0x6e, 0x63, 0x44, 0x65, 0x6c, 0x61, 0x79, 0x54, 0x6f, 0x6c,
0x65, 0x72, 0x61, 0x6e, 0x63, 0x65, 0x12, 0x48, 0x0a, 0x1f, 0x6d, 0x61, 0x78, 0x43, 0x68, 0x61,
0x73, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73,
0x50, 0x65, 0x72, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x18, 0x13, 0x20, 0x01, 0x28, 0x05, 0x52,
0x1f, 0x6d, 0x61, 0x78, 0x43, 0x68, 0x61, 0x73, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x6e, 0x64, 0x65,
0x72, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x50, 0x65, 0x72, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65,
0x12, 0x2c, 0x0a, 0x11, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x42, 0x61, 0x74, 0x74, 0x6c, 0x65,
0x53, 0x74, 0x61, 0x74, 0x65, 0x18, 0x14, 0x20, 0x01, 0x28, 0x05, 0x52, 0x11, 0x70, 0x6c, 0x61,
0x79, 0x65, 0x72, 0x42, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x3c,
0x0a, 0x19, 0x72, 0x6f, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x45, 0x73, 0x74, 0x69, 0x6d, 0x61,
0x74, 0x65, 0x64, 0x44, 0x74, 0x4d, 0x69, 0x6c, 0x6c, 0x69, 0x73, 0x18, 0x15, 0x20, 0x01, 0x28,
0x01, 0x52, 0x19, 0x72, 0x6f, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x45, 0x73, 0x74, 0x69, 0x6d,
0x61, 0x74, 0x65, 0x64, 0x44, 0x74, 0x4d, 0x69, 0x6c, 0x6c, 0x69, 0x73, 0x12, 0x3a, 0x0a, 0x18,
0x72, 0x6f, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x45, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65,
0x64, 0x44, 0x74, 0x4e, 0x61, 0x6e, 0x6f, 0x73, 0x18, 0x16, 0x20, 0x01, 0x28, 0x03, 0x52, 0x18,
0x72, 0x6f, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x45, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65,
0x64, 0x44, 0x74, 0x4e, 0x61, 0x6e, 0x6f, 0x73, 0x12, 0x38, 0x0a, 0x17, 0x77, 0x6f, 0x72, 0x6c,
0x64, 0x54, 0x6f, 0x56, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x47, 0x72, 0x69, 0x64, 0x52, 0x61,
0x74, 0x69, 0x6f, 0x18, 0x17, 0x20, 0x01, 0x28, 0x01, 0x52, 0x17, 0x77, 0x6f, 0x72, 0x6c, 0x64,
0x54, 0x6f, 0x56, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x47, 0x72, 0x69, 0x64, 0x52, 0x61, 0x74,
0x69, 0x6f, 0x12, 0x38, 0x0a, 0x17, 0x76, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x47, 0x72, 0x69,
0x64, 0x54, 0x6f, 0x57, 0x6f, 0x72, 0x6c, 0x64, 0x52, 0x61, 0x74, 0x69, 0x6f, 0x18, 0x18, 0x20,
0x01, 0x28, 0x01, 0x52, 0x17, 0x76, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x47, 0x72, 0x69, 0x64,
0x54, 0x6f, 0x57, 0x6f, 0x72, 0x6c, 0x64, 0x52, 0x61, 0x74, 0x69, 0x6f, 0x12, 0x2c, 0x0a, 0x11,
0x73, 0x70, 0x41, 0x74, 0x6b, 0x4c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x46, 0x72, 0x61, 0x6d, 0x65,
0x73, 0x18, 0x19, 0x20, 0x01, 0x28, 0x05, 0x52, 0x11, 0x73, 0x70, 0x41, 0x74, 0x6b, 0x4c, 0x6f,
0x6f, 0x6b, 0x75, 0x70, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x12, 0x28, 0x0a, 0x0f, 0x72, 0x65,
0x6e, 0x64, 0x65, 0x72, 0x43, 0x61, 0x63, 0x68, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x18, 0x1a, 0x20,
0x01, 0x28, 0x05, 0x52, 0x0f, 0x72, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x43, 0x61, 0x63, 0x68, 0x65,
0x53, 0x69, 0x7a, 0x65, 0x12, 0x5c, 0x0a, 0x10, 0x6d, 0x65, 0x6c, 0x65, 0x65, 0x53, 0x6b, 0x69,
0x6c, 0x6c, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x1b, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x30,
0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x42, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x43, 0x6f,
0x6c, 0x6c, 0x69, 0x64, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x2e, 0x4d, 0x65, 0x6c, 0x65, 0x65,
0x69, 0x64, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x2e, 0x53, 0x74, 0x72, 0x54, 0x6f, 0x56, 0x65,
0x63, 0x32, 0x44, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x61, 0x70, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52,
0x11, 0x73, 0x74, 0x72, 0x54, 0x6f, 0x56, 0x65, 0x63, 0x32, 0x44, 0x4c, 0x69, 0x73, 0x74, 0x4d,
0x61, 0x70, 0x12, 0x6b, 0x0a, 0x15, 0x73, 0x74, 0x72, 0x54, 0x6f, 0x50, 0x6f, 0x6c, 0x79, 0x67,
0x6f, 0x6e, 0x32, 0x44, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x61, 0x70, 0x18, 0x03, 0x20, 0x03, 0x28,
0x0b, 0x32, 0x35, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x42, 0x61, 0x74, 0x74, 0x6c,
0x65, 0x43, 0x6f, 0x6c, 0x6c, 0x69, 0x64, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x2e, 0x53, 0x74,
0x72, 0x54, 0x6f, 0x50, 0x6f, 0x6c, 0x79, 0x67, 0x6f, 0x6e, 0x32, 0x44, 0x4c, 0x69, 0x73, 0x74,
0x4d, 0x61, 0x70, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x15, 0x73, 0x74, 0x72, 0x54, 0x6f, 0x50,
0x6f, 0x6c, 0x79, 0x67, 0x6f, 0x6e, 0x32, 0x44, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x61, 0x70, 0x12,
0x26, 0x0a, 0x0e, 0x73, 0x74, 0x61, 0x67, 0x65, 0x44, 0x69, 0x73, 0x63, 0x72, 0x65, 0x74, 0x65,
0x57, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0e, 0x73, 0x74, 0x61, 0x67, 0x65, 0x44, 0x69,
0x73, 0x63, 0x72, 0x65, 0x74, 0x65, 0x57, 0x12, 0x26, 0x0a, 0x0e, 0x73, 0x74, 0x61, 0x67, 0x65,
0x44, 0x69, 0x73, 0x63, 0x72, 0x65, 0x74, 0x65, 0x48, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x52,
0x0e, 0x73, 0x74, 0x61, 0x67, 0x65, 0x44, 0x69, 0x73, 0x63, 0x72, 0x65, 0x74, 0x65, 0x48, 0x12,
0x1e, 0x0a, 0x0a, 0x73, 0x74, 0x61, 0x67, 0x65, 0x54, 0x69, 0x6c, 0x65, 0x57, 0x18, 0x06, 0x20,
0x01, 0x28, 0x05, 0x52, 0x0a, 0x73, 0x74, 0x61, 0x67, 0x65, 0x54, 0x69, 0x6c, 0x65, 0x57, 0x12,
0x1e, 0x0a, 0x0a, 0x73, 0x74, 0x61, 0x67, 0x65, 0x54, 0x69, 0x6c, 0x65, 0x48, 0x18, 0x07, 0x20,
0x01, 0x28, 0x05, 0x52, 0x0a, 0x73, 0x74, 0x61, 0x67, 0x65, 0x54, 0x69, 0x6c, 0x65, 0x48, 0x12,
0x26, 0x0a, 0x0e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x54, 0x6f, 0x50, 0x69, 0x6e,
0x67, 0x18, 0x08, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61,
0x6c, 0x54, 0x6f, 0x50, 0x69, 0x6e, 0x67, 0x12, 0x34, 0x0a, 0x15, 0x77, 0x69, 0x6c, 0x6c, 0x4b,
0x69, 0x63, 0x6b, 0x49, 0x66, 0x49, 0x6e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x46, 0x6f, 0x72,
0x18, 0x09, 0x20, 0x01, 0x28, 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, 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,
0x32, 0x0a, 0x14, 0x62, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f,
0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x05, 0x52, 0x14, 0x62,
0x61, 0x74, 0x74, 0x6c, 0x65, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x46, 0x72, 0x61,
0x6d, 0x65, 0x73, 0x12, 0x30, 0x0a, 0x13, 0x62, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x44, 0x75, 0x72,
0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4e, 0x61, 0x6e, 0x6f, 0x73, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x03,
0x52, 0x13, 0x62, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e,
0x4e, 0x61, 0x6e, 0x6f, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x46,
0x70, 0x73, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72,
0x46, 0x70, 0x73, 0x12, 0x2a, 0x0a, 0x10, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x44, 0x65, 0x6c, 0x61,
0x79, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x05, 0x52, 0x10, 0x69,
0x6e, 0x70, 0x75, 0x74, 0x44, 0x65, 0x6c, 0x61, 0x79, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x12,
0x2a, 0x0a, 0x10, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x53, 0x63, 0x61, 0x6c, 0x65, 0x46, 0x72, 0x61,
0x6d, 0x65, 0x73, 0x18, 0x10, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x10, 0x69, 0x6e, 0x70, 0x75, 0x74,
0x53, 0x63, 0x61, 0x6c, 0x65, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x12, 0x26, 0x0a, 0x0e, 0x6e,
0x73, 0x74, 0x44, 0x65, 0x6c, 0x61, 0x79, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x11, 0x20,
0x01, 0x28, 0x05, 0x52, 0x0e, 0x6e, 0x73, 0x74, 0x44, 0x65, 0x6c, 0x61, 0x79, 0x46, 0x72, 0x61,
0x6d, 0x65, 0x73, 0x12, 0x46, 0x0a, 0x1e, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x46, 0x72, 0x61, 0x6d,
0x65, 0x55, 0x70, 0x73, 0x79, 0x6e, 0x63, 0x44, 0x65, 0x6c, 0x61, 0x79, 0x54, 0x6f, 0x6c, 0x65,
0x72, 0x61, 0x6e, 0x63, 0x65, 0x18, 0x12, 0x20, 0x01, 0x28, 0x05, 0x52, 0x1e, 0x69, 0x6e, 0x70,
0x75, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x55, 0x70, 0x73, 0x79, 0x6e, 0x63, 0x44, 0x65, 0x6c,
0x61, 0x79, 0x54, 0x6f, 0x6c, 0x65, 0x72, 0x61, 0x6e, 0x63, 0x65, 0x12, 0x48, 0x0a, 0x1f, 0x6d,
0x61, 0x78, 0x43, 0x68, 0x61, 0x73, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x46,
0x72, 0x61, 0x6d, 0x65, 0x73, 0x50, 0x65, 0x72, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x18, 0x13,
0x20, 0x01, 0x28, 0x05, 0x52, 0x1f, 0x6d, 0x61, 0x78, 0x43, 0x68, 0x61, 0x73, 0x69, 0x6e, 0x67,
0x52, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x50, 0x65, 0x72, 0x55,
0x70, 0x64, 0x61, 0x74, 0x65, 0x12, 0x2c, 0x0a, 0x11, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x42,
0x61, 0x74, 0x74, 0x6c, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x18, 0x14, 0x20, 0x01, 0x28, 0x05,
0x52, 0x11, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x42, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x53, 0x74,
0x61, 0x74, 0x65, 0x12, 0x3c, 0x0a, 0x19, 0x72, 0x6f, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x45,
0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x64, 0x44, 0x74, 0x4d, 0x69, 0x6c, 0x6c, 0x69, 0x73,
0x18, 0x15, 0x20, 0x01, 0x28, 0x01, 0x52, 0x19, 0x72, 0x6f, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b,
0x45, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x64, 0x44, 0x74, 0x4d, 0x69, 0x6c, 0x6c, 0x69,
0x73, 0x12, 0x3a, 0x0a, 0x18, 0x72, 0x6f, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x45, 0x73, 0x74,
0x69, 0x6d, 0x61, 0x74, 0x65, 0x64, 0x44, 0x74, 0x4e, 0x61, 0x6e, 0x6f, 0x73, 0x18, 0x16, 0x20,
0x01, 0x28, 0x03, 0x52, 0x18, 0x72, 0x6f, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x45, 0x73, 0x74,
0x69, 0x6d, 0x61, 0x74, 0x65, 0x64, 0x44, 0x74, 0x4e, 0x61, 0x6e, 0x6f, 0x73, 0x12, 0x38, 0x0a,
0x17, 0x77, 0x6f, 0x72, 0x6c, 0x64, 0x54, 0x6f, 0x56, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x47,
0x72, 0x69, 0x64, 0x52, 0x61, 0x74, 0x69, 0x6f, 0x18, 0x17, 0x20, 0x01, 0x28, 0x01, 0x52, 0x17,
0x77, 0x6f, 0x72, 0x6c, 0x64, 0x54, 0x6f, 0x56, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x47, 0x72,
0x69, 0x64, 0x52, 0x61, 0x74, 0x69, 0x6f, 0x12, 0x38, 0x0a, 0x17, 0x76, 0x69, 0x72, 0x74, 0x75,
0x61, 0x6c, 0x47, 0x72, 0x69, 0x64, 0x54, 0x6f, 0x57, 0x6f, 0x72, 0x6c, 0x64, 0x52, 0x61, 0x74,
0x69, 0x6f, 0x18, 0x18, 0x20, 0x01, 0x28, 0x01, 0x52, 0x17, 0x76, 0x69, 0x72, 0x74, 0x75, 0x61,
0x6c, 0x47, 0x72, 0x69, 0x64, 0x54, 0x6f, 0x57, 0x6f, 0x72, 0x6c, 0x64, 0x52, 0x61, 0x74, 0x69,
0x6f, 0x12, 0x2c, 0x0a, 0x11, 0x73, 0x70, 0x41, 0x74, 0x6b, 0x4c, 0x6f, 0x6f, 0x6b, 0x75, 0x70,
0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x19, 0x20, 0x01, 0x28, 0x05, 0x52, 0x11, 0x73, 0x70,
0x41, 0x74, 0x6b, 0x4c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x12,
0x28, 0x0a, 0x0f, 0x72, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x43, 0x61, 0x63, 0x68, 0x65, 0x53, 0x69,
0x7a, 0x65, 0x18, 0x1a, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0f, 0x72, 0x65, 0x6e, 0x64, 0x65, 0x72,
0x43, 0x61, 0x63, 0x68, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x5c, 0x0a, 0x10, 0x6d, 0x65, 0x6c,
0x65, 0x65, 0x53, 0x6b, 0x69, 0x6c, 0x6c, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x1b, 0x20,
0x03, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x42, 0x61, 0x74,
0x74, 0x6c, 0x65, 0x43, 0x6f, 0x6c, 0x6c, 0x69, 0x64, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x2e,
0x4d, 0x65, 0x6c, 0x65, 0x65, 0x53, 0x6b, 0x69, 0x6c, 0x6c, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67,
0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x10, 0x6d, 0x65, 0x6c, 0x65, 0x65, 0x53, 0x6b, 0x69, 0x6c,
0x6c, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x38, 0x0a, 0x17, 0x73, 0x6e, 0x61, 0x70, 0x49,
0x6e, 0x74, 0x6f, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x4f, 0x76, 0x65, 0x72, 0x6c,
0x61, 0x70, 0x18, 0x1c, 0x20, 0x01, 0x28, 0x01, 0x52, 0x17, 0x73, 0x6e, 0x61, 0x70, 0x49, 0x6e,
0x74, 0x6f, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x4f, 0x76, 0x65, 0x72, 0x6c, 0x61,
0x70, 0x12, 0x3c, 0x0a, 0x19, 0x73, 0x6e, 0x61, 0x70, 0x49, 0x6e, 0x74, 0x6f, 0x50, 0x6c, 0x61,
0x74, 0x66, 0x6f, 0x72, 0x6d, 0x54, 0x68, 0x72, 0x65, 0x73, 0x68, 0x6f, 0x6c, 0x64, 0x18, 0x1d,
0x20, 0x01, 0x28, 0x01, 0x52, 0x19, 0x73, 0x6e, 0x61, 0x70, 0x49, 0x6e, 0x74, 0x6f, 0x50, 0x6c,
0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x54, 0x68, 0x72, 0x65, 0x73, 0x68, 0x6f, 0x6c, 0x64, 0x12,
0x28, 0x0a, 0x0f, 0x6a, 0x75, 0x6d, 0x70, 0x69, 0x6e, 0x67, 0x49, 0x6e, 0x69, 0x74, 0x56, 0x65,
0x6c, 0x59, 0x18, 0x1e, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0f, 0x6a, 0x75, 0x6d, 0x70, 0x69, 0x6e,
0x67, 0x49, 0x6e, 0x69, 0x74, 0x56, 0x65, 0x6c, 0x59, 0x12, 0x1a, 0x0a, 0x08, 0x67, 0x72, 0x61,
0x76, 0x69, 0x74, 0x79, 0x58, 0x18, 0x1f, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x67, 0x72, 0x61,
0x76, 0x69, 0x74, 0x79, 0x58, 0x12, 0x1a, 0x0a, 0x08, 0x67, 0x72, 0x61, 0x76, 0x69, 0x74, 0x79,
0x59, 0x18, 0x20, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x67, 0x72, 0x61, 0x76, 0x69, 0x74, 0x79,
0x59, 0x1a, 0x5d, 0x0a, 0x16, 0x53, 0x74, 0x72, 0x54, 0x6f, 0x56, 0x65, 0x63, 0x32, 0x44, 0x4c,
0x69, 0x73, 0x74, 0x4d, 0x61, 0x70, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b,
0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x2d, 0x0a,
0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x73,
0x68, 0x61, 0x72, 0x65, 0x64, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x56, 0x65, 0x63, 0x32,
0x44, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01,
0x1a, 0x65, 0x0a, 0x1a, 0x53, 0x74, 0x72, 0x54, 0x6f, 0x50, 0x6f, 0x6c, 0x79, 0x67, 0x6f, 0x6e,
0x32, 0x44, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x61, 0x70, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10,
0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79,
0x12, 0x31, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32,
0x1b, 0x2e, 0x73, 0x68, 0x61, 0x72, 0x65, 0x64, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x50,
0x6f, 0x6c, 0x79, 0x67, 0x6f, 0x6e, 0x32, 0x44, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x05, 0x76, 0x61,
0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x58, 0x0a, 0x15, 0x4d, 0x65, 0x6c, 0x65, 0x65,
0x53, 0x6b, 0x69, 0x6c, 0x6c, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x45, 0x6e, 0x74, 0x72, 0x79,
0x52, 0x10, 0x6d, 0x65, 0x6c, 0x65, 0x65, 0x53, 0x6b, 0x69, 0x6c, 0x6c, 0x43, 0x6f, 0x6e, 0x66,
0x69, 0x67, 0x1a, 0x5d, 0x0a, 0x16, 0x53, 0x74, 0x72, 0x54, 0x6f, 0x56, 0x65, 0x63, 0x32, 0x44,
0x4c, 0x69, 0x73, 0x74, 0x4d, 0x61, 0x70, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03,
0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x2d,
0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e,
0x73, 0x68, 0x61, 0x72, 0x65, 0x64, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x56, 0x65, 0x63,
0x32, 0x44, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38,
0x01, 0x1a, 0x65, 0x0a, 0x1a, 0x53, 0x74, 0x72, 0x54, 0x6f, 0x50, 0x6f, 0x6c, 0x79, 0x67, 0x6f,
0x6e, 0x32, 0x44, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x61, 0x70, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12,
0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65,
0x79, 0x12, 0x31, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b,
0x32, 0x1b, 0x2e, 0x73, 0x68, 0x61, 0x72, 0x65, 0x64, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e,
0x50, 0x6f, 0x6c, 0x79, 0x67, 0x6f, 0x6e, 0x32, 0x44, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x05, 0x76,
0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x58, 0x0a, 0x15, 0x4d, 0x65, 0x6c, 0x65,
0x65, 0x53, 0x6b, 0x69, 0x6c, 0x6c, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x45, 0x6e, 0x74, 0x72,
0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x03,
0x6b, 0x65, 0x79, 0x12, 0x29, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01,
0x28, 0x0b, 0x32, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x4d, 0x65, 0x6c, 0x65,
0x65, 0x42, 0x75, 0x6c, 0x6c, 0x65, 0x74, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02,
0x38, 0x01, 0x22, 0xd2, 0x02, 0x0a, 0x11, 0x52, 0x6f, 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, 0x40, 0x0a, 0x07, 0x70, 0x6c, 0x61, 0x79,
0x65, 0x72, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x70, 0x72, 0x6f, 0x74,
0x6f, 0x73, 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,
0x79, 0x52, 0x07, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x73, 0x12, 0x26, 0x0a, 0x0e, 0x63, 0x6f,
0x75, 0x6e, 0x74, 0x64, 0x6f, 0x77, 0x6e, 0x4e, 0x61, 0x6e, 0x6f, 0x73, 0x18, 0x03, 0x20, 0x01,
0x28, 0x03, 0x52, 0x0e, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x64, 0x6f, 0x77, 0x6e, 0x4e, 0x61, 0x6e,
0x6f, 0x73, 0x12, 0x37, 0x0a, 0x0c, 0x6d, 0x65, 0x6c, 0x65, 0x65, 0x42, 0x75, 0x6c, 0x6c, 0x65,
0x74, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
0x73, 0x2e, 0x4d, 0x65, 0x6c, 0x65, 0x65, 0x42, 0x75, 0x6c, 0x6c, 0x65, 0x74, 0x52, 0x0c, 0x6d,
0x65, 0x6c, 0x65, 0x65, 0x42, 0x75, 0x6c, 0x6c, 0x65, 0x74, 0x73, 0x12, 0x36, 0x0a, 0x16, 0x62,
0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x55, 0x6e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d, 0x65,
0x64, 0x4d, 0x61, 0x73, 0x6b, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x16, 0x62, 0x61, 0x63,
0x6b, 0x65, 0x6e, 0x64, 0x55, 0x6e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d, 0x65, 0x64, 0x4d,
0x61, 0x73, 0x6b, 0x1a, 0x52, 0x0a, 0x0c, 0x50, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x73, 0x45, 0x6e,
0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05,
0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x2c, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02,
0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x70, 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,
0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x03, 0x6b,
0x65, 0x79, 0x12, 0x29, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28,
0x0b, 0x32, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x4d, 0x65, 0x6c, 0x65, 0x65,
0x42, 0x75, 0x6c, 0x6c, 0x65, 0x74, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38,
0x01, 0x22, 0xd2, 0x02, 0x0a, 0x11, 0x52, 0x6f, 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, 0x40, 0x0a, 0x07, 0x70, 0x6c, 0x61, 0x79, 0x65,
0x72, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
0x73, 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, 0x79,
0x52, 0x07, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x73, 0x12, 0x26, 0x0a, 0x0e, 0x63, 0x6f, 0x75,
0x6e, 0x74, 0x64, 0x6f, 0x77, 0x6e, 0x4e, 0x61, 0x6e, 0x6f, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28,
0x03, 0x52, 0x0e, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x64, 0x6f, 0x77, 0x6e, 0x4e, 0x61, 0x6e, 0x6f,
0x73, 0x12, 0x37, 0x0a, 0x0c, 0x6d, 0x65, 0x6c, 0x65, 0x65, 0x42, 0x75, 0x6c, 0x6c, 0x65, 0x74,
0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73,
0x2e, 0x4d, 0x65, 0x6c, 0x65, 0x65, 0x42, 0x75, 0x6c, 0x6c, 0x65, 0x74, 0x52, 0x0c, 0x6d, 0x65,
0x6c, 0x65, 0x65, 0x42, 0x75, 0x6c, 0x6c, 0x65, 0x74, 0x73, 0x12, 0x36, 0x0a, 0x16, 0x62, 0x61,
0x63, 0x6b, 0x65, 0x6e, 0x64, 0x55, 0x6e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d, 0x65, 0x64,
0x4d, 0x61, 0x73, 0x6b, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x16, 0x62, 0x61, 0x63, 0x6b,
0x65, 0x6e, 0x64, 0x55, 0x6e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d, 0x65, 0x64, 0x4d, 0x61,
0x73, 0x6b, 0x1a, 0x52, 0x0a, 0x0c, 0x50, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x73, 0x45, 0x6e, 0x74,
0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52,
0x03, 0x6b, 0x65, 0x79, 0x12, 0x2c, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20,
0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x70, 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 (
@@ -1423,7 +1590,7 @@ func file_room_downsync_frame_proto_rawDescGZIP() []byte {
return file_room_downsync_frame_proto_rawDescData
}
var file_room_downsync_frame_proto_msgTypes = make([]protoimpl.MessageInfo, 14)
var file_room_downsync_frame_proto_msgTypes = make([]protoimpl.MessageInfo, 15)
var file_room_downsync_frame_proto_goTypes = []interface{}{
(*PlayerDownsync)(nil), // 0: protos.PlayerDownsync
(*InputFrameDecoded)(nil), // 1: protos.InputFrameDecoded
@@ -1432,39 +1599,41 @@ var file_room_downsync_frame_proto_goTypes = []interface{}{
(*HeartbeatUpsync)(nil), // 4: protos.HeartbeatUpsync
(*WsReq)(nil), // 5: protos.WsReq
(*WsResp)(nil), // 6: protos.WsResp
(*MeleeBullet)(nil), // 7: protos.MeleeBullet
(*BattleColliderInfo)(nil), // 8: protos.BattleColliderInfo
(*RoomDownsyncFrame)(nil), // 9: protos.RoomDownsyncFrame
nil, // 10: protos.BattleColliderInfo.StrToVec2DListMapEntry
nil, // 11: protos.BattleColliderInfo.StrToPolygon2DListMapEntry
nil, // 12: protos.BattleColliderInfo.MeleeSkillConfigEntry
nil, // 13: protos.RoomDownsyncFrame.PlayersEntry
(*sharedprotos.Vec2D)(nil), // 14: sharedprotos.Vec2D
(*sharedprotos.Vec2DList)(nil), // 15: sharedprotos.Vec2DList
(*sharedprotos.Polygon2DList)(nil), // 16: sharedprotos.Polygon2DList
(*InputsBufferSnapshot)(nil), // 7: protos.InputsBufferSnapshot
(*MeleeBullet)(nil), // 8: protos.MeleeBullet
(*BattleColliderInfo)(nil), // 9: protos.BattleColliderInfo
(*RoomDownsyncFrame)(nil), // 10: protos.RoomDownsyncFrame
nil, // 11: protos.BattleColliderInfo.StrToVec2DListMapEntry
nil, // 12: protos.BattleColliderInfo.StrToPolygon2DListMapEntry
nil, // 13: protos.BattleColliderInfo.MeleeSkillConfigEntry
nil, // 14: protos.RoomDownsyncFrame.PlayersEntry
(*sharedprotos.Vec2D)(nil), // 15: sharedprotos.Vec2D
(*sharedprotos.Vec2DList)(nil), // 16: sharedprotos.Vec2DList
(*sharedprotos.Polygon2DList)(nil), // 17: sharedprotos.Polygon2DList
}
var file_room_downsync_frame_proto_depIdxs = []int32{
2, // 0: protos.WsReq.inputFrameUpsyncBatch:type_name -> protos.InputFrameUpsync
4, // 1: protos.WsReq.hb:type_name -> protos.HeartbeatUpsync
9, // 2: protos.WsResp.rdf:type_name -> protos.RoomDownsyncFrame
10, // 2: protos.WsResp.rdf:type_name -> protos.RoomDownsyncFrame
3, // 3: protos.WsResp.inputFrameDownsyncBatch:type_name -> protos.InputFrameDownsync
8, // 4: protos.WsResp.bciFrame:type_name -> protos.BattleColliderInfo
14, // 5: protos.MeleeBullet.moveforward:type_name -> sharedprotos.Vec2D
14, // 6: protos.MeleeBullet.hitboxSize:type_name -> sharedprotos.Vec2D
10, // 7: protos.BattleColliderInfo.strToVec2DListMap:type_name -> protos.BattleColliderInfo.StrToVec2DListMapEntry
11, // 8: protos.BattleColliderInfo.strToPolygon2DListMap:type_name -> protos.BattleColliderInfo.StrToPolygon2DListMapEntry
12, // 9: protos.BattleColliderInfo.meleeSkillConfig:type_name -> protos.BattleColliderInfo.MeleeSkillConfigEntry
13, // 10: protos.RoomDownsyncFrame.players:type_name -> protos.RoomDownsyncFrame.PlayersEntry
7, // 11: protos.RoomDownsyncFrame.meleeBullets:type_name -> protos.MeleeBullet
15, // 12: protos.BattleColliderInfo.StrToVec2DListMapEntry.value:type_name -> sharedprotos.Vec2DList
16, // 13: protos.BattleColliderInfo.StrToPolygon2DListMapEntry.value:type_name -> sharedprotos.Polygon2DList
7, // 14: protos.BattleColliderInfo.MeleeSkillConfigEntry.value:type_name -> protos.MeleeBullet
0, // 15: protos.RoomDownsyncFrame.PlayersEntry.value:type_name -> protos.PlayerDownsync
16, // [16:16] is the sub-list for method output_type
16, // [16:16] is the sub-list for method input_type
16, // [16:16] is the sub-list for extension type_name
16, // [16:16] is the sub-list for extension extendee
0, // [0:16] is the sub-list for field type_name
9, // 4: protos.WsResp.bciFrame:type_name -> protos.BattleColliderInfo
3, // 5: protos.InputsBufferSnapshot.toSendInputFrameDownsyncs:type_name -> protos.InputFrameDownsync
15, // 6: protos.MeleeBullet.moveforward:type_name -> sharedprotos.Vec2D
15, // 7: protos.MeleeBullet.hitboxSize:type_name -> sharedprotos.Vec2D
11, // 8: protos.BattleColliderInfo.strToVec2DListMap:type_name -> protos.BattleColliderInfo.StrToVec2DListMapEntry
12, // 9: protos.BattleColliderInfo.strToPolygon2DListMap:type_name -> protos.BattleColliderInfo.StrToPolygon2DListMapEntry
13, // 10: protos.BattleColliderInfo.meleeSkillConfig:type_name -> protos.BattleColliderInfo.MeleeSkillConfigEntry
14, // 11: protos.RoomDownsyncFrame.players:type_name -> protos.RoomDownsyncFrame.PlayersEntry
8, // 12: protos.RoomDownsyncFrame.meleeBullets:type_name -> protos.MeleeBullet
16, // 13: protos.BattleColliderInfo.StrToVec2DListMapEntry.value:type_name -> sharedprotos.Vec2DList
17, // 14: protos.BattleColliderInfo.StrToPolygon2DListMapEntry.value:type_name -> sharedprotos.Polygon2DList
8, // 15: protos.BattleColliderInfo.MeleeSkillConfigEntry.value:type_name -> protos.MeleeBullet
0, // 16: protos.RoomDownsyncFrame.PlayersEntry.value:type_name -> protos.PlayerDownsync
17, // [17:17] is the sub-list for method output_type
17, // [17:17] is the sub-list for method input_type
17, // [17:17] is the sub-list for extension type_name
17, // [17:17] is the sub-list for extension extendee
0, // [0:17] is the sub-list for field type_name
}
func init() { file_room_downsync_frame_proto_init() }
@@ -1558,7 +1727,7 @@ func file_room_downsync_frame_proto_init() {
}
}
file_room_downsync_frame_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*MeleeBullet); i {
switch v := v.(*InputsBufferSnapshot); i {
case 0:
return &v.state
case 1:
@@ -1570,7 +1739,7 @@ func file_room_downsync_frame_proto_init() {
}
}
file_room_downsync_frame_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*BattleColliderInfo); i {
switch v := v.(*MeleeBullet); i {
case 0:
return &v.state
case 1:
@@ -1582,6 +1751,18 @@ func file_room_downsync_frame_proto_init() {
}
}
file_room_downsync_frame_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*BattleColliderInfo); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_room_downsync_frame_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*RoomDownsyncFrame); i {
case 0:
return &v.state
@@ -1600,7 +1781,7 @@ func file_room_downsync_frame_proto_init() {
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_room_downsync_frame_proto_rawDesc,
NumEnums: 0,
NumMessages: 14,
NumMessages: 15,
NumExtensions: 0,
NumServices: 0,
},

View File

@@ -265,9 +265,14 @@ func Serve(c *gin.Context) {
WorldToVirtualGridRatio: pRoom.WorldToVirtualGridRatio,
VirtualGridToWorldRatio: pRoom.VirtualGridToWorldRatio,
SpAtkLookupFrames: pRoom.SpAtkLookupFrames,
RenderCacheSize: pRoom.RenderCacheSize,
MeleeSkillConfig: pRoom.MeleeSkillConfig,
SpAtkLookupFrames: pRoom.SpAtkLookupFrames,
RenderCacheSize: pRoom.RenderCacheSize,
MeleeSkillConfig: pRoom.MeleeSkillConfig,
SnapIntoPlatformOverlap: pRoom.SnapIntoPlatformOverlap,
SnapIntoPlatformThreshold: pRoom.SnapIntoPlatformThreshold,
JumpingInitVelY: pRoom.JumpingInitVelY,
GravityX: pRoom.GravityX,
GravityY: pRoom.GravityY,
}
resp := &pb.WsResp{

BIN
charts/jump_sync_spedup.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.7 MiB

View File

@@ -34,15 +34,18 @@ func NewWorldColliderDisplay(game *Game, stageDiscreteW, stageDiscreteH, stageTi
spaceOffsetX := float64(spaceW) * 0.5
spaceOffsetY := float64(spaceH) * 0.5
virtualGridToWorldRatio := 0.1
playerDefaultSpeed := 20
worldToVirtualGridRatio := float64(1000)
virtualGridToWorldRatio := float64(1) / worldToVirtualGridRatio
playerDefaultSpeed := 1 * worldToVirtualGridRatio
minStep := (int(float64(playerDefaultSpeed)*virtualGridToWorldRatio) << 2)
playerColliderRadius := float64(24)
playerColliderRadius := float64(12)
playerColliders := make([]*resolv.Object, len(playerPosList.Eles))
snapIntoPlatformOverlap := float64(0.1)
space := resolv.NewSpace(int(spaceW), int(spaceH), minStep, minStep)
for i, playerPos := range playerPosList.Eles {
playerCollider := GenerateRectCollider(playerPos.X, playerPos.Y, playerColliderRadius*2, playerColliderRadius*2, spaceOffsetX, spaceOffsetY, "Player") // [WARNING] Deliberately not using a circle because "resolv v0.5.1" doesn't yet align circle center with space cell center, regardless of the "specified within-object offset"
Logger.Info(fmt.Sprintf("Player Collider#%d: player world pos =(%.2f, %.2f), shape=%v", i, playerPos.X, playerPos.Y, ConvexPolygonStr(playerCollider.Shape.(*resolv.ConvexPolygon))))
colliderWidth, colliderHeight := playerColliderRadius*2, playerColliderRadius*4
playerCollider := GenerateRectCollider(playerPos.X, playerPos.Y, colliderWidth, colliderHeight, snapIntoPlatformOverlap, spaceOffsetX, spaceOffsetY, "Player") // [WARNING] Deliberately not using a circle because "resolv v0.5.1" doesn't yet align circle center with space cell center, regardless of the "specified within-object offset"
Logger.Info(fmt.Sprintf("Player Collider#%d: player world pos=(%.2f, %.2f), shape=%v", i, playerPos.X, playerPos.Y, ConvexPolygonStr(playerCollider.Shape.(*resolv.ConvexPolygon))))
playerColliders[i] = playerCollider
space.Add(playerCollider)
}
@@ -50,7 +53,7 @@ func NewWorldColliderDisplay(game *Game, stageDiscreteW, stageDiscreteH, stageTi
barrierLocalId := 0
for _, barrierUnaligned := range barrierList.Eles {
barrierCollider := GenerateConvexPolygonCollider(barrierUnaligned, spaceOffsetX, spaceOffsetY, "Barrier")
Logger.Info(fmt.Sprintf("Added barrier: shape=%v", ConvexPolygonStr(barrierCollider.Shape.(*resolv.ConvexPolygon))))
Logger.Debug(fmt.Sprintf("Added barrier: shape=%v", ConvexPolygonStr(barrierCollider.Shape.(*resolv.ConvexPolygon))))
space.Add(barrierCollider)
barrierLocalId++
}
@@ -59,24 +62,26 @@ func NewWorldColliderDisplay(game *Game, stageDiscreteW, stageDiscreteH, stageTi
moveToCollide := false
if moveToCollide {
newVx, newVy := int32(-2959), int32(-2261)
effPushback := Vec2D{X: float64(0), Y: float64(0)}
toTestPlayerCollider := playerColliders[0]
toTestPlayerCollider.X, toTestPlayerCollider.Y = VirtualGridToPolygonColliderAnchorPos(newVx, newVy, playerColliderRadius, playerColliderRadius, spaceOffsetX, spaceOffsetY, virtualGridToWorldRatio)
newVx, newVy := int32(27999), int32(-420270)
colliderWidth, colliderHeight := playerColliderRadius*2, playerColliderRadius*4
toTestPlayerCollider.X, toTestPlayerCollider.Y = VirtualGridToPolygonColliderTLPos(newVx, newVy, colliderWidth, colliderHeight, spaceOffsetX, spaceOffsetY, virtualGridToWorldRatio)
Logger.Info(fmt.Sprintf("Checking collision for virtual (%d, %d), now playerShape=%v", newVx, newVy, ConvexPolygonStr(toTestPlayerCollider.Shape.(*resolv.ConvexPolygon))))
Logger.Info(fmt.Sprintf("Checking collision for playerShape=%v", ConvexPolygonStr(toTestPlayerCollider.Shape.(*resolv.ConvexPolygon))))
toTestPlayerCollider.Update()
if collision := toTestPlayerCollider.Check(0, 0); collision != nil {
playerShape := toTestPlayerCollider.Shape.(*resolv.ConvexPolygon)
for _, obj := range collision.Objects {
barrierShape := obj.Shape.(*resolv.ConvexPolygon)
if overlapped, pushbackX, pushbackY, overlapResult := CalcPushbacks(0, 0, playerShape, barrierShape); overlapped {
Logger.Warn(fmt.Sprintf("Overlapped: a=%v, b=%v, pushbackX=%v, pushbackY=%v", ConvexPolygonStr(playerShape), ConvexPolygonStr(barrierShape), pushbackX, pushbackY))
bShape := obj.Shape.(*resolv.ConvexPolygon)
Logger.Warn(fmt.Sprintf("Checking potential: a=%v, b=%v", ConvexPolygonStr(playerShape), ConvexPolygonStr(bShape)))
if overlapped, pushbackX, pushbackY, overlapResult := CalcPushbacks(0, 0, playerShape, bShape); overlapped {
Logger.Warn(fmt.Sprintf("Overlapped: a=%v, b=%v, pushbackX=%v, pushbackY=%v", ConvexPolygonStr(playerShape), ConvexPolygonStr(bShape), pushbackX, pushbackY))
effPushback.X += pushbackX
effPushback.Y += pushbackY
} else {
Logger.Warn(fmt.Sprintf("Collided BUT not overlapped: a=%v, b=%v, overlapResult=%v", ConvexPolygonStr(playerShape), ConvexPolygonStr(barrierShape), overlapResult))
Logger.Warn(fmt.Sprintf("Collided BUT not overlapped: a=%v, b=%v, overlapResult=%v", ConvexPolygonStr(playerShape), ConvexPolygonStr(bShape), overlapResult))
}
}
toTestPlayerCollider.X -= effPushback.X
@@ -115,7 +120,7 @@ func NewWorldColliderDisplay(game *Game, stageDiscreteW, stageDiscreteH, stageTi
offenderWx, offenderWy := playerPosList.Eles[0].X, playerPosList.Eles[0].Y
bulletWx, bulletWy := offenderWx+xfac*meleeBullet.HitboxOffset, offenderWy
newBulletCollider := GenerateRectCollider(bulletWx, bulletWy, meleeBullet.HitboxSize.X, meleeBullet.HitboxSize.Y, spaceOffsetX, spaceOffsetY, "MeleeBullet")
newBulletCollider := GenerateRectCollider(bulletWx, bulletWy, meleeBullet.HitboxSize.X, meleeBullet.HitboxSize.Y, 0, spaceOffsetX, spaceOffsetY, "MeleeBullet")
space.Add(newBulletCollider)
bulletShape := newBulletCollider.Shape.(*resolv.ConvexPolygon)
Logger.Warn(fmt.Sprintf("bullet ->: Added bullet collider to space: a=%v", ConvexPolygonStr(bulletShape)))
@@ -138,7 +143,7 @@ func NewWorldColliderDisplay(game *Game, stageDiscreteW, stageDiscreteH, stageTi
offenderWx, offenderWy := playerPosList.Eles[1].X, playerPosList.Eles[1].Y
bulletWx, bulletWy := offenderWx+xfac*meleeBullet.HitboxOffset, offenderWy
newBulletCollider := GenerateRectCollider(bulletWx, bulletWy, meleeBullet.HitboxSize.X, meleeBullet.HitboxSize.Y, spaceOffsetX, spaceOffsetY, "MeleeBullet")
newBulletCollider := GenerateRectCollider(bulletWx, bulletWy, meleeBullet.HitboxSize.X, meleeBullet.HitboxSize.Y, 0, spaceOffsetX, spaceOffsetY, "MeleeBullet")
space.Add(newBulletCollider)
bulletShape := newBulletCollider.Shape.(*resolv.ConvexPolygon)
Logger.Warn(fmt.Sprintf("bullet <-: Added bullet collider to space: a=%v", ConvexPolygonStr(bulletShape)))
@@ -177,7 +182,7 @@ func (world *WorldColliderDisplay) Draw(screen *ebiten.Image) {
}
}
world.Game.DebugDraw(screen, world.Space)
//world.Game.DebugDraw(screen, world.Space)
if world.Game.ShowHelpText {

View File

@@ -10,33 +10,33 @@ func NormVec2D(dx, dy float64) Vec2D {
}
func AlignPolygon2DToBoundingBox(input *Polygon2D) *Polygon2D {
// Transform again to put "anchor" at the top-left point of the bounding box for "resolv"
boundingBoxTL := &Vec2D{
// Transform again to put "anchor" at the "bottom-left point (w.r.t. world space)" of the bounding box for "resolv"
boundingBoxBL := &Vec2D{
X: math.MaxFloat64,
Y: math.MaxFloat64,
}
for _, p := range input.Points {
if p.X < boundingBoxTL.X {
boundingBoxTL.X = p.X
if p.X < boundingBoxBL.X {
boundingBoxBL.X = p.X
}
if p.Y < boundingBoxTL.Y {
boundingBoxTL.Y = p.Y
if p.Y < boundingBoxBL.Y {
boundingBoxBL.Y = p.Y
}
}
// Now "input.Anchor" should move to "input.Anchor+boundingBoxTL", thus "boundingBoxTL" is also the value of the negative diff for all "input.Points"
// Now "input.Anchor" should move to "input.Anchor+boundingBoxBL", thus "boundingBoxBL" is also the value of the negative diff for all "input.Points"
output := &Polygon2D{
Anchor: &Vec2D{
X: input.Anchor.X + boundingBoxTL.X,
Y: input.Anchor.Y + boundingBoxTL.Y,
X: input.Anchor.X + boundingBoxBL.X,
Y: input.Anchor.Y + boundingBoxBL.Y,
},
Points: make([]*Vec2D, len(input.Points)),
}
for i, p := range input.Points {
output.Points[i] = &Vec2D{
X: p.X - boundingBoxTL.X,
Y: p.Y - boundingBoxTL.Y,
X: p.X - boundingBoxBL.X,
Y: p.Y - boundingBoxBL.Y,
}
}

View File

@@ -18,13 +18,13 @@ func ConvexPolygonStr(body *resolv.ConvexPolygon) string {
return fmt.Sprintf("{\n%s\n}", strings.Join(s, ",\n"))
}
func GenerateRectCollider(origX, origY, w, h, spaceOffsetX, spaceOffsetY float64, tag string) *resolv.Object {
cx, cy := WorldToPolygonColliderAnchorPos(origX, origY, w*0.5, h*0.5, spaceOffsetX, spaceOffsetY)
return GenerateRectColliderInCollisionSpace(cx, cy, w, h, tag)
func GenerateRectCollider(wx, wy, w, h, bottomPadding, spaceOffsetX, spaceOffsetY float64, tag string) *resolv.Object {
blX, blY := WorldToPolygonColliderBLPos(wx, wy, w*0.5, h*0.5, bottomPadding, spaceOffsetX, spaceOffsetY)
return generateRectColliderInCollisionSpace(blX, blY, w, h+bottomPadding, tag)
}
func GenerateRectColliderInCollisionSpace(cx, cy, w, h float64, tag string) *resolv.Object {
collider := resolv.NewObject(cx, cy, w, h, tag)
func generateRectColliderInCollisionSpace(blX, blY, w, h float64, tag string) *resolv.Object {
collider := resolv.NewObject(blX, blY, w, h, tag) // Unlike its frontend counter part, the position of a "resolv.Object" must be specified by "bottom-left point" because "w" and "h" must be positive, see "resolv.Object.BoundsToSpace" for details
shape := resolv.NewRectangle(0, 0, w, h)
collider.SetShape(shape)
return collider
@@ -66,6 +66,7 @@ func CalcPushbacks(oldDx, oldDy float64, playerShape, barrierShape *resolv.Conve
playerShape.SetPosition(origX, origY)
}()
playerShape.SetPosition(origX+oldDx, origY+oldDy)
overlapResult := &SatResult{
Overlap: 0,
OverlapX: 0,
@@ -74,7 +75,7 @@ func CalcPushbacks(oldDx, oldDy float64, playerShape, barrierShape *resolv.Conve
BContainedInA: true,
Axis: vector.Vector{0, 0},
}
if overlapped := IsPolygonPairOverlapped(playerShape, barrierShape, overlapResult); overlapped {
if overlapped := isPolygonPairOverlapped(playerShape, barrierShape, overlapResult); overlapped {
pushbackX, pushbackY := overlapResult.Overlap*overlapResult.OverlapX, overlapResult.Overlap*overlapResult.OverlapY
return true, pushbackX, pushbackY, overlapResult
} else {
@@ -91,16 +92,17 @@ type SatResult struct {
Axis vector.Vector
}
func IsPolygonPairOverlapped(a, b *resolv.ConvexPolygon, result *SatResult) bool {
func isPolygonPairOverlapped(a, b *resolv.ConvexPolygon, result *SatResult) bool {
aCnt, bCnt := len(a.Points), len(b.Points)
// Single point case
if 1 == aCnt && 1 == bCnt {
if nil != result {
result.Overlap = 0
}
return a.Points[0].X() == b.Points[0].X() && a.Points[0].Y() == b.Points[0].Y()
return a.Points[0][0] == b.Points[0][0] && a.Points[0][1] == b.Points[0][1]
}
//Logger.Info(fmt.Sprintf("Checking collision between a=%v, b=%v", ConvexPolygonStr(a), ConvexPolygonStr(b)))
if 1 < aCnt {
for _, axis := range a.SATAxes() {
if isPolygonPairSeparatedByDir(a, b, axis.Unit(), result) {
@@ -116,6 +118,7 @@ func IsPolygonPairOverlapped(a, b *resolv.ConvexPolygon, result *SatResult) bool
}
}
}
//Logger.Info(fmt.Sprintf("a=%v and b=%v are overlapped", ConvexPolygonStr(a), ConvexPolygonStr(b)))
return true
}
@@ -137,9 +140,10 @@ func isPolygonPairSeparatedByDir(a, b *resolv.ConvexPolygon, e vector.Vector, re
e = (-2.98, 1.49).Unit()
*/
//Logger.Info(fmt.Sprintf("Checking separation between a=%v, b=%v along axis e={%.3f, %.3f}#1", ConvexPolygonStr(a), ConvexPolygonStr(b), e[0], e[1]))
var aStart, aEnd, bStart, bEnd float64 = math.MaxFloat64, -math.MaxFloat64, math.MaxFloat64, -math.MaxFloat64
for _, p := range a.Points {
dot := (p.X()+a.X)*e.X() + (p.Y()+a.Y)*e.Y()
dot := (p[0]+a.X)*e[0] + (p[1]+a.Y)*e[1]
if aStart > dot {
aStart = dot
@@ -151,7 +155,7 @@ func isPolygonPairSeparatedByDir(a, b *resolv.ConvexPolygon, e vector.Vector, re
}
for _, p := range b.Points {
dot := (p.X()+b.X)*e.X() + (p.Y()+b.Y)*e.Y()
dot := (p[0]+b.X)*e[0] + (p[1]+b.Y)*e[1]
if bStart > dot {
bStart = dot
@@ -168,7 +172,6 @@ func isPolygonPairSeparatedByDir(a, b *resolv.ConvexPolygon, e vector.Vector, re
}
if nil != result {
result.Axis = e
overlap := float64(0)
if aStart < bStart {
@@ -209,16 +212,19 @@ func isPolygonPairSeparatedByDir(a, b *resolv.ConvexPolygon, e vector.Vector, re
absoluteOverlap = -overlap
}
if 0 == currentOverlap || currentOverlap > absoluteOverlap {
if (0 == result.Axis[0] && 0 == result.Axis[1]) || currentOverlap > absoluteOverlap {
var sign float64 = 1
if overlap < 0 {
sign = -1
}
result.Overlap = absoluteOverlap
result.OverlapX = e.X() * sign
result.OverlapY = e.Y() * sign
result.OverlapX = e[0] * sign
result.OverlapY = e[1] * sign
}
result.Axis = e
//Logger.Info(fmt.Sprintf("Checking separation between a=%v, b=%v along axis e={%.3f, %.3f}#2: aStart=%.3f, aEnd=%.3f, bStart=%.3f, bEnd=%.3f, overlap=%.3f, currentOverlap=%.3f, absoluteOverlap=%.3f, result=%v", ConvexPolygonStr(a), ConvexPolygonStr(b), e[0], e[1], aStart, aEnd, bStart, bEnd, overlap, currentOverlap, absoluteOverlap, result))
}
// the specified unit vector "e" doesn't separate "a" and "b", overlap result is generated
@@ -240,20 +246,38 @@ func VirtualGridToWorldPos(vx, vy int32, virtualGridToWorldRatio float64) (float
return wx, wy
}
func WorldToPolygonColliderAnchorPos(wx, wy, halfBoundingW, halfBoundingH, collisionSpaceOffsetX, collisionSpaceOffsetY float64) (float64, float64) {
return wx - halfBoundingW + collisionSpaceOffsetX, wy - halfBoundingH + collisionSpaceOffsetY
func WorldToPolygonColliderBLPos(wx, wy, halfBoundingW, halfBoundingH, bottomPadding, collisionSpaceOffsetX, collisionSpaceOffsetY float64) (float64, float64) {
return wx - halfBoundingW + collisionSpaceOffsetX, wy - halfBoundingH - bottomPadding + collisionSpaceOffsetY
}
func PolygonColliderAnchorToWorldPos(cx, cy, halfBoundingW, halfBoundingH, collisionSpaceOffsetX, collisionSpaceOffsetY float64) (float64, float64) {
return cx + halfBoundingW - collisionSpaceOffsetX, cy + halfBoundingH - collisionSpaceOffsetY
func WorldToPolygonColliderTLPos(wx, wy, halfBoundingW, halfBoundingH, collisionSpaceOffsetX, collisionSpaceOffsetY float64) (float64, float64) {
return wx - halfBoundingW + collisionSpaceOffsetX, wy + halfBoundingH + collisionSpaceOffsetY
}
func PolygonColliderAnchorToVirtualGridPos(cx, cy, halfBoundingW, halfBoundingH, collisionSpaceOffsetX, collisionSpaceOffsetY float64, worldToVirtualGridRatio float64) (int32, int32) {
wx, wy := PolygonColliderAnchorToWorldPos(cx, cy, halfBoundingW, halfBoundingH, collisionSpaceOffsetX, collisionSpaceOffsetY)
func PolygonColliderBLToWorldPos(cx, cy, halfBoundingW, halfBoundingH, bottomPadding, collisionSpaceOffsetX, collisionSpaceOffsetY float64) (float64, float64) {
return cx + halfBoundingW - collisionSpaceOffsetX, cy + halfBoundingH + bottomPadding - collisionSpaceOffsetY
}
func PolygonColliderTLToWorldPos(cx, cy, halfBoundingW, halfBoundingH, collisionSpaceOffsetX, collisionSpaceOffsetY float64) (float64, float64) {
return cx + halfBoundingW - collisionSpaceOffsetX, cy - halfBoundingH - collisionSpaceOffsetY
}
func PolygonColliderBLToVirtualGridPos(cx, cy, halfBoundingW, halfBoundingH, bottomPadding, collisionSpaceOffsetX, collisionSpaceOffsetY float64, worldToVirtualGridRatio float64) (int32, int32) {
wx, wy := PolygonColliderBLToWorldPos(cx, cy, halfBoundingW, halfBoundingH, bottomPadding, collisionSpaceOffsetX, collisionSpaceOffsetY)
return WorldToVirtualGridPos(wx, wy, worldToVirtualGridRatio)
}
func VirtualGridToPolygonColliderAnchorPos(vx, vy int32, halfBoundingW, halfBoundingH, collisionSpaceOffsetX, collisionSpaceOffsetY float64, virtualGridToWorldRatio float64) (float64, float64) {
wx, wy := VirtualGridToWorldPos(vx, vy, virtualGridToWorldRatio)
return WorldToPolygonColliderAnchorPos(wx, wy, halfBoundingW, halfBoundingH, collisionSpaceOffsetX, collisionSpaceOffsetY)
func PolygonColliderTLToVirtualGridPos(cx, cy, halfBoundingW, halfBoundingH, collisionSpaceOffsetX, collisionSpaceOffsetY float64, worldToVirtualGridRatio float64) (int32, int32) {
wx, wy := PolygonColliderTLToWorldPos(cx, cy, halfBoundingW, halfBoundingH, collisionSpaceOffsetX, collisionSpaceOffsetY)
return WorldToVirtualGridPos(wx, wy, worldToVirtualGridRatio)
}
func VirtualGridToPolygonColliderBLPos(vx, vy int32, halfBoundingW, halfBoundingH, bottomPadding, collisionSpaceOffsetX, collisionSpaceOffsetY float64, virtualGridToWorldRatio float64) (float64, float64) {
wx, wy := VirtualGridToWorldPos(vx, vy, virtualGridToWorldRatio)
return WorldToPolygonColliderBLPos(wx, wy, halfBoundingW, halfBoundingH, bottomPadding, collisionSpaceOffsetX, collisionSpaceOffsetY)
}
func VirtualGridToPolygonColliderTLPos(vx, vy int32, halfBoundingW, halfBoundingH, collisionSpaceOffsetX, collisionSpaceOffsetY float64, virtualGridToWorldRatio float64) (float64, float64) {
wx, wy := VirtualGridToWorldPos(vx, vy, virtualGridToWorldRatio)
return WorldToPolygonColliderTLPos(wx, wy, halfBoundingW, halfBoundingH, collisionSpaceOffsetX, collisionSpaceOffsetY)
}

View File

@@ -7,6 +7,7 @@ import (
"encoding/base64"
"encoding/xml"
"errors"
"fmt"
"go.uber.org/zap"
"io/ioutil"
"math"
@@ -43,13 +44,13 @@ type TmxOrTsxPolyline struct {
type TmxOrTsxObject struct {
Id int `xml:"id,attr"`
Gid *int `xml:"gid,attr"`
Gid int `xml:"gid,attr"`
X float64 `xml:"x,attr"`
Y float64 `xml:"y,attr"`
Properties *TmxOrTsxProperties `xml:"properties"`
Polyline *TmxOrTsxPolyline `xml:"polyline"`
Width *float64 `xml:"width,attr"`
Height *float64 `xml:"height,attr"`
Width float64 `xml:"width,attr"`
Height float64 `xml:"height,attr"`
}
type TmxOrTsxObjectGroup struct {
@@ -376,13 +377,37 @@ func ParseTmxLayersAndGroups(pTmxMapIns *TmxMap, gidBoundariesMap map[int]StrToP
}
for _, singleObjInTmxFile := range objGroup.Objects {
if nil == singleObjInTmxFile.Polyline {
continue
}
if nil == singleObjInTmxFile.Properties.Property || "boundary_type" != singleObjInTmxFile.Properties.Property[0].Name || "barrier" != singleObjInTmxFile.Properties.Property[0].Value {
continue
}
if nil == singleObjInTmxFile.Polyline {
pts := make([]*Vec2D, 4)
s := make([]string, 0)
pts[0] = &Vec2D{
X: float64(0),
Y: float64(0),
}
pts[1] = &Vec2D{
X: float64(0),
Y: singleObjInTmxFile.Height,
}
pts[2] = &Vec2D{
X: singleObjInTmxFile.Width,
Y: singleObjInTmxFile.Height,
}
pts[3] = &Vec2D{
X: singleObjInTmxFile.Width,
Y: float64(0),
}
for _, pt := range pts {
s = append(s, fmt.Sprintf("%v,%v", pt.X, pt.Y))
}
singleObjInTmxFile.Polyline = &TmxOrTsxPolyline{
Points: strings.Join(s, " "),
}
}
thePolygon2DInWorld, err := tmxPolylineToPolygon2D(pTmxMapIns, singleObjInTmxFile, singleObjInTmxFile.Polyline)
if nil != err {
panic(err)

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1 +1 @@
{"width":64,"imagePath":"SoldierFireGhost_tex.png","SubTexture":[{"frameWidth":12,"y":42,"frameHeight":11,"width":11,"frameX":-1,"height":11,"name":"biu","frameY":0,"x":16},{"width":5,"y":42,"height":7,"name":"rightArm","x":29},{"frameWidth":15,"y":27,"frameHeight":16,"width":13,"frameX":-1,"height":16,"name":"yinmoqe00","frameY":0,"x":1},{"width":17,"y":1,"height":21,"name":"body","x":28},{"width":5,"y":42,"height":7,"name":"rightShoulder","x":36},{"width":10,"y":45,"height":9,"name":"rightFrontArm","x":1},{"width":7,"y":56,"height":7,"name":"rightHand","x":1},{"width":6,"y":55,"height":6,"name":"leftArm","x":32},{"width":7,"y":55,"height":6,"name":"leftShoulder","x":23},{"width":10,"y":27,"height":11,"name":"leftFrontArm","x":16},{"width":17,"y":24,"height":16,"name":"head","x":28},{"width":25,"y":1,"height":24,"name":"head2","x":1},{"width":8,"y":55,"height":7,"name":"leftHand","x":13},{"frameWidth":4,"y":51,"frameHeight":4,"width":2,"frameX":-1,"height":2,"name":"huomiao01","frameY":-1,"x":29}],"height":64,"name":"SoldierFireGhost"}
{"imagePath":"SoldierFireGhost_tex.png","width":64,"height":64,"name":"SoldierFireGhost","SubTexture":[{"frameY":0,"y":42,"frameWidth":12,"frameHeight":11,"width":11,"height":11,"name":"biu","frameX":-1,"x":16},{"width":5,"y":42,"height":7,"name":"rightArm","x":29},{"frameY":0,"y":27,"frameWidth":15,"frameHeight":16,"width":13,"height":16,"name":"yinmoqe00","frameX":-1,"x":1},{"width":17,"y":1,"height":21,"name":"body","x":28},{"width":5,"y":42,"height":7,"name":"rightShoulder","x":36},{"width":10,"y":45,"height":9,"name":"rightFrontArm","x":1},{"width":7,"y":56,"height":7,"name":"rightHand","x":1},{"width":6,"y":55,"height":6,"name":"leftArm","x":32},{"width":7,"y":55,"height":6,"name":"leftShoulder","x":23},{"width":10,"y":27,"height":11,"name":"leftFrontArm","x":16},{"width":25,"y":1,"height":24,"name":"head2","x":1},{"width":17,"y":24,"height":16,"name":"head","x":28},{"width":8,"y":55,"height":7,"name":"leftHand","x":13},{"frameY":-1,"y":51,"frameWidth":4,"frameHeight":4,"width":2,"height":2,"name":"huomiao01","frameX":-1,"x":29}]}

View File

@@ -1,7 +1,7 @@
{
"ver": "1.0.0",
"uuid": "4a9187d5-a9ad-4464-a03c-d2f3cc277051",
"atlasJson": "{\"width\":64,\"imagePath\":\"SoldierFireGhost_tex.png\",\"SubTexture\":[{\"frameWidth\":12,\"y\":42,\"frameHeight\":11,\"width\":11,\"frameX\":-1,\"height\":11,\"name\":\"biu\",\"frameY\":0,\"x\":16},{\"width\":5,\"y\":42,\"height\":7,\"name\":\"rightArm\",\"x\":29},{\"frameWidth\":15,\"y\":27,\"frameHeight\":16,\"width\":13,\"frameX\":-1,\"height\":16,\"name\":\"yinmoqe00\",\"frameY\":0,\"x\":1},{\"width\":17,\"y\":1,\"height\":21,\"name\":\"body\",\"x\":28},{\"width\":5,\"y\":42,\"height\":7,\"name\":\"rightShoulder\",\"x\":36},{\"width\":10,\"y\":45,\"height\":9,\"name\":\"rightFrontArm\",\"x\":1},{\"width\":7,\"y\":56,\"height\":7,\"name\":\"rightHand\",\"x\":1},{\"width\":6,\"y\":55,\"height\":6,\"name\":\"leftArm\",\"x\":32},{\"width\":7,\"y\":55,\"height\":6,\"name\":\"leftShoulder\",\"x\":23},{\"width\":10,\"y\":27,\"height\":11,\"name\":\"leftFrontArm\",\"x\":16},{\"width\":17,\"y\":24,\"height\":16,\"name\":\"head\",\"x\":28},{\"width\":25,\"y\":1,\"height\":24,\"name\":\"head2\",\"x\":1},{\"width\":8,\"y\":55,\"height\":7,\"name\":\"leftHand\",\"x\":13},{\"frameWidth\":4,\"y\":51,\"frameHeight\":4,\"width\":2,\"frameX\":-1,\"height\":2,\"name\":\"huomiao01\",\"frameY\":-1,\"x\":29}],\"height\":64,\"name\":\"SoldierFireGhost\"}",
"atlasJson": "{\"imagePath\":\"SoldierFireGhost_tex.png\",\"width\":64,\"height\":64,\"name\":\"SoldierFireGhost\",\"SubTexture\":[{\"frameY\":0,\"y\":42,\"frameWidth\":12,\"frameHeight\":11,\"width\":11,\"height\":11,\"name\":\"biu\",\"frameX\":-1,\"x\":16},{\"width\":5,\"y\":42,\"height\":7,\"name\":\"rightArm\",\"x\":29},{\"frameY\":0,\"y\":27,\"frameWidth\":15,\"frameHeight\":16,\"width\":13,\"height\":16,\"name\":\"yinmoqe00\",\"frameX\":-1,\"x\":1},{\"width\":17,\"y\":1,\"height\":21,\"name\":\"body\",\"x\":28},{\"width\":5,\"y\":42,\"height\":7,\"name\":\"rightShoulder\",\"x\":36},{\"width\":10,\"y\":45,\"height\":9,\"name\":\"rightFrontArm\",\"x\":1},{\"width\":7,\"y\":56,\"height\":7,\"name\":\"rightHand\",\"x\":1},{\"width\":6,\"y\":55,\"height\":6,\"name\":\"leftArm\",\"x\":32},{\"width\":7,\"y\":55,\"height\":6,\"name\":\"leftShoulder\",\"x\":23},{\"width\":10,\"y\":27,\"height\":11,\"name\":\"leftFrontArm\",\"x\":16},{\"width\":25,\"y\":1,\"height\":24,\"name\":\"head2\",\"x\":1},{\"width\":17,\"y\":24,\"height\":16,\"name\":\"head\",\"x\":28},{\"width\":8,\"y\":55,\"height\":7,\"name\":\"leftHand\",\"x\":13},{\"frameY\":-1,\"y\":51,\"frameWidth\":4,\"frameHeight\":4,\"width\":2,\"height\":2,\"name\":\"huomiao01\",\"frameX\":-1,\"x\":29}]}",
"texture": "700d963b-2192-4219-a066-8be5b3db7453",
"subMetas": {}
}

View File

@@ -0,0 +1,205 @@
{
"__type__": "cc.AnimationClip",
"_name": "InAirIdle1",
"_objFlags": 0,
"_native": "",
"_duration": 0.5166666666666667,
"sample": 60,
"speed": 1,
"wrapMode": 2,
"curveData": {
"comps": {
"cc.Sprite": {
"spriteFrame": [
{
"frame": 0,
"value": {
"__uuid__": "dd02916e-9ac8-4fe7-a944-d6082eb9007a"
}
},
{
"frame": 0.016666666666666666,
"value": {
"__uuid__": "1906b14b-f3a2-4dc9-9e0d-99e3b334e67b"
}
},
{
"frame": 0.03333333333333333,
"value": {
"__uuid__": "1b4f284c-be67-403b-9f5d-59aa641d3c92"
}
},
{
"frame": 0.05,
"value": {
"__uuid__": "6feb197e-2013-48fd-bbbb-3d2809cb1d63"
}
},
{
"frame": 0.06666666666666667,
"value": {
"__uuid__": "2db4e807-a5d2-4c09-b033-a0ae97e5d0bf"
}
},
{
"frame": 0.08333333333333333,
"value": {
"__uuid__": "73958a6b-31a7-4bb8-babd-1aefba55a793"
}
},
{
"frame": 0.1,
"value": {
"__uuid__": "9545ca77-8002-4ad1-a91e-1e343cdf0e0b"
}
},
{
"frame": 0.11666666666666667,
"value": {
"__uuid__": "581e4c15-9de3-4b72-a91a-2e82ac6b092c"
}
},
{
"frame": 0.13333333333333333,
"value": {
"__uuid__": "4af94082-f36b-4b9e-9077-bd458fd0b188"
}
},
{
"frame": 0.15,
"value": {
"__uuid__": "5463290d-7b25-4625-8be5-1a16dbe3bd83"
}
},
{
"frame": 0.16666666666666666,
"value": {
"__uuid__": "e507775a-1009-47a8-b1a8-8ade0104e4c2"
}
},
{
"frame": 0.18333333333333332,
"value": {
"__uuid__": "6583a9e1-92fb-4db2-9437-9d2b26bc5920"
}
},
{
"frame": 0.2,
"value": {
"__uuid__": "b07e2da2-d1f2-4ec8-acdf-92706d0be9e0"
}
},
{
"frame": 0.21666666666666667,
"value": {
"__uuid__": "dd60bf4f-6b5f-4385-9e46-1e49e6a7cfbe"
}
},
{
"frame": 0.23333333333333334,
"value": {
"__uuid__": "46811e43-c874-41d5-8799-6fafc904cd5a"
}
},
{
"frame": 0.25,
"value": {
"__uuid__": "0a370e7e-e25f-4faf-9a76-73b246338a4d"
}
},
{
"frame": 0.26666666666666666,
"value": {
"__uuid__": "1f003135-e929-4a05-9029-76e7cb8c76ef"
}
},
{
"frame": 0.2833333333333333,
"value": {
"__uuid__": "b78015ba-98e4-4ccd-9852-a7ec053a0ba4"
}
},
{
"frame": 0.3,
"value": {
"__uuid__": "0589abef-dc0d-4d33-a084-25b273ca1368"
}
},
{
"frame": 0.31666666666666665,
"value": {
"__uuid__": "20542755-bbfa-43cd-b593-e73d121b5ed6"
}
},
{
"frame": 0.3333333333333333,
"value": {
"__uuid__": "5d5ac5af-3da7-4b22-9183-5885736e2ca7"
}
},
{
"frame": 0.35,
"value": {
"__uuid__": "47bbe2a2-a983-4aca-8a3e-6cd6df5eee03"
}
},
{
"frame": 0.36666666666666664,
"value": {
"__uuid__": "6d3fb572-d6af-4b7e-9350-9ff482569127"
}
},
{
"frame": 0.38333333333333336,
"value": {
"__uuid__": "573cfba0-4534-4886-849a-61f4f2cbd349"
}
},
{
"frame": 0.4,
"value": {
"__uuid__": "0b4ebd8a-6316-4802-aa24-49ab08e6a75b"
}
},
{
"frame": 0.4166666666666667,
"value": {
"__uuid__": "5b7fff7b-5818-4be8-b65d-c212d15e6e71"
}
},
{
"frame": 0.43333333333333335,
"value": {
"__uuid__": "f964ec77-c016-44fa-8f55-3e59ae30283d"
}
},
{
"frame": 0.45,
"value": {
"__uuid__": "679a79eb-85c6-4445-8517-36465c57c6da"
}
},
{
"frame": 0.4666666666666667,
"value": {
"__uuid__": "8764bb9b-4b08-4bc5-b9e5-93af39321c70"
}
},
{
"frame": 0.48333333333333334,
"value": {
"__uuid__": "f291785e-2685-4ba0-b38b-9607972ce6f0"
}
},
{
"frame": 0.5,
"value": {
"__uuid__": "a4e84eb9-b866-4cdc-8925-a5d29c65aea5"
}
}
]
}
}
},
"events": []
}

View File

@@ -0,0 +1,5 @@
{
"ver": "2.1.0",
"uuid": "43dbf141-be76-48c3-bdef-29233ccbe30d",
"subMetas": {}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 470 KiB

After

Width:  |  Height:  |  Size: 238 KiB

View File

@@ -1,18 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<map version="1.2" tiledversion="1.2.3" orientation="orthogonal" renderorder="right-down" width="128" height="128" tilewidth="16" tileheight="16" infinite="0" nextlayerid="3" nextobjectid="39">
<map version="1.2" tiledversion="1.2.3" orientation="orthogonal" renderorder="right-down" width="128" height="128" tilewidth="16" tileheight="16" infinite="0" nextlayerid="3" nextobjectid="87">
<tileset firstgid="1" source="tiles0.tsx"/>
<tileset firstgid="65" source="tiles1.tsx"/>
<tileset firstgid="129" source="tiles2.tsx"/>
<layer id="2" name="Ground" width="128" height="128">
<data encoding="base64" compression="zlib">
eJzt2q1u22AYhuEo1UhBtYFWKh/bmRRMRYNFPZPxwcKi7jznSInkWk7teG5ex88FLhQD570d5/PP1WazuQIAAAAAAAAAAAAAAAAAgAmu96r3g/N5bjn0fw5U3aGy/3bv0P+p8XDEdoX0f9//GP3Xp93/YaD/9QJa6f95/fvov26773671zeb7jmhupX+5+2fQH/9qztU9v8yQXUz/fXXX3/9a/ovgf7666+//vrrf1n9/4zc7tue/uvq/9Z4PfLZ7vnz38ZP/cv7T53p4Z7i7/+kv/7667/bl/sO/dff/77T3+9ff/3r+38dMGf/Nv1r+w917+v/0vh1okN/67/l9B/b/nFj/X8pxvYf236r/0UZ6t/X+Efj5kj7bv+uxxPpX9e/r/1NS7f7Z/S/a3zXfzH9Pzrvt/vPTf/l9p+yRjyV/ufvP+YY6M5yzr5D5uy/XUCLJfafa8YfmdJe//X0r6Z/9jGgv/7661/doqp/9fyrpV//Vc+/mv7Z9M+mfzb9s+mfTf9s+mfTP5v+2fTPpn82/bPpn03/bPpn0z+b/tn0z6Z/Nv2z6Z/N+9/Z9M+mfzb//9n0z6Z/Nv2z6Z9N/2z6Z9M/m/7Z0vtT3wEAAAAAAAAAAAAAAAA4v39IY4NC
eJzt3DFq3EAUgOFlTRoXJiEkkNQpAr5EyuDKVdKl8k1yh9wg94wMK1DEaqXVjvRGel/xgXFh7PnfSBqx+O5wONwBAAAAAAAAAAAAAAAAAMAM9yfRvwfreelo+78kFN0hsv/xpO3/q/E04LhD+v/ff4j++9Pt/zTS/76CVvov1/8c/fft9W//cHJubfrXhOhW+q/bPwP99Y/uENn//QzRzfSP7b+nGdBf/+gOW+xfE/1z9rf/c/cvMQP6b5f9r7/+efuXmAH9y69t+07x942W3vv666//Nvp/OtE/T/9u7+7X+uuvf1z/tyNK9u/SP7b/WPdz/f80flyp7e/5r57+U9s/Hzz/b8XU/lPbH/XflLH+5xo/Nh4G2vf79z1fSf+4/ufaP3T0uy/R/2Pji/7V9L903e/2L03/evvPeUa8lv7r958yA/21LNl3TMn+xwpa1Ni/1BpfMqe9/vvpf82MLPGz9d/GDCxF/9wzoL/+mftHr3+07Oe/6PWPpn9u+uemf27656Z/bvrnpn9u+uemf27656Z/bvrnpn9u+uemf276z7eHzwnpX0//dyPeDNB/H/3t/7r77/Fzovrnpv+6hu7tkf2PFbSouf/Pk/71vv1+9B7Wf9n+l+75+m/XlP5DZ65XY+e1yOv6Nf2jO9Tav+389Qa3ns/1j93/tyrxjkb/5fqXfp821L/WGcjef63936rtPZH+6/ZvZyDq/73oP96/5PP8pfPDEP3r2f+3zsGc/mveJ/SfZu4cfJ7Z/2/ju/7V9J+r6f9tbv/WknOQvT/xHQAAAAAAAAAAAAAAAID1/QPUuKyX
</data>
</layer>
<objectgroup id="1" name="PlayerStartingPos">
<object id="135" x="1090" y="833.667">
<object id="135" x="1010" y="1432">
<point/>
</object>
<object id="137" x="1215" y="830.5">
<object id="137" x="950" y="1432">
<point/>
</object>
</objectgroup>
@@ -20,149 +20,112 @@
<properties>
<property name="type" value="barrier_and_shelter"/>
</properties>
<object id="8" x="648.242" y="480.606">
<object id="54" x="656" y="1504" width="80" height="16">
<properties>
<property name="boundary_type" value="barrier"/>
</properties>
<polyline points="0,0 0,18.6667 1041.33,21.3333 1041.33,-1.33333"/>
</object>
<object id="9" x="650.667" y="1604.67">
<object id="55" x="735" y="1552" width="113.5" height="15.5">
<properties>
<property name="boundary_type" value="barrier"/>
</properties>
<polyline points="0,0 0,18.6667 1041.33,21.3333 1041.33,-1.33333"/>
</object>
<object id="10" x="634.485" y="505.455">
<object id="57" x="768" y="1472" width="32" height="16">
<properties>
<property name="boundary_type" value="barrier"/>
</properties>
<polyline points="0,0 4,1110 24,1110 24,-8"/>
</object>
<object id="11" x="1677.64" y="501.333">
<object id="58" x="1040" y="1536" width="80" height="16">
<properties>
<property name="boundary_type" value="barrier"/>
</properties>
<polyline points="0,0 4,1110 24,1110 24,-8"/>
</object>
<object id="14" x="688.667" y="464">
<object id="59" x="1040" y="1568" width="224" height="48">
<properties>
<property name="boundary_type" value="barrier"/>
</properties>
<polyline points="0,0 -0.666667,78 33.3333,78 32,-0.666667"/>
</object>
<object id="15" x="833.333" y="495.333">
<object id="60" x="1216" y="1344" width="224" height="16">
<properties>
<property name="boundary_type" value="barrier"/>
</properties>
<polyline points="0,0 -112,1.33333 -111.333,44.6667 -1.33333,44.6667"/>
</object>
<object id="17" x="832" y="574">
<object id="62" x="1040" y="1552" width="208" height="16">
<properties>
<property name="boundary_type" value="barrier"/>
</properties>
<polyline points="0,0 -67.3333,0 -67.3333,-76.6667 0.666667,-76"/>
</object>
<object id="18" x="865.333" y="606.667">
<object id="63" x="1040" y="1504" width="48" height="16">
<properties>
<property name="boundary_type" value="barrier"/>
</properties>
<polyline points="0,0 -210,-0.666667 -210,143.333 0,142.667"/>
</object>
<object id="19" x="754.667" y="1055.33">
<object id="64" x="1040" y="1520" width="64" height="16">
<properties>
<property name="boundary_type" value="barrier"/>
</properties>
<polyline points="-2,1.33333 -100,0.666667 -97.3333,-454 -9.33333,-451.333"/>
</object>
<object id="20" x="769.333" y="747.333">
<object id="65" x="1040" y="1488" width="32" height="16">
<properties>
<property name="boundary_type" value="barrier"/>
</properties>
<polyline points="0,0 -115.333,0.666667 -114.667,160.667 -2,162"/>
</object>
<object id="21" x="768" y="960.667">
<object id="66" x="1040" y="1472" width="16" height="16">
<properties>
<property name="boundary_type" value="barrier"/>
</properties>
<polyline points="0,0 -18,0.666667 -18.6667,95.3333 0,95.3333"/>
</object>
<object id="23" x="786" y="1058.67">
<object id="67" x="784" y="1456" width="256" height="16">
<properties>
<property name="boundary_type" value="barrier"/>
</properties>
<polyline points="0,0 0,-52.6667 -20,-52 -19.3333,-1.33333"/>
</object>
<object id="24" x="1118.67" y="749.333">
<object id="73" x="783.75" y="1567.5" width="96.25" height="15.5">
<properties>
<property name="boundary_type" value="barrier"/>
</properties>
<polyline points="0,0 -0.666667,-94 -254,-93.3333 -256.667,1.33333"/>
</object>
<object id="25" x="1168" y="975.333">
<object id="74" x="815.75" y="1583.75" width="96.25" height="15.5">
<properties>
<property name="boundary_type" value="barrier"/>
</properties>
<polyline points="0,0 0,16.6667 224.667,17.3333 225.333,-2"/>
</object>
<object id="28" x="1394.67" y="958">
<object id="79" x="640" y="1616" width="1056" height="16">
<properties>
<property name="boundary_type" value="barrier"/>
</properties>
<polyline points="0,0 -210.667,1.33333 -210.667,17.3333 -2,18"/>
</object>
<object id="29" x="1119" y="654.5">
<object id="80" x="1296" y="1600">
<properties>
<property name="boundary_type" value="barrier"/>
</properties>
<polyline points="0,0 0,63.5 272.5,65 273,-1"/>
<polyline points="0,0 -32.5,0 -32.25,-16.5 -16.5,-16.5"/>
</object>
<object id="30" x="1136.5" y="717.5">
<object id="82" x="1328" y="1616">
<properties>
<property name="boundary_type" value="barrier"/>
</properties>
<polyline points="0,0 -0.5,17 255,17.5 255,1.5"/>
<polyline points="0,0 -64.5,0 -64.0038,-15.75 -16.4734,-15.75"/>
</object>
<object id="31" x="1152" y="735.667">
<object id="83" x="640" y="480" width="1056" height="16">
<properties>
<property name="boundary_type" value="barrier"/>
</properties>
<polyline points="0,0 0,15 80.3333,15.3333 80.3333,-2"/>
</object>
<object id="32" x="1280.67" y="734.667">
<object id="84" x="640" y="480" width="16" height="1152">
<properties>
<property name="boundary_type" value="barrier"/>
</properties>
<polyline points="0,0 -0.666667,64.3333 48,65 48,0"/>
</object>
<object id="34" x="1329" y="783">
<object id="85" x="1680" y="480" width="16" height="1152">
<properties>
<property name="boundary_type" value="barrier"/>
</properties>
<polyline points="0,0 63.3333,0.333333 63,-48.3333 -0.666667,-48.3333"/>
</object>
<object id="35" x="1296.67" y="799">
<object id="86" x="1104" y="1408" width="96" height="16">
<properties>
<property name="boundary_type" value="barrier"/>
</properties>
<polyline points="0,0 -0.666667,31.3333 31.3333,31.6667 31.3333,-0.333333"/>
</object>
<object id="36" x="1280" y="848">
<properties>
<property name="boundary_type" value="barrier"/>
</properties>
<polyline points="0,0 0.333333,62 112,63 111.667,-1.33333"/>
</object>
<object id="37" x="1392.33" y="911.333">
<properties>
<property name="boundary_type" value="barrier"/>
</properties>
<polyline points="0,0 -81.3333,-0.666667 -81,45 -0.666667,46.3333"/>
</object>
<object id="38" x="1344.33" y="800.667">
<properties>
<property name="boundary_type" value="barrier"/>
</properties>
<polyline points="0,0 0,46.3333 47,46.3333 47,-1"/>
</object>
</objectgroup>
</map>

View File

@@ -9,28 +9,32 @@ message PlayerDownsync {
int32 virtualGridX = 2;
int32 virtualGridY = 3;
int32 dirX = 4;
int32 dirY = 5;
int32 speed = 6; // in terms of virtual grid units
int32 battleState = 7;
int32 joinIndex = 8;
double colliderRadius = 9;
bool removed = 10;
int32 score = 11;
int32 lastMoveGmtMillis = 12;
int32 framesToRecover = 13;
int32 hp = 14;
int32 maxHp = 15;
int32 characterState = 16;
int32 dirY = 5; // "dirX" and "dirY" determines character facing
int32 velX = 6;
int32 velY = 7; // "velX" and "velY" is used to record the accumulated effect by accelerations (including gravity)
int32 speed = 8; // this is the instantaneous scalar attribute of a character, different from but will be accounted in "velX" and "velY"
int32 battleState = 9;
int32 joinIndex = 10;
double colliderRadius = 11;
bool removed = 12;
int32 score = 13;
int32 lastMoveGmtMillis = 14;
int32 framesToRecover = 15;
int32 hp = 16;
int32 maxHp = 17;
int32 characterState = 18;
bool inAir = 19; // by design a standalone field only inferred by the collision result of "applyInputFrameDownsyncDynamicsOnSingleRenderFrame" instead of "characterState", because we need check the transition for "characterState" from this field, i.e. "inAir (prev -> curr)"
string name = 17;
string displayName = 18;
string avatar = 19;
string name = 20;
string displayName = 21;
string avatar = 22;
}
message InputFrameDecoded {
int32 dx = 1;
int32 dy = 2;
int32 btnALevel = 3;
int32 btnBLevel = 4;
}
message InputFrameUpsync {
@@ -68,6 +72,12 @@ message WsResp {
BattleColliderInfo bciFrame = 6;
}
message InputsBufferSnapshot {
int32 refRenderFrameId = 1;
uint64 unconfirmedMask = 2;
repeated InputFrameDownsync toSendInputFrameDownsyncs = 3;
}
message MeleeBullet {
// Jargon reference https://www.thegamer.com/fighting-games-frame-data-explained/
// ALL lengths are in world coordinate
@@ -127,6 +137,12 @@ message BattleColliderInfo {
int32 renderCacheSize = 26;
map<int32, MeleeBullet> meleeSkillConfig = 27; // skillId -> skill
double snapIntoPlatformOverlap = 28;
double snapIntoPlatformThreshold = 29;
int32 jumpingInitVelY = 30;
int32 gravityX = 31;
int32 gravityY = 32;
}
message RoomDownsyncFrame {

View File

@@ -33,14 +33,14 @@
"_active": true,
"_components": [
{
"__id__": 20
"__id__": 23
},
{
"__id__": 21
"__id__": 24
}
],
"_prefab": {
"__id__": 22
"__id__": 25
},
"_opacity": 255,
"_color": {
@@ -65,7 +65,7 @@
"ctor": "Float64Array",
"array": [
0,
3,
0,
0,
0,
0,
@@ -97,7 +97,7 @@
"__id__": 1
},
"_children": [],
"_active": true,
"_active": false,
"_components": [
{
"__id__": 3
@@ -116,8 +116,8 @@
},
"_contentSize": {
"__type__": "cc.Size",
"width": 46.68,
"height": 27.72
"width": 28.01,
"height": 15.12
},
"_anchorPoint": {
"__type__": "cc.Vec2",
@@ -128,8 +128,8 @@
"__type__": "TypedArray",
"ctor": "Float64Array",
"array": [
-5,
50,
0,
0,
0,
0,
0,
@@ -169,8 +169,8 @@
"_useOriginalSize": false,
"_string": "(0, 0)",
"_N$string": "(0, 0)",
"_fontSize": 20,
"_lineHeight": 22,
"_fontSize": 12,
"_lineHeight": 12,
"_enableWrapText": true,
"_N$file": null,
"_isSystemFontUsed": true,
@@ -277,7 +277,7 @@
"__uuid__": "472df5d3-35e7-4184-9e6c-7f41bee65ee3"
},
"_texture": null,
"_stopped": false,
"_stopped": true,
"playOnLoad": true,
"autoRemoveOnFinish": false,
"totalParticles": 200,
@@ -395,8 +395,8 @@
},
"_contentSize": {
"__type__": "cc.Size",
"width": 76,
"height": 84
"width": 24,
"height": 24
},
"_anchorPoint": {
"__type__": "cc.Vec2",
@@ -408,7 +408,7 @@
"ctor": "Float64Array",
"array": [
3,
182,
60,
0,
0,
0,
@@ -451,7 +451,7 @@
"__uuid__": "a2170e4c-df31-41ef-be73-f4f605e75821"
},
"_type": 0,
"_sizeMode": 1,
"_sizeMode": 0,
"_fillType": 0,
"_fillCenter": {
"__type__": "cc.Vec2",
@@ -490,12 +490,15 @@
},
{
"__id__": 15
},
{
"__id__": 18
}
],
"_active": true,
"_components": [],
"_prefab": {
"__id__": 19
"__id__": 22
},
"_opacity": 255,
"_color": {
@@ -584,7 +587,7 @@
"ctor": "Float64Array",
"array": [
0,
0,
-24,
0,
0,
0,
@@ -671,13 +674,128 @@
"_components": [
{
"__id__": 16
},
{
"__id__": 17
}
],
"_prefab": {
"__id__": 18
"__id__": 17
},
"_opacity": 255,
"_color": {
"__type__": "cc.Color",
"r": 255,
"g": 255,
"b": 255,
"a": 255
},
"_contentSize": {
"__type__": "cc.Size",
"width": 0,
"height": 0
},
"_anchorPoint": {
"__type__": "cc.Vec2",
"x": 0.5,
"y": 0.5
},
"_trs": {
"__type__": "TypedArray",
"ctor": "Float64Array",
"array": [
0,
-24,
0,
0,
0,
0,
1,
1,
1,
1
]
},
"_eulerAngles": {
"__type__": "cc.Vec3",
"x": 0,
"y": 0,
"z": 0
},
"_skewX": 0,
"_skewY": 0,
"_is3DNode": false,
"_groupIndex": 0,
"groupIndex": 0,
"_id": ""
},
{
"__type__": "dragonBones.ArmatureDisplay",
"_name": "",
"_objFlags": 0,
"node": {
"__id__": 15
},
"_enabled": true,
"_materials": [
{
"__uuid__": "eca5d2f2-8ef6-41c2-bbe6-f9c79d09c432"
}
],
"_armatureName": "SoldierFireGhost",
"_animationName": "Idle1",
"_preCacheMode": 0,
"_cacheMode": 0,
"playTimes": -1,
"premultipliedAlpha": false,
"_armatureKey": "36230012-8df3-4e85-afad-76ec47d0e4d7#4a9187d5-a9ad-4464-a03c-d2f3cc277051",
"_accTime": 0,
"_playCount": 0,
"_frameCache": null,
"_curFrame": null,
"_playing": false,
"_armatureCache": null,
"_N$dragonAsset": {
"__uuid__": "36230012-8df3-4e85-afad-76ec47d0e4d7"
},
"_N$dragonAtlasAsset": {
"__uuid__": "4a9187d5-a9ad-4464-a03c-d2f3cc277051"
},
"_N$_defaultArmatureIndex": 0,
"_N$_animationIndex": 8,
"_N$_defaultCacheMode": 0,
"_N$timeScale": 1,
"_N$debugBones": false,
"_N$enableBatch": false,
"_id": ""
},
{
"__type__": "cc.PrefabInfo",
"root": {
"__id__": 1
},
"asset": {
"__uuid__": "59bff7a2-23e1-4d69-bce7-afb37eae196a"
},
"fileId": "3b2LJFABVL7ozO2U81FC4U",
"sync": false
},
{
"__type__": "cc.Node",
"_name": "SoldierFireGhostFrameAnim",
"_objFlags": 0,
"_parent": {
"__id__": 11
},
"_children": [],
"_active": false,
"_components": [
{
"__id__": 19
},
{
"__id__": 20
}
],
"_prefab": {
"__id__": 21
},
"_opacity": 255,
"_color": {
@@ -731,7 +849,7 @@
"_name": "",
"_objFlags": 0,
"node": {
"__id__": 15
"__id__": 18
},
"_enabled": true,
"_defaultClip": null,
@@ -745,6 +863,15 @@
{
"__uuid__": "c738236a-0702-45f8-aa38-99457b051997"
},
{
"__uuid__": "c69bcceb-d7d1-4e33-9623-e2a374a0a6b6"
},
{
"__uuid__": "43dbf141-be76-48c3-bdef-29233ccbe30d"
},
{
"__uuid__": "c738236a-0702-45f8-aa38-99457b051997"
},
{
"__uuid__": "c69bcceb-d7d1-4e33-9623-e2a374a0a6b6"
}
@@ -757,7 +884,7 @@
"_name": "",
"_objFlags": 0,
"node": {
"__id__": 15
"__id__": 18
},
"_enabled": true,
"_materials": [

View File

@@ -1,151 +0,0 @@
[
{
"__type__": "cc.Prefab",
"_name": "",
"_objFlags": 0,
"_native": "",
"data": {
"__id__": 1
},
"optimizationPolicy": 0,
"asyncLoadAssets": false,
"readonly": false
},
{
"__type__": "cc.Node",
"_name": "SoldierFireGhost",
"_objFlags": 0,
"_parent": null,
"_children": [],
"_active": true,
"_components": [
{
"__id__": 2
},
{
"__id__": 3
}
],
"_prefab": {
"__id__": 4
},
"_opacity": 255,
"_color": {
"__type__": "cc.Color",
"r": 255,
"g": 255,
"b": 255,
"a": 255
},
"_contentSize": {
"__type__": "cc.Size",
"width": 1425,
"height": 1024
},
"_anchorPoint": {
"__type__": "cc.Vec2",
"x": 0.5,
"y": 0.5
},
"_trs": {
"__type__": "TypedArray",
"ctor": "Float64Array",
"array": [
0,
0,
0,
0,
0,
0,
1,
1,
1,
1
]
},
"_eulerAngles": {
"__type__": "cc.Vec3",
"x": 0,
"y": 0,
"z": 0
},
"_skewX": 0,
"_skewY": 0,
"_is3DNode": false,
"_groupIndex": 0,
"groupIndex": 0,
"_id": ""
},
{
"__type__": "cc.Animation",
"_name": "",
"_objFlags": 0,
"node": {
"__id__": 1
},
"_enabled": true,
"_defaultClip": null,
"_clips": [
{
"__uuid__": "252b321f-81f4-485c-85bd-ea44d298cb76"
},
null,
null,
null,
{
"__uuid__": "c738236a-0702-45f8-aa38-99457b051997"
},
{
"__uuid__": "f51bb583-0010-48f3-a6a1-451a78ac2d65"
},
{
"__uuid__": "c69bcceb-d7d1-4e33-9623-e2a374a0a6b6"
}
],
"playOnLoad": false,
"_id": ""
},
{
"__type__": "cc.Sprite",
"_name": "",
"_objFlags": 0,
"node": {
"__id__": 1
},
"_enabled": true,
"_materials": [
{
"__uuid__": "eca5d2f2-8ef6-41c2-bbe6-f9c79d09c432"
}
],
"_srcBlendFactor": 770,
"_dstBlendFactor": 771,
"_spriteFrame": null,
"_type": 0,
"_sizeMode": 1,
"_fillType": 0,
"_fillCenter": {
"__type__": "cc.Vec2",
"x": 0,
"y": 0
},
"_fillStart": 0,
"_fillRange": 0,
"_isTrimmedMode": true,
"_atlas": {
"__uuid__": "145769c8-a259-42bc-8cce-6e035f493c70"
},
"_id": ""
},
{
"__type__": "cc.PrefabInfo",
"root": {
"__id__": 1
},
"asset": {
"__id__": 0
},
"fileId": "44k8wsxglPsJSrMCX58Yve",
"sync": false
}
]

View File

@@ -1,8 +0,0 @@
{
"ver": "1.2.5",
"uuid": "e3fc2487-17d1-4ff9-ae1f-38e974509077",
"optimizationPolicy": "AUTO",
"asyncLoadAssets": false,
"readonly": false,
"subMetas": {}
}

View File

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

View File

@@ -172,8 +172,8 @@
},
"_contentSize": {
"__type__": "cc.Size",
"width": 3200,
"height": 3200
"width": 2048,
"height": 2048
},
"_anchorPoint": {
"__type__": "cc.Vec2",
@@ -191,8 +191,8 @@
0,
0,
1,
2,
2,
1.5,
1.5,
1
]
},
@@ -454,7 +454,7 @@
"array": [
0,
0,
216.50635094610968,
216.67520680312998,
0,
0,
0,

View File

@@ -5,8 +5,33 @@ window.ATK_CHARACTER_STATE = {
Walking: [1, "Walking"],
Atk1: [2, "Atk1"],
Atked1: [3, "Atked1"],
InAirIdle1: [4, "InAirIdle1"],
InAirAtk1: [5, "Atk1"],
InAirAtked1: [6, "Atked1"],
};
window.toInAirConjugate = function(foo) {
switch (foo) {
case window.ATK_CHARACTER_STATE.Idle1[0]:
case window.ATK_CHARACTER_STATE.Walking[0]:
return window.ATK_CHARACTER_STATE.InAirIdle1[0];
case window.ATK_CHARACTER_STATE.Atk1[0]:
return window.ATK_CHARACTER_STATE.InAirAtk1[0];
case window.ATK_CHARACTER_STATE.Atked1[0]:
return window.ATK_CHARACTER_STATE.InAirAtked1[0];
case window.ATK_CHARACTER_STATE.InAirIdle1[0]:
return window.ATK_CHARACTER_STATE.Idle1[0];
case window.ATK_CHARACTER_STATE.InAirAtk1[0]:
return window.ATK_CHARACTER_STATE.Atk1[0];
case window.ATK_CHARACTER_STATE.InAirAtked1[0]:
return window.ATK_CHARACTER_STATE.Atked1[0];
default:
console.warn(`Invalid characterState ${foo} received, no in air conjugate is available!`);
return null;
}
}
window.ATK_CHARACTER_STATE_ARR = [];
for (let k in window.ATK_CHARACTER_STATE) {
window.ATK_CHARACTER_STATE_ARR.push(window.ATK_CHARACTER_STATE[k]);
@@ -15,6 +40,12 @@ for (let k in window.ATK_CHARACTER_STATE) {
window.ATK_CHARACTER_STATE_INTERRUPT_WAIVE_SET = new Set();
window.ATK_CHARACTER_STATE_INTERRUPT_WAIVE_SET.add(window.ATK_CHARACTER_STATE.Idle1[0]);
window.ATK_CHARACTER_STATE_INTERRUPT_WAIVE_SET.add(window.ATK_CHARACTER_STATE.Walking[0]);
window.ATK_CHARACTER_STATE_INTERRUPT_WAIVE_SET.add(window.ATK_CHARACTER_STATE.InAirIdle1[0]);
window.ATK_CHARACTER_STATE_IN_AIR_SET = new Set();
window.ATK_CHARACTER_STATE_IN_AIR_SET.add(window.ATK_CHARACTER_STATE.InAirIdle1[0]);
window.ATK_CHARACTER_STATE_IN_AIR_SET.add(window.ATK_CHARACTER_STATE.InAirAtk1[0]);
window.ATK_CHARACTER_STATE_IN_AIR_SET.add(window.ATK_CHARACTER_STATE.InAirAtked1[0]);
/*
Kindly note that the use of dragonBones anim is an informed choice for the feasibility of "gotoAndPlayByFrame", which is a required feature by "Map.rollbackAndChase". You might find that "cc.Animation" -- the traditional frame anim -- can also suffice this requirement, yet if we want to develop 3D frontend in the future, working with skeletal anim will make a smoother transition.
@@ -37,6 +68,7 @@ cc.Class({
this.hp = 100;
this.maxHp = 100;
this.framesToRecover = 0;
this.inAir = true;
},
setSpecies(speciesName) {
@@ -49,8 +81,7 @@ cc.Class({
this.animComp = this.effAnimNode.getComponent(dragonBones.ArmatureDisplay);
if (!this.animComp) {
this.animComp = this.effAnimNode.getComponent(cc.Animation);
this.effAnimNode.anchorY = 0.0; // Otherwise the frame anim will show with an incorrect y-offset even if the collider boundaries are all correct!
}
}
this.effAnimNode.active = true;
},
@@ -96,7 +127,7 @@ cc.Class({
_interruptPlayingAnimAndPlayNewAnimDragonBones(rdfPlayer, prevRdfPlayer, newCharacterState, newAnimName, underlyingAnimationCtrl, playingAnimName) {
if (window.ATK_CHARACTER_STATE_INTERRUPT_WAIVE_SET.has(newCharacterState)) {
// No "framesToRecover"
//console.warn(`#DragonBones JoinIndex=${rdfPlayer.joinIndex}, ${playingAnimName} -> ${newAnimName}`);
// console.warn(`#DragonBones JoinIndex=${rdfPlayer.joinIndex}, ${playingAnimName} -> ${newAnimName}`);
underlyingAnimationCtrl.gotoAndPlayByFrame(newAnimName, 0, -1);
} else {
const animationData = underlyingAnimationCtrl._animations[newAnimName];
@@ -112,7 +143,7 @@ cc.Class({
_interruptPlayingAnimAndPlayNewAnimFrameAnim(rdfPlayer, prevRdfPlayer, newCharacterState, newAnimName, playingAnimName) {
if (window.ATK_CHARACTER_STATE_INTERRUPT_WAIVE_SET.has(newCharacterState)) {
// No "framesToRecover"
//console.warn(`#DragonBones JoinIndex=${rdfPlayer.joinIndex}, ${playingAnimName} -> ${newAnimName}`);
//console.warn(`#FrameAnim JoinIndex=${rdfPlayer.joinIndex}, ${playingAnimName} -> ${newAnimName}`);
this.animComp.play(newAnimName, 0);
return;
}

View File

@@ -402,6 +402,7 @@ cc.Class({
console.log(`Received parsedBattleColliderInfo via ws`);
// TODO: Upon reconnection, the backend might have already been sending down data that'd trigger "onRoomDownsyncFrame & onInputFrameDownsyncBatch", but frontend could reject those data due to "battleState != PlayerBattleState.ACTIVE".
Object.assign(self, parsedBattleColliderInfo);
self.gravityX = parsedBattleColliderInfo.gravityX; // to avoid integer default value 0 accidentally becoming null in "Object.assign(...)"
self.tooFastDtIntervalMillis = 0.5 * self.rollbackEstimatedDtMillis;
const tiledMapIns = self.node.getComponent(cc.TiledMap);
@@ -426,6 +427,16 @@ cc.Class({
mapNode.removeAllChildren();
self._resetCurrentMatch();
if (self.showCriticalCoordinateLabels) {
const drawer = new cc.Node();
drawer.setPosition(cc.v2(0, 0))
safelyAddChild(self.node, drawer);
setLocalZOrder(drawer, 999);
const g = drawer.addComponent(cc.Graphics);
g.lineWidth = 2;
self.g = g;
}
tiledMapIns.tmxAsset = tmxAsset;
const newMapSize = tiledMapIns.getMapSize();
const newTileSize = tiledMapIns.getTileSize();
@@ -442,14 +453,19 @@ cc.Class({
}
let barrierIdCounter = 0;
const boundaryObjs = tileCollisionManager.extractBoundaryObjects(self.node);
for (let boundaryObj of boundaryObjs.barriers) {
const x0 = boundaryObj.anchor.x,
y0 = boundaryObj.anchor.y;
const newBarrierCollider = self.collisionSys.createPolygon(x0, y0, Array.from(boundaryObj, p => {
const refBoundaryObjs = tileCollisionManager.extractBoundaryObjects(self.node).barriers;
const boundaryObjs = parsedBattleColliderInfo.strToPolygon2DListMap;
for (let k = 0; k < boundaryObjs["Barrier"].eles.length; k++) {
let boundaryObj = boundaryObjs["Barrier"].eles[k];
const refBoundaryObj = refBoundaryObjs[k];
// boundaryObj = refBoundaryObj;
const [x0, y0] = [boundaryObj.anchor.x, boundaryObj.anchor.y];
const newBarrierCollider = self.collisionSys.createPolygon(x0, y0, Array.from(boundaryObj.points, p => {
return [p.x, p.y];
}));
newBarrierCollider.data = {
hardPushback: true
};
if (self.showCriticalCoordinateLabels) {
for (let i = 0; i < boundaryObj.length; ++i) {
@@ -762,18 +778,19 @@ cc.Class({
if (1 == joinIndex) {
playerScriptIns.setSpecies("SoldierWaterGhost");
} else if (2 == joinIndex) {
playerScriptIns.setSpecies("SoldierFireGhost");
playerScriptIns.setSpecies("SoldierFireGhostFrameAnim");
}
const [wx, wy] = self.virtualGridToWorldPos(vx, vy);
newPlayerNode.setPosition(wx, wy);
playerScriptIns.mapNode = self.node;
const colliderWidth = playerDownsyncInfo.colliderRadius * 2,
colliderHeight = playerDownsyncInfo.colliderRadius * 3;
const [x0, y0] = self.virtualGridToPolygonColliderAnchorPos(vx, vy, colliderWidth, colliderHeight),
pts = [[0, 0], [colliderWidth, 0], [colliderWidth, colliderHeight], [0, colliderHeight]];
colliderHeight = playerDownsyncInfo.colliderRadius * 4;
const cpos = self.virtualGridToPolygonColliderTLPos(vx, vy, colliderWidth * 0.5, colliderHeight * 0.5); // the top-left corner is kept having integer coords
const pts = [[0, 0], [colliderWidth, 0], [colliderWidth, -colliderHeight - self.snapIntoPlatformOverlap], [0, -colliderHeight - self.snapIntoPlatformOverlap]];
const newPlayerCollider = self.collisionSys.createPolygon(x0, y0, pts);
// [WARNING] The animNode "anchor & offset" are tuned to fit in this collider by "ControlledCharacter prefab & AttackingCharacter.js"!
const newPlayerCollider = self.collisionSys.createPolygon(cpos[0], cpos[1], pts);
const collisionPlayerIndex = self.collisionPlayerIndexPrefix + joinIndex;
newPlayerCollider.data = playerDownsyncInfo;
self.collisionSysMap.set(collisionPlayerIndex, newPlayerCollider);
@@ -833,6 +850,7 @@ cc.Class({
*/
// [WARNING] Don't try to get "prevRdf(i.e. renderFrameId == latest-1)" by "self.recentRenderCache.getByFrameId(...)" here, as the cache might have been updated by asynchronous "onRoomDownsyncFrame(...)" calls!
self.applyRoomDownsyncFrameDynamics(rdf, prevRdf);
self.showDebugBoundaries(rdf);
++self.renderFrameId; // [WARNING] It's important to increment the renderFrameId AFTER all the operations above!!!
self.lastRenderFrameIdTriggeredAt = performance.now();
let t3 = performance.now();
@@ -961,13 +979,13 @@ cc.Class({
applyRoomDownsyncFrameDynamics(rdf, prevRdf) {
const self = this;
for (let [playerId, playerRichInfo] of self.playerRichInfoDict.entries()) {
const immediatePlayerInfo = rdf.players[playerId];
const currPlayerDownsync = rdf.players[playerId];
const prevRdfPlayer = (null == prevRdf ? null : prevRdf.players[playerId]);
const [wx, wy] = self.virtualGridToWorldPos(immediatePlayerInfo.virtualGridX, immediatePlayerInfo.virtualGridY);
const [wx, wy] = self.virtualGridToWorldPos(currPlayerDownsync.virtualGridX, currPlayerDownsync.virtualGridY);
//const justJiggling = (self.jigglingEps1D >= Math.abs(wx - playerRichInfo.node.x) && self.jigglingEps1D >= Math.abs(wy - playerRichInfo.node.y));
playerRichInfo.node.setPosition(wx, wy);
playerRichInfo.scriptIns.updateSpeed(immediatePlayerInfo.speed);
playerRichInfo.scriptIns.updateCharacterAnim(immediatePlayerInfo, prevRdfPlayer, false);
playerRichInfo.scriptIns.updateSpeed(currPlayerDownsync.speed);
playerRichInfo.scriptIns.updateCharacterAnim(currPlayerDownsync, prevRdfPlayer, false);
}
// Update countdown
@@ -977,6 +995,73 @@ cc.Class({
}
},
showDebugBoundaries(rdf) {
const self = this;
if (self.showCriticalCoordinateLabels) {
let g = self.g;
g.clear();
for (let k in self.collisionSys._bvh._bodies) {
const body = self.collisionSys._bvh._bodies[k];
if (!body._polygon) continue;
if (null != body.data && null != body.data.joinIndex) {
// character
if (1 == body.data.joinIndex) {
g.strokeColor = cc.Color.BLUE;
} else {
g.strokeColor = cc.Color.RED;
}
} else {
// barrier
g.strokeColor = cc.Color.WHITE;
}
g.moveTo(body.x, body.y);
const cnt = body._coords.length;
for (let j = 0; j < cnt; j += 2) {
const x = body._coords[j],
y = body._coords[j + 1];
g.lineTo(x, y);
}
g.lineTo(body.x, body.y);
g.stroke();
}
// For convenience of recovery upon reconnection, active bullets are always created & immediately removed from "collisionSys" within "applyInputFrameDownsyncDynamicsOnSingleRenderFrame"
for (let k in rdf.meleeBullets) {
const meleeBullet = rdf.meleeBullets[k];
if (
meleeBullet.originatedRenderFrameId + meleeBullet.startupFrames <= rdf.id
&&
meleeBullet.originatedRenderFrameId + meleeBullet.startupFrames + meleeBullet.activeFrames > rdf.id
) {
const offender = rdf.players[meleeBullet.offenderPlayerId];
if (1 == offender.joinIndex) {
g.strokeColor = cc.Color.BLUE;
} else {
g.strokeColor = cc.Color.RED;
}
let xfac = 1; // By now, straight Punch offset doesn't respect "y-axis"
if (0 > offender.dirX) {
xfac = -1;
}
const [offenderWx, offenderWy] = self.virtualGridToWorldPos(offender.virtualGridX, offender.virtualGridY);
const bulletWx = offenderWx + xfac * meleeBullet.hitboxOffset;
const bulletWy = offenderWy;
const bulletCpos = self.worldToPolygonColliderTLPos(bulletWx, bulletWy, meleeBullet.hitboxSize.x * 0.5, meleeBullet.hitboxSize.y * 0.5);
const pts = [[0, 0], [meleeBullet.hitboxSize.x, 0], [meleeBullet.hitboxSize.x, -meleeBullet.hitboxSize.y], [0, -meleeBullet.hitboxSize.y]];
g.moveTo(bulletCpos[0], bulletCpos[1]);
for (let j = 0; j < pts.length; j += 1) {
g.lineTo(pts[j][0] + bulletCpos[0], pts[j][1] + bulletCpos[1]);
}
g.lineTo(bulletCpos[0], bulletCpos[1]);
g.stroke();
}
}
}
},
getCachedInputFrameDownsyncWithPrediction(inputFrameId) {
const self = this;
const inputFrameDownsync = self.recentInputCache.getByFrameId(inputFrameId);
@@ -1003,7 +1088,10 @@ cc.Class({
virtualGridY: currPlayerDownsync.virtualGridY,
dirX: currPlayerDownsync.dirX,
dirY: currPlayerDownsync.dirY,
velX: currPlayerDownsync.velX,
velY: currPlayerDownsync.velY,
characterState: currPlayerDownsync.characterState,
inAir: true,
speed: currPlayerDownsync.speed,
battleState: currPlayerDownsync.battleState,
score: currPlayerDownsync.score,
@@ -1016,27 +1104,104 @@ cc.Class({
}
const nextRenderFrameMeleeBullets = [];
const effPushbacks = new Array(self.playerRichInfoArr.length);
const hardPushbackNorms = new Array(self.playerRichInfoArr.length);
const bulletPushbacks = new Array(self.playerRichInfoArr.length); // Guaranteed determinism regardless of traversal order
const effPushbacks = new Array(self.playerRichInfoArr.length); // Guaranteed determinism regardless of traversal order
// 1. Process player inputs
/*
[WARNING] Player input alone WOULD NOT take "characterState" into any "ATK_CHARACTER_STATE_IN_AIR_SET", only after the calculation of "effPushbacks" do we know exactly whether or not a player is "inAir", the finalize the transition of "thatPlayerInNextFrame.characterState".
*/
if (null != delayedInputFrame) {
const delayedInputFrameForPrevRenderFrame = self.getCachedInputFrameDownsyncWithPrediction(self._convertToInputFrameId(currRenderFrame.id - 1, self.inputDelayFrames));
const inputList = delayedInputFrame.inputList;
for (let j in self.playerRichInfoArr) {
const joinIndex = parseInt(j) + 1;
const playerRichInfo = self.playerRichInfoArr[j];
const playerId = playerRichInfo.id;
const currPlayerDownsync = currRenderFrame.players[playerId];
const thatPlayerInNextFrame = nextRenderFramePlayers[playerId];
if (0 < thatPlayerInNextFrame.framesToRecover) {
// No need to process inputs for this player, but there might be bullet pushbacks on this player
continue;
}
// Reset playerCollider position from the "virtual grid position"
const decodedInput = self.ctrl.decodeInput(inputList[joinIndex - 1]);
const prevDecodedInput = (null == delayedInputFrameForPrevRenderFrame ? null : self.ctrl.decodeInput(delayedInputFrameForPrevRenderFrame.inputList[joinIndex - 1]));
const prevBtnALevel = (null == prevDecodedInput ? 0 : prevDecodedInput.btnALevel);
const prevBtnBLevel = (null == prevDecodedInput ? 0 : prevDecodedInput.btnBLevel);
if (1 == decodedInput.btnBLevel && 0 == prevBtnBLevel) {
const characStateAlreadyInAir = window.ATK_CHARACTER_STATE_IN_AIR_SET.has(thatPlayerInNextFrame.characterState);
const characStateIsInterruptWaivable = window.ATK_CHARACTER_STATE_INTERRUPT_WAIVE_SET.has(thatPlayerInNextFrame.characterState);
if (
!characStateAlreadyInAir
&&
characStateIsInterruptWaivable
) {
thatPlayerInNextFrame.velY = self.jumpingInitVelY;
if (1 == joinIndex) {
console.log(`playerId=${playerId}, joinIndex=${joinIndex} jumped at {renderFrame.id: ${currRenderFrame.id}, virtualX: ${currPlayerDownsync.virtualGridX}, virtualY: ${currPlayerDownsync.virtualGridY}, nextVelX: ${thatPlayerInNextFrame.velX}, nextVelY: ${thatPlayerInNextFrame.velY}}, delayedInputFrame.id=${delayedInputFrame.inputFrameId}`);
}
}
}
if (1 == decodedInput.btnALevel && 0 == prevBtnALevel) {
const punchSkillId = 1;
const punch = window.pb.protos.MeleeBullet.create(self.meleeSkillConfig[punchSkillId]);
thatPlayerInNextFrame.framesToRecover = punch.recoveryFrames;
punch.battleLocalId = self.bulletBattleLocalIdCounter++;
punch.offenderJoinIndex = joinIndex;
punch.offenderPlayerId = playerId;
punch.originatedRenderFrameId = currRenderFrame.id;
nextRenderFrameMeleeBullets.push(punch);
// console.log(`playerId=${playerId}, joinIndex=${joinIndex} triggered a rising-edge of btnA at renderFrame.id=${currRenderFrame.id}, delayedInputFrame.id=${delayedInputFrame.inputFrameId}`);
thatPlayerInNextFrame.characterState = window.ATK_CHARACTER_STATE.Atk1[0];
if (false == currPlayerDownsync.inAir) {
thatPlayerInNextFrame.velX = 0; // prohibits simultaneous movement with Atk1 on the ground
}
} else if (0 == decodedInput.btnALevel && 1 == prevBtnALevel) {
// console.log(`playerId=${playerId} triggered a falling-edge of btnA at renderFrame.id=${currRenderFrame.id}, delayedInputFrame.id=${delayedInputFrame.inputFrameId}`);
} else {
// No bullet trigger, process joystick movement inputs.
if (0 != decodedInput.dx || 0 != decodedInput.dy) {
// Update directions and thus would eventually update moving animation accordingly
thatPlayerInNextFrame.dirX = decodedInput.dx;
thatPlayerInNextFrame.dirY = decodedInput.dy;
thatPlayerInNextFrame.velX = decodedInput.dx * currPlayerDownsync.speed;
thatPlayerInNextFrame.characterState = window.ATK_CHARACTER_STATE.Walking[0];
} else {
thatPlayerInNextFrame.characterState = window.ATK_CHARACTER_STATE.Idle1[0];
thatPlayerInNextFrame.velX = 0;
}
}
}
}
// 2. Process player movement
for (let j in self.playerRichInfoArr) {
const joinIndex = parseInt(j) + 1;
bulletPushbacks[joinIndex - 1] = [0.0, 0.0];
effPushbacks[joinIndex - 1] = [0.0, 0.0];
const playerRichInfo = self.playerRichInfoArr[j];
const playerId = playerRichInfo.id;
const collisionPlayerIndex = self.collisionPlayerIndexPrefix + joinIndex;
const playerCollider = collisionSysMap.get(collisionPlayerIndex);
const currPlayerDownsync = currRenderFrame.players[playerId];
const thatPlayerInNextFrame = nextRenderFramePlayers[playerId];
// Reset playerCollider position from the "virtual grid position"
const [newVx, newVy] = [currPlayerDownsync.virtualGridX + currPlayerDownsync.velX, currPlayerDownsync.virtualGridY + currPlayerDownsync.velY];
const colliderWidth = self.playerRichInfoArr[joinIndex - 1].colliderRadius * 2,
colliderHeight = self.playerRichInfoArr[joinIndex - 1].colliderRadius * 4;
const newCpos = self.virtualGridToPolygonColliderTLPos(newVx, newVy, colliderWidth * 0.5, colliderHeight * 0.5);
playerCollider.x = newCpos[0];
playerCollider.y = newCpos[1];
const newVx = currPlayerDownsync.virtualGridX;
const newVy = currPlayerDownsync.virtualGridY;
[playerCollider.x, playerCollider.y] = self.virtualGridToPolygonColliderAnchorPos(newVx, newVy, self.playerRichInfoArr[joinIndex - 1].colliderRadius, self.playerRichInfoArr[joinIndex - 1].colliderRadius);
if (currPlayerDownsync.inAir) {
thatPlayerInNextFrame.velX += self.gravityX;
thatPlayerInNextFrame.velY += self.gravityY;
}
}
// Check bullet-anything collisions first, because the pushbacks caused by bullets might later be reverted by player-barrier collision
// 3. Add bullet colliders into collision system
const bulletColliders = new Map(); // Will all be removed at the end of `applyInputFrameDownsyncDynamicsOnSingleRenderFrame` due to the need for being rollback-compatible
const removedBulletsAtCurrFrame = new Set();
for (let k in currRenderFrame.meleeBullets) {
@@ -1058,38 +1223,131 @@ cc.Class({
const [offenderWx, offenderWy] = self.virtualGridToWorldPos(offender.virtualGridX, offender.virtualGridY);
const bulletWx = offenderWx + xfac * meleeBullet.hitboxOffset;
const bulletWy = offenderWy;
const [bulletCx, bulletCy] = self.worldToPolygonColliderAnchorPos(bulletWx, bulletWy, meleeBullet.hitboxSize.x * 0.5, meleeBullet.hitboxSize.y * 0.5),
pts = [[0, 0], [meleeBullet.hitboxSize.x, 0], [meleeBullet.hitboxSize.x, meleeBullet.hitboxSize.y], [0, meleeBullet.hitboxSize.y]];
const newBulletCollider = collisionSys.createPolygon(bulletCx, bulletCy, pts);
const bulletCpos = self.worldToPolygonColliderTLPos(bulletWx, bulletWy, meleeBullet.hitboxSize.x * 0.5, meleeBullet.hitboxSize.y * 0.5),
pts = [[0, 0], [meleeBullet.hitboxSize.x, 0], [meleeBullet.hitboxSize.x, -meleeBullet.hitboxSize.y], [0, -meleeBullet.hitboxSize.y]];
const newBulletCollider = collisionSys.createPolygon(bulletCpos[0], bulletCpos[1], pts);
newBulletCollider.data = meleeBullet;
collisionSysMap.set(collisionBulletIndex, newBulletCollider);
bulletColliders.set(collisionBulletIndex, newBulletCollider);
// console.log(`A meleeBullet is added to collisionSys at currRenderFrame.id=${currRenderFrame.id} as start-up frames ended and active frame is not yet ended: ${JSON.stringify(meleeBullet)}`);
}
}
// 4. Invoke collision system stepping
collisionSys.update();
const result1 = collisionSys.createResult(); // Can I reuse a "self.collisionSysResult" object throughout the whole battle?
const result = collisionSys.createResult(); // Can I reuse a "self.collisionSysResult" object throughout the whole battle?
// 5. Calc pushbacks for each player (after its movement) w/o bullets
for (let j in self.playerRichInfoArr) {
const joinIndex = parseInt(j) + 1;
const playerRichInfo = self.playerRichInfoArr[j];
const playerId = playerRichInfo.id;
const collisionPlayerIndex = self.collisionPlayerIndexPrefix + joinIndex;
const playerCollider = collisionSysMap.get(collisionPlayerIndex);
const potentials = playerCollider.potentials();
hardPushbackNorms[joinIndex - 1] = self.calcHardPushbacksNorms(playerCollider, potentials, result, self.snapIntoPlatformOverlap, effPushbacks[joinIndex - 1]);
const currPlayerDownsync = currRenderFrame.players[playerId];
const thatPlayerInNextFrame = nextRenderFramePlayers[playerId];
let fallStopping = false;
let possiblyFallStoppedOnAnotherPlayer = false;
for (const potential of potentials) {
let [isBarrier, isAnotherPlayer, isBullet] = [true == potential.data.hardPushback, null != potential.data.joinIndex, null != potential.data.offenderJoinIndex];
// ignore bullets for this step
if (isBullet) continue;
// Test if the player collides with the wall/another player
if (!playerCollider.collides(potential, result)) continue;
const normAlignmentWithGravity = (result.overlap_x * 0 + result.overlap_y * (-1.0));
const landedOnGravityPushback = (self.snapIntoPlatformThreshold < normAlignmentWithGravity); // prevents false snapping on the lateral sides
let pushback = [result.overlap * result.overlap_x, result.overlap * result.overlap_y];
if (landedOnGravityPushback) {
// kindly note that one player might land on top of another player, and snapping is also required in such case
pushback = [(result.overlap - self.snapIntoPlatformOverlap) * result.overlap_x, (result.overlap - self.snapIntoPlatformOverlap) * result.overlap_y];
thatPlayerInNextFrame.inAir = false;
}
for (let hardPushbackNorm of hardPushbackNorms[joinIndex - 1]) {
// remove pushback component on the directions of "hardPushbackNorms[joinIndex-1]" (by now those hardPushbacks are already accounted in "effPushbacks[joinIndex-1]")
const projectedMagnitude = pushback[0] * hardPushbackNorm[0] + pushback[1] * hardPushbackNorm[1];
if (isBarrier
||
(isAnotherPlayer && 0 > projectedMagnitude)
) {
// [WARNING] Pushing by another player is different from pushing by barrier!
// Otherwise the player couldn't be pushed by another player to opposite dir of a side wall
pushback[0] -= projectedMagnitude * hardPushbackNorm[0];
pushback[1] -= projectedMagnitude * hardPushbackNorm[1];
}
}
effPushbacks[joinIndex - 1][0] += pushback[0];
effPushbacks[joinIndex - 1][1] += pushback[1];
if (currPlayerDownsync.inAir && landedOnGravityPushback) {
fallStopping = true;
if (isAnotherPlayer) {
possiblyFallStoppedOnAnotherPlayer = true;
}
if (1 == thatPlayerInNextFrame.joinIndex) {
console.log(`playerId=${playerId}, joinIndex=${currPlayerDownsync.joinIndex} fallStopping#1 at {renderFrame.id: ${currRenderFrame.id}, virtualX: ${currPlayerDownsync.virtualGridX}, virtualY: ${currPlayerDownsync.virtualGridY}, velX: ${currPlayerDownsync.velX}, velY: ${currPlayerDownsync.velY}} with effPushback={${effPushbacks[joinIndex - 1][0].toFixed(3)}, ${effPushbacks[joinIndex - 1][1].toFixed(3)}}, overlayMag=${result.overlap.toFixed(4)}, possiblyFallStoppedOnAnotherPlayer=${possiblyFallStoppedOnAnotherPlayer}`);
}
}
if (1 == joinIndex && currPlayerDownsync.inAir && isBarrier && !landedOnGravityPushback) {
console.warn(`playerId=${playerId}, joinIndex=${currPlayerDownsync.joinIndex} inAir & pushed back by barrier & not landed at {renderFrame.id: ${currRenderFrame.id}, virtualX: ${currPlayerDownsync.virtualGridX}, virtualY: ${currPlayerDownsync.virtualGridY}, velX: ${currPlayerDownsync.velX}, velY: ${currPlayerDownsync.velY}} with effPushback={${effPushbacks[joinIndex - 1][0].toFixed(3)}, ${effPushbacks[joinIndex - 1][1].toFixed(3)}}, playerColliderPos={${playerCollider.x.toFixed(3)}, ${playerCollider.y.toFixed(3)}}, barrierPos={${potential.x.toFixed(3)}, ${potential.y.toFixed(3)}}, overlayMag=${result.overlap.toFixed(4)}, len(hardPushbackNorms)=${hardPushbackNorms.length}`);
}
if (1 == joinIndex && currPlayerDownsync.inAir && isAnotherPlayer) {
console.warn(`playerId=${playerId}, joinIndex=${currPlayerDownsync.joinIndex} inAir and pushed back by another player at {renderFrame.id: ${currRenderFrame.id}, virtualX: ${currPlayerDownsync.virtualGridX}, virtualY: ${currPlayerDownsync.virtualGridY}, velX: ${currPlayerDownsync.velX}, velY: ${currPlayerDownsync.velY}} with effPushback={${effPushbacks[joinIndex - 1][0].toFixed(3)}, ${effPushbacks[joinIndex - 1][1].toFixed(3)}}, landedOnGravityPushback=${landedOnGravityPushback}, fallStopping=${fallStopping}, playerColliderPos={${playerCollider.x.toFixed(3)}, ${playerCollider.y.toFixed(3)}}, anotherPlayerColliderPos={${potential.x.toFixed(3)}, ${potential.y.toFixed(3)}}, overlayMag=${result.overlap.toFixed(4)}, len(hardPushbackNorms)=${hardPushbackNorms.length}`);
}
}
if (fallStopping) {
thatPlayerInNextFrame.velX = 0;
thatPlayerInNextFrame.velY = 0;
thatPlayerInNextFrame.characterState = window.ATK_CHARACTER_STATE.Idle1[0];
thatPlayerInNextFrame.framesToRecover = 0;
}
if (currPlayerDownsync.inAir) {
thatPlayerInNextFrame.characterState = window.toInAirConjugate(thatPlayerInNextFrame.characterState);
}
}
// 6. Check bullet-anything collisions
bulletColliders.forEach((bulletCollider, collisionBulletIndex) => {
const potentials = bulletCollider.potentials();
const offender = currRenderFrame.players[bulletCollider.data.offenderPlayerId];
let shouldRemove = false;
for (const potential of potentials) {
if (null != potential.data && potential.data.joinIndex == bulletCollider.data.offenderJoinIndex) continue;
if (!bulletCollider.collides(potential, result1)) continue;
if (null != potential.data && null !== potential.data.joinIndex) {
if (!bulletCollider.collides(potential, result)) continue;
if (null != potential.data && null != potential.data.joinIndex) {
const playerId = potential.data.id;
const joinIndex = potential.data.joinIndex;
let xfac = 1;
if (0 > offender.dirX) {
xfac = -1;
}
bulletPushbacks[joinIndex - 1][0] += xfac * bulletCollider.data.pushback; // Only for straight punch, there's no y-pushback
bulletPushbacks[joinIndex - 1][1] += 0;
const thatAckedPlayerInNextFrame = nextRenderFramePlayers[potential.data.id];
thatAckedPlayerInNextFrame.characterState = window.ATK_CHARACTER_STATE.Atked1[0];
const oldFramesToRecover = thatAckedPlayerInNextFrame.framesToRecover;
thatAckedPlayerInNextFrame.framesToRecover = (oldFramesToRecover > bulletCollider.data.hitStunFrames ? oldFramesToRecover : bulletCollider.data.hitStunFrames); // In case the hit player is already stun, we extend it
// Only for straight punch, there's no y-pushback
let bulletPushback = [-xfac * bulletCollider.data.pushback, 0];
// console.log(`playerId=${playerId}, joinIndex=${joinIndex} is supposed to be pushed back by meleeBullet for bulletPushback=${JSON.stringify(bulletPushback)} at renderFrame.id=${currRenderFrame.id}`);
for (let hardPushbackNorm of hardPushbackNorms[joinIndex - 1]) {
const projectedMagnitude = bulletPushback[0] * hardPushbackNorm[0] + bulletPushback[1] * hardPushbackNorm[1];
if (0 > projectedMagnitude) {
// Otherwise when smashing into a wall the atked player would be pushed into the wall first and only got back in the next renderFrame, not what I want here
bulletPushback[0] -= (projectedMagnitude * hardPushbackNorm[0]);
bulletPushback[1] -= (projectedMagnitude * hardPushbackNorm[1]);
// console.log(`playerId=${playerId}, joinIndex=${joinIndex} reducing bulletPushback=${JSON.stringify(bulletPushback)} by ${JSON.stringify([projectedMagnitude * hardPushbackNorm[0], projectedMagnitude * hardPushbackNorm[1]])} where hardPushbackNorm=${JSON.stringify(hardPushbackNorm)}, projectedMagnitude=${projectedMagnitude} at renderFrame.id=${currRenderFrame.id}`);
}
}
// console.log(`playerId=${playerId}, joinIndex=${joinIndex} is actually pushed back by meleeBullet for bulletPushback=${JSON.stringify(bulletPushback)} at renderFrame.id=${currRenderFrame.id}`);
effPushbacks[joinIndex - 1][0] += bulletPushback[0];
effPushbacks[joinIndex - 1][1] += bulletPushback[1];
const [atkedPlayerInCurFrame, atkedPlayerInNextFrame] = [currRenderFrame.players[potential.data.id], nextRenderFramePlayers[potential.data.id]];
atkedPlayerInNextFrame.characterState = window.ATK_CHARACTER_STATE.Atked1[0];
if (atkedPlayerInCurFrame.inAir) {
atkedPlayerInNextFrame.characterState = window.toInAirConjugate(atkedPlayerInNextFrame.characterState);
}
const oldFramesToRecover = atkedPlayerInNextFrame.framesToRecover;
atkedPlayerInNextFrame.framesToRecover = (oldFramesToRecover > bulletCollider.data.hitStunFrames ? oldFramesToRecover : bulletCollider.data.hitStunFrames); // In case the hit player is already stun, we extend it
}
shouldRemove = true;
}
@@ -1111,95 +1369,32 @@ cc.Class({
nextRenderFrameMeleeBullets.push(meleeBullet);
}
// Process player inputs
if (null != delayedInputFrame) {
const delayedInputFrameForPrevRenderFrame = self.getCachedInputFrameDownsyncWithPrediction(self._convertToInputFrameId(currRenderFrame.id - 1, self.inputDelayFrames));
const inputList = delayedInputFrame.inputList;
for (let j in self.playerRichInfoArr) {
const joinIndex = parseInt(j) + 1;
effPushbacks[joinIndex - 1] = [0.0, 0.0];
const playerRichInfo = self.playerRichInfoArr[j];
const playerId = playerRichInfo.id;
const collisionPlayerIndex = self.collisionPlayerIndexPrefix + joinIndex;
const playerCollider = collisionSysMap.get(collisionPlayerIndex);
const currPlayerDownsync = currRenderFrame.players[playerId];
const thatPlayerInNextFrame = nextRenderFramePlayers[playerId];
if (0 < thatPlayerInNextFrame.framesToRecover) {
// No need to process inputs for this player, but there might be bullet pushbacks on this player
playerCollider.x += bulletPushbacks[joinIndex - 1][0];
playerCollider.y += 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 ${thatPlayerInNextFrame.framesToRecover}`);
}
continue;
// 7. Get players out of stuck barriers if there's any
for (let j in self.playerRichInfoArr) {
const joinIndex = parseInt(j) + 1;
const playerId = self.playerRichInfoArr[j].id;
const collisionPlayerIndex = self.collisionPlayerIndexPrefix + joinIndex;
const playerCollider = collisionSysMap.get(collisionPlayerIndex);
// Update "virtual grid position"
const currPlayerDownsync = currRenderFrame.players[playerId];
const thatPlayerInNextFrame = nextRenderFramePlayers[playerId];
const colliderWidth = self.playerRichInfoArr[joinIndex - 1].colliderRadius * 2,
colliderHeight = self.playerRichInfoArr[joinIndex - 1].colliderRadius * 4;
const newVpos = self.polygonColliderTLToVirtualGridPos(playerCollider.x - effPushbacks[joinIndex - 1][0], playerCollider.y - effPushbacks[joinIndex - 1][1], colliderWidth * 0.5, colliderHeight * 0.5);
thatPlayerInNextFrame.virtualGridX = newVpos[0];
thatPlayerInNextFrame.virtualGridY = newVpos[1];
if (1 == thatPlayerInNextFrame.joinIndex) {
if (thatPlayerInNextFrame.inAir && 0 != thatPlayerInNextFrame.velY) {
// console.log(`playerId=${playerId}, joinIndex=${thatPlayerInNextFrame.joinIndex} inAir trajectory: {nextRenderFrame.id: ${currRenderFrame.id + 1}, nextVirtualX: ${thatPlayerInNextFrame.virtualGridX}, nextVirtualY: ${thatPlayerInNextFrame.virtualGridY}, nextVelX: ${thatPlayerInNextFrame.velX}, nextVelY: ${thatPlayerInNextFrame.velY}}, with playerColliderPos={${playerCollider.x.toFixed(3)}, ${playerCollider.y.toFixed(3)}}, effPushback={${effPushbacks[joinIndex - 1][0].toFixed(3)}, ${effPushbacks[joinIndex - 1][1].toFixed(3)}}`);
}
const decodedInput = self.ctrl.decodeInput(inputList[joinIndex - 1]);
const prevDecodedInput = (null == delayedInputFrameForPrevRenderFrame ? null : self.ctrl.decodeInput(delayedInputFrameForPrevRenderFrame.inputList[joinIndex - 1]));
const prevBtnALevel = (null == prevDecodedInput ? 0 : prevDecodedInput.btnALevel);
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}`);
if (self.bulletTriggerEnabled) {
const punchSkillId = 1;
const punch = window.pb.protos.MeleeBullet.create(self.meleeSkillConfig[punchSkillId]);
thatPlayerInNextFrame.framesToRecover = punch.recoveryFrames;
punch.battleLocalId = self.bulletBattleLocalIdCounter++;
punch.offenderJoinIndex = joinIndex;
punch.offenderPlayerId = playerId;
punch.originatedRenderFrameId = currRenderFrame.id;
nextRenderFrameMeleeBullets.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}`);
thatPlayerInNextFrame.characterState = window.ATK_CHARACTER_STATE.Atk1[0];
}
} else if (0 == decodedInput.btnALevel && 1 == prevBtnALevel) {
// console.log(`playerId=${playerId} triggered a falling-edge of btnA at renderFrame.id=${currRenderFrame.id}, delayedInputFrame.id=${delayedInputFrame.inputFrameId}`);
} else {
// No bullet trigger, process movement inputs
if (0 != decodedInput.dx || 0 != decodedInput.dy) {
// Update directions and thus would eventually update moving animation accordingly
thatPlayerInNextFrame.dirX = decodedInput.dx;
thatPlayerInNextFrame.dirY = decodedInput.dy;
thatPlayerInNextFrame.characterState = window.ATK_CHARACTER_STATE.Walking[0];
} else {
thatPlayerInNextFrame.characterState = window.ATK_CHARACTER_STATE.Idle1[0];
}
const [movementX, movementY] = self.virtualGridToWorldPos(decodedInput.dx + currPlayerDownsync.speed * decodedInput.dx, decodedInput.dy + currPlayerDownsync.speed * decodedInput.dy);
playerCollider.x += movementX;
playerCollider.y += movementY;
if (currPlayerDownsync.inAir && !thatPlayerInNextFrame.inAir) {
console.warn(`playerId=${playerId}, joinIndex=${thatPlayerInNextFrame.joinIndex} fallStopping#2 at {nextRenderFrame.id: ${currRenderFrame.id + 1}, nextVirtualX: ${thatPlayerInNextFrame.virtualGridX}, nextVirtualY: ${thatPlayerInNextFrame.virtualGridY}, nextVelX: ${thatPlayerInNextFrame.velX}, nextVelY: ${thatPlayerInNextFrame.velY}}, with playerColliderPos={${playerCollider.x.toFixed(3)}, ${playerCollider.y.toFixed(3)}}, effPushback={${effPushbacks[joinIndex - 1][0].toFixed(3)}, ${effPushbacks[joinIndex - 1][1].toFixed(3)}}`);
}
if (!currPlayerDownsync.inAir && thatPlayerInNextFrame.inAir) {
console.warn(`playerId=${playerId}, joinIndex=${thatPlayerInNextFrame.joinIndex} took off at {nextRenderFrame.id: ${currRenderFrame.id + 1}, nextVirtualX: ${thatPlayerInNextFrame.virtualGridX}, nextVirtualY: ${thatPlayerInNextFrame.virtualGridY}, nextVelX: ${thatPlayerInNextFrame.velX}, nextVelY: ${thatPlayerInNextFrame.velY}}, with playerColliderPos={${playerCollider.x.toFixed(3)}, ${playerCollider.y.toFixed(3)}}, effPushback={${effPushbacks[joinIndex - 1][0].toFixed(3)}, ${effPushbacks[joinIndex - 1][1].toFixed(3)}}`);
}
}
collisionSys.update(); // by now all "bulletCollider"s are removed
const result2 = collisionSys.createResult(); // Can I reuse a "self.collisionSysResult" object throughout the whole battle?
for (let j in self.playerRichInfoArr) {
const joinIndex = parseInt(j) + 1;
const playerId = self.playerRichInfoArr[j].id;
const collisionPlayerIndex = self.collisionPlayerIndexPrefix + joinIndex;
const playerCollider = collisionSysMap.get(collisionPlayerIndex);
const potentials = playerCollider.potentials();
for (const potential of potentials) {
// Test if the player collides with the wall
if (!playerCollider.collides(potential, result2)) continue;
// Push the player out of the wall
effPushbacks[joinIndex - 1][0] += result2.overlap * result2.overlap_x;
effPushbacks[joinIndex - 1][1] += result2.overlap * result2.overlap_y;
}
}
for (let j in self.playerRichInfoArr) {
const joinIndex = parseInt(j) + 1;
const playerId = self.playerRichInfoArr[j].id;
const collisionPlayerIndex = self.collisionPlayerIndexPrefix + joinIndex;
const playerCollider = collisionSysMap.get(collisionPlayerIndex);
const thatPlayerInNextFrame = nextRenderFramePlayers[playerId];
[thatPlayerInNextFrame.virtualGridX, thatPlayerInNextFrame.virtualGridY] = self.polygonColliderAnchorToVirtualGridPos(playerCollider.x - effPushbacks[joinIndex - 1][0], playerCollider.y - effPushbacks[joinIndex - 1][1], self.playerRichInfoArr[j].colliderRadius, self.playerRichInfoArr[j].colliderRadius);
}
}
return window.pb.protos.RoomDownsyncFrame.create({
@@ -1214,11 +1409,10 @@ cc.Class({
This function eventually calculates a "RoomDownsyncFrame" where "RoomDownsyncFrame.id == renderFrameIdEd" if not interruptted.
*/
const self = this;
let i = renderFrameIdSt,
prevLatestRdf = null,
let prevLatestRdf = null,
latestRdf = null;
do {
for (let i = renderFrameIdSt; i < renderFrameIdEd; i++) {
latestRdf = self.recentRenderCache.getByFrameId(i); // typed "RoomDownsyncFrame"; [WARNING] When "true == isChasing", this function can be interruptted by "onRoomDownsyncFrame(rdf)" asynchronously anytime, making this line return "null"!
if (null == latestRdf) {
console.warn(`Couldn't find renderFrame for i=${i} to rollback, self.renderFrameId=${self.renderFrameId}, lastAllConfirmedRenderFrameId=${self.lastAllConfirmedRenderFrameId}, lastAllConfirmedInputFrameId=${self.lastAllConfirmedInputFrameId}, might've been interruptted by onRoomDownsyncFrame`);
@@ -1250,8 +1444,7 @@ cc.Class({
self.chaserRenderFrameId = latestRdf.id;
}
self.recentRenderCache.setByFrameId(latestRdf, latestRdf.id);
++i;
} while (i < renderFrameIdEd);
}
return [prevLatestRdf, latestRdf];
},
@@ -1325,23 +1518,41 @@ cc.Class({
return [wx, wy];
},
worldToPolygonColliderAnchorPos(wx, wy, halfBoundingW, halfBoundingH) {
return [wx - halfBoundingW, wy - halfBoundingH];
worldToPolygonColliderTLPos(wx, wy, halfBoundingW, halfBoundingH) {
return [wx - halfBoundingW, wy + halfBoundingH];
},
polygonColliderAnchorToWorldPos(cx, cy, halfBoundingW, halfBoundingH) {
return [cx + halfBoundingW, cy + halfBoundingH];
polygonColliderTLToWorldPos(cx, cy, halfBoundingW, halfBoundingH) {
return [cx + halfBoundingW, cy - halfBoundingH];
},
polygonColliderAnchorToVirtualGridPos(cx, cy, halfBoundingW, halfBoundingH) {
polygonColliderTLToVirtualGridPos(cx, cy, halfBoundingW, halfBoundingH) {
const self = this;
const [wx, wy] = self.polygonColliderAnchorToWorldPos(cx, cy, halfBoundingW, halfBoundingH);
const [wx, wy] = self.polygonColliderTLToWorldPos(cx, cy, halfBoundingW, halfBoundingH);
return self.worldToVirtualGridPos(wx, wy)
},
virtualGridToPolygonColliderAnchorPos(vx, vy, halfBoundingW, halfBoundingH) {
virtualGridToPolygonColliderTLPos(vx, vy, halfBoundingW, halfBoundingH) {
const self = this;
const [wx, wy] = self.virtualGridToWorldPos(vx, vy);
return self.worldToPolygonColliderAnchorPos(wx, wy, halfBoundingW, halfBoundingH)
return self.worldToPolygonColliderTLPos(wx, wy, halfBoundingW, halfBoundingH)
},
calcHardPushbacksNorms(collider, potentials, result, snapIntoPlatformOverlap, effPushback) {
const self = this;
let ret = [];
for (const potential of potentials) {
if (null == potential.data || !(true == potential.data.hardPushback)) continue;
if (!collider.collides(potential, result)) continue;
// ALWAY snap into hardPushbacks!
// [overlay_x, overlap_y] is the unit vector that points into the platform
const [pushbackX, pushbackY] = [(result.overlap - snapIntoPlatformOverlap) * result.overlap_x, (result.overlap - snapIntoPlatformOverlap) * result.overlap_y];
ret.push([result.overlap_x, result.overlap_y]);
effPushback[0] += pushbackX;
effPushback[1] += pushbackY;
}
return ret;
},
});

View File

@@ -13,6 +13,7 @@ cc.Class({
onLoad() {
const self = this;
window.mapIns = self;
self.showCriticalCoordinateLabels = true;
cc.director.getCollisionManager().enabled = false;
@@ -34,9 +35,11 @@ cc.Class({
self.inputFrameUpsyncDelayTolerance = 2;
self.renderCacheSize = 1024;
self.serverFps = 60;
self.rollbackEstimatedDt = 0.016667;
self.rollbackEstimatedDtMillis = 16.667;
self.rollbackEstimatedDtNanos = 16666666;
self.tooFastDtIntervalMillis = 0.5 * self.rollbackEstimatedDtMillis;
self.worldToVirtualGridRatio = 1000;
self.virtualGridToWorldRatio = 1.0 / self.worldToVirtualGridRatio;
@@ -67,6 +70,16 @@ cc.Class({
}
};
/*
[WARNING] As when a character is standing on a barrier, if not carefully curated there MIGHT BE a bouncing sequence of "[(inAir -> dropIntoBarrier ->), (notInAir -> pushedOutOfBarrier ->)], [(inAir -> ..."
Moreover, "snapIntoPlatformOverlap" should be small enough such that the walking "velX" or jumping initial "velY" can escape from it by 1 renderFrame (when jumping is triggered, the character is waived from snappig for 1 renderFrame).
*/
self.snapIntoPlatformOverlap = 0.1;
self.snapIntoPlatformThreshold = 0.5; // a platform must be "horizontal enough" for a character to "stand on"
self.jumpingInitVelY = 7 * self.worldToVirtualGridRatio; // unit: (virtual grid length/renderFrame)
[self.gravityX, self.gravityY] = [0, -0.5*self.worldToVirtualGridRatio]; // unit: (virtual grid length/renderFrame^2)
const tiledMapIns = self.node.getComponent(cc.TiledMap);
const fullPathOfTmxFile = cc.js.formatStr("map/%s/map", "dungeon");
@@ -80,6 +93,17 @@ cc.Class({
mapNode.removeAllChildren();
self._resetCurrentMatch();
if (self.showCriticalCoordinateLabels) {
const drawer = new cc.Node();
drawer.setPosition(cc.v2(0, 0))
safelyAddChild(self.node, drawer);
setLocalZOrder(drawer, 999);
const g = drawer.addComponent(cc.Graphics);
g.lineWidth = 2;
self.g = g;
}
tiledMapIns.tmxAsset = tmxAsset;
const newMapSize = tiledMapIns.getMapSize();
const newTileSize = tiledMapIns.getTileSize();
@@ -95,8 +119,11 @@ cc.Class({
const newBarrier = self.collisionSys.createPolygon(x0, y0, Array.from(boundaryObj, p => {
return [p.x, p.y];
}));
newBarrier.data = {
hardPushback: true
};
if (self.showCriticalCoordinateLabels) {
if (false && self.showCriticalCoordinateLabels) {
for (let i = 0; i < boundaryObj.length; ++i) {
const barrierVertLabelNode = new cc.Node();
switch (i % 4) {
@@ -136,30 +163,36 @@ cc.Class({
const startRdf = window.pb.protos.RoomDownsyncFrame.create({
id: window.MAGIC_ROOM_DOWNSYNC_FRAME_ID.BATTLE_START,
players: {
10: {
10: window.pb.protos.PlayerDownsync.create({
id: 10,
joinIndex: 1,
virtualGridX: 0,
virtualGridY: 0,
virtualGridX: self.worldToVirtualGridPos(boundaryObjs.playerStartingPositions[0].x, boundaryObjs.playerStartingPositions[0].y)[0],
virtualGridY: self.worldToVirtualGridPos(boundaryObjs.playerStartingPositions[0].x, boundaryObjs.playerStartingPositions[0].y)[1],
speed: 1 * self.worldToVirtualGridRatio,
colliderRadius: 12,
characterState: window.ATK_CHARACTER_STATE.Idle1[0],
characterState: window.ATK_CHARACTER_STATE.InAirIdle1[0],
framesToRecover: 0,
dirX: 0,
dirY: 0,
},
11: {
velX: 0,
velY: 0,
inAir: true,
}),
11: window.pb.protos.PlayerDownsync.create({
id: 11,
joinIndex: 2,
virtualGridX: 80 * self.worldToVirtualGridRatio,
virtualGridY: 0 * self.worldToVirtualGridRatio,
virtualGridX: self.worldToVirtualGridPos(boundaryObjs.playerStartingPositions[1].x, boundaryObjs.playerStartingPositions[1].y)[0],
virtualGridY: self.worldToVirtualGridPos(boundaryObjs.playerStartingPositions[1].x, boundaryObjs.playerStartingPositions[1].y)[1],
speed: 1 * self.worldToVirtualGridRatio,
colliderRadius: 12,
characterState: window.ATK_CHARACTER_STATE.Idle1[0],
characterState: window.ATK_CHARACTER_STATE.InAirIdle1[0],
framesToRecover: 0,
dirX: 0,
dirY: 0,
},
velX: 0,
velY: 0,
inAir: true,
}),
}
});
self.selfPlayerInfo = {
@@ -177,7 +210,8 @@ cc.Class({
const self = this;
if (ALL_BATTLE_STATES.IN_BATTLE == self.battleState) {
const elapsedMillisSinceLastFrameIdTriggered = performance.now() - self.lastRenderFrameIdTriggeredAt;
if (elapsedMillisSinceLastFrameIdTriggered < (self.rollbackEstimatedDtMillis)) {
if (elapsedMillisSinceLastFrameIdTriggered < self.tooFastDtIntervalMillis) {
// [WARNING] We should avoid a frontend ticking too fast to prevent cheating, as well as ticking too slow to cause a "resync avalanche" that impacts user experience!
// console.debug("Avoiding too fast frame@renderFrameId=", self.renderFrameId, ": elapsedMillisSinceLastFrameIdTriggered=", elapsedMillisSinceLastFrameIdTriggered);
return;
}
@@ -194,11 +228,12 @@ cc.Class({
const [prevRdf, rdf] = self.rollbackAndChase(self.renderFrameId, self.renderFrameId + 1, self.collisionSys, self.collisionSysMap, false);
self.applyRoomDownsyncFrameDynamics(rdf, prevRdf);
self.showDebugBoundaries(rdf);
++self.renderFrameId;
self.lastRenderFrameIdTriggeredAt = performance.now();
let t3 = performance.now();
} catch (err) {
console.error("Error during Map.update", err);
} finally {
++self.renderFrameId; // [WARNING] It's important to increment the renderFrameId AFTER all the operations above!!!
}
}
},

View File

@@ -13,7 +13,7 @@ var RingBuffer = function(capacity) {
};
RingBuffer.prototype.put = function(item) {
while (this.cnt >= this.n - 1) {
while (0 < this.cnt && this.cnt >= this.n) {
// Make room for the new element
this.pop();
}
@@ -65,7 +65,7 @@ RingBuffer.prototype.getArrIdxByOffset = function(offsetFromSt) {
};
RingBuffer.prototype.getByFrameId = function(frameId) {
if (frameId >= this.edFrameId) return null;
if (frameId >= this.edFrameId || frameId < this.stFrameId) return null;
const arrIdx = this.getArrIdxByOffset(frameId - this.stFrameId);
return (null == arrIdx ? null : this.eles[arrIdx]);
};

View File

@@ -108,6 +108,7 @@ TileCollisionManager.prototype.continuousMapNodePosToContinuousObjLayerOffset =
window.battleEntityTypeNameToGlobalGid = {};
TileCollisionManager.prototype.extractBoundaryObjects = function(withTiledMapNode) {
let toRet = {
playerStartingPositions: [],
barriers: [],
};
const tiledMapIns = withTiledMapNode.getComponent(cc.TiledMap); // This is a magic name.
@@ -115,6 +116,18 @@ TileCollisionManager.prototype.extractBoundaryObjects = function(withTiledMapNod
const allObjectGroups = tiledMapIns.getObjectGroups();
for (let i = 0; i < allObjectGroups.length; ++i) {
var objectGroup = allObjectGroups[i];
if ("PlayerStartingPos" == objectGroup.getGroupName()) {
var allObjects = objectGroup.getObjects();
for (let j = 0; j < allObjects.length; ++j) {
const cccMaskedX = allObjects[j].x,
cccMaskedY = allObjects[j].y;
const origX = cccMaskedX,
origY = withTiledMapNode.getContentSize().height - cccMaskedY; // FIXME: I don't know why CocosCreator did this, it's stupid and MIGHT NOT WORK IN ISOMETRIC orientation!
let wpos = this.continuousObjLayerOffsetToContinuousMapNodePos(withTiledMapNode, cc.v2(origX, origY));
toRet.playerStartingPositions.push(wpos);
}
continue;
}
if ("barrier_and_shelter" != objectGroup.getProperty("type")) continue;
var allObjects = objectGroup.getObjects();
for (let j = 0; j < allObjects.length; ++j) {
@@ -123,21 +136,33 @@ TileCollisionManager.prototype.extractBoundaryObjects = function(withTiledMapNod
if (0 < gid) {
continue;
}
const polylinePoints = object.polylinePoints;
if (null == polylinePoints) {
continue
}
const boundaryType = object.boundary_type;
let toPushBarriers = [];
toPushBarriers.boundaryType = boundaryType;
let toPushBarrier = [];
toPushBarrier.boundaryType = boundaryType;
switch (boundaryType) {
case "barrier":
let polylinePoints = object.polylinePoints;
if (null == polylinePoints) {
polylinePoints = [{
x: 0,
y: 0
}, {
x: object.width,
y: 0
}, {
x: object.width,
y: -object.height
}, {
x: 0,
y: -object.height
}];
}
for (let k = 0; k < polylinePoints.length; ++k) {
/* Since CocosCreatorv2.1.3, the Y-coord of object polylines is inverted compared to that of the tmx file. */
toPushBarriers.push(this.continuousObjLayerVecToContinuousMapNodeVec(withTiledMapNode, cc.v2(polylinePoints[k].x, -polylinePoints[k].y)));
toPushBarrier.push(this.continuousObjLayerVecToContinuousMapNodeVec(withTiledMapNode, cc.v2(polylinePoints[k].x, -polylinePoints[k].y)));
}
toPushBarriers.anchor = this.continuousObjLayerOffsetToContinuousMapNodePos(withTiledMapNode, object.offset); // DON'T use "(object.x, object.y)" which are wrong/meaningless!
toRet.barriers.push(toPushBarriers);
toPushBarrier.anchor = this.continuousObjLayerOffsetToContinuousMapNodePos(withTiledMapNode, object.offset); // DON'T use "(object.x, object.y)" which are wrong/meaningless!
toRet.barriers.push(toPushBarrier);
break;
default:
break;

View File

@@ -99,6 +99,7 @@ cc.Class({
this.cachedBtnLeftLevel = 0;
this.cachedBtnRightLevel = 0;
this.cachedBtnALevel = 0;
this.cachedBtnBLevel = 0;
this.canvasNode = this.mapNode.parent;
this.mainCameraNode = this.canvasNode.getChildByName("Main Camera"); // Cannot drag and assign the `mainCameraNode` from CocosCreator EDITOR directly, otherwise it'll cause an infinite loading time, till v2.1.0.
@@ -168,6 +169,9 @@ cc.Class({
case cc.macro.KEY.h:
self.cachedBtnALevel = 1;
break;
case cc.macro.KEY.j:
self.cachedBtnBLevel = 1;
break;
default:
break;
}
@@ -190,6 +194,9 @@ cc.Class({
case cc.macro.KEY.h:
self.cachedBtnALevel = 0;
break;
case cc.macro.KEY.j:
self.cachedBtnBLevel = 0;
break;
default:
break;
}
@@ -400,7 +407,8 @@ cc.Class({
getEncodedInput() {
const discretizedDir = this.discretizeDirection(this.stickhead.x, this.stickhead.y, this.joyStickEps).encodedIdx; // There're only 9 dirs, thus using only the lower 4-bits
const btnALevel = (this.cachedBtnALevel << 4);
return (btnALevel + discretizedDir);
const btnBLevel = (this.cachedBtnBLevel << 5);
return (btnBLevel + btnALevel + discretizedDir);
},
decodeInput(encodedInput) {
@@ -410,10 +418,12 @@ cc.Class({
console.error("Unexpected encodedDirection = ", encodedDirection);
}
const btnALevel = ((encodedInput >> 4) & 1);
const btnBLevel = ((encodedInput >> 5) & 1);
return window.pb.protos.InputFrameDecoded.create({
dx: mappedDirection[0],
dy: mappedDirection[1],
btnALevel: btnALevel,
btnBLevel: btnBLevel,
});
},
});

View File

@@ -1196,6 +1196,8 @@ $root.protos = (function() {
* @property {number|null} [virtualGridY] PlayerDownsync virtualGridY
* @property {number|null} [dirX] PlayerDownsync dirX
* @property {number|null} [dirY] PlayerDownsync dirY
* @property {number|null} [velX] PlayerDownsync velX
* @property {number|null} [velY] PlayerDownsync velY
* @property {number|null} [speed] PlayerDownsync speed
* @property {number|null} [battleState] PlayerDownsync battleState
* @property {number|null} [joinIndex] PlayerDownsync joinIndex
@@ -1207,6 +1209,7 @@ $root.protos = (function() {
* @property {number|null} [hp] PlayerDownsync hp
* @property {number|null} [maxHp] PlayerDownsync maxHp
* @property {number|null} [characterState] PlayerDownsync characterState
* @property {boolean|null} [inAir] PlayerDownsync inAir
* @property {string|null} [name] PlayerDownsync name
* @property {string|null} [displayName] PlayerDownsync displayName
* @property {string|null} [avatar] PlayerDownsync avatar
@@ -1267,6 +1270,22 @@ $root.protos = (function() {
*/
PlayerDownsync.prototype.dirY = 0;
/**
* PlayerDownsync velX.
* @member {number} velX
* @memberof protos.PlayerDownsync
* @instance
*/
PlayerDownsync.prototype.velX = 0;
/**
* PlayerDownsync velY.
* @member {number} velY
* @memberof protos.PlayerDownsync
* @instance
*/
PlayerDownsync.prototype.velY = 0;
/**
* PlayerDownsync speed.
* @member {number} speed
@@ -1355,6 +1374,14 @@ $root.protos = (function() {
*/
PlayerDownsync.prototype.characterState = 0;
/**
* PlayerDownsync inAir.
* @member {boolean} inAir
* @memberof protos.PlayerDownsync
* @instance
*/
PlayerDownsync.prototype.inAir = false;
/**
* PlayerDownsync name.
* @member {string} name
@@ -1413,34 +1440,40 @@ $root.protos = (function() {
writer.uint32(/* id 4, wireType 0 =*/32).int32(message.dirX);
if (message.dirY != null && Object.hasOwnProperty.call(message, "dirY"))
writer.uint32(/* id 5, wireType 0 =*/40).int32(message.dirY);
if (message.velX != null && Object.hasOwnProperty.call(message, "velX"))
writer.uint32(/* id 6, wireType 0 =*/48).int32(message.velX);
if (message.velY != null && Object.hasOwnProperty.call(message, "velY"))
writer.uint32(/* id 7, wireType 0 =*/56).int32(message.velY);
if (message.speed != null && Object.hasOwnProperty.call(message, "speed"))
writer.uint32(/* id 6, wireType 0 =*/48).int32(message.speed);
writer.uint32(/* id 8, wireType 0 =*/64).int32(message.speed);
if (message.battleState != null && Object.hasOwnProperty.call(message, "battleState"))
writer.uint32(/* id 7, wireType 0 =*/56).int32(message.battleState);
writer.uint32(/* id 9, wireType 0 =*/72).int32(message.battleState);
if (message.joinIndex != null && Object.hasOwnProperty.call(message, "joinIndex"))
writer.uint32(/* id 8, wireType 0 =*/64).int32(message.joinIndex);
writer.uint32(/* id 10, wireType 0 =*/80).int32(message.joinIndex);
if (message.colliderRadius != null && Object.hasOwnProperty.call(message, "colliderRadius"))
writer.uint32(/* id 9, wireType 1 =*/73).double(message.colliderRadius);
writer.uint32(/* id 11, wireType 1 =*/89).double(message.colliderRadius);
if (message.removed != null && Object.hasOwnProperty.call(message, "removed"))
writer.uint32(/* id 10, wireType 0 =*/80).bool(message.removed);
writer.uint32(/* id 12, wireType 0 =*/96).bool(message.removed);
if (message.score != null && Object.hasOwnProperty.call(message, "score"))
writer.uint32(/* id 11, wireType 0 =*/88).int32(message.score);
writer.uint32(/* id 13, wireType 0 =*/104).int32(message.score);
if (message.lastMoveGmtMillis != null && Object.hasOwnProperty.call(message, "lastMoveGmtMillis"))
writer.uint32(/* id 12, wireType 0 =*/96).int32(message.lastMoveGmtMillis);
writer.uint32(/* id 14, wireType 0 =*/112).int32(message.lastMoveGmtMillis);
if (message.framesToRecover != null && Object.hasOwnProperty.call(message, "framesToRecover"))
writer.uint32(/* id 13, wireType 0 =*/104).int32(message.framesToRecover);
writer.uint32(/* id 15, wireType 0 =*/120).int32(message.framesToRecover);
if (message.hp != null && Object.hasOwnProperty.call(message, "hp"))
writer.uint32(/* id 14, wireType 0 =*/112).int32(message.hp);
writer.uint32(/* id 16, wireType 0 =*/128).int32(message.hp);
if (message.maxHp != null && Object.hasOwnProperty.call(message, "maxHp"))
writer.uint32(/* id 15, wireType 0 =*/120).int32(message.maxHp);
writer.uint32(/* id 17, wireType 0 =*/136).int32(message.maxHp);
if (message.characterState != null && Object.hasOwnProperty.call(message, "characterState"))
writer.uint32(/* id 16, wireType 0 =*/128).int32(message.characterState);
writer.uint32(/* id 18, wireType 0 =*/144).int32(message.characterState);
if (message.inAir != null && Object.hasOwnProperty.call(message, "inAir"))
writer.uint32(/* id 19, wireType 0 =*/152).bool(message.inAir);
if (message.name != null && Object.hasOwnProperty.call(message, "name"))
writer.uint32(/* id 17, wireType 2 =*/138).string(message.name);
writer.uint32(/* id 20, wireType 2 =*/162).string(message.name);
if (message.displayName != null && Object.hasOwnProperty.call(message, "displayName"))
writer.uint32(/* id 18, wireType 2 =*/146).string(message.displayName);
writer.uint32(/* id 21, wireType 2 =*/170).string(message.displayName);
if (message.avatar != null && Object.hasOwnProperty.call(message, "avatar"))
writer.uint32(/* id 19, wireType 2 =*/154).string(message.avatar);
writer.uint32(/* id 22, wireType 2 =*/178).string(message.avatar);
return writer;
};
@@ -1496,58 +1529,70 @@ $root.protos = (function() {
break;
}
case 6: {
message.speed = reader.int32();
message.velX = reader.int32();
break;
}
case 7: {
message.battleState = reader.int32();
message.velY = reader.int32();
break;
}
case 8: {
message.joinIndex = reader.int32();
message.speed = reader.int32();
break;
}
case 9: {
message.colliderRadius = reader.double();
message.battleState = reader.int32();
break;
}
case 10: {
message.removed = reader.bool();
message.joinIndex = reader.int32();
break;
}
case 11: {
message.score = reader.int32();
message.colliderRadius = reader.double();
break;
}
case 12: {
message.lastMoveGmtMillis = reader.int32();
message.removed = reader.bool();
break;
}
case 13: {
message.framesToRecover = reader.int32();
message.score = reader.int32();
break;
}
case 14: {
message.hp = reader.int32();
message.lastMoveGmtMillis = reader.int32();
break;
}
case 15: {
message.maxHp = reader.int32();
message.framesToRecover = reader.int32();
break;
}
case 16: {
message.characterState = reader.int32();
message.hp = reader.int32();
break;
}
case 17: {
message.name = reader.string();
message.maxHp = reader.int32();
break;
}
case 18: {
message.displayName = reader.string();
message.characterState = reader.int32();
break;
}
case 19: {
message.inAir = reader.bool();
break;
}
case 20: {
message.name = reader.string();
break;
}
case 21: {
message.displayName = reader.string();
break;
}
case 22: {
message.avatar = reader.string();
break;
}
@@ -1601,6 +1646,12 @@ $root.protos = (function() {
if (message.dirY != null && message.hasOwnProperty("dirY"))
if (!$util.isInteger(message.dirY))
return "dirY: integer expected";
if (message.velX != null && message.hasOwnProperty("velX"))
if (!$util.isInteger(message.velX))
return "velX: integer expected";
if (message.velY != null && message.hasOwnProperty("velY"))
if (!$util.isInteger(message.velY))
return "velY: integer expected";
if (message.speed != null && message.hasOwnProperty("speed"))
if (!$util.isInteger(message.speed))
return "speed: integer expected";
@@ -1634,6 +1685,9 @@ $root.protos = (function() {
if (message.characterState != null && message.hasOwnProperty("characterState"))
if (!$util.isInteger(message.characterState))
return "characterState: integer expected";
if (message.inAir != null && message.hasOwnProperty("inAir"))
if (typeof message.inAir !== "boolean")
return "inAir: boolean expected";
if (message.name != null && message.hasOwnProperty("name"))
if (!$util.isString(message.name))
return "name: string expected";
@@ -1668,6 +1722,10 @@ $root.protos = (function() {
message.dirX = object.dirX | 0;
if (object.dirY != null)
message.dirY = object.dirY | 0;
if (object.velX != null)
message.velX = object.velX | 0;
if (object.velY != null)
message.velY = object.velY | 0;
if (object.speed != null)
message.speed = object.speed | 0;
if (object.battleState != null)
@@ -1690,6 +1748,8 @@ $root.protos = (function() {
message.maxHp = object.maxHp | 0;
if (object.characterState != null)
message.characterState = object.characterState | 0;
if (object.inAir != null)
message.inAir = Boolean(object.inAir);
if (object.name != null)
message.name = String(object.name);
if (object.displayName != null)
@@ -1718,6 +1778,8 @@ $root.protos = (function() {
object.virtualGridY = 0;
object.dirX = 0;
object.dirY = 0;
object.velX = 0;
object.velY = 0;
object.speed = 0;
object.battleState = 0;
object.joinIndex = 0;
@@ -1729,6 +1791,7 @@ $root.protos = (function() {
object.hp = 0;
object.maxHp = 0;
object.characterState = 0;
object.inAir = false;
object.name = "";
object.displayName = "";
object.avatar = "";
@@ -1743,6 +1806,10 @@ $root.protos = (function() {
object.dirX = message.dirX;
if (message.dirY != null && message.hasOwnProperty("dirY"))
object.dirY = message.dirY;
if (message.velX != null && message.hasOwnProperty("velX"))
object.velX = message.velX;
if (message.velY != null && message.hasOwnProperty("velY"))
object.velY = message.velY;
if (message.speed != null && message.hasOwnProperty("speed"))
object.speed = message.speed;
if (message.battleState != null && message.hasOwnProperty("battleState"))
@@ -1765,6 +1832,8 @@ $root.protos = (function() {
object.maxHp = message.maxHp;
if (message.characterState != null && message.hasOwnProperty("characterState"))
object.characterState = message.characterState;
if (message.inAir != null && message.hasOwnProperty("inAir"))
object.inAir = message.inAir;
if (message.name != null && message.hasOwnProperty("name"))
object.name = message.name;
if (message.displayName != null && message.hasOwnProperty("displayName"))
@@ -1812,6 +1881,7 @@ $root.protos = (function() {
* @property {number|null} [dx] InputFrameDecoded dx
* @property {number|null} [dy] InputFrameDecoded dy
* @property {number|null} [btnALevel] InputFrameDecoded btnALevel
* @property {number|null} [btnBLevel] InputFrameDecoded btnBLevel
*/
/**
@@ -1853,6 +1923,14 @@ $root.protos = (function() {
*/
InputFrameDecoded.prototype.btnALevel = 0;
/**
* InputFrameDecoded btnBLevel.
* @member {number} btnBLevel
* @memberof protos.InputFrameDecoded
* @instance
*/
InputFrameDecoded.prototype.btnBLevel = 0;
/**
* Creates a new InputFrameDecoded instance using the specified properties.
* @function create
@@ -1883,6 +1961,8 @@ $root.protos = (function() {
writer.uint32(/* id 2, wireType 0 =*/16).int32(message.dy);
if (message.btnALevel != null && Object.hasOwnProperty.call(message, "btnALevel"))
writer.uint32(/* id 3, wireType 0 =*/24).int32(message.btnALevel);
if (message.btnBLevel != null && Object.hasOwnProperty.call(message, "btnBLevel"))
writer.uint32(/* id 4, wireType 0 =*/32).int32(message.btnBLevel);
return writer;
};
@@ -1929,6 +2009,10 @@ $root.protos = (function() {
message.btnALevel = reader.int32();
break;
}
case 4: {
message.btnBLevel = reader.int32();
break;
}
default:
reader.skipType(tag & 7);
break;
@@ -1973,6 +2057,9 @@ $root.protos = (function() {
if (message.btnALevel != null && message.hasOwnProperty("btnALevel"))
if (!$util.isInteger(message.btnALevel))
return "btnALevel: integer expected";
if (message.btnBLevel != null && message.hasOwnProperty("btnBLevel"))
if (!$util.isInteger(message.btnBLevel))
return "btnBLevel: integer expected";
return null;
};
@@ -1994,6 +2081,8 @@ $root.protos = (function() {
message.dy = object.dy | 0;
if (object.btnALevel != null)
message.btnALevel = object.btnALevel | 0;
if (object.btnBLevel != null)
message.btnBLevel = object.btnBLevel | 0;
return message;
};
@@ -2014,6 +2103,7 @@ $root.protos = (function() {
object.dx = 0;
object.dy = 0;
object.btnALevel = 0;
object.btnBLevel = 0;
}
if (message.dx != null && message.hasOwnProperty("dx"))
object.dx = message.dx;
@@ -2021,6 +2111,8 @@ $root.protos = (function() {
object.dy = message.dy;
if (message.btnALevel != null && message.hasOwnProperty("btnALevel"))
object.btnALevel = message.btnALevel;
if (message.btnBLevel != null && message.hasOwnProperty("btnBLevel"))
object.btnBLevel = message.btnBLevel;
return object;
};
@@ -3553,6 +3645,292 @@ $root.protos = (function() {
return WsResp;
})();
protos.InputsBufferSnapshot = (function() {
/**
* Properties of an InputsBufferSnapshot.
* @memberof protos
* @interface IInputsBufferSnapshot
* @property {number|null} [refRenderFrameId] InputsBufferSnapshot refRenderFrameId
* @property {number|Long|null} [unconfirmedMask] InputsBufferSnapshot unconfirmedMask
* @property {Array.<protos.InputFrameDownsync>|null} [toSendInputFrameDownsyncs] InputsBufferSnapshot toSendInputFrameDownsyncs
*/
/**
* Constructs a new InputsBufferSnapshot.
* @memberof protos
* @classdesc Represents an InputsBufferSnapshot.
* @implements IInputsBufferSnapshot
* @constructor
* @param {protos.IInputsBufferSnapshot=} [properties] Properties to set
*/
function InputsBufferSnapshot(properties) {
this.toSendInputFrameDownsyncs = [];
if (properties)
for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
if (properties[keys[i]] != null)
this[keys[i]] = properties[keys[i]];
}
/**
* InputsBufferSnapshot refRenderFrameId.
* @member {number} refRenderFrameId
* @memberof protos.InputsBufferSnapshot
* @instance
*/
InputsBufferSnapshot.prototype.refRenderFrameId = 0;
/**
* InputsBufferSnapshot unconfirmedMask.
* @member {number|Long} unconfirmedMask
* @memberof protos.InputsBufferSnapshot
* @instance
*/
InputsBufferSnapshot.prototype.unconfirmedMask = $util.Long ? $util.Long.fromBits(0,0,true) : 0;
/**
* InputsBufferSnapshot toSendInputFrameDownsyncs.
* @member {Array.<protos.InputFrameDownsync>} toSendInputFrameDownsyncs
* @memberof protos.InputsBufferSnapshot
* @instance
*/
InputsBufferSnapshot.prototype.toSendInputFrameDownsyncs = $util.emptyArray;
/**
* Creates a new InputsBufferSnapshot instance using the specified properties.
* @function create
* @memberof protos.InputsBufferSnapshot
* @static
* @param {protos.IInputsBufferSnapshot=} [properties] Properties to set
* @returns {protos.InputsBufferSnapshot} InputsBufferSnapshot instance
*/
InputsBufferSnapshot.create = function create(properties) {
return new InputsBufferSnapshot(properties);
};
/**
* Encodes the specified InputsBufferSnapshot message. Does not implicitly {@link protos.InputsBufferSnapshot.verify|verify} messages.
* @function encode
* @memberof protos.InputsBufferSnapshot
* @static
* @param {protos.InputsBufferSnapshot} message InputsBufferSnapshot message or plain object to encode
* @param {$protobuf.Writer} [writer] Writer to encode to
* @returns {$protobuf.Writer} Writer
*/
InputsBufferSnapshot.encode = function encode(message, writer) {
if (!writer)
writer = $Writer.create();
if (message.refRenderFrameId != null && Object.hasOwnProperty.call(message, "refRenderFrameId"))
writer.uint32(/* id 1, wireType 0 =*/8).int32(message.refRenderFrameId);
if (message.unconfirmedMask != null && Object.hasOwnProperty.call(message, "unconfirmedMask"))
writer.uint32(/* id 2, wireType 0 =*/16).uint64(message.unconfirmedMask);
if (message.toSendInputFrameDownsyncs != null && message.toSendInputFrameDownsyncs.length)
for (var i = 0; i < message.toSendInputFrameDownsyncs.length; ++i)
$root.protos.InputFrameDownsync.encode(message.toSendInputFrameDownsyncs[i], writer.uint32(/* id 3, wireType 2 =*/26).fork()).ldelim();
return writer;
};
/**
* Encodes the specified InputsBufferSnapshot message, length delimited. Does not implicitly {@link protos.InputsBufferSnapshot.verify|verify} messages.
* @function encodeDelimited
* @memberof protos.InputsBufferSnapshot
* @static
* @param {protos.InputsBufferSnapshot} message InputsBufferSnapshot message or plain object to encode
* @param {$protobuf.Writer} [writer] Writer to encode to
* @returns {$protobuf.Writer} Writer
*/
InputsBufferSnapshot.encodeDelimited = function encodeDelimited(message, writer) {
return this.encode(message, writer).ldelim();
};
/**
* Decodes an InputsBufferSnapshot message from the specified reader or buffer.
* @function decode
* @memberof protos.InputsBufferSnapshot
* @static
* @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
* @param {number} [length] Message length if known beforehand
* @returns {protos.InputsBufferSnapshot} InputsBufferSnapshot
* @throws {Error} If the payload is not a reader or valid buffer
* @throws {$protobuf.util.ProtocolError} If required fields are missing
*/
InputsBufferSnapshot.decode = function decode(reader, length) {
if (!(reader instanceof $Reader))
reader = $Reader.create(reader);
var end = length === undefined ? reader.len : reader.pos + length, message = new $root.protos.InputsBufferSnapshot();
while (reader.pos < end) {
var tag = reader.uint32();
switch (tag >>> 3) {
case 1: {
message.refRenderFrameId = reader.int32();
break;
}
case 2: {
message.unconfirmedMask = reader.uint64();
break;
}
case 3: {
if (!(message.toSendInputFrameDownsyncs && message.toSendInputFrameDownsyncs.length))
message.toSendInputFrameDownsyncs = [];
message.toSendInputFrameDownsyncs.push($root.protos.InputFrameDownsync.decode(reader, reader.uint32()));
break;
}
default:
reader.skipType(tag & 7);
break;
}
}
return message;
};
/**
* Decodes an InputsBufferSnapshot message from the specified reader or buffer, length delimited.
* @function decodeDelimited
* @memberof protos.InputsBufferSnapshot
* @static
* @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
* @returns {protos.InputsBufferSnapshot} InputsBufferSnapshot
* @throws {Error} If the payload is not a reader or valid buffer
* @throws {$protobuf.util.ProtocolError} If required fields are missing
*/
InputsBufferSnapshot.decodeDelimited = function decodeDelimited(reader) {
if (!(reader instanceof $Reader))
reader = new $Reader(reader);
return this.decode(reader, reader.uint32());
};
/**
* Verifies an InputsBufferSnapshot message.
* @function verify
* @memberof protos.InputsBufferSnapshot
* @static
* @param {Object.<string,*>} message Plain object to verify
* @returns {string|null} `null` if valid, otherwise the reason why it is not
*/
InputsBufferSnapshot.verify = function verify(message) {
if (typeof message !== "object" || message === null)
return "object expected";
if (message.refRenderFrameId != null && message.hasOwnProperty("refRenderFrameId"))
if (!$util.isInteger(message.refRenderFrameId))
return "refRenderFrameId: integer expected";
if (message.unconfirmedMask != null && message.hasOwnProperty("unconfirmedMask"))
if (!$util.isInteger(message.unconfirmedMask) && !(message.unconfirmedMask && $util.isInteger(message.unconfirmedMask.low) && $util.isInteger(message.unconfirmedMask.high)))
return "unconfirmedMask: integer|Long expected";
if (message.toSendInputFrameDownsyncs != null && message.hasOwnProperty("toSendInputFrameDownsyncs")) {
if (!Array.isArray(message.toSendInputFrameDownsyncs))
return "toSendInputFrameDownsyncs: array expected";
for (var i = 0; i < message.toSendInputFrameDownsyncs.length; ++i) {
var error = $root.protos.InputFrameDownsync.verify(message.toSendInputFrameDownsyncs[i]);
if (error)
return "toSendInputFrameDownsyncs." + error;
}
}
return null;
};
/**
* Creates an InputsBufferSnapshot message from a plain object. Also converts values to their respective internal types.
* @function fromObject
* @memberof protos.InputsBufferSnapshot
* @static
* @param {Object.<string,*>} object Plain object
* @returns {protos.InputsBufferSnapshot} InputsBufferSnapshot
*/
InputsBufferSnapshot.fromObject = function fromObject(object) {
if (object instanceof $root.protos.InputsBufferSnapshot)
return object;
var message = new $root.protos.InputsBufferSnapshot();
if (object.refRenderFrameId != null)
message.refRenderFrameId = object.refRenderFrameId | 0;
if (object.unconfirmedMask != null)
if ($util.Long)
(message.unconfirmedMask = $util.Long.fromValue(object.unconfirmedMask)).unsigned = true;
else if (typeof object.unconfirmedMask === "string")
message.unconfirmedMask = parseInt(object.unconfirmedMask, 10);
else if (typeof object.unconfirmedMask === "number")
message.unconfirmedMask = object.unconfirmedMask;
else if (typeof object.unconfirmedMask === "object")
message.unconfirmedMask = new $util.LongBits(object.unconfirmedMask.low >>> 0, object.unconfirmedMask.high >>> 0).toNumber(true);
if (object.toSendInputFrameDownsyncs) {
if (!Array.isArray(object.toSendInputFrameDownsyncs))
throw TypeError(".protos.InputsBufferSnapshot.toSendInputFrameDownsyncs: array expected");
message.toSendInputFrameDownsyncs = [];
for (var i = 0; i < object.toSendInputFrameDownsyncs.length; ++i) {
if (typeof object.toSendInputFrameDownsyncs[i] !== "object")
throw TypeError(".protos.InputsBufferSnapshot.toSendInputFrameDownsyncs: object expected");
message.toSendInputFrameDownsyncs[i] = $root.protos.InputFrameDownsync.fromObject(object.toSendInputFrameDownsyncs[i]);
}
}
return message;
};
/**
* Creates a plain object from an InputsBufferSnapshot message. Also converts values to other types if specified.
* @function toObject
* @memberof protos.InputsBufferSnapshot
* @static
* @param {protos.InputsBufferSnapshot} message InputsBufferSnapshot
* @param {$protobuf.IConversionOptions} [options] Conversion options
* @returns {Object.<string,*>} Plain object
*/
InputsBufferSnapshot.toObject = function toObject(message, options) {
if (!options)
options = {};
var object = {};
if (options.arrays || options.defaults)
object.toSendInputFrameDownsyncs = [];
if (options.defaults) {
object.refRenderFrameId = 0;
if ($util.Long) {
var long = new $util.Long(0, 0, true);
object.unconfirmedMask = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
} else
object.unconfirmedMask = options.longs === String ? "0" : 0;
}
if (message.refRenderFrameId != null && message.hasOwnProperty("refRenderFrameId"))
object.refRenderFrameId = message.refRenderFrameId;
if (message.unconfirmedMask != null && message.hasOwnProperty("unconfirmedMask"))
if (typeof message.unconfirmedMask === "number")
object.unconfirmedMask = options.longs === String ? String(message.unconfirmedMask) : message.unconfirmedMask;
else
object.unconfirmedMask = options.longs === String ? $util.Long.prototype.toString.call(message.unconfirmedMask) : options.longs === Number ? new $util.LongBits(message.unconfirmedMask.low >>> 0, message.unconfirmedMask.high >>> 0).toNumber(true) : message.unconfirmedMask;
if (message.toSendInputFrameDownsyncs && message.toSendInputFrameDownsyncs.length) {
object.toSendInputFrameDownsyncs = [];
for (var j = 0; j < message.toSendInputFrameDownsyncs.length; ++j)
object.toSendInputFrameDownsyncs[j] = $root.protos.InputFrameDownsync.toObject(message.toSendInputFrameDownsyncs[j], options);
}
return object;
};
/**
* Converts this InputsBufferSnapshot to JSON.
* @function toJSON
* @memberof protos.InputsBufferSnapshot
* @instance
* @returns {Object.<string,*>} JSON object
*/
InputsBufferSnapshot.prototype.toJSON = function toJSON() {
return this.constructor.toObject(this, $protobuf.util.toJSONOptions);
};
/**
* Gets the default type url for InputsBufferSnapshot
* @function getTypeUrl
* @memberof protos.InputsBufferSnapshot
* @static
* @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com")
* @returns {string} The default type url
*/
InputsBufferSnapshot.getTypeUrl = function getTypeUrl(typeUrlPrefix) {
if (typeUrlPrefix === undefined) {
typeUrlPrefix = "type.googleapis.com";
}
return typeUrlPrefix + "/protos.InputsBufferSnapshot";
};
return InputsBufferSnapshot;
})();
protos.MeleeBullet = (function() {
/**
@@ -4167,6 +4545,11 @@ $root.protos = (function() {
* @property {number|null} [spAtkLookupFrames] BattleColliderInfo spAtkLookupFrames
* @property {number|null} [renderCacheSize] BattleColliderInfo renderCacheSize
* @property {Object.<string,protos.MeleeBullet>|null} [meleeSkillConfig] BattleColliderInfo meleeSkillConfig
* @property {number|null} [snapIntoPlatformOverlap] BattleColliderInfo snapIntoPlatformOverlap
* @property {number|null} [snapIntoPlatformThreshold] BattleColliderInfo snapIntoPlatformThreshold
* @property {number|null} [jumpingInitVelY] BattleColliderInfo jumpingInitVelY
* @property {number|null} [gravityX] BattleColliderInfo gravityX
* @property {number|null} [gravityY] BattleColliderInfo gravityY
*/
/**
@@ -4395,6 +4778,46 @@ $root.protos = (function() {
*/
BattleColliderInfo.prototype.meleeSkillConfig = $util.emptyObject;
/**
* BattleColliderInfo snapIntoPlatformOverlap.
* @member {number} snapIntoPlatformOverlap
* @memberof protos.BattleColliderInfo
* @instance
*/
BattleColliderInfo.prototype.snapIntoPlatformOverlap = 0;
/**
* BattleColliderInfo snapIntoPlatformThreshold.
* @member {number} snapIntoPlatformThreshold
* @memberof protos.BattleColliderInfo
* @instance
*/
BattleColliderInfo.prototype.snapIntoPlatformThreshold = 0;
/**
* BattleColliderInfo jumpingInitVelY.
* @member {number} jumpingInitVelY
* @memberof protos.BattleColliderInfo
* @instance
*/
BattleColliderInfo.prototype.jumpingInitVelY = 0;
/**
* BattleColliderInfo gravityX.
* @member {number} gravityX
* @memberof protos.BattleColliderInfo
* @instance
*/
BattleColliderInfo.prototype.gravityX = 0;
/**
* BattleColliderInfo gravityY.
* @member {number} gravityY
* @memberof protos.BattleColliderInfo
* @instance
*/
BattleColliderInfo.prototype.gravityY = 0;
/**
* Creates a new BattleColliderInfo instance using the specified properties.
* @function create
@@ -4480,6 +4903,16 @@ $root.protos = (function() {
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();
}
if (message.snapIntoPlatformOverlap != null && Object.hasOwnProperty.call(message, "snapIntoPlatformOverlap"))
writer.uint32(/* id 28, wireType 1 =*/225).double(message.snapIntoPlatformOverlap);
if (message.snapIntoPlatformThreshold != null && Object.hasOwnProperty.call(message, "snapIntoPlatformThreshold"))
writer.uint32(/* id 29, wireType 1 =*/233).double(message.snapIntoPlatformThreshold);
if (message.jumpingInitVelY != null && Object.hasOwnProperty.call(message, "jumpingInitVelY"))
writer.uint32(/* id 30, wireType 0 =*/240).int32(message.jumpingInitVelY);
if (message.gravityX != null && Object.hasOwnProperty.call(message, "gravityX"))
writer.uint32(/* id 31, wireType 0 =*/248).int32(message.gravityX);
if (message.gravityY != null && Object.hasOwnProperty.call(message, "gravityY"))
writer.uint32(/* id 32, wireType 0 =*/256).int32(message.gravityY);
return writer;
};
@@ -4675,6 +5108,26 @@ $root.protos = (function() {
message.meleeSkillConfig[key] = value;
break;
}
case 28: {
message.snapIntoPlatformOverlap = reader.double();
break;
}
case 29: {
message.snapIntoPlatformThreshold = reader.double();
break;
}
case 30: {
message.jumpingInitVelY = reader.int32();
break;
}
case 31: {
message.gravityX = reader.int32();
break;
}
case 32: {
message.gravityY = reader.int32();
break;
}
default:
reader.skipType(tag & 7);
break;
@@ -4813,6 +5266,21 @@ $root.protos = (function() {
}
}
}
if (message.snapIntoPlatformOverlap != null && message.hasOwnProperty("snapIntoPlatformOverlap"))
if (typeof message.snapIntoPlatformOverlap !== "number")
return "snapIntoPlatformOverlap: number expected";
if (message.snapIntoPlatformThreshold != null && message.hasOwnProperty("snapIntoPlatformThreshold"))
if (typeof message.snapIntoPlatformThreshold !== "number")
return "snapIntoPlatformThreshold: number expected";
if (message.jumpingInitVelY != null && message.hasOwnProperty("jumpingInitVelY"))
if (!$util.isInteger(message.jumpingInitVelY))
return "jumpingInitVelY: integer expected";
if (message.gravityX != null && message.hasOwnProperty("gravityX"))
if (!$util.isInteger(message.gravityX))
return "gravityX: integer expected";
if (message.gravityY != null && message.hasOwnProperty("gravityY"))
if (!$util.isInteger(message.gravityY))
return "gravityY: integer expected";
return null;
};
@@ -4918,6 +5386,16 @@ $root.protos = (function() {
message.meleeSkillConfig[keys[i]] = $root.protos.MeleeBullet.fromObject(object.meleeSkillConfig[keys[i]]);
}
}
if (object.snapIntoPlatformOverlap != null)
message.snapIntoPlatformOverlap = Number(object.snapIntoPlatformOverlap);
if (object.snapIntoPlatformThreshold != null)
message.snapIntoPlatformThreshold = Number(object.snapIntoPlatformThreshold);
if (object.jumpingInitVelY != null)
message.jumpingInitVelY = object.jumpingInitVelY | 0;
if (object.gravityX != null)
message.gravityX = object.gravityX | 0;
if (object.gravityY != null)
message.gravityY = object.gravityY | 0;
return message;
};
@@ -4971,6 +5449,11 @@ $root.protos = (function() {
object.virtualGridToWorldRatio = 0;
object.spAtkLookupFrames = 0;
object.renderCacheSize = 0;
object.snapIntoPlatformOverlap = 0;
object.snapIntoPlatformThreshold = 0;
object.jumpingInitVelY = 0;
object.gravityX = 0;
object.gravityY = 0;
}
if (message.stageName != null && message.hasOwnProperty("stageName"))
object.stageName = message.stageName;
@@ -5040,6 +5523,16 @@ $root.protos = (function() {
for (var j = 0; j < keys2.length; ++j)
object.meleeSkillConfig[keys2[j]] = $root.protos.MeleeBullet.toObject(message.meleeSkillConfig[keys2[j]], options);
}
if (message.snapIntoPlatformOverlap != null && message.hasOwnProperty("snapIntoPlatformOverlap"))
object.snapIntoPlatformOverlap = options.json && !isFinite(message.snapIntoPlatformOverlap) ? String(message.snapIntoPlatformOverlap) : message.snapIntoPlatformOverlap;
if (message.snapIntoPlatformThreshold != null && message.hasOwnProperty("snapIntoPlatformThreshold"))
object.snapIntoPlatformThreshold = options.json && !isFinite(message.snapIntoPlatformThreshold) ? String(message.snapIntoPlatformThreshold) : message.snapIntoPlatformThreshold;
if (message.jumpingInitVelY != null && message.hasOwnProperty("jumpingInitVelY"))
object.jumpingInitVelY = message.jumpingInitVelY;
if (message.gravityX != null && message.hasOwnProperty("gravityX"))
object.gravityX = message.gravityX;
if (message.gravityY != null && message.hasOwnProperty("gravityY"))
object.gravityY = message.gravityY;
return object;
};

View File

@@ -11,24 +11,28 @@ function polygonStr(body) {
return JSON.stringify(coords);
}
const playerCollider = collisionSys.createPolygon(1269.665, 1353.335, [[0, 0], [64, 0], [64, 64], [0, 64]]);
const playerCollider1 = collisionSys.createPolygon(944.000, 676.000, [[0, 0], [24, 0], [24, 48], [0, 48]]);
playerCollider1.data = {isPlayer: true};
const playerCollider2 = collisionSys.createPolygon(958.000, 724.000, [[0, 0], [24, 0], [24, 48], [0, 48]]);
playerCollider2.data = {isPlayer: true};
const barrierCollider1 = collisionSys.createPolygon(1277.7159000000001, 1570.5575, [[642.5696, 319.159], [0, 319.15680000000003], [5.7286, 0], [643.7451, 0.9014999999999986]]);
const barrierCollider2 = collisionSys.createPolygon(1289.039, 1318.0805, [[628.626, 54.254500000000064], [0, 56.03250000000003], [0.42449999999999477, 1.1229999999999905], [625.9715000000001, 0]]);
const barrierCollider3 = collisionSys.createPolygon(1207, 1310, [[69, 581], [0, 579], [8, 3], [79, 0]]);
playerCollider.x += -2.98;
playerCollider.y += -50.0;
collisionSys.update();
const effPushback = [0.0, 0.0];
const result = collisionSys.createResult();
const potentials = playerCollider.potentials();
for (const barrier of potentials) {
if (!playerCollider.collides(barrier, result)) continue;
// Check collision for player1
const potentials = playerCollider1.potentials();
for (const potential of potentials) {
if (null == potential.data || true != potential.data.isPlayer) continue;
console.log(`Collided player potential of a=${polygonStr(playerCollider1)}: b=${polygonStr(potential)}`);
if (!playerCollider1.collides(potential, result)) continue;
console.log(`Collided player of a=${polygonStr(playerCollider1)}: b=${polygonStr(potential)}`);
const pushbackX = result.overlap * result.overlap_x;
const pushbackY = result.overlap * result.overlap_y;
console.log(`Overlapped: a=${polygonStr(result.a)}, b=${polygonStr(result.b)}, pushbackX=${pushbackX}, pushbackY=${pushbackY}`);