Skip to content

Commit

Permalink
Game end fixes... in theory
Browse files Browse the repository at this point in the history
  • Loading branch information
jchv committed Jul 3, 2023
1 parent bc8ea47 commit 4806f7e
Show file tree
Hide file tree
Showing 5 changed files with 108 additions and 66 deletions.
21 changes: 12 additions & 9 deletions game/room/lobby.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,17 +28,19 @@ import (
"github.com/pangbox/server/database/accounts"
gamemodel "github.com/pangbox/server/game/model"
gamepacket "github.com/pangbox/server/game/packet"
"github.com/pangbox/server/gameconfig"
log "github.com/sirupsen/logrus"
orderedmap "github.com/wk8/go-ordered-map/v2"
"golang.org/x/sync/errgroup"
)

type Lobby struct {
actor.Base[LobbyEvent]
logger *log.Entry
storage *Storage
players *orderedmap.OrderedMap[uint32, *LobbyPlayer]
accounts *accounts.Service
logger *log.Entry
storage *Storage
players *orderedmap.OrderedMap[uint32, *LobbyPlayer]
accounts *accounts.Service
configProvider gameconfig.Provider
}

type LobbyPlayer struct {
Expand All @@ -47,12 +49,13 @@ type LobbyPlayer struct {
Joined time.Time
}

func NewLobby(ctx context.Context, logger *log.Entry, accounts *accounts.Service) *Lobby {
func NewLobby(ctx context.Context, logger *log.Entry, accounts *accounts.Service, configProvider gameconfig.Provider) *Lobby {
lobby := &Lobby{
logger: logger,
storage: new(Storage),
players: orderedmap.New[uint32, *LobbyPlayer](),
accounts: accounts,
logger: logger,
storage: new(Storage),
players: orderedmap.New[uint32, *LobbyPlayer](),
accounts: accounts,
configProvider: configProvider,
}
lobby.TryStart(ctx, lobby.task)
return lobby
Expand Down
102 changes: 47 additions & 55 deletions game/room/room.go
Original file line number Diff line number Diff line change
Expand Up @@ -582,63 +582,55 @@ func (r *Room) handleRoomGameTurnEnd(ctx context.Context, event RoomGameTurnEnd)
if nextPlayer == nil {
r.state.CurrentHole++
if r.state.CurrentHole > r.state.NumHoles {
for pair := r.players.Oldest(); pair != nil; pair = pair.Next() {
r.broadcast(ctx, &gamepacket.ServerEvent{
Type: gamepacket.GameEndEvent,
Data: gamepacket.ChatMessage{
Nickname: common.ToPString(pair.Value.Entry.Nickname),
},
GameEnd: &gamepacket.GameEnd{
Score: 0, // ?
Pang: pair.Value.Pang,
},
})
results := &gamepacket.ServerRoomFinishGame{
NumPlayers: uint8(r.players.Len()),
Standings: make([]gamepacket.PlayerGameResult, r.players.Len()),
results := &gamepacket.ServerRoomFinishGame{
NumPlayers: uint8(r.players.Len()),
Standings: make([]gamepacket.PlayerGameResult, r.players.Len()),
}
for i, pair := 0, r.players.Oldest(); pair != nil; pair = pair.Next() {
bonusPang := pair.Value.BonusPang
bonusPang += r.lobby.configProvider.GetCourseBonus()

Check failure on line 591 in game/room/room.go

View workflow job for this annotation

GitHub Actions / Build

not enough arguments in call to r.lobby.configProvider.GetCourseBonus
results.Standings[i].ConnID = pair.Value.Entry.ConnID
results.Standings[i].Pang = pair.Value.Pang
results.Standings[i].Score = int8(pair.Value.Score)
results.Standings[i].BonusPang = bonusPang

totalPang := bonusPang + pair.Value.Pang

newPang, err := r.accounts.AddPang(ctx, int64(pair.Value.Entry.PlayerID), int64(totalPang))
if err != nil {
log.WithError(err).Error("failed giving game-ending pang")
}
for i, pair := 0, r.players.Oldest(); pair != nil; pair = pair.Next() {
results.Standings[i].ConnID = pair.Value.Entry.ConnID
results.Standings[i].Pang = pair.Value.Pang
results.Standings[i].Score = int8(pair.Value.Score)
results.Standings[i].BonusPang = pair.Value.BonusPang

newPang, err := r.accounts.AddPang(ctx, int64(pair.Value.Entry.PlayerID), int64(pair.Value.Pang+pair.Value.BonusPang))
if err != nil {
log.WithError(err).Error("failed giving game-ending pang")
}

if err := pair.Value.Conn.SendMessage(ctx, &gamepacket.ServerPangBalanceData{PangsRemaining: uint64(newPang)}); err != nil {
log.WithError(err).Error("failed informing player of game-ending pang")
}

// reset game state now
pair.Value.Score = 0
pair.Value.Pang = 0
pair.Value.BonusPang = 0
pair.Value.GameState.HoleEnd = false
pair.Value.GameState.ShotSync = nil

i++

if err := pair.Value.Conn.SendMessage(ctx, &gamepacket.ServerPangBalanceData{PangsRemaining: uint64(newPang)}); err != nil {
log.WithError(err).Error("failed informing player of game-ending pang")
}
slices.SortFunc(results.Standings, func(a, b gamepacket.PlayerGameResult) bool {
return a.Score < b.Score
})
results.Standings[0].Place = 1
for i := 1; i < len(results.Standings); i++ {
if results.Standings[i-1].Score == results.Standings[i].Score {
// If tie: use placement of tied player(s)
results.Standings[i].Place = results.Standings[i-1].Place
} else {
// If not tie: use position in standing as placement
results.Standings[i].Place = uint8(i + 1)
}

// reset game state now
pair.Value.Score = 0
pair.Value.Pang = 0
pair.Value.BonusPang = 0
pair.Value.GameState.HoleEnd = false
pair.Value.GameState.ShotSync = nil

i++
}
slices.SortFunc(results.Standings, func(a, b gamepacket.PlayerGameResult) bool {
return a.Score < b.Score
})
results.Standings[0].Place = 1
for i := 1; i < len(results.Standings); i++ {
if results.Standings[i-1].Score == results.Standings[i].Score {
// If tie: use placement of tied player(s)
results.Standings[i].Place = results.Standings[i-1].Place
} else {
// If not tie: use position in standing as placement
results.Standings[i].Place = uint8(i + 1)
}
r.broadcast(ctx, results)
r.state.Open = true
r.state.CurrentHole = 0
r.state.GamePhase = gamemodel.LobbyPhase
}
r.broadcast(ctx, results)
r.state.Open = true
r.state.CurrentHole = 0
r.state.GamePhase = gamemodel.LobbyPhase
} else {
r.broadcast(ctx, &gamepacket.ServerRoomFinishHole{})
for pair := r.players.Oldest(); pair != nil; pair = pair.Next() {
Expand Down Expand Up @@ -682,8 +674,8 @@ func (r *Room) handleRoomGameShotSync(ctx context.Context, event RoomGameShotSyn
Data: *r.state.ShotSync,
})
if pair := r.players.GetPair(r.state.ShotSync.ActiveConnID); pair != nil {
pair.Value.Pang += uint64(r.state.ShotSync.Pang)
pair.Value.BonusPang += uint64(r.state.ShotSync.BonusPang)
pair.Value.Pang = uint64(r.state.ShotSync.Pang)
pair.Value.BonusPang = uint64(r.state.ShotSync.BonusPang)
pair.Value.Stroke++
} else {
log.WithField("ConnID", r.state.ShotSync.ActiveConnID).Warn("couldn't find conn")
Expand Down
2 changes: 1 addition & 1 deletion game/server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ func New(opts Options) *Server {

// Listen listens for connections on a given address and blocks indefinitely.
func (s *Server) Listen(ctx context.Context, addr string) error {
s.lobby = room.NewLobby(ctx, s.logger, s.accountsService)
s.lobby = room.NewLobby(ctx, s.logger, s.accountsService, s.configProvider)
return s.baseServer.Listen(s.logger, addr, func(logger *log.Entry, socket net.Conn) error {
conn := Conn{
ServerConn: common.NewServerConn(
Expand Down
24 changes: 24 additions & 0 deletions gameconfig/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,23 +26,32 @@ type Provider interface {
GetCharacterDefaults(id uint8) CharacterDefaults
GetDefaultClubSetTypeID() uint32
GetDefaultPang() uint64
GetCourseBonus(course uint8, numPlayers, numHoles int) uint64
}

type CharacterDefaults struct {
CharacterID uint8 `json:"CharacterID"`
DefaultPartTypeIDs [24]uint32 `json:"DefaultPartTypeIDs"`
}

type CourseBonusRate struct {
CourseID uint8
CourseName string
BonusRate int
}

type Manifest struct {
CharacterDefaults []CharacterDefaults `json:"CharacterDefaults"`
DefaultClubSetTypeID uint32 `json:"DefaultClubSetTypeID"`
DefaultPang uint64 `json:"DefaultPang"`
CourseBonusRate []CourseBonusRate `json:"CourseBonusRate"`
}

type configFileProvider struct {
characterDefaults map[uint8]CharacterDefaults
defaultClubSetTypeID uint32
defaultPang uint64
courseBonusRate map[uint8]int
}

func Default() Provider {
Expand Down Expand Up @@ -78,10 +87,14 @@ func FromManifest(manifest Manifest) Provider {
characterDefaults: make(map[uint8]CharacterDefaults),
defaultClubSetTypeID: manifest.DefaultClubSetTypeID,
defaultPang: manifest.DefaultPang,
courseBonusRate: make(map[uint8]int),
}
for _, defaults := range manifest.CharacterDefaults {
provider.characterDefaults[defaults.CharacterID] = defaults
}
for _, course := range manifest.CourseBonusRate {
provider.courseBonusRate[course.CourseID] = course.BonusRate
}
return provider
}

Expand All @@ -96,3 +109,14 @@ func (c *configFileProvider) GetDefaultClubSetTypeID() uint32 {
func (c *configFileProvider) GetDefaultPang() uint64 {
return c.defaultPang
}

func (c *configFileProvider) GetCourseBonus(course uint8, numPlayers, numHoles int) uint64 {
bonusRate, ok := c.courseBonusRate[course]
if !ok {
// Should generally not happen...
bonusRate = 20
}

// TODO: this is probably only true for versus
return uint64(bonusRate * numHoles * (numPlayers - 1))
}
25 changes: 24 additions & 1 deletion gameconfig/default.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,28 @@
{
"DefaultPang": 20000,
"DefaultClubSetTypeID": 268435553,
"CharacterDefaults": []
"CharacterDefaults": [],
"CourseBonusRate": [
{"CourseID": 0, "CourseName": "Blue Lagoon", "BonusRate": 20},
{"CourseID": 1, "CourseName": "Blue Water", "BonusRate": 20},
{"CourseID": 2, "CourseName": "Sepia Wind", "BonusRate": 20},
{"CourseID": 3, "CourseName": "Wind Hill", "BonusRate": 20},
{"CourseID": 4, "CourseName": "Wiz Wiz", "BonusRate": 20},
{"CourseID": 5, "CourseName": "West Wiz", "BonusRate": 20},
{"CourseID": 6, "CourseName": "Blue Moon", "BonusRate": 20},
{"CourseID": 7, "CourseName": "Silvia Cannon", "BonusRate": 20},
{"CourseID": 8, "CourseName": "Ice Cannon", "BonusRate": 20},
{"CourseID": 9, "CourseName": "White Wiz", "BonusRate": 20},
{"CourseID": 10, "CourseName": "Shining Sand", "BonusRate": 40},
{"CourseID": 11, "CourseName": "Pink Wind", "BonusRate": 20},
{"CourseID": 13, "CourseName": "Deep Inferno", "BonusRate": 20},
{"CourseID": 14, "CourseName": "Ice Spa", "BonusRate": 20},
{"CourseID": 15, "CourseName": "Lost Seaway", "BonusRate": 20},
{"CourseID": 16, "CourseName": "Eastern Valley", "BonusRate": 20},
{"CourseID": 17, "CourseName": "Chronicle 1. Chaos", "BonusRate": 20},
{"CourseID": 18, "CourseName": "Ice Inferno", "BonusRate": 20},
{"CourseID": 19, "CourseName": "Wiz City", "BonusRate": 20},
{"CourseID": 20, "CourseName": "Abbot Mine", "BonusRate": 20},
{"CourseID": 64, "CourseName": "Grand Zodiac", "BonusRate": 20}
]
}

0 comments on commit 4806f7e

Please sign in to comment.