Files
bd2/go/internal/server/domain/world/field_pack.go
T

88 lines
2.2 KiB
Go

package world
import (
"errors"
"bd2server/internal/server/design/gamedata"
"bd2server/internal/server/domain/command"
)
// LastPlayedPackID prevents LoginUser from selecting a field that this server
// cannot restore. A fresh account keeps the versioned login seed's pack.
func (s *Service) LastPlayedPackID(ctx command.Context) (uint64, error) {
id := uint64(s.state.ActivePackID())
if id == 0 {
var err error
id, err = s.state.LastPlayedPackID(ctx)
if err != nil {
return id, err
}
}
if id == 0 {
id = uint64(s.startingPack())
}
if !s.packUnlocked(ctx, int(id)) {
return 0, errors.New("world: saved login pack is unavailable")
}
if pack, field := s.fieldPacks[int(id)]; field {
if pack.Type == 5 {
return id, nil
}
saved, _ := s.state.Position()
if !pack.MapIDs[saved.Position.MapID] {
return 0, errors.New("world: saved arena map does not belong to pack")
}
}
return id, nil
}
func (s *Service) AttachSquadLevel(ctx command.Context, provider func() (uint64, error)) error {
if provider == nil {
return errors.New("world: nil squad level provider")
}
s.squadLevel = provider
return nil
}
func (s *Service) fieldPackUnlocked(ctx command.Context, pack gamedata.FieldPack) bool {
// A valid committed field position is the existing account's entry marker.
// Restoration does not repeat a purchase or an unlock check.
if saved, found := s.state.Position(); found && saved.PackID == int(pack.ID) && pack.MapIDs[saved.Position.MapID] {
return true
}
// Scheduled arena availability needs its own persisted event domain.
if pack.UseSchedule != 0 {
return false
}
if pack.SquadLevel != 0 {
if s.squadLevel == nil {
return false
}
level, err := s.squadLevel()
if err != nil || level < pack.SquadLevel {
return false
}
}
if pack.HasOpenRule {
if s.inventory == nil {
return false
}
found := false
for _, item := range s.inventory.All(ctx) {
if item.Type == 19 && item.ID == pack.TicketID && item.Count != 0 {
found = true
break
}
}
if !found {
return false
}
}
// Paid packs require a durable purchase marker. An existing saved position
// proves this account already entered it; this does not implement purchase.
if pack.BuyPrice != 0 {
return false
}
return true
}