Refactored module structure for ease of testing backend colliders.

This commit is contained in:
genxium
2022-10-14 16:08:22 +08:00
parent 286944b88c
commit e762d257a6
35 changed files with 308 additions and 400 deletions

View File

@@ -2,10 +2,10 @@ package api
import (
"bytes"
. "dnmshared"
"github.com/gin-gonic/gin"
"io"
"io/ioutil"
. "server/common"
)
func RequestLogger() gin.HandlerFunc {

View File

@@ -16,6 +16,8 @@ import (
"server/models"
"server/storage"
"strconv"
. "dnmshared"
)
var Player = playerController{}

View File

@@ -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 {

View File

@@ -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()

View File

@@ -1,23 +0,0 @@
package common
import (
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
)
var Logger *zap.Logger
var LoggerConfig zap.Config
func init() {
LoggerConfig = zap.NewDevelopmentConfig()
LoggerConfig.Level.SetLevel(zap.InfoLevel)
LoggerConfig.Development = false
LoggerConfig.Sampling = &zap.SamplingConfig{
Initial: 100,
Thereafter: 100,
}
LoggerConfig.EncoderConfig.EncodeLevel = zapcore.CapitalColorLevelEncoder
var err error
Logger, err = LoggerConfig.Build()
ErrFatal(err)
}

View File

@@ -3,6 +3,7 @@ package utils
import (
"bytes"
"crypto/sha1"
. "dnmshared"
"encoding/json"
"fmt"
"go.uber.org/zap"

View File

@@ -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

View File

@@ -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

View File

@@ -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 {

View File

@@ -20,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 (
@@ -43,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
)

View File

@@ -17,6 +17,8 @@ import (
"syscall"
"time"
. "dnmshared"
"github.com/gin-contrib/cors"
"github.com/gin-gonic/gin"
"github.com/robfig/cron"

View File

@@ -1,5 +1,9 @@
package models
import (
. "dnmshared"
)
type Barrier struct {
Boundary *Polygon2D
}

View File

@@ -1,47 +0,0 @@
package models
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"`
}
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)
}

View File

@@ -1,6 +1,7 @@
package models
import (
. "dnmshared"
pb "server/pb_output"
)

View File

@@ -2,6 +2,7 @@ package models
import (
"database/sql"
. "dnmshared"
"fmt"
sq "github.com/Masterminds/squirrel"
"github.com/jmoiron/sqlx"

View File

@@ -2,7 +2,7 @@ package models
import (
"database/sql"
. "server/common"
. "dnmshared"
"server/storage"
sq "github.com/Masterminds/squirrel"

View File

@@ -2,6 +2,7 @@ package models
import (
"database/sql"
. "dnmshared"
"errors"
. "server/common"
"server/common/utils"

View File

@@ -1,17 +1,14 @@
package models
import (
"encoding/xml"
. "dnmshared"
"fmt"
"github.com/golang/protobuf/proto"
"github.com/gorilla/websocket"
"github.com/solarlune/resolv"
"go.uber.org/zap"
"io/ioutil"
"math"
"math/rand"
"os"
"path/filepath"
. "server/common"
"server/common/utils"
pb "server/pb_output"
@@ -19,6 +16,11 @@ import (
"sync"
"sync/atomic"
"time"
"encoding/xml"
"io/ioutil"
"os"
"path/filepath"
)
const (
@@ -261,7 +263,9 @@ 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"}

View File

@@ -2,9 +2,9 @@ package models
import (
"container/heap"
. "dnmshared"
"fmt"
"go.uber.org/zap"
. "server/common"
"sync"
)

View File

@@ -1,445 +0,0 @@
package models
import (
"bytes"
"compress/zlib"
"encoding/base64"
"encoding/xml"
"errors"
"go.uber.org/zap"
"io/ioutil"
"math"
. "server/common"
"strconv"
"strings"
)
const (
LOW_SCORE_TREASURE_TYPE = 1
HIGH_SCORE_TREASURE_TYPE = 2
SPEED_SHOES_TYPE = 3
LOW_SCORE_TREASURE_SCORE = 100
HIGH_SCORE_TREASURE_SCORE = 200
FLIPPED_HORIZONTALLY_FLAG uint32 = 0x80000000
FLIPPED_VERTICALLY_FLAG uint32 = 0x40000000
FLIPPED_DIAGONALLY_FLAG uint32 = 0x20000000
)
// For either a "*.tmx" or "*.tsx" file. [begins]
type TmxOrTsxProperty struct {
Name string `xml:"name,attr"`
Value string `xml:"value,attr"`
}
type TmxOrTsxProperties struct {
Property []*TmxOrTsxProperty `xml:"property"`
}
type TmxOrTsxPolyline struct {
Points string `xml:"points,attr"`
}
type TmxOrTsxObject struct {
Id int `xml:"id,attr"`
Gid *int `xml:"gid,attr"`
X float64 `xml:"x,attr"`
Y float64 `xml:"y,attr"`
Properties *TmxOrTsxProperties `xml:"properties"`
Polyline *TmxOrTsxPolyline `xml:"polyline"`
Width *float64 `xml:"width,attr"`
Height *float64 `xml:"height,attr"`
}
type TmxOrTsxObjectGroup struct {
Draworder string `xml:"draworder,attr"`
Name string `xml:"name,attr"`
Objects []*TmxOrTsxObject `xml:"object"`
}
type TmxOrTsxImage struct {
Source string `xml:"source,attr"`
Width int `xml:"width,attr"`
Height int `xml:"height,attr"`
}
// For either a "*.tmx" or "*.tsx" file. [ends]
// Within a "*.tsx" file. [begins]
type Tsx struct {
Name string `xml:"name,attr"`
TileWidth int `xml:"tilewidth,attr"`
TileHeight int `xml:"tileheight,attr"`
TileCount int `xml:"tilecount,attr"`
Columns int `xml:"columns,attr"`
Image []*TmxOrTsxImage `xml:"image"`
Tiles []*TsxTile `xml:"tile"`
}
type TsxTile struct {
Id int `xml:"id,attr"`
ObjectGroup *TmxOrTsxObjectGroup `xml:"objectgroup"`
Properties *TmxOrTsxProperties `xml:"properties"`
}
// Within a "*.tsx" file. [ends]
// Within a "*.tmx" file. [begins]
type TmxLayerDecodedTileData struct {
Id uint32
Tileset *TmxTileset
FlipHorizontal bool
FlipVertical bool
FlipDiagonal bool
}
type TmxLayerEncodedData struct {
Encoding string `xml:"encoding,attr"`
Compression string `xml:"compression,attr"`
Value string `xml:",chardata"`
}
type TmxLayer struct {
Name string `xml:"name,attr"`
Width int `xml:"width,attr"`
Height int `xml:"height,attr"`
Data *TmxLayerEncodedData `xml:"data"`
Tile []*TmxLayerDecodedTileData
}
type TmxTileset struct {
FirstGid uint32 `xml:"firstgid,attr"`
Name string `xml:"name,attr"`
TileWidth int `xml:"tilewidth,attr"`
TileHeight int `xml:"tileheight,attr"`
Images []*TmxOrTsxImage `xml:"image"`
Source string `xml:"source,attr"`
}
type TmxMap struct {
Version string `xml:"version,attr"`
Orientation string `xml:"orientation,attr"`
Width int `xml:"width,attr"`
Height int `xml:"height,attr"`
TileWidth int `xml:"tilewidth,attr"`
TileHeight int `xml:"tileheight,attr"`
Properties []*TmxOrTsxProperties `xml:"properties"`
Tilesets []*TmxTileset `xml:"tileset"`
Layers []*TmxLayer `xml:"layer"`
ObjectGroups []*TmxOrTsxObjectGroup `xml:"objectgroup"`
}
// Within a "*.tmx" file. [ends]
func (d *TmxLayerEncodedData) decodeBase64() ([]byte, error) {
r := bytes.NewReader([]byte(strings.TrimSpace(d.Value)))
decr := base64.NewDecoder(base64.StdEncoding, r)
if d.Compression == "zlib" {
rclose, err := zlib.NewReader(decr)
if err != nil {
Logger.Error("tmx data decode zlib error: ", zap.Any("encoding", d.Encoding), zap.Any("compression", d.Compression), zap.Any("value", d.Value))
return nil, err
}
return ioutil.ReadAll(rclose)
}
Logger.Error("tmx data decode invalid compression: ", zap.Any("encoding", d.Encoding), zap.Any("compression", d.Compression), zap.Any("value", d.Value))
return nil, errors.New("Invalid compression.")
}
func (l *TmxLayer) decodeBase64() ([]uint32, error) {
databytes, err := l.Data.decodeBase64()
if err != nil {
return nil, err
}
if l.Width == 0 || l.Height == 0 {
return nil, errors.New("Zero width or height.")
}
if len(databytes) != l.Height*l.Width*4 {
Logger.Error("TmxLayer decodeBase64 invalid data bytes:", zap.Any("width", l.Width), zap.Any("height", l.Height), zap.Any("data lenght", len(databytes)))
return nil, errors.New("Data length error.")
}
dindex := 0
gids := make([]uint32, l.Height*l.Width)
for h := 0; h < l.Height; h++ {
for w := 0; w < l.Width; w++ {
gid := uint32(databytes[dindex]) |
uint32(databytes[dindex+1])<<8 |
uint32(databytes[dindex+2])<<16 |
uint32(databytes[dindex+3])<<24
dindex += 4
gids[h*l.Width+w] = gid
}
}
return gids, nil
}
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".
func tmxPolylineToPolygon2D(pTmxMapIns *TmxMap, singleObjInTmxFile *TmxOrTsxObject, targetPolyline *TmxOrTsxPolyline) (*Polygon2D, error) {
if nil == targetPolyline {
return nil, nil
}
singleValueArray := strings.Split(targetPolyline.Points, " ")
theUntransformedAnchor := &Vec2D{
X: singleObjInTmxFile.X,
Y: singleObjInTmxFile.Y,
}
theTransformedAnchor := pTmxMapIns.continuousObjLayerOffsetToContinuousMapNodePos(theUntransformedAnchor)
thePolygon2DFromPolyline := &Polygon2D{
Anchor: &theTransformedAnchor,
Points: make([]*Vec2D, len(singleValueArray)),
}
for k, value := range singleValueArray {
thePolygon2DFromPolyline.Points[k] = &Vec2D{}
for kk, v := range strings.Split(value, ",") {
coordinateValue, err := strconv.ParseFloat(v, 64)
if nil != err {
panic(err)
}
if 0 == (kk % 2) {
thePolygon2DFromPolyline.Points[k].X = (coordinateValue)
} else {
thePolygon2DFromPolyline.Points[k].Y = (coordinateValue)
}
}
tmp := &Vec2D{
X: thePolygon2DFromPolyline.Points[k].X,
Y: thePolygon2DFromPolyline.Points[k].Y,
}
transformedTmp := pTmxMapIns.continuousObjLayerVecToContinuousMapNodeVec(tmp)
thePolygon2DFromPolyline.Points[k].X = transformedTmp.X
thePolygon2DFromPolyline.Points[k].Y = transformedTmp.Y
}
return thePolygon2DFromPolyline, nil
}
func tsxPolylineToOffsetsWrtTileCenter(pTmxMapIns *TmxMap, singleObjInTsxFile *TmxOrTsxObject, targetPolyline *TmxOrTsxPolyline, pTsxIns *Tsx) (*Polygon2D, error) {
if nil == targetPolyline {
return nil, nil
}
var factorHalf float64 = 0.5
offsetFromTopLeftInTileLocalCoordX := singleObjInTsxFile.X
offsetFromTopLeftInTileLocalCoordY := singleObjInTsxFile.Y
singleValueArray := strings.Split(targetPolyline.Points, " ")
pointsCount := len(singleValueArray)
thePolygon2DFromPolyline := &Polygon2D{
Anchor: nil,
Points: make([]*Vec2D, pointsCount),
TileWidth: pTsxIns.TileWidth,
TileHeight: pTsxIns.TileHeight,
}
/*
[WARNING] In this case, the "Treasure"s and "GuardTower"s are put into Tmx file as "ImageObject"s, of each the "ProportionalAnchor" is (0.5, 0). Therefore the "thePolygon2DFromPolyline.Points" are "offsets w.r.t. the BottomCenter". See https://shimo.im/docs/SmLJJhXm2C8XMzZT for details.
*/
for k, value := range singleValueArray {
thePolygon2DFromPolyline.Points[k] = &Vec2D{}
for kk, v := range strings.Split(value, ",") {
coordinateValue, err := strconv.ParseFloat(v, 64)
if nil != err {
panic(err)
}
if 0 == (kk % 2) {
// W.r.t. center.
thePolygon2DFromPolyline.Points[k].X = (coordinateValue + offsetFromTopLeftInTileLocalCoordX) - factorHalf*float64(pTsxIns.TileWidth)
} else {
// W.r.t. bottom.
thePolygon2DFromPolyline.Points[k].Y = float64(pTsxIns.TileHeight) - (coordinateValue + offsetFromTopLeftInTileLocalCoordY)
}
}
}
return thePolygon2DFromPolyline, nil
}
func DeserializeTsxToColliderDict(pTmxMapIns *TmxMap, byteArrOfTsxFile []byte, firstGid int, gidBoundariesMap map[int]StrToPolygon2DListMap) error {
pTsxIns := &Tsx{}
err := xml.Unmarshal(byteArrOfTsxFile, pTsxIns)
if nil != err {
panic(err)
}
/*
// For debug-printing only. -- YFLu, 2019-09-04.
reserializedTmxMap, err := pTmxMapIns.ToXML()
if nil != err {
panic(err)
}
*/
for _, tile := range pTsxIns.Tiles {
globalGid := (firstGid + int(tile.Id))
/**
A tile xml string could be
```
<tile id="13">
<objectgroup draworder="index">
<object id="1" x="-154" y="-159">
<properties>
<property name="boundary_type" value="guardTower"/>
</properties>
<polyline points="0,0 -95,179 18,407 361,434 458,168 333,-7"/>
</object>
</objectgroup>
</tile>
```
, we currently REQUIRE that "`an object of a tile` with ONE OR MORE polylines must come with a single corresponding '<property name=`type` value=`...` />', and viceversa".
Refer to https://shimo.im/docs/SmLJJhXm2C8XMzZT for how we theoretically fit a "Polyline in Tsx" into a "Polygon2D".
*/
theObjGroup := tile.ObjectGroup
if nil == theObjGroup {
continue
}
for _, singleObj := range theObjGroup.Objects {
if nil == singleObj.Polyline {
// Temporarily omit those non-polyline-containing objects.
continue
}
if nil == singleObj.Properties.Property || "boundary_type" != singleObj.Properties.Property[0].Name {
continue
}
key := singleObj.Properties.Property[0].Value
var theStrToPolygon2DListMap StrToPolygon2DListMap
if existingStrToPolygon2DListMap, ok := gidBoundariesMap[globalGid]; ok {
theStrToPolygon2DListMap = existingStrToPolygon2DListMap
} else {
gidBoundariesMap[globalGid] = make(StrToPolygon2DListMap, 0)
theStrToPolygon2DListMap = gidBoundariesMap[globalGid]
}
var pThePolygon2DList *Polygon2DList
if _, ok := theStrToPolygon2DListMap[key]; ok {
pThePolygon2DList = theStrToPolygon2DListMap[key]
} else {
thePolygon2DList := make(Polygon2DList, 0)
theStrToPolygon2DListMap[key] = &thePolygon2DList
pThePolygon2DList = theStrToPolygon2DListMap[key]
}
thePolygon2DFromPolyline, err := tsxPolylineToOffsetsWrtTileCenter(pTmxMapIns, singleObj, singleObj.Polyline, pTsxIns)
if nil != err {
panic(err)
}
*pThePolygon2DList = append(*pThePolygon2DList, thePolygon2DFromPolyline)
}
}
return nil
}
func ParseTmxLayersAndGroups(pTmxMapIns *TmxMap, gidBoundariesMap map[int]StrToPolygon2DListMap) (int32, int32, int32, int32, StrToVec2DListMap, StrToPolygon2DListMap, error) {
toRetStrToVec2DListMap := make(StrToVec2DListMap, 0)
toRetStrToPolygon2DListMap := make(StrToPolygon2DListMap, 0)
for _, objGroup := range pTmxMapIns.ObjectGroups {
switch objGroup.Name {
case "PlayerStartingPos":
var pTheVec2DListToCache *Vec2DList
_, ok := toRetStrToVec2DListMap[objGroup.Name]
if false == ok {
theVec2DListToCache := make(Vec2DList, 0)
toRetStrToVec2DListMap[objGroup.Name] = &theVec2DListToCache
}
pTheVec2DListToCache = toRetStrToVec2DListMap[objGroup.Name]
for _, singleObjInTmxFile := range objGroup.Objects {
theUntransformedPos := &Vec2D{
X: singleObjInTmxFile.X,
Y: singleObjInTmxFile.Y,
}
thePosInWorld := pTmxMapIns.continuousObjLayerOffsetToContinuousMapNodePos(theUntransformedPos)
*pTheVec2DListToCache = append(*pTheVec2DListToCache, &thePosInWorld)
}
case "Barrier":
// Note that in this case, the "Polygon2D.Anchor" of each "TmxOrTsxObject" is exactly overlapping with "Polygon2D.Points[0]".
var pThePolygon2DListToCache *Polygon2DList
_, ok := toRetStrToPolygon2DListMap[objGroup.Name]
if false == ok {
thePolygon2DListToCache := make(Polygon2DList, 0)
toRetStrToPolygon2DListMap[objGroup.Name] = &thePolygon2DListToCache
}
pThePolygon2DListToCache = toRetStrToPolygon2DListMap[objGroup.Name]
for _, singleObjInTmxFile := range objGroup.Objects {
if nil == singleObjInTmxFile.Polyline {
continue
}
if nil == singleObjInTmxFile.Properties.Property || "boundary_type" != singleObjInTmxFile.Properties.Property[0].Name || "barrier" != singleObjInTmxFile.Properties.Property[0].Value {
continue
}
thePolygon2DInWorld, err := tmxPolylineToPolygon2D(pTmxMapIns, singleObjInTmxFile, singleObjInTmxFile.Polyline)
if nil != err {
panic(err)
}
*pThePolygon2DListToCache = append(*pThePolygon2DListToCache, thePolygon2DInWorld)
}
default:
}
}
return int32(pTmxMapIns.Width), int32(pTmxMapIns.Height), int32(pTmxMapIns.TileWidth), int32(pTmxMapIns.TileHeight), toRetStrToVec2DListMap, toRetStrToPolygon2DListMap, nil
}
func (pTmxMap *TmxMap) ToXML() (string, error) {
ret, err := xml.Marshal(pTmxMap)
return string(ret[:]), err
}
type TileRectilinearSize struct {
Width float64
Height float64
}
func (pTmxMapIns *TmxMap) continuousObjLayerVecToContinuousMapNodeVec(continuousObjLayerVec *Vec2D) Vec2D {
var tileRectilinearSize TileRectilinearSize
tileRectilinearSize.Width = float64(pTmxMapIns.TileWidth)
tileRectilinearSize.Height = float64(pTmxMapIns.TileHeight)
tileSizeUnifiedLength := math.Sqrt(tileRectilinearSize.Width*tileRectilinearSize.Width*0.25 + tileRectilinearSize.Height*tileRectilinearSize.Height*0.25)
isometricObjectLayerPointOffsetScaleFactor := (tileSizeUnifiedLength / tileRectilinearSize.Height)
cosineThetaRadian := (tileRectilinearSize.Width * 0.5) / tileSizeUnifiedLength
sineThetaRadian := (tileRectilinearSize.Height * 0.5) / tileSizeUnifiedLength
transMat := [...][2]float64{
{isometricObjectLayerPointOffsetScaleFactor * cosineThetaRadian, -isometricObjectLayerPointOffsetScaleFactor * cosineThetaRadian},
{-isometricObjectLayerPointOffsetScaleFactor * sineThetaRadian, -isometricObjectLayerPointOffsetScaleFactor * sineThetaRadian},
}
convertedVecX := transMat[0][0]*continuousObjLayerVec.X + transMat[0][1]*continuousObjLayerVec.Y
convertedVecY := transMat[1][0]*continuousObjLayerVec.X + transMat[1][1]*continuousObjLayerVec.Y
converted := Vec2D{
X: convertedVecX,
Y: convertedVecY,
}
return converted
}
func (pTmxMapIns *TmxMap) continuousObjLayerOffsetToContinuousMapNodePos(continuousObjLayerOffset *Vec2D) Vec2D {
layerOffset := Vec2D{
X: 0,
Y: float64(pTmxMapIns.Height*pTmxMapIns.TileHeight) * 0.5,
}
calibratedVec := continuousObjLayerOffset
convertedVec := pTmxMapIns.continuousObjLayerVecToContinuousMapNodeVec(calibratedVec)
toRet := Vec2D{
X: layerOffset.X + convertedVec.X,
Y: layerOffset.Y + convertedVec.Y,
}
return toRet
}

View File

@@ -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))
}

View File

@@ -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))
}

View File

@@ -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{}

View File

@@ -14,6 +14,8 @@ import (
"strconv"
"sync/atomic"
"time"
. "dnmshared"
)
const (