Compare commits
31 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
ec2a21dbe7 | ||
|
dc6402c2b7 | ||
|
8038b393e0 | ||
|
4e0f7b52d4 | ||
|
486c46f608 | ||
|
6d075877ec | ||
|
fe826b393b | ||
|
c69aa25353 | ||
|
0f4d067c06 | ||
|
cff31d295c | ||
|
150e30db2a | ||
|
bc8989a0e6 | ||
|
1959a7fd9a | ||
|
3baaf1d52c | ||
|
62f10e0877 | ||
|
c3c7854e92 | ||
|
cb794d70c7 | ||
|
0047259e9f | ||
|
232d8ad148 | ||
|
d49e7830d4 | ||
|
1122f4d71c | ||
|
f2c8d4cd65 | ||
|
4e7f9e63ac | ||
|
e762d257a6 | ||
|
286944b88c | ||
|
05dc593d2c | ||
|
5f9aaddc9c | ||
|
e224aaf680 | ||
|
9c07b43157 | ||
|
3203ea9f1e | ||
|
d90c4ead91 |
86
README.md
@@ -1,47 +1,79 @@
|
||||
# 0. Preface
|
||||
If you'd like to play with the backend code seriously, please read the detailed explanation of its important "lifecycle events" in [this note](https://app.yinxiang.com/fx/5c575124-01db-419b-9c02-ec81f78c6ddc).
|
||||
# Preface
|
||||
|
||||
There could be some left over wechat-game related code pieces, but they're neither meant to work nor supported anymore.
|
||||
This project is a demo for a websocket-based input synchronization method inspired by [GGPO](https://www.ggpo.net/).
|
||||

|
||||
|
||||
Please checkout [this demo video](https://pan.baidu.com/s/123LlWcT9X-wbcYybqYnvmA?pwd=qrlw) to see whether the source codes are doing what you expect for synchronization.
|
||||
|
||||
The video mainly shows the following features.
|
||||
- The backend receives inputs from frontend peers and [by a GGPO-alike manner](https://github.com/pond3r/ggpo/blob/master/doc/README.md) broadcasts back for synchronization.
|
||||
- The game is recovered for a player upon reconnection.
|
||||
- Both backend(Golang) and frontend(JavaScript) execute collision detection and handle collision contacts by the same algorithm. The backend dynamics can be toggled off 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**.
|
||||
|
||||
# 1. Building & running
|
||||
|
||||
## 1.1 Golang1.19.1
|
||||
Documentation TBD.
|
||||
## 1.1 Tools to install
|
||||
### 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)
|
||||
- [Golang1.19.1](https://golang.org/dl/) (mandatory, in China please try a mirror site like [that of ustc](https://mirrors.ustc.edu.cn/golang/))
|
||||
- [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)
|
||||
- [skeema](https://www.skeema.io/) (optional, only for convenient MySQL schema provisioning)
|
||||
- [protobuf CLI](https://developers.google.com/protocol-buffers/docs/downloads) (optional, only for development)
|
||||
|
||||
## 1.2 MySQL
|
||||
The database product to be used for this project is MySQL 5.7, you can install and manage `MySQL` server by [these scripts](https://github.com/genxium/Ubuntu14InitScripts/tree/master/database/mysql).
|
||||
### Frontend
|
||||
- [CocosCreator v2.2.1](https://www.cocos.com/en/cocos-creator-2-2-1-released-with-performance-improvements) (mandatory, **ONLY AVAILABLE on Windows or OSX and should be exactly this version**, DON'T use any other version because CocosCreator is well-known for new versions not being backward incompatible)
|
||||
- [protojs](https://www.npmjs.com/package/protojs) (optional, only for development)
|
||||
|
||||
We use [skeema](https://github.com/skeema/skeema) for schematic synchronization under `<proj-root>/database/skeema-repo-root/` which intentionally doesn't contain a `.skeema` file. Please read [this tutorial](https://shimo.im/doc/wQ0LvB0rlZcbHF5V) for more information. For `Windows 10/11`, you can compile `skeema` from source and config the host to be `127.0.0.1` instead of `localhost` to use it, i.e. circumventing the pitfall for MySQL unix socket connection on Windows.
|
||||
|
||||
The following command(s)
|
||||
## 1.2 Provisioning
|
||||
### Backend/Database
|
||||
It's strongly recommended that `skeema` is used for provisioning [the required schema](https://github.com/genxium/DelayNoMore/tree/main/database/skeema-repo-root) in MySQL instance. When using `skeema` the steps are as follows.
|
||||
```
|
||||
### Optional.
|
||||
### Mandatory after an initial clone
|
||||
user@proj-root/database/skeema-repo-root> cp .skeema.template .skeema
|
||||
|
||||
###
|
||||
user@proj-root/database/skeema-repo-root> skeema diff
|
||||
### Mandatory
|
||||
user@proj-root/database/skeema-repo-root> skeema push
|
||||
```
|
||||
is recommended to be used for checking difference from your "live MySQL server" to the latest expected schema tracked in git.
|
||||
|
||||
## 1.3 Required Config Files
|
||||
On `Windows 10/11`, you can compile `skeema` from source and config the host to be `127.0.0.1` instead of `localhost` to use it, i.e. circumventing the pitfall for MySQL unix socket connection on Windows.
|
||||
|
||||
### 1.3.1 Backend
|
||||
- It needs `<proj-root>/battle_srv/configs/*` which is generated by `cd <proj-root>/battle_srv && cp -r ./configs.template ./configs` and necessary customization.
|
||||
### Backend/Golang
|
||||
```
|
||||
user@proj-root/battle_srv/configs> cp -r ./configs.template ./configs
|
||||
```
|
||||
|
||||
### 1.3.2 Frontend
|
||||
- It needs CocosCreator v2.2.1 to build.
|
||||
- A required "CocosCreator plugin `i18n`" is already enclosed in the project, if you have a globally installed "CocosCreator plugin `i18n`"(often located at `$HOME/.CocosCreator/packages/`) they should be OK to co-exist.
|
||||
- It needs `<proj-root>/frontend/assets/plugin_scripts/conf.js` which is generated by `cd <proj-root>/frontend/assets/plugin_scripts && cp conf.js.template conf.js`.
|
||||
### Frontend
|
||||
```
|
||||
user@proj-root/frontend/assets/plugin_scripts> cp ./conf.js.template ./conf.js
|
||||
```
|
||||
|
||||
## 1.4 Troubleshooting
|
||||
## 1.2 Actual building & running
|
||||
### 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
|
||||
user@anywhere> mysqld
|
||||
|
||||
### 1.4.1 Redis snapshot writing failure
|
||||
### The following command runs redis-server in foreground, it's OK to put it in background
|
||||
user@anywhere> redis-server
|
||||
|
||||
### on Windows using TDM-GCC: mingw32-make run-test
|
||||
user@proj-root/battle_srv> make run-test
|
||||
```
|
||||
|
||||
### Frontend
|
||||
The easy way is to try out 2 players with test accounts on a same machine.
|
||||
- Open CocosCreator v2.2.1 (mandatory, it serves the web content of the following steps)
|
||||
- Open one browser instance, visit _http://localhost:7456?expectedRoomId=1_, input `add`on the username box and click to request a captcha, this is a test account so a captcha would be returned by the backend and filled automatically (as shown in the figure below), then click and click to proceed to a matching scene.
|
||||
- Open another browser instance, visit _http://localhost:7456?expectedRoomId=1_, input `bdd`on the username box and click to request a captcha, this is another test account so a captcha would be returned by the backend and filled automatically, then click and click to proceed, when matched a `battle`(but no competition rule yet) would start.
|
||||
- Try out the onscreen virtual joysticks to move the cars and see if their movements are in-sync.
|
||||

|
||||
|
||||
## 2 Troubleshooting
|
||||
|
||||
### 2.1 Redis snapshot writing failure
|
||||
```
|
||||
ErrFatal {"err": "MISCONF Redis is configured to save RDB snapshots, but is currently not able to persist on disk. Commands that may modify the data set are disabled. Please check Redis logs for details about the error."}
|
||||
```
|
||||
|
||||
Just restart your `redis-server` process.
|
||||
|
||||
# 2. Git configs cautions
|
||||
|
||||
Please make sure that you've set `ignorecase = false` in your `[core] section of <proj-root>/.git/config`.
|
||||
|
@@ -2,10 +2,10 @@ package api
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
. "dnmshared"
|
||||
"github.com/gin-gonic/gin"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
. "server/common"
|
||||
)
|
||||
|
||||
func RequestLogger() gin.HandlerFunc {
|
||||
|
@@ -16,6 +16,8 @@ import (
|
||||
"server/models"
|
||||
"server/storage"
|
||||
"strconv"
|
||||
|
||||
. "dnmshared"
|
||||
)
|
||||
|
||||
var Player = playerController{}
|
||||
|
@@ -1,16 +1,15 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
. "dnmshared"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"go.uber.org/zap"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
// 隐式导入
|
||||
var Conf *config
|
||||
|
||||
const (
|
||||
@@ -72,11 +71,15 @@ func MustParseConfig() {
|
||||
BotServer: new(botServerConf),
|
||||
}
|
||||
execPath, err := os.Executable()
|
||||
ErrFatal(err)
|
||||
if nil != err {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
pwd, err := os.Getwd()
|
||||
Logger.Debug("os.GetWd", zap.String("pwd", pwd))
|
||||
ErrFatal(err)
|
||||
if nil != err {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
appRoot := pwd
|
||||
confDir := filepath.Join(appRoot, "configs")
|
||||
@@ -129,22 +132,21 @@ func loadJSON(fp string, v interface{}) {
|
||||
fp = filepath.Join(Conf.General.ConfDir, fp)
|
||||
}
|
||||
_, err := os.Stat(fp)
|
||||
ErrFatal(err)
|
||||
if nil != err {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
fd, err := os.Open(fp)
|
||||
ErrFatal(err)
|
||||
if nil != err {
|
||||
panic(err)
|
||||
}
|
||||
defer fd.Close()
|
||||
Logger.Info("Opened json file successfully.", zap.String("fp", fp))
|
||||
err = json.NewDecoder(fd).Decode(v)
|
||||
ErrFatal(err)
|
||||
Logger.Info("Loaded json file successfully.", zap.String("fp", fp))
|
||||
}
|
||||
|
||||
// Please only use this auxiliary function before server is fully started up, but not afterwards (启动过程可以使用,运行时不准使用).
|
||||
func ErrFatal(err error) {
|
||||
if err != nil {
|
||||
Logger.Fatal("ErrFatal", zap.NamedError("err", err))
|
||||
if nil != err {
|
||||
panic(err)
|
||||
}
|
||||
Logger.Info("Loaded json file successfully.", zap.String("fp", fp))
|
||||
}
|
||||
|
||||
func isNotExist(p string) bool {
|
||||
|
@@ -5,9 +5,10 @@ import (
|
||||
|
||||
"github.com/imdario/mergo"
|
||||
"go.uber.org/zap"
|
||||
|
||||
. "dnmshared"
|
||||
)
|
||||
|
||||
// 隐式导入
|
||||
var Constants *constants
|
||||
|
||||
func MustParseConstants() {
|
||||
@@ -24,13 +25,11 @@ func MustParseConstants() {
|
||||
if !isNotExist(fp) {
|
||||
testConstants := new(constants)
|
||||
loadJSON(fp, testConstants)
|
||||
//Logger.Debug(spew.Sdump(Constants))
|
||||
//Logger.Debug(spew.Sdump(testConstants))
|
||||
err := mergo.Merge(testConstants, Constants)
|
||||
ErrFatal(err)
|
||||
if nil != err {
|
||||
panic(err)
|
||||
}
|
||||
Constants = testConstants
|
||||
//Logger.Debug("mergo.Merge", zap.Error(err))
|
||||
//Logger.Debug(spew.Sdump(testConstants))
|
||||
}
|
||||
}
|
||||
constantsPost()
|
||||
|
@@ -3,6 +3,7 @@ package utils
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/sha1"
|
||||
. "dnmshared"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"go.uber.org/zap"
|
||||
|
@@ -11,7 +11,6 @@ var (
|
||||
RE_CHINA_PHONE_NUM = regexp.MustCompile(`^(13[0-9]|14[5|7]|15[0|1|2|3|5|6|7|8|9]|18[0|1|2|3|5|6|7|8|9])\d{8}$`)
|
||||
)
|
||||
|
||||
// 隐式导入
|
||||
var ConstVals = &struct {
|
||||
Player struct {
|
||||
CaptchaExpire time.Duration
|
||||
|
@@ -1,6 +1,7 @@
|
||||
package env_tools
|
||||
|
||||
import (
|
||||
. "dnmshared"
|
||||
sq "github.com/Masterminds/squirrel"
|
||||
"github.com/jmoiron/sqlx"
|
||||
_ "github.com/mattn/go-sqlite3"
|
||||
@@ -15,7 +16,9 @@ func LoadPreConf() {
|
||||
Logger.Info(`Merging PreConfSQLite data into MySQL`,
|
||||
zap.String("PreConfSQLitePath", Conf.General.PreConfSQLitePath))
|
||||
db, err := sqlx.Connect("sqlite3", Conf.General.PreConfSQLitePath)
|
||||
ErrFatal(err)
|
||||
if nil != err {
|
||||
panic(err)
|
||||
}
|
||||
defer db.Close()
|
||||
|
||||
loadPreConfToMysql(db)
|
||||
@@ -39,7 +42,9 @@ func loadPreConfToMysql(db *sqlx.DB) {
|
||||
func loadSqlite(db *sqlx.DB, tbs []string) {
|
||||
for _, v := range tbs {
|
||||
result, err := storage.MySQLManagerIns.Exec("truncate " + v)
|
||||
ErrFatal(err)
|
||||
if nil != err {
|
||||
panic(err)
|
||||
}
|
||||
Logger.Info("truncate", zap.Any("truncate "+v, result))
|
||||
query, args, err := sq.Select("*").From(v).ToSql()
|
||||
if err != nil {
|
||||
@@ -70,19 +75,25 @@ func createMysqlData(rows *sqlx.Rows, v string) {
|
||||
func maybeCreateNewPlayerFromBotTable(db *sqlx.DB, tableName string) {
|
||||
var ls []*dbBotPlayer
|
||||
err := db.Select(&ls, "SELECT name, magic_phone_country_code, magic_phone_num, display_name FROM "+tableName)
|
||||
ErrFatal(err)
|
||||
if nil != err {
|
||||
panic(err)
|
||||
}
|
||||
names := make([]string, len(ls), len(ls))
|
||||
for i, v := range ls {
|
||||
names[i] = v.Name
|
||||
}
|
||||
sql := "SELECT name FROM `player` WHERE name in (?)"
|
||||
query, args, err := sqlx.In(sql, names)
|
||||
ErrFatal(err)
|
||||
if nil != err {
|
||||
panic(err)
|
||||
}
|
||||
query = storage.MySQLManagerIns.Rebind(query)
|
||||
// existNames := make([]string, len(ls), len(ls))
|
||||
var existPlayers []*models.Player
|
||||
err = storage.MySQLManagerIns.Select(&existPlayers, query, args...)
|
||||
ErrFatal(err)
|
||||
if nil != err {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
for _, botPlayer := range ls {
|
||||
var flag bool
|
||||
|
@@ -1,6 +1,7 @@
|
||||
package env_tools
|
||||
|
||||
import (
|
||||
. "dnmshared"
|
||||
. "server/common"
|
||||
"server/common/utils"
|
||||
"server/models"
|
||||
@@ -15,7 +16,9 @@ func MergeTestPlayerAccounts() {
|
||||
fp := Conf.General.TestEnvSQLitePath
|
||||
Logger.Info(`Initializing TestPlayerAccounts in runtime MySQLServer from SQLite file:`, zap.String("fp", fp))
|
||||
db, err := sqlx.Connect("sqlite3", fp)
|
||||
ErrFatal(err)
|
||||
if nil != err {
|
||||
panic(err)
|
||||
}
|
||||
defer db.Close()
|
||||
maybeCreateNewPlayer(db, "test_player")
|
||||
}
|
||||
@@ -29,31 +32,35 @@ type dbTestPlayer struct {
|
||||
func maybeCreateNewPlayer(db *sqlx.DB, tableName string) {
|
||||
var ls []*dbTestPlayer
|
||||
err := db.Select(&ls, "SELECT name, magic_phone_country_code, magic_phone_num FROM "+tableName)
|
||||
ErrFatal(err)
|
||||
if nil != err {
|
||||
panic(err)
|
||||
}
|
||||
names := make([]string, len(ls), len(ls))
|
||||
for i, v := range ls {
|
||||
names[i] = v.Name
|
||||
}
|
||||
sql := "SELECT name FROM `player` WHERE name in (?)"
|
||||
query, args, err := sqlx.In(sql, names)
|
||||
ErrFatal(err)
|
||||
if nil != err {
|
||||
panic(err)
|
||||
}
|
||||
query = storage.MySQLManagerIns.Rebind(query)
|
||||
// existNames := make([]string, len(ls), len(ls))
|
||||
var existPlayers []*models.Player
|
||||
err = storage.MySQLManagerIns.Select(&existPlayers, query, args...)
|
||||
ErrFatal(err)
|
||||
if nil != err {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
for _, testPlayer := range ls {
|
||||
var flag bool
|
||||
for _, v := range existPlayers {
|
||||
if testPlayer.Name == v.Name {
|
||||
// 已有数据,合并处理
|
||||
flag = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !flag {
|
||||
// 找不到,新增
|
||||
Logger.Debug("create", zap.Any(tableName, testPlayer))
|
||||
err := createNewPlayer(testPlayer)
|
||||
if err != nil {
|
||||
|
@@ -3,7 +3,6 @@ module server
|
||||
go 1.19
|
||||
|
||||
require (
|
||||
github.com/ByteArena/box2d v1.0.2
|
||||
github.com/Masterminds/squirrel v0.0.0-20180815162352-8a7e65843414
|
||||
github.com/davecgh/go-spew v1.1.1
|
||||
github.com/gin-contrib/cors v0.0.0-20180514151808-6f0a820f94be
|
||||
@@ -21,6 +20,8 @@ require (
|
||||
github.com/thoas/go-funk v0.0.0-20180716193722-1060394a7713
|
||||
go.uber.org/zap v1.9.1
|
||||
google.golang.org/protobuf v1.28.1
|
||||
|
||||
dnmshared v0.0.0
|
||||
)
|
||||
|
||||
require (
|
||||
@@ -44,3 +45,7 @@ require (
|
||||
gopkg.in/go-playground/validator.v8 v8.18.2 // indirect
|
||||
gopkg.in/yaml.v2 v2.2.1 // indirect
|
||||
)
|
||||
|
||||
replace (
|
||||
dnmshared => ../dnmshared
|
||||
)
|
||||
|
@@ -10,8 +10,6 @@ import (
|
||||
"server/api"
|
||||
"server/api/v1"
|
||||
. "server/common"
|
||||
"server/common/utils"
|
||||
"server/configs"
|
||||
"server/env_tools"
|
||||
"server/models"
|
||||
"server/storage"
|
||||
@@ -19,6 +17,8 @@ import (
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
. "dnmshared"
|
||||
|
||||
"github.com/gin-contrib/cors"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/robfig/cron"
|
||||
@@ -30,8 +30,6 @@ func main() {
|
||||
MustParseConstants()
|
||||
storage.Init()
|
||||
env_tools.LoadPreConf()
|
||||
utils.InitWechat(configs.WechatConfigIns)
|
||||
utils.InitWechatGame(configs.WechatGameConfigIns)
|
||||
if Conf.General.ServerEnv == SERVER_ENV_TEST {
|
||||
env_tools.MergeTestPlayerAccounts()
|
||||
}
|
||||
|
@@ -1,5 +1,9 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
. "dnmshared"
|
||||
)
|
||||
|
||||
type Barrier struct {
|
||||
Boundary *Polygon2D
|
||||
}
|
||||
|
@@ -1,132 +0,0 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/ByteArena/box2d"
|
||||
"math"
|
||||
)
|
||||
|
||||
// Use type `float64` for json unmarshalling of numbers.
|
||||
type Direction struct {
|
||||
Dx int32 `json:"dx,omitempty"`
|
||||
Dy int32 `json:"dy,omitempty"`
|
||||
}
|
||||
|
||||
type Vec2D struct {
|
||||
X float64 `json:"x,omitempty"`
|
||||
Y float64 `json:"y,omitempty"`
|
||||
}
|
||||
|
||||
func CreateVec2DFromB2Vec2(b2V2 box2d.B2Vec2) *Vec2D {
|
||||
return &Vec2D{
|
||||
X: b2V2.X,
|
||||
Y: b2V2.Y,
|
||||
}
|
||||
}
|
||||
|
||||
func (v2 *Vec2D) ToB2Vec2() box2d.B2Vec2 {
|
||||
return box2d.MakeB2Vec2(v2.X, v2.Y)
|
||||
}
|
||||
|
||||
type Polygon2D struct {
|
||||
Anchor *Vec2D `json:"-"` // This "Polygon2D.Anchor" is used to be assigned to "B2BodyDef.Position", which in turn is used as the position of the FIRST POINT of the polygon.
|
||||
Points []*Vec2D `json:"-"`
|
||||
|
||||
/*
|
||||
When used to represent a "polyline directly drawn in a `Tmx file`", we can initialize both "Anchor" and "Points" simultaneously.
|
||||
|
||||
Yet when used to represent a "polyline drawn in a `Tsx file`", we have to first initialize "Points w.r.t. center of the tile-rectangle", and then "Anchor(initially nil) of the tile positioned in the `Tmx file`".
|
||||
|
||||
Refer to https://shimo.im/docs/SmLJJhXm2C8XMzZT for more information.
|
||||
*/
|
||||
|
||||
/*
|
||||
[WARNING] Used to cache "`TileWidth & TileHeight` of a Tsx file" only.
|
||||
*/
|
||||
TileWidth int
|
||||
TileHeight int
|
||||
|
||||
/*
|
||||
[WARNING] Used to cache "`Width & TileHeight` of an object in Tmx file" only.
|
||||
*/
|
||||
TmxObjectWidth float64
|
||||
TmxObjectHeight float64
|
||||
}
|
||||
|
||||
func MoveDynamicBody(body *box2d.B2Body, pToTargetPos *box2d.B2Vec2, inSeconds float64) {
|
||||
if body.GetType() != box2d.B2BodyType.B2_dynamicBody {
|
||||
return
|
||||
}
|
||||
body.SetTransform(*pToTargetPos, 0.0)
|
||||
body.SetLinearVelocity(box2d.MakeB2Vec2(0.0, 0.0))
|
||||
body.SetAngularVelocity(0.0)
|
||||
}
|
||||
|
||||
func PrettyPrintFixture(fix *box2d.B2Fixture) {
|
||||
fmt.Printf("\t\tfriction:\t%v\n", fix.M_friction)
|
||||
fmt.Printf("\t\trestitution:\t%v\n", fix.M_restitution)
|
||||
fmt.Printf("\t\tdensity:\t%v\n", fix.M_density)
|
||||
fmt.Printf("\t\tisSensor:\t%v\n", fix.M_isSensor)
|
||||
fmt.Printf("\t\tfilter.categoryBits:\t%d\n", fix.M_filter.CategoryBits)
|
||||
fmt.Printf("\t\tfilter.maskBits:\t%d\n", fix.M_filter.MaskBits)
|
||||
fmt.Printf("\t\tfilter.groupIndex:\t%d\n", fix.M_filter.GroupIndex)
|
||||
|
||||
switch fix.M_shape.GetType() {
|
||||
case box2d.B2Shape_Type.E_circle:
|
||||
{
|
||||
s := fix.M_shape.(*box2d.B2CircleShape)
|
||||
fmt.Printf("\t\tb2CircleShape shape: {\n")
|
||||
fmt.Printf("\t\t\tradius:\t%v\n", s.M_radius)
|
||||
fmt.Printf("\t\t\toffset:\t%v\n", s.M_p)
|
||||
fmt.Printf("\t\t}\n")
|
||||
}
|
||||
break
|
||||
|
||||
case box2d.B2Shape_Type.E_polygon:
|
||||
{
|
||||
s := fix.M_shape.(*box2d.B2PolygonShape)
|
||||
fmt.Printf("\t\tb2PolygonShape shape: {\n")
|
||||
for i := 0; i < s.M_count; i++ {
|
||||
fmt.Printf("\t\t\t%v\n", s.M_vertices[i])
|
||||
}
|
||||
fmt.Printf("\t\t}\n")
|
||||
}
|
||||
break
|
||||
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
func PrettyPrintBody(body *box2d.B2Body) {
|
||||
bodyIndex := body.M_islandIndex
|
||||
|
||||
fmt.Printf("{\n")
|
||||
fmt.Printf("\tHeapRAM addr:\t%p\n", body)
|
||||
fmt.Printf("\ttype:\t%d\n", body.M_type)
|
||||
fmt.Printf("\tposition:\t%v\n", body.GetPosition())
|
||||
fmt.Printf("\tangle:\t%v\n", body.M_sweep.A)
|
||||
fmt.Printf("\tlinearVelocity:\t%v\n", body.GetLinearVelocity())
|
||||
fmt.Printf("\tangularVelocity:\t%v\n", body.GetAngularVelocity())
|
||||
fmt.Printf("\tlinearDamping:\t%v\n", body.M_linearDamping)
|
||||
fmt.Printf("\tangularDamping:\t%v\n", body.M_angularDamping)
|
||||
fmt.Printf("\tallowSleep:\t%d\n", body.M_flags&box2d.B2Body_Flags.E_autoSleepFlag)
|
||||
fmt.Printf("\tawake:\t%d\n", body.M_flags&box2d.B2Body_Flags.E_awakeFlag)
|
||||
fmt.Printf("\tfixedRotation:\t%d\n", body.M_flags&box2d.B2Body_Flags.E_fixedRotationFlag)
|
||||
fmt.Printf("\tbullet:\t%d\n", body.M_flags&box2d.B2Body_Flags.E_bulletFlag)
|
||||
fmt.Printf("\tactive:\t%d\n", body.M_flags&box2d.B2Body_Flags.E_activeFlag)
|
||||
fmt.Printf("\tgravityScale:\t%v\n", body.M_gravityScale)
|
||||
fmt.Printf("\tislandIndex:\t%v\n", bodyIndex)
|
||||
fmt.Printf("\tfixtures: {\n")
|
||||
for f := body.M_fixtureList; f != nil; f = f.M_next {
|
||||
PrettyPrintFixture(f)
|
||||
}
|
||||
fmt.Printf("\t}\n")
|
||||
fmt.Printf("}\n")
|
||||
}
|
||||
|
||||
func Distance(pt1 *Vec2D, pt2 *Vec2D) float64 {
|
||||
dx := pt1.X - pt2.X
|
||||
dy := pt1.Y - pt2.Y
|
||||
return math.Sqrt(dx*dx + dy*dy)
|
||||
}
|
@@ -1,6 +1,7 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
. "dnmshared"
|
||||
pb "server/pb_output"
|
||||
)
|
||||
|
||||
|
@@ -2,6 +2,7 @@ package models
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
. "dnmshared"
|
||||
"fmt"
|
||||
sq "github.com/Masterminds/squirrel"
|
||||
"github.com/jmoiron/sqlx"
|
||||
|
@@ -2,7 +2,7 @@ package models
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
. "server/common"
|
||||
. "dnmshared"
|
||||
"server/storage"
|
||||
|
||||
sq "github.com/Masterminds/squirrel"
|
@@ -2,6 +2,7 @@ package models
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
. "dnmshared"
|
||||
"errors"
|
||||
. "server/common"
|
||||
"server/common/utils"
|
||||
|
@@ -1,6 +1,7 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
. "dnmshared"
|
||||
"encoding/xml"
|
||||
"fmt"
|
||||
"github.com/golang/protobuf/proto"
|
||||
@@ -158,6 +159,7 @@ type Room struct {
|
||||
RenderFrameId int32
|
||||
CurDynamicsRenderFrameId int32 // [WARNING] The dynamics of backend is ALWAYS MOVING FORWARD BY ALL-CONFIRMED INPUTFRAMES (either by upsync or forced), i.e. no rollback
|
||||
ServerFps int32
|
||||
BattleDurationFrames int32
|
||||
BattleDurationNanos int64
|
||||
InputFrameUpsyncDelayTolerance int32
|
||||
MaxChasingRenderFramesPerUpdate int32
|
||||
@@ -175,6 +177,9 @@ type Room struct {
|
||||
InputScaleFrames uint32 // inputDelayedAndScaledFrameId = ((originalFrameId - InputDelayFrames) >> InputScaleFrames)
|
||||
JoinIndexBooleanArr []bool
|
||||
RollbackEstimatedDt float64
|
||||
RollbackEstimatedDtMillis float64
|
||||
RollbackEstimatedDtNanos int64
|
||||
LastRenderFrameIdTriggeredAt int64
|
||||
|
||||
StageName string
|
||||
StageDiscreteW int32
|
||||
@@ -183,6 +188,7 @@ type Room struct {
|
||||
StageTileH int32
|
||||
RawBattleStrToVec2DListMap StrToVec2DListMap
|
||||
RawBattleStrToPolygon2DListMap StrToPolygon2DListMap
|
||||
BackendDynamicsEnabled bool
|
||||
}
|
||||
|
||||
const (
|
||||
@@ -257,10 +263,12 @@ func (pR *Room) ChooseStage() error {
|
||||
* -- YFLu, 2019-09-04
|
||||
*/
|
||||
pwd, err := os.Getwd()
|
||||
ErrFatal(err)
|
||||
if nil != err {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
rand.Seed(time.Now().Unix())
|
||||
stageNameList := []string{ /*"pacman" ,*/ "richsoil"}
|
||||
stageNameList := []string{ /*"simple" ,*/ "richsoil"}
|
||||
chosenStageIndex := rand.Int() % len(stageNameList) // Hardcoded temporarily. -- YFLu
|
||||
|
||||
pR.StageName = stageNameList[chosenStageIndex]
|
||||
@@ -320,7 +328,8 @@ func (pR *Room) ChooseStage() error {
|
||||
barrierPolygon2DList := *(toRetStrToPolygon2DListMap["Barrier"])
|
||||
|
||||
var barrierLocalIdInBattle int32 = 0
|
||||
for _, polygon2D := range barrierPolygon2DList {
|
||||
for _, polygon2DUnaligned := range barrierPolygon2DList {
|
||||
polygon2D := AlignPolygon2DToBoundingBox(polygon2DUnaligned)
|
||||
/*
|
||||
// For debug-printing only.
|
||||
Logger.Info("ChooseStage printing polygon2D for barrierPolygon2DList", zap.Any("barrierLocalIdInBattle", barrierLocalIdInBattle), zap.Any("polygon2D.Anchor", polygon2D.Anchor), zap.Any("polygon2D.Points", polygon2D.Points))
|
||||
@@ -422,16 +431,22 @@ func (pR *Room) StartBattle() {
|
||||
pR.onBattleStoppedForSettlement()
|
||||
}()
|
||||
|
||||
battleMainLoopStartedNanos := utils.UnixtimeNano()
|
||||
totalElapsedNanos := int64(0)
|
||||
pR.LastRenderFrameIdTriggeredAt = utils.UnixtimeNano()
|
||||
|
||||
Logger.Info("The `battleMainLoop` is started for:", zap.Any("roomId", pR.Id))
|
||||
for {
|
||||
stCalculation := utils.UnixtimeNano()
|
||||
|
||||
if totalElapsedNanos > pR.BattleDurationNanos {
|
||||
Logger.Info(fmt.Sprintf("The `battleMainLoop` for roomId=%v is stopped:\n%v", pR.Id, pR.InputsBufferString(true)))
|
||||
elapsedNanosSinceLastFrameIdTriggered := stCalculation - pR.LastRenderFrameIdTriggeredAt
|
||||
if elapsedNanosSinceLastFrameIdTriggered < pR.RollbackEstimatedDtNanos {
|
||||
Logger.Debug(fmt.Sprintf("Avoiding too fast frame@roomId=%v, renderFrameId=%v: elapsedNanosSinceLastFrameIdTriggered=%v", pR.Id, pR.RenderFrameId, elapsedNanosSinceLastFrameIdTriggered))
|
||||
continue
|
||||
}
|
||||
|
||||
if pR.RenderFrameId > pR.BattleDurationFrames {
|
||||
Logger.Info(fmt.Sprintf("The `battleMainLoop` for roomId=%v is stopped@renderFrameId=%v, with battleDurationFrames=%v:\n%v", pR.Id, pR.RenderFrameId, pR.BattleDurationFrames, pR.InputsBufferString(true)))
|
||||
pR.StopBattleForSettlement()
|
||||
return
|
||||
}
|
||||
|
||||
if swapped := atomic.CompareAndSwapInt32(&pR.State, RoomBattleStateIns.IN_BATTLE, RoomBattleStateIns.IN_BATTLE); !swapped {
|
||||
@@ -444,17 +459,12 @@ func (pR *Room) StartBattle() {
|
||||
pR.prefabInputFrameDownsync(noDelayInputFrameId)
|
||||
}
|
||||
|
||||
// Force setting all-confirmed of buffered inputFrames periodically
|
||||
unconfirmedMask := pR.forceConfirmationIfApplicable()
|
||||
|
||||
dynamicsDuration := int64(0)
|
||||
if 0 <= pR.LastAllConfirmedInputFrameId {
|
||||
dynamicsStartedAt := utils.UnixtimeNano()
|
||||
// Apply "all-confirmed inputFrames" to move forward "pR.CurDynamicsRenderFrameId"
|
||||
nextDynamicsRenderFrameId := pR.ConvertToLastUsedRenderFrameId(pR.LastAllConfirmedInputFrameId, pR.InputDelayFrames)
|
||||
Logger.Debug(fmt.Sprintf("roomId=%v, room.RenderFrameId=%v, LastAllConfirmedInputFrameId=%v, InputDelayFrames=%v, nextDynamicsRenderFrameId=%v", pR.Id, pR.RenderFrameId, pR.LastAllConfirmedInputFrameId, pR.InputDelayFrames, nextDynamicsRenderFrameId))
|
||||
pR.applyInputFrameDownsyncDynamics(pR.CurDynamicsRenderFrameId, nextDynamicsRenderFrameId)
|
||||
dynamicsDuration = utils.UnixtimeNano() - dynamicsStartedAt
|
||||
unconfirmedMask := uint64(0)
|
||||
if pR.BackendDynamicsEnabled {
|
||||
// Force setting all-confirmed of buffered inputFrames periodically
|
||||
unconfirmedMask = pR.forceConfirmationIfApplicable()
|
||||
} else {
|
||||
pR.markConfirmationIfApplicable()
|
||||
}
|
||||
|
||||
upperToSendInputFrameId := atomic.LoadInt32(&(pR.LastAllConfirmedInputFrameId))
|
||||
@@ -464,15 +474,28 @@ func (pR *Room) StartBattle() {
|
||||
|
||||
If "NstDelayFrames" becomes larger, "pR.RenderFrameId - refRenderFrameId" possibly becomes larger because the force confirmation is delayed more.
|
||||
|
||||
Hence even upon resync, it's still possible that "refRenderFrameId < frontend.chaserRenderFrameId".
|
||||
Upon resync, it's still possible that "refRenderFrameId < frontend.chaserRenderFrameId" -- and this is allowed.
|
||||
*/
|
||||
refRenderFrameId := pR.ConvertToGeneratingRenderFrameId(upperToSendInputFrameId) + (1 << pR.InputScaleFrames) - 1
|
||||
// [WARNING] The following inequalities are seldom true, but just to avoid that in good network condition the frontend resyncs itself to a "too advanced frontend.renderFrameId", and then starts upsyncing "too advanced inputFrameId".
|
||||
if refRenderFrameId > pR.RenderFrameId {
|
||||
refRenderFrameId = pR.RenderFrameId
|
||||
}
|
||||
if refRenderFrameId > pR.CurDynamicsRenderFrameId {
|
||||
refRenderFrameId = pR.CurDynamicsRenderFrameId
|
||||
|
||||
dynamicsDuration := int64(0)
|
||||
if pR.BackendDynamicsEnabled {
|
||||
if 0 <= pR.LastAllConfirmedInputFrameId {
|
||||
dynamicsStartedAt := utils.UnixtimeNano()
|
||||
// Apply "all-confirmed inputFrames" to move forward "pR.CurDynamicsRenderFrameId"
|
||||
nextDynamicsRenderFrameId := pR.ConvertToLastUsedRenderFrameId(pR.LastAllConfirmedInputFrameId, pR.InputDelayFrames)
|
||||
Logger.Debug(fmt.Sprintf("roomId=%v, room.RenderFrameId=%v, LastAllConfirmedInputFrameId=%v, InputDelayFrames=%v, nextDynamicsRenderFrameId=%v", pR.Id, pR.RenderFrameId, pR.LastAllConfirmedInputFrameId, pR.InputDelayFrames, nextDynamicsRenderFrameId))
|
||||
pR.applyInputFrameDownsyncDynamics(pR.CurDynamicsRenderFrameId, nextDynamicsRenderFrameId)
|
||||
dynamicsDuration = utils.UnixtimeNano() - dynamicsStartedAt
|
||||
}
|
||||
|
||||
// [WARNING] The following inequality are seldom true, but just to avoid that in good network condition the frontend resyncs itself to a "too advanced frontend.renderFrameId", and then starts upsyncing "too advanced inputFrameId".
|
||||
if refRenderFrameId > pR.CurDynamicsRenderFrameId {
|
||||
refRenderFrameId = pR.CurDynamicsRenderFrameId
|
||||
}
|
||||
}
|
||||
for playerId, player := range pR.Players {
|
||||
if swapped := atomic.CompareAndSwapInt32(&player.BattleState, PlayerBattleStateIns.ACTIVE, PlayerBattleStateIns.ACTIVE); !swapped {
|
||||
@@ -516,14 +539,14 @@ func (pR *Room) StartBattle() {
|
||||
// [WARNING] When sending DOWNSYNC_MSG_ACT_FORCED_RESYNC, there MUST BE accompanying "toSendInputFrames" for calculating "refRenderFrameId"!
|
||||
|
||||
if MAGIC_LAST_SENT_INPUT_FRAME_ID_READDED == player.LastSentInputFrameId {
|
||||
Logger.Warn(fmt.Sprintf("Not sending due to empty toSendInputFrames: roomId=%v, playerId=%v, refRenderFrameId=%v, candidateToSendInputFrameId=%v, upperToSendInputFrameId=%v, lastSentInputFrameId=%v, playerAckingInputFrameId=%v", pR.Id, playerId, refRenderFrameId, candidateToSendInputFrameId, upperToSendInputFrameId, player.LastSentInputFrameId, player.AckingInputFrameId))
|
||||
Logger.Warn(fmt.Sprintf("Not sending due to empty toSendInputFrames: roomId=%v, playerId=%v, refRenderFrameId=%v, upperToSendInputFrameId=%v, lastSentInputFrameId=%v, playerAckingInputFrameId=%v", pR.Id, playerId, refRenderFrameId, upperToSendInputFrameId, player.LastSentInputFrameId, player.AckingInputFrameId))
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
indiceInJoinIndexBooleanArr := uint32(player.JoinIndex - 1)
|
||||
var joinMask uint64 = (1 << indiceInJoinIndexBooleanArr)
|
||||
if MAGIC_LAST_SENT_INPUT_FRAME_ID_READDED == player.LastSentInputFrameId || 0 < (unconfirmedMask&joinMask) {
|
||||
if pR.BackendDynamicsEnabled && (MAGIC_LAST_SENT_INPUT_FRAME_ID_READDED == player.LastSentInputFrameId || 0 < (unconfirmedMask&joinMask)) {
|
||||
// [WARNING] Even upon "MAGIC_LAST_SENT_INPUT_FRAME_ID_READDED", it could be true that "0 == (unconfirmedMask & joinMask)"!
|
||||
tmp := pR.RenderFrameBuffer.GetByFrameId(refRenderFrameId)
|
||||
if nil == tmp {
|
||||
@@ -544,6 +567,17 @@ func (pR *Room) StartBattle() {
|
||||
}
|
||||
|
||||
toApplyInputFrameId := pR.ConvertToInputFrameId(refRenderFrameId, pR.InputDelayFrames)
|
||||
if false == pR.BackendDynamicsEnabled {
|
||||
// When "false == pR.BackendDynamicsEnabled", the variable "refRenderFrameId" is not well defined
|
||||
minLastSentInputFrameId := int32(math.MaxInt32)
|
||||
for _, player := range pR.Players {
|
||||
if player.LastSentInputFrameId >= minLastSentInputFrameId {
|
||||
continue
|
||||
}
|
||||
minLastSentInputFrameId = player.LastSentInputFrameId
|
||||
}
|
||||
toApplyInputFrameId = minLastSentInputFrameId
|
||||
}
|
||||
for pR.InputsBuffer.N < pR.InputsBuffer.Cnt || (0 < pR.InputsBuffer.Cnt && pR.InputsBuffer.StFrameId < toApplyInputFrameId) {
|
||||
f := pR.InputsBuffer.Pop().(*pb.InputFrameDownsync)
|
||||
if pR.inputFrameIdDebuggable(f.InputFrameId) {
|
||||
@@ -554,7 +588,6 @@ func (pR *Room) StartBattle() {
|
||||
|
||||
pR.RenderFrameId++
|
||||
elapsedInCalculation := (utils.UnixtimeNano() - stCalculation)
|
||||
totalElapsedNanos = (utils.UnixtimeNano() - battleMainLoopStartedNanos)
|
||||
if elapsedInCalculation > nanosPerFrame {
|
||||
Logger.Warn(fmt.Sprintf("SLOW FRAME! Elapsed time statistics: roomId=%v, room.RenderFrameId=%v, elapsedInCalculation=%v, dynamicsDuration=%v, nanosPerFrame=%v", pR.Id, pR.RenderFrameId, elapsedInCalculation, dynamicsDuration, nanosPerFrame))
|
||||
}
|
||||
@@ -614,9 +647,9 @@ func (pR *Room) onInputFrameDownsyncAllConfirmed(inputFrameDownsync *pb.InputFra
|
||||
inputFrameId := inputFrameDownsync.InputFrameId
|
||||
if -1 == pR.LastAllConfirmedInputFrameIdWithChange || false == pR.equalInputLists(inputFrameDownsync.InputList, pR.LastAllConfirmedInputList) {
|
||||
if -1 == playerId {
|
||||
Logger.Info(fmt.Sprintf("Key inputFrame change: roomId=%v, newInputFrameId=%v, lastInputFrameId=%v, newInputList=%v, lastInputList=%v, InputsBuffer=%v", pR.Id, inputFrameId, pR.LastAllConfirmedInputFrameId, inputFrameDownsync.InputList, pR.LastAllConfirmedInputList, pR.InputsBufferString(false)))
|
||||
Logger.Debug(fmt.Sprintf("Key inputFrame change: roomId=%v, newInputFrameId=%v, lastInputFrameId=%v, newInputList=%v, lastInputList=%v, InputsBuffer=%v", pR.Id, inputFrameId, pR.LastAllConfirmedInputFrameId, inputFrameDownsync.InputList, pR.LastAllConfirmedInputList, pR.InputsBufferString(false)))
|
||||
} else {
|
||||
Logger.Info(fmt.Sprintf("Key inputFrame change: roomId=%v, playerId=%v, newInputFrameId=%v, lastInputFrameId=%v, newInputList=%v, lastInputList=%v, InputsBuffer=%v", pR.Id, playerId, inputFrameId, pR.LastAllConfirmedInputFrameId, inputFrameDownsync.InputList, pR.LastAllConfirmedInputList, pR.InputsBufferString(false)))
|
||||
Logger.Debug(fmt.Sprintf("Key inputFrame change: roomId=%v, playerId=%v, newInputFrameId=%v, lastInputFrameId=%v, newInputList=%v, lastInputList=%v, InputsBuffer=%v", pR.Id, playerId, inputFrameId, pR.LastAllConfirmedInputFrameId, inputFrameDownsync.InputList, pR.LastAllConfirmedInputList, pR.InputsBufferString(false)))
|
||||
}
|
||||
atomic.StoreInt32(&(pR.LastAllConfirmedInputFrameIdWithChange), inputFrameId)
|
||||
}
|
||||
@@ -628,7 +661,7 @@ func (pR *Room) onInputFrameDownsyncAllConfirmed(inputFrameDownsync *pb.InputFra
|
||||
if -1 == playerId {
|
||||
Logger.Debug(fmt.Sprintf("inputFrame lifecycle#2[forced-allconfirmed]: roomId=%v, InputsBuffer=%v", pR.Id, pR.InputsBufferString(false)))
|
||||
} else {
|
||||
Logger.Info(fmt.Sprintf("inputFrame lifecycle#2[allconfirmed]: roomId=%v, playerId=%v, InputsBuffer=%v", pR.Id, playerId, pR.InputsBufferString(false)))
|
||||
Logger.Debug(fmt.Sprintf("inputFrame lifecycle#2[allconfirmed]: roomId=%v, playerId=%v, InputsBuffer=%v", pR.Id, playerId, pR.InputsBufferString(false)))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -780,11 +813,16 @@ func (pR *Room) OnDismissed() {
|
||||
pR.NstDelayFrames = 8
|
||||
pR.InputScaleFrames = uint32(2)
|
||||
pR.ServerFps = 60
|
||||
pR.RollbackEstimatedDt = float64(1.0) / float64(pR.ServerFps)
|
||||
pR.BattleDurationNanos = int64(30 * 1000 * 1000 * 1000)
|
||||
pR.RollbackEstimatedDt = 0.016667 // Use fixed-and-low-precision to mitigate the inconsistent floating-point-number issue between Golang and JavaScript
|
||||
pR.RollbackEstimatedDtMillis = 16.667 // Use fixed-and-low-precision to mitigate the inconsistent floating-point-number issue between Golang and JavaScript
|
||||
pR.RollbackEstimatedDtNanos = 16666666 // A little smaller than the actual per frame time, just for preventing FAST FRAME
|
||||
pR.BattleDurationFrames = 30 * pR.ServerFps
|
||||
pR.BattleDurationNanos = int64(pR.BattleDurationFrames) * (pR.RollbackEstimatedDtNanos + 1)
|
||||
pR.InputFrameUpsyncDelayTolerance = 2
|
||||
pR.MaxChasingRenderFramesPerUpdate = 10
|
||||
|
||||
pR.BackendDynamicsEnabled = true // [WARNING] When "false", recovery upon reconnection wouldn't work!
|
||||
|
||||
pR.ChooseStage()
|
||||
pR.EffectivePlayerCount = 0
|
||||
|
||||
@@ -945,12 +983,12 @@ func (pR *Room) OnPlayerBattleColliderAcked(playerId int32) bool {
|
||||
// Broadcast added or readded player info to all players in the same room
|
||||
for _, eachPlayer := range pR.Players {
|
||||
/*
|
||||
[WARNING]
|
||||
This `playerAckedFrame` is the first ever "RoomDownsyncFrame" for every "PersistentSessionClient on the frontend", and it goes right after each "BattleColliderInfo".
|
||||
[WARNING]
|
||||
This `playerAckedFrame` is the first ever "RoomDownsyncFrame" for every "PersistentSessionClient on the frontend", and it goes right after each "BattleColliderInfo".
|
||||
|
||||
By making use of the sequential nature of each ws session, all later "RoomDownsyncFrame"s generated after `pRoom.StartBattle()` will be put behind this `playerAckedFrame`.
|
||||
By making use of the sequential nature of each ws session, all later "RoomDownsyncFrame"s generated after `pRoom.StartBattle()` will be put behind this `playerAckedFrame`.
|
||||
|
||||
This function is triggered by an upsync message via WebSocket, thus downsync sending is also available by now.
|
||||
This function is triggered by an upsync message via WebSocket, thus downsync sending is also available by now.
|
||||
*/
|
||||
switch targetPlayer.BattleState {
|
||||
case PlayerBattleStateIns.ADDED_PENDING_BATTLE_COLLIDER_ACK:
|
||||
@@ -1052,6 +1090,43 @@ func (pR *Room) prefabInputFrameDownsync(inputFrameId int32) *pb.InputFrameDowns
|
||||
return currInputFrameDownsync
|
||||
}
|
||||
|
||||
func (pR *Room) markConfirmationIfApplicable() {
|
||||
inputFrameId1 := pR.LastAllConfirmedInputFrameId + 1
|
||||
gap := int32(4) // This value is hardcoded and doesn't need be much bigger, because the backend side is supposed to never lag when "false == BackendDynamicsEnabled".
|
||||
inputFrameId2 := inputFrameId1 + gap
|
||||
if inputFrameId2 > pR.InputsBuffer.EdFrameId {
|
||||
inputFrameId2 = pR.InputsBuffer.EdFrameId
|
||||
}
|
||||
|
||||
totPlayerCnt := uint32(pR.Capacity)
|
||||
allConfirmedMask := uint64((1 << totPlayerCnt) - 1)
|
||||
for inputFrameId := inputFrameId1; inputFrameId < inputFrameId2; inputFrameId++ {
|
||||
tmp := pR.InputsBuffer.GetByFrameId(inputFrameId)
|
||||
if nil == tmp {
|
||||
panic(fmt.Sprintf("inputFrameId=%v doesn't exist for roomId=%v, this is abnormal because the server should prefab inputFrameDownsync in a most advanced pace, check the prefab logic! InputsBuffer=%v", inputFrameId, pR.Id, pR.InputsBufferString(false)))
|
||||
}
|
||||
inputFrameDownsync := tmp.(*pb.InputFrameDownsync)
|
||||
for _, player := range pR.Players {
|
||||
bufIndex := pR.toDiscreteInputsBufferIndex(inputFrameId, player.JoinIndex)
|
||||
tmp, loaded := pR.DiscreteInputsBuffer.LoadAndDelete(bufIndex) // It's safe to "LoadAndDelete" here because the "inputFrameUpsync" of this player is already remembered by the corresponding "inputFrameDown".
|
||||
if !loaded {
|
||||
continue
|
||||
}
|
||||
inputFrameUpsync := tmp.(*pb.InputFrameUpsync)
|
||||
indiceInJoinIndexBooleanArr := uint32(player.JoinIndex - 1)
|
||||
inputFrameDownsync.InputList[indiceInJoinIndexBooleanArr] = pR.EncodeUpsyncCmd(inputFrameUpsync)
|
||||
inputFrameDownsync.ConfirmedList |= (1 << indiceInJoinIndexBooleanArr)
|
||||
}
|
||||
|
||||
// Force confirmation of "inputFrame2"
|
||||
if allConfirmedMask == inputFrameDownsync.ConfirmedList {
|
||||
pR.onInputFrameDownsyncAllConfirmed(inputFrameDownsync, -1)
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (pR *Room) forceConfirmationIfApplicable() uint64 {
|
||||
// Force confirmation of non-all-confirmed inputFrame EXACTLY ONE AT A TIME, returns the non-confirmed mask of players, e.g. in a 4-player-battle returning 1001 means that players with JoinIndex=1 and JoinIndex=4 are non-confirmed for inputFrameId2
|
||||
renderFrameId1 := (pR.RenderFrameId - pR.NstDelayFrames) // the renderFrameId which should've been rendered on frontend
|
||||
@@ -1130,24 +1205,30 @@ func (pR *Room) applyInputFrameDownsyncDynamics(fromRenderFrameId int32, toRende
|
||||
encodedInput := inputList[joinIndex-1]
|
||||
decodedInput := DIRECTION_DECODER[encodedInput]
|
||||
decodedInputSpeedFactor := DIRECTION_DECODER_INVERSE_LENGTH[encodedInput]
|
||||
if 0.0 == decodedInputSpeedFactor {
|
||||
continue
|
||||
}
|
||||
baseChange := player.Speed * pR.RollbackEstimatedDt * decodedInputSpeedFactor
|
||||
dx := baseChange * float64(decodedInput[0])
|
||||
dy := baseChange * float64(decodedInput[1])
|
||||
oldDx, oldDy := baseChange*float64(decodedInput[0]), baseChange*float64(decodedInput[1])
|
||||
dx, dy := oldDx, oldDy
|
||||
|
||||
/*
|
||||
// The collision lib seems very slow at worst cases, omitting for now
|
||||
collisionPlayerIndex := COLLISION_PLAYER_INDEX_PREFIX + joinIndex
|
||||
playerCollider := pR.CollisionSysMap[collisionPlayerIndex]
|
||||
if collision := playerCollider.Check(dx, dy, "Barrier"); collision != nil {
|
||||
changeWithCollision := collision.ContactWithObject(collision.Objects[0])
|
||||
dx = changeWithCollision.X()
|
||||
dy = changeWithCollision.Y()
|
||||
collisionPlayerIndex := COLLISION_PLAYER_INDEX_PREFIX + joinIndex
|
||||
playerCollider := pR.CollisionSysMap[collisionPlayerIndex]
|
||||
if collision := playerCollider.Check(oldDx, oldDy, "Barrier"); collision != nil {
|
||||
playerShape := playerCollider.Shape.(*resolv.ConvexPolygon)
|
||||
barrierShape := collision.Objects[0].Shape.(*resolv.ConvexPolygon)
|
||||
if overlapped, pushbackX, pushbackY := CalcPushbacks(oldDx, oldDy, playerShape, barrierShape); overlapped {
|
||||
Logger.Debug(fmt.Sprintf("Collided & overlapped: player.X=%v, player.Y=%v, oldDx=%v, oldDy=%v, playerShape=%v, toCheckBarrier=%v, pushbackX=%v, pushbackY=%v", playerCollider.X, playerCollider.Y, oldDx, oldDy, ConvexPolygonStr(playerShape), ConvexPolygonStr(barrierShape), pushbackX, pushbackY))
|
||||
dx -= pushbackX
|
||||
dy -= pushbackY
|
||||
} else {
|
||||
Logger.Debug(fmt.Sprintf("Collider BUT not overlapped: player.X=%v, player.Y=%v, oldDx=%v, oldDy=%v, playerShape=%v, toCheckBarrier=%v", playerCollider.X, playerCollider.Y, oldDx, oldDy, ConvexPolygonStr(playerShape), ConvexPolygonStr(barrierShape)))
|
||||
}
|
||||
playerCollider.X += dx
|
||||
playerCollider.Y += dy
|
||||
// Update in "collision space"
|
||||
playerCollider.Update()
|
||||
*/
|
||||
}
|
||||
playerCollider.X += dx
|
||||
playerCollider.Y += dy
|
||||
// Update in "collision space"
|
||||
playerCollider.Update()
|
||||
|
||||
player.Dir.Dx = decodedInput[0]
|
||||
player.Dir.Dy = decodedInput[1]
|
||||
@@ -1159,7 +1240,7 @@ func (pR *Room) applyInputFrameDownsyncDynamics(fromRenderFrameId int32, toRende
|
||||
newRenderFrame := pb.RoomDownsyncFrame{
|
||||
Id: collisionSysRenderFrameId + 1,
|
||||
Players: toPbPlayers(pR.Players),
|
||||
CountdownNanos: (pR.BattleDurationNanos - int64(collisionSysRenderFrameId)*int64(pR.RollbackEstimatedDt*1000000000)), // TODO: Make this number more synced with frontend!
|
||||
CountdownNanos: (pR.BattleDurationNanos - int64(collisionSysRenderFrameId)*pR.RollbackEstimatedDtNanos),
|
||||
}
|
||||
pR.RenderFrameBuffer.Put(&newRenderFrame)
|
||||
pR.CurDynamicsRenderFrameId++
|
||||
@@ -1171,12 +1252,18 @@ func (pR *Room) inputFrameIdDebuggable(inputFrameId int32) bool {
|
||||
}
|
||||
|
||||
func (pR *Room) refreshColliders() {
|
||||
playerColliderRadius := float64(12) // hardcoded
|
||||
// Kindly note that by now, we've already got all the shapes in the tmx file into "pR.(Players | Barriers)" from "ParseTmxLayersAndGroups"
|
||||
space := resolv.NewSpace(int(pR.StageDiscreteW), int(pR.StageDiscreteH), int(pR.StageTileW), int(pR.StageTileH)) // allocate a new collision space everytime after a battle is settled
|
||||
spaceW := pR.StageDiscreteW * pR.StageTileW
|
||||
spaceH := pR.StageDiscreteH * pR.StageTileH
|
||||
|
||||
spaceOffsetX := float64(spaceW) * 0.5
|
||||
spaceOffsetY := float64(spaceH) * 0.5
|
||||
|
||||
minStep := int(3) // the approx minimum distance a player can move per frame
|
||||
space := resolv.NewSpace(int(spaceW), int(spaceH), minStep, minStep) // allocate a new collision space everytime after a battle is settled
|
||||
for _, player := range pR.Players {
|
||||
playerCollider := resolv.NewObject(player.X, player.Y, 12, 12) // Radius=12 is hardcoded
|
||||
playerColliderShape := resolv.NewCircle(player.X, player.Y, 12)
|
||||
playerCollider.SetShape(playerColliderShape)
|
||||
playerCollider := GenerateRectCollider(player.X, player.Y, playerColliderRadius*2, playerColliderRadius*2, spaceOffsetX, spaceOffsetY, "Player")
|
||||
space.Add(playerCollider)
|
||||
// Keep track of the collider in "pR.CollisionSysMap"
|
||||
joinIndex := player.JoinIndex
|
||||
@@ -1186,29 +1273,12 @@ func (pR *Room) refreshColliders() {
|
||||
}
|
||||
|
||||
for _, barrier := range pR.Barriers {
|
||||
var w float64 = 0
|
||||
var h float64 = 0
|
||||
for i, pi := range barrier.Boundary.Points {
|
||||
for j, pj := range barrier.Boundary.Points {
|
||||
if i == j {
|
||||
continue
|
||||
}
|
||||
if math.Abs(pj.X-pi.X) > w {
|
||||
w = math.Abs(pj.X - pi.X)
|
||||
}
|
||||
if math.Abs(pj.Y-pi.Y) > h {
|
||||
h = math.Abs(pj.Y - pi.Y)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
barrierColliderShape := resolv.NewConvexPolygon()
|
||||
for _, p := range barrier.Boundary.Points {
|
||||
barrierColliderShape.AddPoints(p.X+barrier.Boundary.Anchor.X, p.Y+barrier.Boundary.Anchor.Y)
|
||||
}
|
||||
|
||||
barrierCollider := resolv.NewObject(barrier.Boundary.Anchor.X, barrier.Boundary.Anchor.Y, w, h, "Barrier")
|
||||
barrierCollider.SetShape(barrierColliderShape)
|
||||
boundaryUnaligned := barrier.Boundary
|
||||
barrierCollider := GenerateConvexPolygonCollider(boundaryUnaligned, spaceOffsetX, spaceOffsetY, "Barrier")
|
||||
space.Add(barrierCollider)
|
||||
}
|
||||
}
|
||||
|
||||
func (pR *Room) printBarrier(barrierCollider *resolv.Object) {
|
||||
Logger.Info(fmt.Sprintf("Barrier in roomId=%v: w=%v, h=%v, shape=%v", pR.Id, barrierCollider.W, barrierCollider.H, barrierCollider.Shape))
|
||||
}
|
||||
|
@@ -2,9 +2,9 @@ package models
|
||||
|
||||
import (
|
||||
"container/heap"
|
||||
. "dnmshared"
|
||||
"fmt"
|
||||
"go.uber.org/zap"
|
||||
. "server/common"
|
||||
"sync"
|
||||
)
|
||||
|
||||
|
@@ -302,6 +302,9 @@ type BattleColliderInfo struct {
|
||||
InputFrameUpsyncDelayTolerance int32 `protobuf:"varint,16,opt,name=inputFrameUpsyncDelayTolerance,proto3" json:"inputFrameUpsyncDelayTolerance,omitempty"`
|
||||
MaxChasingRenderFramesPerUpdate int32 `protobuf:"varint,17,opt,name=maxChasingRenderFramesPerUpdate,proto3" json:"maxChasingRenderFramesPerUpdate,omitempty"`
|
||||
PlayerBattleState int32 `protobuf:"varint,18,opt,name=playerBattleState,proto3" json:"playerBattleState,omitempty"`
|
||||
RollbackEstimatedDt float64 `protobuf:"fixed64,19,opt,name=rollbackEstimatedDt,proto3" json:"rollbackEstimatedDt,omitempty"`
|
||||
RollbackEstimatedDtMillis float64 `protobuf:"fixed64,20,opt,name=rollbackEstimatedDtMillis,proto3" json:"rollbackEstimatedDtMillis,omitempty"`
|
||||
RollbackEstimatedDtNanos int64 `protobuf:"varint,21,opt,name=rollbackEstimatedDtNanos,proto3" json:"rollbackEstimatedDtNanos,omitempty"`
|
||||
}
|
||||
|
||||
func (x *BattleColliderInfo) Reset() {
|
||||
@@ -462,6 +465,27 @@ func (x *BattleColliderInfo) GetPlayerBattleState() int32 {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *BattleColliderInfo) GetRollbackEstimatedDt() float64 {
|
||||
if x != nil {
|
||||
return x.RollbackEstimatedDt
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *BattleColliderInfo) GetRollbackEstimatedDtMillis() float64 {
|
||||
if x != nil {
|
||||
return x.RollbackEstimatedDtMillis
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *BattleColliderInfo) GetRollbackEstimatedDtNanos() int64 {
|
||||
if x != nil {
|
||||
return x.RollbackEstimatedDtNanos
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
type Player struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
@@ -1113,7 +1137,7 @@ var file_room_downsync_frame_proto_rawDesc = []byte{
|
||||
0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x74, 0x72, 0x65, 0x61, 0x73, 0x75, 0x72,
|
||||
0x65, 0x68, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x78, 0x2e, 0x50, 0x6f, 0x6c, 0x79, 0x67, 0x6f, 0x6e,
|
||||
0x32, 0x44, 0x52, 0x0d, 0x70, 0x6f, 0x6c, 0x79, 0x67, 0x6f, 0x6e, 0x32, 0x44, 0x4c, 0x69, 0x73,
|
||||
0x74, 0x22, 0xfe, 0x08, 0x0a, 0x12, 0x42, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x43, 0x6f, 0x6c, 0x6c,
|
||||
0x74, 0x22, 0xaa, 0x0a, 0x0a, 0x12, 0x42, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x43, 0x6f, 0x6c, 0x6c,
|
||||
0x69, 0x64, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x1c, 0x0a, 0x09, 0x73, 0x74, 0x61, 0x67,
|
||||
0x65, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x74, 0x61,
|
||||
0x67, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x68, 0x0a, 0x11, 0x73, 0x74, 0x72, 0x54, 0x6f, 0x56,
|
||||
@@ -1172,129 +1196,140 @@ var file_room_downsync_frame_proto_rawDesc = []byte{
|
||||
0x65, 0x72, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x12, 0x2c, 0x0a, 0x11, 0x70, 0x6c, 0x61, 0x79,
|
||||
0x65, 0x72, 0x42, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x18, 0x12, 0x20,
|
||||
0x01, 0x28, 0x05, 0x52, 0x11, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x42, 0x61, 0x74, 0x74, 0x6c,
|
||||
0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x1a, 0x60, 0x0a, 0x16, 0x53, 0x74, 0x72, 0x54, 0x6f, 0x56,
|
||||
0x65, 0x63, 0x32, 0x44, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x61, 0x70, 0x45, 0x6e, 0x74, 0x72, 0x79,
|
||||
0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b,
|
||||
0x65, 0x79, 0x12, 0x30, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28,
|
||||
0x0b, 0x32, 0x1a, 0x2e, 0x74, 0x72, 0x65, 0x61, 0x73, 0x75, 0x72, 0x65, 0x68, 0x75, 0x6e, 0x74,
|
||||
0x65, 0x72, 0x78, 0x2e, 0x56, 0x65, 0x63, 0x32, 0x44, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x05, 0x76,
|
||||
0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x68, 0x0a, 0x1a, 0x53, 0x74, 0x72, 0x54,
|
||||
0x6f, 0x50, 0x6f, 0x6c, 0x79, 0x67, 0x6f, 0x6e, 0x32, 0x44, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x61,
|
||||
0x70, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20,
|
||||
0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x34, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75,
|
||||
0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x74, 0x72, 0x65, 0x61, 0x73, 0x75,
|
||||
0x72, 0x65, 0x68, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x78, 0x2e, 0x50, 0x6f, 0x6c, 0x79, 0x67, 0x6f,
|
||||
0x6e, 0x32, 0x44, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02,
|
||||
0x38, 0x01, 0x22, 0x96, 0x02, 0x0a, 0x06, 0x50, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x12, 0x0e, 0x0a,
|
||||
0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x02, 0x69, 0x64, 0x12, 0x0c, 0x0a,
|
||||
0x01, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x01, 0x52, 0x01, 0x78, 0x12, 0x0c, 0x0a, 0x01, 0x79,
|
||||
0x18, 0x03, 0x20, 0x01, 0x28, 0x01, 0x52, 0x01, 0x79, 0x12, 0x2c, 0x0a, 0x03, 0x64, 0x69, 0x72,
|
||||
0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x74, 0x72, 0x65, 0x61, 0x73, 0x75, 0x72,
|
||||
0x65, 0x68, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x78, 0x2e, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69,
|
||||
0x6f, 0x6e, 0x52, 0x03, 0x64, 0x69, 0x72, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x70, 0x65, 0x65, 0x64,
|
||||
0x18, 0x05, 0x20, 0x01, 0x28, 0x01, 0x52, 0x05, 0x73, 0x70, 0x65, 0x65, 0x64, 0x12, 0x20, 0x0a,
|
||||
0x0b, 0x62, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x18, 0x06, 0x20, 0x01,
|
||||
0x28, 0x05, 0x52, 0x0b, 0x62, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12,
|
||||
0x2c, 0x0a, 0x11, 0x6c, 0x61, 0x73, 0x74, 0x4d, 0x6f, 0x76, 0x65, 0x47, 0x6d, 0x74, 0x4d, 0x69,
|
||||
0x6c, 0x6c, 0x69, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x05, 0x52, 0x11, 0x6c, 0x61, 0x73, 0x74,
|
||||
0x4d, 0x6f, 0x76, 0x65, 0x47, 0x6d, 0x74, 0x4d, 0x69, 0x6c, 0x6c, 0x69, 0x73, 0x12, 0x14, 0x0a,
|
||||
0x05, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x73, 0x63,
|
||||
0x6f, 0x72, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x18, 0x0b,
|
||||
0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x12, 0x1c, 0x0a,
|
||||
0x09, 0x6a, 0x6f, 0x69, 0x6e, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x05,
|
||||
0x52, 0x09, 0x6a, 0x6f, 0x69, 0x6e, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x22, 0x88, 0x01, 0x0a, 0x0a,
|
||||
0x50, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64,
|
||||
0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61,
|
||||
0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x20,
|
||||
0x0a, 0x0b, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20,
|
||||
0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x4e, 0x61, 0x6d, 0x65,
|
||||
0x12, 0x16, 0x0a, 0x06, 0x61, 0x76, 0x61, 0x74, 0x61, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09,
|
||||
0x52, 0x06, 0x61, 0x76, 0x61, 0x74, 0x61, 0x72, 0x12, 0x1c, 0x0a, 0x09, 0x6a, 0x6f, 0x69, 0x6e,
|
||||
0x49, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x6a, 0x6f, 0x69,
|
||||
0x6e, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x22, 0x56, 0x0a, 0x10, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x46,
|
||||
0x72, 0x61, 0x6d, 0x65, 0x55, 0x70, 0x73, 0x79, 0x6e, 0x63, 0x12, 0x22, 0x0a, 0x0c, 0x69, 0x6e,
|
||||
0x70, 0x75, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05,
|
||||
0x52, 0x0c, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x49, 0x64, 0x12, 0x1e,
|
||||
0x0a, 0x0a, 0x65, 0x6e, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x44, 0x69, 0x72, 0x18, 0x06, 0x20, 0x01,
|
||||
0x28, 0x05, 0x52, 0x0a, 0x65, 0x6e, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x44, 0x69, 0x72, 0x22, 0x7c,
|
||||
0x0a, 0x12, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x44, 0x6f, 0x77, 0x6e,
|
||||
0x73, 0x79, 0x6e, 0x63, 0x12, 0x22, 0x0a, 0x0c, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x46, 0x72, 0x61,
|
||||
0x6d, 0x65, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0c, 0x69, 0x6e, 0x70, 0x75,
|
||||
0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x49, 0x64, 0x12, 0x1c, 0x0a, 0x09, 0x69, 0x6e, 0x70, 0x75,
|
||||
0x74, 0x4c, 0x69, 0x73, 0x74, 0x18, 0x02, 0x20, 0x03, 0x28, 0x04, 0x52, 0x09, 0x69, 0x6e, 0x70,
|
||||
0x75, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x24, 0x0a, 0x0d, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x72,
|
||||
0x6d, 0x65, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0d, 0x63,
|
||||
0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d, 0x65, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x22, 0x3b, 0x0a, 0x0f,
|
||||
0x48, 0x65, 0x61, 0x72, 0x74, 0x62, 0x65, 0x61, 0x74, 0x55, 0x70, 0x73, 0x79, 0x6e, 0x63, 0x12,
|
||||
0x28, 0x0a, 0x0f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61,
|
||||
0x6d, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74,
|
||||
0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x22, 0x9f, 0x03, 0x0a, 0x11, 0x52, 0x6f,
|
||||
0x6f, 0x6d, 0x44, 0x6f, 0x77, 0x6e, 0x73, 0x79, 0x6e, 0x63, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x12,
|
||||
0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x02, 0x69, 0x64, 0x12,
|
||||
0x49, 0x0a, 0x07, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b,
|
||||
0x32, 0x2f, 0x2e, 0x74, 0x72, 0x65, 0x61, 0x73, 0x75, 0x72, 0x65, 0x68, 0x75, 0x6e, 0x74, 0x65,
|
||||
0x72, 0x78, 0x2e, 0x52, 0x6f, 0x6f, 0x6d, 0x44, 0x6f, 0x77, 0x6e, 0x73, 0x79, 0x6e, 0x63, 0x46,
|
||||
0x72, 0x61, 0x6d, 0x65, 0x2e, 0x50, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x73, 0x45, 0x6e, 0x74, 0x72,
|
||||
0x79, 0x52, 0x07, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x73, 0x12, 0x26, 0x0a, 0x0e, 0x63, 0x6f,
|
||||
0x75, 0x6e, 0x74, 0x64, 0x6f, 0x77, 0x6e, 0x4e, 0x61, 0x6e, 0x6f, 0x73, 0x18, 0x03, 0x20, 0x01,
|
||||
0x28, 0x03, 0x52, 0x0e, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x64, 0x6f, 0x77, 0x6e, 0x4e, 0x61, 0x6e,
|
||||
0x6f, 0x73, 0x12, 0x55, 0x0a, 0x0b, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x4d, 0x65, 0x74, 0x61,
|
||||
0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x33, 0x2e, 0x74, 0x72, 0x65, 0x61, 0x73, 0x75,
|
||||
0x72, 0x65, 0x68, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x78, 0x2e, 0x52, 0x6f, 0x6f, 0x6d, 0x44, 0x6f,
|
||||
0x77, 0x6e, 0x73, 0x79, 0x6e, 0x63, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x2e, 0x50, 0x6c, 0x61, 0x79,
|
||||
0x65, 0x72, 0x4d, 0x65, 0x74, 0x61, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0b, 0x70, 0x6c,
|
||||
0x61, 0x79, 0x65, 0x72, 0x4d, 0x65, 0x74, 0x61, 0x73, 0x1a, 0x53, 0x0a, 0x0c, 0x50, 0x6c, 0x61,
|
||||
0x79, 0x65, 0x72, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79,
|
||||
0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x2d, 0x0a, 0x05, 0x76,
|
||||
0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x74, 0x72, 0x65,
|
||||
0x61, 0x73, 0x75, 0x72, 0x65, 0x68, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x78, 0x2e, 0x50, 0x6c, 0x61,
|
||||
0x79, 0x65, 0x72, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x5b,
|
||||
0x0a, 0x10, 0x50, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x4d, 0x65, 0x74, 0x61, 0x73, 0x45, 0x6e, 0x74,
|
||||
0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52,
|
||||
0x03, 0x6b, 0x65, 0x79, 0x12, 0x31, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20,
|
||||
0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x74, 0x72, 0x65, 0x61, 0x73, 0x75, 0x72, 0x65, 0x68, 0x75,
|
||||
0x6e, 0x74, 0x65, 0x72, 0x78, 0x2e, 0x50, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x4d, 0x65, 0x74, 0x61,
|
||||
0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xca, 0x02, 0x0a, 0x05,
|
||||
0x57, 0x73, 0x52, 0x65, 0x71, 0x12, 0x14, 0x0a, 0x05, 0x6d, 0x73, 0x67, 0x49, 0x64, 0x18, 0x01,
|
||||
0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x6d, 0x73, 0x67, 0x49, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x70,
|
||||
0x6c, 0x61, 0x79, 0x65, 0x72, 0x49, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x70,
|
||||
0x6c, 0x61, 0x79, 0x65, 0x72, 0x49, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x61, 0x63, 0x74, 0x18, 0x03,
|
||||
0x20, 0x01, 0x28, 0x05, 0x52, 0x03, 0x61, 0x63, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x6a, 0x6f, 0x69,
|
||||
0x6e, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x6a, 0x6f,
|
||||
0x69, 0x6e, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x24, 0x0a, 0x0d, 0x61, 0x63, 0x6b, 0x69, 0x6e,
|
||||
0x67, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x49, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0d,
|
||||
0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x49, 0x64, 0x12, 0x2e, 0x0a,
|
||||
0x12, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x46, 0x72, 0x61, 0x6d,
|
||||
0x65, 0x49, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x05, 0x52, 0x12, 0x61, 0x63, 0x6b, 0x69, 0x6e,
|
||||
0x67, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x49, 0x64, 0x12, 0x57, 0x0a,
|
||||
0x15, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x55, 0x70, 0x73, 0x79, 0x6e,
|
||||
0x63, 0x42, 0x61, 0x74, 0x63, 0x68, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x74,
|
||||
0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x30, 0x0a, 0x13, 0x72, 0x6f, 0x6c, 0x6c, 0x62, 0x61,
|
||||
0x63, 0x6b, 0x45, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x64, 0x44, 0x74, 0x18, 0x13, 0x20,
|
||||
0x01, 0x28, 0x01, 0x52, 0x13, 0x72, 0x6f, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x45, 0x73, 0x74,
|
||||
0x69, 0x6d, 0x61, 0x74, 0x65, 0x64, 0x44, 0x74, 0x12, 0x3c, 0x0a, 0x19, 0x72, 0x6f, 0x6c, 0x6c,
|
||||
0x62, 0x61, 0x63, 0x6b, 0x45, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x64, 0x44, 0x74, 0x4d,
|
||||
0x69, 0x6c, 0x6c, 0x69, 0x73, 0x18, 0x14, 0x20, 0x01, 0x28, 0x01, 0x52, 0x19, 0x72, 0x6f, 0x6c,
|
||||
0x6c, 0x62, 0x61, 0x63, 0x6b, 0x45, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x64, 0x44, 0x74,
|
||||
0x4d, 0x69, 0x6c, 0x6c, 0x69, 0x73, 0x12, 0x3a, 0x0a, 0x18, 0x72, 0x6f, 0x6c, 0x6c, 0x62, 0x61,
|
||||
0x63, 0x6b, 0x45, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x64, 0x44, 0x74, 0x4e, 0x61, 0x6e,
|
||||
0x6f, 0x73, 0x18, 0x15, 0x20, 0x01, 0x28, 0x03, 0x52, 0x18, 0x72, 0x6f, 0x6c, 0x6c, 0x62, 0x61,
|
||||
0x63, 0x6b, 0x45, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x64, 0x44, 0x74, 0x4e, 0x61, 0x6e,
|
||||
0x6f, 0x73, 0x1a, 0x60, 0x0a, 0x16, 0x53, 0x74, 0x72, 0x54, 0x6f, 0x56, 0x65, 0x63, 0x32, 0x44,
|
||||
0x4c, 0x69, 0x73, 0x74, 0x4d, 0x61, 0x70, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03,
|
||||
0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x30,
|
||||
0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e,
|
||||
0x74, 0x72, 0x65, 0x61, 0x73, 0x75, 0x72, 0x65, 0x68, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x78, 0x2e,
|
||||
0x56, 0x65, 0x63, 0x32, 0x44, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65,
|
||||
0x3a, 0x02, 0x38, 0x01, 0x1a, 0x68, 0x0a, 0x1a, 0x53, 0x74, 0x72, 0x54, 0x6f, 0x50, 0x6f, 0x6c,
|
||||
0x79, 0x67, 0x6f, 0x6e, 0x32, 0x44, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x61, 0x70, 0x45, 0x6e, 0x74,
|
||||
0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
|
||||
0x03, 0x6b, 0x65, 0x79, 0x12, 0x34, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20,
|
||||
0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x74, 0x72, 0x65, 0x61, 0x73, 0x75, 0x72, 0x65, 0x68, 0x75,
|
||||
0x6e, 0x74, 0x65, 0x72, 0x78, 0x2e, 0x50, 0x6f, 0x6c, 0x79, 0x67, 0x6f, 0x6e, 0x32, 0x44, 0x4c,
|
||||
0x69, 0x73, 0x74, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x96,
|
||||
0x02, 0x0a, 0x06, 0x50, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18,
|
||||
0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x02, 0x69, 0x64, 0x12, 0x0c, 0x0a, 0x01, 0x78, 0x18, 0x02,
|
||||
0x20, 0x01, 0x28, 0x01, 0x52, 0x01, 0x78, 0x12, 0x0c, 0x0a, 0x01, 0x79, 0x18, 0x03, 0x20, 0x01,
|
||||
0x28, 0x01, 0x52, 0x01, 0x79, 0x12, 0x2c, 0x0a, 0x03, 0x64, 0x69, 0x72, 0x18, 0x04, 0x20, 0x01,
|
||||
0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x74, 0x72, 0x65, 0x61, 0x73, 0x75, 0x72, 0x65, 0x68, 0x75, 0x6e,
|
||||
0x74, 0x65, 0x72, 0x78, 0x2e, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x03,
|
||||
0x64, 0x69, 0x72, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x70, 0x65, 0x65, 0x64, 0x18, 0x05, 0x20, 0x01,
|
||||
0x28, 0x01, 0x52, 0x05, 0x73, 0x70, 0x65, 0x65, 0x64, 0x12, 0x20, 0x0a, 0x0b, 0x62, 0x61, 0x74,
|
||||
0x74, 0x6c, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0b,
|
||||
0x62, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x2c, 0x0a, 0x11, 0x6c,
|
||||
0x61, 0x73, 0x74, 0x4d, 0x6f, 0x76, 0x65, 0x47, 0x6d, 0x74, 0x4d, 0x69, 0x6c, 0x6c, 0x69, 0x73,
|
||||
0x18, 0x07, 0x20, 0x01, 0x28, 0x05, 0x52, 0x11, 0x6c, 0x61, 0x73, 0x74, 0x4d, 0x6f, 0x76, 0x65,
|
||||
0x47, 0x6d, 0x74, 0x4d, 0x69, 0x6c, 0x6c, 0x69, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x63, 0x6f,
|
||||
0x72, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x12,
|
||||
0x18, 0x0a, 0x07, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x08,
|
||||
0x52, 0x07, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x12, 0x1c, 0x0a, 0x09, 0x6a, 0x6f, 0x69,
|
||||
0x6e, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x6a, 0x6f,
|
||||
0x69, 0x6e, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x22, 0x88, 0x01, 0x0a, 0x0a, 0x50, 0x6c, 0x61, 0x79,
|
||||
0x65, 0x72, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01,
|
||||
0x28, 0x05, 0x52, 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02,
|
||||
0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x69,
|
||||
0x73, 0x70, 0x6c, 0x61, 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52,
|
||||
0x0b, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06,
|
||||
0x61, 0x76, 0x61, 0x74, 0x61, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x61, 0x76,
|
||||
0x61, 0x74, 0x61, 0x72, 0x12, 0x1c, 0x0a, 0x09, 0x6a, 0x6f, 0x69, 0x6e, 0x49, 0x6e, 0x64, 0x65,
|
||||
0x78, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x6a, 0x6f, 0x69, 0x6e, 0x49, 0x6e, 0x64,
|
||||
0x65, 0x78, 0x22, 0x56, 0x0a, 0x10, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65,
|
||||
0x55, 0x70, 0x73, 0x79, 0x6e, 0x63, 0x12, 0x22, 0x0a, 0x0c, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x46,
|
||||
0x72, 0x61, 0x6d, 0x65, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0c, 0x69, 0x6e,
|
||||
0x70, 0x75, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x49, 0x64, 0x12, 0x1e, 0x0a, 0x0a, 0x65, 0x6e,
|
||||
0x63, 0x6f, 0x64, 0x65, 0x64, 0x44, 0x69, 0x72, 0x18, 0x06, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0a,
|
||||
0x65, 0x6e, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x44, 0x69, 0x72, 0x22, 0x7c, 0x0a, 0x12, 0x49, 0x6e,
|
||||
0x70, 0x75, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x44, 0x6f, 0x77, 0x6e, 0x73, 0x79, 0x6e, 0x63,
|
||||
0x12, 0x22, 0x0a, 0x0c, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x49, 0x64,
|
||||
0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0c, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x46, 0x72, 0x61,
|
||||
0x6d, 0x65, 0x49, 0x64, 0x12, 0x1c, 0x0a, 0x09, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x4c, 0x69, 0x73,
|
||||
0x74, 0x18, 0x02, 0x20, 0x03, 0x28, 0x04, 0x52, 0x09, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x4c, 0x69,
|
||||
0x73, 0x74, 0x12, 0x24, 0x0a, 0x0d, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d, 0x65, 0x64, 0x4c,
|
||||
0x69, 0x73, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0d, 0x63, 0x6f, 0x6e, 0x66, 0x69,
|
||||
0x72, 0x6d, 0x65, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x22, 0x3b, 0x0a, 0x0f, 0x48, 0x65, 0x61, 0x72,
|
||||
0x74, 0x62, 0x65, 0x61, 0x74, 0x55, 0x70, 0x73, 0x79, 0x6e, 0x63, 0x12, 0x28, 0x0a, 0x0f, 0x63,
|
||||
0x6c, 0x69, 0x65, 0x6e, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x01,
|
||||
0x20, 0x01, 0x28, 0x03, 0x52, 0x0f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x54, 0x69, 0x6d, 0x65,
|
||||
0x73, 0x74, 0x61, 0x6d, 0x70, 0x22, 0x9f, 0x03, 0x0a, 0x11, 0x52, 0x6f, 0x6f, 0x6d, 0x44, 0x6f,
|
||||
0x77, 0x6e, 0x73, 0x79, 0x6e, 0x63, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69,
|
||||
0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x02, 0x69, 0x64, 0x12, 0x49, 0x0a, 0x07, 0x70,
|
||||
0x6c, 0x61, 0x79, 0x65, 0x72, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x74,
|
||||
0x72, 0x65, 0x61, 0x73, 0x75, 0x72, 0x65, 0x68, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x78, 0x2e, 0x52,
|
||||
0x6f, 0x6f, 0x6d, 0x44, 0x6f, 0x77, 0x6e, 0x73, 0x79, 0x6e, 0x63, 0x46, 0x72, 0x61, 0x6d, 0x65,
|
||||
0x2e, 0x50, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x07, 0x70,
|
||||
0x6c, 0x61, 0x79, 0x65, 0x72, 0x73, 0x12, 0x26, 0x0a, 0x0e, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x64,
|
||||
0x6f, 0x77, 0x6e, 0x4e, 0x61, 0x6e, 0x6f, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e,
|
||||
0x63, 0x6f, 0x75, 0x6e, 0x74, 0x64, 0x6f, 0x77, 0x6e, 0x4e, 0x61, 0x6e, 0x6f, 0x73, 0x12, 0x55,
|
||||
0x0a, 0x0b, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x4d, 0x65, 0x74, 0x61, 0x73, 0x18, 0x04, 0x20,
|
||||
0x03, 0x28, 0x0b, 0x32, 0x33, 0x2e, 0x74, 0x72, 0x65, 0x61, 0x73, 0x75, 0x72, 0x65, 0x68, 0x75,
|
||||
0x6e, 0x74, 0x65, 0x72, 0x78, 0x2e, 0x52, 0x6f, 0x6f, 0x6d, 0x44, 0x6f, 0x77, 0x6e, 0x73, 0x79,
|
||||
0x6e, 0x63, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x2e, 0x50, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x4d, 0x65,
|
||||
0x74, 0x61, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0b, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72,
|
||||
0x4d, 0x65, 0x74, 0x61, 0x73, 0x1a, 0x53, 0x0a, 0x0c, 0x50, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x73,
|
||||
0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01,
|
||||
0x28, 0x05, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x2d, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65,
|
||||
0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x74, 0x72, 0x65, 0x61, 0x73, 0x75, 0x72,
|
||||
0x65, 0x68, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x78, 0x2e, 0x50, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x52,
|
||||
0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x5b, 0x0a, 0x10, 0x50, 0x6c,
|
||||
0x61, 0x79, 0x65, 0x72, 0x4d, 0x65, 0x74, 0x61, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10,
|
||||
0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x03, 0x6b, 0x65, 0x79,
|
||||
0x12, 0x31, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32,
|
||||
0x1b, 0x2e, 0x74, 0x72, 0x65, 0x61, 0x73, 0x75, 0x72, 0x65, 0x68, 0x75, 0x6e, 0x74, 0x65, 0x72,
|
||||
0x78, 0x2e, 0x50, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x05, 0x76, 0x61,
|
||||
0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xca, 0x02, 0x0a, 0x05, 0x57, 0x73, 0x52, 0x65,
|
||||
0x71, 0x12, 0x14, 0x0a, 0x05, 0x6d, 0x73, 0x67, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05,
|
||||
0x52, 0x05, 0x6d, 0x73, 0x67, 0x49, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x6c, 0x61, 0x79, 0x65,
|
||||
0x72, 0x49, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x70, 0x6c, 0x61, 0x79, 0x65,
|
||||
0x72, 0x49, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x61, 0x63, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05,
|
||||
0x52, 0x03, 0x61, 0x63, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x6a, 0x6f, 0x69, 0x6e, 0x49, 0x6e, 0x64,
|
||||
0x65, 0x78, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x6a, 0x6f, 0x69, 0x6e, 0x49, 0x6e,
|
||||
0x64, 0x65, 0x78, 0x12, 0x24, 0x0a, 0x0d, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x46, 0x72, 0x61,
|
||||
0x6d, 0x65, 0x49, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0d, 0x61, 0x63, 0x6b, 0x69,
|
||||
0x6e, 0x67, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x49, 0x64, 0x12, 0x2e, 0x0a, 0x12, 0x61, 0x63, 0x6b,
|
||||
0x69, 0x6e, 0x67, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x49, 0x64, 0x18,
|
||||
0x06, 0x20, 0x01, 0x28, 0x05, 0x52, 0x12, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x49, 0x6e, 0x70,
|
||||
0x75, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x49, 0x64, 0x12, 0x57, 0x0a, 0x15, 0x69, 0x6e, 0x70,
|
||||
0x75, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x55, 0x70, 0x73, 0x79, 0x6e, 0x63, 0x42, 0x61, 0x74,
|
||||
0x63, 0x68, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x74, 0x72, 0x65, 0x61, 0x73,
|
||||
0x75, 0x72, 0x65, 0x68, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x78, 0x2e, 0x49, 0x6e, 0x70, 0x75, 0x74,
|
||||
0x46, 0x72, 0x61, 0x6d, 0x65, 0x55, 0x70, 0x73, 0x79, 0x6e, 0x63, 0x52, 0x15, 0x69, 0x6e, 0x70,
|
||||
0x75, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x55, 0x70, 0x73, 0x79, 0x6e, 0x63, 0x42, 0x61, 0x74,
|
||||
0x63, 0x68, 0x12, 0x30, 0x0a, 0x02, 0x68, 0x62, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20,
|
||||
0x2e, 0x74, 0x72, 0x65, 0x61, 0x73, 0x75, 0x72, 0x65, 0x68, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x78,
|
||||
0x2e, 0x48, 0x65, 0x61, 0x72, 0x74, 0x62, 0x65, 0x61, 0x74, 0x55, 0x70, 0x73, 0x79, 0x6e, 0x63,
|
||||
0x52, 0x02, 0x68, 0x62, 0x22, 0xa4, 0x02, 0x0a, 0x06, 0x57, 0x73, 0x52, 0x65, 0x73, 0x70, 0x12,
|
||||
0x10, 0x0a, 0x03, 0x72, 0x65, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x03, 0x72, 0x65,
|
||||
0x74, 0x12, 0x20, 0x0a, 0x0b, 0x65, 0x63, 0x68, 0x6f, 0x65, 0x64, 0x4d, 0x73, 0x67, 0x49, 0x64,
|
||||
0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0b, 0x65, 0x63, 0x68, 0x6f, 0x65, 0x64, 0x4d, 0x73,
|
||||
0x67, 0x49, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x61, 0x63, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05,
|
||||
0x52, 0x03, 0x61, 0x63, 0x74, 0x12, 0x34, 0x0a, 0x03, 0x72, 0x64, 0x66, 0x18, 0x04, 0x20, 0x01,
|
||||
0x28, 0x0b, 0x32, 0x22, 0x2e, 0x74, 0x72, 0x65, 0x61, 0x73, 0x75, 0x72, 0x65, 0x68, 0x75, 0x6e,
|
||||
0x74, 0x65, 0x72, 0x78, 0x2e, 0x52, 0x6f, 0x6f, 0x6d, 0x44, 0x6f, 0x77, 0x6e, 0x73, 0x79, 0x6e,
|
||||
0x63, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x52, 0x03, 0x72, 0x64, 0x66, 0x12, 0x5d, 0x0a, 0x17, 0x69,
|
||||
0x6e, 0x70, 0x75, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x44, 0x6f, 0x77, 0x6e, 0x73, 0x79, 0x6e,
|
||||
0x63, 0x42, 0x61, 0x74, 0x63, 0x68, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x74,
|
||||
0x72, 0x65, 0x61, 0x73, 0x75, 0x72, 0x65, 0x68, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x78, 0x2e, 0x49,
|
||||
0x6e, 0x70, 0x75, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x55, 0x70, 0x73, 0x79, 0x6e, 0x63, 0x52,
|
||||
0x15, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x55, 0x70, 0x73, 0x79, 0x6e,
|
||||
0x63, 0x42, 0x61, 0x74, 0x63, 0x68, 0x12, 0x30, 0x0a, 0x02, 0x68, 0x62, 0x18, 0x08, 0x20, 0x01,
|
||||
0x28, 0x0b, 0x32, 0x20, 0x2e, 0x74, 0x72, 0x65, 0x61, 0x73, 0x75, 0x72, 0x65, 0x68, 0x75, 0x6e,
|
||||
0x74, 0x65, 0x72, 0x78, 0x2e, 0x48, 0x65, 0x61, 0x72, 0x74, 0x62, 0x65, 0x61, 0x74, 0x55, 0x70,
|
||||
0x73, 0x79, 0x6e, 0x63, 0x52, 0x02, 0x68, 0x62, 0x22, 0xa4, 0x02, 0x0a, 0x06, 0x57, 0x73, 0x52,
|
||||
0x65, 0x73, 0x70, 0x12, 0x10, 0x0a, 0x03, 0x72, 0x65, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05,
|
||||
0x52, 0x03, 0x72, 0x65, 0x74, 0x12, 0x20, 0x0a, 0x0b, 0x65, 0x63, 0x68, 0x6f, 0x65, 0x64, 0x4d,
|
||||
0x73, 0x67, 0x49, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0b, 0x65, 0x63, 0x68, 0x6f,
|
||||
0x65, 0x64, 0x4d, 0x73, 0x67, 0x49, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x61, 0x63, 0x74, 0x18, 0x03,
|
||||
0x20, 0x01, 0x28, 0x05, 0x52, 0x03, 0x61, 0x63, 0x74, 0x12, 0x34, 0x0a, 0x03, 0x72, 0x64, 0x66,
|
||||
0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x74, 0x72, 0x65, 0x61, 0x73, 0x75, 0x72,
|
||||
0x65, 0x68, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x78, 0x2e, 0x52, 0x6f, 0x6f, 0x6d, 0x44, 0x6f, 0x77,
|
||||
0x6e, 0x73, 0x79, 0x6e, 0x63, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x52, 0x03, 0x72, 0x64, 0x66, 0x12,
|
||||
0x5d, 0x0a, 0x17, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x44, 0x6f, 0x77,
|
||||
0x6e, 0x73, 0x79, 0x6e, 0x63, 0x42, 0x61, 0x74, 0x63, 0x68, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b,
|
||||
0x32, 0x23, 0x2e, 0x74, 0x72, 0x65, 0x61, 0x73, 0x75, 0x72, 0x65, 0x68, 0x75, 0x6e, 0x74, 0x65,
|
||||
0x72, 0x78, 0x2e, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x44, 0x6f, 0x77,
|
||||
0x6e, 0x73, 0x79, 0x6e, 0x63, 0x52, 0x17, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x46, 0x72, 0x61, 0x6d,
|
||||
0x65, 0x44, 0x6f, 0x77, 0x6e, 0x73, 0x79, 0x6e, 0x63, 0x42, 0x61, 0x74, 0x63, 0x68, 0x12, 0x3f,
|
||||
0x0a, 0x08, 0x62, 0x63, 0x69, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b,
|
||||
0x32, 0x23, 0x2e, 0x74, 0x72, 0x65, 0x61, 0x73, 0x75, 0x72, 0x65, 0x68, 0x75, 0x6e, 0x74, 0x65,
|
||||
0x72, 0x78, 0x2e, 0x42, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x43, 0x6f, 0x6c, 0x6c, 0x69, 0x64, 0x65,
|
||||
0x72, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x08, 0x62, 0x63, 0x69, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x42,
|
||||
0x03, 0x5a, 0x01, 0x2e, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
0x6e, 0x70, 0x75, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x44, 0x6f, 0x77, 0x6e, 0x73, 0x79, 0x6e,
|
||||
0x63, 0x52, 0x17, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x44, 0x6f, 0x77,
|
||||
0x6e, 0x73, 0x79, 0x6e, 0x63, 0x42, 0x61, 0x74, 0x63, 0x68, 0x12, 0x3f, 0x0a, 0x08, 0x62, 0x63,
|
||||
0x69, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x74,
|
||||
0x72, 0x65, 0x61, 0x73, 0x75, 0x72, 0x65, 0x68, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x78, 0x2e, 0x42,
|
||||
0x61, 0x74, 0x74, 0x6c, 0x65, 0x43, 0x6f, 0x6c, 0x6c, 0x69, 0x64, 0x65, 0x72, 0x49, 0x6e, 0x66,
|
||||
0x6f, 0x52, 0x08, 0x62, 0x63, 0x69, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x42, 0x03, 0x5a, 0x01, 0x2e,
|
||||
0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
}
|
||||
|
||||
var (
|
||||
|
@@ -6,6 +6,8 @@ import (
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
"github.com/jmoiron/sqlx"
|
||||
"go.uber.org/zap"
|
||||
|
||||
. "dnmshared"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -15,8 +17,12 @@ var (
|
||||
func initMySQL() {
|
||||
var err error
|
||||
MySQLManagerIns, err = sqlx.Connect("mysql", Conf.MySQL.DSN+"?charset=utf8mb4")
|
||||
ErrFatal(err)
|
||||
if nil != err {
|
||||
panic(err)
|
||||
}
|
||||
err = MySQLManagerIns.Ping()
|
||||
ErrFatal(err)
|
||||
if nil != err {
|
||||
panic(err)
|
||||
}
|
||||
Logger.Info("MySQLManagerIns", zap.Any("mysql", MySQLManagerIns))
|
||||
}
|
||||
|
@@ -7,6 +7,8 @@ import (
|
||||
"github.com/go-redis/redis"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
"go.uber.org/zap"
|
||||
|
||||
. "dnmshared"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -20,6 +22,8 @@ func initRedis() {
|
||||
DB: Conf.Redis.Dbname, // use default DB
|
||||
})
|
||||
pong, err := RedisManagerIns.Ping().Result()
|
||||
ErrFatal(err)
|
||||
if nil != err {
|
||||
panic(err)
|
||||
}
|
||||
Logger.Info("Redis", zap.String("ping", pong))
|
||||
}
|
||||
|
@@ -17,7 +17,9 @@ func loadTMX(fp string, pTmxMapIns *models.TmxMap) {
|
||||
}
|
||||
|
||||
byteArr, err := ioutil.ReadFile(fp)
|
||||
ErrFatal(err)
|
||||
if nil != err {
|
||||
panic(err)
|
||||
}
|
||||
models.DeserializeToTmxMapIns(byteArr, pTmxMapIns)
|
||||
for _, info := range pTmxMapIns.TreasuresInfo {
|
||||
fmt.Printf("treasuresInfo: %v\n", info)
|
||||
@@ -33,7 +35,9 @@ func loadTSX(fp string, pTsxIns *models.Tsx) {
|
||||
}
|
||||
|
||||
byteArr, err := ioutil.ReadFile(fp)
|
||||
ErrFatal(err)
|
||||
if nil != err {
|
||||
panic(err)
|
||||
}
|
||||
models.DeserializeToTsxIns(byteArr, pTsxIns)
|
||||
for _, Pos := range pTsxIns.TrapPolyLineList {
|
||||
fmt.Printf("%v\n", Pos)
|
||||
@@ -43,10 +47,14 @@ func loadTSX(fp string, pTsxIns *models.Tsx) {
|
||||
func getTMXInfo() {
|
||||
relativePath = "../frontend/assets/resources/map/treasurehunter.tmx"
|
||||
execPath, err := os.Executable()
|
||||
ErrFatal(err)
|
||||
if nil != err {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
pwd, err := os.Getwd()
|
||||
ErrFatal(err)
|
||||
if nil != err {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
fmt.Printf("execPath = %v, pwd = %s, returning...\n", execPath, pwd)
|
||||
|
||||
@@ -61,10 +69,14 @@ func getTSXInfo() {
|
||||
|
||||
relativePath = "../frontend/assets/resources/map/tile_1.tsx"
|
||||
execPath, err := os.Executable()
|
||||
ErrFatal(err)
|
||||
if nil != err {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
pwd, err := os.Getwd()
|
||||
ErrFatal(err)
|
||||
if nil != err {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
fmt.Printf("execPath = %v, pwd = %s, returning...\n", execPath, pwd)
|
||||
tsxIns := models.Tsx{}
|
||||
|
@@ -14,6 +14,8 @@ import (
|
||||
"strconv"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
. "dnmshared"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -261,6 +263,9 @@ func Serve(c *gin.Context) {
|
||||
InputFrameUpsyncDelayTolerance: pRoom.InputFrameUpsyncDelayTolerance,
|
||||
MaxChasingRenderFramesPerUpdate: pRoom.MaxChasingRenderFramesPerUpdate,
|
||||
PlayerBattleState: pThePlayer.BattleState, // For frontend to know whether it's rejoining
|
||||
RollbackEstimatedDt: pRoom.RollbackEstimatedDt,
|
||||
RollbackEstimatedDtMillis: pRoom.RollbackEstimatedDtMillis,
|
||||
RollbackEstimatedDtNanos: pRoom.RollbackEstimatedDtNanos,
|
||||
}
|
||||
|
||||
resp := &pb.WsResp{
|
||||
|
21
collider_visualizer/Makefile
Normal file
@@ -0,0 +1,21 @@
|
||||
PROJECTNAME=viscol.exe
|
||||
ROOT_DIR=.
|
||||
all: help
|
||||
## Available proxies for downloading go modules are listed in "https://github.com/golang/go/wiki/Modules#how-do-i-use-vendoring-with-modules-is-vendoring-going-away".
|
||||
GOPROXY=https://mirrors.aliyun.com/goproxy
|
||||
|
||||
build:
|
||||
go build -o $(ROOT_DIR)/$(PROJECTNAME)
|
||||
|
||||
run: build
|
||||
./$(PROJECTNAME)
|
||||
|
||||
.PHONY: help
|
||||
|
||||
help: Makefile
|
||||
@echo
|
||||
@echo " Choose a command run:"
|
||||
@echo
|
||||
@sed -n 's/^##//p' $< | column -t -s ':' | sed -e 's/^/ /'
|
||||
@echo
|
||||
|
52
collider_visualizer/common.go
Normal file
@@ -0,0 +1,52 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/hajimehoshi/ebiten/v2"
|
||||
"github.com/solarlune/resolv"
|
||||
"image/color"
|
||||
)
|
||||
|
||||
var (
|
||||
PolygonFillerImage = ebiten.NewImage(1, 1)
|
||||
)
|
||||
|
||||
func DrawPolygon(screen *ebiten.Image, shape *resolv.ConvexPolygon, clr color.Color) {
|
||||
PolygonFillerImage.Fill(clr)
|
||||
indices := []uint16{}
|
||||
vs := []ebiten.Vertex{}
|
||||
coors := shape.Transformed()
|
||||
centerX := float64(0)
|
||||
centerY := float64(0)
|
||||
n := uint16(len(coors))
|
||||
for i, coor := range coors {
|
||||
centerX += coor.X()
|
||||
centerY += coor.Y()
|
||||
vs = append(vs, ebiten.Vertex{
|
||||
DstX: float32(coor.X()),
|
||||
DstY: float32(coor.Y()),
|
||||
SrcX: 0,
|
||||
SrcY: 0,
|
||||
ColorR: 1,
|
||||
ColorG: 1,
|
||||
ColorB: 1,
|
||||
ColorA: 1,
|
||||
})
|
||||
indices = append(indices, uint16(i), uint16(i+1)%n, n)
|
||||
}
|
||||
|
||||
centerX = centerX / float64(n)
|
||||
centerY = centerY / float64(n)
|
||||
|
||||
vs = append(vs, ebiten.Vertex{
|
||||
DstX: float32(centerX),
|
||||
DstY: float32(centerY),
|
||||
SrcX: 0,
|
||||
SrcY: 0,
|
||||
ColorR: 1,
|
||||
ColorG: 1,
|
||||
ColorB: 1,
|
||||
ColorA: 1,
|
||||
})
|
||||
|
||||
screen.DrawTriangles(vs, indices, PolygonFillerImage, nil)
|
||||
}
|
BIN
collider_visualizer/excel.ttf
Normal file
27
collider_visualizer/go.mod
Normal file
@@ -0,0 +1,27 @@
|
||||
module viscol
|
||||
|
||||
go 1.19
|
||||
|
||||
require (
|
||||
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0
|
||||
github.com/hajimehoshi/ebiten/v2 v2.4.7
|
||||
github.com/solarlune/resolv v0.5.1
|
||||
golang.org/x/image v0.0.0-20220902085622-e7cb96979f69
|
||||
dnmshared v0.0.0
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/ebitengine/purego v0.0.0-20220905075623-aeed57cda744 // indirect
|
||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20220806181222-55e207c401ad // indirect
|
||||
github.com/hajimehoshi/file2byteslice v0.0.0-20210813153925-5340248a8f41 // indirect
|
||||
github.com/jezek/xgb v1.0.1 // indirect
|
||||
github.com/kvartborg/vector v0.0.0-20200419093813-2cba0cabb4f0 // indirect
|
||||
go.uber.org/atomic v1.7.0 // indirect
|
||||
go.uber.org/multierr v1.6.0 // indirect
|
||||
go.uber.org/zap v1.23.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20190731235908-ec7cb31e5a56 // indirect
|
||||
golang.org/x/mobile v0.0.0-20220722155234-aaac322e2105 // indirect
|
||||
golang.org/x/sys v0.0.0-20220818161305-2296e01440c6 // indirect
|
||||
)
|
||||
|
||||
replace dnmshared => ../dnmshared
|
96
collider_visualizer/go.sum
Normal file
@@ -0,0 +1,96 @@
|
||||
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/ebitengine/purego v0.0.0-20220905075623-aeed57cda744 h1:A8UnJ/5OKzki4HBDwoRQz7I6sxKsokpMXcGh+fUxpfc=
|
||||
github.com/ebitengine/purego v0.0.0-20220905075623-aeed57cda744/go.mod h1:Eh8I3yvknDYZeCuXH9kRNaPuHEwvXDCk378o9xszmHg=
|
||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20220806181222-55e207c401ad h1:kX51IjbsJPCvzV9jUoVQG9GEUqIq5hjfYzXTqQ52Rh8=
|
||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20220806181222-55e207c401ad/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF08vX0COfcOBJRhZ8lUbR+ZWIs0Y5g=
|
||||
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k=
|
||||
github.com/hajimehoshi/bitmapfont/v2 v2.2.1 h1:y7zcy02/UgO24IL3COqYtrRZzhRucNBtmCo/SNU648k=
|
||||
github.com/hajimehoshi/bitmapfont/v2 v2.2.1/go.mod h1:wjrYAy8vKgj9JsFgnYAOK346/uvE22TlmqouzdnYIs0=
|
||||
github.com/hajimehoshi/ebiten/v2 v2.4.7 h1:XuvB7R0Rbw/O7g6vNU8gqr5b9e7MNhhAONMSsyreLDI=
|
||||
github.com/hajimehoshi/ebiten/v2 v2.4.7/go.mod h1:Ofk1EfQZZ8tL0TlEPF5wPrnN+8Oa/ywuQOYh+uYsqLQ=
|
||||
github.com/hajimehoshi/file2byteslice v0.0.0-20210813153925-5340248a8f41 h1:s01qIIRG7vN/5ndLwkDktjx44ulFk6apvAjVBYR50Yo=
|
||||
github.com/hajimehoshi/file2byteslice v0.0.0-20210813153925-5340248a8f41/go.mod h1:CqqAHp7Dk/AqQiwuhV1yT2334qbA/tFWQW0MD2dGqUE=
|
||||
github.com/hajimehoshi/go-mp3 v0.3.3/go.mod h1:qMJj/CSDxx6CGHiZeCgbiq2DSUkbK0UbtXShQcnfyMM=
|
||||
github.com/hajimehoshi/oto v0.6.1/go.mod h1:0QXGEkbuJRohbJaxr7ZQSxnju7hEhseiPx2hrh6raOI=
|
||||
github.com/hajimehoshi/oto/v2 v2.3.1/go.mod h1:seWLbgHH7AyUMYKfKYT9pg7PhUu9/SisyJvNTT+ASQo=
|
||||
github.com/jakecoffman/cp v1.2.1/go.mod h1:JjY/Fp6d8E1CHnu74gWNnU0+b9VzEdUVPoJxg2PsTQg=
|
||||
github.com/jezek/xgb v1.0.1 h1:YUGhxps0aR7J2Xplbs23OHnV1mWaxFVcOl9b+1RQkt8=
|
||||
github.com/jezek/xgb v1.0.1/go.mod h1:nrhwO0FX/enq75I7Y7G8iN1ubpSGZEiA3v9e9GyRFlk=
|
||||
github.com/jfreymuth/oggvorbis v1.0.4/go.mod h1:1U4pqWmghcoVsCJJ4fRBKv9peUJMBHixthRlBeD6uII=
|
||||
github.com/jfreymuth/vorbis v1.0.2/go.mod h1:DoftRo4AznKnShRl1GxiTFCseHr4zR9BN3TWXyuzrqQ=
|
||||
github.com/kvartborg/vector v0.0.0-20200419093813-2cba0cabb4f0 h1:v8lWpj5957KtDMKu+xQtlu6G3ZoZR6Tn9bsfZCRG5Xw=
|
||||
github.com/kvartborg/vector v0.0.0-20200419093813-2cba0cabb4f0/go.mod h1:GAX7tMJqXx9fB1BrsTWPOXy6IBRX+J461BffVPAdpwo=
|
||||
github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/solarlune/resolv v0.5.1 h1:Ul6PAs/zaxiMUOEYz1Z6VeUj5k3CDcWMvSh+kivybDY=
|
||||
github.com/solarlune/resolv v0.5.1/go.mod h1:HjM2f/0NoVjVdZsi26GtugX5aFbA62COEFEXkOhveRw=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw=
|
||||
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
|
||||
go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4=
|
||||
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
|
||||
go.uber.org/zap v1.23.0 h1:OjGQ5KQDEUawVHxNwQgPpiypGHOxo2mNZsOqTak4fFY=
|
||||
go.uber.org/zap v1.23.0/go.mod h1:D+nX8jyLsMHMYrln8A0rJjFt/T/9/bGgIhAqxv5URuY=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190731235908-ec7cb31e5a56 h1:estk1glOnSVeJ9tdEZZc5mAMDZk5lNJNyJ6DvrBkTEU=
|
||||
golang.org/x/exp v0.0.0-20190731235908-ec7cb31e5a56/go.mod h1:JhuoJpWY28nO4Vef9tZUw9qufEGTyX1+7lmHxV5q5G4=
|
||||
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
||||
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||
golang.org/x/image v0.0.0-20220722155232-062f8c9fd539/go.mod h1:doUCurBvlfPMKfmIpRIywoHmhN3VyhnoFDbvIEWF4hY=
|
||||
golang.org/x/image v0.0.0-20220902085622-e7cb96979f69 h1:Lj6HJGCSn5AjxRAH2+r35Mir4icalbqku+CLUtjnvXY=
|
||||
golang.org/x/image v0.0.0-20220902085622-e7cb96979f69/go.mod h1:doUCurBvlfPMKfmIpRIywoHmhN3VyhnoFDbvIEWF4hY=
|
||||
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
|
||||
golang.org/x/mobile v0.0.0-20190415191353-3e0bab5405d6/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
|
||||
golang.org/x/mobile v0.0.0-20220722155234-aaac322e2105 h1:3vUV5x5+3LfQbgk7paCM6INOaJG9xXQbn79xoNkwfIk=
|
||||
golang.org/x/mobile v0.0.0-20220722155234-aaac322e2105/go.mod h1:pe2sM7Uk+2Su1y7u/6Z8KJ24D7lepUjFZbhFOrmDfuQ=
|
||||
golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
|
||||
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190429190828-d89cdac9e872/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210616045830-e2b7044e8c71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220712014510-0a85c31ab51e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220818161305-2296e01440c6 h1:Sx/u41w+OwrInGdEckYmEuU5gHoGSL4QbDz3S9s6j4U=
|
||||
golang.org/x/sys v0.0.0-20220818161305-2296e01440c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.1.8-0.20211022200916-316ba0b74098/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo=
|
||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
171
collider_visualizer/main.go
Normal file
@@ -0,0 +1,171 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
_ "embed"
|
||||
"fmt"
|
||||
"image/color"
|
||||
|
||||
"go.uber.org/zap"
|
||||
|
||||
"github.com/golang/freetype/truetype"
|
||||
"github.com/hajimehoshi/ebiten/v2"
|
||||
"github.com/hajimehoshi/ebiten/v2/ebitenutil"
|
||||
"github.com/hajimehoshi/ebiten/v2/text"
|
||||
"github.com/solarlune/resolv"
|
||||
"golang.org/x/image/font"
|
||||
|
||||
"encoding/xml"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
. "dnmshared"
|
||||
)
|
||||
|
||||
func parseStage(stageName string) (int32, int32, int32, int32, StrToVec2DListMap, StrToPolygon2DListMap, error) {
|
||||
pwd, err := os.Getwd()
|
||||
if nil != err {
|
||||
Logger.Error("Failed to get current working dir:", zap.Any("pwd", pwd), zap.Any("err", err))
|
||||
}
|
||||
|
||||
relativePathForAllStages := "../frontend/assets/resources/map"
|
||||
relativePathForChosenStage := fmt.Sprintf("%s/%s", relativePathForAllStages, stageName)
|
||||
|
||||
pTmxMapIns := &TmxMap{}
|
||||
|
||||
absDirPathContainingDirectlyTmxFile := filepath.Join(pwd, relativePathForChosenStage)
|
||||
absTmxFilePath := fmt.Sprintf("%s/map.tmx", absDirPathContainingDirectlyTmxFile)
|
||||
if !filepath.IsAbs(absTmxFilePath) {
|
||||
panic("Tmx filepath must be absolute!")
|
||||
}
|
||||
|
||||
byteArr, err := ioutil.ReadFile(absTmxFilePath)
|
||||
if nil != err {
|
||||
panic(err)
|
||||
}
|
||||
err = xml.Unmarshal(byteArr, pTmxMapIns)
|
||||
if nil != err {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// Obtain the content of `gidBoundariesMapInB2World`.
|
||||
gidBoundariesMapInB2World := make(map[int]StrToPolygon2DListMap, 0)
|
||||
for _, tileset := range pTmxMapIns.Tilesets {
|
||||
relativeTsxFilePath := fmt.Sprintf("%s/%s", filepath.Join(pwd, relativePathForChosenStage), tileset.Source) // Note that "TmxTileset.Source" can be a string of "relative path".
|
||||
absTsxFilePath, err := filepath.Abs(relativeTsxFilePath)
|
||||
if nil != err {
|
||||
panic(err)
|
||||
}
|
||||
if !filepath.IsAbs(absTsxFilePath) {
|
||||
panic("Filepath must be absolute!")
|
||||
}
|
||||
|
||||
byteArrOfTsxFile, err := ioutil.ReadFile(absTsxFilePath)
|
||||
if nil != err {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
DeserializeTsxToColliderDict(pTmxMapIns, byteArrOfTsxFile, int(tileset.FirstGid), gidBoundariesMapInB2World)
|
||||
}
|
||||
|
||||
return ParseTmxLayersAndGroups(pTmxMapIns, gidBoundariesMapInB2World)
|
||||
}
|
||||
|
||||
//go:embed excel.ttf
|
||||
var excelFont []byte
|
||||
|
||||
type Game struct {
|
||||
World WorldInterface
|
||||
Width, Height int
|
||||
Debug bool
|
||||
ShowHelpText bool
|
||||
Screen *ebiten.Image
|
||||
FontFace font.Face
|
||||
}
|
||||
|
||||
func NewGame() *Game {
|
||||
|
||||
stageName := "simple" // Use this for calibration
|
||||
// stageName := "richsoil"
|
||||
stageDiscreteW, stageDiscreteH, stageTileW, stageTileH, playerPosMap, barrierMap, err := parseStage(stageName)
|
||||
if nil != err {
|
||||
panic(err)
|
||||
}
|
||||
PolygonFillerImage.Fill(color.RGBA{60, 60, 60, 255}) // Required to init color of the polygons!
|
||||
|
||||
spaceW := stageDiscreteW * stageTileW
|
||||
spaceH := stageDiscreteH * stageTileH
|
||||
|
||||
ebiten.SetWindowResizable(true)
|
||||
ebiten.SetWindowTitle("resolv test")
|
||||
|
||||
g := &Game{
|
||||
Width: int(spaceW),
|
||||
Height: int(spaceH),
|
||||
ShowHelpText: true,
|
||||
}
|
||||
|
||||
g.World = NewWorldColliderDisplay(g, stageDiscreteW, stageDiscreteH, stageTileW, stageTileH, playerPosMap, barrierMap)
|
||||
|
||||
fontData, _ := truetype.Parse(excelFont)
|
||||
|
||||
g.FontFace = truetype.NewFace(fontData, &truetype.Options{Size: 10})
|
||||
|
||||
return g
|
||||
}
|
||||
|
||||
func (g *Game) Update() error {
|
||||
g.World.Update()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (g *Game) Draw(screen *ebiten.Image) {
|
||||
g.Screen = screen
|
||||
screen.Fill(color.RGBA{20, 20, 40, 255})
|
||||
g.World.Draw(screen)
|
||||
}
|
||||
|
||||
func (g *Game) DrawText(screen *ebiten.Image, x, y int, textLines ...string) {
|
||||
rectHeight := 10
|
||||
for _, txt := range textLines {
|
||||
w := float64(font.MeasureString(g.FontFace, txt).Round())
|
||||
ebitenutil.DrawRect(screen, float64(x), float64(y-8), w, float64(rectHeight), color.RGBA{0, 0, 0, 192})
|
||||
|
||||
text.Draw(screen, txt, g.FontFace, x+1, y+1, color.RGBA{0, 0, 150, 255})
|
||||
text.Draw(screen, txt, g.FontFace, x, y, color.RGBA{100, 150, 255, 255})
|
||||
y += rectHeight
|
||||
}
|
||||
}
|
||||
|
||||
func (g *Game) DebugDraw(screen *ebiten.Image, space *resolv.Space) {
|
||||
|
||||
for y := 0; y < space.Height(); y++ {
|
||||
for x := 0; x < space.Width(); x++ {
|
||||
cell := space.Cell(x, y)
|
||||
|
||||
cw := float64(space.CellWidth)
|
||||
ch := float64(space.CellHeight)
|
||||
cx := float64(cell.X) * cw
|
||||
cy := float64(cell.Y) * ch
|
||||
|
||||
drawColor := color.RGBA{20, 20, 20, 255}
|
||||
|
||||
if cell.Occupied() {
|
||||
drawColor = color.RGBA{255, 255, 0, 255}
|
||||
}
|
||||
|
||||
ebitenutil.DrawLine(screen, cx, cy, cx+cw, cy, drawColor)
|
||||
ebitenutil.DrawLine(screen, cx+cw, cy, cx+cw, cy+ch, drawColor)
|
||||
ebitenutil.DrawLine(screen, cx+cw, cy+ch, cx, cy+ch, drawColor)
|
||||
ebitenutil.DrawLine(screen, cx, cy+ch, cx, cy, drawColor)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (g *Game) Layout(w, h int) (int, int) {
|
||||
return g.Width, g.Height
|
||||
}
|
||||
|
||||
func main() {
|
||||
ebiten.RunGame(NewGame())
|
||||
}
|
111
collider_visualizer/worldColliderDisplay.go
Normal file
@@ -0,0 +1,111 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
. "dnmshared"
|
||||
"fmt"
|
||||
"github.com/hajimehoshi/ebiten/v2"
|
||||
"github.com/solarlune/resolv"
|
||||
"go.uber.org/zap"
|
||||
"image/color"
|
||||
)
|
||||
|
||||
type WorldColliderDisplay struct {
|
||||
Game *Game
|
||||
Space *resolv.Space
|
||||
}
|
||||
|
||||
func (world *WorldColliderDisplay) Init() {
|
||||
}
|
||||
|
||||
func NewWorldColliderDisplay(game *Game, stageDiscreteW, stageDiscreteH, stageTileW, stageTileH int32, playerPosMap StrToVec2DListMap, barrierMap StrToPolygon2DListMap) *WorldColliderDisplay {
|
||||
|
||||
playerList := *(playerPosMap["PlayerStartingPos"])
|
||||
barrierList := *(barrierMap["Barrier"])
|
||||
|
||||
world := &WorldColliderDisplay{Game: game}
|
||||
|
||||
Logger.Info("Parsed variables", zap.Any("stageDiscreteW", stageDiscreteW), zap.Any("stageDiscreteH", stageDiscreteH), zap.Any("stageTileW", stageTileW), zap.Any("stageTileH", stageTileH))
|
||||
|
||||
spaceW := stageDiscreteW * stageTileW
|
||||
spaceH := stageDiscreteH * stageTileH
|
||||
|
||||
spaceOffsetX := float64(spaceW) * 0.5
|
||||
spaceOffsetY := float64(spaceH) * 0.5
|
||||
|
||||
playerColliderRadius := float64(32)
|
||||
playerColliders := make([]*resolv.Object, len(playerList))
|
||||
space := resolv.NewSpace(int(spaceW), int(spaceH), 16, 16)
|
||||
for i, player := range playerList {
|
||||
playerCollider := GenerateRectCollider(player.X, player.Y, playerColliderRadius*2, playerColliderRadius*2, spaceOffsetX, spaceOffsetY, "Player") // [WARNING] Deliberately not using a circle because "resolv v0.5.1" doesn't yet align circle center with space cell center, regardless of the "specified within-object offset"
|
||||
Logger.Info(fmt.Sprintf("Player Collider#%d: player.X=%v, player.Y=%v, radius=%v, spaceOffsetX=%v, spaceOffsetY=%v, shape=%v; calibrationCheckX=player.X-radius+spaceOffsetX=%v", i, player.X, player.Y, playerColliderRadius, spaceOffsetX, spaceOffsetY, playerCollider.Shape, player.X-playerColliderRadius+spaceOffsetX))
|
||||
playerColliders[i] = playerCollider
|
||||
space.Add(playerCollider)
|
||||
}
|
||||
|
||||
barrierLocalId := 0
|
||||
for _, barrierUnaligned := range barrierList {
|
||||
barrierCollider := GenerateConvexPolygonCollider(barrierUnaligned, spaceOffsetX, spaceOffsetY, "Barrier")
|
||||
Logger.Info(fmt.Sprintf("Added barrier: shape=%v", barrierCollider.Shape))
|
||||
space.Add(barrierCollider)
|
||||
barrierLocalId++
|
||||
}
|
||||
|
||||
world.Space = space
|
||||
|
||||
moveToCollide := true
|
||||
if moveToCollide {
|
||||
toTestPlayerCollider := playerColliders[0]
|
||||
oldDx, oldDy := -2.98, -50.0
|
||||
dx, dy := oldDx, oldDy
|
||||
if collision := toTestPlayerCollider.Check(oldDx, oldDy, "Barrier"); collision != nil {
|
||||
playerShape := toTestPlayerCollider.Shape.(*resolv.ConvexPolygon)
|
||||
barrierShape := collision.Objects[0].Shape.(*resolv.ConvexPolygon)
|
||||
if overlapped, pushbackX, pushbackY := CalcPushbacks(oldDx, oldDy, playerShape, barrierShape); overlapped {
|
||||
Logger.Info(fmt.Sprintf("Collided & overlapped: player.X=%v, player.Y=%v, oldDx=%v, oldDy=%v, playerShape=%v, toCheckBarrier=%v, pushbackX=%v, pushbackY=%v", toTestPlayerCollider.X, toTestPlayerCollider.Y, oldDx, oldDy, ConvexPolygonStr(playerShape), ConvexPolygonStr(barrierShape), pushbackX, pushbackY))
|
||||
dx -= pushbackX
|
||||
dy -= pushbackY
|
||||
} else {
|
||||
Logger.Info(fmt.Sprintf("Collider BUT not overlapped: player.X=%v, player.Y=%v, oldDx=%v, oldDy=%v, playerShape=%v, toCheckBarrier=%v", toTestPlayerCollider.X, toTestPlayerCollider.Y, oldDx, oldDy, ConvexPolygonStr(playerShape), ConvexPolygonStr(barrierShape)))
|
||||
}
|
||||
}
|
||||
|
||||
toTestPlayerCollider.X += dx
|
||||
toTestPlayerCollider.Y += dy
|
||||
toTestPlayerCollider.Update()
|
||||
}
|
||||
|
||||
return world
|
||||
}
|
||||
|
||||
func (world *WorldColliderDisplay) Update() {
|
||||
|
||||
}
|
||||
|
||||
func (world *WorldColliderDisplay) Draw(screen *ebiten.Image) {
|
||||
|
||||
for _, o := range world.Space.Objects() {
|
||||
if o.HasTags("Player") {
|
||||
drawColor := color.RGBA{0, 255, 0, 255}
|
||||
DrawPolygon(screen, o.Shape.(*resolv.ConvexPolygon), drawColor)
|
||||
} else {
|
||||
drawColor := color.RGBA{60, 60, 60, 255}
|
||||
DrawPolygon(screen, o.Shape.(*resolv.ConvexPolygon), drawColor)
|
||||
}
|
||||
}
|
||||
|
||||
world.Game.DebugDraw(screen, world.Space)
|
||||
|
||||
if world.Game.ShowHelpText {
|
||||
|
||||
world.Game.DrawText(screen, 16, 16,
|
||||
"~ Collider Display test ~",
|
||||
"F1: Toggle Debug View",
|
||||
"F2: Show / Hide help text",
|
||||
"R: Restart world",
|
||||
fmt.Sprintf("%d FPS (frames per second)", int(ebiten.CurrentFPS())),
|
||||
fmt.Sprintf("%d TPS (ticks per second)", int(ebiten.CurrentTPS())),
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
}
|
9
collider_visualizer/worldinterface.go
Normal file
@@ -0,0 +1,9 @@
|
||||
package main
|
||||
|
||||
import "github.com/hajimehoshi/ebiten/v2"
|
||||
|
||||
type WorldInterface interface {
|
||||
Init()
|
||||
Update()
|
||||
Draw(*ebiten.Image)
|
||||
}
|
51
dnmshared/geometry.go
Normal file
@@ -0,0 +1,51 @@
|
||||
package dnmshared
|
||||
|
||||
import (
|
||||
"math"
|
||||
)
|
||||
|
||||
// Use type `float64` for json unmarshalling of numbers.
|
||||
type Direction struct {
|
||||
Dx int32 `json:"dx,omitempty"`
|
||||
Dy int32 `json:"dy,omitempty"`
|
||||
}
|
||||
|
||||
type Vec2D struct {
|
||||
X float64 `json:"x,omitempty"`
|
||||
Y float64 `json:"y,omitempty"`
|
||||
}
|
||||
|
||||
func NormVec2D(dx, dy float64) Vec2D {
|
||||
return Vec2D{dy, -dx}
|
||||
}
|
||||
|
||||
type Polygon2D struct {
|
||||
Anchor *Vec2D `json:"-"` // This "Polygon2D.Anchor" is used to be assigned to "B2BodyDef.Position", which in turn is used as the position of the FIRST POINT of the polygon.
|
||||
Points []*Vec2D `json:"-"`
|
||||
|
||||
/*
|
||||
When used to represent a "polyline directly drawn in a `Tmx file`", we can initialize both "Anchor" and "Points" simultaneously.
|
||||
|
||||
Yet when used to represent a "polyline drawn in a `Tsx file`", we have to first initialize "Points w.r.t. center of the tile-rectangle", and then "Anchor(initially nil) of the tile positioned in the `Tmx file`".
|
||||
|
||||
Refer to https://shimo.im/docs/SmLJJhXm2C8XMzZT for more information.
|
||||
*/
|
||||
|
||||
/*
|
||||
[WARNING] Used to cache "`TileWidth & TileHeight` of a Tsx file" only.
|
||||
*/
|
||||
TileWidth int
|
||||
TileHeight int
|
||||
|
||||
/*
|
||||
[WARNING] Used to cache "`Width & TileHeight` of an object in Tmx file" only.
|
||||
*/
|
||||
TmxObjectWidth float64
|
||||
TmxObjectHeight float64
|
||||
}
|
||||
|
||||
func Distance(pt1 *Vec2D, pt2 *Vec2D) float64 {
|
||||
dx := pt1.X - pt2.X
|
||||
dy := pt1.Y - pt2.Y
|
||||
return math.Sqrt(dx*dx + dy*dy)
|
||||
}
|
3
dnmshared/go.mod
Normal file
@@ -0,0 +1,3 @@
|
||||
module tiled
|
||||
|
||||
go 1.19
|
@@ -1,4 +1,4 @@
|
||||
package common
|
||||
package dnmshared
|
||||
|
||||
import (
|
||||
"go.uber.org/zap"
|
||||
@@ -19,5 +19,7 @@ func init() {
|
||||
LoggerConfig.EncoderConfig.EncodeLevel = zapcore.CapitalColorLevelEncoder
|
||||
var err error
|
||||
Logger, err = LoggerConfig.Build()
|
||||
ErrFatal(err)
|
||||
if nil != err {
|
||||
panic(err)
|
||||
}
|
||||
}
|
220
dnmshared/resolv_helper.go
Normal file
@@ -0,0 +1,220 @@
|
||||
package dnmshared
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/kvartborg/vector"
|
||||
"github.com/solarlune/resolv"
|
||||
"math"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func ConvexPolygonStr(body *resolv.ConvexPolygon) string {
|
||||
var s []string = make([]string, len(body.Points))
|
||||
for i, p := range body.Points {
|
||||
s[i] = fmt.Sprintf("[%v, %v]", p[0]+body.X, p[1]+body.Y)
|
||||
}
|
||||
|
||||
return fmt.Sprintf("[%s]", strings.Join(s, ", "))
|
||||
}
|
||||
|
||||
func GenerateRectCollider(origX, origY, w, h, spaceOffsetX, spaceOffsetY float64, tag string) *resolv.Object {
|
||||
collider := resolv.NewObject(origX-w*0.5+spaceOffsetX, origY-h*0.5+spaceOffsetY, w, h, tag)
|
||||
shape := resolv.NewRectangle(0, 0, w, h)
|
||||
collider.SetShape(shape)
|
||||
return collider
|
||||
}
|
||||
|
||||
func GenerateConvexPolygonCollider(unalignedSrc *Polygon2D, spaceOffsetX, spaceOffsetY float64, tag string) *resolv.Object {
|
||||
aligned := AlignPolygon2DToBoundingBox(unalignedSrc)
|
||||
var w, h float64 = 0, 0
|
||||
|
||||
shape := resolv.NewConvexPolygon()
|
||||
for i, pi := range aligned.Points {
|
||||
for j, pj := range aligned.Points {
|
||||
if i == j {
|
||||
continue
|
||||
}
|
||||
if math.Abs(pj.X-pi.X) > w {
|
||||
w = math.Abs(pj.X - pi.X)
|
||||
}
|
||||
if math.Abs(pj.Y-pi.Y) > h {
|
||||
h = math.Abs(pj.Y - pi.Y)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for i := 0; i < len(aligned.Points); i++ {
|
||||
p := aligned.Points[i]
|
||||
shape.AddPoints(p.X, p.Y)
|
||||
}
|
||||
|
||||
collider := resolv.NewObject(aligned.Anchor.X+spaceOffsetX, aligned.Anchor.Y+spaceOffsetY, w, h, tag)
|
||||
collider.SetShape(shape)
|
||||
|
||||
return collider
|
||||
}
|
||||
|
||||
func CalcPushbacks(oldDx, oldDy float64, playerShape, barrierShape *resolv.ConvexPolygon) (bool, float64, float64) {
|
||||
origX, origY := playerShape.Position()
|
||||
defer func() {
|
||||
playerShape.SetPosition(origX, origY)
|
||||
}()
|
||||
playerShape.SetPosition(origX+oldDx, origY+oldDy)
|
||||
overlapResult := &SatResult{
|
||||
Overlap: 0,
|
||||
OverlapX: 0,
|
||||
OverlapY: 0,
|
||||
AContainedInB: true,
|
||||
BContainedInA: true,
|
||||
Axis: vector.Vector{0, 0},
|
||||
}
|
||||
if overlapped := IsPolygonPairOverlapped(playerShape, barrierShape, overlapResult); overlapped {
|
||||
pushbackX, pushbackY := overlapResult.Overlap*overlapResult.OverlapX, overlapResult.Overlap*overlapResult.OverlapY
|
||||
return true, pushbackX, pushbackY
|
||||
} else {
|
||||
return false, 0, 0
|
||||
}
|
||||
}
|
||||
|
||||
type SatResult struct {
|
||||
Overlap float64
|
||||
OverlapX float64
|
||||
OverlapY float64
|
||||
AContainedInB bool
|
||||
BContainedInA bool
|
||||
Axis vector.Vector
|
||||
}
|
||||
|
||||
func IsPolygonPairOverlapped(a, b *resolv.ConvexPolygon, result *SatResult) bool {
|
||||
aCnt, bCnt := len(a.Points), len(b.Points)
|
||||
// Single point case
|
||||
if 1 == aCnt && 1 == bCnt {
|
||||
if nil != result {
|
||||
result.Overlap = 0
|
||||
}
|
||||
return a.Points[0].X() == b.Points[0].X() && a.Points[0].Y() == b.Points[0].Y()
|
||||
}
|
||||
|
||||
if 1 < aCnt {
|
||||
for _, axis := range a.SATAxes() {
|
||||
if isPolygonPairSeparatedByDir(a, b, axis.Unit(), result) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if 1 < bCnt {
|
||||
for _, axis := range b.SATAxes() {
|
||||
if isPolygonPairSeparatedByDir(a, b, axis.Unit(), result) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func isPolygonPairSeparatedByDir(a, b *resolv.ConvexPolygon, e vector.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.
|
||||
|
||||
Consider the following example
|
||||
a: {
|
||||
anchor: [1337.19 1696.74]
|
||||
points: [[0 0] [24 0] [24 24] [0 24]]
|
||||
},
|
||||
b: {
|
||||
anchor: [1277.72 1570.56]
|
||||
points: [[642.57 319.16] [0 319.16] [5.73 0] [643.75 0.90]]
|
||||
}
|
||||
|
||||
e = (-2.98, 1.49).Unit()
|
||||
*/
|
||||
|
||||
var aStart, aEnd, bStart, bEnd float64 = math.MaxFloat64, -math.MaxFloat64, math.MaxFloat64, -math.MaxFloat64
|
||||
for _, p := range a.Points {
|
||||
dot := (p.X()+a.X)*e.X() + (p.Y()+a.Y)*e.Y()
|
||||
|
||||
if aStart > dot {
|
||||
aStart = dot
|
||||
}
|
||||
|
||||
if aEnd < dot {
|
||||
aEnd = dot
|
||||
}
|
||||
}
|
||||
|
||||
for _, p := range b.Points {
|
||||
dot := (p.X()+b.X)*e.X() + (p.Y()+b.Y)*e.Y()
|
||||
|
||||
if bStart > dot {
|
||||
bStart = dot
|
||||
}
|
||||
|
||||
if bEnd < dot {
|
||||
bEnd = dot
|
||||
}
|
||||
}
|
||||
|
||||
if aStart > bEnd || aEnd < bStart {
|
||||
// Separated by unit vector "e"
|
||||
return true
|
||||
}
|
||||
|
||||
if nil != result {
|
||||
result.Axis = e
|
||||
overlap := float64(0)
|
||||
|
||||
if aStart < bStart {
|
||||
result.AContainedInB = false
|
||||
|
||||
if aEnd < bEnd {
|
||||
overlap = aEnd - bStart
|
||||
result.BContainedInA = false
|
||||
} else {
|
||||
option1 := aEnd - bStart
|
||||
option2 := bEnd - aStart
|
||||
if option1 < option2 {
|
||||
overlap = option1
|
||||
} else {
|
||||
overlap = -option2
|
||||
}
|
||||
}
|
||||
} else {
|
||||
result.BContainedInA = false
|
||||
|
||||
if aEnd > bEnd {
|
||||
overlap = aStart - bEnd
|
||||
result.AContainedInB = false
|
||||
} else {
|
||||
option1 := aEnd - bStart
|
||||
option2 := bEnd - aStart
|
||||
if option1 < option2 {
|
||||
overlap = option1
|
||||
} else {
|
||||
overlap = -option2
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
currentOverlap := result.Overlap
|
||||
absoluteOverlap := overlap
|
||||
if overlap < 0 {
|
||||
absoluteOverlap = -overlap
|
||||
}
|
||||
|
||||
if 0 == currentOverlap || currentOverlap > absoluteOverlap {
|
||||
var sign float64 = 1
|
||||
if overlap < 0 {
|
||||
sign = -1
|
||||
}
|
||||
|
||||
result.Overlap = absoluteOverlap
|
||||
result.OverlapX = e.X() * sign
|
||||
result.OverlapY = e.Y() * sign
|
||||
}
|
||||
}
|
||||
|
||||
// the specified unit vector "e" doesn't separate "a" and "b", overlap result is generated
|
||||
return false
|
||||
}
|
@@ -1,4 +1,4 @@
|
||||
package models
|
||||
package dnmshared
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
@@ -9,7 +9,6 @@ import (
|
||||
"go.uber.org/zap"
|
||||
"io/ioutil"
|
||||
"math"
|
||||
. "server/common"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
@@ -176,8 +175,8 @@ func (l *TmxLayer) decodeBase64() ([]uint32, error) {
|
||||
|
||||
type Vec2DList []*Vec2D
|
||||
type Polygon2DList []*Polygon2D
|
||||
type StrToVec2DListMap map[string]*Vec2DList // Note that it's deliberately NOT using "map[string]Vec2DList", for the easy of passing return value to "models/room.go".
|
||||
type StrToPolygon2DListMap map[string]*Polygon2DList // Note that it's deliberately NOT using "map[string]Polygon2DList", for the easy of passing return value to "models/room.go".
|
||||
type StrToVec2DListMap map[string]*Vec2DList
|
||||
type StrToPolygon2DListMap map[string]*Polygon2DList
|
||||
|
||||
func tmxPolylineToPolygon2D(pTmxMapIns *TmxMap, singleObjInTmxFile *TmxOrTsxObject, targetPolyline *TmxOrTsxPolyline) (*Polygon2D, error) {
|
||||
if nil == targetPolyline {
|
||||
@@ -443,3 +442,40 @@ func (pTmxMapIns *TmxMap) continuousObjLayerOffsetToContinuousMapNodePos(continu
|
||||
|
||||
return toRet
|
||||
}
|
||||
|
||||
func AlignPolygon2DToBoundingBox(input *Polygon2D) *Polygon2D {
|
||||
// Transform again to put "anchor" at the top-left point of the bounding box for "resolv"
|
||||
float64Max := float64(99999999999999.9)
|
||||
boundingBoxTL := &Vec2D{
|
||||
X: float64Max,
|
||||
Y: float64Max,
|
||||
}
|
||||
for _, p := range input.Points {
|
||||
if p.X < boundingBoxTL.X {
|
||||
boundingBoxTL.X = p.X
|
||||
}
|
||||
if p.Y < boundingBoxTL.Y {
|
||||
boundingBoxTL.Y = p.Y
|
||||
}
|
||||
}
|
||||
|
||||
// Now "input.Anchor" should move to "input.Anchor+boundingBoxTL", thus "boundingBoxTL" is also the value of the negative diff for all "input.Points"
|
||||
output := &Polygon2D{
|
||||
Anchor: &Vec2D{
|
||||
X: input.Anchor.X + boundingBoxTL.X,
|
||||
Y: input.Anchor.Y + boundingBoxTL.Y,
|
||||
},
|
||||
Points: make([]*Vec2D, len(input.Points)),
|
||||
TileWidth: input.TileWidth,
|
||||
TileHeight: input.TileHeight,
|
||||
}
|
||||
|
||||
for i, p := range input.Points {
|
||||
output.Points[i] = &Vec2D{
|
||||
X: p.X - boundingBoxTL.X,
|
||||
Y: p.Y - boundingBoxTL.Y,
|
||||
}
|
||||
}
|
||||
|
||||
return output
|
||||
}
|
@@ -1,5 +0,0 @@
|
||||
{
|
||||
"ver": "2.0.0",
|
||||
"uuid": "51b3303a-7c55-4f8b-b6b9-b5efb6164d19",
|
||||
"subMetas": {}
|
||||
}
|
@@ -1,5 +0,0 @@
|
||||
{
|
||||
"ver": "2.0.0",
|
||||
"uuid": "8347ba4a-e73c-4173-a9ba-f7711fae5a90",
|
||||
"subMetas": {}
|
||||
}
|
@@ -1,5 +0,0 @@
|
||||
{
|
||||
"ver": "2.0.0",
|
||||
"uuid": "05720598-8487-406c-b2f3-2059240fde56",
|
||||
"subMetas": {}
|
||||
}
|
@@ -1,5 +0,0 @@
|
||||
{
|
||||
"ver": "2.0.2",
|
||||
"uuid": "4e2296fe-8855-4fb4-a407-fea295ded82e",
|
||||
"subMetas": {}
|
||||
}
|
@@ -1,5 +0,0 @@
|
||||
{
|
||||
"ver": "2.0.0",
|
||||
"uuid": "da664a14-58c3-4f57-8aca-1270f96bf3ee",
|
||||
"subMetas": {}
|
||||
}
|
@@ -1,5 +0,0 @@
|
||||
{
|
||||
"ver": "2.0.0",
|
||||
"uuid": "59b65107-0da7-47b3-a08d-7de824dd5a39",
|
||||
"subMetas": {}
|
||||
}
|
@@ -1,335 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<map version="1.2" tiledversion="1.2.3" orientation="isometric" renderorder="right-down" width="50" height="50" tilewidth="64" tileheight="64" infinite="0" nextlayerid="11" nextobjectid="213">
|
||||
<tileset firstgid="1" source="Tile_W64_H64_S01.tsx"/>
|
||||
<tileset firstgid="17" source="Tile_W300_H300_S01.tsx"/>
|
||||
<layer id="1" name="GroundFloor" width="50" height="50">
|
||||
<data encoding="base64" compression="zlib">
|
||||
eJztz0ENACAMALGR4F8zNspyjwronZm7xPlcD0sPSw9LD0sPSw9LD0sPSw9LD0sPSw9LD0sPSw9LD0sPSw9LD0sPSw9LD0sPy7bHBg/ldQwR
|
||||
</data>
|
||||
</layer>
|
||||
<objectgroup id="2" name="PlayerStartingPos">
|
||||
<object id="135" x="320" y="2884">
|
||||
<point/>
|
||||
</object>
|
||||
<object id="137" x="2876" y="320">
|
||||
<point/>
|
||||
</object>
|
||||
</objectgroup>
|
||||
<layer id="3" name="FirsrtFloor" width="50" height="50">
|
||||
<data encoding="base64" compression="zlib">
|
||||
eJztWctuBCEMW7Vqt9v2/7+32gMSQnnYTmB6WB+ZwZmEkHHgdnuBxe8/5WLwcyHXuzH2ccAuw5Wty3j/bjyzxlC7M9iYrFxZfNbnqi/IOqAxqfow8AWOoXZmZL58k9xvzrg1L+JS9oO6LijfCR882yvWdUH5rG+KuBgfrFo42+7CJ/m+l5MWoloYjZ+CUsN2+OLVc0YDRPa9nNzhC7LPs//Xo8FuNs5wRvt2Rw7v8AXZ5zty2FvL3Xsf4e+qsVf60l1jq754MR2w8qFSY6MaqdSRJ7KYRnNWIL509iseZ4de93TyHZirwOOM1lXtC6JnSg+K2FPnVHSysr9P+4Dq8a5+Wp2jcHq5FPWgFXuZXu/sqxCuHX1cR+1BtN4A0y96/ycldiu8XOquxWhNOZ1LDFA+RCdn/4OOeFjw9nLl/5TVUPZ8YIX3bSd6z26w33zKl0xzM/xd2hvhnKFo7ox/h/ZmtOcpXzp1q6K5PXjfjPSAKJcF9jwXQdd9B8q1E8pZYUW3zlBqVYSOPRatm1XjKrUqQsUXties1qqs9kd8im5l7ovQnOzYr0wuWc+YOz7kvcq6ILkU9ZOqhmfvdj17M6rn3ayGV30YUM8qB6qxeIK9n96FaixmXOVDJ3bomRc4/AGscghn
|
||||
</data>
|
||||
</layer>
|
||||
<objectgroup id="7" name="HighScoreTreasure">
|
||||
<object id="172" gid="16" x="1736" y="708" width="64" height="64"/>
|
||||
<object id="173" gid="16" x="2284" y="768" width="64" height="64"/>
|
||||
<object id="170" gid="16" x="916" y="1608" width="64" height="64"/>
|
||||
<object id="171" gid="16" x="1166" y="2674" width="64" height="64"/>
|
||||
<object id="199" gid="16" x="2536.36" y="2533.7" width="64" height="64"/>
|
||||
<object id="200" gid="16" x="2812.12" y="3045.82" width="64" height="64"/>
|
||||
<object id="201" gid="16" x="3033.33" y="2824.61" width="64" height="64"/>
|
||||
<object id="202" gid="16" x="2093.94" y="1467.03" width="64" height="64"/>
|
||||
<object id="203" gid="16" x="654.545" y="664" width="64" height="64"/>
|
||||
<object id="204" gid="16" x="172.727" y="376.121" width="64" height="64"/>
|
||||
<object id="205" gid="16" x="360.606" y="176.121" width="64" height="64"/>
|
||||
</objectgroup>
|
||||
<objectgroup id="4" name="Barrier">
|
||||
<properties>
|
||||
<property name="type" value="barrier_and_shelter"/>
|
||||
</properties>
|
||||
<object id="1" x="234" y="730">
|
||||
<properties>
|
||||
<property name="boundary_type" value="barrier"/>
|
||||
</properties>
|
||||
<polyline points="0,0 -74,78 178,330 250,258"/>
|
||||
</object>
|
||||
<object id="2" x="804" y="156">
|
||||
<properties>
|
||||
<property name="boundary_type" value="barrier"/>
|
||||
</properties>
|
||||
<polyline points="0,0 -74,78 178,330 250,258"/>
|
||||
</object>
|
||||
<object id="3" x="230" y="410">
|
||||
<properties>
|
||||
<property name="boundary_type" value="barrier"/>
|
||||
</properties>
|
||||
<polyline points="250,-258 -74,78 178,330 504,0"/>
|
||||
</object>
|
||||
<object id="4" x="2470" y="2650">
|
||||
<properties>
|
||||
<property name="boundary_type" value="barrier"/>
|
||||
</properties>
|
||||
<polyline points="250,-258 -74,78 178,330 504,0"/>
|
||||
</object>
|
||||
<object id="5" x="1082.23" y="1537.08">
|
||||
<properties>
|
||||
<property name="boundary_type" value="barrier"/>
|
||||
</properties>
|
||||
<polyline points="548.339,-547.082 -94.2284,95.4898 230.657,408.918 867.772,-230"/>
|
||||
</object>
|
||||
<object id="6" x="1188" y="604">
|
||||
<properties>
|
||||
<property name="boundary_type" value="barrier"/>
|
||||
</properties>
|
||||
<polyline points="0,0 -74,78 178,330 250,258"/>
|
||||
</object>
|
||||
<object id="7" x="889.741" y="770">
|
||||
<properties>
|
||||
<property name="boundary_type" value="barrier"/>
|
||||
</properties>
|
||||
<polyline points="-26,22 -93.7407,98.1818 283.593,478 358.259,416.909"/>
|
||||
</object>
|
||||
<object id="8" x="691.741" y="1088">
|
||||
<properties>
|
||||
<property name="boundary_type" value="barrier"/>
|
||||
</properties>
|
||||
<polyline points="-18,30 -93.7407,98.1818 169.593,356 238.259,288.909"/>
|
||||
</object>
|
||||
<object id="9" x="311.741" y="1916">
|
||||
<properties>
|
||||
<property name="boundary_type" value="barrier"/>
|
||||
</properties>
|
||||
<polyline points="-22,30 -96.4077,103.515 867.593,1062 938.259,992.909"/>
|
||||
</object>
|
||||
<object id="10" x="629.741" y="1854">
|
||||
<properties>
|
||||
<property name="boundary_type" value="barrier"/>
|
||||
</properties>
|
||||
<polyline points="-22,30 -93.7407,98.1818 361.593,548 430.259,480.909"/>
|
||||
</object>
|
||||
<object id="11" x="1015.74" y="1852">
|
||||
<properties>
|
||||
<property name="boundary_type" value="barrier"/>
|
||||
</properties>
|
||||
<polyline points="-26,26 -93.7407,98.1818 329.593,512 396.259,450.909"/>
|
||||
</object>
|
||||
<object id="12" x="1973.74" y="514">
|
||||
<properties>
|
||||
<property name="boundary_type" value="barrier"/>
|
||||
</properties>
|
||||
<polyline points="-26,26 -93.7407,98.1818 355.593,538 424.259,474.909"/>
|
||||
</object>
|
||||
<object id="13" x="2041.74" y="194">
|
||||
<properties>
|
||||
<property name="boundary_type" value="barrier"/>
|
||||
</properties>
|
||||
<polyline points="-26,26 -93.7407,98.1818 865.593,1048 934.259,992.909"/>
|
||||
</object>
|
||||
<object id="14" x="1975.74" y="896">
|
||||
<properties>
|
||||
<property name="boundary_type" value="barrier"/>
|
||||
</properties>
|
||||
<polyline points="-26,26 -93.7407,98.1818 317.593,508 382.259,440.909"/>
|
||||
</object>
|
||||
<object id="15" x="1917.74" y="1798">
|
||||
<properties>
|
||||
<property name="boundary_type" value="barrier"/>
|
||||
</properties>
|
||||
<polyline points="-26,26 -93.7407,98.1818 285.593,472 352.259,402.909"/>
|
||||
</object>
|
||||
<object id="16" x="1399.74" y="2564">
|
||||
<properties>
|
||||
<property name="boundary_type" value="barrier"/>
|
||||
</properties>
|
||||
<polyline points="-26,26 -93.7407,98.1818 161.593,348 228.259,278.909"/>
|
||||
</object>
|
||||
<object id="17" x="1595.74" y="2372">
|
||||
<properties>
|
||||
<property name="boundary_type" value="barrier"/>
|
||||
</properties>
|
||||
<polyline points="-26,26 -93.7407,98.1818 161.593,348 226.259,280.909"/>
|
||||
</object>
|
||||
<object id="18" x="1791.74" y="2184">
|
||||
<properties>
|
||||
<property name="boundary_type" value="barrier"/>
|
||||
</properties>
|
||||
<polyline points="-26,26 -93.7407,98.1818 161.593,348 226.259,280.909"/>
|
||||
</object>
|
||||
<object id="19" x="2301.74" y="1670">
|
||||
<properties>
|
||||
<property name="boundary_type" value="barrier"/>
|
||||
</properties>
|
||||
<polyline points="-26,26 -93.7407,98.1818 161.593,348 226.259,280.909"/>
|
||||
</object>
|
||||
<object id="20" x="2489.74" y="1478">
|
||||
<properties>
|
||||
<property name="boundary_type" value="barrier"/>
|
||||
</properties>
|
||||
<polyline points="-26,26 -93.7407,98.1818 161.593,348 226.259,280.909"/>
|
||||
</object>
|
||||
<object id="21" x="2683.74" y="1284">
|
||||
<properties>
|
||||
<property name="boundary_type" value="barrier"/>
|
||||
</properties>
|
||||
<polyline points="-26,26 -93.7407,98.1818 161.593,348 226.259,280.909"/>
|
||||
</object>
|
||||
<object id="22" x="2109.74" y="2690">
|
||||
<properties>
|
||||
<property name="boundary_type" value="barrier"/>
|
||||
</properties>
|
||||
<polyline points="-26,26 -93.7407,98.1818 161.593,348 226.259,280.909"/>
|
||||
</object>
|
||||
<object id="23" x="2809.74" y="1986">
|
||||
<properties>
|
||||
<property name="boundary_type" value="barrier"/>
|
||||
</properties>
|
||||
<polyline points="-26,26 -93.7407,98.1818 161.593,348 226.259,280.909"/>
|
||||
</object>
|
||||
<object id="41" x="1069.7" y="415.152">
|
||||
<properties>
|
||||
<property name="boundary_type" value="barrier"/>
|
||||
</properties>
|
||||
<polyline points="0,0 -66.6667,-72.7273 -330.303,196.97 -266.667,260.606"/>
|
||||
</object>
|
||||
<object id="42" x="684.848" y="793.939">
|
||||
<properties>
|
||||
<property name="boundary_type" value="barrier"/>
|
||||
</properties>
|
||||
<polyline points="0,0 -66.6667,-72.7273 -330.303,196.97 -266.667,260.606"/>
|
||||
</object>
|
||||
<object id="43" x="360.606" y="1560.61">
|
||||
<properties>
|
||||
<property name="boundary_type" value="barrier"/>
|
||||
</properties>
|
||||
<polyline points="381.818,-375.758 309.091,-442.424 -330.303,196.97 -266.667,260.606"/>
|
||||
</object>
|
||||
<object id="44" x="1445.45" y="475.758">
|
||||
<properties>
|
||||
<property name="boundary_type" value="barrier"/>
|
||||
</properties>
|
||||
<polyline points="381.818,-375.758 309.091,-442.424 -330.303,196.97 -266.667,260.606"/>
|
||||
</object>
|
||||
<object id="45" x="354.545" y="2778.79">
|
||||
<properties>
|
||||
<property name="boundary_type" value="barrier"/>
|
||||
<property name="debug_mark" value="1"/>
|
||||
</properties>
|
||||
<polyline points="123.031,-135.636 67.6364,-192.909 -323.636,198.303 -258.667,265.939"/>
|
||||
</object>
|
||||
<object id="46" x="481.818" y="2906.06">
|
||||
<properties>
|
||||
<property name="boundary_type" value="barrier"/>
|
||||
</properties>
|
||||
<polyline points="136.364,-130.303 63.6364,-190.909 -330.636,202.637 -266.667,260.606"/>
|
||||
</object>
|
||||
<object id="47" x="2915.15" y="224.242">
|
||||
<properties>
|
||||
<property name="boundary_type" value="barrier"/>
|
||||
</properties>
|
||||
<polyline points="136.364,-130.303 63.6364,-190.909 -330.303,196.97 -266.667,260.606"/>
|
||||
</object>
|
||||
<object id="48" x="3048.48" y="351.515">
|
||||
<properties>
|
||||
<property name="boundary_type" value="barrier"/>
|
||||
</properties>
|
||||
<polyline points="136.364,-130.303 63.6364,-190.909 -330.303,196.97 -266.667,260.606"/>
|
||||
</object>
|
||||
<object id="49" x="869.697" y="1754.55">
|
||||
<properties>
|
||||
<property name="boundary_type" value="barrier"/>
|
||||
</properties>
|
||||
<polyline points="-3.0303,-3.0303 -66.6667,-66.6667 -330.303,204.97 -258.667,273.939"/>
|
||||
</object>
|
||||
<object id="50" x="2021.21" y="609.091">
|
||||
<properties>
|
||||
<property name="boundary_type" value="barrier"/>
|
||||
</properties>
|
||||
<polyline points="-3.0303,-3.0303 -66.6667,-66.6667 -330.303,196.97 -266.667,260.606"/>
|
||||
</object>
|
||||
<object id="51" x="2406.06" y="1309.09">
|
||||
<properties>
|
||||
<property name="boundary_type" value="barrier"/>
|
||||
</properties>
|
||||
<polyline points="118.182,-124.242 57.5758,-184.848 -330.303,196.97 -266.667,260.606"/>
|
||||
</object>
|
||||
<object id="52" x="1454.55" y="2266.67">
|
||||
<properties>
|
||||
<property name="boundary_type" value="barrier"/>
|
||||
</properties>
|
||||
<polyline points="118.182,-124.242 57.5758,-184.848 -330.303,196.97 -266.667,260.606"/>
|
||||
</object>
|
||||
<object id="53" x="1818.18" y="2648.48">
|
||||
<properties>
|
||||
<property name="boundary_type" value="barrier"/>
|
||||
</properties>
|
||||
<polyline points="200,-193.939 133.333,-260.606 -330.303,196.97 -266.667,260.606"/>
|
||||
</object>
|
||||
<object id="54" x="2718.18" y="1754.55">
|
||||
<properties>
|
||||
<property name="boundary_type" value="barrier"/>
|
||||
</properties>
|
||||
<polyline points="200,-193.939 133.333,-260.606 -330.303,196.97 -266.667,260.606"/>
|
||||
</object>
|
||||
<object id="55" x="2342.42" y="2596.97">
|
||||
<properties>
|
||||
<property name="boundary_type" value="barrier"/>
|
||||
</properties>
|
||||
<polyline points="60.6061,-72.7273 3.0303,-136.364 -330.303,196.97 -266.667,260.606"/>
|
||||
</object>
|
||||
<object id="56" x="2793.94" y="2151.52">
|
||||
<properties>
|
||||
<property name="boundary_type" value="barrier"/>
|
||||
</properties>
|
||||
<polyline points="60.6061,-72.7273 3.0303,-136.364 -330.303,196.97 -266.667,260.606"/>
|
||||
</object>
|
||||
<object id="57" x="69.697" y="57.5758">
|
||||
<properties>
|
||||
<property name="boundary_type" value="barrier"/>
|
||||
</properties>
|
||||
<polyline points="0,0 -78.7879,-1.27898e-13 -66.6667,3121.21 1.13687e-13,3121.21"/>
|
||||
</object>
|
||||
<object id="59" x="3200" y="66.6667">
|
||||
<properties>
|
||||
<property name="boundary_type" value="barrier"/>
|
||||
</properties>
|
||||
<polyline points="0,0 -6.06061,-78.7879 -3215.15,-81.8182 -3221.21,9.09091"/>
|
||||
</object>
|
||||
<object id="60" x="3203.03" y="3221.21">
|
||||
<properties>
|
||||
<property name="boundary_type" value="barrier"/>
|
||||
</properties>
|
||||
<polyline points="0,0 -6.06061,-78.7879 -3215.15,-81.8182 -3221.21,9.09091"/>
|
||||
</object>
|
||||
<object id="61" x="3209.09" y="27.2727">
|
||||
<properties>
|
||||
<property name="boundary_type" value="barrier"/>
|
||||
</properties>
|
||||
<polyline points="0,0 -78.7879,-1.27898e-13 -66.6667,3121.21 1.13687e-13,3121.21"/>
|
||||
</object>
|
||||
</objectgroup>
|
||||
<objectgroup id="5" name="LowScoreTreasure">
|
||||
<object id="165" gid="13" x="1520" y="204" width="64" height="64" visible="0"/>
|
||||
<object id="166" gid="13" x="1372" y="352" width="64" height="64" visible="0"/>
|
||||
<object id="167" gid="13" x="1184" y="524" width="64" height="64" visible="0"/>
|
||||
<object id="168" gid="13" x="544" y="1184" width="64" height="64" visible="0"/>
|
||||
<object id="169" gid="13" x="294" y="1442" width="64" height="64" visible="0"/>
|
||||
<object id="174" gid="16" x="2750" y="1234" width="64" height="64" visible="0"/>
|
||||
<object id="175" gid="13" x="1562" y="1990" width="64" height="64" visible="0"/>
|
||||
<object id="176" gid="13" x="1846" y="1718" width="64" height="64" visible="0"/>
|
||||
<object id="177" gid="13" x="906" y="2438" width="64" height="64" visible="0"/>
|
||||
<object id="178" gid="13" x="638" y="2186" width="64" height="64" visible="0"/>
|
||||
<object id="179" gid="13" x="378" y="1878" width="64" height="64" visible="0"/>
|
||||
<object id="180" gid="13" x="580" y="1672" width="64" height="64" visible="0"/>
|
||||
<object id="181" gid="13" x="1518" y="634" width="64" height="64" visible="0"/>
|
||||
<object id="182" gid="13" x="1818" y="410" width="64" height="64" visible="0"/>
|
||||
<object id="183" gid="13" x="2308" y="360" width="64" height="64" visible="0"/>
|
||||
<object id="184" gid="13" x="2524" y="576" width="64" height="64" visible="0"/>
|
||||
<object id="186" gid="13" x="2726" y="790" width="64" height="64" visible="0"/>
|
||||
<object id="187" gid="13" x="2928" y="972" width="64" height="64" visible="0"/>
|
||||
<object id="192" gid="13" x="1484.85" y="3064" width="64" height="64" visible="0"/>
|
||||
<object id="193" gid="13" x="1972.73" y="3048.85" width="64" height="64" visible="0"/>
|
||||
<object id="194" gid="13" x="2006.06" y="2664" width="64" height="64" visible="0"/>
|
||||
<object id="195" gid="13" x="312.121" y="2291.27" width="64" height="64" visible="0"/>
|
||||
<object id="196" gid="13" x="503.03" y="2488.24" width="64" height="64" visible="0"/>
|
||||
<object id="197" gid="13" x="606.061" y="3076.12" width="64" height="64" visible="0"/>
|
||||
<object id="198" gid="13" x="833.333" y="2842.79" width="64" height="64" visible="0"/>
|
||||
<object id="206" gid="13" x="2612.12" y="2064" width="64" height="64" visible="0"/>
|
||||
<object id="207" gid="13" x="3030.3" y="1985.21" width="64" height="64" visible="0"/>
|
||||
</objectgroup>
|
||||
<objectgroup id="6" name="GuardTower">
|
||||
<object id="188" gid="17" x="1429.33" y="1781.33" width="300" height="300" visible="0"/>
|
||||
<object id="210" gid="17" x="1784.67" y="1414" width="300" height="300"/>
|
||||
<object id="211" gid="17" x="2786" y="2783.33" width="300" height="300"/>
|
||||
<object id="212" gid="17" x="532.667" y="543.333" width="300" height="300"/>
|
||||
</objectgroup>
|
||||
</map>
|
@@ -1,5 +0,0 @@
|
||||
{
|
||||
"ver": "2.0.2",
|
||||
"uuid": "7fd0b77d-0736-4e00-89eb-7111f07ed4f1",
|
||||
"subMetas": {}
|
||||
}
|
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<map version="1.2" tiledversion="1.2.3" orientation="isometric" renderorder="right-down" width="50" height="50" tilewidth="64" tileheight="64" infinite="0" nextlayerid="11" nextobjectid="213">
|
||||
<map version="1.2" tiledversion="1.2.3" orientation="isometric" renderorder="right-down" width="50" height="50" tilewidth="64" tileheight="64" infinite="0" nextlayerid="11" nextobjectid="218">
|
||||
<tileset firstgid="1" source="Tile_W64_H64_S01.tsx"/>
|
||||
<tileset firstgid="17" source="Tile_W300_H300_S01.tsx"/>
|
||||
<layer id="1" name="GroundFloor" width="50" height="50" locked="1">
|
||||
@@ -33,7 +33,7 @@
|
||||
<object id="204" gid="16" x="172.727" y="376.121" width="64" height="64"/>
|
||||
<object id="205" gid="16" x="360.606" y="176.121" width="64" height="64"/>
|
||||
</objectgroup>
|
||||
<objectgroup id="4" name="Barrier" locked="1">
|
||||
<objectgroup id="4" name="Barrier">
|
||||
<properties>
|
||||
<property name="type" value="barrier_and_shelter"/>
|
||||
</properties>
|
||||
@@ -271,29 +271,29 @@
|
||||
</properties>
|
||||
<polyline points="60.6061,-72.7273 3.0303,-136.364 -330.303,196.97 -266.667,260.606"/>
|
||||
</object>
|
||||
<object id="57" x="69.697" y="57.5758">
|
||||
<object id="213" x="1854.55" y="-1351.52">
|
||||
<properties>
|
||||
<property name="boundary_type" value="barrier"/>
|
||||
</properties>
|
||||
<polyline points="0,0 -78.7879,-1.27898e-13 -66.6667,3121.21 1.13687e-13,3121.21"/>
|
||||
<polyline points="0,0 -3190.91,3215.15 -3115.15,3290.91 48.4848,54.5455"/>
|
||||
</object>
|
||||
<object id="59" x="3200" y="66.6667">
|
||||
<object id="214" x="-572.727" y="1257.58">
|
||||
<properties>
|
||||
<property name="boundary_type" value="barrier"/>
|
||||
</properties>
|
||||
<polyline points="0,0 -6.06061,-78.7879 -3215.15,-81.8182 -3221.21,9.09091"/>
|
||||
<polyline points="0,0 2575.76,2624.24 2472.73,2727.27 -136.364,112.121"/>
|
||||
</object>
|
||||
<object id="60" x="3203.03" y="3221.21">
|
||||
<object id="216" x="1190.91" y="-584.848">
|
||||
<properties>
|
||||
<property name="boundary_type" value="barrier"/>
|
||||
</properties>
|
||||
<polyline points="0,0 -6.06061,-78.7879 -3215.15,-81.8182 -3221.21,9.09091"/>
|
||||
<polyline points="0,0 2657.58,2627.27 2818.18,2466.67 172.727,-166.667"/>
|
||||
</object>
|
||||
<object id="61" x="3209.09" y="27.2727">
|
||||
<object id="217" x="1887.88" y="3748.48">
|
||||
<properties>
|
||||
<property name="boundary_type" value="barrier"/>
|
||||
</properties>
|
||||
<polyline points="0,0 -78.7879,-1.27898e-13 -66.6667,3121.21 1.13687e-13,3121.21"/>
|
||||
<polyline points="0,0 221.212,227.273 2087.88,-1627.27 1842.42,-1872.73"/>
|
||||
</object>
|
||||
</objectgroup>
|
||||
<objectgroup id="5" name="LowScoreTreasure">
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"ver": "1.0.1",
|
||||
"uuid": "33d33d2f-5ca7-4677-9c82-4ced71aa0f8a",
|
||||
"uuid": "6955a517-3fb6-4777-b8b0-74dbd76f18e4",
|
||||
"isSubpackage": false,
|
||||
"subpackageName": "",
|
||||
"subMetas": {}
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"ver": "1.0.1",
|
||||
"uuid": "f9460fe9-26ad-4e4b-8a3c-c97bef705a71",
|
||||
"uuid": "51c54820-d753-4be8-a855-5760eed8f7ef",
|
||||
"isSubpackage": false,
|
||||
"subpackageName": "",
|
||||
"subMetas": {}
|
Before Width: | Height: | Size: 96 KiB After Width: | Height: | Size: 96 KiB |
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"ver": "2.3.3",
|
||||
"uuid": "b711d3f8-b9f4-41ab-a7e4-6562992fb65e",
|
||||
"uuid": "136d09e9-c33c-45dc-abb7-e367d730c814",
|
||||
"type": "sprite",
|
||||
"wrapMode": "clamp",
|
||||
"filterMode": "bilinear",
|
||||
@@ -11,8 +11,8 @@
|
||||
"subMetas": {
|
||||
"Tile_W256_H128_S01": {
|
||||
"ver": "1.0.4",
|
||||
"uuid": "2d6c9481-6bd5-4c19-b468-529d027226c3",
|
||||
"rawTextureUuid": "b711d3f8-b9f4-41ab-a7e4-6562992fb65e",
|
||||
"uuid": "7acc48f5-d9c9-4438-8794-57a85590bd97",
|
||||
"rawTextureUuid": "136d09e9-c33c-45dc-abb7-e367d730c814",
|
||||
"trimType": "auto",
|
||||
"trimThreshold": 1,
|
||||
"rotated": false,
|
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"ver": "2.0.0",
|
||||
"uuid": "df775ad6-885e-411b-8b2a-f4bcf70b4fbf",
|
||||
"subMetas": {}
|
||||
}
|
Before Width: | Height: | Size: 229 KiB After Width: | Height: | Size: 229 KiB |
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"ver": "2.3.3",
|
||||
"uuid": "757f31be-7ad1-42dc-bd6b-2b4c7652e457",
|
||||
"uuid": "d8e6c175-1f17-48df-a0aa-cdd9785f4d3a",
|
||||
"type": "sprite",
|
||||
"wrapMode": "clamp",
|
||||
"filterMode": "bilinear",
|
||||
@@ -11,8 +11,8 @@
|
||||
"subMetas": {
|
||||
"Tile_W256_H256_S01": {
|
||||
"ver": "1.0.4",
|
||||
"uuid": "0d9aafd3-d738-473c-95b8-bf577b78f03d",
|
||||
"rawTextureUuid": "757f31be-7ad1-42dc-bd6b-2b4c7652e457",
|
||||
"uuid": "4a23290b-bf5a-4849-ac19-6ebd4b7daa59",
|
||||
"rawTextureUuid": "d8e6c175-1f17-48df-a0aa-cdd9785f4d3a",
|
||||
"trimType": "auto",
|
||||
"trimThreshold": 1,
|
||||
"rotated": false,
|
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"ver": "2.0.0",
|
||||
"uuid": "81508f64-031d-4d00-9aa0-8e9841907d0a",
|
||||
"subMetas": {}
|
||||
}
|
Before Width: | Height: | Size: 52 KiB After Width: | Height: | Size: 52 KiB |
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"ver": "2.3.3",
|
||||
"uuid": "2385ca17-af24-4122-a271-785f3010d7f2",
|
||||
"uuid": "74245e28-6cec-4960-ac41-5b482ad8fd13",
|
||||
"type": "sprite",
|
||||
"wrapMode": "clamp",
|
||||
"filterMode": "bilinear",
|
||||
@@ -11,8 +11,8 @@
|
||||
"subMetas": {
|
||||
"Tile_W256_H256_S02": {
|
||||
"ver": "1.0.4",
|
||||
"uuid": "34e3f356-e65d-4745-8f70-7706aa4083f8",
|
||||
"rawTextureUuid": "2385ca17-af24-4122-a271-785f3010d7f2",
|
||||
"uuid": "8fc46c1f-6fb4-4290-99f3-b773b92312b7",
|
||||
"rawTextureUuid": "74245e28-6cec-4960-ac41-5b482ad8fd13",
|
||||
"trimType": "auto",
|
||||
"trimThreshold": 1,
|
||||
"rotated": false,
|
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"ver": "2.0.0",
|
||||
"uuid": "4e822a8b-f3be-4b83-b61d-9e04c56c5eba",
|
||||
"subMetas": {}
|
||||
}
|
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"ver": "2.0.2",
|
||||
"uuid": "a9a02975-8df5-42a1-bc25-b0ff7c1c03ba",
|
||||
"subMetas": {}
|
||||
}
|
Before Width: | Height: | Size: 45 KiB After Width: | Height: | Size: 45 KiB |
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"ver": "2.3.3",
|
||||
"uuid": "0a5e9b39-6a98-4b45-9ad5-6df3effec2ef",
|
||||
"uuid": "c30bd4d7-efdc-410c-8bdf-4a3dfc77bebd",
|
||||
"type": "sprite",
|
||||
"wrapMode": "clamp",
|
||||
"filterMode": "bilinear",
|
||||
@@ -11,8 +11,8 @@
|
||||
"subMetas": {
|
||||
"Tile_W300_H300_S01": {
|
||||
"ver": "1.0.4",
|
||||
"uuid": "acb30663-c0cf-4727-a046-26e40610c49f",
|
||||
"rawTextureUuid": "0a5e9b39-6a98-4b45-9ad5-6df3effec2ef",
|
||||
"uuid": "66b49304-7b5b-442c-92a5-d2b368abf659",
|
||||
"rawTextureUuid": "c30bd4d7-efdc-410c-8bdf-4a3dfc77bebd",
|
||||
"trimType": "auto",
|
||||
"trimThreshold": 1,
|
||||
"rotated": false,
|
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"ver": "2.0.0",
|
||||
"uuid": "8c8beea4-faa3-4270-aa27-dc5f2b7766c2",
|
||||
"subMetas": {}
|
||||
}
|
Before Width: | Height: | Size: 45 KiB After Width: | Height: | Size: 45 KiB |
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"ver": "2.3.3",
|
||||
"uuid": "5e68ce04-f41f-4ab0-a55c-608542e5638a",
|
||||
"uuid": "dd454e0f-4474-4801-8e86-ba134f6293a9",
|
||||
"type": "sprite",
|
||||
"wrapMode": "clamp",
|
||||
"filterMode": "bilinear",
|
||||
@@ -11,8 +11,8 @@
|
||||
"subMetas": {
|
||||
"Tile_W64_H64_S01": {
|
||||
"ver": "1.0.4",
|
||||
"uuid": "610a5bd5-c643-426e-a6e8-63acc5c516d9",
|
||||
"rawTextureUuid": "5e68ce04-f41f-4ab0-a55c-608542e5638a",
|
||||
"uuid": "e287ce95-457a-48b3-9c94-314bbcb69009",
|
||||
"rawTextureUuid": "dd454e0f-4474-4801-8e86-ba134f6293a9",
|
||||
"trimType": "auto",
|
||||
"trimThreshold": 1,
|
||||
"rotated": false,
|
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"ver": "2.0.0",
|
||||
"uuid": "c63de1bc-6d0e-467e-848b-f5c021a1b950",
|
||||
"subMetas": {}
|
||||
}
|
40
frontend/assets/resources/map/simple/map.tmx
Normal file
@@ -0,0 +1,40 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<map version="1.2" tiledversion="1.2.3" orientation="isometric" renderorder="right-down" width="50" height="50" tilewidth="64" tileheight="64" infinite="0" nextlayerid="11" nextobjectid="214">
|
||||
<tileset firstgid="1" source="Tile_W64_H64_S01.tsx"/>
|
||||
<tileset firstgid="17" source="Tile_W300_H300_S01.tsx"/>
|
||||
<layer id="1" name="GroundFloor" width="50" height="50" locked="1">
|
||||
<data encoding="base64" compression="zlib">
|
||||
eJztz0ENACAMALGR4F8zNspyjwronZm7xPlcD0sPSw9LD0sPSw9LD0sPSw9LD0sPSw9LD0sPSw9LD0sPSw9LD0sPSw9LD0sPy7bHBg/ldQwR
|
||||
</data>
|
||||
</layer>
|
||||
<objectgroup id="2" name="PlayerStartingPos">
|
||||
<object id="135" x="1442.33" y="2063">
|
||||
<point/>
|
||||
</object>
|
||||
<object id="137" x="2270" y="1640">
|
||||
<point/>
|
||||
</object>
|
||||
</objectgroup>
|
||||
<layer id="3" name="FirsrtFloor" width="50" height="50">
|
||||
<data encoding="base64" compression="zlib">
|
||||
eJztwQENAAAAwqD3T20ON6AAAAAAAAAAAADg3wAnEAAB
|
||||
</data>
|
||||
</layer>
|
||||
<objectgroup id="4" name="Barrier">
|
||||
<properties>
|
||||
<property name="type" value="barrier_and_shelter"/>
|
||||
</properties>
|
||||
<object id="5" x="1082.23" y="1537.08">
|
||||
<properties>
|
||||
<property name="boundary_type" value="barrier"/>
|
||||
</properties>
|
||||
<polyline points="548.339,-547.082 -94.2284,95.4898 230.657,408.918 867.772,-230"/>
|
||||
</object>
|
||||
<object id="213" x="1044" y="1852">
|
||||
<properties>
|
||||
<property name="boundary_type" value="barrier"/>
|
||||
</properties>
|
||||
<polyline points="1101.33,-342 470.926,284.848 526.26,339.333 1152.93,-285.091"/>
|
||||
</object>
|
||||
</objectgroup>
|
||||
</map>
|
5
frontend/assets/resources/map/simple/map.tmx.meta
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"ver": "2.0.2",
|
||||
"uuid": "9b8777b4-8725-46ea-96c0-d580e9f023d1",
|
||||
"subMetas": {}
|
||||
}
|
@@ -46,6 +46,9 @@ message BattleColliderInfo {
|
||||
int32 inputFrameUpsyncDelayTolerance = 16;
|
||||
int32 maxChasingRenderFramesPerUpdate = 17;
|
||||
int32 playerBattleState = 18;
|
||||
double rollbackEstimatedDt = 19;
|
||||
double rollbackEstimatedDtMillis = 20;
|
||||
int64 rollbackEstimatedDtNanos = 21;
|
||||
}
|
||||
|
||||
message Player {
|
||||
|
@@ -304,7 +304,6 @@
|
||||
"__id__": 5
|
||||
},
|
||||
"_enabled": true,
|
||||
"useDiffFrameAlgo": true,
|
||||
"canvasNode": {
|
||||
"__id__": 2
|
||||
},
|
||||
@@ -317,22 +316,9 @@
|
||||
"player2Prefab": {
|
||||
"__uuid__": "1f479636-9eb8-4612-8f97-371964d6eae3"
|
||||
},
|
||||
"treasurePrefab": {
|
||||
"__uuid__": "ec3f3234-9b84-43c2-a3cd-58b924cce8e5"
|
||||
},
|
||||
"trapPrefab": {
|
||||
"__uuid__": "9f340a31-ddfa-46c2-94c7-d11615aedcb1"
|
||||
},
|
||||
"speedShoePrefab": null,
|
||||
"polygonBoundaryBarrierPrefab": {
|
||||
"__uuid__": "4154eec0-d644-482f-a889-c00ae6b69958"
|
||||
},
|
||||
"polygonBoundaryShelterPrefab": {
|
||||
"__uuid__": "f820a6ec-e7a9-46cf-9b8a-331aa3e21487"
|
||||
},
|
||||
"polygonBoundaryShelterZReducerPrefab": {
|
||||
"__uuid__": "a36d024b-a979-4d18-b089-19af313ffb82"
|
||||
},
|
||||
"keyboardInputControllerNode": {
|
||||
"__id__": 8
|
||||
},
|
||||
@@ -351,9 +337,6 @@
|
||||
"countdownLabel": {
|
||||
"__id__": 30
|
||||
},
|
||||
"trapBulletPrefab": {
|
||||
"__uuid__": "7673e0e4-bebd-4caa-8a10-a6e1e86f1b2f"
|
||||
},
|
||||
"resultPanelPrefab": {
|
||||
"__uuid__": "c4cfe3bd-c59e-4d5b-95cb-c933b120e184"
|
||||
},
|
||||
@@ -369,13 +352,12 @@
|
||||
"playersInfoPrefab": {
|
||||
"__uuid__": "b4e519f4-e698-4403-9ff2-47b8dacb077e"
|
||||
},
|
||||
"guardTowerPrefab": {
|
||||
"__uuid__": "31a63530-7811-45bc-a4ee-571faf917e35"
|
||||
},
|
||||
"forceBigEndianFloatingNumDecoding": false,
|
||||
"backgroundMapTiledIns": {
|
||||
"__id__": 4
|
||||
},
|
||||
"renderFrameIdLagTolerance": 4,
|
||||
"teleportEps1D": 0.001,
|
||||
"_id": "d12gkAmppNlIzqcRDELa91"
|
||||
},
|
||||
{
|
||||
@@ -557,7 +539,7 @@
|
||||
"array": [
|
||||
0,
|
||||
0,
|
||||
217.54856073274254,
|
||||
342.9460598986377,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
@@ -1579,6 +1561,7 @@
|
||||
"mapNode": {
|
||||
"__id__": 5
|
||||
},
|
||||
"speed": 5000,
|
||||
"_id": "76ImpM7XtPSbiLHDXdsJa+"
|
||||
},
|
||||
{
|
||||
@@ -1631,7 +1614,6 @@
|
||||
"joyStickEps": 0.1,
|
||||
"magicLeanLowerBound": 0.414,
|
||||
"magicLeanUpperBound": 2.414,
|
||||
"pollerFps": 24,
|
||||
"linearScaleFacBase": 1,
|
||||
"minScale": 1,
|
||||
"maxScale": 2,
|
||||
|
@@ -440,7 +440,7 @@
|
||||
"array": [
|
||||
0,
|
||||
0,
|
||||
216.50635094610968,
|
||||
216.05530045313827,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
|
@@ -6,7 +6,10 @@ cc.Class({
|
||||
type: cc.Node,
|
||||
default: null
|
||||
},
|
||||
|
||||
speed: {
|
||||
type: cc.Float,
|
||||
default: 500
|
||||
},
|
||||
},
|
||||
|
||||
onLoad () {
|
||||
@@ -26,6 +29,9 @@ cc.Class({
|
||||
if (!selfPlayerRichInfo) return;
|
||||
const selfPlayerNode = selfPlayerRichInfo.node;
|
||||
if (!selfPlayerNode) return;
|
||||
self.mainCamera.node.setPosition(selfPlayerNode.position);
|
||||
const pDiff = selfPlayerNode.position.sub(self.mainCamera.node.position);
|
||||
pDiff.normalizeSelf();
|
||||
const newCamPos = self.mainCamera.node.position.add(pDiff.mul(dt*self.speed));
|
||||
self.mainCamera.node.setPosition(newCamPos);
|
||||
}
|
||||
});
|
||||
|
@@ -67,19 +67,6 @@ cc.Class({
|
||||
|
||||
onLoad() {
|
||||
|
||||
//kobako: 腾讯统计代码
|
||||
//WARN: 打包到微信小游戏的时候会导致出错
|
||||
/*
|
||||
(function() {
|
||||
var mta = document.createElement("script");
|
||||
mta.src = "//pingjs.qq.com/h5/stats.js?v2.0.4";
|
||||
mta.setAttribute("name", "MTAH5");
|
||||
mta.setAttribute("sid", "500674632");
|
||||
var s = document.getElementsByTagName("script")[0];
|
||||
s.parentNode.insertBefore(mta, s);
|
||||
})();
|
||||
*/
|
||||
|
||||
window.atFirstLocationHref = window.location.href.split('#')[0];
|
||||
const self = this;
|
||||
self.getRetCodeList();
|
||||
@@ -97,10 +84,8 @@ cc.Class({
|
||||
self.smsLoginCaptchaLabel.active = true;
|
||||
|
||||
self.loginButton.active = true;
|
||||
self.checkPhoneNumber = self.checkPhoneNumber.bind(self);
|
||||
self.checkIntAuthTokenExpire = self.checkIntAuthTokenExpire.bind(self);
|
||||
self.checkCaptcha = self.checkCaptcha.bind(self);
|
||||
self.onSMSCaptchaGetButtonClicked = self.onSMSCaptchaGetButtonClicked.bind(self);
|
||||
self.onLoginButtonClicked = self.onLoginButtonClicked.bind(self);
|
||||
self.onSMSCaptchaGetButtonClicked = self.onSMSCaptchaGetButtonClicked.bind(self);
|
||||
self.smsLoginCaptchaButton.on('click', self.onSMSCaptchaGetButtonClicked);
|
||||
|
||||
self.loadingNode = cc.instantiate(this.loadingPrefab);
|
||||
@@ -125,11 +110,12 @@ cc.Class({
|
||||
window.WsReq = protoRoot.lookupType("treasurehunterx.WsReq");
|
||||
window.WsResp = protoRoot.lookupType("treasurehunterx.WsResp");
|
||||
self.checkIntAuthTokenExpire().then(
|
||||
() => {
|
||||
const intAuthToken = JSON.parse(cc.sys.localStorage.getItem('selfPlayer')).intAuthToken;
|
||||
(intAuthToken) => {
|
||||
console.log("Successfully found `intAuthToken` in local cache");
|
||||
self.useTokenLogin(intAuthToken);
|
||||
},
|
||||
() => {
|
||||
console.warn("Failed to find `intAuthToken` in local cache");
|
||||
window.clearBoundRoomIdInBothVolatileAndPersistentStorage();
|
||||
}
|
||||
);
|
||||
@@ -221,11 +207,28 @@ cc.Class({
|
||||
checkIntAuthTokenExpire() {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (!cc.sys.localStorage.getItem('selfPlayer')) {
|
||||
console.warn("Couldn't find selfPlayer key in local cache");
|
||||
reject();
|
||||
return;
|
||||
}
|
||||
const selfPlayer = JSON.parse(cc.sys.localStorage.getItem('selfPlayer'));
|
||||
(selfPlayer.intAuthToken && new Date().getTime() < selfPlayer.expiresAt) ? resolve() : reject();
|
||||
if (null == selfPlayer) {
|
||||
console.warn("Couldn't find selfPlayer object in local cache");
|
||||
reject();
|
||||
return;
|
||||
}
|
||||
|
||||
if (null == selfPlayer.intAuthToken) {
|
||||
console.warn("Couldn't find selfPlayer object with key `intAuthToken` in local cache");
|
||||
reject();
|
||||
return;
|
||||
}
|
||||
if (new Date().getTime() > selfPlayer.expiresAt) {
|
||||
console.warn("Couldn't find unexpired selfPlayer `intAuthToken` in local cache");
|
||||
reject();
|
||||
return;
|
||||
}
|
||||
resolve(selfPlayer.intAuthToken);
|
||||
})
|
||||
},
|
||||
|
||||
@@ -278,13 +281,15 @@ cc.Class({
|
||||
intAuthToken: _intAuthToken
|
||||
},
|
||||
success: function(resp) {
|
||||
console.log("Login attempt `useTokenLogin` succeeded.");
|
||||
self.onLoggedIn(resp);
|
||||
},
|
||||
error: function(xhr, status, errMsg) {
|
||||
console.log("Login attempt `useTokenLogin` failed, about to execute `clearBoundRoomIdInBothVolatileAndPersistentStorage`.");
|
||||
console.warn("Login attempt `useTokenLogin` failed, about to execute `clearBoundRoomIdInBothVolatileAndPersistentStorage`.");
|
||||
window.clearBoundRoomIdInBothVolatileAndPersistentStorage()
|
||||
},
|
||||
timeout: function() {
|
||||
console.warn("Login attempt `useTokenLogin` timed out, about to enable interactive controls.");
|
||||
self.enableInteractiveControls(true);
|
||||
},
|
||||
});
|
||||
@@ -335,7 +340,7 @@ cc.Class({
|
||||
|
||||
onLoggedIn(res) {
|
||||
const self = this;
|
||||
cc.log(`OnLoggedIn ${JSON.stringify(res)}.`)
|
||||
console.log("OnLoggedIn ", JSON.stringify(res))
|
||||
if (res.ret === self.retCodeDict.OK) {
|
||||
self.enableInteractiveControls(false);
|
||||
const date = Number(res.expiresAt);
|
||||
@@ -360,6 +365,7 @@ cc.Class({
|
||||
);
|
||||
cc.director.loadScene('default_map');
|
||||
} else {
|
||||
console.log("OnLoggedIn failed, about to remove `selfPlayer` in local cache.")
|
||||
cc.sys.localStorage.removeItem("selfPlayer");
|
||||
window.clearBoundRoomIdInBothVolatileAndPersistentStorage();
|
||||
self.enableInteractiveControls(true);
|
||||
|
@@ -111,6 +111,10 @@ cc.Class({
|
||||
type: cc.Integer,
|
||||
default: 4 // implies (renderFrameIdLagTolerance >> inputScaleFrames) count of inputFrameIds
|
||||
},
|
||||
teleportEps1D: {
|
||||
type: cc.Float,
|
||||
default: 1e-3
|
||||
},
|
||||
},
|
||||
|
||||
_inputFrameIdDebuggable(inputFrameId) {
|
||||
@@ -129,7 +133,7 @@ cc.Class({
|
||||
|
||||
dumpToInputCache: function(inputFrameDownsync) {
|
||||
const self = this;
|
||||
let minToKeepInputFrameId = self._convertToInputFrameId(self.lastAllConfirmedRenderFrameId, self.inputDelayFrames); // [WARNING] This could be different from "self.lastAllConfirmedInputFrameId". We'd like to keep the corresponding inputFrame for "self.lastAllConfirmedRenderFrameId" such that a rollback could place "self.chaserRenderFrameId = self.lastAllConfirmedRenderFrameId" for the worst case incorrect prediction.
|
||||
let minToKeepInputFrameId = self._convertToInputFrameId(self.lastAllConfirmedRenderFrameId, self.inputDelayFrames); // [WARNING] This could be different from "self.lastAllConfirmedInputFrameId". We'd like to keep the corresponding delayedInputFrame for "self.lastAllConfirmedRenderFrameId" such that a rollback could place "self.chaserRenderFrameId = self.lastAllConfirmedRenderFrameId" for the worst case incorrect prediction.
|
||||
if (minToKeepInputFrameId > self.lastAllConfirmedInputFrameId) {
|
||||
minToKeepInputFrameId = self.lastAllConfirmedInputFrameId;
|
||||
}
|
||||
@@ -249,8 +253,8 @@ cc.Class({
|
||||
if (null != window.handleBattleColliderInfo) {
|
||||
window.handleBattleColliderInfo = null;
|
||||
}
|
||||
if (null != window.handleClientSessionCloseOrError) {
|
||||
window.handleClientSessionCloseOrError = null;
|
||||
if (null != window.handleClientSessionError) {
|
||||
window.handleClientSessionError = null;
|
||||
}
|
||||
},
|
||||
|
||||
@@ -345,8 +349,8 @@ cc.Class({
|
||||
window.forceBigEndianFloatingNumDecoding = self.forceBigEndianFloatingNumDecoding;
|
||||
|
||||
console.warn("+++++++ Map onLoad()");
|
||||
window.handleClientSessionCloseOrError = function() {
|
||||
console.warn('+++++++ Common handleClientSessionCloseOrError()');
|
||||
window.handleClientSessionError = function() {
|
||||
console.warn('+++++++ Common handleClientSessionError()');
|
||||
|
||||
if (ALL_BATTLE_STATES.IN_SETTLEMENT == self.battleState) {
|
||||
console.log("Battled ended by settlement");
|
||||
@@ -378,7 +382,8 @@ cc.Class({
|
||||
window.clearBoundRoomIdInBothVolatileAndPersistentStorage();
|
||||
window.initPersistentSessionClient(self.initAfterWSConnected, null /* Deliberately NOT passing in any `expectedRoomId`. -- YFLu */ );
|
||||
};
|
||||
resultPanelScriptIns.onCloseDelegate = () => {};
|
||||
resultPanelScriptIns.onCloseDelegate = () => {
|
||||
};
|
||||
|
||||
self.gameRuleNode = cc.instantiate(self.gameRulePrefab);
|
||||
self.gameRuleNode.width = self.canvasNode.width;
|
||||
@@ -414,8 +419,10 @@ cc.Class({
|
||||
self.inputScaleFrames = parsedBattleColliderInfo.inputScaleFrames;
|
||||
self.inputFrameUpsyncDelayTolerance = parsedBattleColliderInfo.inputFrameUpsyncDelayTolerance;
|
||||
|
||||
self.rollbackEstimatedDt = 1.0 / parsedBattleColliderInfo.serverFps;
|
||||
self.rollbackEstimatedDtMillis = 1000.0 * self.rollbackEstimatedDt;
|
||||
self.battleDurationNanos = parsedBattleColliderInfo.battleDurationNanos;
|
||||
self.rollbackEstimatedDt = parsedBattleColliderInfo.rollbackEstimatedDt;
|
||||
self.rollbackEstimatedDtMillis = parsedBattleColliderInfo.rollbackEstimatedDtMillis;
|
||||
self.rollbackEstimatedDtNanos = parsedBattleColliderInfo.rollbackEstimatedDtNanos;
|
||||
self.rollbackEstimatedDtToleranceMillis = self.rollbackEstimatedDtMillis / 1000.0;
|
||||
self.maxChasingRenderFramesPerUpdate = parsedBattleColliderInfo.maxChasingRenderFramesPerUpdate;
|
||||
|
||||
@@ -466,6 +473,7 @@ cc.Class({
|
||||
pts.push([boundaryObj[i].x - x0, boundaryObj[i].y - y0]);
|
||||
}
|
||||
const newBarrierLatest = self.latestCollisionSys.createPolygon(x0, y0, pts);
|
||||
// console.log("Created barrier: ", newBarrierLatest);
|
||||
const newBarrierChaser = self.chaserCollisionSys.createPolygon(x0, y0, pts);
|
||||
++barrierIdCounter;
|
||||
const collisionBarrierIndex = (self.collisionBarrierIndexPrefix + barrierIdCounter);
|
||||
@@ -630,7 +638,7 @@ cc.Class({
|
||||
return true;
|
||||
},
|
||||
|
||||
onInputFrameDownsyncBatch(batch, dumpRenderCacheRet /* second param is default to null */ ) {
|
||||
onInputFrameDownsyncBatch(batch) {
|
||||
const self = this;
|
||||
if (ALL_BATTLE_STATES.IN_BATTLE != self.battleState
|
||||
&& ALL_BATTLE_STATES.IN_SETTLEMENT != self.battleState) {
|
||||
@@ -644,49 +652,42 @@ cc.Class({
|
||||
if (inputFrameDownsyncId < self.lastAllConfirmedInputFrameId) {
|
||||
continue;
|
||||
}
|
||||
if (window.RING_BUFF_NON_CONSECUTIVE_SET == dumpRenderCacheRet) {
|
||||
// Deliberately left blank, in this case "chaserRenderFrameId" is already reset to proper value.
|
||||
} else {
|
||||
const inputFrameIdConsecutive = (inputFrameDownsyncId == self.lastAllConfirmedInputFrameId + 1);
|
||||
const localInputFrame = self.recentInputCache.getByFrameId(inputFrameDownsyncId);
|
||||
if (null == localInputFrame && false == inputFrameIdConsecutive) {
|
||||
throw "localInputFrame not existing and is NOT CONSECUTIVELY EXTENDING recentInputCache: inputFrameDownsyncId=" + inputFrameDownsyncId + ", lastAllConfirmedInputFrameId=" + self.lastAllConfirmedInputFrameId + ", recentInputCache=" + self._stringifyRecentInputCache(false);
|
||||
} else if (null == firstPredictedYetIncorrectInputFrameId && null != localInputFrame && !self.equalInputLists(localInputFrame.inputList, inputFrameDownsync.inputList)) {
|
||||
firstPredictedYetIncorrectInputFrameId = inputFrameDownsyncId;
|
||||
}
|
||||
const localInputFrame = self.recentInputCache.getByFrameId(inputFrameDownsyncId);
|
||||
if (null != localInputFrame
|
||||
&&
|
||||
null == firstPredictedYetIncorrectInputFrameId
|
||||
&&
|
||||
!self.equalInputLists(localInputFrame.inputList, inputFrameDownsync.inputList)
|
||||
) {
|
||||
firstPredictedYetIncorrectInputFrameId = inputFrameDownsyncId;
|
||||
}
|
||||
self.lastAllConfirmedInputFrameId = inputFrameDownsyncId;
|
||||
self.dumpToInputCache(inputFrameDownsync);
|
||||
}
|
||||
|
||||
if (null != firstPredictedYetIncorrectInputFrameId) {
|
||||
const inputFrameId1 = firstPredictedYetIncorrectInputFrameId;
|
||||
const renderFrameId1 = self._convertToFirstUsedRenderFrameId(inputFrameId1, self.inputDelayFrames); // a.k.a. "firstRenderFrameIdUsingIncorrectInputFrameId"
|
||||
if (renderFrameId1 < self.renderFrameId) {
|
||||
/*
|
||||
A typical case is as follows.
|
||||
--------------------------------------------------------
|
||||
[self.lastAllConfirmedRenderFrameId] : 22
|
||||
if (null == firstPredictedYetIncorrectInputFrameId) return;
|
||||
const inputFrameId1 = firstPredictedYetIncorrectInputFrameId;
|
||||
const renderFrameId1 = self._convertToFirstUsedRenderFrameId(inputFrameId1, self.inputDelayFrames); // a.k.a. "firstRenderFrameIdUsingIncorrectInputFrameId"
|
||||
if (renderFrameId1 >= self.renderFrameId) return; // No need to rollback when "renderFrameId1 == self.renderFrameId", because the "corresponding delayedInputFrame for renderFrameId1" is NOT YET EXECUTED BY NOW, it just went through "++self.renderFrameId" in "update(dt)" and javascript-runtime is mostly single-threaded in our programmable range.
|
||||
|
||||
<renderFrameId1> : 36
|
||||
if (renderFrameId1 >= self.chaserRenderFrameId) return;
|
||||
|
||||
/*
|
||||
A typical case is as follows.
|
||||
--------------------------------------------------------
|
||||
[self.lastAllConfirmedRenderFrameId] : 22
|
||||
|
||||
<renderFrameId1> : 36
|
||||
|
||||
|
||||
<self.chaserRenderFrameId> : 62
|
||||
<self.chaserRenderFrameId> : 62
|
||||
|
||||
[self.renderFrameId] : 64
|
||||
--------------------------------------------------------
|
||||
*/
|
||||
if (renderFrameId1 < self.chaserRenderFrameId) {
|
||||
// The actual rollback-and-chase would later be executed in update(dt).
|
||||
console.warn("Mismatched input detected, resetting chaserRenderFrameId: inputFrameId1:", inputFrameId1, ", renderFrameId1:", renderFrameId1, ", chaserRenderFrameId before reset: ", self.chaserRenderFrameId);
|
||||
self.chaserRenderFrameId = renderFrameId1;
|
||||
} else {
|
||||
// Deliberately left blank, chasing is ongoing.
|
||||
}
|
||||
} else {
|
||||
// No need to rollback when "renderFrameId1 == self.renderFrameId", because the "corresponding delayedInputFrame for renderFrameId2" is NOT YET EXECUTED BY NOW, it just went through "++self.renderFrameId" in "update(dt)" and javascript-runtime is mostly single-threaded in our programmable range.
|
||||
}
|
||||
}
|
||||
[self.renderFrameId] : 64
|
||||
--------------------------------------------------------
|
||||
*/
|
||||
// The actual rollback-and-chase would later be executed in update(dt).
|
||||
console.warn("Mismatched input detected, resetting chaserRenderFrameId: inputFrameId1:", inputFrameId1, ", renderFrameId1:", renderFrameId1, ", chaserRenderFrameId before reset: ", self.chaserRenderFrameId);
|
||||
self.chaserRenderFrameId = renderFrameId1;
|
||||
},
|
||||
|
||||
onPlayerAdded(rdf) {
|
||||
@@ -740,9 +741,15 @@ cc.Class({
|
||||
newPlayerNode.setPosition(cc.v2(x, y));
|
||||
newPlayerNode.getComponent("SelfPlayer").mapNode = self.node;
|
||||
const currentSelfColliderCircle = newPlayerNode.getComponent(cc.CircleCollider);
|
||||
const r = currentSelfColliderCircle.radius,
|
||||
d = 2 * r;
|
||||
// The collision box of an individual player is a polygon instead of a circle, because the backend collision engine doesn't handle circle alignment well.
|
||||
const x0 = x - r,
|
||||
y0 = y - r;
|
||||
let pts = [[0, 0], [d, 0], [d, d], [0, d]];
|
||||
|
||||
const newPlayerColliderLatest = self.latestCollisionSys.createCircle(x, y, currentSelfColliderCircle.radius);
|
||||
const newPlayerColliderChaser = self.chaserCollisionSys.createCircle(x, y, currentSelfColliderCircle.radius);
|
||||
const newPlayerColliderLatest = self.latestCollisionSys.createPolygon(x0, y0, pts);
|
||||
const newPlayerColliderChaser = self.chaserCollisionSys.createPolygon(x0, y0, pts);
|
||||
const collisionPlayerIndex = self.collisionPlayerIndexPrefix + joinIndex;
|
||||
self.latestCollisionSysMap.set(collisionPlayerIndex, newPlayerColliderLatest);
|
||||
self.chaserCollisionSysMap.set(collisionPlayerIndex, newPlayerColliderChaser);
|
||||
@@ -796,8 +803,14 @@ cc.Class({
|
||||
self.chaserRenderFrameId = nextChaserRenderFrameId; // Move the cursor "self.chaserRenderFrameId", keep in mind that "self.chaserRenderFrameId" is not monotonic!
|
||||
let t2 = performance.now();
|
||||
|
||||
// Inside "self.rollbackAndChase", the "self.latestCollisionSys" is ALWAYS ROLLED BACK to "self.recentRenderCache.get(self.renderFrameId)" before being applied dynamics from corresponding inputFrameDownsync, REGARDLESS OF whether or not "self.chaserRenderFrameId == self.renderFrameId" now.
|
||||
// Inside the following "self.rollbackAndChase" (which actually ROLLS FORWARD), the "self.latestCollisionSys" is ALWAYS "ROLLED BACK" to "self.recentRenderCache.get(self.renderFrameId)" before being applied dynamics from corresponding delayedInputFrame, REGARDLESS OF whether or not "self.chaserRenderFrameId == self.renderFrameId" now.
|
||||
const rdf = self.rollbackAndChase(self.renderFrameId, self.renderFrameId + 1, self.latestCollisionSys, self.latestCollisionSysMap);
|
||||
/*
|
||||
const nonTrivialChaseEnded = (prevChaserRenderFrameId < nextChaserRenderFrameId && nextChaserRenderFrameId == self.renderFrameId);
|
||||
if (nonTrivialChaseEnded) {
|
||||
console.debug("Non-trivial chase ended, prevChaserRenderFrameId=" + prevChaserRenderFrameId + ", nextChaserRenderFrameId=" + nextChaserRenderFrameId);
|
||||
}
|
||||
*/
|
||||
self.applyRoomDownsyncFrameDynamics(rdf);
|
||||
let t3 = performance.now();
|
||||
} catch (err) {
|
||||
@@ -805,7 +818,7 @@ cc.Class({
|
||||
} finally {
|
||||
// Update countdown
|
||||
if (null != self.countdownNanos) {
|
||||
self.countdownNanos -= (performance.now() - self.lastRenderFrameIdTriggeredAt) * 1000000;
|
||||
self.countdownNanos = self.battleDurationNanos - self.renderFrameId * self.rollbackEstimatedDtNanos;
|
||||
if (self.countdownNanos <= 0) {
|
||||
self.onBattleStopped(self.playerRichInfoDict);
|
||||
return;
|
||||
@@ -946,10 +959,12 @@ cc.Class({
|
||||
const joinIndex = playerRichInfo.joinIndex;
|
||||
const collisionPlayerIndex = self.collisionPlayerIndexPrefix + joinIndex;
|
||||
const playerCollider = collisionSysMap.get(collisionPlayerIndex);
|
||||
const currentSelfColliderCircle = playerRichInfo.node.getComponent(cc.CircleCollider);
|
||||
const r = currentSelfColliderCircle.radius;
|
||||
rdf.players[playerRichInfo.id] = {
|
||||
id: playerRichInfo.id,
|
||||
x: playerCollider.x,
|
||||
y: playerCollider.y,
|
||||
x: playerCollider.x + r, // [WARNING] the (x, y) of "playerCollider" is offset to the anchor (i.e. first point of all points) of the polygon shape
|
||||
y: playerCollider.y + r,
|
||||
dir: self.ctrl.decodeDirection(null == inputFrameAppliedOnPrevRenderFrame ? 0 : inputFrameAppliedOnPrevRenderFrame.inputList[joinIndex - 1]),
|
||||
speed: (null == speedRefRenderFrame ? playerRichInfo.speed : speedRefRenderFrame.players[playerRichInfo.id].speed),
|
||||
joinIndex: joinIndex
|
||||
@@ -974,8 +989,15 @@ cc.Class({
|
||||
|
||||
self.playerRichInfoDict.forEach((playerRichInfo, playerId) => {
|
||||
const immediatePlayerInfo = rdf.players[playerId];
|
||||
playerRichInfo.node.setPosition(immediatePlayerInfo.x, immediatePlayerInfo.y);
|
||||
playerRichInfo.scriptIns.scheduleNewDirection(immediatePlayerInfo.dir, true);
|
||||
const dx = (immediatePlayerInfo.x - playerRichInfo.node.x);
|
||||
const dy = (immediatePlayerInfo.y - playerRichInfo.node.y);
|
||||
const selfJiggling = (playerId == self.selfPlayerInfo.playerId && (0 != dx && self.teleportEps1D >= Math.abs(dx) && 0 != dy && self.teleportEps1D >= Math.abs(dy)));
|
||||
if (!selfJiggling) {
|
||||
playerRichInfo.node.setPosition(immediatePlayerInfo.x, immediatePlayerInfo.y);
|
||||
} else {
|
||||
console.log("selfJiggling: dx = ", dx, ", dy = ", dy);
|
||||
}
|
||||
playerRichInfo.scriptIns.scheduleNewDirection(immediatePlayerInfo.dir, false);
|
||||
playerRichInfo.scriptIns.updateSpeed(immediatePlayerInfo.speed);
|
||||
});
|
||||
},
|
||||
@@ -1012,8 +1034,11 @@ cc.Class({
|
||||
const collisionPlayerIndex = self.collisionPlayerIndexPrefix + joinIndex;
|
||||
const playerCollider = collisionSysMap.get(collisionPlayerIndex);
|
||||
const player = latestRdf.players[playerId];
|
||||
playerCollider.x = player.x;
|
||||
playerCollider.y = player.y;
|
||||
|
||||
const currentSelfColliderCircle = playerRichInfo.node.getComponent(cc.CircleCollider);
|
||||
const r = currentSelfColliderCircle.radius;
|
||||
playerCollider.x = player.x - r;
|
||||
playerCollider.y = player.y - r;
|
||||
});
|
||||
|
||||
/*
|
||||
|
@@ -1,24 +1,20 @@
|
||||
window.DIRECTION_DECODER = [
|
||||
[0, 0, null],
|
||||
[0, +1, null],
|
||||
[0, -1, null],
|
||||
[+2, 0, null],
|
||||
[-2, 0, null],
|
||||
[+2, +1, null],
|
||||
[-2, -1, null],
|
||||
[+2, -1, null],
|
||||
[-2, +1, null],
|
||||
[+2, 0, null],
|
||||
[-2, 0, null],
|
||||
[0, +1, null],
|
||||
[0, -1, null],
|
||||
// The 3rd value matches low-precision constants in backend.
|
||||
[0, 0, 0.0],
|
||||
[0, +1, 1.0],
|
||||
[0, -1, 1.0],
|
||||
[+2, 0, 0.5],
|
||||
[-2, 0, 0.5],
|
||||
[+2, +1, 0.4472],
|
||||
[-2, -1, 0.4472],
|
||||
[+2, -1, 0.4472],
|
||||
[-2, +1, 0.4472],
|
||||
[+2, 0, 0.5],
|
||||
[-2, 0, 0.5],
|
||||
[0, +1, 1.0],
|
||||
[0, -1, 1.0],
|
||||
];
|
||||
|
||||
for (let k in window.DIRECTION_DECODER) {
|
||||
const length = Math.sqrt(window.DIRECTION_DECODER[k][0]*window.DIRECTION_DECODER[k][0] + window.DIRECTION_DECODER[k][1]*window.DIRECTION_DECODER[k][1]);
|
||||
window.DIRECTION_DECODER[k][2] = (0 == length ? 0 : (1.0/length));
|
||||
}
|
||||
|
||||
cc.Class({
|
||||
extends: cc.Component,
|
||||
properties: {
|
||||
|
@@ -104,18 +104,6 @@ window.getExpectedRoomIdSync = function() {
|
||||
return null;
|
||||
};
|
||||
|
||||
window.unsetClientSessionCloseOrErrorFlag = function() {
|
||||
cc.sys.localStorage.removeItem("ClientSessionCloseOrErrorFlag");
|
||||
return;
|
||||
}
|
||||
|
||||
window.setClientSessionCloseOrErrorFlag = function() {
|
||||
const oldVal = cc.sys.localStorage.getItem("ClientSessionCloseOrErrorFlag");
|
||||
if (true == oldVal) return false;
|
||||
cc.sys.localStorage.setItem("ClientSessionCloseOrErrorFlag", true);
|
||||
return true;
|
||||
}
|
||||
|
||||
window.initPersistentSessionClient = function(onopenCb, expectedRoomId) {
|
||||
if (window.clientSession && window.clientSession.readyState == WebSocket.OPEN) {
|
||||
if (null != onopenCb) {
|
||||
@@ -124,7 +112,9 @@ window.initPersistentSessionClient = function(onopenCb, expectedRoomId) {
|
||||
return;
|
||||
}
|
||||
|
||||
const intAuthToken = cc.sys.localStorage.getItem("selfPlayer") ? JSON.parse(cc.sys.localStorage.getItem('selfPlayer')).intAuthToken : "";
|
||||
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 + backendAddress.WS_PATH_PREFIX + "?intAuthToken=" + intAuthToken;
|
||||
|
||||
@@ -144,19 +134,19 @@ window.initPersistentSessionClient = function(onopenCb, expectedRoomId) {
|
||||
const clientSession = new WebSocket(urlToConnect);
|
||||
clientSession.binaryType = 'arraybuffer'; // Make 'event.data' of 'onmessage' an "ArrayBuffer" instead of a "Blob"
|
||||
|
||||
clientSession.onopen = function(event) {
|
||||
console.log("The WS clientSession is opened.");
|
||||
clientSession.onopen = function(evt) {
|
||||
console.log("The WS clientSession is opened. clientSession.id=", clientSession.id);
|
||||
window.clientSession = clientSession;
|
||||
if (null == onopenCb) return;
|
||||
onopenCb();
|
||||
};
|
||||
|
||||
clientSession.onmessage = function(event) {
|
||||
if (null == event || null == event.data) {
|
||||
clientSession.onmessage = function(evt) {
|
||||
if (null == evt || null == evt.data) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const resp = window.WsResp.decode(new Uint8Array(event.data));
|
||||
const resp = window.WsResp.decode(new Uint8Array(evt.data));
|
||||
switch (resp.act) {
|
||||
case window.DOWNSYNC_MSG_ACT_HB_REQ:
|
||||
window.handleHbRequirements(resp); // 获取boundRoomId并存储到localStorage
|
||||
@@ -189,65 +179,60 @@ window.initPersistentSessionClient = function(onopenCb, expectedRoomId) {
|
||||
const inputFrameIdConsecutive = (resp.inputFrameDownsyncBatch[0].inputFrameId == mapIns.lastAllConfirmedInputFrameId + 1);
|
||||
const renderFrameIdConsecutive = (resp.rdf.id <= mapIns.renderFrameId + mapIns.renderFrameIdLagTolerance);
|
||||
if (inputFrameIdConsecutive && renderFrameIdConsecutive) {
|
||||
console.log("Got consecutive resync@localRenderFrameId=", mapIns.renderFrameId, ", @lastAllConfirmedRenderFrameId=", mapIns.lastAllConfirmedRenderFrameId, "@lastAllConfirmedInputFrameId=", mapIns.lastAllConfirmedInputFrameId, ", @localRecentInputCache=", mapIns._stringifyRecentInputCache(false), ", the incoming resp=\n", JSON.stringify(resp));
|
||||
// console.log("Got consecutive resync@localRenderFrameId=", mapIns.renderFrameId, ", @lastAllConfirmedRenderFrameId=", mapIns.lastAllConfirmedRenderFrameId, "@lastAllConfirmedInputFrameId=", mapIns.lastAllConfirmedInputFrameId, ", @localRecentInputCache=", mapIns._stringifyRecentInputCache(false), ", the incoming resp=\n", JSON.stringify(resp));
|
||||
mapIns.onInputFrameDownsyncBatch(resp.inputFrameDownsyncBatch);
|
||||
} else {
|
||||
console.warn("Got forced resync@localRenderFrameId=", mapIns.renderFrameId, ", @lastAllConfirmedRenderFrameId=", mapIns.lastAllConfirmedRenderFrameId, "@lastAllConfirmedInputFrameId=", mapIns.lastAllConfirmedInputFrameId, ", @localRecentInputCache=", mapIns._stringifyRecentInputCache(false), ", the incoming resp=\n", JSON.stringify(resp, null, 2));
|
||||
// console.warn("Got forced resync@localRenderFrameId=", mapIns.renderFrameId, ", @lastAllConfirmedRenderFrameId=", mapIns.lastAllConfirmedRenderFrameId, "@lastAllConfirmedInputFrameId=", mapIns.lastAllConfirmedInputFrameId, ", @localRecentInputCache=", mapIns._stringifyRecentInputCache(false), ", the incoming resp=\n", JSON.stringify(resp, null, 2));
|
||||
console.warn("Got forced resync@localRenderFrameId=", mapIns.renderFrameId, ", @lastAllConfirmedRenderFrameId=", mapIns.lastAllConfirmedRenderFrameId, "@lastAllConfirmedInputFrameId=", mapIns.lastAllConfirmedInputFrameId, ", @localRecentInputCache=", mapIns._stringifyRecentInputCache(false), ", inputFrameIdConsecutive=", inputFrameIdConsecutive, ", renderFrameIdConsecutive=", renderFrameIdConsecutive);
|
||||
// The following order of execution is important
|
||||
const dumpRenderCacheRet = mapIns.onRoomDownsyncFrame(resp.rdf);
|
||||
mapIns.onInputFrameDownsyncBatch(resp.inputFrameDownsyncBatch, dumpRenderCacheRet);
|
||||
mapIns.onRoomDownsyncFrame(resp.rdf);
|
||||
mapIns.onInputFrameDownsyncBatch(resp.inputFrameDownsyncBatch);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} catch (e) {
|
||||
console.error("Unexpected error when parsing data of:", event.data, e);
|
||||
console.error("Unexpected error when parsing data of:", evt.data, e);
|
||||
}
|
||||
};
|
||||
|
||||
clientSession.onerror = function(event) {
|
||||
if (!window.setClientSessionCloseOrErrorFlag()) {
|
||||
return;
|
||||
clientSession.onerror = function(evt) {
|
||||
console.error("Error caught on the WS clientSession: ", evt);
|
||||
if (window.handleClientSessionError) {
|
||||
window.handleClientSessionError();
|
||||
}
|
||||
console.error("Error caught on the WS clientSession: ", event);
|
||||
if (window.clientSessionPingInterval) {
|
||||
clearInterval(window.clientSessionPingInterval);
|
||||
}
|
||||
if (window.handleClientSessionCloseOrError) {
|
||||
window.handleClientSessionCloseOrError();
|
||||
}
|
||||
window.unsetClientSessionCloseOrErrorFlag();
|
||||
};
|
||||
|
||||
clientSession.onclose = function(event) {
|
||||
if (!window.setClientSessionCloseOrErrorFlag()) {
|
||||
return;
|
||||
}
|
||||
console.warn("The WS clientSession is closed: ", event);
|
||||
if (window.clientSessionPingInterval) {
|
||||
clearInterval(window.clientSessionPingInterval);
|
||||
}
|
||||
if (false == event.wasClean) {
|
||||
// Chrome doesn't allow the use of "CustomCloseCode"s (yet) and will callback with a "WebsocketStdCloseCode 1006" and "false == event.wasClean" here. See https://tools.ietf.org/html/rfc6455#section-7.4 for more information.
|
||||
if (window.handleClientSessionCloseOrError) {
|
||||
window.handleClientSessionCloseOrError();
|
||||
clientSession.onclose = function(evt) {
|
||||
// [WARNING] The callback "onclose" might be called AFTER the webpage is refreshed with "1001 == evt.code".
|
||||
console.warn("The WS clientSession is closed: ", evt, clientSession);
|
||||
if (false == evt.wasClean) {
|
||||
/*
|
||||
Chrome doesn't allow the use of "CustomCloseCode"s (yet) and will callback with a "WebsocketStdCloseCode 1006" and "false == evt.wasClean" here. See https://tools.ietf.org/html/rfc6455#section-7.4 for more information.
|
||||
*/
|
||||
if (window.handleClientSessionError) {
|
||||
window.handleClientSessionError();
|
||||
}
|
||||
} else {
|
||||
switch (event.code) {
|
||||
switch (evt.code) {
|
||||
case constants.RET_CODE.PLAYER_NOT_ADDABLE_TO_ROOM:
|
||||
case constants.RET_CODE.PLAYER_NOT_READDABLE_TO_ROOM:
|
||||
window.clearBoundRoomIdInBothVolatileAndPersistentStorage();
|
||||
break;
|
||||
case constants.RET_CODE.UNKNOWN_ERROR:
|
||||
case constants.RET_CODE.MYSQL_ERROR:
|
||||
case constants.RET_CODE.PLAYER_NOT_FOUND:
|
||||
case constants.RET_CODE.PLAYER_CHEATING:
|
||||
window.clearBoundRoomIdInBothVolatileAndPersistentStorage();
|
||||
case 1006: // Peer(i.e. the backend) gone unexpectedly
|
||||
if (window.handleClientSessionError) {
|
||||
window.handleClientSessionError();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (window.handleClientSessionCloseOrError) {
|
||||
window.handleClientSessionCloseOrError();
|
||||
}
|
||||
}
|
||||
window.unsetClientSessionCloseOrErrorFlag();
|
||||
};
|
||||
};
|
||||
|
||||
@@ -258,17 +243,17 @@ window.clearLocalStorageAndBackToLoginScene = function(shouldRetainBoundRoomIdIn
|
||||
window.mapIns.musicEffectManagerScriptIns.stopAllMusic();
|
||||
}
|
||||
/**
|
||||
* Here I deliberately removed the callback in the "common `handleClientSessionCloseOrError` callback"
|
||||
* Here I deliberately removed the callback in the "common `handleClientSessionError` callback"
|
||||
* within which another invocation to `clearLocalStorageAndBackToLoginScene` will be made.
|
||||
*
|
||||
* It'll be re-assigned to the common one upon reentrance of `Map.onLoad`.
|
||||
*
|
||||
* -- YFLu 2019-04-06
|
||||
*/
|
||||
window.handleClientSessionCloseOrError = () => {
|
||||
console.warn("+++++++ Special handleClientSessionCloseOrError() assigned within `clearLocalStorageAndBackToLoginScene`");
|
||||
window.handleClientSessionError = () => {
|
||||
console.warn("+++++++ Special handleClientSessionError() assigned within `clearLocalStorageAndBackToLoginScene`");
|
||||
// TBD.
|
||||
window.handleClientSessionCloseOrError = null; // To ensure that it's called at most once.
|
||||
window.handleClientSessionError = null; // To ensure that it's called at most once.
|
||||
};
|
||||
window.closeWSConnection();
|
||||
window.clearSelfPlayer();
|
||||
|
39
frontend/assets/scripts/collision_test_nodejs.js
Normal file
@@ -0,0 +1,39 @@
|
||||
const collisions = require('./modules/Collisions');
|
||||
|
||||
const collisionSys = new collisions.Collisions();
|
||||
|
||||
/*
|
||||
Backend result reference
|
||||
|
||||
2022-10-22T12:11:25.156+0800 INFO collider_visualizer/worldColliderDisplay.go:77 Collided: player.X=1257.665, player.Y=1415.335, oldDx=-2.98, oldDy=-50, playerShape=&{[[0 0] [64 0] [64 64] [0 64]] 1254.685 1365.335 true}, toCheckBarrier=&{[[628.626 54.254500000000064] [0 56.03250000000003] [0.42449999999999477 1.1229999999999905] [625.9715000000001 0]] 1289.039 1318.0805 true}, pushbackX=-0.15848054013127655, pushbackY=-56.03205175509715, result=&{56.03227587710039 -0.0028283794946841584 -0.9999960001267175 false false [0.9988052279193613 -0.04886836073527201]}
|
||||
*/
|
||||
function polygonStr(body) {
|
||||
let coords = [];
|
||||
let cnt = body._coords.length;
|
||||
for (let ix = 0, iy = 1; ix < cnt; ix += 2, iy += 2) {
|
||||
coords.push([body._coords[ix], body._coords[iy]]);
|
||||
}
|
||||
return JSON.stringify(coords);
|
||||
}
|
||||
|
||||
const playerCollider = collisionSys.createPolygon(1257.665, 1415.335, [[0, 0], [64, 0], [64, 64], [0, 64]]);
|
||||
const barrierCollider = collisionSys.createPolygon(1289.039, 1318.0805, [[628.626, 54.254500000000064], [0, 56.03250000000003], [0.42449999999999477, 1.1229999999999905], [625.9715000000001, 0]]);
|
||||
|
||||
const oldDx = -2.98;
|
||||
const oldDy = -50.0;
|
||||
|
||||
playerCollider.x += oldDx;
|
||||
playerCollider.y += oldDy;
|
||||
|
||||
collisionSys.update();
|
||||
const result = collisionSys.createResult();
|
||||
|
||||
const potentials = playerCollider.potentials();
|
||||
|
||||
let overlapCheckId = 0;
|
||||
for (const barrier of potentials) {
|
||||
if (!playerCollider.collides(barrier, result)) continue;
|
||||
const pushbackX = result.overlap * result.overlap_x;
|
||||
const pushbackY = result.overlap * result.overlap_y;
|
||||
console.log("For overlapCheckId=" + overlapCheckId + ", the overlap: a=", polygonStr(result.a), ", b=", polygonStr(result.b), ", pushbackX=", pushbackX, ", pushbackY=", pushbackY);
|
||||
}
|
9
frontend/assets/scripts/collision_test_nodejs.js.meta
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"ver": "1.0.5",
|
||||
"uuid": "fce86138-76fc-44d5-8eac-2731b3b0cefd",
|
||||
"isPlugin": false,
|
||||
"loadPluginInWeb": true,
|
||||
"loadPluginInNative": true,
|
||||
"loadPluginInEditor": false,
|
||||
"subMetas": {}
|
||||
}
|
@@ -1197,6 +1197,9 @@ $root.treasurehunterx = (function() {
|
||||
* @property {number|null} [inputFrameUpsyncDelayTolerance] BattleColliderInfo inputFrameUpsyncDelayTolerance
|
||||
* @property {number|null} [maxChasingRenderFramesPerUpdate] BattleColliderInfo maxChasingRenderFramesPerUpdate
|
||||
* @property {number|null} [playerBattleState] BattleColliderInfo playerBattleState
|
||||
* @property {number|null} [rollbackEstimatedDt] BattleColliderInfo rollbackEstimatedDt
|
||||
* @property {number|null} [rollbackEstimatedDtMillis] BattleColliderInfo rollbackEstimatedDtMillis
|
||||
* @property {number|Long|null} [rollbackEstimatedDtNanos] BattleColliderInfo rollbackEstimatedDtNanos
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -1360,6 +1363,30 @@ $root.treasurehunterx = (function() {
|
||||
*/
|
||||
BattleColliderInfo.prototype.playerBattleState = 0;
|
||||
|
||||
/**
|
||||
* BattleColliderInfo rollbackEstimatedDt.
|
||||
* @member {number} rollbackEstimatedDt
|
||||
* @memberof treasurehunterx.BattleColliderInfo
|
||||
* @instance
|
||||
*/
|
||||
BattleColliderInfo.prototype.rollbackEstimatedDt = 0;
|
||||
|
||||
/**
|
||||
* BattleColliderInfo rollbackEstimatedDtMillis.
|
||||
* @member {number} rollbackEstimatedDtMillis
|
||||
* @memberof treasurehunterx.BattleColliderInfo
|
||||
* @instance
|
||||
*/
|
||||
BattleColliderInfo.prototype.rollbackEstimatedDtMillis = 0;
|
||||
|
||||
/**
|
||||
* BattleColliderInfo rollbackEstimatedDtNanos.
|
||||
* @member {number|Long} rollbackEstimatedDtNanos
|
||||
* @memberof treasurehunterx.BattleColliderInfo
|
||||
* @instance
|
||||
*/
|
||||
BattleColliderInfo.prototype.rollbackEstimatedDtNanos = $util.Long ? $util.Long.fromBits(0,0,false) : 0;
|
||||
|
||||
/**
|
||||
* Creates a new BattleColliderInfo instance using the specified properties.
|
||||
* @function create
|
||||
@@ -1426,6 +1453,12 @@ $root.treasurehunterx = (function() {
|
||||
writer.uint32(/* id 17, wireType 0 =*/136).int32(message.maxChasingRenderFramesPerUpdate);
|
||||
if (message.playerBattleState != null && Object.hasOwnProperty.call(message, "playerBattleState"))
|
||||
writer.uint32(/* id 18, wireType 0 =*/144).int32(message.playerBattleState);
|
||||
if (message.rollbackEstimatedDt != null && Object.hasOwnProperty.call(message, "rollbackEstimatedDt"))
|
||||
writer.uint32(/* id 19, wireType 1 =*/153).double(message.rollbackEstimatedDt);
|
||||
if (message.rollbackEstimatedDtMillis != null && Object.hasOwnProperty.call(message, "rollbackEstimatedDtMillis"))
|
||||
writer.uint32(/* id 20, wireType 1 =*/161).double(message.rollbackEstimatedDtMillis);
|
||||
if (message.rollbackEstimatedDtNanos != null && Object.hasOwnProperty.call(message, "rollbackEstimatedDtNanos"))
|
||||
writer.uint32(/* id 21, wireType 0 =*/168).int64(message.rollbackEstimatedDtNanos);
|
||||
return writer;
|
||||
};
|
||||
|
||||
@@ -1570,6 +1603,18 @@ $root.treasurehunterx = (function() {
|
||||
message.playerBattleState = reader.int32();
|
||||
break;
|
||||
}
|
||||
case 19: {
|
||||
message.rollbackEstimatedDt = reader.double();
|
||||
break;
|
||||
}
|
||||
case 20: {
|
||||
message.rollbackEstimatedDtMillis = reader.double();
|
||||
break;
|
||||
}
|
||||
case 21: {
|
||||
message.rollbackEstimatedDtNanos = reader.int64();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
reader.skipType(tag & 7);
|
||||
break;
|
||||
@@ -1673,6 +1718,15 @@ $root.treasurehunterx = (function() {
|
||||
if (message.playerBattleState != null && message.hasOwnProperty("playerBattleState"))
|
||||
if (!$util.isInteger(message.playerBattleState))
|
||||
return "playerBattleState: integer expected";
|
||||
if (message.rollbackEstimatedDt != null && message.hasOwnProperty("rollbackEstimatedDt"))
|
||||
if (typeof message.rollbackEstimatedDt !== "number")
|
||||
return "rollbackEstimatedDt: number expected";
|
||||
if (message.rollbackEstimatedDtMillis != null && message.hasOwnProperty("rollbackEstimatedDtMillis"))
|
||||
if (typeof message.rollbackEstimatedDtMillis !== "number")
|
||||
return "rollbackEstimatedDtMillis: number expected";
|
||||
if (message.rollbackEstimatedDtNanos != null && message.hasOwnProperty("rollbackEstimatedDtNanos"))
|
||||
if (!$util.isInteger(message.rollbackEstimatedDtNanos) && !(message.rollbackEstimatedDtNanos && $util.isInteger(message.rollbackEstimatedDtNanos.low) && $util.isInteger(message.rollbackEstimatedDtNanos.high)))
|
||||
return "rollbackEstimatedDtNanos: integer|Long expected";
|
||||
return null;
|
||||
};
|
||||
|
||||
@@ -1747,6 +1801,19 @@ $root.treasurehunterx = (function() {
|
||||
message.maxChasingRenderFramesPerUpdate = object.maxChasingRenderFramesPerUpdate | 0;
|
||||
if (object.playerBattleState != null)
|
||||
message.playerBattleState = object.playerBattleState | 0;
|
||||
if (object.rollbackEstimatedDt != null)
|
||||
message.rollbackEstimatedDt = Number(object.rollbackEstimatedDt);
|
||||
if (object.rollbackEstimatedDtMillis != null)
|
||||
message.rollbackEstimatedDtMillis = Number(object.rollbackEstimatedDtMillis);
|
||||
if (object.rollbackEstimatedDtNanos != null)
|
||||
if ($util.Long)
|
||||
(message.rollbackEstimatedDtNanos = $util.Long.fromValue(object.rollbackEstimatedDtNanos)).unsigned = false;
|
||||
else if (typeof object.rollbackEstimatedDtNanos === "string")
|
||||
message.rollbackEstimatedDtNanos = parseInt(object.rollbackEstimatedDtNanos, 10);
|
||||
else if (typeof object.rollbackEstimatedDtNanos === "number")
|
||||
message.rollbackEstimatedDtNanos = object.rollbackEstimatedDtNanos;
|
||||
else if (typeof object.rollbackEstimatedDtNanos === "object")
|
||||
message.rollbackEstimatedDtNanos = new $util.LongBits(object.rollbackEstimatedDtNanos.low >>> 0, object.rollbackEstimatedDtNanos.high >>> 0).toNumber();
|
||||
return message;
|
||||
};
|
||||
|
||||
@@ -1788,6 +1855,13 @@ $root.treasurehunterx = (function() {
|
||||
object.inputFrameUpsyncDelayTolerance = 0;
|
||||
object.maxChasingRenderFramesPerUpdate = 0;
|
||||
object.playerBattleState = 0;
|
||||
object.rollbackEstimatedDt = 0;
|
||||
object.rollbackEstimatedDtMillis = 0;
|
||||
if ($util.Long) {
|
||||
var long = new $util.Long(0, 0, false);
|
||||
object.rollbackEstimatedDtNanos = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
|
||||
} else
|
||||
object.rollbackEstimatedDtNanos = options.longs === String ? "0" : 0;
|
||||
}
|
||||
if (message.stageName != null && message.hasOwnProperty("stageName"))
|
||||
object.stageName = message.stageName;
|
||||
@@ -1835,6 +1909,15 @@ $root.treasurehunterx = (function() {
|
||||
object.maxChasingRenderFramesPerUpdate = message.maxChasingRenderFramesPerUpdate;
|
||||
if (message.playerBattleState != null && message.hasOwnProperty("playerBattleState"))
|
||||
object.playerBattleState = message.playerBattleState;
|
||||
if (message.rollbackEstimatedDt != null && message.hasOwnProperty("rollbackEstimatedDt"))
|
||||
object.rollbackEstimatedDt = options.json && !isFinite(message.rollbackEstimatedDt) ? String(message.rollbackEstimatedDt) : message.rollbackEstimatedDt;
|
||||
if (message.rollbackEstimatedDtMillis != null && message.hasOwnProperty("rollbackEstimatedDtMillis"))
|
||||
object.rollbackEstimatedDtMillis = options.json && !isFinite(message.rollbackEstimatedDtMillis) ? String(message.rollbackEstimatedDtMillis) : message.rollbackEstimatedDtMillis;
|
||||
if (message.rollbackEstimatedDtNanos != null && message.hasOwnProperty("rollbackEstimatedDtNanos"))
|
||||
if (typeof message.rollbackEstimatedDtNanos === "number")
|
||||
object.rollbackEstimatedDtNanos = options.longs === String ? String(message.rollbackEstimatedDtNanos) : message.rollbackEstimatedDtNanos;
|
||||
else
|
||||
object.rollbackEstimatedDtNanos = options.longs === String ? $util.Long.prototype.toString.call(message.rollbackEstimatedDtNanos) : options.longs === Number ? new $util.LongBits(message.rollbackEstimatedDtNanos.low >>> 0, message.rollbackEstimatedDtNanos.high >>> 0).toNumber() : message.rollbackEstimatedDtNanos;
|
||||
return object;
|
||||
};
|
||||
|
||||
|
BIN
screenshot-1.png
Normal file
After Width: | Height: | Size: 430 KiB |
BIN
screenshot-2.png
Normal file
After Width: | Height: | Size: 684 KiB |