Compare commits

..

29 Commits

Author SHA1 Message Date
genxium
7a0127b17d Updated README. 2023-01-20 14:32:38 +08:00
genxium
59c8427c70 Enhanced turn-around performance. 2023-01-20 11:29:27 +08:00
genxium
c357ebad3b Updated README again. 2023-01-19 22:19:40 +08:00
genxium
b2e1f7c2a6 Updated README. 2023-01-19 10:45:48 +08:00
genxium
9a8c32197e Added TurnAroundFramesToRecover. 2023-01-19 09:20:52 +08:00
genxium
a82a238ce9 Added frontend log for inspection of "onPeerInputFrameUpsync". 2023-01-18 22:43:10 +08:00
genxium
5b76c5bbfb Minor fix. 2023-01-18 18:03:54 +08:00
genxium
b81c470135 Drafted peer inputFrameUpsync broadcasting mechanism. 2023-01-18 17:53:58 +08:00
genxium
48074d48af Misc fixes for UI alignments. 2023-01-18 12:22:12 +08:00
genxium
342efc623c Made frontend landscape. 2023-01-17 23:35:23 +08:00
genxium
b8e757064d Further enhanced frontend input processing and fixed frame data logging. 2023-01-17 17:38:18 +08:00
genxium
71b9e72592 Minor fix. 2023-01-17 15:16:31 +08:00
genxium
21b48b7c0d Updated frontend input generation. 2023-01-17 13:07:26 +08:00
genxium
fbfca965e6 Minor update. 2023-01-17 12:49:49 +08:00
genxium
b27b567c77 Fixed frontend action triggers. 2023-01-17 12:48:51 +08:00
genxium
e9119530f1 Updated README for UDP discussion. 2023-01-16 23:25:40 +08:00
genxium
e6a4295773 Updated charts in README. 2023-01-15 17:43:02 +08:00
Wing
aa14529bf8 Merge pull request #19 from genxium/explosion
Drafted bullet explosion data structure.
2023-01-15 17:23:52 +08:00
genxium
84af0d1572 Drafted bullet explosion data structure. 2023-01-15 17:21:34 +08:00
genxium
16fb23c376 Updated charts and refs in README. 2023-01-14 23:06:45 +08:00
genxium
d1f8a58154 Updated README. 2023-01-14 09:35:56 +08:00
genxium
89c31e8944 Updated README. 2023-01-13 15:13:27 +08:00
genxium
45380d170f Fixed fireball rollback sync. 2023-01-13 14:55:56 +08:00
genxium
dd9c03404e Fixed fireball rollback mechanism. 2023-01-13 12:10:06 +08:00
genxium
29e402ea71 Integrated onwall movements to multiplayer battle. 2023-01-12 18:09:02 +08:00
genxium
b1e3d6525c Fixes for wall jumping. 2023-01-12 16:09:20 +08:00
genxium
845282db50 Minor fix. 2023-01-12 12:55:57 +08:00
genxium
71a5a7b727 Drafted anti-air attack for Monk. 2023-01-11 22:24:31 +08:00
genxium
934a495d47 Updates for fireball bullet. 2023-01-11 18:42:57 +08:00
87 changed files with 12870 additions and 6845 deletions

View File

@@ -47,3 +47,26 @@ renderFrameId | toApplyInputFrameId
..., ..., ..., 368 | 90 ..., ..., ..., 368 | 90
369, 370, 371, 372 | 91 369, 370, 371, 372 | 91
373, 374, 375, ... | 92 373, 374, 375, ... | 92
# Would using UDP instead of TCP yield better synchronization performance?
Yes, but with non-trivial efforts.
## Neat advantage using UDP
Let's check an actual use case. As soon as an inputFrame becomes all-confirmed, the server should downsync it to all active players -- and upon reception loss of the packet containing this "all-confirmed downsync inputFrame" to a certain player, the server MUST retransmit another packet containing the same inputFrame to that player.
To apply UDP on this use case, additional `ack & retransmission mechanism` would be required, which is a moderately difficult task -- don't just pick a 3rd party lib using TCP flow-control alike `sliding window mechanism`, e.g. [RUDP](https://www.geeksforgeeks.org/reliable-user-datagram-protocol-rudp/)! Here's why.
Assume that the server is downsyncing `sequence of packets[#1, #2, #3, #4, #5, #6, #7, #8, #9, #10]`, when using TCP we get the advantage that each active player is guaranteed to receive that same sequence in the same order -- however in a bad, lossy network when `packet#2` got lost several times for a certain player whose reception window size is just 5, it has to wait for the arrival of `packet#2` at `[_, #3, #4, #5, #6]`, thus unable to process `[#7, #8, #9, #10]` which could contain `unpredictable inputFrame` while `#2` being `correct prediction` for that player.
That's so neat but still an advantage for using UDP! Yet if the TCP flow-control alike `sliding window mechanism` is employed on UDP, such advantage'd be compromised.
To summarize, if UDP is used we need
- an `ack & retransmission mechanism` built on top of it to guarantee reception of critical packets for active players, and
- reception order is not necessary to be reserved (mimic [markConfirmationIfApplicable](https://github.com/genxium/DelayNoMore/blob/v0.9.14/battle_srv/models/room.go#L1085) to maintain `lastAllConfirmedInputFrameId`), but
- TCP flow-control alike `sliding window mechanism` should be avoided to gain advantage over TCP.
## Additional hassles to care about using UDP
When using UDP, it's also necessary to verify authorization of each incoming packet, e.g. by simple time limited symmetric key, due to being connectionless.
## Why not hybrid?
Instead of replacing all use of TCP by UDP, it's more reasonable to keep using TCP for login and the "all-confirmed downsync inputFrames" from server to players (and possibly "upsync inputFrames" from player to server, but tradeoff on that remains to be discussed), while using UDP for broadcasting inputFrames of each individual player asap (either using p2p or not) just for **better prediction performance**!

View File

@@ -1,25 +1,38 @@
# Preface # Preface
This project is a demo for a websocket-based rollback netcode inspired by [GGPO](https://github.com/pond3r/ggpo/blob/master/doc/README.md). This project is a demo for a websocket-based rollback netcode inspired by [GGPO](https://github.com/pond3r/ggpo/blob/master/doc/README.md). As lots of feedbacks ask for a discussion on using UDP instead, I tried to summarize my personal opinion about it in [ConcerningEdgeCases](./ConcerningEdgeCases.md) -- not necessarily correct but that's indeed a question to face :)
_(the following gif is sped up to ~1.5x for file size reduction, kindly note that animations are resumed from a partial progress)_ The following video is recorded over INTERNET using an input delay of 4 frames and it feels SMOOTH when playing! Please also checkout these demo videos
- [source video of the first gif](https://pan.baidu.com/s/1ML6hNupaPHPJRd5rcTvQvw?pwd=8ruc)
- [phone v.s. PC over internet battle#1](https://pan.baidu.com/s/1NuGxuMwrV_jalcToyUZPLg?pwd=kfkr)
- [phone v.s. PC over internet battle#2](https://pan.baidu.com/s/1kMiFdwDHyJpZJ0GGU1Y3eA?pwd=46gd)
- [PC Wifi viewing Phone 4g](https://pan.baidu.com/s/1PJEtC9iB_fcabMWhbx2oAg?pwd=tp7k)
- [PC Wifi viewing Phone Wifi (over internet of course)](https://pan.baidu.com/s/108rvC1CcUdiQeMauXWsLJg?pwd=mn39)
![gif_demo](./charts/jump_sync_spedup.gif) to see how this demo carries out a full 60fps synchronization with the help of _batched input upsync/downsync_ for satisfying network I/O performance.
Please also checkout [this demo video](https://pan.baidu.com/s/1Lmot9cb0pYylfUvC8G4fDg?pwd=ia97) to see how this demo carries out a full 60fps synchronization with the help of _batched input upsync/downsync_ for satisfying network I/O performance. ![gif_demo_1](./charts/internet_fireball_explosion_wallmove_spedup.gif)
The video mainly shows the following features. ![gif_demo_2](./charts/jump_sync_spedup.gif)
- The backend receives inputs from frontend peers and broadcasts back for synchronization.
- The game is recovered for a player upon reconnection. All gifs are sped up to ~1.5x for file size reduction, kindly note that animations are resumed from a partial progress!
- Both backend(Golang) and frontend(JavaScript) execute collision detection and handle collision contacts by the same algorithm. The backend dynamics is togglable by [Room.BackendDynamicsEnabled](https://github.com/genxium/DelayNoMore/blob/v0.5.2/battle_srv/models/room.go#L813), but **when turned off the game couldn't support recovery upon reconnection**.
# Notable Features
- Backend dynamics toggle via [Room.BackendDynamicsEnabled](https://github.com/genxium/DelayNoMore/blob/v0.9.14/battle_srv/models/room.go#L786)
- Recovery upon reconnection (only if backend dynamics is ON)
- Automatically correction for "slow ticker", especially "active slow ticker" which is well-known to be a headache for input synchronization
- Frame data logging toggle for both frontend & backend, useful for debugging out of sync entities when developing new features
_(how input delay roughly works)_ _(how input delay roughly works)_
![input_delay_intro](./charts/InputDelayIntro.jpg) ![input_delay_intro](./charts/InputDelayIntro.jpg)
_(how rollback-and-chase in this project roughly works)_ _(how rollback-and-chase in this project roughly works, kindly note that by the current implementation, each frontend only maintains a `lastAllConfirmedInputFrameId` for all the other peers, because the backend only downsyncs all-confirmed inputFrames, see [markConfirmationIfApplicable](https://github.com/genxium/DelayNoMore/blob/v0.9.14/battle_srv/models/room.go#L1085) for more information -- if a serverless peer-to-peer communication is seriously needed here, consider porting [markConfirmationIfApplicable](https://github.com/genxium/DelayNoMore/blob/v0.9.14/battle_srv/models/room.go#L1085) into frontend for maintaining `lastAllConfirmedInputFrameId` under chaotic reception order of inputFrames from peers)_
![server_clients](./charts/ServerClients.jpg)
![rollback_and_chase_intro](./charts/RollbackAndChase.jpg) ![rollback_and_chase_intro](./charts/RollbackAndChase.jpg)
(By use of [GopherJs](https://github.com/gopherjs/gopherjs), the frontend codes for dynamics are now automatically generated)
![floating_point_accumulation_err](./charts/AvoidingFloatingPointAccumulationErr.jpg) ![floating_point_accumulation_err](./charts/AvoidingFloatingPointAccumulationErr.jpg)
# 1. Building & running # 1. Building & running
@@ -27,7 +40,8 @@ _(how rollback-and-chase in this project roughly works)_
## 1.1 Tools to install ## 1.1 Tools to install
### Backend ### Backend
- [Command Line Tools for Xcode](https://developer.apple.com/download/all/?q=command%20line%20tools) (on OSX) or [TDM-GCC](https://jmeubank.github.io/tdm-gcc/download/) (on Windows) (a `make` executable mandatory) - [Command Line Tools for Xcode](https://developer.apple.com/download/all/?q=command%20line%20tools) (on OSX) or [TDM-GCC](https://jmeubank.github.io/tdm-gcc/download/) (on Windows) (a `make` executable mandatory)
- [Golang1.18.6](https://golang.org/dl/) (brought down to 1.18 for GopherJs support, mandatory, in China please try a mirror site like [that of ustc](https://mirrors.ustc.edu.cn/golang/)) - [Golang1.18.6](https://golang.org/dl/) (brought down to 1.18 for _GopherJs_ support, mandatory, in China please try a mirror site like [that of ustc](https://mirrors.ustc.edu.cn/golang/))
- [GopherJs1.18.0-beta1](https://github.com/gopherjs/gopherjs/tree/v1.18.0-beta1) (optional, only for developemnt)
- [MySQL 5.7](https://dev.mysql.com/downloads/windows/installer/5.7.html) (mandatory, for OSX not all versions of 5.7 can be found thus 5.7.24 is recommended) - [MySQL 5.7](https://dev.mysql.com/downloads/windows/installer/5.7.html) (mandatory, for OSX not all versions of 5.7 can be found thus 5.7.24 is recommended)
- [Redis 3.0.503 or above](https://redis.io/download/) (mandatory) - [Redis 3.0.503 or above](https://redis.io/download/) (mandatory)
- [skeema](https://www.skeema.io/) (optional, only for convenient MySQL schema provisioning) - [skeema](https://www.skeema.io/) (optional, only for convenient MySQL schema provisioning)
@@ -60,7 +74,7 @@ user@proj-root/battle_srv/configs> cp -r ./configs.template ./configs
user@proj-root/frontend/assets/plugin_scripts> cp ./conf.js.template ./conf.js user@proj-root/frontend/assets/plugin_scripts> cp ./conf.js.template ./conf.js
``` ```
## 1.2 Actual building & running ## 1.3 Actual building & running
### Backend ### Backend
``` ```
### The following command runs mysql-server in foreground, it's almost NEVER run in such a way, please find a proper way to run it for yourself ### The following command runs mysql-server in foreground, it's almost NEVER run in such a way, please find a proper way to run it for yourself
@@ -89,3 +103,11 @@ ErrFatal {"err": "MISCONF Redis is configured to save RDB snapshots, but
``` ```
Just restart your `redis-server` process. Just restart your `redis-server` process.
### 2.2 Why not show "PING value" on frontend display?
The most important reason for not showing "PING value" is simple: in most games the "PING value" is collected by a dedicated kernel thread which doesn't interfere the UI thread or the primary networking thread. As this demo primarily runs on browser by far, I don't have this capability easily.
Moreover, in practice I found that to spot sync anomalies, the following tools are much more useful than the "PING VALUE".
- Detection of [prediction mismatch on the frontend](https://github.com/genxium/DelayNoMore/blob/v0.9.19/frontend/assets/scripts/Map.js#L842).
- Detection of [type#1 forceConfirmation on the backend](https://github.com/genxium/DelayNoMore/blob/v0.9.19/battle_srv/models/room.go#L1246).
- Detection of [type#2 forceConfirmation on the backend](https://github.com/genxium/DelayNoMore/blob/v0.9.19/battle_srv/models/room.go#L1259).

View File

@@ -89,6 +89,7 @@ func setRouter(router *gin.Engine) {
router.StaticFS("/asset", http.Dir(filepath.Join(Conf.General.AppRoot, "asset"))) router.StaticFS("/asset", http.Dir(filepath.Join(Conf.General.AppRoot, "asset")))
router.GET("/ping", f) router.GET("/ping", f)
router.GET("/tsrht", ws.Serve) router.GET("/tsrht", ws.Serve)
router.GET("/tsrhtSecondary", ws.HandleSecondaryWsSessionForPlayer)
apiRouter := router.Group("/api") apiRouter := router.Group("/api")
{ {

View File

@@ -38,6 +38,10 @@ func toPbRoomDownsyncFrame(rdf *battle.RoomDownsyncFrame) *pb.RoomDownsyncFrame
BattleState: last.BattleState, BattleState: last.BattleState,
CharacterState: last.CharacterState, CharacterState: last.CharacterState,
InAir: last.InAir, InAir: last.InAir,
OnWall: last.OnWall,
OnWallNormX: last.OnWallNormX,
OnWallNormY: last.OnWallNormY,
CapturedByInertia: last.CapturedByInertia,
JoinIndex: last.JoinIndex, JoinIndex: last.JoinIndex,
BulletTeamId: last.BulletTeamId, BulletTeamId: last.BulletTeamId,
ChCollisionTeamId: last.ChCollisionTeamId, ChCollisionTeamId: last.ChCollisionTeamId,
@@ -52,62 +56,74 @@ func toPbRoomDownsyncFrame(rdf *battle.RoomDownsyncFrame) *pb.RoomDownsyncFrame
for i, last := range rdf.MeleeBullets { for i, last := range rdf.MeleeBullets {
pbBullet := &pb.MeleeBullet{ pbBullet := &pb.MeleeBullet{
BulletLocalId: last.BulletLocalId, BulletLocalId: last.BattleAttr.BulletLocalId,
OriginatedRenderFrameId: last.OriginatedRenderFrameId, OriginatedRenderFrameId: last.BattleAttr.OriginatedRenderFrameId,
OffenderJoinIndex: last.OffenderJoinIndex, OffenderJoinIndex: last.BattleAttr.OffenderJoinIndex,
TeamId: last.BattleAttr.TeamId,
StartupFrames: last.StartupFrames, StartupFrames: last.Bullet.StartupFrames,
CancellableStFrame: last.CancellableStFrame, CancellableStFrame: last.Bullet.CancellableStFrame,
CancellableEdFrame: last.CancellableEdFrame, CancellableEdFrame: last.Bullet.CancellableEdFrame,
ActiveFrames: last.ActiveFrames, ActiveFrames: last.Bullet.ActiveFrames,
HitStunFrames: last.HitStunFrames, HitStunFrames: last.Bullet.HitStunFrames,
BlockStunFrames: last.BlockStunFrames, BlockStunFrames: last.Bullet.BlockStunFrames,
PushbackVelX: last.PushbackVelX, PushbackVelX: last.Bullet.PushbackVelX,
PushbackVelY: last.PushbackVelY, PushbackVelY: last.Bullet.PushbackVelY,
Damage: last.Damage, Damage: last.Bullet.Damage,
SelfLockVelX: last.SelfLockVelX, SelfLockVelX: last.Bullet.SelfLockVelX,
SelfLockVelY: last.SelfLockVelY, SelfLockVelY: last.Bullet.SelfLockVelY,
HitboxOffsetX: last.HitboxOffsetX, HitboxOffsetX: last.Bullet.HitboxOffsetX,
HitboxOffsetY: last.HitboxOffsetY, HitboxOffsetY: last.Bullet.HitboxOffsetY,
HitboxSizeX: last.HitboxSizeX, HitboxSizeX: last.Bullet.HitboxSizeX,
HitboxSizeY: last.HitboxSizeY, HitboxSizeY: last.Bullet.HitboxSizeY,
BlowUp: last.BlowUp, BlowUp: last.Bullet.BlowUp,
TeamId: last.TeamId,
SpeciesId: last.Bullet.SpeciesId,
ExplosionFrames: last.Bullet.ExplosionFrames,
BlState: last.BlState,
FramesInBlState: last.FramesInBlState,
} }
ret.MeleeBullets[i] = pbBullet ret.MeleeBullets[i] = pbBullet
} }
for i, last := range rdf.FireballBullets { for i, last := range rdf.FireballBullets {
pbBullet := &pb.FireballBullet{ pbBullet := &pb.FireballBullet{
BulletLocalId: last.BulletLocalId, BulletLocalId: last.BattleAttr.BulletLocalId,
OriginatedRenderFrameId: last.OriginatedRenderFrameId, OriginatedRenderFrameId: last.BattleAttr.OriginatedRenderFrameId,
OffenderJoinIndex: last.OffenderJoinIndex, OffenderJoinIndex: last.BattleAttr.OffenderJoinIndex,
TeamId: last.BattleAttr.TeamId,
StartupFrames: last.StartupFrames, StartupFrames: last.Bullet.StartupFrames,
CancellableStFrame: last.CancellableStFrame, CancellableStFrame: last.Bullet.CancellableStFrame,
CancellableEdFrame: last.CancellableEdFrame, CancellableEdFrame: last.Bullet.CancellableEdFrame,
ActiveFrames: last.ActiveFrames, ActiveFrames: last.Bullet.ActiveFrames,
HitStunFrames: last.HitStunFrames, HitStunFrames: last.Bullet.HitStunFrames,
BlockStunFrames: last.BlockStunFrames, BlockStunFrames: last.Bullet.BlockStunFrames,
PushbackVelX: last.PushbackVelX, PushbackVelX: last.Bullet.PushbackVelX,
PushbackVelY: last.PushbackVelY, PushbackVelY: last.Bullet.PushbackVelY,
Damage: last.Damage, Damage: last.Bullet.Damage,
SelfLockVelX: last.SelfLockVelX, SelfLockVelX: last.Bullet.SelfLockVelX,
SelfLockVelY: last.SelfLockVelY, SelfLockVelY: last.Bullet.SelfLockVelY,
HitboxOffsetX: last.HitboxOffsetX, HitboxOffsetX: last.Bullet.HitboxOffsetX,
HitboxOffsetY: last.HitboxOffsetY, HitboxOffsetY: last.Bullet.HitboxOffsetY,
HitboxSizeX: last.HitboxSizeX, HitboxSizeX: last.Bullet.HitboxSizeX,
HitboxSizeY: last.HitboxSizeY, HitboxSizeY: last.Bullet.HitboxSizeY,
BlowUp: last.BlowUp, BlowUp: last.Bullet.BlowUp,
TeamId: last.TeamId,
SpeciesId: last.Bullet.SpeciesId,
ExplosionFrames: last.Bullet.ExplosionFrames,
BlState: last.BlState,
FramesInBlState: last.FramesInBlState,
VirtualGridX: last.VirtualGridX, VirtualGridX: last.VirtualGridX,
VirtualGridY: last.VirtualGridY, VirtualGridY: last.VirtualGridY,
@@ -147,6 +163,10 @@ func toPbPlayers(modelInstances map[int32]*Player, withMetaInfo bool) []*pb.Play
BattleState: last.BattleState, BattleState: last.BattleState,
CharacterState: last.CharacterState, CharacterState: last.CharacterState,
InAir: last.InAir, InAir: last.InAir,
OnWall: last.OnWall,
OnWallNormX: last.OnWallNormX,
OnWallNormY: last.OnWallNormY,
CapturedByInertia: last.CapturedByInertia,
JoinIndex: last.JoinIndex, JoinIndex: last.JoinIndex,
BulletTeamId: last.BulletTeamId, BulletTeamId: last.BulletTeamId,
ChCollisionTeamId: last.ChCollisionTeamId, ChCollisionTeamId: last.ChCollisionTeamId,
@@ -195,6 +215,10 @@ func toJsPlayers(modelInstances map[int32]*Player) []*battle.PlayerDownsync {
MaxHp: last.MaxHp, MaxHp: last.MaxHp,
ColliderRadius: last.ColliderRadius, ColliderRadius: last.ColliderRadius,
InAir: last.InAir, InAir: last.InAir,
OnWall: last.OnWall,
OnWallNormX: last.OnWallNormX,
OnWallNormY: last.OnWallNormY,
CapturedByInertia: last.CapturedByInertia,
Score: last.Score, Score: last.Score,
Removed: last.Removed, Removed: last.Removed,
} }

View File

@@ -31,6 +31,7 @@ const (
DOWNSYNC_MSG_ACT_INPUT_BATCH = int32(2) DOWNSYNC_MSG_ACT_INPUT_BATCH = int32(2)
DOWNSYNC_MSG_ACT_BATTLE_STOPPED = int32(3) DOWNSYNC_MSG_ACT_BATTLE_STOPPED = int32(3)
DOWNSYNC_MSG_ACT_FORCED_RESYNC = int32(4) DOWNSYNC_MSG_ACT_FORCED_RESYNC = int32(4)
DOWNSYNC_MSG_ACT_PEER_INPUT_BATCH = int32(5)
DOWNSYNC_MSG_ACT_BATTLE_READY_TO_START = int32(-1) DOWNSYNC_MSG_ACT_BATTLE_READY_TO_START = int32(-1)
DOWNSYNC_MSG_ACT_BATTLE_START = int32(0) DOWNSYNC_MSG_ACT_BATTLE_START = int32(0)
@@ -117,9 +118,14 @@ type Room struct {
* Moreover, during the invocation of `PlayerSignalToCloseDict`, the `Player` instance is supposed to be deallocated (though not synchronously). * Moreover, during the invocation of `PlayerSignalToCloseDict`, the `Player` instance is supposed to be deallocated (though not synchronously).
*/ */
PlayerDownsyncSessionDict map[int32]*websocket.Conn PlayerDownsyncSessionDict map[int32]*websocket.Conn
PlayerDownsyncChanDict map[int32](chan pb.InputsBufferSnapshot)
PlayerActiveWatchdogDict map[int32](*Watchdog)
PlayerSignalToCloseDict map[int32]SignalToCloseConnCbType PlayerSignalToCloseDict map[int32]SignalToCloseConnCbType
PlayerDownsyncChanDict map[int32](chan pb.InputsBufferSnapshot)
PlayerSecondaryDownsyncSessionDict map[int32]*websocket.Conn
PlayerSecondarySignalToCloseDict map[int32]SignalToCloseConnCbType
PlayerSecondaryDownsyncChanDict map[int32](chan pb.InputsBufferSnapshot)
PlayerActiveWatchdogDict map[int32](*Watchdog)
Score float32 Score float32
State int32 State int32
Index int Index int
@@ -184,7 +190,7 @@ func (pR *Room) AddPlayerIfPossible(pPlayerFromDbInit *Player, session *websocke
pR.PlayerSignalToCloseDict[playerId] = signalToCloseConnOfThisPlayer pR.PlayerSignalToCloseDict[playerId] = signalToCloseConnOfThisPlayer
newWatchdog := NewWatchdog(ConstVals.Ws.WillKickIfInactiveFor, func() { newWatchdog := NewWatchdog(ConstVals.Ws.WillKickIfInactiveFor, func() {
Logger.Warn("Conn inactive watchdog triggered#1:", zap.Any("playerId", playerId), zap.Any("roomId", pR.Id), zap.Any("roomState", pR.State), zap.Any("roomEffectivePlayerCount", pR.EffectivePlayerCount)) Logger.Warn("Conn inactive watchdog triggered#1:", zap.Any("playerId", playerId), zap.Any("roomId", pR.Id), zap.Any("roomState", pR.State), zap.Any("roomEffectivePlayerCount", pR.EffectivePlayerCount))
signalToCloseConnOfThisPlayer(Constants.RetCode.ActiveWatchdog, "") pR.signalToCloseAllSessionsOfPlayer(playerId, Constants.RetCode.ActiveWatchdog)
}) })
newWatchdog.Stop() newWatchdog.Stop()
pR.PlayerActiveWatchdogDict[playerId] = newWatchdog pR.PlayerActiveWatchdogDict[playerId] = newWatchdog
@@ -221,7 +227,7 @@ func (pR *Room) ReAddPlayerIfPossible(pTmpPlayerInstance *Player, session *webso
pR.PlayerSignalToCloseDict[playerId] = signalToCloseConnOfThisPlayer pR.PlayerSignalToCloseDict[playerId] = signalToCloseConnOfThisPlayer
pR.PlayerActiveWatchdogDict[playerId] = NewWatchdog(ConstVals.Ws.WillKickIfInactiveFor, func() { pR.PlayerActiveWatchdogDict[playerId] = NewWatchdog(ConstVals.Ws.WillKickIfInactiveFor, func() {
Logger.Warn("Conn inactive watchdog triggered#2:", zap.Any("playerId", playerId), zap.Any("roomId", pR.Id), zap.Any("roomState", pR.State), zap.Any("roomEffectivePlayerCount", pR.EffectivePlayerCount)) Logger.Warn("Conn inactive watchdog triggered#2:", zap.Any("playerId", playerId), zap.Any("roomId", pR.Id), zap.Any("roomState", pR.State), zap.Any("roomEffectivePlayerCount", pR.EffectivePlayerCount))
signalToCloseConnOfThisPlayer(Constants.RetCode.ActiveWatchdog, "") pR.signalToCloseAllSessionsOfPlayer(playerId, Constants.RetCode.ActiveWatchdog)
}) // For ReAdded player the new watchdog starts immediately }) // For ReAdded player the new watchdog starts immediately
Logger.Warn("ReAddPlayerIfPossible finished.", zap.Any("roomId", pR.Id), zap.Any("playerId", playerId), zap.Any("joinIndex", pEffectiveInRoomPlayerInstance.JoinIndex), zap.Any("playerBattleState", pEffectiveInRoomPlayerInstance.BattleState), zap.Any("roomState", pR.State), zap.Any("roomEffectivePlayerCount", pR.EffectivePlayerCount), zap.Any("AckingFrameId", pEffectiveInRoomPlayerInstance.AckingFrameId), zap.Any("AckingInputFrameId", pEffectiveInRoomPlayerInstance.AckingInputFrameId), zap.Any("LastSentInputFrameId", pEffectiveInRoomPlayerInstance.LastSentInputFrameId)) Logger.Warn("ReAddPlayerIfPossible finished.", zap.Any("roomId", pR.Id), zap.Any("playerId", playerId), zap.Any("joinIndex", pEffectiveInRoomPlayerInstance.JoinIndex), zap.Any("playerBattleState", pEffectiveInRoomPlayerInstance.BattleState), zap.Any("roomState", pR.State), zap.Any("roomEffectivePlayerCount", pR.EffectivePlayerCount), zap.Any("AckingFrameId", pEffectiveInRoomPlayerInstance.AckingFrameId), zap.Any("AckingInputFrameId", pEffectiveInRoomPlayerInstance.AckingInputFrameId), zap.Any("LastSentInputFrameId", pEffectiveInRoomPlayerInstance.LastSentInputFrameId))
@@ -335,7 +341,20 @@ func (pR *Room) playerDownsyncStr(player *battle.PlayerDownsync) string {
if player.InAir { if player.InAir {
inAirInt = 1 inAirInt = 1
} }
s := fmt.Sprintf("{%d,%d,%d,%d,%d,%d,%d}", player.JoinIndex, player.VirtualGridX, player.VirtualGridY, player.VelX, player.VelY, player.FramesToRecover, inAirInt) onWallInt := 0
if player.OnWall {
onWallInt = 1
}
s := fmt.Sprintf("{%d,%d,%d,%d,%d,%d,%d,%d}", player.JoinIndex, player.VirtualGridX, player.VirtualGridY, player.VelX, player.VelY, player.FramesToRecover, inAirInt, onWallInt)
return s
}
func (pR *Room) fireballDownsyncStr(fireball *battle.FireballBullet) string {
if nil == fireball {
return ""
}
s := fmt.Sprintf("{%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d}", fireball.BattleAttr.BulletLocalId, fireball.BattleAttr.OriginatedRenderFrameId, fireball.BattleAttr.OffenderJoinIndex, fireball.VirtualGridX, fireball.VirtualGridY, fireball.VelX, fireball.VelY, fireball.DirX, fireball.DirY, fireball.Bullet.HitboxSizeX, fireball.Bullet.HitboxSizeY)
return s return s
} }
@@ -365,7 +384,11 @@ func (pR *Room) rdfIdToActuallyUsedInputString() string {
for _, player := range rdf.PlayersArr { for _, player := range rdf.PlayersArr {
playersStrBldr = append(playersStrBldr, pR.playerDownsyncStr(player)) playersStrBldr = append(playersStrBldr, pR.playerDownsyncStr(player))
} }
s = append(s, fmt.Sprintf("rdfId:%d\nplayers:[%v]\nactuallyUsedinputList:{%v}", rdfId, strings.Join(playersStrBldr, ","), pR.inputFrameDownsyncStr(pR.rdfIdToActuallyUsedInput[rdfId]))) fireballsStrBldr := make([]string, 0, len(rdf.FireballBullets))
for _, fireball := range rdf.FireballBullets {
fireballsStrBldr = append(fireballsStrBldr, pR.fireballDownsyncStr(fireball))
}
s = append(s, fmt.Sprintf("rdfId:%d\nplayers:[%v]\nfireballs:[%v]\nactuallyUsedinputList:{%v}", rdfId, strings.Join(playersStrBldr, ","), strings.Join(fireballsStrBldr, ","), pR.inputFrameDownsyncStr(pR.rdfIdToActuallyUsedInput[rdfId])))
} }
return strings.Join(s, "\n") return strings.Join(s, "\n")
@@ -381,7 +404,7 @@ func (pR *Room) StartBattle() {
for _, player := range pR.Players { for _, player := range pR.Players {
speciesId := int(player.JoinIndex - 1) // FIXME: Hardcoded the values for now speciesId := int(player.JoinIndex - 1) // FIXME: Hardcoded the values for now
if player.JoinIndex == 2 { if player.JoinIndex == 1 {
speciesId = 4096 speciesId = 4096
} }
chosenCh := battle.Characters[speciesId] chosenCh := battle.Characters[speciesId]
@@ -465,7 +488,7 @@ func (pR *Room) StartBattle() {
kickoffFrameJs := pR.RenderFrameBuffer.GetByFrameId(0).(*battle.RoomDownsyncFrame) kickoffFrameJs := pR.RenderFrameBuffer.GetByFrameId(0).(*battle.RoomDownsyncFrame)
pbKickOffRenderFrame := toPbRoomDownsyncFrame(kickoffFrameJs) pbKickOffRenderFrame := toPbRoomDownsyncFrame(kickoffFrameJs)
pbKickOffRenderFrame.SpeciesIdList = pR.SpeciesIdList pbKickOffRenderFrame.SpeciesIdList = pR.SpeciesIdList
pR.sendSafely(pbKickOffRenderFrame, nil, DOWNSYNC_MSG_ACT_BATTLE_START, playerId, true) pR.sendSafely(pbKickOffRenderFrame, nil, DOWNSYNC_MSG_ACT_BATTLE_START, playerId, true, MAGIC_JOIN_INDEX_DEFAULT)
} }
Logger.Info(fmt.Sprintf("In `battleMainLoop` for roomId=%v sent out kickoffFrame", pR.Id)) Logger.Info(fmt.Sprintf("In `battleMainLoop` for roomId=%v sent out kickoffFrame", pR.Id))
} }
@@ -492,7 +515,7 @@ func (pR *Room) StartBattle() {
} }
} }
downsyncLoop := func(playerId int32, player *Player, playerDownsyncChan chan pb.InputsBufferSnapshot) { downsyncLoop := func(playerId int32, player *Player, playerDownsyncChan chan pb.InputsBufferSnapshot, playerSecondaryDownsyncChan chan pb.InputsBufferSnapshot) {
defer func() { defer func() {
if r := recover(); r != nil { if r := recover(); r != nil {
Logger.Error("downsyncLoop, recovery spot#1, recovered from: ", zap.Any("roomId", pR.Id), zap.Any("playerId", playerId), zap.Any("panic", r)) Logger.Error("downsyncLoop, recovery spot#1, recovered from: ", zap.Any("roomId", pR.Id), zap.Any("playerId", playerId), zap.Any("panic", r))
@@ -500,19 +523,23 @@ func (pR *Room) StartBattle() {
Logger.Info(fmt.Sprintf("The `downsyncLoop` for (roomId=%v, playerId=%v) is stopped@renderFrameId=%v", pR.Id, playerId, pR.RenderFrameId)) Logger.Info(fmt.Sprintf("The `downsyncLoop` for (roomId=%v, playerId=%v) is stopped@renderFrameId=%v", pR.Id, playerId, pR.RenderFrameId))
}() }()
Logger.Debug(fmt.Sprintf("Started downsyncLoop for (roomId: %d, playerId:%d, playerDownsyncChan:%p)", pR.Id, playerId, playerDownsyncChan)) //Logger.Info(fmt.Sprintf("Started downsyncLoop for (roomId: %d, playerId:%d, playerDownsyncChan:%p)", pR.Id, playerId, playerDownsyncChan))
for { for {
select {
case inputsBufferSnapshot := <-playerDownsyncChan:
nowBattleState := atomic.LoadInt32(&pR.State) nowBattleState := atomic.LoadInt32(&pR.State)
switch nowBattleState { switch nowBattleState {
case RoomBattleStateIns.IDLE, RoomBattleStateIns.STOPPING_BATTLE_FOR_SETTLEMENT, RoomBattleStateIns.IN_SETTLEMENT, 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)) Logger.Warn(fmt.Sprintf("Battle is not waiting/preparing/active for playerDownsyncChan for (roomId: %d, playerId:%d)", pR.Id, playerId))
return return
} }
select {
case inputsBufferSnapshot := <-playerDownsyncChan:
pR.downsyncToSinglePlayer(playerId, player, inputsBufferSnapshot.RefRenderFrameId, inputsBufferSnapshot.UnconfirmedMask, inputsBufferSnapshot.ToSendInputFrameDownsyncs, inputsBufferSnapshot.ShouldForceResync) 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)) //Logger.Info(fmt.Sprintf("Sent inputsBufferSnapshot(refRenderFrameId:%d, unconfirmedMask:%v) to for (roomId: %d, playerId:%d)#2", inputsBufferSnapshot.RefRenderFrameId, inputsBufferSnapshot.UnconfirmedMask, pR.Id, playerId))
case inputsBufferSnapshot2 := <-playerSecondaryDownsyncChan:
pR.downsyncPeerInputFrameUpsyncToSinglePlayer(playerId, player, inputsBufferSnapshot2.ToSendInputFrameDownsyncs, inputsBufferSnapshot2.PeerJoinIndex)
//Logger.Info(fmt.Sprintf("Sent secondary inputsBufferSnapshot to for (roomId: %d, playerId:%d)#2", pR.Id, playerId))
default: default:
} }
} }
@@ -525,7 +552,8 @@ func (pR *Room) StartBattle() {
Each "playerDownsyncChan" stays alive through out the lifecycle of room instead of each "playerDownsyncSession", i.e. not closed or dereferenced upon disconnection. Each "playerDownsyncChan" stays alive through out the lifecycle of room instead of each "playerDownsyncSession", i.e. not closed or dereferenced upon disconnection.
*/ */
pR.PlayerDownsyncChanDict[playerId] = make(chan pb.InputsBufferSnapshot, pR.InputsBuffer.N) pR.PlayerDownsyncChanDict[playerId] = make(chan pb.InputsBufferSnapshot, pR.InputsBuffer.N)
go downsyncLoop(playerId, player, pR.PlayerDownsyncChanDict[playerId]) pR.PlayerSecondaryDownsyncChanDict[playerId] = make(chan pb.InputsBufferSnapshot, pR.InputsBuffer.N)
go downsyncLoop(playerId, player, pR.PlayerDownsyncChanDict[playerId], pR.PlayerSecondaryDownsyncChanDict[playerId])
} }
pR.onBattlePrepare(func() { pR.onBattlePrepare(func() {
@@ -582,6 +610,16 @@ func (pR *Room) OnBattleCmdReceived(pReq *pb.WsReq) {
inputsBufferSnapshot := pR.markConfirmationIfApplicable(inputFrameUpsyncBatch, playerId, player) inputsBufferSnapshot := pR.markConfirmationIfApplicable(inputFrameUpsyncBatch, playerId, player)
if nil != inputsBufferSnapshot { if nil != inputsBufferSnapshot {
pR.downsyncToAllPlayers(inputsBufferSnapshot) pR.downsyncToAllPlayers(inputsBufferSnapshot)
} else {
// no new all-confirmed
toSendInputFrameDownsyncs := pR.cloneInputsBuffer(inputFrameUpsyncBatch[0].InputFrameId, inputFrameUpsyncBatch[len(inputFrameUpsyncBatch)-1].InputFrameId+1)
inputsBufferSnapshot = &pb.InputsBufferSnapshot{
ToSendInputFrameDownsyncs: toSendInputFrameDownsyncs,
PeerJoinIndex: player.JoinIndex,
}
//Logger.Info(fmt.Sprintf("OnBattleCmdReceived no new all-confirmed: roomId=%v, fromPlayerId=%v, forming peer broadcasting snapshot=%v", pR.Id, playerId, inputsBufferSnapshot))
pR.broadcastPeerUpsyncForBetterPrediction(inputsBufferSnapshot)
} }
} }
@@ -633,7 +671,7 @@ func (pR *Room) StopBattleForSettlement() {
PlayersArr: toPbPlayers(pR.Players, false), PlayersArr: toPbPlayers(pR.Players, false),
CountdownNanos: -1, // TODO: Replace this magic constant! CountdownNanos: -1, // TODO: Replace this magic constant!
} }
pR.sendSafely(&assembledFrame, nil, DOWNSYNC_MSG_ACT_BATTLE_STOPPED, playerId, true) pR.sendSafely(&assembledFrame, nil, DOWNSYNC_MSG_ACT_BATTLE_STOPPED, playerId, true, MAGIC_JOIN_INDEX_DEFAULT)
} }
// Note that `pR.onBattleStoppedForSettlement` will be called by `battleMainLoop`. // Note that `pR.onBattleStoppedForSettlement` will be called by `battleMainLoop`.
} }
@@ -662,7 +700,7 @@ func (pR *Room) onBattlePrepare(cb BattleStartCbType) {
Logger.Info("Sending out frame for RoomBattleState.PREPARE:", zap.Any("battleReadyToStartFrame", battleReadyToStartFrame)) Logger.Info("Sending out frame for RoomBattleState.PREPARE:", zap.Any("battleReadyToStartFrame", battleReadyToStartFrame))
for _, player := range pR.Players { for _, player := range pR.Players {
pR.sendSafely(battleReadyToStartFrame, nil, DOWNSYNC_MSG_ACT_BATTLE_READY_TO_START, player.Id, true) pR.sendSafely(battleReadyToStartFrame, nil, DOWNSYNC_MSG_ACT_BATTLE_READY_TO_START, player.Id, true, MAGIC_JOIN_INDEX_DEFAULT)
} }
battlePreparationNanos := int64(6000000000) battlePreparationNanos := int64(6000000000)
@@ -731,6 +769,7 @@ func (pR *Room) OnDismissed() {
pR.CharacterConfigsArr = make([]*battle.CharacterConfig, pR.Capacity) pR.CharacterConfigsArr = make([]*battle.CharacterConfig, pR.Capacity)
pR.CollisionSysMap = make(map[int32]*resolv.Object) pR.CollisionSysMap = make(map[int32]*resolv.Object)
pR.PlayerDownsyncSessionDict = make(map[int32]*websocket.Conn) pR.PlayerDownsyncSessionDict = make(map[int32]*websocket.Conn)
pR.PlayerSecondaryDownsyncSessionDict = make(map[int32]*websocket.Conn)
for _, oldWatchdog := range pR.PlayerActiveWatchdogDict { for _, oldWatchdog := range pR.PlayerActiveWatchdogDict {
oldWatchdog.Stop() oldWatchdog.Stop()
} }
@@ -739,7 +778,12 @@ func (pR *Room) OnDismissed() {
close(oldChan) close(oldChan)
} }
pR.PlayerDownsyncChanDict = make(map[int32](chan pb.InputsBufferSnapshot)) pR.PlayerDownsyncChanDict = make(map[int32](chan pb.InputsBufferSnapshot))
for _, oldChan := range pR.PlayerSecondaryDownsyncChanDict {
close(oldChan)
}
pR.PlayerSecondaryDownsyncChanDict = make(map[int32](chan pb.InputsBufferSnapshot))
pR.PlayerSignalToCloseDict = make(map[int32]SignalToCloseConnCbType) pR.PlayerSignalToCloseDict = make(map[int32]SignalToCloseConnCbType)
pR.PlayerSecondarySignalToCloseDict = make(map[int32]SignalToCloseConnCbType)
pR.JoinIndexBooleanArr = make([]bool, pR.Capacity) pR.JoinIndexBooleanArr = make([]bool, pR.Capacity)
pR.RenderCacheSize = 1024 pR.RenderCacheSize = 1024
pR.RenderFrameBuffer = battle.NewRingBuffer(pR.RenderCacheSize) pR.RenderFrameBuffer = battle.NewRingBuffer(pR.RenderCacheSize)
@@ -764,7 +808,7 @@ func (pR *Room) OnDismissed() {
pR.BattleDurationFrames = int32(60 * serverFps) pR.BattleDurationFrames = int32(60 * serverFps)
pR.BattleDurationNanos = int64(pR.BattleDurationFrames) * (pR.RollbackEstimatedDtNanos + 1) pR.BattleDurationNanos = int64(pR.BattleDurationFrames) * (pR.RollbackEstimatedDtNanos + 1)
pR.InputFrameUpsyncDelayTolerance = battle.ConvertToNoDelayInputFrameId(pR.NstDelayFrames) - 1 // this value should be strictly smaller than (NstDelayFrames >> InputScaleFrames), otherwise "type#1 forceConfirmation" might become a lag avalanche pR.InputFrameUpsyncDelayTolerance = battle.ConvertToNoDelayInputFrameId(pR.NstDelayFrames) - 1 // this value should be strictly smaller than (NstDelayFrames >> InputScaleFrames), otherwise "type#1 forceConfirmation" might become a lag avalanche
pR.MaxChasingRenderFramesPerUpdate = 12 // Don't set this value too high to avoid exhausting frontend CPU within a single frame pR.MaxChasingRenderFramesPerUpdate = 4 // Don't set this value too high to avoid exhausting frontend CPU within a single frame
pR.BackendDynamicsEnabled = true // [WARNING] When "false", recovery upon reconnection wouldn't work! pR.BackendDynamicsEnabled = true // [WARNING] When "false", recovery upon reconnection wouldn't work!
pR.ForceAllResyncOnAnyActiveSlowTicker = true // See tradeoff discussion in "downsyncToAllPlayers" pR.ForceAllResyncOnAnyActiveSlowTicker = true // See tradeoff discussion in "downsyncToAllPlayers"
@@ -782,19 +826,24 @@ func (pR *Room) OnDismissed() {
} }
func (pR *Room) expelPlayerDuringGame(playerId int32) { func (pR *Room) expelPlayerDuringGame(playerId int32) {
if signalToCloseConnOfThisPlayer, existent := pR.PlayerSignalToCloseDict[playerId]; existent { pR.signalToCloseAllSessionsOfPlayer(playerId, Constants.RetCode.UnknownError)
signalToCloseConnOfThisPlayer(Constants.RetCode.UnknownError, "") // TODO: Specify an error code
}
pR.onPlayerExpelledDuringGame(playerId) pR.onPlayerExpelledDuringGame(playerId)
} }
func (pR *Room) expelPlayerForDismissal(playerId int32) { func (pR *Room) expelPlayerForDismissal(playerId int32) {
if signalToCloseConnOfThisPlayer, existent := pR.PlayerSignalToCloseDict[playerId]; existent { pR.signalToCloseAllSessionsOfPlayer(playerId, Constants.RetCode.UnknownError)
signalToCloseConnOfThisPlayer(Constants.RetCode.UnknownError, "") // TODO: Specify an error code
}
pR.onPlayerExpelledForDismissal(playerId) pR.onPlayerExpelledForDismissal(playerId)
} }
func (pR *Room) signalToCloseAllSessionsOfPlayer(playerId int32, retCode int) {
if signalToCloseConnOfThisPlayer, existent := pR.PlayerSignalToCloseDict[playerId]; existent {
signalToCloseConnOfThisPlayer(retCode, "") // TODO: Specify an error code
}
if signalToCloseConnOfThisPlayer2, existent2 := pR.PlayerSecondarySignalToCloseDict[playerId]; existent2 {
signalToCloseConnOfThisPlayer2(retCode, "") // TODO: Specify an error code
}
}
func (pR *Room) onPlayerExpelledDuringGame(playerId int32) { func (pR *Room) onPlayerExpelledDuringGame(playerId int32) {
pR.onPlayerLost(playerId) pR.onPlayerLost(playerId)
} }
@@ -812,6 +861,10 @@ func (pR *Room) OnPlayerDisconnected(playerId int32) {
} }
}() }()
if signalToCloseConnOfThisPlayer2, existent2 := pR.PlayerSecondarySignalToCloseDict[playerId]; existent2 {
signalToCloseConnOfThisPlayer2(Constants.RetCode.UnknownError, "") // TODO: Specify an error code
}
if player, existent := pR.Players[playerId]; existent { if player, existent := pR.Players[playerId]; existent {
thatPlayerBattleState := atomic.LoadInt32(&(player.BattleState)) thatPlayerBattleState := atomic.LoadInt32(&(player.BattleState))
switch thatPlayerBattleState { switch thatPlayerBattleState {
@@ -871,6 +924,8 @@ func (pR *Room) clearPlayerNetworkSession(playerId int32) {
delete(pR.PlayerActiveWatchdogDict, playerId) delete(pR.PlayerActiveWatchdogDict, playerId)
delete(pR.PlayerDownsyncSessionDict, playerId) delete(pR.PlayerDownsyncSessionDict, playerId)
delete(pR.PlayerSignalToCloseDict, playerId) delete(pR.PlayerSignalToCloseDict, playerId)
delete(pR.PlayerSecondaryDownsyncSessionDict, playerId)
delete(pR.PlayerSecondarySignalToCloseDict, playerId)
} }
} }
@@ -960,7 +1015,7 @@ func (pR *Room) OnPlayerBattleColliderAcked(playerId int32) bool {
Logger.Debug(fmt.Sprintf("OnPlayerBattleColliderAcked-middle: roomId=%v, roomState=%v, targetPlayerId=%v, targetPlayerBattleState=%v, thatPlayerId=%v, thatPlayerBattleState=%v", pR.Id, pR.State, targetPlayer.Id, targetPlayer.BattleState, thatPlayer.Id, thatPlayerBattleState)) Logger.Debug(fmt.Sprintf("OnPlayerBattleColliderAcked-middle: roomId=%v, roomState=%v, targetPlayerId=%v, targetPlayerBattleState=%v, thatPlayerId=%v, thatPlayerBattleState=%v", pR.Id, pR.State, targetPlayer.Id, targetPlayer.BattleState, thatPlayer.Id, thatPlayerBattleState))
if thatPlayerId == targetPlayer.Id || (PlayerBattleStateIns.ADDED_PENDING_BATTLE_COLLIDER_ACK == thatPlayerBattleState || PlayerBattleStateIns.ACTIVE == thatPlayerBattleState) { if thatPlayerId == targetPlayer.Id || (PlayerBattleStateIns.ADDED_PENDING_BATTLE_COLLIDER_ACK == thatPlayerBattleState || PlayerBattleStateIns.ACTIVE == thatPlayerBattleState) {
Logger.Debug(fmt.Sprintf("OnPlayerBattleColliderAcked-sending DOWNSYNC_MSG_ACT_PLAYER_ADDED_AND_ACKED: roomId=%v, roomState=%v, targetPlayerId=%v, targetPlayerBattleState=%v, capacity=%v, EffectivePlayerCount=%v", pR.Id, pR.State, targetPlayer.Id, targetPlayer.BattleState, pR.Capacity, pR.EffectivePlayerCount)) Logger.Debug(fmt.Sprintf("OnPlayerBattleColliderAcked-sending DOWNSYNC_MSG_ACT_PLAYER_ADDED_AND_ACKED: roomId=%v, roomState=%v, targetPlayerId=%v, targetPlayerBattleState=%v, capacity=%v, EffectivePlayerCount=%v", pR.Id, pR.State, targetPlayer.Id, targetPlayer.BattleState, pR.Capacity, pR.EffectivePlayerCount))
pR.sendSafely(playerAckedFrame, nil, DOWNSYNC_MSG_ACT_PLAYER_ADDED_AND_ACKED, thatPlayer.Id, true) pR.sendSafely(playerAckedFrame, nil, DOWNSYNC_MSG_ACT_PLAYER_ADDED_AND_ACKED, thatPlayer.Id, true, MAGIC_JOIN_INDEX_DEFAULT)
} }
} }
atomic.StoreInt32(&(targetPlayer.BattleState), PlayerBattleStateIns.ACTIVE) atomic.StoreInt32(&(targetPlayer.BattleState), PlayerBattleStateIns.ACTIVE)
@@ -993,19 +1048,19 @@ func (pR *Room) OnPlayerBattleColliderAcked(playerId int32) bool {
return true return true
} }
func (pR *Room) sendSafely(roomDownsyncFrame *pb.RoomDownsyncFrame, toSendInputFrameDownsyncs []*pb.InputFrameDownsync, act int32, playerId int32, needLockExplicitly bool) { func (pR *Room) sendSafely(roomDownsyncFrame *pb.RoomDownsyncFrame, toSendInputFrameDownsyncs []*pb.InputFrameDownsync, act int32, playerId int32, needLockExplicitly bool, peerJoinIndex int32) {
defer func() { defer func() {
if r := recover(); r != nil { if r := recover(); r != nil {
Logger.Error("sendSafely, recovered from: ", zap.Any("roomId", pR.Id), zap.Any("playerId", playerId), zap.Any("panic", r)) Logger.Error("sendSafely, recovered from: ", zap.Any("roomId", pR.Id), zap.Any("playerId", playerId), zap.Any("panic", r))
} }
}() }()
if playerDownsyncSession, existent := pR.PlayerDownsyncSessionDict[playerId]; existent {
pResp := &pb.WsResp{ pResp := &pb.WsResp{
Ret: int32(Constants.RetCode.Ok), Ret: int32(Constants.RetCode.Ok),
Act: act, Act: act,
Rdf: roomDownsyncFrame, Rdf: roomDownsyncFrame,
InputFrameDownsyncBatch: toSendInputFrameDownsyncs, InputFrameDownsyncBatch: toSendInputFrameDownsyncs,
PeerJoinIndex: peerJoinIndex,
} }
theBytes, marshalErr := proto.Marshal(pResp) theBytes, marshalErr := proto.Marshal(pResp)
@@ -1013,8 +1068,23 @@ func (pR *Room) sendSafely(roomDownsyncFrame *pb.RoomDownsyncFrame, toSendInputF
panic(fmt.Sprintf("Error marshaling downsync message: roomId=%v, playerId=%v, roomState=%v, roomEffectivePlayerCount=%v", pR.Id, playerId, pR.State, pR.EffectivePlayerCount)) panic(fmt.Sprintf("Error marshaling downsync message: roomId=%v, playerId=%v, roomState=%v, roomEffectivePlayerCount=%v", pR.Id, playerId, pR.State, pR.EffectivePlayerCount))
} }
if MAGIC_JOIN_INDEX_DEFAULT == peerJoinIndex {
if playerDownsyncSession, existent := pR.PlayerDownsyncSessionDict[playerId]; existent {
if err := playerDownsyncSession.WriteMessage(websocket.BinaryMessage, theBytes); nil != err { if err := playerDownsyncSession.WriteMessage(websocket.BinaryMessage, theBytes); nil != err {
panic(fmt.Sprintf("Error sending downsync message: roomId=%v, playerId=%v, roomState=%v, roomEffectivePlayerCount=%v, err=%v", pR.Id, playerId, pR.State, pR.EffectivePlayerCount, err)) panic(fmt.Sprintf("Error sending primary downsync message: roomId=%v, playerId=%v, roomState=%v, roomEffectivePlayerCount=%v, err=%v", pR.Id, playerId, pR.State, pR.EffectivePlayerCount, err))
}
}
} else {
/*
[FIXME]
This branch is preferred to use an additional session of each player for sending, and the session is preferrably UDP instead of any TCP-based protocol, but I'm being lazy here.
See `<proj-root>/ConcerningEdgeCases.md` for the advantage of using UDP as a supplement.
*/
if playerSecondaryDownsyncSession, existent := pR.PlayerSecondaryDownsyncSessionDict[playerId]; existent {
if err := playerSecondaryDownsyncSession.WriteMessage(websocket.BinaryMessage, theBytes); nil != err {
panic(fmt.Sprintf("Error sending secondary downsync message: roomId=%v, playerId=%v, roomState=%v, roomEffectivePlayerCount=%v, err=%v", pR.Id, playerId, pR.State, pR.EffectivePlayerCount, err))
}
} }
} }
} }
@@ -1325,11 +1395,35 @@ func (pR *Room) doBattleMainLoopPerTickBackendDynamicsWithProperLocking(prevRend
snapshotStFrameId = refSnapshotStFrameId snapshotStFrameId = refSnapshotStFrameId
} }
inputsBufferSnapshot := pR.produceInputsBufferSnapshotWithCurDynamicsRenderFrameAsRef(unconfirmedMask, snapshotStFrameId, pR.LastAllConfirmedInputFrameId+1) inputsBufferSnapshot := pR.produceInputsBufferSnapshotWithCurDynamicsRenderFrameAsRef(unconfirmedMask, snapshotStFrameId, pR.LastAllConfirmedInputFrameId+1)
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, unconfirmedMask)) //Logger.Warn(fmt.Sprintf("[forceConfirmation] roomId=%v, room.RenderFrameId=%v, room.CurDynamicsRenderFrameId=%v, room.LastAllConfirmedInputFrameId=%v, unconfirmedMask=%v", pR.Id, pR.RenderFrameId, pR.CurDynamicsRenderFrameId, pR.LastAllConfirmedInputFrameId, unconfirmedMask))
pR.downsyncToAllPlayers(inputsBufferSnapshot) pR.downsyncToAllPlayers(inputsBufferSnapshot)
} }
} }
func (pR *Room) broadcastPeerUpsyncForBetterPrediction(inputsBufferSnapshot *pb.InputsBufferSnapshot) {
// See `<proj-root>/ConcerningEdgeCases.md` for why this method exists.
for _, player := range pR.PlayersArr {
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 player.JoinIndex == inputsBufferSnapshot.PeerJoinIndex {
continue
}
if playerSecondaryDownsyncChan, existent := pR.PlayerSecondaryDownsyncChanDict[player.Id]; existent {
/*
[FIXME]
This function is preferred to use an additional go-channel of each player for sending, see "downsyncLoop" & "Room.sendSafely" for more information!
*/
playerSecondaryDownsyncChan <- (*inputsBufferSnapshot)
} else {
Logger.Warn(fmt.Sprintf("playerDownsyncChan for (roomId: %d, playerId:%d) is gone", pR.Id, player.Id))
}
}
}
func (pR *Room) downsyncToAllPlayers(inputsBufferSnapshot *pb.InputsBufferSnapshot) { func (pR *Room) downsyncToAllPlayers(inputsBufferSnapshot *pb.InputsBufferSnapshot) {
/* /*
[WARNING] This function MUST BE called while "pR.InputsBufferLock" is LOCKED to **preserve the order of generation of "inputsBufferSnapshot" for sending** -- see comments in "OnBattleCmdReceived" and [this issue](https://github.com/genxium/DelayNoMore/issues/12). [WARNING] This function MUST BE called while "pR.InputsBufferLock" is LOCKED to **preserve the order of generation of "inputsBufferSnapshot" for sending** -- see comments in "OnBattleCmdReceived" and [this issue](https://github.com/genxium/DelayNoMore/issues/12).
@@ -1406,14 +1500,14 @@ func (pR *Room) downsyncToSinglePlayer(playerId int32, player *Player, refRender
We hereby assume that Golang runtime allocates & frees small amount of RAM quickly enough compared to either network I/O blocking in worst cases or the high frequency "per inputFrameDownsync*player" locking (though "OnBattleCmdReceived" locks at the same frequency but it's inevitable). We hereby assume that Golang runtime allocates & frees small amount of RAM quickly enough compared to either network I/O blocking in worst cases or the high frequency "per inputFrameDownsync*player" locking (though "OnBattleCmdReceived" locks at the same frequency but it's inevitable).
*/ */
playerJoinIndex := player.JoinIndex - 1 playerJoinIndexInBooleanArr := player.JoinIndex - 1
playerBattleState := atomic.LoadInt32(&(player.BattleState)) playerBattleState := atomic.LoadInt32(&(player.BattleState))
switch playerBattleState { 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: 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 return
} }
isSlowTicker := (0 < (unconfirmedMask & uint64(1<<uint32(playerJoinIndex)))) isSlowTicker := (0 < (unconfirmedMask & uint64(1<<uint32(playerJoinIndexInBooleanArr))))
shouldResync1 := (PlayerBattleStateIns.READDED_BATTLE_COLLIDER_ACKED == playerBattleState) // i.e. implies that "MAGIC_LAST_SENT_INPUT_FRAME_ID_READDED == player.LastSentInputFrameId" shouldResync1 := (PlayerBattleStateIns.READDED_BATTLE_COLLIDER_ACKED == playerBattleState) // i.e. implies that "MAGIC_LAST_SENT_INPUT_FRAME_ID_READDED == player.LastSentInputFrameId"
shouldResync2 := isSlowTicker // 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 := isSlowTicker // 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
shouldResync3 := shouldForceResync shouldResync3 := shouldForceResync
@@ -1438,13 +1532,13 @@ func (pR *Room) downsyncToSinglePlayer(playerId int32, player *Player, refRender
refRenderFrame.BackendUnconfirmedMask = unconfirmedMask refRenderFrame.BackendUnconfirmedMask = unconfirmedMask
pbRefRenderFrame := toPbRoomDownsyncFrame(refRenderFrame) pbRefRenderFrame := toPbRoomDownsyncFrame(refRenderFrame)
pbRefRenderFrame.SpeciesIdList = pR.SpeciesIdList pbRefRenderFrame.SpeciesIdList = pR.SpeciesIdList
pR.sendSafely(pbRefRenderFrame, toSendInputFrameDownsyncsSnapshot, DOWNSYNC_MSG_ACT_FORCED_RESYNC, playerId, false) pR.sendSafely(pbRefRenderFrame, toSendInputFrameDownsyncsSnapshot, DOWNSYNC_MSG_ACT_FORCED_RESYNC, playerId, false, MAGIC_JOIN_INDEX_DEFAULT)
//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 { if shouldResync1 || shouldResync3 {
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)) Logger.Debug(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 { } else {
pR.sendSafely(nil, toSendInputFrameDownsyncsSnapshot, DOWNSYNC_MSG_ACT_INPUT_BATCH, playerId, false) pR.sendSafely(nil, toSendInputFrameDownsyncsSnapshot, DOWNSYNC_MSG_ACT_INPUT_BATCH, playerId, false, MAGIC_JOIN_INDEX_DEFAULT)
} }
player.LastSentInputFrameId = toSendInputFrameIdEd - 1 player.LastSentInputFrameId = toSendInputFrameIdEd - 1
if shouldResync1 { if shouldResync1 {
@@ -1452,6 +1546,16 @@ func (pR *Room) downsyncToSinglePlayer(playerId int32, player *Player, refRender
} }
} }
func (pR *Room) downsyncPeerInputFrameUpsyncToSinglePlayer(playerId int32, player *Player, toSendInputFrameDownsyncsSnapshot []*pb.InputFrameDownsync, peerJoinIndex int32) {
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:
return
}
pR.sendSafely(nil, toSendInputFrameDownsyncsSnapshot, DOWNSYNC_MSG_ACT_PEER_INPUT_BATCH, playerId, false, peerJoinIndex)
}
func (pR *Room) cloneInputsBuffer(stFrameId, edFrameId int32) []*pb.InputFrameDownsync { func (pR *Room) cloneInputsBuffer(stFrameId, edFrameId int32) []*pb.InputFrameDownsync {
// [WARNING] This function MUST BE called while "pR.InputsBufferLock" is locked! // [WARNING] This function MUST BE called while "pR.InputsBufferLock" is locked!
cloned := make([]*pb.InputFrameDownsync, 0, edFrameId-stFrameId) cloned := make([]*pb.InputFrameDownsync, 0, edFrameId-stFrameId)
@@ -1484,3 +1588,22 @@ func (pR *Room) cloneInputsBuffer(stFrameId, edFrameId int32) []*pb.InputFrameDo
return cloned return cloned
} }
func (pR *Room) SetSecondarySession(playerId int32, session *websocket.Conn, signalToCloseConnOfThisPlayer SignalToCloseConnCbType) {
// TODO: Use a dedicated lock
if player, ok := pR.Players[playerId]; ok {
playerBattleState := atomic.LoadInt32(&(player.BattleState))
switch playerBattleState {
case PlayerBattleStateIns.DISCONNECTED, PlayerBattleStateIns.LOST, PlayerBattleStateIns.EXPELLED_DURING_GAME, PlayerBattleStateIns.EXPELLED_IN_DISMISSAL:
// Kindly note that "PlayerBattleStateIns.ADDED_PENDING_BATTLE_COLLIDER_ACK, PlayerBattleStateIns.READDED_PENDING_BATTLE_COLLIDER_ACK" are allowed
return
}
if _, existent := pR.PlayerDownsyncSessionDict[playerId]; existent {
if _, existent2 := pR.PlayerSecondaryDownsyncSessionDict[playerId]; !existent2 {
Logger.Info(fmt.Sprintf("SetSecondarySession for roomId=%v, playerId=%d, pR.Players=%v", pR.Id, playerId, pR.Players))
pR.PlayerSecondaryDownsyncSessionDict[playerId] = session
pR.PlayerSecondarySignalToCloseDict[playerId] = signalToCloseConnOfThisPlayer
}
}
}
}

View File

@@ -30,9 +30,9 @@ type PlayerDownsync struct {
VirtualGridX int32 `protobuf:"varint,2,opt,name=virtualGridX,proto3" json:"virtualGridX,omitempty"` VirtualGridX int32 `protobuf:"varint,2,opt,name=virtualGridX,proto3" json:"virtualGridX,omitempty"`
VirtualGridY int32 `protobuf:"varint,3,opt,name=virtualGridY,proto3" json:"virtualGridY,omitempty"` VirtualGridY int32 `protobuf:"varint,3,opt,name=virtualGridY,proto3" json:"virtualGridY,omitempty"`
DirX int32 `protobuf:"varint,4,opt,name=dirX,proto3" json:"dirX,omitempty"` DirX int32 `protobuf:"varint,4,opt,name=dirX,proto3" json:"dirX,omitempty"`
DirY int32 `protobuf:"varint,5,opt,name=dirY,proto3" json:"dirY,omitempty"` // "dirX" and "dirY" determines character facing DirY int32 `protobuf:"varint,5,opt,name=dirY,proto3" json:"dirY,omitempty"`
VelX int32 `protobuf:"varint,6,opt,name=velX,proto3" json:"velX,omitempty"` VelX int32 `protobuf:"varint,6,opt,name=velX,proto3" json:"velX,omitempty"`
VelY int32 `protobuf:"varint,7,opt,name=velY,proto3" json:"velY,omitempty"` // "velX" and "velY" is used to record the accumulated effect by accelerations (including gravity) VelY int32 `protobuf:"varint,7,opt,name=velY,proto3" json:"velY,omitempty"` // "velX" and "velY" is used to record the accumulated effect by inertia and accelerations (including gravity)
Speed int32 `protobuf:"varint,8,opt,name=speed,proto3" json:"speed,omitempty"` // this is the instantaneous scalar attribute of a character, different from but will be accounted in "velX" and "velY" Speed int32 `protobuf:"varint,8,opt,name=speed,proto3" json:"speed,omitempty"` // this is the instantaneous scalar attribute of a character, different from but will be accounted in "velX" and "velY"
BattleState int32 `protobuf:"varint,9,opt,name=battleState,proto3" json:"battleState,omitempty"` BattleState int32 `protobuf:"varint,9,opt,name=battleState,proto3" json:"battleState,omitempty"`
JoinIndex int32 `protobuf:"varint,10,opt,name=joinIndex,proto3" json:"joinIndex,omitempty"` JoinIndex int32 `protobuf:"varint,10,opt,name=joinIndex,proto3" json:"joinIndex,omitempty"`
@@ -51,6 +51,10 @@ type PlayerDownsync struct {
FramesInvinsible int32 `protobuf:"varint,23,opt,name=framesInvinsible,proto3" json:"framesInvinsible,omitempty"` FramesInvinsible int32 `protobuf:"varint,23,opt,name=framesInvinsible,proto3" json:"framesInvinsible,omitempty"`
BulletTeamId int32 `protobuf:"varint,24,opt,name=bulletTeamId,proto3" json:"bulletTeamId,omitempty"` BulletTeamId int32 `protobuf:"varint,24,opt,name=bulletTeamId,proto3" json:"bulletTeamId,omitempty"`
ChCollisionTeamId int32 `protobuf:"varint,25,opt,name=chCollisionTeamId,proto3" json:"chCollisionTeamId,omitempty"` ChCollisionTeamId int32 `protobuf:"varint,25,opt,name=chCollisionTeamId,proto3" json:"chCollisionTeamId,omitempty"`
OnWall bool `protobuf:"varint,26,opt,name=onWall,proto3" json:"onWall,omitempty"` // like "inAir", its by design a standalone field only inferred by the collision result of "applyInputFrameDownsyncDynamicsOnSingleRenderFrame" instead of "characterState", because we need check the transition for "characterState" from this field, i.e. "onWall (prev -> curr)"
OnWallNormX int32 `protobuf:"varint,27,opt,name=onWallNormX,proto3" json:"onWallNormX,omitempty"`
OnWallNormY int32 `protobuf:"varint,28,opt,name=onWallNormY,proto3" json:"onWallNormY,omitempty"`
CapturedByInertia bool `protobuf:"varint,29,opt,name=capturedByInertia,proto3" json:"capturedByInertia,omitempty"` // like "inAir", its by design a standalone field only inferred by the calc result of "applyInputFrameDownsyncDynamicsOnSingleRenderFrame" instead of "characterState"
Name string `protobuf:"bytes,997,opt,name=name,proto3" json:"name,omitempty"` Name string `protobuf:"bytes,997,opt,name=name,proto3" json:"name,omitempty"`
DisplayName string `protobuf:"bytes,998,opt,name=displayName,proto3" json:"displayName,omitempty"` DisplayName string `protobuf:"bytes,998,opt,name=displayName,proto3" json:"displayName,omitempty"`
Avatar string `protobuf:"bytes,999,opt,name=avatar,proto3" json:"avatar,omitempty"` Avatar string `protobuf:"bytes,999,opt,name=avatar,proto3" json:"avatar,omitempty"`
@@ -263,6 +267,34 @@ func (x *PlayerDownsync) GetChCollisionTeamId() int32 {
return 0 return 0
} }
func (x *PlayerDownsync) GetOnWall() bool {
if x != nil {
return x.OnWall
}
return false
}
func (x *PlayerDownsync) GetOnWallNormX() int32 {
if x != nil {
return x.OnWallNormX
}
return 0
}
func (x *PlayerDownsync) GetOnWallNormY() int32 {
if x != nil {
return x.OnWallNormY
}
return 0
}
func (x *PlayerDownsync) GetCapturedByInertia() bool {
if x != nil {
return x.CapturedByInertia
}
return false
}
func (x *PlayerDownsync) GetName() string { func (x *PlayerDownsync) GetName() string {
if x != nil { if x != nil {
return x.Name return x.Name
@@ -362,6 +394,7 @@ type InputFrameUpsync struct {
InputFrameId int32 `protobuf:"varint,1,opt,name=inputFrameId,proto3" json:"inputFrameId,omitempty"` InputFrameId int32 `protobuf:"varint,1,opt,name=inputFrameId,proto3" json:"inputFrameId,omitempty"`
Encoded uint64 `protobuf:"varint,2,opt,name=encoded,proto3" json:"encoded,omitempty"` Encoded uint64 `protobuf:"varint,2,opt,name=encoded,proto3" json:"encoded,omitempty"`
JoinIndex int32 `protobuf:"varint,3,opt,name=joinIndex,proto3" json:"joinIndex,omitempty"`
} }
func (x *InputFrameUpsync) Reset() { func (x *InputFrameUpsync) Reset() {
@@ -410,6 +443,13 @@ func (x *InputFrameUpsync) GetEncoded() uint64 {
return 0 return 0
} }
func (x *InputFrameUpsync) GetJoinIndex() int32 {
if x != nil {
return x.JoinIndex
}
return 0
}
type InputFrameDownsync struct { type InputFrameDownsync struct {
state protoimpl.MessageState state protoimpl.MessageState
sizeCache protoimpl.SizeCache sizeCache protoimpl.SizeCache
@@ -634,6 +674,7 @@ type WsResp struct {
Rdf *RoomDownsyncFrame `protobuf:"bytes,4,opt,name=rdf,proto3" json:"rdf,omitempty"` Rdf *RoomDownsyncFrame `protobuf:"bytes,4,opt,name=rdf,proto3" json:"rdf,omitempty"`
InputFrameDownsyncBatch []*InputFrameDownsync `protobuf:"bytes,5,rep,name=inputFrameDownsyncBatch,proto3" json:"inputFrameDownsyncBatch,omitempty"` InputFrameDownsyncBatch []*InputFrameDownsync `protobuf:"bytes,5,rep,name=inputFrameDownsyncBatch,proto3" json:"inputFrameDownsyncBatch,omitempty"`
BciFrame *BattleColliderInfo `protobuf:"bytes,6,opt,name=bciFrame,proto3" json:"bciFrame,omitempty"` BciFrame *BattleColliderInfo `protobuf:"bytes,6,opt,name=bciFrame,proto3" json:"bciFrame,omitempty"`
PeerJoinIndex int32 `protobuf:"varint,7,opt,name=peerJoinIndex,proto3" json:"peerJoinIndex,omitempty"` // Only used when "InputsBufferSnapshot.peerJoinIndex" is used.
} }
func (x *WsResp) Reset() { func (x *WsResp) Reset() {
@@ -710,6 +751,13 @@ func (x *WsResp) GetBciFrame() *BattleColliderInfo {
return nil return nil
} }
func (x *WsResp) GetPeerJoinIndex() int32 {
if x != nil {
return x.PeerJoinIndex
}
return 0
}
type InputsBufferSnapshot struct { type InputsBufferSnapshot struct {
state protoimpl.MessageState state protoimpl.MessageState
sizeCache protoimpl.SizeCache sizeCache protoimpl.SizeCache
@@ -719,6 +767,7 @@ type InputsBufferSnapshot struct {
UnconfirmedMask uint64 `protobuf:"varint,2,opt,name=unconfirmedMask,proto3" json:"unconfirmedMask,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"` ToSendInputFrameDownsyncs []*InputFrameDownsync `protobuf:"bytes,3,rep,name=toSendInputFrameDownsyncs,proto3" json:"toSendInputFrameDownsyncs,omitempty"`
ShouldForceResync bool `protobuf:"varint,4,opt,name=shouldForceResync,proto3" json:"shouldForceResync,omitempty"` ShouldForceResync bool `protobuf:"varint,4,opt,name=shouldForceResync,proto3" json:"shouldForceResync,omitempty"`
PeerJoinIndex int32 `protobuf:"varint,5,opt,name=peerJoinIndex,proto3" json:"peerJoinIndex,omitempty"` // Only used when "WsResp.peerJoinIndex" is used.
} }
func (x *InputsBufferSnapshot) Reset() { func (x *InputsBufferSnapshot) Reset() {
@@ -781,6 +830,13 @@ func (x *InputsBufferSnapshot) GetShouldForceResync() bool {
return false return false
} }
func (x *InputsBufferSnapshot) GetPeerJoinIndex() int32 {
if x != nil {
return x.PeerJoinIndex
}
return 0
}
type MeleeBullet struct { type MeleeBullet struct {
state protoimpl.MessageState state protoimpl.MessageState
sizeCache protoimpl.SizeCache sizeCache protoimpl.SizeCache
@@ -807,6 +863,10 @@ type MeleeBullet struct {
BlowUp bool `protobuf:"varint,18,opt,name=blowUp,proto3" json:"blowUp,omitempty"` BlowUp bool `protobuf:"varint,18,opt,name=blowUp,proto3" json:"blowUp,omitempty"`
TeamId int32 `protobuf:"varint,19,opt,name=teamId,proto3" json:"teamId,omitempty"` TeamId int32 `protobuf:"varint,19,opt,name=teamId,proto3" json:"teamId,omitempty"`
BulletLocalId int32 `protobuf:"varint,20,opt,name=bulletLocalId,proto3" json:"bulletLocalId,omitempty"` BulletLocalId int32 `protobuf:"varint,20,opt,name=bulletLocalId,proto3" json:"bulletLocalId,omitempty"`
SpeciesId int32 `protobuf:"varint,21,opt,name=speciesId,proto3" json:"speciesId,omitempty"`
ExplosionFrames int32 `protobuf:"varint,22,opt,name=explosionFrames,proto3" json:"explosionFrames,omitempty"`
BlState int32 `protobuf:"varint,23,opt,name=blState,proto3" json:"blState,omitempty"`
FramesInBlState int32 `protobuf:"varint,24,opt,name=framesInBlState,proto3" json:"framesInBlState,omitempty"`
} }
func (x *MeleeBullet) Reset() { func (x *MeleeBullet) Reset() {
@@ -981,6 +1041,34 @@ func (x *MeleeBullet) GetBulletLocalId() int32 {
return 0 return 0
} }
func (x *MeleeBullet) GetSpeciesId() int32 {
if x != nil {
return x.SpeciesId
}
return 0
}
func (x *MeleeBullet) GetExplosionFrames() int32 {
if x != nil {
return x.ExplosionFrames
}
return 0
}
func (x *MeleeBullet) GetBlState() int32 {
if x != nil {
return x.BlState
}
return 0
}
func (x *MeleeBullet) GetFramesInBlState() int32 {
if x != nil {
return x.FramesInBlState
}
return 0
}
type FireballBullet struct { type FireballBullet struct {
state protoimpl.MessageState state protoimpl.MessageState
sizeCache protoimpl.SizeCache sizeCache protoimpl.SizeCache
@@ -1006,6 +1094,10 @@ type FireballBullet struct {
BlowUp bool `protobuf:"varint,18,opt,name=blowUp,proto3" json:"blowUp,omitempty"` BlowUp bool `protobuf:"varint,18,opt,name=blowUp,proto3" json:"blowUp,omitempty"`
TeamId int32 `protobuf:"varint,19,opt,name=teamId,proto3" json:"teamId,omitempty"` TeamId int32 `protobuf:"varint,19,opt,name=teamId,proto3" json:"teamId,omitempty"`
BulletLocalId int32 `protobuf:"varint,20,opt,name=bulletLocalId,proto3" json:"bulletLocalId,omitempty"` BulletLocalId int32 `protobuf:"varint,20,opt,name=bulletLocalId,proto3" json:"bulletLocalId,omitempty"`
SpeciesId int32 `protobuf:"varint,21,opt,name=speciesId,proto3" json:"speciesId,omitempty"`
ExplosionFrames int32 `protobuf:"varint,22,opt,name=explosionFrames,proto3" json:"explosionFrames,omitempty"`
BlState int32 `protobuf:"varint,23,opt,name=blState,proto3" json:"blState,omitempty"`
FramesInBlState int32 `protobuf:"varint,24,opt,name=framesInBlState,proto3" json:"framesInBlState,omitempty"`
VirtualGridX int32 `protobuf:"varint,999,opt,name=virtualGridX,proto3" json:"virtualGridX,omitempty"` VirtualGridX int32 `protobuf:"varint,999,opt,name=virtualGridX,proto3" json:"virtualGridX,omitempty"`
VirtualGridY int32 `protobuf:"varint,1000,opt,name=virtualGridY,proto3" json:"virtualGridY,omitempty"` VirtualGridY int32 `protobuf:"varint,1000,opt,name=virtualGridY,proto3" json:"virtualGridY,omitempty"`
DirX int32 `protobuf:"varint,1001,opt,name=dirX,proto3" json:"dirX,omitempty"` DirX int32 `protobuf:"varint,1001,opt,name=dirX,proto3" json:"dirX,omitempty"`
@@ -1187,6 +1279,34 @@ func (x *FireballBullet) GetBulletLocalId() int32 {
return 0 return 0
} }
func (x *FireballBullet) GetSpeciesId() int32 {
if x != nil {
return x.SpeciesId
}
return 0
}
func (x *FireballBullet) GetExplosionFrames() int32 {
if x != nil {
return x.ExplosionFrames
}
return 0
}
func (x *FireballBullet) GetBlState() int32 {
if x != nil {
return x.BlState
}
return 0
}
func (x *FireballBullet) GetFramesInBlState() int32 {
if x != nil {
return x.FramesInBlState
}
return 0
}
func (x *FireballBullet) GetVirtualGridX() int32 { func (x *FireballBullet) GetVirtualGridX() int32 {
if x != nil { if x != nil {
return x.VirtualGridX return x.VirtualGridX
@@ -1504,7 +1624,7 @@ var file_room_downsync_frame_proto_rawDesc = []byte{
0x0a, 0x19, 0x72, 0x6f, 0x6f, 0x6d, 0x5f, 0x64, 0x6f, 0x77, 0x6e, 0x73, 0x79, 0x6e, 0x63, 0x5f, 0x0a, 0x19, 0x72, 0x6f, 0x6f, 0x6d, 0x5f, 0x64, 0x6f, 0x77, 0x6e, 0x73, 0x79, 0x6e, 0x63, 0x5f,
0x66, 0x72, 0x61, 0x6d, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x06, 0x70, 0x72, 0x6f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x06, 0x70, 0x72, 0x6f,
0x74, 0x6f, 0x73, 0x1a, 0x0e, 0x67, 0x65, 0x6f, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x2e, 0x70, 0x72, 0x74, 0x6f, 0x73, 0x1a, 0x0e, 0x67, 0x65, 0x6f, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x2e, 0x70, 0x72,
0x6f, 0x74, 0x6f, 0x22, 0xe9, 0x06, 0x0a, 0x0e, 0x50, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x44, 0x6f, 0x6f, 0x74, 0x6f, 0x22, 0xf3, 0x07, 0x0a, 0x0e, 0x50, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x44, 0x6f,
0x77, 0x6e, 0x73, 0x79, 0x6e, 0x63, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x77, 0x6e, 0x73, 0x79, 0x6e, 0x63, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01,
0x28, 0x05, 0x52, 0x02, 0x69, 0x64, 0x12, 0x22, 0x0a, 0x0c, 0x76, 0x69, 0x72, 0x74, 0x75, 0x61, 0x28, 0x05, 0x52, 0x02, 0x69, 0x64, 0x12, 0x22, 0x0a, 0x0c, 0x76, 0x69, 0x72, 0x74, 0x75, 0x61,
0x6c, 0x47, 0x72, 0x69, 0x64, 0x58, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0c, 0x76, 0x69, 0x6c, 0x47, 0x72, 0x69, 0x64, 0x58, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0c, 0x76, 0x69,
@@ -1553,136 +1673,160 @@ var file_room_downsync_frame_proto_rawDesc = []byte{
0x28, 0x05, 0x52, 0x0c, 0x62, 0x75, 0x6c, 0x6c, 0x65, 0x74, 0x54, 0x65, 0x61, 0x6d, 0x49, 0x64, 0x28, 0x05, 0x52, 0x0c, 0x62, 0x75, 0x6c, 0x6c, 0x65, 0x74, 0x54, 0x65, 0x61, 0x6d, 0x49, 0x64,
0x12, 0x2c, 0x0a, 0x11, 0x63, 0x68, 0x43, 0x6f, 0x6c, 0x6c, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x54, 0x12, 0x2c, 0x0a, 0x11, 0x63, 0x68, 0x43, 0x6f, 0x6c, 0x6c, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x54,
0x65, 0x61, 0x6d, 0x49, 0x64, 0x18, 0x19, 0x20, 0x01, 0x28, 0x05, 0x52, 0x11, 0x63, 0x68, 0x43, 0x65, 0x61, 0x6d, 0x49, 0x64, 0x18, 0x19, 0x20, 0x01, 0x28, 0x05, 0x52, 0x11, 0x63, 0x68, 0x43,
0x6f, 0x6c, 0x6c, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x54, 0x65, 0x61, 0x6d, 0x49, 0x64, 0x12, 0x13, 0x6f, 0x6c, 0x6c, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x54, 0x65, 0x61, 0x6d, 0x49, 0x64, 0x12, 0x16,
0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0xe5, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x0a, 0x06, 0x6f, 0x6e, 0x57, 0x61, 0x6c, 0x6c, 0x18, 0x1a, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06,
0x61, 0x6d, 0x65, 0x12, 0x21, 0x0a, 0x0b, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x4e, 0x61, 0x6f, 0x6e, 0x57, 0x61, 0x6c, 0x6c, 0x12, 0x20, 0x0a, 0x0b, 0x6f, 0x6e, 0x57, 0x61, 0x6c, 0x6c,
0x6d, 0x65, 0x18, 0xe6, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x4e, 0x6f, 0x72, 0x6d, 0x58, 0x18, 0x1b, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0b, 0x6f, 0x6e, 0x57,
0x61, 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x17, 0x0a, 0x06, 0x61, 0x76, 0x61, 0x74, 0x61, 0x72, 0x61, 0x6c, 0x6c, 0x4e, 0x6f, 0x72, 0x6d, 0x58, 0x12, 0x20, 0x0a, 0x0b, 0x6f, 0x6e, 0x57, 0x61,
0x18, 0xe7, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x61, 0x76, 0x61, 0x74, 0x61, 0x72, 0x22, 0x6c, 0x6c, 0x4e, 0x6f, 0x72, 0x6d, 0x59, 0x18, 0x1c, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0b, 0x6f,
0x6f, 0x0a, 0x11, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x44, 0x65, 0x63, 0x6e, 0x57, 0x61, 0x6c, 0x6c, 0x4e, 0x6f, 0x72, 0x6d, 0x59, 0x12, 0x2c, 0x0a, 0x11, 0x63, 0x61,
0x6f, 0x64, 0x65, 0x64, 0x12, 0x0e, 0x0a, 0x02, 0x64, 0x78, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x70, 0x74, 0x75, 0x72, 0x65, 0x64, 0x42, 0x79, 0x49, 0x6e, 0x65, 0x72, 0x74, 0x69, 0x61, 0x18,
0x52, 0x02, 0x64, 0x78, 0x12, 0x0e, 0x0a, 0x02, 0x64, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x1d, 0x20, 0x01, 0x28, 0x08, 0x52, 0x11, 0x63, 0x61, 0x70, 0x74, 0x75, 0x72, 0x65, 0x64, 0x42,
0x52, 0x02, 0x64, 0x79, 0x12, 0x1c, 0x0a, 0x09, 0x62, 0x74, 0x6e, 0x41, 0x4c, 0x65, 0x76, 0x65, 0x79, 0x49, 0x6e, 0x65, 0x72, 0x74, 0x69, 0x61, 0x12, 0x13, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65,
0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x62, 0x74, 0x6e, 0x41, 0x4c, 0x65, 0x76, 0x18, 0xe5, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x21, 0x0a,
0x65, 0x6c, 0x12, 0x1c, 0x0a, 0x09, 0x62, 0x74, 0x6e, 0x42, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x18, 0x0b, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0xe6, 0x07, 0x20,
0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x62, 0x74, 0x6e, 0x42, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x4e, 0x61, 0x6d, 0x65,
0x22, 0x50, 0x0a, 0x10, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x55, 0x70, 0x12, 0x17, 0x0a, 0x06, 0x61, 0x76, 0x61, 0x74, 0x61, 0x72, 0x18, 0xe7, 0x07, 0x20, 0x01, 0x28,
0x73, 0x79, 0x6e, 0x63, 0x12, 0x22, 0x0a, 0x0c, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x46, 0x72, 0x61, 0x09, 0x52, 0x06, 0x61, 0x76, 0x61, 0x74, 0x61, 0x72, 0x22, 0x6f, 0x0a, 0x11, 0x49, 0x6e, 0x70,
0x6d, 0x65, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0c, 0x69, 0x6e, 0x70, 0x75, 0x75, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x44, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x12, 0x0e,
0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x49, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x63, 0x6f, 0x0a, 0x02, 0x64, 0x78, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x02, 0x64, 0x78, 0x12, 0x0e,
0x64, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x07, 0x65, 0x6e, 0x63, 0x6f, 0x64, 0x0a, 0x02, 0x64, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x02, 0x64, 0x79, 0x12, 0x1c,
0x65, 0x64, 0x22, 0x7c, 0x0a, 0x12, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x0a, 0x09, 0x62, 0x74, 0x6e, 0x41, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28,
0x44, 0x6f, 0x77, 0x6e, 0x73, 0x79, 0x6e, 0x63, 0x12, 0x22, 0x0a, 0x0c, 0x69, 0x6e, 0x70, 0x75, 0x05, 0x52, 0x09, 0x62, 0x74, 0x6e, 0x41, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x1c, 0x0a, 0x09,
0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0c, 0x62, 0x74, 0x6e, 0x42, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52,
0x69, 0x6e, 0x70, 0x75, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x49, 0x64, 0x12, 0x1c, 0x0a, 0x09, 0x09, 0x62, 0x74, 0x6e, 0x42, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x22, 0x6e, 0x0a, 0x10, 0x49, 0x6e,
0x69, 0x6e, 0x70, 0x75, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x18, 0x02, 0x20, 0x03, 0x28, 0x04, 0x52, 0x70, 0x75, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x55, 0x70, 0x73, 0x79, 0x6e, 0x63, 0x12, 0x22,
0x09, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x24, 0x0a, 0x0d, 0x63, 0x6f, 0x0a, 0x0c, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x49, 0x64, 0x18, 0x01,
0x6e, 0x66, 0x69, 0x72, 0x6d, 0x65, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0c, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65,
0x04, 0x52, 0x0d, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d, 0x65, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x49, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x18, 0x02, 0x20,
0x22, 0x3b, 0x0a, 0x0f, 0x48, 0x65, 0x61, 0x72, 0x74, 0x62, 0x65, 0x61, 0x74, 0x55, 0x70, 0x73, 0x01, 0x28, 0x04, 0x52, 0x07, 0x65, 0x6e, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x12, 0x1c, 0x0a, 0x09,
0x79, 0x6e, 0x63, 0x12, 0x28, 0x0a, 0x0f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x54, 0x69, 0x6d, 0x6a, 0x6f, 0x69, 0x6e, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52,
0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0f, 0x63, 0x6c, 0x09, 0x6a, 0x6f, 0x69, 0x6e, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x22, 0x7c, 0x0a, 0x12, 0x49, 0x6e,
0x69, 0x65, 0x6e, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x22, 0xb8, 0x02, 0x70, 0x75, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x44, 0x6f, 0x77, 0x6e, 0x73, 0x79, 0x6e, 0x63,
0x0a, 0x05, 0x57, 0x73, 0x52, 0x65, 0x71, 0x12, 0x14, 0x0a, 0x05, 0x6d, 0x73, 0x67, 0x49, 0x64, 0x12, 0x22, 0x0a, 0x0c, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x49, 0x64,
0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x6d, 0x73, 0x67, 0x49, 0x64, 0x12, 0x1a, 0x0a, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0c, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x46, 0x72, 0x61,
0x08, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x49, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x6d, 0x65, 0x49, 0x64, 0x12, 0x1c, 0x0a, 0x09, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x4c, 0x69, 0x73,
0x08, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x49, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x61, 0x63, 0x74, 0x74, 0x18, 0x02, 0x20, 0x03, 0x28, 0x04, 0x52, 0x09, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x4c, 0x69,
0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x03, 0x61, 0x63, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x6a, 0x73, 0x74, 0x12, 0x24, 0x0a, 0x0d, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d, 0x65, 0x64, 0x4c,
0x6f, 0x69, 0x6e, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x69, 0x73, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0d, 0x63, 0x6f, 0x6e, 0x66, 0x69,
0x6a, 0x6f, 0x69, 0x6e, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x24, 0x0a, 0x0d, 0x61, 0x63, 0x6b, 0x72, 0x6d, 0x65, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x22, 0x3b, 0x0a, 0x0f, 0x48, 0x65, 0x61, 0x72,
0x69, 0x6e, 0x67, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x49, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x74, 0x62, 0x65, 0x61, 0x74, 0x55, 0x70, 0x73, 0x79, 0x6e, 0x63, 0x12, 0x28, 0x0a, 0x0f, 0x63,
0x52, 0x0d, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x49, 0x64, 0x12, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x01,
0x2e, 0x0a, 0x12, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x46, 0x72, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x54, 0x69, 0x6d, 0x65,
0x61, 0x6d, 0x65, 0x49, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x05, 0x52, 0x12, 0x61, 0x63, 0x6b, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x22, 0xb8, 0x02, 0x0a, 0x05, 0x57, 0x73, 0x52, 0x65, 0x71, 0x12,
0x69, 0x6e, 0x67, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x49, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x6d, 0x73, 0x67, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05,
0x4e, 0x0a, 0x15, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x55, 0x70, 0x73, 0x6d, 0x73, 0x67, 0x49, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x49,
0x79, 0x6e, 0x63, 0x42, 0x61, 0x74, 0x63, 0x68, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x49,
0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x46, 0x72, 0x61, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x61, 0x63, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x03,
0x6d, 0x65, 0x55, 0x70, 0x73, 0x79, 0x6e, 0x63, 0x52, 0x15, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x46, 0x61, 0x63, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x6a, 0x6f, 0x69, 0x6e, 0x49, 0x6e, 0x64, 0x65, 0x78,
0x72, 0x61, 0x6d, 0x65, 0x55, 0x70, 0x73, 0x79, 0x6e, 0x63, 0x42, 0x61, 0x74, 0x63, 0x68, 0x12, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x6a, 0x6f, 0x69, 0x6e, 0x49, 0x6e, 0x64, 0x65,
0x27, 0x0a, 0x02, 0x68, 0x62, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x70, 0x72, 0x78, 0x12, 0x24, 0x0a, 0x0d, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x46, 0x72, 0x61, 0x6d, 0x65,
0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x48, 0x65, 0x61, 0x72, 0x74, 0x62, 0x65, 0x61, 0x74, 0x55, 0x70, 0x49, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0d, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67,
0x73, 0x79, 0x6e, 0x63, 0x52, 0x02, 0x68, 0x62, 0x22, 0x89, 0x02, 0x0a, 0x06, 0x57, 0x73, 0x52, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x49, 0x64, 0x12, 0x2e, 0x0a, 0x12, 0x61, 0x63, 0x6b, 0x69, 0x6e,
0x65, 0x73, 0x70, 0x12, 0x10, 0x0a, 0x03, 0x72, 0x65, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x67, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x49, 0x64, 0x18, 0x06, 0x20,
0x52, 0x03, 0x72, 0x65, 0x74, 0x12, 0x20, 0x0a, 0x0b, 0x65, 0x63, 0x68, 0x6f, 0x65, 0x64, 0x4d, 0x01, 0x28, 0x05, 0x52, 0x12, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x49, 0x6e, 0x70, 0x75, 0x74,
0x73, 0x67, 0x49, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0b, 0x65, 0x63, 0x68, 0x6f, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x49, 0x64, 0x12, 0x4e, 0x0a, 0x15, 0x69, 0x6e, 0x70, 0x75, 0x74,
0x65, 0x64, 0x4d, 0x73, 0x67, 0x49, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x61, 0x63, 0x74, 0x18, 0x03, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x55, 0x70, 0x73, 0x79, 0x6e, 0x63, 0x42, 0x61, 0x74, 0x63, 0x68,
0x20, 0x01, 0x28, 0x05, 0x52, 0x03, 0x61, 0x63, 0x74, 0x12, 0x2b, 0x0a, 0x03, 0x72, 0x64, 0x66, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e,
0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x55, 0x70, 0x73, 0x79, 0x6e, 0x63,
0x52, 0x6f, 0x6f, 0x6d, 0x44, 0x6f, 0x77, 0x6e, 0x73, 0x79, 0x6e, 0x63, 0x46, 0x72, 0x61, 0x6d, 0x52, 0x15, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x55, 0x70, 0x73, 0x79,
0x65, 0x52, 0x03, 0x72, 0x64, 0x66, 0x12, 0x54, 0x0a, 0x17, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x46, 0x6e, 0x63, 0x42, 0x61, 0x74, 0x63, 0x68, 0x12, 0x27, 0x0a, 0x02, 0x68, 0x62, 0x18, 0x08, 0x20,
0x72, 0x61, 0x6d, 0x65, 0x44, 0x6f, 0x77, 0x6e, 0x73, 0x79, 0x6e, 0x63, 0x42, 0x61, 0x74, 0x63, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x48, 0x65, 0x61,
0x68, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x72, 0x74, 0x62, 0x65, 0x61, 0x74, 0x55, 0x70, 0x73, 0x79, 0x6e, 0x63, 0x52, 0x02, 0x68, 0x62,
0x2e, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x44, 0x6f, 0x77, 0x6e, 0x73, 0x22, 0xaf, 0x02, 0x0a, 0x06, 0x57, 0x73, 0x52, 0x65, 0x73, 0x70, 0x12, 0x10, 0x0a, 0x03, 0x72,
0x79, 0x6e, 0x63, 0x52, 0x17, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x44, 0x65, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x03, 0x72, 0x65, 0x74, 0x12, 0x20, 0x0a,
0x6f, 0x77, 0x6e, 0x73, 0x79, 0x6e, 0x63, 0x42, 0x61, 0x74, 0x63, 0x68, 0x12, 0x36, 0x0a, 0x08, 0x0b, 0x65, 0x63, 0x68, 0x6f, 0x65, 0x64, 0x4d, 0x73, 0x67, 0x49, 0x64, 0x18, 0x02, 0x20, 0x01,
0x62, 0x63, 0x69, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x28, 0x05, 0x52, 0x0b, 0x65, 0x63, 0x68, 0x6f, 0x65, 0x64, 0x4d, 0x73, 0x67, 0x49, 0x64, 0x12,
0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x42, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x43, 0x6f, 0x10, 0x0a, 0x03, 0x61, 0x63, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x03, 0x61, 0x63,
0x6c, 0x6c, 0x69, 0x64, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x08, 0x62, 0x63, 0x69, 0x46, 0x74, 0x12, 0x2b, 0x0a, 0x03, 0x72, 0x64, 0x66, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19,
0x72, 0x61, 0x6d, 0x65, 0x22, 0xf4, 0x01, 0x0a, 0x14, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x73, 0x42, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x52, 0x6f, 0x6f, 0x6d, 0x44, 0x6f, 0x77, 0x6e,
0x75, 0x66, 0x66, 0x65, 0x72, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x12, 0x2a, 0x0a, 0x73, 0x79, 0x6e, 0x63, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x52, 0x03, 0x72, 0x64, 0x66, 0x12, 0x54,
0x10, 0x72, 0x65, 0x66, 0x52, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x49, 0x0a, 0x17, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x44, 0x6f, 0x77, 0x6e,
0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x10, 0x72, 0x65, 0x66, 0x52, 0x65, 0x6e, 0x64, 0x73, 0x79, 0x6e, 0x63, 0x42, 0x61, 0x74, 0x63, 0x68, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32,
0x65, 0x72, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x49, 0x64, 0x12, 0x28, 0x0a, 0x0f, 0x75, 0x6e, 0x63, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x46, 0x72,
0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d, 0x65, 0x64, 0x4d, 0x61, 0x73, 0x6b, 0x18, 0x02, 0x20, 0x01, 0x61, 0x6d, 0x65, 0x44, 0x6f, 0x77, 0x6e, 0x73, 0x79, 0x6e, 0x63, 0x52, 0x17, 0x69, 0x6e, 0x70,
0x28, 0x04, 0x52, 0x0f, 0x75, 0x6e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d, 0x65, 0x64, 0x4d, 0x75, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x44, 0x6f, 0x77, 0x6e, 0x73, 0x79, 0x6e, 0x63, 0x42,
0x61, 0x73, 0x6b, 0x12, 0x58, 0x0a, 0x19, 0x74, 0x6f, 0x53, 0x65, 0x6e, 0x64, 0x49, 0x6e, 0x70, 0x61, 0x74, 0x63, 0x68, 0x12, 0x36, 0x0a, 0x08, 0x62, 0x63, 0x69, 0x46, 0x72, 0x61, 0x6d, 0x65,
0x75, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x44, 0x6f, 0x77, 0x6e, 0x73, 0x79, 0x6e, 0x63, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e,
0x18, 0x03, 0x20, 0x03, 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,
0x49, 0x6e, 0x70, 0x75, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x44, 0x6f, 0x77, 0x6e, 0x73, 0x79, 0x66, 0x6f, 0x52, 0x08, 0x62, 0x63, 0x69, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x12, 0x24, 0x0a, 0x0d,
0x6e, 0x63, 0x52, 0x19, 0x74, 0x6f, 0x53, 0x65, 0x6e, 0x64, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x46, 0x70, 0x65, 0x65, 0x72, 0x4a, 0x6f, 0x69, 0x6e, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x07, 0x20,
0x72, 0x61, 0x6d, 0x65, 0x44, 0x6f, 0x77, 0x6e, 0x73, 0x79, 0x6e, 0x63, 0x73, 0x12, 0x2c, 0x0a, 0x01, 0x28, 0x05, 0x52, 0x0d, 0x70, 0x65, 0x65, 0x72, 0x4a, 0x6f, 0x69, 0x6e, 0x49, 0x6e, 0x64,
0x11, 0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x46, 0x6f, 0x72, 0x63, 0x65, 0x52, 0x65, 0x73, 0x79, 0x65, 0x78, 0x22, 0x9a, 0x02, 0x0a, 0x14, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x73, 0x42, 0x75, 0x66,
0x6e, 0x63, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x11, 0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x66, 0x65, 0x72, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x12, 0x2a, 0x0a, 0x10, 0x72,
0x46, 0x6f, 0x72, 0x63, 0x65, 0x52, 0x65, 0x73, 0x79, 0x6e, 0x63, 0x22, 0xfd, 0x05, 0x0a, 0x0b, 0x65, 0x66, 0x52, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x49, 0x64, 0x18,
0x4d, 0x65, 0x6c, 0x65, 0x65, 0x42, 0x75, 0x6c, 0x6c, 0x65, 0x74, 0x12, 0x38, 0x0a, 0x17, 0x6f, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x10, 0x72, 0x65, 0x66, 0x52, 0x65, 0x6e, 0x64, 0x65, 0x72,
0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x65, 0x64, 0x52, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x46, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x49, 0x64, 0x12, 0x28, 0x0a, 0x0f, 0x75, 0x6e, 0x63, 0x6f, 0x6e,
0x72, 0x61, 0x6d, 0x65, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x17, 0x6f, 0x72, 0x66, 0x69, 0x72, 0x6d, 0x65, 0x64, 0x4d, 0x61, 0x73, 0x6b, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04,
0x69, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x65, 0x64, 0x52, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x46, 0x72, 0x52, 0x0f, 0x75, 0x6e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d, 0x65, 0x64, 0x4d, 0x61, 0x73,
0x61, 0x6d, 0x65, 0x49, 0x64, 0x12, 0x2c, 0x0a, 0x11, 0x6f, 0x66, 0x66, 0x65, 0x6e, 0x64, 0x65, 0x6b, 0x12, 0x58, 0x0a, 0x19, 0x74, 0x6f, 0x53, 0x65, 0x6e, 0x64, 0x49, 0x6e, 0x70, 0x75, 0x74,
0x72, 0x4a, 0x6f, 0x69, 0x6e, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x44, 0x6f, 0x77, 0x6e, 0x73, 0x79, 0x6e, 0x63, 0x73, 0x18, 0x03,
0x52, 0x11, 0x6f, 0x66, 0x66, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x4a, 0x6f, 0x69, 0x6e, 0x49, 0x6e, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x49, 0x6e,
0x64, 0x65, 0x78, 0x12, 0x24, 0x0a, 0x0d, 0x73, 0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x46, 0x72, 0x70, 0x75, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x44, 0x6f, 0x77, 0x6e, 0x73, 0x79, 0x6e, 0x63,
0x61, 0x6d, 0x65, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0d, 0x73, 0x74, 0x61, 0x72, 0x52, 0x19, 0x74, 0x6f, 0x53, 0x65, 0x6e, 0x64, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x46, 0x72, 0x61,
0x74, 0x75, 0x70, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x12, 0x2e, 0x0a, 0x12, 0x63, 0x61, 0x6e, 0x6d, 0x65, 0x44, 0x6f, 0x77, 0x6e, 0x73, 0x79, 0x6e, 0x63, 0x73, 0x12, 0x2c, 0x0a, 0x11, 0x73,
0x63, 0x65, 0x6c, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x53, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x18, 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x46, 0x6f, 0x72, 0x63, 0x65, 0x52, 0x65, 0x73, 0x79, 0x6e, 0x63,
0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x12, 0x63, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x6c, 0x61, 0x62, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x11, 0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x46, 0x6f,
0x6c, 0x65, 0x53, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x12, 0x2e, 0x0a, 0x12, 0x63, 0x61, 0x6e, 0x72, 0x63, 0x65, 0x52, 0x65, 0x73, 0x79, 0x6e, 0x63, 0x12, 0x24, 0x0a, 0x0d, 0x70, 0x65, 0x65,
0x63, 0x65, 0x6c, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x45, 0x64, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x18, 0x72, 0x4a, 0x6f, 0x69, 0x6e, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05,
0x05, 0x20, 0x01, 0x28, 0x05, 0x52, 0x12, 0x63, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x6c, 0x61, 0x62, 0x52, 0x0d, 0x70, 0x65, 0x65, 0x72, 0x4a, 0x6f, 0x69, 0x6e, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x22,
0x6c, 0x65, 0x45, 0x64, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x12, 0x22, 0x0a, 0x0c, 0x61, 0x63, 0x74, 0x89, 0x07, 0x0a, 0x0b, 0x4d, 0x65, 0x6c, 0x65, 0x65, 0x42, 0x75, 0x6c, 0x6c, 0x65, 0x74, 0x12,
0x69, 0x76, 0x65, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x05, 0x52, 0x38, 0x0a, 0x17, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x65, 0x64, 0x52, 0x65, 0x6e,
0x0c, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x12, 0x24, 0x0a, 0x64, 0x65, 0x72, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05,
0x0d, 0x68, 0x69, 0x74, 0x53, 0x74, 0x75, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x07, 0x52, 0x17, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x65, 0x64, 0x52, 0x65, 0x6e, 0x64,
0x20, 0x01, 0x28, 0x05, 0x52, 0x0d, 0x68, 0x69, 0x74, 0x53, 0x74, 0x75, 0x6e, 0x46, 0x72, 0x61, 0x65, 0x72, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x49, 0x64, 0x12, 0x2c, 0x0a, 0x11, 0x6f, 0x66, 0x66,
0x6d, 0x65, 0x73, 0x12, 0x28, 0x0a, 0x0f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x53, 0x74, 0x75, 0x6e, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x4a, 0x6f, 0x69, 0x6e, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x02,
0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0f, 0x62, 0x6c, 0x20, 0x01, 0x28, 0x05, 0x52, 0x11, 0x6f, 0x66, 0x66, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x4a, 0x6f,
0x6f, 0x63, 0x6b, 0x53, 0x74, 0x75, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x12, 0x22, 0x0a, 0x69, 0x6e, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x24, 0x0a, 0x0d, 0x73, 0x74, 0x61, 0x72, 0x74,
0x0c, 0x70, 0x75, 0x73, 0x68, 0x62, 0x61, 0x63, 0x6b, 0x56, 0x65, 0x6c, 0x58, 0x18, 0x09, 0x20, 0x75, 0x70, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0d,
0x01, 0x28, 0x05, 0x52, 0x0c, 0x70, 0x75, 0x73, 0x68, 0x62, 0x61, 0x63, 0x6b, 0x56, 0x65, 0x6c, 0x73, 0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x12, 0x2e, 0x0a,
0x58, 0x12, 0x22, 0x0a, 0x0c, 0x70, 0x75, 0x73, 0x68, 0x62, 0x61, 0x63, 0x6b, 0x56, 0x65, 0x6c, 0x12, 0x63, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x53, 0x74, 0x46, 0x72,
0x59, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0c, 0x70, 0x75, 0x73, 0x68, 0x62, 0x61, 0x63, 0x61, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x12, 0x63, 0x61, 0x6e, 0x63, 0x65,
0x6b, 0x56, 0x65, 0x6c, 0x59, 0x12, 0x16, 0x0a, 0x06, 0x64, 0x61, 0x6d, 0x61, 0x67, 0x65, 0x18, 0x6c, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x53, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x12, 0x2e, 0x0a,
0x0b, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x64, 0x61, 0x6d, 0x61, 0x67, 0x65, 0x12, 0x22, 0x0a, 0x12, 0x63, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x45, 0x64, 0x46, 0x72,
0x0c, 0x73, 0x65, 0x6c, 0x66, 0x4c, 0x6f, 0x63, 0x6b, 0x56, 0x65, 0x6c, 0x58, 0x18, 0x0c, 0x20, 0x61, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x52, 0x12, 0x63, 0x61, 0x6e, 0x63, 0x65,
0x01, 0x28, 0x05, 0x52, 0x0c, 0x73, 0x65, 0x6c, 0x66, 0x4c, 0x6f, 0x63, 0x6b, 0x56, 0x65, 0x6c, 0x6c, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x45, 0x64, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x12, 0x22, 0x0a,
0x58, 0x12, 0x22, 0x0a, 0x0c, 0x73, 0x65, 0x6c, 0x66, 0x4c, 0x6f, 0x63, 0x6b, 0x56, 0x65, 0x6c, 0x0c, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x06, 0x20,
0x59, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0c, 0x73, 0x65, 0x6c, 0x66, 0x4c, 0x6f, 0x63, 0x01, 0x28, 0x05, 0x52, 0x0c, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x46, 0x72, 0x61, 0x6d, 0x65,
0x6b, 0x56, 0x65, 0x6c, 0x59, 0x12, 0x24, 0x0a, 0x0d, 0x68, 0x69, 0x74, 0x62, 0x6f, 0x78, 0x4f, 0x73, 0x12, 0x24, 0x0a, 0x0d, 0x68, 0x69, 0x74, 0x53, 0x74, 0x75, 0x6e, 0x46, 0x72, 0x61, 0x6d,
0x66, 0x66, 0x73, 0x65, 0x74, 0x58, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0d, 0x68, 0x69, 0x65, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0d, 0x68, 0x69, 0x74, 0x53, 0x74, 0x75,
0x74, 0x62, 0x6f, 0x78, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x58, 0x12, 0x24, 0x0a, 0x0d, 0x68, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x12, 0x28, 0x0a, 0x0f, 0x62, 0x6c, 0x6f, 0x63, 0x6b,
0x69, 0x74, 0x62, 0x6f, 0x78, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x59, 0x18, 0x0f, 0x20, 0x01, 0x53, 0x74, 0x75, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x05,
0x28, 0x05, 0x52, 0x0d, 0x68, 0x69, 0x74, 0x62, 0x6f, 0x78, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x52, 0x0f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x53, 0x74, 0x75, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65,
0x59, 0x12, 0x20, 0x0a, 0x0b, 0x68, 0x69, 0x74, 0x62, 0x6f, 0x78, 0x53, 0x69, 0x7a, 0x65, 0x58, 0x73, 0x12, 0x22, 0x0a, 0x0c, 0x70, 0x75, 0x73, 0x68, 0x62, 0x61, 0x63, 0x6b, 0x56, 0x65, 0x6c,
0x18, 0x10, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0b, 0x68, 0x69, 0x74, 0x62, 0x6f, 0x78, 0x53, 0x69, 0x58, 0x18, 0x09, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0c, 0x70, 0x75, 0x73, 0x68, 0x62, 0x61, 0x63,
0x7a, 0x65, 0x58, 0x12, 0x20, 0x0a, 0x0b, 0x68, 0x69, 0x74, 0x62, 0x6f, 0x78, 0x53, 0x69, 0x7a, 0x6b, 0x56, 0x65, 0x6c, 0x58, 0x12, 0x22, 0x0a, 0x0c, 0x70, 0x75, 0x73, 0x68, 0x62, 0x61, 0x63,
0x65, 0x59, 0x18, 0x11, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0b, 0x68, 0x69, 0x74, 0x62, 0x6f, 0x78, 0x6b, 0x56, 0x65, 0x6c, 0x59, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0c, 0x70, 0x75, 0x73,
0x53, 0x69, 0x7a, 0x65, 0x59, 0x12, 0x16, 0x0a, 0x06, 0x62, 0x6c, 0x6f, 0x77, 0x55, 0x70, 0x18, 0x68, 0x62, 0x61, 0x63, 0x6b, 0x56, 0x65, 0x6c, 0x59, 0x12, 0x16, 0x0a, 0x06, 0x64, 0x61, 0x6d,
0x12, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x62, 0x6c, 0x6f, 0x77, 0x55, 0x70, 0x12, 0x16, 0x0a, 0x61, 0x67, 0x65, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x64, 0x61, 0x6d, 0x61, 0x67,
0x06, 0x74, 0x65, 0x61, 0x6d, 0x49, 0x64, 0x18, 0x13, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x74, 0x65, 0x12, 0x22, 0x0a, 0x0c, 0x73, 0x65, 0x6c, 0x66, 0x4c, 0x6f, 0x63, 0x6b, 0x56, 0x65, 0x6c,
0x65, 0x61, 0x6d, 0x49, 0x64, 0x12, 0x24, 0x0a, 0x0d, 0x62, 0x75, 0x6c, 0x6c, 0x65, 0x74, 0x4c, 0x58, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0c, 0x73, 0x65, 0x6c, 0x66, 0x4c, 0x6f, 0x63,
0x6f, 0x63, 0x61, 0x6c, 0x49, 0x64, 0x18, 0x14, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0d, 0x62, 0x75, 0x6b, 0x56, 0x65, 0x6c, 0x58, 0x12, 0x22, 0x0a, 0x0c, 0x73, 0x65, 0x6c, 0x66, 0x4c, 0x6f, 0x63,
0x6c, 0x6c, 0x65, 0x74, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x49, 0x64, 0x22, 0xb5, 0x07, 0x0a, 0x0e, 0x6b, 0x56, 0x65, 0x6c, 0x59, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0c, 0x73, 0x65, 0x6c,
0x66, 0x4c, 0x6f, 0x63, 0x6b, 0x56, 0x65, 0x6c, 0x59, 0x12, 0x24, 0x0a, 0x0d, 0x68, 0x69, 0x74,
0x62, 0x6f, 0x78, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x58, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x05,
0x52, 0x0d, 0x68, 0x69, 0x74, 0x62, 0x6f, 0x78, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x58, 0x12,
0x24, 0x0a, 0x0d, 0x68, 0x69, 0x74, 0x62, 0x6f, 0x78, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x59,
0x18, 0x0f, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0d, 0x68, 0x69, 0x74, 0x62, 0x6f, 0x78, 0x4f, 0x66,
0x66, 0x73, 0x65, 0x74, 0x59, 0x12, 0x20, 0x0a, 0x0b, 0x68, 0x69, 0x74, 0x62, 0x6f, 0x78, 0x53,
0x69, 0x7a, 0x65, 0x58, 0x18, 0x10, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0b, 0x68, 0x69, 0x74, 0x62,
0x6f, 0x78, 0x53, 0x69, 0x7a, 0x65, 0x58, 0x12, 0x20, 0x0a, 0x0b, 0x68, 0x69, 0x74, 0x62, 0x6f,
0x78, 0x53, 0x69, 0x7a, 0x65, 0x59, 0x18, 0x11, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0b, 0x68, 0x69,
0x74, 0x62, 0x6f, 0x78, 0x53, 0x69, 0x7a, 0x65, 0x59, 0x12, 0x16, 0x0a, 0x06, 0x62, 0x6c, 0x6f,
0x77, 0x55, 0x70, 0x18, 0x12, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x62, 0x6c, 0x6f, 0x77, 0x55,
0x70, 0x12, 0x16, 0x0a, 0x06, 0x74, 0x65, 0x61, 0x6d, 0x49, 0x64, 0x18, 0x13, 0x20, 0x01, 0x28,
0x05, 0x52, 0x06, 0x74, 0x65, 0x61, 0x6d, 0x49, 0x64, 0x12, 0x24, 0x0a, 0x0d, 0x62, 0x75, 0x6c,
0x6c, 0x65, 0x74, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x49, 0x64, 0x18, 0x14, 0x20, 0x01, 0x28, 0x05,
0x52, 0x0d, 0x62, 0x75, 0x6c, 0x6c, 0x65, 0x74, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x49, 0x64, 0x12,
0x1c, 0x0a, 0x09, 0x73, 0x70, 0x65, 0x63, 0x69, 0x65, 0x73, 0x49, 0x64, 0x18, 0x15, 0x20, 0x01,
0x28, 0x05, 0x52, 0x09, 0x73, 0x70, 0x65, 0x63, 0x69, 0x65, 0x73, 0x49, 0x64, 0x12, 0x28, 0x0a,
0x0f, 0x65, 0x78, 0x70, 0x6c, 0x6f, 0x73, 0x69, 0x6f, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73,
0x18, 0x16, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0f, 0x65, 0x78, 0x70, 0x6c, 0x6f, 0x73, 0x69, 0x6f,
0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x62, 0x6c, 0x53, 0x74, 0x61,
0x74, 0x65, 0x18, 0x17, 0x20, 0x01, 0x28, 0x05, 0x52, 0x07, 0x62, 0x6c, 0x53, 0x74, 0x61, 0x74,
0x65, 0x12, 0x28, 0x0a, 0x0f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x49, 0x6e, 0x42, 0x6c, 0x53,
0x74, 0x61, 0x74, 0x65, 0x18, 0x18, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0f, 0x66, 0x72, 0x61, 0x6d,
0x65, 0x73, 0x49, 0x6e, 0x42, 0x6c, 0x53, 0x74, 0x61, 0x74, 0x65, 0x22, 0xc1, 0x08, 0x0a, 0x0e,
0x46, 0x69, 0x72, 0x65, 0x62, 0x61, 0x6c, 0x6c, 0x42, 0x75, 0x6c, 0x6c, 0x65, 0x74, 0x12, 0x38, 0x46, 0x69, 0x72, 0x65, 0x62, 0x61, 0x6c, 0x6c, 0x42, 0x75, 0x6c, 0x6c, 0x65, 0x74, 0x12, 0x38,
0x0a, 0x17, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x65, 0x64, 0x52, 0x65, 0x6e, 0x64, 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, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x65, 0x72, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52,
@@ -1730,94 +1874,102 @@ var file_room_downsync_frame_proto_rawDesc = []byte{
0x12, 0x16, 0x0a, 0x06, 0x74, 0x65, 0x61, 0x6d, 0x49, 0x64, 0x18, 0x13, 0x20, 0x01, 0x28, 0x05, 0x12, 0x16, 0x0a, 0x06, 0x74, 0x65, 0x61, 0x6d, 0x49, 0x64, 0x18, 0x13, 0x20, 0x01, 0x28, 0x05,
0x52, 0x06, 0x74, 0x65, 0x61, 0x6d, 0x49, 0x64, 0x12, 0x24, 0x0a, 0x0d, 0x62, 0x75, 0x6c, 0x6c, 0x52, 0x06, 0x74, 0x65, 0x61, 0x6d, 0x49, 0x64, 0x12, 0x24, 0x0a, 0x0d, 0x62, 0x75, 0x6c, 0x6c,
0x65, 0x74, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x49, 0x64, 0x18, 0x14, 0x20, 0x01, 0x28, 0x05, 0x52, 0x65, 0x74, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x49, 0x64, 0x18, 0x14, 0x20, 0x01, 0x28, 0x05, 0x52,
0x0d, 0x62, 0x75, 0x6c, 0x6c, 0x65, 0x74, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x49, 0x64, 0x12, 0x23, 0x0d, 0x62, 0x75, 0x6c, 0x6c, 0x65, 0x74, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x49, 0x64, 0x12, 0x1c,
0x0a, 0x0c, 0x76, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x47, 0x72, 0x69, 0x64, 0x58, 0x18, 0xe7, 0x0a, 0x09, 0x73, 0x70, 0x65, 0x63, 0x69, 0x65, 0x73, 0x49, 0x64, 0x18, 0x15, 0x20, 0x01, 0x28,
0x07, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0c, 0x76, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x47, 0x72, 0x05, 0x52, 0x09, 0x73, 0x70, 0x65, 0x63, 0x69, 0x65, 0x73, 0x49, 0x64, 0x12, 0x28, 0x0a, 0x0f,
0x69, 0x64, 0x58, 0x12, 0x23, 0x0a, 0x0c, 0x76, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x47, 0x72, 0x65, 0x78, 0x70, 0x6c, 0x6f, 0x73, 0x69, 0x6f, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x18,
0x69, 0x64, 0x59, 0x18, 0xe8, 0x07, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0c, 0x76, 0x69, 0x72, 0x74, 0x16, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0f, 0x65, 0x78, 0x70, 0x6c, 0x6f, 0x73, 0x69, 0x6f, 0x6e,
0x75, 0x61, 0x6c, 0x47, 0x72, 0x69, 0x64, 0x59, 0x12, 0x13, 0x0a, 0x04, 0x64, 0x69, 0x72, 0x58, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x62, 0x6c, 0x53, 0x74, 0x61, 0x74,
0x18, 0xe9, 0x07, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x64, 0x69, 0x72, 0x58, 0x12, 0x13, 0x0a, 0x65, 0x18, 0x17, 0x20, 0x01, 0x28, 0x05, 0x52, 0x07, 0x62, 0x6c, 0x53, 0x74, 0x61, 0x74, 0x65,
0x04, 0x64, 0x69, 0x72, 0x59, 0x18, 0xea, 0x07, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x64, 0x69, 0x12, 0x28, 0x0a, 0x0f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x49, 0x6e, 0x42, 0x6c, 0x53, 0x74,
0x72, 0x59, 0x12, 0x13, 0x0a, 0x04, 0x76, 0x65, 0x6c, 0x58, 0x18, 0xeb, 0x07, 0x20, 0x01, 0x28, 0x61, 0x74, 0x65, 0x18, 0x18, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0f, 0x66, 0x72, 0x61, 0x6d, 0x65,
0x05, 0x52, 0x04, 0x76, 0x65, 0x6c, 0x58, 0x12, 0x13, 0x0a, 0x04, 0x76, 0x65, 0x6c, 0x59, 0x18, 0x73, 0x49, 0x6e, 0x42, 0x6c, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x23, 0x0a, 0x0c, 0x76, 0x69,
0xec, 0x07, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x76, 0x65, 0x6c, 0x59, 0x12, 0x15, 0x0a, 0x05, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x47, 0x72, 0x69, 0x64, 0x58, 0x18, 0xe7, 0x07, 0x20, 0x01, 0x28,
0x73, 0x70, 0x65, 0x65, 0x64, 0x18, 0xed, 0x07, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x73, 0x70, 0x05, 0x52, 0x0c, 0x76, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x47, 0x72, 0x69, 0x64, 0x58, 0x12,
0x65, 0x65, 0x64, 0x22, 0xc9, 0x05, 0x0a, 0x12, 0x42, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x43, 0x6f, 0x23, 0x0a, 0x0c, 0x76, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x47, 0x72, 0x69, 0x64, 0x59, 0x18,
0x6c, 0x6c, 0x69, 0x64, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x1c, 0x0a, 0x09, 0x73, 0x74, 0xe8, 0x07, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0c, 0x76, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x47,
0x61, 0x67, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x72, 0x69, 0x64, 0x59, 0x12, 0x13, 0x0a, 0x04, 0x64, 0x69, 0x72, 0x58, 0x18, 0xe9, 0x07, 0x20,
0x74, 0x61, 0x67, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x26, 0x0a, 0x0e, 0x69, 0x6e, 0x74, 0x65, 0x01, 0x28, 0x05, 0x52, 0x04, 0x64, 0x69, 0x72, 0x58, 0x12, 0x13, 0x0a, 0x04, 0x64, 0x69, 0x72,
0x72, 0x76, 0x61, 0x6c, 0x54, 0x6f, 0x50, 0x69, 0x6e, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x59, 0x18, 0xea, 0x07, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x64, 0x69, 0x72, 0x59, 0x12, 0x13,
0x52, 0x0e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x54, 0x6f, 0x50, 0x69, 0x6e, 0x67, 0x0a, 0x04, 0x76, 0x65, 0x6c, 0x58, 0x18, 0xeb, 0x07, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x76,
0x12, 0x34, 0x0a, 0x15, 0x77, 0x69, 0x6c, 0x6c, 0x4b, 0x69, 0x63, 0x6b, 0x49, 0x66, 0x49, 0x6e, 0x65, 0x6c, 0x58, 0x12, 0x13, 0x0a, 0x04, 0x76, 0x65, 0x6c, 0x59, 0x18, 0xec, 0x07, 0x20, 0x01,
0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x46, 0x6f, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x28, 0x05, 0x52, 0x04, 0x76, 0x65, 0x6c, 0x59, 0x12, 0x15, 0x0a, 0x05, 0x73, 0x70, 0x65, 0x65,
0x15, 0x77, 0x69, 0x6c, 0x6c, 0x4b, 0x69, 0x63, 0x6b, 0x49, 0x66, 0x49, 0x6e, 0x61, 0x63, 0x74, 0x64, 0x18, 0xed, 0x07, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x73, 0x70, 0x65, 0x65, 0x64, 0x22,
0x69, 0x76, 0x65, 0x46, 0x6f, 0x72, 0x12, 0x20, 0x0a, 0x0b, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0xc9, 0x05, 0x0a, 0x12, 0x42, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x43, 0x6f, 0x6c, 0x6c, 0x69, 0x64,
0x6f, 0x6f, 0x6d, 0x49, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0b, 0x62, 0x6f, 0x75, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x1c, 0x0a, 0x09, 0x73, 0x74, 0x61, 0x67, 0x65, 0x4e,
0x6e, 0x64, 0x52, 0x6f, 0x6f, 0x6d, 0x49, 0x64, 0x12, 0x30, 0x0a, 0x13, 0x62, 0x61, 0x74, 0x74, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x74, 0x61, 0x67, 0x65,
0x6c, 0x65, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4e, 0x61, 0x6e, 0x6f, 0x73, 0x18, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x26, 0x0a, 0x0e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c,
0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x13, 0x62, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x44, 0x75, 0x72, 0x54, 0x6f, 0x50, 0x69, 0x6e, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0e, 0x69, 0x6e,
0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4e, 0x61, 0x6e, 0x6f, 0x73, 0x12, 0x46, 0x0a, 0x1e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x54, 0x6f, 0x50, 0x69, 0x6e, 0x67, 0x12, 0x34, 0x0a, 0x15,
0x70, 0x75, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x55, 0x70, 0x73, 0x79, 0x6e, 0x63, 0x44, 0x65, 0x77, 0x69, 0x6c, 0x6c, 0x4b, 0x69, 0x63, 0x6b, 0x49, 0x66, 0x49, 0x6e, 0x61, 0x63, 0x74, 0x69,
0x6c, 0x61, 0x79, 0x54, 0x6f, 0x6c, 0x65, 0x72, 0x61, 0x6e, 0x63, 0x65, 0x18, 0x06, 0x20, 0x01, 0x76, 0x65, 0x46, 0x6f, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x15, 0x77, 0x69, 0x6c,
0x28, 0x05, 0x52, 0x1e, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x55, 0x70, 0x6c, 0x4b, 0x69, 0x63, 0x6b, 0x49, 0x66, 0x49, 0x6e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x46,
0x73, 0x79, 0x6e, 0x63, 0x44, 0x65, 0x6c, 0x61, 0x79, 0x54, 0x6f, 0x6c, 0x65, 0x72, 0x61, 0x6e, 0x6f, 0x72, 0x12, 0x20, 0x0a, 0x0b, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x6f, 0x6f, 0x6d, 0x49,
0x63, 0x65, 0x12, 0x48, 0x0a, 0x1f, 0x6d, 0x61, 0x78, 0x43, 0x68, 0x61, 0x73, 0x69, 0x6e, 0x67, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0b, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x6f,
0x52, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x50, 0x65, 0x72, 0x55, 0x6f, 0x6d, 0x49, 0x64, 0x12, 0x30, 0x0a, 0x13, 0x62, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x44, 0x75,
0x70, 0x64, 0x61, 0x74, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x05, 0x52, 0x1f, 0x6d, 0x61, 0x78, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4e, 0x61, 0x6e, 0x6f, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28,
0x43, 0x68, 0x61, 0x73, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x46, 0x72, 0x61, 0x03, 0x52, 0x13, 0x62, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f,
0x6d, 0x65, 0x73, 0x50, 0x65, 0x72, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x12, 0x3c, 0x0a, 0x19, 0x6e, 0x4e, 0x61, 0x6e, 0x6f, 0x73, 0x12, 0x46, 0x0a, 0x1e, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x46,
0x72, 0x6f, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x45, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x72, 0x61, 0x6d, 0x65, 0x55, 0x70, 0x73, 0x79, 0x6e, 0x63, 0x44, 0x65, 0x6c, 0x61, 0x79, 0x54,
0x64, 0x44, 0x74, 0x4d, 0x69, 0x6c, 0x6c, 0x69, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x01, 0x52, 0x6f, 0x6c, 0x65, 0x72, 0x61, 0x6e, 0x63, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x05, 0x52, 0x1e,
0x19, 0x72, 0x6f, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x45, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x55, 0x70, 0x73, 0x79, 0x6e, 0x63,
0x65, 0x64, 0x44, 0x74, 0x4d, 0x69, 0x6c, 0x6c, 0x69, 0x73, 0x12, 0x3a, 0x0a, 0x18, 0x72, 0x6f, 0x44, 0x65, 0x6c, 0x61, 0x79, 0x54, 0x6f, 0x6c, 0x65, 0x72, 0x61, 0x6e, 0x63, 0x65, 0x12, 0x48,
0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x45, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x64, 0x44, 0x0a, 0x1f, 0x6d, 0x61, 0x78, 0x43, 0x68, 0x61, 0x73, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x6e, 0x64,
0x74, 0x4e, 0x61, 0x6e, 0x6f, 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x03, 0x52, 0x18, 0x72, 0x6f, 0x65, 0x72, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x50, 0x65, 0x72, 0x55, 0x70, 0x64, 0x61, 0x74,
0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x45, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x64, 0x44, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x05, 0x52, 0x1f, 0x6d, 0x61, 0x78, 0x43, 0x68, 0x61, 0x73,
0x74, 0x4e, 0x61, 0x6e, 0x6f, 0x73, 0x12, 0x28, 0x0a, 0x0f, 0x72, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x50,
0x43, 0x61, 0x63, 0x68, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x05, 0x52, 0x65, 0x72, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x12, 0x3c, 0x0a, 0x19, 0x72, 0x6f, 0x6c, 0x6c,
0x0f, 0x72, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x43, 0x61, 0x63, 0x68, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x62, 0x61, 0x63, 0x6b, 0x45, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x64, 0x44, 0x74, 0x4d,
0x12, 0x22, 0x0a, 0x0c, 0x73, 0x70, 0x61, 0x63, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x58, 0x69, 0x6c, 0x6c, 0x69, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x01, 0x52, 0x19, 0x72, 0x6f, 0x6c,
0x18, 0x0b, 0x20, 0x01, 0x28, 0x01, 0x52, 0x0c, 0x73, 0x70, 0x61, 0x63, 0x65, 0x4f, 0x66, 0x66, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x45, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x64, 0x44, 0x74,
0x73, 0x65, 0x74, 0x58, 0x12, 0x22, 0x0a, 0x0c, 0x73, 0x70, 0x61, 0x63, 0x65, 0x4f, 0x66, 0x66, 0x4d, 0x69, 0x6c, 0x6c, 0x69, 0x73, 0x12, 0x3a, 0x0a, 0x18, 0x72, 0x6f, 0x6c, 0x6c, 0x62, 0x61,
0x73, 0x65, 0x74, 0x59, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x01, 0x52, 0x0c, 0x73, 0x70, 0x61, 0x63, 0x63, 0x6b, 0x45, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x64, 0x44, 0x74, 0x4e, 0x61, 0x6e,
0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x59, 0x12, 0x2a, 0x0a, 0x10, 0x63, 0x6f, 0x6c, 0x6c, 0x6f, 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x03, 0x52, 0x18, 0x72, 0x6f, 0x6c, 0x6c, 0x62, 0x61,
0x69, 0x73, 0x69, 0x6f, 0x6e, 0x4d, 0x69, 0x6e, 0x53, 0x74, 0x65, 0x70, 0x18, 0x0d, 0x20, 0x01, 0x63, 0x6b, 0x45, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x64, 0x44, 0x74, 0x4e, 0x61, 0x6e,
0x28, 0x05, 0x52, 0x10, 0x63, 0x6f, 0x6c, 0x6c, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x4d, 0x69, 0x6e, 0x6f, 0x73, 0x12, 0x28, 0x0a, 0x0f, 0x72, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x43, 0x61, 0x63, 0x68,
0x53, 0x74, 0x65, 0x70, 0x12, 0x39, 0x0a, 0x17, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x44, 0x61, 0x74, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0f, 0x72, 0x65, 0x6e,
0x61, 0x4c, 0x6f, 0x67, 0x67, 0x69, 0x6e, 0x67, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x64, 0x65, 0x72, 0x43, 0x61, 0x63, 0x68, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x22, 0x0a, 0x0c,
0x80, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x17, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x44, 0x61, 0x74, 0x73, 0x70, 0x61, 0x63, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x58, 0x18, 0x0b, 0x20, 0x01,
0x61, 0x4c, 0x6f, 0x67, 0x67, 0x69, 0x6e, 0x67, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x22, 0x28, 0x01, 0x52, 0x0c, 0x73, 0x70, 0x61, 0x63, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x58,
0xc2, 0x03, 0x0a, 0x11, 0x52, 0x6f, 0x6f, 0x6d, 0x44, 0x6f, 0x77, 0x6e, 0x73, 0x79, 0x6e, 0x63, 0x12, 0x22, 0x0a, 0x0c, 0x73, 0x70, 0x61, 0x63, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x59,
0x46, 0x72, 0x61, 0x6d, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x01, 0x52, 0x0c, 0x73, 0x70, 0x61, 0x63, 0x65, 0x4f, 0x66, 0x66,
0x05, 0x52, 0x02, 0x69, 0x64, 0x12, 0x36, 0x0a, 0x0a, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x73, 0x73, 0x65, 0x74, 0x59, 0x12, 0x2a, 0x0a, 0x10, 0x63, 0x6f, 0x6c, 0x6c, 0x69, 0x73, 0x69, 0x6f,
0x41, 0x72, 0x72, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6e, 0x4d, 0x69, 0x6e, 0x53, 0x74, 0x65, 0x70, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x05, 0x52, 0x10,
0x6f, 0x73, 0x2e, 0x50, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x44, 0x6f, 0x77, 0x6e, 0x73, 0x79, 0x6e, 0x63, 0x6f, 0x6c, 0x6c, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x4d, 0x69, 0x6e, 0x53, 0x74, 0x65, 0x70,
0x63, 0x52, 0x0a, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x73, 0x41, 0x72, 0x72, 0x12, 0x26, 0x0a, 0x12, 0x39, 0x0a, 0x17, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x44, 0x61, 0x74, 0x61, 0x4c, 0x6f, 0x67,
0x0e, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x64, 0x6f, 0x77, 0x6e, 0x4e, 0x61, 0x6e, 0x6f, 0x73, 0x18, 0x67, 0x69, 0x6e, 0x67, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x80, 0x08, 0x20, 0x01,
0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x64, 0x6f, 0x77, 0x6e, 0x28, 0x08, 0x52, 0x17, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x44, 0x61, 0x74, 0x61, 0x4c, 0x6f, 0x67,
0x4e, 0x61, 0x6e, 0x6f, 0x73, 0x12, 0x37, 0x0a, 0x0c, 0x6d, 0x65, 0x6c, 0x65, 0x65, 0x42, 0x75, 0x67, 0x69, 0x6e, 0x67, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x22, 0xc2, 0x03, 0x0a, 0x11,
0x6c, 0x6c, 0x65, 0x74, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x70, 0x72, 0x52, 0x6f, 0x6f, 0x6d, 0x44, 0x6f, 0x77, 0x6e, 0x73, 0x79, 0x6e, 0x63, 0x46, 0x72, 0x61, 0x6d,
0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x4d, 0x65, 0x6c, 0x65, 0x65, 0x42, 0x75, 0x6c, 0x6c, 0x65, 0x74, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x02, 0x69,
0x52, 0x0c, 0x6d, 0x65, 0x6c, 0x65, 0x65, 0x42, 0x75, 0x6c, 0x6c, 0x65, 0x74, 0x73, 0x12, 0x40, 0x64, 0x12, 0x36, 0x0a, 0x0a, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x73, 0x41, 0x72, 0x72, 0x18,
0x0a, 0x0f, 0x66, 0x69, 0x72, 0x65, 0x62, 0x61, 0x6c, 0x6c, 0x42, 0x75, 0x6c, 0x6c, 0x65, 0x74, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x50,
0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x44, 0x6f, 0x77, 0x6e, 0x73, 0x79, 0x6e, 0x63, 0x52, 0x0a, 0x70,
0x2e, 0x46, 0x69, 0x72, 0x65, 0x62, 0x61, 0x6c, 0x6c, 0x42, 0x75, 0x6c, 0x6c, 0x65, 0x74, 0x52, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x73, 0x41, 0x72, 0x72, 0x12, 0x26, 0x0a, 0x0e, 0x63, 0x6f, 0x75,
0x0f, 0x66, 0x69, 0x72, 0x65, 0x62, 0x61, 0x6c, 0x6c, 0x42, 0x75, 0x6c, 0x6c, 0x65, 0x74, 0x73, 0x6e, 0x74, 0x64, 0x6f, 0x77, 0x6e, 0x4e, 0x61, 0x6e, 0x6f, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28,
0x12, 0x37, 0x0a, 0x16, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x55, 0x6e, 0x63, 0x6f, 0x6e, 0x03, 0x52, 0x0e, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x64, 0x6f, 0x77, 0x6e, 0x4e, 0x61, 0x6e, 0x6f,
0x66, 0x69, 0x72, 0x6d, 0x65, 0x64, 0x4d, 0x61, 0x73, 0x6b, 0x18, 0x80, 0x08, 0x20, 0x01, 0x28, 0x73, 0x12, 0x37, 0x0a, 0x0c, 0x6d, 0x65, 0x6c, 0x65, 0x65, 0x42, 0x75, 0x6c, 0x6c, 0x65, 0x74,
0x04, 0x52, 0x16, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x55, 0x6e, 0x63, 0x6f, 0x6e, 0x66, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73,
0x69, 0x72, 0x6d, 0x65, 0x64, 0x4d, 0x61, 0x73, 0x6b, 0x12, 0x2d, 0x0a, 0x11, 0x73, 0x68, 0x6f, 0x2e, 0x4d, 0x65, 0x6c, 0x65, 0x65, 0x42, 0x75, 0x6c, 0x6c, 0x65, 0x74, 0x52, 0x0c, 0x6d, 0x65,
0x75, 0x6c, 0x64, 0x46, 0x6f, 0x72, 0x63, 0x65, 0x52, 0x65, 0x73, 0x79, 0x6e, 0x63, 0x18, 0x81, 0x6c, 0x65, 0x65, 0x42, 0x75, 0x6c, 0x6c, 0x65, 0x74, 0x73, 0x12, 0x40, 0x0a, 0x0f, 0x66, 0x69,
0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x11, 0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x46, 0x6f, 0x72, 0x72, 0x65, 0x62, 0x61, 0x6c, 0x6c, 0x42, 0x75, 0x6c, 0x6c, 0x65, 0x74, 0x73, 0x18, 0x05, 0x20,
0x63, 0x65, 0x52, 0x65, 0x73, 0x79, 0x6e, 0x63, 0x12, 0x25, 0x0a, 0x0d, 0x73, 0x70, 0x65, 0x63, 0x03, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x46, 0x69, 0x72,
0x69, 0x65, 0x73, 0x49, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x18, 0x82, 0x08, 0x20, 0x03, 0x28, 0x05, 0x65, 0x62, 0x61, 0x6c, 0x6c, 0x42, 0x75, 0x6c, 0x6c, 0x65, 0x74, 0x52, 0x0f, 0x66, 0x69, 0x72,
0x52, 0x0d, 0x73, 0x70, 0x65, 0x63, 0x69, 0x65, 0x73, 0x49, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x65, 0x62, 0x61, 0x6c, 0x6c, 0x42, 0x75, 0x6c, 0x6c, 0x65, 0x74, 0x73, 0x12, 0x37, 0x0a, 0x16,
0x33, 0x0a, 0x14, 0x62, 0x75, 0x6c, 0x6c, 0x65, 0x74, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x49, 0x64, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x55, 0x6e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d,
0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x18, 0x83, 0x08, 0x20, 0x01, 0x28, 0x05, 0x52, 0x14, 0x65, 0x64, 0x4d, 0x61, 0x73, 0x6b, 0x18, 0x80, 0x08, 0x20, 0x01, 0x28, 0x04, 0x52, 0x16, 0x62,
0x62, 0x75, 0x6c, 0x6c, 0x65, 0x74, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x49, 0x64, 0x43, 0x6f, 0x75, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x55, 0x6e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d, 0x65,
0x6e, 0x74, 0x65, 0x72, 0x42, 0x13, 0x5a, 0x11, 0x62, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x5f, 0x73, 0x64, 0x4d, 0x61, 0x73, 0x6b, 0x12, 0x2d, 0x0a, 0x11, 0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x46,
0x72, 0x76, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x6f, 0x72, 0x63, 0x65, 0x52, 0x65, 0x73, 0x79, 0x6e, 0x63, 0x18, 0x81, 0x08, 0x20, 0x01, 0x28,
0x33, 0x08, 0x52, 0x11, 0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x46, 0x6f, 0x72, 0x63, 0x65, 0x52, 0x65,
0x73, 0x79, 0x6e, 0x63, 0x12, 0x25, 0x0a, 0x0d, 0x73, 0x70, 0x65, 0x63, 0x69, 0x65, 0x73, 0x49,
0x64, 0x4c, 0x69, 0x73, 0x74, 0x18, 0x82, 0x08, 0x20, 0x03, 0x28, 0x05, 0x52, 0x0d, 0x73, 0x70,
0x65, 0x63, 0x69, 0x65, 0x73, 0x49, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x33, 0x0a, 0x14, 0x62,
0x75, 0x6c, 0x6c, 0x65, 0x74, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x49, 0x64, 0x43, 0x6f, 0x75, 0x6e,
0x74, 0x65, 0x72, 0x18, 0x83, 0x08, 0x20, 0x01, 0x28, 0x05, 0x52, 0x14, 0x62, 0x75, 0x6c, 0x6c,
0x65, 0x74, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x49, 0x64, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72,
0x42, 0x13, 0x5a, 0x11, 0x62, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x5f, 0x73, 0x72, 0x76, 0x2f, 0x70,
0x72, 0x6f, 0x74, 0x6f, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
} }
var ( var (

View File

@@ -46,6 +46,7 @@ func Serve(c *gin.Context) {
c.AbortWithStatus(http.StatusBadRequest) c.AbortWithStatus(http.StatusBadRequest)
return return
} }
boundRoomId := 0 boundRoomId := 0
expectedRoomId := 0 expectedRoomId := 0
var err error var err error
@@ -395,3 +396,89 @@ func Serve(c *gin.Context) {
startOrFeedHeartbeatWatchdog(conn) startOrFeedHeartbeatWatchdog(conn)
go receivingLoopAgainstPlayer() go receivingLoopAgainstPlayer()
} }
func HandleSecondaryWsSessionForPlayer(c *gin.Context) {
token, ok := c.GetQuery("intAuthToken")
if !ok {
Logger.Warn("Secondary ws session req must have intAuthToken param!")
c.AbortWithStatus(http.StatusBadRequest)
return
}
boundRoomId := 0
var err error = nil
if boundRoomIdStr, hasBoundRoomId := c.GetQuery("boundRoomId"); hasBoundRoomId {
boundRoomId, err = strconv.Atoi(boundRoomIdStr)
if err != nil {
c.AbortWithStatus(http.StatusBadRequest)
return
}
} else {
Logger.Warn("Secondary ws session req must have boundRoomId param:", zap.Any("intAuthToken", token))
c.AbortWithStatus(http.StatusBadRequest)
return
}
var pRoom *models.Room = nil
// Deliberately querying playerId after querying room, because the former is against persistent storage and could be slow!
if tmpPRoom, existent := (*models.RoomMapManagerIns)[int32(boundRoomId)]; !existent {
Logger.Warn("Secondary ws session failed to get:\n", zap.Any("intAuthToken", token), zap.Any("forBoundRoomId", boundRoomId))
c.AbortWithStatus(http.StatusBadRequest)
} else {
pRoom = tmpPRoom
}
// TODO: Wrap the following 2 stmts by sql transaction!
playerId, err := models.GetPlayerIdByToken(token)
if err != nil || playerId == 0 {
// TODO: Abort with specific message.
Logger.Warn("Secondary ws session playerLogin record not found for ws authentication:", zap.Any("intAuthToken", token))
c.AbortWithStatus(http.StatusBadRequest)
return
}
Logger.Info("Secondary ws session playerLogin record has been found for ws authentication:", zap.Any("playerId", playerId), zap.Any("intAuthToken", token), zap.Any("boundRoomId", boundRoomId))
conn, err := upgrader.Upgrade(c.Writer, c.Request, nil)
if err != nil {
Logger.Error("Secondary ws session upgrade:", zap.Error(err), zap.Any("playerId", playerId))
c.AbortWithStatus(http.StatusBadRequest)
return
}
connHasBeenSignaledToClose := int32(0)
pConnHasBeenSignaledToClose := &connHasBeenSignaledToClose
signalToCloseConnOfThisPlayer := func(customRetCode int, customRetMsg string) {
if swapped := atomic.CompareAndSwapInt32(pConnHasBeenSignaledToClose, 0, 1); !swapped {
return
}
Logger.Warn("Secondary ws session signalToCloseConnOfThisPlayer:", zap.Any("playerId", playerId), zap.Any("customRetCode", customRetCode), zap.Any("customRetMsg", customRetMsg))
defer func() {
if r := recover(); r != nil {
Logger.Error("Secondary ws session recovered from: ", zap.Any("panic", r))
}
}()
closeMessage := websocket.FormatCloseMessage(customRetCode, customRetMsg)
err := conn.WriteControl(websocket.CloseMessage, closeMessage, time.Now().Add(time.Millisecond*(ConstVals.Ws.WillKickIfInactiveFor)))
if err != nil {
Logger.Error("Secondary ws session unable to send the CloseFrame control message to player(client-side):", zap.Any("playerId", playerId), zap.Error(err))
}
time.AfterFunc(3*time.Second, func() {
// To actually terminates the underlying TCP connection which might be in `CLOSE_WAIT` state if inspected by `netstat`.
conn.Close()
})
}
onReceivedCloseMessageFromClient := func(code int, text string) error {
Logger.Warn("Secondary ws session triggered `onReceivedCloseMessageFromClient`:", zap.Any("code", code), zap.Any("playerId", playerId), zap.Any("message", text))
signalToCloseConnOfThisPlayer(code, text)
return nil
}
conn.SetCloseHandler(onReceivedCloseMessageFromClient)
pRoom.SetSecondarySession(int32(playerId), conn, signalToCloseConnOfThisPlayer)
}

File diff suppressed because one or more lines are too long

BIN
charts/ServerClients.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 79 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 MiB

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,7 @@
{
"ver": "1.0.1",
"uuid": "c7c2ac6e-f1ea-4233-b6a4-aa5b96b61e17",
"isSubpackage": false,
"subpackageName": "",
"subMetas": {}
}

View File

@@ -0,0 +1,55 @@
{
"__type__": "cc.AnimationClip",
"_name": "Fireball1Explosion",
"_objFlags": 0,
"_native": "",
"_duration": 0.26666666666666666,
"sample": 60,
"speed": 1,
"wrapMode": 1,
"curveData": {
"comps": {
"cc.Sprite": {
"spriteFrame": [
{
"frame": 0,
"value": {
"__uuid__": "f4ad4f9f-4890-450b-9334-68fe6b903893"
}
},
{
"frame": 0.05,
"value": {
"__uuid__": "c6a5994f-251d-4191-a550-dfef979bab59"
}
},
{
"frame": 0.11666666666666667,
"value": {
"__uuid__": "417e58d9-e364-47f7-9364-f31ad3452adc"
}
},
{
"frame": 0.15,
"value": {
"__uuid__": "8b566f26-b34d-4da6-bdaa-078358a5b685"
}
},
{
"frame": 0.2,
"value": {
"__uuid__": "6ec5f75d-307e-4292-b667-cbbb5a52c2f6"
}
},
{
"frame": 0.25,
"value": {
"__uuid__": "d89977f1-d927-4a08-9591-9feb1daf68c8"
}
}
]
}
}
},
"events": []
}

View File

@@ -0,0 +1,5 @@
{
"ver": "2.1.0",
"uuid": "7941215a-2b8c-4798-954b-4f1b16d5f6f5",
"subMetas": {}
}

View File

@@ -0,0 +1,79 @@
{
"__type__": "cc.AnimationClip",
"_name": "MeleeExplosion1",
"_objFlags": 0,
"_native": "",
"_duration": 0.16666666666666666,
"sample": 60,
"speed": 1,
"wrapMode": 1,
"curveData": {
"comps": {
"cc.Sprite": {
"spriteFrame": [
{
"frame": 0,
"value": {
"__uuid__": "ab4866e8-ce52-4bc1-be19-b03687acf0d6"
}
},
{
"frame": 0.016666666666666666,
"value": {
"__uuid__": "67cc8a51-0ebe-49db-a941-7aabc5655ecf"
}
},
{
"frame": 0.03333333333333333,
"value": {
"__uuid__": "367592d0-3566-4b6a-8707-01d6a8dbe34a"
}
},
{
"frame": 0.05,
"value": {
"__uuid__": "cc336b1e-b5d8-4a89-96fc-7ada0e232389"
}
},
{
"frame": 0.06666666666666667,
"value": {
"__uuid__": "a457cc63-08bd-4cfa-b84a-7287d0343ecf"
}
},
{
"frame": 0.08333333333333333,
"value": {
"__uuid__": "89697d35-cde3-4392-a231-db91d4ede29b"
}
},
{
"frame": 0.1,
"value": {
"__uuid__": "3815bf7a-0a48-40e0-b791-0a0be9ec0da6"
}
},
{
"frame": 0.11666666666666667,
"value": {
"__uuid__": "20e691ee-a0c0-4710-8981-8dee1911e819"
}
},
{
"frame": 0.13333333333333333,
"value": {
"__uuid__": "94e678c5-0780-4f2b-bf3b-86c6c0a75c23"
}
},
{
"frame": 0.15,
"value": {
"__uuid__": "af4f9c62-4c7e-43a4-b9b3-dd3effbbbafb"
}
}
]
}
}
},
"events": []
}

View File

@@ -0,0 +1,5 @@
{
"ver": "2.1.0",
"uuid": "954a2924-89df-4df4-93fc-36d2b22e7619",
"subMetas": {}
}

View File

@@ -0,0 +1,79 @@
{
"__type__": "cc.AnimationClip",
"_name": "MeleeExplosion2",
"_objFlags": 0,
"_native": "",
"_duration": 0.26666666666666666,
"sample": 60,
"speed": 1,
"wrapMode": 1,
"curveData": {
"comps": {
"cc.Sprite": {
"spriteFrame": [
{
"frame": 0,
"value": {
"__uuid__": "89e54317-7835-4d4c-9c04-579da8b33c54"
}
},
{
"frame": 0.016666666666666666,
"value": {
"__uuid__": "2a186e00-a0c5-4c8a-b0ab-c84d56dcee7c"
}
},
{
"frame": 0.05,
"value": {
"__uuid__": "083168e3-6ccc-4c5b-a800-2554bffc67d4"
}
},
{
"frame": 0.08333333333333333,
"value": {
"__uuid__": "d4b12ec9-6f04-493c-91e5-22b1a212262a"
}
},
{
"frame": 0.13333333333333333,
"value": {
"__uuid__": "13038788-b0f9-4714-960b-c98619a0d0ce"
}
},
{
"frame": 0.16666666666666666,
"value": {
"__uuid__": "94c21ed7-94a2-47a4-9537-fe5d9c51d7b0"
}
},
{
"frame": 0.2,
"value": {
"__uuid__": "d5340298-923c-4bd7-9fd7-7a2e029a2b44"
}
},
{
"frame": 0.21666666666666667,
"value": {
"__uuid__": "c4b145c0-0145-4e09-8559-9ef508d95be8"
}
},
{
"frame": 0.23333333333333334,
"value": {
"__uuid__": "79398d4d-305e-4987-b199-d9d9649cf490"
}
},
{
"frame": 0.25,
"value": {
"__uuid__": "c032eb65-fdf3-41e6-b868-d95df34168df"
}
}
]
}
}
},
"events": []
}

View File

@@ -0,0 +1,5 @@
{
"ver": "2.1.0",
"uuid": "5bd304eb-c8ba-426f-a9ab-5698ac62de85",
"subMetas": {}
}

View File

@@ -0,0 +1,79 @@
{
"__type__": "cc.AnimationClip",
"_name": "MeleeExplosion3",
"_objFlags": 0,
"_native": "",
"_duration": 0.26666666666666666,
"sample": 60,
"speed": 1,
"wrapMode": 1,
"curveData": {
"comps": {
"cc.Sprite": {
"spriteFrame": [
{
"frame": 0,
"value": {
"__uuid__": "20d9ce6b-d9ab-4402-8c59-770ad0adf570"
}
},
{
"frame": 0.016666666666666666,
"value": {
"__uuid__": "0654601f-6788-4a2c-aed4-8dfbe1c5fdd0"
}
},
{
"frame": 0.03333333333333333,
"value": {
"__uuid__": "0913e11a-c796-4b58-94cf-f70b3869deff"
}
},
{
"frame": 0.06666666666666667,
"value": {
"__uuid__": "d6b58622-2cc3-4ee6-a34f-1a18deb73700"
}
},
{
"frame": 0.08333333333333333,
"value": {
"__uuid__": "b83c6261-b86f-4323-ad11-7375cac02a2b"
}
},
{
"frame": 0.11666666666666667,
"value": {
"__uuid__": "b458c047-b7b5-4476-996e-d4c1ca85ef9c"
}
},
{
"frame": 0.15,
"value": {
"__uuid__": "3971256a-8120-448e-8adf-de8d67dedfd3"
}
},
{
"frame": 0.18333333333333332,
"value": {
"__uuid__": "0e548d92-36c8-4795-b3dc-2bc2cfcd7170"
}
},
{
"frame": 0.21666666666666667,
"value": {
"__uuid__": "25f94245-87b0-4954-abab-c817c80fed37"
}
},
{
"frame": 0.25,
"value": {
"__uuid__": "20d9ce6b-d9ab-4402-8c59-770ad0adf570"
}
}
]
}
}
},
"events": []
}

View File

@@ -0,0 +1,5 @@
{
"ver": "2.1.0",
"uuid": "5054633c-a588-4506-b4ac-eef29b1d8511",
"subMetas": {}
}

View File

@@ -0,0 +1,476 @@
<?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>Explosion1_1.png</key>
<dict>
<key>aliases</key>
<array/>
<key>spriteOffset</key>
<string>{0,0}</string>
<key>spriteSize</key>
<string>{71,67}</string>
<key>spriteSourceSize</key>
<string>{71,67}</string>
<key>textureRect</key>
<string>{{0,506},{71,67}}</string>
<key>textureRotated</key>
<true/>
</dict>
<key>Explosion1_10.png</key>
<dict>
<key>aliases</key>
<array/>
<key>spriteOffset</key>
<string>{0,0}</string>
<key>spriteSize</key>
<string>{71,67}</string>
<key>spriteSourceSize</key>
<string>{71,67}</string>
<key>textureRect</key>
<string>{{0,577},{71,67}}</string>
<key>textureRotated</key>
<true/>
</dict>
<key>Explosion1_2.png</key>
<dict>
<key>aliases</key>
<array/>
<key>spriteOffset</key>
<string>{0,0}</string>
<key>spriteSize</key>
<string>{71,67}</string>
<key>spriteSourceSize</key>
<string>{71,67}</string>
<key>textureRect</key>
<string>{{67,506},{71,67}}</string>
<key>textureRotated</key>
<true/>
</dict>
<key>Explosion1_3.png</key>
<dict>
<key>aliases</key>
<array/>
<key>spriteOffset</key>
<string>{0,0}</string>
<key>spriteSize</key>
<string>{71,67}</string>
<key>spriteSourceSize</key>
<string>{71,67}</string>
<key>textureRect</key>
<string>{{67,577},{71,67}}</string>
<key>textureRotated</key>
<true/>
</dict>
<key>Explosion1_4.png</key>
<dict>
<key>aliases</key>
<array/>
<key>spriteOffset</key>
<string>{0,0}</string>
<key>spriteSize</key>
<string>{71,67}</string>
<key>spriteSourceSize</key>
<string>{71,67}</string>
<key>textureRect</key>
<string>{{134,506},{71,67}}</string>
<key>textureRotated</key>
<true/>
</dict>
<key>Explosion1_5.png</key>
<dict>
<key>aliases</key>
<array/>
<key>spriteOffset</key>
<string>{0,0}</string>
<key>spriteSize</key>
<string>{71,67}</string>
<key>spriteSourceSize</key>
<string>{71,67}</string>
<key>textureRect</key>
<string>{{134,577},{71,67}}</string>
<key>textureRotated</key>
<true/>
</dict>
<key>Explosion1_6.png</key>
<dict>
<key>aliases</key>
<array/>
<key>spriteOffset</key>
<string>{0,0}</string>
<key>spriteSize</key>
<string>{71,67}</string>
<key>spriteSourceSize</key>
<string>{71,67}</string>
<key>textureRect</key>
<string>{{355,503},{71,67}}</string>
<key>textureRotated</key>
<false/>
</dict>
<key>Explosion1_7.png</key>
<dict>
<key>aliases</key>
<array/>
<key>spriteOffset</key>
<string>{0,0}</string>
<key>spriteSize</key>
<string>{71,67}</string>
<key>spriteSourceSize</key>
<string>{71,67}</string>
<key>textureRect</key>
<string>{{426,503},{71,67}}</string>
<key>textureRotated</key>
<false/>
</dict>
<key>Explosion1_8.png</key>
<dict>
<key>aliases</key>
<array/>
<key>spriteOffset</key>
<string>{0,0}</string>
<key>spriteSize</key>
<string>{71,67}</string>
<key>spriteSourceSize</key>
<string>{71,67}</string>
<key>textureRect</key>
<string>{{355,570},{71,67}}</string>
<key>textureRotated</key>
<true/>
</dict>
<key>Explosion1_9.png</key>
<dict>
<key>aliases</key>
<array/>
<key>spriteOffset</key>
<string>{0,0}</string>
<key>spriteSize</key>
<string>{71,67}</string>
<key>spriteSourceSize</key>
<string>{71,67}</string>
<key>textureRect</key>
<string>{{422,570},{71,67}}</string>
<key>textureRotated</key>
<false/>
</dict>
<key>Explosion2_1.png</key>
<dict>
<key>aliases</key>
<array/>
<key>spriteOffset</key>
<string>{0,0}</string>
<key>spriteSize</key>
<string>{88,45}</string>
<key>spriteSourceSize</key>
<string>{88,45}</string>
<key>textureRect</key>
<string>{{462,0},{88,45}}</string>
<key>textureRotated</key>
<true/>
</dict>
<key>Explosion2_10.png</key>
<dict>
<key>aliases</key>
<array/>
<key>spriteOffset</key>
<string>{0,0}</string>
<key>spriteSize</key>
<string>{88,45}</string>
<key>spriteSourceSize</key>
<string>{88,45}</string>
<key>textureRect</key>
<string>{{462,88},{88,45}}</string>
<key>textureRotated</key>
<true/>
</dict>
<key>Explosion2_2.png</key>
<dict>
<key>aliases</key>
<array/>
<key>spriteOffset</key>
<string>{0,0}</string>
<key>spriteSize</key>
<string>{88,45}</string>
<key>spriteSourceSize</key>
<string>{88,45}</string>
<key>textureRect</key>
<string>{{462,176},{88,45}}</string>
<key>textureRotated</key>
<true/>
</dict>
<key>Explosion2_3.png</key>
<dict>
<key>aliases</key>
<array/>
<key>spriteOffset</key>
<string>{0,0}</string>
<key>spriteSize</key>
<string>{88,45}</string>
<key>spriteSourceSize</key>
<string>{88,45}</string>
<key>textureRect</key>
<string>{{462,264},{88,45}}</string>
<key>textureRotated</key>
<true/>
</dict>
<key>Explosion2_4.png</key>
<dict>
<key>aliases</key>
<array/>
<key>spriteOffset</key>
<string>{0,0}</string>
<key>spriteSize</key>
<string>{88,45}</string>
<key>spriteSourceSize</key>
<string>{88,45}</string>
<key>textureRect</key>
<string>{{0,304},{88,45}}</string>
<key>textureRotated</key>
<false/>
</dict>
<key>Explosion2_5.png</key>
<dict>
<key>aliases</key>
<array/>
<key>spriteOffset</key>
<string>{0,0}</string>
<key>spriteSize</key>
<string>{88,45}</string>
<key>spriteSourceSize</key>
<string>{88,45}</string>
<key>textureRect</key>
<string>{{88,304},{88,45}}</string>
<key>textureRotated</key>
<false/>
</dict>
<key>Explosion2_6.png</key>
<dict>
<key>aliases</key>
<array/>
<key>spriteOffset</key>
<string>{0,0}</string>
<key>spriteSize</key>
<string>{88,45}</string>
<key>spriteSourceSize</key>
<string>{88,45}</string>
<key>textureRect</key>
<string>{{176,304},{88,45}}</string>
<key>textureRotated</key>
<false/>
</dict>
<key>Explosion2_7.png</key>
<dict>
<key>aliases</key>
<array/>
<key>spriteOffset</key>
<string>{0,0}</string>
<key>spriteSize</key>
<string>{88,45}</string>
<key>spriteSourceSize</key>
<string>{88,45}</string>
<key>textureRect</key>
<string>{{264,304},{88,45}}</string>
<key>textureRotated</key>
<false/>
</dict>
<key>Explosion2_8.png</key>
<dict>
<key>aliases</key>
<array/>
<key>spriteOffset</key>
<string>{0,0}</string>
<key>spriteSize</key>
<string>{88,45}</string>
<key>spriteSourceSize</key>
<string>{88,45}</string>
<key>textureRect</key>
<string>{{352,304},{88,45}}</string>
<key>textureRotated</key>
<false/>
</dict>
<key>Explosion2_9.png</key>
<dict>
<key>aliases</key>
<array/>
<key>spriteOffset</key>
<string>{0,0}</string>
<key>spriteSize</key>
<string>{88,45}</string>
<key>spriteSourceSize</key>
<string>{88,45}</string>
<key>textureRect</key>
<string>{{456,352},{88,45}}</string>
<key>textureRotated</key>
<true/>
</dict>
<key>Explosion3_1.png</key>
<dict>
<key>aliases</key>
<array/>
<key>spriteOffset</key>
<string>{0,0}</string>
<key>spriteSize</key>
<string>{154,152}</string>
<key>spriteSourceSize</key>
<string>{154,152}</string>
<key>textureRect</key>
<string>{{0,0},{154,152}}</string>
<key>textureRotated</key>
<false/>
</dict>
<key>Explosion3_10.png</key>
<dict>
<key>aliases</key>
<array/>
<key>spriteOffset</key>
<string>{0,0}</string>
<key>spriteSize</key>
<string>{154,152}</string>
<key>spriteSourceSize</key>
<string>{154,152}</string>
<key>textureRect</key>
<string>{{154,0},{154,152}}</string>
<key>textureRotated</key>
<false/>
</dict>
<key>Explosion3_2.png</key>
<dict>
<key>aliases</key>
<array/>
<key>spriteOffset</key>
<string>{0,0}</string>
<key>spriteSize</key>
<string>{154,152}</string>
<key>spriteSourceSize</key>
<string>{154,152}</string>
<key>textureRect</key>
<string>{{308,0},{154,152}}</string>
<key>textureRotated</key>
<false/>
</dict>
<key>Explosion3_3.png</key>
<dict>
<key>aliases</key>
<array/>
<key>spriteOffset</key>
<string>{0,0}</string>
<key>spriteSize</key>
<string>{154,152}</string>
<key>spriteSourceSize</key>
<string>{154,152}</string>
<key>textureRect</key>
<string>{{0,152},{154,152}}</string>
<key>textureRotated</key>
<false/>
</dict>
<key>Explosion3_4.png</key>
<dict>
<key>aliases</key>
<array/>
<key>spriteOffset</key>
<string>{0,0}</string>
<key>spriteSize</key>
<string>{154,152}</string>
<key>spriteSourceSize</key>
<string>{154,152}</string>
<key>textureRect</key>
<string>{{154,152},{154,152}}</string>
<key>textureRotated</key>
<false/>
</dict>
<key>Explosion3_5.png</key>
<dict>
<key>aliases</key>
<array/>
<key>spriteOffset</key>
<string>{0,0}</string>
<key>spriteSize</key>
<string>{154,152}</string>
<key>spriteSourceSize</key>
<string>{154,152}</string>
<key>textureRect</key>
<string>{{308,152},{154,152}}</string>
<key>textureRotated</key>
<false/>
</dict>
<key>Explosion3_6.png</key>
<dict>
<key>aliases</key>
<array/>
<key>spriteOffset</key>
<string>{0,0}</string>
<key>spriteSize</key>
<string>{154,152}</string>
<key>spriteSourceSize</key>
<string>{154,152}</string>
<key>textureRect</key>
<string>{{0,352},{154,152}}</string>
<key>textureRotated</key>
<true/>
</dict>
<key>Explosion3_7.png</key>
<dict>
<key>aliases</key>
<array/>
<key>spriteOffset</key>
<string>{0,0}</string>
<key>spriteSize</key>
<string>{154,152}</string>
<key>spriteSourceSize</key>
<string>{154,152}</string>
<key>textureRect</key>
<string>{{152,349},{154,152}}</string>
<key>textureRotated</key>
<true/>
</dict>
<key>Explosion3_8.png</key>
<dict>
<key>aliases</key>
<array/>
<key>spriteOffset</key>
<string>{0,0}</string>
<key>spriteSize</key>
<string>{154,152}</string>
<key>spriteSourceSize</key>
<string>{154,152}</string>
<key>textureRect</key>
<string>{{201,503},{154,152}}</string>
<key>textureRotated</key>
<false/>
</dict>
<key>Explosion3_9.png</key>
<dict>
<key>aliases</key>
<array/>
<key>spriteOffset</key>
<string>{0,0}</string>
<key>spriteSize</key>
<string>{154,152}</string>
<key>spriteSourceSize</key>
<string>{154,152}</string>
<key>textureRect</key>
<string>{{304,349},{154,152}}</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>MeleeExplosions.png</string>
<key>size</key>
<string>{507,655}</string>
<key>smartupdate</key>
<string>$TexturePacker:SmartUpdate:6c1498ee6f30bdad4abeb6a9f6af8367:4c81e1a1720f2ad3535ac93f1b42991f:d9b184ec81b83b14db5cf31d298727df$</string>
<key>textureFileName</key>
<string>MeleeExplosions.png</string>
</dict>
</dict>
</plist>

View File

@@ -0,0 +1,672 @@
{
"ver": "1.2.4",
"uuid": "1c4c1dcb-54af-485b-9119-abd6d6d84526",
"rawTextureUuid": "b11569aa-2e43-4084-a3e5-42eec243c4eb",
"size": {
"width": 507,
"height": 655
},
"type": "Texture Packer",
"subMetas": {
"Explosion1_1.png": {
"ver": "1.0.4",
"uuid": "ab4866e8-ce52-4bc1-be19-b03687acf0d6",
"rawTextureUuid": "b11569aa-2e43-4084-a3e5-42eec243c4eb",
"trimType": "auto",
"trimThreshold": 1,
"rotated": true,
"offsetX": 0,
"offsetY": 0,
"trimX": 0,
"trimY": 506,
"width": 71,
"height": 67,
"rawWidth": 71,
"rawHeight": 67,
"borderTop": 0,
"borderBottom": 0,
"borderLeft": 0,
"borderRight": 0,
"spriteType": "normal",
"subMetas": {}
},
"Explosion1_10.png": {
"ver": "1.0.4",
"uuid": "af4f9c62-4c7e-43a4-b9b3-dd3effbbbafb",
"rawTextureUuid": "b11569aa-2e43-4084-a3e5-42eec243c4eb",
"trimType": "auto",
"trimThreshold": 1,
"rotated": true,
"offsetX": 0,
"offsetY": 0,
"trimX": 0,
"trimY": 577,
"width": 71,
"height": 67,
"rawWidth": 71,
"rawHeight": 67,
"borderTop": 0,
"borderBottom": 0,
"borderLeft": 0,
"borderRight": 0,
"spriteType": "normal",
"subMetas": {}
},
"Explosion1_2.png": {
"ver": "1.0.4",
"uuid": "67cc8a51-0ebe-49db-a941-7aabc5655ecf",
"rawTextureUuid": "b11569aa-2e43-4084-a3e5-42eec243c4eb",
"trimType": "auto",
"trimThreshold": 1,
"rotated": true,
"offsetX": 0,
"offsetY": 0,
"trimX": 67,
"trimY": 506,
"width": 71,
"height": 67,
"rawWidth": 71,
"rawHeight": 67,
"borderTop": 0,
"borderBottom": 0,
"borderLeft": 0,
"borderRight": 0,
"spriteType": "normal",
"subMetas": {}
},
"Explosion1_3.png": {
"ver": "1.0.4",
"uuid": "367592d0-3566-4b6a-8707-01d6a8dbe34a",
"rawTextureUuid": "b11569aa-2e43-4084-a3e5-42eec243c4eb",
"trimType": "auto",
"trimThreshold": 1,
"rotated": true,
"offsetX": 0,
"offsetY": 0,
"trimX": 67,
"trimY": 577,
"width": 71,
"height": 67,
"rawWidth": 71,
"rawHeight": 67,
"borderTop": 0,
"borderBottom": 0,
"borderLeft": 0,
"borderRight": 0,
"spriteType": "normal",
"subMetas": {}
},
"Explosion1_4.png": {
"ver": "1.0.4",
"uuid": "cc336b1e-b5d8-4a89-96fc-7ada0e232389",
"rawTextureUuid": "b11569aa-2e43-4084-a3e5-42eec243c4eb",
"trimType": "auto",
"trimThreshold": 1,
"rotated": true,
"offsetX": 0,
"offsetY": 0,
"trimX": 134,
"trimY": 506,
"width": 71,
"height": 67,
"rawWidth": 71,
"rawHeight": 67,
"borderTop": 0,
"borderBottom": 0,
"borderLeft": 0,
"borderRight": 0,
"spriteType": "normal",
"subMetas": {}
},
"Explosion1_5.png": {
"ver": "1.0.4",
"uuid": "a457cc63-08bd-4cfa-b84a-7287d0343ecf",
"rawTextureUuid": "b11569aa-2e43-4084-a3e5-42eec243c4eb",
"trimType": "auto",
"trimThreshold": 1,
"rotated": true,
"offsetX": 0,
"offsetY": 0,
"trimX": 134,
"trimY": 577,
"width": 71,
"height": 67,
"rawWidth": 71,
"rawHeight": 67,
"borderTop": 0,
"borderBottom": 0,
"borderLeft": 0,
"borderRight": 0,
"spriteType": "normal",
"subMetas": {}
},
"Explosion1_6.png": {
"ver": "1.0.4",
"uuid": "89697d35-cde3-4392-a231-db91d4ede29b",
"rawTextureUuid": "b11569aa-2e43-4084-a3e5-42eec243c4eb",
"trimType": "auto",
"trimThreshold": 1,
"rotated": false,
"offsetX": 0,
"offsetY": 0,
"trimX": 355,
"trimY": 503,
"width": 71,
"height": 67,
"rawWidth": 71,
"rawHeight": 67,
"borderTop": 0,
"borderBottom": 0,
"borderLeft": 0,
"borderRight": 0,
"spriteType": "normal",
"subMetas": {}
},
"Explosion1_7.png": {
"ver": "1.0.4",
"uuid": "3815bf7a-0a48-40e0-b791-0a0be9ec0da6",
"rawTextureUuid": "b11569aa-2e43-4084-a3e5-42eec243c4eb",
"trimType": "auto",
"trimThreshold": 1,
"rotated": false,
"offsetX": 0,
"offsetY": 0,
"trimX": 426,
"trimY": 503,
"width": 71,
"height": 67,
"rawWidth": 71,
"rawHeight": 67,
"borderTop": 0,
"borderBottom": 0,
"borderLeft": 0,
"borderRight": 0,
"spriteType": "normal",
"subMetas": {}
},
"Explosion1_8.png": {
"ver": "1.0.4",
"uuid": "20e691ee-a0c0-4710-8981-8dee1911e819",
"rawTextureUuid": "b11569aa-2e43-4084-a3e5-42eec243c4eb",
"trimType": "auto",
"trimThreshold": 1,
"rotated": true,
"offsetX": 0,
"offsetY": 0,
"trimX": 355,
"trimY": 570,
"width": 71,
"height": 67,
"rawWidth": 71,
"rawHeight": 67,
"borderTop": 0,
"borderBottom": 0,
"borderLeft": 0,
"borderRight": 0,
"spriteType": "normal",
"subMetas": {}
},
"Explosion1_9.png": {
"ver": "1.0.4",
"uuid": "94e678c5-0780-4f2b-bf3b-86c6c0a75c23",
"rawTextureUuid": "b11569aa-2e43-4084-a3e5-42eec243c4eb",
"trimType": "auto",
"trimThreshold": 1,
"rotated": false,
"offsetX": 0,
"offsetY": 0,
"trimX": 422,
"trimY": 570,
"width": 71,
"height": 67,
"rawWidth": 71,
"rawHeight": 67,
"borderTop": 0,
"borderBottom": 0,
"borderLeft": 0,
"borderRight": 0,
"spriteType": "normal",
"subMetas": {}
},
"Explosion2_1.png": {
"ver": "1.0.4",
"uuid": "89e54317-7835-4d4c-9c04-579da8b33c54",
"rawTextureUuid": "b11569aa-2e43-4084-a3e5-42eec243c4eb",
"trimType": "auto",
"trimThreshold": 1,
"rotated": true,
"offsetX": 0,
"offsetY": 0,
"trimX": 462,
"trimY": 0,
"width": 88,
"height": 45,
"rawWidth": 88,
"rawHeight": 45,
"borderTop": 0,
"borderBottom": 0,
"borderLeft": 0,
"borderRight": 0,
"spriteType": "normal",
"subMetas": {}
},
"Explosion2_10.png": {
"ver": "1.0.4",
"uuid": "c032eb65-fdf3-41e6-b868-d95df34168df",
"rawTextureUuid": "b11569aa-2e43-4084-a3e5-42eec243c4eb",
"trimType": "auto",
"trimThreshold": 1,
"rotated": true,
"offsetX": 0,
"offsetY": 0,
"trimX": 462,
"trimY": 88,
"width": 88,
"height": 45,
"rawWidth": 88,
"rawHeight": 45,
"borderTop": 0,
"borderBottom": 0,
"borderLeft": 0,
"borderRight": 0,
"spriteType": "normal",
"subMetas": {}
},
"Explosion2_2.png": {
"ver": "1.0.4",
"uuid": "2a186e00-a0c5-4c8a-b0ab-c84d56dcee7c",
"rawTextureUuid": "b11569aa-2e43-4084-a3e5-42eec243c4eb",
"trimType": "auto",
"trimThreshold": 1,
"rotated": true,
"offsetX": 0,
"offsetY": 0,
"trimX": 462,
"trimY": 176,
"width": 88,
"height": 45,
"rawWidth": 88,
"rawHeight": 45,
"borderTop": 0,
"borderBottom": 0,
"borderLeft": 0,
"borderRight": 0,
"spriteType": "normal",
"subMetas": {}
},
"Explosion2_3.png": {
"ver": "1.0.4",
"uuid": "083168e3-6ccc-4c5b-a800-2554bffc67d4",
"rawTextureUuid": "b11569aa-2e43-4084-a3e5-42eec243c4eb",
"trimType": "auto",
"trimThreshold": 1,
"rotated": true,
"offsetX": 0,
"offsetY": 0,
"trimX": 462,
"trimY": 264,
"width": 88,
"height": 45,
"rawWidth": 88,
"rawHeight": 45,
"borderTop": 0,
"borderBottom": 0,
"borderLeft": 0,
"borderRight": 0,
"spriteType": "normal",
"subMetas": {}
},
"Explosion2_4.png": {
"ver": "1.0.4",
"uuid": "d4b12ec9-6f04-493c-91e5-22b1a212262a",
"rawTextureUuid": "b11569aa-2e43-4084-a3e5-42eec243c4eb",
"trimType": "auto",
"trimThreshold": 1,
"rotated": false,
"offsetX": 0,
"offsetY": 0,
"trimX": 0,
"trimY": 304,
"width": 88,
"height": 45,
"rawWidth": 88,
"rawHeight": 45,
"borderTop": 0,
"borderBottom": 0,
"borderLeft": 0,
"borderRight": 0,
"spriteType": "normal",
"subMetas": {}
},
"Explosion2_5.png": {
"ver": "1.0.4",
"uuid": "13038788-b0f9-4714-960b-c98619a0d0ce",
"rawTextureUuid": "b11569aa-2e43-4084-a3e5-42eec243c4eb",
"trimType": "auto",
"trimThreshold": 1,
"rotated": false,
"offsetX": 0,
"offsetY": 0,
"trimX": 88,
"trimY": 304,
"width": 88,
"height": 45,
"rawWidth": 88,
"rawHeight": 45,
"borderTop": 0,
"borderBottom": 0,
"borderLeft": 0,
"borderRight": 0,
"spriteType": "normal",
"subMetas": {}
},
"Explosion2_6.png": {
"ver": "1.0.4",
"uuid": "94c21ed7-94a2-47a4-9537-fe5d9c51d7b0",
"rawTextureUuid": "b11569aa-2e43-4084-a3e5-42eec243c4eb",
"trimType": "auto",
"trimThreshold": 1,
"rotated": false,
"offsetX": 0,
"offsetY": 0,
"trimX": 176,
"trimY": 304,
"width": 88,
"height": 45,
"rawWidth": 88,
"rawHeight": 45,
"borderTop": 0,
"borderBottom": 0,
"borderLeft": 0,
"borderRight": 0,
"spriteType": "normal",
"subMetas": {}
},
"Explosion2_7.png": {
"ver": "1.0.4",
"uuid": "d5340298-923c-4bd7-9fd7-7a2e029a2b44",
"rawTextureUuid": "b11569aa-2e43-4084-a3e5-42eec243c4eb",
"trimType": "auto",
"trimThreshold": 1,
"rotated": false,
"offsetX": 0,
"offsetY": 0,
"trimX": 264,
"trimY": 304,
"width": 88,
"height": 45,
"rawWidth": 88,
"rawHeight": 45,
"borderTop": 0,
"borderBottom": 0,
"borderLeft": 0,
"borderRight": 0,
"spriteType": "normal",
"subMetas": {}
},
"Explosion2_8.png": {
"ver": "1.0.4",
"uuid": "c4b145c0-0145-4e09-8559-9ef508d95be8",
"rawTextureUuid": "b11569aa-2e43-4084-a3e5-42eec243c4eb",
"trimType": "auto",
"trimThreshold": 1,
"rotated": false,
"offsetX": 0,
"offsetY": 0,
"trimX": 352,
"trimY": 304,
"width": 88,
"height": 45,
"rawWidth": 88,
"rawHeight": 45,
"borderTop": 0,
"borderBottom": 0,
"borderLeft": 0,
"borderRight": 0,
"spriteType": "normal",
"subMetas": {}
},
"Explosion2_9.png": {
"ver": "1.0.4",
"uuid": "79398d4d-305e-4987-b199-d9d9649cf490",
"rawTextureUuid": "b11569aa-2e43-4084-a3e5-42eec243c4eb",
"trimType": "auto",
"trimThreshold": 1,
"rotated": true,
"offsetX": 0,
"offsetY": 0,
"trimX": 456,
"trimY": 352,
"width": 88,
"height": 45,
"rawWidth": 88,
"rawHeight": 45,
"borderTop": 0,
"borderBottom": 0,
"borderLeft": 0,
"borderRight": 0,
"spriteType": "normal",
"subMetas": {}
},
"Explosion3_1.png": {
"ver": "1.0.4",
"uuid": "84e28787-c6cb-435b-8f59-20d9afe6bf3a",
"rawTextureUuid": "b11569aa-2e43-4084-a3e5-42eec243c4eb",
"trimType": "auto",
"trimThreshold": 1,
"rotated": false,
"offsetX": 0,
"offsetY": 0,
"trimX": 0,
"trimY": 0,
"width": 154,
"height": 152,
"rawWidth": 154,
"rawHeight": 152,
"borderTop": 0,
"borderBottom": 0,
"borderLeft": 0,
"borderRight": 0,
"spriteType": "normal",
"subMetas": {}
},
"Explosion3_10.png": {
"ver": "1.0.4",
"uuid": "20d9ce6b-d9ab-4402-8c59-770ad0adf570",
"rawTextureUuid": "b11569aa-2e43-4084-a3e5-42eec243c4eb",
"trimType": "auto",
"trimThreshold": 1,
"rotated": false,
"offsetX": 0,
"offsetY": 0,
"trimX": 154,
"trimY": 0,
"width": 154,
"height": 152,
"rawWidth": 154,
"rawHeight": 152,
"borderTop": 0,
"borderBottom": 0,
"borderLeft": 0,
"borderRight": 0,
"spriteType": "normal",
"subMetas": {}
},
"Explosion3_2.png": {
"ver": "1.0.4",
"uuid": "0654601f-6788-4a2c-aed4-8dfbe1c5fdd0",
"rawTextureUuid": "b11569aa-2e43-4084-a3e5-42eec243c4eb",
"trimType": "auto",
"trimThreshold": 1,
"rotated": false,
"offsetX": 0,
"offsetY": 0,
"trimX": 308,
"trimY": 0,
"width": 154,
"height": 152,
"rawWidth": 154,
"rawHeight": 152,
"borderTop": 0,
"borderBottom": 0,
"borderLeft": 0,
"borderRight": 0,
"spriteType": "normal",
"subMetas": {}
},
"Explosion3_3.png": {
"ver": "1.0.4",
"uuid": "0913e11a-c796-4b58-94cf-f70b3869deff",
"rawTextureUuid": "b11569aa-2e43-4084-a3e5-42eec243c4eb",
"trimType": "auto",
"trimThreshold": 1,
"rotated": false,
"offsetX": 0,
"offsetY": 0,
"trimX": 0,
"trimY": 152,
"width": 154,
"height": 152,
"rawWidth": 154,
"rawHeight": 152,
"borderTop": 0,
"borderBottom": 0,
"borderLeft": 0,
"borderRight": 0,
"spriteType": "normal",
"subMetas": {}
},
"Explosion3_4.png": {
"ver": "1.0.4",
"uuid": "d6b58622-2cc3-4ee6-a34f-1a18deb73700",
"rawTextureUuid": "b11569aa-2e43-4084-a3e5-42eec243c4eb",
"trimType": "auto",
"trimThreshold": 1,
"rotated": false,
"offsetX": 0,
"offsetY": 0,
"trimX": 154,
"trimY": 152,
"width": 154,
"height": 152,
"rawWidth": 154,
"rawHeight": 152,
"borderTop": 0,
"borderBottom": 0,
"borderLeft": 0,
"borderRight": 0,
"spriteType": "normal",
"subMetas": {}
},
"Explosion3_5.png": {
"ver": "1.0.4",
"uuid": "b83c6261-b86f-4323-ad11-7375cac02a2b",
"rawTextureUuid": "b11569aa-2e43-4084-a3e5-42eec243c4eb",
"trimType": "auto",
"trimThreshold": 1,
"rotated": false,
"offsetX": 0,
"offsetY": 0,
"trimX": 308,
"trimY": 152,
"width": 154,
"height": 152,
"rawWidth": 154,
"rawHeight": 152,
"borderTop": 0,
"borderBottom": 0,
"borderLeft": 0,
"borderRight": 0,
"spriteType": "normal",
"subMetas": {}
},
"Explosion3_6.png": {
"ver": "1.0.4",
"uuid": "b458c047-b7b5-4476-996e-d4c1ca85ef9c",
"rawTextureUuid": "b11569aa-2e43-4084-a3e5-42eec243c4eb",
"trimType": "auto",
"trimThreshold": 1,
"rotated": true,
"offsetX": 0,
"offsetY": 0,
"trimX": 0,
"trimY": 352,
"width": 154,
"height": 152,
"rawWidth": 154,
"rawHeight": 152,
"borderTop": 0,
"borderBottom": 0,
"borderLeft": 0,
"borderRight": 0,
"spriteType": "normal",
"subMetas": {}
},
"Explosion3_7.png": {
"ver": "1.0.4",
"uuid": "3971256a-8120-448e-8adf-de8d67dedfd3",
"rawTextureUuid": "b11569aa-2e43-4084-a3e5-42eec243c4eb",
"trimType": "auto",
"trimThreshold": 1,
"rotated": true,
"offsetX": 0,
"offsetY": 0,
"trimX": 152,
"trimY": 349,
"width": 154,
"height": 152,
"rawWidth": 154,
"rawHeight": 152,
"borderTop": 0,
"borderBottom": 0,
"borderLeft": 0,
"borderRight": 0,
"spriteType": "normal",
"subMetas": {}
},
"Explosion3_8.png": {
"ver": "1.0.4",
"uuid": "0e548d92-36c8-4795-b3dc-2bc2cfcd7170",
"rawTextureUuid": "b11569aa-2e43-4084-a3e5-42eec243c4eb",
"trimType": "auto",
"trimThreshold": 1,
"rotated": false,
"offsetX": 0,
"offsetY": 0,
"trimX": 201,
"trimY": 503,
"width": 154,
"height": 152,
"rawWidth": 154,
"rawHeight": 152,
"borderTop": 0,
"borderBottom": 0,
"borderLeft": 0,
"borderRight": 0,
"spriteType": "normal",
"subMetas": {}
},
"Explosion3_9.png": {
"ver": "1.0.4",
"uuid": "25f94245-87b0-4954-abab-c817c80fed37",
"rawTextureUuid": "b11569aa-2e43-4084-a3e5-42eec243c4eb",
"trimType": "auto",
"trimThreshold": 1,
"rotated": true,
"offsetX": 0,
"offsetY": 0,
"trimX": 304,
"trimY": 349,
"width": 154,
"height": 152,
"rawWidth": 154,
"rawHeight": 152,
"borderTop": 0,
"borderBottom": 0,
"borderLeft": 0,
"borderRight": 0,
"spriteType": "normal",
"subMetas": {}
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

View File

@@ -0,0 +1,12 @@
{
"ver": "2.3.3",
"uuid": "b11569aa-2e43-4084-a3e5-42eec243c4eb",
"type": "raw",
"wrapMode": "clamp",
"filterMode": "bilinear",
"premultiplyAlpha": false,
"genMipmaps": false,
"packable": true,
"platformSettings": {},
"subMetas": {}
}

View File

@@ -0,0 +1,7 @@
{
"ver": "1.0.1",
"uuid": "b07a911d-2d61-486d-9edc-1b3ba53c9911",
"isSubpackage": false,
"subpackageName": "",
"subMetas": {}
}

View File

@@ -0,0 +1,145 @@
{
"__type__": "cc.AnimationClip",
"_name": "Fireball1",
"_objFlags": 0,
"_native": "",
"_duration": 0.35,
"sample": 60,
"speed": 1,
"wrapMode": 2,
"curveData": {
"comps": {
"cc.Sprite": {
"spriteFrame": [
{
"frame": 0,
"value": {
"__uuid__": "dbe67025-9878-4e13-8f3d-81e04734810a"
}
},
{
"frame": 0.016666666666666666,
"value": {
"__uuid__": "e92702d5-d5fd-49e6-ab6b-2296b43fa6d6"
}
},
{
"frame": 0.03333333333333333,
"value": {
"__uuid__": "e1a89340-0b92-4e6b-93f2-e983302d70ce"
}
},
{
"frame": 0.05,
"value": {
"__uuid__": "b0bb4a7a-4ae3-48fc-9913-3b6d1d36c56f"
}
},
{
"frame": 0.06666666666666667,
"value": {
"__uuid__": "b44d585b-8e18-4767-b263-ed3a53cd3250"
}
},
{
"frame": 0.08333333333333333,
"value": {
"__uuid__": "a87a9ea8-2d84-4a3b-83e3-a4d7b8ac96b8"
}
},
{
"frame": 0.1,
"value": {
"__uuid__": "a1604f9d-c0ea-4f92-b09b-3608245bda8e"
}
},
{
"frame": 0.11666666666666667,
"value": {
"__uuid__": "4372818f-1e44-4180-a0ce-4a34cee4fc5b"
}
},
{
"frame": 0.13333333333333333,
"value": {
"__uuid__": "dbe67025-9878-4e13-8f3d-81e04734810a"
}
},
{
"frame": 0.15,
"value": {
"__uuid__": "5d867617-7f50-4fa8-804d-ce28c47ea407"
}
},
{
"frame": 0.16666666666666666,
"value": {
"__uuid__": "824c9bee-42b7-4a94-86f8-6356f11aee16"
}
},
{
"frame": 0.18333333333333332,
"value": {
"__uuid__": "6389164e-93bb-4d4d-9740-5e2d5cdb1029"
}
},
{
"frame": 0.2,
"value": {
"__uuid__": "d184a083-6043-4ca6-bd14-8db1b6be1d2e"
}
},
{
"frame": 0.21666666666666667,
"value": {
"__uuid__": "361b1722-e362-46e5-939e-e2d1666df374"
}
},
{
"frame": 0.23333333333333334,
"value": {
"__uuid__": "662fbe4f-a1f4-46f7-83e4-eafd021432da"
}
},
{
"frame": 0.25,
"value": {
"__uuid__": "5e509118-a44b-4e7f-9686-c6bb0b30f0b0"
}
},
{
"frame": 0.26666666666666666,
"value": {
"__uuid__": "bc1110c7-4423-4c43-965c-0cb3dd8e31ff"
}
},
{
"frame": 0.2833333333333333,
"value": {
"__uuid__": "33cc8d11-1568-47a7-b4f1-cef4888302e5"
}
},
{
"frame": 0.3,
"value": {
"__uuid__": "83bb5dd3-510c-4fce-b393-840f14efb8cd"
}
},
{
"frame": 0.31666666666666665,
"value": {
"__uuid__": "1db706f5-366a-421c-843f-a4bb016f80ec"
}
},
{
"frame": 0.3333333333333333,
"value": {
"__uuid__": "41a4f35a-01c0-4a22-b5cc-7bfe25ed4501"
}
}
]
}
}
},
"events": []
}

View File

@@ -0,0 +1,5 @@
{
"ver": "2.1.0",
"uuid": "ba12416b-eec3-4260-8402-7fc25b125624",
"subMetas": {}
}

View File

@@ -18,61 +18,43 @@
} }
}, },
{ {
"frame": 0.06666666666666667, "frame": 0.05,
"value": { "value": {
"__uuid__": "dd9a00aa-ddbc-4b01-a7cb-3c43c3a655b6" "__uuid__": "dd9a00aa-ddbc-4b01-a7cb-3c43c3a655b6"
} }
}, },
{ {
"frame": 0.11666666666666667, "frame": 0.08333333333333333,
"value": {
"__uuid__": "f66e83bd-1afc-4957-bb16-488d70566ed1"
}
},
{
"frame": 0.16666666666666666,
"value": {
"__uuid__": "bd682c41-dc62-49ff-a96a-18b33e50a6de"
}
},
{
"frame": 0.23333333333333334,
"value": {
"__uuid__": "94ccab85-e32f-4e13-b0e5-72c798f78ad1"
}
},
{
"frame": 0.3,
"value": { "value": {
"__uuid__": "e80d3a01-5048-42b7-a280-cb6aa01602c2" "__uuid__": "e80d3a01-5048-42b7-a280-cb6aa01602c2"
} }
}, },
{ {
"frame": 0.36666666666666664, "frame": 0.11666666666666667,
"value": { "value": {
"__uuid__": "d899088c-be62-47b4-9ebf-0a89a2261565" "__uuid__": "d899088c-be62-47b4-9ebf-0a89a2261565"
} }
}, },
{ {
"frame": 0.4166666666666667, "frame": 0.15,
"value": { "value": {
"__uuid__": "5b1e5aa7-fd82-47ae-a5b2-6d4983d848ed" "__uuid__": "5b1e5aa7-fd82-47ae-a5b2-6d4983d848ed"
} }
}, },
{ {
"frame": 0.48333333333333334, "frame": 0.18333333333333332,
"value": { "value": {
"__uuid__": "c2945988-b4bb-4583-a5ef-2fa02b23a347" "__uuid__": "c2945988-b4bb-4583-a5ef-2fa02b23a347"
} }
}, },
{ {
"frame": 0.5666666666666667, "frame": 0.23333333333333334,
"value": { "value": {
"__uuid__": "070ea1e3-9c07-4735-8b94-515ef70216ad" "__uuid__": "070ea1e3-9c07-4735-8b94-515ef70216ad"
} }
}, },
{ {
"frame": 0.6666666666666666, "frame": 0.2833333333333333,
"value": { "value": {
"__uuid__": "3b8bc5c0-26df-4218-b7dc-134a36080a35" "__uuid__": "3b8bc5c0-26df-4218-b7dc-134a36080a35"
} }

View File

@@ -0,0 +1,61 @@
{
"__type__": "cc.AnimationClip",
"_name": "Dashing",
"_objFlags": 0,
"_native": "",
"_duration": 0.35,
"sample": 60,
"speed": 1,
"wrapMode": 1,
"curveData": {
"comps": {
"cc.Sprite": {
"spriteFrame": [
{
"frame": 0,
"value": {
"__uuid__": "cf396dac-50c9-4389-90c0-55f49fd3276d"
}
},
{
"frame": 0.05,
"value": {
"__uuid__": "b9e4b5d5-c296-48c8-aa60-d22db0e5a632"
}
},
{
"frame": 0.11666666666666667,
"value": {
"__uuid__": "e456c710-69f5-4dcc-9f5d-dd486a9198a1"
}
},
{
"frame": 0.16666666666666666,
"value": {
"__uuid__": "ec6df76f-0004-4216-9b83-449487fe0cda"
}
},
{
"frame": 0.23333333333333334,
"value": {
"__uuid__": "26032d0f-845c-4b96-89a6-d88113ed7827"
}
},
{
"frame": 0.2833333333333333,
"value": {
"__uuid__": "e3e0169c-3c56-4206-a20e-35e4d0471873"
}
},
{
"frame": 0.3333333333333333,
"value": {
"__uuid__": "80b98036-c5de-492b-b0e8-f1703f3a7d20"
}
}
]
}
}
},
"events": []
}

View File

@@ -0,0 +1,5 @@
{
"ver": "2.1.0",
"uuid": "38b2c892-347b-4009-93f8-65b2ab1614f0",
"subMetas": {}
}

View File

@@ -15,9 +15,9 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{112,128}</string> <string>{112,128}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{824,544},{112,128}}</string> <string>{{384,989},{112,128}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<false/> <true/>
</dict> </dict>
<key>Atk1_1.png</key> <key>Atk1_1.png</key>
<dict> <dict>
@@ -30,9 +30,9 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{112,128}</string> <string>{112,128}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{0,1200},{112,128}}</string> <string>{{256,990},{112,128}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<false/> <true/>
</dict> </dict>
<key>Atk1_10.png</key> <key>Atk1_10.png</key>
<dict> <dict>
@@ -90,9 +90,9 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{112,128}</string> <string>{112,128}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{0,964},{112,128}}</string> <string>{{128,1082},{112,128}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<false/> <true/>
</dict> </dict>
<key>Atk1_4.png</key> <key>Atk1_4.png</key>
<dict> <dict>
@@ -105,9 +105,9 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{112,128}</string> <string>{112,128}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{112,964},{112,128}}</string> <string>{{0,1188},{112,128}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<false/> <true/>
</dict> </dict>
<key>Atk1_5.png</key> <key>Atk1_5.png</key>
<dict> <dict>
@@ -120,7 +120,7 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{96,128}</string> <string>{96,128}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{840,288},{96,128}}</string> <string>{{512,643},{96,128}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<false/> <false/>
</dict> </dict>
@@ -135,7 +135,7 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{96,128}</string> <string>{96,128}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{840,416},{96,128}}</string> <string>{{512,771},{96,128}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<false/> <false/>
</dict> </dict>
@@ -165,7 +165,7 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{80,128}</string> <string>{80,128}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{936,384},{80,128}}</string> <string>{{937,384},{80,128}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<false/> <false/>
</dict> </dict>
@@ -180,7 +180,7 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{80,128}</string> <string>{80,128}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{936,512},{80,128}}</string> <string>{{528,515},{80,128}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<false/> <false/>
</dict> </dict>
@@ -195,7 +195,7 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{80,128}</string> <string>{80,128}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{936,640},{80,128}}</string> <string>{{936,512},{80,128}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<false/> <false/>
</dict> </dict>
@@ -210,7 +210,7 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{96,128}</string> <string>{96,128}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{582,531},{96,128}}</string> <string>{{512,899},{96,128}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<false/> <false/>
</dict> </dict>
@@ -225,7 +225,7 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{128,112}</string> <string>{128,112}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{326,871},{128,112}}</string> <string>{{0,1076},{128,112}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<false/> <false/>
</dict> </dict>
@@ -240,7 +240,7 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{96,96}</string> <string>{96,96}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{696,1200},{96,96}}</string> <string>{{688,1357},{96,96}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<false/> <false/>
</dict> </dict>
@@ -255,7 +255,7 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{96,112}</string> <string>{96,112}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{416,983},{96,112}}</string> <string>{{240,1360},{96,112}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<true/> <true/>
</dict> </dict>
@@ -270,7 +270,7 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{96,112}</string> <string>{96,112}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{656,1092},{96,112}}</string> <string>{{352,1358},{96,112}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<true/> <true/>
</dict> </dict>
@@ -285,9 +285,9 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{96,112}</string> <string>{96,112}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{528,1113},{96,112}}</string> <string>{{920,1072},{96,112}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<true/> <false/>
</dict> </dict>
<key>Atk2_5.png</key> <key>Atk2_5.png</key>
<dict> <dict>
@@ -300,9 +300,9 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{96,112}</string> <string>{96,112}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{392,1207},{96,112}}</string> <string>{{914,1184},{96,112}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<true/> <false/>
</dict> </dict>
<key>Atk2_6.png</key> <key>Atk2_6.png</key>
<dict> <dict>
@@ -330,7 +330,7 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{128,112}</string> <string>{128,112}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{454,871},{128,112}}</string> <string>{{806,631},{128,112}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<false/> <false/>
</dict> </dict>
@@ -525,7 +525,7 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{96,128}</string> <string>{96,128}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{582,659},{96,128}}</string> <string>{{512,1027},{96,128}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<false/> <false/>
</dict> </dict>
@@ -540,7 +540,7 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{112,112}</string> <string>{112,112}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{240,1081},{112,112}}</string> <string>{{802,1149},{112,112}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<false/> <false/>
</dict> </dict>
@@ -555,9 +555,9 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{96,112}</string> <string>{96,112}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{504,1209},{96,112}}</string> <string>{{800,1261},{96,112}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<false/> <true/>
</dict> </dict>
<key>Atked1_3.png</key> <key>Atked1_3.png</key>
<dict> <dict>
@@ -570,7 +570,7 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{128,112}</string> <string>{128,112}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{678,980},{128,112}}</string> <string>{{806,743},{128,112}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<false/> <false/>
</dict> </dict>
@@ -634,37 +634,112 @@
<key>textureRotated</key> <key>textureRotated</key>
<false/> <false/>
</dict> </dict>
<key>Dashing_1.png</key>
<dict>
<key>aliases</key>
<array/>
<key>spriteOffset</key>
<string>{0,0}</string>
<key>spriteSize</key>
<string>{114,112}</string>
<key>spriteSourceSize</key>
<string>{114,112}</string>
<key>textureRect</key>
<string>{{806,1037},{114,112}}</string>
<key>textureRotated</key>
<false/>
</dict>
<key>Dashing_2.png</key>
<dict>
<key>aliases</key>
<array/>
<key>spriteOffset</key>
<string>{0,0}</string>
<key>spriteSize</key>
<string>{114,112}</string>
<key>spriteSourceSize</key>
<string>{114,112}</string>
<key>textureRect</key>
<string>{{384,1213},{114,112}}</string>
<key>textureRotated</key>
<true/>
</dict>
<key>Dashing_3.png</key>
<dict>
<key>aliases</key>
<array/>
<key>spriteOffset</key>
<string>{0,0}</string>
<key>spriteSize</key>
<string>{114,112}</string>
<key>spriteSourceSize</key>
<string>{114,112}</string>
<key>textureRect</key>
<string>{{464,1327},{114,112}}</string>
<key>textureRotated</key>
<true/>
</dict>
<key>Dashing_4.png</key>
<dict>
<key>aliases</key>
<array/>
<key>spriteOffset</key>
<string>{0,0}</string>
<key>spriteSize</key>
<string>{114,112}</string>
<key>spriteSourceSize</key>
<string>{114,112}</string>
<key>textureRect</key>
<string>{{496,1213},{114,112}}</string>
<key>textureRotated</key>
<true/>
</dict>
<key>Dashing_5.png</key>
<dict>
<key>aliases</key>
<array/>
<key>spriteOffset</key>
<string>{0,0}</string>
<key>spriteSize</key>
<string>{114,112}</string>
<key>spriteSourceSize</key>
<string>{114,112}</string>
<key>textureRect</key>
<string>{{464,1327},{114,112}}</string>
<key>textureRotated</key>
<true/>
</dict>
<key>Dashing_6.png</key>
<dict>
<key>aliases</key>
<array/>
<key>spriteOffset</key>
<string>{0,0}</string>
<key>spriteSize</key>
<string>{114,112}</string>
<key>spriteSourceSize</key>
<string>{114,112}</string>
<key>textureRect</key>
<string>{{576,1327},{114,112}}</string>
<key>textureRotated</key>
<true/>
</dict>
<key>Dashing_7.png</key>
<dict>
<key>aliases</key>
<array/>
<key>spriteOffset</key>
<string>{0,0}</string>
<key>spriteSize</key>
<string>{114,112}</string>
<key>spriteSourceSize</key>
<string>{114,112}</string>
<key>textureRect</key>
<string>{{688,1043},{114,112}}</string>
<key>textureRotated</key>
<false/>
</dict>
<key>GetUp1_1.png</key> <key>GetUp1_1.png</key>
<dict>
<key>aliases</key>
<array/>
<key>spriteOffset</key>
<string>{0,0}</string>
<key>spriteSize</key>
<string>{128,118}</string>
<key>spriteSourceSize</key>
<string>{128,118}</string>
<key>textureRect</key>
<string>{{806,791},{128,118}}</string>
<key>textureRotated</key>
<false/>
</dict>
<key>GetUp1_2.png</key>
<dict>
<key>aliases</key>
<array/>
<key>spriteOffset</key>
<string>{0,0}</string>
<key>spriteSize</key>
<string>{128,118}</string>
<key>spriteSourceSize</key>
<string>{128,118}</string>
<key>textureRect</key>
<string>{{0,846},{128,118}}</string>
<key>textureRotated</key>
<false/>
</dict>
<key>GetUp1_3.png</key>
<dict> <dict>
<key>aliases</key> <key>aliases</key>
<array/> <array/>
@@ -679,6 +754,36 @@
<key>textureRotated</key> <key>textureRotated</key>
<false/> <false/>
</dict> </dict>
<key>GetUp1_2.png</key>
<dict>
<key>aliases</key>
<array/>
<key>spriteOffset</key>
<string>{0,0}</string>
<key>spriteSize</key>
<string>{128,118}</string>
<key>spriteSourceSize</key>
<string>{128,118}</string>
<key>textureRect</key>
<string>{{0,958},{128,118}}</string>
<key>textureRotated</key>
<false/>
</dict>
<key>GetUp1_3.png</key>
<dict>
<key>aliases</key>
<array/>
<key>spriteOffset</key>
<string>{0,0}</string>
<key>spriteSize</key>
<string>{128,118}</string>
<key>spriteSourceSize</key>
<string>{128,118}</string>
<key>textureRect</key>
<string>{{384,753},{128,118}}</string>
<key>textureRotated</key>
<false/>
</dict>
<key>GetUp1_4.png</key> <key>GetUp1_4.png</key>
<dict> <dict>
<key>aliases</key> <key>aliases</key>
@@ -690,7 +795,7 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{128,118}</string> <string>{128,118}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{326,753},{128,118}}</string> <string>{{678,631},{128,118}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<false/> <false/>
</dict> </dict>
@@ -705,7 +810,7 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{128,118}</string> <string>{128,118}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{454,753},{128,118}}</string> <string>{{384,871},{128,118}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<false/> <false/>
</dict> </dict>
@@ -720,7 +825,7 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{128,118}</string> <string>{128,118}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{678,862},{128,118}}</string> <string>{{256,872},{128,118}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<false/> <false/>
</dict> </dict>
@@ -735,7 +840,7 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{128,118}</string> <string>{128,118}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{806,909},{128,118}}</string> <string>{{128,964},{128,118}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<false/> <false/>
</dict> </dict>
@@ -750,7 +855,7 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{70,128}</string> <string>{70,128}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{256,489},{70,128}}</string> <string>{{608,531},{70,128}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<false/> <false/>
</dict> </dict>
@@ -765,7 +870,7 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{70,128}</string> <string>{70,128}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{256,617},{70,128}}</string> <string>{{608,659},{70,128}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<false/> <false/>
</dict> </dict>
@@ -780,7 +885,7 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{70,128}</string> <string>{70,128}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{256,745},{70,128}}</string> <string>{{608,787},{70,128}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<false/> <false/>
</dict> </dict>
@@ -795,7 +900,7 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{70,128}</string> <string>{70,128}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{256,873},{70,128}}</string> <string>{{608,915},{70,128}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<false/> <false/>
</dict> </dict>
@@ -810,9 +915,9 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{70,128}</string> <string>{70,128}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{112,1200},{70,128}}</string> <string>{{128,1290},{70,128}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<false/> <true/>
</dict> </dict>
<key>Idle1_14.png</key> <key>Idle1_14.png</key>
<dict> <dict>
@@ -825,9 +930,9 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{70,128}</string> <string>{70,128}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{182,1200},{70,128}}</string> <string>{{0,1300},{70,128}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<false/> <true/>
</dict> </dict>
<key>Idle1_15.png</key> <key>Idle1_15.png</key>
<dict> <dict>
@@ -840,9 +945,9 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{70,128}</string> <string>{70,128}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{252,1200},{70,128}}</string> <string>{{0,1370},{70,128}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<false/> <true/>
</dict> </dict>
<key>Idle1_2.png</key> <key>Idle1_2.png</key>
<dict> <dict>
@@ -855,9 +960,9 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{70,128}</string> <string>{70,128}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{252,1200},{70,128}}</string> <string>{{0,1370},{70,128}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<false/> <true/>
</dict> </dict>
<key>Idle1_3.png</key> <key>Idle1_3.png</key>
<dict> <dict>
@@ -870,9 +975,9 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{70,128}</string> <string>{70,128}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{182,1200},{70,128}}</string> <string>{{0,1300},{70,128}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<false/> <true/>
</dict> </dict>
<key>Idle1_4.png</key> <key>Idle1_4.png</key>
<dict> <dict>
@@ -885,9 +990,9 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{70,128}</string> <string>{70,128}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{112,1200},{70,128}}</string> <string>{{128,1290},{70,128}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<false/> <true/>
</dict> </dict>
<key>Idle1_5.png</key> <key>Idle1_5.png</key>
<dict> <dict>
@@ -900,7 +1005,7 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{70,128}</string> <string>{70,128}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{256,873},{70,128}}</string> <string>{{608,915},{70,128}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<false/> <false/>
</dict> </dict>
@@ -915,7 +1020,7 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{70,128}</string> <string>{70,128}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{256,745},{70,128}}</string> <string>{{608,787},{70,128}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<false/> <false/>
</dict> </dict>
@@ -930,7 +1035,7 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{70,128}</string> <string>{70,128}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{256,617},{70,128}}</string> <string>{{608,659},{70,128}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<false/> <false/>
</dict> </dict>
@@ -945,9 +1050,9 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{70,128}</string> <string>{70,128}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{322,1200},{70,128}}</string> <string>{{806,967},{70,128}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<false/> <true/>
</dict> </dict>
<key>Idle1_9.png</key> <key>Idle1_9.png</key>
<dict> <dict>
@@ -960,7 +1065,7 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{70,128}</string> <string>{70,128}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{528,1043},{70,128}}</string> <string>{{678,973},{70,128}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<true/> <true/>
</dict> </dict>
@@ -975,7 +1080,7 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{112,96}</string> <string>{112,96}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{128,1092},{112,96}}</string> <string>{{128,1360},{112,96}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<false/> <false/>
</dict> </dict>
@@ -1005,7 +1110,7 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{144,112}</string> <string>{144,112}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{680,512},{144,112}}</string> <string>{{0,489},{144,112}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<false/> <false/>
</dict> </dict>
@@ -1020,7 +1125,7 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{128,112}</string> <string>{128,112}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{806,1027},{128,112}}</string> <string>{{678,749},{128,112}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<false/> <false/>
</dict> </dict>
@@ -1035,7 +1140,7 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{96,96}</string> <string>{96,96}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{792,1139},{96,96}}</string> <string>{{784,1357},{96,96}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<false/> <false/>
</dict> </dict>
@@ -1050,7 +1155,7 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{80,96}</string> <string>{80,96}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{934,1104},{80,96}}</string> <string>{{934,976},{80,96}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<false/> <false/>
</dict> </dict>
@@ -1065,7 +1170,7 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{112,112}</string> <string>{112,112}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{352,1081},{112,112}}</string> <string>{{688,1155},{112,112}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<false/> <false/>
</dict> </dict>
@@ -1080,7 +1185,7 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{128,96}</string> <string>{128,96}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{0,1092},{128,96}}</string> <string>{{256,1102},{128,96}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<false/> <false/>
</dict> </dict>
@@ -1095,7 +1200,7 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{80,112}</string> <string>{80,112}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{934,768},{80,112}}</string> <string>{{934,640},{80,112}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<false/> <false/>
</dict> </dict>
@@ -1110,7 +1215,7 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{80,112}</string> <string>{80,112}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{934,880},{80,112}}</string> <string>{{934,752},{80,112}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<false/> <false/>
</dict> </dict>
@@ -1125,9 +1230,9 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{64,128}</string> <string>{64,128}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{464,1079},{64,128}}</string> <string>{{256,1294},{64,128}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<false/> <true/>
</dict> </dict>
<key>InAirIdle1_3.png</key> <key>InAirIdle1_3.png</key>
<dict> <dict>
@@ -1140,7 +1245,7 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{80,112}</string> <string>{80,112}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{934,992},{80,112}}</string> <string>{{934,864},{80,112}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<false/> <false/>
</dict> </dict>
@@ -1155,9 +1260,9 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{80,96}</string> <string>{80,96}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{224,1001},{80,96}}</string> <string>{{608,1043},{80,96}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<true/> <false/>
</dict> </dict>
<key>InAirIdle1_5.png</key> <key>InAirIdle1_5.png</key>
<dict> <dict>
@@ -1170,9 +1275,9 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{80,96}</string> <string>{80,96}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{320,1001},{80,96}}</string> <string>{{608,1139},{80,96}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<true/> <false/>
</dict> </dict>
<key>InAirIdle1_6.png</key> <key>InAirIdle1_6.png</key>
<dict> <dict>
@@ -1185,9 +1290,9 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{80,96}</string> <string>{80,96}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{792,1235},{80,96}}</string> <string>{{688,1267},{80,96}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<false/> <true/>
</dict> </dict>
<key>InAirIdle1_7.png</key> <key>InAirIdle1_7.png</key>
<dict> <dict>
@@ -1200,9 +1305,9 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{96,112}</string> <string>{96,112}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{600,1209},{96,112}}</string> <string>{{912,1296},{96,112}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<false/> <true/>
</dict> </dict>
<key>InAirIdle1_8.png</key> <key>InAirIdle1_8.png</key>
<dict> <dict>
@@ -1215,9 +1320,9 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{96,128}</string> <string>{96,128}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{582,787},{96,128}}</string> <string>{{128,1194},{96,128}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<false/> <true/>
</dict> </dict>
<key>InAirIdle1_9.png</key> <key>InAirIdle1_9.png</key>
<dict> <dict>
@@ -1230,9 +1335,9 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{96,128}</string> <string>{96,128}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{582,915},{96,128}}</string> <string>{{256,1198},{96,128}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<false/> <true/>
</dict> </dict>
<key>LayDown1_1.png</key> <key>LayDown1_1.png</key>
<dict> <dict>
@@ -1264,6 +1369,96 @@
<key>textureRotated</key> <key>textureRotated</key>
<false/> <false/>
</dict> </dict>
<key>OnWall1_1.png</key>
<dict>
<key>aliases</key>
<array/>
<key>spriteOffset</key>
<string>{0,0}</string>
<key>spriteSize</key>
<string>{112,97}</string>
<key>spriteSourceSize</key>
<string>{112,97}</string>
<key>textureRect</key>
<string>{{840,288},{112,97}}</string>
<key>textureRotated</key>
<true/>
</dict>
<key>OnWall1_2.png</key>
<dict>
<key>aliases</key>
<array/>
<key>spriteOffset</key>
<string>{0,0}</string>
<key>spriteSize</key>
<string>{112,97}</string>
<key>spriteSourceSize</key>
<string>{112,97}</string>
<key>textureRect</key>
<string>{{840,400},{112,97}}</string>
<key>textureRotated</key>
<true/>
</dict>
<key>OnWall1_3.png</key>
<dict>
<key>aliases</key>
<array/>
<key>spriteOffset</key>
<string>{0,0}</string>
<key>spriteSize</key>
<string>{112,97}</string>
<key>spriteSourceSize</key>
<string>{112,97}</string>
<key>textureRect</key>
<string>{{840,400},{112,97}}</string>
<key>textureRotated</key>
<true/>
</dict>
<key>TurnAround1_1.png</key>
<dict>
<key>aliases</key>
<array/>
<key>spriteOffset</key>
<string>{0,0}</string>
<key>spriteSize</key>
<string>{112,128}</string>
<key>spriteSourceSize</key>
<string>{112,128}</string>
<key>textureRect</key>
<string>{{806,855},{112,128}}</string>
<key>textureRotated</key>
<true/>
</dict>
<key>TurnAround1_2.png</key>
<dict>
<key>aliases</key>
<array/>
<key>spriteOffset</key>
<string>{0,0}</string>
<key>spriteSize</key>
<string>{112,128}</string>
<key>spriteSourceSize</key>
<string>{112,128}</string>
<key>textureRect</key>
<string>{{678,861},{112,128}}</string>
<key>textureRotated</key>
<true/>
</dict>
<key>TurnAround1_3.png</key>
<dict>
<key>aliases</key>
<array/>
<key>spriteOffset</key>
<string>{0,0}</string>
<key>spriteSize</key>
<string>{112,128}</string>
<key>spriteSourceSize</key>
<string>{112,128}</string>
<key>textureRect</key>
<string>{{384,1101},{112,128}}</string>
<key>textureRotated</key>
<true/>
</dict>
<key>Walking_1.png</key> <key>Walking_1.png</key>
<dict> <dict>
<key>aliases</key> <key>aliases</key>
@@ -1275,7 +1470,7 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{119,128}</string> <string>{119,128}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{0,489},{119,128}}</string> <string>{{144,489},{119,128}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<true/> <true/>
</dict> </dict>
@@ -1290,7 +1485,7 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{119,128}</string> <string>{119,128}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{128,489},{119,128}}</string> <string>{{0,601},{119,128}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<true/> <true/>
</dict> </dict>
@@ -1305,7 +1500,7 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{119,128}</string> <string>{119,128}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{0,608},{119,128}}</string> <string>{{272,515},{119,128}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<true/> <true/>
</dict> </dict>
@@ -1335,7 +1530,7 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{119,128}</string> <string>{119,128}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{326,515},{119,128}}</string> <string>{{0,720},{119,128}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<true/> <true/>
</dict> </dict>
@@ -1350,7 +1545,7 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{119,128}</string> <string>{119,128}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{454,515},{119,128}}</string> <string>{{400,515},{119,128}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<true/> <true/>
</dict> </dict>
@@ -1365,7 +1560,7 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{119,128}</string> <string>{119,128}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{678,624},{119,128}}</string> <string>{{256,634},{119,128}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<true/> <true/>
</dict> </dict>
@@ -1380,7 +1575,7 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{119,128}</string> <string>{119,128}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{806,672},{119,128}}</string> <string>{{128,727},{119,128}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<true/> <true/>
</dict> </dict>
@@ -1395,7 +1590,7 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{119,128}</string> <string>{119,128}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{0,727},{119,128}}</string> <string>{{0,839},{119,128}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<true/> <true/>
</dict> </dict>
@@ -1410,7 +1605,7 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{119,128}</string> <string>{119,128}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{128,727},{119,128}}</string> <string>{{384,634},{119,128}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<true/> <true/>
</dict> </dict>
@@ -1425,7 +1620,7 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{119,128}</string> <string>{119,128}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{326,634},{119,128}}</string> <string>{{680,512},{119,128}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<true/> <true/>
</dict> </dict>
@@ -1440,7 +1635,7 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{119,128}</string> <string>{119,128}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{454,634},{119,128}}</string> <string>{{808,512},{119,128}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<true/> <true/>
</dict> </dict>
@@ -1455,7 +1650,7 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{119,128}</string> <string>{119,128}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{678,743},{119,128}}</string> <string>{{256,753},{119,128}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<true/> <true/>
</dict> </dict>
@@ -1471,9 +1666,9 @@
<key>realTextureFileName</key> <key>realTextureFileName</key>
<string>KnifeGirl.png</string> <string>KnifeGirl.png</string>
<key>size</key> <key>size</key>
<string>{1020,1331}</string> <string>{1024,1456}</string>
<key>smartupdate</key> <key>smartupdate</key>
<string>$TexturePacker:SmartUpdate:9514b6b35473e14baf98f68515bcb817:1aae9dd4a8024ce783fdab093a39672a:1ae107e0c6667a1ecb5ed98687517e0e$</string> <string>$TexturePacker:SmartUpdate:8fd7507b5e24a1de6da5e4a6c568fcd3:d861e924a13180a640774a9c85662e57:1ae107e0c6667a1ecb5ed98687517e0e$</string>
<key>textureFileName</key> <key>textureFileName</key>
<string>KnifeGirl.png</string> <string>KnifeGirl.png</string>
</dict> </dict>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 104 KiB

After

Width:  |  Height:  |  Size: 119 KiB

View File

@@ -0,0 +1,37 @@
{
"__type__": "cc.AnimationClip",
"_name": "OnWall",
"_objFlags": 0,
"_native": "",
"_duration": 0.26666666666666666,
"sample": 60,
"speed": 1,
"wrapMode": 1,
"curveData": {
"comps": {
"cc.Sprite": {
"spriteFrame": [
{
"frame": 0,
"value": {
"__uuid__": "c18886db-8116-4602-84f2-51652a90269a"
}
},
{
"frame": 0.13333333333333333,
"value": {
"__uuid__": "0d81cbf0-dff8-4672-99b3-2ec8055c6931"
}
},
{
"frame": 0.25,
"value": {
"__uuid__": "a183e740-3c2d-4890-8430-39a00f55f446"
}
}
]
}
}
},
"events": []
}

View File

@@ -0,0 +1,5 @@
{
"ver": "2.1.0",
"uuid": "411f964a-4dd8-424c-b2e2-d92b10474ce2",
"subMetas": {}
}

View File

@@ -3,7 +3,7 @@
"_name": "Walking", "_name": "Walking",
"_objFlags": 0, "_objFlags": 0,
"_native": "", "_native": "",
"_duration": 1.5166666666666666, "_duration": 0.6333333333333333,
"sample": 60, "sample": 60,
"speed": 1.2, "speed": 1.2,
"wrapMode": 2, "wrapMode": 2,
@@ -13,78 +13,78 @@
"spriteFrame": [ "spriteFrame": [
{ {
"frame": 0, "frame": 0,
"value": {
"__uuid__": "c3b14ecc-a6d9-4cb3-8637-ca7b407a0f5c"
}
},
{
"frame": 0.08333333333333333,
"value": { "value": {
"__uuid__": "9435195e-4560-495e-b1ae-083c0c87e8a0" "__uuid__": "9435195e-4560-495e-b1ae-083c0c87e8a0"
} }
}, },
{ {
"frame": 0.18333333333333332, "frame": 0.06666666666666667,
"value": { "value": {
"__uuid__": "ec048360-7a17-4f22-ba52-eb86ec1acae8" "__uuid__": "ec048360-7a17-4f22-ba52-eb86ec1acae8"
} }
}, },
{ {
"frame": 0.2833333333333333, "frame": 0.11666666666666667,
"value": { "value": {
"__uuid__": "82bb81e3-667c-4280-8710-211f4904ef2f" "__uuid__": "82bb81e3-667c-4280-8710-211f4904ef2f"
} }
}, },
{ {
"frame": 0.4, "frame": 0.16666666666666666,
"value": {
"__uuid__": "c3b14ecc-a6d9-4cb3-8637-ca7b407a0f5c"
}
},
{
"frame": 0.21666666666666667,
"value": { "value": {
"__uuid__": "f958fb7f-ef5a-4918-81f3-564004572f45" "__uuid__": "f958fb7f-ef5a-4918-81f3-564004572f45"
} }
}, },
{ {
"frame": 0.5333333333333333, "frame": 0.26666666666666666,
"value": { "value": {
"__uuid__": "8a0ecf92-db26-4206-9a80-20e749055def" "__uuid__": "8a0ecf92-db26-4206-9a80-20e749055def"
} }
}, },
{ {
"frame": 0.65, "frame": 0.31666666666666665,
"value": { "value": {
"__uuid__": "942f2e02-a700-4fbf-877e-08c93e4d4010" "__uuid__": "942f2e02-a700-4fbf-877e-08c93e4d4010"
} }
}, },
{ {
"frame": 0.7666666666666667, "frame": 0.36666666666666664,
"value": { "value": {
"__uuid__": "30546064-1a11-499e-8523-a82c83951c73" "__uuid__": "30546064-1a11-499e-8523-a82c83951c73"
} }
}, },
{ {
"frame": 0.9, "frame": 0.4166666666666667,
"value": { "value": {
"__uuid__": "515bb75f-7a1f-4500-8aa9-c895915ce19f" "__uuid__": "515bb75f-7a1f-4500-8aa9-c895915ce19f"
} }
}, },
{ {
"frame": 1.0333333333333334, "frame": 0.4666666666666667,
"value": { "value": {
"__uuid__": "9100da6b-7582-4afb-9698-3d67d3b2012d" "__uuid__": "9100da6b-7582-4afb-9698-3d67d3b2012d"
} }
}, },
{ {
"frame": 1.2166666666666666, "frame": 0.5166666666666667,
"value": { "value": {
"__uuid__": "1257f72d-0cb3-4750-ae70-13c2d8eb2269" "__uuid__": "1257f72d-0cb3-4750-ae70-13c2d8eb2269"
} }
}, },
{ {
"frame": 1.3833333333333333, "frame": 0.5666666666666667,
"value": { "value": {
"__uuid__": "1d34b6db-27ba-4e26-864d-0f00d501765e" "__uuid__": "1d34b6db-27ba-4e26-864d-0f00d501765e"
} }
}, },
{ {
"frame": 1.5, "frame": 0.6166666666666667,
"value": { "value": {
"__uuid__": "c317a75a-52c0-4c38-9300-a064cbf4efb3" "__uuid__": "c317a75a-52c0-4c38-9300-a064cbf4efb3"
} }

View File

@@ -3,7 +3,7 @@
"_name": "Atk3", "_name": "Atk3",
"_objFlags": 0, "_objFlags": 0,
"_native": "", "_native": "",
"_duration": 0.6333333333333333, "_duration": 0.5333333333333333,
"sample": 60, "sample": 60,
"speed": 1, "speed": 1,
"wrapMode": 1, "wrapMode": 1,
@@ -13,84 +13,72 @@
"spriteFrame": [ "spriteFrame": [
{ {
"frame": 0, "frame": 0,
"value": {
"__uuid__": "318745eb-06b1-4e7f-88d1-e23e02d99e67"
}
},
{
"frame": 0.06666666666666667,
"value": {
"__uuid__": "a64b6f59-fa72-4f5d-89dc-81a469244ea5"
}
},
{
"frame": 0.11666666666666667,
"value": {
"__uuid__": "f800d4a1-2396-4aa5-a578-11481db1d8bf"
}
},
{
"frame": 0.16666666666666666,
"value": { "value": {
"__uuid__": "d97f6a5f-8e63-40d7-bd14-9dc71e15e5db" "__uuid__": "d97f6a5f-8e63-40d7-bd14-9dc71e15e5db"
} }
}, },
{ {
"frame": 0.23333333333333334, "frame": 0.03333333333333333,
"value": { "value": {
"__uuid__": "196bcbf9-e89f-4b26-b736-73e2fa787e50" "__uuid__": "196bcbf9-e89f-4b26-b736-73e2fa787e50"
} }
}, },
{ {
"frame": 0.3, "frame": 0.08333333333333333,
"value": { "value": {
"__uuid__": "3229e023-e63d-4a4e-af72-2b1409ea43c5" "__uuid__": "3229e023-e63d-4a4e-af72-2b1409ea43c5"
} }
}, },
{ {
"frame": 0.36666666666666664, "frame": 0.11666666666666667,
"value": { "value": {
"__uuid__": "e2d6e8b8-b468-4edb-b8c3-860bd85ebeae" "__uuid__": "e2d6e8b8-b468-4edb-b8c3-860bd85ebeae"
} }
}, },
{ {
"frame": 0.4166666666666667, "frame": 0.16666666666666666,
"value": {
"__uuid__": "318745eb-06b1-4e7f-88d1-e23e02d99e67"
}
},
{
"frame": 0.21666666666666667,
"value": { "value": {
"__uuid__": "bba6f088-0e1f-4a12-9872-41670be1152a" "__uuid__": "bba6f088-0e1f-4a12-9872-41670be1152a"
} }
}, },
{ {
"frame": 0.45, "frame": 0.26666666666666666,
"value": { "value": {
"__uuid__": "2c5de5b2-9009-48fa-bef4-ae34cc94f876" "__uuid__": "2c5de5b2-9009-48fa-bef4-ae34cc94f876"
} }
}, },
{ {
"frame": 0.48333333333333334, "frame": 0.31666666666666665,
"value": { "value": {
"__uuid__": "6f27b252-6eaf-4b4b-9c5a-46ba899e4845" "__uuid__": "6f27b252-6eaf-4b4b-9c5a-46ba899e4845"
} }
}, },
{ {
"frame": 0.5166666666666667, "frame": 0.36666666666666664,
"value": { "value": {
"__uuid__": "4ebd5c60-efa6-4950-a4c8-74a7a8517333" "__uuid__": "4ebd5c60-efa6-4950-a4c8-74a7a8517333"
} }
}, },
{ {
"frame": 0.55, "frame": 0.4166666666666667,
"value": { "value": {
"__uuid__": "a207290f-4556-4adb-8a11-e1d5ba342550" "__uuid__": "a207290f-4556-4adb-8a11-e1d5ba342550"
} }
}, },
{ {
"frame": 0.5833333333333334, "frame": 0.4666666666666667,
"value": { "value": {
"__uuid__": "e9d442d2-981d-437d-87c0-085162017de7" "__uuid__": "e9d442d2-981d-437d-87c0-085162017de7"
} }
}, },
{ {
"frame": 0.6166666666666667, "frame": 0.5166666666666667,
"value": { "value": {
"__uuid__": "9b4d5c8c-5ec0-4fd7-a45e-6b0bc8ff9119" "__uuid__": "9b4d5c8c-5ec0-4fd7-a45e-6b0bc8ff9119"
} }

View File

@@ -0,0 +1,85 @@
{
"__type__": "cc.AnimationClip",
"_name": "Atk5",
"_objFlags": 0,
"_native": "",
"_duration": 1.0166666666666666,
"sample": 60,
"speed": 1,
"wrapMode": 1,
"curveData": {
"comps": {
"cc.Sprite": {
"spriteFrame": [
{
"frame": 0,
"value": {
"__uuid__": "6aa88bb9-0427-496f-ae7d-dc06410e904e"
}
},
{
"frame": 0.08333333333333333,
"value": {
"__uuid__": "cdc65f83-c526-48b6-8a96-758b098568fe"
}
},
{
"frame": 0.16666666666666666,
"value": {
"__uuid__": "927636af-2d1d-4801-a546-857f5eeb256d"
}
},
{
"frame": 0.26666666666666666,
"value": {
"__uuid__": "2aeeb833-9151-4160-9775-9e08a376fd63"
}
},
{
"frame": 0.36666666666666664,
"value": {
"__uuid__": "2bd1de9e-30e5-4bc5-b6c3-5c286754b0b7"
}
},
{
"frame": 0.4666666666666667,
"value": {
"__uuid__": "15a6ebb3-289a-46fb-ac94-f6efa0d90510"
}
},
{
"frame": 0.5833333333333334,
"value": {
"__uuid__": "6ca922c0-cb62-4b1b-8773-79685a58bbd6"
}
},
{
"frame": 0.7,
"value": {
"__uuid__": "d60ceb6f-3a45-47dd-8d3f-bcfe8c919d85"
}
},
{
"frame": 0.8,
"value": {
"__uuid__": "c313f6a1-e0fa-4321-8336-c32f471b2592"
}
},
{
"frame": 0.9,
"value": {
"__uuid__": "bb886d03-7f3e-45c8-acfd-393091f09adb"
}
},
{
"frame": 1,
"value": {
"__uuid__": "1be255c3-f8c9-43ae-be68-2e500e7f1125"
}
}
]
}
}
},
"events": []
}

View File

@@ -0,0 +1,5 @@
{
"ver": "2.1.0",
"uuid": "0abbd156-980e-475e-9994-3c958bd913fc",
"subMetas": {}
}

View File

@@ -3,7 +3,7 @@
"_name": "InAirIdle1ByJump", "_name": "InAirIdle1ByJump",
"_objFlags": 0, "_objFlags": 0,
"_native": "", "_native": "",
"_duration": 0.7833333333333333, "_duration": 0.5833333333333334,
"sample": 60, "sample": 60,
"speed": 1, "speed": 1,
"wrapMode": 1, "wrapMode": 1,
@@ -18,67 +18,67 @@
} }
}, },
{ {
"frame": 0.05, "frame": 0.03333333333333333,
"value": { "value": {
"__uuid__": "06d18871-0cb6-41eb-a484-5c6a4c04d5d5" "__uuid__": "06d18871-0cb6-41eb-a484-5c6a4c04d5d5"
} }
}, },
{ {
"frame": 0.11666666666666667, "frame": 0.06666666666666667,
"value": { "value": {
"__uuid__": "f298ff82-ad9d-4945-ab19-14c3e3d54c95" "__uuid__": "f298ff82-ad9d-4945-ab19-14c3e3d54c95"
} }
}, },
{ {
"frame": 0.18333333333333332, "frame": 0.11666666666666667,
"value": { "value": {
"__uuid__": "bb5924a6-40cf-4e43-8c94-e51b27861656" "__uuid__": "bb5924a6-40cf-4e43-8c94-e51b27861656"
} }
}, },
{ {
"frame": 0.25, "frame": 0.16666666666666666,
"value": { "value": {
"__uuid__": "fc4b5181-77af-44ec-836e-c14eec8d20c4" "__uuid__": "fc4b5181-77af-44ec-836e-c14eec8d20c4"
} }
}, },
{ {
"frame": 0.3333333333333333, "frame": 0.21666666666666667,
"value": { "value": {
"__uuid__": "5ddd3db3-79b2-4f0c-bb76-2446801ff665" "__uuid__": "5ddd3db3-79b2-4f0c-bb76-2446801ff665"
} }
}, },
{ {
"frame": 0.4166666666666667, "frame": 0.26666666666666666,
"value": { "value": {
"__uuid__": "032785ce-c911-479b-be1c-2e0899a586d0" "__uuid__": "032785ce-c911-479b-be1c-2e0899a586d0"
} }
}, },
{ {
"frame": 0.48333333333333334, "frame": 0.31666666666666665,
"value": { "value": {
"__uuid__": "d651269d-1c08-49f8-bc38-d301bf26b0e1" "__uuid__": "d651269d-1c08-49f8-bc38-d301bf26b0e1"
} }
}, },
{ {
"frame": 0.5666666666666667, "frame": 0.36666666666666664,
"value": { "value": {
"__uuid__": "e270563e-d98d-4a80-82db-837183053ae3" "__uuid__": "e270563e-d98d-4a80-82db-837183053ae3"
} }
}, },
{ {
"frame": 0.6333333333333333, "frame": 0.43333333333333335,
"value": { "value": {
"__uuid__": "aec31ef8-46dc-4f0e-9cba-18f6c96c5c33" "__uuid__": "aec31ef8-46dc-4f0e-9cba-18f6c96c5c33"
} }
}, },
{ {
"frame": 0.7, "frame": 0.5,
"value": { "value": {
"__uuid__": "e64b3a8d-41a9-45f6-9aeb-9e49b6317080" "__uuid__": "e64b3a8d-41a9-45f6-9aeb-9e49b6317080"
} }
}, },
{ {
"frame": 0.7666666666666667, "frame": 0.5666666666666667,
"value": { "value": {
"__uuid__": "cf886091-24a9-4cfb-8cb9-e3db977035ab" "__uuid__": "cf886091-24a9-4cfb-8cb9-e3db977035ab"
} }

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 217 KiB

After

Width:  |  Height:  |  Size: 269 KiB

View File

@@ -15,7 +15,7 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{62,92}</string> <string>{62,92}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{1277,188},{62,92}}</string> <string>{{1307,188},{62,92}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<false/> <false/>
</dict> </dict>
@@ -30,7 +30,7 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{77,99}</string> <string>{77,99}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{748,0},{77,99}}</string> <string>{{782,101},{77,99}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<false/> <false/>
</dict> </dict>
@@ -45,7 +45,7 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{112,99}</string> <string>{112,99}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{408,348},{112,99}}</string> <string>{{381,360},{112,99}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<true/> <true/>
</dict> </dict>
@@ -60,7 +60,7 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{96,100}</string> <string>{96,100}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{664,315},{96,100}}</string> <string>{{704,312},{96,100}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<false/> <false/>
</dict> </dict>
@@ -75,7 +75,7 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{62,92}</string> <string>{62,92}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{1277,188},{62,92}}</string> <string>{{1307,188},{62,92}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<false/> <false/>
</dict> </dict>
@@ -90,7 +90,7 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{58,97}</string> <string>{58,97}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{1023,194},{58,97}}</string> <string>{{983,388},{58,97}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<false/> <false/>
</dict> </dict>
@@ -105,9 +105,9 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{60,90}</string> <string>{60,90}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{1393,141},{60,90}}</string> <string>{{1424,0},{60,90}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<true/> <false/>
</dict> </dict>
<key>Atk2_2.png</key> <key>Atk2_2.png</key>
<dict> <dict>
@@ -120,7 +120,7 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{84,96}</string> <string>{84,96}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{1087,97},{84,96}}</string> <string>{{1082,291},{84,96}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<false/> <false/>
</dict> </dict>
@@ -135,7 +135,7 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{55,100}</string> <string>{55,100}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{731,101},{55,100}}</string> <string>{{738,206},{55,100}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<false/> <false/>
</dict> </dict>
@@ -150,9 +150,9 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{63,100}</string> <string>{63,100}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{717,206},{63,100}}</string> <string>{{0,437},{63,100}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<false/> <true/>
</dict> </dict>
<key>Atk2_5.png</key> <key>Atk2_5.png</key>
<dict> <dict>
@@ -165,7 +165,7 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{66,101}</string> <string>{66,101}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{682,0},{66,101}}</string> <string>{{755,0},{66,101}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<false/> <false/>
</dict> </dict>
@@ -180,7 +180,7 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{80,95}</string> <string>{80,95}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{1126,0},{80,95}}</string> <string>{{1099,387},{80,95}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<false/> <false/>
</dict> </dict>
@@ -195,7 +195,7 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{116,109}</string> <string>{116,109}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{315,119},{116,109}}</string> <string>{{336,244},{116,109}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<true/> <true/>
</dict> </dict>
@@ -210,7 +210,7 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{102,96}</string> <string>{102,96}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{621,213},{102,96}}</string> <string>{{608,325},{102,96}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<true/> <true/>
</dict> </dict>
@@ -225,9 +225,9 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{75,102}</string> <string>{75,102}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{139,421},{75,102}}</string> <string>{{663,210},{75,102}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<true/> <false/>
</dict> </dict>
<key>Atk3_0.png</key> <key>Atk3_0.png</key>
<dict> <dict>
@@ -240,7 +240,7 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{66,109}</string> <string>{66,109}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{469,110},{66,109}}</string> <string>{{480,339},{66,109}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<false/> <false/>
</dict> </dict>
@@ -255,7 +255,7 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{66,113}</string> <string>{66,113}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{355,235},{66,113}}</string> <string>{{403,114},{66,113}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<false/> <false/>
</dict> </dict>
@@ -330,7 +330,7 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{78,131}</string> <string>{78,131}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{137,290},{78,131}}</string> <string>{{78,0},{78,131}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<false/> <false/>
</dict> </dict>
@@ -345,9 +345,9 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{59,139}</string> <string>{59,139}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{0,437},{59,139}}</string> <string>{{78,290},{59,139}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<true/> <false/>
</dict> </dict>
<key>Atk3_8.png</key> <key>Atk3_8.png</key>
<dict> <dict>
@@ -360,7 +360,7 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{59,139}</string> <string>{59,139}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{78,290},{59,139}}</string> <string>{{137,290},{59,139}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<false/> <false/>
</dict> </dict>
@@ -375,9 +375,9 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{62,97}</string> <string>{62,97}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{507,434},{62,97}}</string> <string>{{962,291},{62,97}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<true/> <false/>
</dict> </dict>
<key>Atked1_1.png</key> <key>Atked1_1.png</key>
<dict> <dict>
@@ -390,9 +390,9 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{73,95}</string> <string>{73,95}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{1171,95},{73,95}}</string> <string>{{641,427},{73,95}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<false/> <true/>
</dict> </dict>
<key>Atked1_2.png</key> <key>Atked1_2.png</key>
<dict> <dict>
@@ -405,7 +405,7 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{90,89}</string> <string>{90,89}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{1324,0},{90,89}}</string> <string>{{1335,0},{90,89}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<true/> <true/>
</dict> </dict>
@@ -420,7 +420,7 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{95,80}</string> <string>{95,80}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{1084,291},{95,80}}</string> <string>{{1168,193},{95,80}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<true/> <true/>
</dict> </dict>
@@ -435,7 +435,7 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{80,95}</string> <string>{80,95}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{1010,388},{80,95}}</string> <string>{{1166,290},{80,95}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<false/> <false/>
</dict> </dict>
@@ -450,7 +450,7 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{83,92}</string> <string>{83,92}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{1208,382},{83,92}}</string> <string>{{1299,382},{83,92}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<false/> <false/>
</dict> </dict>
@@ -465,7 +465,7 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{92,83}</string> <string>{92,83}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{1224,284},{92,83}}</string> <string>{{1306,284},{92,83}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<true/> <true/>
</dict> </dict>
@@ -480,7 +480,7 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{112,45}</string> <string>{112,45}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{424,115},{112,45}}</string> <string>{{469,112},{112,45}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<true/> <true/>
</dict> </dict>
@@ -495,7 +495,7 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{88,69}</string> <string>{88,69}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{604,427},{88,69}}</string> <string>{{1443,222},{88,69}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<false/> <false/>
</dict> </dict>
@@ -510,7 +510,7 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{91,90}</string> <string>{91,90}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{1303,93},{91,90}}</string> <string>{{1313,93},{91,90}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<true/> <true/>
</dict> </dict>
@@ -525,7 +525,7 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{120,93}</string> <string>{120,93}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{222,123},{120,93}}</string> <string>{{254,124},{120,93}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<true/> <true/>
</dict> </dict>
@@ -540,9 +540,9 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{100,112}</string> <string>{100,112}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{241,396},{100,112}}</string> <string>{{408,0},{100,112}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<true/> <false/>
</dict> </dict>
<key>GetUp1_5.png</key> <key>GetUp1_5.png</key>
<dict> <dict>
@@ -555,7 +555,7 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{106,93}</string> <string>{106,93}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{507,328},{106,93}}</string> <string>{{570,219},{106,93}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<true/> <true/>
</dict> </dict>
@@ -570,7 +570,7 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{106,79}</string> <string>{106,79}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{542,217},{106,79}}</string> <string>{{571,108},{106,79}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<true/> <true/>
</dict> </dict>
@@ -585,7 +585,7 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{73,87}</string> <string>{73,87}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{1307,280},{73,87}}</string> <string>{{1382,376},{73,87}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<false/> <false/>
</dict> </dict>
@@ -600,9 +600,9 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{67,90}</string> <string>{67,90}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{1413,74},{67,90}}</string> <string>{{1403,90},{67,90}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<true/> <false/>
</dict> </dict>
<key>GetUp1_9.png</key> <key>GetUp1_9.png</key>
<dict> <dict>
@@ -615,7 +615,7 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{58,97}</string> <string>{58,97}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{1023,194},{58,97}}</string> <string>{{983,388},{58,97}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<false/> <false/>
</dict> </dict>
@@ -630,7 +630,7 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{58,95}</string> <string>{58,95}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{1090,386},{58,95}}</string> <string>{{1219,0},{58,95}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<false/> <false/>
</dict> </dict>
@@ -645,7 +645,7 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{58,97}</string> <string>{58,97}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{1029,97},{58,97}}</string> <string>{{1024,291},{58,97}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<false/> <false/>
</dict> </dict>
@@ -660,7 +660,7 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{60,94}</string> <string>{60,94}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{1148,386},{60,94}}</string> <string>{{1179,385},{60,94}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<false/> <false/>
</dict> </dict>
@@ -675,7 +675,7 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{58,97}</string> <string>{58,97}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{1081,194},{58,97}}</string> <string>{{1036,194},{58,97}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<false/> <false/>
</dict> </dict>
@@ -690,7 +690,7 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{58,97}</string> <string>{58,97}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{1068,0},{58,97}}</string> <string>{{1041,388},{58,97}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<false/> <false/>
</dict> </dict>
@@ -705,9 +705,9 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{60,95}</string> <string>{60,95}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{1206,0},{60,95}}</string> <string>{{546,440},{60,95}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<false/> <true/>
</dict> </dict>
<key>Idle1_5.png</key> <key>Idle1_5.png</key>
<dict> <dict>
@@ -720,7 +720,7 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{60,94}</string> <string>{60,94}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{1164,288},{60,94}}</string> <string>{{1239,385},{60,94}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<false/> <false/>
</dict> </dict>
@@ -735,7 +735,7 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{59,93}</string> <string>{59,93}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{789,403},{59,93}}</string> <string>{{1248,191},{59,93}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<false/> <false/>
</dict> </dict>
@@ -750,7 +750,7 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{58,93}</string> <string>{58,93}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{1266,0},{58,93}}</string> <string>{{1277,0},{58,93}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<false/> <false/>
</dict> </dict>
@@ -765,7 +765,7 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{59,93}</string> <string>{59,93}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{1244,95},{59,93}}</string> <string>{{1254,95},{59,93}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<false/> <false/>
</dict> </dict>
@@ -780,7 +780,7 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{60,94}</string> <string>{60,94}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{1217,190},{60,94}}</string> <string>{{1246,288},{60,94}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<false/> <false/>
</dict> </dict>
@@ -795,7 +795,7 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{77,68}</string> <string>{77,68}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{1437,417},{77,68}}</string> <string>{{1473,291},{77,68}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<true/> <true/>
</dict> </dict>
@@ -810,7 +810,7 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{118,76}</string> <string>{118,76}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{215,278},{118,76}}</string> <string>{{196,284},{118,76}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<true/> <true/>
</dict> </dict>
@@ -825,7 +825,7 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{104,65}</string> <string>{104,65}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{617,0},{104,65}}</string> <string>{{650,106},{104,65}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<true/> <true/>
</dict> </dict>
@@ -840,9 +840,9 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{80,66}</string> <string>{80,66}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{1380,285},{80,66}}</string> <string>{{1473,368},{80,66}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<false/> <true/>
</dict> </dict>
<key>InAirAtk1_12.png</key> <key>InAirAtk1_12.png</key>
<dict> <dict>
@@ -855,7 +855,7 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{102,67}</string> <string>{102,67}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{664,104},{102,67}}</string> <string>{{715,104},{102,67}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<true/> <true/>
</dict> </dict>
@@ -870,9 +870,9 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{79,66}</string> <string>{79,66}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{1339,201},{79,66}}</string> <string>{{1470,90},{79,66}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<true/> <false/>
</dict> </dict>
<key>InAirAtk1_3.png</key> <key>InAirAtk1_3.png</key>
<dict> <dict>
@@ -885,7 +885,7 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{124,64}</string> <string>{124,64}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{78,0},{124,64}}</string> <string>{{156,0},{124,64}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<true/> <true/>
</dict> </dict>
@@ -900,7 +900,7 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{104,64}</string> <string>{104,64}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{600,323},{104,64}}</string> <string>{{691,0},{104,64}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<true/> <true/>
</dict> </dict>
@@ -915,7 +915,7 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{79,61}</string> <string>{79,61}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{1376,417},{79,61}}</string> <string>{{1484,0},{79,61}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<true/> <true/>
</dict> </dict>
@@ -930,7 +930,7 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{124,64}</string> <string>{124,64}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{142,0},{124,64}}</string> <string>{{160,124},{124,64}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<true/> <true/>
</dict> </dict>
@@ -945,7 +945,7 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{106,67}</string> <string>{106,67}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{597,107},{106,67}}</string> <string>{{624,0},{106,67}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<true/> <true/>
</dict> </dict>
@@ -960,7 +960,7 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{79,66}</string> <string>{79,66}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{1380,351},{79,66}}</string> <string>{{1470,156},{79,66}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<false/> <false/>
</dict> </dict>
@@ -975,7 +975,7 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{118,64}</string> <string>{118,64}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{291,243},{118,64}}</string> <string>{{272,284},{118,64}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<true/> <true/>
</dict> </dict>
@@ -990,9 +990,9 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{71,119}</string> <string>{71,119}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{242,0},{71,119}}</string> <string>{{100,429},{71,119}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<false/> <true/>
</dict> </dict>
<key>InAirIdle1_1.png</key> <key>InAirIdle1_1.png</key>
<dict> <dict>
@@ -1005,7 +1005,7 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{71,119}</string> <string>{71,119}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{313,0},{71,119}}</string> <string>{{282,0},{71,119}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<false/> <false/>
</dict> </dict>
@@ -1020,7 +1020,7 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{55,114}</string> <string>{55,114}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{353,361},{55,114}}</string> <string>{{353,0},{55,114}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<false/> <false/>
</dict> </dict>
@@ -1035,7 +1035,7 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{62,124}</string> <string>{62,124}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{160,124},{62,124}}</string> <string>{{220,0},{62,124}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<false/> <false/>
</dict> </dict>
@@ -1050,9 +1050,9 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{74,90}</string> <string>{74,90}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{1413,0},{74,90}}</string> <string>{{1369,184},{74,90}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<true/> <false/>
</dict> </dict>
<key>InAirIdle1_3.png</key> <key>InAirIdle1_3.png</key>
<dict> <dict>
@@ -1065,7 +1065,7 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{110,54}</string> <string>{110,54}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{440,0},{110,54}}</string> <string>{{508,0},{110,54}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<true/> <true/>
</dict> </dict>
@@ -1080,7 +1080,7 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{85,88}</string> <string>{85,88}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{1291,376},{85,88}}</string> <string>{{736,412},{85,88}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<false/> <false/>
</dict> </dict>
@@ -1095,7 +1095,7 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{64,112}</string> <string>{64,112}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{421,235},{64,112}}</string> <string>{{445,227},{64,112}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<false/> <false/>
</dict> </dict>
@@ -1110,7 +1110,7 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{62,107}</string> <string>{62,107}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{555,0},{62,107}}</string> <string>{{546,333},{62,107}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<false/> <false/>
</dict> </dict>
@@ -1125,9 +1125,9 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{85,84}</string> <string>{85,84}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{1405,201},{85,84}}</string> <string>{{1389,291},{85,84}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<false/> <true/>
</dict> </dict>
<key>InAirIdle1_8.png</key> <key>InAirIdle1_8.png</key>
<dict> <dict>
@@ -1140,7 +1140,7 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{109,61}</string> <string>{109,61}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{494,0},{109,61}}</string> <string>{{509,224},{109,61}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<true/> <true/>
</dict> </dict>
@@ -1155,7 +1155,7 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{78,95}</string> <string>{78,95}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{1139,193},{78,95}}</string> <string>{{1176,96},{78,95}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<false/> <false/>
</dict> </dict>
@@ -1170,7 +1170,7 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{115,56}</string> <string>{115,56}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{384,0},{115,56}}</string> <string>{{347,119},{115,56}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<true/> <true/>
</dict> </dict>
@@ -1185,7 +1185,7 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{109,57}</string> <string>{109,57}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{485,219},{109,57}}</string> <string>{{514,110},{109,57}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<true/> <true/>
</dict> </dict>
@@ -1200,7 +1200,7 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{108,62}</string> <string>{108,62}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{535,109},{108,62}}</string> <string>{{562,0},{108,62}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<true/> <true/>
</dict> </dict>
@@ -1215,9 +1215,9 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{123,36}</string> <string>{123,36}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{206,0},{123,36}}</string> <string>{{160,248},{123,36}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<true/> <false/>
</dict> </dict>
<key>LayDown1_4.png</key> <key>LayDown1_4.png</key>
<dict> <dict>
@@ -1230,7 +1230,52 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{123,30}</string> <string>{123,30}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{160,248},{123,30}}</string> <string>{{224,124},{123,30}}</string>
<key>textureRotated</key>
<true/>
</dict>
<key>TurnAround1_1.png</key>
<dict>
<key>aliases</key>
<array/>
<key>spriteOffset</key>
<string>{0,0}</string>
<key>spriteSize</key>
<string>{74,96}</string>
<key>spriteSourceSize</key>
<string>{74,96}</string>
<key>textureRect</key>
<string>{{1094,194},{74,96}}</string>
<key>textureRotated</key>
<false/>
</dict>
<key>TurnAround1_2.png</key>
<dict>
<key>aliases</key>
<array/>
<key>spriteOffset</key>
<string>{0,0}</string>
<key>spriteSize</key>
<string>{74,96}</string>
<key>spriteSourceSize</key>
<string>{74,96}</string>
<key>textureRect</key>
<string>{{1102,97},{74,96}}</string>
<key>textureRotated</key>
<false/>
</dict>
<key>TurnAround1_3.png</key>
<dict>
<key>aliases</key>
<array/>
<key>spriteOffset</key>
<string>{0,0}</string>
<key>spriteSize</key>
<string>{74,96}</string>
<key>spriteSourceSize</key>
<string>{74,96}</string>
<key>textureRect</key>
<string>{{1145,0},{74,96}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<false/> <false/>
</dict> </dict>
@@ -1245,9 +1290,9 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{81,97}</string> <string>{81,97}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{692,415},{81,97}}</string> <string>{{219,402},{81,97}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<true/> <false/>
</dict> </dict>
<key>Walking_10.png</key> <key>Walking_10.png</key>
<dict> <dict>
@@ -1260,7 +1305,7 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{81,97}</string> <string>{81,97}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{760,306},{81,97}}</string> <string>{{300,402},{81,97}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<false/> <false/>
</dict> </dict>
@@ -1275,7 +1320,7 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{81,97}</string> <string>{81,97}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{780,201},{81,97}}</string> <string>{{821,0},{81,97}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<false/> <false/>
</dict> </dict>
@@ -1290,7 +1335,7 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{81,97}</string> <string>{81,97}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{786,99},{81,97}}</string> <string>{{793,200},{81,97}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<false/> <false/>
</dict> </dict>
@@ -1305,7 +1350,7 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{81,97}</string> <string>{81,97}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{825,0},{81,97}}</string> <string>{{859,97},{81,97}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<false/> <false/>
</dict> </dict>
@@ -1320,7 +1365,7 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{81,97}</string> <string>{81,97}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{841,298},{81,97}}</string> <string>{{902,0},{81,97}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<false/> <false/>
</dict> </dict>
@@ -1335,7 +1380,7 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{81,97}</string> <string>{81,97}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{848,395},{81,97}}</string> <string>{{800,297},{81,97}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<false/> <false/>
</dict> </dict>
@@ -1350,7 +1395,7 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{81,97}</string> <string>{81,97}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{861,196},{81,97}}</string> <string>{{874,194},{81,97}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<false/> <false/>
</dict> </dict>
@@ -1365,7 +1410,7 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{81,97}</string> <string>{81,97}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{867,97},{81,97}}</string> <string>{{940,97},{81,97}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<false/> <false/>
</dict> </dict>
@@ -1380,7 +1425,7 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{81,97}</string> <string>{81,97}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{906,0},{81,97}}</string> <string>{{983,0},{81,97}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<false/> <false/>
</dict> </dict>
@@ -1395,7 +1440,7 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{81,97}</string> <string>{81,97}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{922,293},{81,97}}</string> <string>{{821,394},{81,97}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<false/> <false/>
</dict> </dict>
@@ -1410,7 +1455,7 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{81,97}</string> <string>{81,97}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{942,194},{81,97}}</string> <string>{{881,291},{81,97}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<false/> <false/>
</dict> </dict>
@@ -1425,7 +1470,7 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{81,97}</string> <string>{81,97}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{948,97},{81,97}}</string> <string>{{955,194},{81,97}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<false/> <false/>
</dict> </dict>
@@ -1440,7 +1485,7 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{81,97}</string> <string>{81,97}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{987,0},{81,97}}</string> <string>{{1021,97},{81,97}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<false/> <false/>
</dict> </dict>
@@ -1455,7 +1500,7 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{81,97}</string> <string>{81,97}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{929,390},{81,97}}</string> <string>{{1064,0},{81,97}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<false/> <false/>
</dict> </dict>
@@ -1470,7 +1515,7 @@
<key>spriteSourceSize</key> <key>spriteSourceSize</key>
<string>{81,97}</string> <string>{81,97}</string>
<key>textureRect</key> <key>textureRect</key>
<string>{{1003,291},{81,97}}</string> <string>{{902,388},{81,97}}</string>
<key>textureRotated</key> <key>textureRotated</key>
<false/> <false/>
</dict> </dict>
@@ -1486,9 +1531,9 @@
<key>realTextureFileName</key> <key>realTextureFileName</key>
<string>MonkGirl.png</string> <string>MonkGirl.png</string>
<key>size</key> <key>size</key>
<string>{1505,496}</string> <string>{1549,500}</string>
<key>smartupdate</key> <key>smartupdate</key>
<string>$TexturePacker:SmartUpdate:8383576ddc6ed0fb9e6adcbc98ec9c07:b0caf27c9f592741053365a3d87b3473:7b088363a1f16e4f4ff313aecc52227b$</string> <string>$TexturePacker:SmartUpdate:f2fd96a7a4bba5a2e1c4622dcb63e1f2:17c698372c46bf0be82704dd808cd6f4:7b088363a1f16e4f4ff313aecc52227b$</string>
<key>textureFileName</key> <key>textureFileName</key>
<string>MonkGirl.png</string> <string>MonkGirl.png</string>
</dict> </dict>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 96 KiB

After

Width:  |  Height:  |  Size: 98 KiB

View File

@@ -1,23 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<map version="1.2" tiledversion="1.2.3" orientation="orthogonal" renderorder="right-down" width="128" height="128" tilewidth="16" tileheight="16" infinite="0" nextlayerid="6" nextobjectid="113"> <map version="1.2" tiledversion="1.2.3" orientation="orthogonal" renderorder="right-down" width="128" height="64" tilewidth="16" tileheight="16" infinite="0" nextlayerid="7" nextobjectid="135">
<tileset firstgid="1" source="tiles0.tsx"/> <tileset firstgid="1" source="tiles0.tsx"/>
<tileset firstgid="65" source="tiles1.tsx"/> <tileset firstgid="65" source="tiles1.tsx"/>
<tileset firstgid="129" source="tiles2.tsx"/> <tileset firstgid="129" source="tiles2.tsx"/>
<layer id="2" name="Ground" width="128" height="128"> <layer id="6" name="Ground" width="128" height="64">
<data encoding="base64" compression="zlib"> <data encoding="base64" compression="zlib">
eJzt3LFu00AcwOEoFUuHigqBBANTByRegrlTWWBj6gsgWGBCqngAFgZ23hNHsiXj5mLncs6dfd/wSVUbWa1/f199VpSLzWZzAQAAAAAAAAAAAAAAAAAAES5buX8Pzue+p+t/X6HcHXL237a6/p8atwHbFdL///4h+q9Pv//tSP/LAlrpP1//ffRft93f/ry179wM14TcrfQ/b/8a6K9/7g45+z+LkLuZ/nn7r2kG9Nc/d4cl9i+J/nX2d/3X3T/FDOi/XK5//fWvt3+KGdA//bntnik+nGjua19//fVfRv+XLf3r6d/v3f9af/31z9f/6YiU/fv0z9t/rPu+/r8bH47U9Xf/V07/qe3vNu7/l2Jq/6ntt/ovylj/fY3fNq4C7Yf9h+6OpH++/vvaX/UMu8/R/0XjRv9i+h9a9/v9U9O/3P4x94jH0v/8/afMwPBcpuw7JmX/bQEtSuyf6hwfEtNe//X0P2ZG5ji2/qfPwN9ELVIdR/90/afMgP7LpL/+JXXL1T93B/31X3L/Xwnpv7z+S6Z/3fSvm/51079u+tdN/7rpXzf966Z/3fSvm/51079u+pfrJkD/MvrP9X7RUPc55kD/cvpfj3gSoP86+uegf3xv/Zet9Ps//dfXP/S/vfv5+4T6xwytT97/Pe5ja7jed9/PfQ2fev3rf9ih//nD/q8LaBqyb43QP2zXMrTn2hnbr12PHD93+65/7g6l9u86vznBqfvzOdvr/3i9Tr1+p3hGM1d7/dM/Twv1zzEDU/YItfefu8Fwts71nGjqHlH/8/bvZmDOz3s55hmB/o+lvJ8/tH8I+REhpr3+4/1OnYOY/jEz8DOS/tPEzsGrTVz/3WcBfA207nxvfG5fq/+8/WM1/d/F9t/5sgn3/9Z73a7ln5b+0/uTvwMAAAAAAAAAAAAAAABwfv8AQJoGWw== eJzt2ztuAjEURmELlIYuiKRHyk4iGjo2wP6XkRDGUmThxwx3fC3+U3wNw8v3eEyabEMIWwAAAAAAAAAAAADo4IQ/3h08+3t/B2/KM1BeOzPQXjsz0F47M6iv/c3oc6zeh/7+/Q+NHr1P6z7YGz2H/svWXur1TP/SvqL/OP1LnSz6t7Qt9a1dp//4/VvOgJJeM3hlLf2tzNljI83glY2+9vcMpRko9E/PgFz3NfbBKDNQ7r+kvdU+GHEGHv2/Gl9zNHrOKOh/t5vQX8dt7d+JeC19PDo2yr1+NHEG3i28+m8m8f6//jpnbAzkfsNr15eqfR/1+z/tfxP/Fvj/mFX/0dD/7pz0fsR69p8rmHv20D9vl5mZ1flb67VkP81pT/8QPialmT1z/5f2QK/7v7Q/6Z/vb6F0DvToXzuf1PvDv4Nn/4s4+mujvzb6a6O/Nvpro782+mujvzb6a6O/Nvpro782+mujvzb6a6O/Nvpro782+mujvzb6a6O/tvg/UN4t6E9/+tO/d3+s1/8HUhSy6A==
</data> </data>
</layer> </layer>
<objectgroup id="1" name="PlayerStartingPos"> <objectgroup id="1" name="PlayerStartingPos">
<object id="135" x="1040.33" y="1081"> <object id="135" x="1400" y="580">
<point/> <point/>
</object> </object>
<object id="137" x="1134.67" y="1081.67"> <object id="137" x="1500" y="580">
<point/> <point/>
</object> </object>
</objectgroup> </objectgroup>
<objectgroup id="4" name="NpcStartingPos"> <objectgroup id="4" name="NpcStartingPos">
<object id="108" x="926" y="1447"> <object id="108" x="927.333" y="535">
<properties> <properties>
<property name="dirX" value="-2"/> <property name="dirX" value="-2"/>
<property name="speciesId" value="4196"/> <property name="speciesId" value="4196"/>
@@ -26,28 +26,28 @@
</object> </object>
</objectgroup> </objectgroup>
<objectgroup id="5" name="NpcPatrolCue"> <objectgroup id="5" name="NpcPatrolCue">
<object id="109" x="773.337" y="1468.67"> <object id="109" x="774.67" y="556.67">
<properties> <properties>
<property name="flAct" value="36"/> <property name="flAct" value="36"/>
<property name="frAct" value="35"/> <property name="frAct" value="35"/>
</properties> </properties>
<point/> <point/>
</object> </object>
<object id="110" x="728" y="1500"> <object id="110" x="729.333" y="588">
<properties> <properties>
<property name="flAct" value="4"/> <property name="flAct" value="4"/>
<property name="frAct" value="35"/> <property name="frAct" value="35"/>
</properties> </properties>
<point/> <point/>
</object> </object>
<object id="111" x="668" y="1500"> <object id="111" x="669.333" y="588">
<properties> <properties>
<property name="flAct" value="3"/> <property name="flAct" value="3"/>
<property name="frAct" value="3"/> <property name="frAct" value="3"/>
</properties> </properties>
<point/> <point/>
</object> </object>
<object id="112" x="984" y="1447"> <object id="112" x="985.333" y="535">
<properties> <properties>
<property name="flAct" value="4"/> <property name="flAct" value="4"/>
<property name="frAct" value="4"/> <property name="frAct" value="4"/>
@@ -59,197 +59,147 @@
<properties> <properties>
<property name="type" value="barrier_and_shelter"/> <property name="type" value="barrier_and_shelter"/>
</properties> </properties>
<object id="54" x="656" y="1504" width="80" height="16"> <object id="57" x="768" y="560" width="32" height="16">
<properties> <properties>
<property name="boundary_type" value="barrier"/> <property name="boundary_type" value="barrier"/>
</properties> </properties>
</object> </object>
<object id="55" x="736" y="1552" width="112" height="16"> <object id="60" x="1232" y="432" width="208" height="16">
<properties> <properties>
<property name="boundary_type" value="barrier"/> <property name="boundary_type" value="barrier"/>
</properties> </properties>
</object> </object>
<object id="57" x="768" y="1472" width="32" height="16"> <object id="65" x="1040" y="576" width="32" height="16">
<properties> <properties>
<property name="boundary_type" value="barrier"/> <property name="boundary_type" value="barrier"/>
</properties> </properties>
</object> </object>
<object id="58" x="1040" y="1536" width="80" height="16"> <object id="66" x="1040" y="560" width="16" height="16">
<properties> <properties>
<property name="boundary_type" value="barrier"/> <property name="boundary_type" value="barrier"/>
</properties> </properties>
</object> </object>
<object id="59" x="1040" y="1568" width="224" height="48"> <object id="67" x="784" y="544" width="256" height="16">
<properties> <properties>
<property name="boundary_type" value="barrier"/> <property name="boundary_type" value="barrier"/>
</properties> </properties>
</object> </object>
<object id="60" x="1216" y="1344" width="224" height="16"> <object id="84" x="640" y="224" width="16" height="800">
<properties> <properties>
<property name="boundary_type" value="barrier"/> <property name="boundary_type" value="barrier"/>
</properties> </properties>
</object> </object>
<object id="62" x="1040" y="1552" width="208" height="16"> <object id="85" x="1680" y="224" width="16" height="800">
<properties> <properties>
<property name="boundary_type" value="barrier"/> <property name="boundary_type" value="barrier"/>
</properties> </properties>
</object> </object>
<object id="63" x="1040" y="1504" width="48" height="16"> <object id="86" x="1104" y="496" width="96" height="16">
<properties> <properties>
<property name="boundary_type" value="barrier"/> <property name="boundary_type" value="barrier"/>
</properties> </properties>
</object> </object>
<object id="64" x="1040" y="1520" width="64" height="16"> <object id="90" x="1232" y="496" width="320" height="16">
<properties> <properties>
<property name="boundary_type" value="barrier"/> <property name="boundary_type" value="barrier"/>
</properties> </properties>
</object> </object>
<object id="65" x="1040" y="1488" width="32" height="16"> <object id="97" x="1248" y="416" width="158" height="16">
<properties> <properties>
<property name="boundary_type" value="barrier"/> <property name="boundary_type" value="barrier"/>
</properties> </properties>
</object> </object>
<object id="66" x="1040" y="1472" width="16" height="16"> <object id="98" x="1280" y="400" width="96" height="16">
<properties> <properties>
<property name="boundary_type" value="barrier"/> <property name="boundary_type" value="barrier"/>
</properties> </properties>
</object> </object>
<object id="67" x="784" y="1456" width="256" height="16"> <object id="100" x="1552" y="576" width="128" height="16">
<properties> <properties>
<property name="boundary_type" value="barrier"/> <property name="boundary_type" value="barrier"/>
</properties> </properties>
</object> </object>
<object id="73" x="784" y="1568" width="96" height="16"> <object id="101" x="1568" y="560" width="112" height="16">
<properties> <properties>
<property name="boundary_type" value="barrier"/> <property name="boundary_type" value="barrier"/>
</properties> </properties>
</object> </object>
<object id="74" x="816" y="1584" width="96" height="16"> <object id="102" x="1584" y="544" width="96" height="16">
<properties> <properties>
<property name="boundary_type" value="barrier"/> <property name="boundary_type" value="barrier"/>
</properties> </properties>
</object> </object>
<object id="79" x="640" y="1616" width="1056" height="16"> <object id="103" x="1600" y="528" width="80" height="16">
<properties> <properties>
<property name="boundary_type" value="barrier"/> <property name="boundary_type" value="barrier"/>
</properties> </properties>
</object> </object>
<object id="83" x="640" y="480" width="1056" height="16"> <object id="104" x="768" y="382" width="304" height="16">
<properties> <properties>
<property name="boundary_type" value="barrier"/> <property name="boundary_type" value="barrier"/>
</properties> </properties>
</object> </object>
<object id="84" x="640" y="480" width="16" height="1152"> <object id="105" x="768" y="302" width="16" height="96">
<properties> <properties>
<property name="boundary_type" value="barrier"/> <property name="boundary_type" value="barrier"/>
</properties> </properties>
</object> </object>
<object id="85" x="1680" y="480" width="16" height="1152"> <object id="106" x="1056" y="302" width="16" height="96">
<properties> <properties>
<property name="boundary_type" value="barrier"/> <property name="boundary_type" value="barrier"/>
</properties> </properties>
</object> </object>
<object id="86" x="1104" y="1408" width="96" height="16"> <object id="113" x="640" y="1008" width="1056" height="16">
<properties> <properties>
<property name="boundary_type" value="barrier"/> <property name="boundary_type" value="barrier"/>
</properties> </properties>
</object> </object>
<object id="87" x="1456" y="1568" width="224" height="48"> <object id="114" x="640" y="224" width="1056" height="16">
<properties> <properties>
<property name="boundary_type" value="barrier"/> <property name="boundary_type" value="barrier"/>
</properties> </properties>
</object> </object>
<object id="88" x="1264" y="1584" width="16" height="32"> <object id="119" x="656" y="592" width="1024" height="416">
<properties> <properties>
<property name="boundary_type" value="barrier"/> <property name="boundary_type" value="barrier"/>
</properties> </properties>
</object> </object>
<object id="89" x="1280" y="1600" width="16" height="16"> <object id="120" x="736" y="512" width="16" height="16">
<properties> <properties>
<property name="boundary_type" value="barrier"/> <property name="boundary_type" value="barrier"/>
</properties> </properties>
</object> </object>
<object id="90" x="1232" y="1408" width="304" height="16"> <object id="121" x="736" y="336" width="16" height="16">
<properties> <properties>
<property name="boundary_type" value="barrier"/> <property name="boundary_type" value="barrier"/>
</properties> </properties>
</object> </object>
<object id="91" x="1440" y="1584" width="16" height="32"> <object id="125" x="688" y="448" width="16" height="16">
<properties> <properties>
<property name="boundary_type" value="barrier"/> <property name="boundary_type" value="barrier"/>
</properties> </properties>
</object> </object>
<object id="92" x="1424" y="1600" width="16" height="16"> <object id="127" x="1088" y="320" width="16" height="16">
<properties> <properties>
<property name="boundary_type" value="barrier"/> <property name="boundary_type" value="barrier"/>
</properties> </properties>
</object> </object>
<object id="93" x="1488" y="1552" width="192" height="16"> <object id="128" x="1120" y="336" width="16" height="16">
<properties> <properties>
<property name="boundary_type" value="barrier"/> <property name="boundary_type" value="barrier"/>
</properties> </properties>
</object> </object>
<object id="94" x="1504" y="1536" width="176" height="16"> <object id="129" x="1136" y="368" width="16" height="16">
<properties> <properties>
<property name="boundary_type" value="barrier"/> <property name="boundary_type" value="barrier"/>
</properties> </properties>
</object> </object>
<object id="95" x="1520" y="1520" width="160" height="16"> <object id="130" x="1168" y="384" width="16" height="16">
<properties> <properties>
<property name="boundary_type" value="barrier"/> <property name="boundary_type" value="barrier"/>
</properties> </properties>
</object> </object>
<object id="96" x="1568" y="1408" width="16" height="16"> <object id="132" x="1184" y="416" width="16" height="16">
<properties>
<property name="boundary_type" value="barrier"/>
</properties>
</object>
<object id="97" x="1248" y="1328" width="158" height="16">
<properties>
<property name="boundary_type" value="barrier"/>
</properties>
</object>
<object id="98" x="1280" y="1312" width="96" height="16">
<properties>
<property name="boundary_type" value="barrier"/>
</properties>
</object>
<object id="99" x="1536" y="1504" width="144" height="16">
<properties>
<property name="boundary_type" value="barrier"/>
</properties>
</object>
<object id="100" x="1552" y="1488" width="128" height="16">
<properties>
<property name="boundary_type" value="barrier"/>
</properties>
</object>
<object id="101" x="1568" y="1472" width="112" height="16">
<properties>
<property name="boundary_type" value="barrier"/>
</properties>
</object>
<object id="102" x="1584" y="1456" width="96" height="16">
<properties>
<property name="boundary_type" value="barrier"/>
</properties>
</object>
<object id="103" x="1600" y="1440" width="80" height="16">
<properties>
<property name="boundary_type" value="barrier"/>
</properties>
</object>
<object id="104" x="928" y="1088" width="304" height="16">
<properties>
<property name="boundary_type" value="barrier"/>
</properties>
</object>
<object id="105" x="928" y="1008" width="16" height="96">
<properties>
<property name="boundary_type" value="barrier"/>
</properties>
</object>
<object id="106" x="1216" y="1008" width="16" height="96">
<properties> <properties>
<property name="boundary_type" value="barrier"/> <property name="boundary_type" value="barrier"/>
</properties> </properties>

View File

@@ -9,9 +9,9 @@ message PlayerDownsync {
int32 virtualGridX = 2; int32 virtualGridX = 2;
int32 virtualGridY = 3; int32 virtualGridY = 3;
int32 dirX = 4; int32 dirX = 4;
int32 dirY = 5; // "dirX" and "dirY" determines character facing int32 dirY = 5;
int32 velX = 6; int32 velX = 6;
int32 velY = 7; // "velX" and "velY" is used to record the accumulated effect by accelerations (including gravity) int32 velY = 7; // "velX" and "velY" is used to record the accumulated effect by inertia and accelerations (including gravity)
int32 speed = 8; // this is the instantaneous scalar attribute of a character, different from but will be accounted in "velX" and "velY" int32 speed = 8; // this is the instantaneous scalar attribute of a character, different from but will be accounted in "velX" and "velY"
int32 battleState = 9; int32 battleState = 9;
int32 joinIndex = 10; int32 joinIndex = 10;
@@ -32,6 +32,12 @@ message PlayerDownsync {
int32 bulletTeamId = 24; int32 bulletTeamId = 24;
int32 chCollisionTeamId = 25; int32 chCollisionTeamId = 25;
bool onWall = 26; // like "inAir", its by design a standalone field only inferred by the collision result of "applyInputFrameDownsyncDynamicsOnSingleRenderFrame" instead of "characterState", because we need check the transition for "characterState" from this field, i.e. "onWall (prev -> curr)"
int32 onWallNormX = 27;
int32 onWallNormY = 28;
bool capturedByInertia = 29; // like "inAir", its by design a standalone field only inferred by the calc result of "applyInputFrameDownsyncDynamicsOnSingleRenderFrame" instead of "characterState"
string name = 997; string name = 997;
string displayName = 998; string displayName = 998;
string avatar = 999; string avatar = 999;
@@ -47,6 +53,7 @@ message InputFrameDecoded {
message InputFrameUpsync { message InputFrameUpsync {
int32 inputFrameId = 1; int32 inputFrameId = 1;
uint64 encoded = 2; uint64 encoded = 2;
int32 joinIndex = 3;
} }
message InputFrameDownsync { message InputFrameDownsync {
@@ -77,6 +84,7 @@ message WsResp {
RoomDownsyncFrame rdf = 4; RoomDownsyncFrame rdf = 4;
repeated InputFrameDownsync inputFrameDownsyncBatch = 5; repeated InputFrameDownsync inputFrameDownsyncBatch = 5;
BattleColliderInfo bciFrame = 6; BattleColliderInfo bciFrame = 6;
int32 peerJoinIndex = 7; // Only used when "InputsBufferSnapshot.peerJoinIndex" is used.
} }
message InputsBufferSnapshot { message InputsBufferSnapshot {
@@ -84,6 +92,7 @@ message InputsBufferSnapshot {
uint64 unconfirmedMask = 2; uint64 unconfirmedMask = 2;
repeated InputFrameDownsync toSendInputFrameDownsyncs = 3; repeated InputFrameDownsync toSendInputFrameDownsyncs = 3;
bool shouldForceResync = 4; bool shouldForceResync = 4;
int32 peerJoinIndex = 5; // Only used when "WsResp.peerJoinIndex" is used.
} }
message MeleeBullet { message MeleeBullet {
@@ -117,6 +126,11 @@ message MeleeBullet {
int32 teamId = 19; int32 teamId = 19;
int32 bulletLocalId = 20; int32 bulletLocalId = 20;
int32 speciesId = 21;
int32 explosionFrames = 22;
int32 blState = 23;
int32 framesInBlState = 24;
} }
message FireballBullet { message FireballBullet {
@@ -146,6 +160,11 @@ message FireballBullet {
int32 teamId = 19; int32 teamId = 19;
int32 bulletLocalId = 20; int32 bulletLocalId = 20;
int32 speciesId = 21;
int32 explosionFrames = 22;
int32 blState = 23;
int32 framesInBlState = 24;
int32 virtualGridX = 999; int32 virtualGridX = 999;
int32 virtualGridY = 1000; int32 virtualGridY = 1000;

View File

@@ -31,13 +31,10 @@
"_components": [ "_components": [
{ {
"__id__": 22 "__id__": 22
},
{
"__id__": 23
} }
], ],
"_prefab": { "_prefab": {
"__id__": 24 "__id__": 23
}, },
"_opacity": 255, "_opacity": 255,
"_color": { "_color": {
@@ -648,6 +645,14 @@
}, },
{ {
"__uuid__": "9b500cb0-8048-4715-81db-cc975c914225" "__uuid__": "9b500cb0-8048-4715-81db-cc975c914225"
},
null,
null,
{
"__uuid__": "38b2c892-347b-4009-93f8-65b2ab1614f0"
},
{
"__uuid__": "411f964a-4dd8-424c-b2e2-d92b10474ce2"
} }
], ],
"playOnLoad": false, "playOnLoad": false,
@@ -814,6 +819,9 @@
}, },
{ {
"__uuid__": "7e0a1e98-ee5a-446f-bec2-7d72b6916503" "__uuid__": "7e0a1e98-ee5a-446f-bec2-7d72b6916503"
},
{
"__uuid__": "0abbd156-980e-475e-9994-3c958bd913fc"
} }
], ],
"playOnLoad": false, "playOnLoad": false,
@@ -869,32 +877,6 @@
"fileId": "7aN7Gcc/tBw5EGlTJVBj2+", "fileId": "7aN7Gcc/tBw5EGlTJVBj2+",
"sync": false "sync": false
}, },
{
"__type__": "cc.Sprite",
"_name": "",
"_objFlags": 0,
"node": {
"__id__": 1
},
"_enabled": true,
"_materials": [],
"_srcBlendFactor": 770,
"_dstBlendFactor": 771,
"_spriteFrame": null,
"_type": 0,
"_sizeMode": 0,
"_fillType": 0,
"_fillCenter": {
"__type__": "cc.Vec2",
"x": 0,
"y": 0
},
"_fillStart": 0,
"_fillRange": 0,
"_isTrimmedMode": true,
"_atlas": null,
"_id": ""
},
{ {
"__type__": "b74b05YDqZFRo4OkZRFZX8k", "__type__": "b74b05YDqZFRo4OkZRFZX8k",
"_name": "", "_name": "",

View File

@@ -8,7 +8,8 @@
"__id__": 1 "__id__": 1
}, },
"optimizationPolicy": 0, "optimizationPolicy": 0,
"asyncLoadAssets": false "asyncLoadAssets": false,
"readonly": false
}, },
{ {
"__type__": "cc.Node", "__type__": "cc.Node",
@@ -27,20 +28,19 @@
}, },
{ {
"__id__": 11 "__id__": 11
},
{
"__id__": 14
} }
], ],
"_active": true, "_active": true,
"_level": 1,
"_components": [ "_components": [
{ {
"__id__": 14 "__id__": 17
},
{
"__id__": 15
} }
], ],
"_prefab": { "_prefab": {
"__id__": 16 "__id__": 18
}, },
"_opacity": 255, "_opacity": 255,
"_color": { "_color": {
@@ -52,25 +52,14 @@
}, },
"_contentSize": { "_contentSize": {
"__type__": "cc.Size", "__type__": "cc.Size",
"width": 1024, "width": 960,
"height": 1920 "height": 640
}, },
"_anchorPoint": { "_anchorPoint": {
"__type__": "cc.Vec2", "__type__": "cc.Vec2",
"x": 0.5, "x": 0.5,
"y": 0.5 "y": 0.5
}, },
"_quat": {
"__type__": "cc.Quat",
"x": 0,
"y": 0,
"z": 0,
"w": 1
},
"_skewX": 0,
"_skewY": 0,
"groupIndex": 0,
"_id": "",
"_trs": { "_trs": {
"__type__": "TypedArray", "__type__": "TypedArray",
"ctor": "Float64Array", "ctor": "Float64Array",
@@ -86,18 +75,29 @@
1, 1,
1 1
] ]
} },
"_eulerAngles": {
"__type__": "cc.Vec3",
"x": 0,
"y": 0,
"z": 0
},
"_skewX": 0,
"_skewY": 0,
"_is3DNode": false,
"_groupIndex": 0,
"groupIndex": 0,
"_id": ""
}, },
{ {
"__type__": "cc.Node", "__type__": "cc.Node",
"_name": "WhiteStars", "_name": "Background",
"_objFlags": 0, "_objFlags": 0,
"_parent": { "_parent": {
"__id__": 1 "__id__": 1
}, },
"_children": [], "_children": [],
"_active": true, "_active": true,
"_level": 2,
"_components": [ "_components": [
{ {
"__id__": 3 "__id__": 3
@@ -109,37 +109,26 @@
"_opacity": 255, "_opacity": 255,
"_color": { "_color": {
"__type__": "cc.Color", "__type__": "cc.Color",
"r": 255, "r": 0,
"g": 255, "g": 163,
"b": 255, "b": 255,
"a": 255 "a": 255
}, },
"_contentSize": { "_contentSize": {
"__type__": "cc.Size", "__type__": "cc.Size",
"width": 268, "width": 1920,
"height": 112 "height": 1280
}, },
"_anchorPoint": { "_anchorPoint": {
"__type__": "cc.Vec2", "__type__": "cc.Vec2",
"x": 0.5, "x": 0.5,
"y": 0.5 "y": 0.5
}, },
"_quat": {
"__type__": "cc.Quat",
"x": 0,
"y": 0,
"z": 0,
"w": 1
},
"_skewX": 0,
"_skewY": 0,
"groupIndex": 0,
"_id": "",
"_trs": { "_trs": {
"__type__": "TypedArray", "__type__": "TypedArray",
"ctor": "Float64Array", "ctor": "Float64Array",
"array": [ "array": [
-16, 0,
0, 0,
0, 0,
0, 0,
@@ -150,7 +139,19 @@
1, 1,
1 1
] ]
} },
"_eulerAngles": {
"__type__": "cc.Vec3",
"x": 0,
"y": 0,
"z": 0
},
"_skewX": 0,
"_skewY": 0,
"_is3DNode": false,
"_groupIndex": 0,
"groupIndex": 0,
"_id": ""
}, },
{ {
"__type__": "cc.Sprite", "__type__": "cc.Sprite",
@@ -160,11 +161,18 @@
"__id__": 2 "__id__": 2
}, },
"_enabled": true, "_enabled": true,
"_materials": [
{
"__uuid__": "eca5d2f2-8ef6-41c2-bbe6-f9c79d09c432"
}
],
"_srcBlendFactor": 770,
"_dstBlendFactor": 771,
"_spriteFrame": { "_spriteFrame": {
"__uuid__": "1a2d934e-9d6d-45bf-83c6-564586cc8400" "__uuid__": "637f31c2-c53e-4dec-ae11-d56c0c6177ad"
}, },
"_type": 0, "_type": 0,
"_sizeMode": 1, "_sizeMode": 0,
"_fillType": 0, "_fillType": 0,
"_fillCenter": { "_fillCenter": {
"__type__": "cc.Vec2", "__type__": "cc.Vec2",
@@ -174,12 +182,9 @@
"_fillStart": 0, "_fillStart": 0,
"_fillRange": 0, "_fillRange": 0,
"_isTrimmedMode": true, "_isTrimmedMode": true,
"_state": 0,
"_atlas": { "_atlas": {
"__uuid__": "030d9286-e8a2-40cf-98f8-baf713f0b8c4" "__uuid__": "030d9286-e8a2-40cf-98f8-baf713f0b8c4"
}, },
"_srcBlendFactor": 770,
"_dstBlendFactor": 771,
"_id": "" "_id": ""
}, },
{ {
@@ -190,7 +195,7 @@
"asset": { "asset": {
"__uuid__": "230eeb1f-e0f9-4a41-ab6c-05b3771cbf3e" "__uuid__": "230eeb1f-e0f9-4a41-ab6c-05b3771cbf3e"
}, },
"fileId": "50Mjaee6xFXLrZ/mSBD3P5", "fileId": "83iQr+5XNNF5E2qjV+WUp0",
"sync": false "sync": false
}, },
{ {
@@ -202,7 +207,6 @@
}, },
"_children": [], "_children": [],
"_active": true, "_active": true,
"_level": 3,
"_components": [ "_components": [
{ {
"__id__": 6 "__id__": 6
@@ -229,17 +233,6 @@
"x": 0.5, "x": 0.5,
"y": 0.5 "y": 0.5
}, },
"_quat": {
"__type__": "cc.Quat",
"x": 0,
"y": 0,
"z": 0,
"w": 1
},
"_skewX": 0,
"_skewY": 0,
"groupIndex": 0,
"_id": "",
"_trs": { "_trs": {
"__type__": "TypedArray", "__type__": "TypedArray",
"ctor": "Float64Array", "ctor": "Float64Array",
@@ -255,7 +248,19 @@
1, 1,
1 1
] ]
} },
"_eulerAngles": {
"__type__": "cc.Vec3",
"x": 0,
"y": 0,
"z": 0
},
"_skewX": 0,
"_skewY": 0,
"_is3DNode": false,
"_groupIndex": 0,
"groupIndex": 0,
"_id": ""
}, },
{ {
"__type__": "cc.Sprite", "__type__": "cc.Sprite",
@@ -265,6 +270,13 @@
"__id__": 5 "__id__": 5
}, },
"_enabled": true, "_enabled": true,
"_materials": [
{
"__uuid__": "eca5d2f2-8ef6-41c2-bbe6-f9c79d09c432"
}
],
"_srcBlendFactor": 770,
"_dstBlendFactor": 771,
"_spriteFrame": { "_spriteFrame": {
"__uuid__": "75a2c1e3-2c22-480c-9572-eb65f4a554e1" "__uuid__": "75a2c1e3-2c22-480c-9572-eb65f4a554e1"
}, },
@@ -279,12 +291,9 @@
"_fillStart": 0, "_fillStart": 0,
"_fillRange": 0, "_fillRange": 0,
"_isTrimmedMode": true, "_isTrimmedMode": true,
"_state": 0,
"_atlas": { "_atlas": {
"__uuid__": "030d9286-e8a2-40cf-98f8-baf713f0b8c4" "__uuid__": "030d9286-e8a2-40cf-98f8-baf713f0b8c4"
}, },
"_srcBlendFactor": 770,
"_dstBlendFactor": 771,
"_id": "" "_id": ""
}, },
{ {
@@ -307,7 +316,6 @@
}, },
"_children": [], "_children": [],
"_active": true, "_active": true,
"_level": 2,
"_components": [ "_components": [
{ {
"__id__": 9 "__id__": 9
@@ -327,24 +335,13 @@
"_contentSize": { "_contentSize": {
"__type__": "cc.Size", "__type__": "cc.Size",
"width": 111.23, "width": 111.23,
"height": 200 "height": 252
}, },
"_anchorPoint": { "_anchorPoint": {
"__type__": "cc.Vec2", "__type__": "cc.Vec2",
"x": 0.5, "x": 0.5,
"y": 0.5 "y": 0.5
}, },
"_quat": {
"__type__": "cc.Quat",
"x": 0,
"y": 0,
"z": 0,
"w": 1
},
"_skewX": 0,
"_skewY": 0,
"groupIndex": 0,
"_id": "",
"_trs": { "_trs": {
"__type__": "TypedArray", "__type__": "TypedArray",
"ctor": "Float64Array", "ctor": "Float64Array",
@@ -360,7 +357,19 @@
0.66667, 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": ""
}, },
{ {
"__type__": "cc.Label", "__type__": "cc.Label",
@@ -370,6 +379,11 @@
"__id__": 8 "__id__": 8
}, },
"_enabled": true, "_enabled": true,
"_materials": [
{
"__uuid__": "eca5d2f2-8ef6-41c2-bbe6-f9c79d09c432"
}
],
"_useOriginalSize": false, "_useOriginalSize": false,
"_string": "3", "_string": "3",
"_N$string": "3", "_N$string": "3",
@@ -407,7 +421,6 @@
}, },
"_children": [], "_children": [],
"_active": true, "_active": true,
"_level": 2,
"_components": [ "_components": [
{ {
"__id__": 12 "__id__": 12
@@ -434,17 +447,6 @@
"x": 0.5, "x": 0.5,
"y": 0.5 "y": 0.5
}, },
"_quat": {
"__type__": "cc.Quat",
"x": 0,
"y": 0,
"z": 0,
"w": 1
},
"_skewX": 0,
"_skewY": 0,
"groupIndex": 0,
"_id": "",
"_trs": { "_trs": {
"__type__": "TypedArray", "__type__": "TypedArray",
"ctor": "Float64Array", "ctor": "Float64Array",
@@ -460,7 +462,19 @@
1, 1,
1 1
] ]
} },
"_eulerAngles": {
"__type__": "cc.Vec3",
"x": 0,
"y": 0,
"z": 0
},
"_skewX": 0,
"_skewY": 0,
"_is3DNode": false,
"_groupIndex": 0,
"groupIndex": 0,
"_id": ""
}, },
{ {
"__type__": "cc.Sprite", "__type__": "cc.Sprite",
@@ -470,6 +484,13 @@
"__id__": 11 "__id__": 11
}, },
"_enabled": true, "_enabled": true,
"_materials": [
{
"__uuid__": "eca5d2f2-8ef6-41c2-bbe6-f9c79d09c432"
}
],
"_srcBlendFactor": 770,
"_dstBlendFactor": 771,
"_spriteFrame": { "_spriteFrame": {
"__uuid__": "637f31c2-c53e-4dec-ae11-d56c0c6177ad" "__uuid__": "637f31c2-c53e-4dec-ae11-d56c0c6177ad"
}, },
@@ -484,12 +505,9 @@
"_fillStart": 0, "_fillStart": 0,
"_fillRange": 0, "_fillRange": 0,
"_isTrimmedMode": true, "_isTrimmedMode": true,
"_state": 0,
"_atlas": { "_atlas": {
"__uuid__": "030d9286-e8a2-40cf-98f8-baf713f0b8c4" "__uuid__": "030d9286-e8a2-40cf-98f8-baf713f0b8c4"
}, },
"_srcBlendFactor": 770,
"_dstBlendFactor": 771,
"_id": "" "_id": ""
}, },
{ {
@@ -503,6 +521,115 @@
"fileId": "21dxpL7zlKIIDhUt+GIMbg", "fileId": "21dxpL7zlKIIDhUt+GIMbg",
"sync": false "sync": false
}, },
{
"__type__": "cc.Node",
"_name": "WhiteStars",
"_objFlags": 0,
"_parent": {
"__id__": 1
},
"_children": [],
"_active": true,
"_components": [
{
"__id__": 15
}
],
"_prefab": {
"__id__": 16
},
"_opacity": 255,
"_color": {
"__type__": "cc.Color",
"r": 255,
"g": 255,
"b": 255,
"a": 255
},
"_contentSize": {
"__type__": "cc.Size",
"width": 268,
"height": 112
},
"_anchorPoint": {
"__type__": "cc.Vec2",
"x": 0.5,
"y": 0.5
},
"_trs": {
"__type__": "TypedArray",
"ctor": "Float64Array",
"array": [
-16,
0,
0,
0,
0,
0,
1,
1,
1,
1
]
},
"_eulerAngles": {
"__type__": "cc.Vec3",
"x": 0,
"y": 0,
"z": 0
},
"_skewX": 0,
"_skewY": 0,
"_is3DNode": false,
"_groupIndex": 0,
"groupIndex": 0,
"_id": ""
},
{
"__type__": "cc.Sprite",
"_name": "",
"_objFlags": 0,
"node": {
"__id__": 14
},
"_enabled": true,
"_materials": [
{
"__uuid__": "eca5d2f2-8ef6-41c2-bbe6-f9c79d09c432"
}
],
"_srcBlendFactor": 770,
"_dstBlendFactor": 771,
"_spriteFrame": {
"__uuid__": "1a2d934e-9d6d-45bf-83c6-564586cc8400"
},
"_type": 0,
"_sizeMode": 1,
"_fillType": 0,
"_fillCenter": {
"__type__": "cc.Vec2",
"x": 0,
"y": 0
},
"_fillStart": 0,
"_fillRange": 0,
"_isTrimmedMode": true,
"_atlas": {
"__uuid__": "030d9286-e8a2-40cf-98f8-baf713f0b8c4"
},
"_id": ""
},
{
"__type__": "cc.PrefabInfo",
"root": {
"__id__": 1
},
"asset": {
"__uuid__": "230eeb1f-e0f9-4a41-ab6c-05b3771cbf3e"
},
"fileId": "50Mjaee6xFXLrZ/mSBD3P5",
"sync": false
},
{ {
"__type__": "6a3d6Y6Ki1BiqAVSKIRdwRl", "__type__": "6a3d6Y6Ki1BiqAVSKIRdwRl",
"_name": "", "_name": "",
@@ -516,34 +643,6 @@
}, },
"_id": "" "_id": ""
}, },
{
"__type__": "cc.Sprite",
"_name": "",
"_objFlags": 0,
"node": {
"__id__": 1
},
"_enabled": true,
"_spriteFrame": {
"__uuid__": "334d4f93-b007-49e8-9268-35891d4f4ebb"
},
"_type": 0,
"_sizeMode": 1,
"_fillType": 0,
"_fillCenter": {
"__type__": "cc.Vec2",
"x": 0,
"y": 0
},
"_fillStart": 0,
"_fillRange": 0,
"_isTrimmedMode": true,
"_state": 0,
"_atlas": null,
"_srcBlendFactor": 770,
"_dstBlendFactor": 771,
"_id": ""
},
{ {
"__type__": "cc.PrefabInfo", "__type__": "cc.PrefabInfo",
"root": { "root": {

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
{ {
"ver": "1.2.5", "ver": "1.2.5",
"uuid": "3ed4c7bc-79d0-4075-a563-d5a58ae798f9", "uuid": "dc804c5c-ff76-445e-ac69-52269055c3c5",
"optimizationPolicy": "AUTO", "optimizationPolicy": "AUTO",
"asyncLoadAssets": false, "asyncLoadAssets": false,
"readonly": false, "readonly": false,

View File

@@ -0,0 +1,443 @@
[
{
"__type__": "cc.Prefab",
"_name": "",
"_objFlags": 0,
"_native": "",
"data": {
"__id__": 1
},
"optimizationPolicy": 0,
"asyncLoadAssets": false,
"readonly": false
},
{
"__type__": "cc.Node",
"_name": "Root",
"_objFlags": 0,
"_parent": null,
"_children": [
{
"__id__": 2
}
],
"_active": true,
"_components": [
{
"__id__": 12
}
],
"_prefab": {
"__id__": 13
},
"_opacity": 255,
"_color": {
"__type__": "cc.Color",
"r": 255,
"g": 255,
"b": 255,
"a": 255
},
"_contentSize": {
"__type__": "cc.Size",
"width": 120,
"height": 120
},
"_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": 2,
"groupIndex": 2,
"_id": ""
},
{
"__type__": "cc.Node",
"_name": "animNode",
"_objFlags": 0,
"_parent": {
"__id__": 1
},
"_children": [
{
"__id__": 3
},
{
"__id__": 7
}
],
"_active": true,
"_components": [],
"_prefab": {
"__id__": 11
},
"_opacity": 255,
"_color": {
"__type__": "cc.Color",
"r": 255,
"g": 255,
"b": 255,
"a": 255
},
"_contentSize": {
"__type__": "cc.Size",
"width": 0,
"height": 0
},
"_anchorPoint": {
"__type__": "cc.Vec2",
"x": 0.5,
"y": 0.5
},
"_trs": {
"__type__": "TypedArray",
"ctor": "Float64Array",
"array": [
0,
0,
0,
0,
0,
0,
1,
1,
1,
1
]
},
"_eulerAngles": {
"__type__": "cc.Vec3",
"x": 0,
"y": 0,
"z": 0
},
"_skewX": 0,
"_skewY": 0,
"_is3DNode": false,
"_groupIndex": 0,
"groupIndex": 0,
"_id": ""
},
{
"__type__": "cc.Node",
"_name": "Fireball1",
"_objFlags": 0,
"_parent": {
"__id__": 2
},
"_children": [],
"_active": false,
"_components": [
{
"__id__": 4
},
{
"__id__": 5
}
],
"_prefab": {
"__id__": 6
},
"_opacity": 255,
"_color": {
"__type__": "cc.Color",
"r": 255,
"g": 255,
"b": 255,
"a": 255
},
"_contentSize": {
"__type__": "cc.Size",
"width": 117,
"height": 55
},
"_anchorPoint": {
"__type__": "cc.Vec2",
"x": 0.5,
"y": 0.5
},
"_trs": {
"__type__": "TypedArray",
"ctor": "Float64Array",
"array": [
-32,
0,
0,
0,
0,
0,
1,
1,
1,
1
]
},
"_eulerAngles": {
"__type__": "cc.Vec3",
"x": 0,
"y": 0,
"z": 0
},
"_skewX": 0,
"_skewY": 0,
"_is3DNode": false,
"_groupIndex": 0,
"groupIndex": 0,
"_id": ""
},
{
"__type__": "cc.Sprite",
"_name": "",
"_objFlags": 0,
"node": {
"__id__": 3
},
"_enabled": true,
"_materials": [
{
"__uuid__": "eca5d2f2-8ef6-41c2-bbe6-f9c79d09c432"
}
],
"_srcBlendFactor": 770,
"_dstBlendFactor": 771,
"_spriteFrame": null,
"_type": 0,
"_sizeMode": 1,
"_fillType": 0,
"_fillCenter": {
"__type__": "cc.Vec2",
"x": 0,
"y": 0
},
"_fillStart": 0,
"_fillRange": 0,
"_isTrimmedMode": true,
"_atlas": {
"__uuid__": "6dcd5722-8ef9-47fd-9520-861d2713e274"
},
"_id": ""
},
{
"__type__": "cc.Animation",
"_name": "",
"_objFlags": 0,
"node": {
"__id__": 3
},
"_enabled": true,
"_defaultClip": {
"__uuid__": "ba12416b-eec3-4260-8402-7fc25b125624"
},
"_clips": [
{
"__uuid__": "ba12416b-eec3-4260-8402-7fc25b125624"
},
{
"__uuid__": "7941215a-2b8c-4798-954b-4f1b16d5f6f5"
}
],
"playOnLoad": false,
"_id": ""
},
{
"__type__": "cc.PrefabInfo",
"root": {
"__id__": 1
},
"asset": {
"__uuid__": "d92d4831-cd65-4eb5-90bd-b77021aec35b"
},
"fileId": "5f1s6pDt5F3rknJTu0gQW7",
"sync": false
},
{
"__type__": "cc.Node",
"_name": "MeleeExplosion",
"_objFlags": 0,
"_parent": {
"__id__": 2
},
"_children": [],
"_active": false,
"_components": [
{
"__id__": 8
},
{
"__id__": 9
}
],
"_prefab": {
"__id__": 10
},
"_opacity": 255,
"_color": {
"__type__": "cc.Color",
"r": 255,
"g": 255,
"b": 255,
"a": 255
},
"_contentSize": {
"__type__": "cc.Size",
"width": 0,
"height": 0
},
"_anchorPoint": {
"__type__": "cc.Vec2",
"x": 0.5,
"y": 0.5
},
"_trs": {
"__type__": "TypedArray",
"ctor": "Float64Array",
"array": [
24,
8,
0,
0,
0,
0,
1,
1,
1,
1
]
},
"_eulerAngles": {
"__type__": "cc.Vec3",
"x": 0,
"y": 0,
"z": 0
},
"_skewX": 0,
"_skewY": 0,
"_is3DNode": false,
"_groupIndex": 0,
"groupIndex": 0,
"_id": ""
},
{
"__type__": "cc.Animation",
"_name": "",
"_objFlags": 0,
"node": {
"__id__": 7
},
"_enabled": true,
"_defaultClip": null,
"_clips": [
{
"__uuid__": "954a2924-89df-4df4-93fc-36d2b22e7619"
},
{
"__uuid__": "5bd304eb-c8ba-426f-a9ab-5698ac62de85"
},
{
"__uuid__": "5054633c-a588-4506-b4ac-eef29b1d8511"
}
],
"playOnLoad": false,
"_id": ""
},
{
"__type__": "cc.Sprite",
"_name": "",
"_objFlags": 0,
"node": {
"__id__": 7
},
"_enabled": true,
"_materials": [],
"_srcBlendFactor": 770,
"_dstBlendFactor": 771,
"_spriteFrame": null,
"_type": 0,
"_sizeMode": 1,
"_fillType": 0,
"_fillCenter": {
"__type__": "cc.Vec2",
"x": 0,
"y": 0
},
"_fillStart": 0,
"_fillRange": 0,
"_isTrimmedMode": true,
"_atlas": {
"__uuid__": "1c4c1dcb-54af-485b-9119-abd6d6d84526"
},
"_id": ""
},
{
"__type__": "cc.PrefabInfo",
"root": {
"__id__": 1
},
"asset": {
"__uuid__": "d92d4831-cd65-4eb5-90bd-b77021aec35b"
},
"fileId": "fd9jQiClRJSI00917fifB8",
"sync": false
},
{
"__type__": "cc.PrefabInfo",
"root": {
"__id__": 1
},
"asset": {
"__uuid__": "d92d4831-cd65-4eb5-90bd-b77021aec35b"
},
"fileId": "3824oBeVVL1KOAQ6Zd9CC5",
"sync": false
},
{
"__type__": "e66a2qRmRZGnqSyVMwLy6Pw",
"_name": "",
"_objFlags": 0,
"node": {
"__id__": 1
},
"_enabled": true,
"animNode": {
"__id__": 2
},
"_id": ""
},
{
"__type__": "cc.PrefabInfo",
"root": {
"__id__": 1
},
"asset": {
"__uuid__": "d92d4831-cd65-4eb5-90bd-b77021aec35b"
},
"fileId": "4cx75uwJJFa7U8QL187QCL",
"sync": false
}
]

View File

@@ -0,0 +1,8 @@
{
"ver": "1.2.5",
"uuid": "d92d4831-cd65-4eb5-90bd-b77021aec35b",
"optimizationPolicy": "AUTO",
"asyncLoadAssets": false,
"readonly": false,
"subMetas": {}
}

View File

@@ -21,20 +21,20 @@
"__id__": 2 "__id__": 2
}, },
{ {
"__id__": 10 "__id__": 5
} }
], ],
"_active": true, "_active": true,
"_components": [ "_components": [
{ {
"__id__": 13 "__id__": 12
}, },
{ {
"__id__": 14 "__id__": 13
} }
], ],
"_prefab": { "_prefab": {
"__id__": 15 "__id__": 14
}, },
"_opacity": 255, "_opacity": 255,
"_color": { "_color": {
@@ -46,8 +46,72 @@
}, },
"_contentSize": { "_contentSize": {
"__type__": "cc.Size", "__type__": "cc.Size",
"width": 1024, "width": 960,
"height": 1920 "height": 640
},
"_anchorPoint": {
"__type__": "cc.Vec2",
"x": 0.5,
"y": 0.5
},
"_trs": {
"__type__": "TypedArray",
"ctor": "Float64Array",
"array": [
480,
320,
0,
0,
0,
0,
1,
1,
1,
1
]
},
"_eulerAngles": {
"__type__": "cc.Vec3",
"x": 0,
"y": 0,
"z": 0
},
"_skewX": 0,
"_skewY": 0,
"_is3DNode": false,
"_groupIndex": 0,
"groupIndex": 0,
"_id": ""
},
{
"__type__": "cc.Node",
"_name": "Background",
"_objFlags": 0,
"_parent": {
"__id__": 1
},
"_children": [],
"_active": true,
"_components": [
{
"__id__": 3
}
],
"_prefab": {
"__id__": 4
},
"_opacity": 255,
"_color": {
"__type__": "cc.Color",
"r": 255,
"g": 255,
"b": 255,
"a": 255
},
"_contentSize": {
"__type__": "cc.Size",
"width": 1920,
"height": 1280
}, },
"_anchorPoint": { "_anchorPoint": {
"__type__": "cc.Vec2", "__type__": "cc.Vec2",
@@ -83,6 +147,51 @@
"groupIndex": 0, "groupIndex": 0,
"_id": "" "_id": ""
}, },
{
"__type__": "cc.Sprite",
"_name": "",
"_objFlags": 0,
"node": {
"__id__": 2
},
"_enabled": true,
"_materials": [
{
"__uuid__": "eca5d2f2-8ef6-41c2-bbe6-f9c79d09c432"
}
],
"_srcBlendFactor": 770,
"_dstBlendFactor": 771,
"_spriteFrame": {
"__uuid__": "637f31c2-c53e-4dec-ae11-d56c0c6177ad"
},
"_type": 0,
"_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": ""
},
{
"__type__": "cc.PrefabInfo",
"root": {
"__id__": 1
},
"asset": {
"__uuid__": "32b8e752-8362-4783-a4a6-1160af8b7109"
},
"fileId": "a7oR1cZvVO/pp9QJgLnJyt",
"sync": false
},
{ {
"__type__": "cc.Node", "__type__": "cc.Node",
"_name": "modeButton", "_name": "modeButton",
@@ -92,20 +201,20 @@
}, },
"_children": [ "_children": [
{ {
"__id__": 3 "__id__": 6
} }
], ],
"_active": true, "_active": true,
"_components": [ "_components": [
{ {
"__id__": 7 "__id__": 9
}, },
{ {
"__id__": 8 "__id__": 10
} }
], ],
"_prefab": { "_prefab": {
"__id__": 9 "__id__": 11
}, },
"_opacity": 255, "_opacity": 255,
"_color": { "_color": {
@@ -117,8 +226,8 @@
}, },
"_contentSize": { "_contentSize": {
"__type__": "cc.Size", "__type__": "cc.Size",
"width": 280, "width": 240,
"height": 130 "height": 100
}, },
"_anchorPoint": { "_anchorPoint": {
"__type__": "cc.Vec2", "__type__": "cc.Vec2",
@@ -130,7 +239,7 @@
"ctor": "Float64Array", "ctor": "Float64Array",
"array": [ "array": [
0, 0,
-564, -90.495,
0, 0,
0, 0,
0, 0,
@@ -159,20 +268,17 @@
"_name": "Label", "_name": "Label",
"_objFlags": 0, "_objFlags": 0,
"_parent": { "_parent": {
"__id__": 2 "__id__": 5
}, },
"_children": [], "_children": [],
"_active": true, "_active": true,
"_components": [ "_components": [
{ {
"__id__": 4 "__id__": 7
},
{
"__id__": 5
} }
], ],
"_prefab": { "_prefab": {
"__id__": 6 "__id__": 8
}, },
"_opacity": 255, "_opacity": 255,
"_color": { "_color": {
@@ -226,7 +332,7 @@
"_name": "", "_name": "",
"_objFlags": 0, "_objFlags": 0,
"node": { "node": {
"__id__": 3 "__id__": 6
}, },
"_enabled": true, "_enabled": true,
"_materials": [ "_materials": [
@@ -235,8 +341,8 @@
} }
], ],
"_useOriginalSize": false, "_useOriginalSize": false,
"_string": "gameRule.mode", "_string": "1 v 1",
"_N$string": "gameRule.mode", "_N$string": "1 v 1",
"_fontSize": 55, "_fontSize": 55,
"_lineHeight": 50, "_lineHeight": 50,
"_enableWrapText": false, "_enableWrapText": false,
@@ -251,17 +357,6 @@
"_N$cacheMode": 0, "_N$cacheMode": 0,
"_id": "" "_id": ""
}, },
{
"__type__": "744dcs4DCdNprNhG0xwq6FK",
"_name": "",
"_objFlags": 0,
"node": {
"__id__": 3
},
"_enabled": true,
"_dataID": "gameRule.mode",
"_id": ""
},
{ {
"__type__": "cc.PrefabInfo", "__type__": "cc.PrefabInfo",
"root": { "root": {
@@ -278,7 +373,7 @@
"_name": "", "_name": "",
"_objFlags": 0, "_objFlags": 0,
"node": { "node": {
"__id__": 2 "__id__": 5
}, },
"_enabled": true, "_enabled": true,
"_materials": [ "_materials": [
@@ -312,7 +407,7 @@
"_name": "", "_name": "",
"_objFlags": 0, "_objFlags": 0,
"node": { "node": {
"__id__": 2 "__id__": 5
}, },
"_enabled": true, "_enabled": true,
"_normalMaterial": null, "_normalMaterial": null,
@@ -375,7 +470,7 @@
"hoverSprite": null, "hoverSprite": null,
"_N$disabledSprite": null, "_N$disabledSprite": null,
"_N$target": { "_N$target": {
"__id__": 2 "__id__": 5
}, },
"_id": "" "_id": ""
}, },
@@ -390,115 +485,6 @@
"fileId": "c54lqSflFD8ogSYAhsAkKh", "fileId": "c54lqSflFD8ogSYAhsAkKh",
"sync": false "sync": false
}, },
{
"__type__": "cc.Node",
"_name": "decoration",
"_objFlags": 0,
"_parent": {
"__id__": 1
},
"_children": [],
"_active": true,
"_components": [
{
"__id__": 11
}
],
"_prefab": {
"__id__": 12
},
"_opacity": 255,
"_color": {
"__type__": "cc.Color",
"r": 255,
"g": 255,
"b": 255,
"a": 255
},
"_contentSize": {
"__type__": "cc.Size",
"width": 543,
"height": 117
},
"_anchorPoint": {
"__type__": "cc.Vec2",
"x": 0.5,
"y": 0.5
},
"_trs": {
"__type__": "TypedArray",
"ctor": "Float64Array",
"array": [
0,
-312,
0,
0,
0,
0,
1,
1,
1,
1
]
},
"_eulerAngles": {
"__type__": "cc.Vec3",
"x": 0,
"y": 0,
"z": 0
},
"_skewX": 0,
"_skewY": 0,
"_is3DNode": false,
"_groupIndex": 0,
"groupIndex": 0,
"_id": ""
},
{
"__type__": "cc.Sprite",
"_name": "",
"_objFlags": 0,
"node": {
"__id__": 10
},
"_enabled": true,
"_materials": [
{
"__uuid__": "eca5d2f2-8ef6-41c2-bbe6-f9c79d09c432"
}
],
"_srcBlendFactor": 770,
"_dstBlendFactor": 771,
"_spriteFrame": {
"__uuid__": "153d890a-fc37-4d59-8779-93a8fb19fa85"
},
"_type": 0,
"_sizeMode": 1,
"_fillType": 0,
"_fillCenter": {
"__type__": "cc.Vec2",
"x": 0,
"y": 0
},
"_fillStart": 0,
"_fillRange": 0,
"_isTrimmedMode": true,
"_atlas": {
"__uuid__": "030d9286-e8a2-40cf-98f8-baf713f0b8c4"
},
"_id": ""
},
{
"__type__": "cc.PrefabInfo",
"root": {
"__id__": 1
},
"asset": {
"__uuid__": "32b8e752-8362-4783-a4a6-1160af8b7109"
},
"fileId": "1bbMLAzntHZpEudL8lM/Lx",
"sync": false
},
{ {
"__type__": "dd92bKVy8FJY7uq3ieoNZCZ", "__type__": "dd92bKVy8FJY7uq3ieoNZCZ",
"_name": "", "_name": "",
@@ -508,41 +494,36 @@
}, },
"_enabled": true, "_enabled": true,
"modeButton": { "modeButton": {
"__id__": 8 "__id__": 10
}, },
"mapNode": null, "mapNode": null,
"_id": "" "_id": ""
}, },
{ {
"__type__": "cc.Sprite", "__type__": "cc.Widget",
"_name": "", "_name": "",
"_objFlags": 0, "_objFlags": 0,
"node": { "node": {
"__id__": 1 "__id__": 1
}, },
"_enabled": true, "_enabled": true,
"_materials": [ "alignMode": 1,
{ "_target": null,
"__uuid__": "eca5d2f2-8ef6-41c2-bbe6-f9c79d09c432" "_alignFlags": 18,
} "_left": 0,
], "_right": 0,
"_srcBlendFactor": 770, "_top": 0,
"_dstBlendFactor": 771, "_bottom": 0,
"_spriteFrame": { "_verticalCenter": 0,
"__uuid__": "7838f276-ab48-445a-b858-937dd27d9520" "_horizontalCenter": 0,
}, "_isAbsLeft": true,
"_type": 0, "_isAbsRight": true,
"_sizeMode": 0, "_isAbsTop": true,
"_fillType": 0, "_isAbsBottom": true,
"_fillCenter": { "_isAbsHorizontalCenter": true,
"__type__": "cc.Vec2", "_isAbsVerticalCenter": true,
"x": 0, "_originalWidth": 0,
"y": 0 "_originalHeight": 0,
},
"_fillStart": 0,
"_fillRange": 0,
"_isTrimmedMode": true,
"_atlas": null,
"_id": "" "_id": ""
}, },
{ {

View File

@@ -8,7 +8,8 @@
"__id__": 1 "__id__": 1
}, },
"optimizationPolicy": 0, "optimizationPolicy": 0,
"asyncLoadAssets": false "asyncLoadAssets": false,
"readonly": false
}, },
{ {
"__type__": "cc.Node", "__type__": "cc.Node",
@@ -20,18 +21,17 @@
"__id__": 2 "__id__": 2
}, },
{ {
"__id__": 6 "__id__": 5
} }
], ],
"_active": true, "_active": true,
"_level": 1,
"_components": [ "_components": [
{ {
"__id__": 9 "__id__": 8
} }
], ],
"_prefab": { "_prefab": {
"__id__": 10 "__id__": 9
}, },
"_opacity": 255, "_opacity": 255,
"_color": { "_color": {
@@ -51,24 +51,12 @@
"x": 0.5, "x": 0.5,
"y": 0.5 "y": 0.5
}, },
"_quat": {
"__type__": "cc.Quat",
"x": 0,
"y": 0,
"z": 0,
"w": 1
},
"_skewX": 0,
"_skewY": 0,
"_zIndex": 0,
"groupIndex": 0,
"_id": "",
"_trs": { "_trs": {
"__type__": "TypedArray", "__type__": "TypedArray",
"ctor": "Float64Array", "ctor": "Float64Array",
"array": [ "array": [
512, 480,
0, 480,
0, 0,
0, 0,
0, 0,
@@ -78,7 +66,19 @@
1, 1,
1 1
] ]
} },
"_eulerAngles": {
"__type__": "cc.Vec3",
"x": 0,
"y": 0,
"z": 0
},
"_skewX": 0,
"_skewY": 0,
"_is3DNode": false,
"_groupIndex": 0,
"groupIndex": 0,
"_id": ""
}, },
{ {
"__type__": "cc.Node", "__type__": "cc.Node",
@@ -89,17 +89,13 @@
}, },
"_children": [], "_children": [],
"_active": true, "_active": true,
"_level": 0,
"_components": [ "_components": [
{ {
"__id__": 3 "__id__": 3
},
{
"__id__": 4
} }
], ],
"_prefab": { "_prefab": {
"__id__": 5 "__id__": 4
}, },
"_opacity": 255, "_opacity": 255,
"_color": { "_color": {
@@ -111,32 +107,20 @@
}, },
"_contentSize": { "_contentSize": {
"__type__": "cc.Size", "__type__": "cc.Size",
"width": 303.5, "width": 805.7,
"height": 30 "height": 35.28
}, },
"_anchorPoint": { "_anchorPoint": {
"__type__": "cc.Vec2", "__type__": "cc.Vec2",
"x": 0.5, "x": 0.5,
"y": 0.5 "y": 0.5
}, },
"_quat": {
"__type__": "cc.Quat",
"x": 0,
"y": 0,
"z": 0,
"w": 1
},
"_skewX": 0,
"_skewY": 0,
"_zIndex": 0,
"groupIndex": 0,
"_id": "",
"_trs": { "_trs": {
"__type__": "TypedArray", "__type__": "TypedArray",
"ctor": "Float64Array", "ctor": "Float64Array",
"array": [ "array": [
0, 0,
210, -150,
0, 0,
0, 0,
0, 0,
@@ -146,7 +130,19 @@
1, 1,
1 1
] ]
} },
"_eulerAngles": {
"__type__": "cc.Vec3",
"x": 0,
"y": 0,
"z": 0
},
"_skewX": 0,
"_skewY": 0,
"_is3DNode": false,
"_groupIndex": 0,
"groupIndex": 0,
"_id": ""
}, },
{ {
"__type__": "cc.Label", "__type__": "cc.Label",
@@ -156,32 +152,26 @@
"__id__": 2 "__id__": 2
}, },
"_enabled": true, "_enabled": true,
"_srcBlendFactor": 1, "_materials": [
"_dstBlendFactor": 771, {
"__uuid__": "eca5d2f2-8ef6-41c2-bbe6-f9c79d09c432"
}
],
"_useOriginalSize": false, "_useOriginalSize": false,
"_string": "login.tips.loginSuccess", "_string": "Logged in successfully, loading game resources...",
"_N$string": "login.tips.loginSuccess", "_N$string": "Logged in successfully, loading game resources...",
"_fontSize": 30, "_fontSize": 28,
"_lineHeight": 30, "_lineHeight": 28,
"_enableWrapText": true, "_enableWrapText": true,
"_N$file": null, "_N$file": null,
"_isSystemFontUsed": true, "_isSystemFontUsed": true,
"_spacingX": 0, "_spacingX": 0,
"_batchAsBitmap": false,
"_N$horizontalAlign": 1, "_N$horizontalAlign": 1,
"_N$verticalAlign": 1, "_N$verticalAlign": 1,
"_N$fontFamily": "Arial", "_N$fontFamily": "Arial",
"_N$overflow": 0, "_N$overflow": 3,
"_id": "" "_N$cacheMode": 0,
},
{
"__type__": "744dcs4DCdNprNhG0xwq6FK",
"_name": "",
"_objFlags": 0,
"node": {
"__id__": 2
},
"_enabled": true,
"_dataID": "login.tips.loginSuccess",
"_id": "" "_id": ""
}, },
{ {
@@ -204,14 +194,13 @@
}, },
"_children": [], "_children": [],
"_active": true, "_active": true,
"_level": 0,
"_components": [ "_components": [
{ {
"__id__": 7 "__id__": 6
} }
], ],
"_prefab": { "_prefab": {
"__id__": 8 "__id__": 7
}, },
"_opacity": 255, "_opacity": 255,
"_color": { "_color": {
@@ -231,24 +220,12 @@
"x": 0.5, "x": 0.5,
"y": 0.5 "y": 0.5
}, },
"_quat": {
"__type__": "cc.Quat",
"x": 0,
"y": 0,
"z": 0,
"w": 1
},
"_skewX": 0,
"_skewY": 0,
"_zIndex": 0,
"groupIndex": 0,
"_id": "",
"_trs": { "_trs": {
"__type__": "TypedArray", "__type__": "TypedArray",
"ctor": "Float64Array", "ctor": "Float64Array",
"array": [ "array": [
0, 0,
333, 0,
0, 0,
0, 0,
0, 0,
@@ -258,16 +235,29 @@
1, 1,
1 1
] ]
} },
"_eulerAngles": {
"__type__": "cc.Vec3",
"x": 0,
"y": 0,
"z": 0
},
"_skewX": 0,
"_skewY": 0,
"_is3DNode": false,
"_groupIndex": 0,
"groupIndex": 0,
"_id": ""
}, },
{ {
"__type__": "cc.Sprite", "__type__": "cc.Sprite",
"_name": "", "_name": "",
"_objFlags": 0, "_objFlags": 0,
"node": { "node": {
"__id__": 6 "__id__": 5
}, },
"_enabled": true, "_enabled": true,
"_materials": [],
"_srcBlendFactor": 770, "_srcBlendFactor": 770,
"_dstBlendFactor": 771, "_dstBlendFactor": 771,
"_spriteFrame": null, "_spriteFrame": null,
@@ -282,7 +272,6 @@
"_fillStart": 0, "_fillStart": 0,
"_fillRange": 0, "_fillRange": 0,
"_isTrimmedMode": true, "_isTrimmedMode": true,
"_state": 0,
"_atlas": null, "_atlas": null,
"_id": "" "_id": ""
}, },
@@ -307,7 +296,7 @@
"_enabled": true, "_enabled": true,
"alignMode": 0, "alignMode": 0,
"_target": null, "_target": null,
"_alignFlags": 20, "_alignFlags": 18,
"_left": 0, "_left": 0,
"_right": 0, "_right": 0,
"_top": 0, "_top": 0,

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 121 KiB

View File

@@ -1,34 +0,0 @@
{
"ver": "2.3.3",
"uuid": "825df908-a4cb-449d-9731-8ef53f3fd44f",
"type": "sprite",
"wrapMode": "clamp",
"filterMode": "bilinear",
"premultiplyAlpha": false,
"genMipmaps": false,
"packable": true,
"platformSettings": {},
"subMetas": {
"MiniGame_Background": {
"ver": "1.0.4",
"uuid": "7838f276-ab48-445a-b858-937dd27d9520",
"rawTextureUuid": "825df908-a4cb-449d-9731-8ef53f3fd44f",
"trimType": "auto",
"trimThreshold": 1,
"rotated": false,
"offsetX": 0,
"offsetY": 0,
"trimX": 0,
"trimY": 0,
"width": 750,
"height": 1624,
"rawWidth": 750,
"rawHeight": 1624,
"borderTop": 0,
"borderBottom": 0,
"borderLeft": 0,
"borderRight": 0,
"subMetas": {}
}
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 95 KiB

View File

@@ -1,34 +0,0 @@
{
"ver": "2.3.3",
"uuid": "94b8bb09-e8ac-4402-a933-b79f01b5a813",
"type": "sprite",
"wrapMode": "clamp",
"filterMode": "bilinear",
"premultiplyAlpha": false,
"genMipmaps": false,
"packable": true,
"platformSettings": {},
"subMetas": {
"MiniGame_Blackboard": {
"ver": "1.0.4",
"uuid": "334d4f93-b007-49e8-9268-35891d4f4ebb",
"rawTextureUuid": "94b8bb09-e8ac-4402-a933-b79f01b5a813",
"trimType": "auto",
"trimThreshold": 1,
"rotated": false,
"offsetX": 0,
"offsetY": 0,
"trimX": 0,
"trimY": 0,
"width": 1024,
"height": 1920,
"rawWidth": 1024,
"rawHeight": 1920,
"borderTop": 0,
"borderBottom": 0,
"borderLeft": 0,
"borderRight": 0,
"subMetas": {}
}
}
}

View File

@@ -72,25 +72,25 @@
"__id__": 3 "__id__": 3
}, },
{ {
"__id__": 8 "__id__": 9
} }
], ],
"_active": true, "_active": true,
"_components": [ "_components": [
{
"__id__": 37
},
{
"__id__": 38
},
{
"__id__": 39
},
{ {
"__id__": 40 "__id__": 40
}, },
{ {
"__id__": 41 "__id__": 41
},
{
"__id__": 42
},
{
"__id__": 43
},
{
"__id__": 44
} }
], ],
"_prefab": null, "_prefab": null,
@@ -104,8 +104,8 @@
}, },
"_contentSize": { "_contentSize": {
"__type__": "cc.Size", "__type__": "cc.Size",
"width": 1024, "width": 960,
"height": 1920 "height": 640
}, },
"_anchorPoint": { "_anchorPoint": {
"__type__": "cc.Vec2", "__type__": "cc.Vec2",
@@ -116,8 +116,8 @@
"__type__": "TypedArray", "__type__": "TypedArray",
"ctor": "Float64Array", "ctor": "Float64Array",
"array": [ "array": [
512, 480,
960, 320,
0, 0,
0, 0,
0, 0,
@@ -158,7 +158,7 @@
"__id__": 5 "__id__": 5
}, },
{ {
"__id__": 36 "__id__": 39
} }
], ],
"_prefab": null, "_prefab": null,
@@ -172,8 +172,8 @@
}, },
"_contentSize": { "_contentSize": {
"__type__": "cc.Size", "__type__": "cc.Size",
"width": 2048, "width": 960,
"height": 2048 "height": 640
}, },
"_anchorPoint": { "_anchorPoint": {
"__type__": "cc.Vec2", "__type__": "cc.Vec2",
@@ -191,8 +191,8 @@
0, 0,
0, 0,
1, 1,
1.5, 1.2,
1.5, 1.2,
1 1
] ]
}, },
@@ -234,6 +234,9 @@
"controlledCharacterPrefab": { "controlledCharacterPrefab": {
"__uuid__": "59bff7a2-23e1-4d69-bce7-afb37eae196a" "__uuid__": "59bff7a2-23e1-4d69-bce7-afb37eae196a"
}, },
"fireballPrefab": {
"__uuid__": "d92d4831-cd65-4eb5-90bd-b77021aec35b"
},
"joystickInputControllerNode": { "joystickInputControllerNode": {
"__id__": 6 "__id__": 6
}, },
@@ -244,10 +247,10 @@
"__uuid__": "670b477e-61a1-4778-879b-35913f7c79d2" "__uuid__": "670b477e-61a1-4778-879b-35913f7c79d2"
}, },
"boundRoomIdLabel": { "boundRoomIdLabel": {
"__id__": 15 "__id__": 16
}, },
"countdownLabel": { "countdownLabel": {
"__id__": 21 "__id__": 23
}, },
"resultPanelPrefab": { "resultPanelPrefab": {
"__uuid__": "c4cfe3bd-c59e-4d5b-95cb-c933b120e184" "__uuid__": "c4cfe3bd-c59e-4d5b-95cb-c933b120e184"
@@ -256,7 +259,7 @@
"__uuid__": "32b8e752-8362-4783-a4a6-1160af8b7109" "__uuid__": "32b8e752-8362-4783-a4a6-1160af8b7109"
}, },
"findingPlayerPrefab": { "findingPlayerPrefab": {
"__uuid__": "3ed4c7bc-79d0-4075-a563-d5a58ae798f9" "__uuid__": "dc804c5c-ff76-445e-ac69-52269055c3c5"
}, },
"countdownToBeginGamePrefab": { "countdownToBeginGamePrefab": {
"__uuid__": "230eeb1f-e0f9-4a41-ab6c-05b3771cbf3e" "__uuid__": "230eeb1f-e0f9-4a41-ab6c-05b3771cbf3e"
@@ -268,6 +271,7 @@
"renderFrameIdLagTolerance": 4, "renderFrameIdLagTolerance": 4,
"jigglingEps1D": 0.001, "jigglingEps1D": 0.001,
"bulletTriggerEnabled": true, "bulletTriggerEnabled": true,
"closeOnForcedtoResyncNotSelf": true,
"_id": "d12gkAmppNlIzqcRDELa91" "_id": "d12gkAmppNlIzqcRDELa91"
}, },
{ {
@@ -279,13 +283,13 @@
}, },
"_children": [ "_children": [
{ {
"__id__": 30 "__id__": 33
} }
], ],
"_active": true, "_active": true,
"_components": [ "_components": [
{ {
"__id__": 35 "__id__": 38
} }
], ],
"_prefab": null, "_prefab": null,
@@ -311,16 +315,16 @@
"__type__": "TypedArray", "__type__": "TypedArray",
"ctor": "Float64Array", "ctor": "Float64Array",
"array": [ "array": [
0, -199.439,
-500, -172.557,
0, 0,
0, 0,
0, 0,
0, 0,
1, 1,
0.66667, 0.4,
0.66667, 0.4,
0.66667 0.4
] ]
}, },
"_eulerAngles": { "_eulerAngles": {
@@ -338,30 +342,31 @@
}, },
{ {
"__type__": "cc.Node", "__type__": "cc.Node",
"_name": "WidgetsAboveAll", "_name": "Interactive",
"_objFlags": 0, "_objFlags": 0,
"_parent": { "_parent": {
"__id__": 8 "__id__": 8
}, },
"_children": [ "_children": [
{
"__id__": 10
},
{ {
"__id__": 6 "__id__": 6
}, },
{
"__id__": 20
},
{ {
"__id__": 22 "__id__": 22
}, },
{ {
"__id__": 26 "__id__": 24
},
{
"__id__": 28
} }
], ],
"_active": true, "_active": true,
"_components": [], "_components": [
{
"__id__": 32
}
],
"_prefab": null, "_prefab": null,
"_opacity": 255, "_opacity": 255,
"_color": { "_color": {
@@ -408,6 +413,75 @@
"_is3DNode": false, "_is3DNode": false,
"_groupIndex": 0, "_groupIndex": 0,
"groupIndex": 0, "groupIndex": 0,
"_id": "bb5Zj3NPxJgrEYDllBW7Gj"
},
{
"__type__": "cc.Node",
"_name": "WidgetsAboveAll",
"_objFlags": 0,
"_parent": {
"__id__": 9
},
"_children": [
{
"__id__": 11
},
{
"__id__": 7
}
],
"_active": true,
"_components": [
{
"__id__": 21
}
],
"_prefab": null,
"_opacity": 255,
"_color": {
"__type__": "cc.Color",
"r": 255,
"g": 255,
"b": 255,
"a": 255
},
"_contentSize": {
"__type__": "cc.Size",
"width": 1280,
"height": 1280
},
"_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": "c6fPdAUURDX69j0zTeIFZv" "_id": "c6fPdAUURDX69j0zTeIFZv"
}, },
{ {
@@ -419,13 +493,13 @@
}, },
"_children": [ "_children": [
{ {
"__id__": 7 "__id__": 8
} }
], ],
"_active": true, "_active": true,
"_components": [ "_components": [
{ {
"__id__": 9 "__id__": 10
} }
], ],
"_prefab": null, "_prefab": null,
@@ -453,7 +527,7 @@
"array": [ "array": [
0, 0,
0, 0,
215.81269742929726, 209.57814771583418,
0, 0,
0, 0,
0, 0,
@@ -481,7 +555,7 @@
"_name": "", "_name": "",
"_objFlags": 0, "_objFlags": 0,
"node": { "node": {
"__id__": 8 "__id__": 9
}, },
"_enabled": true, "_enabled": true,
"_cullingMask": 4294967295, "_cullingMask": 4294967295,
@@ -517,20 +591,20 @@
"_name": "DebugInfo", "_name": "DebugInfo",
"_objFlags": 0, "_objFlags": 0,
"_parent": { "_parent": {
"__id__": 7 "__id__": 8
}, },
"_children": [ "_children": [
{ {
"__id__": 11 "__id__": 12
} }
], ],
"_active": true, "_active": true,
"_components": [ "_components": [
{ {
"__id__": 18 "__id__": 19
}, },
{ {
"__id__": 19 "__id__": 20
} }
], ],
"_prefab": null, "_prefab": null,
@@ -556,8 +630,8 @@
"__type__": "TypedArray", "__type__": "TypedArray",
"ctor": "Float64Array", "ctor": "Float64Array",
"array": [ "array": [
-478, -447.294,
627, 135.702,
0, 0,
0, 0,
0, 0,
@@ -586,23 +660,23 @@
"_name": "RoomIdIndicator", "_name": "RoomIdIndicator",
"_objFlags": 0, "_objFlags": 0,
"_parent": { "_parent": {
"__id__": 10 "__id__": 11
}, },
"_children": [ "_children": [
{ {
"__id__": 12 "__id__": 13
}, },
{ {
"__id__": 14 "__id__": 15
} }
], ],
"_active": false, "_active": false,
"_components": [ "_components": [
{ {
"__id__": 16 "__id__": 17
}, },
{ {
"__id__": 17 "__id__": 18
} }
], ],
"_prefab": null, "_prefab": null,
@@ -658,13 +732,13 @@
"_name": "label", "_name": "label",
"_objFlags": 0, "_objFlags": 0,
"_parent": { "_parent": {
"__id__": 11 "__id__": 12
}, },
"_children": [], "_children": [],
"_active": true, "_active": true,
"_components": [ "_components": [
{ {
"__id__": 13 "__id__": 14
} }
], ],
"_prefab": null, "_prefab": null,
@@ -720,7 +794,7 @@
"_name": "", "_name": "",
"_objFlags": 0, "_objFlags": 0,
"node": { "node": {
"__id__": 12 "__id__": 13
}, },
"_enabled": true, "_enabled": true,
"_materials": [], "_materials": [],
@@ -748,13 +822,13 @@
"_name": "BoundRoomIdLabel", "_name": "BoundRoomIdLabel",
"_objFlags": 0, "_objFlags": 0,
"_parent": { "_parent": {
"__id__": 11 "__id__": 12
}, },
"_children": [], "_children": [],
"_active": true, "_active": true,
"_components": [ "_components": [
{ {
"__id__": 15 "__id__": 16
} }
], ],
"_prefab": null, "_prefab": null,
@@ -810,7 +884,7 @@
"_name": "", "_name": "",
"_objFlags": 0, "_objFlags": 0,
"node": { "node": {
"__id__": 14 "__id__": 15
}, },
"_enabled": true, "_enabled": true,
"_materials": [], "_materials": [],
@@ -838,7 +912,7 @@
"_name": "", "_name": "",
"_objFlags": 0, "_objFlags": 0,
"node": { "node": {
"__id__": 11 "__id__": 12
}, },
"_enabled": true, "_enabled": true,
"_layoutSize": { "_layoutSize": {
@@ -871,7 +945,7 @@
"_name": "", "_name": "",
"_objFlags": 0, "_objFlags": 0,
"node": { "node": {
"__id__": 11 "__id__": 12
}, },
"_enabled": true, "_enabled": true,
"_materials": [], "_materials": [],
@@ -901,7 +975,7 @@
"_name": "", "_name": "",
"_objFlags": 0, "_objFlags": 0,
"node": { "node": {
"__id__": 10 "__id__": 11
}, },
"_enabled": true, "_enabled": true,
"_materials": [], "_materials": [],
@@ -927,7 +1001,7 @@
"_name": "", "_name": "",
"_objFlags": 0, "_objFlags": 0,
"node": { "node": {
"__id__": 10 "__id__": 11
}, },
"_enabled": true, "_enabled": true,
"_layoutSize": { "_layoutSize": {
@@ -955,6 +1029,33 @@
"_N$affectedByScale": false, "_N$affectedByScale": false,
"_id": "f6GkgYwn9JvKLqbGG1zmeD" "_id": "f6GkgYwn9JvKLqbGG1zmeD"
}, },
{
"__type__": "cc.Widget",
"_name": "",
"_objFlags": 0,
"node": {
"__id__": 8
},
"_enabled": true,
"alignMode": 2,
"_target": null,
"_alignFlags": 18,
"_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": 0,
"_originalHeight": 0,
"_id": "aenJ9ZDDRKDoS7u5MxeZOb"
},
{ {
"__type__": "cc.Node", "__type__": "cc.Node",
"_name": "CountdownSeconds", "_name": "CountdownSeconds",
@@ -966,7 +1067,7 @@
"_active": true, "_active": true,
"_components": [ "_components": [
{ {
"__id__": 21 "__id__": 23
} }
], ],
"_prefab": null, "_prefab": null,
@@ -993,7 +1094,7 @@
"ctor": "Float64Array", "ctor": "Float64Array",
"array": [ "array": [
0, 0,
591, 181.094,
0, 0,
0, 0,
0, 0,
@@ -1022,7 +1123,7 @@
"_name": "", "_name": "",
"_objFlags": 0, "_objFlags": 0,
"node": { "node": {
"__id__": 20 "__id__": 22
}, },
"_enabled": true, "_enabled": true,
"_materials": [ "_materials": [
@@ -1056,7 +1157,7 @@
}, },
"_children": [ "_children": [
{ {
"__id__": 23 "__id__": 25
} }
], ],
"_active": true, "_active": true,
@@ -1084,16 +1185,16 @@
"__type__": "TypedArray", "__type__": "TypedArray",
"ctor": "Float64Array", "ctor": "Float64Array",
"array": [ "array": [
143.689, 178,
-584.849, -179.607,
0, 0,
0, 0,
0, 0,
0, 0,
1, 1,
0.66667, 0.5,
0.66667, 0.5,
0.66667 0.5
] ]
}, },
"_eulerAngles": { "_eulerAngles": {
@@ -1114,16 +1215,16 @@
"_name": "Background", "_name": "Background",
"_objFlags": 0, "_objFlags": 0,
"_parent": { "_parent": {
"__id__": 22 "__id__": 24
}, },
"_children": [], "_children": [],
"_active": true, "_active": true,
"_components": [ "_components": [
{ {
"__id__": 24 "__id__": 26
}, },
{ {
"__id__": 25 "__id__": 27
} }
], ],
"_prefab": null, "_prefab": null,
@@ -1179,7 +1280,7 @@
"_name": "", "_name": "",
"_objFlags": 0, "_objFlags": 0,
"node": { "node": {
"__id__": 23 "__id__": 25
}, },
"_enabled": true, "_enabled": true,
"_materials": [ "_materials": [
@@ -1213,7 +1314,7 @@
"_name": "", "_name": "",
"_objFlags": 0, "_objFlags": 0,
"node": { "node": {
"__id__": 23 "__id__": 25
}, },
"_enabled": true, "_enabled": true,
"alignMode": 0, "alignMode": 0,
@@ -1244,7 +1345,7 @@
}, },
"_children": [ "_children": [
{ {
"__id__": 27 "__id__": 29
} }
], ],
"_active": true, "_active": true,
@@ -1272,16 +1373,16 @@
"__type__": "TypedArray", "__type__": "TypedArray",
"ctor": "Float64Array", "ctor": "Float64Array",
"array": [ "array": [
370.368, 395,
-424.647, -123.879,
0, 0,
0, 0,
0, 0,
0, 0,
1, 1,
0.66667, 0.5,
0.66667, 0.5,
0.66667 0.5
] ]
}, },
"_eulerAngles": { "_eulerAngles": {
@@ -1302,16 +1403,16 @@
"_name": "Background", "_name": "Background",
"_objFlags": 0, "_objFlags": 0,
"_parent": { "_parent": {
"__id__": 26 "__id__": 28
}, },
"_children": [], "_children": [],
"_active": true, "_active": true,
"_components": [ "_components": [
{ {
"__id__": 28 "__id__": 30
}, },
{ {
"__id__": 29 "__id__": 31
} }
], ],
"_prefab": null, "_prefab": null,
@@ -1367,7 +1468,7 @@
"_name": "", "_name": "",
"_objFlags": 0, "_objFlags": 0,
"node": { "node": {
"__id__": 27 "__id__": 29
}, },
"_enabled": true, "_enabled": true,
"_materials": [ "_materials": [
@@ -1401,7 +1502,7 @@
"_name": "", "_name": "",
"_objFlags": 0, "_objFlags": 0,
"node": { "node": {
"__id__": 27 "__id__": 29
}, },
"_enabled": true, "_enabled": true,
"alignMode": 0, "alignMode": 0,
@@ -1423,6 +1524,33 @@
"_originalHeight": 40, "_originalHeight": 40,
"_id": "5bXB50moJH9aH7RcbRuSS5" "_id": "5bXB50moJH9aH7RcbRuSS5"
}, },
{
"__type__": "cc.Widget",
"_name": "",
"_objFlags": 0,
"node": {
"__id__": 7
},
"_enabled": true,
"alignMode": 1,
"_target": null,
"_alignFlags": 20,
"_left": 0,
"_right": 0,
"_top": 0,
"_bottom": 640,
"_verticalCenter": 0,
"_horizontalCenter": 0,
"_isAbsLeft": true,
"_isAbsRight": true,
"_isAbsTop": true,
"_isAbsBottom": true,
"_isAbsHorizontalCenter": true,
"_isAbsVerticalCenter": true,
"_originalWidth": 0,
"_originalHeight": 0,
"_id": "60S5//1JxMULAtkfxKep87"
},
{ {
"__type__": "cc.Node", "__type__": "cc.Node",
"_name": "JoystickBG", "_name": "JoystickBG",
@@ -1432,16 +1560,16 @@
}, },
"_children": [ "_children": [
{ {
"__id__": 31 "__id__": 34
} }
], ],
"_active": true, "_active": true,
"_components": [ "_components": [
{ {
"__id__": 33 "__id__": 36
}, },
{ {
"__id__": 34 "__id__": 37
} }
], ],
"_prefab": null, "_prefab": null,
@@ -1497,13 +1625,13 @@
"_name": "Joystick", "_name": "Joystick",
"_objFlags": 0, "_objFlags": 0,
"_parent": { "_parent": {
"__id__": 30 "__id__": 33
}, },
"_children": [], "_children": [],
"_active": true, "_active": true,
"_components": [ "_components": [
{ {
"__id__": 32 "__id__": 35
} }
], ],
"_prefab": null, "_prefab": null,
@@ -1559,7 +1687,7 @@
"_name": "", "_name": "",
"_objFlags": 0, "_objFlags": 0,
"node": { "node": {
"__id__": 31 "__id__": 34
}, },
"_enabled": true, "_enabled": true,
"_materials": [ "_materials": [
@@ -1593,7 +1721,7 @@
"_name": "", "_name": "",
"_objFlags": 0, "_objFlags": 0,
"node": { "node": {
"__id__": 30 "__id__": 33
}, },
"_enabled": true, "_enabled": true,
"_materials": [ "_materials": [
@@ -1627,7 +1755,7 @@
"_name": "", "_name": "",
"_objFlags": 0, "_objFlags": 0,
"node": { "node": {
"__id__": 30 "__id__": 33
}, },
"_enabled": true, "_enabled": true,
"alignMode": 0, "alignMode": 0,
@@ -1684,21 +1812,11 @@
"__id__": 3 "__id__": 3
}, },
"_enabled": true, "_enabled": true,
"BGMEffect": { "BGMEffect": null,
"__uuid__": "64a79efa-97de-4cb5-b2a9-01500c60573a" "crashedByTrapBullet": null,
}, "highScoreTreasurePicked": null,
"crashedByTrapBullet": { "treasurePicked": null,
"__uuid__": "1d604e42-8cee-466f-884d-e74cae21ce3b" "countDown10SecToEnd": null,
},
"highScoreTreasurePicked": {
"__uuid__": "0164d22c-d965-461f-867e-b30e2d56cc5c"
},
"treasurePicked": {
"__uuid__": "7704b97e-6367-420c-b7af-d0750a2bbb30"
},
"countDown10SecToEnd": {
"__uuid__": "261d1d7d-a5cc-4cb7-a737-194427055fd4"
},
"mapNode": { "mapNode": {
"__id__": 3 "__id__": 3
}, },
@@ -1714,8 +1832,8 @@
"_enabled": true, "_enabled": true,
"_designResolution": { "_designResolution": {
"__type__": "cc.Size", "__type__": "cc.Size",
"width": 1024, "width": 960,
"height": 1920 "height": 640
}, },
"_fitWidth": true, "_fitWidth": true,
"_fitHeight": false, "_fitHeight": false,
@@ -1756,9 +1874,9 @@
"__id__": 2 "__id__": 2
}, },
"_enabled": true, "_enabled": true,
"alignMode": 0, "alignMode": 1,
"_target": null, "_target": null,
"_alignFlags": 0, "_alignFlags": 18,
"_left": 6240, "_left": 6240,
"_right": -4000, "_right": -4000,
"_top": -8320, "_top": -8320,
@@ -1790,10 +1908,10 @@
"__id__": 3 "__id__": 3
}, },
"stickhead": { "stickhead": {
"__id__": 31 "__id__": 34
}, },
"base": { "base": {
"__id__": 30 "__id__": 33
}, },
"joyStickEps": 0.1, "joyStickEps": 0.1,
"magicLeanLowerBound": 0.414, "magicLeanLowerBound": 0.414,
@@ -1814,10 +1932,10 @@
"linearMovingEps": 0.1, "linearMovingEps": 0.1,
"scaleByEps": 0.0375, "scaleByEps": 0.0375,
"btnA": { "btnA": {
"__id__": 22 "__id__": 24
}, },
"btnB": { "btnB": {
"__id__": 26 "__id__": 28
}, },
"_id": "e9oVYTr7ROlpp/IrNjBUmR" "_id": "e9oVYTr7ROlpp/IrNjBUmR"
} }

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -15,6 +15,9 @@ window.ATK_CHARACTER_STATE = {
Atk2: [11, "Atk2"], Atk2: [11, "Atk2"],
Atk3: [12, "Atk3"], Atk3: [12, "Atk3"],
Atk4: [13, "Atk4"], Atk4: [13, "Atk4"],
Atk5: [14, "Atk5"],
Dashing: [15, "Dashing"],
OnWall: [16, "OnWall"],
}; };
window.ATK_CHARACTER_STATE_ARR = []; window.ATK_CHARACTER_STATE_ARR = [];
@@ -30,6 +33,8 @@ window.ATK_CHARACTER_STATE_INTERRUPT_WAIVE_SET.add(window.ATK_CHARACTER_STATE.In
window.ATK_CHARACTER_STATE_INTERRUPT_WAIVE_SET.add(window.ATK_CHARACTER_STATE.BlownUp1[0]); window.ATK_CHARACTER_STATE_INTERRUPT_WAIVE_SET.add(window.ATK_CHARACTER_STATE.BlownUp1[0]);
window.ATK_CHARACTER_STATE_INTERRUPT_WAIVE_SET.add(window.ATK_CHARACTER_STATE.LayDown1[0]); window.ATK_CHARACTER_STATE_INTERRUPT_WAIVE_SET.add(window.ATK_CHARACTER_STATE.LayDown1[0]);
window.ATK_CHARACTER_STATE_INTERRUPT_WAIVE_SET.add(window.ATK_CHARACTER_STATE.GetUp1[0]); window.ATK_CHARACTER_STATE_INTERRUPT_WAIVE_SET.add(window.ATK_CHARACTER_STATE.GetUp1[0]);
window.ATK_CHARACTER_STATE_INTERRUPT_WAIVE_SET.add(window.ATK_CHARACTER_STATE.Dashing[0]);
window.ATK_CHARACTER_STATE_INTERRUPT_WAIVE_SET.add(window.ATK_CHARACTER_STATE.OnWall[0]);
window.ATK_CHARACTER_STATE_IN_AIR_SET = new Set(); window.ATK_CHARACTER_STATE_IN_AIR_SET = new Set();
window.ATK_CHARACTER_STATE_IN_AIR_SET.add(window.ATK_CHARACTER_STATE.InAirIdle1NoJump[0]); window.ATK_CHARACTER_STATE_IN_AIR_SET.add(window.ATK_CHARACTER_STATE.InAirIdle1NoJump[0]);
@@ -37,6 +42,7 @@ window.ATK_CHARACTER_STATE_IN_AIR_SET.add(window.ATK_CHARACTER_STATE.InAirIdle1B
window.ATK_CHARACTER_STATE_IN_AIR_SET.add(window.ATK_CHARACTER_STATE.InAirAtk1[0]); window.ATK_CHARACTER_STATE_IN_AIR_SET.add(window.ATK_CHARACTER_STATE.InAirAtk1[0]);
window.ATK_CHARACTER_STATE_IN_AIR_SET.add(window.ATK_CHARACTER_STATE.InAirAtked1[0]); window.ATK_CHARACTER_STATE_IN_AIR_SET.add(window.ATK_CHARACTER_STATE.InAirAtked1[0]);
window.ATK_CHARACTER_STATE_IN_AIR_SET.add(window.ATK_CHARACTER_STATE.BlownUp1[0]); window.ATK_CHARACTER_STATE_IN_AIR_SET.add(window.ATK_CHARACTER_STATE.BlownUp1[0]);
window.ATK_CHARACTER_STATE_IN_AIR_SET.add(window.ATK_CHARACTER_STATE.OnWall[0]);
/* /*
Kindly note that the use of dragonBones anim is an informed choice for the feasibility of "gotoAndPlayByFrame", which is a required feature by "Map.rollbackAndChase". You might find that "cc.Animation" -- the traditional frame anim -- can also suffice this requirement, yet if we want to develop 3D frontend in the future, working with skeletal anim will make a smoother transition. Kindly note that the use of dragonBones anim is an informed choice for the feasibility of "gotoAndPlayByFrame", which is a required feature by "Map.rollbackAndChase". You might find that "cc.Animation" -- the traditional frame anim -- can also suffice this requirement, yet if we want to develop 3D frontend in the future, working with skeletal anim will make a smoother transition.
@@ -78,16 +84,24 @@ cc.Class({
updateCharacterAnim(rdfPlayer, prevRdfPlayer, forceAnimSwitch, chConfig) { updateCharacterAnim(rdfPlayer, prevRdfPlayer, forceAnimSwitch, chConfig) {
// As this function might be called after many frames of a rollback, it's possible that the playing animation was predicted, different from "prevRdfPlayer.CharacterState" but same as "newCharacterState". More granular checks are needed to determine whether we should interrupt the playing animation. // As this function might be called after many frames of a rollback, it's possible that the playing animation was predicted, different from "prevRdfPlayer.CharacterState" but same as "newCharacterState". More granular checks are needed to determine whether we should interrupt the playing animation.
let newCharacterState = rdfPlayer.CharacterState;
// Update directions // Update directions
if (this.animComp && this.animComp.node) { if (this.animComp && this.animComp.node) {
if (0 > rdfPlayer.DirX) { if (0 > rdfPlayer.DirX) {
this.animNode.scaleX = (-1.0); this.animNode.scaleX = (-1.0);
} else if (0 < rdfPlayer.DirX) { } else if (0 < rdfPlayer.DirX) {
this.animNode.scaleX = (1.0); this.animNode.scaleX = (+1.0);
}
if (ATK_CHARACTER_STATE.OnWall[0] == newCharacterState) {
if (0 < rdfPlayer.OnWallNormX) {
this.animNode.scaleX = (-1.0);
} else {
this.animNode.scaleX = (+1.0);
}
} }
} }
let newCharacterState = rdfPlayer.CharacterState;
let newAnimName = window.ATK_CHARACTER_STATE_ARR[newCharacterState][1]; let newAnimName = window.ATK_CHARACTER_STATE_ARR[newCharacterState][1];
let playingAnimName = null; let playingAnimName = null;
let underlyingAnimationCtrl = null; let underlyingAnimationCtrl = null;

View File

@@ -0,0 +1,36 @@
window.BULLET_STATE = {
Startup: 0,
Active: 1,
Exploding: 2,
};
cc.Class({
extends: cc.Component,
properties: {
animNode: {
type: cc.Node,
default: null
},
},
updateAnim(newAnimName, frameIdxInAnim, dirX, spontaneousLooping, rdf, newAnimIdx) {
this.animComp = this.effAnimNode.getComponent(cc.Animation);
// Update directions
if (this.animComp && this.animComp.node) {
if (0 > dirX) {
this.animNode.scaleX = (-1.0);
} else if (0 < dirX) {
this.animNode.scaleX = (1.0);
}
}
const currentClip = this.animComp.currentClip;
if (true == spontaneousLooping && (null != currentClip && currentClip.name == newAnimName)) {
return;
}
const targetClip = this.animComp.getClips()[newAnimIdx];
let fromTime = (frameIdxInAnim / targetClip.sample); // TODO: Anyway to avoid using division here?
this.animComp.play(newAnimName, fromTime);
},
});

View File

@@ -1,6 +1,6 @@
{ {
"ver": "1.0.5", "ver": "1.0.5",
"uuid": "247b7613-6c6e-4f01-b1d6-5f8f041b5688", "uuid": "a4b909c4-56a8-4b70-b6ea-b7f928077747",
"isPlugin": false, "isPlugin": false,
"loadPluginInWeb": true, "loadPluginInWeb": true,
"loadPluginInNative": true, "loadPluginInNative": true,

View File

@@ -29,9 +29,6 @@ cc.Class({
if (!selfPlayerRichInfo) return; if (!selfPlayerRichInfo) return;
const selfPlayerNode = selfPlayerRichInfo.node; const selfPlayerNode = selfPlayerRichInfo.node;
if (!selfPlayerNode) return; if (!selfPlayerNode) return;
const pDiff = selfPlayerNode.position.sub(self.mainCamera.node.position); self.mapNode.setPosition(cc.v2().sub(selfPlayerNode.position));
pDiff.normalizeSelf();
const newCamPos = self.mainCamera.node.position.add(pDiff.mul(dt*self.speed));
self.mainCamera.node.setPosition(newCamPos);
} }
}); });

View File

@@ -14,10 +14,6 @@ cc.Class({
type: cc.Node, type: cc.Node,
default: null default: null
}, },
myAvatarNode: {
type: cc.Node,
default: null
},
exitBtnNode: { exitBtnNode: {
type: cc.Node, type: cc.Node,
default: null default: null
@@ -25,8 +21,7 @@ cc.Class({
}, },
// LIFE-CYCLE CALLBACKS: // LIFE-CYCLE CALLBACKS:
onLoad() { onLoad() {},
},
init() { init() {
if (null != this.firstPlayerInfoNode) { if (null != this.firstPlayerInfoNode) {
@@ -79,20 +74,11 @@ cc.Class({
} }
} }
//显示自己的头像名称以及他人的头像名称
for (let i in playerMetas) { for (let i in playerMetas) {
const playerMeta = playerMetas[i]; const playerMeta = playerMetas[i];
console.log("Showing playerMeta:", playerMeta); console.log("Showing playerMeta:", playerMeta);
const playerInfoNode = this.playersInfoNode[playerMeta.joinIndex]; const playerInfoNode = this.playersInfoNode[playerMeta.joinIndex];
(() => { //远程加载头像
let remoteUrl = playerMeta.avatar;
if (remoteUrl == null || remoteUrl == '') {
cc.log(`No avatar to show for :`);
cc.log(playerMeta);
}
})();
function isEmptyString(str) { function isEmptyString(str) {
return str == null || str == '' return str == null || str == ''
} }

View File

@@ -0,0 +1,29 @@
const Bullet = require("./Bullet");
cc.Class({
extends: Bullet,
ctor() {
this.lastUsed = -1;
this.bulletLocalId = -1;
this.speciesName = null;
},
setSpecies(speciesName, fireballBullet, rdf) {
if (speciesName == this.speciesName) return;
if (null != this.speciesName) {
for (let k in this.animNode.children) {
const child = this.children[k];
if (!child.active) continue;
if (child == effAnimNode || child.name == speciesName) continue;
child.active = false;
}
}
this.speciesName = speciesName;
this.effAnimNode = this.animNode.getChildByName(this.speciesName);
this.effAnimNode.active = true;
},
onLoad() {},
});

View File

@@ -0,0 +1,9 @@
{
"ver": "1.0.5",
"uuid": "e66a2a91-9916-469e-a4b2-54cc0bcba3f0",
"isPlugin": false,
"loadPluginInWeb": true,
"loadPluginInNative": true,
"loadPluginInEditor": false,
"subMetas": {}
}

View File

@@ -68,6 +68,8 @@ cc.Class({
// LIFE-CYCLE CALLBACKS: // LIFE-CYCLE CALLBACKS:
onLoad() { onLoad() {
cc.view.setOrientation(cc.macro.ORIENTATION_AUTO);
cc.view.enableAutoFullScreen(true);
window.atFirstLocationHref = window.location.href.split('#')[0]; window.atFirstLocationHref = window.location.href.split('#')[0];
const self = this; const self = this;

View File

@@ -2,6 +2,7 @@ const i18n = require('LanguageData');
i18n.init(window.language); // languageID should be equal to the one we input in New Language ID input field i18n.init(window.language); // languageID should be equal to the one we input in New Language ID input field
const RingBuffer = require('./RingBuffer'); const RingBuffer = require('./RingBuffer');
const PriorityQueue = require("./PriorityQueue");
window.ALL_MAP_STATES = { window.ALL_MAP_STATES = {
VISUAL: 0, // For free dragging & zooming. VISUAL: 0, // For free dragging & zooming.
@@ -44,6 +45,10 @@ cc.Class({
type: cc.Prefab, type: cc.Prefab,
default: null, default: null,
}, },
fireballPrefab: {
type: cc.Prefab,
default: null,
},
joystickInputControllerNode: { joystickInputControllerNode: {
type: cc.Node, type: cc.Node,
default: null default: null
@@ -129,7 +134,7 @@ cc.Class({
previousSelfInput = (null == previousInputFrameDownsync ? null : previousInputFrameDownsync.InputList[joinIndex - 1]); previousSelfInput = (null == previousInputFrameDownsync ? null : previousInputFrameDownsync.InputList[joinIndex - 1]);
if (null != existingInputFrame) { if (null != existingInputFrame) {
// This could happen upon either [type#1] or [type#2] forceConfirmation, where "refRenderFrame" is accompanied by some "inputFrameDownsyncs". The check here also guarantees that we don't override history // This could happen upon either [type#1] or [type#2] forceConfirmation, where "refRenderFrame" is accompanied by some "inputFrameDownsyncs". The check here also guarantees that we don't override history
console.log(`noDelayInputFrameId=${inputFrameId} already exists in recentInputCache: recentInputCache=${self._stringifyRecentInputCache(false)}`); //console.log(`noDelayInputFrameId=${inputFrameId} already exists in recentInputCache: recentInputCache=${self._stringifyRecentInputCache(false)}`);
return [previousSelfInput, existingInputFrame.InputList[joinIndex - 1]]; return [previousSelfInput, existingInputFrame.InputList[joinIndex - 1]];
} }
@@ -287,6 +292,30 @@ cc.Class({
self.playerRichInfoDict = new Map(); self.playerRichInfoDict = new Map();
// Clearing previous info of all players. [ENDS] // Clearing previous info of all players. [ENDS]
// Clearing cached fireball rendering nodes [BEGINS]
if (null != self.cachedFireballs) {
while (!self.cachedFireballs.isEmpty()) {
const v = self.cachedFireballs.pop();
if (v && v.node && v.node.parent) {
v.node.parent.removeChild(v.node);
}
}
} else {
self.cachedFireballs = new PriorityQueue();
}
for (let k = 0; k < 1000; k++) {
const newFireballNode = cc.instantiate(self.fireballPrefab);
const newFireball = newFireballNode.getComponent("Fireball");
newFireballNode.setPosition(cc.v2(Number.MAX_VALUE, Number.MAX_VALUE));
safelyAddChild(self.node, newFireballNode);
setLocalZOrder(newFireballNode, 10);
newFireball.lastUsed = -1;
newFireball.bulletLocalId = -1;
const initLookupKey = -(k + 1); // there's definitely no suck "bulletLocalId"
self.cachedFireballs.push(newFireball.lastUsed, newFireball, initLookupKey);
}
// Clearing cached fireball rendering nodes [ENDS]
self.renderFrameId = 0; // After battle started self.renderFrameId = 0; // After battle started
self.bulletBattleLocalIdCounter = 0; self.bulletBattleLocalIdCounter = 0;
self.lastAllConfirmedInputFrameId = -1; self.lastAllConfirmedInputFrameId = -1;
@@ -380,11 +409,14 @@ cc.Class({
}, },
onLoad() { onLoad() {
cc.view.setOrientation(cc.macro.ORIENTATION_LANDSCAPE);
cc.view.enableAutoFullScreen(true);
const self = this; const self = this;
window.mapIns = self; window.mapIns = self;
window.forceBigEndianFloatingNumDecoding = self.forceBigEndianFloatingNumDecoding; window.forceBigEndianFloatingNumDecoding = self.forceBigEndianFloatingNumDecoding;
self.showCriticalCoordinateLabels = true; self.showCriticalCoordinateLabels = false;
console.warn("+++++++ Map onLoad()"); console.warn("+++++++ Map onLoad()");
@@ -444,7 +476,6 @@ cc.Class({
console.log(`Received parsedBattleColliderInfo via ws`); console.log(`Received parsedBattleColliderInfo via ws`);
// TODO: Upon reconnection, the backend might have already been sending down data that'd trigger "onRoomDownsyncFrame & onInputFrameDownsyncBatch", but frontend could reject those data due to "battleState != PlayerBattleState.ACTIVE". // TODO: Upon reconnection, the backend might have already been sending down data that'd trigger "onRoomDownsyncFrame & onInputFrameDownsyncBatch", but frontend could reject those data due to "battleState != PlayerBattleState.ACTIVE".
Object.assign(self, parsedBattleColliderInfo); Object.assign(self, parsedBattleColliderInfo);
self.tooFastDtIntervalMillis = 0.5 * self.rollbackEstimatedDtMillis;
const tiledMapIns = self.node.getComponent(cc.TiledMap); const tiledMapIns = self.node.getComponent(cc.TiledMap);
@@ -578,19 +609,19 @@ cc.Class({
const jsPlayersArr = new Array(pbRdf.playersArr.length).fill(null); const jsPlayersArr = new Array(pbRdf.playersArr.length).fill(null);
for (let k = 0; k < pbRdf.playersArr.length; ++k) { for (let k = 0; k < pbRdf.playersArr.length; ++k) {
const pbPlayer = pbRdf.playersArr[k]; const pbPlayer = pbRdf.playersArr[k];
const jsPlayer = gopkgs.NewPlayerDownsyncJs(pbPlayer.id, pbPlayer.virtualGridX, pbPlayer.virtualGridY, pbPlayer.dirX, pbPlayer.dirY, pbPlayer.velX, pbPlayer.velY, pbPlayer.framesToRecover, pbPlayer.framesInChState, pbPlayer.activeSkillId, pbPlayer.activeSkillHit, pbPlayer.framesInvinsible, pbPlayer.speed, pbPlayer.battleState, pbPlayer.characterState, pbPlayer.joinIndex, pbPlayer.hp, pbPlayer.maxHp, pbPlayer.colliderRadius, pbPlayer.inAir); const jsPlayer = gopkgs.NewPlayerDownsyncJs(pbPlayer.id, pbPlayer.virtualGridX, pbPlayer.virtualGridY, pbPlayer.dirX, pbPlayer.dirY, pbPlayer.velX, pbPlayer.velY, pbPlayer.framesToRecover, pbPlayer.framesInChState, pbPlayer.activeSkillId, pbPlayer.activeSkillHit, pbPlayer.framesInvinsible, pbPlayer.speed, pbPlayer.battleState, pbPlayer.characterState, pbPlayer.joinIndex, pbPlayer.hp, pbPlayer.maxHp, pbPlayer.colliderRadius, pbPlayer.inAir, pbPlayer.onWall, pbPlayer.onWallNormX, pbPlayer.onWallNormY, pbPlayer.capturedByInertia, pbPlayer.bulletTeamId, pbPlayer.chCollisionTeamId);
jsPlayersArr[k] = jsPlayer; jsPlayersArr[k] = jsPlayer;
} }
const jsMeleeBulletsArr = new Array(pbRdf.meleeBullets.length).fill(null); const jsMeleeBulletsArr = new Array(pbRdf.meleeBullets.length).fill(null);
for (let k = 0; k < pbRdf.meleeBullets.length; ++k) { for (let k = 0; k < pbRdf.meleeBullets.length; ++k) {
const pbBullet = pbRdf.meleeBullets[k]; const pbBullet = pbRdf.meleeBullets[k];
const jsMeleeBullet = gopkgs.NewMeleeBulletJs(pbBullet.bulletLocalId, pbBullet.originatedRenderFrameId, pbBullet.offenderJoinIndex, pbBullet.startupFrames, pbBullet.cancellableStFrame, pbBullet.cancellableEdFrame, pbBullet.activeFrames, pbBullet.hitStunFrames, pbBullet.blockStunFrames, pbBullet.pushbackVelX, pbBullet.pushbackVelY, pbBullet.damage, pbBullet.selfLockVelX, pbBullet.selfLockVelY, pbBullet.hitboxOffsetX, pbBullet.hitboxOffsetY, pbBullet.hitboxSizeX, pbBullet.hitboxSizeY, pbBullet.blowUp); const jsMeleeBullet = gopkgs.NewMeleeBulletJs(pbBullet.bulletLocalId, pbBullet.originatedRenderFrameId, pbBullet.offenderJoinIndex, pbBullet.startupFrames, pbBullet.cancellableStFrame, pbBullet.cancellableEdFrame, pbBullet.activeFrames, pbBullet.hitStunFrames, pbBullet.blockStunFrames, pbBullet.pushbackVelX, pbBullet.pushbackVelY, pbBullet.damage, pbBullet.selfLockVelX, pbBullet.selfLockVelY, pbBullet.hitboxOffsetX, pbBullet.hitboxOffsetY, pbBullet.hitboxSizeX, pbBullet.hitboxSizeY, pbBullet.blowUp, pbBullet.teamId, pbBullet.blState, pbBullet.framesInBlState, pbBullet.explosionFrames, pbBullet.speciesId);
jsMeleeBulletsArr[k] = jsMeleeBullet; jsMeleeBulletsArr[k] = jsMeleeBullet;
} }
const jsFireballBulletsArr = new Array(pbRdf.fireballBullets.length).fill(null); const jsFireballBulletsArr = new Array(pbRdf.fireballBullets.length).fill(null);
for (let k = 0; k < pbRdf.fireballBullets.length; ++k) { for (let k = 0; k < pbRdf.fireballBullets.length; ++k) {
const pbBullet = pbRdf.fireballBullets[k]; const pbBullet = pbRdf.fireballBullets[k];
const jsFireballBullet = gopkgs.NewFireballBulletJs(pbBullet.bulletLocalId, pbBullet.originatedRenderFrameId, pbBullet.offenderJoinIndex, pbBullet.startupFrames, pbBullet.cancellableStFrame, pbBullet.cancellableEdFrame, pbBullet.activeFrames, pbBullet.hitStunFrames, pbBullet.blockStunFrames, pbBullet.pushbackVelX, pbBullet.pushbackVelY, pbBullet.damage, pbBullet.selfLockVelX, pbBullet.selfLockVelY, pbBullet.hitboxOffsetX, pbBullet.hitboxOffsetY, pbBullet.hitboxSizeX, pbBullet.hitboxSizeY, pbBullet.blowUp, pbBullet.teamId, pbBullet.virtualGridX, pbBullet.virtualGridY, pbBullet.dirX, pbBullet.dirY, pbBullet.velX, pbBullet.velY, pbBullet.speed); const jsFireballBullet = gopkgs.NewFireballBulletJs(pbBullet.bulletLocalId, pbBullet.originatedRenderFrameId, pbBullet.offenderJoinIndex, pbBullet.startupFrames, pbBullet.cancellableStFrame, pbBullet.cancellableEdFrame, pbBullet.activeFrames, pbBullet.hitStunFrames, pbBullet.blockStunFrames, pbBullet.pushbackVelX, pbBullet.pushbackVelY, pbBullet.damage, pbBullet.selfLockVelX, pbBullet.selfLockVelY, pbBullet.hitboxOffsetX, pbBullet.hitboxOffsetY, pbBullet.hitboxSizeX, pbBullet.hitboxSizeY, pbBullet.blowUp, pbBullet.teamId, pbBullet.virtualGridX, pbBullet.virtualGridY, pbBullet.dirX, pbBullet.dirY, pbBullet.velX, pbBullet.velY, pbBullet.speed, pbBullet.blState, pbBullet.framesInBlState, pbBullet.explosionFrames, pbBullet.speciesId);
jsFireballBulletsArr[k] = jsFireballBullet; jsFireballBulletsArr[k] = jsFireballBullet;
} }
@@ -691,6 +722,8 @@ cc.Class({
equalPlayers(lhs, rhs) { equalPlayers(lhs, rhs) {
if (null == lhs || null == rhs) return false; if (null == lhs || null == rhs) return false;
if (null == lhs && null != rhs) return false;
if (null != lhs && null == rhs) return false;
if (lhs.VirtualGridX != rhs.VirtualGridX) return false; if (lhs.VirtualGridX != rhs.VirtualGridX) return false;
if (lhs.VirtualGridY != rhs.VirtualGridY) return false; if (lhs.VirtualGridY != rhs.VirtualGridY) return false;
if (lhs.DirX != rhs.DirX) return false; if (lhs.DirX != rhs.DirX) return false;
@@ -709,20 +742,43 @@ cc.Class({
equalMeleeBullets(lhs, rhs) { equalMeleeBullets(lhs, rhs) {
if (null == lhs || null == rhs) return false; if (null == lhs || null == rhs) return false;
if (lhs.battleLocalId != rhs.battleLocalId) return false; if (null == lhs && null != rhs) return false;
if (lhs.offenderPlayerId != rhs.offenderPlayerId) return false; if (null != lhs && null == rhs) return false;
if (lhs.offenderJoinIndex != rhs.offenderJoinIndex) return false; if (lhs.BattleAttr.BulletLocalId != rhs.BattleAttr.BulletLocalId) return false;
if (lhs.originatedRenderFrameId != rhs.originatedRenderFrameId) return false; if (lhs.BattleAttr.OffenderJoinIndex != rhs.BattleAttr.OffenderJoinIndex) return false;
if (lhs.BattleAttr.OriginatedRenderFrameId != rhs.BattleAttr.OriginatedRenderFrameId) return false;
return true;
},
equalFireballBullets(lhs, rhs) {
if (null == lhs || null == rhs) return false;
if (null == lhs && null != rhs) return false;
if (null != lhs && null == rhs) return false;
if (lhs.BattleAttr.BulletLocalId != rhs.BattleAttr.BulletLocalId) return false;
if (lhs.BattleAttr.OffenderJoinIndex != rhs.BattleAttr.OffenderJoinIndex) return false;
if (lhs.BattleAttr.OriginatedRenderFrameId != rhs.BattleAttr.OriginatedRenderFrameId) return false;
if (lhs.VirtualGridX != rhs.Bullet.VirtualGridX) return false;
if (lhs.VirtualGridY != rhs.Bullet.VirtualGridY) return false;
if (lhs.DirX != rhs.DirX) return false;
if (lhs.DirY != rhs.DirY) return false;
if (lhs.VelX != rhs.VelX) return false;
if (lhs.VelY != rhs.VelY) return false;
if (lhs.Speed != rhs.Speed) return false;
return true; return true;
}, },
equalRoomDownsyncFrames(lhs, rhs) { equalRoomDownsyncFrames(lhs, rhs) {
if (null == lhs || null == rhs) return false; if (null == lhs || null == rhs) return false;
for (let k in lhs.players) { for (let k in lhs.PlayersArr) {
if (!this.equalPlayers(lhs.players[k], rhs.players[k])) return false; if (!this.equalPlayers(lhs.PlayersArr[k], rhs.PlayersArr[k])) return false;
} }
for (let k in lhs.meleeBullets) { for (let k in lhs.MeleeBullets) {
if (!this.equalMeleeBullets(lhs.meleeBullets[k], rhs.meleeBullets[k])) return false; if (!this.equalMeleeBullets(lhs.MeleeBullets[k], rhs.MeleeBullets[k])) return false;
}
for (let k in lhs.fireballBullet) {
if (!this.equalFireballBullets(lhs.FireballBullets[k], rhs.FireballBullets[k])) return false;
} }
return true; return true;
}, },
@@ -783,13 +839,41 @@ cc.Class({
-------------------------------------------------------- --------------------------------------------------------
*/ */
// The actual rollback-and-chase would later be executed in update(dt). // The actual rollback-and-chase would later be executed in update(dt).
console.warn(`Mismatched input detected, resetting chaserRenderFrameId: ${self.chaserRenderFrameId}->${renderFrameId1} by firstPredictedYetIncorrectInputFrameId: ${firstPredictedYetIncorrectInputFrameId} console.log(`Mismatched input detected, resetting chaserRenderFrameId: ${self.chaserRenderFrameId}->${renderFrameId1} by firstPredictedYetIncorrectInputFrameId: ${firstPredictedYetIncorrectInputFrameId}
lastAllConfirmedInputFrameId=${self.lastAllConfirmedInputFrameId} lastAllConfirmedInputFrameId=${self.lastAllConfirmedInputFrameId}
recentInputCache=${self._stringifyRecentInputCache(false)} recentInputCache=${self._stringifyRecentInputCache(false)}
batchInputFrameIdRange=[${batch[0].inputFrameId}, ${batch[batch.length - 1].inputFrameId}]`); batchInputFrameIdRange=[${batch[0].inputFrameId}, ${batch[batch.length - 1].inputFrameId}]`);
self.chaserRenderFrameId = renderFrameId1; self.chaserRenderFrameId = renderFrameId1;
}, },
onPeerInputFrameUpsync(peerJoinIndex, batch /* []*pb.InputFrameDownsync */ ) {
// TODO: find some kind of synchronization mechanism against "getOrPrefabInputFrameUpsync"!
// See `<proj-root>/ConcerningEdgeCases.md` for why this method exists.
if (null == batch) {
return;
}
const self = this;
if (!self.recentInputCache) {
return;
}
if (ALL_BATTLE_STATES.IN_SETTLEMENT == self.battleState) {
return;
}
//console.log(`Received peer inputFrameUpsync batch w/ inputFrameId in [${batch[0].inputFrameId}, ${batch[batch.length - 1].inputFrameId}] for prediction assistance`);
for (let k in batch) {
const inputFrameDownsync = batch[k];
const inputFrameDownsyncId = inputFrameDownsync.inputFrameId;
if (inputFrameDownsyncId <= self.lastAllConfirmedInputFrameId) {
continue;
}
self.getOrPrefabInputFrameUpsync(inputFrameDownsyncId); // Make sure that inputFrame exists locally
const existingInputFrame = self.recentInputCache.GetByFrameId(inputFrameDownsyncId);
existingInputFrame.InputList[peerJoinIndex - 1] = inputFrameDownsync.inputList[peerJoinIndex - 1]; // No need to change "confirmedList", leave it to "onInputFrameDownsyncBatch" -- we're just helping prediction here
self.recentInputCache.SetByFrameId(existingInputFrame, inputFrameDownsyncId);
}
},
onPlayerAdded(rdf /* pb.RoomDownsyncFrame */ ) { onPlayerAdded(rdf /* pb.RoomDownsyncFrame */ ) {
const self = this; const self = this;
// Update the "finding player" GUI and show it if not previously present // Update the "finding player" GUI and show it if not previously present
@@ -854,21 +938,28 @@ batchInputFrameIdRange=[${batch[0].inputFrameId}, ${batch[batch.length - 1].inpu
update(dt) { update(dt) {
const self = this; const self = this;
if (ALL_BATTLE_STATES.IN_BATTLE == self.battleState) { if (ALL_BATTLE_STATES.IN_BATTLE == self.battleState) {
const elapsedMillisSinceLastFrameIdTriggered = performance.now() - self.lastRenderFrameIdTriggeredAt; /*
if (elapsedMillisSinceLastFrameIdTriggered < self.tooFastDtIntervalMillis) { [WARNING] Different devices might differ in the rate of calling "update(dt)", and the game engine is responsible of keeping this rate statistically constant.
// [WARNING] We should avoid a frontend ticking too fast to prevent cheating, as well as ticking too slow to cause a "resync avalanche" that impacts user experience!
// console.debug("Avoiding too fast frame@renderFrameId=", self.renderFrameId, ": elapsedMillisSinceLastFrameIdTriggered=", elapsedMillisSinceLastFrameIdTriggered); Significantly different rates of calling "update(dt)" among players in a same battle would result in frequent [type#1 forceConfirmation], if you have any doubt on troubles caused by this, sample the FPS curve from all players in that battle.
return;
} Kindly note that Significantly different network bandwidths or delay fluctuations would result in frequent [type#1 forceConfirmation] too, but CAUSE FROM DIFFERENT LOCAL "update(dt)" RATE SHOULD BE THE FIRST TO INVESTIGATE AND ELIMINATE -- because we have control on it, but no one has control on the internet.
*/
try { try {
let st = performance.now(); let st = performance.now();
const noDelayInputFrameId = gopkgs.ConvertToNoDelayInputFrameId(self.renderFrameId);
let prevSelfInput = null, let prevSelfInput = null,
currSelfInput = null; currSelfInput = null;
const noDelayInputFrameId = gopkgs.ConvertToNoDelayInputFrameId(self.renderFrameId);
if (gopkgs.ShouldGenerateInputFrameUpsync(self.renderFrameId)) { if (gopkgs.ShouldGenerateInputFrameUpsync(self.renderFrameId)) {
[prevSelfInput, currSelfInput] = self.getOrPrefabInputFrameUpsync(noDelayInputFrameId); [prevSelfInput, currSelfInput] = self.getOrPrefabInputFrameUpsync(noDelayInputFrameId);
} }
const delayedInputFrameId = gopkgs.ConvertToDelayedInputFrameId(self.renderFrameId);
if (null == self.recentInputCache.GetByFrameId(delayedInputFrameId)) {
// Possible edge case after resync
self.getOrPrefabInputFrameUpsync(delayedInputFrameId);
}
let t0 = performance.now(); let t0 = performance.now();
if (self.shouldSendInputFrameUpsyncBatch(prevSelfInput, currSelfInput, self.lastUpsyncInputFrameId, noDelayInputFrameId)) { if (self.shouldSendInputFrameUpsyncBatch(prevSelfInput, currSelfInput, self.lastUpsyncInputFrameId, noDelayInputFrameId)) {
// TODO: Is the following statement run asynchronously in an implicit manner? Should I explicitly run it asynchronously? // TODO: Is the following statement run asynchronously in an implicit manner? Should I explicitly run it asynchronously?
@@ -899,17 +990,17 @@ batchInputFrameIdRange=[${batch[0].inputFrameId}, ${batch[batch.length - 1].inpu
} }
*/ */
// [WARNING] Don't try to get "prevRdf(i.e. renderFrameId == latest-1)" by "self.recentRenderCache.getByFrameId(...)" here, as the cache might have been updated by asynchronous "onRoomDownsyncFrame(...)" calls! // [WARNING] Don't try to get "prevRdf(i.e. renderFrameId == latest-1)" by "self.recentRenderCache.getByFrameId(...)" here, as the cache might have been updated by asynchronous "onRoomDownsyncFrame(...)" calls!
if (self.othersForcedDownsyncRenderFrameDict.has(rdf.id)) { if (self.othersForcedDownsyncRenderFrameDict.has(rdf.Id)) {
const delayedInputFrameId = gopkgs.ConvertToDelayedInputFrameId(rdf.id); const delayedInputFrameId = gopkgs.ConvertToDelayedInputFrameId(rdf.Id);
const othersForcedDownsyncRenderFrame = self.othersForcedDownsyncRenderFrameDict.get(rdf.id); const othersForcedDownsyncRenderFrame = self.othersForcedDownsyncRenderFrameDict.get(rdf.Id);
if (self.lastAllConfirmedInputFrameId >= delayedInputFrameId && !self.equalRoomDownsyncFrames(othersForcedDownsyncRenderFrame, rdf)) { if (self.lastAllConfirmedInputFrameId >= delayedInputFrameId && !self.equalRoomDownsyncFrames(othersForcedDownsyncRenderFrame, rdf)) {
console.warn(`Mismatched render frame@rdf.id=${rdf.id} w/ inputFrameId=${delayedInputFrameId}: console.warn(`Mismatched render frame@rdf.id=${rdf.Id} w/ inputFrameId=${delayedInputFrameId}:
rdf=${JSON.stringify(rdf)} rdf=${JSON.stringify(rdf)}
othersForcedDownsyncRenderFrame=${JSON.stringify(othersForcedDownsyncRenderFrame)}`); othersForcedDownsyncRenderFrame=${JSON.stringify(othersForcedDownsyncRenderFrame)}`);
// closeWSConnection(constants.RET_CODE.CLIENT_MISMATCHED_RENDER_FRAME, ""); // closeWSConnection(constants.RET_CODE.CLIENT_MISMATCHED_RENDER_FRAME, "");
// self.onManualRejoinRequired("[DEBUG] CLIENT_MISMATCHED_RENDER_FRAME"); // self.onManualRejoinRequired("[DEBUG] CLIENT_MISMATCHED_RENDER_FRAME");
rdf = othersForcedDownsyncRenderFrame; rdf = othersForcedDownsyncRenderFrame;
self.othersForcedDownsyncRenderFrameDict.delete(rdf.id); self.othersForcedDownsyncRenderFrameDict.delete(rdf.Id);
} }
} }
self.applyRoomDownsyncFrameDynamics(rdf, prevRdf); self.applyRoomDownsyncFrameDynamics(rdf, prevRdf);
@@ -1053,6 +1144,77 @@ othersForcedDownsyncRenderFrame=${JSON.stringify(othersForcedDownsyncRenderFrame
playerRichInfo.scriptIns.updateCharacterAnim(currPlayerDownsync, prevRdfPlayer, false, chConfig); playerRichInfo.scriptIns.updateCharacterAnim(currPlayerDownsync, prevRdfPlayer, false, chConfig);
} }
// Move all to infinitely far away first
for (let k in self.cachedFireballs.list) {
const pqNode = self.cachedFireballs.list[k];
const fireball = pqNode.value;
fireball.node.setPosition(cc.v2(Number.MAX_VALUE, Number.MAX_VALUE));
}
for (let k in rdf.MeleeBullets) {
const meleeBullet = rdf.MeleeBullets[k];
const isExploding = (window.BULLET_STATE.Exploding == meleeBullet.BlState);
if (isExploding) {
let pqNode = self.cachedFireballs.popAny(meleeBullet.BattleAttr.BulletLocalId);
let speciesName = `MeleeExplosion`;
let animName = `MeleeExplosion${meleeBullet.Bullet.SpeciesId}`;
const offender = rdf.PlayersArr[meleeBullet.BattleAttr.OffenderJoinIndex - 1];
let xfac = 1; // By now, straight Punch offset doesn't respect "y-axis"
if (0 > offender.DirX) {
xfac = -1;
}
const [wx, wy] = gopkgs.VirtualGridToWorldPos(offender.VirtualGridX + xfac * meleeBullet.Bullet.HitboxOffsetX, offender.VirtualGridY);
if (null == pqNode) {
pqNode = self.cachedFireballs.pop();
//console.log(`@rdf.Id=${rdf.Id}, origRdfId=${meleeBullet.BattleAttr.OriginatedRenderFrameId}, startupFrames=${meleeBullet.Bullet.StartupFrames}, using a new fireball node for rendering for bulletLocalId=${meleeBullet.BattleAttr.BulletLocalId} at wpos=(${wx},${wy})`);
} else {
//console.log(`@rdf.Id=${rdf.Id}, origRdfId=${meleeBullet.BattleAttr.OriginatedRenderFrameId}, startupFrames=${meleeBullet.Bullet.StartupFrames}, using a cached fireball node for rendering for bulletLocalId=${meleeBullet.BattleAttr.BulletLocalId} at wpos=(${wx},${wy})`);
}
const cachedFireball = pqNode.value;
cachedFireball.setSpecies(speciesName, meleeBullet, rdf);
const newAnimIdx = meleeBullet.Bullet.SpeciesId - 1;
cachedFireball.updateAnim(animName, meleeBullet.FramesInBlState, offender.DirX, false, rdf, newAnimIdx);
cachedFireball.lastUsed = self.renderFrameId;
cachedFireball.bulletLocalId = meleeBullet.BattleAttr.BulletLocalId;
cachedFireball.node.setPosition(cc.v2(wx, wy));
self.cachedFireballs.push(cachedFireball.lastUsed, cachedFireball, meleeBullet.BattleAttr.BulletLocalId);
} else {
//console.log(`@rdf.Id=${rdf.Id}, origRdfId=${meleeBullet.BattleAttr.OriginatedRenderFrameId}, startupFrames=${meleeBullet.Bullet.StartupFrames}, activeFrames=${meleeBullet.Bullet.ActiveFrames}, not rendering melee node for bulletLocalId=${meleeBullet.BattleAttr.BulletLocalId}`);
}
}
for (let k in rdf.FireballBullets) {
const fireballBullet = rdf.FireballBullets[k];
const isExploding = (window.BULLET_STATE.Exploding == fireballBullet.BlState);
if (gopkgs.IsFireballBulletActive(fireballBullet, rdf) || isExploding) {
let pqNode = self.cachedFireballs.popAny(fireballBullet.BattleAttr.BulletLocalId);
let speciesName = `Fireball${fireballBullet.Bullet.SpeciesId}`;
let animName = (BULLET_STATE.Exploding == fireballBullet.BlState ? `Fireball${fireballBullet.Bullet.SpeciesId}Explosion` : speciesName);
const [wx, wy] = gopkgs.VirtualGridToWorldPos(fireballBullet.VirtualGridX, fireballBullet.VirtualGridY);
if (null == pqNode) {
pqNode = self.cachedFireballs.pop();
//console.log(`@rdf.Id=${rdf.Id}, origRdfId=${fireballBullet.BattleAttr.OriginatedRenderFrameId}, startupFrames=${fireballBullet.Bullet.StartupFrames}, using a new fireball node for rendering for bulletLocalId=${fireballBullet.BattleAttr.BulletLocalId} at wpos=(${wx},${wy})`);
} else {
//console.log(`@rdf.Id=${rdf.Id}, origRdfId=${fireballBullet.BattleAttr.OriginatedRenderFrameId}, startupFrames=${fireballBullet.Bullet.StartupFrames}, using a cached fireball node for rendering for bulletLocalId=${fireballBullet.BattleAttr.BulletLocalId} at wpos=(${wx},${wy})`);
}
const cachedFireball = pqNode.value;
cachedFireball.setSpecies(speciesName, fireballBullet, rdf);
const spontaneousLooping = !isExploding;
const newAnimIdx = (spontaneousLooping ? 0 : 1);
cachedFireball.updateAnim(animName, fireballBullet.FramesInBlState, fireballBullet.DirX, spontaneousLooping, rdf, newAnimIdx);
cachedFireball.lastUsed = self.renderFrameId;
cachedFireball.bulletLocalId = fireballBullet.BattleAttr.BulletLocalId;
cachedFireball.node.setPosition(cc.v2(wx, wy));
self.cachedFireballs.push(cachedFireball.lastUsed, cachedFireball, fireballBullet.BattleAttr.BulletLocalId);
} else {
//console.log(`@rdf.Id=${rdf.Id}, origRdfId=${fireballBullet.BattleAttr.OriginatedRenderFrameId}, startupFrames=${fireballBullet.Bullet.StartupFrames}, activeFrames=${fireballBullet.Bullet.ActiveFrames}, not rendering fireball node for bulletLocalId=${fireballBullet.BattleAttr.BulletLocalId}`);
}
}
// Update countdown // Update countdown
self.countdownNanos = self.battleDurationNanos - self.renderFrameId * self.rollbackEstimatedDtNanos; self.countdownNanos = self.battleDurationNanos - self.renderFrameId * self.rollbackEstimatedDtNanos;
if (self.countdownNanos <= 0) { if (self.countdownNanos <= 0) {
@@ -1070,13 +1232,26 @@ othersForcedDownsyncRenderFrame=${JSON.stringify(othersForcedDownsyncRenderFrame
throw `Couldn't find renderFrame for i=${i} to rollback (are you using Firefox?), self.renderFrameId=${self.renderFrameId}, lastAllConfirmedInputFrameId=${self.lastAllConfirmedInputFrameId}, might've been interruptted by onRoomDownsyncFrame`; throw `Couldn't find renderFrame for i=${i} to rollback (are you using Firefox?), self.renderFrameId=${self.renderFrameId}, lastAllConfirmedInputFrameId=${self.lastAllConfirmedInputFrameId}, might've been interruptted by onRoomDownsyncFrame`;
} }
const j = gopkgs.ConvertToDelayedInputFrameId(i); const j = gopkgs.ConvertToDelayedInputFrameId(i);
const delayedInputFrame = self.recentInputCache.GetByFrameId(j); // Don't make prediction here, the inputFrameDownsyncs in recentInputCache was already predicted while prefabbing const delayedInputFrame = self.recentInputCache.GetByFrameId(j);
if (null == delayedInputFrame) { /*
// Shouldn't happen! const prevJ = gopkgs.ConvertToDelayedInputFrameId(i - 1);
throw `Failed to get cached delayedInputFrame for i=${i}, j=${j}, renderFrameId=${self.renderFrameId}, lastUpsyncInputFrameId=${self.lastUpsyncInputFrameId}, lastAllConfirmedInputFrameId=${self.lastAllConfirmedInputFrameId}, chaserRenderFrameId=${self.chaserRenderFrameId}; recentRenderCache=${self._stringifyRecentRenderCache(false)}, recentInputCache=${self._stringifyRecentInputCache(false)}`; const prevDelayedInputFrame = self.recentInputCache.GetByFrameId(prevJ);
const prevBtnALevel = (null == prevDelayedInputFrame ? 0 : ((prevDelayedInputFrame.InputList[self.selfPlayerInfo.JoinIndex - 1] >> 4) & 1));
const btnALevel = ((delayedInputFrame.InputList[self.selfPlayerInfo.JoinIndex - 1] >> 4) & 1);
if (
ATK_CHARACTER_STATE.Atk1[0] == currRdf.PlayersArr[self.selfPlayerInfo.JoinIndex - 1].CharacterState
||
ATK_CHARACTER_STATE.Atk2[0] == currRdf.PlayersArr[self.selfPlayerInfo.JoinIndex - 1].CharacterState
) {
console.log(`rdf.Id=${i}, (btnALevel,j)=(${btnALevel},${j}), (prevBtnALevel,prevJ) is (${prevBtnALevel},${prevJ}), in cancellable atk!`);
} }
if (btnALevel > 0) {
if (btnALevel > prevBtnALevel) {
console.log(`rdf.Id=${i}, rising edge of btnA triggered`);
}
}
*/
const jPrev = gopkgs.ConvertToDelayedInputFrameId(i - 1);
if (self.frameDataLoggingEnabled) { if (self.frameDataLoggingEnabled) {
const actuallyUsedInputClone = delayedInputFrame.InputList.slice(); const actuallyUsedInputClone = delayedInputFrame.InputList.slice();
const inputFrameDownsyncClone = { const inputFrameDownsyncClone = {
@@ -1174,7 +1349,12 @@ othersForcedDownsyncRenderFrame=${JSON.stringify(othersForcedDownsyncRenderFrame
playerDownsyncStr(playerDownsync) { playerDownsyncStr(playerDownsync) {
if (null == playerDownsync) return ""; if (null == playerDownsync) return "";
return `{${playerDownsync.JoinIndex},${playerDownsync.VirtualGridX},${playerDownsync.VirtualGridY},${playerDownsync.VelX},${playerDownsync.VelY},${playerDownsync.FramesToRecover},${playerDownsync.InAir ? 1 : 0}}`; return `{${playerDownsync.JoinIndex},${playerDownsync.VirtualGridX},${playerDownsync.VirtualGridY},${playerDownsync.VelX},${playerDownsync.VelY},${playerDownsync.FramesToRecover},${playerDownsync.InAir ? 1 : 0},${playerDownsync.OnWall ? 1 : 0}}`;
},
fireballDownsyncStr(fireball) {
if (null == fireball) return "";
return `{${fireball.BattleAttr.BulletLocalId},${fireball.BattleAttr.OriginatedRenderFrameId},${fireball.BattleAttr.OffenderJoinIndex},${fireball.VirtualGridX},${fireball.VirtualGridY},${fireball.VelX},${fireball.VelY},${fireball.DirX},${fireball.DirY},${fireball.Bullet.HitboxSizeX},${fireball.Bullet.HitboxSizeY}}`;
}, },
inputFrameDownsyncStr(inputFrameDownsync) { inputFrameDownsyncStr(inputFrameDownsync) {
@@ -1203,8 +1383,13 @@ othersForcedDownsyncRenderFrame=${JSON.stringify(othersForcedDownsyncRenderFrame
for (let k in rdf.PlayersArr) { for (let k in rdf.PlayersArr) {
playersStrBldr.push(self.playerDownsyncStr(rdf.PlayersArr[k])); playersStrBldr.push(self.playerDownsyncStr(rdf.PlayersArr[k]));
} }
const fireballsStrBldr = [];
for (let k in rdf.FireballBullets) {
fireballsStrBldr.push(self.fireballDownsyncStr(rdf.FireballBullets[k]));
}
s.push(`rdfId:${i} s.push(`rdfId:${i}
players:[${playersStrBldr.join(',')}] players:[${playersStrBldr.join(',')}]
fireballs:[${fireballsStrBldr.join(',')}]
actuallyUsedinputList:{${self.inputFrameDownsyncStr(actuallyUsedInputClone)}}`); actuallyUsedinputList:{${self.inputFrameDownsyncStr(actuallyUsedInputClone)}}`);
} }
@@ -1242,6 +1427,7 @@ actuallyUsedinputList:{${self.inputFrameDownsyncStr(actuallyUsedInputClone)}}`);
case ATK_CHARACTER_STATE.BlownUp1[0]: case ATK_CHARACTER_STATE.BlownUp1[0]:
case ATK_CHARACTER_STATE.InAirIdle1NoJump[0]: case ATK_CHARACTER_STATE.InAirIdle1NoJump[0]:
case ATK_CHARACTER_STATE.InAirIdle1ByJump[0]: case ATK_CHARACTER_STATE.InAirIdle1ByJump[0]:
case ATK_CHARACTER_STATE.OnWall[0]:
[colliderWidth, colliderHeight] = [player.ColliderRadius * 2, player.ColliderRadius * 2]; [colliderWidth, colliderHeight] = [player.ColliderRadius * 2, player.ColliderRadius * 2];
break; break;
} }
@@ -1262,12 +1448,8 @@ actuallyUsedinputList:{${self.inputFrameDownsyncStr(actuallyUsedInputClone)}}`);
for (let k in rdf.MeleeBullets) { for (let k in rdf.MeleeBullets) {
const meleeBullet = rdf.MeleeBullets[k]; const meleeBullet = rdf.MeleeBullets[k];
if ( if (gopkgs.IsMeleeBulletActive(meleeBullet, rdf)) {
meleeBullet.Bullet.OriginatedRenderFrameId + meleeBullet.Bullet.StartupFrames <= rdf.Id const offender = rdf.PlayersArr[meleeBullet.BattleAttr.OffenderJoinIndex - 1];
&&
meleeBullet.Bullet.OriginatedRenderFrameId + meleeBullet.Bullet.StartupFrames + meleeBullet.Bullet.ActiveFrames > rdf.Id
) {
const offender = rdf.PlayersArr[meleeBullet.Bullet.OffenderJoinIndex - 1];
if (1 == offender.JoinIndex) { if (1 == offender.JoinIndex) {
g2.strokeColor = cc.Color.BLUE; g2.strokeColor = cc.Color.BLUE;
} else { } else {
@@ -1294,12 +1476,8 @@ actuallyUsedinputList:{${self.inputFrameDownsyncStr(actuallyUsedInputClone)}}`);
for (let k in rdf.FireballBullets) { for (let k in rdf.FireballBullets) {
const fireballBullet = rdf.FireballBullets[k]; const fireballBullet = rdf.FireballBullets[k];
if ( if (gopkgs.IsFireballBulletActive(fireballBullet, rdf)) {
fireballBullet.Bullet.OriginatedRenderFrameId + fireballBullet.Bullet.StartupFrames <= rdf.Id const offender = rdf.PlayersArr[fireballBullet.BattleAttr.OffenderJoinIndex - 1];
&&
fireballBullet.Bullet.OriginatedRenderFrameId + fireballBullet.Bullet.StartupFrames + fireballBullet.Bullet.ActiveFrames > rdf.Id
) {
const offender = rdf.PlayersArr[fireballBullet.Bullet.OffenderJoinIndex - 1];
if (1 == offender.JoinIndex) { if (1 == offender.JoinIndex) {
g2.strokeColor = cc.Color.BLUE; g2.strokeColor = cc.Color.BLUE;
} else { } else {

View File

@@ -11,9 +11,11 @@ cc.Class({
}, },
onLoad() { onLoad() {
cc.view.setOrientation(cc.macro.ORIENTATION_LANDSCAPE);
cc.view.enableAutoFullScreen(true);
const self = this; const self = this;
window.mapIns = self; window.mapIns = self;
self.showCriticalCoordinateLabels = true; self.showCriticalCoordinateLabels = false;
const mapNode = self.node; const mapNode = self.node;
const canvasNode = mapNode.parent; const canvasNode = mapNode.parent;
@@ -29,7 +31,7 @@ cc.Class({
/** Init required prefab ended. */ /** Init required prefab ended. */
self.inputFrameUpsyncDelayTolerance = 2; self.inputFrameUpsyncDelayTolerance = 2;
self.collisionMinStep = 8; self.collisionMinStep = 2;
self.renderCacheSize = 1024; self.renderCacheSize = 1024;
self.serverFps = 60; self.serverFps = 60;
@@ -92,9 +94,11 @@ cc.Class({
const p1Vpos = gopkgs.WorldToVirtualGridPos(boundaryObjs.playerStartingPositions[0].x, boundaryObjs.playerStartingPositions[0].y); const p1Vpos = gopkgs.WorldToVirtualGridPos(boundaryObjs.playerStartingPositions[0].x, boundaryObjs.playerStartingPositions[0].y);
const p2Vpos = gopkgs.WorldToVirtualGridPos(boundaryObjs.playerStartingPositions[1].x, boundaryObjs.playerStartingPositions[1].y); const p2Vpos = gopkgs.WorldToVirtualGridPos(boundaryObjs.playerStartingPositions[1].x, boundaryObjs.playerStartingPositions[1].y);
const speedV = gopkgs.WorldToVirtualGridPos(1.0, 0);
const colliderRadiusV = gopkgs.WorldToVirtualGridPos(12.0, 0); const colliderRadiusV = gopkgs.WorldToVirtualGridPos(12.0, 0);
const speciesIdList = [1, 4096];
const chConfigsOrderedByJoinIndex = gopkgs.GetCharacterConfigsOrderedByJoinIndex(speciesIdList);
const startRdf = window.pb.protos.RoomDownsyncFrame.create({ const startRdf = window.pb.protos.RoomDownsyncFrame.create({
id: window.MAGIC_ROOM_DOWNSYNC_FRAME_ID.BATTLE_START, id: window.MAGIC_ROOM_DOWNSYNC_FRAME_ID.BATTLE_START,
playersArr: [ playersArr: [
@@ -103,7 +107,7 @@ cc.Class({
joinIndex: 1, joinIndex: 1,
virtualGridX: p1Vpos[0], virtualGridX: p1Vpos[0],
virtualGridY: p1Vpos[1], virtualGridY: p1Vpos[1],
speed: speedV[0], speed: chConfigsOrderedByJoinIndex[0].Speed,
colliderRadius: colliderRadiusV[0], colliderRadius: colliderRadiusV[0],
characterState: window.ATK_CHARACTER_STATE.InAirIdle1NoJump[0], characterState: window.ATK_CHARACTER_STATE.InAirIdle1NoJump[0],
framesToRecover: 0, framesToRecover: 0,
@@ -112,13 +116,14 @@ cc.Class({
velX: 0, velX: 0,
velY: 0, velY: 0,
inAir: true, inAir: true,
onWall: false,
}), }),
window.pb.protos.PlayerDownsync.create({ window.pb.protos.PlayerDownsync.create({
id: 11, id: 11,
joinIndex: 2, joinIndex: 2,
virtualGridX: p2Vpos[0], virtualGridX: p2Vpos[0],
virtualGridY: p2Vpos[1], virtualGridY: p2Vpos[1],
speed: speedV[0], speed: chConfigsOrderedByJoinIndex[1].Speed,
colliderRadius: colliderRadiusV[0], colliderRadius: colliderRadiusV[0],
characterState: window.ATK_CHARACTER_STATE.InAirIdle1NoJump[0], characterState: window.ATK_CHARACTER_STATE.InAirIdle1NoJump[0],
framesToRecover: 0, framesToRecover: 0,
@@ -127,9 +132,10 @@ cc.Class({
velX: 0, velX: 0,
velY: 0, velY: 0,
inAir: true, inAir: true,
onWall: false,
}), }),
], ],
speciesIdList: [4096, 0], speciesIdList: speciesIdList,
}); });
self.selfPlayerInfo = { self.selfPlayerInfo = {
@@ -150,7 +156,7 @@ cc.Class({
if (elapsedMillisSinceLastFrameIdTriggered < self.tooFastDtIntervalMillis) { if (elapsedMillisSinceLastFrameIdTriggered < self.tooFastDtIntervalMillis) {
// [WARNING] We should avoid a frontend ticking too fast to prevent cheating, as well as ticking too slow to cause a "resync avalanche" that impacts user experience! // [WARNING] We should avoid a frontend ticking too fast to prevent cheating, as well as ticking too slow to cause a "resync avalanche" that impacts user experience!
// console.debug("Avoiding too fast frame@renderFrameId=", self.renderFrameId, ": elapsedMillisSinceLastFrameIdTriggered=", elapsedMillisSinceLastFrameIdTriggered); // console.debug("Avoiding too fast frame@renderFrameId=", self.renderFrameId, ": elapsedMillisSinceLastFrameIdTriggered=", elapsedMillisSinceLastFrameIdTriggered);
return; //return;
} }
try { try {
let st = performance.now(); let st = performance.now();

View File

@@ -12,32 +12,15 @@ var BinaryHeap = function (customCompare) {
* @private * @private
*/ */
this.list = []; this.list = [];
this.lookupKeyToIndex = {};
if (customCompare) { if (customCompare) {
this.compare = customCompare; this.compare = customCompare;
} }
}; };
/** BinaryHeap.prototype.contains = function (lookupKey) {
* Builds a heap with the provided keys and values, this will discard the return null != this.lookupKeyToIndex[lookupKey];
* heap's current data.
*
* @param {Array} keys An array of keys.
* @param {Array} values An array of values. This must be the same size as the
* key array.
*/
BinaryHeap.prototype.buildHeap = function (keys, values) {
if (typeof values !== 'undefined' && values.length !== keys.length) {
throw new Error('Key array must be the same length as value array');
}
var nodeArray = [];
for (var i = 0; i < keys.length; i++) {
nodeArray.push(new Node(keys[i], values ? values[i] : undefined));
}
buildHeapFromNodeArray(this, nodeArray);
}; };
/** /**
@@ -45,6 +28,7 @@ BinaryHeap.prototype.buildHeap = function (keys, values) {
*/ */
BinaryHeap.prototype.clear = function () { BinaryHeap.prototype.clear = function () {
this.list.length = 0; this.list.length = 0;
this.lookupKeyToIndex = null;
}; };
/** /**
@@ -53,15 +37,20 @@ BinaryHeap.prototype.clear = function () {
* @return {Node} node The heap's minimum node or undefined if the heap is * @return {Node} node The heap's minimum node or undefined if the heap is
* empty. * empty.
*/ */
BinaryHeap.prototype.extractMinimum = function () { BinaryHeap.prototype.pop = function () {
if (!this.list.length) { if (0 == this.list.length) {
return undefined; return null;
} }
if (this.list.length === 1) { if (1 == this.list.length) {
delete this.lookupKeyToIndex[Object.keys(this.lookupKeyToIndex)[0]];
return this.list.shift(); return this.list.shift();
} }
var min = this.list[0]; var min = this.list[0];
delete this.lookupKeyToIndex[min.lookupKey];
this.list[0] = this.list.pop(); this.list[0] = this.list.pop();
this.lookupKeyToIndex[this.list[0].lookupKey] = 0;
heapify(this, 0); heapify(this, 0);
return min; return min;
}; };
@@ -72,8 +61,8 @@ BinaryHeap.prototype.extractMinimum = function () {
* @return {Node} node The heap's minimum node or undefined if the heap is * @return {Node} node The heap's minimum node or undefined if the heap is
* empty. * empty.
*/ */
BinaryHeap.prototype.findMinimum = function () { BinaryHeap.prototype.top = function () {
return this.isEmpty() ? undefined : this.list[0]; return this.isEmpty() ? null : this.list[0];
}; };
/** /**
@@ -83,25 +72,79 @@ BinaryHeap.prototype.findMinimum = function () {
* @param {Object} value The value to insert. * @param {Object} value The value to insert.
* @return {Node} node The inserted node. * @return {Node} node The inserted node.
*/ */
BinaryHeap.prototype.insert = function (key, value) { BinaryHeap.prototype.push = function (key, value, lookupKey) {
var i = this.list.length; var i = this.list.length;
var node = new Node(key, value); var node = new Node(key, value, lookupKey);
this.list.push(node); this.list.push(node);
var parent = getParent(i); this.lookupKeyToIndex[lookupKey] = i;
while (typeof parent !== 'undefined' && let u = getParent(i);
this.compare(this.list[i], this.list[parent]) < 0) { while (null != u && this.compare(this.list[i], this.list[u]) < 0) {
swap(this.list, i, parent); swap(this.list, i, u, this.lookupKeyToIndex);
i = parent; i = u;
parent = getParent(i); u = getParent(i);
} }
return node; return node;
}; };
BinaryHeap.prototype.update = function (lookupKey, newKey, newValue) {
if (null == this.lookupKeyToIndex[lookupKey]) return null;
var i = this.lookupKeyToIndex[lookupKey];
this.list[i].key = newKey;
this.list[i].value = newValue;
let u = getParent(i);
if (null != u && this.compare(this.list[i], this.list[u]) < 0) {
while (null != u && this.compare(this.list[i], this.list[u]) < 0) {
swap(this.list, i, u, this.lookupKeyToIndex);
i = u;
u = getParent(i);
}
} else {
heapify(this, i);
}
};
BinaryHeap.prototype.popAny = function (lookupKey) {
if (null == this.lookupKeyToIndex[lookupKey]) return null;
if (0 == this.list.length) {
return null;
}
if (1 == this.list.length) {
delete this.lookupKeyToIndex[Object.keys(this.lookupKeyToIndex)[0]];
return this.list.shift();
}
var i = this.lookupKeyToIndex[lookupKey];
var old = this.list[i];
delete this.lookupKeyToIndex[old.lookupKey];
this.list[i] = this.list.pop();
this.lookupKeyToIndex[this.list[i].lookupKey] = i;
let u = getParent(i);
if (null != u && this.compare(this.list[i], this.list[u]) < 0) {
while (null != u && this.compare(this.list[i], this.list[u]) < 0) {
swap(this.list, i, u, this.lookupKeyToIndex);
i = u;
u = getParent(i);
}
} else {
heapify(this, i);
}
return old;
};
/** /**
* @return {boolean} Whether the heap is empty. * @return {boolean} Whether the heap is empty.
*/ */
BinaryHeap.prototype.isEmpty = function () { BinaryHeap.prototype.isEmpty = function () {
return !this.list.length; return 0 == this.list.length;
}; };
/** /**
@@ -111,16 +154,6 @@ BinaryHeap.prototype.size = function () {
return this.list.length; return this.list.length;
}; };
/**
* Joins another heap to this one.
*
* @param {BinaryHeap} otherHeap The other heap.
*/
BinaryHeap.prototype.union = function (otherHeap) {
var array = this.list.concat(otherHeap.list);
buildHeapFromNodeArray(this, array);
};
/** /**
* Compares two nodes with each other. * Compares two nodes with each other.
* *
@@ -147,34 +180,27 @@ BinaryHeap.prototype.compare = function (a, b) {
* @param {number} i The index of the node to heapify. * @param {number} i The index of the node to heapify.
*/ */
function heapify(heap, i) { function heapify(heap, i) {
var l = getLeft(i); let cur = i;
var r = getRight(i); let smallest = -1;
var smallest = i; while (cur != smallest) {
const l = getLeft(cur);
const r = getRight(cur);
smallest = cur;
if (l < heap.list.length && if (l < heap.list.length &&
heap.compare(heap.list[l], heap.list[i]) < 0) { heap.compare(heap.list[l], heap.list[smallest]) < 0) {
smallest = l; smallest = l;
} }
if (r < heap.list.length && if (r < heap.list.length &&
heap.compare(heap.list[r], heap.list[smallest]) < 0) { heap.compare(heap.list[r], heap.list[smallest]) < 0) {
smallest = r; smallest = r;
} }
if (smallest !== i) {
swap(heap.list, i, smallest);
heapify(heap, smallest);
}
}
/** if (smallest !== cur) {
* Builds a heap from a node array, this will discard the heap's current data. swap(heap.list, cur, smallest, heap.lookupKeyToIndex);
* cur = smallest;
* @private smallest = -1;
* @param {BinaryHeap} heap The heap to override. }
* @param {Node[]} nodeArray The array of nodes for the new heap.
*/
function buildHeapFromNodeArray(heap, nodeArray) {
heap.list = nodeArray;
for (var i = Math.floor(heap.list.length / 2); i >= 0; i--) {
heapify(heap, i);
} }
} }
@@ -186,10 +212,16 @@ function buildHeapFromNodeArray(heap, nodeArray) {
* @param {number} a The index of the first element. * @param {number} a The index of the first element.
* @param {number} b The index of the second element. * @param {number} b The index of the second element.
*/ */
function swap(array, a, b) { function swap(array, a, b, lookupKeyToIndex) {
var aLookupKey = array[a].lookupKey;
var bLookupKey = array[b].lookupKey;
var temp = array[a]; var temp = array[a];
array[a] = array[b]; array[a] = array[b];
array[b] = temp; array[b] = temp;
lookupKeyToIndex[aLookupKey] = b;
lookupKeyToIndex[bLookupKey] = a;
} }
/** /**
@@ -200,8 +232,8 @@ function swap(array, a, b) {
* @return {number} The index of the node's parent. * @return {number} The index of the node's parent.
*/ */
function getParent(i) { function getParent(i) {
if (i === 0) { if (0 == i) {
return undefined; return null;
} }
return Math.floor((i - 1) / 2); return Math.floor((i - 1) / 2);
} }
@@ -235,9 +267,10 @@ function getRight(i) {
* @param {Object} key The key of the new node. * @param {Object} key The key of the new node.
* @param {Object} value The value of the new node. * @param {Object} value The value of the new node.
*/ */
function Node(key, value) { function Node(key, value, lookupKey) {
this.key = key; this.key = key;
this.value = value; this.value = value;
this.lookupKey = lookupKey;
} }
module.exports = BinaryHeap; module.exports = BinaryHeap;

View File

@@ -0,0 +1,9 @@
{
"ver": "1.0.5",
"uuid": "20a75b4a-e220-42cd-bab4-9fc63a289b3f",
"isPlugin": false,
"loadPluginInWeb": true,
"loadPluginInNative": true,
"loadPluginInEditor": false,
"subMetas": {}
}

View File

@@ -11,14 +11,6 @@ cc.Class({
type: cc.Object, type: cc.Object,
default: null default: null
}, },
myAvatarNode: {
type: cc.Node,
default: null,
},
myNameNode: {
type: cc.Node,
default: null,
},
rankingNodes: { rankingNodes: {
type: [cc.Node], type: [cc.Node],
default: [], default: [],
@@ -46,22 +38,6 @@ cc.Class({
showPlayerInfo(playerRichInfoDict) { showPlayerInfo(playerRichInfoDict) {
this.showRanking(playerRichInfoDict); this.showRanking(playerRichInfoDict);
this.showMyAvatar();
this.showMyName();
},
showMyName() {
const selfPlayerInfo = JSON.parse(cc.sys.localStorage.getItem('selfPlayer'));
let name = 'No name';
if (null == selfPlayerInfo.displayName || "" == selfPlayerInfo.displayName) {
name = selfPlayerInfo.name;
} else {
name = selfPlayerInfo.displayName;
}
if (!this.myNameNode) return;
const myNameNodeLabel = this.myNameNode.getComponent(cc.Label);
if (!myNameNodeLabel || null == name) return;
myNameNodeLabel.string = name;
}, },
showRanking(playerRichInfoDict) { showRanking(playerRichInfoDict) {
@@ -115,42 +91,6 @@ cc.Class({
} }
}, },
showMyAvatar() {
const self = this;
const selfPlayerInfo = JSON.parse(cc.sys.localStorage.getItem('selfPlayer'));
let remoteUrl = selfPlayerInfo.avatar;
if (remoteUrl == null || remoteUrl == '') {
cc.log(`No avatar to show for myself, check storage.`);
return;
} else {
cc.loader.load({
url: remoteUrl,
type: 'jpg'
}, function(err, texture) {
if (err != null || texture == null) {
console.log(err);
} else {
const sf = new cc.SpriteFrame();
sf.setTexture(texture);
self.myAvatarNode.getComponent(cc.Sprite).spriteFrame = sf;
}
});
}
},
showRibbon(winnerInfo, ribbonNode) {
const selfPlayerInfo = JSON.parse(cc.sys.localStorage.getItem('selfPlayer'));
const texture = (selfPlayerInfo.playerId == winnerInfo.id) ? "textures/resultPanel/WinRibbon" : "textures/resultPanel/loseRibbon";
cc.loader.loadRes(texture, cc.SpriteFrame, function(err, spriteFrame) {
if (err) {
console.log(err);
return;
}
ribbonNode.getComponent(cc.Sprite).spriteFrame = spriteFrame;
});
},
onClose(evt) { onClose(evt) {
if (this.node.parent) { if (this.node.parent) {
this.node.parent.removeChild(this.node); this.node.parent.removeChild(this.node);

View File

@@ -106,8 +106,13 @@ cc.Class({
this.cachedBtnDownLevel = 0; this.cachedBtnDownLevel = 0;
this.cachedBtnLeftLevel = 0; this.cachedBtnLeftLevel = 0;
this.cachedBtnRightLevel = 0; this.cachedBtnRightLevel = 0;
this.realtimeBtnALevel = 0;
this.cachedBtnALevel = 0; this.cachedBtnALevel = 0;
this.btnAEdgeTriggerLock = false;
this.realtimeBtnBLevel = 0;
this.cachedBtnBLevel = 0; this.cachedBtnBLevel = 0;
this.btnBEdgeTriggerLock = false;
this.canvasNode = this.mapNode.parent; this.canvasNode = this.mapNode.parent;
this.mainCameraNode = this.canvasNode.getChildByName("Main Camera"); // Cannot drag and assign the `mainCameraNode` from CocosCreator EDITOR directly, otherwise it'll cause an infinite loading time, till v2.1.0. this.mainCameraNode = this.canvasNode.getChildByName("Main Camera"); // Cannot drag and assign the `mainCameraNode` from CocosCreator EDITOR directly, otherwise it'll cause an infinite loading time, till v2.1.0.
@@ -163,31 +168,25 @@ cc.Class({
if (self.btnA) { if (self.btnA) {
self.btnA.on(cc.Node.EventType.TOUCH_START, function(evt) { self.btnA.on(cc.Node.EventType.TOUCH_START, function(evt) {
self.cachedBtnALevel = 1; self._triggerEdgeBtnA(true);
evt.target.runAction(cc.scaleTo(0.1, 0.3));
}); });
self.btnA.on(cc.Node.EventType.TOUCH_END, function(evt) { self.btnA.on(cc.Node.EventType.TOUCH_END, function(evt) {
self.cachedBtnALevel = 0; self._triggerEdgeBtnA(false);
evt.target.runAction(cc.scaleTo(0.1, 1.0));
}); });
self.btnA.on(cc.Node.EventType.TOUCH_CANCEL, function(evt) { self.btnA.on(cc.Node.EventType.TOUCH_CANCEL, function(evt) {
self.cachedBtnALevel = 0; self._triggerEdgeBtnA(false);
evt.target.runAction(cc.scaleTo(0.1, 1.0));
}); });
} }
if (self.btnB) { if (self.btnB) {
self.btnB.on(cc.Node.EventType.TOUCH_START, function(evt) { self.btnB.on(cc.Node.EventType.TOUCH_START, function(evt) {
self.cachedBtnBLevel = 1; self._triggerEdgeBtnB(true);
evt.target.runAction(cc.scaleTo(0.1, 0.3));
}); });
self.btnB.on(cc.Node.EventType.TOUCH_END, function(evt) { self.btnB.on(cc.Node.EventType.TOUCH_END, function(evt) {
self.cachedBtnBLevel = 0; self._triggerEdgeBtnB(false);
evt.target.runAction(cc.scaleTo(0.1, 1.0));
}); });
self.btnB.on(cc.Node.EventType.TOUCH_CANCEL, function(evt) { self.btnB.on(cc.Node.EventType.TOUCH_CANCEL, function(evt) {
self.cachedBtnBLevel = 0; self._triggerEdgeBtnB(false);
evt.target.runAction(cc.scaleTo(0.1, 1.0));
}); });
} }
@@ -195,22 +194,38 @@ cc.Class({
cc.systemEvent.on(cc.SystemEvent.EventType.KEY_DOWN, function(evt) { cc.systemEvent.on(cc.SystemEvent.EventType.KEY_DOWN, function(evt) {
switch (evt.keyCode) { switch (evt.keyCode) {
case cc.macro.KEY.w: case cc.macro.KEY.w:
self.cachedBtnUpLevel = 0;
self.cachedBtnDownLevel = 0;
self.cachedBtnLeftLevel = 0;
self.cachedBtnRightLevel = 0;
self.cachedBtnUpLevel = 1; self.cachedBtnUpLevel = 1;
break; break;
case cc.macro.KEY.s: case cc.macro.KEY.s:
self.cachedBtnUpLevel = 0;
self.cachedBtnDownLevel = 0;
self.cachedBtnLeftLevel = 0;
self.cachedBtnRightLevel = 0;
self.cachedBtnDownLevel = 1; self.cachedBtnDownLevel = 1;
break; break;
case cc.macro.KEY.a: case cc.macro.KEY.a:
self.cachedBtnUpLevel = 0;
self.cachedBtnDownLevel = 0;
self.cachedBtnLeftLevel = 0;
self.cachedBtnRightLevel = 0;
self.cachedBtnLeftLevel = 1; self.cachedBtnLeftLevel = 1;
break; break;
case cc.macro.KEY.d: case cc.macro.KEY.d:
self.cachedBtnUpLevel = 0;
self.cachedBtnDownLevel = 0;
self.cachedBtnLeftLevel = 0;
self.cachedBtnRightLevel = 0;
self.cachedBtnRightLevel = 1; self.cachedBtnRightLevel = 1;
break; break;
case cc.macro.KEY.h: case cc.macro.KEY.h:
self.cachedBtnALevel = 1; self._triggerEdgeBtnA(true);
break; break;
case cc.macro.KEY.j: case cc.macro.KEY.j:
self.cachedBtnBLevel = 1; self._triggerEdgeBtnB(true);
break; break;
default: default:
break; break;
@@ -232,10 +247,10 @@ cc.Class({
self.cachedBtnRightLevel = 0; self.cachedBtnRightLevel = 0;
break; break;
case cc.macro.KEY.h: case cc.macro.KEY.h:
self.cachedBtnALevel = 0; self._triggerEdgeBtnA(false);
break; break;
case cc.macro.KEY.j: case cc.macro.KEY.j:
self.cachedBtnBLevel = 0; self._triggerEdgeBtnB(false);
break; break;
default: default:
break; break;
@@ -448,6 +463,12 @@ cc.Class({
const discretizedDir = this.discretizeDirection(this.stickhead.x, this.stickhead.y, this.joyStickEps).encodedIdx; // There're only 9 dirs, thus using only the lower 4-bits const discretizedDir = this.discretizeDirection(this.stickhead.x, this.stickhead.y, this.joyStickEps).encodedIdx; // There're only 9 dirs, thus using only the lower 4-bits
const btnALevel = (this.cachedBtnALevel << 4); const btnALevel = (this.cachedBtnALevel << 4);
const btnBLevel = (this.cachedBtnBLevel << 5); const btnBLevel = (this.cachedBtnBLevel << 5);
this.cachedBtnALevel = this.realtimeBtnALevel;
this.cachedBtnBLevel = this.realtimeBtnBLevel;
this.btnAEdgeTriggerLock = false;
this.btnBEdgeTriggerLock = false;
return (btnBLevel + btnALevel + discretizedDir); return (btnBLevel + btnALevel + discretizedDir);
}, },
@@ -466,4 +487,30 @@ cc.Class({
btnBLevel: btnBLevel, btnBLevel: btnBLevel,
}); });
}, },
_triggerEdgeBtnA(rising) {
this.realtimeBtnALevel = (rising ? 1 : 0);
if (!this.btnAEdgeTriggerLock && (1 - this.realtimeBtnALevel) == this.cachedBtnALevel) {
this.cachedBtnALevel = this.realtimeBtnALevel;
this.btnAEdgeTriggerLock = true;
}
if (rising) {
this.btnA.runAction(cc.scaleTo(0.1, 0.3));
} else {
this.btnA.runAction(cc.scaleTo(0.1, 0.5));
}
},
_triggerEdgeBtnB(rising, evt) {
this.realtimeBtnBLevel = (rising ? 1 : 0);
if (!this.btnBEdgeTriggerLock && (1 - this.realtimeBtnBLevel) == this.cachedBtnBLevel) {
this.cachedBtnBLevel = this.realtimeBtnBLevel;
this.btnBEdgeTriggerLock = true;
}
if (rising) {
this.btnB.runAction(cc.scaleTo(0.1, 0.3));
} else {
this.btnB.runAction(cc.scaleTo(0.1, 0.5));
}
},
}); });

View File

@@ -11,6 +11,7 @@ window.DOWNSYNC_MSG_ACT_HB_REQ = 1;
window.DOWNSYNC_MSG_ACT_INPUT_BATCH = 2; window.DOWNSYNC_MSG_ACT_INPUT_BATCH = 2;
window.DOWNSYNC_MSG_ACT_BATTLE_STOPPED = 3; window.DOWNSYNC_MSG_ACT_BATTLE_STOPPED = 3;
window.DOWNSYNC_MSG_ACT_FORCED_RESYNC = 4; window.DOWNSYNC_MSG_ACT_FORCED_RESYNC = 4;
window.DOWNSYNC_MSG_ACT_PEER_INPUT_BATCH = 5;
window.sendSafely = function(msgStr) { window.sendSafely = function(msgStr) {
/** /**
@@ -65,6 +66,7 @@ window.handleHbRequirements = function(resp) {
} }
if (window.handleBattleColliderInfo) { if (window.handleBattleColliderInfo) {
window.initSecondarySession(null, window.boundRoomId);
window.handleBattleColliderInfo(resp.bciFrame); window.handleBattleColliderInfo(resp.bciFrame);
} }
}; };
@@ -130,8 +132,6 @@ window.initPersistentSessionClient = function(onopenCb, expectedRoomId) {
} }
} }
const currentHistoryState = window.history && window.history.state ? window.history.state : {};
const clientSession = new WebSocket(urlToConnect); const clientSession = new WebSocket(urlToConnect);
clientSession.binaryType = 'arraybuffer'; // Make 'event.data' of 'onmessage' an "ArrayBuffer" instead of a "Blob" clientSession.binaryType = 'arraybuffer'; // Make 'event.data' of 'onmessage' an "ArrayBuffer" instead of a "Blob"
@@ -240,3 +240,56 @@ window.clearLocalStorageAndBackToLoginScene = function(shouldRetainBoundRoomIdIn
cc.director.loadScene('login'); cc.director.loadScene('login');
}; };
// For secondary ws session
window.initSecondarySession = function(onopenCb, boundRoomId) {
if (window.secondarySession && window.secondarySession.readyState == WebSocket.OPEN) {
if (null != onopenCb) {
onopenCb();
}
return;
}
const selfPlayerStr = cc.sys.localStorage.getItem("selfPlayer");
const selfPlayer = null == selfPlayerStr ? null : JSON.parse(selfPlayerStr);
const intAuthToken = null == selfPlayer ? "" : selfPlayer.intAuthToken;
let urlToConnect = backendAddress.PROTOCOL.replace('http', 'ws') + '://' + backendAddress.HOST + ":" + backendAddress.PORT + "/tsrhtSecondary?isSecondary=true&intAuthToken=" + intAuthToken + "&boundRoomId=" + boundRoomId;
const clientSession = new WebSocket(urlToConnect);
clientSession.binaryType = 'arraybuffer'; // Make 'event.data' of 'onmessage' an "ArrayBuffer" instead of a "Blob"
clientSession.onopen = function(evt) {
console.warn("The secondary WS clientSession is opened.");
window.secondarySession = clientSession;
if (null == onopenCb) return;
onopenCb();
};
clientSession.onmessage = function(evt) {
if (null == evt || null == evt.data) {
return;
}
try {
const resp = window.pb.protos.WsResp.decode(new Uint8Array(evt.data));
//console.log(`Got non-empty onmessage decoded: resp.act=${resp.act}`);
switch (resp.act) {
case window.DOWNSYNC_MSG_ACT_PEER_INPUT_BATCH:
mapIns.onPeerInputFrameUpsync(resp.peerJoinIndex, resp.inputFrameDownsyncBatch);
break;
default:
break;
}
} catch (e) {
console.error("Secondary ws session, unexpected error when parsing data of:", evt.data, e);
}
};
clientSession.onerror = function(evt) {
console.error("Secondary ws session, error caught on the WS clientSession: ", evt);
};
clientSession.onclose = function(evt) {
// [WARNING] The callback "onclose" might be called AFTER the webpage is refreshed with "1001 == evt.code".
console.warn(`Secondary ws session is closed: evt=${JSON.stringify(evt)}, evt.code=${evt.code}`);
};
};

View File

@@ -1216,6 +1216,10 @@ $root.protos = (function() {
* @property {number|null} [framesInvinsible] PlayerDownsync framesInvinsible * @property {number|null} [framesInvinsible] PlayerDownsync framesInvinsible
* @property {number|null} [bulletTeamId] PlayerDownsync bulletTeamId * @property {number|null} [bulletTeamId] PlayerDownsync bulletTeamId
* @property {number|null} [chCollisionTeamId] PlayerDownsync chCollisionTeamId * @property {number|null} [chCollisionTeamId] PlayerDownsync chCollisionTeamId
* @property {boolean|null} [onWall] PlayerDownsync onWall
* @property {number|null} [onWallNormX] PlayerDownsync onWallNormX
* @property {number|null} [onWallNormY] PlayerDownsync onWallNormY
* @property {boolean|null} [capturedByInertia] PlayerDownsync capturedByInertia
* @property {string|null} [name] PlayerDownsync name * @property {string|null} [name] PlayerDownsync name
* @property {string|null} [displayName] PlayerDownsync displayName * @property {string|null} [displayName] PlayerDownsync displayName
* @property {string|null} [avatar] PlayerDownsync avatar * @property {string|null} [avatar] PlayerDownsync avatar
@@ -1436,6 +1440,38 @@ $root.protos = (function() {
*/ */
PlayerDownsync.prototype.chCollisionTeamId = 0; PlayerDownsync.prototype.chCollisionTeamId = 0;
/**
* PlayerDownsync onWall.
* @member {boolean} onWall
* @memberof protos.PlayerDownsync
* @instance
*/
PlayerDownsync.prototype.onWall = false;
/**
* PlayerDownsync onWallNormX.
* @member {number} onWallNormX
* @memberof protos.PlayerDownsync
* @instance
*/
PlayerDownsync.prototype.onWallNormX = 0;
/**
* PlayerDownsync onWallNormY.
* @member {number} onWallNormY
* @memberof protos.PlayerDownsync
* @instance
*/
PlayerDownsync.prototype.onWallNormY = 0;
/**
* PlayerDownsync capturedByInertia.
* @member {boolean} capturedByInertia
* @memberof protos.PlayerDownsync
* @instance
*/
PlayerDownsync.prototype.capturedByInertia = false;
/** /**
* PlayerDownsync name. * PlayerDownsync name.
* @member {string} name * @member {string} name
@@ -1534,6 +1570,14 @@ $root.protos = (function() {
writer.uint32(/* id 24, wireType 0 =*/192).int32(message.bulletTeamId); writer.uint32(/* id 24, wireType 0 =*/192).int32(message.bulletTeamId);
if (message.chCollisionTeamId != null && Object.hasOwnProperty.call(message, "chCollisionTeamId")) if (message.chCollisionTeamId != null && Object.hasOwnProperty.call(message, "chCollisionTeamId"))
writer.uint32(/* id 25, wireType 0 =*/200).int32(message.chCollisionTeamId); writer.uint32(/* id 25, wireType 0 =*/200).int32(message.chCollisionTeamId);
if (message.onWall != null && Object.hasOwnProperty.call(message, "onWall"))
writer.uint32(/* id 26, wireType 0 =*/208).bool(message.onWall);
if (message.onWallNormX != null && Object.hasOwnProperty.call(message, "onWallNormX"))
writer.uint32(/* id 27, wireType 0 =*/216).int32(message.onWallNormX);
if (message.onWallNormY != null && Object.hasOwnProperty.call(message, "onWallNormY"))
writer.uint32(/* id 28, wireType 0 =*/224).int32(message.onWallNormY);
if (message.capturedByInertia != null && Object.hasOwnProperty.call(message, "capturedByInertia"))
writer.uint32(/* id 29, wireType 0 =*/232).bool(message.capturedByInertia);
if (message.name != null && Object.hasOwnProperty.call(message, "name")) if (message.name != null && Object.hasOwnProperty.call(message, "name"))
writer.uint32(/* id 997, wireType 2 =*/7978).string(message.name); writer.uint32(/* id 997, wireType 2 =*/7978).string(message.name);
if (message.displayName != null && Object.hasOwnProperty.call(message, "displayName")) if (message.displayName != null && Object.hasOwnProperty.call(message, "displayName"))
@@ -1674,6 +1718,22 @@ $root.protos = (function() {
message.chCollisionTeamId = reader.int32(); message.chCollisionTeamId = reader.int32();
break; break;
} }
case 26: {
message.onWall = reader.bool();
break;
}
case 27: {
message.onWallNormX = reader.int32();
break;
}
case 28: {
message.onWallNormY = reader.int32();
break;
}
case 29: {
message.capturedByInertia = reader.bool();
break;
}
case 997: { case 997: {
message.name = reader.string(); message.name = reader.string();
break; break;
@@ -1796,6 +1856,18 @@ $root.protos = (function() {
if (message.chCollisionTeamId != null && message.hasOwnProperty("chCollisionTeamId")) if (message.chCollisionTeamId != null && message.hasOwnProperty("chCollisionTeamId"))
if (!$util.isInteger(message.chCollisionTeamId)) if (!$util.isInteger(message.chCollisionTeamId))
return "chCollisionTeamId: integer expected"; return "chCollisionTeamId: integer expected";
if (message.onWall != null && message.hasOwnProperty("onWall"))
if (typeof message.onWall !== "boolean")
return "onWall: boolean expected";
if (message.onWallNormX != null && message.hasOwnProperty("onWallNormX"))
if (!$util.isInteger(message.onWallNormX))
return "onWallNormX: integer expected";
if (message.onWallNormY != null && message.hasOwnProperty("onWallNormY"))
if (!$util.isInteger(message.onWallNormY))
return "onWallNormY: integer expected";
if (message.capturedByInertia != null && message.hasOwnProperty("capturedByInertia"))
if (typeof message.capturedByInertia !== "boolean")
return "capturedByInertia: boolean expected";
if (message.name != null && message.hasOwnProperty("name")) if (message.name != null && message.hasOwnProperty("name"))
if (!$util.isString(message.name)) if (!$util.isString(message.name))
return "name: string expected"; return "name: string expected";
@@ -1870,6 +1942,14 @@ $root.protos = (function() {
message.bulletTeamId = object.bulletTeamId | 0; message.bulletTeamId = object.bulletTeamId | 0;
if (object.chCollisionTeamId != null) if (object.chCollisionTeamId != null)
message.chCollisionTeamId = object.chCollisionTeamId | 0; message.chCollisionTeamId = object.chCollisionTeamId | 0;
if (object.onWall != null)
message.onWall = Boolean(object.onWall);
if (object.onWallNormX != null)
message.onWallNormX = object.onWallNormX | 0;
if (object.onWallNormY != null)
message.onWallNormY = object.onWallNormY | 0;
if (object.capturedByInertia != null)
message.capturedByInertia = Boolean(object.capturedByInertia);
if (object.name != null) if (object.name != null)
message.name = String(object.name); message.name = String(object.name);
if (object.displayName != null) if (object.displayName != null)
@@ -1918,6 +1998,10 @@ $root.protos = (function() {
object.framesInvinsible = 0; object.framesInvinsible = 0;
object.bulletTeamId = 0; object.bulletTeamId = 0;
object.chCollisionTeamId = 0; object.chCollisionTeamId = 0;
object.onWall = false;
object.onWallNormX = 0;
object.onWallNormY = 0;
object.capturedByInertia = false;
object.name = ""; object.name = "";
object.displayName = ""; object.displayName = "";
object.avatar = ""; object.avatar = "";
@@ -1972,6 +2056,14 @@ $root.protos = (function() {
object.bulletTeamId = message.bulletTeamId; object.bulletTeamId = message.bulletTeamId;
if (message.chCollisionTeamId != null && message.hasOwnProperty("chCollisionTeamId")) if (message.chCollisionTeamId != null && message.hasOwnProperty("chCollisionTeamId"))
object.chCollisionTeamId = message.chCollisionTeamId; object.chCollisionTeamId = message.chCollisionTeamId;
if (message.onWall != null && message.hasOwnProperty("onWall"))
object.onWall = message.onWall;
if (message.onWallNormX != null && message.hasOwnProperty("onWallNormX"))
object.onWallNormX = message.onWallNormX;
if (message.onWallNormY != null && message.hasOwnProperty("onWallNormY"))
object.onWallNormY = message.onWallNormY;
if (message.capturedByInertia != null && message.hasOwnProperty("capturedByInertia"))
object.capturedByInertia = message.capturedByInertia;
if (message.name != null && message.hasOwnProperty("name")) if (message.name != null && message.hasOwnProperty("name"))
object.name = message.name; object.name = message.name;
if (message.displayName != null && message.hasOwnProperty("displayName")) if (message.displayName != null && message.hasOwnProperty("displayName"))
@@ -2291,6 +2383,7 @@ $root.protos = (function() {
* @interface IInputFrameUpsync * @interface IInputFrameUpsync
* @property {number|null} [inputFrameId] InputFrameUpsync inputFrameId * @property {number|null} [inputFrameId] InputFrameUpsync inputFrameId
* @property {number|Long|null} [encoded] InputFrameUpsync encoded * @property {number|Long|null} [encoded] InputFrameUpsync encoded
* @property {number|null} [joinIndex] InputFrameUpsync joinIndex
*/ */
/** /**
@@ -2324,6 +2417,14 @@ $root.protos = (function() {
*/ */
InputFrameUpsync.prototype.encoded = $util.Long ? $util.Long.fromBits(0,0,true) : 0; InputFrameUpsync.prototype.encoded = $util.Long ? $util.Long.fromBits(0,0,true) : 0;
/**
* InputFrameUpsync joinIndex.
* @member {number} joinIndex
* @memberof protos.InputFrameUpsync
* @instance
*/
InputFrameUpsync.prototype.joinIndex = 0;
/** /**
* Creates a new InputFrameUpsync instance using the specified properties. * Creates a new InputFrameUpsync instance using the specified properties.
* @function create * @function create
@@ -2352,6 +2453,8 @@ $root.protos = (function() {
writer.uint32(/* id 1, wireType 0 =*/8).int32(message.inputFrameId); writer.uint32(/* id 1, wireType 0 =*/8).int32(message.inputFrameId);
if (message.encoded != null && Object.hasOwnProperty.call(message, "encoded")) if (message.encoded != null && Object.hasOwnProperty.call(message, "encoded"))
writer.uint32(/* id 2, wireType 0 =*/16).uint64(message.encoded); writer.uint32(/* id 2, wireType 0 =*/16).uint64(message.encoded);
if (message.joinIndex != null && Object.hasOwnProperty.call(message, "joinIndex"))
writer.uint32(/* id 3, wireType 0 =*/24).int32(message.joinIndex);
return writer; return writer;
}; };
@@ -2394,6 +2497,10 @@ $root.protos = (function() {
message.encoded = reader.uint64(); message.encoded = reader.uint64();
break; break;
} }
case 3: {
message.joinIndex = reader.int32();
break;
}
default: default:
reader.skipType(tag & 7); reader.skipType(tag & 7);
break; break;
@@ -2435,6 +2542,9 @@ $root.protos = (function() {
if (message.encoded != null && message.hasOwnProperty("encoded")) if (message.encoded != null && message.hasOwnProperty("encoded"))
if (!$util.isInteger(message.encoded) && !(message.encoded && $util.isInteger(message.encoded.low) && $util.isInteger(message.encoded.high))) if (!$util.isInteger(message.encoded) && !(message.encoded && $util.isInteger(message.encoded.low) && $util.isInteger(message.encoded.high)))
return "encoded: integer|Long expected"; return "encoded: integer|Long expected";
if (message.joinIndex != null && message.hasOwnProperty("joinIndex"))
if (!$util.isInteger(message.joinIndex))
return "joinIndex: integer expected";
return null; return null;
}; };
@@ -2461,6 +2571,8 @@ $root.protos = (function() {
message.encoded = object.encoded; message.encoded = object.encoded;
else if (typeof object.encoded === "object") else if (typeof object.encoded === "object")
message.encoded = new $util.LongBits(object.encoded.low >>> 0, object.encoded.high >>> 0).toNumber(true); message.encoded = new $util.LongBits(object.encoded.low >>> 0, object.encoded.high >>> 0).toNumber(true);
if (object.joinIndex != null)
message.joinIndex = object.joinIndex | 0;
return message; return message;
}; };
@@ -2484,6 +2596,7 @@ $root.protos = (function() {
object.encoded = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long; object.encoded = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
} else } else
object.encoded = options.longs === String ? "0" : 0; object.encoded = options.longs === String ? "0" : 0;
object.joinIndex = 0;
} }
if (message.inputFrameId != null && message.hasOwnProperty("inputFrameId")) if (message.inputFrameId != null && message.hasOwnProperty("inputFrameId"))
object.inputFrameId = message.inputFrameId; object.inputFrameId = message.inputFrameId;
@@ -2492,6 +2605,8 @@ $root.protos = (function() {
object.encoded = options.longs === String ? String(message.encoded) : message.encoded; object.encoded = options.longs === String ? String(message.encoded) : message.encoded;
else else
object.encoded = options.longs === String ? $util.Long.prototype.toString.call(message.encoded) : options.longs === Number ? new $util.LongBits(message.encoded.low >>> 0, message.encoded.high >>> 0).toNumber(true) : message.encoded; object.encoded = options.longs === String ? $util.Long.prototype.toString.call(message.encoded) : options.longs === Number ? new $util.LongBits(message.encoded.low >>> 0, message.encoded.high >>> 0).toNumber(true) : message.encoded;
if (message.joinIndex != null && message.hasOwnProperty("joinIndex"))
object.joinIndex = message.joinIndex;
return object; return object;
}; };
@@ -3444,6 +3559,7 @@ $root.protos = (function() {
* @property {protos.RoomDownsyncFrame|null} [rdf] WsResp rdf * @property {protos.RoomDownsyncFrame|null} [rdf] WsResp rdf
* @property {Array.<protos.InputFrameDownsync>|null} [inputFrameDownsyncBatch] WsResp inputFrameDownsyncBatch * @property {Array.<protos.InputFrameDownsync>|null} [inputFrameDownsyncBatch] WsResp inputFrameDownsyncBatch
* @property {protos.BattleColliderInfo|null} [bciFrame] WsResp bciFrame * @property {protos.BattleColliderInfo|null} [bciFrame] WsResp bciFrame
* @property {number|null} [peerJoinIndex] WsResp peerJoinIndex
*/ */
/** /**
@@ -3510,6 +3626,14 @@ $root.protos = (function() {
*/ */
WsResp.prototype.bciFrame = null; WsResp.prototype.bciFrame = null;
/**
* WsResp peerJoinIndex.
* @member {number} peerJoinIndex
* @memberof protos.WsResp
* @instance
*/
WsResp.prototype.peerJoinIndex = 0;
/** /**
* Creates a new WsResp instance using the specified properties. * Creates a new WsResp instance using the specified properties.
* @function create * @function create
@@ -3547,6 +3671,8 @@ $root.protos = (function() {
$root.protos.InputFrameDownsync.encode(message.inputFrameDownsyncBatch[i], writer.uint32(/* id 5, wireType 2 =*/42).fork()).ldelim(); $root.protos.InputFrameDownsync.encode(message.inputFrameDownsyncBatch[i], writer.uint32(/* id 5, wireType 2 =*/42).fork()).ldelim();
if (message.bciFrame != null && Object.hasOwnProperty.call(message, "bciFrame")) if (message.bciFrame != null && Object.hasOwnProperty.call(message, "bciFrame"))
$root.protos.BattleColliderInfo.encode(message.bciFrame, writer.uint32(/* id 6, wireType 2 =*/50).fork()).ldelim(); $root.protos.BattleColliderInfo.encode(message.bciFrame, writer.uint32(/* id 6, wireType 2 =*/50).fork()).ldelim();
if (message.peerJoinIndex != null && Object.hasOwnProperty.call(message, "peerJoinIndex"))
writer.uint32(/* id 7, wireType 0 =*/56).int32(message.peerJoinIndex);
return writer; return writer;
}; };
@@ -3607,6 +3733,10 @@ $root.protos = (function() {
message.bciFrame = $root.protos.BattleColliderInfo.decode(reader, reader.uint32()); message.bciFrame = $root.protos.BattleColliderInfo.decode(reader, reader.uint32());
break; break;
} }
case 7: {
message.peerJoinIndex = reader.int32();
break;
}
default: default:
reader.skipType(tag & 7); reader.skipType(tag & 7);
break; break;
@@ -3670,6 +3800,9 @@ $root.protos = (function() {
if (error) if (error)
return "bciFrame." + error; return "bciFrame." + error;
} }
if (message.peerJoinIndex != null && message.hasOwnProperty("peerJoinIndex"))
if (!$util.isInteger(message.peerJoinIndex))
return "peerJoinIndex: integer expected";
return null; return null;
}; };
@@ -3711,6 +3844,8 @@ $root.protos = (function() {
throw TypeError(".protos.WsResp.bciFrame: object expected"); throw TypeError(".protos.WsResp.bciFrame: object expected");
message.bciFrame = $root.protos.BattleColliderInfo.fromObject(object.bciFrame); message.bciFrame = $root.protos.BattleColliderInfo.fromObject(object.bciFrame);
} }
if (object.peerJoinIndex != null)
message.peerJoinIndex = object.peerJoinIndex | 0;
return message; return message;
}; };
@@ -3735,6 +3870,7 @@ $root.protos = (function() {
object.act = 0; object.act = 0;
object.rdf = null; object.rdf = null;
object.bciFrame = null; object.bciFrame = null;
object.peerJoinIndex = 0;
} }
if (message.ret != null && message.hasOwnProperty("ret")) if (message.ret != null && message.hasOwnProperty("ret"))
object.ret = message.ret; object.ret = message.ret;
@@ -3751,6 +3887,8 @@ $root.protos = (function() {
} }
if (message.bciFrame != null && message.hasOwnProperty("bciFrame")) if (message.bciFrame != null && message.hasOwnProperty("bciFrame"))
object.bciFrame = $root.protos.BattleColliderInfo.toObject(message.bciFrame, options); object.bciFrame = $root.protos.BattleColliderInfo.toObject(message.bciFrame, options);
if (message.peerJoinIndex != null && message.hasOwnProperty("peerJoinIndex"))
object.peerJoinIndex = message.peerJoinIndex;
return object; return object;
}; };
@@ -3793,6 +3931,7 @@ $root.protos = (function() {
* @property {number|Long|null} [unconfirmedMask] InputsBufferSnapshot unconfirmedMask * @property {number|Long|null} [unconfirmedMask] InputsBufferSnapshot unconfirmedMask
* @property {Array.<protos.InputFrameDownsync>|null} [toSendInputFrameDownsyncs] InputsBufferSnapshot toSendInputFrameDownsyncs * @property {Array.<protos.InputFrameDownsync>|null} [toSendInputFrameDownsyncs] InputsBufferSnapshot toSendInputFrameDownsyncs
* @property {boolean|null} [shouldForceResync] InputsBufferSnapshot shouldForceResync * @property {boolean|null} [shouldForceResync] InputsBufferSnapshot shouldForceResync
* @property {number|null} [peerJoinIndex] InputsBufferSnapshot peerJoinIndex
*/ */
/** /**
@@ -3843,6 +3982,14 @@ $root.protos = (function() {
*/ */
InputsBufferSnapshot.prototype.shouldForceResync = false; InputsBufferSnapshot.prototype.shouldForceResync = false;
/**
* InputsBufferSnapshot peerJoinIndex.
* @member {number} peerJoinIndex
* @memberof protos.InputsBufferSnapshot
* @instance
*/
InputsBufferSnapshot.prototype.peerJoinIndex = 0;
/** /**
* Creates a new InputsBufferSnapshot instance using the specified properties. * Creates a new InputsBufferSnapshot instance using the specified properties.
* @function create * @function create
@@ -3876,6 +4023,8 @@ $root.protos = (function() {
$root.protos.InputFrameDownsync.encode(message.toSendInputFrameDownsyncs[i], writer.uint32(/* id 3, wireType 2 =*/26).fork()).ldelim(); $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")) if (message.shouldForceResync != null && Object.hasOwnProperty.call(message, "shouldForceResync"))
writer.uint32(/* id 4, wireType 0 =*/32).bool(message.shouldForceResync); writer.uint32(/* id 4, wireType 0 =*/32).bool(message.shouldForceResync);
if (message.peerJoinIndex != null && Object.hasOwnProperty.call(message, "peerJoinIndex"))
writer.uint32(/* id 5, wireType 0 =*/40).int32(message.peerJoinIndex);
return writer; return writer;
}; };
@@ -3928,6 +4077,10 @@ $root.protos = (function() {
message.shouldForceResync = reader.bool(); message.shouldForceResync = reader.bool();
break; break;
} }
case 5: {
message.peerJoinIndex = reader.int32();
break;
}
default: default:
reader.skipType(tag & 7); reader.skipType(tag & 7);
break; break;
@@ -3981,6 +4134,9 @@ $root.protos = (function() {
if (message.shouldForceResync != null && message.hasOwnProperty("shouldForceResync")) if (message.shouldForceResync != null && message.hasOwnProperty("shouldForceResync"))
if (typeof message.shouldForceResync !== "boolean") if (typeof message.shouldForceResync !== "boolean")
return "shouldForceResync: boolean expected"; return "shouldForceResync: boolean expected";
if (message.peerJoinIndex != null && message.hasOwnProperty("peerJoinIndex"))
if (!$util.isInteger(message.peerJoinIndex))
return "peerJoinIndex: integer expected";
return null; return null;
}; };
@@ -4019,6 +4175,8 @@ $root.protos = (function() {
} }
if (object.shouldForceResync != null) if (object.shouldForceResync != null)
message.shouldForceResync = Boolean(object.shouldForceResync); message.shouldForceResync = Boolean(object.shouldForceResync);
if (object.peerJoinIndex != null)
message.peerJoinIndex = object.peerJoinIndex | 0;
return message; return message;
}; };
@@ -4045,6 +4203,7 @@ $root.protos = (function() {
} else } else
object.unconfirmedMask = options.longs === String ? "0" : 0; object.unconfirmedMask = options.longs === String ? "0" : 0;
object.shouldForceResync = false; object.shouldForceResync = false;
object.peerJoinIndex = 0;
} }
if (message.refRenderFrameId != null && message.hasOwnProperty("refRenderFrameId")) if (message.refRenderFrameId != null && message.hasOwnProperty("refRenderFrameId"))
object.refRenderFrameId = message.refRenderFrameId; object.refRenderFrameId = message.refRenderFrameId;
@@ -4060,6 +4219,8 @@ $root.protos = (function() {
} }
if (message.shouldForceResync != null && message.hasOwnProperty("shouldForceResync")) if (message.shouldForceResync != null && message.hasOwnProperty("shouldForceResync"))
object.shouldForceResync = message.shouldForceResync; object.shouldForceResync = message.shouldForceResync;
if (message.peerJoinIndex != null && message.hasOwnProperty("peerJoinIndex"))
object.peerJoinIndex = message.peerJoinIndex;
return object; return object;
}; };
@@ -4118,6 +4279,10 @@ $root.protos = (function() {
* @property {boolean|null} [blowUp] MeleeBullet blowUp * @property {boolean|null} [blowUp] MeleeBullet blowUp
* @property {number|null} [teamId] MeleeBullet teamId * @property {number|null} [teamId] MeleeBullet teamId
* @property {number|null} [bulletLocalId] MeleeBullet bulletLocalId * @property {number|null} [bulletLocalId] MeleeBullet bulletLocalId
* @property {number|null} [speciesId] MeleeBullet speciesId
* @property {number|null} [explosionFrames] MeleeBullet explosionFrames
* @property {number|null} [blState] MeleeBullet blState
* @property {number|null} [framesInBlState] MeleeBullet framesInBlState
*/ */
/** /**
@@ -4295,6 +4460,38 @@ $root.protos = (function() {
*/ */
MeleeBullet.prototype.bulletLocalId = 0; MeleeBullet.prototype.bulletLocalId = 0;
/**
* MeleeBullet speciesId.
* @member {number} speciesId
* @memberof protos.MeleeBullet
* @instance
*/
MeleeBullet.prototype.speciesId = 0;
/**
* MeleeBullet explosionFrames.
* @member {number} explosionFrames
* @memberof protos.MeleeBullet
* @instance
*/
MeleeBullet.prototype.explosionFrames = 0;
/**
* MeleeBullet blState.
* @member {number} blState
* @memberof protos.MeleeBullet
* @instance
*/
MeleeBullet.prototype.blState = 0;
/**
* MeleeBullet framesInBlState.
* @member {number} framesInBlState
* @memberof protos.MeleeBullet
* @instance
*/
MeleeBullet.prototype.framesInBlState = 0;
/** /**
* Creates a new MeleeBullet instance using the specified properties. * Creates a new MeleeBullet instance using the specified properties.
* @function create * @function create
@@ -4359,6 +4556,14 @@ $root.protos = (function() {
writer.uint32(/* id 19, wireType 0 =*/152).int32(message.teamId); writer.uint32(/* id 19, wireType 0 =*/152).int32(message.teamId);
if (message.bulletLocalId != null && Object.hasOwnProperty.call(message, "bulletLocalId")) if (message.bulletLocalId != null && Object.hasOwnProperty.call(message, "bulletLocalId"))
writer.uint32(/* id 20, wireType 0 =*/160).int32(message.bulletLocalId); writer.uint32(/* id 20, wireType 0 =*/160).int32(message.bulletLocalId);
if (message.speciesId != null && Object.hasOwnProperty.call(message, "speciesId"))
writer.uint32(/* id 21, wireType 0 =*/168).int32(message.speciesId);
if (message.explosionFrames != null && Object.hasOwnProperty.call(message, "explosionFrames"))
writer.uint32(/* id 22, wireType 0 =*/176).int32(message.explosionFrames);
if (message.blState != null && Object.hasOwnProperty.call(message, "blState"))
writer.uint32(/* id 23, wireType 0 =*/184).int32(message.blState);
if (message.framesInBlState != null && Object.hasOwnProperty.call(message, "framesInBlState"))
writer.uint32(/* id 24, wireType 0 =*/192).int32(message.framesInBlState);
return writer; return writer;
}; };
@@ -4473,6 +4678,22 @@ $root.protos = (function() {
message.bulletLocalId = reader.int32(); message.bulletLocalId = reader.int32();
break; break;
} }
case 21: {
message.speciesId = reader.int32();
break;
}
case 22: {
message.explosionFrames = reader.int32();
break;
}
case 23: {
message.blState = reader.int32();
break;
}
case 24: {
message.framesInBlState = reader.int32();
break;
}
default: default:
reader.skipType(tag & 7); reader.skipType(tag & 7);
break; break;
@@ -4568,6 +4789,18 @@ $root.protos = (function() {
if (message.bulletLocalId != null && message.hasOwnProperty("bulletLocalId")) if (message.bulletLocalId != null && message.hasOwnProperty("bulletLocalId"))
if (!$util.isInteger(message.bulletLocalId)) if (!$util.isInteger(message.bulletLocalId))
return "bulletLocalId: integer expected"; return "bulletLocalId: integer expected";
if (message.speciesId != null && message.hasOwnProperty("speciesId"))
if (!$util.isInteger(message.speciesId))
return "speciesId: integer expected";
if (message.explosionFrames != null && message.hasOwnProperty("explosionFrames"))
if (!$util.isInteger(message.explosionFrames))
return "explosionFrames: integer expected";
if (message.blState != null && message.hasOwnProperty("blState"))
if (!$util.isInteger(message.blState))
return "blState: integer expected";
if (message.framesInBlState != null && message.hasOwnProperty("framesInBlState"))
if (!$util.isInteger(message.framesInBlState))
return "framesInBlState: integer expected";
return null; return null;
}; };
@@ -4623,6 +4856,14 @@ $root.protos = (function() {
message.teamId = object.teamId | 0; message.teamId = object.teamId | 0;
if (object.bulletLocalId != null) if (object.bulletLocalId != null)
message.bulletLocalId = object.bulletLocalId | 0; message.bulletLocalId = object.bulletLocalId | 0;
if (object.speciesId != null)
message.speciesId = object.speciesId | 0;
if (object.explosionFrames != null)
message.explosionFrames = object.explosionFrames | 0;
if (object.blState != null)
message.blState = object.blState | 0;
if (object.framesInBlState != null)
message.framesInBlState = object.framesInBlState | 0;
return message; return message;
}; };
@@ -4660,6 +4901,10 @@ $root.protos = (function() {
object.blowUp = false; object.blowUp = false;
object.teamId = 0; object.teamId = 0;
object.bulletLocalId = 0; object.bulletLocalId = 0;
object.speciesId = 0;
object.explosionFrames = 0;
object.blState = 0;
object.framesInBlState = 0;
} }
if (message.originatedRenderFrameId != null && message.hasOwnProperty("originatedRenderFrameId")) if (message.originatedRenderFrameId != null && message.hasOwnProperty("originatedRenderFrameId"))
object.originatedRenderFrameId = message.originatedRenderFrameId; object.originatedRenderFrameId = message.originatedRenderFrameId;
@@ -4701,6 +4946,14 @@ $root.protos = (function() {
object.teamId = message.teamId; object.teamId = message.teamId;
if (message.bulletLocalId != null && message.hasOwnProperty("bulletLocalId")) if (message.bulletLocalId != null && message.hasOwnProperty("bulletLocalId"))
object.bulletLocalId = message.bulletLocalId; object.bulletLocalId = message.bulletLocalId;
if (message.speciesId != null && message.hasOwnProperty("speciesId"))
object.speciesId = message.speciesId;
if (message.explosionFrames != null && message.hasOwnProperty("explosionFrames"))
object.explosionFrames = message.explosionFrames;
if (message.blState != null && message.hasOwnProperty("blState"))
object.blState = message.blState;
if (message.framesInBlState != null && message.hasOwnProperty("framesInBlState"))
object.framesInBlState = message.framesInBlState;
return object; return object;
}; };
@@ -4759,6 +5012,10 @@ $root.protos = (function() {
* @property {boolean|null} [blowUp] FireballBullet blowUp * @property {boolean|null} [blowUp] FireballBullet blowUp
* @property {number|null} [teamId] FireballBullet teamId * @property {number|null} [teamId] FireballBullet teamId
* @property {number|null} [bulletLocalId] FireballBullet bulletLocalId * @property {number|null} [bulletLocalId] FireballBullet bulletLocalId
* @property {number|null} [speciesId] FireballBullet speciesId
* @property {number|null} [explosionFrames] FireballBullet explosionFrames
* @property {number|null} [blState] FireballBullet blState
* @property {number|null} [framesInBlState] FireballBullet framesInBlState
* @property {number|null} [virtualGridX] FireballBullet virtualGridX * @property {number|null} [virtualGridX] FireballBullet virtualGridX
* @property {number|null} [virtualGridY] FireballBullet virtualGridY * @property {number|null} [virtualGridY] FireballBullet virtualGridY
* @property {number|null} [dirX] FireballBullet dirX * @property {number|null} [dirX] FireballBullet dirX
@@ -4943,6 +5200,38 @@ $root.protos = (function() {
*/ */
FireballBullet.prototype.bulletLocalId = 0; FireballBullet.prototype.bulletLocalId = 0;
/**
* FireballBullet speciesId.
* @member {number} speciesId
* @memberof protos.FireballBullet
* @instance
*/
FireballBullet.prototype.speciesId = 0;
/**
* FireballBullet explosionFrames.
* @member {number} explosionFrames
* @memberof protos.FireballBullet
* @instance
*/
FireballBullet.prototype.explosionFrames = 0;
/**
* FireballBullet blState.
* @member {number} blState
* @memberof protos.FireballBullet
* @instance
*/
FireballBullet.prototype.blState = 0;
/**
* FireballBullet framesInBlState.
* @member {number} framesInBlState
* @memberof protos.FireballBullet
* @instance
*/
FireballBullet.prototype.framesInBlState = 0;
/** /**
* FireballBullet virtualGridX. * FireballBullet virtualGridX.
* @member {number} virtualGridX * @member {number} virtualGridX
@@ -5063,6 +5352,14 @@ $root.protos = (function() {
writer.uint32(/* id 19, wireType 0 =*/152).int32(message.teamId); writer.uint32(/* id 19, wireType 0 =*/152).int32(message.teamId);
if (message.bulletLocalId != null && Object.hasOwnProperty.call(message, "bulletLocalId")) if (message.bulletLocalId != null && Object.hasOwnProperty.call(message, "bulletLocalId"))
writer.uint32(/* id 20, wireType 0 =*/160).int32(message.bulletLocalId); writer.uint32(/* id 20, wireType 0 =*/160).int32(message.bulletLocalId);
if (message.speciesId != null && Object.hasOwnProperty.call(message, "speciesId"))
writer.uint32(/* id 21, wireType 0 =*/168).int32(message.speciesId);
if (message.explosionFrames != null && Object.hasOwnProperty.call(message, "explosionFrames"))
writer.uint32(/* id 22, wireType 0 =*/176).int32(message.explosionFrames);
if (message.blState != null && Object.hasOwnProperty.call(message, "blState"))
writer.uint32(/* id 23, wireType 0 =*/184).int32(message.blState);
if (message.framesInBlState != null && Object.hasOwnProperty.call(message, "framesInBlState"))
writer.uint32(/* id 24, wireType 0 =*/192).int32(message.framesInBlState);
if (message.virtualGridX != null && Object.hasOwnProperty.call(message, "virtualGridX")) if (message.virtualGridX != null && Object.hasOwnProperty.call(message, "virtualGridX"))
writer.uint32(/* id 999, wireType 0 =*/7992).int32(message.virtualGridX); writer.uint32(/* id 999, wireType 0 =*/7992).int32(message.virtualGridX);
if (message.virtualGridY != null && Object.hasOwnProperty.call(message, "virtualGridY")) if (message.virtualGridY != null && Object.hasOwnProperty.call(message, "virtualGridY"))
@@ -5191,6 +5488,22 @@ $root.protos = (function() {
message.bulletLocalId = reader.int32(); message.bulletLocalId = reader.int32();
break; break;
} }
case 21: {
message.speciesId = reader.int32();
break;
}
case 22: {
message.explosionFrames = reader.int32();
break;
}
case 23: {
message.blState = reader.int32();
break;
}
case 24: {
message.framesInBlState = reader.int32();
break;
}
case 999: { case 999: {
message.virtualGridX = reader.int32(); message.virtualGridX = reader.int32();
break; break;
@@ -5314,6 +5627,18 @@ $root.protos = (function() {
if (message.bulletLocalId != null && message.hasOwnProperty("bulletLocalId")) if (message.bulletLocalId != null && message.hasOwnProperty("bulletLocalId"))
if (!$util.isInteger(message.bulletLocalId)) if (!$util.isInteger(message.bulletLocalId))
return "bulletLocalId: integer expected"; return "bulletLocalId: integer expected";
if (message.speciesId != null && message.hasOwnProperty("speciesId"))
if (!$util.isInteger(message.speciesId))
return "speciesId: integer expected";
if (message.explosionFrames != null && message.hasOwnProperty("explosionFrames"))
if (!$util.isInteger(message.explosionFrames))
return "explosionFrames: integer expected";
if (message.blState != null && message.hasOwnProperty("blState"))
if (!$util.isInteger(message.blState))
return "blState: integer expected";
if (message.framesInBlState != null && message.hasOwnProperty("framesInBlState"))
if (!$util.isInteger(message.framesInBlState))
return "framesInBlState: integer expected";
if (message.virtualGridX != null && message.hasOwnProperty("virtualGridX")) if (message.virtualGridX != null && message.hasOwnProperty("virtualGridX"))
if (!$util.isInteger(message.virtualGridX)) if (!$util.isInteger(message.virtualGridX))
return "virtualGridX: integer expected"; return "virtualGridX: integer expected";
@@ -5390,6 +5715,14 @@ $root.protos = (function() {
message.teamId = object.teamId | 0; message.teamId = object.teamId | 0;
if (object.bulletLocalId != null) if (object.bulletLocalId != null)
message.bulletLocalId = object.bulletLocalId | 0; message.bulletLocalId = object.bulletLocalId | 0;
if (object.speciesId != null)
message.speciesId = object.speciesId | 0;
if (object.explosionFrames != null)
message.explosionFrames = object.explosionFrames | 0;
if (object.blState != null)
message.blState = object.blState | 0;
if (object.framesInBlState != null)
message.framesInBlState = object.framesInBlState | 0;
if (object.virtualGridX != null) if (object.virtualGridX != null)
message.virtualGridX = object.virtualGridX | 0; message.virtualGridX = object.virtualGridX | 0;
if (object.virtualGridY != null) if (object.virtualGridY != null)
@@ -5441,6 +5774,10 @@ $root.protos = (function() {
object.blowUp = false; object.blowUp = false;
object.teamId = 0; object.teamId = 0;
object.bulletLocalId = 0; object.bulletLocalId = 0;
object.speciesId = 0;
object.explosionFrames = 0;
object.blState = 0;
object.framesInBlState = 0;
object.virtualGridX = 0; object.virtualGridX = 0;
object.virtualGridY = 0; object.virtualGridY = 0;
object.dirX = 0; object.dirX = 0;
@@ -5489,6 +5826,14 @@ $root.protos = (function() {
object.teamId = message.teamId; object.teamId = message.teamId;
if (message.bulletLocalId != null && message.hasOwnProperty("bulletLocalId")) if (message.bulletLocalId != null && message.hasOwnProperty("bulletLocalId"))
object.bulletLocalId = message.bulletLocalId; object.bulletLocalId = message.bulletLocalId;
if (message.speciesId != null && message.hasOwnProperty("speciesId"))
object.speciesId = message.speciesId;
if (message.explosionFrames != null && message.hasOwnProperty("explosionFrames"))
object.explosionFrames = message.explosionFrames;
if (message.blState != null && message.hasOwnProperty("blState"))
object.blState = message.blState;
if (message.framesInBlState != null && message.hasOwnProperty("framesInBlState"))
object.framesInBlState = message.framesInBlState;
if (message.virtualGridX != null && message.hasOwnProperty("virtualGridX")) if (message.virtualGridX != null && message.hasOwnProperty("virtualGridX"))
object.virtualGridX = message.virtualGridX; object.virtualGridX = message.virtualGridX;
if (message.virtualGridY != null && message.hasOwnProperty("virtualGridY")) if (message.virtualGridY != null && message.hasOwnProperty("virtualGridY"))

View File

@@ -68,7 +68,7 @@
"shelter_z_reducer", "shelter_z_reducer",
"shelter" "shelter"
], ],
"last-module-event-record-time": 1673325961305, "last-module-event-record-time": 1673930863015,
"simulator-orientation": false, "simulator-orientation": false,
"simulator-resolution": { "simulator-resolution": {
"height": 640, "height": 640,

View File

@@ -6,16 +6,22 @@ all: help
GOPROXY=https://goproxy.io GOPROXY=https://goproxy.io
serve: serve:
gopherjs clean
gopherjs serve $(PROJECTNAME) gopherjs serve $(PROJECTNAME)
build: clean:
gopherjs build $(PROJECTNAME) gopherjs clean
rm ../frontend/assets/plugin_scripts/jsexport.js && mv ./jsexport.js ../frontend/assets/plugin_scripts/jsexport.js rm -f ../frontend/assets/plugin_scripts/jsexport.js
#rm -f ../frontend/assets/plugin_scripts/jsexport.js.map
build-min: build: clean
gopherjs build $(PROJECTNAME)
mv ./jsexport.js ../frontend/assets/plugin_scripts/
#mv ./jsexport.js.map ../frontend/assets/plugin_scripts/
build-min: clean
gopherjs build -m $(PROJECTNAME) gopherjs build -m $(PROJECTNAME)
rm ../frontend/assets/plugin_scripts/jsexport.js && mv ./jsexport.js ../frontend/assets/plugin_scripts/jsexport.js mv ./jsexport.js ../frontend/assets/plugin_scripts/
#mv ./jsexport.js.map ../frontend/assets/plugin_scripts/
.PHONY: help .PHONY: help

View File

@@ -1,6 +1,7 @@
package battle package battle
import ( import (
//"fmt"
"math" "math"
"resolv" "resolv"
) )
@@ -29,6 +30,7 @@ const (
SNAP_INTO_PLATFORM_OVERLAP = float64(0.1) SNAP_INTO_PLATFORM_OVERLAP = float64(0.1)
SNAP_INTO_PLATFORM_THRESHOLD = float64(0.5) SNAP_INTO_PLATFORM_THRESHOLD = float64(0.5)
VERTICAL_PLATFORM_THRESHOLD = float64(0.9)
NO_SKILL = -1 NO_SKILL = -1
NO_SKILL_HIT = -1 NO_SKILL_HIT = -1
@@ -49,6 +51,12 @@ var DIRECTION_DECODER = [][]int32{
{-1, +1}, {-1, +1},
} }
const (
BULLET_STARTUP = int32(0)
BULLET_ACTIVE = int32(1)
BULLET_EXPLODING = int32(2)
)
const ( const (
ATK_CHARACTER_STATE_IDLE1 = int32(0) ATK_CHARACTER_STATE_IDLE1 = int32(0)
ATK_CHARACTER_STATE_WALKING = int32(1) ATK_CHARACTER_STATE_WALKING = int32(1)
@@ -65,6 +73,12 @@ const (
ATK_CHARACTER_STATE_ATK2 = int32(11) ATK_CHARACTER_STATE_ATK2 = int32(11)
ATK_CHARACTER_STATE_ATK3 = int32(12) ATK_CHARACTER_STATE_ATK3 = int32(12)
ATK_CHARACTER_STATE_ATK4 = int32(13) ATK_CHARACTER_STATE_ATK4 = int32(13)
ATK_CHARACTER_STATE_ATK5 = int32(14)
ATK_CHARACTER_STATE_DASHING = int32(15)
ATK_CHARACTER_STATE_ONWALL = int32(16)
ATK_CHARACTER_STATE_TURNAROUND = int32(17)
) )
var inAirSet = map[int32]bool{ var inAirSet = map[int32]bool{
@@ -73,6 +87,7 @@ var inAirSet = map[int32]bool{
ATK_CHARACTER_STATE_INAIR_ATK1: true, ATK_CHARACTER_STATE_INAIR_ATK1: true,
ATK_CHARACTER_STATE_INAIR_ATKED1: true, ATK_CHARACTER_STATE_INAIR_ATKED1: true,
ATK_CHARACTER_STATE_BLOWN_UP1: true, ATK_CHARACTER_STATE_BLOWN_UP1: true,
ATK_CHARACTER_STATE_ONWALL: true,
} }
var noOpSet = map[int32]bool{ var noOpSet = map[int32]bool{
@@ -101,6 +116,13 @@ var nonAttackingSet = map[int32]bool{
ATK_CHARACTER_STATE_GET_UP1: true, ATK_CHARACTER_STATE_GET_UP1: true,
} }
func intAbs(x int32) int32 {
if x < 0 {
return -x
}
return x
}
func ShouldPrefabInputFrameDownsync(prevRenderFrameId int32, renderFrameId int32) (bool, int32) { func ShouldPrefabInputFrameDownsync(prevRenderFrameId int32, renderFrameId int32) (bool, int32) {
for i := prevRenderFrameId + 1; i <= renderFrameId; i++ { for i := prevRenderFrameId + 1; i <= renderFrameId; i++ {
if (0 <= i) && (0 == (i & ((1 << INPUT_SCALE_FRAMES) - 1))) { if (0 <= i) && (0 == (i & ((1 << INPUT_SCALE_FRAMES) - 1))) {
@@ -154,7 +176,7 @@ type SatResult struct {
Axis resolv.Vector Axis resolv.Vector
} }
func CalcPushbacks(oldDx, oldDy float64, playerShape, barrierShape *resolv.ConvexPolygon) (bool, float64, float64, *SatResult) { func calcPushbacks(oldDx, oldDy float64, playerShape, barrierShape *resolv.ConvexPolygon) (bool, float64, float64, *SatResult) {
origX, origY := playerShape.Position() origX, origY := playerShape.Position()
defer func() { defer func() {
playerShape.SetPosition(origX, origY) playerShape.SetPosition(origX, origY)
@@ -206,6 +228,34 @@ func isPolygonPairOverlapped(a, b *resolv.ConvexPolygon, result *SatResult) bool
return true return true
} }
func IsMeleeBulletActive(meleeBullet *MeleeBullet, currRenderFrame *RoomDownsyncFrame) bool {
if BULLET_EXPLODING == meleeBullet.BlState {
return false
}
return (meleeBullet.BattleAttr.OriginatedRenderFrameId+meleeBullet.Bullet.StartupFrames <= currRenderFrame.Id) && (meleeBullet.BattleAttr.OriginatedRenderFrameId+meleeBullet.Bullet.StartupFrames+meleeBullet.Bullet.ActiveFrames > currRenderFrame.Id)
}
func IsMeleeBulletAlive(meleeBullet *MeleeBullet, currRenderFrame *RoomDownsyncFrame) bool {
if BULLET_EXPLODING == meleeBullet.BlState {
return meleeBullet.FramesInBlState < meleeBullet.Bullet.ExplosionFrames
}
return (meleeBullet.BattleAttr.OriginatedRenderFrameId+meleeBullet.Bullet.StartupFrames+meleeBullet.Bullet.ActiveFrames > currRenderFrame.Id)
}
func IsFireballBulletActive(fireballBullet *FireballBullet, currRenderFrame *RoomDownsyncFrame) bool {
if BULLET_EXPLODING == fireballBullet.BlState {
return false
}
return (fireballBullet.BattleAttr.OriginatedRenderFrameId+fireballBullet.Bullet.StartupFrames < currRenderFrame.Id) && (fireballBullet.BattleAttr.OriginatedRenderFrameId+fireballBullet.Bullet.StartupFrames+fireballBullet.Bullet.ActiveFrames > currRenderFrame.Id)
}
func IsFireballBulletAlive(fireballBullet *FireballBullet, currRenderFrame *RoomDownsyncFrame) bool {
if BULLET_EXPLODING == fireballBullet.BlState {
return fireballBullet.FramesInBlState < fireballBullet.Bullet.ExplosionFrames
}
return (fireballBullet.BattleAttr.OriginatedRenderFrameId+fireballBullet.Bullet.StartupFrames+fireballBullet.Bullet.ActiveFrames > currRenderFrame.Id)
}
func isPolygonPairSeparatedByDir(a, b *resolv.ConvexPolygon, e resolv.Vector, result *SatResult) bool { func isPolygonPairSeparatedByDir(a, b *resolv.ConvexPolygon, e resolv.Vector, result *SatResult) bool {
/* /*
[WARNING] This function is deliberately made private, it shouldn't be used alone (i.e. not along the norms of a polygon), otherwise the pushbacks calculated would be meaningless. [WARNING] This function is deliberately made private, it shouldn't be used alone (i.e. not along the norms of a polygon), otherwise the pushbacks calculated would be meaningless.
@@ -315,8 +365,8 @@ func isPolygonPairSeparatedByDir(a, b *resolv.ConvexPolygon, e resolv.Vector, re
func WorldToVirtualGridPos(wx, wy float64) (int32, int32) { func WorldToVirtualGridPos(wx, wy float64) (int32, int32) {
// [WARNING] Introduces loss of precision! // [WARNING] Introduces loss of precision!
// In JavaScript floating numbers suffer from seemingly non-deterministic arithmetics, and even if certain libs solved this issue by approaches such as fixed-point-number, they might not be used in other libs -- e.g. the "collision libs" we're interested in -- thus couldn't kill all pains. // In JavaScript floating numbers suffer from seemingly non-deterministic arithmetics, and even if certain libs solved this issue by approaches such as fixed-point-number, they might not be used in other libs -- e.g. the "collision libs" we're interested in -- thus couldn't kill all pains.
var virtualGridX int32 = int32(math.Floor(wx * WORLD_TO_VIRTUAL_GRID_RATIO)) var virtualGridX int32 = int32(math.Round(wx * WORLD_TO_VIRTUAL_GRID_RATIO))
var virtualGridY int32 = int32(math.Floor(wy * WORLD_TO_VIRTUAL_GRID_RATIO)) var virtualGridY int32 = int32(math.Round(wy * WORLD_TO_VIRTUAL_GRID_RATIO))
return virtualGridX, virtualGridY return virtualGridX, virtualGridY
} }
@@ -345,9 +395,25 @@ func VirtualGridToPolygonColliderBLPos(vx, vy int32, halfBoundingW, halfBounding
return WorldToPolygonColliderBLPos(wx, wy, halfBoundingW, halfBoundingH, topPadding, bottomPadding, leftPadding, rightPadding, collisionSpaceOffsetX, collisionSpaceOffsetY) return WorldToPolygonColliderBLPos(wx, wy, halfBoundingW, halfBoundingH, topPadding, bottomPadding, leftPadding, rightPadding, collisionSpaceOffsetX, collisionSpaceOffsetY)
} }
func calcHardPushbacksNorms(joinIndex int32, playerCollider *resolv.Object, playerShape *resolv.ConvexPolygon, snapIntoPlatformOverlap float64, pEffPushback *Vec2D) *[]Vec2D { func calcHardPushbacksNorms(joinIndex int32, currPlayerDownsync, thatPlayerInNextFrame *PlayerDownsync, playerCollider *resolv.Object, playerShape *resolv.ConvexPolygon, snapIntoPlatformOverlap float64, pEffPushback *Vec2D) *[]Vec2D {
ret := make([]Vec2D, 0, 10) // no one would simultaneously have more than 5 hardPushbacks ret := make([]Vec2D, 0, 10) // no one would simultaneously have more than 5 hardPushbacks
collision := playerCollider.Check(0, 0) virtualGripToWall := float64(0)
if ATK_CHARACTER_STATE_ONWALL == currPlayerDownsync.CharacterState && 0 == thatPlayerInNextFrame.VelX && currPlayerDownsync.DirX == thatPlayerInNextFrame.DirX {
/*
I'm not sure whether this is a bug of "resolv_tailored" (maybe due to my changes), on the x-axis a playerCollider whose right edge reaches "1680.1" is not deemed collided with a side wall whose left edge is "1680.0", while the same extent of intersection is OK in y-axis.
The workaround here is to grant a "virtualGripToWall" in x-axis to guarantee that if
- "currPlayerDownsync" is on wall, and
- "thatPlayerInNextFrame.VelX" is 0 (i.e. no proactive move against the wall), and
- there's no change in player facing direction
*/
xfac := float64(1)
if 0 > thatPlayerInNextFrame.DirX {
xfac = -xfac
}
virtualGripToWall = xfac * float64(currPlayerDownsync.Speed) * VIRTUAL_GRID_TO_WORLD_RATIO
}
collision := playerCollider.Check(virtualGripToWall, 0)
if nil == collision { if nil == collision {
return &ret return &ret
} }
@@ -357,8 +423,7 @@ func calcHardPushbacksNorms(joinIndex int32, playerCollider *resolv.Object, play
for _, obj := range collision.Objects { for _, obj := range collision.Objects {
isBarrier := false isBarrier := false
switch obj.Data.(type) { switch obj.Data.(type) {
case *PlayerDownsync: case *PlayerDownsync, *MeleeBullet, *FireballBullet:
case *MeleeBullet, *FireballBullet:
default: default:
// By default it's a regular barrier, even if data is nil, note that Golang syntax of switch-case is kind of confusing, this "default" condition is met only if "!*PlayerDownsync && !*MeleeBullet && !*FireballBullet". // By default it's a regular barrier, even if data is nil, note that Golang syntax of switch-case is kind of confusing, this "default" condition is met only if "!*PlayerDownsync && !*MeleeBullet && !*FireballBullet".
isBarrier = true isBarrier = true
@@ -368,7 +433,7 @@ func calcHardPushbacksNorms(joinIndex int32, playerCollider *resolv.Object, play
continue continue
} }
barrierShape := obj.Shape.(*resolv.ConvexPolygon) barrierShape := obj.Shape.(*resolv.ConvexPolygon)
overlapped, pushbackX, pushbackY, overlapResult := CalcPushbacks(0, 0, playerShape, barrierShape) overlapped, pushbackX, pushbackY, overlapResult := calcPushbacks(0, 0, playerShape, barrierShape)
if !overlapped { if !overlapped {
continue continue
} }
@@ -419,14 +484,26 @@ func deriveOpPattern(currPlayerDownsync, thatPlayerInNextFrame *PlayerDownsync,
if decodedInput.BtnBLevel > prevBtnBLevel { if decodedInput.BtnBLevel > prevBtnBLevel {
if _, existent := inAirSet[currPlayerDownsync.CharacterState]; !existent { if _, existent := inAirSet[currPlayerDownsync.CharacterState]; !existent {
jumpedOrNot = true jumpedOrNot = true
} else if ATK_CHARACTER_STATE_ONWALL == currPlayerDownsync.CharacterState {
jumpedOrNot = true
} }
} }
} }
patternId := PATTERN_ID_NO_OP patternId := PATTERN_ID_NO_OP
if 0 < decodedInput.BtnALevel {
if decodedInput.BtnALevel > prevBtnALevel { if decodedInput.BtnALevel > prevBtnALevel {
if 0 > effDy {
patternId = 3
} else if 0 < effDy {
patternId = 2
} else {
patternId = 1 patternId = 1
} }
} else {
patternId = 4 // Holding
}
}
return patternId, jumpedOrNot, effDx, effDy return patternId, jumpedOrNot, effDx, effDy
} }
@@ -448,6 +525,7 @@ func ApplyInputFrameDownsyncDynamicsOnSingleRenderFrame(inputsBuffer *RingBuffer
VelY: currPlayerDownsync.VelY, VelY: currPlayerDownsync.VelY,
CharacterState: currPlayerDownsync.CharacterState, CharacterState: currPlayerDownsync.CharacterState,
InAir: true, InAir: true,
OnWall: false,
Speed: currPlayerDownsync.Speed, Speed: currPlayerDownsync.Speed,
BattleState: currPlayerDownsync.BattleState, BattleState: currPlayerDownsync.BattleState,
Score: currPlayerDownsync.Score, Score: currPlayerDownsync.Score,
@@ -461,6 +539,9 @@ func ApplyInputFrameDownsyncDynamicsOnSingleRenderFrame(inputsBuffer *RingBuffer
ActiveSkillHit: currPlayerDownsync.ActiveSkillHit, ActiveSkillHit: currPlayerDownsync.ActiveSkillHit,
FramesInvinsible: currPlayerDownsync.FramesInvinsible - 1, FramesInvinsible: currPlayerDownsync.FramesInvinsible - 1,
ColliderRadius: currPlayerDownsync.ColliderRadius, ColliderRadius: currPlayerDownsync.ColliderRadius,
OnWallNormX: currPlayerDownsync.OnWallNormX,
OnWallNormY: currPlayerDownsync.OnWallNormY,
CapturedByInertia: currPlayerDownsync.CapturedByInertia,
} }
if nextRenderFramePlayers[i].FramesToRecover < 0 { if nextRenderFramePlayers[i].FramesToRecover < 0 {
nextRenderFramePlayers[i].FramesToRecover = 0 nextRenderFramePlayers[i].FramesToRecover = 0
@@ -479,15 +560,11 @@ func ApplyInputFrameDownsyncDynamicsOnSingleRenderFrame(inputsBuffer *RingBuffer
bulletLocalId := currRenderFrame.BulletLocalIdCounter bulletLocalId := currRenderFrame.BulletLocalIdCounter
// 1. Process player inputs // 1. Process player inputs
for i, currPlayerDownsync := range currRenderFrame.PlayersArr { for i, currPlayerDownsync := range currRenderFrame.PlayersArr {
jumpedOrNotList[i] = false
chConfig := chConfigsOrderedByJoinIndex[i] chConfig := chConfigsOrderedByJoinIndex[i]
thatPlayerInNextFrame := nextRenderFramePlayers[i] thatPlayerInNextFrame := nextRenderFramePlayers[i]
patternId, jumpedOrNot, effDx, effDy := deriveOpPattern(currPlayerDownsync, thatPlayerInNextFrame, currRenderFrame, inputsBuffer) patternId, jumpedOrNot, effDx, effDy := deriveOpPattern(currPlayerDownsync, thatPlayerInNextFrame, currRenderFrame, inputsBuffer)
if jumpedOrNot { jumpedOrNotList[i] = jumpedOrNot
thatPlayerInNextFrame.VelY = int32(chConfig.JumpingInitVelY)
jumpedOrNotList[i] = true
}
joinIndex := currPlayerDownsync.JoinIndex joinIndex := currPlayerDownsync.JoinIndex
skillId := chConfig.SkillMapper(patternId, currPlayerDownsync) skillId := chConfig.SkillMapper(patternId, currPlayerDownsync)
if skillConfig, existent := skills[skillId]; existent { if skillConfig, existent := skills[skillId]; existent {
@@ -504,40 +581,48 @@ func ApplyInputFrameDownsyncDynamicsOnSingleRenderFrame(inputsBuffer *RingBuffer
switch v := skillConfig.Hits[thatPlayerInNextFrame.ActiveSkillHit].(type) { switch v := skillConfig.Hits[thatPlayerInNextFrame.ActiveSkillHit].(type) {
case *MeleeBullet: case *MeleeBullet:
var newBullet MeleeBullet = *v // Copied primitive fields into an onstack variable var newBullet MeleeBullet = *v // Copied primitive fields into an onstack variable
newBullet.BulletLocalId = bulletLocalId newBullet.BattleAttr = &BulletBattleAttr{
bulletLocalId++ BulletLocalId: bulletLocalId,
newBullet.OriginatedRenderFrameId = currRenderFrame.Id OriginatedRenderFrameId: currRenderFrame.Id,
newBullet.OffenderJoinIndex = joinIndex OffenderJoinIndex: joinIndex,
nextRenderFrameMeleeBullets = append(nextRenderFrameMeleeBullets, &newBullet) TeamId: currPlayerDownsync.BulletTeamId,
if NO_LOCK_VEL != v.SelfLockVelX {
hasLockVel = true
thatPlayerInNextFrame.VelX = xfac * v.SelfLockVelX
} }
if NO_LOCK_VEL != v.SelfLockVelY { bulletLocalId++
newBullet.BlState = BULLET_STARTUP
nextRenderFrameMeleeBullets = append(nextRenderFrameMeleeBullets, &newBullet)
if NO_LOCK_VEL != v.Bullet.SelfLockVelX {
hasLockVel = true hasLockVel = true
thatPlayerInNextFrame.VelY = v.SelfLockVelY thatPlayerInNextFrame.VelX = xfac * v.Bullet.SelfLockVelX
}
if NO_LOCK_VEL != v.Bullet.SelfLockVelY {
hasLockVel = true
thatPlayerInNextFrame.VelY = v.Bullet.SelfLockVelY
} }
case *FireballBullet: case *FireballBullet:
var newBullet FireballBullet = *v // Copied primitive fields into an onstack variable var newBullet FireballBullet = *v // Copied primitive fields into an onstack variable
newBullet.BulletLocalId = bulletLocalId newBullet.BattleAttr = &BulletBattleAttr{
bulletLocalId++ BulletLocalId: bulletLocalId,
xfac := int32(1) OriginatedRenderFrameId: currRenderFrame.Id,
if 0 > thatPlayerInNextFrame.DirX { OffenderJoinIndex: joinIndex,
xfac = -xfac TeamId: currPlayerDownsync.BulletTeamId,
} }
newBullet.VirtualGridX, newBullet.VirtualGridY = currPlayerDownsync.VirtualGridX+xfac*newBullet.HitboxOffsetX, currPlayerDownsync.VirtualGridY bulletLocalId++
newBullet.OriginatedRenderFrameId = currRenderFrame.Id newBullet.VirtualGridX, newBullet.VirtualGridY = currPlayerDownsync.VirtualGridX+xfac*newBullet.Bullet.HitboxOffsetX, currPlayerDownsync.VirtualGridY+newBullet.Bullet.HitboxOffsetY
newBullet.OffenderJoinIndex = joinIndex newBullet.DirX = xfac
newBullet.DirY = 0
newBullet.VelX = newBullet.Speed * xfac newBullet.VelX = newBullet.Speed * xfac
newBullet.VelY = 0 newBullet.VelY = 0
newBullet.BlState = BULLET_STARTUP
nextRenderFrameFireballBullets = append(nextRenderFrameFireballBullets, &newBullet) nextRenderFrameFireballBullets = append(nextRenderFrameFireballBullets, &newBullet)
if NO_LOCK_VEL != v.SelfLockVelX { //fmt.Printf("Created new fireball @currRenderFrame.Id=%d, %p, bulletLocalId=%d, virtualGridX=%d, virtualGridY=%d, offenderVpos=(%d,%d)\n", currRenderFrame.Id, &newBullet, bulletLocalId, newBullet.VirtualGridX, newBullet.VirtualGridY, currPlayerDownsync.VirtualGridX, currPlayerDownsync.VirtualGridY)
if NO_LOCK_VEL != v.Bullet.SelfLockVelX {
hasLockVel = true hasLockVel = true
thatPlayerInNextFrame.VelX = xfac * v.SelfLockVelX thatPlayerInNextFrame.VelX = xfac * v.Bullet.SelfLockVelX
} }
if NO_LOCK_VEL != v.SelfLockVelY { if NO_LOCK_VEL != v.Bullet.SelfLockVelY {
hasLockVel = true hasLockVel = true
thatPlayerInNextFrame.VelY = v.SelfLockVelY thatPlayerInNextFrame.VelY = v.Bullet.SelfLockVelY
} }
} }
@@ -549,15 +634,55 @@ func ApplyInputFrameDownsyncDynamicsOnSingleRenderFrame(inputsBuffer *RingBuffer
} }
if 0 == currPlayerDownsync.FramesToRecover { if 0 == currPlayerDownsync.FramesToRecover {
if 0 != effDx || 0 != effDy { prevCapturedByInertia := currPlayerDownsync.CapturedByInertia
thatPlayerInNextFrame.DirX, thatPlayerInNextFrame.DirY = effDx, effDy isWallJumping := (currPlayerDownsync.Speed < intAbs(currPlayerDownsync.VelX))
thatPlayerInNextFrame.VelX = effDx * currPlayerDownsync.Speed /*
if isWallJumping {
fmt.Printf("joinIndex=%d is wall jumping\n{renderFrame.id: %d, currPlayerDownsync.Speed: %d, currPlayerDownsync.VelX: %d}\n", currPlayerDownsync.JoinIndex, currRenderFrame.Id, currPlayerDownsync.Speed, currPlayerDownsync.VelX)
}
*/
alignedWithInertia := true
if 0 == effDx && 0 != thatPlayerInNextFrame.VelX {
alignedWithInertia = false
} else if 0 != effDx && 0 == thatPlayerInNextFrame.VelX {
alignedWithInertia = false
} else if 0 > effDx*thatPlayerInNextFrame.VelX {
alignedWithInertia = false
}
if !isWallJumping && !prevCapturedByInertia && !alignedWithInertia {
/*
[WARNING] A "turn-around", or in more generic direction schema a "change in direction" is a hurdle for our current "prediction+rollback" approach, yet applying a "FramesToRecover" for "turn-around" can alleviate the graphical inconsistence to a huge extent! For better operational experience, this is intentionally NOT APPLIED TO WALL JUMPING!
When "false == alignedWithInertia", we're GUARANTEED TO BE WRONG AT INPUT PREDICTION ON THE FRONTEND, but we COULD STILL BE RIGHT AT POSITION PREDICTION WITHIN "InertiaFramesToRecover" -- which together with "INPUT_DELAY_FRAMES" grants the frontend a big chance to be graphically consistent even upon wrong prediction!
*/
//fmt.Printf("joinIndex=%d is not wall jumping and not aligned w/ inertia\n{renderFrame.id: %d, effDx: %d, thatPlayerInNextFrame.VelX: %d}\n", currPlayerDownsync.JoinIndex, currRenderFrame.Id, effDx, thatPlayerInNextFrame.VelX)
thatPlayerInNextFrame.CapturedByInertia = true
thatPlayerInNextFrame.FramesToRecover = chConfig.InertiaFramesToRecover
} else {
thatPlayerInNextFrame.CapturedByInertia = false
if 0 != effDx {
xfac := int32(1)
if 0 > effDx {
xfac = -xfac
}
thatPlayerInNextFrame.DirX = effDx
thatPlayerInNextFrame.DirY = effDy
if isWallJumping {
//fmt.Printf("joinIndex=%d is controlling while wall jumping\n{renderFrame.id: %d, currPlayerDownsync.Speed: %d, currPlayerDownsync.VelX: %d, effDx: %d}\n", currPlayerDownsync.JoinIndex, currRenderFrame.Id, currPlayerDownsync.Speed, currPlayerDownsync.VelX, effDx)
thatPlayerInNextFrame.VelX = xfac * intAbs(currPlayerDownsync.VelX)
} else {
thatPlayerInNextFrame.VelX = xfac * currPlayerDownsync.Speed
}
thatPlayerInNextFrame.CharacterState = ATK_CHARACTER_STATE_WALKING thatPlayerInNextFrame.CharacterState = ATK_CHARACTER_STATE_WALKING
} else { } else {
thatPlayerInNextFrame.CharacterState = ATK_CHARACTER_STATE_IDLE1 thatPlayerInNextFrame.CharacterState = ATK_CHARACTER_STATE_IDLE1
thatPlayerInNextFrame.VelX = 0 thatPlayerInNextFrame.VelX = 0
} }
} }
}
} }
// 2. Process player movement // 2. Process player movement
@@ -565,20 +690,39 @@ func ApplyInputFrameDownsyncDynamicsOnSingleRenderFrame(inputsBuffer *RingBuffer
for i, currPlayerDownsync := range currRenderFrame.PlayersArr { for i, currPlayerDownsync := range currRenderFrame.PlayersArr {
joinIndex := currPlayerDownsync.JoinIndex joinIndex := currPlayerDownsync.JoinIndex
effPushbacks[joinIndex-1].X, effPushbacks[joinIndex-1].Y = float64(0), float64(0) effPushbacks[joinIndex-1].X, effPushbacks[joinIndex-1].Y = float64(0), float64(0)
thatPlayerInNextFrame := nextRenderFramePlayers[i]
chConfig := chConfigsOrderedByJoinIndex[i] chConfig := chConfigsOrderedByJoinIndex[i]
// Reset playerCollider position from the "virtual grid position" // Reset playerCollider position from the "virtual grid position"
newVx, newVy := currPlayerDownsync.VirtualGridX+currPlayerDownsync.VelX, currPlayerDownsync.VirtualGridY+currPlayerDownsync.VelY newVx, newVy := currPlayerDownsync.VirtualGridX+currPlayerDownsync.VelX, currPlayerDownsync.VirtualGridY+currPlayerDownsync.VelY
if jumpedOrNotList[i] { if jumpedOrNotList[i] {
// We haven't proceeded with "OnWall" calculation for "thatPlayerInNextFrame", thus use "currPlayerDownsync.OnWall" for checking
if ATK_CHARACTER_STATE_ONWALL == currPlayerDownsync.CharacterState {
if 0 < currPlayerDownsync.VelX*currPlayerDownsync.OnWallNormX {
newVx -= currPlayerDownsync.VelX // Cancel the alleged horizontal movement pointing to same direction of wall inward norm first
}
xfac := int32(-1)
if 0 > currPlayerDownsync.OnWallNormX {
// Always jump to the opposite direction of wall inward norm
xfac = -xfac
}
newVx += xfac * chConfig.WallJumpingInitVelX
newVy += chConfig.WallJumpingInitVelY
thatPlayerInNextFrame.VelX = int32(xfac * chConfig.WallJumpingInitVelX)
thatPlayerInNextFrame.VelY = int32(chConfig.WallJumpingInitVelY)
thatPlayerInNextFrame.FramesToRecover = chConfig.WallJumpingFramesToRecover
} else {
thatPlayerInNextFrame.VelY = int32(chConfig.JumpingInitVelY)
newVy += chConfig.JumpingInitVelY // Immediately gets out of any snapping newVy += chConfig.JumpingInitVelY // Immediately gets out of any snapping
} }
}
wx, wy := VirtualGridToWorldPos(newVx, newVy) wx, wy := VirtualGridToWorldPos(newVx, newVy)
colliderWidth, colliderHeight := currPlayerDownsync.ColliderRadius*2, currPlayerDownsync.ColliderRadius*4 colliderWidth, colliderHeight := currPlayerDownsync.ColliderRadius*2, currPlayerDownsync.ColliderRadius*4
switch currPlayerDownsync.CharacterState { switch currPlayerDownsync.CharacterState {
case ATK_CHARACTER_STATE_LAY_DOWN1: case ATK_CHARACTER_STATE_LAY_DOWN1:
colliderWidth, colliderHeight = currPlayerDownsync.ColliderRadius*4, currPlayerDownsync.ColliderRadius*2 colliderWidth, colliderHeight = currPlayerDownsync.ColliderRadius*4, currPlayerDownsync.ColliderRadius*2
case ATK_CHARACTER_STATE_BLOWN_UP1, ATK_CHARACTER_STATE_INAIR_IDLE1_NO_JUMP, ATK_CHARACTER_STATE_INAIR_IDLE1_BY_JUMP: case ATK_CHARACTER_STATE_BLOWN_UP1, ATK_CHARACTER_STATE_INAIR_IDLE1_NO_JUMP, ATK_CHARACTER_STATE_INAIR_IDLE1_BY_JUMP, ATK_CHARACTER_STATE_ONWALL:
colliderWidth, colliderHeight = currPlayerDownsync.ColliderRadius*2, currPlayerDownsync.ColliderRadius*2 colliderWidth, colliderHeight = currPlayerDownsync.ColliderRadius*2, currPlayerDownsync.ColliderRadius*2
} }
@@ -590,41 +734,80 @@ func ApplyInputFrameDownsyncDynamicsOnSingleRenderFrame(inputsBuffer *RingBuffer
// Add to collision system // Add to collision system
collisionSys.Add(playerCollider) collisionSys.Add(playerCollider)
thatPlayerInNextFrame := nextRenderFramePlayers[i]
if currPlayerDownsync.InAir { if currPlayerDownsync.InAir {
if ATK_CHARACTER_STATE_ONWALL == currPlayerDownsync.CharacterState && !jumpedOrNotList[i] {
thatPlayerInNextFrame.VelX += GRAVITY_X
thatPlayerInNextFrame.VelY = chConfig.WallSlidingVelY
} else {
thatPlayerInNextFrame.VelX += GRAVITY_X thatPlayerInNextFrame.VelX += GRAVITY_X
thatPlayerInNextFrame.VelY += GRAVITY_Y thatPlayerInNextFrame.VelY += GRAVITY_Y
} }
} }
}
// 3. Add bullet colliders into collision system // 3. Add bullet colliders into collision system
// [WARNING] For rollback compatibility, static data of "BulletConfig" & "BattleAttr(static since instantiated)" can just be copies of the pointers in "RenderFrameBuffer", however, FireballBullets movement data as well as bullet animation data must be copies of instances for each RenderFrame!
bulletColliders := make([]*resolv.Object, 0, len(currRenderFrame.MeleeBullets)) // Will all be removed at the end of this function due to the need for being rollback-compatible bulletColliders := make([]*resolv.Object, 0, len(currRenderFrame.MeleeBullets)) // Will all be removed at the end of this function due to the need for being rollback-compatible
for _, meleeBullet := range currRenderFrame.MeleeBullets { for _, prevMelee := range currRenderFrame.MeleeBullets {
if (meleeBullet.OriginatedRenderFrameId+meleeBullet.StartupFrames <= currRenderFrame.Id) && (meleeBullet.OriginatedRenderFrameId+meleeBullet.StartupFrames+meleeBullet.ActiveFrames > currRenderFrame.Id) { meleeBullet := &MeleeBullet{
offender := currRenderFrame.PlayersArr[meleeBullet.OffenderJoinIndex-1] Bullet: prevMelee.Bullet,
BattleAttr: prevMelee.BattleAttr,
FramesInBlState: prevMelee.FramesInBlState + 1,
BlState: prevMelee.BlState,
}
if IsMeleeBulletAlive(meleeBullet, currRenderFrame) {
if IsMeleeBulletActive(meleeBullet, currRenderFrame) {
offender := currRenderFrame.PlayersArr[meleeBullet.BattleAttr.OffenderJoinIndex-1]
xfac := int32(1) // By now, straight Punch offset doesn't respect "y-axis" xfac := int32(1) // By now, straight Punch offset doesn't respect "y-axis"
if 0 > offender.DirX { if 0 > offender.DirX {
xfac = -xfac xfac = -xfac
} }
bulletWx, bulletWy := VirtualGridToWorldPos(offender.VirtualGridX+xfac*meleeBullet.HitboxOffsetX, offender.VirtualGridY) bulletWx, bulletWy := VirtualGridToWorldPos(offender.VirtualGridX+xfac*meleeBullet.Bullet.HitboxOffsetX, offender.VirtualGridY)
hitboxSizeWx, hitboxSizeWy := VirtualGridToWorldPos(meleeBullet.HitboxSizeX, meleeBullet.HitboxSizeY) hitboxSizeWx, hitboxSizeWy := VirtualGridToWorldPos(meleeBullet.Bullet.HitboxSizeX, meleeBullet.Bullet.HitboxSizeY)
newBulletCollider := GenerateRectCollider(bulletWx, bulletWy, hitboxSizeWx, hitboxSizeWy, SNAP_INTO_PLATFORM_OVERLAP, SNAP_INTO_PLATFORM_OVERLAP, SNAP_INTO_PLATFORM_OVERLAP, SNAP_INTO_PLATFORM_OVERLAP, collisionSpaceOffsetX, collisionSpaceOffsetY, meleeBullet, "MeleeBullet") newBulletCollider := GenerateRectCollider(bulletWx, bulletWy, hitboxSizeWx, hitboxSizeWy, SNAP_INTO_PLATFORM_OVERLAP, SNAP_INTO_PLATFORM_OVERLAP, SNAP_INTO_PLATFORM_OVERLAP, SNAP_INTO_PLATFORM_OVERLAP, collisionSpaceOffsetX, collisionSpaceOffsetY, meleeBullet, "MeleeBullet")
collisionSys.Add(newBulletCollider) collisionSys.Add(newBulletCollider)
bulletColliders = append(bulletColliders, newBulletCollider) bulletColliders = append(bulletColliders, newBulletCollider)
} else if meleeBullet.OriginatedRenderFrameId+meleeBullet.StartupFrames+meleeBullet.ActiveFrames > currRenderFrame.Id { meleeBullet.BlState = BULLET_ACTIVE
if meleeBullet.BlState != prevMelee.BlState {
meleeBullet.FramesInBlState = 0
}
}
nextRenderFrameMeleeBullets = append(nextRenderFrameMeleeBullets, meleeBullet) nextRenderFrameMeleeBullets = append(nextRenderFrameMeleeBullets, meleeBullet)
} }
} }
for _, fireballBullet := range currRenderFrame.FireballBullets { for _, prevFireball := range currRenderFrame.FireballBullets {
if (fireballBullet.OriginatedRenderFrameId+fireballBullet.StartupFrames < currRenderFrame.Id) && (fireballBullet.OriginatedRenderFrameId+fireballBullet.StartupFrames+fireballBullet.ActiveFrames > currRenderFrame.Id) { fireballBullet := &FireballBullet{
VirtualGridX: prevFireball.VirtualGridX,
VirtualGridY: prevFireball.VirtualGridY,
DirX: prevFireball.DirX,
DirY: prevFireball.DirY,
VelX: prevFireball.VelX,
VelY: prevFireball.VelY,
Speed: prevFireball.Speed,
Bullet: prevFireball.Bullet,
BattleAttr: prevFireball.BattleAttr,
FramesInBlState: prevFireball.FramesInBlState + 1,
BlState: prevFireball.BlState,
}
if IsFireballBulletAlive(fireballBullet, currRenderFrame) {
if IsFireballBulletActive(fireballBullet, currRenderFrame) {
bulletWx, bulletWy := VirtualGridToWorldPos(fireballBullet.VirtualGridX, fireballBullet.VirtualGridY) bulletWx, bulletWy := VirtualGridToWorldPos(fireballBullet.VirtualGridX, fireballBullet.VirtualGridY)
hitboxSizeWx, hitboxSizeWy := VirtualGridToWorldPos(fireballBullet.HitboxSizeX, fireballBullet.HitboxSizeY) hitboxSizeWx, hitboxSizeWy := VirtualGridToWorldPos(fireballBullet.Bullet.HitboxSizeX, fireballBullet.Bullet.HitboxSizeY)
newBulletCollider := GenerateRectCollider(bulletWx, bulletWy, hitboxSizeWx, hitboxSizeWy, SNAP_INTO_PLATFORM_OVERLAP, SNAP_INTO_PLATFORM_OVERLAP, SNAP_INTO_PLATFORM_OVERLAP, SNAP_INTO_PLATFORM_OVERLAP, collisionSpaceOffsetX, collisionSpaceOffsetY, fireballBullet, "FireballBullet") newBulletCollider := GenerateRectCollider(bulletWx, bulletWy, hitboxSizeWx, hitboxSizeWy, SNAP_INTO_PLATFORM_OVERLAP, SNAP_INTO_PLATFORM_OVERLAP, SNAP_INTO_PLATFORM_OVERLAP, SNAP_INTO_PLATFORM_OVERLAP, collisionSpaceOffsetX, collisionSpaceOffsetY, fireballBullet, "FireballBullet")
collisionSys.Add(newBulletCollider) collisionSys.Add(newBulletCollider)
bulletColliders = append(bulletColliders, newBulletCollider) bulletColliders = append(bulletColliders, newBulletCollider)
} else if fireballBullet.OriginatedRenderFrameId+fireballBullet.StartupFrames+fireballBullet.ActiveFrames > currRenderFrame.Id { fireballBullet.BlState = BULLET_ACTIVE
if fireballBullet.BlState != prevFireball.BlState {
fireballBullet.FramesInBlState = 0
}
fireballBullet.VirtualGridX, fireballBullet.VirtualGridY = fireballBullet.VirtualGridX+fireballBullet.VelX, fireballBullet.VirtualGridY+fireballBullet.VelY
//fmt.Printf("Pushing active fireball to next frame @currRenderFrame.Id=%d, bulletLocalId=%d, virtualGridX=%d, virtualGridY=%d, blState=%d\n", currRenderFrame.Id, fireballBullet.BattleAttr.BulletLocalId, fireballBullet.VirtualGridX, fireballBullet.VirtualGridY, fireballBullet.BlState)
} else {
//fmt.Printf("Pushing non-active fireball to next frame @currRenderFrame.Id=%d, bulletLocalId=%d, virtualGridX=%d, virtualGridY=%d, blState=%d\n", currRenderFrame.Id, fireballBullet.BattleAttr.BulletLocalId, fireballBullet.VirtualGridX, fireballBullet.VirtualGridY, fireballBullet.BlState)
}
nextRenderFrameFireballBullets = append(nextRenderFrameFireballBullets, fireballBullet) nextRenderFrameFireballBullets = append(nextRenderFrameFireballBullets, fireballBullet)
} }
} }
@@ -634,8 +817,8 @@ func ApplyInputFrameDownsyncDynamicsOnSingleRenderFrame(inputsBuffer *RingBuffer
joinIndex := currPlayerDownsync.JoinIndex joinIndex := currPlayerDownsync.JoinIndex
playerCollider := playerColliders[i] playerCollider := playerColliders[i]
playerShape := playerCollider.Shape.(*resolv.ConvexPolygon) playerShape := playerCollider.Shape.(*resolv.ConvexPolygon)
hardPushbackNorms[joinIndex-1] = calcHardPushbacksNorms(joinIndex, playerCollider, playerShape, SNAP_INTO_PLATFORM_OVERLAP, &(effPushbacks[joinIndex-1]))
thatPlayerInNextFrame := nextRenderFramePlayers[i] thatPlayerInNextFrame := nextRenderFramePlayers[i]
hardPushbackNorms[joinIndex-1] = calcHardPushbacksNorms(joinIndex, currPlayerDownsync, thatPlayerInNextFrame, playerCollider, playerShape, SNAP_INTO_PLATFORM_OVERLAP, &(effPushbacks[joinIndex-1]))
chConfig := chConfigsOrderedByJoinIndex[i] chConfig := chConfigsOrderedByJoinIndex[i]
landedOnGravityPushback := false landedOnGravityPushback := false
@@ -656,7 +839,7 @@ func ApplyInputFrameDownsyncDynamicsOnSingleRenderFrame(inputsBuffer *RingBuffer
continue continue
} }
bShape := obj.Shape.(*resolv.ConvexPolygon) bShape := obj.Shape.(*resolv.ConvexPolygon)
overlapped, pushbackX, pushbackY, overlapResult := CalcPushbacks(0, 0, playerShape, bShape) overlapped, pushbackX, pushbackY, overlapResult := calcPushbacks(0, 0, playerShape, bShape)
if !overlapped { if !overlapped {
continue continue
} }
@@ -684,24 +867,27 @@ func ApplyInputFrameDownsyncDynamicsOnSingleRenderFrame(inputsBuffer *RingBuffer
} }
if landedOnGravityPushback { if landedOnGravityPushback {
thatPlayerInNextFrame.InAir = false thatPlayerInNextFrame.InAir = false
if currPlayerDownsync.InAir && 0 >= currPlayerDownsync.VelY { fallStopping := (currPlayerDownsync.InAir && 0 >= currPlayerDownsync.VelY)
// fallStopping if fallStopping {
thatPlayerInNextFrame.VelY = 0 thatPlayerInNextFrame.VelY = 0
thatPlayerInNextFrame.VelX = 0 thatPlayerInNextFrame.VelX = 0
if _, existent := nonAttackingSet[thatPlayerInNextFrame.CharacterState]; existent {
if ATK_CHARACTER_STATE_BLOWN_UP1 == thatPlayerInNextFrame.CharacterState { if ATK_CHARACTER_STATE_BLOWN_UP1 == thatPlayerInNextFrame.CharacterState {
thatPlayerInNextFrame.CharacterState = ATK_CHARACTER_STATE_LAY_DOWN1 thatPlayerInNextFrame.CharacterState = ATK_CHARACTER_STATE_LAY_DOWN1
thatPlayerInNextFrame.FramesToRecover = chConfig.LayDownFramesToRecover thatPlayerInNextFrame.FramesToRecover = chConfig.LayDownFramesToRecover
} else { } else {
switch currPlayerDownsync.CharacterState {
case ATK_CHARACTER_STATE_BLOWN_UP1, ATK_CHARACTER_STATE_INAIR_IDLE1_NO_JUMP, ATK_CHARACTER_STATE_INAIR_IDLE1_BY_JUMP, ATK_CHARACTER_STATE_ONWALL:
// [WARNING] To prevent bouncing due to abrupt change of collider shape, it's important that we check "currPlayerDownsync" instead of "thatPlayerInNextFrame" here!
halfColliderWidthDiff, halfColliderHeightDiff := int32(0), currPlayerDownsync.ColliderRadius halfColliderWidthDiff, halfColliderHeightDiff := int32(0), currPlayerDownsync.ColliderRadius
_, halfColliderWorldHeightDiff := VirtualGridToWorldPos(halfColliderWidthDiff, halfColliderHeightDiff) _, halfColliderWorldHeightDiff := VirtualGridToWorldPos(halfColliderWidthDiff, halfColliderHeightDiff)
effPushbacks[joinIndex-1].Y -= halfColliderWorldHeightDiff // To prevent bouncing due to abrupt change of collider shape effPushbacks[joinIndex-1].Y -= halfColliderWorldHeightDiff
thatPlayerInNextFrame.CharacterState = ATK_CHARACTER_STATE_IDLE1
} }
thatPlayerInNextFrame.CharacterState = ATK_CHARACTER_STATE_IDLE1
thatPlayerInNextFrame.FramesToRecover = 0
} }
} else { } else {
// landedOnGravityPushback not fallStopping, could be in LayDown or GetUp
if _, existent := nonAttackingSet[thatPlayerInNextFrame.CharacterState]; existent { if _, existent := nonAttackingSet[thatPlayerInNextFrame.CharacterState]; existent {
// not fallStopping, could be in LayDown or GetUp
if ATK_CHARACTER_STATE_LAY_DOWN1 == thatPlayerInNextFrame.CharacterState { if ATK_CHARACTER_STATE_LAY_DOWN1 == thatPlayerInNextFrame.CharacterState {
if 0 == thatPlayerInNextFrame.FramesToRecover { if 0 == thatPlayerInNextFrame.FramesToRecover {
thatPlayerInNextFrame.CharacterState = ATK_CHARACTER_STATE_GET_UP1 thatPlayerInNextFrame.CharacterState = ATK_CHARACTER_STATE_GET_UP1
@@ -716,30 +902,62 @@ func ApplyInputFrameDownsyncDynamicsOnSingleRenderFrame(inputsBuffer *RingBuffer
} }
} }
} }
if chConfig.OnWallEnabled {
if thatPlayerInNextFrame.InAir {
// [WARNING] Sticking to wall MUST BE based on "InAir", otherwise we would get gravity reduction from ground up incorrectly!
if _, existent := noOpSet[currPlayerDownsync.CharacterState]; !existent {
// [WARNING] Sticking to wall could only be triggered by proactive player input
for _, hardPushbackNorm := range *hardPushbackNorms[joinIndex-1] {
normAlignmentWithHorizon1 := (hardPushbackNorm.X*float64(1.0) + hardPushbackNorm.Y*float64(0.0))
normAlignmentWithHorizon2 := (hardPushbackNorm.X*float64(-1.0) + hardPushbackNorm.Y*float64(0.0))
if VERTICAL_PLATFORM_THRESHOLD < normAlignmentWithHorizon1 {
thatPlayerInNextFrame.OnWall = true
thatPlayerInNextFrame.OnWallNormX, thatPlayerInNextFrame.OnWallNormY = int32(hardPushbackNorm.X), int32(hardPushbackNorm.Y)
break
}
if VERTICAL_PLATFORM_THRESHOLD < normAlignmentWithHorizon2 {
thatPlayerInNextFrame.OnWall = true
thatPlayerInNextFrame.OnWallNormX, thatPlayerInNextFrame.OnWallNormY = int32(hardPushbackNorm.X), int32(hardPushbackNorm.Y)
break
}
}
if !currPlayerDownsync.OnWall && thatPlayerInNextFrame.OnWall {
// To avoid mysterious climbing up the wall after sticking on it
thatPlayerInNextFrame.VelY = 0
}
}
}
if !thatPlayerInNextFrame.OnWall {
thatPlayerInNextFrame.OnWallNormX, thatPlayerInNextFrame.OnWallNormY = 0, 0
}
}
} }
// 5. Check bullet-anything collisions // 5. Check bullet-anything collisions
for _, bulletCollider := range bulletColliders { for _, bulletCollider := range bulletColliders {
collision := bulletCollider.Check(0, 0) collision := bulletCollider.Check(0, 0)
bulletCollider.Space.Remove(bulletCollider) // Make sure that the bulletCollider is always removed for each renderFrame bulletCollider.Space.Remove(bulletCollider) // Make sure that the bulletCollider is always removed for each renderFrame
addToNextRenderFrame := true exploded := false
if nil != collision { if nil != collision {
switch v := bulletCollider.Data.(type) { switch v := bulletCollider.Data.(type) {
case *MeleeBullet: case *MeleeBullet:
bulletShape := bulletCollider.Shape.(*resolv.ConvexPolygon) bulletShape := bulletCollider.Shape.(*resolv.ConvexPolygon)
offender := currRenderFrame.PlayersArr[v.OffenderJoinIndex-1] offender := currRenderFrame.PlayersArr[v.BattleAttr.OffenderJoinIndex-1]
for _, obj := range collision.Objects { for _, obj := range collision.Objects {
defenderShape := obj.Shape.(*resolv.ConvexPolygon) defenderShape := obj.Shape.(*resolv.ConvexPolygon)
switch t := obj.Data.(type) { switch t := obj.Data.(type) {
case *PlayerDownsync: case *PlayerDownsync:
if v.OffenderJoinIndex == t.JoinIndex { if v.BattleAttr.OffenderJoinIndex == t.JoinIndex {
continue continue
} }
overlapped, _, _, _ := CalcPushbacks(0, 0, bulletShape, defenderShape) overlapped, _, _, _ := calcPushbacks(0, 0, bulletShape, defenderShape)
if !overlapped { if !overlapped {
continue continue
} }
addToNextRenderFrame = false exploded = true
if _, existent := invinsibleSet[t.CharacterState]; existent { if _, existent := invinsibleSet[t.CharacterState]; existent {
continue continue
} }
@@ -750,38 +968,36 @@ func ApplyInputFrameDownsyncDynamicsOnSingleRenderFrame(inputsBuffer *RingBuffer
if 0 > offender.DirX { if 0 > offender.DirX {
xfac = -xfac xfac = -xfac
} }
pushbackVelX, pushbackVelY := xfac*v.PushbackVelX, v.PushbackVelY pushbackVelX, pushbackVelY := xfac*v.Bullet.PushbackVelX, v.Bullet.PushbackVelY
atkedPlayerInNextFrame := nextRenderFramePlayers[t.JoinIndex-1] atkedPlayerInNextFrame := nextRenderFramePlayers[t.JoinIndex-1]
atkedPlayerInNextFrame.VelX = pushbackVelX atkedPlayerInNextFrame.VelX = pushbackVelX
atkedPlayerInNextFrame.VelY = pushbackVelY atkedPlayerInNextFrame.VelY = pushbackVelY
if v.BlowUp { if v.Bullet.BlowUp {
atkedPlayerInNextFrame.CharacterState = ATK_CHARACTER_STATE_BLOWN_UP1 atkedPlayerInNextFrame.CharacterState = ATK_CHARACTER_STATE_BLOWN_UP1
} else { } else {
atkedPlayerInNextFrame.CharacterState = ATK_CHARACTER_STATE_ATKED1 atkedPlayerInNextFrame.CharacterState = ATK_CHARACTER_STATE_ATKED1
} }
oldFramesToRecover := nextRenderFramePlayers[t.JoinIndex-1].FramesToRecover oldFramesToRecover := nextRenderFramePlayers[t.JoinIndex-1].FramesToRecover
if v.HitStunFrames > oldFramesToRecover { if v.Bullet.HitStunFrames > oldFramesToRecover {
atkedPlayerInNextFrame.FramesToRecover = v.HitStunFrames atkedPlayerInNextFrame.FramesToRecover = v.Bullet.HitStunFrames
} }
default:
addToNextRenderFrame = false
} }
} }
case *FireballBullet: case *FireballBullet:
bulletShape := bulletCollider.Shape.(*resolv.ConvexPolygon) bulletShape := bulletCollider.Shape.(*resolv.ConvexPolygon)
offender := currRenderFrame.PlayersArr[v.OffenderJoinIndex-1] offender := currRenderFrame.PlayersArr[v.BattleAttr.OffenderJoinIndex-1]
for _, obj := range collision.Objects { for _, obj := range collision.Objects {
defenderShape := obj.Shape.(*resolv.ConvexPolygon) defenderShape := obj.Shape.(*resolv.ConvexPolygon)
switch t := obj.Data.(type) { switch t := obj.Data.(type) {
case *PlayerDownsync: case *PlayerDownsync:
if v.OffenderJoinIndex == t.JoinIndex { if v.BattleAttr.OffenderJoinIndex == t.JoinIndex {
continue continue
} }
overlapped, _, _, _ := CalcPushbacks(0, 0, bulletShape, defenderShape) overlapped, _, _, _ := calcPushbacks(0, 0, bulletShape, defenderShape)
if !overlapped { if !overlapped {
continue continue
} }
addToNextRenderFrame = false exploded = true
if _, existent := invinsibleSet[t.CharacterState]; existent { if _, existent := invinsibleSet[t.CharacterState]; existent {
continue continue
} }
@@ -792,32 +1008,35 @@ func ApplyInputFrameDownsyncDynamicsOnSingleRenderFrame(inputsBuffer *RingBuffer
if 0 > offender.DirX { if 0 > offender.DirX {
xfac = -xfac xfac = -xfac
} }
pushbackVelX, pushbackVelY := xfac*v.PushbackVelX, v.PushbackVelY pushbackVelX, pushbackVelY := xfac*v.Bullet.PushbackVelX, v.Bullet.PushbackVelY
atkedPlayerInNextFrame := nextRenderFramePlayers[t.JoinIndex-1] atkedPlayerInNextFrame := nextRenderFramePlayers[t.JoinIndex-1]
atkedPlayerInNextFrame.VelX = pushbackVelX atkedPlayerInNextFrame.VelX = pushbackVelX
atkedPlayerInNextFrame.VelY = pushbackVelY atkedPlayerInNextFrame.VelY = pushbackVelY
if v.BlowUp { if v.Bullet.BlowUp {
atkedPlayerInNextFrame.CharacterState = ATK_CHARACTER_STATE_BLOWN_UP1 atkedPlayerInNextFrame.CharacterState = ATK_CHARACTER_STATE_BLOWN_UP1
} else { } else {
atkedPlayerInNextFrame.CharacterState = ATK_CHARACTER_STATE_ATKED1 atkedPlayerInNextFrame.CharacterState = ATK_CHARACTER_STATE_ATKED1
} }
oldFramesToRecover := nextRenderFramePlayers[t.JoinIndex-1].FramesToRecover oldFramesToRecover := nextRenderFramePlayers[t.JoinIndex-1].FramesToRecover
if v.HitStunFrames > oldFramesToRecover { if v.Bullet.HitStunFrames > oldFramesToRecover {
atkedPlayerInNextFrame.FramesToRecover = v.HitStunFrames atkedPlayerInNextFrame.FramesToRecover = v.Bullet.HitStunFrames
} }
default: default:
addToNextRenderFrame = false exploded = true
} }
} }
} }
} }
if addToNextRenderFrame { if exploded {
switch v := bulletCollider.Data.(type) { switch v := bulletCollider.Data.(type) {
case *MeleeBullet: case *MeleeBullet:
nextRenderFrameMeleeBullets = append(nextRenderFrameMeleeBullets, v) v.BlState = BULLET_EXPLODING
v.FramesInBlState = 0
//fmt.Printf("melee exploded @currRenderFrame.Id=%d, bulletLocalId=%d, blState=%d\n", currRenderFrame.Id, v.BattleAttr.BulletLocalId, v.BlState)
case *FireballBullet: case *FireballBullet:
v.VirtualGridX, v.VirtualGridY = v.VirtualGridX+v.VelX, v.VirtualGridY+v.VelY v.BlState = BULLET_EXPLODING
nextRenderFrameFireballBullets = append(nextRenderFrameFireballBullets, v) v.FramesInBlState = 0
//fmt.Printf("fireball exploded @currRenderFrame.Id=%d, bulletLocalId=%d, virtualGridX=%d, virtualGridY=%d, blState=%d\n", currRenderFrame.Id, v.BattleAttr.BulletLocalId, v.VirtualGridX, v.VirtualGridY, v.BlState)
} }
} }
} }
@@ -835,7 +1054,9 @@ func ApplyInputFrameDownsyncDynamicsOnSingleRenderFrame(inputsBuffer *RingBuffer
oldNextCharacterState := thatPlayerInNextFrame.CharacterState oldNextCharacterState := thatPlayerInNextFrame.CharacterState
switch oldNextCharacterState { switch oldNextCharacterState {
case ATK_CHARACTER_STATE_IDLE1, ATK_CHARACTER_STATE_WALKING: case ATK_CHARACTER_STATE_IDLE1, ATK_CHARACTER_STATE_WALKING:
if jumpedOrNotList[i] || ATK_CHARACTER_STATE_INAIR_IDLE1_BY_JUMP == currPlayerDownsync.CharacterState { if thatPlayerInNextFrame.OnWall {
thatPlayerInNextFrame.CharacterState = ATK_CHARACTER_STATE_ONWALL
} else if jumpedOrNotList[i] || ATK_CHARACTER_STATE_INAIR_IDLE1_BY_JUMP == currPlayerDownsync.CharacterState {
thatPlayerInNextFrame.CharacterState = ATK_CHARACTER_STATE_INAIR_IDLE1_BY_JUMP thatPlayerInNextFrame.CharacterState = ATK_CHARACTER_STATE_INAIR_IDLE1_BY_JUMP
} else { } else {
thatPlayerInNextFrame.CharacterState = ATK_CHARACTER_STATE_INAIR_IDLE1_NO_JUMP thatPlayerInNextFrame.CharacterState = ATK_CHARACTER_STATE_INAIR_IDLE1_NO_JUMP
@@ -867,6 +1088,7 @@ func ApplyInputFrameDownsyncDynamicsOnSingleRenderFrame(inputsBuffer *RingBuffer
return &RoomDownsyncFrame{ return &RoomDownsyncFrame{
Id: currRenderFrame.Id + 1, Id: currRenderFrame.Id + 1,
PlayersArr: nextRenderFramePlayers, PlayersArr: nextRenderFramePlayers,
BulletLocalIdCounter: bulletLocalId,
MeleeBullets: nextRenderFrameMeleeBullets, MeleeBullets: nextRenderFrameMeleeBullets,
FireballBullets: nextRenderFrameFireballBullets, FireballBullets: nextRenderFrameFireballBullets,
} }
@@ -949,3 +1171,82 @@ func AlignPolygon2DToBoundingBox(input *Polygon2D) *Polygon2D {
return output return output
} }
func NewMeleeBullet(bulletLocalId, originatedRenderFrameId, offenderJoinIndex, startupFrames, cancellableStFrame, cancellableEdFrame, activeFrames, hitStunFrames, blockStunFrames, pushbackVelX, pushbackVelY, damage, selfLockVelX, selfLockVelY, hitboxOffsetX, hitboxOffsetY, hitboxSizeX, hitboxSizeY int32, blowUp bool, teamId, blState, framesInBlState, explosionFrames, speciesId int32) *MeleeBullet {
return &MeleeBullet{
BlState: blState,
FramesInBlState: framesInBlState,
BattleAttr: &BulletBattleAttr{
BulletLocalId: bulletLocalId,
OriginatedRenderFrameId: originatedRenderFrameId,
OffenderJoinIndex: offenderJoinIndex,
TeamId: teamId,
},
Bullet: &BulletConfig{
StartupFrames: startupFrames,
CancellableStFrame: cancellableStFrame,
CancellableEdFrame: cancellableEdFrame,
ActiveFrames: activeFrames,
HitStunFrames: hitStunFrames,
BlockStunFrames: blockStunFrames,
PushbackVelX: pushbackVelX,
PushbackVelY: pushbackVelY,
Damage: damage,
SelfLockVelX: selfLockVelX,
SelfLockVelY: selfLockVelY,
HitboxOffsetX: hitboxOffsetX,
HitboxOffsetY: hitboxOffsetY,
HitboxSizeX: hitboxSizeX,
HitboxSizeY: hitboxSizeY,
BlowUp: blowUp,
ExplosionFrames: explosionFrames,
SpeciesId: speciesId,
},
}
}
func NewFireballBullet(bulletLocalId, originatedRenderFrameId, offenderJoinIndex, startupFrames, cancellableStFrame, cancellableEdFrame, activeFrames, hitStunFrames, blockStunFrames, pushbackVelX, pushbackVelY, damage, selfLockVelX, selfLockVelY, hitboxOffsetX, hitboxOffsetY, hitboxSizeX, hitboxSizeY int32, blowUp bool, teamId int32, virtualGridX, virtualGridY, dirX, dirY, velX, velY, speed, blState, framesInBlState, explosionFrames, speciesId int32) *FireballBullet {
return &FireballBullet{
VirtualGridX: virtualGridX,
VirtualGridY: virtualGridY,
DirX: dirX,
DirY: dirY,
VelX: velX,
VelY: velY,
Speed: speed,
BattleAttr: &BulletBattleAttr{
BulletLocalId: bulletLocalId,
OriginatedRenderFrameId: originatedRenderFrameId,
OffenderJoinIndex: offenderJoinIndex,
TeamId: teamId,
},
Bullet: &BulletConfig{
StartupFrames: startupFrames,
CancellableStFrame: cancellableStFrame,
CancellableEdFrame: cancellableEdFrame,
ActiveFrames: activeFrames,
HitStunFrames: hitStunFrames,
BlockStunFrames: blockStunFrames,
PushbackVelX: pushbackVelX,
PushbackVelY: pushbackVelY,
Damage: damage,
SelfLockVelX: selfLockVelX,
SelfLockVelY: selfLockVelY,
HitboxOffsetX: hitboxOffsetX,
HitboxOffsetY: hitboxOffsetY,
HitboxSizeX: hitboxSizeX,
HitboxSizeY: hitboxSizeY,
BlowUp: blowUp,
ExplosionFrames: explosionFrames,
SpeciesId: speciesId,
},
}
}

View File

@@ -17,6 +17,16 @@ type CharacterConfig struct {
Speed int32 Speed int32
JumpingInitVelY int32 JumpingInitVelY int32
JumpingFramesToRecover int32 // Not used yet
DashingEnabled bool
OnWallEnabled bool
WallJumpingFramesToRecover int32
WallJumpingInitVelX int32
WallJumpingInitVelY int32
WallSlidingVelY int32
InertiaFramesToRecover int32
SkillMapper SkillMapperType SkillMapper SkillMapperType
} }
@@ -35,8 +45,14 @@ var Characters = map[int]*CharacterConfig{
GetUpInvinsibleFrames: int32(10), GetUpInvinsibleFrames: int32(10),
GetUpFramesToRecover: int32(27), GetUpFramesToRecover: int32(27),
Speed: int32(float64(1.2) * WORLD_TO_VIRTUAL_GRID_RATIO), Speed: int32(float64(2.5) * WORLD_TO_VIRTUAL_GRID_RATIO),
JumpingInitVelY: int32(float64(8) * WORLD_TO_VIRTUAL_GRID_RATIO), JumpingInitVelY: int32(float64(8) * WORLD_TO_VIRTUAL_GRID_RATIO),
JumpingFramesToRecover: int32(2),
InertiaFramesToRecover: int32(5),
DashingEnabled: false,
OnWallEnabled: false,
SkillMapper: func(patternId int, currPlayerDownsync *PlayerDownsync) int { SkillMapper: func(patternId int, currPlayerDownsync *PlayerDownsync) int {
if 1 == patternId { if 1 == patternId {
@@ -51,8 +67,8 @@ var Characters = map[int]*CharacterConfig{
if skillConfig, existent1 := skills[int(currPlayerDownsync.ActiveSkillId)]; existent1 { if skillConfig, existent1 := skills[int(currPlayerDownsync.ActiveSkillId)]; existent1 {
switch v := skillConfig.Hits[currPlayerDownsync.ActiveSkillHit].(type) { switch v := skillConfig.Hits[currPlayerDownsync.ActiveSkillHit].(type) {
case *MeleeBullet: case *MeleeBullet:
if v.CancellableStFrame <= currPlayerDownsync.FramesInChState && currPlayerDownsync.FramesInChState < v.CancellableEdFrame { if v.Bullet.CancellableStFrame <= currPlayerDownsync.FramesInChState && currPlayerDownsync.FramesInChState < v.Bullet.CancellableEdFrame {
if nextSkillId, existent2 := v.CancelTransit[patternId]; existent2 { if nextSkillId, existent2 := v.Bullet.CancelTransit[patternId]; existent2 {
return nextSkillId return nextSkillId
} }
} }
@@ -78,8 +94,18 @@ var Characters = map[int]*CharacterConfig{
GetUpInvinsibleFrames: int32(10), GetUpInvinsibleFrames: int32(10),
GetUpFramesToRecover: int32(27), GetUpFramesToRecover: int32(27),
Speed: int32(float64(1.4) * WORLD_TO_VIRTUAL_GRID_RATIO), Speed: int32(float64(2.6) * WORLD_TO_VIRTUAL_GRID_RATIO),
JumpingInitVelY: int32(float64(7.5) * WORLD_TO_VIRTUAL_GRID_RATIO), JumpingInitVelY: int32(float64(7.5) * WORLD_TO_VIRTUAL_GRID_RATIO),
JumpingFramesToRecover: int32(2),
InertiaFramesToRecover: int32(5),
DashingEnabled: true,
OnWallEnabled: true,
WallJumpingFramesToRecover: int32(8), // 8 would be the minimum for an avg human
WallJumpingInitVelX: int32(float64(2.8) * WORLD_TO_VIRTUAL_GRID_RATIO), // Default is "appeared facing right", but actually holding ctrl against left
WallJumpingInitVelY: int32(float64(7) * WORLD_TO_VIRTUAL_GRID_RATIO),
WallSlidingVelY: int32(float64(-1) * WORLD_TO_VIRTUAL_GRID_RATIO),
SkillMapper: func(patternId int, currPlayerDownsync *PlayerDownsync) int { SkillMapper: func(patternId int, currPlayerDownsync *PlayerDownsync) int {
if 1 == patternId { if 1 == patternId {
@@ -94,8 +120,8 @@ var Characters = map[int]*CharacterConfig{
if skillConfig, existent1 := skills[int(currPlayerDownsync.ActiveSkillId)]; existent1 { if skillConfig, existent1 := skills[int(currPlayerDownsync.ActiveSkillId)]; existent1 {
switch v := skillConfig.Hits[currPlayerDownsync.ActiveSkillHit].(type) { switch v := skillConfig.Hits[currPlayerDownsync.ActiveSkillHit].(type) {
case *MeleeBullet: case *MeleeBullet:
if v.CancellableStFrame <= currPlayerDownsync.FramesInChState && currPlayerDownsync.FramesInChState < v.CancellableEdFrame { if v.Bullet.CancellableStFrame <= currPlayerDownsync.FramesInChState && currPlayerDownsync.FramesInChState < v.Bullet.CancellableEdFrame {
if nextSkillId, existent2 := v.CancelTransit[patternId]; existent2 { if nextSkillId, existent2 := v.Bullet.CancelTransit[patternId]; existent2 {
return nextSkillId return nextSkillId
} }
} }
@@ -121,8 +147,14 @@ var Characters = map[int]*CharacterConfig{
GetUpInvinsibleFrames: int32(8), GetUpInvinsibleFrames: int32(8),
GetUpFramesToRecover: int32(30), GetUpFramesToRecover: int32(30),
Speed: int32(float64(1.0) * WORLD_TO_VIRTUAL_GRID_RATIO), Speed: int32(float64(2.0) * WORLD_TO_VIRTUAL_GRID_RATIO),
JumpingInitVelY: int32(float64(9) * WORLD_TO_VIRTUAL_GRID_RATIO), JumpingInitVelY: int32(float64(7.5) * WORLD_TO_VIRTUAL_GRID_RATIO),
JumpingFramesToRecover: int32(2),
InertiaFramesToRecover: int32(5),
DashingEnabled: false,
OnWallEnabled: false,
SkillMapper: func(patternId int, currPlayerDownsync *PlayerDownsync) int { SkillMapper: func(patternId int, currPlayerDownsync *PlayerDownsync) int {
if 1 == patternId { if 1 == patternId {
@@ -130,21 +162,29 @@ var Characters = map[int]*CharacterConfig{
if currPlayerDownsync.InAir { if currPlayerDownsync.InAir {
return 257 return 257
} else { } else {
return 10 return 7
} }
} else { } else {
// Now that "0 < FramesToRecover", we're only able to fire any skill if it's a cancellation // Now that "0 < FramesToRecover", we're only able to fire any skill if it's a cancellation
if skillConfig, existent1 := skills[int(currPlayerDownsync.ActiveSkillId)]; existent1 { if skillConfig, existent1 := skills[int(currPlayerDownsync.ActiveSkillId)]; existent1 {
switch v := skillConfig.Hits[currPlayerDownsync.ActiveSkillHit].(type) { switch v := skillConfig.Hits[currPlayerDownsync.ActiveSkillHit].(type) {
case *MeleeBullet: case *MeleeBullet:
if v.CancellableStFrame <= currPlayerDownsync.FramesInChState && currPlayerDownsync.FramesInChState < v.CancellableEdFrame { if v.Bullet.CancellableStFrame <= currPlayerDownsync.FramesInChState && currPlayerDownsync.FramesInChState < v.Bullet.CancellableEdFrame {
if nextSkillId, existent2 := v.CancelTransit[patternId]; existent2 { if nextSkillId, existent2 := v.Bullet.CancelTransit[patternId]; existent2 {
return nextSkillId return nextSkillId
} }
} }
} }
} }
} }
} else if 2 == patternId {
if !currPlayerDownsync.InAir {
return 11
}
} else if 3 == patternId {
if !currPlayerDownsync.InAir {
return 10
}
} }
// By default no skill can be fired // By default no skill can be fired
@@ -162,7 +202,7 @@ var skills = map[int]*Skill{
BoundChState: ATK_CHARACTER_STATE_ATK1, BoundChState: ATK_CHARACTER_STATE_ATK1,
Hits: []interface{}{ Hits: []interface{}{
&MeleeBullet{ &MeleeBullet{
Bullet: Bullet{ Bullet: &BulletConfig{
StartupFrames: int32(7), StartupFrames: int32(7),
ActiveFrames: int32(22), ActiveFrames: int32(22),
HitStunFrames: int32(13), HitStunFrames: int32(13),
@@ -182,7 +222,9 @@ var skills = map[int]*Skill{
CancelTransit: map[int]int{ CancelTransit: map[int]int{
1: 2, 1: 2,
}, },
// TODO: Use non-zero "selfLockVel" BlowUp: false,
ExplosionFrames: 9,
SpeciesId: int32(1),
}, },
}, },
}, },
@@ -195,7 +237,7 @@ var skills = map[int]*Skill{
BoundChState: ATK_CHARACTER_STATE_ATK2, BoundChState: ATK_CHARACTER_STATE_ATK2,
Hits: []interface{}{ Hits: []interface{}{
&MeleeBullet{ &MeleeBullet{
Bullet: Bullet{ Bullet: &BulletConfig{
StartupFrames: int32(18), StartupFrames: int32(18),
ActiveFrames: int32(18), ActiveFrames: int32(18),
HitStunFrames: int32(18), HitStunFrames: int32(18),
@@ -214,6 +256,9 @@ var skills = map[int]*Skill{
CancelTransit: map[int]int{ CancelTransit: map[int]int{
1: 3, 1: 3,
}, },
BlowUp: false,
ExplosionFrames: 9,
SpeciesId: int32(1),
}, },
}, },
}, },
@@ -226,8 +271,8 @@ var skills = map[int]*Skill{
BoundChState: ATK_CHARACTER_STATE_ATK3, BoundChState: ATK_CHARACTER_STATE_ATK3,
Hits: []interface{}{ Hits: []interface{}{
&MeleeBullet{ &MeleeBullet{
Bullet: Bullet{ Bullet: &BulletConfig{
StartupFrames: int32(15), StartupFrames: int32(8),
ActiveFrames: int32(30), ActiveFrames: int32(30),
HitStunFrames: MAX_INT32, HitStunFrames: MAX_INT32,
BlockStunFrames: int32(9), BlockStunFrames: int32(9),
@@ -236,11 +281,13 @@ var skills = map[int]*Skill{
SelfLockVelY: int32(float64(5) * WORLD_TO_VIRTUAL_GRID_RATIO), SelfLockVelY: int32(float64(5) * WORLD_TO_VIRTUAL_GRID_RATIO),
PushbackVelX: int32(float64(2) * WORLD_TO_VIRTUAL_GRID_RATIO), PushbackVelX: int32(float64(2) * WORLD_TO_VIRTUAL_GRID_RATIO),
PushbackVelY: int32(float64(7) * WORLD_TO_VIRTUAL_GRID_RATIO), PushbackVelY: int32(float64(7) * WORLD_TO_VIRTUAL_GRID_RATIO),
HitboxOffsetX: int32(float64(32) * WORLD_TO_VIRTUAL_GRID_RATIO), HitboxOffsetX: int32(float64(16) * WORLD_TO_VIRTUAL_GRID_RATIO),
HitboxOffsetY: int32(0), HitboxOffsetY: int32(float64(8) * WORLD_TO_VIRTUAL_GRID_RATIO),
HitboxSizeX: int32(float64(48) * WORLD_TO_VIRTUAL_GRID_RATIO), HitboxSizeX: int32(float64(32) * WORLD_TO_VIRTUAL_GRID_RATIO),
HitboxSizeY: int32(float64(32) * WORLD_TO_VIRTUAL_GRID_RATIO), HitboxSizeY: int32(float64(32) * WORLD_TO_VIRTUAL_GRID_RATIO),
BlowUp: true, BlowUp: true,
ExplosionFrames: 9,
SpeciesId: int32(1),
}, },
}, },
}, },
@@ -253,7 +300,7 @@ var skills = map[int]*Skill{
BoundChState: ATK_CHARACTER_STATE_ATK1, BoundChState: ATK_CHARACTER_STATE_ATK1,
Hits: []interface{}{ Hits: []interface{}{
&MeleeBullet{ &MeleeBullet{
Bullet: Bullet{ Bullet: &BulletConfig{
StartupFrames: int32(7), StartupFrames: int32(7),
ActiveFrames: int32(22), ActiveFrames: int32(22),
HitStunFrames: int32(13), HitStunFrames: int32(13),
@@ -273,7 +320,9 @@ var skills = map[int]*Skill{
CancelTransit: map[int]int{ CancelTransit: map[int]int{
1: 5, 1: 5,
}, },
// TODO: Use non-zero "selfLockVel" BlowUp: false,
ExplosionFrames: 15,
SpeciesId: int32(2),
}, },
}, },
}, },
@@ -286,7 +335,7 @@ var skills = map[int]*Skill{
BoundChState: ATK_CHARACTER_STATE_ATK2, BoundChState: ATK_CHARACTER_STATE_ATK2,
Hits: []interface{}{ Hits: []interface{}{
&MeleeBullet{ &MeleeBullet{
Bullet: Bullet{ Bullet: &BulletConfig{
StartupFrames: int32(18), StartupFrames: int32(18),
ActiveFrames: int32(18), ActiveFrames: int32(18),
HitStunFrames: int32(18), HitStunFrames: int32(18),
@@ -300,11 +349,14 @@ var skills = map[int]*Skill{
HitboxOffsetY: int32(0), HitboxOffsetY: int32(0),
HitboxSizeX: int32(float64(24) * WORLD_TO_VIRTUAL_GRID_RATIO), HitboxSizeX: int32(float64(24) * WORLD_TO_VIRTUAL_GRID_RATIO),
HitboxSizeY: int32(float64(32) * WORLD_TO_VIRTUAL_GRID_RATIO), HitboxSizeY: int32(float64(32) * WORLD_TO_VIRTUAL_GRID_RATIO),
CancellableStFrame: int32(22), CancellableStFrame: int32(23),
CancellableEdFrame: int32(36), CancellableEdFrame: int32(36),
CancelTransit: map[int]int{ CancelTransit: map[int]int{
1: 6, 1: 6,
}, },
BlowUp: false,
ExplosionFrames: 15,
SpeciesId: int32(2),
}, },
}, },
}, },
@@ -317,21 +369,23 @@ var skills = map[int]*Skill{
BoundChState: ATK_CHARACTER_STATE_ATK3, BoundChState: ATK_CHARACTER_STATE_ATK3,
Hits: []interface{}{ Hits: []interface{}{
&MeleeBullet{ &MeleeBullet{
Bullet: Bullet{ Bullet: &BulletConfig{
StartupFrames: int32(15), StartupFrames: int32(8),
ActiveFrames: int32(28), ActiveFrames: int32(28),
HitStunFrames: MAX_INT32, HitStunFrames: MAX_INT32,
BlockStunFrames: int32(9), BlockStunFrames: int32(9),
Damage: int32(10), Damage: int32(10),
SelfLockVelX: int32(float64(-0.1) * WORLD_TO_VIRTUAL_GRID_RATIO), SelfLockVelX: NO_LOCK_VEL,
SelfLockVelY: NO_LOCK_VEL, SelfLockVelY: NO_LOCK_VEL,
PushbackVelX: int32(float64(2) * WORLD_TO_VIRTUAL_GRID_RATIO), PushbackVelX: int32(float64(2) * WORLD_TO_VIRTUAL_GRID_RATIO),
PushbackVelY: int32(float64(7) * WORLD_TO_VIRTUAL_GRID_RATIO), PushbackVelY: int32(float64(3) * WORLD_TO_VIRTUAL_GRID_RATIO),
HitboxOffsetX: int32(float64(24) * WORLD_TO_VIRTUAL_GRID_RATIO), HitboxOffsetX: int32(float64(24) * WORLD_TO_VIRTUAL_GRID_RATIO),
HitboxOffsetY: int32(0), HitboxOffsetY: int32(0),
HitboxSizeX: int32(float64(32) * WORLD_TO_VIRTUAL_GRID_RATIO), HitboxSizeX: int32(float64(32) * WORLD_TO_VIRTUAL_GRID_RATIO),
HitboxSizeY: int32(float64(32) * WORLD_TO_VIRTUAL_GRID_RATIO), HitboxSizeY: int32(float64(32) * WORLD_TO_VIRTUAL_GRID_RATIO),
BlowUp: true, BlowUp: true,
ExplosionFrames: 15,
SpeciesId: int32(2),
}, },
}, },
}, },
@@ -344,13 +398,13 @@ var skills = map[int]*Skill{
BoundChState: ATK_CHARACTER_STATE_ATK1, BoundChState: ATK_CHARACTER_STATE_ATK1,
Hits: []interface{}{ Hits: []interface{}{
&MeleeBullet{ &MeleeBullet{
Bullet: Bullet{ Bullet: &BulletConfig{
StartupFrames: int32(7), StartupFrames: int32(7),
ActiveFrames: int32(22), ActiveFrames: int32(22),
HitStunFrames: int32(13), HitStunFrames: int32(13),
BlockStunFrames: int32(9), BlockStunFrames: int32(9),
Damage: int32(5), Damage: int32(5),
SelfLockVelX: int32(float64(0.05) * WORLD_TO_VIRTUAL_GRID_RATIO), SelfLockVelX: NO_LOCK_VEL,
SelfLockVelY: NO_LOCK_VEL, SelfLockVelY: NO_LOCK_VEL,
PushbackVelX: int32(float64(0.5) * WORLD_TO_VIRTUAL_GRID_RATIO), PushbackVelX: int32(float64(0.5) * WORLD_TO_VIRTUAL_GRID_RATIO),
PushbackVelY: int32(0), PushbackVelY: int32(0),
@@ -362,9 +416,11 @@ var skills = map[int]*Skill{
CancellableEdFrame: int32(30), CancellableEdFrame: int32(30),
CancelTransit: map[int]int{ CancelTransit: map[int]int{
1: 2, 1: 8,
}, },
// TODO: Use non-zero "selfLockVel" BlowUp: false,
ExplosionFrames: 9,
SpeciesId: int32(1),
}, },
}, },
}, },
@@ -377,7 +433,7 @@ var skills = map[int]*Skill{
BoundChState: ATK_CHARACTER_STATE_ATK2, BoundChState: ATK_CHARACTER_STATE_ATK2,
Hits: []interface{}{ Hits: []interface{}{
&MeleeBullet{ &MeleeBullet{
Bullet: Bullet{ Bullet: &BulletConfig{
StartupFrames: int32(18), StartupFrames: int32(18),
ActiveFrames: int32(18), ActiveFrames: int32(18),
HitStunFrames: int32(18), HitStunFrames: int32(18),
@@ -394,34 +450,40 @@ var skills = map[int]*Skill{
CancellableStFrame: int32(22), CancellableStFrame: int32(22),
CancellableEdFrame: int32(36), CancellableEdFrame: int32(36),
CancelTransit: map[int]int{ CancelTransit: map[int]int{
1: 3, 1: 9,
}, },
BlowUp: false,
ExplosionFrames: 9,
SpeciesId: int32(1),
}, },
}, },
}, },
}, },
9: &Skill{ 9: &Skill{
RecoveryFrames: int32(50), RecoveryFrames: int32(40),
RecoveryFramesOnBlock: int32(50), RecoveryFramesOnBlock: int32(40),
RecoveryFramesOnHit: int32(50), RecoveryFramesOnHit: int32(40),
ReleaseTriggerType: int32(1), ReleaseTriggerType: int32(1),
BoundChState: ATK_CHARACTER_STATE_ATK3, BoundChState: ATK_CHARACTER_STATE_ATK3,
Hits: []interface{}{ Hits: []interface{}{
&MeleeBullet{ &MeleeBullet{
Bullet: Bullet{ Bullet: &BulletConfig{
StartupFrames: int32(15), StartupFrames: int32(7),
ActiveFrames: int32(30), ActiveFrames: int32(30),
HitStunFrames: MAX_INT32, HitStunFrames: MAX_INT32,
BlockStunFrames: int32(9), BlockStunFrames: int32(9),
Damage: int32(10), Damage: int32(10),
SelfLockVelX: int32(float64(0.5) * WORLD_TO_VIRTUAL_GRID_RATIO), SelfLockVelX: int32(float64(1) * WORLD_TO_VIRTUAL_GRID_RATIO),
SelfLockVelY: int32(float64(5) * WORLD_TO_VIRTUAL_GRID_RATIO), SelfLockVelY: NO_LOCK_VEL,
PushbackVelX: int32(float64(2) * WORLD_TO_VIRTUAL_GRID_RATIO), PushbackVelX: int32(float64(2) * WORLD_TO_VIRTUAL_GRID_RATIO),
PushbackVelY: int32(float64(7) * WORLD_TO_VIRTUAL_GRID_RATIO), PushbackVelY: int32(float64(4) * WORLD_TO_VIRTUAL_GRID_RATIO),
HitboxOffsetX: int32(float64(32) * WORLD_TO_VIRTUAL_GRID_RATIO), HitboxOffsetX: int32(float64(10) * WORLD_TO_VIRTUAL_GRID_RATIO),
HitboxOffsetY: int32(0), HitboxOffsetY: int32(0),
HitboxSizeX: int32(float64(48) * WORLD_TO_VIRTUAL_GRID_RATIO), HitboxSizeX: int32(float64(32) * WORLD_TO_VIRTUAL_GRID_RATIO),
HitboxSizeY: int32(float64(32) * WORLD_TO_VIRTUAL_GRID_RATIO), HitboxSizeY: int32(float64(32) * WORLD_TO_VIRTUAL_GRID_RATIO),
BlowUp: true,
ExplosionFrames: 9,
SpeciesId: int32(1),
}, },
}, },
}, },
@@ -434,9 +496,9 @@ var skills = map[int]*Skill{
BoundChState: ATK_CHARACTER_STATE_ATK4, BoundChState: ATK_CHARACTER_STATE_ATK4,
Hits: []interface{}{ Hits: []interface{}{
&FireballBullet{ &FireballBullet{
Speed: int32(float64(8) * WORLD_TO_VIRTUAL_GRID_RATIO), Speed: int32(float64(5) * WORLD_TO_VIRTUAL_GRID_RATIO),
Bullet: Bullet{ Bullet: &BulletConfig{
StartupFrames: int32(15), StartupFrames: int32(12),
ActiveFrames: MAX_INT32, ActiveFrames: MAX_INT32,
HitStunFrames: int32(15), HitStunFrames: int32(15),
BlockStunFrames: int32(9), BlockStunFrames: int32(9),
@@ -445,10 +507,42 @@ var skills = map[int]*Skill{
SelfLockVelY: NO_LOCK_VEL, SelfLockVelY: NO_LOCK_VEL,
PushbackVelX: int32(float64(2) * WORLD_TO_VIRTUAL_GRID_RATIO), PushbackVelX: int32(float64(2) * WORLD_TO_VIRTUAL_GRID_RATIO),
PushbackVelY: int32(0), PushbackVelY: int32(0),
HitboxOffsetX: int32(float64(32) * WORLD_TO_VIRTUAL_GRID_RATIO), HitboxOffsetX: int32(float64(24) * WORLD_TO_VIRTUAL_GRID_RATIO),
HitboxOffsetY: int32(0), HitboxOffsetY: int32(float64(5) * WORLD_TO_VIRTUAL_GRID_RATIO),
HitboxSizeX: int32(float64(48) * WORLD_TO_VIRTUAL_GRID_RATIO), HitboxSizeX: int32(float64(48) * WORLD_TO_VIRTUAL_GRID_RATIO),
HitboxSizeY: int32(float64(32) * WORLD_TO_VIRTUAL_GRID_RATIO), HitboxSizeY: int32(float64(32) * WORLD_TO_VIRTUAL_GRID_RATIO),
BlowUp: false,
ExplosionFrames: 15,
SpeciesId: int32(1),
},
},
},
},
11: &Skill{
RecoveryFrames: int32(60),
RecoveryFramesOnBlock: int32(60),
RecoveryFramesOnHit: int32(60),
ReleaseTriggerType: int32(1),
BoundChState: ATK_CHARACTER_STATE_ATK5,
Hits: []interface{}{
&MeleeBullet{
Bullet: &BulletConfig{
StartupFrames: int32(3),
ActiveFrames: int32(25),
HitStunFrames: MAX_INT32,
BlockStunFrames: int32(9),
Damage: int32(30),
SelfLockVelX: int32(float64(1) * WORLD_TO_VIRTUAL_GRID_RATIO),
SelfLockVelY: int32(float64(8) * WORLD_TO_VIRTUAL_GRID_RATIO),
PushbackVelX: int32(float64(2) * WORLD_TO_VIRTUAL_GRID_RATIO),
PushbackVelY: int32(float64(7) * WORLD_TO_VIRTUAL_GRID_RATIO),
HitboxOffsetX: int32(float64(8) * WORLD_TO_VIRTUAL_GRID_RATIO),
HitboxOffsetY: int32(0),
HitboxSizeX: int32(float64(40) * WORLD_TO_VIRTUAL_GRID_RATIO),
HitboxSizeY: int32(float64(64) * WORLD_TO_VIRTUAL_GRID_RATIO),
BlowUp: true,
ExplosionFrames: 15,
SpeciesId: int32(3),
}, },
}, },
}, },
@@ -461,7 +555,7 @@ var skills = map[int]*Skill{
BoundChState: ATK_CHARACTER_STATE_INAIR_ATK1, BoundChState: ATK_CHARACTER_STATE_INAIR_ATK1,
Hits: []interface{}{ Hits: []interface{}{
&MeleeBullet{ &MeleeBullet{
Bullet: Bullet{ Bullet: &BulletConfig{
StartupFrames: int32(3), StartupFrames: int32(3),
ActiveFrames: int32(20), ActiveFrames: int32(20),
HitStunFrames: int32(18), HitStunFrames: int32(18),
@@ -475,6 +569,9 @@ var skills = map[int]*Skill{
HitboxOffsetY: int32(0), HitboxOffsetY: int32(0),
HitboxSizeX: int32(float64(32) * WORLD_TO_VIRTUAL_GRID_RATIO), HitboxSizeX: int32(float64(32) * WORLD_TO_VIRTUAL_GRID_RATIO),
HitboxSizeY: int32(float64(24) * WORLD_TO_VIRTUAL_GRID_RATIO), HitboxSizeY: int32(float64(24) * WORLD_TO_VIRTUAL_GRID_RATIO),
BlowUp: false,
ExplosionFrames: 9,
SpeciesId: int32(1),
}, },
}, },
}, },
@@ -487,7 +584,7 @@ var skills = map[int]*Skill{
BoundChState: ATK_CHARACTER_STATE_INAIR_ATK1, BoundChState: ATK_CHARACTER_STATE_INAIR_ATK1,
Hits: []interface{}{ Hits: []interface{}{
&MeleeBullet{ &MeleeBullet{
Bullet: Bullet{ Bullet: &BulletConfig{
StartupFrames: int32(3), StartupFrames: int32(3),
ActiveFrames: int32(10), ActiveFrames: int32(10),
HitStunFrames: int32(15), HitStunFrames: int32(15),
@@ -501,6 +598,9 @@ var skills = map[int]*Skill{
HitboxOffsetY: int32(0), HitboxOffsetY: int32(0),
HitboxSizeX: int32(float64(32) * WORLD_TO_VIRTUAL_GRID_RATIO), HitboxSizeX: int32(float64(32) * WORLD_TO_VIRTUAL_GRID_RATIO),
HitboxSizeY: int32(float64(24) * WORLD_TO_VIRTUAL_GRID_RATIO), HitboxSizeY: int32(float64(24) * WORLD_TO_VIRTUAL_GRID_RATIO),
BlowUp: false,
ExplosionFrames: 15,
SpeciesId: int32(2),
}, },
}, },
}, },
@@ -513,7 +613,7 @@ var skills = map[int]*Skill{
BoundChState: ATK_CHARACTER_STATE_INAIR_ATK1, BoundChState: ATK_CHARACTER_STATE_INAIR_ATK1,
Hits: []interface{}{ Hits: []interface{}{
&MeleeBullet{ &MeleeBullet{
Bullet: Bullet{ Bullet: &BulletConfig{
StartupFrames: int32(3), StartupFrames: int32(3),
ActiveFrames: int32(20), ActiveFrames: int32(20),
HitStunFrames: int32(18), HitStunFrames: int32(18),
@@ -527,6 +627,9 @@ var skills = map[int]*Skill{
HitboxOffsetY: int32(0), HitboxOffsetY: int32(0),
HitboxSizeX: int32(float64(32) * WORLD_TO_VIRTUAL_GRID_RATIO), HitboxSizeX: int32(float64(32) * WORLD_TO_VIRTUAL_GRID_RATIO),
HitboxSizeY: int32(float64(24) * WORLD_TO_VIRTUAL_GRID_RATIO), HitboxSizeY: int32(float64(24) * WORLD_TO_VIRTUAL_GRID_RATIO),
BlowUp: false,
ExplosionFrames: 9,
SpeciesId: int32(1),
}, },
}, },
}, },

View File

@@ -33,6 +33,11 @@ type PlayerDownsync struct {
MaxHp int32 MaxHp int32
CharacterState int32 CharacterState int32
InAir bool InAir bool
OnWall bool
OnWallNormX int32
OnWallNormY int32
CapturedByInertia bool
ActiveSkillId int32 ActiveSkillId int32
ActiveSkillHit int32 ActiveSkillHit int32
@@ -59,12 +64,7 @@ type Barrier struct {
Boundary *Polygon2D Boundary *Polygon2D
} }
type Bullet struct { type BulletConfig struct {
BulletLocalId int32 // for referencing cached nodes in frontend rendering
// for offender
OriginatedRenderFrameId int32 // Copied from the first bullet for all subsequent bullets
OffenderJoinIndex int32 // Copied to favor collision handling of the dispatched bullet
StartupFrames int32 // from "OriginatedRenderFrameId" StartupFrames int32 // from "OriginatedRenderFrameId"
CancellableStFrame int32 // from "OriginatedRenderFrameId" CancellableStFrame int32 // from "OriginatedRenderFrameId"
CancellableEdFrame int32 // from "OriginatedRenderFrameId" CancellableEdFrame int32 // from "OriginatedRenderFrameId"
@@ -86,14 +86,26 @@ type Bullet struct {
HitboxSizeY int32 HitboxSizeY int32
BlowUp bool BlowUp bool
ExplosionFrames int32
SpeciesId int32 // For fireball, this SpeciesId specifies both the active animation and the explosion animation, for melee it specifies the explosion animation
CancelTransit map[int]int CancelTransit map[int]int
}
type BulletBattleAttr struct {
BulletLocalId int32 // for referencing cached nodes in frontend rendering
// for offender
OriginatedRenderFrameId int32 // Copied from the first bullet for all subsequent bullets
OffenderJoinIndex int32 // Copied to favor collision handling of the dispatched bullet
TeamId int32 TeamId int32
} }
type MeleeBullet struct { type MeleeBullet struct {
Bullet BlState int32 // bullet state, e.g. STARTUP, ACTIVE, EXPLODING
FramesInBlState int32
BattleAttr *BulletBattleAttr
Bullet *BulletConfig
} }
type FireballBullet struct { type FireballBullet struct {
@@ -104,7 +116,10 @@ type FireballBullet struct {
VelX int32 VelX int32
VelY int32 VelY int32
Speed int32 Speed int32
Bullet BlState int32 // bullet state, e.g. STARTUP, ACTIVE, EXPLODING
FramesInBlState int32
BattleAttr *BulletBattleAttr
Bullet *BulletConfig
} }
type Skill struct { type Skill struct {
@@ -115,6 +130,7 @@ type Skill struct {
ReleaseTriggerType int32 // 1: rising-edge, 2: falling-edge ReleaseTriggerType int32 // 1: rising-edge, 2: falling-edge
BoundChState int32 BoundChState int32
Hits []interface{} // Hits within a "Skill" are automatically triggered Hits []interface{} // Hits within a "Skill" are automatically triggered
// [WARN] Multihit of a fireball is more difficult to handle than that of melee, because we have to count from the fireball's first hit; the situation becomes even more complicated when a multihit fireball is in a crowd -- remains to be designed
} }
type RoomDownsyncFrame struct { type RoomDownsyncFrame struct {

View File

@@ -42,7 +42,7 @@ func NewBarrierJs(boundary *Polygon2D) *js.Object {
}) })
} }
func NewPlayerDownsyncJs(id, virtualGridX, virtualGridY, dirX, dirY, velX, velY, framesToRecover, framesInChState, activeSkillId, activeSkillHit, framesInvinsible, speed, battleState, characterState, joinIndex, hp, maxHp, colliderRadius int32, inAir bool, bulletTeamId, chCollisionTeamId int32) *js.Object { func NewPlayerDownsyncJs(id, virtualGridX, virtualGridY, dirX, dirY, velX, velY, framesToRecover, framesInChState, activeSkillId, activeSkillHit, framesInvinsible, speed, battleState, characterState, joinIndex, hp, maxHp, colliderRadius int32, inAir, onWall bool, onWallNormX, onWallNormY int32, capturedByInertia bool, bulletTeamId, chCollisionTeamId int32) *js.Object {
return js.MakeWrapper(&PlayerDownsync{ return js.MakeWrapper(&PlayerDownsync{
Id: id, Id: id,
VirtualGridX: virtualGridX, VirtualGridX: virtualGridX,
@@ -64,82 +64,21 @@ func NewPlayerDownsyncJs(id, virtualGridX, virtualGridY, dirX, dirY, velX, velY,
MaxHp: maxHp, MaxHp: maxHp,
ColliderRadius: colliderRadius, ColliderRadius: colliderRadius,
InAir: inAir, InAir: inAir,
OnWall: onWall,
OnWallNormX: onWallNormX,
OnWallNormY: onWallNormY,
CapturedByInertia: capturedByInertia,
BulletTeamId: bulletTeamId, BulletTeamId: bulletTeamId,
ChCollisionTeamId: chCollisionTeamId, ChCollisionTeamId: chCollisionTeamId,
}) })
} }
func NewMeleeBulletJs(bulletLocalId, originatedRenderFrameId, offenderJoinIndex, startupFrames, cancellableStFrame, cancellableEdFrame, activeFrames, hitStunFrames, blockStunFrames, pushbackVelX, pushbackVelY, damage, selfLockVelX, selfLockVelY, hitboxOffsetX, hitboxOffsetY, hitboxSizeX, hitboxSizeY int32, blowUp bool, teamId int32) *js.Object { func NewMeleeBulletJs(bulletLocalId, originatedRenderFrameId, offenderJoinIndex, startupFrames, cancellableStFrame, cancellableEdFrame, activeFrames, hitStunFrames, blockStunFrames, pushbackVelX, pushbackVelY, damage, selfLockVelX, selfLockVelY, hitboxOffsetX, hitboxOffsetY, hitboxSizeX, hitboxSizeY int32, blowUp bool, teamId, blState, framesInBlState, explosionFrames, speciesId int32) *js.Object {
return js.MakeWrapper(&MeleeBullet{ return js.MakeWrapper(NewMeleeBullet(bulletLocalId, originatedRenderFrameId, offenderJoinIndex, startupFrames, cancellableStFrame, cancellableEdFrame, activeFrames, hitStunFrames, blockStunFrames, pushbackVelX, pushbackVelY, damage, selfLockVelX, selfLockVelY, hitboxOffsetX, hitboxOffsetY, hitboxSizeX, hitboxSizeY, blowUp, teamId, blState, framesInBlState, explosionFrames, speciesId))
Bullet: Bullet{
BulletLocalId: bulletLocalId,
OriginatedRenderFrameId: originatedRenderFrameId,
OffenderJoinIndex: offenderJoinIndex,
StartupFrames: startupFrames,
CancellableStFrame: cancellableStFrame,
CancellableEdFrame: cancellableEdFrame,
ActiveFrames: activeFrames,
HitStunFrames: hitStunFrames,
BlockStunFrames: blockStunFrames,
PushbackVelX: pushbackVelX,
PushbackVelY: pushbackVelY,
Damage: damage,
SelfLockVelX: selfLockVelX,
SelfLockVelY: selfLockVelY,
HitboxOffsetX: hitboxOffsetX,
HitboxOffsetY: hitboxOffsetY,
HitboxSizeX: hitboxSizeX,
HitboxSizeY: hitboxSizeY,
BlowUp: blowUp,
TeamId: teamId,
},
})
} }
func NewFireballBulletJs(bulletLocalId, originatedRenderFrameId, offenderJoinIndex, startupFrames, cancellableStFrame, cancellableEdFrame, activeFrames, hitStunFrames, blockStunFrames, pushbackVelX, pushbackVelY, damage, selfLockVelX, selfLockVelY, hitboxOffsetX, hitboxOffsetY, hitboxSizeX, hitboxSizeY int32, blowUp bool, teamId int32, virtualGridX, virtualGridY, dirX, dirY, velX, velY, speed int32) *js.Object { func NewFireballBulletJs(bulletLocalId, originatedRenderFrameId, offenderJoinIndex, startupFrames, cancellableStFrame, cancellableEdFrame, activeFrames, hitStunFrames, blockStunFrames, pushbackVelX, pushbackVelY, damage, selfLockVelX, selfLockVelY, hitboxOffsetX, hitboxOffsetY, hitboxSizeX, hitboxSizeY int32, blowUp bool, teamId int32, virtualGridX, virtualGridY, dirX, dirY, velX, velY, speed, blState, framesInBlState, explosionFrames, speciesId int32) *js.Object {
return js.MakeWrapper(&FireballBullet{ return js.MakeWrapper(NewFireballBullet(bulletLocalId, originatedRenderFrameId, offenderJoinIndex, startupFrames, cancellableStFrame, cancellableEdFrame, activeFrames, hitStunFrames, blockStunFrames, pushbackVelX, pushbackVelY, damage, selfLockVelX, selfLockVelY, hitboxOffsetX, hitboxOffsetY, hitboxSizeX, hitboxSizeY, blowUp, teamId, virtualGridX, virtualGridY, dirX, dirY, velX, velY, speed, blState, framesInBlState, explosionFrames, speciesId))
VirtualGridX: virtualGridX,
VirtualGridY: virtualGridY,
DirX: dirX,
DirY: dirY,
VelX: velX,
VelY: velY,
Speed: speed,
Bullet: Bullet{
BulletLocalId: bulletLocalId,
OriginatedRenderFrameId: originatedRenderFrameId,
OffenderJoinIndex: offenderJoinIndex,
StartupFrames: startupFrames,
CancellableStFrame: cancellableStFrame,
CancellableEdFrame: cancellableEdFrame,
ActiveFrames: activeFrames,
HitStunFrames: hitStunFrames,
BlockStunFrames: blockStunFrames,
PushbackVelX: pushbackVelX,
PushbackVelY: pushbackVelY,
Damage: damage,
SelfLockVelX: selfLockVelX,
SelfLockVelY: selfLockVelY,
HitboxOffsetX: hitboxOffsetX,
HitboxOffsetY: hitboxOffsetY,
HitboxSizeX: hitboxSizeX,
HitboxSizeY: hitboxSizeY,
BlowUp: blowUp,
TeamId: teamId,
},
})
} }
func NewNpcPatrolCue(flAct, frAct uint64, x, y float64) *js.Object { func NewNpcPatrolCue(flAct, frAct uint64, x, y float64) *js.Object {
@@ -233,5 +172,9 @@ func main() {
"ConvertToFirstUsedRenderFrameId": ConvertToFirstUsedRenderFrameId, "ConvertToFirstUsedRenderFrameId": ConvertToFirstUsedRenderFrameId,
"ConvertToLastUsedRenderFrameId": ConvertToLastUsedRenderFrameId, "ConvertToLastUsedRenderFrameId": ConvertToLastUsedRenderFrameId,
"ShouldGenerateInputFrameUpsync": ShouldGenerateInputFrameUpsync, "ShouldGenerateInputFrameUpsync": ShouldGenerateInputFrameUpsync,
"IsMeleeBulletActive": IsMeleeBulletActive,
"IsMeleeBulletAlive": IsMeleeBulletAlive,
"IsFireballBulletActive": IsFireballBulletActive,
"IsFireballBulletAlive": IsFireballBulletAlive,
}) })
} }

View File

@@ -66,4 +66,21 @@ hp application/json application/javascript;
proxy_pass http://tsrht_cluster/tsrht$is_args$args; proxy_pass http://tsrht_cluster/tsrht$is_args$args;
} }
location ~^/tsrhtSecondary$ {
# Reference http://www.tornadoweb.org/en/stable/guide/running.html
proxy_pass_header Server;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Scheme $scheme;
# Reverse-proxy for ws connection.
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_pass http://tsrht_cluster/tsrhtSecondary$is_args$args;
}
} }