Compare commits

..

8 Commits
v0.9 ... v0.9.5

Author SHA1 Message Date
genxium
34c4a24b64 Further enhanced backend dynamics force confirmation trigger. 2022-12-18 19:41:13 +08:00
genxium
4e7c3060fe Fixed frontend packaging. 2022-12-18 16:59:38 +08:00
genxium
2928cbbe3c Updated comments. 2022-12-18 14:03:22 +08:00
genxium
850eee20a8 Enhanced forceConfirmation trigger for backend dynamics. 2022-12-18 12:20:44 +08:00
genxium
5eec7fcfe7 Minor fix. 2022-12-17 18:22:52 +08:00
genxium
4e42c0770c Updated anim of the second character. 2022-12-17 18:15:29 +08:00
genxium
8647c1a859 Enhanced force-resync mechanism to guarantee consistency across all players in a same room upon anyone reconnected. 2022-12-16 18:59:58 +08:00
genxium
a41c68fb13 Applied snapping on all-sides to avoid random zero-overlap detection uncertainty. 2022-12-16 15:57:49 +08:00
45 changed files with 3081 additions and 1928 deletions

View File

@@ -2,15 +2,17 @@
1. Server received too late (solution: force confirmation)
2. Client received too late (solution: prediction and frame chasing, big impact on user experience because the graphics will be inconsistent if mismatches occur too often)
# Potential avalanche from local lag
# Potential avalanche from `ACTIVE SLOW TICKER`
Under the current "input delay" algorithm, the lag of a single player would cause all the other players to receive outdated commands, e.g. when at a certain moment
- player#1: renderFrameId = 100, significantly lagged due to local CPU overheated
- player#1: renderFrameId = 100, **still active in battle but significantly lagged** due to local CPU overheated
- player#2: renderFrameId = 240
- player#3: renderFrameId = 239
- player#4: renderFrameId = 242
players #2, #3 #4 would receive "outdated(in their subjective feelings) but all-confirmed commands" from then on, thus forced to rollback and chase many frames - the lag due to "large range of frame-chasing" would then further deteriorate the situation - like an avalanche.
**BE CAUTIOUS, THIS `ACTIVE SLOW TICKER` SITUATION HAPPENS QUITE OFTEN FOR REAL DEVICES** where different operating systems and temporary CPU overheat cause different lags for different player in a same battle! If not properly handled, slow tickers would be `inputing in the "history" of other players`, resulting in too frequent prediction mismatch and thus inconsistent graphics for other players!
In a "no-server & p2p" setup, I couldn't think of a proper way to cope with such edge case. Solely on the frontend we could only mitigate the impact to players #2, #3, #4, e.g. a potential lag due to "large range of frame-chasing" is proactively avoided in `<proj-root>/frontend/assets/scripts/Map.js, function update(dt)`.
To be fair, **a "p2p" setup can reduce round-trip to single-trip**, but w/o a point of authority in such case player#1 needs a way to recognize the slowness (e.g. check the received peer inputs) and ticks faster for a while to catch up; in contrast in a "server as authority" setup, the server could force confirming an inputFrame without player#1's upsync, and notify player#1 to apply a "roomDownsyncFrame" as well as drop all its outdated local inputFrames.

View File

@@ -1,6 +1,7 @@
PROJECTNAME=server.exe
ROOT_DIR=.
GOPROXY=https://mirrors.aliyun.com/goproxy
#GOPROXY=https://mirrors.aliyun.com/goproxy
GOPROXY=https://goproxy.io
all: help
gen-constants:

View File

