mirror of
https://github.com/genxium/DelayNoMore
synced 2024-12-26 11:48:56 +00:00
Fixed some trivial runtime errors.
This commit is contained in:
parent
a2a8be9068
commit
cd83539197
@ -348,7 +348,7 @@ func (pR *Room) EncodeUpsyncCmd(upsyncCmd *pb.InputFrameUpsync) uint64 {
|
|||||||
|
|
||||||
func (pR *Room) AllPlayerInputsBufferString() string {
|
func (pR *Room) AllPlayerInputsBufferString() string {
|
||||||
s := make([]string, 0)
|
s := make([]string, 0)
|
||||||
s = append(s, fmt.Sprintf("{lastAllConfirmedInputFrameId: %v, lastAllConfirmedInputFrameIdWithChange: %v}", pR.LastAllConfirmedInputFrameId, pR.LastAllConfirmedInputFrameIdWithChange))
|
s = append(s, fmt.Sprintf("\n{stInputFrameId: %v, edInputFrameId: %v, lastAllConfirmedInputFrameIdWithChange: %v, lastAllConfirmedInputFrameId: %v}", pR.AllPlayerInputsBuffer.StFrameId, pR.AllPlayerInputsBuffer.EdFrameId, pR.LastAllConfirmedInputFrameIdWithChange, pR.LastAllConfirmedInputFrameId))
|
||||||
for playerId, player := range pR.Players {
|
for playerId, player := range pR.Players {
|
||||||
s = append(s, fmt.Sprintf("{playerId: %v, ackingFrameId: %v, ackingInputFrameId: %v, lastSentInputFrameId: %v}", playerId, player.AckingFrameId, player.AckingInputFrameId, player.LastSentInputFrameId))
|
s = append(s, fmt.Sprintf("{playerId: %v, ackingFrameId: %v, ackingInputFrameId: %v, lastSentInputFrameId: %v}", playerId, player.AckingFrameId, player.AckingInputFrameId, player.LastSentInputFrameId))
|
||||||
}
|
}
|
||||||
@ -456,7 +456,7 @@ func (pR *Room) StartBattle() {
|
|||||||
toSendInputFrames := make([]*pb.InputFrameDownsync, 0, pR.AllPlayerInputsBuffer.Cnt)
|
toSendInputFrames := make([]*pb.InputFrameDownsync, 0, pR.AllPlayerInputsBuffer.Cnt)
|
||||||
candidateToSendInputFrameId := atomic.LoadInt32(&(pR.Players[playerId].LastSentInputFrameId)) + 1
|
candidateToSendInputFrameId := atomic.LoadInt32(&(pR.Players[playerId].LastSentInputFrameId)) + 1
|
||||||
if candidateToSendInputFrameId < pR.AllPlayerInputsBuffer.StFrameId {
|
if candidateToSendInputFrameId < pR.AllPlayerInputsBuffer.StFrameId {
|
||||||
Logger.Warn("LastSentInputFrameId already popped:", zap.Any("roomId", pR.Id), zap.Any("playerId", playerId), zap.Any("lastSentInputFrameId", candidateToSendInputFrameId-1), zap.Any("playerAckingInputFrameId", player.AckingInputFrameId), zap.Any("AllPlayerInputsBuffer", pR.AllPlayerInputsBufferString()))
|
Logger.Warn(fmt.Sprintf("LastSentInputFrameId already popped: roomId=%v, playerId=%v, lastSentInputFrameId=%v, playerAckingInputFrameId=%v, AllPlayerInputsBuffer=%v", pR.Id, playerId, candidateToSendInputFrameId-1, player.AckingInputFrameId, pR.AllPlayerInputsBufferString()))
|
||||||
candidateToSendInputFrameId = pR.AllPlayerInputsBuffer.StFrameId
|
candidateToSendInputFrameId = pR.AllPlayerInputsBuffer.StFrameId
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -534,7 +534,7 @@ func (pR *Room) OnBattleCmdReceived(pReq *pb.WsReq) {
|
|||||||
ackingInputFrameId := pReq.AckingInputFrameId
|
ackingInputFrameId := pReq.AckingInputFrameId
|
||||||
|
|
||||||
if _, existent := pR.Players[playerId]; !existent {
|
if _, existent := pR.Players[playerId]; !existent {
|
||||||
Logger.Warn("upcmd player doesn't exist:", zap.Any("roomId", pR.Id), zap.Any("playerId", playerId))
|
Logger.Warn(fmt.Sprintf("upcmd player doesn't exist: roomId=%v, playerId=%v", pR.Id, playerId))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -549,7 +549,7 @@ func (pR *Room) OnBattleCmdReceived(pReq *pb.WsReq) {
|
|||||||
for _, inputFrameUpsync := range inputFrameUpsyncBatch {
|
for _, inputFrameUpsync := range inputFrameUpsyncBatch {
|
||||||
clientInputFrameId := inputFrameUpsync.InputFrameId
|
clientInputFrameId := inputFrameUpsync.InputFrameId
|
||||||
if clientInputFrameId < pR.AllPlayerInputsBuffer.StFrameId {
|
if clientInputFrameId < pR.AllPlayerInputsBuffer.StFrameId {
|
||||||
Logger.Warn("Obsolete inputFrameUpsync:", zap.Any("roomId", pR.Id), zap.Any("playerId", playerId), zap.Any("clientInputFrameId", clientInputFrameId), zap.Any("StFrameId", pR.AllPlayerInputsBuffer.StFrameId), zap.Any("EdFrameId", pR.AllPlayerInputsBuffer.EdFrameId))
|
Logger.Warn(fmt.Sprintf("Obsolete inputFrameUpsync: roomId=%v, playerId=%v, clientInputFrameId=%v, AllPlayerInputsBuffer=%v", pR.Id, playerId, clientInputFrameId, pR.AllPlayerInputsBufferString()))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -557,36 +557,36 @@ func (pR *Room) OnBattleCmdReceived(pReq *pb.WsReq) {
|
|||||||
encodedInput := pR.EncodeUpsyncCmd(inputFrameUpsync)
|
encodedInput := pR.EncodeUpsyncCmd(inputFrameUpsync)
|
||||||
|
|
||||||
if clientInputFrameId >= pR.AllPlayerInputsBuffer.EdFrameId {
|
if clientInputFrameId >= pR.AllPlayerInputsBuffer.EdFrameId {
|
||||||
Logger.Warn("inputFrame too advanced! is the player cheating?", zap.Any("roomId", pR.Id), zap.Any("playerId", playerId), zap.Any("inputFrameId", clientInputFrameId), zap.Any("EdFrameId", pR.AllPlayerInputsBuffer.EdFrameId))
|
Logger.Warn(fmt.Sprintf("inputFrame too advanced! is the player cheating?: roomId=%v, playerId=%v, clientInputFrameId=%v, AllPlayerInputsBuffer=%v", pR.Id, playerId, clientInputFrameId, pR.AllPlayerInputsBufferString()))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
tmp2 := pR.AllPlayerInputsBuffer.GetByFrameId(clientInputFrameId)
|
tmp2 := pR.AllPlayerInputsBuffer.GetByFrameId(clientInputFrameId)
|
||||||
if nil == tmp2 {
|
if nil == tmp2 {
|
||||||
// This shouldn't happen due to the previous 2 checks
|
// This shouldn't happen due to the previous 2 checks
|
||||||
Logger.Warn("Mysterious error getting an input frame:", zap.Any("roomId", pR.Id), zap.Any("playerId", playerId), zap.Any("clientInputFrameId", clientInputFrameId), zap.Any("StFrameId", pR.AllPlayerInputsBuffer.StFrameId), zap.Any("EdFrameId", pR.AllPlayerInputsBuffer.EdFrameId))
|
Logger.Warn(fmt.Sprintf("Mysterious error getting an input frame: roomId=%v, playerId=%v, clientInputFrameId=%v, AllPlayerInputsBuffer=%v", pR.Id, playerId, clientInputFrameId, pR.AllPlayerInputsBufferString()))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
inputFrameDownsync := tmp2.(*pb.InputFrameDownsync)
|
inputFrameDownsync := tmp2.(*pb.InputFrameDownsync)
|
||||||
oldConfirmedList := atomic.LoadUint64(&(inputFrameDownsync.ConfirmedList))
|
oldConfirmedList := atomic.LoadUint64(&(inputFrameDownsync.ConfirmedList))
|
||||||
if (oldConfirmedList & joinMask) > 0 {
|
if (oldConfirmedList & joinMask) > 0 {
|
||||||
Logger.Warn("Cmd already confirmed but getting set attempt, omitting this upsync cmd:", zap.Any("roomId", pR.Id), zap.Any("playerId", playerId), zap.Any("clientInputFrameId", clientInputFrameId), zap.Any("StFrameId", pR.AllPlayerInputsBuffer.StFrameId), zap.Any("EdFrameId", pR.AllPlayerInputsBuffer.EdFrameId))
|
Logger.Warn(fmt.Sprintf("Cmd already confirmed but getting set attempt, omitting this upsync cmd: roomId=%v, playerId=%v, clientInputFrameId=%v, AllPlayerInputsBuffer=%v", pR.Id, playerId, clientInputFrameId, pR.AllPlayerInputsBufferString()))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// In Golang 1.12, there's no "compare-and-swap primitive" on a custom struct (or it's pointer, unless it's an unsafe pointer https://pkg.go.dev/sync/atomic@go1.12#CompareAndSwapPointer). Although CAS on custom struct is possible in Golang 1.19 https://pkg.go.dev/sync/atomic@go1.19.1#Value.CompareAndSwap, using a single word is still faster whenever possible.
|
// In Golang 1.12, there's no "compare-and-swap primitive" on a custom struct (or it's pointer, unless it's an unsafe pointer https://pkg.go.dev/sync/atomic@go1.12#CompareAndSwapPointer). Although CAS on custom struct is possible in Golang 1.19 https://pkg.go.dev/sync/atomic@go1.19.1#Value.CompareAndSwap, using a single word is still faster whenever possible.
|
||||||
if swapped := atomic.CompareAndSwapUint64(&inputFrameDownsync.InputList[indiceInJoinIndexBooleanArr], uint64(0), encodedInput); !swapped {
|
if swapped := atomic.CompareAndSwapUint64(&inputFrameDownsync.InputList[indiceInJoinIndexBooleanArr], uint64(0), encodedInput); !swapped {
|
||||||
Logger.Warn("Failed input CAS:", zap.Any("roomId", pR.Id), zap.Any("playerId", playerId), zap.Any("clientInputFrameId", clientInputFrameId))
|
Logger.Warn(fmt.Sprintf("Failed input CAS: roomId=%v, playerId=%v, clientInputFrameId=%v", pR.Id, playerId, clientInputFrameId))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
newConfirmedList := (oldConfirmedList | joinMask)
|
newConfirmedList := (oldConfirmedList | joinMask)
|
||||||
if swapped := atomic.CompareAndSwapUint64(&(inputFrameDownsync.ConfirmedList), oldConfirmedList, newConfirmedList); !swapped {
|
if swapped := atomic.CompareAndSwapUint64(&(inputFrameDownsync.ConfirmedList), oldConfirmedList, newConfirmedList); !swapped {
|
||||||
// [WARNING] Upon this error, the actual input has already been updated, which is an expected result if it caused by the force confirmation from "battleMainLoop".
|
// [WARNING] Upon this error, the actual input has already been updated, which is an expected result if it caused by the force confirmation from "battleMainLoop".
|
||||||
Logger.Warn("Failed confirm CAS:", zap.Any("roomId", pR.Id), zap.Any("playerId", playerId), zap.Any("clientInputFrameId", clientInputFrameId))
|
Logger.Warn(fmt.Sprintf("Failed confirm CAS: roomId=%v, playerId=%v, clientInputFrameId=%v", pR.Id, playerId, clientInputFrameId))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
totPlayerCnt := uint32(len(pR.Players))
|
totPlayerCnt := uint32(pR.Capacity)
|
||||||
allConfirmedMask := uint64((1 << totPlayerCnt) - 1)
|
allConfirmedMask := uint64((1 << totPlayerCnt) - 1)
|
||||||
if allConfirmedMask == newConfirmedList {
|
if allConfirmedMask == newConfirmedList {
|
||||||
pR.onInputFrameDownsyncAllConfirmed(inputFrameDownsync, playerId)
|
pR.onInputFrameDownsyncAllConfirmed(inputFrameDownsync, playerId)
|
||||||
@ -598,7 +598,7 @@ func (pR *Room) onInputFrameDownsyncAllConfirmed(inputFrameDownsync *pb.InputFra
|
|||||||
clientInputFrameId := inputFrameDownsync.InputFrameId
|
clientInputFrameId := inputFrameDownsync.InputFrameId
|
||||||
if false == pR.equalInputLists(inputFrameDownsync.InputList, pR.LastAllConfirmedInputList) {
|
if false == pR.equalInputLists(inputFrameDownsync.InputList, pR.LastAllConfirmedInputList) {
|
||||||
atomic.StoreInt32(&(pR.LastAllConfirmedInputFrameIdWithChange), clientInputFrameId) // [WARNING] Different from the CAS in "battleMainLoop", it's safe to just update "pR.LastAllConfirmedInputFrameIdWithChange" here, because only monotonic increment is possible here!
|
atomic.StoreInt32(&(pR.LastAllConfirmedInputFrameIdWithChange), clientInputFrameId) // [WARNING] Different from the CAS in "battleMainLoop", it's safe to just update "pR.LastAllConfirmedInputFrameIdWithChange" here, because only monotonic increment is possible here!
|
||||||
Logger.Info("Key inputFrame change", zap.Any("roomId", pR.Id), zap.Any("inputFrameId", clientInputFrameId), zap.Any("lastInputFrameId", pR.LastAllConfirmedInputFrameId), zap.Any("AllPlayerInputsBuffer", pR.AllPlayerInputsBufferString()), zap.Any("newInputList", inputFrameDownsync.InputList), zap.Any("lastInputList", pR.LastAllConfirmedInputList))
|
Logger.Info(fmt.Sprintf("Key inputFrame change: roomId=%v, playerId=%v, clientInputFrameId=%v, lastInputFrameId=%v, newInputList=%v, lastInputList=%v, AllPlayerInputsBuffer=%v", pR.Id, playerId, clientInputFrameId, pR.LastAllConfirmedInputFrameId, inputFrameDownsync.InputList, pR.LastAllConfirmedInputList, pR.AllPlayerInputsBufferString()))
|
||||||
}
|
}
|
||||||
atomic.StoreInt32(&(pR.LastAllConfirmedInputFrameId), clientInputFrameId) // [WARNING] It's IMPORTANT that "pR.LastAllConfirmedInputFrameId" is NOT NECESSARILY CONSECUTIVE, i.e. if one of the players disconnects and reconnects within a considerable amount of frame delays!
|
atomic.StoreInt32(&(pR.LastAllConfirmedInputFrameId), clientInputFrameId) // [WARNING] It's IMPORTANT that "pR.LastAllConfirmedInputFrameId" is NOT NECESSARILY CONSECUTIVE, i.e. if one of the players disconnects and reconnects within a considerable amount of frame delays!
|
||||||
for i, v := range inputFrameDownsync.InputList {
|
for i, v := range inputFrameDownsync.InputList {
|
||||||
@ -606,7 +606,7 @@ func (pR *Room) onInputFrameDownsyncAllConfirmed(inputFrameDownsync *pb.InputFra
|
|||||||
pR.LastAllConfirmedInputList[i] = v
|
pR.LastAllConfirmedInputList[i] = v
|
||||||
}
|
}
|
||||||
if pR.inputFrameIdDebuggable(clientInputFrameId) {
|
if pR.inputFrameIdDebuggable(clientInputFrameId) {
|
||||||
Logger.Info("inputFrame lifecycle#2[allconfirmed]", zap.Any("roomId", pR.Id), zap.Any("playerId", playerId), zap.Any("inputFrameId", clientInputFrameId), zap.Any("AllPlayerInputsBuffer", pR.AllPlayerInputsBufferString()))
|
Logger.Info(fmt.Sprintf("inputFrame lifecycle#2[allconfirmed]: roomId=%v, playerId=%v, clientInputFrameId=%v, AllPlayerInputsBuffer=%v", pR.Id, playerId, clientInputFrameId, pR.LastAllConfirmedInputFrameId, pR.AllPlayerInputsBufferString()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1074,7 +1074,7 @@ func (pR *Room) applyInputFrameDownsyncDynamics(fromRenderFrameId int32, toRende
|
|||||||
if nil == tmp {
|
if nil == tmp {
|
||||||
panic(fmt.Sprintf("delayedInputFrameId=%v doesn't exist for roomId=%v, this is abnormal because it's to be used for applying dynamics to [fromRenderFrameId:%v, toRenderFrameId:%v) @ collisionSysRenderFrameId=%v! AllPlayerInputsBuffer=%v", delayedInputFrameId, pR.Id, fromRenderFrameId, toRenderFrameId, collisionSysRenderFrameId, pR.AllPlayerInputsBufferString()))
|
panic(fmt.Sprintf("delayedInputFrameId=%v doesn't exist for roomId=%v, this is abnormal because it's to be used for applying dynamics to [fromRenderFrameId:%v, toRenderFrameId:%v) @ collisionSysRenderFrameId=%v! AllPlayerInputsBuffer=%v", delayedInputFrameId, pR.Id, fromRenderFrameId, toRenderFrameId, collisionSysRenderFrameId, pR.AllPlayerInputsBufferString()))
|
||||||
}
|
}
|
||||||
delayedInputFrame := tmp.(pb.InputFrameDownsync)
|
delayedInputFrame := tmp.(*pb.InputFrameDownsync)
|
||||||
if swapped := atomic.CompareAndSwapUint64(&(delayedInputFrame.ConfirmedList), allConfirmedMask, allConfirmedMask); !swapped {
|
if swapped := atomic.CompareAndSwapUint64(&(delayedInputFrame.ConfirmedList), allConfirmedMask, allConfirmedMask); !swapped {
|
||||||
panic(fmt.Sprintf("delayedInputFrameId=%v is not yet all-confirmed for roomId=%v, this is abnormal because it's to be used for applying dynamics to [fromRenderFrameId:%v, toRenderFrameId:%v) @ collisionSysRenderFrameId=%v! AllPlayerInputsBuffer=%v", delayedInputFrameId, pR.Id, fromRenderFrameId, toRenderFrameId, collisionSysRenderFrameId, pR.AllPlayerInputsBufferString()))
|
panic(fmt.Sprintf("delayedInputFrameId=%v is not yet all-confirmed for roomId=%v, this is abnormal because it's to be used for applying dynamics to [fromRenderFrameId:%v, toRenderFrameId:%v) @ collisionSysRenderFrameId=%v! AllPlayerInputsBuffer=%v", delayedInputFrameId, pR.Id, fromRenderFrameId, toRenderFrameId, collisionSysRenderFrameId, pR.AllPlayerInputsBufferString()))
|
||||||
}
|
}
|
||||||
|
@ -6,8 +6,6 @@ import (
|
|||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"encoding/xml"
|
"encoding/xml"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
|
||||||
"github.com/ByteArena/box2d"
|
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"math"
|
"math"
|
||||||
@ -181,17 +179,12 @@ 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 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 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 TmxPolylineToPolygon2DInB2World(pTmxMapIns *TmxMap, singleObjInTmxFile *TmxOrTsxObject, targetPolyline *TmxOrTsxPolyline) (*Polygon2D, error) {
|
func tmxPolylineToPolygon2D(pTmxMapIns *TmxMap, singleObjInTmxFile *TmxOrTsxObject, targetPolyline *TmxOrTsxPolyline) (*Polygon2D, error) {
|
||||||
if nil == targetPolyline {
|
if nil == targetPolyline {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
singleValueArray := strings.Split(targetPolyline.Points, " ")
|
singleValueArray := strings.Split(targetPolyline.Points, " ")
|
||||||
pointsCount := len(singleValueArray)
|
|
||||||
|
|
||||||
if pointsCount >= box2d.B2_maxPolygonVertices {
|
|
||||||
return nil, errors.New(fmt.Sprintf("During `TmxPolylineToPolygon2DInB2World`, you have a polygon with pointsCount == %v, exceeding or equal to box2d.B2_maxPolygonVertices == %v, of polyines [%v]", pointsCount, box2d.B2_maxPolygonVertices, singleValueArray))
|
|
||||||
}
|
|
||||||
|
|
||||||
theUntransformedAnchor := &Vec2D{
|
theUntransformedAnchor := &Vec2D{
|
||||||
X: singleObjInTmxFile.X,
|
X: singleObjInTmxFile.X,
|
||||||
@ -217,7 +210,6 @@ func TmxPolylineToPolygon2DInB2World(pTmxMapIns *TmxMap, singleObjInTmxFile *Tmx
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Transform to B2World space coordinate.
|
|
||||||
tmp := &Vec2D{
|
tmp := &Vec2D{
|
||||||
X: thePolygon2DFromPolyline.Points[k].X,
|
X: thePolygon2DFromPolyline.Points[k].X,
|
||||||
Y: thePolygon2DFromPolyline.Points[k].Y,
|
Y: thePolygon2DFromPolyline.Points[k].Y,
|
||||||
@ -230,7 +222,7 @@ func TmxPolylineToPolygon2DInB2World(pTmxMapIns *TmxMap, singleObjInTmxFile *Tmx
|
|||||||
return thePolygon2DFromPolyline, nil
|
return thePolygon2DFromPolyline, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func TsxPolylineToOffsetsWrtTileCenterInB2World(pTmxMapIns *TmxMap, singleObjInTsxFile *TmxOrTsxObject, targetPolyline *TmxOrTsxPolyline, pTsxIns *Tsx) (*Polygon2D, error) {
|
func tsxPolylineToOffsetsWrtTileCenter(pTmxMapIns *TmxMap, singleObjInTsxFile *TmxOrTsxObject, targetPolyline *TmxOrTsxPolyline, pTsxIns *Tsx) (*Polygon2D, error) {
|
||||||
if nil == targetPolyline {
|
if nil == targetPolyline {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
@ -241,10 +233,6 @@ func TsxPolylineToOffsetsWrtTileCenterInB2World(pTmxMapIns *TmxMap, singleObjInT
|
|||||||
singleValueArray := strings.Split(targetPolyline.Points, " ")
|
singleValueArray := strings.Split(targetPolyline.Points, " ")
|
||||||
pointsCount := len(singleValueArray)
|
pointsCount := len(singleValueArray)
|
||||||
|
|
||||||
if pointsCount >= box2d.B2_maxPolygonVertices {
|
|
||||||
return nil, errors.New(fmt.Sprintf("During `TsxPolylineToOffsetsWrtTileCenterInB2World`, you have a polygon with pointsCount == %v, exceeding or equal to box2d.B2_maxPolygonVertices == %v", pointsCount, box2d.B2_maxPolygonVertices))
|
|
||||||
}
|
|
||||||
|
|
||||||
thePolygon2DFromPolyline := &Polygon2D{
|
thePolygon2DFromPolyline := &Polygon2D{
|
||||||
Anchor: nil,
|
Anchor: nil,
|
||||||
Points: make([]*Vec2D, pointsCount),
|
Points: make([]*Vec2D, pointsCount),
|
||||||
@ -253,7 +241,7 @@ func TsxPolylineToOffsetsWrtTileCenterInB2World(pTmxMapIns *TmxMap, singleObjInT
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
[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 we calculate that "thePolygon2DFromPolyline.Points" are "offsets(in B2World) w.r.t. the BottomCenter". See https://shimo.im/docs/SmLJJhXm2C8XMzZT for details.
|
[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 {
|
for k, value := range singleValueArray {
|
||||||
@ -271,14 +259,12 @@ func TsxPolylineToOffsetsWrtTileCenterInB2World(pTmxMapIns *TmxMap, singleObjInT
|
|||||||
thePolygon2DFromPolyline.Points[k].Y = float64(pTsxIns.TileHeight) - (coordinateValue + offsetFromTopLeftInTileLocalCoordY)
|
thePolygon2DFromPolyline.Points[k].Y = float64(pTsxIns.TileHeight) - (coordinateValue + offsetFromTopLeftInTileLocalCoordY)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// No need to transform for B2World space coordinate because the marks in a Tsx file is already rectilinear.
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return thePolygon2DFromPolyline, nil
|
return thePolygon2DFromPolyline, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func DeserializeTsxToColliderDict(pTmxMapIns *TmxMap, byteArrOfTsxFile []byte, firstGid int, gidBoundariesMapInB2World map[int]StrToPolygon2DListMap) error {
|
func DeserializeTsxToColliderDict(pTmxMapIns *TmxMap, byteArrOfTsxFile []byte, firstGid int, gidBoundariesMap map[int]StrToPolygon2DListMap) error {
|
||||||
pTsxIns := &Tsx{}
|
pTsxIns := &Tsx{}
|
||||||
err := xml.Unmarshal(byteArrOfTsxFile, pTsxIns)
|
err := xml.Unmarshal(byteArrOfTsxFile, pTsxIns)
|
||||||
if nil != err {
|
if nil != err {
|
||||||
@ -312,7 +298,7 @@ func DeserializeTsxToColliderDict(pTmxMapIns *TmxMap, byteArrOfTsxFile []byte, f
|
|||||||
```
|
```
|
||||||
, 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".
|
, 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" and then into the corresponding "B2BodyDef & B2Body in the `world of colliding bodies`".
|
Refer to https://shimo.im/docs/SmLJJhXm2C8XMzZT for how we theoretically fit a "Polyline in Tsx" into a "Polygon2D".
|
||||||
*/
|
*/
|
||||||
|
|
||||||
theObjGroup := tile.ObjectGroup
|
theObjGroup := tile.ObjectGroup
|
||||||
@ -331,11 +317,11 @@ func DeserializeTsxToColliderDict(pTmxMapIns *TmxMap, byteArrOfTsxFile []byte, f
|
|||||||
key := singleObj.Properties.Property[0].Value
|
key := singleObj.Properties.Property[0].Value
|
||||||
|
|
||||||
var theStrToPolygon2DListMap StrToPolygon2DListMap
|
var theStrToPolygon2DListMap StrToPolygon2DListMap
|
||||||
if existingStrToPolygon2DListMap, ok := gidBoundariesMapInB2World[globalGid]; ok {
|
if existingStrToPolygon2DListMap, ok := gidBoundariesMap[globalGid]; ok {
|
||||||
theStrToPolygon2DListMap = existingStrToPolygon2DListMap
|
theStrToPolygon2DListMap = existingStrToPolygon2DListMap
|
||||||
} else {
|
} else {
|
||||||
gidBoundariesMapInB2World[globalGid] = make(StrToPolygon2DListMap, 0)
|
gidBoundariesMap[globalGid] = make(StrToPolygon2DListMap, 0)
|
||||||
theStrToPolygon2DListMap = gidBoundariesMapInB2World[globalGid]
|
theStrToPolygon2DListMap = gidBoundariesMap[globalGid]
|
||||||
}
|
}
|
||||||
|
|
||||||
var pThePolygon2DList *Polygon2DList
|
var pThePolygon2DList *Polygon2DList
|
||||||
@ -347,7 +333,7 @@ func DeserializeTsxToColliderDict(pTmxMapIns *TmxMap, byteArrOfTsxFile []byte, f
|
|||||||
pThePolygon2DList = theStrToPolygon2DListMap[key]
|
pThePolygon2DList = theStrToPolygon2DListMap[key]
|
||||||
}
|
}
|
||||||
|
|
||||||
thePolygon2DFromPolyline, err := TsxPolylineToOffsetsWrtTileCenterInB2World(pTmxMapIns, singleObj, singleObj.Polyline, pTsxIns)
|
thePolygon2DFromPolyline, err := tsxPolylineToOffsetsWrtTileCenter(pTmxMapIns, singleObj, singleObj.Polyline, pTsxIns)
|
||||||
if nil != err {
|
if nil != err {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
@ -357,16 +343,9 @@ func DeserializeTsxToColliderDict(pTmxMapIns *TmxMap, byteArrOfTsxFile []byte, f
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func ParseTmxLayersAndGroups(pTmxMapIns *TmxMap, gidBoundariesMapInB2World map[int]StrToPolygon2DListMap) (int32, int32, int32, int32, StrToVec2DListMap, StrToPolygon2DListMap, error) {
|
func ParseTmxLayersAndGroups(pTmxMapIns *TmxMap, gidBoundariesMap map[int]StrToPolygon2DListMap) (int32, int32, int32, int32, StrToVec2DListMap, StrToPolygon2DListMap, error) {
|
||||||
toRetStrToVec2DListMap := make(StrToVec2DListMap, 0)
|
toRetStrToVec2DListMap := make(StrToVec2DListMap, 0)
|
||||||
toRetStrToPolygon2DListMap := make(StrToPolygon2DListMap, 0)
|
toRetStrToPolygon2DListMap := make(StrToPolygon2DListMap, 0)
|
||||||
/*
|
|
||||||
Note that both
|
|
||||||
- "Vec2D"s of "toRetStrToVec2DListMap", and
|
|
||||||
- "Polygon2D"s of "toRetStrToPolygon2DListMap"
|
|
||||||
|
|
||||||
are already transformed into the "coordinate of B2World".
|
|
||||||
*/
|
|
||||||
|
|
||||||
for _, objGroup := range pTmxMapIns.ObjectGroups {
|
for _, objGroup := range pTmxMapIns.ObjectGroups {
|
||||||
switch objGroup.Name {
|
switch objGroup.Name {
|
||||||
@ -376,10 +355,8 @@ func ParseTmxLayersAndGroups(pTmxMapIns *TmxMap, gidBoundariesMapInB2World map[i
|
|||||||
if false == ok {
|
if false == ok {
|
||||||
theVec2DListToCache := make(Vec2DList, 0)
|
theVec2DListToCache := make(Vec2DList, 0)
|
||||||
toRetStrToVec2DListMap[objGroup.Name] = &theVec2DListToCache
|
toRetStrToVec2DListMap[objGroup.Name] = &theVec2DListToCache
|
||||||
pTheVec2DListToCache = toRetStrToVec2DListMap[objGroup.Name]
|
|
||||||
} else {
|
|
||||||
pTheVec2DListToCache = toRetStrToVec2DListMap[objGroup.Name]
|
|
||||||
}
|
}
|
||||||
|
pTheVec2DListToCache = toRetStrToVec2DListMap[objGroup.Name]
|
||||||
for _, singleObjInTmxFile := range objGroup.Objects {
|
for _, singleObjInTmxFile := range objGroup.Objects {
|
||||||
theUntransformedPos := &Vec2D{
|
theUntransformedPos := &Vec2D{
|
||||||
X: singleObjInTmxFile.X,
|
X: singleObjInTmxFile.X,
|
||||||
@ -389,16 +366,14 @@ func ParseTmxLayersAndGroups(pTmxMapIns *TmxMap, gidBoundariesMapInB2World map[i
|
|||||||
*pTheVec2DListToCache = append(*pTheVec2DListToCache, &thePosInWorld)
|
*pTheVec2DListToCache = append(*pTheVec2DListToCache, &thePosInWorld)
|
||||||
}
|
}
|
||||||
case "Barrier":
|
case "Barrier":
|
||||||
// Note that in this case, the "Polygon2D.Anchor" of each "TmxOrTsxObject" is exactly overlapping with "Polygon2D.Points[0]" w.r.t. B2World.
|
// Note that in this case, the "Polygon2D.Anchor" of each "TmxOrTsxObject" is exactly overlapping with "Polygon2D.Points[0]".
|
||||||
var pThePolygon2DListToCache *Polygon2DList
|
var pThePolygon2DListToCache *Polygon2DList
|
||||||
_, ok := toRetStrToPolygon2DListMap[objGroup.Name]
|
_, ok := toRetStrToPolygon2DListMap[objGroup.Name]
|
||||||
if false == ok {
|
if false == ok {
|
||||||
thePolygon2DListToCache := make(Polygon2DList, 0)
|
thePolygon2DListToCache := make(Polygon2DList, 0)
|
||||||
toRetStrToPolygon2DListMap[objGroup.Name] = &thePolygon2DListToCache
|
toRetStrToPolygon2DListMap[objGroup.Name] = &thePolygon2DListToCache
|
||||||
pThePolygon2DListToCache = toRetStrToPolygon2DListMap[objGroup.Name]
|
|
||||||
} else {
|
|
||||||
pThePolygon2DListToCache = toRetStrToPolygon2DListMap[objGroup.Name]
|
|
||||||
}
|
}
|
||||||
|
pThePolygon2DListToCache = toRetStrToPolygon2DListMap[objGroup.Name]
|
||||||
|
|
||||||
for _, singleObjInTmxFile := range objGroup.Objects {
|
for _, singleObjInTmxFile := range objGroup.Objects {
|
||||||
if nil == singleObjInTmxFile.Polyline {
|
if nil == singleObjInTmxFile.Polyline {
|
||||||
@ -408,7 +383,7 @@ func ParseTmxLayersAndGroups(pTmxMapIns *TmxMap, gidBoundariesMapInB2World map[i
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
thePolygon2DInWorld, err := TmxPolylineToPolygon2DInB2World(pTmxMapIns, singleObjInTmxFile, singleObjInTmxFile.Polyline)
|
thePolygon2DInWorld, err := tmxPolylineToPolygon2D(pTmxMapIns, singleObjInTmxFile, singleObjInTmxFile.Polyline)
|
||||||
if nil != err {
|
if nil != err {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
@ -440,7 +440,7 @@
|
|||||||
"array": [
|
"array": [
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
216.05530045313827,
|
209.73151519075364,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
|
@ -1047,6 +1047,7 @@ cc.Class({
|
|||||||
const inputList = self.getCachedInputFrameDownsyncWithPrediction(j).inputList;
|
const inputList = self.getCachedInputFrameDownsyncWithPrediction(j).inputList;
|
||||||
for (let j in self.playerRichInfoArr) {
|
for (let j in self.playerRichInfoArr) {
|
||||||
const joinIndex = parseInt(j) + 1;
|
const joinIndex = parseInt(j) + 1;
|
||||||
|
const playerId = self.playerRichInfoArr[j].id;
|
||||||
const collisionPlayerIndex = self.collisionPlayerIndexPrefix + joinIndex;
|
const collisionPlayerIndex = self.collisionPlayerIndexPrefix + joinIndex;
|
||||||
const playerCollider = collisionSysMap.get(collisionPlayerIndex);
|
const playerCollider = collisionSysMap.get(collisionPlayerIndex);
|
||||||
const player = renderFrame.players[playerId];
|
const player = renderFrame.players[playerId];
|
||||||
|
@ -166,6 +166,7 @@ window.initPersistentSessionClient = function(onopenCb, expectedRoomId) {
|
|||||||
break;
|
break;
|
||||||
case window.DOWNSYNC_MSG_ACT_FORCED_RESYNC:
|
case window.DOWNSYNC_MSG_ACT_FORCED_RESYNC:
|
||||||
if (window.handleInputFrameDownsyncBatch && window.handleRoomDownsyncFrame) {
|
if (window.handleInputFrameDownsyncBatch && window.handleRoomDownsyncFrame) {
|
||||||
|
console.warn("GOT forced resync:", resp);
|
||||||
// The following order of execution is important, because "handleInputFrameDownsyncBatch" is only available when state is IN_BATTLE
|
// The following order of execution is important, because "handleInputFrameDownsyncBatch" is only available when state is IN_BATTLE
|
||||||
window.handleRoomDownsyncFrame(resp.rdf);
|
window.handleRoomDownsyncFrame(resp.rdf);
|
||||||
window.handleInputFrameDownsyncBatch(resp.inputFrameDownsyncBatch);
|
window.handleInputFrameDownsyncBatch(resp.inputFrameDownsyncBatch);
|
||||||
|
Loading…
Reference in New Issue
Block a user