mirror of
				https://github.com/genxium/DelayNoMore
				synced 2025-11-04 13:27:15 +00:00 
			
		
		
		
	A broken commit during backend bullet adaptation.
This commit is contained in:
		@@ -2,7 +2,6 @@ package models
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	. "battle_srv/protos"
 | 
						. "battle_srv/protos"
 | 
				
			||||||
	. "dnmshared/sharedprotos"
 | 
					 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func toPbPlayers(modelInstances map[int32]*Player, withMetaInfo bool) map[int32]*PlayerDownsync {
 | 
					func toPbPlayers(modelInstances map[int32]*Player, withMetaInfo bool) map[int32]*PlayerDownsync {
 | 
				
			||||||
@@ -16,10 +15,8 @@ func toPbPlayers(modelInstances map[int32]*Player, withMetaInfo bool) map[int32]
 | 
				
			|||||||
			Id:             last.Id,
 | 
								Id:             last.Id,
 | 
				
			||||||
			VirtualGridX:   last.VirtualGridX,
 | 
								VirtualGridX:   last.VirtualGridX,
 | 
				
			||||||
			VirtualGridY:   last.VirtualGridY,
 | 
								VirtualGridY:   last.VirtualGridY,
 | 
				
			||||||
			Dir: &Direction{
 | 
								DirX:           last.DirX,
 | 
				
			||||||
				Dx: last.Dir.Dx,
 | 
								DirY:           last.DirY,
 | 
				
			||||||
				Dy: last.Dir.Dy,
 | 
					 | 
				
			||||||
			},
 | 
					 | 
				
			||||||
			ColliderRadius: last.ColliderRadius,
 | 
								ColliderRadius: last.ColliderRadius,
 | 
				
			||||||
			Speed:          last.Speed,
 | 
								Speed:          last.Speed,
 | 
				
			||||||
			BattleState:    last.BattleState,
 | 
								BattleState:    last.BattleState,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -4,7 +4,6 @@ import (
 | 
				
			|||||||
	. "battle_srv/protos"
 | 
						. "battle_srv/protos"
 | 
				
			||||||
	"battle_srv/storage"
 | 
						"battle_srv/storage"
 | 
				
			||||||
	. "dnmshared"
 | 
						. "dnmshared"
 | 
				
			||||||
	. "dnmshared/sharedprotos"
 | 
					 | 
				
			||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
	sq "github.com/Masterminds/squirrel"
 | 
						sq "github.com/Masterminds/squirrel"
 | 
				
			||||||
	"github.com/jmoiron/sqlx"
 | 
						"github.com/jmoiron/sqlx"
 | 
				
			||||||
@@ -64,12 +63,7 @@ func GetPlayerById(id int) (*Player, error) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
func getPlayer(cond sq.Eq) (*Player, error) {
 | 
					func getPlayer(cond sq.Eq) (*Player, error) {
 | 
				
			||||||
	p := Player{}
 | 
						p := Player{}
 | 
				
			||||||
	pd := PlayerDownsync{
 | 
						pd := PlayerDownsync{}
 | 
				
			||||||
		Dir: &Direction{
 | 
					 | 
				
			||||||
			Dx: 0,
 | 
					 | 
				
			||||||
			Dy: 0,
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	query, args, err := sq.Select("*").From("player").Where(cond).Limit(1).ToSql()
 | 
						query, args, err := sq.Select("*").From("player").Where(cond).Limit(1).ToSql()
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -54,6 +54,7 @@ const (
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	COLLISION_PLAYER_INDEX_PREFIX  = (1 << 17)
 | 
						COLLISION_PLAYER_INDEX_PREFIX  = (1 << 17)
 | 
				
			||||||
	COLLISION_BARRIER_INDEX_PREFIX = (1 << 16)
 | 
						COLLISION_BARRIER_INDEX_PREFIX = (1 << 16)
 | 
				
			||||||
 | 
						COLLISION_BULLET_INDEX_PREFIX  = (1 << 15)
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const (
 | 
					const (
 | 
				
			||||||
@@ -1147,13 +1148,6 @@ func (pR *Room) applyInputFrameDownsyncDynamics(fromRenderFrameId int32, toRende
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		nextRenderFrame := pR.applyInputFrameDownsyncDynamicsOnSingleRenderFrame(delayedInputFrame, currRenderFrame, pR.CollisionSysMap)
 | 
							nextRenderFrame := pR.applyInputFrameDownsyncDynamicsOnSingleRenderFrame(delayedInputFrame, currRenderFrame, pR.CollisionSysMap)
 | 
				
			||||||
		// Update in the latest player pointers
 | 
					 | 
				
			||||||
		for playerId, playerDownsync := range nextRenderFrame.Players {
 | 
					 | 
				
			||||||
			pR.Players[playerId].VirtualGridX = playerDownsync.VirtualGridX
 | 
					 | 
				
			||||||
			pR.Players[playerId].VirtualGridY = playerDownsync.VirtualGridY
 | 
					 | 
				
			||||||
			pR.Players[playerId].Dir.Dx = playerDownsync.Dir.Dx
 | 
					 | 
				
			||||||
			pR.Players[playerId].Dir.Dy = playerDownsync.Dir.Dy
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		pR.RenderFrameBuffer.Put(nextRenderFrame)
 | 
							pR.RenderFrameBuffer.Put(nextRenderFrame)
 | 
				
			||||||
		pR.CurDynamicsRenderFrameId++
 | 
							pR.CurDynamicsRenderFrameId++
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -1169,15 +1163,20 @@ func (pR *Room) applyInputFrameDownsyncDynamicsOnSingleRenderFrame(delayedInputF
 | 
				
			|||||||
			Id:              playerId,
 | 
								Id:              playerId,
 | 
				
			||||||
			VirtualGridX:    currPlayerDownsync.VirtualGridX,
 | 
								VirtualGridX:    currPlayerDownsync.VirtualGridX,
 | 
				
			||||||
			VirtualGridY:    currPlayerDownsync.VirtualGridY,
 | 
								VirtualGridY:    currPlayerDownsync.VirtualGridY,
 | 
				
			||||||
			Dir: &Direction{
 | 
								DirX:            currPlayerDownsync.DirX,
 | 
				
			||||||
				Dx: currPlayerDownsync.Dir.Dx,
 | 
								DirY:            currPlayerDownsync.DirY,
 | 
				
			||||||
				Dy: currPlayerDownsync.Dir.Dy,
 | 
								CharacterState:  currPlayerDownsync.CharacterState,
 | 
				
			||||||
			},
 | 
					 | 
				
			||||||
			Speed:           currPlayerDownsync.Speed,
 | 
								Speed:           currPlayerDownsync.Speed,
 | 
				
			||||||
			BattleState:     currPlayerDownsync.BattleState,
 | 
								BattleState:     currPlayerDownsync.BattleState,
 | 
				
			||||||
			Score:           currPlayerDownsync.Score,
 | 
								Score:           currPlayerDownsync.Score,
 | 
				
			||||||
			Removed:         currPlayerDownsync.Removed,
 | 
								Removed:         currPlayerDownsync.Removed,
 | 
				
			||||||
			JoinIndex:       currPlayerDownsync.JoinIndex,
 | 
								JoinIndex:       currPlayerDownsync.JoinIndex,
 | 
				
			||||||
 | 
								FramesToRecover: currPlayerDownsync.FramesToRecover - 1,
 | 
				
			||||||
 | 
								Hp:              currPlayerDownsync.Hp,
 | 
				
			||||||
 | 
								MaxHp:           currPlayerDownsync.MaxHp,
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if nextRenderFramePlayers[playerId].FramesToRecover < 0 {
 | 
				
			||||||
 | 
								nextRenderFramePlayers[playerId].FramesToRecover = 0
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -1185,29 +1184,113 @@ func (pR *Room) applyInputFrameDownsyncDynamicsOnSingleRenderFrame(delayedInputF
 | 
				
			|||||||
		Id:             currRenderFrame.Id + 1,
 | 
							Id:             currRenderFrame.Id + 1,
 | 
				
			||||||
		Players:        nextRenderFramePlayers,
 | 
							Players:        nextRenderFramePlayers,
 | 
				
			||||||
		CountdownNanos: (pR.BattleDurationNanos - int64(currRenderFrame.Id)*pR.RollbackEstimatedDtNanos),
 | 
							CountdownNanos: (pR.BattleDurationNanos - int64(currRenderFrame.Id)*pR.RollbackEstimatedDtNanos),
 | 
				
			||||||
 | 
							MeleeBullets:   make([]*MeleeBullet, 0), // Is there any better way to reduce malloc/free impact, e.g. smart prediction for fixed memory allocation?
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						bulletPushbacks := make([]Vec2D, pR.Capacity) // Guaranteed determinism regardless of traversal order
 | 
				
			||||||
 | 
						effPushbacks := make([]Vec2D, pR.Capacity)    // Guaranteed determinism regardless of traversal order
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Reset playerCollider position from the "virtual grid position"
 | 
				
			||||||
 | 
						for playerId, player := range pR.Players {
 | 
				
			||||||
 | 
							joinIndex := player.JoinIndex
 | 
				
			||||||
 | 
							bulletPushbacks[joinIndex-1].X, bulletPushbacks[joinIndex-1].Y = float64(0), float64(0)
 | 
				
			||||||
 | 
							effPushbacks[joinIndex-1].X, effPushbacks[joinIndex-1].Y = float64(0), float64(0)
 | 
				
			||||||
 | 
							currPlayerDownsync := currRenderFrame.Players[playerId]
 | 
				
			||||||
 | 
							newVx, newVy := currPlayerDownsync.VirtualGridX, currPlayerDownsync.VirtualGridY
 | 
				
			||||||
 | 
							collisionPlayerIndex := COLLISION_PLAYER_INDEX_PREFIX + joinIndex
 | 
				
			||||||
 | 
							playerCollider := collisionSysMap[collisionPlayerIndex]
 | 
				
			||||||
 | 
							playerCollider.X, playerCollider.Y = VirtualGridToPolygonColliderAnchorPos(newVx, newVy, player.ColliderRadius, player.ColliderRadius, pR.collisionSpaceOffsetX, pR.collisionSpaceOffsetY, pR.VirtualGridToWorldRatio)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Check bullet-anything collisions first, because the pushbacks caused by bullets might later be reverted by player-barrier collision
 | 
				
			||||||
 | 
						bulletColliders := make(map[int32]*resolv.Object, 0) // Will all be removed at the end of `applyInputFrameDownsyncDynamicsOnSingleRenderFrame` due to the need for being rollback-compatible
 | 
				
			||||||
 | 
						removedBulletsAtCurrFrame := make(map[int32]int32, 0)
 | 
				
			||||||
 | 
						for _, meleeBullet := range currRenderFrame.MeleeBullets {
 | 
				
			||||||
 | 
							if (meleeBullet.OriginatedRenderFrameId+meleeBullet.StartupFrames <= currRenderFrame.Id) && (meleeBullet.OriginatedRenderFrameId+meleeBullet.StartupFrames+meleeBullet.ActiveFrames > currRenderFrame.Id) {
 | 
				
			||||||
 | 
								collisionBulletIndex := COLLISION_BULLET_INDEX_PREFIX + meleeBullet.BattleLocalId
 | 
				
			||||||
 | 
								collisionOffenderIndex := COLLISION_PLAYER_INDEX_PREFIX + meleeBullet.OffenderJoinIndex
 | 
				
			||||||
 | 
								offenderCollider := collisionSysMap[collisionOffenderIndex]
 | 
				
			||||||
 | 
								offender := currRenderFrame.Players[meleeBullet.OffenderPlayerId]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								xfac, yfac := float64(1.0), float64(0) // By now, straight Punch offset doesn't respect "y-axis"
 | 
				
			||||||
 | 
								if 0 > offender.DirX {
 | 
				
			||||||
 | 
									xfac = float64(-1.0)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								offenderWx, offenderWy := PolygonColliderAnchorToWorldPos(offenderCollider.X, offenderCollider.Y, offender.ColliderRadius, offender.ColliderRadius, pR.collisionSpaceOffsetX, pR.collisionSpaceOffsetY)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								bulletWx, bulletWy := offenderWx+xfac*meleeBullet.HitboxOffset, offenderWy+yfac*meleeBullet.HitboxOffset
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								newBulletCollider := GenerateRectCollider(bulletWx, bulletWy, xfac*meleeBullet.HitboxSize.X, meleeBullet.HitboxSize.Y, pR.collisionSpaceOffsetX, pR.collisionSpaceOffsetY, "MeleeBullet")
 | 
				
			||||||
 | 
								// newBulletCollider.collisionBulletIndex = collisionBulletIndex
 | 
				
			||||||
 | 
								// newBulletCollider.offenderPlayerId = meleeBullet.offenderPlayerId
 | 
				
			||||||
 | 
								// newBulletCollider.pushback = meleeBullet.pushback
 | 
				
			||||||
 | 
								// newBulletCollider.hitStunFrames = meleeBullet.hitStunFrames
 | 
				
			||||||
 | 
								collisionSysMap[collisionBulletIndex] = newBulletCollider
 | 
				
			||||||
 | 
								bulletColliders[collisionBulletIndex] = newBulletCollider
 | 
				
			||||||
 | 
								newBulletCollider.Update()
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// for _, bulletCollider := range bulletColliders {
 | 
				
			||||||
 | 
						// 	shouldRemove := false
 | 
				
			||||||
 | 
						// 	if collision := bulletCollider.Check(0, 0); collision != nil {
 | 
				
			||||||
 | 
						// 		bulletShape := bulletCollider.Shape.(*resolv.ConvexPolygon)
 | 
				
			||||||
 | 
						// 		for _, obj := range collision.Objects {
 | 
				
			||||||
 | 
						// 			bShape := obj.Shape.(*resolv.ConvexPolygon)
 | 
				
			||||||
 | 
						// 			if overlapped, pushbackX, pushbackY, overlapResult := CalcPushbacks(0, 0, bulletShape, bShape); overlapped {
 | 
				
			||||||
 | 
						// 				bulletPushbacks[joinIndex-1].X += pushbackX
 | 
				
			||||||
 | 
						// 				bulletPushbacks[joinIndex-1].Y += pushbackY
 | 
				
			||||||
 | 
						// 			}
 | 
				
			||||||
 | 
						// 		}
 | 
				
			||||||
 | 
						// 		shouldRemove = true
 | 
				
			||||||
 | 
						// 	}
 | 
				
			||||||
 | 
						// 	if shouldRemove {
 | 
				
			||||||
 | 
						// 		removedBulletsAtCurrFrame[bulletCollider.CollisionBulletIndex] = 1
 | 
				
			||||||
 | 
						// 	}
 | 
				
			||||||
 | 
						// }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for _, meleeBullet := range currRenderFrame.MeleeBullets {
 | 
				
			||||||
 | 
							collisionBulletIndex := COLLISION_BULLET_INDEX_PREFIX + meleeBullet.BattleLocalId
 | 
				
			||||||
 | 
							if bulletCollider, existent := collisionSysMap[collisionBulletIndex]; existent {
 | 
				
			||||||
 | 
								bulletCollider.Space.Remove(bulletCollider)
 | 
				
			||||||
 | 
								delete(collisionSysMap, collisionBulletIndex)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if _, existent := removedBulletsAtCurrFrame[collisionBulletIndex]; existent {
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							toRet.MeleeBullets = append(toRet.MeleeBullets, meleeBullet)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if nil != delayedInputFrame {
 | 
						if nil != delayedInputFrame {
 | 
				
			||||||
		inputList := delayedInputFrame.InputList
 | 
							inputList := delayedInputFrame.InputList
 | 
				
			||||||
		effPushbacks := make([]Vec2D, pR.Capacity) // Guaranteed determinism regardless of traversal order
 | 
							// Process player inputs
 | 
				
			||||||
		for playerId, player := range pR.Players {
 | 
							for playerId, player := range pR.Players {
 | 
				
			||||||
			joinIndex := player.JoinIndex
 | 
								joinIndex := player.JoinIndex
 | 
				
			||||||
			effPushbacks[joinIndex-1].X, effPushbacks[joinIndex-1].Y = float64(0), float64(0)
 | 
					 | 
				
			||||||
			currPlayerDownsync := currRenderFrame.Players[playerId]
 | 
					 | 
				
			||||||
			decodedInput := pR.decodeInput(inputList[joinIndex-1])
 | 
					 | 
				
			||||||
			proposedVirtualGridDx, proposedVirtualGridDy := (decodedInput.Dx + decodedInput.Dx*currPlayerDownsync.Speed), (decodedInput.Dy + decodedInput.Dy*currPlayerDownsync.Speed)
 | 
					 | 
				
			||||||
			newVx, newVy := (currPlayerDownsync.VirtualGridX + proposedVirtualGridDx), (currPlayerDownsync.VirtualGridY + proposedVirtualGridDy)
 | 
					 | 
				
			||||||
			// Reset playerCollider position from the "virtual grid position"
 | 
					 | 
				
			||||||
			collisionPlayerIndex := COLLISION_PLAYER_INDEX_PREFIX + joinIndex
 | 
								collisionPlayerIndex := COLLISION_PLAYER_INDEX_PREFIX + joinIndex
 | 
				
			||||||
			playerCollider := collisionSysMap[collisionPlayerIndex]
 | 
								playerCollider := collisionSysMap[collisionPlayerIndex]
 | 
				
			||||||
			playerCollider.X, playerCollider.Y = VirtualGridToPolygonColliderAnchorPos(newVx, newVy, player.ColliderRadius, player.ColliderRadius, pR.collisionSpaceOffsetX, pR.collisionSpaceOffsetY, pR.VirtualGridToWorldRatio)
 | 
								if 0 < nextRenderFramePlayers[playerId].FramesToRecover {
 | 
				
			||||||
 | 
									// No need to process inputs for this player, but there might be bullet pushbacks on this player
 | 
				
			||||||
 | 
									playerCollider.X += bulletPushbacks[joinIndex-1].X
 | 
				
			||||||
 | 
									playerCollider.Y += bulletPushbacks[joinIndex-1].Y
 | 
				
			||||||
 | 
									continue
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								currPlayerDownsync := currRenderFrame.Players[playerId]
 | 
				
			||||||
 | 
								decodedInput := pR.decodeInput(inputList[joinIndex-1])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if 0 != decodedInput.Dx || 0 != decodedInput.Dy {
 | 
				
			||||||
 | 
									nextRenderFramePlayers[playerId].DirX = decodedInput.Dx
 | 
				
			||||||
 | 
									nextRenderFramePlayers[playerId].DirY = decodedInput.Dy
 | 
				
			||||||
 | 
									nextRenderFramePlayers[playerId].CharacterState = 1
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									nextRenderFramePlayers[playerId].CharacterState = 0
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								movementX, movementY := VirtualGridToWorldPos(decodedInput.Dx+decodedInput.Dx*currPlayerDownsync.Speed, decodedInput.Dy+decodedInput.Dy*currPlayerDownsync.Speed, pR.VirtualGridToWorldRatio)
 | 
				
			||||||
 | 
								playerCollider.X += movementX
 | 
				
			||||||
 | 
								playerCollider.Y += movementY
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			// Update in the collision system
 | 
								// Update in the collision system
 | 
				
			||||||
			playerCollider.Update()
 | 
								playerCollider.Update()
 | 
				
			||||||
			if 0 != decodedInput.Dx || 0 != decodedInput.Dy {
 | 
					 | 
				
			||||||
				nextRenderFramePlayers[playerId].Dir.Dx = decodedInput.Dx
 | 
					 | 
				
			||||||
				nextRenderFramePlayers[playerId].Dir.Dy = decodedInput.Dy
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// handle pushbacks upon collision after all movements treated as simultaneous
 | 
							// handle pushbacks upon collision after all movements treated as simultaneous
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,7 +1,7 @@
 | 
				
			|||||||
// Code generated by protoc-gen-go. DO NOT EDIT.
 | 
					// Code generated by protoc-gen-go. DO NOT EDIT.
 | 
				
			||||||
// versions:
 | 
					// versions:
 | 
				
			||||||
// 	protoc-gen-go v1.28.1
 | 
					// 	protoc-gen-go v1.28.1
 | 
				
			||||||
// 	protoc        v3.7.1
 | 
					// 	protoc        v3.21.4
 | 
				
			||||||
// source: room_downsync_frame.proto
 | 
					// source: room_downsync_frame.proto
 | 
				
			||||||
 | 
					
 | 
				
			||||||
package protos
 | 
					package protos
 | 
				
			||||||
@@ -260,21 +260,22 @@ type PlayerDownsync struct {
 | 
				
			|||||||
	Id                int32   `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"`
 | 
						Id                int32   `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"`
 | 
				
			||||||
	VirtualGridX      int32   `protobuf:"varint,2,opt,name=virtualGridX,proto3" json:"virtualGridX,omitempty"`
 | 
						VirtualGridX      int32   `protobuf:"varint,2,opt,name=virtualGridX,proto3" json:"virtualGridX,omitempty"`
 | 
				
			||||||
	VirtualGridY      int32   `protobuf:"varint,3,opt,name=virtualGridY,proto3" json:"virtualGridY,omitempty"`
 | 
						VirtualGridY      int32   `protobuf:"varint,3,opt,name=virtualGridY,proto3" json:"virtualGridY,omitempty"`
 | 
				
			||||||
	Dir               *sharedprotos.Direction `protobuf:"bytes,4,opt,name=dir,proto3" json:"dir,omitempty"`
 | 
						DirX              int32   `protobuf:"varint,4,opt,name=dirX,proto3" json:"dirX,omitempty"`
 | 
				
			||||||
	Speed             int32                   `protobuf:"varint,5,opt,name=speed,proto3" json:"speed,omitempty"` // in terms of virtual grid units
 | 
						DirY              int32   `protobuf:"varint,5,opt,name=dirY,proto3" json:"dirY,omitempty"`
 | 
				
			||||||
	BattleState       int32                   `protobuf:"varint,6,opt,name=battleState,proto3" json:"battleState,omitempty"`
 | 
						Speed             int32   `protobuf:"varint,6,opt,name=speed,proto3" json:"speed,omitempty"` // in terms of virtual grid units
 | 
				
			||||||
	JoinIndex         int32                   `protobuf:"varint,7,opt,name=joinIndex,proto3" json:"joinIndex,omitempty"`
 | 
						BattleState       int32   `protobuf:"varint,7,opt,name=battleState,proto3" json:"battleState,omitempty"`
 | 
				
			||||||
	ColliderRadius    float64                 `protobuf:"fixed64,8,opt,name=colliderRadius,proto3" json:"colliderRadius,omitempty"`
 | 
						JoinIndex         int32   `protobuf:"varint,8,opt,name=joinIndex,proto3" json:"joinIndex,omitempty"`
 | 
				
			||||||
	Removed           bool                    `protobuf:"varint,9,opt,name=removed,proto3" json:"removed,omitempty"`
 | 
						ColliderRadius    float64 `protobuf:"fixed64,9,opt,name=colliderRadius,proto3" json:"colliderRadius,omitempty"`
 | 
				
			||||||
	Score             int32                   `protobuf:"varint,10,opt,name=score,proto3" json:"score,omitempty"`
 | 
						Removed           bool    `protobuf:"varint,10,opt,name=removed,proto3" json:"removed,omitempty"`
 | 
				
			||||||
	LastMoveGmtMillis int32                   `protobuf:"varint,11,opt,name=lastMoveGmtMillis,proto3" json:"lastMoveGmtMillis,omitempty"`
 | 
						Score             int32   `protobuf:"varint,11,opt,name=score,proto3" json:"score,omitempty"`
 | 
				
			||||||
	FramesToRecover   int32                   `protobuf:"varint,12,opt,name=framesToRecover,proto3" json:"framesToRecover,omitempty"`
 | 
						LastMoveGmtMillis int32   `protobuf:"varint,12,opt,name=lastMoveGmtMillis,proto3" json:"lastMoveGmtMillis,omitempty"`
 | 
				
			||||||
	Hp                int32                   `protobuf:"varint,13,opt,name=hp,proto3" json:"hp,omitempty"`
 | 
						FramesToRecover   int32   `protobuf:"varint,13,opt,name=framesToRecover,proto3" json:"framesToRecover,omitempty"`
 | 
				
			||||||
	MaxHp             int32                   `protobuf:"varint,14,opt,name=maxHp,proto3" json:"maxHp,omitempty"`
 | 
						Hp                int32   `protobuf:"varint,14,opt,name=hp,proto3" json:"hp,omitempty"`
 | 
				
			||||||
	CharacterState    int32                   `protobuf:"varint,15,opt,name=characterState,proto3" json:"characterState,omitempty"`
 | 
						MaxHp             int32   `protobuf:"varint,15,opt,name=maxHp,proto3" json:"maxHp,omitempty"`
 | 
				
			||||||
	Name              string                  `protobuf:"bytes,16,opt,name=name,proto3" json:"name,omitempty"`
 | 
						CharacterState    int32   `protobuf:"varint,16,opt,name=characterState,proto3" json:"characterState,omitempty"`
 | 
				
			||||||
	DisplayName       string                  `protobuf:"bytes,17,opt,name=displayName,proto3" json:"displayName,omitempty"`
 | 
						Name              string  `protobuf:"bytes,17,opt,name=name,proto3" json:"name,omitempty"`
 | 
				
			||||||
	Avatar            string                  `protobuf:"bytes,18,opt,name=avatar,proto3" json:"avatar,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"`
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (x *PlayerDownsync) Reset() {
 | 
					func (x *PlayerDownsync) Reset() {
 | 
				
			||||||
@@ -330,11 +331,18 @@ func (x *PlayerDownsync) GetVirtualGridY() int32 {
 | 
				
			|||||||
	return 0
 | 
						return 0
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (x *PlayerDownsync) GetDir() *sharedprotos.Direction {
 | 
					func (x *PlayerDownsync) GetDirX() int32 {
 | 
				
			||||||
	if x != nil {
 | 
						if x != nil {
 | 
				
			||||||
		return x.Dir
 | 
							return x.DirX
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return nil
 | 
						return 0
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (x *PlayerDownsync) GetDirY() int32 {
 | 
				
			||||||
 | 
						if x != nil {
 | 
				
			||||||
 | 
							return x.DirY
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return 0
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (x *PlayerDownsync) GetSpeed() int32 {
 | 
					func (x *PlayerDownsync) GetSpeed() int32 {
 | 
				
			||||||
@@ -1198,167 +1206,166 @@ var file_room_downsync_frame_proto_rawDesc = []byte{
 | 
				
			|||||||
	0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x73, 0x68, 0x61,
 | 
						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,
 | 
						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,
 | 
						0x6e, 0x32, 0x44, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02,
 | 
				
			||||||
	0x38, 0x01, 0x22, 0xb5, 0x04, 0x0a, 0x0e, 0x50, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x44, 0x6f, 0x77,
 | 
						0x38, 0x01, 0x22, 0xb2, 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,
 | 
						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,
 | 
						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, 0x72,
 | 
						0x47, 0x72, 0x69, 0x64, 0x58, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0c, 0x76, 0x69, 0x72,
 | 
				
			||||||
	0x74, 0x75, 0x61, 0x6c, 0x47, 0x72, 0x69, 0x64, 0x58, 0x12, 0x22, 0x0a, 0x0c, 0x76, 0x69, 0x72,
 | 
						0x74, 0x75, 0x61, 0x6c, 0x47, 0x72, 0x69, 0x64, 0x58, 0x12, 0x22, 0x0a, 0x0c, 0x76, 0x69, 0x72,
 | 
				
			||||||
	0x74, 0x75, 0x61, 0x6c, 0x47, 0x72, 0x69, 0x64, 0x59, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52,
 | 
						0x74, 0x75, 0x61, 0x6c, 0x47, 0x72, 0x69, 0x64, 0x59, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52,
 | 
				
			||||||
	0x0c, 0x76, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x47, 0x72, 0x69, 0x64, 0x59, 0x12, 0x29, 0x0a,
 | 
						0x0c, 0x76, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x47, 0x72, 0x69, 0x64, 0x59, 0x12, 0x12, 0x0a,
 | 
				
			||||||
	0x03, 0x64, 0x69, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x73, 0x68, 0x61,
 | 
						0x04, 0x64, 0x69, 0x72, 0x58, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x64, 0x69, 0x72,
 | 
				
			||||||
	0x72, 0x65, 0x64, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74,
 | 
						0x58, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x69, 0x72, 0x59, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x52,
 | 
				
			||||||
	0x69, 0x6f, 0x6e, 0x52, 0x03, 0x64, 0x69, 0x72, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x70, 0x65, 0x65,
 | 
						0x04, 0x64, 0x69, 0x72, 0x59, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x70, 0x65, 0x65, 0x64, 0x18, 0x06,
 | 
				
			||||||
	0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x73, 0x70, 0x65, 0x65, 0x64, 0x12, 0x20,
 | 
						0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x73, 0x70, 0x65, 0x65, 0x64, 0x12, 0x20, 0x0a, 0x0b, 0x62,
 | 
				
			||||||
	0x0a, 0x0b, 0x62, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x18, 0x06, 0x20,
 | 
						0x61, 0x74, 0x74, 0x6c, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x05,
 | 
				
			||||||
	0x01, 0x28, 0x05, 0x52, 0x0b, 0x62, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65,
 | 
						0x52, 0x0b, 0x62, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x1c, 0x0a,
 | 
				
			||||||
	0x12, 0x1c, 0x0a, 0x09, 0x6a, 0x6f, 0x69, 0x6e, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x07, 0x20,
 | 
						0x09, 0x6a, 0x6f, 0x69, 0x6e, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x08, 0x20, 0x01, 0x28, 0x05,
 | 
				
			||||||
	0x01, 0x28, 0x05, 0x52, 0x09, 0x6a, 0x6f, 0x69, 0x6e, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x26,
 | 
						0x52, 0x09, 0x6a, 0x6f, 0x69, 0x6e, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x26, 0x0a, 0x0e, 0x63,
 | 
				
			||||||
	0x0a, 0x0e, 0x63, 0x6f, 0x6c, 0x6c, 0x69, 0x64, 0x65, 0x72, 0x52, 0x61, 0x64, 0x69, 0x75, 0x73,
 | 
						0x6f, 0x6c, 0x6c, 0x69, 0x64, 0x65, 0x72, 0x52, 0x61, 0x64, 0x69, 0x75, 0x73, 0x18, 0x09, 0x20,
 | 
				
			||||||
	0x18, 0x08, 0x20, 0x01, 0x28, 0x01, 0x52, 0x0e, 0x63, 0x6f, 0x6c, 0x6c, 0x69, 0x64, 0x65, 0x72,
 | 
						0x01, 0x28, 0x01, 0x52, 0x0e, 0x63, 0x6f, 0x6c, 0x6c, 0x69, 0x64, 0x65, 0x72, 0x52, 0x61, 0x64,
 | 
				
			||||||
	0x52, 0x61, 0x64, 0x69, 0x75, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65,
 | 
						0x69, 0x75, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x18, 0x0a,
 | 
				
			||||||
	0x64, 0x18, 0x09, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64,
 | 
						0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x12, 0x14, 0x0a,
 | 
				
			||||||
	0x12, 0x14, 0x0a, 0x05, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x05, 0x52,
 | 
						0x05, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x73, 0x63,
 | 
				
			||||||
	0x05, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x12, 0x2c, 0x0a, 0x11, 0x6c, 0x61, 0x73, 0x74, 0x4d, 0x6f,
 | 
						0x6f, 0x72, 0x65, 0x12, 0x2c, 0x0a, 0x11, 0x6c, 0x61, 0x73, 0x74, 0x4d, 0x6f, 0x76, 0x65, 0x47,
 | 
				
			||||||
	0x76, 0x65, 0x47, 0x6d, 0x74, 0x4d, 0x69, 0x6c, 0x6c, 0x69, 0x73, 0x18, 0x0b, 0x20, 0x01, 0x28,
 | 
						0x6d, 0x74, 0x4d, 0x69, 0x6c, 0x6c, 0x69, 0x73, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x05, 0x52, 0x11,
 | 
				
			||||||
	0x05, 0x52, 0x11, 0x6c, 0x61, 0x73, 0x74, 0x4d, 0x6f, 0x76, 0x65, 0x47, 0x6d, 0x74, 0x4d, 0x69,
 | 
						0x6c, 0x61, 0x73, 0x74, 0x4d, 0x6f, 0x76, 0x65, 0x47, 0x6d, 0x74, 0x4d, 0x69, 0x6c, 0x6c, 0x69,
 | 
				
			||||||
	0x6c, 0x6c, 0x69, 0x73, 0x12, 0x28, 0x0a, 0x0f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x54, 0x6f,
 | 
						0x73, 0x12, 0x28, 0x0a, 0x0f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x54, 0x6f, 0x52, 0x65, 0x63,
 | 
				
			||||||
	0x52, 0x65, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0f, 0x66,
 | 
						0x6f, 0x76, 0x65, 0x72, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0f, 0x66, 0x72, 0x61, 0x6d,
 | 
				
			||||||
	0x72, 0x61, 0x6d, 0x65, 0x73, 0x54, 0x6f, 0x52, 0x65, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x12, 0x0e,
 | 
						0x65, 0x73, 0x54, 0x6f, 0x52, 0x65, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x12, 0x0e, 0x0a, 0x02, 0x68,
 | 
				
			||||||
	0x0a, 0x02, 0x68, 0x70, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x05, 0x52, 0x02, 0x68, 0x70, 0x12, 0x14,
 | 
						0x70, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x05, 0x52, 0x02, 0x68, 0x70, 0x12, 0x14, 0x0a, 0x05, 0x6d,
 | 
				
			||||||
	0x0a, 0x05, 0x6d, 0x61, 0x78, 0x48, 0x70, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x6d,
 | 
						0x61, 0x78, 0x48, 0x70, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x6d, 0x61, 0x78, 0x48,
 | 
				
			||||||
	0x61, 0x78, 0x48, 0x70, 0x12, 0x26, 0x0a, 0x0e, 0x63, 0x68, 0x61, 0x72, 0x61, 0x63, 0x74, 0x65,
 | 
						0x70, 0x12, 0x26, 0x0a, 0x0e, 0x63, 0x68, 0x61, 0x72, 0x61, 0x63, 0x74, 0x65, 0x72, 0x53, 0x74,
 | 
				
			||||||
	0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0e, 0x63, 0x68,
 | 
						0x61, 0x74, 0x65, 0x18, 0x10, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0e, 0x63, 0x68, 0x61, 0x72, 0x61,
 | 
				
			||||||
	0x61, 0x72, 0x61, 0x63, 0x74, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x12, 0x0a, 0x04,
 | 
						0x63, 0x74, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d,
 | 
				
			||||||
	0x6e, 0x61, 0x6d, 0x65, 0x18, 0x10, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65,
 | 
						0x65, 0x18, 0x11, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x20, 0x0a,
 | 
				
			||||||
	0x12, 0x20, 0x0a, 0x0b, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x18,
 | 
						0x0b, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x12, 0x20, 0x01,
 | 
				
			||||||
	0x11, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x4e, 0x61,
 | 
						0x28, 0x09, 0x52, 0x0b, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x12,
 | 
				
			||||||
	0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x61, 0x76, 0x61, 0x74, 0x61, 0x72, 0x18, 0x12, 0x20, 0x01,
 | 
						0x16, 0x0a, 0x06, 0x61, 0x76, 0x61, 0x74, 0x61, 0x72, 0x18, 0x13, 0x20, 0x01, 0x28, 0x09, 0x52,
 | 
				
			||||||
	0x28, 0x09, 0x52, 0x06, 0x61, 0x76, 0x61, 0x74, 0x61, 0x72, 0x22, 0x51, 0x0a, 0x11, 0x49, 0x6e,
 | 
						0x06, 0x61, 0x76, 0x61, 0x74, 0x61, 0x72, 0x22, 0x51, 0x0a, 0x11, 0x49, 0x6e, 0x70, 0x75, 0x74,
 | 
				
			||||||
	0x70, 0x75, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x44, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x12,
 | 
						0x46, 0x72, 0x61, 0x6d, 0x65, 0x44, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x12, 0x0e, 0x0a, 0x02,
 | 
				
			||||||
	0x0e, 0x0a, 0x02, 0x64, 0x78, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x02, 0x64, 0x78, 0x12,
 | 
						0x64, 0x78, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x02, 0x64, 0x78, 0x12, 0x0e, 0x0a, 0x02,
 | 
				
			||||||
	0x0e, 0x0a, 0x02, 0x64, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x02, 0x64, 0x79, 0x12,
 | 
						0x64, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x02, 0x64, 0x79, 0x12, 0x1c, 0x0a, 0x09,
 | 
				
			||||||
	0x1c, 0x0a, 0x09, 0x62, 0x74, 0x6e, 0x41, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x18, 0x03, 0x20, 0x01,
 | 
						0x62, 0x74, 0x6e, 0x41, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52,
 | 
				
			||||||
	0x28, 0x05, 0x52, 0x09, 0x62, 0x74, 0x6e, 0x41, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x22, 0x50, 0x0a,
 | 
						0x09, 0x62, 0x74, 0x6e, 0x41, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x22, 0x50, 0x0a, 0x10, 0x49, 0x6e,
 | 
				
			||||||
	0x10, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x55, 0x70, 0x73, 0x79, 0x6e,
 | 
						0x70, 0x75, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x55, 0x70, 0x73, 0x79, 0x6e, 0x63, 0x12, 0x22,
 | 
				
			||||||
	0x63, 0x12, 0x22, 0x0a, 0x0c, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x49,
 | 
						0x0a, 0x0c, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x49, 0x64, 0x18, 0x01,
 | 
				
			||||||
	0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0c, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x46, 0x72,
 | 
						0x20, 0x01, 0x28, 0x05, 0x52, 0x0c, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65,
 | 
				
			||||||
	0x61, 0x6d, 0x65, 0x49, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x63, 0x6f, 0x64, 0x65, 0x64,
 | 
						0x49, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x18, 0x02, 0x20,
 | 
				
			||||||
	0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x07, 0x65, 0x6e, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x22,
 | 
						0x01, 0x28, 0x04, 0x52, 0x07, 0x65, 0x6e, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x22, 0x7c, 0x0a, 0x12,
 | 
				
			||||||
	0x7c, 0x0a, 0x12, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x44, 0x6f, 0x77,
 | 
						0x49, 0x6e, 0x70, 0x75, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x44, 0x6f, 0x77, 0x6e, 0x73, 0x79,
 | 
				
			||||||
	0x6e, 0x73, 0x79, 0x6e, 0x63, 0x12, 0x22, 0x0a, 0x0c, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x46, 0x72,
 | 
						0x6e, 0x63, 0x12, 0x22, 0x0a, 0x0c, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65,
 | 
				
			||||||
	0x61, 0x6d, 0x65, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0c, 0x69, 0x6e, 0x70,
 | 
						0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0c, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x46,
 | 
				
			||||||
	0x75, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x49, 0x64, 0x12, 0x1c, 0x0a, 0x09, 0x69, 0x6e, 0x70,
 | 
						0x72, 0x61, 0x6d, 0x65, 0x49, 0x64, 0x12, 0x1c, 0x0a, 0x09, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x4c,
 | 
				
			||||||
	0x75, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x18, 0x02, 0x20, 0x03, 0x28, 0x04, 0x52, 0x09, 0x69, 0x6e,
 | 
						0x69, 0x73, 0x74, 0x18, 0x02, 0x20, 0x03, 0x28, 0x04, 0x52, 0x09, 0x69, 0x6e, 0x70, 0x75, 0x74,
 | 
				
			||||||
	0x70, 0x75, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x24, 0x0a, 0x0d, 0x63, 0x6f, 0x6e, 0x66, 0x69,
 | 
						0x4c, 0x69, 0x73, 0x74, 0x12, 0x24, 0x0a, 0x0d, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d, 0x65,
 | 
				
			||||||
	0x72, 0x6d, 0x65, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0d,
 | 
						0x64, 0x4c, 0x69, 0x73, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0d, 0x63, 0x6f, 0x6e,
 | 
				
			||||||
	0x63, 0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d, 0x65, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x22, 0x3b, 0x0a,
 | 
						0x66, 0x69, 0x72, 0x6d, 0x65, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x22, 0x3b, 0x0a, 0x0f, 0x48, 0x65,
 | 
				
			||||||
	0x0f, 0x48, 0x65, 0x61, 0x72, 0x74, 0x62, 0x65, 0x61, 0x74, 0x55, 0x70, 0x73, 0x79, 0x6e, 0x63,
 | 
						0x61, 0x72, 0x74, 0x62, 0x65, 0x61, 0x74, 0x55, 0x70, 0x73, 0x79, 0x6e, 0x63, 0x12, 0x28, 0x0a,
 | 
				
			||||||
	0x12, 0x28, 0x0a, 0x0f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74,
 | 
						0x0f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70,
 | 
				
			||||||
	0x61, 0x6d, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0f, 0x63, 0x6c, 0x69, 0x65, 0x6e,
 | 
						0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x54, 0x69,
 | 
				
			||||||
	0x74, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x22, 0xb8, 0x02, 0x0a, 0x05, 0x57,
 | 
						0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x22, 0xb8, 0x02, 0x0a, 0x05, 0x57, 0x73, 0x52, 0x65,
 | 
				
			||||||
	0x73, 0x52, 0x65, 0x71, 0x12, 0x14, 0x0a, 0x05, 0x6d, 0x73, 0x67, 0x49, 0x64, 0x18, 0x01, 0x20,
 | 
						0x71, 0x12, 0x14, 0x0a, 0x05, 0x6d, 0x73, 0x67, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05,
 | 
				
			||||||
	0x01, 0x28, 0x05, 0x52, 0x05, 0x6d, 0x73, 0x67, 0x49, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x6c,
 | 
						0x52, 0x05, 0x6d, 0x73, 0x67, 0x49, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x6c, 0x61, 0x79, 0x65,
 | 
				
			||||||
	0x61, 0x79, 0x65, 0x72, 0x49, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x70, 0x6c,
 | 
						0x72, 0x49, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x70, 0x6c, 0x61, 0x79, 0x65,
 | 
				
			||||||
	0x61, 0x79, 0x65, 0x72, 0x49, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x61, 0x63, 0x74, 0x18, 0x03, 0x20,
 | 
						0x72, 0x49, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x61, 0x63, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05,
 | 
				
			||||||
	0x01, 0x28, 0x05, 0x52, 0x03, 0x61, 0x63, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x6a, 0x6f, 0x69, 0x6e,
 | 
						0x52, 0x03, 0x61, 0x63, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x6a, 0x6f, 0x69, 0x6e, 0x49, 0x6e, 0x64,
 | 
				
			||||||
	0x49, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x6a, 0x6f, 0x69,
 | 
						0x65, 0x78, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x6a, 0x6f, 0x69, 0x6e, 0x49, 0x6e,
 | 
				
			||||||
	0x6e, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x24, 0x0a, 0x0d, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67,
 | 
						0x64, 0x65, 0x78, 0x12, 0x24, 0x0a, 0x0d, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x46, 0x72, 0x61,
 | 
				
			||||||
	0x46, 0x72, 0x61, 0x6d, 0x65, 0x49, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0d, 0x61,
 | 
						0x6d, 0x65, 0x49, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0d, 0x61, 0x63, 0x6b, 0x69,
 | 
				
			||||||
	0x63, 0x6b, 0x69, 0x6e, 0x67, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x49, 0x64, 0x12, 0x2e, 0x0a, 0x12,
 | 
						0x6e, 0x67, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x49, 0x64, 0x12, 0x2e, 0x0a, 0x12, 0x61, 0x63, 0x6b,
 | 
				
			||||||
	0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65,
 | 
						0x69, 0x6e, 0x67, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x49, 0x64, 0x18,
 | 
				
			||||||
	0x49, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x05, 0x52, 0x12, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67,
 | 
						0x06, 0x20, 0x01, 0x28, 0x05, 0x52, 0x12, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x49, 0x6e, 0x70,
 | 
				
			||||||
	0x49, 0x6e, 0x70, 0x75, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x49, 0x64, 0x12, 0x4e, 0x0a, 0x15,
 | 
						0x75, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x49, 0x64, 0x12, 0x4e, 0x0a, 0x15, 0x69, 0x6e, 0x70,
 | 
				
			||||||
	0x69, 0x6e, 0x70, 0x75, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x55, 0x70, 0x73, 0x79, 0x6e, 0x63,
 | 
						0x75, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x55, 0x70, 0x73, 0x79, 0x6e, 0x63, 0x42, 0x61, 0x74,
 | 
				
			||||||
	0x42, 0x61, 0x74, 0x63, 0x68, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x70, 0x72,
 | 
						0x63, 0x68, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
 | 
				
			||||||
	0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x55,
 | 
						0x73, 0x2e, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x55, 0x70, 0x73, 0x79,
 | 
				
			||||||
	0x70, 0x73, 0x79, 0x6e, 0x63, 0x52, 0x15, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x46, 0x72, 0x61, 0x6d,
 | 
						0x6e, 0x63, 0x52, 0x15, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x55, 0x70,
 | 
				
			||||||
	0x65, 0x55, 0x70, 0x73, 0x79, 0x6e, 0x63, 0x42, 0x61, 0x74, 0x63, 0x68, 0x12, 0x27, 0x0a, 0x02,
 | 
						0x73, 0x79, 0x6e, 0x63, 0x42, 0x61, 0x74, 0x63, 0x68, 0x12, 0x27, 0x0a, 0x02, 0x68, 0x62, 0x18,
 | 
				
			||||||
	0x68, 0x62, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
 | 
						0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x48,
 | 
				
			||||||
	0x73, 0x2e, 0x48, 0x65, 0x61, 0x72, 0x74, 0x62, 0x65, 0x61, 0x74, 0x55, 0x70, 0x73, 0x79, 0x6e,
 | 
						0x65, 0x61, 0x72, 0x74, 0x62, 0x65, 0x61, 0x74, 0x55, 0x70, 0x73, 0x79, 0x6e, 0x63, 0x52, 0x02,
 | 
				
			||||||
	0x63, 0x52, 0x02, 0x68, 0x62, 0x22, 0x89, 0x02, 0x0a, 0x06, 0x57, 0x73, 0x52, 0x65, 0x73, 0x70,
 | 
						0x68, 0x62, 0x22, 0x89, 0x02, 0x0a, 0x06, 0x57, 0x73, 0x52, 0x65, 0x73, 0x70, 0x12, 0x10, 0x0a,
 | 
				
			||||||
	0x12, 0x10, 0x0a, 0x03, 0x72, 0x65, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x03, 0x72,
 | 
						0x03, 0x72, 0x65, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x03, 0x72, 0x65, 0x74, 0x12,
 | 
				
			||||||
	0x65, 0x74, 0x12, 0x20, 0x0a, 0x0b, 0x65, 0x63, 0x68, 0x6f, 0x65, 0x64, 0x4d, 0x73, 0x67, 0x49,
 | 
						0x20, 0x0a, 0x0b, 0x65, 0x63, 0x68, 0x6f, 0x65, 0x64, 0x4d, 0x73, 0x67, 0x49, 0x64, 0x18, 0x02,
 | 
				
			||||||
	0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0b, 0x65, 0x63, 0x68, 0x6f, 0x65, 0x64, 0x4d,
 | 
						0x20, 0x01, 0x28, 0x05, 0x52, 0x0b, 0x65, 0x63, 0x68, 0x6f, 0x65, 0x64, 0x4d, 0x73, 0x67, 0x49,
 | 
				
			||||||
	0x73, 0x67, 0x49, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x61, 0x63, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28,
 | 
						0x64, 0x12, 0x10, 0x0a, 0x03, 0x61, 0x63, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x03,
 | 
				
			||||||
	0x05, 0x52, 0x03, 0x61, 0x63, 0x74, 0x12, 0x2b, 0x0a, 0x03, 0x72, 0x64, 0x66, 0x18, 0x04, 0x20,
 | 
						0x61, 0x63, 0x74, 0x12, 0x2b, 0x0a, 0x03, 0x72, 0x64, 0x66, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b,
 | 
				
			||||||
	0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x52, 0x6f, 0x6f,
 | 
						0x32, 0x19, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x52, 0x6f, 0x6f, 0x6d, 0x44, 0x6f,
 | 
				
			||||||
	0x6d, 0x44, 0x6f, 0x77, 0x6e, 0x73, 0x79, 0x6e, 0x63, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x52, 0x03,
 | 
						0x77, 0x6e, 0x73, 0x79, 0x6e, 0x63, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x52, 0x03, 0x72, 0x64, 0x66,
 | 
				
			||||||
	0x72, 0x64, 0x66, 0x12, 0x54, 0x0a, 0x17, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x46, 0x72, 0x61, 0x6d,
 | 
						0x12, 0x54, 0x0a, 0x17, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x44, 0x6f,
 | 
				
			||||||
	0x65, 0x44, 0x6f, 0x77, 0x6e, 0x73, 0x79, 0x6e, 0x63, 0x42, 0x61, 0x74, 0x63, 0x68, 0x18, 0x05,
 | 
						0x77, 0x6e, 0x73, 0x79, 0x6e, 0x63, 0x42, 0x61, 0x74, 0x63, 0x68, 0x18, 0x05, 0x20, 0x03, 0x28,
 | 
				
			||||||
	0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x49, 0x6e,
 | 
						0x0b, 0x32, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x49, 0x6e, 0x70, 0x75, 0x74,
 | 
				
			||||||
	0x70, 0x75, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x44, 0x6f, 0x77, 0x6e, 0x73, 0x79, 0x6e, 0x63,
 | 
						0x46, 0x72, 0x61, 0x6d, 0x65, 0x44, 0x6f, 0x77, 0x6e, 0x73, 0x79, 0x6e, 0x63, 0x52, 0x17, 0x69,
 | 
				
			||||||
	0x52, 0x17, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x44, 0x6f, 0x77, 0x6e,
 | 
						0x6e, 0x70, 0x75, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x44, 0x6f, 0x77, 0x6e, 0x73, 0x79, 0x6e,
 | 
				
			||||||
	0x73, 0x79, 0x6e, 0x63, 0x42, 0x61, 0x74, 0x63, 0x68, 0x12, 0x36, 0x0a, 0x08, 0x62, 0x63, 0x69,
 | 
						0x63, 0x42, 0x61, 0x74, 0x63, 0x68, 0x12, 0x36, 0x0a, 0x08, 0x62, 0x63, 0x69, 0x46, 0x72, 0x61,
 | 
				
			||||||
	0x46, 0x72, 0x61, 0x6d, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x70, 0x72,
 | 
						0x6d, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
 | 
				
			||||||
	0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x42, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x43, 0x6f, 0x6c, 0x6c, 0x69,
 | 
						0x73, 0x2e, 0x42, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x43, 0x6f, 0x6c, 0x6c, 0x69, 0x64, 0x65, 0x72,
 | 
				
			||||||
	0x64, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x08, 0x62, 0x63, 0x69, 0x46, 0x72, 0x61, 0x6d,
 | 
						0x49, 0x6e, 0x66, 0x6f, 0x52, 0x08, 0x62, 0x63, 0x69, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x22, 0xe5,
 | 
				
			||||||
	0x65, 0x22, 0xe5, 0x05, 0x0a, 0x0b, 0x4d, 0x65, 0x6c, 0x65, 0x65, 0x42, 0x75, 0x6c, 0x6c, 0x65,
 | 
						0x05, 0x0a, 0x0b, 0x4d, 0x65, 0x6c, 0x65, 0x65, 0x42, 0x75, 0x6c, 0x6c, 0x65, 0x74, 0x12, 0x24,
 | 
				
			||||||
	0x74, 0x12, 0x24, 0x0a, 0x0d, 0x62, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x4c, 0x6f, 0x63, 0x61, 0x6c,
 | 
						0x0a, 0x0d, 0x62, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x49, 0x64, 0x18,
 | 
				
			||||||
	0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0d, 0x62, 0x61, 0x74, 0x74, 0x6c, 0x65,
 | 
						0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0d, 0x62, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x4c, 0x6f, 0x63,
 | 
				
			||||||
	0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x49, 0x64, 0x12, 0x24, 0x0a, 0x0d, 0x73, 0x74, 0x61, 0x72, 0x74,
 | 
						0x61, 0x6c, 0x49, 0x64, 0x12, 0x24, 0x0a, 0x0d, 0x73, 0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x46,
 | 
				
			||||||
	0x75, 0x70, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0d,
 | 
						0x72, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0d, 0x73, 0x74, 0x61,
 | 
				
			||||||
	0x73, 0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x12, 0x22, 0x0a,
 | 
						0x72, 0x74, 0x75, 0x70, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x12, 0x22, 0x0a, 0x0c, 0x61, 0x63,
 | 
				
			||||||
	0x0c, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x03, 0x20,
 | 
						0x74, 0x69, 0x76, 0x65, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05,
 | 
				
			||||||
	0x01, 0x28, 0x05, 0x52, 0x0c, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x46, 0x72, 0x61, 0x6d, 0x65,
 | 
						0x52, 0x0c, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x12, 0x26,
 | 
				
			||||||
	0x73, 0x12, 0x26, 0x0a, 0x0e, 0x72, 0x65, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x46, 0x72, 0x61,
 | 
						0x0a, 0x0e, 0x72, 0x65, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73,
 | 
				
			||||||
	0x6d, 0x65, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0e, 0x72, 0x65, 0x63, 0x6f, 0x76,
 | 
						0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0e, 0x72, 0x65, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79,
 | 
				
			||||||
	0x65, 0x72, 0x79, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x12, 0x34, 0x0a, 0x15, 0x72, 0x65, 0x63,
 | 
						0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x12, 0x34, 0x0a, 0x15, 0x72, 0x65, 0x63, 0x6f, 0x76, 0x65,
 | 
				
			||||||
	0x6f, 0x76, 0x65, 0x72, 0x79, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x4f, 0x6e, 0x42, 0x6c, 0x6f,
 | 
						0x72, 0x79, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x4f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x18,
 | 
				
			||||||
	0x63, 0x6b, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x52, 0x15, 0x72, 0x65, 0x63, 0x6f, 0x76, 0x65,
 | 
						0x05, 0x20, 0x01, 0x28, 0x05, 0x52, 0x15, 0x72, 0x65, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x46,
 | 
				
			||||||
	0x72, 0x79, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x4f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12,
 | 
						0x72, 0x61, 0x6d, 0x65, 0x73, 0x4f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x30, 0x0a, 0x13,
 | 
				
			||||||
	0x30, 0x0a, 0x13, 0x72, 0x65, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x46, 0x72, 0x61, 0x6d, 0x65,
 | 
						0x72, 0x65, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x4f, 0x6e,
 | 
				
			||||||
	0x73, 0x4f, 0x6e, 0x48, 0x69, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x05, 0x52, 0x13, 0x72, 0x65,
 | 
						0x48, 0x69, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x05, 0x52, 0x13, 0x72, 0x65, 0x63, 0x6f, 0x76,
 | 
				
			||||||
	0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x4f, 0x6e, 0x48, 0x69,
 | 
						0x65, 0x72, 0x79, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x4f, 0x6e, 0x48, 0x69, 0x74, 0x12, 0x35,
 | 
				
			||||||
	0x74, 0x12, 0x35, 0x0a, 0x0b, 0x6d, 0x6f, 0x76, 0x65, 0x66, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64,
 | 
						0x0a, 0x0b, 0x6d, 0x6f, 0x76, 0x65, 0x66, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x18, 0x07, 0x20,
 | 
				
			||||||
	0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x73, 0x68, 0x61, 0x72, 0x65, 0x64, 0x70,
 | 
						0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x73, 0x68, 0x61, 0x72, 0x65, 0x64, 0x70, 0x72, 0x6f, 0x74,
 | 
				
			||||||
	0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x56, 0x65, 0x63, 0x32, 0x44, 0x52, 0x0b, 0x6d, 0x6f, 0x76,
 | 
						0x6f, 0x73, 0x2e, 0x56, 0x65, 0x63, 0x32, 0x44, 0x52, 0x0b, 0x6d, 0x6f, 0x76, 0x65, 0x66, 0x6f,
 | 
				
			||||||
	0x65, 0x66, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x12, 0x22, 0x0a, 0x0c, 0x68, 0x69, 0x74, 0x62,
 | 
						0x72, 0x77, 0x61, 0x72, 0x64, 0x12, 0x22, 0x0a, 0x0c, 0x68, 0x69, 0x74, 0x62, 0x6f, 0x78, 0x4f,
 | 
				
			||||||
	0x6f, 0x78, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x18, 0x08, 0x20, 0x01, 0x28, 0x01, 0x52, 0x0c,
 | 
						0x66, 0x66, 0x73, 0x65, 0x74, 0x18, 0x08, 0x20, 0x01, 0x28, 0x01, 0x52, 0x0c, 0x68, 0x69, 0x74,
 | 
				
			||||||
	0x68, 0x69, 0x74, 0x62, 0x6f, 0x78, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x12, 0x33, 0x0a, 0x0a,
 | 
						0x62, 0x6f, 0x78, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x12, 0x33, 0x0a, 0x0a, 0x68, 0x69, 0x74,
 | 
				
			||||||
	0x68, 0x69, 0x74, 0x62, 0x6f, 0x78, 0x53, 0x69, 0x7a, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b,
 | 
						0x62, 0x6f, 0x78, 0x53, 0x69, 0x7a, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e,
 | 
				
			||||||
	0x32, 0x13, 0x2e, 0x73, 0x68, 0x61, 0x72, 0x65, 0x64, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e,
 | 
						0x73, 0x68, 0x61, 0x72, 0x65, 0x64, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x56, 0x65, 0x63,
 | 
				
			||||||
	0x56, 0x65, 0x63, 0x32, 0x44, 0x52, 0x0a, 0x68, 0x69, 0x74, 0x62, 0x6f, 0x78, 0x53, 0x69, 0x7a,
 | 
						0x32, 0x44, 0x52, 0x0a, 0x68, 0x69, 0x74, 0x62, 0x6f, 0x78, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x38,
 | 
				
			||||||
	0x65, 0x12, 0x38, 0x0a, 0x17, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x65, 0x64, 0x52,
 | 
						0x0a, 0x17, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x65, 0x64, 0x52, 0x65, 0x6e, 0x64,
 | 
				
			||||||
	0x65, 0x6e, 0x64, 0x65, 0x72, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x49, 0x64, 0x18, 0x0a, 0x20, 0x01,
 | 
						0x65, 0x72, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x49, 0x64, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x05, 0x52,
 | 
				
			||||||
	0x28, 0x05, 0x52, 0x17, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x65, 0x64, 0x52, 0x65,
 | 
						0x17, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x65, 0x64, 0x52, 0x65, 0x6e, 0x64, 0x65,
 | 
				
			||||||
	0x6e, 0x64, 0x65, 0x72, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x49, 0x64, 0x12, 0x24, 0x0a, 0x0d, 0x68,
 | 
						0x72, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x49, 0x64, 0x12, 0x24, 0x0a, 0x0d, 0x68, 0x69, 0x74, 0x53,
 | 
				
			||||||
	0x69, 0x74, 0x53, 0x74, 0x75, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x0b, 0x20, 0x01,
 | 
						0x74, 0x75, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x05, 0x52,
 | 
				
			||||||
	0x28, 0x05, 0x52, 0x0d, 0x68, 0x69, 0x74, 0x53, 0x74, 0x75, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65,
 | 
						0x0d, 0x68, 0x69, 0x74, 0x53, 0x74, 0x75, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x12, 0x28,
 | 
				
			||||||
	0x73, 0x12, 0x28, 0x0a, 0x0f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x53, 0x74, 0x75, 0x6e, 0x46, 0x72,
 | 
						0x0a, 0x0f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x53, 0x74, 0x75, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65,
 | 
				
			||||||
	0x61, 0x6d, 0x65, 0x73, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0f, 0x62, 0x6c, 0x6f, 0x63,
 | 
						0x73, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x53, 0x74,
 | 
				
			||||||
	0x6b, 0x53, 0x74, 0x75, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x70,
 | 
						0x75, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x75, 0x73, 0x68,
 | 
				
			||||||
	0x75, 0x73, 0x68, 0x62, 0x61, 0x63, 0x6b, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x01, 0x52, 0x08, 0x70,
 | 
						0x62, 0x61, 0x63, 0x6b, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x01, 0x52, 0x08, 0x70, 0x75, 0x73, 0x68,
 | 
				
			||||||
	0x75, 0x73, 0x68, 0x62, 0x61, 0x63, 0x6b, 0x12, 0x2e, 0x0a, 0x12, 0x72, 0x65, 0x6c, 0x65, 0x61,
 | 
						0x62, 0x61, 0x63, 0x6b, 0x12, 0x2e, 0x0a, 0x12, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x54,
 | 
				
			||||||
	0x73, 0x65, 0x54, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x54, 0x79, 0x70, 0x65, 0x18, 0x0e, 0x20,
 | 
						0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x54, 0x79, 0x70, 0x65, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x05,
 | 
				
			||||||
	0x01, 0x28, 0x05, 0x52, 0x12, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x54, 0x72, 0x69, 0x67,
 | 
						0x52, 0x12, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x54, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72,
 | 
				
			||||||
	0x67, 0x65, 0x72, 0x54, 0x79, 0x70, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x64, 0x61, 0x6d, 0x61, 0x67,
 | 
						0x54, 0x79, 0x70, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x64, 0x61, 0x6d, 0x61, 0x67, 0x65, 0x18, 0x0f,
 | 
				
			||||||
	0x65, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x64, 0x61, 0x6d, 0x61, 0x67, 0x65, 0x12,
 | 
						0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x64, 0x61, 0x6d, 0x61, 0x67, 0x65, 0x12, 0x2c, 0x0a, 0x11,
 | 
				
			||||||
	0x2c, 0x0a, 0x11, 0x6f, 0x66, 0x66, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x4a, 0x6f, 0x69, 0x6e, 0x49,
 | 
						0x6f, 0x66, 0x66, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x4a, 0x6f, 0x69, 0x6e, 0x49, 0x6e, 0x64, 0x65,
 | 
				
			||||||
	0x6e, 0x64, 0x65, 0x78, 0x18, 0x10, 0x20, 0x01, 0x28, 0x05, 0x52, 0x11, 0x6f, 0x66, 0x66, 0x65,
 | 
						0x78, 0x18, 0x10, 0x20, 0x01, 0x28, 0x05, 0x52, 0x11, 0x6f, 0x66, 0x66, 0x65, 0x6e, 0x64, 0x65,
 | 
				
			||||||
	0x6e, 0x64, 0x65, 0x72, 0x4a, 0x6f, 0x69, 0x6e, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x2a, 0x0a,
 | 
						0x72, 0x4a, 0x6f, 0x69, 0x6e, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x2a, 0x0a, 0x10, 0x6f, 0x66,
 | 
				
			||||||
	0x10, 0x6f, 0x66, 0x66, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x50, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x49,
 | 
						0x66, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x50, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x49, 0x64, 0x18, 0x11,
 | 
				
			||||||
	0x64, 0x18, 0x11, 0x20, 0x01, 0x28, 0x05, 0x52, 0x10, 0x6f, 0x66, 0x66, 0x65, 0x6e, 0x64, 0x65,
 | 
						0x20, 0x01, 0x28, 0x05, 0x52, 0x10, 0x6f, 0x66, 0x66, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x50, 0x6c,
 | 
				
			||||||
	0x72, 0x50, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x49, 0x64, 0x22, 0x9a, 0x02, 0x0a, 0x11, 0x52, 0x6f,
 | 
						0x61, 0x79, 0x65, 0x72, 0x49, 0x64, 0x22, 0x9a, 0x02, 0x0a, 0x11, 0x52, 0x6f, 0x6f, 0x6d, 0x44,
 | 
				
			||||||
	0x6f, 0x6d, 0x44, 0x6f, 0x77, 0x6e, 0x73, 0x79, 0x6e, 0x63, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x12,
 | 
						0x6f, 0x77, 0x6e, 0x73, 0x79, 0x6e, 0x63, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x12, 0x0e, 0x0a, 0x02,
 | 
				
			||||||
	0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x02, 0x69, 0x64, 0x12,
 | 
						0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x02, 0x69, 0x64, 0x12, 0x40, 0x0a, 0x07,
 | 
				
			||||||
	0x40, 0x0a, 0x07, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b,
 | 
						0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x26, 0x2e,
 | 
				
			||||||
	0x32, 0x26, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x52, 0x6f, 0x6f, 0x6d, 0x44, 0x6f,
 | 
						0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x52, 0x6f, 0x6f, 0x6d, 0x44, 0x6f, 0x77, 0x6e, 0x73,
 | 
				
			||||||
	0x77, 0x6e, 0x73, 0x79, 0x6e, 0x63, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x2e, 0x50, 0x6c, 0x61, 0x79,
 | 
						0x79, 0x6e, 0x63, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x2e, 0x50, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x73,
 | 
				
			||||||
	0x65, 0x72, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x07, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72,
 | 
						0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x07, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x73, 0x12, 0x26,
 | 
				
			||||||
	0x73, 0x12, 0x26, 0x0a, 0x0e, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x64, 0x6f, 0x77, 0x6e, 0x4e, 0x61,
 | 
						0x0a, 0x0e, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x64, 0x6f, 0x77, 0x6e, 0x4e, 0x61, 0x6e, 0x6f, 0x73,
 | 
				
			||||||
	0x6e, 0x6f, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, 0x63, 0x6f, 0x75, 0x6e, 0x74,
 | 
						0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x64, 0x6f, 0x77,
 | 
				
			||||||
	0x64, 0x6f, 0x77, 0x6e, 0x4e, 0x61, 0x6e, 0x6f, 0x73, 0x12, 0x37, 0x0a, 0x0c, 0x6d, 0x65, 0x6c,
 | 
						0x6e, 0x4e, 0x61, 0x6e, 0x6f, 0x73, 0x12, 0x37, 0x0a, 0x0c, 0x6d, 0x65, 0x6c, 0x65, 0x65, 0x42,
 | 
				
			||||||
	0x65, 0x65, 0x42, 0x75, 0x6c, 0x6c, 0x65, 0x74, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32,
 | 
						0x75, 0x6c, 0x6c, 0x65, 0x74, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x70,
 | 
				
			||||||
	0x13, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x4d, 0x65, 0x6c, 0x65, 0x65, 0x42, 0x75,
 | 
						0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x4d, 0x65, 0x6c, 0x65, 0x65, 0x42, 0x75, 0x6c, 0x6c, 0x65,
 | 
				
			||||||
	0x6c, 0x6c, 0x65, 0x74, 0x52, 0x0c, 0x6d, 0x65, 0x6c, 0x65, 0x65, 0x42, 0x75, 0x6c, 0x6c, 0x65,
 | 
						0x74, 0x52, 0x0c, 0x6d, 0x65, 0x6c, 0x65, 0x65, 0x42, 0x75, 0x6c, 0x6c, 0x65, 0x74, 0x73, 0x1a,
 | 
				
			||||||
	0x74, 0x73, 0x1a, 0x52, 0x0a, 0x0c, 0x50, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x73, 0x45, 0x6e, 0x74,
 | 
						0x52, 0x0a, 0x0c, 0x50, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12,
 | 
				
			||||||
	0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52,
 | 
						0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x03, 0x6b, 0x65,
 | 
				
			||||||
	0x03, 0x6b, 0x65, 0x79, 0x12, 0x2c, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20,
 | 
						0x79, 0x12, 0x2c, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b,
 | 
				
			||||||
	0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x50, 0x6c, 0x61,
 | 
						0x32, 0x16, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x50, 0x6c, 0x61, 0x79, 0x65, 0x72,
 | 
				
			||||||
	0x79, 0x65, 0x72, 0x44, 0x6f, 0x77, 0x6e, 0x73, 0x79, 0x6e, 0x63, 0x52, 0x05, 0x76, 0x61, 0x6c,
 | 
						0x44, 0x6f, 0x77, 0x6e, 0x73, 0x79, 0x6e, 0x63, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a,
 | 
				
			||||||
	0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x42, 0x13, 0x5a, 0x11, 0x62, 0x61, 0x74, 0x74, 0x6c, 0x65,
 | 
						0x02, 0x38, 0x01, 0x42, 0x13, 0x5a, 0x11, 0x62, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x5f, 0x73, 0x72,
 | 
				
			||||||
	0x5f, 0x73, 0x72, 0x76, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f,
 | 
						0x76, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
 | 
				
			||||||
	0x74, 0x6f, 0x33,
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var (
 | 
					var (
 | 
				
			||||||
@@ -1388,32 +1395,30 @@ var file_room_downsync_frame_proto_goTypes = []interface{}{
 | 
				
			|||||||
	nil,                                // 10: protos.BattleColliderInfo.StrToVec2DListMapEntry
 | 
						nil,                                // 10: protos.BattleColliderInfo.StrToVec2DListMapEntry
 | 
				
			||||||
	nil,                                // 11: protos.BattleColliderInfo.StrToPolygon2DListMapEntry
 | 
						nil,                                // 11: protos.BattleColliderInfo.StrToPolygon2DListMapEntry
 | 
				
			||||||
	nil,                                // 12: protos.RoomDownsyncFrame.PlayersEntry
 | 
						nil,                                // 12: protos.RoomDownsyncFrame.PlayersEntry
 | 
				
			||||||
	(*sharedprotos.Direction)(nil),     // 13: sharedprotos.Direction
 | 
						(*sharedprotos.Vec2D)(nil),         // 13: sharedprotos.Vec2D
 | 
				
			||||||
	(*sharedprotos.Vec2D)(nil),         // 14: sharedprotos.Vec2D
 | 
						(*sharedprotos.Vec2DList)(nil),     // 14: sharedprotos.Vec2DList
 | 
				
			||||||
	(*sharedprotos.Vec2DList)(nil),     // 15: sharedprotos.Vec2DList
 | 
						(*sharedprotos.Polygon2DList)(nil), // 15: sharedprotos.Polygon2DList
 | 
				
			||||||
	(*sharedprotos.Polygon2DList)(nil), // 16: sharedprotos.Polygon2DList
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
var file_room_downsync_frame_proto_depIdxs = []int32{
 | 
					var file_room_downsync_frame_proto_depIdxs = []int32{
 | 
				
			||||||
	10, // 0: protos.BattleColliderInfo.strToVec2DListMap:type_name -> protos.BattleColliderInfo.StrToVec2DListMapEntry
 | 
						10, // 0: protos.BattleColliderInfo.strToVec2DListMap:type_name -> protos.BattleColliderInfo.StrToVec2DListMapEntry
 | 
				
			||||||
	11, // 1: protos.BattleColliderInfo.strToPolygon2DListMap:type_name -> protos.BattleColliderInfo.StrToPolygon2DListMapEntry
 | 
						11, // 1: protos.BattleColliderInfo.strToPolygon2DListMap:type_name -> protos.BattleColliderInfo.StrToPolygon2DListMapEntry
 | 
				
			||||||
	13, // 2: protos.PlayerDownsync.dir:type_name -> sharedprotos.Direction
 | 
						3,  // 2: protos.WsReq.inputFrameUpsyncBatch:type_name -> protos.InputFrameUpsync
 | 
				
			||||||
	3,  // 3: protos.WsReq.inputFrameUpsyncBatch:type_name -> protos.InputFrameUpsync
 | 
						5,  // 3: protos.WsReq.hb:type_name -> protos.HeartbeatUpsync
 | 
				
			||||||
	5,  // 4: protos.WsReq.hb:type_name -> protos.HeartbeatUpsync
 | 
						9,  // 4: protos.WsResp.rdf:type_name -> protos.RoomDownsyncFrame
 | 
				
			||||||
	9,  // 5: protos.WsResp.rdf:type_name -> protos.RoomDownsyncFrame
 | 
						4,  // 5: protos.WsResp.inputFrameDownsyncBatch:type_name -> protos.InputFrameDownsync
 | 
				
			||||||
	4,  // 6: protos.WsResp.inputFrameDownsyncBatch:type_name -> protos.InputFrameDownsync
 | 
						0,  // 6: protos.WsResp.bciFrame:type_name -> protos.BattleColliderInfo
 | 
				
			||||||
	0,  // 7: protos.WsResp.bciFrame:type_name -> protos.BattleColliderInfo
 | 
						13, // 7: protos.MeleeBullet.moveforward:type_name -> sharedprotos.Vec2D
 | 
				
			||||||
	14, // 8: protos.MeleeBullet.moveforward:type_name -> sharedprotos.Vec2D
 | 
						13, // 8: protos.MeleeBullet.hitboxSize:type_name -> sharedprotos.Vec2D
 | 
				
			||||||
	14, // 9: protos.MeleeBullet.hitboxSize:type_name -> sharedprotos.Vec2D
 | 
						12, // 9: protos.RoomDownsyncFrame.players:type_name -> protos.RoomDownsyncFrame.PlayersEntry
 | 
				
			||||||
	12, // 10: protos.RoomDownsyncFrame.players:type_name -> protos.RoomDownsyncFrame.PlayersEntry
 | 
						8,  // 10: protos.RoomDownsyncFrame.meleeBullets:type_name -> protos.MeleeBullet
 | 
				
			||||||
	8,  // 11: protos.RoomDownsyncFrame.meleeBullets:type_name -> protos.MeleeBullet
 | 
						14, // 11: protos.BattleColliderInfo.StrToVec2DListMapEntry.value:type_name -> sharedprotos.Vec2DList
 | 
				
			||||||
	15, // 12: protos.BattleColliderInfo.StrToVec2DListMapEntry.value:type_name -> sharedprotos.Vec2DList
 | 
						15, // 12: protos.BattleColliderInfo.StrToPolygon2DListMapEntry.value:type_name -> sharedprotos.Polygon2DList
 | 
				
			||||||
	16, // 13: protos.BattleColliderInfo.StrToPolygon2DListMapEntry.value:type_name -> sharedprotos.Polygon2DList
 | 
						1,  // 13: protos.RoomDownsyncFrame.PlayersEntry.value:type_name -> protos.PlayerDownsync
 | 
				
			||||||
	1,  // 14: protos.RoomDownsyncFrame.PlayersEntry.value:type_name -> protos.PlayerDownsync
 | 
						14, // [14:14] is the sub-list for method output_type
 | 
				
			||||||
	15, // [15:15] is the sub-list for method output_type
 | 
						14, // [14:14] is the sub-list for method input_type
 | 
				
			||||||
	15, // [15:15] is the sub-list for method input_type
 | 
						14, // [14:14] is the sub-list for extension type_name
 | 
				
			||||||
	15, // [15:15] is the sub-list for extension type_name
 | 
						14, // [14:14] is the sub-list for extension extendee
 | 
				
			||||||
	15, // [15:15] is the sub-list for extension extendee
 | 
						0,  // [0:14] is the sub-list for field type_name
 | 
				
			||||||
	0,  // [0:15] is the sub-list for field type_name
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func init() { file_room_downsync_frame_proto_init() }
 | 
					func init() { file_room_downsync_frame_proto_init() }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,7 +1,7 @@
 | 
				
			|||||||
// Code generated by protoc-gen-go. DO NOT EDIT.
 | 
					// Code generated by protoc-gen-go. DO NOT EDIT.
 | 
				
			||||||
// versions:
 | 
					// versions:
 | 
				
			||||||
// 	protoc-gen-go v1.28.1
 | 
					// 	protoc-gen-go v1.28.1
 | 
				
			||||||
// 	protoc        v3.7.1
 | 
					// 	protoc        v3.21.4
 | 
				
			||||||
// source: geometry.proto
 | 
					// source: geometry.proto
 | 
				
			||||||
 | 
					
 | 
				
			||||||
package sharedprotos
 | 
					package sharedprotos
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,17 +1,18 @@
 | 
				
			|||||||
<?xml version="1.0" encoding="UTF-8"?>
 | 
					<?xml version="1.0" encoding="UTF-8"?>
 | 
				
			||||||
<map version="1.2" tiledversion="1.2.3" orientation="orthogonal" renderorder="right-down" width="64" height="64" tilewidth="16" tileheight="16" infinite="0" nextlayerid="2" nextobjectid="12">
 | 
					<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">
 | 
				
			||||||
 <tileset firstgid="1" source="tiles0.tsx"/>
 | 
					 <tileset firstgid="1" source="tiles0.tsx"/>
 | 
				
			||||||
 <tileset firstgid="65" source="tiles1.tsx"/>
 | 
					 <tileset firstgid="65" source="tiles1.tsx"/>
 | 
				
			||||||
 <layer id="1" name="Ground" width="64" height="64">
 | 
					 <tileset firstgid="129" source="tiles2.tsx"/>
 | 
				
			||||||
 | 
					 <layer id="2" name="Ground" width="128" height="128">
 | 
				
			||||||
  <data encoding="base64" compression="zlib">
 | 
					  <data encoding="base64" compression="zlib">
 | 
				
			||||||
   eJzt0jEOwjAUREGLkiLmALRU3In7HwMKkFCUCCwiNrKnmCbVvh8fSikHAAAA/qruYEOr84Zd+vM9re0v+vXr1z9S/7f0l3KZ9dXZ91r67QeAXxyf0jv0Z/tvO9iS7F+T3ucG+Xuk96RvkN4CMJLaIL0VttLy7r19euHdA+zX6YP0vlR3z/3ax2tfarw+TAO0L/VPb3ruXvv3o7z7lv70zuQN0vtgz+6DDSsZ
 | 
					   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
 | 
				
			||||||
  </data>
 | 
					  </data>
 | 
				
			||||||
 </layer>
 | 
					 </layer>
 | 
				
			||||||
 <objectgroup id="1" name="PlayerStartingPos">
 | 
					 <objectgroup id="1" name="PlayerStartingPos">
 | 
				
			||||||
  <object id="135" x="512" y="512">
 | 
					  <object id="135" x="1090" y="833.667">
 | 
				
			||||||
   <point/>
 | 
					   <point/>
 | 
				
			||||||
  </object>
 | 
					  </object>
 | 
				
			||||||
  <object id="137" x="640" y="640">
 | 
					  <object id="137" x="1215" y="830.5">
 | 
				
			||||||
   <point/>
 | 
					   <point/>
 | 
				
			||||||
  </object>
 | 
					  </object>
 | 
				
			||||||
 </objectgroup>
 | 
					 </objectgroup>
 | 
				
			||||||
@@ -19,71 +20,149 @@
 | 
				
			|||||||
  <properties>
 | 
					  <properties>
 | 
				
			||||||
   <property name="type" value="barrier_and_shelter"/>
 | 
					   <property name="type" value="barrier_and_shelter"/>
 | 
				
			||||||
  </properties>
 | 
					  </properties>
 | 
				
			||||||
  <object id="1" x="400" y="224.5">
 | 
					  <object id="8" x="648.242" y="480.606">
 | 
				
			||||||
   <properties>
 | 
					 | 
				
			||||||
    <property name="boundary_type" value="barrier"/>
 | 
					 | 
				
			||||||
   </properties>
 | 
					 | 
				
			||||||
   <polyline points="0,0 0,141.5 17,141.5 17,-1"/>
 | 
					 | 
				
			||||||
  </object>
 | 
					 | 
				
			||||||
  <object id="2" x="559.5" y="207.5">
 | 
					 | 
				
			||||||
   <properties>
 | 
					 | 
				
			||||||
    <property name="boundary_type" value="barrier"/>
 | 
					 | 
				
			||||||
   </properties>
 | 
					 | 
				
			||||||
   <polyline points="0,0 1,158.5 17,158.5 17,0"/>
 | 
					 | 
				
			||||||
  </object>
 | 
					 | 
				
			||||||
  <object id="3" x="448.5" y="353">
 | 
					 | 
				
			||||||
   <properties>
 | 
					 | 
				
			||||||
    <property name="boundary_type" value="barrier"/>
 | 
					 | 
				
			||||||
   </properties>
 | 
					 | 
				
			||||||
   <polyline points="0,0 0,14.5 -49,14.5 -49,-1.5"/>
 | 
					 | 
				
			||||||
  </object>
 | 
					 | 
				
			||||||
  <object id="4" x="577.5" y="351.5">
 | 
					 | 
				
			||||||
   <properties>
 | 
					 | 
				
			||||||
    <property name="boundary_type" value="barrier"/>
 | 
					 | 
				
			||||||
   </properties>
 | 
					 | 
				
			||||||
   <polyline points="0,0 -98,1 -98,16 -1,15.5"/>
 | 
					 | 
				
			||||||
  </object>
 | 
					 | 
				
			||||||
  <object id="5" x="449.333" y="654.667">
 | 
					 | 
				
			||||||
   <properties>
 | 
					 | 
				
			||||||
    <property name="boundary_type" value="barrier"/>
 | 
					 | 
				
			||||||
   </properties>
 | 
					 | 
				
			||||||
   <polyline points="0,0 -178.667,0.666667 -178.667,17.3333 -0.666667,17.3333"/>
 | 
					 | 
				
			||||||
  </object>
 | 
					 | 
				
			||||||
  <object id="6" x="432.5" y="703.5">
 | 
					 | 
				
			||||||
   <properties>
 | 
					 | 
				
			||||||
    <property name="boundary_type" value="barrier"/>
 | 
					 | 
				
			||||||
   </properties>
 | 
					 | 
				
			||||||
   <polyline points="0,0 -191.667,0.666667 -191.667,17.3333 -0.715174,17.3333"/>
 | 
					 | 
				
			||||||
  </object>
 | 
					 | 
				
			||||||
  <object id="7" x="400" y="751">
 | 
					 | 
				
			||||||
   <properties>
 | 
					 | 
				
			||||||
    <property name="boundary_type" value="barrier"/>
 | 
					 | 
				
			||||||
   </properties>
 | 
					 | 
				
			||||||
   <polyline points="0,0 -191.667,0.666667 -191.667,17.3333 -0.715174,17.3333"/>
 | 
					 | 
				
			||||||
  </object>
 | 
					 | 
				
			||||||
  <object id="8" x="-9.33333" y="-13.3333">
 | 
					 | 
				
			||||||
   <properties>
 | 
					   <properties>
 | 
				
			||||||
    <property name="boundary_type" value="barrier"/>
 | 
					    <property name="boundary_type" value="barrier"/>
 | 
				
			||||||
   </properties>
 | 
					   </properties>
 | 
				
			||||||
   <polyline points="0,0 0,18.6667 1041.33,21.3333 1041.33,-1.33333"/>
 | 
					   <polyline points="0,0 0,18.6667 1041.33,21.3333 1041.33,-1.33333"/>
 | 
				
			||||||
  </object>
 | 
					  </object>
 | 
				
			||||||
  <object id="9" x="-9.33333" y="1014.67">
 | 
					  <object id="9" x="650.667" y="1604.67">
 | 
				
			||||||
   <properties>
 | 
					   <properties>
 | 
				
			||||||
    <property name="boundary_type" value="barrier"/>
 | 
					    <property name="boundary_type" value="barrier"/>
 | 
				
			||||||
   </properties>
 | 
					   </properties>
 | 
				
			||||||
   <polyline points="0,0 0,18.6667 1041.33,21.3333 1041.33,-1.33333"/>
 | 
					   <polyline points="0,0 0,18.6667 1041.33,21.3333 1041.33,-1.33333"/>
 | 
				
			||||||
  </object>
 | 
					  </object>
 | 
				
			||||||
  <object id="10" x="-14" y="-40">
 | 
					  <object id="10" x="634.485" y="505.455">
 | 
				
			||||||
   <properties>
 | 
					   <properties>
 | 
				
			||||||
    <property name="boundary_type" value="barrier"/>
 | 
					    <property name="boundary_type" value="barrier"/>
 | 
				
			||||||
   </properties>
 | 
					   </properties>
 | 
				
			||||||
   <polyline points="0,0 4,1110 24,1110 24,-8"/>
 | 
					   <polyline points="0,0 4,1110 24,1110 24,-8"/>
 | 
				
			||||||
  </object>
 | 
					  </object>
 | 
				
			||||||
  <object id="11" x="1014" y="-42">
 | 
					  <object id="11" x="1677.64" y="501.333">
 | 
				
			||||||
   <properties>
 | 
					   <properties>
 | 
				
			||||||
    <property name="boundary_type" value="barrier"/>
 | 
					    <property name="boundary_type" value="barrier"/>
 | 
				
			||||||
   </properties>
 | 
					   </properties>
 | 
				
			||||||
   <polyline points="0,0 4,1110 24,1110 24,-8"/>
 | 
					   <polyline points="0,0 4,1110 24,1110 24,-8"/>
 | 
				
			||||||
  </object>
 | 
					  </object>
 | 
				
			||||||
 | 
					  <object id="14" x="688.667" y="464">
 | 
				
			||||||
 | 
					   <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">
 | 
				
			||||||
 | 
					   <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">
 | 
				
			||||||
 | 
					   <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">
 | 
				
			||||||
 | 
					   <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">
 | 
				
			||||||
 | 
					   <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">
 | 
				
			||||||
 | 
					   <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">
 | 
				
			||||||
 | 
					   <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">
 | 
				
			||||||
 | 
					   <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">
 | 
				
			||||||
 | 
					   <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">
 | 
				
			||||||
 | 
					   <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">
 | 
				
			||||||
 | 
					   <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">
 | 
				
			||||||
 | 
					   <properties>
 | 
				
			||||||
 | 
					    <property name="boundary_type" value="barrier"/>
 | 
				
			||||||
 | 
					   </properties>
 | 
				
			||||||
 | 
					   <polyline points="0,0 0,63.5 272.5,65 273,-1"/>
 | 
				
			||||||
 | 
					  </object>
 | 
				
			||||||
 | 
					  <object id="30" x="1136.5" y="717.5">
 | 
				
			||||||
 | 
					   <properties>
 | 
				
			||||||
 | 
					    <property name="boundary_type" value="barrier"/>
 | 
				
			||||||
 | 
					   </properties>
 | 
				
			||||||
 | 
					   <polyline points="0,0 -0.5,17 255,17.5 255,1.5"/>
 | 
				
			||||||
 | 
					  </object>
 | 
				
			||||||
 | 
					  <object id="31" x="1152" y="735.667">
 | 
				
			||||||
 | 
					   <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">
 | 
				
			||||||
 | 
					   <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">
 | 
				
			||||||
 | 
					   <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">
 | 
				
			||||||
 | 
					   <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>
 | 
					 </objectgroup>
 | 
				
			||||||
</map>
 | 
					</map>
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										4
									
								
								frontend/assets/resources/map/dungeon/tiles2.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								frontend/assets/resources/map/dungeon/tiles2.tsx
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,4 @@
 | 
				
			|||||||
 | 
					<?xml version="1.0" encoding="UTF-8"?>
 | 
				
			||||||
 | 
					<tileset version="1.2" tiledversion="1.2.3" name="tiles2" tilewidth="16" tileheight="16" tilecount="64" columns="16">
 | 
				
			||||||
 | 
					 <image source="watabou_pixel_dungeon_orig_files/tiles2.png" width="256" height="64"/>
 | 
				
			||||||
 | 
					</tileset>
 | 
				
			||||||
							
								
								
									
										5
									
								
								frontend/assets/resources/map/dungeon/tiles2.tsx.meta
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								frontend/assets/resources/map/dungeon/tiles2.tsx.meta
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,5 @@
 | 
				
			|||||||
 | 
					{
 | 
				
			||||||
 | 
					  "ver": "2.0.0",
 | 
				
			||||||
 | 
					  "uuid": "2e53500f-f9c8-4b5b-b74c-f2adbc2ec34d",
 | 
				
			||||||
 | 
					  "subMetas": {}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -38,22 +38,23 @@ message PlayerDownsync {
 | 
				
			|||||||
  int32 id = 1;
 | 
					  int32 id = 1;
 | 
				
			||||||
  int32 virtualGridX = 2; 
 | 
					  int32 virtualGridX = 2; 
 | 
				
			||||||
  int32 virtualGridY = 3; 
 | 
					  int32 virtualGridY = 3; 
 | 
				
			||||||
  sharedprotos.Direction dir = 4;
 | 
					  int32 dirX = 4;
 | 
				
			||||||
  int32 speed = 5; // in terms of virtual grid units
 | 
					  int32 dirY = 5;
 | 
				
			||||||
  int32 battleState = 6;
 | 
					  int32 speed = 6; // in terms of virtual grid units
 | 
				
			||||||
  int32 joinIndex = 7;
 | 
					  int32 battleState = 7;
 | 
				
			||||||
  double colliderRadius = 8;
 | 
					  int32 joinIndex = 8;
 | 
				
			||||||
  bool removed = 9;
 | 
					  double colliderRadius = 9;
 | 
				
			||||||
  int32 score = 10;
 | 
					  bool removed = 10;
 | 
				
			||||||
  int32 lastMoveGmtMillis = 11;
 | 
					  int32 score = 11;
 | 
				
			||||||
  int32 framesToRecover = 12;
 | 
					  int32 lastMoveGmtMillis = 12;
 | 
				
			||||||
  int32 hp = 13;
 | 
					  int32 framesToRecover = 13;
 | 
				
			||||||
  int32 maxHp = 14;
 | 
					  int32 hp = 14;
 | 
				
			||||||
  int32 characterState = 15;
 | 
					  int32 maxHp = 15;
 | 
				
			||||||
 | 
					  int32 characterState = 16;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  string name = 16;
 | 
					  string name = 17;
 | 
				
			||||||
  string displayName = 17;
 | 
					  string displayName = 18;
 | 
				
			||||||
  string avatar = 18;
 | 
					  string avatar = 19;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
message InputFrameDecoded {
 | 
					message InputFrameDecoded {
 | 
				
			||||||
@@ -123,8 +124,6 @@ message MeleeBullet {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  int32 offenderJoinIndex = 16;    
 | 
					  int32 offenderJoinIndex = 16;    
 | 
				
			||||||
  int32 offenderPlayerId = 17;    
 | 
					  int32 offenderPlayerId = 17;    
 | 
				
			||||||
 | 
					 | 
				
			||||||
  int32 offenderPlayerId = 17;    
 | 
					 | 
				
			||||||
} 
 | 
					} 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
message RoomDownsyncFrame {
 | 
					message RoomDownsyncFrame {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -277,6 +277,7 @@
 | 
				
			|||||||
    "forceBigEndianFloatingNumDecoding": false,
 | 
					    "forceBigEndianFloatingNumDecoding": false,
 | 
				
			||||||
    "renderFrameIdLagTolerance": 4,
 | 
					    "renderFrameIdLagTolerance": 4,
 | 
				
			||||||
    "jigglingEps1D": 0.001,
 | 
					    "jigglingEps1D": 0.001,
 | 
				
			||||||
 | 
					    "bulletTriggerEnabled": true,
 | 
				
			||||||
    "_id": "4b+kZ46VhC0LCBixXEK2dk"
 | 
					    "_id": "4b+kZ46VhC0LCBixXEK2dk"
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  {
 | 
					  {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -95,6 +95,9 @@ cc.Class({
 | 
				
			|||||||
      type: cc.Float,
 | 
					      type: cc.Float,
 | 
				
			||||||
      default: 1e-3
 | 
					      default: 1e-3
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					    bulletTriggerEnabled: {
 | 
				
			||||||
 | 
					      default: false
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  _inputFrameIdDebuggable(inputFrameId) {
 | 
					  _inputFrameIdDebuggable(inputFrameId) {
 | 
				
			||||||
@@ -321,10 +324,10 @@ cc.Class({
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    self.battleState = ALL_BATTLE_STATES.WAITING;
 | 
					    self.battleState = ALL_BATTLE_STATES.WAITING;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    self.countdownNanos = null;
 | 
				
			||||||
    if (self.countdownLabel) {
 | 
					    if (self.countdownLabel) {
 | 
				
			||||||
      self.countdownLabel.string = "";
 | 
					      self.countdownLabel.string = "";
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    self.countdownNanos = null;
 | 
					 | 
				
			||||||
    if (self.findingPlayerNode) {
 | 
					    if (self.findingPlayerNode) {
 | 
				
			||||||
      const findingPlayerScriptIns = self.findingPlayerNode.getComponent("FindingPlayer");
 | 
					      const findingPlayerScriptIns = self.findingPlayerNode.getComponent("FindingPlayer");
 | 
				
			||||||
      findingPlayerScriptIns.init();
 | 
					      findingPlayerScriptIns.init();
 | 
				
			||||||
@@ -741,17 +744,15 @@ cc.Class({
 | 
				
			|||||||
    self.playersInfoNode.getComponent("PlayersInfo").clearInfo();
 | 
					    self.playersInfoNode.getComponent("PlayersInfo").clearInfo();
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  spawnPlayerNode(joinIndex, vx, vy, playerRichInfo) {
 | 
					  spawnPlayerNode(joinIndex, vx, vy, playerDownsyncInfo) {
 | 
				
			||||||
    const self = this;
 | 
					    const self = this;
 | 
				
			||||||
    const newPlayerNode = cc.instantiate(self.controlledCharacterPrefab)
 | 
					    const newPlayerNode = cc.instantiate(self.controlledCharacterPrefab)
 | 
				
			||||||
    const playerScriptIns = newPlayerNode.getComponent("ControlledCharacter");
 | 
					    const playerScriptIns = newPlayerNode.getComponent("ControlledCharacter");
 | 
				
			||||||
    playerScriptIns.joinIndex = joinIndex;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (1 == joinIndex) {
 | 
					    if (1 == joinIndex) {
 | 
				
			||||||
      playerScriptIns.setSpecies("SoldierWaterGhost");
 | 
					      playerScriptIns.setSpecies("SoldierWaterGhost");
 | 
				
			||||||
    } else if (2 == joinIndex) {
 | 
					    } else if (2 == joinIndex) {
 | 
				
			||||||
      playerScriptIns.setSpecies("SoldierFireGhost");
 | 
					      playerScriptIns.setSpecies("SoldierFireGhost");
 | 
				
			||||||
      if (0 == playerRichInfo.dir.dx && 0 == playerRichInfo.dir.dy) {
 | 
					      if (0 == playerDownsyncInfo.dirX && 0 == playerDownsyncInfo.dirY) {
 | 
				
			||||||
        playerScriptIns.animComp.node.scaleX = (-1.0);
 | 
					        playerScriptIns.animComp.node.scaleX = (-1.0);
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -760,16 +761,15 @@ cc.Class({
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    newPlayerNode.setPosition(cc.v2(wpos[0], wpos[1]));
 | 
					    newPlayerNode.setPosition(cc.v2(wpos[0], wpos[1]));
 | 
				
			||||||
    playerScriptIns.mapNode = self.node;
 | 
					    playerScriptIns.mapNode = self.node;
 | 
				
			||||||
    const cpos = self.virtualGridToPlayerColliderPos(vx, vy, playerRichInfo);
 | 
					    const cpos = self.virtualGridToPlayerColliderPos(vx, vy, playerDownsyncInfo);
 | 
				
			||||||
    const d = playerRichInfo.colliderRadius * 2,
 | 
					    const d = playerDownsyncInfo.colliderRadius * 2,
 | 
				
			||||||
      x0 = cpos[0],
 | 
					      x0 = cpos[0],
 | 
				
			||||||
      y0 = cpos[1];
 | 
					      y0 = cpos[1];
 | 
				
			||||||
    let pts = [[0, 0], [d, 0], [d, d], [0, d]];
 | 
					    let pts = [[0, 0], [d, 0], [d, d], [0, d]];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const newPlayerCollider = self.collisionSys.createPolygon(x0, y0, pts);
 | 
					    const newPlayerCollider = self.collisionSys.createPolygon(x0, y0, pts);
 | 
				
			||||||
    const collisionPlayerIndex = self.collisionPlayerIndexPrefix + joinIndex;
 | 
					    const collisionPlayerIndex = self.collisionPlayerIndexPrefix + joinIndex;
 | 
				
			||||||
    newPlayerCollider.collisionPlayerIndex = parseInt(collisionPlayerIndex);
 | 
					    newPlayerCollider.data = playerDownsyncInfo;
 | 
				
			||||||
    newPlayerCollider.playerId = parseInt(playerRichInfo.id);
 | 
					 | 
				
			||||||
    self.collisionSysMap.set(collisionPlayerIndex, newPlayerCollider);
 | 
					    self.collisionSysMap.set(collisionPlayerIndex, newPlayerCollider);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    safelyAddChild(self.node, newPlayerNode);
 | 
					    safelyAddChild(self.node, newPlayerNode);
 | 
				
			||||||
@@ -777,9 +777,9 @@ cc.Class({
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    newPlayerNode.active = true;
 | 
					    newPlayerNode.active = true;
 | 
				
			||||||
    playerScriptIns.updateCharacterAnim({
 | 
					    playerScriptIns.updateCharacterAnim({
 | 
				
			||||||
      dx: playerRichInfo.dir.dx,
 | 
					      dx: playerDownsyncInfo.dirX,
 | 
				
			||||||
      dy: playerRichInfo.dir.dy
 | 
					      dy: playerDownsyncInfo.dirY,
 | 
				
			||||||
    }, playerRichInfo, true);
 | 
					    }, playerDownsyncInfo, true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return [newPlayerNode, playerScriptIns];
 | 
					    return [newPlayerNode, playerScriptIns];
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
@@ -973,8 +973,6 @@ cc.Class({
 | 
				
			|||||||
      const dy = (wpos[1] - playerRichInfo.node.y);
 | 
					      const dy = (wpos[1] - playerRichInfo.node.y);
 | 
				
			||||||
      //const justJiggling = (self.jigglingEps1D >= Math.abs(dx) && self.jigglingEps1D >= Math.abs(dy));
 | 
					      //const justJiggling = (self.jigglingEps1D >= Math.abs(dx) && self.jigglingEps1D >= Math.abs(dy));
 | 
				
			||||||
      playerRichInfo.node.setPosition(wpos[0], wpos[1]);
 | 
					      playerRichInfo.node.setPosition(wpos[0], wpos[1]);
 | 
				
			||||||
      playerRichInfo.virtualGridX = immediatePlayerInfo.virtualGridX;
 | 
					 | 
				
			||||||
      playerRichInfo.virtualGridY = immediatePlayerInfo.virtualGridY;
 | 
					 | 
				
			||||||
      // TODO: check "rdf.players[playerId].characterState" instead, might have to play Atk/Atked anim!
 | 
					      // TODO: check "rdf.players[playerId].characterState" instead, might have to play Atk/Atked anim!
 | 
				
			||||||
      if (null != delayedInputFrameForPrevRenderFrame) {
 | 
					      if (null != delayedInputFrameForPrevRenderFrame) {
 | 
				
			||||||
        const decodedInput = self.ctrl.decodeInput(delayedInputFrameForPrevRenderFrame.inputList[playerRichInfo.joinIndex - 1]);
 | 
					        const decodedInput = self.ctrl.decodeInput(delayedInputFrameForPrevRenderFrame.inputList[playerRichInfo.joinIndex - 1]);
 | 
				
			||||||
@@ -1003,17 +1001,15 @@ cc.Class({
 | 
				
			|||||||
  // TODO: Write unit-test for this function to compare with its backend counter part
 | 
					  // TODO: Write unit-test for this function to compare with its backend counter part
 | 
				
			||||||
  applyInputFrameDownsyncDynamicsOnSingleRenderFrame(delayedInputFrame, currRenderFrame, collisionSys, collisionSysMap) {
 | 
					  applyInputFrameDownsyncDynamicsOnSingleRenderFrame(delayedInputFrame, currRenderFrame, collisionSys, collisionSysMap) {
 | 
				
			||||||
    const self = this;
 | 
					    const self = this;
 | 
				
			||||||
    const nextRenderFramePlayers = {}
 | 
					    const nextRenderFramePlayers = {};
 | 
				
			||||||
    for (let playerId in currRenderFrame.players) {
 | 
					    for (let playerId in currRenderFrame.players) {
 | 
				
			||||||
      const currPlayerDownsync = currRenderFrame.players[playerId];
 | 
					      const currPlayerDownsync = currRenderFrame.players[playerId];
 | 
				
			||||||
      nextRenderFramePlayers[playerId] = {
 | 
					      nextRenderFramePlayers[playerId] = {
 | 
				
			||||||
        id: playerId,
 | 
					        id: playerId,
 | 
				
			||||||
        virtualGridX: currPlayerDownsync.virtualGridX,
 | 
					        virtualGridX: currPlayerDownsync.virtualGridX,
 | 
				
			||||||
        virtualGridY: currPlayerDownsync.virtualGridY,
 | 
					        virtualGridY: currPlayerDownsync.virtualGridY,
 | 
				
			||||||
        dir: {
 | 
					        dirX: currPlayerDownsync.dirX,
 | 
				
			||||||
          dx: currPlayerDownsync.dir.dx,
 | 
					        dirY: currPlayerDownsync.dirY,
 | 
				
			||||||
          dy: currPlayerDownsync.dir.dy,
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        characterState: currPlayerDownsync.characterState,
 | 
					        characterState: currPlayerDownsync.characterState,
 | 
				
			||||||
        speed: currPlayerDownsync.speed,
 | 
					        speed: currPlayerDownsync.speed,
 | 
				
			||||||
        battleState: currPlayerDownsync.battleState,
 | 
					        battleState: currPlayerDownsync.battleState,
 | 
				
			||||||
@@ -1034,6 +1030,8 @@ cc.Class({
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    const bulletPushbacks = new Array(self.playerRichInfoArr.length); // Guaranteed determinism regardless of traversal order
 | 
					    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
 | 
					    const effPushbacks = new Array(self.playerRichInfoArr.length); // Guaranteed determinism regardless of traversal order
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Reset playerCollider position from the "virtual grid position"
 | 
				
			||||||
    for (let j in self.playerRichInfoArr) {
 | 
					    for (let j in self.playerRichInfoArr) {
 | 
				
			||||||
      const joinIndex = parseInt(j) + 1;
 | 
					      const joinIndex = parseInt(j) + 1;
 | 
				
			||||||
      bulletPushbacks[joinIndex - 1] = [0.0, 0.0];
 | 
					      bulletPushbacks[joinIndex - 1] = [0.0, 0.0];
 | 
				
			||||||
@@ -1042,17 +1040,17 @@ cc.Class({
 | 
				
			|||||||
      const playerId = playerRichInfo.id;
 | 
					      const playerId = playerRichInfo.id;
 | 
				
			||||||
      const collisionPlayerIndex = self.collisionPlayerIndexPrefix + joinIndex;
 | 
					      const collisionPlayerIndex = self.collisionPlayerIndexPrefix + joinIndex;
 | 
				
			||||||
      const playerCollider = collisionSysMap.get(collisionPlayerIndex);
 | 
					      const playerCollider = collisionSysMap.get(collisionPlayerIndex);
 | 
				
			||||||
      const player = currRenderFrame.players[playerId];
 | 
					      const currPlayerDownsync = currRenderFrame.players[playerId];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      const newVx = player.virtualGridX;
 | 
					      const newVx = currPlayerDownsync.virtualGridX;
 | 
				
			||||||
      const newVy = player.virtualGridY;
 | 
					      const newVy = currPlayerDownsync.virtualGridY;
 | 
				
			||||||
      const newCpos = self.virtualGridToPlayerColliderPos(newVx, newVy, self.playerRichInfoArr[joinIndex - 1]);
 | 
					      const newCpos = self.virtualGridToPlayerColliderPos(newVx, newVy, self.playerRichInfoArr[joinIndex - 1]);
 | 
				
			||||||
      playerCollider.x = newCpos[0];
 | 
					      playerCollider.x = newCpos[0];
 | 
				
			||||||
      playerCollider.y = newCpos[1];
 | 
					      playerCollider.y = newCpos[1];
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Check bullet-anything collisions first, because the pushbacks caused by bullets might later be reverted by player-barrier collision 
 | 
					    // Check bullet-anything collisions first, because the pushbacks caused by bullets might later be reverted by player-barrier collision 
 | 
				
			||||||
    const colliderBullets = new Map(); // Will all be removed at the end of `applyInputFrameDownsyncDynamicsOnSingleRenderFrame` due to the need for being rollback-compatible
 | 
					    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();
 | 
					    const removedBulletsAtCurrFrame = new Set();
 | 
				
			||||||
    for (let k in currRenderFrame.meleeBullets) {
 | 
					    for (let k in currRenderFrame.meleeBullets) {
 | 
				
			||||||
      const meleeBullet = currRenderFrame.meleeBullets[k];
 | 
					      const meleeBullet = currRenderFrame.meleeBullets[k];
 | 
				
			||||||
@@ -1066,39 +1064,39 @@ cc.Class({
 | 
				
			|||||||
        const offenderCollider = collisionSysMap.get(collisionOffenderIndex);
 | 
					        const offenderCollider = collisionSysMap.get(collisionOffenderIndex);
 | 
				
			||||||
        const offender = currRenderFrame.players[meleeBullet.offenderPlayerId];
 | 
					        const offender = currRenderFrame.players[meleeBullet.offenderPlayerId];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        const xfac = Math.sign(offender.dir.dx),
 | 
					        let xfac = 1,
 | 
				
			||||||
          yfac = 0; // By now, straight Punch offset doesn't respect "y-axis"
 | 
					          yfac = 0; // By now, straight Punch offset doesn't respect "y-axis"
 | 
				
			||||||
 | 
					        if (0 > offender.dirX) {
 | 
				
			||||||
 | 
					          xfac = -1;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
        const x0 = offenderCollider.x + xfac * meleeBullet.hitboxOffset,
 | 
					        const x0 = offenderCollider.x + xfac * meleeBullet.hitboxOffset,
 | 
				
			||||||
          y0 = offenderCollider.y + yfac * meleeBullet.hitboxOffset;
 | 
					          y0 = offenderCollider.y + yfac * meleeBullet.hitboxOffset;
 | 
				
			||||||
        const pts = [[0, 0], [xfac * meleeBullet.hitboxSize.x, 0], [xfac * meleeBullet.hitboxSize.x, meleeBullet.hitboxSize.y], [0, meleeBullet.hitboxSize.y]];
 | 
					        const pts = [[0, 0], [xfac * meleeBullet.hitboxSize.x, 0], [xfac * meleeBullet.hitboxSize.x, meleeBullet.hitboxSize.y], [0, meleeBullet.hitboxSize.y]];
 | 
				
			||||||
        const newBulletCollider = collisionSys.createPolygon(x0, y0, pts);
 | 
					        const newBulletCollider = collisionSys.createPolygon(x0, y0, pts);
 | 
				
			||||||
        newBulletCollider.collisionBulletIndex = collisionBulletIndex;
 | 
					        newBulletCollider.data = meleeBullet;
 | 
				
			||||||
        newBulletCollider.offenderPlayerId = meleeBullet.offenderPlayerId;
 | 
					 | 
				
			||||||
        newBulletCollider.pushback = meleeBullet.pushback;
 | 
					 | 
				
			||||||
        newBulletCollider.hitStunFrames = meleeBullet.hitStunFrames;
 | 
					 | 
				
			||||||
        collisionSysMap.set(collisionBulletIndex, newBulletCollider);
 | 
					        collisionSysMap.set(collisionBulletIndex, newBulletCollider);
 | 
				
			||||||
        colliderBullets.set(collisionBulletIndex, newBulletCollider);
 | 
					        bulletColliders.set(collisionBulletIndex, newBulletCollider);
 | 
				
			||||||
        console.log(`A meleeBullet=${JSON.stringify(meleeBullet)} is added to collisionSys at renderFrame.id=${currRenderFrame.id} as start-up frames ended and active frame is not yet ended`);
 | 
					      // console.log(`A meleeBullet is added to collisionSys at renderFrame.id=${currRenderFrame.id} as start-up frames ended and active frame is not yet ended: ${JSON.stringify(meleeBullet)}`);
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    collisionSys.update();
 | 
					    collisionSys.update();
 | 
				
			||||||
    const result1 = collisionSys.createResult(); // Can I reuse a "self.collisionSysResult" object throughout the whole battle?
 | 
					    const result1 = collisionSys.createResult(); // Can I reuse a "self.collisionSysResult" object throughout the whole battle?
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    colliderBullets.forEach((bulletCollider, collisionBulletIndex) => {
 | 
					    bulletColliders.forEach((bulletCollider, collisionBulletIndex) => {
 | 
				
			||||||
      const potentials = bulletCollider.potentials();
 | 
					      const potentials = bulletCollider.potentials();
 | 
				
			||||||
      let shouldRemove = false;
 | 
					      let shouldRemove = false;
 | 
				
			||||||
      for (const potential of potentials) {
 | 
					      for (const potential of potentials) {
 | 
				
			||||||
        if (null != potential.playerId && potential.playerId == bulletCollider.offenderPlayerId) continue;
 | 
					        if (null != potential.data && potential.data.joinIndex == bulletCollider.data.offenderJoinIndex) continue;
 | 
				
			||||||
        if (!bulletCollider.collides(potential, result1)) continue;
 | 
					        if (!bulletCollider.collides(potential, result1)) continue;
 | 
				
			||||||
        if (null != potential.playerId) {
 | 
					        if (null != potential.data && null !== potential.data.joinIndex) {
 | 
				
			||||||
          const joinIndex = potential.collisionPlayerIndex - self.collisionPlayerIndexPrefix;
 | 
					          const joinIndex = potential.data.joinIndex;
 | 
				
			||||||
          bulletPushbacks[joinIndex - 1][0] += result1.overlap_x * bulletCollider.pushback;
 | 
					          bulletPushbacks[joinIndex - 1][0] += bulletCollider.data.pushback; // Only for straight punch, there's no y-pushback
 | 
				
			||||||
          bulletPushbacks[joinIndex - 1][1] += result1.overlap_y * bulletCollider.pushback;
 | 
					          bulletPushbacks[joinIndex - 1][1] += 0;
 | 
				
			||||||
          const thatAckedPlayerInNextFrame = nextRenderFramePlayers[potential.playerId];
 | 
					          const thatAckedPlayerInNextFrame = nextRenderFramePlayers[potential.data.id];
 | 
				
			||||||
          thatAckedPlayerInNextFrame.characterState = window.ATK_CHARACTER_STATE.Atked1[0];
 | 
					          thatAckedPlayerInNextFrame.characterState = window.ATK_CHARACTER_STATE.Atked1[0];
 | 
				
			||||||
          const oldFrameToRecover = thatAckedPlayerInNextFrame.framesToRecover;
 | 
					          const oldFrameToRecover = thatAckedPlayerInNextFrame.framesToRecover;
 | 
				
			||||||
          thatAckedPlayerInNextFrame.framesToRecover = oldFrameToRecover > bulletCollider.hitStunFrames ? oldFrameToRecover : bulletCollider.hitStunFrames; // In case the hit player is already stun, we take the larger "hitStunFrames" 
 | 
					          thatAckedPlayerInNextFrame.framesToRecover = (oldFrameToRecover > bulletCollider.data.hitStunFrames ? oldFrameToRecover : bulletCollider.data.hitStunFrames); // In case the hit player is already stun, we extend it 
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        shouldRemove = true;
 | 
					        shouldRemove = true;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
@@ -1107,9 +1105,9 @@ cc.Class({
 | 
				
			|||||||
      }
 | 
					      }
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // [WARNING] Remove bullets from collisionSys ANYWAY for the convenience of rollback
 | 
				
			||||||
    for (let k in currRenderFrame.meleeBullets) {
 | 
					    for (let k in currRenderFrame.meleeBullets) {
 | 
				
			||||||
      const meleeBullet = currRenderFrame.meleeBullets[k];
 | 
					      const meleeBullet = currRenderFrame.meleeBullets[k];
 | 
				
			||||||
      // [WARNING] remove from collisionSys ANYWAY for the convenience of rollback
 | 
					 | 
				
			||||||
      const collisionBulletIndex = self.collisionBulletIndexPrefix + meleeBullet.battleLocalId;
 | 
					      const collisionBulletIndex = self.collisionBulletIndexPrefix + meleeBullet.battleLocalId;
 | 
				
			||||||
      if (collisionSysMap.has(collisionBulletIndex)) {
 | 
					      if (collisionSysMap.has(collisionBulletIndex)) {
 | 
				
			||||||
        const bulletCollider = collisionSysMap.get(collisionBulletIndex);
 | 
					        const bulletCollider = collisionSysMap.get(collisionBulletIndex);
 | 
				
			||||||
@@ -1120,10 +1118,10 @@ cc.Class({
 | 
				
			|||||||
      toRet.meleeBullets.push(meleeBullet);
 | 
					      toRet.meleeBullets.push(meleeBullet);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Process player inputs
 | 
				
			||||||
    if (null != delayedInputFrame) {
 | 
					    if (null != delayedInputFrame) {
 | 
				
			||||||
      const delayedInputFrameForPrevRenderFrame = self.getCachedInputFrameDownsyncWithPrediction(self._convertToInputFrameId(currRenderFrame.id - 1, self.inputDelayFrames));
 | 
					      const delayedInputFrameForPrevRenderFrame = self.getCachedInputFrameDownsyncWithPrediction(self._convertToInputFrameId(currRenderFrame.id - 1, self.inputDelayFrames));
 | 
				
			||||||
      const inputList = delayedInputFrame.inputList;
 | 
					      const inputList = delayedInputFrame.inputList;
 | 
				
			||||||
      // Process player inputs
 | 
					 | 
				
			||||||
      for (let j in self.playerRichInfoArr) {
 | 
					      for (let j in self.playerRichInfoArr) {
 | 
				
			||||||
        const joinIndex = parseInt(j) + 1;
 | 
					        const joinIndex = parseInt(j) + 1;
 | 
				
			||||||
        effPushbacks[joinIndex - 1] = [0.0, 0.0];
 | 
					        effPushbacks[joinIndex - 1] = [0.0, 0.0];
 | 
				
			||||||
@@ -1131,13 +1129,14 @@ cc.Class({
 | 
				
			|||||||
        const playerId = playerRichInfo.id;
 | 
					        const playerId = playerRichInfo.id;
 | 
				
			||||||
        const collisionPlayerIndex = self.collisionPlayerIndexPrefix + joinIndex;
 | 
					        const collisionPlayerIndex = self.collisionPlayerIndexPrefix + joinIndex;
 | 
				
			||||||
        const playerCollider = collisionSysMap.get(collisionPlayerIndex);
 | 
					        const playerCollider = collisionSysMap.get(collisionPlayerIndex);
 | 
				
			||||||
        const player = currRenderFrame.players[playerId];
 | 
					        const currPlayerDownsync = currRenderFrame.players[playerId];
 | 
				
			||||||
        if (0 < nextRenderFramePlayers[playerId].framesToRecover) {
 | 
					        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  
 | 
					          // No need to process inputs for this player, but there might be bullet pushbacks on this player  
 | 
				
			||||||
          if (0 != bulletPushbacks[joinIndex - 1][0] || 0 != bulletPushbacks[joinIndex - 1][1]) {
 | 
					 | 
				
			||||||
          playerCollider.x += bulletPushbacks[joinIndex - 1][0];
 | 
					          playerCollider.x += bulletPushbacks[joinIndex - 1][0];
 | 
				
			||||||
          playerCollider.y += bulletPushbacks[joinIndex - 1][1];
 | 
					          playerCollider.y += bulletPushbacks[joinIndex - 1][1];
 | 
				
			||||||
            console.log(`playerId=${playerId}, joinIndex=${joinIndex} is pushbacked back by ${bulletPushbacks[joinIndex - 1]} by bullet impacts, now its framesToRecover is ${player.framesToRecover}`);
 | 
					          if (0 != bulletPushbacks[joinIndex - 1][0] || 0 != bulletPushbacks[joinIndex - 1][1]) {
 | 
				
			||||||
 | 
					            console.log(`playerId=${playerId}, joinIndex=${joinIndex} is pushbacked back by ${bulletPushbacks[joinIndex - 1]} by bullet impacts, now its framesToRecover is ${currPlayerDownsync.framesToRecover}`);
 | 
				
			||||||
          }
 | 
					          }
 | 
				
			||||||
          continue;
 | 
					          continue;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@@ -1148,33 +1147,32 @@ cc.Class({
 | 
				
			|||||||
        const prevBtnALevel = (null == prevDecodedInput ? 0 : prevDecodedInput.btnALevel);
 | 
					        const prevBtnALevel = (null == prevDecodedInput ? 0 : prevDecodedInput.btnALevel);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (1 == decodedInput.btnALevel && 0 == prevBtnALevel) {
 | 
					        if (1 == decodedInput.btnALevel && 0 == prevBtnALevel) {
 | 
				
			||||||
          console.log(`playerId=${playerId} triggered a rising-edge of btnA at renderFrame.id=${currRenderFrame.id}, delayedInputFrame.id=${delayedInputFrame.inputFrameId}`);
 | 
					          // console.log(`playerId=${playerId} triggered a rising-edge of btnA at renderFrame.id=${currRenderFrame.id}, delayedInputFrame.id=${delayedInputFrame.inputFrameId}`);
 | 
				
			||||||
        // The online map is not yet ready for bullet shooting!
 | 
					          if (self.bulletTriggerEnabled) {
 | 
				
			||||||
        /*
 | 
					            thatPlayerInNextFrame.framesToRecover = window.PunchAtkConfig.recoveryFrames;
 | 
				
			||||||
        nextRenderFramePlayers[playerId].framesToRecover = PunchAtkConfig.recoveryFrames;
 | 
					            const punch = window.pb.protos.MeleeBullet.create(window.PunchAtkConfig);
 | 
				
			||||||
        const punch = window.pb.protos.MeleeBullet.create(PunchAtkConfig);
 | 
					 | 
				
			||||||
            punch.battleLocalId = self.bulletBattleLocalIdCounter++;
 | 
					            punch.battleLocalId = self.bulletBattleLocalIdCounter++;
 | 
				
			||||||
            punch.offenderJoinIndex = joinIndex;
 | 
					            punch.offenderJoinIndex = joinIndex;
 | 
				
			||||||
            punch.offenderPlayerId = playerId;
 | 
					            punch.offenderPlayerId = playerId;
 | 
				
			||||||
            punch.originatedRenderFrameId = currRenderFrame.id;
 | 
					            punch.originatedRenderFrameId = currRenderFrame.id;
 | 
				
			||||||
            toRet.meleeBullets.push(punch);
 | 
					            toRet.meleeBullets.push(punch);
 | 
				
			||||||
        console.log(`A rising-edge of meleeBullet=${JSON.stringify(punch)} is created at renderFrame.id=${currRenderFrame.id}, delayedInputFrame.id=${delayedInputFrame.inputFrameId}`);
 | 
					            console.log(`A rising-edge of meleeBullet is created at renderFrame.id=${currRenderFrame.id}, delayedInputFrame.id=${delayedInputFrame.inputFrameId}: ${JSON.stringify(punch)}`);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        nextRenderFramePlayers[playerId].characterState = window.ATK_CHARACTER_STATE.Atk1[0];
 | 
					            thatPlayerInNextFrame.characterState = window.ATK_CHARACTER_STATE.Atk1[0];
 | 
				
			||||||
        */
 | 
					          }
 | 
				
			||||||
        } else if (0 == decodedInput.btnALevel && 1 == prevBtnALevel) {
 | 
					        } 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}`);
 | 
					          // console.log(`playerId=${playerId} triggered a falling-edge of btnA at renderFrame.id=${currRenderFrame.id}, delayedInputFrame.id=${delayedInputFrame.inputFrameId}`);
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
          // No trigger, process movement inputs
 | 
					          // No trigger, process movement inputs
 | 
				
			||||||
          if (0 != decodedInput.dx || 0 != decodedInput.dy) {
 | 
					          if (0 != decodedInput.dx || 0 != decodedInput.dy) {
 | 
				
			||||||
            // Update directions and thus would eventually update moving animation accordingly
 | 
					            // Update directions and thus would eventually update moving animation accordingly
 | 
				
			||||||
            nextRenderFramePlayers[playerId].dir.dx = decodedInput.dx;
 | 
					            thatPlayerInNextFrame.dirX = decodedInput.dx;
 | 
				
			||||||
            nextRenderFramePlayers[playerId].dir.dy = decodedInput.dy;
 | 
					            thatPlayerInNextFrame.dirY = decodedInput.dy;
 | 
				
			||||||
            nextRenderFramePlayers[playerId].characterState = window.ATK_CHARACTER_STATE.Walking[0];
 | 
					            thatPlayerInNextFrame.characterState = window.ATK_CHARACTER_STATE.Walking[0];
 | 
				
			||||||
          } else {
 | 
					          } else {
 | 
				
			||||||
            nextRenderFramePlayers[playerId].characterState = window.ATK_CHARACTER_STATE.Idle1[0];
 | 
					            thatPlayerInNextFrame.characterState = window.ATK_CHARACTER_STATE.Idle1[0];
 | 
				
			||||||
          }
 | 
					          }
 | 
				
			||||||
          const movement = self.virtualGridToWorldPos(decodedInput.dx + player.speed * decodedInput.dx, decodedInput.dy + player.speed * decodedInput.dy);
 | 
					          const movement = self.virtualGridToWorldPos(decodedInput.dx + currPlayerDownsync.speed * decodedInput.dx, decodedInput.dy + currPlayerDownsync.speed * decodedInput.dy);
 | 
				
			||||||
          playerCollider.x += movement[0];
 | 
					          playerCollider.x += movement[0];
 | 
				
			||||||
          playerCollider.y += movement[1];
 | 
					          playerCollider.y += movement[1];
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@@ -1204,8 +1202,9 @@ cc.Class({
 | 
				
			|||||||
        const collisionPlayerIndex = self.collisionPlayerIndexPrefix + joinIndex;
 | 
					        const collisionPlayerIndex = self.collisionPlayerIndexPrefix + joinIndex;
 | 
				
			||||||
        const playerCollider = collisionSysMap.get(collisionPlayerIndex);
 | 
					        const playerCollider = collisionSysMap.get(collisionPlayerIndex);
 | 
				
			||||||
        const newVpos = self.playerColliderAnchorToVirtualGridPos(playerCollider.x - effPushbacks[joinIndex - 1][0], playerCollider.y - effPushbacks[joinIndex - 1][1], self.playerRichInfoArr[j]);
 | 
					        const newVpos = self.playerColliderAnchorToVirtualGridPos(playerCollider.x - effPushbacks[joinIndex - 1][0], playerCollider.y - effPushbacks[joinIndex - 1][1], self.playerRichInfoArr[j]);
 | 
				
			||||||
        nextRenderFramePlayers[playerId].virtualGridX = newVpos[0];
 | 
					        const thatPlayerInNextFrame = nextRenderFramePlayers[playerId];
 | 
				
			||||||
        nextRenderFramePlayers[playerId].virtualGridY = newVpos[1];
 | 
					        thatPlayerInNextFrame.virtualGridX = newVpos[0];
 | 
				
			||||||
 | 
					        thatPlayerInNextFrame.virtualGridY = newVpos[1];
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -3,27 +3,27 @@ i18n.init(window.language); // languageID should be equal to the one we input in
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
const OnlineMap = require('./Map');
 | 
					const OnlineMap = require('./Map');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const PunchAtkConfig = {
 | 
					window.PunchAtkConfig = {
 | 
				
			||||||
  // for offender
 | 
					  // for offender
 | 
				
			||||||
  startupFrames: 18,
 | 
					  startupFrames: 18,
 | 
				
			||||||
  activeFrames: 42,
 | 
					  activeFrames: 42,
 | 
				
			||||||
  recoveryFrames: 60, // usually but not always "startupFrames+activeFrames"
 | 
					  recoveryFrames: 61, // usually but not always "startupFrames+activeFrames", I hereby set it to be 1 frame more than the actual animation to avoid critical transition, i.e. when the animation is 1 frame from ending but "rdfPlayer.framesToRecover" is already counted 0 and the player triggers an other same attack, making an effective bullet trigger but no animation is played due to same animName is still playing
 | 
				
			||||||
  recoveryFramesOnBlock: 60, // usually but not always the same as "recoveryFrames" 
 | 
					  recoveryFramesOnBlock: 61,
 | 
				
			||||||
  recoveryFramesOnHit: 60, // usually but not always the same as "recoveryFrames"
 | 
					  recoveryFramesOnHit: 61,
 | 
				
			||||||
  moveforward: {
 | 
					  moveforward: {
 | 
				
			||||||
    x: 0,
 | 
					    x: 0,
 | 
				
			||||||
    y: 0,
 | 
					    y: 0,
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  hitboxOffset: 12.0, // should be about the radius of the PlayerCollider 
 | 
					  hitboxOffset: 12.0, // should be about the radius of the PlayerCollider 
 | 
				
			||||||
  hitboxSize: {
 | 
					  hitboxSize: {
 | 
				
			||||||
    x: 32.0,
 | 
					    x: 45.0,
 | 
				
			||||||
    y: 32.0,
 | 
					    y: 32.0,
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // for defender
 | 
					  // for defender
 | 
				
			||||||
  hitStunFrames: 18,
 | 
					  hitStunFrames: 18,
 | 
				
			||||||
  blockStunFrames: 9,
 | 
					  blockStunFrames: 9,
 | 
				
			||||||
  pushback: 11.0,
 | 
					  pushback: 22.0,
 | 
				
			||||||
  releaseTriggerType: 1, // 1: rising-edge, 2: falling-edge  
 | 
					  releaseTriggerType: 1, // 1: rising-edge, 2: falling-edge  
 | 
				
			||||||
  damage: 5
 | 
					  damage: 5
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
@@ -35,45 +35,6 @@ cc.Class({
 | 
				
			|||||||
    console.warn("+++++++ Map onDestroy()");
 | 
					    console.warn("+++++++ Map onDestroy()");
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  spawnPlayerNode(joinIndex, vx, vy, playerRichInfo) {
 | 
					 | 
				
			||||||
    const self = this;
 | 
					 | 
				
			||||||
    const newPlayerNode = cc.instantiate(self.controlledCharacterPrefab)
 | 
					 | 
				
			||||||
    const playerScriptIns = newPlayerNode.getComponent("ControlledCharacter");
 | 
					 | 
				
			||||||
    if (1 == joinIndex) {
 | 
					 | 
				
			||||||
      playerScriptIns.setSpecies("SoldierWaterGhost");
 | 
					 | 
				
			||||||
    } else if (2 == joinIndex) {
 | 
					 | 
				
			||||||
      playerScriptIns.setSpecies("SoldierFireGhost");
 | 
					 | 
				
			||||||
      playerScriptIns.animComp.node.scaleX = (-1.0);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    const wpos = self.virtualGridToWorldPos(vx, vy);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    newPlayerNode.setPosition(cc.v2(wpos[0], wpos[1]));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    playerScriptIns.mapNode = self.node;
 | 
					 | 
				
			||||||
    const cpos = self.virtualGridToPlayerColliderPos(vx, vy, playerRichInfo);
 | 
					 | 
				
			||||||
    const d = playerRichInfo.colliderRadius * 2,
 | 
					 | 
				
			||||||
      x0 = cpos[0],
 | 
					 | 
				
			||||||
      y0 = cpos[1];
 | 
					 | 
				
			||||||
    let pts = [[0, 0], [d, 0], [d, d], [0, d]];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    const newPlayerCollider = self.collisionSys.createPolygon(x0, y0, pts);
 | 
					 | 
				
			||||||
    const collisionPlayerIndex = self.collisionPlayerIndexPrefix + joinIndex;
 | 
					 | 
				
			||||||
    newPlayerCollider.collisionPlayerIndex = parseInt(collisionPlayerIndex);
 | 
					 | 
				
			||||||
    newPlayerCollider.playerId = parseInt(playerRichInfo.id);
 | 
					 | 
				
			||||||
    self.collisionSysMap.set(collisionPlayerIndex, newPlayerCollider);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    safelyAddChild(self.node, newPlayerNode);
 | 
					 | 
				
			||||||
    setLocalZOrder(newPlayerNode, 5);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    newPlayerNode.active = true;
 | 
					 | 
				
			||||||
    playerScriptIns.updateCharacterAnim({
 | 
					 | 
				
			||||||
      dx: playerRichInfo.dir.dx,
 | 
					 | 
				
			||||||
      dy: playerRichInfo.dir.dy
 | 
					 | 
				
			||||||
    }, playerRichInfo, true);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    return [newPlayerNode, playerScriptIns];
 | 
					 | 
				
			||||||
  },
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  onLoad() {
 | 
					  onLoad() {
 | 
				
			||||||
    const self = this;
 | 
					    const self = this;
 | 
				
			||||||
    window.mapIns = self;
 | 
					    window.mapIns = self;
 | 
				
			||||||
@@ -182,10 +143,8 @@ cc.Class({
 | 
				
			|||||||
            colliderRadius: 12,
 | 
					            colliderRadius: 12,
 | 
				
			||||||
            characterState: window.ATK_CHARACTER_STATE.Idle1[0],
 | 
					            characterState: window.ATK_CHARACTER_STATE.Idle1[0],
 | 
				
			||||||
            framesToRecover: 0,
 | 
					            framesToRecover: 0,
 | 
				
			||||||
            dir: {
 | 
					            dirX: 0,
 | 
				
			||||||
              dx: 0,
 | 
					            dirY: 0,
 | 
				
			||||||
              dy: 0
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
          },
 | 
					          },
 | 
				
			||||||
          11: {
 | 
					          11: {
 | 
				
			||||||
            id: 11,
 | 
					            id: 11,
 | 
				
			||||||
@@ -196,10 +155,8 @@ cc.Class({
 | 
				
			|||||||
            colliderRadius: 12,
 | 
					            colliderRadius: 12,
 | 
				
			||||||
            characterState: window.ATK_CHARACTER_STATE.Idle1[0],
 | 
					            characterState: window.ATK_CHARACTER_STATE.Idle1[0],
 | 
				
			||||||
            framesToRecover: 0,
 | 
					            framesToRecover: 0,
 | 
				
			||||||
            dir: {
 | 
					            dirX: 0,
 | 
				
			||||||
              dx: 0,
 | 
					            dirY: 0,
 | 
				
			||||||
              dy: 0
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
          },
 | 
					          },
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      };
 | 
					      };
 | 
				
			||||||
@@ -243,214 +200,4 @@ cc.Class({
 | 
				
			|||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
 | 
					 | 
				
			||||||
  // Overriding this function to test experimental dynamics
 | 
					 | 
				
			||||||
  applyInputFrameDownsyncDynamicsOnSingleRenderFrame(delayedInputFrame, currRenderFrame, collisionSys, collisionSysMap) {
 | 
					 | 
				
			||||||
    const self = this;
 | 
					 | 
				
			||||||
    const nextRenderFramePlayers = {}
 | 
					 | 
				
			||||||
    for (let playerId in currRenderFrame.players) {
 | 
					 | 
				
			||||||
      const currPlayerDownsync = currRenderFrame.players[playerId];
 | 
					 | 
				
			||||||
      nextRenderFramePlayers[playerId] = {
 | 
					 | 
				
			||||||
        id: playerId,
 | 
					 | 
				
			||||||
        virtualGridX: currPlayerDownsync.virtualGridX,
 | 
					 | 
				
			||||||
        virtualGridY: currPlayerDownsync.virtualGridY,
 | 
					 | 
				
			||||||
        dir: {
 | 
					 | 
				
			||||||
          dx: currPlayerDownsync.dir.dx,
 | 
					 | 
				
			||||||
          dy: currPlayerDownsync.dir.dy,
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        characterState: currPlayerDownsync.characterState,
 | 
					 | 
				
			||||||
        speed: currPlayerDownsync.speed,
 | 
					 | 
				
			||||||
        battleState: currPlayerDownsync.battleState,
 | 
					 | 
				
			||||||
        score: currPlayerDownsync.score,
 | 
					 | 
				
			||||||
        removed: currPlayerDownsync.removed,
 | 
					 | 
				
			||||||
        joinIndex: currPlayerDownsync.joinIndex,
 | 
					 | 
				
			||||||
        framesToRecover: (0 < currPlayerDownsync.framesToRecover ? currPlayerDownsync.framesToRecover - 1 : 0),
 | 
					 | 
				
			||||||
        hp: currPlayerDownsync.hp,
 | 
					 | 
				
			||||||
        maxHp: currPlayerDownsync.maxHp,
 | 
					 | 
				
			||||||
      };
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    const toRet = {
 | 
					 | 
				
			||||||
      id: currRenderFrame.id + 1,
 | 
					 | 
				
			||||||
      players: nextRenderFramePlayers,
 | 
					 | 
				
			||||||
      meleeBullets: []
 | 
					 | 
				
			||||||
    };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    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
 | 
					 | 
				
			||||||
    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 player = currRenderFrame.players[playerId];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      const newVx = player.virtualGridX;
 | 
					 | 
				
			||||||
      const newVy = player.virtualGridY;
 | 
					 | 
				
			||||||
      const newCpos = self.virtualGridToPlayerColliderPos(newVx, newVy, self.playerRichInfoArr[joinIndex - 1]);
 | 
					 | 
				
			||||||
      playerCollider.x = newCpos[0];
 | 
					 | 
				
			||||||
      playerCollider.y = newCpos[1];
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // Check bullet-anything collisions first, because the pushbacks caused by bullets might later be reverted by player-barrier collision 
 | 
					 | 
				
			||||||
    const colliderBullets = 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) {
 | 
					 | 
				
			||||||
      const meleeBullet = currRenderFrame.meleeBullets[k];
 | 
					 | 
				
			||||||
      if (
 | 
					 | 
				
			||||||
        meleeBullet.originatedRenderFrameId + meleeBullet.startupFrames <= currRenderFrame.id
 | 
					 | 
				
			||||||
        &&
 | 
					 | 
				
			||||||
        meleeBullet.originatedRenderFrameId + meleeBullet.startupFrames + meleeBullet.activeFrames > currRenderFrame.id
 | 
					 | 
				
			||||||
      ) {
 | 
					 | 
				
			||||||
        const collisionBulletIndex = self.collisionBulletIndexPrefix + meleeBullet.battleLocalId;
 | 
					 | 
				
			||||||
        const collisionOffenderIndex = self.collisionPlayerIndexPrefix + meleeBullet.offenderJoinIndex;
 | 
					 | 
				
			||||||
        const offenderCollider = collisionSysMap.get(collisionOffenderIndex);
 | 
					 | 
				
			||||||
        const offender = currRenderFrame.players[meleeBullet.offenderPlayerId];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        const xfac = Math.sign(offender.dir.dx),
 | 
					 | 
				
			||||||
          yfac = 0; // By now, straight Punch offset doesn't respect "y-axis" 
 | 
					 | 
				
			||||||
        const x0 = offenderCollider.x + xfac * meleeBullet.hitboxOffset,
 | 
					 | 
				
			||||||
          y0 = offenderCollider.y + yfac * meleeBullet.hitboxOffset;
 | 
					 | 
				
			||||||
        const pts = [[0, 0], [xfac * meleeBullet.hitboxSize.x, 0], [xfac * meleeBullet.hitboxSize.x, meleeBullet.hitboxSize.y], [0, meleeBullet.hitboxSize.y]];
 | 
					 | 
				
			||||||
        const newBulletCollider = collisionSys.createPolygon(x0, y0, pts);
 | 
					 | 
				
			||||||
        newBulletCollider.collisionBulletIndex = collisionBulletIndex;
 | 
					 | 
				
			||||||
        newBulletCollider.offenderPlayerId = meleeBullet.offenderPlayerId;
 | 
					 | 
				
			||||||
        newBulletCollider.pushback = meleeBullet.pushback;
 | 
					 | 
				
			||||||
        newBulletCollider.hitStunFrames = meleeBullet.hitStunFrames;
 | 
					 | 
				
			||||||
        collisionSysMap.set(collisionBulletIndex, newBulletCollider);
 | 
					 | 
				
			||||||
        colliderBullets.set(collisionBulletIndex, newBulletCollider);
 | 
					 | 
				
			||||||
        console.log(`A meleeBullet=${JSON.stringify(meleeBullet)} is added to collisionSys at renderFrame.id=${currRenderFrame.id} as start-up frames ended and active frame is not yet ended`);
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    collisionSys.update();
 | 
					 | 
				
			||||||
    const result1 = collisionSys.createResult(); // Can I reuse a "self.collisionSysResult" object throughout the whole battle?
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    colliderBullets.forEach((bulletCollider, collisionBulletIndex) => {
 | 
					 | 
				
			||||||
      const potentials = bulletCollider.potentials();
 | 
					 | 
				
			||||||
      let shouldRemove = false;
 | 
					 | 
				
			||||||
      for (const potential of potentials) {
 | 
					 | 
				
			||||||
        if (null != potential.playerId && potential.playerId == bulletCollider.offenderPlayerId) continue;
 | 
					 | 
				
			||||||
        if (!bulletCollider.collides(potential, result1)) continue;
 | 
					 | 
				
			||||||
        if (null != potential.playerId) {
 | 
					 | 
				
			||||||
          const joinIndex = potential.collisionPlayerIndex - self.collisionPlayerIndexPrefix;
 | 
					 | 
				
			||||||
          bulletPushbacks[joinIndex - 1][0] += result1.overlap_x * bulletCollider.pushback;
 | 
					 | 
				
			||||||
          bulletPushbacks[joinIndex - 1][1] += result1.overlap_y * bulletCollider.pushback;
 | 
					 | 
				
			||||||
          const thatAckedPlayerInNextFrame = nextRenderFramePlayers[potential.playerId];
 | 
					 | 
				
			||||||
          thatAckedPlayerInNextFrame.characterState = window.ATK_CHARACTER_STATE.Atked1[0];
 | 
					 | 
				
			||||||
          const oldFrameToRecover = thatAckedPlayerInNextFrame.framesToRecover;
 | 
					 | 
				
			||||||
          thatAckedPlayerInNextFrame.framesToRecover = oldFrameToRecover > bulletCollider.hitStunFrames ? oldFrameToRecover : bulletCollider.hitStunFrames; // In case the hit player is already stun, we take the larger "hitStunFrames" 
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        shouldRemove = true;
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
      if (shouldRemove) {
 | 
					 | 
				
			||||||
        removedBulletsAtCurrFrame.add(collisionBulletIndex);
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    for (let k in currRenderFrame.meleeBullets) {
 | 
					 | 
				
			||||||
      const meleeBullet = currRenderFrame.meleeBullets[k];
 | 
					 | 
				
			||||||
      // [WARNING] remove from collisionSys ANYWAY for the convenience of rollback
 | 
					 | 
				
			||||||
      const collisionBulletIndex = self.collisionBulletIndexPrefix + meleeBullet.battleLocalId;
 | 
					 | 
				
			||||||
      if (collisionSysMap.has(collisionBulletIndex)) {
 | 
					 | 
				
			||||||
        const bulletCollider = collisionSysMap.get(collisionBulletIndex);
 | 
					 | 
				
			||||||
        bulletCollider.remove();
 | 
					 | 
				
			||||||
        collisionSysMap.delete(collisionBulletIndex);
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
      if (removedBulletsAtCurrFrame.has(collisionBulletIndex)) continue;
 | 
					 | 
				
			||||||
      toRet.meleeBullets.push(meleeBullet);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (null != delayedInputFrame) {
 | 
					 | 
				
			||||||
      const delayedInputFrameForPrevRenderFrame = self.getCachedInputFrameDownsyncWithPrediction(self._convertToInputFrameId(currRenderFrame.id - 1, self.inputDelayFrames));
 | 
					 | 
				
			||||||
      const inputList = delayedInputFrame.inputList;
 | 
					 | 
				
			||||||
      // Process player inputs
 | 
					 | 
				
			||||||
      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 player = currRenderFrame.players[playerId];
 | 
					 | 
				
			||||||
        if (0 < nextRenderFramePlayers[playerId].framesToRecover) {
 | 
					 | 
				
			||||||
          // No need to process inputs for this player, but there might be bullet pushbacks on this player  
 | 
					 | 
				
			||||||
          if (0 != bulletPushbacks[joinIndex - 1][0] || 0 != bulletPushbacks[joinIndex - 1][1]) {
 | 
					 | 
				
			||||||
            playerCollider.x += bulletPushbacks[joinIndex - 1][0];
 | 
					 | 
				
			||||||
            playerCollider.y += bulletPushbacks[joinIndex - 1][1];
 | 
					 | 
				
			||||||
            console.log(`playerId=${playerId}, joinIndex=${joinIndex} is pushbacked back by ${bulletPushbacks[joinIndex - 1]} by bullet impacts, now its framesToRecover is ${player.framesToRecover}`);
 | 
					 | 
				
			||||||
          }
 | 
					 | 
				
			||||||
          continue;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        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}`);
 | 
					 | 
				
			||||||
          nextRenderFramePlayers[playerId].framesToRecover = PunchAtkConfig.recoveryFrames;
 | 
					 | 
				
			||||||
          const punch = window.pb.protos.MeleeBullet.create(PunchAtkConfig);
 | 
					 | 
				
			||||||
          punch.battleLocalId = self.bulletBattleLocalIdCounter++;
 | 
					 | 
				
			||||||
          punch.offenderJoinIndex = joinIndex;
 | 
					 | 
				
			||||||
          punch.offenderPlayerId = playerId;
 | 
					 | 
				
			||||||
          punch.originatedRenderFrameId = currRenderFrame.id;
 | 
					 | 
				
			||||||
          toRet.meleeBullets.push(punch);
 | 
					 | 
				
			||||||
          console.log(`A rising-edge of meleeBullet=${JSON.stringify(punch)} is created at renderFrame.id=${currRenderFrame.id}, delayedInputFrame.id=${delayedInputFrame.inputFrameId}`);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
          nextRenderFramePlayers[playerId].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 trigger, process movement inputs
 | 
					 | 
				
			||||||
          if (0 != decodedInput.dx || 0 != decodedInput.dy) {
 | 
					 | 
				
			||||||
            // Update directions and thus would eventually update moving animation accordingly
 | 
					 | 
				
			||||||
            nextRenderFramePlayers[playerId].dir.dx = decodedInput.dx;
 | 
					 | 
				
			||||||
            nextRenderFramePlayers[playerId].dir.dy = decodedInput.dy;
 | 
					 | 
				
			||||||
            nextRenderFramePlayers[playerId].characterState = window.ATK_CHARACTER_STATE.Walking[0];
 | 
					 | 
				
			||||||
          } else {
 | 
					 | 
				
			||||||
            nextRenderFramePlayers[playerId].characterState = window.ATK_CHARACTER_STATE.Idle1[0];
 | 
					 | 
				
			||||||
          }
 | 
					 | 
				
			||||||
          const movement = self.virtualGridToWorldPos(decodedInput.dx + player.speed * decodedInput.dx, decodedInput.dy + player.speed * decodedInput.dy);
 | 
					 | 
				
			||||||
          playerCollider.x += movement[0];
 | 
					 | 
				
			||||||
          playerCollider.y += movement[1];
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      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 newVpos = self.playerColliderAnchorToVirtualGridPos(playerCollider.x - effPushbacks[joinIndex - 1][0], playerCollider.y - effPushbacks[joinIndex - 1][1], self.playerRichInfoArr[j]);
 | 
					 | 
				
			||||||
        nextRenderFramePlayers[playerId].virtualGridX = newVpos[0];
 | 
					 | 
				
			||||||
        nextRenderFramePlayers[playerId].virtualGridY = newVpos[1];
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    return toRet;
 | 
					 | 
				
			||||||
  },
 | 
					 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 
 | 
				
			|||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
		Reference in New Issue
	
	Block a user