@@ -61,13 +61,13 @@ const (
)
const (
ATK_CHARACTER_STATE_IDLE1 = 0
ATK_CHARACTER_STATE_WALKING = 1
ATK_CHARACTER_STATE_ATK1 = 2
ATK_CHARACTER_STATE_ATKED1 = 3
ATK_CHARACTER_STATE_INAIR_IDLE1 = 4
ATK_CHARACTER_STATE_INAIR_ATK1 = 5
ATK_CHARACTER_STATE_INAIR_ATKED1 = 6
ATK_CHARACTER_STATE_IDLE1 = int32(0)
ATK_CHARACTER_STATE_WALKING = int32(1)
ATK_CHARACTER_STATE_ATK1 = int32(2)
ATK_CHARACTER_STATE_ATKED1 = int32(3)
ATK_CHARACTER_STATE_INAIR_IDLE1 = int32(4)
ATK_CHARACTER_STATE_INAIR_ATK1 = int32(5)
ATK_CHARACTER_STATE_INAIR_ATKED1 = int32(6)
)
const (
@@ -161,8 +161,9 @@ type Room struct {
DismissalWaitGroup sync.WaitGroup
Barriers map[int32]*Barrier
InputsBuffer *RingBuffer // Indices are STRICTLY consecutive
InputsBufferLock sync.Mutex // Guards [InputsBuffer, LastAllConfirmedInputFrameId, LastAllConfirmedInputList, LastAllConfirmedInputFrameIdWithChange]
InputsBufferLock sync.Mutex // Guards [InputsBuffer, LatestPlayerUpsyncedInputFrameId, LastAllConfirmedInputFrameId, LastAllConfirmedInputList, LastAllConfirmedInputFrameIdWithChange]
RenderFrameBuffer *RingBuffer // Indices are STRICTLY consecutive
LatestPlayerUpsyncedInputFrameId int32
LastAllConfirmedInputFrameId int32
LastAllConfirmedInputFrameIdWithChange int32
LastAllConfirmedInputList []uint64
@@ -401,11 +402,11 @@ func (pR *Room) StartBattle() {
pR.collisionSpaceOffsetX, pR.collisionSpaceOffsetY = float64(spaceW)*0.5, float64(spaceH)*0.5
pR.refreshColliders(spaceW, spaceH)
/**
* Will be triggered from a goroutine which executes the critical `Room.AddPlayerIfPossible`, thus the `battleMainLoop` should be detached.
* All of the consecutive stages, e.g. settlement, dismissal, should share the same goroutine with `battleMainLoop`.
*
* As "defer" is only applicable to function scope, the use of "pR.InputsBufferLock" within "battleMainLoop" is embedded into each subroutine call.
/*
Will be triggered from a goroutine which executes the critical `Room.AddPlayerIfPossible`, thus the `battleMainLoop` should be detached.
All of the consecutive stages, e.g. settlement, dismissal, should share the same goroutine with `battleMainLoop`.
As "defer" is only applicable to function scope, the use of "pR.InputsBufferLock" within "battleMainLoop" is embedded into each subroutine call.
*/
battleMainLoop := func() {
defer func() {
@@ -451,10 +452,7 @@ func (pR *Room) StartBattle() {
thatPlayerBattleState := atomic.LoadInt32(&(player.BattleState)) // Might be changed in "OnPlayerDisconnected/OnPlayerLost" from other threads
// [WARNING] DON'T try to send any message to an inactive player!
switch thatPlayerBattleState {
case PlayerBattleStateIns.DISCONNECTED:
case PlayerBattleStateIns.LOST:
case PlayerBattleStateIns.EXPELLED_DURING_GAME:
case PlayerBattleStateIns.EXPELLED_IN_DISMISSAL:
case PlayerBattleStateIns.DISCONNECTED, PlayerBattleStateIns.LOST, PlayerBattleStateIns.EXPELLED_DURING_GAME, PlayerBattleStateIns.EXPELLED_IN_DISMISSAL:
continue
}
kickoffFrame := pR.RenderFrameBuffer.GetByFrameId(0).(*RoomDownsyncFrame)
@@ -500,16 +498,12 @@ func (pR *Room) StartBattle() {
case inputsBufferSnapshot := <-playerDownsyncChan:
nowBattleState := atomic.LoadInt32(&pR.State)
switch nowBattleState {
case RoomBattleStateIns.IDLE:
case RoomBattleStateIns.STOPPING_BATTLE_FOR_SETTLEMENT:
case RoomBattleStateIns.IN_SETTLEMENT:
case RoomBattleStateIns.IN_DISMISSAL:
case RoomBattleStateIns.IDLE, RoomBattleStateIns.STOPPING_BATTLE_FOR_SETTLEMENT, RoomBattleStateIns.IN_SETTLEMENT, RoomBattleStateIns.IN_DISMISSAL:
Logger.Warn(fmt.Sprintf("Battle is not waiting/preparing/active for playerDownsyncChan for (roomId: %d, playerId:%d)", pR.Id, playerId))
return
}
pR.downsyncToSinglePlayer(playerId, player, inputsBufferSnapshot.RefRenderFrameId, inputsBufferSnapshot.UnconfirmedMask, inputsBufferSnapshot.ToSendInputFrameDownsyncs)
Logger.Debug(fmt.Sprintf("Sent inputsBufferSnapshot(refRenderFrameId:%d, unconfirmedMask:%v) to for (roomId: %d, playerId:%d)#2", inputsBufferSnapshot.RefRenderFrameId, inputsBufferSnapshot.UnconfirmedMask, pR.Id, playerId))
pR.downsyncToSinglePlayer(playerId, player, inputsBufferSnapshot.RefRenderFrameId, inputsBufferSnapshot.UnconfirmedMask, inputsBufferSnapshot.ToSendInputFrameDownsyncs, inputsBufferSnapshot.ShouldForceResync)
//Logger.Info(fmt.Sprintf("Sent inputsBufferSnapshot(refRenderFrameId:%d, unconfirmedMask:%v) to for (roomId: %d, playerId:%d)#2", inputsBufferSnapshot.RefRenderFrameId, inputsBufferSnapshot.UnconfirmedMask, pR.Id, playerId))
default:
}
}
@@ -740,6 +734,7 @@ func (pR *Room) OnDismissed() {
pR.RenderFrameBuffer = NewRingBuffer(pR.RenderCacheSize)
pR.InputsBuffer = NewRingBuffer((pR.RenderCacheSize >> 1) + 1)
pR.LatestPlayerUpsyncedInputFrameId = -1
pR.LastAllConfirmedInputFrameId = -1
pR.LastAllConfirmedInputFrameIdWithChange = -1
pR.LastAllConfirmedInputList = make([]uint64, pR.Capacity)
@@ -747,14 +742,14 @@ func (pR *Room) OnDismissed() {
pR.RenderFrameId = 0
pR.CurDynamicsRenderFrameId = 0
pR.InputDelayFrames = 8
pR.NstDelayFrames = 8
pR.NstDelayFrames = 12
pR.InputScaleFrames = uint32(2)
pR.ServerFps = 60
pR.RollbackEstimatedDtMillis = 16.667 // Use fixed-and-low-precision to mitigate the inconsistent floating-point-number issue between Golang and JavaScript
pR.RollbackEstimatedDtNanos = 16666666 // A little smaller than the actual per frame time, just for logging FAST FRAME
dilutedServerFps := float64(55.0)
dilutedServerFps := float64(57.0) // Don't set this value too small, otherwise we might miss force confirmation needs for slow tickers!
pR.dilutedRollbackEstimatedDtNanos = int64(float64(pR.RollbackEstimatedDtNanos) * float64(pR.ServerFps) / dilutedServerFps)
pR.BattleDurationFrames = 60 * pR.ServerFps
pR.BattleDurationFrames = 90 * pR.ServerFps
pR.BattleDurationNanos = int64(pR.BattleDurationFrames) * (pR.RollbackEstimatedDtNanos + 1)
pR.InputFrameUpsyncDelayTolerance = 2
pR.MaxChasingRenderFramesPerUpdate = 8
@@ -765,7 +760,7 @@ func (pR *Room) OnDismissed() {
pR.MeleeSkillConfig[punchSkillId] = &MeleeBullet{
// for offender
StartupFrames: int32(10),
ActiveFrames: int32(3),
ActiveFrames: int32(10),
RecoveryFrames: int32(34),
RecoveryFramesOnBlock: int32(34),
RecoveryFramesOnHit: int32(34),
@@ -837,10 +832,7 @@ func (pR *Room) OnPlayerDisconnected(playerId int32) {
if player, existent := pR.Players[playerId]; existent {
thatPlayerBattleState := atomic.LoadInt32(&(player.BattleState))
switch thatPlayerBattleState {
case PlayerBattleStateIns.DISCONNECTED:
case PlayerBattleStateIns.LOST:
case PlayerBattleStateIns.EXPELLED_DURING_GAME:
case PlayerBattleStateIns.EXPELLED_IN_DISMISSAL:
case PlayerBattleStateIns.DISCONNECTED, PlayerBattleStateIns.LOST, PlayerBattleStateIns.EXPELLED_DURING_GAME, PlayerBattleStateIns.EXPELLED_IN_DISMISSAL:
Logger.Info("Room OnPlayerDisconnected[early return #1]:", zap.Any("playerId", playerId), zap.Any("playerBattleState", pR.Players[playerId].BattleState), zap.Any("roomId", pR.Id), zap.Any("nowRoomBattleState", pR.State), zap.Any("nowRoomEffectivePlayerCount", pR.EffectivePlayerCount))
return
}
@@ -987,6 +979,7 @@ func (pR *Room) OnPlayerBattleColliderAcked(playerId int32) bool {
case PlayerBattleStateIns.READDED_PENDING_BATTLE_COLLIDER_ACK:
shouldTryToStartBattle = false
atomic.StoreInt32(&(targetPlayer.BattleState), PlayerBattleStateIns.READDED_BATTLE_COLLIDER_ACKED)
Logger.Warn(fmt.Sprintf("OnPlayerBattleColliderAcked-reAdded: roomId=%v, roomState=%v, targetPlayerId=%v, targetPlayerBattleState=%v, capacity=%v, EffectivePlayerCount=%v", pR.Id, pR.State, targetPlayer.Id, targetPlayer.BattleState, pR.Capacity, pR.EffectivePlayerCount))
default:
}
@@ -1094,7 +1087,7 @@ func (pR *Room) markConfirmationIfApplicable(inputFrameUpsyncBatch []*InputFrame
continue
}
if clientInputFrameId < pR.LastAllConfirmedInputFrameId {
Logger.Info(fmt.Sprintf("Omitting obsolete inputFrameUpsync#2: roomId=%v, playerId=%v, clientInputFrameId=%v, InputsBuffer=%v", pR.Id, playerId, clientInputFrameId, pR.InputsBufferString(false)))
Logger.Debug(fmt.Sprintf("Omitting obsolete inputFrameUpsync#2: roomId=%v, playerId=%v, clientInputFrameId=%v, InputsBuffer=%v", pR.Id, playerId, clientInputFrameId, pR.InputsBufferString(false)))
continue
}
if clientInputFrameId > pR.InputsBuffer.EdFrameId {
@@ -1111,6 +1104,10 @@ func (pR *Room) markConfirmationIfApplicable(inputFrameUpsyncBatch []*InputFrame
}
targetInputFrameDownsync.InputList[player.JoinIndex-1] = inputFrameUpsync.Encoded
targetInputFrameDownsync.ConfirmedList |= uint64(1 << uint32(player.JoinIndex-1))
if inputFrameUpsync.InputFrameId > pR.LatestPlayerUpsyncedInputFrameId {
pR.LatestPlayerUpsyncedInputFrameId = inputFrameUpsync.InputFrameId
}
}
newAllConfirmedCount := int32(0)
@@ -1174,69 +1171,61 @@ func (pR *Room) markConfirmationIfApplicable(inputFrameUpsyncBatch []*InputFrame
func (pR *Room) forceConfirmationIfApplicable(prevRenderFrameId int32) *InputsBufferSnapshot {
// [WARNING] This function MUST BE called while "pR.InputsBufferLock" is locked!
// Force confirmation of non-all-confirmed inputFrame EXACTLY ONE AT A TIME, returns the non-confirmed mask of players, e.g. in a 4-player-battle returning 1001 means that players with JoinIndex=1 and JoinIndex=4 are non-confirmed for inputFrameId2
renderFrameId1 := (pR.RenderFrameId - pR.NstDelayFrames) // the renderFrameId which should've been rendered on frontend
if 0 > renderFrameId1 {
return nil
}
ok := false
renderFrameId2 := int32(-1)
if ok, renderFrameId2 = pR.shouldPrefabInputFrameDownsync(prevRenderFrameId-pR.NstDelayFrames, renderFrameId1); !ok {
/*
The backend "shouldPrefabInputFrameDownsync" shares the same rule as frontend "shouldGenerateInputFrameUpsync".
It's also important that "forceConfirmationIfApplicable" is NOT EXECUTED for every renderFrame, such that when a player is forced to resync, it has some time, i.e. (1 << InputScaleFrames) renderFrames, to upsync again.
*/
return nil
}
inputFrameId2 := pR.ConvertToInputFrameId(renderFrameId2, 0) // The inputFrame to force confirmation (if necessary)
if inputFrameId2 < pR.LastAllConfirmedInputFrameId {
// No need to force confirmation, the inputFrames already arrived
Logger.Debug(fmt.Sprintf("inputFrameId2=%v is already all-confirmed for roomId=%v[type#1], no need to force confirmation of it", inputFrameId2, pR.Id))
return nil
}
tmp := pR.InputsBuffer.GetByFrameId(inputFrameId2)
if nil == tmp {
panic(fmt.Sprintf("inputFrameId2=%v doesn't exist for roomId=%v, this is abnormal because the server should prefab inputFrameDownsync in a most advanced pace, check the prefab logic! InputsBuffer=%v", inputFrameId2, pR.Id, pR.InputsBufferString(false)))
}
totPlayerCnt := uint32(pR.Capacity)
allConfirmedMask := uint64((1 << totPlayerCnt) - 1)
// Force confirmation of "inputFrame2"
inputFrame2 := tmp.(*InputFrameDownsync)
oldConfirmedList := inputFrame2.ConfirmedList
unconfirmedMask := (oldConfirmedList ^ allConfirmedMask)
inputFrame2.ConfirmedList = allConfirmedMask
pR.onInputFrameDownsyncAllConfirmed(inputFrame2, -1)
if 0 < unconfirmedMask {
// This condition should be rarely met!
/*
Upon resynced on frontend, "refRenderFrameId" is now set to as advanced as possible, and it's the frontend's responsibility now to pave way for the "gap inputFrames"
If "NstDelayFrames" becomes larger, "pR.RenderFrameId - refRenderFrameId" possibly becomes larger because the force confirmation is delayed more.
Upon resync, it's still possible that "refRenderFrameId < frontend.chaserRenderFrameId" -- and this is allowed.
*/
refRenderFrameIdIfNeeded := pR.ConvertToLastUsedRenderFrameId(pR.LastAllConfirmedInputFrameId, pR.InputDelayFrames)
var inputsBufferSnapshot *InputsBufferSnapshot = nil
if pR.LatestPlayerUpsyncedInputFrameId > (pR.LastAllConfirmedInputFrameId + (pR.NstDelayFrames >> pR.InputScaleFrames)) {
// Type#1 check whether there's a significantly slow ticker among players
for j := pR.LastAllConfirmedInputFrameId + 1; j <= pR.LatestPlayerUpsyncedInputFrameId; j++ {
tmp := pR.InputsBuffer.GetByFrameId(j)
if nil == tmp {
panic(fmt.Sprintf("inputFrameId=%v doesn't exist for roomId=%v! InputsBuffer=%v", j, pR.Id, pR.InputsBufferString(false)))
}
inputFrameDownsync := tmp.(*InputFrameDownsync)
pR.onInputFrameDownsyncAllConfirmed(inputFrameDownsync, -1)
}
refRenderFrameIdIfNeeded := pR.CurDynamicsRenderFrameId - 1
if 0 > refRenderFrameIdIfNeeded {
// Without a "refRenderFrame", there's no point to force confirmation, i.e. nothing to downsync to the "ACTIVE but slowly ticking frontend(s)"
return nil
}
Logger.Warn(fmt.Sprintf("[type#1 forceConfirmation] For roomId=%d@renderFrameId=%d, curDynamicsRenderFrameId=%d, LatestPlayerUpsyncedInputFrameId:%d, LastAllConfirmedInputFrameId:%d, (pR.NstDelayFrames >> pR.InputScaleFrames):%d; there's a slow ticker suspect, forcing all-confirmation", pR.Id, pR.RenderFrameId, pR.CurDynamicsRenderFrameId, pR.LatestPlayerUpsyncedInputFrameId, pR.LastAllConfirmedInputFrameId, (pR.NstDelayFrames >> pR.InputScaleFrames)))
snapshotStFrameId := pR.ConvertToInputFrameId(refRenderFrameIdIfNeeded, pR.InputDelayFrames)
toSendInputFrameDownsyncs := pR.cloneInputsBuffer(snapshotStFrameId, pR.LastAllConfirmedInputFrameId+1)
return &InputsBufferSnapshot{
// Duplicate downsynced inputFrameIds will be filtered out by frontend.
toSendInputFrameDownsyncs := pR.cloneInputsBuffer(snapshotStFrameId, pR.LatestPlayerUpsyncedInputFrameId+1)
inputsBufferSnapshot = &InputsBufferSnapshot{
RefRenderFrameId: refRenderFrameIdIfNeeded,
UnconfirmedMask: unconfirmedMask,
UnconfirmedMask: allConfirmedMask, // Will force resync all players in the same battle.
ToSendInputFrameDownsyncs: toSendInputFrameDownsyncs,
}
} else {
return nil
// Type#2 helps resolve the edge case when all players are disconnected temporarily
shouldForceResync := false
for _, player := range pR.PlayersArr {
playerBattleState := atomic.LoadInt32(&(player.BattleState))
if PlayerBattleStateIns.READDED_BATTLE_COLLIDER_ACKED == playerBattleState {
shouldForceResync = true
break
}
}
if shouldForceResync {
refRenderFrameIdIfNeeded := pR.CurDynamicsRenderFrameId - 1
if 0 > refRenderFrameIdIfNeeded {
return nil
}
Logger.Warn(fmt.Sprintf("[type#2 forceConfirmation] For roomId=%d@renderFrameId=%d, curDynamicsRenderFrameId=%d, LatestPlayerUpsyncedInputFrameId:%d, LastAllConfirmedInputFrameId:%d; there's at least one reconnected player, forcing all-confirmation", pR.Id, pR.RenderFrameId, pR.CurDynamicsRenderFrameId, pR.LatestPlayerUpsyncedInputFrameId, pR.LastAllConfirmedInputFrameId))
snapshotStFrameId := pR.ConvertToInputFrameId(refRenderFrameIdIfNeeded, pR.InputDelayFrames)
// Duplicate downsynced inputFrameIds will be filtered out by frontend.
toSendInputFrameDownsyncs := pR.cloneInputsBuffer(snapshotStFrameId, pR.LatestPlayerUpsyncedInputFrameId+1)
inputsBufferSnapshot = &InputsBufferSnapshot{
RefRenderFrameId: refRenderFrameIdIfNeeded,
UnconfirmedMask: allConfirmedMask, // Will force resync all players in the same battle.
ToSendInputFrameDownsyncs: toSendInputFrameDownsyncs,
}
}
}
return inputsBufferSnapshot
}
func (pR *Room) applyInputFrameDownsyncDynamics(fromRenderFrameId int32, toRenderFrameId int32, spaceOffsetX, spaceOffsetY float64) {
@@ -1278,6 +1267,7 @@ func (pR *Room) applyInputFrameDownsyncDynamics(fromRenderFrameId int32, toRende
// TODO: Write unit-test for this function to compare with its frontend counter part
func (pR *Room) applyInputFrameDownsyncDynamicsOnSingleRenderFrame(delayedInputFrame *InputFrameDownsync, currRenderFrame *RoomDownsyncFrame, collisionSysMap map[int32]*resolv.Object) *RoomDownsyncFrame {
topPadding, bottomPadding, leftPadding, rightPadding := pR.SnapIntoPlatformOverlap, pR.SnapIntoPlatformOverlap, pR.SnapIntoPlatformOverlap, pR.SnapIntoPlatformOverlap
// [WARNING] This function MUST BE called while "pR.InputsBufferLock" is locked!
nextRenderFramePlayers := make(map[int32]*PlayerDownsync, pR.Capacity)
// Make a copy first
@@ -1344,9 +1334,9 @@ func (pR *Room) applyInputFrameDownsyncDynamicsOnSingleRenderFrame(delayedInputF
}
if !characStateAlreadyInAir && characStateIsInterruptWaivable {
thatPlayerInNextFrame.VelY = pR.JumpingInitVelY
if 1 == currPlayerDownsync.JoinIndex {
Logger.Info(fmt.Sprintf("playerId=%v, joinIndex=%v jumped at {renderFrame.id: %d, virtualX: %d, virtualY: %d, nextVelX: %d, nextVelY: %d}, delayedInputFrame.id=%d", playerId, joinIndex, currRenderFrame.Id, currPlayerDownsync.VirtualGridX, currPlayerDownsync.VirtualGridY, thatPlayerInNextFrame.VelX, thatPlayerInNextFrame.VelY, delayedInputFrame.InputFrameId))
}
// if 1 == currPlayerDownsync.JoinIndex {
// Logger.Info(fmt.Sprintf("playerId=%v, joinIndex=%v jumped at {renderFrame.id: %d, virtualX: %d, virtualY: %d, nextVelX: %d, nextVelY: %d, nextCharacterState=%d, inAir=%v}, delayedInputFrame.id=%d", playerId, joinIndex, currRenderFrame.Id, currPlayerDownsync.VirtualGridX, currPlayerDownsync.VirtualGridY, thatPlayerInNextFrame.VelX, thatPlayerInNextFrame.VelY, thatPlayerInNextFrame.CharacterState, currPlayerDownsync.InAir, delayedInputFrame.InputFrameId))
// }
}
}
@@ -1395,9 +1385,12 @@ func (pR *Room) applyInputFrameDownsyncDynamicsOnSingleRenderFrame(delayedInputF
currPlayerDownsync, thatPlayerInNextFrame := currRenderFrame.Players[playerId], nextRenderFramePlayers[playerId]
// Reset playerCollider position from the "virtual grid position"
newVx, newVy := currPlayerDownsync.VirtualGridX+currPlayerDownsync.VelX, currPlayerDownsync.VirtualGridY+currPlayerDownsync.VelY
if thatPlayerInNextFrame.VelY == pR.JumpingInitVelY {
newVy += thatPlayerInNextFrame.VelY
}
colliderWidth, colliderHeight := player.ColliderRadius*2, player.ColliderRadius*4
playerCollider.X, playerCollider.Y = VirtualGridToPolygonColliderBLPos(newVx, newVy, colliderWidth*0.5, colliderHeight*0.5, pR.SnapIntoPlatformOverlap, pR.collisionSpaceOffsetX, pR.collisionSpaceOffsetY, pR.VirtualGridToWorldRatio)
halfColliderWidth, halfColliderHeight := player.ColliderRadius, player.ColliderRadius+player.ColliderRadius // avoid multiplying
playerCollider.X, playerCollider.Y = VirtualGridToPolygonColliderBLPos(newVx, newVy, halfColliderWidth, halfColliderHeight, topPadding, bottomPadding, leftPadding, rightPadding, pR.collisionSpaceOffsetX, pR.collisionSpaceOffsetY, pR.VirtualGridToWorldRatio)
// Update in the collision system
playerCollider.Update()
@@ -1423,8 +1416,7 @@ func (pR *Room) applyInputFrameDownsyncDynamicsOnSingleRenderFrame(delayedInputF
}
offenderWx, offenderWy := VirtualGridToWorldPos(offender.VirtualGridX, offender.VirtualGridY, pR.VirtualGridToWorldRatio)
bulletWx, bulletWy := offenderWx+xfac*meleeBullet.HitboxOffset, offenderWy
newBulletCollider := GenerateRectCollider(bulletWx, bulletWy, meleeBullet.HitboxSize.X, meleeBullet.HitboxSize.Y, 0, pR.collisionSpaceOffsetX, pR.collisionSpaceOffsetY, "MeleeBullet")
newBulletCollider := GenerateRectCollider(bulletWx, bulletWy, meleeBullet.HitboxSize.X, meleeBullet.HitboxSize.Y, topPadding, bottomPadding, leftPadding, rightPadding, pR.collisionSpaceOffsetX, pR.collisionSpaceOffsetY, "MeleeBullet")
newBulletCollider.Data = meleeBullet
pR.Space.Add(newBulletCollider)
collisionSysMap[collisionBulletIndex] = newBulletCollider
@@ -1444,65 +1436,65 @@ func (pR *Room) applyInputFrameDownsyncDynamicsOnSingleRenderFrame(delayedInputF
playerCollider := collisionSysMap[collisionPlayerIndex]
playerShape := playerCollider.Shape.(*resolv.ConvexPolygon)
hardPushbackNorms[joinIndex-1] = pR.calcHardPushbacksNorms(playerCollider, playerShape, pR.SnapIntoPlatformOverlap, &(effPushbacks[joinIndex-1]))
if 0 < len(hardPushbackNorms[joinIndex-1]) {
Logger.Debug(fmt.Sprintf("playerId=%d, joinIndex=%d got %d non-empty hardPushbacks at renderFrame.id=%d", playerId, joinIndex, len(hardPushbackNorms), currRenderFrame.Id))
}
currPlayerDownsync, thatPlayerInNextFrame := currRenderFrame.Players[playerId], nextRenderFramePlayers[playerId]
fallStopping := false
possiblyFallStoppedOnAnotherPlayer := false
collision := playerCollider.Check(0, 0)
if nil == collision {
continue
}
for _, obj := range collision.Objects {
isBarrier, isAnotherPlayer, isBullet := false, false, false
switch obj.Data.(type) {
case *Barrier:
isBarrier = true
case *Player:
isAnotherPlayer = true
case *MeleeBullet:
isBullet = true
}
if isBullet {
// ignore bullets for this step
continue
}
bShape := obj.Shape.(*resolv.ConvexPolygon)
overlapped, pushbackX, pushbackY, overlapResult := CalcPushbacks(0, 0, playerShape, bShape)
if !overlapped {
continue
}
normAlignmentWithGravity := (overlapResult.OverlapX*float64(0) + overlapResult.OverlapY*float64(-1.0))
landedOnGravityPushback := (pR.SnapIntoPlatformThreshold < normAlignmentWithGravity) // prevents false snapping on the lateral sides
if landedOnGravityPushback {
// kindly note that one player might land on top of another player, and snapping is also required in such case
pushbackX, pushbackY = (overlapResult.Overlap-pR.SnapIntoPlatformOverlap)*overlapResult.OverlapX, (overlapResult.Overlap-pR.SnapIntoPlatformOverlap)*overlapResult.OverlapY
thatPlayerInNextFrame.InAir = false
}
for _, hardPushbackNorm := range hardPushbackNorms[joinIndex-1] {
projectedMagnitude := pushbackX*hardPushbackNorm.X + pushbackY*hardPushbackNorm.Y
if isBarrier || (isAnotherPlayer && 0 > projectedMagnitude) {
pushbackX -= projectedMagnitude * hardPushbackNorm.X
pushbackY -= projectedMagnitude * hardPushbackNorm.Y
if collision := playerCollider.Check(0, 0); nil != collision {
for _, obj := range collision.Objects {
isBarrier, isAnotherPlayer, isBullet := false, false, false
switch obj.Data.(type) {
case *Barrier:
isBarrier = true
case *Player:
isAnotherPlayer = true
case *MeleeBullet:
isBullet = true
}
if isBullet {
// ignore bullets for this step
continue
}
bShape := obj.Shape.(*resolv.ConvexPolygon)
overlapped, pushbackX, pushbackY, overlapResult := CalcPushbacks(0, 0, playerShape, bShape)
if !overlapped {
continue
}
normAlignmentWithGravity := (overlapResult.OverlapX*float64(0) + overlapResult.OverlapY*float64(-1.0))
landedOnGravityPushback := (pR.SnapIntoPlatformThreshold < normAlignmentWithGravity) // prevents false snapping on the lateral sides
if landedOnGravityPushback {
// kindly note that one player might land on top of another player, and snapping is also required in such case
pushbackX, pushbackY = (overlapResult.Overlap-pR.SnapIntoPlatformOverlap)*overlapResult.OverlapX, (overlapResult.Overlap-pR.SnapIntoPlatformOverlap)*overlapResult.OverlapY
thatPlayerInNextFrame.InAir = false
}
}
effPushbacks[joinIndex-1].X += pushbackX
effPushbacks[joinIndex-1].Y += pushbackY
if currPlayerDownsync.InAir && landedOnGravityPushback {
fallStopping = true
if isAnotherPlayer {
possiblyFallStoppedOnAnotherPlayer = true
// [WARNING] See comments of this substep in frontend.
pushbackX, pushbackY = (overlapResult.Overlap-pR.SnapIntoPlatformOverlap*2)*overlapResult.OverlapX, (overlapResult.Overlap-pR.SnapIntoPlatformOverlap*2)*overlapResult.OverlapY
}
if 1 == thatPlayerInNextFrame.JoinIndex {
Logger.Info(fmt.Sprintf("playerId=%d, joinIndex=%d fallStopping#1 at {renderFrame.id: %d, virtualX: %d, virtualY: %d, velX: %d, velY: %d} with effPushback={%.3f, %.3f}, overlapMag=%.4f, possiblyFallStoppedOnAnotherPlayer=%v", playerId, joinIndex, currRenderFrame.Id, currPlayerDownsync.VirtualGridX, currPlayerDownsync.VirtualGridY, currPlayerDownsync.VelX, currPlayerDownsync.VelY, effPushbacks[joinIndex-1].X, effPushbacks[joinIndex-1].Y, overlapResult.Overlap, possiblyFallStoppedOnAnotherPlayer))
for _, hardPushbackNorm := range hardPushbackNorms[joinIndex-1] {
projectedMagnitude := pushbackX*hardPushbackNorm.X + pushbackY*hardPushbackNorm.Y
if isBarrier || (isAnotherPlayer && 0 > projectedMagnitude) {
pushbackX -= projectedMagnitude * hardPushbackNorm.X
pushbackY -= projectedMagnitude * hardPushbackNorm.Y
}
}
effPushbacks[joinIndex-1].X += pushbackX
effPushbacks[joinIndex-1].Y += pushbackY
if currPlayerDownsync.InAir && landedOnGravityPushback {
fallStopping = true
if isAnotherPlayer {
possiblyFallStoppedOnAnotherPlayer = true
}
}
if 1 == joinIndex {
halfColliderWidth, halfColliderHeight := player.ColliderRadius, player.ColliderRadius+player.ColliderRadius // avoid multiplying
if fallStopping {
Logger.Debug(fmt.Sprintf("playerId=%d, joinIndex=%d fallStopping#1\n{renderFrame.id: %d, possiblyFallStoppedOnAnotherPlayer: %v}\nplayerColliderPos=%v, effPushback={%.3f, %.3f}, overlapMag=%.4f", playerId, joinIndex, currRenderFrame.Id, possiblyFallStoppedOnAnotherPlayer, RectCenterStr(playerCollider, halfColliderWidth, halfColliderHeight, topPadding, bottomPadding, leftPadding, rightPadding, pR.collisionSpaceOffsetX, pR.collisionSpaceOffsetY), effPushbacks[joinIndex-1].X, effPushbacks[joinIndex-1].Y, overlapResult.Overlap))
} else if currPlayerDownsync.InAir && isBarrier && !landedOnGravityPushback {
//Logger.Warn(fmt.Sprintf("playerId=%d, joinIndex=%d inAir & pushed back by barrier & not landed at {renderFrame.id: %d}\nplayerColliderPos=%v, effPushback={%.3f, %.3f}, overlapMag=%.4f, len(hardPushbackNorms)=%d", playerId, joinIndex, currRenderFrame.Id, RectCenterStr(playerCollider, halfColliderWidth, halfColliderHeight, topPadding, bottomPadding, leftPadding, rightPadding, pR.collisionSpaceOffsetX, pR.collisionSpaceOffsetY), effPushbacks[joinIndex-1].X, effPushbacks[joinIndex-1].Y, overlapResult.Overlap, len(hardPushbackNorms)))
} else if currPlayerDownsync.InAir && isAnotherPlayer {
//Logger.Warn(fmt.Sprintf("playerId=%d, joinIndex=%d inAir & pushed back by another player\n{renderFrame.id: %d}\nplayerColliderPos=%v, anotherPlayerColliderPos=%v, effPushback={%.3f, %.3f}, landedOnGravityPushback=%v, fallStopping=%v, overlapMag=%.4f, len(hardPushbackNorms)=%d", playerId, joinIndex, currRenderFrame.Id, RectCenterStr(playerCollider, halfColliderWidth, halfColliderHeight, topPadding, bottomPadding, leftPadding, rightPadding, pR.collisionSpaceOffsetX, pR.collisionSpaceOffsetY), RectCenterStr(obj, halfColliderWidth, halfColliderHeight, topPadding, bottomPadding, leftPadding, rightPadding, pR.collisionSpaceOffsetX, pR.collisionSpaceOffsetY), effPushbacks[joinIndex-1].X, effPushbacks[joinIndex-1].Y, landedOnGravityPushback, fallStopping, overlapResult.Overlap, len(hardPushbackNorms)))
}
}
}
if 1 == joinIndex && currPlayerDownsync.InAir && isBarrier && !landedOnGravityPushback {
Logger.Warn(fmt.Sprintf("playerId=%d, joinIndex=%d inAir & pushed back by barrier & not landed at {renderFrame.id: %d, virtualX: %d, virtualY: %d, velX: %d, velY: %d} with effPushback={%.3f, %.3f}, playerColliderPos={%.3f, %.3f}, barrierPos={%.3f, %.3f}, overlapMag=%.4f, len(hardPushbackNorms)=%d", playerId, joinIndex, currRenderFrame.Id, currPlayerDownsync.VirtualGridX, currPlayerDownsync.VirtualGridY, currPlayerDownsync.VelX, currPlayerDownsync.VelY, effPushbacks[joinIndex-1].X, effPushbacks[joinIndex-1].Y, playerCollider.X-pR.collisionSpaceOffsetX, playerCollider.Y-pR.collisionSpaceOffsetY, bShape.X-pR.collisionSpaceOffsetX, bShape.Y-pR.collisionSpaceOffsetY, overlapResult.Overlap, len(hardPushbackNorms)))
}
if 1 == joinIndex && currPlayerDownsync.InAir && isAnotherPlayer {
Logger.Warn(fmt.Sprintf("playerId=%d, joinIndex=%d inAir & pushed back by another player at {renderFrame.id: %d, virtualX: %d, virtualY: %d, velX: %d, velY: %d} with effPushback={%.3f, %.3f}, landedOnGravityPushback=%v, fallStopping=%v, playerColliderPos={%.3f, %.3f}, anotherPlayerColliderPos={%.3f, %.3f}, overlapMag=%.4f, len(hardPushbackNorms)=%d", playerId, joinIndex, currRenderFrame.Id, currPlayerDownsync.VirtualGridX, currPlayerDownsync.VirtualGridY, currPlayerDownsync.VelX, currPlayerDownsync.VelY, effPushbacks[joinIndex-1].X, effPushbacks[joinIndex-1].Y, landedOnGravityPushback, fallStopping, playerCollider.X-pR.collisionSpaceOffsetX, playerCollider.Y-pR.collisionSpaceOffsetY, bShape.X-pR.collisionSpaceOffsetX, bShape.Y-pR.collisionSpaceOffsetY, overlapResult.Overlap, len(hardPushbackNorms)))
}
}
if fallStopping {
@@ -1512,15 +1504,14 @@ func (pR *Room) applyInputFrameDownsyncDynamicsOnSingleRenderFrame(delayedInputF
thatPlayerInNextFrame.FramesToRecover = 0
}
if currPlayerDownsync.InAir {
switch thatPlayerInNextFrame.CharacterState {
case ATK_CHARACTER_STATE_IDLE1:
case ATK_CHARACTER_STATE_WALKING:
oldNextCharacterState := thatPlayerInNextFrame.CharacterState
switch oldNextCharacterState {
case ATK_CHARACTER_STATE_IDLE1, ATK_CHARACTER_STATE_WALKING:
thatPlayerInNextFrame.CharacterState = ATK_CHARACTER_STATE_INAIR_IDLE1
case ATK_CHARACTER_STATE_ATK1:
thatPlayerInNextFrame.CharacterState = ATK_CHARACTER_STATE_INAIR_ATK1
case ATK_CHARACTER_STATE_ATKED1:
thatPlayerInNextFrame.CharacterState = ATK_CHARACTER_STATE_INAIR_ATKED1
default:
}
}
}
@@ -1599,21 +1590,18 @@ func (pR *Room) applyInputFrameDownsyncDynamicsOnSingleRenderFrame(delayedInputF
playerId := player.Id
collisionPlayerIndex := COLLISION_PLAYER_INDEX_PREFIX + joinIndex
playerCollider := collisionSysMap[collisionPlayerIndex]
playerShape := playerCollider.Shape.(*resolv.ConvexPolygon)
// Update "virtual grid position"
currPlayerDownsync, thatPlayerInNextFrame := currRenderFrame.Players[playerId], nextRenderFramePlayers[playerId]
colliderWidth, colliderHeight := player.ColliderRadius*2, player.ColliderRadius*4
thatPlayerInNextFrame.VirtualGridX, thatPlayerInNextFrame.VirtualGridY = PolygonColliderBLToVirtualGridPos(playerCollider.X-effPushbacks[joinIndex-1].X, playerCollider.Y-effPushbacks[joinIndex-1].Y, colliderWidth*0.5, colliderHeight*0.5, pR.SnapIntoPlatformOverlap, pR.collisionSpaceOffsetX, pR.collisionSpaceOffsetY, pR.WorldToVirtualGridRatio)
halfColliderWidth, halfColliderHeight := player.ColliderRadius, player.ColliderRadius+player.ColliderRadius // avoid multiplying
thatPlayerInNextFrame.VirtualGridX, thatPlayerInNextFrame.VirtualGridY = PolygonColliderBLToVirtualGridPos(playerCollider.X-effPushbacks[joinIndex-1].X, playerCollider.Y-effPushbacks[joinIndex-1].Y, halfColliderWidth, halfColliderHeight, topPadding, bottomPadding, leftPadding, rightPadding, pR.collisionSpaceOffsetX, pR.collisionSpaceOffsetY, pR.WorldToVirtualGridRatio)
if 1 == thatPlayerInNextFrame.JoinIndex {
if thatPlayerInNextFrame.InAir && (0 != thatPlayerInNextFrame.VelY) {
// Logger.Info(fmt.Sprintf("playerId=%d, joinIndex=%d inAir trajectory: {nextRenderFrame.id: %d, nextVirtualX: %d, nextVirtualY: %d, nextVelX: %d, nextVelY: %d}, with playerColliderPos={%.3f, %.3f}, effPushback={%.3f, %.3f}", playerId, joinIndex, currRenderFrame.Id+1, thatPlayerInNextFrame.VirtualGridX, thatPlayerInNextFrame.VirtualGridY, thatPlayerInNextFrame.VelX, thatPlayerInNextFrame.VelY, playerShape.X-pR.collisionSpaceOffsetX, playerShape.Y-pR.collisionSpaceOffsetY, effPushbacks[joinIndex-1].X, effPushbacks[joinIndex-1].Y))
}
if currPlayerDownsync.InAir && !thatPlayerInNextFrame.InAir {
Logger.Warn(fmt.Sprintf("playerId=%d, joinIndex=%d fallStopping#2 at {nextRenderFrame.id: %d, nextVirtualX: %d, nextVirtualY: %d, nextVelX: %d, nextVelY: %d}, with playerColliderPos={%.3f, %.3f}, effPushback={%.3f, %.3f}", playerId, joinIndex, currRenderFrame.Id+1, thatPlayerInNextFrame.VirtualGridX, thatPlayerInNextFrame.VirtualGridY, thatPlayerInNextFrame.VelX, thatPlayerInNextFrame.VelY, playerShape.X-pR.collisionSpaceOffsetX, playerShape.Y-pR.collisionSpaceOffsetY, effPushbacks[joinIndex-1].X, effPushbacks[joinIndex-1].Y))
}
if !currPlayerDownsync.InAir && thatPlayerInNextFrame.InAir {
Logger.Warn(fmt.Sprintf("playerId=%d, joinIndex=%d took off at {nextRenderFrame.id: %d, nextVirtualX: %d, nextVirtualY: %d, nextVelX: %d, nextVelY: %d}, with playerColliderPos={%.3f, %.3f}, effPushback={%.3f, %.3f}", playerId, joinIndex, currRenderFrame.Id+1, thatPlayerInNextFrame.VirtualGridX, thatPlayerInNextFrame.VirtualGridY, thatPlayerInNextFrame.VelX, thatPlayerInNextFrame.VelY, playerShape.X-pR.collisionSpaceOffsetX, playerShape.Y-pR.collisionSpaceOffsetY, effPushbacks[joinIndex-1].X, effPushbacks[joinIndex-1].Y))
//Logger.Warn(fmt.Sprintf("playerId=%d, joinIndex=%d fallStopping#2:\n{nextRenderFrame.id: %d, nextVirtualX: %d, nextVirtualY: %d, nextVelX: %d, nextVelY: %d}\n\tcalculated from <- playerColliderPos=%v, effPushback={%.3f, %.3f}", playerId, joinIndex, currRenderFrame.Id+1, thatPlayerInNextFrame.VirtualGridX, thatPlayerInNextFrame.VirtualGridY, thatPlayerInNextFrame.VelX, thatPlayerInNextFrame.VelY, RectCenterStr(playerCollider, halfColliderWidth, halfColliderHeight, topPadding, bottomPadding, leftPadding, rightPadding, pR.collisionSpaceOffsetX, pR.collisionSpaceOffsetY), effPushbacks[joinIndex-1].X, effPushbacks[joinIndex-1].Y))
} else if !currPlayerDownsync.InAir && thatPlayerInNextFrame.InAir {
//Logger.Warn(fmt.Sprintf("playerId=%d, joinIndex=%d took off:\n{nextRenderFrame.id: %d, nextVirtualX: %d, nextVirtualY: %d, nextVelX: %d, nextVelY: %d}\n\tcalculated from <- playerColliderPos=%v, effPushback={%.3f, %.3f}", playerId, joinIndex, currRenderFrame.Id+1, thatPlayerInNextFrame.VirtualGridX, thatPlayerInNextFrame.VirtualGridY, thatPlayerInNextFrame.VelX, thatPlayerInNextFrame.VelY, RectCenterStr(playerCollider, halfColliderWidth, halfColliderHeight, topPadding, bottomPadding, leftPadding, rightPadding, pR.collisionSpaceOffsetX, pR.collisionSpaceOffsetY), effPushbacks[joinIndex-1].X, effPushbacks[joinIndex-1].Y))
} else if thatPlayerInNextFrame.InAir && (0 != thatPlayerInNextFrame.VelY) {
//Logger.Info(fmt.Sprintf("playerId=%d, joinIndex=%d inAir trajectory:\n{nextRenderFrame.id: %d, nextVirtualX: %d, nextVirtualY: %d, nextVelX: %d, nextVelY: %d}\n\tcalculated from <- playerColliderPos=%v, effPushback={%.3f, %.3f}", playerId, joinIndex, currRenderFrame.Id+1, thatPlayerInNextFrame.VirtualGridX, thatPlayerInNextFrame.VirtualGridY, thatPlayerInNextFrame.VelX, thatPlayerInNextFrame.VelY, RectCenterStr(playerCollider, halfColliderWidth, halfColliderHeight, topPadding, bottomPadding, leftPadding, rightPadding, pR.collisionSpaceOffsetX, pR.collisionSpaceOffsetY), effPushbacks[joinIndex-1].X, effPushbacks[joinIndex-1].Y))
}
}
}
@@ -1645,12 +1633,14 @@ func (pR *Room) inputFrameIdDebuggable(inputFrameId int32) bool {
func (pR *Room) refreshColliders(spaceW, spaceH int32) {
// Kindly note that by now, we've already got all the shapes in the tmx file into "pR.(Players | Barriers)" from "ParseTmxLayersAndGroups"
minStep := (int(float64(pR.PlayerDefaultSpeed)*pR.VirtualGridToWorldRatio) << 1) // the approx minimum distance a player can move per frame in world coordinate
topPadding, bottomPadding, leftPadding, rightPadding := pR.SnapIntoPlatformOverlap, pR.SnapIntoPlatformOverlap, pR.SnapIntoPlatformOverlap, pR.SnapIntoPlatformOverlap
minStep := (int(float64(pR.PlayerDefaultSpeed)*pR.VirtualGridToWorldRatio) << 3) // the approx minimum distance a player can move per frame in world coordinate
pR.Space = resolv.NewSpace(int(spaceW), int(spaceH), minStep, minStep) // allocate a new collision space everytime after a battle is settled
for _, player := range pR.Players {
wx, wy := VirtualGridToWorldPos(player.VirtualGridX, player.VirtualGridY, pR.VirtualGridToWorldRatio)
colliderWidth, colliderHeight := player.ColliderRadius*2, player.ColliderRadius*4
playerCollider := GenerateRectCollider(wx, wy, colliderWidth, colliderHeight, pR.SnapIntoPlatformOverlap, pR.collisionSpaceOffsetX, pR.collisionSpaceOffsetY, "Player") // the coords of all barrier boundaries are multiples of tileWidth(i.e. 16), by adding snapping y-padding when "landedOnGravityPushback" all "playerCollider.Y" would be a multiple of 1.0
playerCollider := GenerateRectCollider(wx, wy, colliderWidth, colliderHeight, topPadding, bottomPadding, leftPadding, rightPadding, pR.collisionSpaceOffsetX, pR.collisionSpaceOffsetY, "Player") // the coords of all barrier boundaries are multiples of tileWidth(i.e. 16), by adding snapping y-padding when "landedOnGravityPushback" all "playerCollider.Y" would be a multiple of 1.0
playerCollider.Data = player
pR.Space.Add(playerCollider)
// Keep track of the collider in "pR.CollisionSysMap"
@@ -1702,7 +1692,7 @@ func (pR *Room) doBattleMainLoopPerTickBackendDynamicsWithProperLocking(prevRend
}
if nil != inputsBufferSnapshot {
// Logger.Warn(fmt.Sprintf("roomId=%v, room.RenderFrameId=%v, room.CurDynamicsRenderFrameId=%v, room.LastAllConfirmedInputFrameId=%v, unconfirmedMask=%v", pR.Id, pR.RenderFrameId, pR.CurDynamicsRenderFrameId, pR.LastAllConfirmedInputFrameId, inputsBufferSnapshot.UnconfirmedMask))
Logger.Debug(fmt.Sprintf("[forceConfirmation] roomId=%v, room.RenderFrameId=%v, room.CurDynamicsRenderFrameId=%v, room.LastAllConfirmedInputFrameId=%v, unconfirmedMask=%v", pR.Id, pR.RenderFrameId, pR.CurDynamicsRenderFrameId, pR.LastAllConfirmedInputFrameId, inputsBufferSnapshot.UnconfirmedMask))
pR.downsyncToAllPlayers(inputsBufferSnapshot)
}
}
@@ -1726,30 +1716,50 @@ func (pR *Room) downsyncToAllPlayers(inputsBufferSnapshot *InputsBufferSnapshot)
The difference from our current approach is that the "pR.PlayerDownsyncChanDict[playerId]" in use is a Golang channel, i.e. when executing #4 it automatically executes #3 (before) & #7 (after) as well, thus we couldn't do #5 & #6 in between.
*/
for playerId, playerDownsyncChan := range pR.PlayerDownsyncChanDict {
if true == pR.BackendDynamicsEnabled {
for _, player := range pR.PlayersArr {
/*
[WARNING] Since v0.9.1, the inconsistence between frontend & backend collision handling results became too difficult to track, therefore before we can let frontend use a Golang compiled library for "applyInputFrameDownsyncDynamicsOnSingleRenderFrame", it's a compromise here to force resync for all players in a same room if any player recovered from a reconnection (when it's most likely for anyone to notice an inconsistence).
That said, we ensured that if "false == BackendDynamicsEnabled" and noone ever disconnects & reconnects, the frontend collision handling results are always consistent.
*/
playerBattleState := atomic.LoadInt32(&(player.BattleState))
thatPlayerJoinMask := uint64(1 << uint32(player.JoinIndex-1))
if PlayerBattleStateIns.READDED_BATTLE_COLLIDER_ACKED == playerBattleState {
inputsBufferSnapshot.ShouldForceResync = true
break
} else if PlayerBattleStateIns.ACTIVE == playerBattleState && 0 < (inputsBufferSnapshot.UnconfirmedMask&thatPlayerJoinMask) {
/*
[WARNING] Whenever there's an `ACTIVE SLOW TICKER`, all players should also be resynced to avoid inconsistent display. See `<proj-root>/ConcerningEdgeCases.md` for more information.
*/
inputsBufferSnapshot.ShouldForceResync = true
break
}
}
}
for _, player := range pR.PlayersArr {
/*
[WARNING] While the order of generation of "inputsBufferSnapshot" is preserved for sending, the underlying network I/O blocking action is dispatched to "downsyncLoop of each player" such that "markConfirmationIfApplicable & forceConfirmationIfApplicable" can re-hold "pR.InputsBufferLock" asap and proceed with more inputFrameUpsyncs.
The use of "downsyncLoop of each player" also waives the need of guarding each "pR.PlayerDownsyncSessionDict[playerId]" from multithread-access (e.g. by a "pR.PlayerDownsyncSessionMutexDict[playerId]"), i.e. Gorilla v1.2.0 "conn.WriteMessage" isn't thread-safe https://github.com/gorilla/websocket/blob/v1.2.0/conn.go#L585.
*/
if player, existent := pR.Players[playerId]; existent {
playerBattleState := atomic.LoadInt32(&(player.BattleState))
switch playerBattleState {
case PlayerBattleStateIns.DISCONNECTED:
case PlayerBattleStateIns.LOST:
case PlayerBattleStateIns.EXPELLED_DURING_GAME:
case PlayerBattleStateIns.EXPELLED_IN_DISMISSAL:
case PlayerBattleStateIns.ADDED_PENDING_BATTLE_COLLIDER_ACK:
case PlayerBattleStateIns.READDED_PENDING_BATTLE_COLLIDER_ACK:
continue
}
playerBattleState := atomic.LoadInt32(&(player.BattleState))
switch playerBattleState {
case PlayerBattleStateIns.DISCONNECTED, PlayerBattleStateIns.LOST, PlayerBattleStateIns.EXPELLED_DURING_GAME, PlayerBattleStateIns.EXPELLED_IN_DISMISSAL, PlayerBattleStateIns.ADDED_PENDING_BATTLE_COLLIDER_ACK, PlayerBattleStateIns.READDED_PENDING_BATTLE_COLLIDER_ACK:
continue
}
if playerDownsyncChan, existent := pR.PlayerDownsyncChanDict[player.Id]; existent {
playerDownsyncChan <- (*inputsBufferSnapshot)
// Logger.Info(fmt.Sprintf("Sent inputsBufferSnapshot(refRenderFrameId:%d, unconfirmedMask:%v) to for (roomId: %d, playerId:%d, playerDownsyncChan:%p)#1", inputsBufferSnapshot.RefRenderFrameId, inputsBufferSnapshot.UnconfirmedMask, pR.Id, playerId, playerDownsyncChan))
//Logger.Info(fmt.Sprintf("Sent inputsBufferSnapshot(refRenderFrameId:%d, unconfirmedMask:%v) to for (roomId: %d, playerId:%d, playerDownsyncChan:%p)#1", inputsBufferSnapshot.RefRenderFrameId, inputsBufferSnapshot.UnconfirmedMask, pR.Id, player.Id, playerDownsyncChan))
} else {
Logger.Warn(fmt.Sprintf("playerDownsyncChan for (roomId: %d, playerId:%d) is gone", pR.Id, player.Id))
}
}
}
func (pR *Room) downsyncToSinglePlayer(playerId int32, player *Player, refRenderFrameId int32, unconfirmedMask uint64, toSendInputFrameDownsyncsSnapshot []*InputFrameDownsync) {
func (pR *Room) downsyncToSinglePlayer(playerId int32, player *Player, refRenderFrameId int32, unconfirmedMask uint64, toSendInputFrameDownsyncsSnapshot []*InputFrameDownsync, shouldForceResync bool) {
/*
[WARNING] This function MUST BE called while "pR.InputsBufferLock" is unlocked -- otherwise the network I/O blocking of "sendSafely" might cause significant lag for "markConfirmationIfApplicable & forceConfirmationIfApplicable"!
@@ -1759,33 +1769,22 @@ func (pR *Room) downsyncToSinglePlayer(playerId int32, player *Player, refRender
playerJoinIndex := player.JoinIndex - 1
playerBattleState := atomic.LoadInt32(&(player.BattleState))
switch playerBattleState {
case PlayerBattleStateIns.DISCONNECTED:
case PlayerBattleStateIns.LOST:
case PlayerBattleStateIns.EXPELLED_DURING_GAME:
case PlayerBattleStateIns.EXPELLED_IN_DISMISSAL:
case PlayerBattleStateIns.ADDED_PENDING_BATTLE_COLLIDER_ACK:
case PlayerBattleStateIns.READDED_PENDING_BATTLE_COLLIDER_ACK:
case PlayerBattleStateIns.DISCONNECTED, PlayerBattleStateIns.LOST, PlayerBattleStateIns.EXPELLED_DURING_GAME, PlayerBattleStateIns.EXPELLED_IN_DISMISSAL, PlayerBattleStateIns.ADDED_PENDING_BATTLE_COLLIDER_ACK, PlayerBattleStateIns.READDED_PENDING_BATTLE_COLLIDER_ACK:
return
}
shouldResync1 := (PlayerBattleStateIns.READDED_BATTLE_COLLIDER_ACKED == playerBattleState) // i.e. implies that "MAGIC_LAST_SENT_INPUT_FRAME_ID_READDED == player.LastSentInputFrameId"
shouldResync2 := (0 < (unconfirmedMask & uint64(1<<uint32(playerJoinIndex)))) // This condition is critical, if we don't send resync upon this condition, the "reconnected or slowly-clocking player" might never get its input synced
// shouldResync2 := (0 < unconfirmedMask) // An easier version of the above, might keep sending "refRenderFrame"s to still connected players when any player is disconnected
shouldResyncOverall := (shouldResync1 || shouldResync2)
if shouldResyncOverall {
// A rejoined player, should guarantee that when it resyncs to "refRenderFrameId" a matching inputFrame to apply exists
Logger.Debug(fmt.Sprintf("Resyncing player: roomId=%v, playerId=%v, playerJoinIndex=%v, renderFrameId=%v, curDynamicsRenderFrameId=%v, playerLastSentInputFrameId=%v, refRenderFrameId=%v", pR.Id, playerId, player.JoinIndex, pR.RenderFrameId, pR.CurDynamicsRenderFrameId, player.LastSentInputFrameId, refRenderFrameId))
}
shouldResync3 := shouldForceResync
shouldResyncOverall := (shouldResync1 || shouldResync2 || shouldResync3)
/*
Resync helps
1. when player with a slower frontend clock lags significantly behind and thus wouldn't get its inputUpsync recognized due to faster "forceConfirmation"
2. reconnection
*/
//toSendInputFrameIdSt, toSendInputFrameIdEd := toSendInputFrameDownsyncsSnapshot[0].InputFrameId, toSendInputFrameDownsyncsSnapshot[len(toSendInputFrameDownsyncsSnapshot)-1].InputFrameId+1
_, toSendInputFrameIdEd := toSendInputFrameDownsyncsSnapshot[0].InputFrameId, toSendInputFrameDownsyncsSnapshot[len(toSendInputFrameDownsyncsSnapshot)-1].InputFrameId+1
toSendInputFrameIdSt, toSendInputFrameIdEd := toSendInputFrameDownsyncsSnapshot[0].InputFrameId, toSendInputFrameDownsyncsSnapshot[len(toSendInputFrameDownsyncsSnapshot)-1].InputFrameId+1
if pR.BackendDynamicsEnabled && shouldResyncOverall {
tmp := pR.RenderFrameBuffer.GetByFrameId(refRenderFrameId)
if nil == tmp {
@@ -1796,9 +1795,15 @@ func (pR *Room) downsyncToSinglePlayer(playerId int32, player *Player, refRender
for _, player := range pR.PlayersArr {
refRenderFrame.Players[player.Id].ColliderRadius = player.ColliderRadius // hardcoded for now
}
if shouldResync3 {
refRenderFrame.ShouldForceResync = true
}
refRenderFrame.BackendUnconfirmedMask = unconfirmedMask
pR.sendSafely(refRenderFrame, toSendInputFrameDownsyncsSnapshot, DOWNSYNC_MSG_ACT_FORCED_RESYNC, playerId, false)
// Logger.Warn(fmt.Sprintf("Sent refRenderFrameId=%v & inputFrameIds [%d, %d), for roomId=%v, playerId=%d, playerJoinIndex=%d, renderFrameId=%d, curDynamicsRenderFrameId=%d, playerLastSentInputFrameId=%d: InputsBuffer=%v", refRenderFrameId, toSendInputFrameIdSt, toSendInputFrameIdEd, pR.Id, playerId, player.JoinIndex, pR.RenderFrameId, pR.CurDynamicsRenderFrameId, player.LastSentInputFrameId, pR.InputsBufferString(false)))
//Logger.Warn(fmt.Sprintf("Sent refRenderFrameId=%v & inputFrameIds [%d, %d), for roomId=%v, playerId=%d, playerJoinIndex=%d, renderFrameId=%d, curDynamicsRenderFrameId=%d, playerLastSentInputFrameId=%d: InputsBuffer=%v", refRenderFrameId, toSendInputFrameIdSt, toSendInputFrameIdEd, pR.Id, playerId, player.JoinIndex, pR.RenderFrameId, pR.CurDynamicsRenderFrameId, player.LastSentInputFrameId, pR.InputsBufferString(false)))
if shouldResync1 {
Logger.Warn(fmt.Sprintf("Sent refRenderFrameId=%v & inputFrameIds [%d, %d), for roomId=%v, playerId=%d, playerJoinIndex=%d, renderFrameId=%d, curDynamicsRenderFrameId=%d, playerLastSentInputFrameId=%d: shouldResync1=%v, shouldResync2=%v, shouldResync3=%v, playerBattleState=%d", refRenderFrameId, toSendInputFrameIdSt, toSendInputFrameIdEd, pR.Id, playerId, player.JoinIndex, pR.RenderFrameId, pR.CurDynamicsRenderFrameId, player.LastSentInputFrameId, shouldResync1, shouldResync2, shouldResync3, playerBattleState))
}
} else {
pR.sendSafely(nil, toSendInputFrameDownsyncsSnapshot, DOWNSYNC_MSG_ACT_INPUT_BATCH, playerId, false)
}

View File

@@ -670,6 +670,7 @@ type InputsBufferSnapshot struct {
RefRenderFrameId int32 `protobuf:"varint,1,opt,name=refRenderFrameId,proto3" json:"refRenderFrameId,omitempty"`
UnconfirmedMask uint64 `protobuf:"varint,2,opt,name=unconfirmedMask,proto3" json:"unconfirmedMask,omitempty"`
ToSendInputFrameDownsyncs []*InputFrameDownsync `protobuf:"bytes,3,rep,name=toSendInputFrameDownsyncs,proto3" json:"toSendInputFrameDownsyncs,omitempty"`
ShouldForceResync bool `protobuf:"varint,4,opt,name=shouldForceResync,proto3" json:"shouldForceResync,omitempty"`
}
func (x *InputsBufferSnapshot) Reset() {
@@ -725,6 +726,13 @@ func (x *InputsBufferSnapshot) GetToSendInputFrameDownsyncs() []*InputFrameDowns
return nil
}
func (x *InputsBufferSnapshot) GetShouldForceResync() bool {
if x != nil {
return x.ShouldForceResync
}
return false
}
type MeleeBullet struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
@@ -1199,6 +1207,7 @@ type RoomDownsyncFrame struct {
CountdownNanos int64 `protobuf:"varint,3,opt,name=countdownNanos,proto3" json:"countdownNanos,omitempty"`
MeleeBullets []*MeleeBullet `protobuf:"bytes,4,rep,name=meleeBullets,proto3" json:"meleeBullets,omitempty"` // I don't know how to mimic inheritance/composition in protobuf by far, thus using an array for each type of bullet as a compromise
BackendUnconfirmedMask uint64 `protobuf:"varint,5,opt,name=backendUnconfirmedMask,proto3" json:"backendUnconfirmedMask,omitempty"` // Indexed by "joinIndex", same compression concern as stated in InputFrameDownsync
ShouldForceResync bool `protobuf:"varint,6,opt,name=shouldForceResync,proto3" json:"shouldForceResync,omitempty"`
}
func (x *RoomDownsyncFrame) Reset() {
@@ -1268,6 +1277,13 @@ func (x *RoomDownsyncFrame) GetBackendUnconfirmedMask() uint64 {
return 0
}
func (x *RoomDownsyncFrame) GetShouldForceResync() bool {
if x != nil {
return x.ShouldForceResync
}
return false
}
var File_room_downsync_frame_proto protoreflect.FileDescriptor
var file_room_downsync_frame_proto_rawDesc = []byte{
@@ -1373,7 +1389,7 @@ var file_room_downsync_frame_proto_rawDesc = []byte{
0x74, 0x63, 0x68, 0x12, 0x36, 0x0a, 0x08, 0x62, 0x63, 0x69, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x18,
0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x42,
0x61, 0x74, 0x74, 0x6c, 0x65, 0x43, 0x6f, 0x6c, 0x6c, 0x69, 0x64, 0x65, 0x72, 0x49, 0x6e, 0x66,
0x6f, 0x52, 0x08, 0x62, 0x63, 0x69, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x22, 0xc6, 0x01, 0x0a, 0x14,
0x6f, 0x52, 0x08, 0x62, 0x63, 0x69, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x22, 0xf4, 0x01, 0x0a, 0x14,
0x49, 0x6e, 0x70, 0x75, 0x74, 0x73, 0x42, 0x75, 0x66, 0x66, 0x65, 0x72, 0x53, 0x6e, 0x61, 0x70,
0x73, 0x68, 0x6f, 0x74, 0x12, 0x2a, 0x0a, 0x10, 0x72, 0x65, 0x66, 0x52, 0x65, 0x6e, 0x64, 0x65,
0x72, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x10,
@@ -1386,196 +1402,201 @@ var file_room_downsync_frame_proto_rawDesc = []byte{
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x46, 0x72, 0x61, 0x6d,
0x65, 0x44, 0x6f, 0x77, 0x6e, 0x73, 0x79, 0x6e, 0x63, 0x52, 0x19, 0x74, 0x6f, 0x53, 0x65, 0x6e,
0x64, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x44, 0x6f, 0x77, 0x6e, 0x73,
0x79, 0x6e, 0x63, 0x73, 0x22, 0xe5, 0x05, 0x0a, 0x0b, 0x4d, 0x65, 0x6c, 0x65, 0x65, 0x42, 0x75,
0x6c, 0x6c, 0x65, 0x74, 0x12, 0x24, 0x0a, 0x0d, 0x62, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x4c, 0x6f,
0x63, 0x61, 0x6c, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0d, 0x62, 0x61, 0x74,
0x74, 0x6c, 0x65, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x49, 0x64, 0x12, 0x24, 0x0a, 0x0d, 0x73, 0x74,
0x61, 0x72, 0x74, 0x75, 0x70, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28,
0x05, 0x52, 0x0d, 0x73, 0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73,
0x12, 0x22, 0x0a, 0x0c, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73,
0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0c, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x46, 0x72,
0x61, 0x6d, 0x65, 0x73, 0x12, 0x26, 0x0a, 0x0e, 0x72, 0x65, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79,
0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0e, 0x72, 0x65,
0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x12, 0x34, 0x0a, 0x15,
0x72, 0x65, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x4f, 0x6e,
0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x52, 0x15, 0x72, 0x65, 0x63,
0x6f, 0x76, 0x65, 0x72, 0x79, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x4f, 0x6e, 0x42, 0x6c, 0x6f,
0x63, 0x6b, 0x12, 0x30, 0x0a, 0x13, 0x72, 0x65, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x46, 0x72,
0x61, 0x6d, 0x65, 0x73, 0x4f, 0x6e, 0x48, 0x69, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x05, 0x52,
0x13, 0x72, 0x65, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x4f,
0x6e, 0x48, 0x69, 0x74, 0x12, 0x35, 0x0a, 0x0b, 0x6d, 0x6f, 0x76, 0x65, 0x66, 0x6f, 0x72, 0x77,
0x61, 0x72, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x73, 0x68, 0x61, 0x72,
0x65, 0x64, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x56, 0x65, 0x63, 0x32, 0x44, 0x52, 0x0b,
0x6d, 0x6f, 0x76, 0x65, 0x66, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x12, 0x22, 0x0a, 0x0c, 0x68,
0x69, 0x74, 0x62, 0x6f, 0x78, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x18, 0x08, 0x20, 0x01, 0x28,
0x01, 0x52, 0x0c, 0x68, 0x69, 0x74, 0x62, 0x6f, 0x78, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x12,
0x33, 0x0a, 0x0a, 0x68, 0x69, 0x74, 0x62, 0x6f, 0x78, 0x53, 0x69, 0x7a, 0x65, 0x18, 0x09, 0x20,
0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x73, 0x68, 0x61, 0x72, 0x65, 0x64, 0x70, 0x72, 0x6f, 0x74,
0x6f, 0x73, 0x2e, 0x56, 0x65, 0x63, 0x32, 0x44, 0x52, 0x0a, 0x68, 0x69, 0x74, 0x62, 0x6f, 0x78,
0x53, 0x69, 0x7a, 0x65, 0x12, 0x38, 0x0a, 0x17, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x74,
0x65, 0x64, 0x52, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x49, 0x64, 0x18,
0x0a, 0x20, 0x01, 0x28, 0x05, 0x52, 0x17, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x65,
0x64, 0x52, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x49, 0x64, 0x12, 0x24,
0x0a, 0x0d, 0x68, 0x69, 0x74, 0x53, 0x74, 0x75, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x18,
0x0b, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0d, 0x68, 0x69, 0x74, 0x53, 0x74, 0x75, 0x6e, 0x46, 0x72,
0x61, 0x6d, 0x65, 0x73, 0x12, 0x28, 0x0a, 0x0f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x53, 0x74, 0x75,
0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0f, 0x62,
0x6c, 0x6f, 0x63, 0x6b, 0x53, 0x74, 0x75, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x12, 0x1a,
0x0a, 0x08, 0x70, 0x75, 0x73, 0x68, 0x62, 0x61, 0x63, 0x6b, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x01,
0x52, 0x08, 0x70, 0x75, 0x73, 0x68, 0x62, 0x61, 0x63, 0x6b, 0x12, 0x2e, 0x0a, 0x12, 0x72, 0x65,
0x6c, 0x65, 0x61, 0x73, 0x65, 0x54, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x54, 0x79, 0x70, 0x65,
0x18, 0x0e, 0x20, 0x01, 0x28, 0x05, 0x52, 0x12, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x54,
0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x54, 0x79, 0x70, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x64, 0x61,
0x6d, 0x61, 0x67, 0x65, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x64, 0x61, 0x6d, 0x61,
0x67, 0x65, 0x12, 0x2c, 0x0a, 0x11, 0x6f, 0x66, 0x66, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x4a, 0x6f,
0x69, 0x6e, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x10, 0x20, 0x01, 0x28, 0x05, 0x52, 0x11, 0x6f,
0x66, 0x66, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x4a, 0x6f, 0x69, 0x6e, 0x49, 0x6e, 0x64, 0x65, 0x78,
0x12, 0x2a, 0x0a, 0x10, 0x6f, 0x66, 0x66, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x50, 0x6c, 0x61, 0x79,
0x65, 0x72, 0x49, 0x64, 0x18, 0x11, 0x20, 0x01, 0x28, 0x05, 0x52, 0x10, 0x6f, 0x66, 0x66, 0x65,
0x6e, 0x64, 0x65, 0x72, 0x50, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x49, 0x64, 0x22, 0xf2, 0x0e, 0x0a,
0x12, 0x42, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x43, 0x6f, 0x6c, 0x6c, 0x69, 0x64, 0x65, 0x72, 0x49,
0x6e, 0x66, 0x6f, 0x12, 0x1c, 0x0a, 0x09, 0x73, 0x74, 0x61, 0x67, 0x65, 0x4e, 0x61, 0x6d, 0x65,
0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x74, 0x61, 0x67, 0x65, 0x4e, 0x61, 0x6d,
0x65, 0x12, 0x5f, 0x0a, 0x11, 0x73, 0x74, 0x72, 0x54, 0x6f, 0x56, 0x65, 0x63, 0x32, 0x44, 0x4c,
0x69, 0x73, 0x74, 0x4d, 0x61, 0x70, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x70,
0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x42, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x43, 0x6f, 0x6c, 0x6c,
0x69, 0x64, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x2e, 0x53, 0x74, 0x72, 0x54, 0x6f, 0x56, 0x65,
0x63, 0x32, 0x44, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x61, 0x70, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52,
0x11, 0x73, 0x74, 0x72, 0x54, 0x6f, 0x56, 0x65, 0x63, 0x32, 0x44, 0x4c, 0x69, 0x73, 0x74, 0x4d,
0x61, 0x70, 0x12, 0x6b, 0x0a, 0x15, 0x73, 0x74, 0x72, 0x54, 0x6f, 0x50, 0x6f, 0x6c, 0x79, 0x67,
0x6f, 0x6e, 0x32, 0x44, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x61, 0x70, 0x18, 0x03, 0x20, 0x03, 0x28,
0x0b, 0x32, 0x35, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x42, 0x61, 0x74, 0x74, 0x6c,
0x65, 0x43, 0x6f, 0x6c, 0x6c, 0x69, 0x64, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x2e, 0x53, 0x74,
0x72, 0x54, 0x6f, 0x50, 0x6f, 0x6c, 0x79, 0x67, 0x6f, 0x6e, 0x32, 0x44, 0x4c, 0x69, 0x73, 0x74,
0x4d, 0x61, 0x70, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x15, 0x73, 0x74, 0x72, 0x54, 0x6f, 0x50,
0x6f, 0x6c, 0x79, 0x67, 0x6f, 0x6e, 0x32, 0x44, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x61, 0x70, 0x12,
0x26, 0x0a, 0x0e, 0x73, 0x74, 0x61, 0x67, 0x65, 0x44, 0x69, 0x73, 0x63, 0x72, 0x65, 0x74, 0x65,
0x57, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0e, 0x73, 0x74, 0x61, 0x67, 0x65, 0x44, 0x69,
0x73, 0x63, 0x72, 0x65, 0x74, 0x65, 0x57, 0x12, 0x26, 0x0a, 0x0e, 0x73, 0x74, 0x61, 0x67, 0x65,
0x44, 0x69, 0x73, 0x63, 0x72, 0x65, 0x74, 0x65, 0x48, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x52,
0x0e, 0x73, 0x74, 0x61, 0x67, 0x65, 0x44, 0x69, 0x73, 0x63, 0x72, 0x65, 0x74, 0x65, 0x48, 0x12,
0x1e, 0x0a, 0x0a, 0x73, 0x74, 0x61, 0x67, 0x65, 0x54, 0x69, 0x6c, 0x65, 0x57, 0x18, 0x06, 0x20,
0x01, 0x28, 0x05, 0x52, 0x0a, 0x73, 0x74, 0x61, 0x67, 0x65, 0x54, 0x69, 0x6c, 0x65, 0x57, 0x12,
0x1e, 0x0a, 0x0a, 0x73, 0x74, 0x61, 0x67, 0x65, 0x54, 0x69, 0x6c, 0x65, 0x48, 0x18, 0x07, 0x20,
0x01, 0x28, 0x05, 0x52, 0x0a, 0x73, 0x74, 0x61, 0x67, 0x65, 0x54, 0x69, 0x6c, 0x65, 0x48, 0x12,
0x26, 0x0a, 0x0e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x54, 0x6f, 0x50, 0x69, 0x6e,
0x67, 0x18, 0x08, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61,
0x6c, 0x54, 0x6f, 0x50, 0x69, 0x6e, 0x67, 0x12, 0x34, 0x0a, 0x15, 0x77, 0x69, 0x6c, 0x6c, 0x4b,
0x69, 0x63, 0x6b, 0x49, 0x66, 0x49, 0x6e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x46, 0x6f, 0x72,
0x18, 0x09, 0x20, 0x01, 0x28, 0x05, 0x52, 0x15, 0x77, 0x69, 0x6c, 0x6c, 0x4b, 0x69, 0x63, 0x6b,
0x49, 0x66, 0x49, 0x6e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x46, 0x6f, 0x72, 0x12, 0x20, 0x0a,
0x0b, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x6f, 0x6f, 0x6d, 0x49, 0x64, 0x18, 0x0a, 0x20, 0x01,
0x28, 0x05, 0x52, 0x0b, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x6f, 0x6f, 0x6d, 0x49, 0x64, 0x12,
0x32, 0x0a, 0x14, 0x62, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f,
0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x05, 0x52, 0x14, 0x62,
0x61, 0x74, 0x74, 0x6c, 0x65, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x46, 0x72, 0x61,
0x6d, 0x65, 0x73, 0x12, 0x30, 0x0a, 0x13, 0x62, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x44, 0x75, 0x72,
0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4e, 0x61, 0x6e, 0x6f, 0x73, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x03,
0x52, 0x13, 0x62, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e,
0x4e, 0x61, 0x6e, 0x6f, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x46,
0x70, 0x73, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72,
0x46, 0x70, 0x73, 0x12, 0x2a, 0x0a, 0x10, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x44, 0x65, 0x6c, 0x61,
0x79, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x05, 0x52, 0x10, 0x69,
0x6e, 0x70, 0x75, 0x74, 0x44, 0x65, 0x6c, 0x61, 0x79, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x12,
0x2a, 0x0a, 0x10, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x53, 0x63, 0x61, 0x6c, 0x65, 0x46, 0x72, 0x61,
0x6d, 0x65, 0x73, 0x18, 0x10, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x10, 0x69, 0x6e, 0x70, 0x75, 0x74,
0x53, 0x63, 0x61, 0x6c, 0x65, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x12, 0x26, 0x0a, 0x0e, 0x6e,
0x73, 0x74, 0x44, 0x65, 0x6c, 0x61, 0x79, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x11, 0x20,
0x01, 0x28, 0x05, 0x52, 0x0e, 0x6e, 0x73, 0x74, 0x44, 0x65, 0x6c, 0x61, 0x79, 0x46, 0x72, 0x61,
0x6d, 0x65, 0x73, 0x12, 0x46, 0x0a, 0x1e, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x46, 0x72, 0x61, 0x6d,
0x65, 0x55, 0x70, 0x73, 0x79, 0x6e, 0x63, 0x44, 0x65, 0x6c, 0x61, 0x79, 0x54, 0x6f, 0x6c, 0x65,
0x72, 0x61, 0x6e, 0x63, 0x65, 0x18, 0x12, 0x20, 0x01, 0x28, 0x05, 0x52, 0x1e, 0x69, 0x6e, 0x70,
0x75, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x55, 0x70, 0x73, 0x79, 0x6e, 0x63, 0x44, 0x65, 0x6c,
0x61, 0x79, 0x54, 0x6f, 0x6c, 0x65, 0x72, 0x61, 0x6e, 0x63, 0x65, 0x12, 0x48, 0x0a, 0x1f, 0x6d,
0x61, 0x78, 0x43, 0x68, 0x61, 0x73, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x46,
0x72, 0x61, 0x6d, 0x65, 0x73, 0x50, 0x65, 0x72, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x18, 0x13,
0x20, 0x01, 0x28, 0x05, 0x52, 0x1f, 0x6d, 0x61, 0x78, 0x43, 0x68, 0x61, 0x73, 0x69, 0x6e, 0x67,
0x52, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x50, 0x65, 0x72, 0x55,
0x70, 0x64, 0x61, 0x74, 0x65, 0x12, 0x2c, 0x0a, 0x11, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x42,
0x61, 0x74, 0x74, 0x6c, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x18, 0x14, 0x20, 0x01, 0x28, 0x05,
0x52, 0x11, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x42, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x53, 0x74,
0x61, 0x74, 0x65, 0x12, 0x3c, 0x0a, 0x19, 0x72, 0x6f, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x45,
0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x64, 0x44, 0x74, 0x4d, 0x69, 0x6c, 0x6c, 0x69, 0x73,
0x18, 0x15, 0x20, 0x01, 0x28, 0x01, 0x52, 0x19, 0x72, 0x6f, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b,
0x45, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x64, 0x44, 0x74, 0x4d, 0x69, 0x6c, 0x6c, 0x69,
0x73, 0x12, 0x3a, 0x0a, 0x18, 0x72, 0x6f, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x45, 0x73, 0x74,
0x69, 0x6d, 0x61, 0x74, 0x65, 0x64, 0x44, 0x74, 0x4e, 0x61, 0x6e, 0x6f, 0x73, 0x18, 0x16, 0x20,
0x01, 0x28, 0x03, 0x52, 0x18, 0x72, 0x6f, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x45, 0x73, 0x74,
0x69, 0x6d, 0x61, 0x74, 0x65, 0x64, 0x44, 0x74, 0x4e, 0x61, 0x6e, 0x6f, 0x73, 0x12, 0x38, 0x0a,
0x17, 0x77, 0x6f, 0x72, 0x6c, 0x64, 0x54, 0x6f, 0x56, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x47,
0x72, 0x69, 0x64, 0x52, 0x61, 0x74, 0x69, 0x6f, 0x18, 0x17, 0x20, 0x01, 0x28, 0x01, 0x52, 0x17,
0x77, 0x6f, 0x72, 0x6c, 0x64, 0x54, 0x6f, 0x56, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x47, 0x72,
0x69, 0x64, 0x52, 0x61, 0x74, 0x69, 0x6f, 0x12, 0x38, 0x0a, 0x17, 0x76, 0x69, 0x72, 0x74, 0x75,
0x61, 0x6c, 0x47, 0x72, 0x69, 0x64, 0x54, 0x6f, 0x57, 0x6f, 0x72, 0x6c, 0x64, 0x52, 0x61, 0x74,
0x69, 0x6f, 0x18, 0x18, 0x20, 0x01, 0x28, 0x01, 0x52, 0x17, 0x76, 0x69, 0x72, 0x74, 0x75, 0x61,
0x6c, 0x47, 0x72, 0x69, 0x64, 0x54, 0x6f, 0x57, 0x6f, 0x72, 0x6c, 0x64, 0x52, 0x61, 0x74, 0x69,
0x6f, 0x12, 0x2c, 0x0a, 0x11, 0x73, 0x70, 0x41, 0x74, 0x6b, 0x4c, 0x6f, 0x6f, 0x6b, 0x75, 0x70,
0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x19, 0x20, 0x01, 0x28, 0x05, 0x52, 0x11, 0x73, 0x70,
0x41, 0x74, 0x6b, 0x4c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x12,
0x28, 0x0a, 0x0f, 0x72, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x43, 0x61, 0x63, 0x68, 0x65, 0x53, 0x69,
0x7a, 0x65, 0x18, 0x1a, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0f, 0x72, 0x65, 0x6e, 0x64, 0x65, 0x72,
0x43, 0x61, 0x63, 0x68, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x5c, 0x0a, 0x10, 0x6d, 0x65, 0x6c,
0x65, 0x65, 0x53, 0x6b, 0x69, 0x6c, 0x6c, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x1b, 0x20,
0x03, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x42, 0x61, 0x74,
0x74, 0x6c, 0x65, 0x43, 0x6f, 0x6c, 0x6c, 0x69, 0x64, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x2e,
0x4d, 0x65, 0x6c, 0x65, 0x65, 0x53, 0x6b, 0x69, 0x6c, 0x6c, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67,
0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x10, 0x6d, 0x65, 0x6c, 0x65, 0x65, 0x53, 0x6b, 0x69, 0x6c,
0x6c, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x38, 0x0a, 0x17, 0x73, 0x6e, 0x61, 0x70, 0x49,
0x6e, 0x74, 0x6f, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x4f, 0x76, 0x65, 0x72, 0x6c,
0x61, 0x70, 0x18, 0x1c, 0x20, 0x01, 0x28, 0x01, 0x52, 0x17, 0x73, 0x6e, 0x61, 0x70, 0x49, 0x6e,
0x74, 0x6f, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x4f, 0x76, 0x65, 0x72, 0x6c, 0x61,
0x70, 0x12, 0x3c, 0x0a, 0x19, 0x73, 0x6e, 0x61, 0x70, 0x49, 0x6e, 0x74, 0x6f, 0x50, 0x6c, 0x61,
0x74, 0x66, 0x6f, 0x72, 0x6d, 0x54, 0x68, 0x72, 0x65, 0x73, 0x68, 0x6f, 0x6c, 0x64, 0x18, 0x1d,
0x20, 0x01, 0x28, 0x01, 0x52, 0x19, 0x73, 0x6e, 0x61, 0x70, 0x49, 0x6e, 0x74, 0x6f, 0x50, 0x6c,
0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x54, 0x68, 0x72, 0x65, 0x73, 0x68, 0x6f, 0x6c, 0x64, 0x12,
0x28, 0x0a, 0x0f, 0x6a, 0x75, 0x6d, 0x70, 0x69, 0x6e, 0x67, 0x49, 0x6e, 0x69, 0x74, 0x56, 0x65,
0x6c, 0x59, 0x18, 0x1e, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0f, 0x6a, 0x75, 0x6d, 0x70, 0x69, 0x6e,
0x67, 0x49, 0x6e, 0x69, 0x74, 0x56, 0x65, 0x6c, 0x59, 0x12, 0x1a, 0x0a, 0x08, 0x67, 0x72, 0x61,
0x76, 0x69, 0x74, 0x79, 0x58, 0x18, 0x1f, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x67, 0x72, 0x61,
0x76, 0x69, 0x74, 0x79, 0x58, 0x12, 0x1a, 0x0a, 0x08, 0x67, 0x72, 0x61, 0x76, 0x69, 0x74, 0x79,
0x59, 0x18, 0x20, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x67, 0x72, 0x61, 0x76, 0x69, 0x74, 0x79,
0x59, 0x1a, 0x5d, 0x0a, 0x16, 0x53, 0x74, 0x72, 0x54, 0x6f, 0x56, 0x65, 0x63, 0x32, 0x44, 0x4c,
0x69, 0x73, 0x74, 0x4d, 0x61, 0x70, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b,
0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x2d, 0x0a,
0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x73,
0x68, 0x61, 0x72, 0x65, 0x64, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x56, 0x65, 0x63, 0x32,
0x44, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01,
0x1a, 0x65, 0x0a, 0x1a, 0x53, 0x74, 0x72, 0x54, 0x6f, 0x50, 0x6f, 0x6c, 0x79, 0x67, 0x6f, 0x6e,
0x32, 0x44, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x61, 0x70, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10,
0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79,
0x12, 0x31, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32,
0x1b, 0x2e, 0x73, 0x68, 0x61, 0x72, 0x65, 0x64, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x50,
0x6f, 0x6c, 0x79, 0x67, 0x6f, 0x6e, 0x32, 0x44, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x05, 0x76, 0x61,
0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x58, 0x0a, 0x15, 0x4d, 0x65, 0x6c, 0x65, 0x65,
0x53, 0x6b, 0x69, 0x6c, 0x6c, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x45, 0x6e, 0x74, 0x72, 0x79,
0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x03, 0x6b,
0x65, 0x79, 0x12, 0x29, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28,
0x0b, 0x32, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x4d, 0x65, 0x6c, 0x65, 0x65,
0x42, 0x75, 0x6c, 0x6c, 0x65, 0x74, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38,
0x01, 0x22, 0xd2, 0x02, 0x0a, 0x11, 0x52, 0x6f, 0x6f, 0x6d, 0x44, 0x6f, 0x77, 0x6e, 0x73, 0x79,
0x6e, 0x63, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20,
0x01, 0x28, 0x05, 0x52, 0x02, 0x69, 0x64, 0x12, 0x40, 0x0a, 0x07, 0x70, 0x6c, 0x61, 0x79, 0x65,
0x72, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
0x73, 0x2e, 0x52, 0x6f, 0x6f, 0x6d, 0x44, 0x6f, 0x77, 0x6e, 0x73, 0x79, 0x6e, 0x63, 0x46, 0x72,
0x61, 0x6d, 0x65, 0x2e, 0x50, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79,
0x52, 0x07, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x73, 0x12, 0x26, 0x0a, 0x0e, 0x63, 0x6f, 0x75,
0x6e, 0x74, 0x64, 0x6f, 0x77, 0x6e, 0x4e, 0x61, 0x6e, 0x6f, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28,
0x03, 0x52, 0x0e, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x64, 0x6f, 0x77, 0x6e, 0x4e, 0x61, 0x6e, 0x6f,
0x73, 0x12, 0x37, 0x0a, 0x0c, 0x6d, 0x65, 0x6c, 0x65, 0x65, 0x42, 0x75, 0x6c, 0x6c, 0x65, 0x74,
0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73,
0x2e, 0x4d, 0x65, 0x6c, 0x65, 0x65, 0x42, 0x75, 0x6c, 0x6c, 0x65, 0x74, 0x52, 0x0c, 0x6d, 0x65,
0x6c, 0x65, 0x65, 0x42, 0x75, 0x6c, 0x6c, 0x65, 0x74, 0x73, 0x12, 0x36, 0x0a, 0x16, 0x62, 0x61,
0x63, 0x6b, 0x65, 0x6e, 0x64, 0x55, 0x6e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d, 0x65, 0x64,
0x4d, 0x61, 0x73, 0x6b, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x16, 0x62, 0x61, 0x63, 0x6b,
0x79, 0x6e, 0x63, 0x73, 0x12, 0x2c, 0x0a, 0x11, 0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x46, 0x6f,
0x72, 0x63, 0x65, 0x52, 0x65, 0x73, 0x79, 0x6e, 0x63, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52,
0x11, 0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x46, 0x6f, 0x72, 0x63, 0x65, 0x52, 0x65, 0x73, 0x79,
0x6e, 0x63, 0x22, 0xe5, 0x05, 0x0a, 0x0b, 0x4d, 0x65, 0x6c, 0x65, 0x65, 0x42, 0x75, 0x6c, 0x6c,
0x65, 0x74, 0x12, 0x24, 0x0a, 0x0d, 0x62, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x4c, 0x6f, 0x63, 0x61,
0x6c, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0d, 0x62, 0x61, 0x74, 0x74, 0x6c,
0x65, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x49, 0x64, 0x12, 0x24, 0x0a, 0x0d, 0x73, 0x74, 0x61, 0x72,
0x74, 0x75, 0x70, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52,
0x0d, 0x73, 0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x12, 0x22,
0x0a, 0x0c, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x03,
0x20, 0x01, 0x28, 0x05, 0x52, 0x0c, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x46, 0x72, 0x61, 0x6d,
0x65, 0x73, 0x12, 0x26, 0x0a, 0x0e, 0x72, 0x65, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x46, 0x72,
0x61, 0x6d, 0x65, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0e, 0x72, 0x65, 0x63, 0x6f,
0x76, 0x65, 0x72, 0x79, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x12, 0x34, 0x0a, 0x15, 0x72, 0x65,
0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x4f, 0x6e, 0x42, 0x6c,
0x6f, 0x63, 0x6b, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x52, 0x15, 0x72, 0x65, 0x63, 0x6f, 0x76,
0x65, 0x72, 0x79, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x4f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b,
0x12, 0x30, 0x0a, 0x13, 0x72, 0x65, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x46, 0x72, 0x61, 0x6d,
0x65, 0x73, 0x4f, 0x6e, 0x48, 0x69, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x05, 0x52, 0x13, 0x72,
0x65, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x4f, 0x6e, 0x48,
0x69, 0x74, 0x12, 0x35, 0x0a, 0x0b, 0x6d, 0x6f, 0x76, 0x65, 0x66, 0x6f, 0x72, 0x77, 0x61, 0x72,
0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x73, 0x68, 0x61, 0x72, 0x65, 0x64,
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x56, 0x65, 0x63, 0x32, 0x44, 0x52, 0x0b, 0x6d, 0x6f,
0x76, 0x65, 0x66, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x12, 0x22, 0x0a, 0x0c, 0x68, 0x69, 0x74,
0x62, 0x6f, 0x78, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x18, 0x08, 0x20, 0x01, 0x28, 0x01, 0x52,
0x0c, 0x68, 0x69, 0x74, 0x62, 0x6f, 0x78, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x12, 0x33, 0x0a,
0x0a, 0x68, 0x69, 0x74, 0x62, 0x6f, 0x78, 0x53, 0x69, 0x7a, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28,
0x0b, 0x32, 0x13, 0x2e, 0x73, 0x68, 0x61, 0x72, 0x65, 0x64, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73,
0x2e, 0x56, 0x65, 0x63, 0x32, 0x44, 0x52, 0x0a, 0x68, 0x69, 0x74, 0x62, 0x6f, 0x78, 0x53, 0x69,
0x7a, 0x65, 0x12, 0x38, 0x0a, 0x17, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x65, 0x64,
0x52, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x49, 0x64, 0x18, 0x0a, 0x20,
0x01, 0x28, 0x05, 0x52, 0x17, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x65, 0x64, 0x52,
0x65, 0x6e, 0x64, 0x65, 0x72, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x49, 0x64, 0x12, 0x24, 0x0a, 0x0d,
0x68, 0x69, 0x74, 0x53, 0x74, 0x75, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x0b, 0x20,
0x01, 0x28, 0x05, 0x52, 0x0d, 0x68, 0x69, 0x74, 0x53, 0x74, 0x75, 0x6e, 0x46, 0x72, 0x61, 0x6d,
0x65, 0x73, 0x12, 0x28, 0x0a, 0x0f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x53, 0x74, 0x75, 0x6e, 0x46,
0x72, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0f, 0x62, 0x6c, 0x6f,
0x63, 0x6b, 0x53, 0x74, 0x75, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x12, 0x1a, 0x0a, 0x08,
0x70, 0x75, 0x73, 0x68, 0x62, 0x61, 0x63, 0x6b, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x01, 0x52, 0x08,
0x70, 0x75, 0x73, 0x68, 0x62, 0x61, 0x63, 0x6b, 0x12, 0x2e, 0x0a, 0x12, 0x72, 0x65, 0x6c, 0x65,
0x61, 0x73, 0x65, 0x54, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x54, 0x79, 0x70, 0x65, 0x18, 0x0e,
0x20, 0x01, 0x28, 0x05, 0x52, 0x12, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x54, 0x72, 0x69,
0x67, 0x67, 0x65, 0x72, 0x54, 0x79, 0x70, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x64, 0x61, 0x6d, 0x61,
0x67, 0x65, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x64, 0x61, 0x6d, 0x61, 0x67, 0x65,
0x12, 0x2c, 0x0a, 0x11, 0x6f, 0x66, 0x66, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x4a, 0x6f, 0x69, 0x6e,
0x49, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x10, 0x20, 0x01, 0x28, 0x05, 0x52, 0x11, 0x6f, 0x66, 0x66,
0x65, 0x6e, 0x64, 0x65, 0x72, 0x4a, 0x6f, 0x69, 0x6e, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x2a,
0x0a, 0x10, 0x6f, 0x66, 0x66, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x50, 0x6c, 0x61, 0x79, 0x65, 0x72,
0x49, 0x64, 0x18, 0x11, 0x20, 0x01, 0x28, 0x05, 0x52, 0x10, 0x6f, 0x66, 0x66, 0x65, 0x6e, 0x64,
0x65, 0x72, 0x50, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x49, 0x64, 0x22, 0xf2, 0x0e, 0x0a, 0x12, 0x42,
0x61, 0x74, 0x74, 0x6c, 0x65, 0x43, 0x6f, 0x6c, 0x6c, 0x69, 0x64, 0x65, 0x72, 0x49, 0x6e, 0x66,
0x6f, 0x12, 0x1c, 0x0a, 0x09, 0x73, 0x74, 0x61, 0x67, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01,
0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x74, 0x61, 0x67, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12,
0x5f, 0x0a, 0x11, 0x73, 0x74, 0x72, 0x54, 0x6f, 0x56, 0x65, 0x63, 0x32, 0x44, 0x4c, 0x69, 0x73,
0x74, 0x4d, 0x61, 0x70, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x70, 0x72, 0x6f,
0x74, 0x6f, 0x73, 0x2e, 0x42, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x43, 0x6f, 0x6c, 0x6c, 0x69, 0x64,
0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x2e, 0x53, 0x74, 0x72, 0x54, 0x6f, 0x56, 0x65, 0x63, 0x32,
0x44, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x61, 0x70, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x11, 0x73,
0x74, 0x72, 0x54, 0x6f, 0x56, 0x65, 0x63, 0x32, 0x44, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x61, 0x70,
0x12, 0x6b, 0x0a, 0x15, 0x73, 0x74, 0x72, 0x54, 0x6f, 0x50, 0x6f, 0x6c, 0x79, 0x67, 0x6f, 0x6e,
0x32, 0x44, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x61, 0x70, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32,
0x35, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x42, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x43,
0x6f, 0x6c, 0x6c, 0x69, 0x64, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x2e, 0x53, 0x74, 0x72, 0x54,
0x6f, 0x50, 0x6f, 0x6c, 0x79, 0x67, 0x6f, 0x6e, 0x32, 0x44, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x61,
0x70, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x15, 0x73, 0x74, 0x72, 0x54, 0x6f, 0x50, 0x6f, 0x6c,
0x79, 0x67, 0x6f, 0x6e, 0x32, 0x44, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x61, 0x70, 0x12, 0x26, 0x0a,
0x0e, 0x73, 0x74, 0x61, 0x67, 0x65, 0x44, 0x69, 0x73, 0x63, 0x72, 0x65, 0x74, 0x65, 0x57, 0x18,
0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0e, 0x73, 0x74, 0x61, 0x67, 0x65, 0x44, 0x69, 0x73, 0x63,
0x72, 0x65, 0x74, 0x65, 0x57, 0x12, 0x26, 0x0a, 0x0e, 0x73, 0x74, 0x61, 0x67, 0x65, 0x44, 0x69,
0x73, 0x63, 0x72, 0x65, 0x74, 0x65, 0x48, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0e, 0x73,
0x74, 0x61, 0x67, 0x65, 0x44, 0x69, 0x73, 0x63, 0x72, 0x65, 0x74, 0x65, 0x48, 0x12, 0x1e, 0x0a,
0x0a, 0x73, 0x74, 0x61, 0x67, 0x65, 0x54, 0x69, 0x6c, 0x65, 0x57, 0x18, 0x06, 0x20, 0x01, 0x28,
0x05, 0x52, 0x0a, 0x73, 0x74, 0x61, 0x67, 0x65, 0x54, 0x69, 0x6c, 0x65, 0x57, 0x12, 0x1e, 0x0a,
0x0a, 0x73, 0x74, 0x61, 0x67, 0x65, 0x54, 0x69, 0x6c, 0x65, 0x48, 0x18, 0x07, 0x20, 0x01, 0x28,
0x05, 0x52, 0x0a, 0x73, 0x74, 0x61, 0x67, 0x65, 0x54, 0x69, 0x6c, 0x65, 0x48, 0x12, 0x26, 0x0a,
0x0e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x54, 0x6f, 0x50, 0x69, 0x6e, 0x67, 0x18,
0x08, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x54,
0x6f, 0x50, 0x69, 0x6e, 0x67, 0x12, 0x34, 0x0a, 0x15, 0x77, 0x69, 0x6c, 0x6c, 0x4b, 0x69, 0x63,
0x6b, 0x49, 0x66, 0x49, 0x6e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x46, 0x6f, 0x72, 0x18, 0x09,
0x20, 0x01, 0x28, 0x05, 0x52, 0x15, 0x77, 0x69, 0x6c, 0x6c, 0x4b, 0x69, 0x63, 0x6b, 0x49, 0x66,
0x49, 0x6e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x46, 0x6f, 0x72, 0x12, 0x20, 0x0a, 0x0b, 0x62,
0x6f, 0x75, 0x6e, 0x64, 0x52, 0x6f, 0x6f, 0x6d, 0x49, 0x64, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x05,
0x52, 0x0b, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x6f, 0x6f, 0x6d, 0x49, 0x64, 0x12, 0x32, 0x0a,
0x14, 0x62, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x46,
0x72, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x05, 0x52, 0x14, 0x62, 0x61, 0x74,
0x74, 0x6c, 0x65, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65,
0x73, 0x12, 0x30, 0x0a, 0x13, 0x62, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x44, 0x75, 0x72, 0x61, 0x74,
0x69, 0x6f, 0x6e, 0x4e, 0x61, 0x6e, 0x6f, 0x73, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x03, 0x52, 0x13,
0x62, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4e, 0x61,
0x6e, 0x6f, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x46, 0x70, 0x73,
0x18, 0x0e, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x46, 0x70,
0x73, 0x12, 0x2a, 0x0a, 0x10, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x44, 0x65, 0x6c, 0x61, 0x79, 0x46,
0x72, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x05, 0x52, 0x10, 0x69, 0x6e, 0x70,
0x75, 0x74, 0x44, 0x65, 0x6c, 0x61, 0x79, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x12, 0x2a, 0x0a,
0x10, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x53, 0x63, 0x61, 0x6c, 0x65, 0x46, 0x72, 0x61, 0x6d, 0x65,
0x73, 0x18, 0x10, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x10, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x53, 0x63,
0x61, 0x6c, 0x65, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x12, 0x26, 0x0a, 0x0e, 0x6e, 0x73, 0x74,
0x44, 0x65, 0x6c, 0x61, 0x79, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x11, 0x20, 0x01, 0x28,
0x05, 0x52, 0x0e, 0x6e, 0x73, 0x74, 0x44, 0x65, 0x6c, 0x61, 0x79, 0x46, 0x72, 0x61, 0x6d, 0x65,
0x73, 0x12, 0x46, 0x0a, 0x1e, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x55,
0x70, 0x73, 0x79, 0x6e, 0x63, 0x44, 0x65, 0x6c, 0x61, 0x79, 0x54, 0x6f, 0x6c, 0x65, 0x72, 0x61,
0x6e, 0x63, 0x65, 0x18, 0x12, 0x20, 0x01, 0x28, 0x05, 0x52, 0x1e, 0x69, 0x6e, 0x70, 0x75, 0x74,
0x46, 0x72, 0x61, 0x6d, 0x65, 0x55, 0x70, 0x73, 0x79, 0x6e, 0x63, 0x44, 0x65, 0x6c, 0x61, 0x79,
0x54, 0x6f, 0x6c, 0x65, 0x72, 0x61, 0x6e, 0x63, 0x65, 0x12, 0x48, 0x0a, 0x1f, 0x6d, 0x61, 0x78,
0x43, 0x68, 0x61, 0x73, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x46, 0x72, 0x61,
0x6d, 0x65, 0x73, 0x50, 0x65, 0x72, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x18, 0x13, 0x20, 0x01,
0x28, 0x05, 0x52, 0x1f, 0x6d, 0x61, 0x78, 0x43, 0x68, 0x61, 0x73, 0x69, 0x6e, 0x67, 0x52, 0x65,
0x6e, 0x64, 0x65, 0x72, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x50, 0x65, 0x72, 0x55, 0x70, 0x64,
0x61, 0x74, 0x65, 0x12, 0x2c, 0x0a, 0x11, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x42, 0x61, 0x74,
0x74, 0x6c, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x18, 0x14, 0x20, 0x01, 0x28, 0x05, 0x52, 0x11,
0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x42, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x53, 0x74, 0x61, 0x74,
0x65, 0x12, 0x3c, 0x0a, 0x19, 0x72, 0x6f, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x45, 0x73, 0x74,
0x69, 0x6d, 0x61, 0x74, 0x65, 0x64, 0x44, 0x74, 0x4d, 0x69, 0x6c, 0x6c, 0x69, 0x73, 0x18, 0x15,
0x20, 0x01, 0x28, 0x01, 0x52, 0x19, 0x72, 0x6f, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x45, 0x73,
0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x64, 0x44, 0x74, 0x4d, 0x69, 0x6c, 0x6c, 0x69, 0x73, 0x12,
0x3a, 0x0a, 0x18, 0x72, 0x6f, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x45, 0x73, 0x74, 0x69, 0x6d,
0x61, 0x74, 0x65, 0x64, 0x44, 0x74, 0x4e, 0x61, 0x6e, 0x6f, 0x73, 0x18, 0x16, 0x20, 0x01, 0x28,
0x03, 0x52, 0x18, 0x72, 0x6f, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x45, 0x73, 0x74, 0x69, 0x6d,
0x61, 0x74, 0x65, 0x64, 0x44, 0x74, 0x4e, 0x61, 0x6e, 0x6f, 0x73, 0x12, 0x38, 0x0a, 0x17, 0x77,
0x6f, 0x72, 0x6c, 0x64, 0x54, 0x6f, 0x56, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x47, 0x72, 0x69,
0x64, 0x52, 0x61, 0x74, 0x69, 0x6f, 0x18, 0x17, 0x20, 0x01, 0x28, 0x01, 0x52, 0x17, 0x77, 0x6f,
0x72, 0x6c, 0x64, 0x54, 0x6f, 0x56, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x47, 0x72, 0x69, 0x64,
0x52, 0x61, 0x74, 0x69, 0x6f, 0x12, 0x38, 0x0a, 0x17, 0x76, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c,
0x47, 0x72, 0x69, 0x64, 0x54, 0x6f, 0x57, 0x6f, 0x72, 0x6c, 0x64, 0x52, 0x61, 0x74, 0x69, 0x6f,
0x18, 0x18, 0x20, 0x01, 0x28, 0x01, 0x52, 0x17, 0x76, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x47,
0x72, 0x69, 0x64, 0x54, 0x6f, 0x57, 0x6f, 0x72, 0x6c, 0x64, 0x52, 0x61, 0x74, 0x69, 0x6f, 0x12,
0x2c, 0x0a, 0x11, 0x73, 0x70, 0x41, 0x74, 0x6b, 0x4c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x46, 0x72,
0x61, 0x6d, 0x65, 0x73, 0x18, 0x19, 0x20, 0x01, 0x28, 0x05, 0x52, 0x11, 0x73, 0x70, 0x41, 0x74,
0x6b, 0x4c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x12, 0x28, 0x0a,
0x0f, 0x72, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x43, 0x61, 0x63, 0x68, 0x65, 0x53, 0x69, 0x7a, 0x65,
0x18, 0x1a, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0f, 0x72, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x43, 0x61,
0x63, 0x68, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x5c, 0x0a, 0x10, 0x6d, 0x65, 0x6c, 0x65, 0x65,
0x53, 0x6b, 0x69, 0x6c, 0x6c, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x1b, 0x20, 0x03, 0x28,
0x0b, 0x32, 0x30, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x42, 0x61, 0x74, 0x74, 0x6c,
0x65, 0x43, 0x6f, 0x6c, 0x6c, 0x69, 0x64, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x2e, 0x4d, 0x65,
0x6c, 0x65, 0x65, 0x53, 0x6b, 0x69, 0x6c, 0x6c, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x45, 0x6e,
0x74, 0x72, 0x79, 0x52, 0x10, 0x6d, 0x65, 0x6c, 0x65, 0x65, 0x53, 0x6b, 0x69, 0x6c, 0x6c, 0x43,
0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x38, 0x0a, 0x17, 0x73, 0x6e, 0x61, 0x70, 0x49, 0x6e, 0x74,
0x6f, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x4f, 0x76, 0x65, 0x72, 0x6c, 0x61, 0x70,
0x18, 0x1c, 0x20, 0x01, 0x28, 0x01, 0x52, 0x17, 0x73, 0x6e, 0x61, 0x70, 0x49, 0x6e, 0x74, 0x6f,
0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x4f, 0x76, 0x65, 0x72, 0x6c, 0x61, 0x70, 0x12,
0x3c, 0x0a, 0x19, 0x73, 0x6e, 0x61, 0x70, 0x49, 0x6e, 0x74, 0x6f, 0x50, 0x6c, 0x61, 0x74, 0x66,
0x6f, 0x72, 0x6d, 0x54, 0x68, 0x72, 0x65, 0x73, 0x68, 0x6f, 0x6c, 0x64, 0x18, 0x1d, 0x20, 0x01,
0x28, 0x01, 0x52, 0x19, 0x73, 0x6e, 0x61, 0x70, 0x49, 0x6e, 0x74, 0x6f, 0x50, 0x6c, 0x61, 0x74,
0x66, 0x6f, 0x72, 0x6d, 0x54, 0x68, 0x72, 0x65, 0x73, 0x68, 0x6f, 0x6c, 0x64, 0x12, 0x28, 0x0a,
0x0f, 0x6a, 0x75, 0x6d, 0x70, 0x69, 0x6e, 0x67, 0x49, 0x6e, 0x69, 0x74, 0x56, 0x65, 0x6c, 0x59,
0x18, 0x1e, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0f, 0x6a, 0x75, 0x6d, 0x70, 0x69, 0x6e, 0x67, 0x49,
0x6e, 0x69, 0x74, 0x56, 0x65, 0x6c, 0x59, 0x12, 0x1a, 0x0a, 0x08, 0x67, 0x72, 0x61, 0x76, 0x69,
0x74, 0x79, 0x58, 0x18, 0x1f, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x67, 0x72, 0x61, 0x76, 0x69,
0x74, 0x79, 0x58, 0x12, 0x1a, 0x0a, 0x08, 0x67, 0x72, 0x61, 0x76, 0x69, 0x74, 0x79, 0x59, 0x18,
0x20, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x67, 0x72, 0x61, 0x76, 0x69, 0x74, 0x79, 0x59, 0x1a,
0x5d, 0x0a, 0x16, 0x53, 0x74, 0x72, 0x54, 0x6f, 0x56, 0x65, 0x63, 0x32, 0x44, 0x4c, 0x69, 0x73,
0x74, 0x4d, 0x61, 0x70, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79,
0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x2d, 0x0a, 0x05, 0x76,
0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x73, 0x68, 0x61,
0x72, 0x65, 0x64, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x56, 0x65, 0x63, 0x32, 0x44, 0x4c,
0x69, 0x73, 0x74, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x65,
0x0a, 0x1a, 0x53, 0x74, 0x72, 0x54, 0x6f, 0x50, 0x6f, 0x6c, 0x79, 0x67, 0x6f, 0x6e, 0x32, 0x44,
0x4c, 0x69, 0x73, 0x74, 0x4d, 0x61, 0x70, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03,
0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x31,
0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e,
0x73, 0x68, 0x61, 0x72, 0x65, 0x64, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x50, 0x6f, 0x6c,
0x79, 0x67, 0x6f, 0x6e, 0x32, 0x44, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75,
0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x58, 0x0a, 0x15, 0x4d, 0x65, 0x6c, 0x65, 0x65, 0x53, 0x6b,
0x69, 0x6c, 0x6c, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10,
0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x03, 0x6b, 0x65, 0x79,
0x12, 0x29, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32,
0x13, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x4d, 0x65, 0x6c, 0x65, 0x65, 0x42, 0x75,
0x6c, 0x6c, 0x65, 0x74, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22,
0x80, 0x03, 0x0a, 0x11, 0x52, 0x6f, 0x6f, 0x6d, 0x44, 0x6f, 0x77, 0x6e, 0x73, 0x79, 0x6e, 0x63,
0x46, 0x72, 0x61, 0x6d, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28,
0x05, 0x52, 0x02, 0x69, 0x64, 0x12, 0x40, 0x0a, 0x07, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x73,
0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e,
0x52, 0x6f, 0x6f, 0x6d, 0x44, 0x6f, 0x77, 0x6e, 0x73, 0x79, 0x6e, 0x63, 0x46, 0x72, 0x61, 0x6d,
0x65, 0x2e, 0x50, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x07,
0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x73, 0x12, 0x26, 0x0a, 0x0e, 0x63, 0x6f, 0x75, 0x6e, 0x74,
0x64, 0x6f, 0x77, 0x6e, 0x4e, 0x61, 0x6e, 0x6f, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52,
0x0e, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x64, 0x6f, 0x77, 0x6e, 0x4e, 0x61, 0x6e, 0x6f, 0x73, 0x12,
0x37, 0x0a, 0x0c, 0x6d, 0x65, 0x6c, 0x65, 0x65, 0x42, 0x75, 0x6c, 0x6c, 0x65, 0x74, 0x73, 0x18,
0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x4d,
0x65, 0x6c, 0x65, 0x65, 0x42, 0x75, 0x6c, 0x6c, 0x65, 0x74, 0x52, 0x0c, 0x6d, 0x65, 0x6c, 0x65,
0x65, 0x42, 0x75, 0x6c, 0x6c, 0x65, 0x74, 0x73, 0x12, 0x36, 0x0a, 0x16, 0x62, 0x61, 0x63, 0x6b,
0x65, 0x6e, 0x64, 0x55, 0x6e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d, 0x65, 0x64, 0x4d, 0x61,
0x73, 0x6b, 0x1a, 0x52, 0x0a, 0x0c, 0x50, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x73, 0x45, 0x6e, 0x74,
0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52,
0x03, 0x6b, 0x65, 0x79, 0x12, 0x2c, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20,
0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x50, 0x6c, 0x61,
0x79, 0x65, 0x72, 0x44, 0x6f, 0x77, 0x6e, 0x73, 0x79, 0x6e, 0x63, 0x52, 0x05, 0x76, 0x61, 0x6c,
0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x42, 0x13, 0x5a, 0x11, 0x62, 0x61, 0x74, 0x74, 0x6c, 0x65,
0x5f, 0x73, 0x72, 0x76, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f,
0x74, 0x6f, 0x33,
0x73, 0x6b, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x16, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e,
0x64, 0x55, 0x6e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d, 0x65, 0x64, 0x4d, 0x61, 0x73, 0x6b,
0x12, 0x2c, 0x0a, 0x11, 0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x46, 0x6f, 0x72, 0x63, 0x65, 0x52,
0x65, 0x73, 0x79, 0x6e, 0x63, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x11, 0x73, 0x68, 0x6f,
0x75, 0x6c, 0x64, 0x46, 0x6f, 0x72, 0x63, 0x65, 0x52, 0x65, 0x73, 0x79, 0x6e, 0x63, 0x1a, 0x52,
0x0a, 0x0c, 0x50, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10,
0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x03, 0x6b, 0x65, 0x79,
0x12, 0x2c, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32,
0x16, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x50, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x44,
0x6f, 0x77, 0x6e, 0x73, 0x79, 0x6e, 0x63, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02,
0x38, 0x01, 0x42, 0x13, 0x5a, 0x11, 0x62, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x5f, 0x73, 0x72, 0x76,
0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (

View File

@@ -7,6 +7,7 @@ fi
basedir=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
PROJECTNAME=server.exe
OS_USER=$USER
ServerEnv=$1
LOG_PATH="/var/log/treasure-hunter.log"
@@ -17,5 +18,5 @@ PID_FILE="$basedir/treasure-hunter.pid"
sudo su - root -c "touch $LOG_PATH"
sudo su - root -c "chown $OS_USER:$OS_USER $LOG_PATH"
ServerEnv=$ServerEnv $basedir/server >$LOG_PATH 2>&1 &
ServerEnv=$ServerEnv $basedir/$PROJECTNAME >$LOG_PATH 2>&1 &
echo $! > $PID_FILE

View File

@@ -7,3 +7,10 @@ ffmpeg -i input.mp4 -filter:v "setpts=0.5*PTS" output.mp4
```
ffmpeg -ss 12 -t 13 -i input.mp4 -vf "fps=10,scale=480:-1" -loop 0 output.gif
```
# Extract GIF (with alpha channel, e.g. exported from Fighter Factory Studio) to PNG sequence
```
ffmpeg -vsync vfr -i input.gif output%d.png
```
The `-vsync vfr` tells ffmpeg to disrespect the original delays set within the GIF file, otherwise many duplicate frame will be extracted by the default 60FPS.

View File

@@ -2,7 +2,8 @@ PROJECTNAME=viscol.exe
ROOT_DIR=.
all: help
## Available proxies for downloading go modules are listed in "https://github.com/golang/go/wiki/Modules#how-do-i-use-vendoring-with-modules-is-vendoring-going-away".
GOPROXY=https://mirrors.aliyun.com/goproxy
#GOPROXY=https://mirrors.aliyun.com/goproxy
GOPROXY=https://goproxy.io
build:
GOPROXY=$(GOPROXY) go build -o $(ROOT_DIR)/$(PROJECTNAME)

View File

@@ -37,14 +37,15 @@ func NewWorldColliderDisplay(game *Game, stageDiscreteW, stageDiscreteH, stageTi
worldToVirtualGridRatio := float64(1000)
virtualGridToWorldRatio := float64(1) / worldToVirtualGridRatio
playerDefaultSpeed := 1 * worldToVirtualGridRatio
minStep := (int(float64(playerDefaultSpeed)*virtualGridToWorldRatio) << 2)
minStep := (int(float64(playerDefaultSpeed)*virtualGridToWorldRatio) << 3)
playerColliderRadius := float64(12)
playerColliders := make([]*resolv.Object, len(playerPosList.Eles))
snapIntoPlatformOverlap := float64(0.1)
space := resolv.NewSpace(int(spaceW), int(spaceH), minStep, minStep)
topPadding, bottomPadding, leftPadding, rightPadding := snapIntoPlatformOverlap, snapIntoPlatformOverlap, snapIntoPlatformOverlap, snapIntoPlatformOverlap
for i, playerPos := range playerPosList.Eles {
colliderWidth, colliderHeight := playerColliderRadius*2, playerColliderRadius*4
playerCollider := GenerateRectCollider(playerPos.X, playerPos.Y, colliderWidth, colliderHeight, snapIntoPlatformOverlap, spaceOffsetX, spaceOffsetY, "Player") // [WARNING] Deliberately not using a circle because "resolv v0.5.1" doesn't yet align circle center with space cell center, regardless of the "specified within-object offset"
playerCollider := GenerateRectCollider(playerPos.X, playerPos.Y, colliderWidth, colliderHeight, topPadding, bottomPadding, leftPadding, rightPadding, spaceOffsetX, spaceOffsetY, "Player") // [WARNING] Deliberately not using a circle because "resolv v0.5.1" doesn't yet align circle center with space cell center, regardless of the "specified within-object offset"
Logger.Info(fmt.Sprintf("Player Collider#%d: player world pos=(%.2f, %.2f), shape=%v", i, playerPos.X, playerPos.Y, ConvexPolygonStr(playerCollider.Shape.(*resolv.ConvexPolygon))))
playerColliders[i] = playerCollider
space.Add(playerCollider)
@@ -60,13 +61,13 @@ func NewWorldColliderDisplay(game *Game, stageDiscreteW, stageDiscreteH, stageTi
world.Space = space
moveToCollide := false
moveToCollide := true
if moveToCollide {
effPushback := Vec2D{X: float64(0), Y: float64(0)}
toTestPlayerCollider := playerColliders[0]
newVx, newVy := int32(27999), int32(-420270)
colliderWidth, colliderHeight := playerColliderRadius*2, playerColliderRadius*4
toTestPlayerCollider.X, toTestPlayerCollider.Y = VirtualGridToPolygonColliderTLPos(newVx, newVy, colliderWidth, colliderHeight, spaceOffsetX, spaceOffsetY, virtualGridToWorldRatio)
//colliderWidth, colliderHeight := playerColliderRadius*2, playerColliderRadius*4
//newVx, newVy := int32(27999), int32(-420270)
//toTestPlayerCollider.X, toTestPlayerCollider.Y = VirtualGridToPolygonColliderBLPos(newVx, newVy, colliderWidth, colliderHeight, topPadding, bottomPadding, leftPadding, rightPadding, spaceOffsetX, spaceOffsetY, virtualGridToWorldRatio)
Logger.Info(fmt.Sprintf("Checking collision for playerShape=%v", ConvexPolygonStr(toTestPlayerCollider.Shape.(*resolv.ConvexPolygon))))
@@ -114,13 +115,12 @@ func NewWorldColliderDisplay(game *Game, stageDiscreteW, stageDiscreteH, stageTi
ReleaseTriggerType: int32(1), // 1: rising-edge, 2: falling-edge
Damage: int32(5),
}
bulletLeftToRight := true
bulletLeftToRight := false
if bulletLeftToRight {
xfac := float64(1.0)
offenderWx, offenderWy := playerPosList.Eles[0].X, playerPosList.Eles[0].Y
bulletWx, bulletWy := offenderWx+xfac*meleeBullet.HitboxOffset, offenderWy
newBulletCollider := GenerateRectCollider(bulletWx, bulletWy, meleeBullet.HitboxSize.X, meleeBullet.HitboxSize.Y, 0, spaceOffsetX, spaceOffsetY, "MeleeBullet")
newBulletCollider := GenerateRectCollider(bulletWx, bulletWy, meleeBullet.HitboxSize.X, meleeBullet.HitboxSize.Y, topPadding, bottomPadding, leftPadding, rightPadding, spaceOffsetX, spaceOffsetY, "MeleeBullet")
space.Add(newBulletCollider)
bulletShape := newBulletCollider.Shape.(*resolv.ConvexPolygon)
Logger.Warn(fmt.Sprintf("bullet ->: Added bullet collider to space: a=%v", ConvexPolygonStr(bulletShape)))
@@ -137,13 +137,13 @@ func NewWorldColliderDisplay(game *Game, stageDiscreteW, stageDiscreteH, stageTi
}
}
bulletRightToLeft := true
bulletRightToLeft := false
if bulletRightToLeft {
xfac := float64(-1.0)
offenderWx, offenderWy := playerPosList.Eles[1].X, playerPosList.Eles[1].Y
bulletWx, bulletWy := offenderWx+xfac*meleeBullet.HitboxOffset, offenderWy
newBulletCollider := GenerateRectCollider(bulletWx, bulletWy, meleeBullet.HitboxSize.X, meleeBullet.HitboxSize.Y, 0, spaceOffsetX, spaceOffsetY, "MeleeBullet")
newBulletCollider := GenerateRectCollider(bulletWx, bulletWy, meleeBullet.HitboxSize.X, meleeBullet.HitboxSize.Y, topPadding, bottomPadding, leftPadding, rightPadding, spaceOffsetX, spaceOffsetY, "MeleeBullet")
space.Add(newBulletCollider)
bulletShape := newBulletCollider.Shape.(*resolv.ConvexPolygon)
Logger.Warn(fmt.Sprintf("bullet <-: Added bullet collider to space: a=%v", ConvexPolygonStr(bulletShape)))

View File

@@ -18,9 +18,13 @@ func ConvexPolygonStr(body *resolv.ConvexPolygon) string {
return fmt.Sprintf("{\n%s\n}", strings.Join(s, ",\n"))
}
func GenerateRectCollider(wx, wy, w, h, bottomPadding, spaceOffsetX, spaceOffsetY float64, tag string) *resolv.Object {
blX, blY := WorldToPolygonColliderBLPos(wx, wy, w*0.5, h*0.5, bottomPadding, spaceOffsetX, spaceOffsetY)
return generateRectColliderInCollisionSpace(blX, blY, w, h+bottomPadding, tag)
func RectCenterStr(body *resolv.Object, halfBoundingW, halfBoundingH, topPadding, bottomPadding, leftPadding, rightPadding, spaceOffsetX, spaceOffsetY float64) string {
return fmt.Sprintf("{%.2f, %.2f}", body.X+leftPadding+halfBoundingW-spaceOffsetX, body.Y+bottomPadding+halfBoundingH-spaceOffsetY)
}
func GenerateRectCollider(wx, wy, w, h, topPadding, bottomPadding, leftPadding, rightPadding, spaceOffsetX, spaceOffsetY float64, tag string) *resolv.Object {
blX, blY := WorldToPolygonColliderBLPos(wx, wy, w*0.5, h*0.5, topPadding, bottomPadding, leftPadding, rightPadding, spaceOffsetX, spaceOffsetY)
return generateRectColliderInCollisionSpace(blX, blY, leftPadding+w+rightPadding, bottomPadding+h+topPadding, tag)
}
func generateRectColliderInCollisionSpace(blX, blY, w, h float64, tag string) *resolv.Object {
@@ -246,38 +250,20 @@ func VirtualGridToWorldPos(vx, vy int32, virtualGridToWorldRatio float64) (float
return wx, wy
}
func WorldToPolygonColliderBLPos(wx, wy, halfBoundingW, halfBoundingH, bottomPadding, collisionSpaceOffsetX, collisionSpaceOffsetY float64) (float64, float64) {
return wx - halfBoundingW + collisionSpaceOffsetX, wy - halfBoundingH - bottomPadding + collisionSpaceOffsetY
func WorldToPolygonColliderBLPos(wx, wy, halfBoundingW, halfBoundingH, topPadding, bottomPadding, leftPadding, rightPadding, collisionSpaceOffsetX, collisionSpaceOffsetY float64) (float64, float64) {
return wx - halfBoundingW - leftPadding + collisionSpaceOffsetX, wy - halfBoundingH - bottomPadding + collisionSpaceOffsetY
}
func WorldToPolygonColliderTLPos(wx, wy, halfBoundingW, halfBoundingH, collisionSpaceOffsetX, collisionSpaceOffsetY float64) (float64, float64) {
return wx - halfBoundingW + collisionSpaceOffsetX, wy + halfBoundingH + collisionSpaceOffsetY
func PolygonColliderBLToWorldPos(cx, cy, halfBoundingW, halfBoundingH, topPadding, bottomPadding, leftPadding, rightPadding, collisionSpaceOffsetX, collisionSpaceOffsetY float64) (float64, float64) {
return cx + halfBoundingW + leftPadding - collisionSpaceOffsetX, cy + halfBoundingH + bottomPadding - collisionSpaceOffsetY
}
func PolygonColliderBLToWorldPos(cx, cy, halfBoundingW, halfBoundingH, bottomPadding, collisionSpaceOffsetX, collisionSpaceOffsetY float64) (float64, float64) {
return cx + halfBoundingW - collisionSpaceOffsetX, cy + halfBoundingH + bottomPadding - collisionSpaceOffsetY
}
func PolygonColliderTLToWorldPos(cx, cy, halfBoundingW, halfBoundingH, collisionSpaceOffsetX, collisionSpaceOffsetY float64) (float64, float64) {
return cx + halfBoundingW - collisionSpaceOffsetX, cy - halfBoundingH - collisionSpaceOffsetY
}
func PolygonColliderBLToVirtualGridPos(cx, cy, halfBoundingW, halfBoundingH, bottomPadding, collisionSpaceOffsetX, collisionSpaceOffsetY float64, worldToVirtualGridRatio float64) (int32, int32) {
wx, wy := PolygonColliderBLToWorldPos(cx, cy, halfBoundingW, halfBoundingH, bottomPadding, collisionSpaceOffsetX, collisionSpaceOffsetY)
func PolygonColliderBLToVirtualGridPos(cx, cy, halfBoundingW, halfBoundingH, topPadding, bottomPadding, leftPadding, rightPadding, collisionSpaceOffsetX, collisionSpaceOffsetY float64, worldToVirtualGridRatio float64) (int32, int32) {
wx, wy := PolygonColliderBLToWorldPos(cx, cy, halfBoundingW, halfBoundingH, topPadding, bottomPadding, leftPadding, rightPadding, collisionSpaceOffsetX, collisionSpaceOffsetY)
return WorldToVirtualGridPos(wx, wy, worldToVirtualGridRatio)
}
func PolygonColliderTLToVirtualGridPos(cx, cy, halfBoundingW, halfBoundingH, collisionSpaceOffsetX, collisionSpaceOffsetY float64, worldToVirtualGridRatio float64) (int32, int32) {
wx, wy := PolygonColliderTLToWorldPos(cx, cy, halfBoundingW, halfBoundingH, collisionSpaceOffsetX, collisionSpaceOffsetY)
return WorldToVirtualGridPos(wx, wy, worldToVirtualGridRatio)
}
func VirtualGridToPolygonColliderBLPos(vx, vy int32, halfBoundingW, halfBoundingH, bottomPadding, collisionSpaceOffsetX, collisionSpaceOffsetY float64, virtualGridToWorldRatio float64) (float64, float64) {
func VirtualGridToPolygonColliderBLPos(vx, vy int32, halfBoundingW, halfBoundingH, topPadding, bottomPadding, leftPadding, rightPadding, collisionSpaceOffsetX, collisionSpaceOffsetY float64, virtualGridToWorldRatio float64) (float64, float64) {
wx, wy := VirtualGridToWorldPos(vx, vy, virtualGridToWorldRatio)
return WorldToPolygonColliderBLPos(wx, wy, halfBoundingW, halfBoundingH, bottomPadding, collisionSpaceOffsetX, collisionSpaceOffsetY)
}
func VirtualGridToPolygonColliderTLPos(vx, vy int32, halfBoundingW, halfBoundingH, collisionSpaceOffsetX, collisionSpaceOffsetY float64, virtualGridToWorldRatio float64) (float64, float64) {
wx, wy := VirtualGridToWorldPos(vx, vy, virtualGridToWorldRatio)
return WorldToPolygonColliderTLPos(wx, wy, halfBoundingW, halfBoundingH, collisionSpaceOffsetX, collisionSpaceOffsetY)
return WorldToPolygonColliderBLPos(wx, wy, halfBoundingW, halfBoundingH, topPadding, bottomPadding, leftPadding, rightPadding, collisionSpaceOffsetX, collisionSpaceOffsetY)
}

View File

@@ -1,229 +0,0 @@
{
"__type__": "cc.AnimationClip",
"_name": "Atk1",
"_objFlags": 0,
"_native": "",
"_duration": 0.5833333333333334,
"sample": 60,
"speed": 1,
"wrapMode": 1,
"curveData": {
"comps": {
"cc.Sprite": {
"spriteFrame": [
{
"frame": 0,
"value": {
"__uuid__": "7fedc57f-6998-45fc-899d-ea5edd41ab13"
}
},
{
"frame": 0.016666666666666666,
"value": {
"__uuid__": "d55c2f3c-9110-4627-b8b2-0f9395f0d145"
}
},
{
"frame": 0.03333333333333333,
"value": {
"__uuid__": "1228879d-d28e-48e4-a3ce-5ceda0d1831f"
}
},
{
"frame": 0.05,
"value": {
"__uuid__": "e88dd5c4-cc5d-46e0-88de-e382e2bcadd7"
}
},
{
"frame": 0.06666666666666667,
"value": {
"__uuid__": "df069f5c-7fc0-4731-bb7f-9d2032498e4c"
}
},
{
"frame": 0.08333333333333333,
"value": {
"__uuid__": "4815763d-64e1-4b15-b795-38900861c651"
}
},
{
"frame": 0.1,
"value": {
"__uuid__": "0dca4f06-bf25-4e7f-ac3a-1687e284f5d6"
}
},
{
"frame": 0.11666666666666667,
"value": {
"__uuid__": "de8db3c9-affd-45ef-a536-e2d28ebc8094"
}
},
{
"frame": 0.13333333333333333,
"value": {
"__uuid__": "baaafb8b-9c1a-45ea-ba80-eb8048b61b57"
}
},
{
"frame": 0.15,
"value": {
"__uuid__": "9ffa7db6-1aec-4a1e-a8a9-118f2a6e50dc"
}
},
{
"frame": 0.16666666666666666,
"value": {
"__uuid__": "f2f296ad-0e19-4b00-b061-8c9edff98d0d"
}
},
{
"frame": 0.18333333333333332,
"value": {
"__uuid__": "3e546607-d27f-40fa-9967-771c55a12590"
}
},
{
"frame": 0.2,
"value": {
"__uuid__": "fece0129-e8ae-45be-b963-e2b821add0d3"
}
},
{
"frame": 0.21666666666666667,
"value": {
"__uuid__": "f5f48bec-3d2a-49de-9416-26cc75d34e32"
}
},
{
"frame": 0.23333333333333334,
"value": {
"__uuid__": "b083cfc9-a439-4600-b336-b50ca08b68c4"
}
},
{
"frame": 0.25,
"value": {
"__uuid__": "d04003f5-16c1-4510-898b-9148b76eb958"
}
},
{
"frame": 0.26666666666666666,
"value": {
"__uuid__": "2159f038-bffa-480c-a2bd-c305868f2fd9"
}
},
{
"frame": 0.2833333333333333,
"value": {
"__uuid__": "1d3de292-7dd4-4e28-b1d2-23fc38318390"
}
},
{
"frame": 0.3,
"value": {
"__uuid__": "3031ca7c-e1f7-4d14-b29e-5a7102cab245"
}
},
{
"frame": 0.31666666666666665,
"value": {
"__uuid__": "987e9d14-b6fc-46c7-93ed-8914e42bfa8b"
}
},
{
"frame": 0.3333333333333333,
"value": {
"__uuid__": "327db66e-2136-4d52-9727-399d60715a86"
}
},
{
"frame": 0.35,
"value": {
"__uuid__": "82ab2dcd-22e9-490f-96c4-4786018c91d0"
}
},
{
"frame": 0.36666666666666664,
"value": {
"__uuid__": "36812959-85a6-40fb-9a38-1b4d871eba92"
}
},
{
"frame": 0.38333333333333336,
"value": {
"__uuid__": "2941d74c-7b9c-43dc-a5c4-45952220d9a2"
}
},
{
"frame": 0.4,
"value": {
"__uuid__": "4aed2032-25d5-42fd-983a-4473e2985a99"
}
},
{
"frame": 0.4166666666666667,
"value": {
"__uuid__": "3db216c1-3362-4404-8db6-11615bfa6e64"
}
},
{
"frame": 0.43333333333333335,
"value": {
"__uuid__": "2cf0cb17-cbb0-4d64-9c91-83639a363158"
}
},
{
"frame": 0.45,
"value": {
"__uuid__": "9c057e2c-1dc4-4c6c-adb7-85bf691cefb5"
}
},
{
"frame": 0.4666666666666667,
"value": {
"__uuid__": "49c07a7f-2ace-4e2b-ba4c-724aad12ec5c"
}
},
{
"frame": 0.48333333333333334,
"value": {
"__uuid__": "cec3c067-c958-4988-b113-2f10d7f4f5ea"
}
},
{
"frame": 0.5,
"value": {
"__uuid__": "ad57f789-a25a-411c-b130-62a8ab16177f"
}
},
{
"frame": 0.5166666666666667,
"value": {
"__uuid__": "3c2a21a5-7c85-48f3-95ff-0d7a32e5e852"
}
},
{
"frame": 0.5333333333333333,
"value": {
"__uuid__": "fe15eece-07a5-4d15-927b-af980aea7693"
}
},
{
"frame": 0.55,
"value": {
"__uuid__": "30ac103a-0f2b-45db-9442-461479beeb0d"
}
},
{
"frame": 0.5666666666666667,
"value": {
"__uuid__": "76272ec6-0721-4496-941b-5cb6a52b2c35"
}
}
]
}
}
},
"events": []
}

View File

@@ -1,133 +0,0 @@
{
"__type__": "cc.AnimationClip",
"_name": "Atked1",
"_objFlags": 0,
"_native": "",
"_duration": 0.31666666666666665,
"sample": 60,
"speed": 1,
"wrapMode": 1,
"curveData": {
"comps": {
"cc.Sprite": {
"spriteFrame": [
{
"frame": 0,
"value": {
"__uuid__": "6fd7cfcb-95b2-4197-a065-6bc48365f855"
}
},
{
"frame": 0.016666666666666666,
"value": {
"__uuid__": "39aaeff6-3116-4e12-8ec4-9362a8a2fea2"
}
},
{
"frame": 0.03333333333333333,
"value": {
"__uuid__": "fb4e42e6-0fae-48d4-a600-217e01d43e57"
}
},
{
"frame": 0.05,
"value": {
"__uuid__": "2af606d7-4b3d-4355-95d1-a3ab673d2a2e"
}
},
{
"frame": 0.06666666666666667,
"value": {
"__uuid__": "be18e65b-346c-4efb-84cb-7f317fcaf8ac"
}
},
{
"frame": 0.08333333333333333,
"value": {
"__uuid__": "d269af72-8b89-420c-ba9e-6892cda06e80"
}
},
{
"frame": 0.1,
"value": {
"__uuid__": "30539c9d-6dbb-4409-8562-6c24b12010c2"
}
},
{
"frame": 0.11666666666666667,
"value": {
"__uuid__": "96b655f9-9a90-4cb1-86ab-0be881ad8983"
}
},
{
"frame": 0.13333333333333333,
"value": {
"__uuid__": "a86f8107-3d8d-426e-9a17-c856c1ab292a"
}
},
{
"frame": 0.15,
"value": {
"__uuid__": "d7f99f14-9257-426a-9e90-a948e7ca8d23"
}
},
{
"frame": 0.16666666666666666,
"value": {
"__uuid__": "809dcbcf-9edd-4b8b-8bc8-42394ce0a9c2"
}
},
{
"frame": 0.18333333333333332,
"value": {
"__uuid__": "f3e74927-2eea-4306-ba0a-c89972ca88f1"
}
},
{
"frame": 0.2,
"value": {
"__uuid__": "af7a23f6-9b5c-4fe8-aa74-741f18500866"
}
},
{
"frame": 0.21666666666666667,
"value": {
"__uuid__": "4cc6ecdb-3741-4a2e-87a0-a93739a38d37"
}
},
{
"frame": 0.23333333333333334,
"value": {
"__uuid__": "f809b6d3-6f5b-4cf4-b148-5cf7fdf407a5"
}
},
{
"frame": 0.25,
"value": {
"__uuid__": "b1c9e526-fe26-42a8-9257-7e5549847273"
}
},
{
"frame": 0.26666666666666666,
"value": {
"__uuid__": "db62c862-7553-4f99-b758-8c4a4aec438a"
}
},
{
"frame": 0.2833333333333333,
"value": {
"__uuid__": "55f68905-bff7-48ea-b497-5077f49b2aca"
}
},
{
"frame": 0.3,
"value": {
"__uuid__": "b01f45f9-c394-4706-aae1-d1d26a84f48a"
}
}
]
}
}
},
"events": []
}

View File

@@ -1,432 +0,0 @@
{
"__type__": "cc.AnimationClip",
"_name": "Idle1",
"_objFlags": 0,
"_native": "",
"_duration": 1.1166666666666667,
"sample": 60,
"speed": 1,
"wrapMode": 2,
"curveData": {
"comps": {
"cc.Sprite": {
"spriteFrame": [
{
"frame": 0,
"value": {
"__uuid__": "91bba749-7338-4bdc-b9a2-0450a183378f"
}
},
{
"frame": 0.016666666666666666,
"value": {
"__uuid__": "31b10e1f-7433-4c0d-b9a7-576adc0cdb51"
}
},
{
"frame": 0.03333333333333333,
"value": {
"__uuid__": "80d4afc7-d21a-4eec-ab5e-ec833e1e905b"
}
},
{
"frame": 0.05,
"value": {
"__uuid__": "d75070b5-3dbe-4d77-886e-8851f31e8ac8"
}
},
{
"frame": 0.06666666666666667,
"value": {
"__uuid__": "a30e880e-1ff1-434d-bdbc-a3a2e0de671b"
}
},
{
"frame": 0.08333333333333333,
"value": {
"__uuid__": "87cec524-adf7-48a6-af37-b1bae14b9317"
}
},
{
"frame": 0.1,
"value": {
"__uuid__": "d415a590-b4bf-4590-834a-b075705e063a"
}
},
{
"frame": 0.11666666666666667,
"value": {
"__uuid__": "e8b7eb99-0b52-4f01-8dd3-6c1ff23a8552"
}
},
{
"frame": 0.13333333333333333,
"value": {
"__uuid__": "599c03fd-c5f1-45b1-9cd8-0164f8e82fe0"
}
},
{
"frame": 0.15,
"value": {
"__uuid__": "0f71de95-9947-40da-929f-dd25bf43884e"
}
},
{
"frame": 0.16666666666666666,
"value": {
"__uuid__": "99980a57-3af2-4c23-84b8-87759ee79e10"
}
},
{
"frame": 0.18333333333333332,
"value": {
"__uuid__": "ab001dd3-587c-4a23-adbc-5f0d3eedccaf"
}
},
{
"frame": 0.2,
"value": {
"__uuid__": "9869ec96-1c78-482e-bff8-95d0b064d0f6"
}
},
{
"frame": 0.21666666666666667,
"value": {
"__uuid__": "0863d34e-0116-4134-b17e-32dae8f1589f"
}
},
{
"frame": 0.23333333333333334,
"value": {
"__uuid__": "10454569-56bb-4721-9a94-49015f5e11cc"
}
},
{
"frame": 0.25,
"value": {
"__uuid__": "b13c9ee9-a497-43b3-9b54-83250bc62cc6"
}
},
{
"frame": 0.26666666666666666,
"value": {
"__uuid__": "80e898d9-10a9-4817-988c-7571744173e7"
}
},
{
"frame": 0.2833333333333333,
"value": {
"__uuid__": "0e4e927d-0c67-43a1-aade-a6b5ea3fe498"
}
},
{
"frame": 0.3,
"value": {
"__uuid__": "6c327da9-60a2-4b63-89ca-05e7bb9b8c5f"
}
},
{
"frame": 0.31666666666666665,
"value": {
"__uuid__": "9e71217f-0580-481e-b2ea-8886eb7cf492"
}
},
{
"frame": 0.3333333333333333,
"value": {
"__uuid__": "ed851c4e-6a42-4643-8d50-1bac3d55b1ac"
}
},
{
"frame": 0.35,
"value": {
"__uuid__": "3a4738ba-bf3c-47cf-98f7-7e68aba0c96c"
}
},
{
"frame": 0.36666666666666664,
"value": {
"__uuid__": "d035e717-c8ab-4cdc-b59f-c61c9e85990a"
}
},
{
"frame": 0.38333333333333336,
"value": {
"__uuid__": "4bf6ea06-54bf-4c25-87f7-c7d9dca56fab"
}
},
{
"frame": 0.4,
"value": {
"__uuid__": "a4b324b1-1191-43ee-ac76-a4536d1dbac7"
}
},
{
"frame": 0.4166666666666667,
"value": {
"__uuid__": "4e2ac5fa-1c68-4cbd-80e6-a94af579796d"
}
},
{
"frame": 0.43333333333333335,
"value": {
"__uuid__": "64cd0353-429a-4a47-a6fc-b0f12e565e94"
}
},
{
"frame": 0.45,
"value": {
"__uuid__": "3fa0ae73-f8f8-455f-82c3-24a428379e95"
}
},
{
"frame": 0.4666666666666667,
"value": {
"__uuid__": "a4679596-56d5-44f2-a349-7579ad7fbe33"
}
},
{
"frame": 0.48333333333333334,
"value": {
"__uuid__": "3293d474-dfb3-412a-aca1-ce76f70a2181"
}
},
{
"frame": 0.5,
"value": {
"__uuid__": "9794aec3-5e18-4df4-bae2-296f7c5ed935"
}
},
{
"frame": 0.5166666666666667,
"value": {
"__uuid__": "4373d7b7-ea22-4ba2-a6df-c0672d4310a2"
}
},
{
"frame": 0.5333333333333333,
"value": {
"__uuid__": "89b6617e-2131-4bc6-840a-048af7944bb8"
}
},
{
"frame": 0.55,
"value": {
"__uuid__": "9c267a7b-ab24-49b4-a2f3-26d885799f23"
}
},
{
"frame": 0.5666666666666667,
"value": {
"__uuid__": "df3255ea-00af-47c2-9deb-4ccd27a62706"
}
},
{
"frame": 0.5833333333333334,
"value": {
"__uuid__": "e15242c9-29ba-411a-a93f-dddad5613956"
}
},
{
"frame": 0.6,
"value": {
"__uuid__": "ef3f8029-d5cc-4024-95ca-1f2aa062a0d5"
}
},
{
"frame": 0.6166666666666667,
"value": {
"__uuid__": "7b48f205-a1e8-4233-8c72-11ae9c0ccea7"
}
},
{
"frame": 0.6333333333333333,
"value": {
"__uuid__": "ffc69bce-fd84-42d8-b8c9-fe05e6c7fa03"
}
},
{
"frame": 0.65,
"value": {
"__uuid__": "81805795-ab34-47c1-ab45-57f54d28e72f"
}
},
{
"frame": 0.6666666666666666,
"value": {
"__uuid__": "adae26a6-7991-4583-966c-4364ba35474d"
}
},
{
"frame": 0.6833333333333333,
"value": {
"__uuid__": "ab51a779-10b7-4039-ac45-6ada002e702f"
}
},
{
"frame": 0.7,
"value": {
"__uuid__": "173d4746-0af5-40ae-a472-ba6406c700dc"
}
},
{
"frame": 0.7166666666666667,
"value": {
"__uuid__": "4054d644-4b5c-473d-ad2c-1c1eb06b01d7"
}
},
{
"frame": 0.7333333333333333,
"value": {
"__uuid__": "0f55009f-71dc-4e70-8152-7dbc2a16a17c"
}
},
{
"frame": 0.75,
"value": {
"__uuid__": "d273f52f-4ec1-4ccf-8820-92879682213e"
}
},
{
"frame": 0.7666666666666667,
"value": {
"__uuid__": "37c2f336-a3c8-4b46-8031-d48c3f36c675"
}
},
{
"frame": 0.7833333333333333,
"value": {
"__uuid__": "8cee57cb-5e79-4fe9-8368-745b38a37021"
}
},
{
"frame": 0.8,
"value": {
"__uuid__": "4e67aa7d-d6a6-405b-99c4-ef5be609fdf4"
}
},
{
"frame": 0.8166666666666667,
"value": {
"__uuid__": "b0b7fc1a-f42a-4977-bfef-93841bdfa2f8"
}
},
{
"frame": 0.8333333333333334,
"value": {
"__uuid__": "352bbb78-d87c-425d-b39e-a401432f0070"
}
},
{
"frame": 0.85,
"value": {
"__uuid__": "9aaadf6a-808f-44f4-b7a8-392138851168"
}
},
{
"frame": 0.8666666666666667,
"value": {
"__uuid__": "a319abd0-a689-400c-8f2a-94ccc70e50f9"
}
},
{
"frame": 0.8833333333333333,
"value": {
"__uuid__": "2efd4c0f-10c1-41be-81b5-40b3d10cb863"
}
},
{
"frame": 0.9,
"value": {
"__uuid__": "8b94f28d-7da8-4e83-a9d6-46072b24a847"
}
},
{
"frame": 0.9166666666666666,
"value": {
"__uuid__": "1f153a21-9a57-4bf7-a7bb-fa2a2e3b9484"
}
},
{
"frame": 0.9333333333333333,
"value": {
"__uuid__": "2d3ad677-51b8-4d53-924c-dea3f66f0510"
}
},
{
"frame": 0.95,
"value": {
"__uuid__": "68aabf9d-5b21-4405-b92d-18a837895c37"
}
},
{
"frame": 0.9666666666666667,
"value": {
"__uuid__": "cb893520-96b5-4ce4-a9dd-90ca4eac1882"
}
},
{
"frame": 0.9833333333333333,
"value": {
"__uuid__": "498ee98f-7211-4495-99fe-662aee098217"
}
},
{
"frame": 1,
"value": {
"__uuid__": "da05be2e-e07f-4081-a99d-9c1b1459b862"
}
},
{
"frame": 1.0166666666666666,
"value": {
"__uuid__": "46e64686-1071-4db2-8f3d-4a0a00dc8e10"
}
},
{
"frame": 1.0333333333333334,
"value": {
"__uuid__": "5a082e4d-d615-411f-880e-b03bda363cea"
}
},
{
"frame": 1.05,
"value": {
"__uuid__": "6d582b00-b973-4397-8866-32f531d4366e"
}
},
{
"frame": 1.0666666666666667,
"value": {
"__uuid__": "1de67f2c-e9ea-438d-8f30-b7c40159bc92"
}
},
{
"frame": 1.0833333333333333,
"value": {
"__uuid__": "6e98330a-9709-44e1-8704-aa6430bd8236"
}
},
{
"frame": 1.1,
"value": {
"__uuid__": "b2557433-9168-4b78-a9ac-78b33633b1d8"
}
}
]
}
}
},
"events": [
{
"frame": 0,
"func": "",
"params": []
},
{
"frame": 0,
"func": "",
"params": []
}
]
}

View File

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

View File

@@ -1,385 +0,0 @@
{
"__type__": "cc.AnimationClip",
"_name": "Walking",
"_objFlags": 0,
"_native": "",
"_duration": 1.0166666666666666,
"sample": 60,
"speed": 1,
"wrapMode": 2,
"curveData": {
"comps": {
"cc.Sprite": {
"spriteFrame": [
{
"frame": 0,
"value": {
"__uuid__": "5a9af6ac-cccc-4964-90a1-7136468d64ae"
}
},
{
"frame": 0.016666666666666666,
"value": {
"__uuid__": "e62f3718-263c-4a93-8405-55aca440180f"
}
},
{
"frame": 0.03333333333333333,
"value": {
"__uuid__": "700a3fef-00d2-437a-a323-cc79802d76f5"
}
},
{
"frame": 0.05,
"value": {
"__uuid__": "bf8ce5ef-5171-45ab-97dd-8c9da2dbcd5a"
}
},
{
"frame": 0.06666666666666667,
"value": {
"__uuid__": "0894f61a-e4a0-458d-890e-aa3d60e4bf4f"
}
},
{
"frame": 0.08333333333333333,
"value": {
"__uuid__": "1995a986-6421-427c-92fe-4e3bae551e67"
}
},
{
"frame": 0.1,
"value": {
"__uuid__": "4ca1ce37-410d-4437-8b7a-498292e74bc6"
}
},
{
"frame": 0.11666666666666667,
"value": {
"__uuid__": "1e23a398-6051-4a69-a71d-7ea4909da77e"
}
},
{
"frame": 0.13333333333333333,
"value": {
"__uuid__": "ef18849a-0d4d-4bfe-a707-073958511ca6"
}
},
{
"frame": 0.15,
"value": {
"__uuid__": "f217d368-9fc9-48cd-b635-059a7bc472a4"
}
},
{
"frame": 0.16666666666666666,
"value": {
"__uuid__": "b312cebf-3945-40c7-a367-3bc1d6689109"
}
},
{
"frame": 0.18333333333333332,
"value": {
"__uuid__": "476ddde6-8fd9-40cc-a789-0a08ebff5352"
}
},
{
"frame": 0.2,
"value": {
"__uuid__": "b27f06dc-217d-4b68-a747-4c1d3c27151f"
}
},
{
"frame": 0.21666666666666667,
"value": {
"__uuid__": "83d15d82-f23d-40c4-b4ef-da4ce6964fc9"
}
},
{
"frame": 0.23333333333333334,
"value": {
"__uuid__": "7cc81715-c432-4ee2-bf67-a77a4dadcd89"
}
},
{
"frame": 0.25,
"value": {
"__uuid__": "463ae409-a045-40d1-ac44-1f2aac439065"
}
},
{
"frame": 0.26666666666666666,
"value": {
"__uuid__": "84e68a5e-f23b-4570-ac4f-d85f1eba292c"
}
},
{
"frame": 0.2833333333333333,
"value": {
"__uuid__": "ce73c3ce-b543-4f9b-892c-27b76a9c84dc"
}
},
{
"frame": 0.3,
"value": {
"__uuid__": "25280250-fab5-464c-b26e-1a5f1733aa09"
}
},
{
"frame": 0.31666666666666665,
"value": {
"__uuid__": "abf595ad-a861-482c-8f5a-43f243516a5b"
}
},
{
"frame": 0.3333333333333333,
"value": {
"__uuid__": "238ce540-4c4a-41c0-967c-32218e3dfd3c"
}
},
{
"frame": 0.35,
"value": {
"__uuid__": "0a3f1bbf-788b-4d78-b737-2ec5364fe5a4"
}
},
{
"frame": 0.36666666666666664,
"value": {
"__uuid__": "c6397500-a2d9-4d68-b874-299bbc4a2173"
}
},
{
"frame": 0.38333333333333336,
"value": {
"__uuid__": "914aeb36-e7ab-4676-8016-8cf3a4fef6c6"
}
},
{
"frame": 0.4,
"value": {
"__uuid__": "1c7a050e-c52b-4402-911d-bc2d9ffed627"
}
},
{
"frame": 0.4166666666666667,
"value": {
"__uuid__": "74eaaf1d-5de5-411d-86d4-839022712426"
}
},
{
"frame": 0.43333333333333335,
"value": {
"__uuid__": "b42fe407-2c81-4960-a697-0125815e1bc7"
}
},
{
"frame": 0.45,
"value": {
"__uuid__": "9395f625-e627-4a0a-85cb-05f9b3a99d48"
}
},
{
"frame": 0.4666666666666667,
"value": {
"__uuid__": "5805ad62-293f-4d81-ad59-ac290ba2e2d3"
}
},
{
"frame": 0.48333333333333334,
"value": {
"__uuid__": "9c79bea6-dc45-4113-ace8-c7145cc889db"
}
},
{
"frame": 0.5,
"value": {
"__uuid__": "cabc4d77-a49d-4c43-9144-01c5283fe206"
}
},
{
"frame": 0.5166666666666667,
"value": {
"__uuid__": "0514d19b-a3ad-478d-99da-fa91190148b7"
}
},
{
"frame": 0.5333333333333333,
"value": {
"__uuid__": "57646810-7598-4723-b12f-5e15e8299aaa"
}
},
{
"frame": 0.55,
"value": {
"__uuid__": "65e5cbd3-15f3-4526-a347-db55ac24bf51"
}
},
{
"frame": 0.5666666666666667,
"value": {
"__uuid__": "1555d6f4-1bdf-4b64-99b2-bb13195257f4"
}
},
{
"frame": 0.5833333333333334,
"value": {
"__uuid__": "843e335d-fdb6-4a23-9949-3c81d977fb21"
}
},
{
"frame": 0.6,
"value": {
"__uuid__": "781f66e7-dd7f-4ff5-a38e-9423762b4b52"
}
},
{
"frame": 0.6166666666666667,
"value": {
"__uuid__": "ef990cae-899c-451f-91fd-7a42ac949534"
}
},
{
"frame": 0.6333333333333333,
"value": {
"__uuid__": "a2df488a-e91b-46b0-8c25-2ba8551ab539"
}
},
{
"frame": 0.65,
"value": {
"__uuid__": "6650a6e0-6ddd-42ec-af68-1a1a032e19b5"
}
},
{
"frame": 0.6666666666666666,
"value": {
"__uuid__": "9a54c669-7f7d-41e4-8939-1853967d0dbf"
}
},
{
"frame": 0.6833333333333333,
"value": {
"__uuid__": "da04432e-3845-465b-9ddf-ce2bd7c7174e"
}
},
{
"frame": 0.7,
"value": {
"__uuid__": "aa7a792d-22dc-4d28-8d27-52ddfcd8d147"
}
},
{
"frame": 0.7166666666666667,
"value": {
"__uuid__": "ceb00ecc-d391-4b19-b9d6-e53792590c46"
}
},
{
"frame": 0.7333333333333333,
"value": {
"__uuid__": "33b3fa05-9894-4393-b9ce-f819c5818bf3"
}
},
{
"frame": 0.75,
"value": {
"__uuid__": "972cc5ec-ca1c-4127-8e21-f339df92a4fd"
}
},
{
"frame": 0.7666666666666667,
"value": {
"__uuid__": "3874c9de-2b47-4327-b4f8-c61d3896cefe"
}
},
{
"frame": 0.7833333333333333,
"value": {
"__uuid__": "4a6f08e6-7f96-4451-8f71-7bee8cd63cf2"
}
},
{
"frame": 0.8,
"value": {
"__uuid__": "256f3d2b-4cb9-4523-bf7a-c48380e249bb"
}
},
{
"frame": 0.8166666666666667,
"value": {
"__uuid__": "4c40c070-9cba-44f9-acd6-2408f569f21c"
}
},
{
"frame": 0.8333333333333334,
"value": {
"__uuid__": "454bfff4-b8a1-4f90-b708-bbf295b99498"
}
},
{
"frame": 0.85,
"value": {
"__uuid__": "f0288374-f487-4870-b921-8baf851bb865"
}
},
{
"frame": 0.8666666666666667,
"value": {
"__uuid__": "2fd06c6a-c3de-4b7f-bef7-1cba61c9909c"
}
},
{
"frame": 0.8833333333333333,
"value": {
"__uuid__": "d4d08680-1b77-4b44-92bd-be27c03747fa"
}
},
{
"frame": 0.9,
"value": {
"__uuid__": "5a85b0ce-7a4e-4d84-b4fb-089cdff45265"
}
},
{
"frame": 0.9166666666666666,
"value": {
"__uuid__": "ac515982-6ac2-462c-b186-c4468b489e39"
}
},
{
"frame": 0.9333333333333333,
"value": {
"__uuid__": "92571718-c75c-4c09-9aac-b1b043bb70a7"
}
},
{
"frame": 0.95,
"value": {
"__uuid__": "a248383c-2cf6-487e-8941-a05f6c08bc60"
}
},
{
"frame": 0.9666666666666667,
"value": {
"__uuid__": "c4f035dc-a01e-4b8e-a1b7-f4faf9515e99"
}
},
{
"frame": 0.9833333333333333,
"value": {
"__uuid__": "a6f9c9b4-1129-4b6a-b4c3-2a3d425c746a"
}
},
{
"frame": 1,
"value": {
"__uuid__": "d99d68fa-73c7-4057-98ec-9aa45864c050"
}
}
]
}
}
},
"events": []
}

View File

@@ -0,0 +1,7 @@
{
"ver": "1.0.1",
"uuid": "d7459b4f-ba3f-4ead-9e0d-ec2387c9ee1f",
"isSubpackage": false,
"subpackageName": "",
"subMetas": {}
}

View File

@@ -0,0 +1,43 @@
{
"__type__": "cc.AnimationClip",
"_name": "Atk1",
"_objFlags": 0,
"_native": "",
"_duration": 0.36666666666666664,
"sample": 60,
"speed": 1,
"wrapMode": 1,
"curveData": {
"comps": {
"cc.Sprite": {
"spriteFrame": [
{
"frame": 0,
"value": {
"__uuid__": "a5607dff-7c39-47bc-8f27-86586f219387"
}
},
{
"frame": 0.11666666666666667,
"value": {
"__uuid__": "bbcfe7c4-2341-4d58-b758-17920dbc4e0e"
}
},
{
"frame": 0.2833333333333333,
"value": {
"__uuid__": "93e45cd6-652b-4732-8139-587170884ae4"
}
},
{
"frame": 0.35,
"value": {
"__uuid__": "2c65c72d-34c0-424c-9a7e-2d961a68a1b6"
}
}
]
}
}
},
"events": []
}

View File

@@ -0,0 +1,25 @@
{
"__type__": "cc.AnimationClip",
"_name": "Atked1",
"_objFlags": 0,
"_native": "",
"_duration": 0.016666666666666666,
"sample": 60,
"speed": 1,
"wrapMode": 1,
"curveData": {
"comps": {
"cc.Sprite": {
"spriteFrame": [
{
"frame": 0,
"value": {
"__uuid__": "26166514-7b99-4e18-a3ef-515718a7597f"
}
}
]
}
}
},
"events": []
}

View File

@@ -0,0 +1,54 @@
{
"__type__": "cc.AnimationClip",
"_name": "Idle1",
"_objFlags": 0,
"_native": "",
"_duration": 0.11666666666666667,
"sample": 60,
"speed": 0.3,
"wrapMode": 2,
"curveData": {
"comps": {
"cc.Sprite": {
"spriteFrame": [
{
"frame": 0,
"value": {
"__uuid__": "3437907b-f662-4805-9723-78839fd930f5"
}
},
{
"frame": 0.03333333333333333,
"value": {
"__uuid__": "86de4c9c-202c-417b-abdb-7f5d4ae87045"
}
},
{
"frame": 0.06666666666666667,
"value": {
"__uuid__": "2e8dd9ad-e227-405f-a22a-33079051e709"
}
},
{
"frame": 0.1,
"value": {
"__uuid__": "03d976f3-4abb-40e9-85b9-ff532009b7ea"
}
}
]
}
}
},
"events": [
{
"frame": 0,
"func": "",
"params": []
},
{
"frame": 0,
"func": "",
"params": []
}
]
}

View File

@@ -0,0 +1,37 @@
{
"__type__": "cc.AnimationClip",
"_name": "InAirAtk1",
"_objFlags": 0,
"_native": "",
"_duration": 0.35,
"sample": 60,
"speed": 1,
"wrapMode": 1,
"curveData": {
"comps": {
"cc.Sprite": {
"spriteFrame": [
{
"frame": 0.016666666666666666,
"value": {
"__uuid__": "58e0a91a-e6ce-482d-8668-713867301837"
}
},
{
"frame": 0.2,
"value": {
"__uuid__": "aca5205f-5749-42fa-be3b-4f4888faf766"
}
},
{
"frame": 0.3333333333333333,
"value": {
"__uuid__": "d0f43a74-3f79-42b6-9d1e-a6c17c0cd07f"
}
}
]
}
}
},
"events": []
}

View File

@@ -0,0 +1,5 @@
{
"ver": "2.1.0",
"uuid": "8710591c-3f5e-4911-83e7-42cc18be6af9",
"subMetas": {}
}

View File

@@ -0,0 +1,25 @@
{
"__type__": "cc.AnimationClip",
"_name": "InAirIdle1",
"_objFlags": 0,
"_native": "",
"_duration": 0.016666666666666666,
"sample": 60,
"speed": 0.1,
"wrapMode": 2,
"curveData": {
"comps": {
"cc.Sprite": {
"spriteFrame": [
{
"frame": 0,
"value": {
"__uuid__": "ca385337-356e-49eb-8081-36b1505411a2"
}
}
]
}
}
},
"events": []
}

View File

@@ -0,0 +1,551 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>frames</key>
<dict>
<key>Atk1_1.png</key>
<dict>
<key>aliases</key>
<array/>
<key>spriteOffset</key>
<string>{0,0}</string>
<key>spriteSize</key>
<string>{74,85}</string>
<key>spriteSourceSize</key>
<string>{74,85}</string>
<key>textureRect</key>
<string>{{176,366},{74,85}}</string>
<key>textureRotated</key>
<false/>
</dict>
<key>Atk1_2.png</key>
<dict>
<key>aliases</key>
<array/>
<key>spriteOffset</key>
<string>{0,0}</string>
<key>spriteSize</key>
<string>{74,85}</string>
<key>spriteSourceSize</key>
<string>{74,85}</string>
<key>textureRect</key>
<string>{{0,375},{74,85}}</string>
<key>textureRotated</key>
<true/>
</dict>
<key>Atk1_3.png</key>
<dict>
<key>aliases</key>
<array/>
<key>spriteOffset</key>
<string>{0,0}</string>
<key>spriteSize</key>
<string>{74,85}</string>
<key>spriteSourceSize</key>
<string>{74,85}</string>
<key>textureRect</key>
<string>{{85,388},{74,85}}</string>
<key>textureRotated</key>
<true/>
</dict>
<key>Atk1_4.png</key>
<dict>
<key>aliases</key>
<array/>
<key>spriteOffset</key>
<string>{0,0}</string>
<key>spriteSize</key>
<string>{74,85}</string>
<key>spriteSourceSize</key>
<string>{74,85}</string>
<key>textureRect</key>
<string>{{0,449},{74,85}}</string>
<key>textureRotated</key>
<true/>
</dict>
<key>Atk1_5.png</key>
<dict>
<key>aliases</key>
<array/>
<key>spriteOffset</key>
<string>{0,0}</string>
<key>spriteSize</key>
<string>{74,85}</string>
<key>spriteSourceSize</key>
<string>{74,85}</string>
<key>textureRect</key>
<string>{{0,375},{74,85}}</string>
<key>textureRotated</key>
<true/>
</dict>
<key>Atk1_6.png</key>
<dict>
<key>aliases</key>
<array/>
<key>spriteOffset</key>
<string>{0,0}</string>
<key>spriteSize</key>
<string>{74,85}</string>
<key>spriteSourceSize</key>
<string>{74,85}</string>
<key>textureRect</key>
<string>{{85,462},{74,85}}</string>
<key>textureRotated</key>
<true/>
</dict>
<key>Atked1_1.png</key>
<dict>
<key>aliases</key>
<array/>
<key>spriteOffset</key>
<string>{0,0}</string>
<key>spriteSize</key>
<string>{47,82}</string>
<key>spriteSourceSize</key>
<string>{47,82}</string>
<key>textureRect</key>
<string>{{170,451},{47,82}}</string>
<key>textureRotated</key>
<true/>
</dict>
<key>Atked1_2.png</key>
<dict>
<key>aliases</key>
<array/>
<key>spriteOffset</key>
<string>{0,0}</string>
<key>spriteSize</key>
<string>{47,82}</string>
<key>spriteSourceSize</key>
<string>{47,82}</string>
<key>textureRect</key>
<string>{{170,498},{47,82}}</string>
<key>textureRotated</key>
<true/>
</dict>
<key>Idle1_1.png</key>
<dict>
<key>aliases</key>
<array/>
<key>spriteOffset</key>
<string>{0,0}</string>
<key>spriteSize</key>
<string>{56,86}</string>
<key>spriteSourceSize</key>
<string>{56,86}</string>
<key>textureRect</key>
<string>{{190,194},{56,86}}</string>
<key>textureRotated</key>
<false/>
</dict>
<key>Idle1_2.png</key>
<dict>
<key>aliases</key>
<array/>
<key>spriteOffset</key>
<string>{0,0}</string>
<key>spriteSize</key>
<string>{56,86}</string>
<key>spriteSourceSize</key>
<string>{56,86}</string>
<key>textureRect</key>
<string>{{185,280},{56,86}}</string>
<key>textureRotated</key>
<false/>
</dict>
<key>Idle1_3.png</key>
<dict>
<key>aliases</key>
<array/>
<key>spriteOffset</key>
<string>{0,0}</string>
<key>spriteSize</key>
<string>{56,86}</string>
<key>spriteSourceSize</key>
<string>{56,86}</string>
<key>textureRect</key>
<string>{{90,332},{56,86}}</string>
<key>textureRotated</key>
<true/>
</dict>
<key>Idle1_4.png</key>
<dict>
<key>aliases</key>
<array/>
<key>spriteOffset</key>
<string>{0,0}</string>
<key>spriteSize</key>
<string>{56,86}</string>
<key>spriteSourceSize</key>
<string>{56,86}</string>
<key>textureRect</key>
<string>{{185,280},{56,86}}</string>
<key>textureRotated</key>
<false/>
</dict>
<key>InAirAtk1_1.png</key>
<dict>
<key>aliases</key>
<array/>
<key>spriteOffset</key>
<string>{0,0}</string>
<key>spriteSize</key>
<string>{63,95}</string>
<key>spriteSourceSize</key>
<string>{63,95}</string>
<key>textureRect</key>
<string>{{104,43},{63,95}}</string>
<key>textureRotated</key>
<true/>
</dict>
<key>InAirAtk1_2.png</key>
<dict>
<key>aliases</key>
<array/>
<key>spriteOffset</key>
<string>{0,0}</string>
<key>spriteSize</key>
<string>{63,95}</string>
<key>spriteSourceSize</key>
<string>{63,95}</string>
<key>textureRect</key>
<string>{{0,86},{63,95}}</string>
<key>textureRotated</key>
<true/>
</dict>
<key>InAirAtk1_3.png</key>
<dict>
<key>aliases</key>
<array/>
<key>spriteOffset</key>
<string>{0,0}</string>
<key>spriteSize</key>
<string>{63,95}</string>
<key>spriteSourceSize</key>
<string>{63,95}</string>
<key>textureRect</key>
<string>{{95,106},{63,95}}</string>
<key>textureRotated</key>
<true/>
</dict>
<key>InAirAtk1_4.png</key>
<dict>
<key>aliases</key>
<array/>
<key>spriteOffset</key>
<string>{0,0}</string>
<key>spriteSize</key>
<string>{63,95}</string>
<key>spriteSourceSize</key>
<string>{63,95}</string>
<key>textureRect</key>
<string>{{0,149},{63,95}}</string>
<key>textureRotated</key>
<true/>
</dict>
<key>InAirAtk1_5.png</key>
<dict>
<key>aliases</key>
<array/>
<key>spriteOffset</key>
<string>{0,0}</string>
<key>spriteSize</key>
<string>{63,95}</string>
<key>spriteSourceSize</key>
<string>{63,95}</string>
<key>textureRect</key>
<string>{{104,43},{63,95}}</string>
<key>textureRotated</key>
<true/>
</dict>
<key>InAirAtk1_6.png</key>
<dict>
<key>aliases</key>
<array/>
<key>spriteOffset</key>
<string>{0,0}</string>
<key>spriteSize</key>
<string>{63,95}</string>
<key>spriteSourceSize</key>
<string>{63,95}</string>
<key>textureRect</key>
<string>{{95,169},{63,95}}</string>
<key>textureRotated</key>
<true/>
</dict>
<key>InAirAtk1_7.png</key>
<dict>
<key>aliases</key>
<array/>
<key>spriteOffset</key>
<string>{0,0}</string>
<key>spriteSize</key>
<string>{63,95}</string>
<key>spriteSourceSize</key>
<string>{63,95}</string>
<key>textureRect</key>
<string>{{0,212},{63,95}}</string>
<key>textureRotated</key>
<true/>
</dict>
<key>InAirAtked1_1.png</key>
<dict>
<key>aliases</key>
<array/>
<key>spriteOffset</key>
<string>{0,0}</string>
<key>spriteSize</key>
<string>{47,82}</string>
<key>spriteSourceSize</key>
<string>{47,82}</string>
<key>textureRect</key>
<string>{{170,451},{47,82}}</string>
<key>textureRotated</key>
<true/>
</dict>
<key>InAirAtked1_2.png</key>
<dict>
<key>aliases</key>
<array/>
<key>spriteOffset</key>
<string>{0,0}</string>
<key>spriteSize</key>
<string>{47,82}</string>
<key>spriteSourceSize</key>
<string>{47,82}</string>
<key>textureRect</key>
<string>{{170,498},{47,82}}</string>
<key>textureRotated</key>
<true/>
</dict>
<key>InAirIdle1_1.png</key>
<dict>
<key>aliases</key>
<array/>
<key>spriteOffset</key>
<string>{0,0}</string>
<key>spriteSize</key>
<string>{43,104}</string>
<key>spriteSourceSize</key>
<string>{43,104}</string>
<key>textureRect</key>
<string>{{0,0},{43,104}}</string>
<key>textureRotated</key>
<true/>
</dict>
<key>InAirIdle1_2.png</key>
<dict>
<key>aliases</key>
<array/>
<key>spriteOffset</key>
<string>{0,0}</string>
<key>spriteSize</key>
<string>{43,104}</string>
<key>spriteSourceSize</key>
<string>{43,104}</string>
<key>textureRect</key>
<string>{{104,0},{43,104}}</string>
<key>textureRotated</key>
<true/>
</dict>
<key>InAirIdle1_3.png</key>
<dict>
<key>aliases</key>
<array/>
<key>spriteOffset</key>
<string>{0,0}</string>
<key>spriteSize</key>
<string>{43,104}</string>
<key>spriteSourceSize</key>
<string>{43,104}</string>
<key>textureRect</key>
<string>{{208,0},{43,104}}</string>
<key>textureRotated</key>
<false/>
</dict>
<key>InAirIdle1_4.png</key>
<dict>
<key>aliases</key>
<array/>
<key>spriteOffset</key>
<string>{0,0}</string>
<key>spriteSize</key>
<string>{43,104}</string>
<key>spriteSourceSize</key>
<string>{43,104}</string>
<key>textureRect</key>
<string>{{104,0},{43,104}}</string>
<key>textureRotated</key>
<true/>
</dict>
<key>InAirIdle1_5.png</key>
<dict>
<key>aliases</key>
<array/>
<key>spriteOffset</key>
<string>{0,0}</string>
<key>spriteSize</key>
<string>{43,104}</string>
<key>spriteSourceSize</key>
<string>{43,104}</string>
<key>textureRect</key>
<string>{{0,0},{43,104}}</string>
<key>textureRotated</key>
<true/>
</dict>
<key>InAirIdle1_6.png</key>
<dict>
<key>aliases</key>
<array/>
<key>spriteOffset</key>
<string>{0,0}</string>
<key>spriteSize</key>
<string>{43,104}</string>
<key>spriteSourceSize</key>
<string>{43,104}</string>
<key>textureRect</key>
<string>{{0,43},{43,104}}</string>
<key>textureRotated</key>
<true/>
</dict>
<key>Walking_1.png</key>
<dict>
<key>aliases</key>
<array/>
<key>spriteOffset</key>
<string>{0,0}</string>
<key>spriteSize</key>
<string>{50,90}</string>
<key>spriteSourceSize</key>
<string>{50,90}</string>
<key>textureRect</key>
<string>{{199,104},{50,90}}</string>
<key>textureRotated</key>
<false/>
</dict>
<key>Walking_2.png</key>
<dict>
<key>aliases</key>
<array/>
<key>spriteOffset</key>
<string>{0,0}</string>
<key>spriteSize</key>
<string>{50,90}</string>
<key>spriteSourceSize</key>
<string>{50,90}</string>
<key>textureRect</key>
<string>{{95,232},{50,90}}</string>
<key>textureRotated</key>
<true/>
</dict>
<key>Walking_3.png</key>
<dict>
<key>aliases</key>
<array/>
<key>spriteOffset</key>
<string>{0,0}</string>
<key>spriteSize</key>
<string>{50,90}</string>
<key>spriteSourceSize</key>
<string>{50,90}</string>
<key>textureRect</key>
<string>{{0,275},{50,90}}</string>
<key>textureRotated</key>
<true/>
</dict>
<key>Walking_4.png</key>
<dict>
<key>aliases</key>
<array/>
<key>spriteOffset</key>
<string>{0,0}</string>
<key>spriteSize</key>
<string>{50,90}</string>
<key>spriteSourceSize</key>
<string>{50,90}</string>
<key>textureRect</key>
<string>{{90,282},{50,90}}</string>
<key>textureRotated</key>
<true/>
</dict>
<key>Walking_5.png</key>
<dict>
<key>aliases</key>
<array/>
<key>spriteOffset</key>
<string>{0,0}</string>
<key>spriteSize</key>
<string>{50,90}</string>
<key>spriteSourceSize</key>
<string>{50,90}</string>
<key>textureRect</key>
<string>{{0,325},{50,90}}</string>
<key>textureRotated</key>
<true/>
</dict>
<key>Walking_6.png</key>
<dict>
<key>aliases</key>
<array/>
<key>spriteOffset</key>
<string>{0,0}</string>
<key>spriteSize</key>
<string>{50,90}</string>
<key>spriteSourceSize</key>
<string>{50,90}</string>
<key>textureRect</key>
<string>{{90,282},{50,90}}</string>
<key>textureRotated</key>
<true/>
</dict>
<key>Walking_7.png</key>
<dict>
<key>aliases</key>
<array/>
<key>spriteOffset</key>
<string>{0,0}</string>
<key>spriteSize</key>
<string>{50,90}</string>
<key>spriteSourceSize</key>
<string>{50,90}</string>
<key>textureRect</key>
<string>{{0,275},{50,90}}</string>
<key>textureRotated</key>
<true/>
</dict>
<key>Walking_8.png</key>
<dict>
<key>aliases</key>
<array/>
<key>spriteOffset</key>
<string>{0,0}</string>
<key>spriteSize</key>
<string>{50,90}</string>
<key>spriteSourceSize</key>
<string>{50,90}</string>
<key>textureRect</key>
<string>{{95,232},{50,90}}</string>
<key>textureRotated</key>
<true/>
</dict>
</dict>
<key>metadata</key>
<dict>
<key>format</key>
<integer>3</integer>
<key>pixelFormat</key>
<string>RGBA8888</string>
<key>premultiplyAlpha</key>
<false/>
<key>realTextureFileName</key>
<string>UltramanTiga.png</string>
<key>size</key>
<string>{252,545}</string>
<key>smartupdate</key>
<string>$TexturePacker:SmartUpdate:4a857ca23ea86a140850bef35b0258da:88d012415ccd7dd313108f39b071523a:1c886ab62fdbd8d1a0c538b1b57b3521$</string>
<key>textureFileName</key>
<string>UltramanTiga.png</string>
</dict>
</dict>
</plist>

View File

@@ -0,0 +1,782 @@
{
"ver": "1.2.4",
"uuid": "5d522f7b-359b-4f38-ac35-55fdbee56cae",
"rawTextureUuid": "b4ea3971-8f28-4cc7-96a4-83f10dce229f",
"size": {
"width": 252,
"height": 545
},
"type": "Texture Packer",
"subMetas": {
"Atk1_1.png": {
"ver": "1.0.4",
"uuid": "8e9ca384-97ec-4e75-a285-6d74d64a3c3c",
"rawTextureUuid": "b4ea3971-8f28-4cc7-96a4-83f10dce229f",
"trimType": "auto",
"trimThreshold": 1,
"rotated": false,
"offsetX": 0,
"offsetY": 0,
"trimX": 176,
"trimY": 366,
"width": 74,
"height": 85,
"rawWidth": 74,
"rawHeight": 85,
"borderTop": 0,
"borderBottom": 0,
"borderLeft": 0,
"borderRight": 0,
"spriteType": "normal",
"subMetas": {}
},
"Atk1_2.png": {
"ver": "1.0.4",
"uuid": "a5607dff-7c39-47bc-8f27-86586f219387",
"rawTextureUuid": "b4ea3971-8f28-4cc7-96a4-83f10dce229f",
"trimType": "auto",
"trimThreshold": 1,
"rotated": true,
"offsetX": 0,
"offsetY": 0,
"trimX": 0,
"trimY": 375,
"width": 74,
"height": 85,
"rawWidth": 74,
"rawHeight": 85,
"borderTop": 0,
"borderBottom": 0,
"borderLeft": 0,
"borderRight": 0,
"spriteType": "normal",
"subMetas": {}
},
"Atk1_3.png": {
"ver": "1.0.4",
"uuid": "bbcfe7c4-2341-4d58-b758-17920dbc4e0e",
"rawTextureUuid": "b4ea3971-8f28-4cc7-96a4-83f10dce229f",
"trimType": "auto",
"trimThreshold": 1,
"rotated": true,
"offsetX": 0,
"offsetY": 0,
"trimX": 85,
"trimY": 388,
"width": 74,
"height": 85,
"rawWidth": 74,
"rawHeight": 85,
"borderTop": 0,
"borderBottom": 0,
"borderLeft": 0,
"borderRight": 0,
"spriteType": "normal",
"subMetas": {}
},
"Atk1_4.png": {
"ver": "1.0.4",
"uuid": "93e45cd6-652b-4732-8139-587170884ae4",
"rawTextureUuid": "b4ea3971-8f28-4cc7-96a4-83f10dce229f",
"trimType": "auto",
"trimThreshold": 1,
"rotated": true,
"offsetX": 0,
"offsetY": 0,
"trimX": 0,
"trimY": 449,
"width": 74,
"height": 85,
"rawWidth": 74,
"rawHeight": 85,
"borderTop": 0,
"borderBottom": 0,
"borderLeft": 0,
"borderRight": 0,
"spriteType": "normal",
"subMetas": {}
},
"Atk1_5.png": {
"ver": "1.0.4",
"uuid": "2c65c72d-34c0-424c-9a7e-2d961a68a1b6",
"rawTextureUuid": "b4ea3971-8f28-4cc7-96a4-83f10dce229f",
"trimType": "auto",
"trimThreshold": 1,
"rotated": true,
"offsetX": 0,
"offsetY": 0,
"trimX": 0,
"trimY": 375,
"width": 74,
"height": 85,
"rawWidth": 74,
"rawHeight": 85,
"borderTop": 0,
"borderBottom": 0,
"borderLeft": 0,
"borderRight": 0,
"spriteType": "normal",
"subMetas": {}
},
"Atk1_6.png": {
"ver": "1.0.4",
"uuid": "d977ee77-cde3-47be-b63d-82a5b116b69a",
"rawTextureUuid": "b4ea3971-8f28-4cc7-96a4-83f10dce229f",
"trimType": "auto",
"trimThreshold": 1,
"rotated": true,
"offsetX": 0,
"offsetY": 0,
"trimX": 85,
"trimY": 462,
"width": 74,
"height": 85,
"rawWidth": 74,
"rawHeight": 85,
"borderTop": 0,
"borderBottom": 0,
"borderLeft": 0,
"borderRight": 0,
"spriteType": "normal",
"subMetas": {}
},
"Atked1_1.png": {
"ver": "1.0.4",
"uuid": "26166514-7b99-4e18-a3ef-515718a7597f",
"rawTextureUuid": "b4ea3971-8f28-4cc7-96a4-83f10dce229f",
"trimType": "auto",
"trimThreshold": 1,
"rotated": true,
"offsetX": 0,
"offsetY": 0,
"trimX": 170,
"trimY": 451,
"width": 47,
"height": 82,
"rawWidth": 47,
"rawHeight": 82,
"borderTop": 0,
"borderBottom": 0,
"borderLeft": 0,
"borderRight": 0,
"spriteType": "normal",
"subMetas": {}
},
"Atked1_2.png": {
"ver": "1.0.4",
"uuid": "98d06843-f140-4d6a-9aa6-0949a1690dca",
"rawTextureUuid": "b4ea3971-8f28-4cc7-96a4-83f10dce229f",
"trimType": "auto",
"trimThreshold": 1,
"rotated": true,
"offsetX": 0,
"offsetY": 0,
"trimX": 170,
"trimY": 498,
"width": 47,
"height": 82,
"rawWidth": 47,
"rawHeight": 82,
"borderTop": 0,
"borderBottom": 0,
"borderLeft": 0,
"borderRight": 0,
"spriteType": "normal",
"subMetas": {}
},
"Idle1_1.png": {
"ver": "1.0.4",
"uuid": "3437907b-f662-4805-9723-78839fd930f5",
"rawTextureUuid": "b4ea3971-8f28-4cc7-96a4-83f10dce229f",
"trimType": "auto",
"trimThreshold": 1,
"rotated": false,
"offsetX": 0,
"offsetY": 0,
"trimX": 190,
"trimY": 194,
"width": 56,
"height": 86,
"rawWidth": 56,
"rawHeight": 86,
"borderTop": 0,
"borderBottom": 0,
"borderLeft": 0,
"borderRight": 0,
"spriteType": "normal",
"subMetas": {}
},
"Idle1_2.png": {
"ver": "1.0.4",
"uuid": "86de4c9c-202c-417b-abdb-7f5d4ae87045",
"rawTextureUuid": "b4ea3971-8f28-4cc7-96a4-83f10dce229f",
"trimType": "auto",
"trimThreshold": 1,
"rotated": false,
"offsetX": 0,
"offsetY": 0,
"trimX": 185,
"trimY": 280,
"width": 56,
"height": 86,
"rawWidth": 56,
"rawHeight": 86,
"borderTop": 0,
"borderBottom": 0,
"borderLeft": 0,
"borderRight": 0,
"spriteType": "normal",
"subMetas": {}
},
"Idle1_3.png": {
"ver": "1.0.4",
"uuid": "2e8dd9ad-e227-405f-a22a-33079051e709",
"rawTextureUuid": "b4ea3971-8f28-4cc7-96a4-83f10dce229f",
"trimType": "auto",
"trimThreshold": 1,
"rotated": true,
"offsetX": 0,
"offsetY": 0,
"trimX": 90,
"trimY": 332,
"width": 56,
"height": 86,
"rawWidth": 56,
"rawHeight": 86,
"borderTop": 0,
"borderBottom": 0,
"borderLeft": 0,
"borderRight": 0,
"spriteType": "normal",
"subMetas": {}
},
"Idle1_4.png": {
"ver": "1.0.4",
"uuid": "03d976f3-4abb-40e9-85b9-ff532009b7ea",
"rawTextureUuid": "b4ea3971-8f28-4cc7-96a4-83f10dce229f",
"trimType": "auto",
"trimThreshold": 1,
"rotated": false,
"offsetX": 0,
"offsetY": 0,
"trimX": 185,
"trimY": 280,
"width": 56,
"height": 86,
"rawWidth": 56,
"rawHeight": 86,
"borderTop": 0,
"borderBottom": 0,
"borderLeft": 0,
"borderRight": 0,
"spriteType": "normal",
"subMetas": {}
},
"InAirAtk1_1.png": {
"ver": "1.0.4",
"uuid": "d0f43a74-3f79-42b6-9d1e-a6c17c0cd07f",
"rawTextureUuid": "b4ea3971-8f28-4cc7-96a4-83f10dce229f",
"trimType": "auto",
"trimThreshold": 1,
"rotated": true,
"offsetX": 0,
"offsetY": 0,
"trimX": 104,
"trimY": 43,
"width": 63,
"height": 95,
"rawWidth": 63,
"rawHeight": 95,
"borderTop": 0,
"borderBottom": 0,
"borderLeft": 0,
"borderRight": 0,
"spriteType": "normal",
"subMetas": {}
},
"InAirAtk1_2.png": {
"ver": "1.0.4",
"uuid": "58e0a91a-e6ce-482d-8668-713867301837",
"rawTextureUuid": "b4ea3971-8f28-4cc7-96a4-83f10dce229f",
"trimType": "auto",
"trimThreshold": 1,
"rotated": true,
"offsetX": 0,
"offsetY": 0,
"trimX": 0,
"trimY": 86,
"width": 63,
"height": 95,
"rawWidth": 63,
"rawHeight": 95,
"borderTop": 0,
"borderBottom": 0,
"borderLeft": 0,
"borderRight": 0,
"spriteType": "normal",
"subMetas": {}
},
"InAirAtk1_3.png": {
"ver": "1.0.4",
"uuid": "aca5205f-5749-42fa-be3b-4f4888faf766",
"rawTextureUuid": "b4ea3971-8f28-4cc7-96a4-83f10dce229f",
"trimType": "auto",
"trimThreshold": 1,
"rotated": true,
"offsetX": 0,
"offsetY": 0,
"trimX": 95,
"trimY": 106,
"width": 63,
"height": 95,
"rawWidth": 63,
"rawHeight": 95,
"borderTop": 0,
"borderBottom": 0,
"borderLeft": 0,
"borderRight": 0,
"spriteType": "normal",
"subMetas": {}
},
"InAirAtk1_4.png": {
"ver": "1.0.4",
"uuid": "4b08f81b-4412-4d98-aa39-11fc140b00a2",
"rawTextureUuid": "b4ea3971-8f28-4cc7-96a4-83f10dce229f",
"trimType": "auto",
"trimThreshold": 1,
"rotated": true,
"offsetX": 0,
"offsetY": 0,
"trimX": 0,
"trimY": 149,
"width": 63,
"height": 95,
"rawWidth": 63,
"rawHeight": 95,
"borderTop": 0,
"borderBottom": 0,
"borderLeft": 0,
"borderRight": 0,
"spriteType": "normal",
"subMetas": {}
},
"InAirAtk1_5.png": {
"ver": "1.0.4",
"uuid": "618142b5-4eb9-4b06-948c-9346381af4b4",
"rawTextureUuid": "b4ea3971-8f28-4cc7-96a4-83f10dce229f",
"trimType": "auto",
"trimThreshold": 1,
"rotated": true,
"offsetX": 0,
"offsetY": 0,
"trimX": 104,
"trimY": 43,
"width": 63,
"height": 95,
"rawWidth": 63,
"rawHeight": 95,
"borderTop": 0,
"borderBottom": 0,
"borderLeft": 0,
"borderRight": 0,
"spriteType": "normal",
"subMetas": {}
},
"InAirAtk1_6.png": {
"ver": "1.0.4",
"uuid": "caf2aac4-bb75-41f2-8deb-334b20b36cc2",
"rawTextureUuid": "b4ea3971-8f28-4cc7-96a4-83f10dce229f",
"trimType": "auto",
"trimThreshold": 1,
"rotated": true,
"offsetX": 0,
"offsetY": 0,
"trimX": 95,
"trimY": 169,
"width": 63,
"height": 95,
"rawWidth": 63,
"rawHeight": 95,
"borderTop": 0,
"borderBottom": 0,
"borderLeft": 0,
"borderRight": 0,
"spriteType": "normal",
"subMetas": {}
},
"InAirAtk1_7.png": {
"ver": "1.0.4",
"uuid": "b5368d17-52da-4a4b-82e9-7808a973a16d",
"rawTextureUuid": "b4ea3971-8f28-4cc7-96a4-83f10dce229f",
"trimType": "auto",
"trimThreshold": 1,
"rotated": true,
"offsetX": 0,
"offsetY": 0,
"trimX": 0,
"trimY": 212,
"width": 63,
"height": 95,
"rawWidth": 63,
"rawHeight": 95,
"borderTop": 0,
"borderBottom": 0,
"borderLeft": 0,
"borderRight": 0,
"spriteType": "normal",
"subMetas": {}
},
"InAirAtked1_1.png": {
"ver": "1.0.4",
"uuid": "e643e1e4-6a6a-4c73-995c-d49e3c4c750c",
"rawTextureUuid": "b4ea3971-8f28-4cc7-96a4-83f10dce229f",
"trimType": "auto",
"trimThreshold": 1,
"rotated": true,
"offsetX": 0,
"offsetY": 0,
"trimX": 170,
"trimY": 451,
"width": 47,
"height": 82,
"rawWidth": 47,
"rawHeight": 82,
"borderTop": 0,
"borderBottom": 0,
"borderLeft": 0,
"borderRight": 0,
"spriteType": "normal",
"subMetas": {}
},
"InAirAtked1_2.png": {
"ver": "1.0.4",
"uuid": "982e48da-cac3-4c1e-96f6-3c659c43ecdd",
"rawTextureUuid": "b4ea3971-8f28-4cc7-96a4-83f10dce229f",
"trimType": "auto",
"trimThreshold": 1,
"rotated": true,
"offsetX": 0,
"offsetY": 0,
"trimX": 170,
"trimY": 498,
"width": 47,
"height": 82,
"rawWidth": 47,
"rawHeight": 82,
"borderTop": 0,
"borderBottom": 0,
"borderLeft": 0,
"borderRight": 0,
"spriteType": "normal",
"subMetas": {}
},
"InAirIdle1_1.png": {
"ver": "1.0.4",
"uuid": "55dc7736-f0bc-46b8-9705-efcdb19ddb85",
"rawTextureUuid": "b4ea3971-8f28-4cc7-96a4-83f10dce229f",
"trimType": "auto",
"trimThreshold": 1,
"rotated": true,
"offsetX": 0,
"offsetY": 0,
"trimX": 0,
"trimY": 0,
"width": 43,
"height": 104,
"rawWidth": 43,
"rawHeight": 104,
"borderTop": 0,
"borderBottom": 0,
"borderLeft": 0,
"borderRight": 0,
"spriteType": "normal",
"subMetas": {}
},
"InAirIdle1_2.png": {
"ver": "1.0.4",
"uuid": "5a18d76d-6e98-43c9-8f0a-99111256e1d5",
"rawTextureUuid": "b4ea3971-8f28-4cc7-96a4-83f10dce229f",
"trimType": "auto",
"trimThreshold": 1,
"rotated": true,
"offsetX": 0,
"offsetY": 0,
"trimX": 104,
"trimY": 0,
"width": 43,
"height": 104,
"rawWidth": 43,
"rawHeight": 104,
"borderTop": 0,
"borderBottom": 0,
"borderLeft": 0,
"borderRight": 0,
"spriteType": "normal",
"subMetas": {}
},
"InAirIdle1_3.png": {
"ver": "1.0.4",
"uuid": "7c0bb61d-15f8-4d41-9225-2a1f339b80b1",
"rawTextureUuid": "b4ea3971-8f28-4cc7-96a4-83f10dce229f",
"trimType": "auto",
"trimThreshold": 1,
"rotated": false,
"offsetX": 0,
"offsetY": 0,
"trimX": 208,
"trimY": 0,
"width": 43,
"height": 104,
"rawWidth": 43,
"rawHeight": 104,
"borderTop": 0,
"borderBottom": 0,
"borderLeft": 0,
"borderRight": 0,
"spriteType": "normal",
"subMetas": {}
},
"InAirIdle1_4.png": {
"ver": "1.0.4",
"uuid": "7cb60116-3f96-44bb-9bf7-6fbfc2ca9772",
"rawTextureUuid": "b4ea3971-8f28-4cc7-96a4-83f10dce229f",
"trimType": "auto",
"trimThreshold": 1,
"rotated": true,
"offsetX": 0,
"offsetY": 0,
"trimX": 104,
"trimY": 0,
"width": 43,
"height": 104,
"rawWidth": 43,
"rawHeight": 104,
"borderTop": 0,
"borderBottom": 0,
"borderLeft": 0,
"borderRight": 0,
"spriteType": "normal",
"subMetas": {}
},
"InAirIdle1_5.png": {
"ver": "1.0.4",
"uuid": "e8d32f3e-0b66-4b35-b4ed-7823a047cc88",
"rawTextureUuid": "b4ea3971-8f28-4cc7-96a4-83f10dce229f",
"trimType": "auto",
"trimThreshold": 1,
"rotated": true,
"offsetX": 0,
"offsetY": 0,
"trimX": 0,
"trimY": 0,
"width": 43,
"height": 104,
"rawWidth": 43,
"rawHeight": 104,
"borderTop": 0,
"borderBottom": 0,
"borderLeft": 0,
"borderRight": 0,
"spriteType": "normal",
"subMetas": {}
},
"InAirIdle1_6.png": {
"ver": "1.0.4",
"uuid": "ca385337-356e-49eb-8081-36b1505411a2",
"rawTextureUuid": "b4ea3971-8f28-4cc7-96a4-83f10dce229f",
"trimType": "auto",
"trimThreshold": 1,
"rotated": true,
"offsetX": 0,
"offsetY": 0,
"trimX": 0,
"trimY": 43,
"width": 43,
"height": 104,
"rawWidth": 43,
"rawHeight": 104,
"borderTop": 0,
"borderBottom": 0,
"borderLeft": 0,
"borderRight": 0,
"spriteType": "normal",
"subMetas": {}
},
"Walking_1.png": {
"ver": "1.0.4",
"uuid": "b706e9a2-827e-42bc-9920-c0e644eb8a75",
"rawTextureUuid": "b4ea3971-8f28-4cc7-96a4-83f10dce229f",
"trimType": "auto",
"trimThreshold": 1,
"rotated": false,
"offsetX": 0,
"offsetY": 0,
"trimX": 199,
"trimY": 104,
"width": 50,
"height": 90,
"rawWidth": 50,
"rawHeight": 90,
"borderTop": 0,
"borderBottom": 0,
"borderLeft": 0,
"borderRight": 0,
"spriteType": "normal",
"subMetas": {}
},
"Walking_2.png": {
"ver": "1.0.4",
"uuid": "f9141513-f9b3-4fc8-8900-b793294c82c6",
"rawTextureUuid": "b4ea3971-8f28-4cc7-96a4-83f10dce229f",
"trimType": "auto",
"trimThreshold": 1,
"rotated": true,
"offsetX": 0,
"offsetY": 0,
"trimX": 95,
"trimY": 232,
"width": 50,
"height": 90,
"rawWidth": 50,
"rawHeight": 90,
"borderTop": 0,
"borderBottom": 0,
"borderLeft": 0,
"borderRight": 0,
"spriteType": "normal",
"subMetas": {}
},
"Walking_3.png": {
"ver": "1.0.4",
"uuid": "6e12b8d0-488c-4885-9b4a-712af055be78",
"rawTextureUuid": "b4ea3971-8f28-4cc7-96a4-83f10dce229f",
"trimType": "auto",
"trimThreshold": 1,
"rotated": true,
"offsetX": 0,
"offsetY": 0,
"trimX": 0,
"trimY": 275,
"width": 50,
"height": 90,
"rawWidth": 50,
"rawHeight": 90,
"borderTop": 0,
"borderBottom": 0,
"borderLeft": 0,
"borderRight": 0,
"spriteType": "normal",
"subMetas": {}
},
"Walking_4.png": {
"ver": "1.0.4",
"uuid": "a4be80d2-4593-4d92-994b-de7fc66642f0",
"rawTextureUuid": "b4ea3971-8f28-4cc7-96a4-83f10dce229f",
"trimType": "auto",
"trimThreshold": 1,
"rotated": true,
"offsetX": 0,
"offsetY": 0,
"trimX": 90,
"trimY": 282,
"width": 50,
"height": 90,
"rawWidth": 50,
"rawHeight": 90,
"borderTop": 0,
"borderBottom": 0,
"borderLeft": 0,
"borderRight": 0,
"spriteType": "normal",
"subMetas": {}
},
"Walking_5.png": {
"ver": "1.0.4",
"uuid": "bc355af2-caa1-4458-be7f-f84184d27c11",
"rawTextureUuid": "b4ea3971-8f28-4cc7-96a4-83f10dce229f",
"trimType": "auto",
"trimThreshold": 1,
"rotated": true,
"offsetX": 0,
"offsetY": 0,
"trimX": 0,
"trimY": 325,
"width": 50,
"height": 90,
"rawWidth": 50,
"rawHeight": 90,
"borderTop": 0,
"borderBottom": 0,
"borderLeft": 0,
"borderRight": 0,
"spriteType": "normal",
"subMetas": {}
},
"Walking_6.png": {
"ver": "1.0.4",
"uuid": "4fa095aa-f08d-4baa-84c9-10e8eac6ea01",
"rawTextureUuid": "b4ea3971-8f28-4cc7-96a4-83f10dce229f",
"trimType": "auto",
"trimThreshold": 1,
"rotated": true,
"offsetX": 0,
"offsetY": 0,
"trimX": 90,
"trimY": 282,
"width": 50,
"height": 90,
"rawWidth": 50,
"rawHeight": 90,
"borderTop": 0,
"borderBottom": 0,
"borderLeft": 0,
"borderRight": 0,
"spriteType": "normal",
"subMetas": {}
},
"Walking_7.png": {
"ver": "1.0.4",
"uuid": "01424fa9-4b4b-472a-ae90-923d0877fb66",
"rawTextureUuid": "b4ea3971-8f28-4cc7-96a4-83f10dce229f",
"trimType": "auto",
"trimThreshold": 1,
"rotated": true,
"offsetX": 0,
"offsetY": 0,
"trimX": 0,
"trimY": 275,
"width": 50,
"height": 90,
"rawWidth": 50,
"rawHeight": 90,
"borderTop": 0,
"borderBottom": 0,
"borderLeft": 0,
"borderRight": 0,
"spriteType": "normal",
"subMetas": {}
},
"Walking_8.png": {
"ver": "1.0.4",
"uuid": "5d8fe180-61eb-448d-bbcf-100d1763ebc8",
"rawTextureUuid": "b4ea3971-8f28-4cc7-96a4-83f10dce229f",
"trimType": "auto",
"trimThreshold": 1,
"rotated": true,
"offsetX": 0,
"offsetY": 0,
"trimX": 95,
"trimY": 232,
"width": 50,
"height": 90,
"rawWidth": 50,
"rawHeight": 90,
"borderTop": 0,
"borderBottom": 0,
"borderLeft": 0,
"borderRight": 0,
"spriteType": "normal",
"subMetas": {}
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

View File

@@ -0,0 +1,12 @@
{
"ver": "2.3.3",
"uuid": "b4ea3971-8f28-4cc7-96a4-83f10dce229f",
"type": "raw",
"wrapMode": "clamp",
"filterMode": "bilinear",
"premultiplyAlpha": false,
"genMipmaps": false,
"packable": true,
"platformSettings": {},
"subMetas": {}
}

View File

@@ -0,0 +1,67 @@
{
"__type__": "cc.AnimationClip",
"_name": "Walking",
"_objFlags": 0,
"_native": "",
"_duration": 0.36666666666666664,
"sample": 60,
"speed": 1,
"wrapMode": 2,
"curveData": {
"comps": {
"cc.Sprite": {
"spriteFrame": [
{
"frame": 0,
"value": {
"__uuid__": "b706e9a2-827e-42bc-9920-c0e644eb8a75"
}
},
{
"frame": 0.05,
"value": {
"__uuid__": "f9141513-f9b3-4fc8-8900-b793294c82c6"
}
},
{
"frame": 0.1,
"value": {
"__uuid__": "6e12b8d0-488c-4885-9b4a-712af055be78"
}
},
{
"frame": 0.16666666666666666,
"value": {
"__uuid__": "a4be80d2-4593-4d92-994b-de7fc66642f0"
}
},
{
"frame": 0.21666666666666667,
"value": {
"__uuid__": "bc355af2-caa1-4458-be7f-f84184d27c11"
}
},
{
"frame": 0.26666666666666666,
"value": {
"__uuid__": "4fa095aa-f08d-4baa-84c9-10e8eac6ea01"
}
},
{
"frame": 0.31666666666666665,
"value": {
"__uuid__": "01424fa9-4b4b-472a-ae90-923d0877fb66"
}
},
{
"frame": 0.35,
"value": {
"__uuid__": "5d8fe180-61eb-448d-bbcf-100d1763ebc8"
}
}
]
}
}
},
"events": []
}

View File

@@ -9,10 +9,10 @@
</data>
</layer>
<objectgroup id="1" name="PlayerStartingPos">
<object id="135" x="1010" y="1432">
<object id="135" x="882" y="1437.33">
<point/>
</object>
<object id="137" x="950" y="1432">
<object id="137" x="955.333" y="1434.67">
<point/>
</object>
</objectgroup>

View File

@@ -76,6 +76,7 @@ message InputsBufferSnapshot {
int32 refRenderFrameId = 1;
uint64 unconfirmedMask = 2;
repeated InputFrameDownsync toSendInputFrameDownsyncs = 3;
bool shouldForceResync = 4;
}
message MeleeBullet {
@@ -151,4 +152,5 @@ message RoomDownsyncFrame {
int64 countdownNanos = 3;
repeated MeleeBullet meleeBullets = 4; // I don't know how to mimic inheritance/composition in protobuf by far, thus using an array for each type of bullet as a compromise
uint64 backendUnconfirmedMask = 5; // Indexed by "joinIndex", same compression concern as stated in InputFrameDownsync
bool shouldForceResync = 6;
}

View File

@@ -779,7 +779,7 @@
},
{
"__type__": "cc.Node",
"_name": "SoldierFireGhostFrameAnim",
"_name": "UltramanTiga",
"_objFlags": 0,
"_parent": {
"__id__": 11
@@ -826,8 +826,8 @@
0,
0,
1,
1,
1,
0.7,
0.7,
1
]
},
@@ -870,7 +870,7 @@
"__uuid__": "43dbf141-be76-48c3-bdef-29233ccbe30d"
},
{
"__uuid__": "c738236a-0702-45f8-aa38-99457b051997"
"__uuid__": "8710591c-3f5e-4911-83e7-42cc18be6af9"
},
{
"__uuid__": "c69bcceb-d7d1-4e33-9623-e2a374a0a6b6"
@@ -907,7 +907,7 @@
"_fillRange": 0,
"_isTrimmedMode": true,
"_atlas": {
"__uuid__": "145769c8-a259-42bc-8cce-6e035f493c70"
"__uuid__": "5d522f7b-359b-4f38-ac35-55fdbee56cae"
},
"_id": ""
},
@@ -919,7 +919,7 @@
"asset": {
"__uuid__": "59bff7a2-23e1-4d69-bce7-afb37eae196a"
},
"fileId": "4c+Ci1MGpP47N3wJ0ujhEm",
"fileId": "17JdhftghBYr81MfV9i6cy",
"sync": false
},
{

View File

@@ -78,19 +78,19 @@
"_active": true,
"_components": [
{
"__id__": 29
"__id__": 37
},
{
"__id__": 30
"__id__": 38
},
{
"__id__": 31
"__id__": 39
},
{
"__id__": 32
"__id__": 40
},
{
"__id__": 33
"__id__": 41
}
],
"_prefab": null,
@@ -158,7 +158,7 @@
"__id__": 5
},
{
"__id__": 28
"__id__": 36
}
],
"_prefab": null,
@@ -279,13 +279,13 @@
},
"_children": [
{
"__id__": 22
"__id__": 30
}
],
"_active": true,
"_components": [
{
"__id__": 27
"__id__": 35
}
],
"_prefab": null,
@@ -352,6 +352,12 @@
},
{
"__id__": 20
},
{
"__id__": 22
},
{
"__id__": 26
}
],
"_active": true,
@@ -447,7 +453,7 @@
"array": [
0,
0,
216.50635094610968,
215.81269742929726,
0,
0,
0,
@@ -1043,10 +1049,10 @@
},
{
"__type__": "cc.Node",
"_name": "JoystickBG",
"_name": "BtnA",
"_objFlags": 0,
"_parent": {
"__id__": 6
"__id__": 7
},
"_children": [
{
@@ -1054,12 +1060,70 @@
}
],
"_active": true,
"_components": [],
"_prefab": null,
"_opacity": 255,
"_color": {
"__type__": "cc.Color",
"r": 255,
"g": 255,
"b": 255,
"a": 255
},
"_contentSize": {
"__type__": "cc.Size",
"width": 200,
"height": 200
},
"_anchorPoint": {
"__type__": "cc.Vec2",
"x": 0.5,
"y": 0.5
},
"_trs": {
"__type__": "TypedArray",
"ctor": "Float64Array",
"array": [
143.689,
-584.849,
0,
0,
0,
0,
1,
0.66667,
0.66667,
0.66667
]
},
"_eulerAngles": {
"__type__": "cc.Vec3",
"x": 0,
"y": 0,
"z": 0
},
"_skewX": 0,
"_skewY": 0,
"_is3DNode": false,
"_groupIndex": 0,
"groupIndex": 0,
"_id": "35ITFOFadFX5FVNVNUZbrn"
},
{
"__type__": "cc.Node",
"_name": "Background",
"_objFlags": 0,
"_parent": {
"__id__": 22
},
"_children": [],
"_active": true,
"_components": [
{
"__id__": 25
"__id__": 24
},
{
"__id__": 26
"__id__": 25
}
],
"_prefab": null,
@@ -1073,8 +1137,8 @@
},
"_contentSize": {
"__type__": "cc.Size",
"width": 400,
"height": 400
"width": 200,
"height": 200
},
"_anchorPoint": {
"__type__": "cc.Vec2",
@@ -1108,6 +1172,324 @@
"_is3DNode": false,
"_groupIndex": 0,
"groupIndex": 0,
"_id": "8f/j+BH3VFzowR9kS36/D8"
},
{
"__type__": "cc.Sprite",
"_name": "",
"_objFlags": 0,
"node": {
"__id__": 23
},
"_enabled": true,
"_materials": [
{
"__uuid__": "eca5d2f2-8ef6-41c2-bbe6-f9c79d09c432"
}
],
"_srcBlendFactor": 770,
"_dstBlendFactor": 771,
"_spriteFrame": {
"__uuid__": "350fd890-3d28-4e53-9dfa-1bf00d857737"
},
"_type": 1,
"_sizeMode": 0,
"_fillType": 0,
"_fillCenter": {
"__type__": "cc.Vec2",
"x": 0,
"y": 0
},
"_fillStart": 0,
"_fillRange": 0,
"_isTrimmedMode": true,
"_atlas": {
"__uuid__": "030d9286-e8a2-40cf-98f8-baf713f0b8c4"
},
"_id": "bdYe//0u9Dj79RLi8Rt6un"
},
{
"__type__": "cc.Widget",
"_name": "",
"_objFlags": 0,
"node": {
"__id__": 23
},
"_enabled": true,
"alignMode": 0,
"_target": null,
"_alignFlags": 45,
"_left": 0,
"_right": 0,
"_top": 0,
"_bottom": 0,
"_verticalCenter": 0,
"_horizontalCenter": 0,
"_isAbsLeft": true,
"_isAbsRight": true,
"_isAbsTop": true,
"_isAbsBottom": true,
"_isAbsHorizontalCenter": true,
"_isAbsVerticalCenter": true,
"_originalWidth": 100,
"_originalHeight": 40,
"_id": "98p5OL5fdGep1z6jWXKTu9"
},
{
"__type__": "cc.Node",
"_name": "BtnB",
"_objFlags": 0,
"_parent": {
"__id__": 7
},
"_children": [
{
"__id__": 27
}
],
"_active": true,
"_components": [],
"_prefab": null,
"_opacity": 255,
"_color": {
"__type__": "cc.Color",
"r": 255,
"g": 255,
"b": 255,
"a": 255
},
"_contentSize": {
"__type__": "cc.Size",
"width": 200,
"height": 200
},
"_anchorPoint": {
"__type__": "cc.Vec2",
"x": 0.5,
"y": 0.5
},
"_trs": {
"__type__": "TypedArray",
"ctor": "Float64Array",
"array": [
370.368,
-424.647,
0,
0,
0,
0,
1,
0.66667,
0.66667,
0.66667
]
},
"_eulerAngles": {
"__type__": "cc.Vec3",
"x": 0,
"y": 0,
"z": 0
},
"_skewX": 0,
"_skewY": 0,
"_is3DNode": false,
"_groupIndex": 0,
"groupIndex": 0,
"_id": "92c5tbNsZPG7f09UQLXv+j"
},
{
"__type__": "cc.Node",
"_name": "Background",
"_objFlags": 0,
"_parent": {
"__id__": 26
},
"_children": [],
"_active": true,
"_components": [
{
"__id__": 28
},
{
"__id__": 29
}
],
"_prefab": null,
"_opacity": 255,
"_color": {
"__type__": "cc.Color",
"r": 255,
"g": 255,
"b": 255,
"a": 255
},
"_contentSize": {
"__type__": "cc.Size",
"width": 200,
"height": 200
},
"_anchorPoint": {
"__type__": "cc.Vec2",
"x": 0.5,
"y": 0.5
},
"_trs": {
"__type__": "TypedArray",
"ctor": "Float64Array",
"array": [
0,
0,
0,
0,
0,
0,
1,
1,
-1,
1
]
},
"_eulerAngles": {
"__type__": "cc.Vec3",
"x": 0,
"y": 0,
"z": 0
},
"_skewX": 0,
"_skewY": 0,
"_is3DNode": false,
"_groupIndex": 0,
"groupIndex": 0,
"_id": "96xSPG8lxPZIsW+n65WcbU"
},
{
"__type__": "cc.Sprite",
"_name": "",
"_objFlags": 0,
"node": {
"__id__": 27
},
"_enabled": true,
"_materials": [
{
"__uuid__": "eca5d2f2-8ef6-41c2-bbe6-f9c79d09c432"
}
],
"_srcBlendFactor": 770,
"_dstBlendFactor": 771,
"_spriteFrame": {
"__uuid__": "a2170e4c-df31-41ef-be73-f4f605e75821"
},
"_type": 1,
"_sizeMode": 0,
"_fillType": 0,
"_fillCenter": {
"__type__": "cc.Vec2",
"x": 0,
"y": 0
},
"_fillStart": 0,
"_fillRange": 0,
"_isTrimmedMode": true,
"_atlas": {
"__uuid__": "030d9286-e8a2-40cf-98f8-baf713f0b8c4"
},
"_id": "2euUQEzg9FdZu2ijWBxgrr"
},
{
"__type__": "cc.Widget",
"_name": "",
"_objFlags": 0,
"node": {
"__id__": 27
},
"_enabled": true,
"alignMode": 0,
"_target": null,
"_alignFlags": 45,
"_left": 0,
"_right": 0,
"_top": 0,
"_bottom": 0,
"_verticalCenter": 0,
"_horizontalCenter": 0,
"_isAbsLeft": true,
"_isAbsRight": true,
"_isAbsTop": true,
"_isAbsBottom": true,
"_isAbsHorizontalCenter": true,
"_isAbsVerticalCenter": true,
"_originalWidth": 100,
"_originalHeight": 40,
"_id": "5bXB50moJH9aH7RcbRuSS5"
},
{
"__type__": "cc.Node",
"_name": "JoystickBG",
"_objFlags": 0,
"_parent": {
"__id__": 6
},
"_children": [
{
"__id__": 31
}
],
"_active": true,
"_components": [
{
"__id__": 33
},
{
"__id__": 34
}
],
"_prefab": null,
"_opacity": 255,
"_color": {
"__type__": "cc.Color",
"r": 255,
"g": 255,
"b": 255,
"a": 255
},
"_contentSize": {
"__type__": "cc.Size",
"width": 400,
"height": 400
},
"_anchorPoint": {
"__type__": "cc.Vec2",
"x": 0.5,
"y": 0.5
},
"_trs": {
"__type__": "TypedArray",
"ctor": "Float64Array",
"array": [
-380,
0,
0,
0,
0,
0,
1,
1,
1,
1
]
},
"_eulerAngles": {
"__type__": "cc.Vec3",
"x": 0,
"y": 0,
"z": 0
},
"_skewX": 0,
"_skewY": 0,
"_is3DNode": false,
"_groupIndex": 0,
"groupIndex": 0,
"_id": "88u3wQvvdO8pbrNWhs3ifP"
},
{
@@ -1115,13 +1497,13 @@
"_name": "Joystick",
"_objFlags": 0,
"_parent": {
"__id__": 22
"__id__": 30
},
"_children": [],
"_active": true,
"_components": [
{
"__id__": 24
"__id__": 32
}
],
"_prefab": null,
@@ -1177,7 +1559,7 @@
"_name": "",
"_objFlags": 0,
"node": {
"__id__": 23
"__id__": 31
},
"_enabled": true,
"_materials": [
@@ -1211,7 +1593,7 @@
"_name": "",
"_objFlags": 0,
"node": {
"__id__": 22
"__id__": 30
},
"_enabled": true,
"_materials": [
@@ -1245,7 +1627,7 @@
"_name": "",
"_objFlags": 0,
"node": {
"__id__": 22
"__id__": 30
},
"_enabled": true,
"alignMode": 0,
@@ -1408,10 +1790,10 @@
"__id__": 3
},
"stickhead": {
"__id__": 23
"__id__": 31
},
"base": {
"__id__": 22
"__id__": 30
},
"joyStickEps": 0.1,
"magicLeanLowerBound": 0.414,
@@ -1431,6 +1813,12 @@
},
"linearMovingEps": 0.1,
"scaleByEps": 0.0375,
"btnA": {
"__id__": 22
},
"btnB": {
"__id__": 26
},
"_id": "e9oVYTr7ROlpp/IrNjBUmR"
}
]

View File

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

View File

@@ -78,19 +78,19 @@
"_active": true,
"_components": [
{
"__id__": 19
"__id__": 27
},
{
"__id__": 20
"__id__": 28
},
{
"__id__": 21
"__id__": 29
},
{
"__id__": 22
"__id__": 30
},
{
"__id__": 23
"__id__": 31
}
],
"_prefab": null,
@@ -289,13 +289,13 @@
},
"_children": [
{
"__id__": 13
"__id__": 21
}
],
"_active": true,
"_components": [
{
"__id__": 18
"__id__": 26
}
],
"_prefab": null,
@@ -359,6 +359,12 @@
},
{
"__id__": 11
},
{
"__id__": 13
},
{
"__id__": 17
}
],
"_active": true,
@@ -454,7 +460,7 @@
"array": [
0,
0,
216.67520680312998,
215.81269742929726,
0,
0,
0,
@@ -607,10 +613,10 @@
},
{
"__type__": "cc.Node",
"_name": "JoystickBG",
"_name": "BtnA",
"_objFlags": 0,
"_parent": {
"__id__": 7
"__id__": 8
},
"_children": [
{
@@ -618,12 +624,70 @@
}
],
"_active": true,
"_components": [],
"_prefab": null,
"_opacity": 255,
"_color": {
"__type__": "cc.Color",
"r": 255,
"g": 255,
"b": 255,
"a": 255
},
"_contentSize": {
"__type__": "cc.Size",
"width": 200,
"height": 200
},
"_anchorPoint": {
"__type__": "cc.Vec2",
"x": 0.5,
"y": 0.5
},
"_trs": {
"__type__": "TypedArray",
"ctor": "Float64Array",
"array": [
143.689,
-584.849,
0,
0,
0,
0,
1,
0.66667,
0.66667,
0.66667
]
},
"_eulerAngles": {
"__type__": "cc.Vec3",
"x": 0,
"y": 0,
"z": 0
},
"_skewX": 0,
"_skewY": 0,
"_is3DNode": false,
"_groupIndex": 0,
"groupIndex": 0,
"_id": "a5pbciqqBEiYlyy7SLwP4V"
},
{
"__type__": "cc.Node",
"_name": "Background",
"_objFlags": 0,
"_parent": {
"__id__": 13
},
"_children": [],
"_active": true,
"_components": [
{
"__id__": 16
"__id__": 15
},
{
"__id__": 17
"__id__": 16
}
],
"_prefab": null,
@@ -637,8 +701,8 @@
},
"_contentSize": {
"__type__": "cc.Size",
"width": 400,
"height": 400
"width": 200,
"height": 200
},
"_anchorPoint": {
"__type__": "cc.Vec2",
@@ -672,6 +736,324 @@
"_is3DNode": false,
"_groupIndex": 0,
"groupIndex": 0,
"_id": "ffojLoj41JCpizkLkManxw"
},
{
"__type__": "cc.Sprite",
"_name": "",
"_objFlags": 0,
"node": {
"__id__": 14
},
"_enabled": true,
"_materials": [
{
"__uuid__": "eca5d2f2-8ef6-41c2-bbe6-f9c79d09c432"
}
],
"_srcBlendFactor": 770,
"_dstBlendFactor": 771,
"_spriteFrame": {
"__uuid__": "350fd890-3d28-4e53-9dfa-1bf00d857737"
},
"_type": 1,
"_sizeMode": 0,
"_fillType": 0,
"_fillCenter": {
"__type__": "cc.Vec2",
"x": 0,
"y": 0
},
"_fillStart": 0,
"_fillRange": 0,
"_isTrimmedMode": true,
"_atlas": {
"__uuid__": "030d9286-e8a2-40cf-98f8-baf713f0b8c4"
},
"_id": "21Oz9QwBZPALzRoJujKVPG"
},
{
"__type__": "cc.Widget",
"_name": "",
"_objFlags": 0,
"node": {
"__id__": 14
},
"_enabled": true,
"alignMode": 0,
"_target": null,
"_alignFlags": 45,
"_left": 0,
"_right": 0,
"_top": 0,
"_bottom": 0,
"_verticalCenter": 0,
"_horizontalCenter": 0,
"_isAbsLeft": true,
"_isAbsRight": true,
"_isAbsTop": true,
"_isAbsBottom": true,
"_isAbsHorizontalCenter": true,
"_isAbsVerticalCenter": true,
"_originalWidth": 100,
"_originalHeight": 40,
"_id": "beUmgK1D1M07I7kTL4NFLK"
},
{
"__type__": "cc.Node",
"_name": "BtnB",
"_objFlags": 0,
"_parent": {
"__id__": 8
},
"_children": [
{
"__id__": 18
}
],
"_active": true,
"_components": [],
"_prefab": null,
"_opacity": 255,
"_color": {
"__type__": "cc.Color",
"r": 255,
"g": 255,
"b": 255,
"a": 255
},
"_contentSize": {
"__type__": "cc.Size",
"width": 200,
"height": 200
},
"_anchorPoint": {
"__type__": "cc.Vec2",
"x": 0.5,
"y": 0.5
},
"_trs": {
"__type__": "TypedArray",
"ctor": "Float64Array",
"array": [
370.368,
-424.647,
0,
0,
0,
0,
1,
0.66667,
0.66667,
0.66667
]
},
"_eulerAngles": {
"__type__": "cc.Vec3",
"x": 0,
"y": 0,
"z": 0
},
"_skewX": 0,
"_skewY": 0,
"_is3DNode": false,
"_groupIndex": 0,
"groupIndex": 0,
"_id": "9eZHUAtItPMKp7OrItdaWA"
},
{
"__type__": "cc.Node",
"_name": "Background",
"_objFlags": 0,
"_parent": {
"__id__": 17
},
"_children": [],
"_active": true,
"_components": [
{
"__id__": 19
},
{
"__id__": 20
}
],
"_prefab": null,
"_opacity": 255,
"_color": {
"__type__": "cc.Color",
"r": 255,
"g": 255,
"b": 255,
"a": 255
},
"_contentSize": {
"__type__": "cc.Size",
"width": 200,
"height": 200
},
"_anchorPoint": {
"__type__": "cc.Vec2",
"x": 0.5,
"y": 0.5
},
"_trs": {
"__type__": "TypedArray",
"ctor": "Float64Array",
"array": [
0,
0,
0,
0,
0,
0,
1,
1,
-1,
1
]
},
"_eulerAngles": {
"__type__": "cc.Vec3",
"x": 0,
"y": 0,
"z": 0
},
"_skewX": 0,
"_skewY": 0,
"_is3DNode": false,
"_groupIndex": 0,
"groupIndex": 0,
"_id": "e2JXxje+hAC7LjZqzgq8RF"
},
{
"__type__": "cc.Sprite",
"_name": "",
"_objFlags": 0,
"node": {
"__id__": 18
},
"_enabled": true,
"_materials": [
{
"__uuid__": "eca5d2f2-8ef6-41c2-bbe6-f9c79d09c432"
}
],
"_srcBlendFactor": 770,
"_dstBlendFactor": 771,
"_spriteFrame": {
"__uuid__": "a2170e4c-df31-41ef-be73-f4f605e75821"
},
"_type": 1,
"_sizeMode": 0,
"_fillType": 0,
"_fillCenter": {
"__type__": "cc.Vec2",
"x": 0,
"y": 0
},
"_fillStart": 0,
"_fillRange": 0,
"_isTrimmedMode": true,
"_atlas": {
"__uuid__": "030d9286-e8a2-40cf-98f8-baf713f0b8c4"
},
"_id": "54DvUzQvpKMrmsuRaQRSxf"
},
{
"__type__": "cc.Widget",
"_name": "",
"_objFlags": 0,
"node": {
"__id__": 18
},
"_enabled": true,
"alignMode": 0,
"_target": null,
"_alignFlags": 45,
"_left": 0,
"_right": 0,
"_top": 0,
"_bottom": 0,
"_verticalCenter": 0,
"_horizontalCenter": 0,
"_isAbsLeft": true,
"_isAbsRight": true,
"_isAbsTop": true,
"_isAbsBottom": true,
"_isAbsHorizontalCenter": true,
"_isAbsVerticalCenter": true,
"_originalWidth": 100,
"_originalHeight": 40,
"_id": "5fVLGAIhROj6UDGotnneup"
},
{
"__type__": "cc.Node",
"_name": "JoystickBG",
"_objFlags": 0,
"_parent": {
"__id__": 7
},
"_children": [
{
"__id__": 22
}
],
"_active": true,
"_components": [
{
"__id__": 24
},
{
"__id__": 25
}
],
"_prefab": null,
"_opacity": 255,
"_color": {
"__type__": "cc.Color",
"r": 255,
"g": 255,
"b": 255,
"a": 255
},
"_contentSize": {
"__type__": "cc.Size",
"width": 400,
"height": 400
},
"_anchorPoint": {
"__type__": "cc.Vec2",
"x": 0.5,
"y": 0.5
},
"_trs": {
"__type__": "TypedArray",
"ctor": "Float64Array",
"array": [
-380,
0,
0,
0,
0,
0,
1,
1,
1,
1
]
},
"_eulerAngles": {
"__type__": "cc.Vec3",
"x": 0,
"y": 0,
"z": 0
},
"_skewX": 0,
"_skewY": 0,
"_is3DNode": false,
"_groupIndex": 0,
"groupIndex": 0,
"_id": "88u3wQvvdO8pbrNWhs3ifP"
},
{
@@ -679,13 +1061,13 @@
"_name": "Joystick",
"_objFlags": 0,
"_parent": {
"__id__": 13
"__id__": 21
},
"_children": [],
"_active": true,
"_components": [
{
"__id__": 15
"__id__": 23
}
],
"_prefab": null,
@@ -741,7 +1123,7 @@
"_name": "",
"_objFlags": 0,
"node": {
"__id__": 14
"__id__": 22
},
"_enabled": true,
"_materials": [
@@ -775,7 +1157,7 @@
"_name": "",
"_objFlags": 0,
"node": {
"__id__": 13
"__id__": 21
},
"_enabled": true,
"_materials": [
@@ -809,7 +1191,7 @@
"_name": "",
"_objFlags": 0,
"node": {
"__id__": 13
"__id__": 21
},
"_enabled": true,
"alignMode": 0,
@@ -944,10 +1326,10 @@
"__id__": 3
},
"stickhead": {
"__id__": 14
"__id__": 22
},
"base": {
"__id__": 13
"__id__": 21
},
"joyStickEps": 0.1,
"magicLeanLowerBound": 0.414,
@@ -967,6 +1349,12 @@
},
"linearMovingEps": 0.1,
"scaleByEps": 0.0375,
"btnA": {
"__id__": 13
},
"btnB": {
"__id__": 17
},
"_id": "e9oVYTr7ROlpp/IrNjBUmR"
}
]

View File

@@ -98,7 +98,7 @@ cc.Class({
}
let newCharacterState = rdfPlayer.characterState;
const newAnimName = window.ATK_CHARACTER_STATE_ARR[newCharacterState][1];
let newAnimName = window.ATK_CHARACTER_STATE_ARR[newCharacterState][1];
let playingAnimName = null;
let underlyingAnimationCtrl = null;

View File

@@ -347,7 +347,6 @@ cc.Class({
const mapNode = self.node;
const canvasNode = mapNode.parent;
cc.director.getCollisionManager().enabled = false;
// self.musicEffectManagerScriptIns = self.node.getComponent("MusicEffectManager");
self.musicEffectManagerScriptIns = null;
@@ -588,12 +587,13 @@ cc.Class({
}
const shouldForceDumping1 = (window.MAGIC_ROOM_DOWNSYNC_FRAME_ID.BATTLE_START == rdf.id);
const shouldForceDumping2 = (rdf.id > self.renderFrameId + self.renderFrameIdLagTolerance);
const shouldForceResync = rdf.shouldForceResync;
const [dumpRenderCacheRet, oldStRenderFrameId, oldEdRenderFrameId] = (shouldForceDumping1 || shouldForceDumping2) ? self.recentRenderCache.setByFrameId(rdf, rdf.id) : [window.RING_BUFF_CONSECUTIVE_SET, null, null];
const [dumpRenderCacheRet, oldStRenderFrameId, oldEdRenderFrameId] = (shouldForceDumping1 || shouldForceDumping2 || shouldForceResync) ? self.recentRenderCache.setByFrameId(rdf, rdf.id) : [window.RING_BUFF_CONSECUTIVE_SET, null, null];
if (window.RING_BUFF_FAILED_TO_SET == dumpRenderCacheRet) {
throw `Failed to dump render cache#1 (maybe recentRenderCache too small)! rdf.id=${rdf.id}, lastAllConfirmedRenderFrameId=${self.lastAllConfirmedRenderFrameId}, lastAllConfirmedInputFrameId=${self.lastAllConfirmedInputFrameId}; recentRenderCache=${self._stringifyRecentRenderCache(false)}, recentInputCache=${self._stringifyRecentInputCache(false)}`;
}
if (window.MAGIC_ROOM_DOWNSYNC_FRAME_ID.BATTLE_START < rdf.id && window.RING_BUFF_CONSECUTIVE_SET == dumpRenderCacheRet) {
if (!shouldForceResync && (window.MAGIC_ROOM_DOWNSYNC_FRAME_ID.BATTLE_START < rdf.id && window.RING_BUFF_CONSECUTIVE_SET == dumpRenderCacheRet)) {
/*
Don't change
- lastAllConfirmedRenderFrameId, it's updated only in "rollbackAndChase" (except for when RING_BUFF_NON_CONSECUTIVE_SET)
@@ -614,7 +614,7 @@ cc.Class({
}
}
if (null == self.renderFrameId || self.renderFrameId <= rdf.id) {
if (null == self.renderFrameId || self.renderFrameId <= rdf.id || shouldForceResync) {
// In fact, not having "window.RING_BUFF_CONSECUTIVE_SET == dumpRenderCacheRet" should already imply that "self.renderFrameId <= rdf.id", but here we double check and log the anomaly
if (window.MAGIC_ROOM_DOWNSYNC_FRAME_ID.BATTLE_START == rdf.id) {
@@ -778,16 +778,22 @@ cc.Class({
if (1 == joinIndex) {
playerScriptIns.setSpecies("SoldierWaterGhost");
} else if (2 == joinIndex) {
playerScriptIns.setSpecies("SoldierFireGhostFrameAnim");
playerScriptIns.setSpecies("UltramanTiga");
}
const [wx, wy] = self.virtualGridToWorldPos(vx, vy);
newPlayerNode.setPosition(wx, wy);
playerScriptIns.mapNode = self.node;
const colliderWidth = playerDownsyncInfo.colliderRadius * 2,
colliderHeight = playerDownsyncInfo.colliderRadius * 4;
const cpos = self.virtualGridToPolygonColliderTLPos(vx, vy, colliderWidth * 0.5, colliderHeight * 0.5); // the top-left corner is kept having integer coords
const pts = [[0, 0], [colliderWidth, 0], [colliderWidth, -colliderHeight - self.snapIntoPlatformOverlap], [0, -colliderHeight - self.snapIntoPlatformOverlap]];
const halfColliderWidth = playerDownsyncInfo.colliderRadius,
halfColliderHeight = playerDownsyncInfo.colliderRadius + playerDownsyncInfo.colliderRadius; // avoid multiplying
const colliderWidth = halfColliderWidth + halfColliderWidth,
colliderHeight = halfColliderHeight + halfColliderHeight; // avoid multiplying
const leftPadding = self.snapIntoPlatformOverlap,
rightPadding = self.snapIntoPlatformOverlap,
topPadding = self.snapIntoPlatformOverlap,
bottomPadding = self.snapIntoPlatformOverlap;
const cpos = self.virtualGridToPolygonColliderBLPos(vx, vy, halfColliderWidth, halfColliderHeight, topPadding, bottomPadding, leftPadding, rightPadding); // the collider center is kept having integer coords
const pts = [[0, 0], [leftPadding + colliderWidth + rightPadding, 0], [leftPadding + colliderWidth + rightPadding, bottomPadding + colliderHeight + topPadding], [0, bottomPadding + colliderHeight + topPadding]];
// [WARNING] The animNode "anchor & offset" are tuned to fit in this collider by "ControlledCharacter prefab & AttackingCharacter.js"!
const newPlayerCollider = self.collisionSys.createPolygon(cpos[0], cpos[1], pts);
@@ -997,6 +1003,10 @@ cc.Class({
showDebugBoundaries(rdf) {
const self = this;
const leftPadding = self.snapIntoPlatformOverlap,
rightPadding = self.snapIntoPlatformOverlap,
topPadding = self.snapIntoPlatformOverlap,
bottomPadding = self.snapIntoPlatformOverlap;
if (self.showCriticalCoordinateLabels) {
let g = self.g;
g.clear();
@@ -1048,8 +1058,10 @@ cc.Class({
const [offenderWx, offenderWy] = self.virtualGridToWorldPos(offender.virtualGridX, offender.virtualGridY);
const bulletWx = offenderWx + xfac * meleeBullet.hitboxOffset;
const bulletWy = offenderWy;
const bulletCpos = self.worldToPolygonColliderTLPos(bulletWx, bulletWy, meleeBullet.hitboxSize.x * 0.5, meleeBullet.hitboxSize.y * 0.5);
const pts = [[0, 0], [meleeBullet.hitboxSize.x, 0], [meleeBullet.hitboxSize.x, -meleeBullet.hitboxSize.y], [0, -meleeBullet.hitboxSize.y]];
const halfColliderWidth = meleeBullet.hitboxSize.x * 0.5,
halfColliderHeight = meleeBullet.hitboxSize.y * 0.5; // avoid multiplying
const bulletCpos = self.worldToPolygonColliderBLPos(bulletWx, bulletWy, halfColliderWidth, halfColliderHeight, topPadding, bottomPadding, leftPadding, rightPadding);
const pts = [[0, 0], [leftPadding + meleeBullet.hitboxSize.x + rightPadding, 0], [leftPadding + meleeBullet.hitboxSize.x + rightPadding, bottomPadding + meleeBullet.hitboxSize.y + topPadding], [0, bottomPadding + meleeBullet.hitboxSize.y + topPadding]];
g.moveTo(bulletCpos[0], bulletCpos[1]);
for (let j = 0; j < pts.length; j += 1) {
@@ -1079,6 +1091,10 @@ cc.Class({
// TODO: Write unit-test for this function to compare with its backend counter part
applyInputFrameDownsyncDynamicsOnSingleRenderFrame(delayedInputFrame, currRenderFrame, collisionSys, collisionSysMap) {
const self = this;
const leftPadding = self.snapIntoPlatformOverlap,
rightPadding = self.snapIntoPlatformOverlap,
topPadding = self.snapIntoPlatformOverlap,
bottomPadding = self.snapIntoPlatformOverlap;
const nextRenderFramePlayers = {};
for (let playerId in currRenderFrame.players) {
const currPlayerDownsync = currRenderFrame.players[playerId];
@@ -1188,10 +1204,14 @@ cc.Class({
const currPlayerDownsync = currRenderFrame.players[playerId];
const thatPlayerInNextFrame = nextRenderFramePlayers[playerId];
// Reset playerCollider position from the "virtual grid position"
const [newVx, newVy] = [currPlayerDownsync.virtualGridX + currPlayerDownsync.velX, currPlayerDownsync.virtualGridY + currPlayerDownsync.velY];
const colliderWidth = self.playerRichInfoArr[joinIndex - 1].colliderRadius * 2,
colliderHeight = self.playerRichInfoArr[joinIndex - 1].colliderRadius * 4;
const newCpos = self.virtualGridToPolygonColliderTLPos(newVx, newVy, colliderWidth * 0.5, colliderHeight * 0.5);
const newVpos = [currPlayerDownsync.virtualGridX + currPlayerDownsync.velX, currPlayerDownsync.virtualGridY + currPlayerDownsync.velY];
if (thatPlayerInNextFrame.velY == self.jumpingInitVelY) {
// This step can be waived, but putting the jumping inclination here makes it easier to read logs.
newVpos[1] += self.jumpingInitVelY;
}
const halfColliderWidth = self.playerRichInfoArr[j].colliderRadius,
halfColliderHeight = self.playerRichInfoArr[j].colliderRadius + self.playerRichInfoArr[j].colliderRadius; // avoid multiplying
const newCpos = self.virtualGridToPolygonColliderBLPos(newVpos[0], newVpos[1], halfColliderWidth, halfColliderHeight, topPadding, bottomPadding, leftPadding, rightPadding);
playerCollider.x = newCpos[0];
playerCollider.y = newCpos[1];
@@ -1223,8 +1243,10 @@ cc.Class({
const [offenderWx, offenderWy] = self.virtualGridToWorldPos(offender.virtualGridX, offender.virtualGridY);
const bulletWx = offenderWx + xfac * meleeBullet.hitboxOffset;
const bulletWy = offenderWy;
const bulletCpos = self.worldToPolygonColliderTLPos(bulletWx, bulletWy, meleeBullet.hitboxSize.x * 0.5, meleeBullet.hitboxSize.y * 0.5),
pts = [[0, 0], [meleeBullet.hitboxSize.x, 0], [meleeBullet.hitboxSize.x, -meleeBullet.hitboxSize.y], [0, -meleeBullet.hitboxSize.y]];
const halfColliderWidth = meleeBullet.hitboxSize.x * 0.5,
halfColliderHeight = meleeBullet.hitboxSize.y * 0.5;
const bulletCpos = self.worldToPolygonColliderBLPos(bulletWx, bulletWy, halfColliderWidth, halfColliderHeight, topPadding, bottomPadding, leftPadding, rightPadding);
const pts = [[0, 0], [leftPadding + meleeBullet.hitboxSize.x + rightPadding, 0], [leftPadding + meleeBullet.hitboxSize.x + rightPadding, bottomPadding + meleeBullet.hitboxSize.y + topPadding], [0, bottomPadding + meleeBullet.hitboxSize.y + topPadding]];
const newBulletCollider = collisionSys.createPolygon(bulletCpos[0], bulletCpos[1], pts);
newBulletCollider.data = meleeBullet;
collisionSysMap.set(collisionBulletIndex, newBulletCollider);
@@ -1248,6 +1270,9 @@ cc.Class({
const currPlayerDownsync = currRenderFrame.players[playerId];
const thatPlayerInNextFrame = nextRenderFramePlayers[playerId];
const halfColliderWidth = self.playerRichInfoArr[j].colliderRadius,
halfColliderHeight = self.playerRichInfoArr[j].colliderRadius + self.playerRichInfoArr[j].colliderRadius; // avoid multiplying
let fallStopping = false;
let possiblyFallStoppedOnAnotherPlayer = false;
for (const potential of potentials) {
@@ -1261,10 +1286,16 @@ cc.Class({
const landedOnGravityPushback = (self.snapIntoPlatformThreshold < normAlignmentWithGravity); // prevents false snapping on the lateral sides
let pushback = [result.overlap * result.overlap_x, result.overlap * result.overlap_y];
if (landedOnGravityPushback) {
// kindly note that one player might land on top of another player, and snapping is also required in such case
// kindly note that one player might land on top of another player
pushback = [(result.overlap - self.snapIntoPlatformOverlap) * result.overlap_x, (result.overlap - self.snapIntoPlatformOverlap) * result.overlap_y];
thatPlayerInNextFrame.inAir = false;
}
if (isAnotherPlayer) {
/*
[WARNING] The "zero overlap collision" might be randomly detected/missed on either frontend or backend, to have deterministic result we added paddings to all sides of a playerCollider. As each velocity component of (velX, velY) being a multiple of 0.5 at any renderFrame, each position component of (x, y) can only be a multiple of 0.5 too, thus whenever a 1-dimensional collision happens between players from [player#1: i*0.5, player#2: j*0.5, not collided yet] to [player#1: (i+k)*0.5, player#2: j*0.5, collided], the overlap becomes (i+k-j)*0.5+2*s, and after snapping subtraction the effPushback magnitude for each player is (i+k-j)*0.5, resulting in 0.5-multiples-position for the next renderFrame.
*/
pushback = [(result.overlap - self.snapIntoPlatformOverlap * 2) * result.overlap_x, (result.overlap - self.snapIntoPlatformOverlap * 2) * result.overlap_y]; // will overwrite the previous pushback value if "landedOnGravityPushback" is also true
}
for (let hardPushbackNorm of hardPushbackNorms[joinIndex - 1]) {
// remove pushback component on the directions of "hardPushbackNorms[joinIndex-1]" (by now those hardPushbacks are already accounted in "effPushbacks[joinIndex-1]")
const projectedMagnitude = pushback[0] * hardPushbackNorm[0] + pushback[1] * hardPushbackNorm[1];
@@ -1281,23 +1312,29 @@ cc.Class({
effPushbacks[joinIndex - 1][0] += pushback[0];
effPushbacks[joinIndex - 1][1] += pushback[1];
// It's not meaningful to log the virtual positions and velocities inside this step.
if (currPlayerDownsync.inAir && landedOnGravityPushback) {
fallStopping = true;
if (isAnotherPlayer) {
possiblyFallStoppedOnAnotherPlayer = true;
}
if (1 == thatPlayerInNextFrame.joinIndex) {
console.log(`playerId=${playerId}, joinIndex=${currPlayerDownsync.joinIndex} fallStopping#1 at {renderFrame.id: ${currRenderFrame.id}, virtualX: ${currPlayerDownsync.virtualGridX}, virtualY: ${currPlayerDownsync.virtualGridY}, velX: ${currPlayerDownsync.velX}, velY: ${currPlayerDownsync.velY}} with effPushback={${effPushbacks[joinIndex - 1][0].toFixed(3)}, ${effPushbacks[joinIndex - 1][1].toFixed(3)}}, overlayMag=${result.overlap.toFixed(4)}, possiblyFallStoppedOnAnotherPlayer=${possiblyFallStoppedOnAnotherPlayer}`);
}
if (1 == joinIndex) {
if (fallStopping) {
console.info(`playerId=${playerId}, joinIndex=${thatPlayerInNextFrame.joinIndex} fallStopping#1:
{renderFrame.id: ${currRenderFrame.id}, possiblyFallStoppedOnAnotherPlayer: ${possiblyFallStoppedOnAnotherPlayer}}
playerColliderPos=${self.stringifyColliderCenterInWorld(playerCollider, halfColliderWidth, halfColliderHeight, topPadding, bottomPadding, leftPadding, rightPadding)}, effPushback={${effPushbacks[joinIndex - 1][0].toFixed(3)}, ${effPushbacks[joinIndex - 1][1].toFixed(3)}}, overlayMag=${result.overlap.toFixed(4)}`);
} else if (currPlayerDownsync.inAir && isBarrier && !landedOnGravityPushback) {
console.warn(`playerId=${playerId}, joinIndex=${currPlayerDownsync.joinIndex} inAir & pushed back by barrier & not landed:
{renderFrame.id: ${currRenderFrame.id}}
playerColliderPos=${self.stringifyColliderCenterInWorld(playerCollider, halfColliderWidth, halfColliderHeight, topPadding, bottomPadding, leftPadding, rightPadding)}, effPushback={${effPushbacks[joinIndex - 1][0].toFixed(3)}, ${effPushbacks[joinIndex - 1][1].toFixed(3)}}, overlayMag=${result.overlap.toFixed(4)}, len(hardPushbackNorms)=${hardPushbackNorms.length}`);
} else if (currPlayerDownsync.inAir && isAnotherPlayer) {
console.warn(`playerId=${playerId}, joinIndex=${currPlayerDownsync.joinIndex} inAir and pushed back by another player
{renderFrame.id: ${currRenderFrame.id}}
playerColliderPos=${self.stringifyColliderCenterInWorld(playerCollider, halfColliderWidth, halfColliderHeight, topPadding, bottomPadding, leftPadding, rightPadding)}, anotherPlayerColliderPos=${self.stringifyColliderCenterInWorld(potential, halfColliderWidth, halfColliderHeight, topPadding, bottomPadding, leftPadding, rightPadding)}, effPushback={${effPushbacks[joinIndex - 1][0].toFixed(3)}, ${effPushbacks[joinIndex - 1][1].toFixed(3)}}, landedOnGravityPushback=${landedOnGravityPushback}, fallStopping=${fallStopping}, overlayMag=${result.overlap.toFixed(4)}, len(hardPushbackNorms)=${hardPushbackNorms.length}`);
}
}
if (1 == joinIndex && currPlayerDownsync.inAir && isBarrier && !landedOnGravityPushback) {
console.warn(`playerId=${playerId}, joinIndex=${currPlayerDownsync.joinIndex} inAir & pushed back by barrier & not landed at {renderFrame.id: ${currRenderFrame.id}, virtualX: ${currPlayerDownsync.virtualGridX}, virtualY: ${currPlayerDownsync.virtualGridY}, velX: ${currPlayerDownsync.velX}, velY: ${currPlayerDownsync.velY}} with effPushback={${effPushbacks[joinIndex - 1][0].toFixed(3)}, ${effPushbacks[joinIndex - 1][1].toFixed(3)}}, playerColliderPos={${playerCollider.x.toFixed(3)}, ${playerCollider.y.toFixed(3)}}, barrierPos={${potential.x.toFixed(3)}, ${potential.y.toFixed(3)}}, overlayMag=${result.overlap.toFixed(4)}, len(hardPushbackNorms)=${hardPushbackNorms.length}`);
}
if (1 == joinIndex && currPlayerDownsync.inAir && isAnotherPlayer) {
console.warn(`playerId=${playerId}, joinIndex=${currPlayerDownsync.joinIndex} inAir and pushed back by another player at {renderFrame.id: ${currRenderFrame.id}, virtualX: ${currPlayerDownsync.virtualGridX}, virtualY: ${currPlayerDownsync.virtualGridY}, velX: ${currPlayerDownsync.velX}, velY: ${currPlayerDownsync.velY}} with effPushback={${effPushbacks[joinIndex - 1][0].toFixed(3)}, ${effPushbacks[joinIndex - 1][1].toFixed(3)}}, landedOnGravityPushback=${landedOnGravityPushback}, fallStopping=${fallStopping}, playerColliderPos={${playerCollider.x.toFixed(3)}, ${playerCollider.y.toFixed(3)}}, anotherPlayerColliderPos={${potential.x.toFixed(3)}, ${potential.y.toFixed(3)}}, overlayMag=${result.overlap.toFixed(4)}, len(hardPushbackNorms)=${hardPushbackNorms.length}`);
}
}
if (fallStopping) {
@@ -1378,21 +1415,27 @@ cc.Class({
// Update "virtual grid position"
const currPlayerDownsync = currRenderFrame.players[playerId];
const thatPlayerInNextFrame = nextRenderFramePlayers[playerId];
const colliderWidth = self.playerRichInfoArr[joinIndex - 1].colliderRadius * 2,
colliderHeight = self.playerRichInfoArr[joinIndex - 1].colliderRadius * 4;
const newVpos = self.polygonColliderTLToVirtualGridPos(playerCollider.x - effPushbacks[joinIndex - 1][0], playerCollider.y - effPushbacks[joinIndex - 1][1], colliderWidth * 0.5, colliderHeight * 0.5);
const halfColliderWidth = self.playerRichInfoArr[j].colliderRadius,
halfColliderHeight = self.playerRichInfoArr[j].colliderRadius + self.playerRichInfoArr[j].colliderRadius; // avoid multiplying
const newVpos = self.polygonColliderBLToVirtualGridPos(playerCollider.x - effPushbacks[joinIndex - 1][0], playerCollider.y - effPushbacks[joinIndex - 1][1], halfColliderWidth, halfColliderHeight, topPadding, bottomPadding, leftPadding, rightPadding);
thatPlayerInNextFrame.virtualGridX = newVpos[0];
thatPlayerInNextFrame.virtualGridY = newVpos[1];
if (1 == thatPlayerInNextFrame.joinIndex) {
if (thatPlayerInNextFrame.inAir && 0 != thatPlayerInNextFrame.velY) {
// console.log(`playerId=${playerId}, joinIndex=${thatPlayerInNextFrame.joinIndex} inAir trajectory: {nextRenderFrame.id: ${currRenderFrame.id + 1}, nextVirtualX: ${thatPlayerInNextFrame.virtualGridX}, nextVirtualY: ${thatPlayerInNextFrame.virtualGridY}, nextVelX: ${thatPlayerInNextFrame.velX}, nextVelY: ${thatPlayerInNextFrame.velY}}, with playerColliderPos={${playerCollider.x.toFixed(3)}, ${playerCollider.y.toFixed(3)}}, effPushback={${effPushbacks[joinIndex - 1][0].toFixed(3)}, ${effPushbacks[joinIndex - 1][1].toFixed(3)}}`);
}
if (currPlayerDownsync.inAir && !thatPlayerInNextFrame.inAir) {
console.warn(`playerId=${playerId}, joinIndex=${thatPlayerInNextFrame.joinIndex} fallStopping#2 at {nextRenderFrame.id: ${currRenderFrame.id + 1}, nextVirtualX: ${thatPlayerInNextFrame.virtualGridX}, nextVirtualY: ${thatPlayerInNextFrame.virtualGridY}, nextVelX: ${thatPlayerInNextFrame.velX}, nextVelY: ${thatPlayerInNextFrame.velY}}, with playerColliderPos={${playerCollider.x.toFixed(3)}, ${playerCollider.y.toFixed(3)}}, effPushback={${effPushbacks[joinIndex - 1][0].toFixed(3)}, ${effPushbacks[joinIndex - 1][1].toFixed(3)}}`);
}
if (!currPlayerDownsync.inAir && thatPlayerInNextFrame.inAir) {
console.warn(`playerId=${playerId}, joinIndex=${thatPlayerInNextFrame.joinIndex} took off at {nextRenderFrame.id: ${currRenderFrame.id + 1}, nextVirtualX: ${thatPlayerInNextFrame.virtualGridX}, nextVirtualY: ${thatPlayerInNextFrame.virtualGridY}, nextVelX: ${thatPlayerInNextFrame.velX}, nextVelY: ${thatPlayerInNextFrame.velY}}, with playerColliderPos={${playerCollider.x.toFixed(3)}, ${playerCollider.y.toFixed(3)}}, effPushback={${effPushbacks[joinIndex - 1][0].toFixed(3)}, ${effPushbacks[joinIndex - 1][1].toFixed(3)}}`);
console.warn(`playerId=${playerId}, joinIndex=${thatPlayerInNextFrame.joinIndex} fallStopping#2:
{nextRenderFrame.id: ${currRenderFrame.id + 1}, nextVirtualX: ${thatPlayerInNextFrame.virtualGridX}, nextVirtualY: ${thatPlayerInNextFrame.virtualGridY}, nextVelX: ${thatPlayerInNextFrame.velX}, nextVelY: ${thatPlayerInNextFrame.velY}}
calculated from <- playerColliderPos=${self.stringifyColliderCenterInWorld(playerCollider, halfColliderWidth, halfColliderHeight, topPadding, bottomPadding, leftPadding, rightPadding)}, effPushback={${effPushbacks[joinIndex - 1][0].toFixed(3)}, ${effPushbacks[joinIndex - 1][1].toFixed(3)}}`);
} else if (!currPlayerDownsync.inAir && thatPlayerInNextFrame.inAir) {
console.warn(`playerId=${playerId}, joinIndex=${thatPlayerInNextFrame.joinIndex} took off:
{nextRenderFrame.id: ${currRenderFrame.id + 1}, nextVirtualX: ${thatPlayerInNextFrame.virtualGridX}, nextVirtualY: ${thatPlayerInNextFrame.virtualGridY}, nextVelX: ${thatPlayerInNextFrame.velX}, nextVelY: ${thatPlayerInNextFrame.velY}}
calculated from <- playerColliderPos=${self.stringifyColliderCenterInWorld(playerCollider, halfColliderWidth, halfColliderHeight, topPadding, bottomPadding, leftPadding, rightPadding)}, effPushback={${effPushbacks[joinIndex - 1][0].toFixed(3)}, ${effPushbacks[joinIndex - 1][1].toFixed(3)}}`);
} else if (thatPlayerInNextFrame.inAir && 0 != thatPlayerInNextFrame.velY) {
/*
console.log(`playerId=${playerId}, joinIndex=${thatPlayerInNextFrame.joinIndex} inAir trajectory:
{nextRenderFrame.id: ${currRenderFrame.id + 1}, nextVirtualX: ${thatPlayerInNextFrame.virtualGridX}, nextVirtualY: ${thatPlayerInNextFrame.virtualGridY}, nextVelX: ${thatPlayerInNextFrame.velX}, nextVelY: ${thatPlayerInNextFrame.velY}};
calculated from <- playerColliderPos=${self.stringifyColliderCenterInWorld(playerCollider, halfColliderWidth, halfColliderHeight, topPadding, bottomPadding, leftPadding, rightPadding)}, effPushback={${effPushbacks[joinIndex - 1][0].toFixed(3)}, ${effPushbacks[joinIndex - 1][1].toFixed(3)}}`);
*/
}
}
}
@@ -1457,16 +1500,16 @@ cc.Class({
const immediatePlayerInfo = players[playerId];
self.playerRichInfoDict.set(playerId, immediatePlayerInfo);
const [theNode, theScriptIns] = self.spawnPlayerNode(immediatePlayerInfo.joinIndex, immediatePlayerInfo.virtualGridX, immediatePlayerInfo.virtualGridY, immediatePlayerInfo);
const nodeAndScriptIns = self.spawnPlayerNode(immediatePlayerInfo.joinIndex, immediatePlayerInfo.virtualGridX, immediatePlayerInfo.virtualGridY, immediatePlayerInfo);
Object.assign(self.playerRichInfoDict.get(playerId), {
node: theNode,
scriptIns: theScriptIns,
node: nodeAndScriptIns[0],
scriptIns: nodeAndScriptIns[1],
});
if (self.selfPlayerInfo.id == playerId) {
self.selfPlayerInfo = Object.assign(self.selfPlayerInfo, immediatePlayerInfo);
theScriptIns.showArrowTipNode();
nodeAndScriptIns[1].showArrowTipNode();
}
}
self.playerRichInfoArr = new Array(self.playerRichInfoDict.size);
@@ -1513,29 +1556,31 @@ cc.Class({
virtualGridToWorldPos(vx, vy) {
// No loss of precision
const self = this;
let wx = parseFloat(vx) * self.virtualGridToWorldRatio;
let wy = parseFloat(vy) * self.virtualGridToWorldRatio;
return [wx, wy];
return [vx * self.virtualGridToWorldRatio, vy * self.virtualGridToWorldRatio];
},
worldToPolygonColliderTLPos(wx, wy, halfBoundingW, halfBoundingH) {
return [wx - halfBoundingW, wy + halfBoundingH];
worldToPolygonColliderBLPos(wx, wy, halfBoundingW, halfBoundingH, topPadding, bottomPadding, leftPadding, rightPadding) {
return [wx - halfBoundingW - leftPadding, wy - halfBoundingH - bottomPadding];
},
polygonColliderTLToWorldPos(cx, cy, halfBoundingW, halfBoundingH) {
return [cx + halfBoundingW, cy - halfBoundingH];
polygonColliderBLToWorldPos(cx, cy, halfBoundingW, halfBoundingH, topPadding, bottomPadding, leftPadding, rightPadding) {
return [cx + halfBoundingW + leftPadding, cy + halfBoundingH + bottomPadding];
},
polygonColliderTLToVirtualGridPos(cx, cy, halfBoundingW, halfBoundingH) {
polygonColliderBLToVirtualGridPos(cx, cy, halfBoundingW, halfBoundingH, topPadding, bottomPadding, leftPadding, rightPadding) {
const self = this;
const [wx, wy] = self.polygonColliderTLToWorldPos(cx, cy, halfBoundingW, halfBoundingH);
const [wx, wy] = self.polygonColliderBLToWorldPos(cx, cy, halfBoundingW, halfBoundingH, topPadding, bottomPadding, leftPadding, rightPadding);
return self.worldToVirtualGridPos(wx, wy)
},
virtualGridToPolygonColliderTLPos(vx, vy, halfBoundingW, halfBoundingH) {
virtualGridToPolygonColliderBLPos(vx, vy, halfBoundingW, halfBoundingH, topPadding, bottomPadding, leftPadding, rightPadding) {
const self = this;
const [wx, wy] = self.virtualGridToWorldPos(vx, vy);
return self.worldToPolygonColliderTLPos(wx, wy, halfBoundingW, halfBoundingH)
return self.worldToPolygonColliderBLPos(wx, wy, halfBoundingW, halfBoundingH, topPadding, bottomPadding, leftPadding, rightPadding)
},
stringifyColliderCenterInWorld(playerCollider, halfBoundingW, halfBoundingH, topPadding, bottomPadding, leftPadding, rightPadding) {
return `{${(playerCollider.x + leftPadding + halfBoundingW).toFixed(2)}, ${(playerCollider.y + bottomPadding + halfBoundingH).toFixed(2)}}`;
},
calcHardPushbacksNorms(collider, potentials, result, snapIntoPlatformOverlap, effPushback) {
@@ -1546,11 +1591,10 @@ cc.Class({
if (!collider.collides(potential, result)) continue;
// ALWAY snap into hardPushbacks!
// [overlay_x, overlap_y] is the unit vector that points into the platform
const [pushbackX, pushbackY] = [(result.overlap - snapIntoPlatformOverlap) * result.overlap_x, (result.overlap - snapIntoPlatformOverlap) * result.overlap_y];
const pushback = [(result.overlap - snapIntoPlatformOverlap) * result.overlap_x, (result.overlap - snapIntoPlatformOverlap) * result.overlap_y];
ret.push([result.overlap_x, result.overlap_y]);
effPushback[0] += pushbackX;
effPushback[1] += pushbackY;
effPushback[0] += pushback[0];
effPushback[1] += pushback[1];
}
return ret;

View File

@@ -15,8 +15,6 @@ cc.Class({
window.mapIns = self;
self.showCriticalCoordinateLabels = true;
cc.director.getCollisionManager().enabled = false;
const mapNode = self.node;
const canvasNode = mapNode.parent;
@@ -47,7 +45,7 @@ cc.Class({
1: {
// for offender
startupFrames: 10,
activeFrames: 3,
activeFrames: 20,
recoveryFrames: 34, // 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: 34,
recoveryFramesOnHit: 34,

View File

@@ -88,6 +88,14 @@ cc.Class({
default: 0.0375,
type: cc.Float
},
btnA: {
default: null,
type: cc.Node
},
btnB: {
default: null,
type: cc.Node
},
},
start() {},
@@ -137,6 +145,7 @@ cc.Class({
});
translationListenerNode.inTouchPoints = new Map();
/*
zoomingListenerNode.on(cc.Node.EventType.TOUCH_START, function(event) {
self._touchStartEvent(event);
});
@@ -150,6 +159,37 @@ cc.Class({
self._touchEndEvent(event);
});
zoomingListenerNode.inTouchPoints = new Map();
*/
if (self.btnA) {
self.btnA.on(cc.Node.EventType.TOUCH_START, function(evt) {
self.cachedBtnALevel = 1;
evt.target.runAction(cc.scaleTo(0.1, 0.3));
});
self.btnA.on(cc.Node.EventType.TOUCH_END, function(evt) {
self.cachedBtnALevel = 0;
evt.target.runAction(cc.scaleTo(0.1, 1.0));
});
self.btnA.on(cc.Node.EventType.TOUCH_CANCEL, function(evt) {
self.cachedBtnALevel = 0;
evt.target.runAction(cc.scaleTo(0.1, 1.0));
});
}
if (self.btnB) {
self.btnB.on(cc.Node.EventType.TOUCH_START, function(evt) {
self.cachedBtnBLevel = 1;
evt.target.runAction(cc.scaleTo(0.1, 0.3));
});
self.btnB.on(cc.Node.EventType.TOUCH_END, function(evt) {
self.cachedBtnBLevel = 0;
evt.target.runAction(cc.scaleTo(0.1, 1.0));
});
self.btnB.on(cc.Node.EventType.TOUCH_CANCEL, function(evt) {
self.cachedBtnBLevel = 0;
evt.target.runAction(cc.scaleTo(0.1, 1.0));
});
}
// Setup keyboard controls for the ease of attach debugging
cc.systemEvent.on(cc.SystemEvent.EventType.KEY_DOWN, function(evt) {

View File

@@ -146,7 +146,7 @@ window.initPersistentSessionClient = function(onopenCb, expectedRoomId) {
}
try {
const resp = window.pb.protos.WsResp.decode(new Uint8Array(evt.data));
// console.log(`Got non-empty onmessage decoded: resp.act=${resp.act}`);
//console.log(`Got non-empty onmessage decoded: resp.act=${resp.act}`);
switch (resp.act) {
case window.DOWNSYNC_MSG_ACT_HB_REQ:
window.handleHbRequirements(resp);

View File

@@ -3654,6 +3654,7 @@ $root.protos = (function() {
* @property {number|null} [refRenderFrameId] InputsBufferSnapshot refRenderFrameId
* @property {number|Long|null} [unconfirmedMask] InputsBufferSnapshot unconfirmedMask
* @property {Array.<protos.InputFrameDownsync>|null} [toSendInputFrameDownsyncs] InputsBufferSnapshot toSendInputFrameDownsyncs
* @property {boolean|null} [shouldForceResync] InputsBufferSnapshot shouldForceResync
*/
/**
@@ -3696,6 +3697,14 @@ $root.protos = (function() {
*/
InputsBufferSnapshot.prototype.toSendInputFrameDownsyncs = $util.emptyArray;
/**
* InputsBufferSnapshot shouldForceResync.
* @member {boolean} shouldForceResync
* @memberof protos.InputsBufferSnapshot
* @instance
*/
InputsBufferSnapshot.prototype.shouldForceResync = false;
/**
* Creates a new InputsBufferSnapshot instance using the specified properties.
* @function create
@@ -3727,6 +3736,8 @@ $root.protos = (function() {
if (message.toSendInputFrameDownsyncs != null && message.toSendInputFrameDownsyncs.length)
for (var i = 0; i < message.toSendInputFrameDownsyncs.length; ++i)
$root.protos.InputFrameDownsync.encode(message.toSendInputFrameDownsyncs[i], writer.uint32(/* id 3, wireType 2 =*/26).fork()).ldelim();
if (message.shouldForceResync != null && Object.hasOwnProperty.call(message, "shouldForceResync"))
writer.uint32(/* id 4, wireType 0 =*/32).bool(message.shouldForceResync);
return writer;
};
@@ -3775,6 +3786,10 @@ $root.protos = (function() {
message.toSendInputFrameDownsyncs.push($root.protos.InputFrameDownsync.decode(reader, reader.uint32()));
break;
}
case 4: {
message.shouldForceResync = reader.bool();
break;
}
default:
reader.skipType(tag & 7);
break;
@@ -3825,6 +3840,9 @@ $root.protos = (function() {
return "toSendInputFrameDownsyncs." + error;
}
}
if (message.shouldForceResync != null && message.hasOwnProperty("shouldForceResync"))
if (typeof message.shouldForceResync !== "boolean")
return "shouldForceResync: boolean expected";
return null;
};
@@ -3861,6 +3879,8 @@ $root.protos = (function() {
message.toSendInputFrameDownsyncs[i] = $root.protos.InputFrameDownsync.fromObject(object.toSendInputFrameDownsyncs[i]);
}
}
if (object.shouldForceResync != null)
message.shouldForceResync = Boolean(object.shouldForceResync);
return message;
};
@@ -3886,6 +3906,7 @@ $root.protos = (function() {
object.unconfirmedMask = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
} else
object.unconfirmedMask = options.longs === String ? "0" : 0;
object.shouldForceResync = false;
}
if (message.refRenderFrameId != null && message.hasOwnProperty("refRenderFrameId"))
object.refRenderFrameId = message.refRenderFrameId;
@@ -3899,6 +3920,8 @@ $root.protos = (function() {
for (var j = 0; j < message.toSendInputFrameDownsyncs.length; ++j)
object.toSendInputFrameDownsyncs[j] = $root.protos.InputFrameDownsync.toObject(message.toSendInputFrameDownsyncs[j], options);
}
if (message.shouldForceResync != null && message.hasOwnProperty("shouldForceResync"))
object.shouldForceResync = message.shouldForceResync;
return object;
};
@@ -5576,6 +5599,7 @@ $root.protos = (function() {
* @property {number|Long|null} [countdownNanos] RoomDownsyncFrame countdownNanos
* @property {Array.<protos.MeleeBullet>|null} [meleeBullets] RoomDownsyncFrame meleeBullets
* @property {number|Long|null} [backendUnconfirmedMask] RoomDownsyncFrame backendUnconfirmedMask
* @property {boolean|null} [shouldForceResync] RoomDownsyncFrame shouldForceResync
*/
/**
@@ -5635,6 +5659,14 @@ $root.protos = (function() {
*/
RoomDownsyncFrame.prototype.backendUnconfirmedMask = $util.Long ? $util.Long.fromBits(0,0,true) : 0;
/**
* RoomDownsyncFrame shouldForceResync.
* @member {boolean} shouldForceResync
* @memberof protos.RoomDownsyncFrame
* @instance
*/
RoomDownsyncFrame.prototype.shouldForceResync = false;
/**
* Creates a new RoomDownsyncFrame instance using the specified properties.
* @function create
@@ -5673,6 +5705,8 @@ $root.protos = (function() {
$root.protos.MeleeBullet.encode(message.meleeBullets[i], writer.uint32(/* id 4, wireType 2 =*/34).fork()).ldelim();
if (message.backendUnconfirmedMask != null && Object.hasOwnProperty.call(message, "backendUnconfirmedMask"))
writer.uint32(/* id 5, wireType 0 =*/40).uint64(message.backendUnconfirmedMask);
if (message.shouldForceResync != null && Object.hasOwnProperty.call(message, "shouldForceResync"))
writer.uint32(/* id 6, wireType 0 =*/48).bool(message.shouldForceResync);
return writer;
};
@@ -5748,6 +5782,10 @@ $root.protos = (function() {
message.backendUnconfirmedMask = reader.uint64();
break;
}
case 6: {
message.shouldForceResync = reader.bool();
break;
}
default:
reader.skipType(tag & 7);
break;
@@ -5815,6 +5853,9 @@ $root.protos = (function() {
if (message.backendUnconfirmedMask != null && message.hasOwnProperty("backendUnconfirmedMask"))
if (!$util.isInteger(message.backendUnconfirmedMask) && !(message.backendUnconfirmedMask && $util.isInteger(message.backendUnconfirmedMask.low) && $util.isInteger(message.backendUnconfirmedMask.high)))
return "backendUnconfirmedMask: integer|Long expected";
if (message.shouldForceResync != null && message.hasOwnProperty("shouldForceResync"))
if (typeof message.shouldForceResync !== "boolean")
return "shouldForceResync: boolean expected";
return null;
};
@@ -5870,6 +5911,8 @@ $root.protos = (function() {
message.backendUnconfirmedMask = object.backendUnconfirmedMask;
else if (typeof object.backendUnconfirmedMask === "object")
message.backendUnconfirmedMask = new $util.LongBits(object.backendUnconfirmedMask.low >>> 0, object.backendUnconfirmedMask.high >>> 0).toNumber(true);
if (object.shouldForceResync != null)
message.shouldForceResync = Boolean(object.shouldForceResync);
return message;
};
@@ -5902,6 +5945,7 @@ $root.protos = (function() {
object.backendUnconfirmedMask = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
} else
object.backendUnconfirmedMask = options.longs === String ? "0" : 0;
object.shouldForceResync = false;
}
if (message.id != null && message.hasOwnProperty("id"))
object.id = message.id;
@@ -5926,6 +5970,8 @@ $root.protos = (function() {
object.backendUnconfirmedMask = options.longs === String ? String(message.backendUnconfirmedMask) : message.backendUnconfirmedMask;
else
object.backendUnconfirmedMask = options.longs === String ? $util.Long.prototype.toString.call(message.backendUnconfirmedMask) : options.longs === Number ? new $util.LongBits(message.backendUnconfirmedMask.low >>> 0, message.backendUnconfirmedMask.high >>> 0).toNumber(true) : message.backendUnconfirmedMask;
if (message.shouldForceResync != null && message.hasOwnProperty("shouldForceResync"))
object.shouldForceResync = message.shouldForceResync;
return object;
};

View File

@@ -17,13 +17,13 @@
},
"encryptJs": true,
"excludeScenes": [
"475b849b-44b3-4390-982d-bd0d9e695093"
"368b10b6-88fc-423c-9fcd-545d9fc673bd"
],
"fb-instant-games": {},
"includeSDKBox": false,
"inlineSpriteFrames": true,
"inlineSpriteFrames_native": true,
"md5Cache": true,
"md5Cache": false,
"mergeStartScene": true,
"optimizeHotUpdate": false,
"orientation": {

View File

@@ -34,7 +34,6 @@
"design-resolution-width": 960,
"excluded-modules": [
"Collider",
"DragonBones",
"Geom Utils",
"Mesh",
"MotionStreak",
@@ -69,7 +68,7 @@
"shelter_z_reducer",
"shelter"
],
"last-module-event-record-time": 1579766511782,
"last-module-event-record-time": 1671346284377,
"simulator-orientation": false,
"simulator-resolution": {
"height": 640,