Files
bd2/go/internal/server/design/gamedata/field_pack.go
T

129 lines
3.1 KiB
Go

package gamedata
import (
"database/sql"
"fmt"
)
// FieldPack describes non-story arena fields. PackType comes from the protocol
// enum; IDs and entry restrictions come from the installed GameData tables.
type FieldPack struct {
ID, Type, BuyPrice, UseSchedule uint64
TicketID, SquadLevel uint64
HasOpenRule bool
MapIDs map[int]bool
}
func LoadFieldPacks(root, version string) (map[int]FieldPack, error) {
db, closeDB, err := openStatDatabase(root, version)
if err != nil {
return nil, err
}
defer closeDB()
return loadFieldPacks(db)
}
func loadFieldPacks(db *sql.DB) (map[int]FieldPack, error) {
result := map[int]FieldPack{}
rows, err := db.Query("SELECT id,ProtoBuf FROM PackTable ORDER BY id")
if err != nil {
return nil, err
}
for rows.Next() {
var id int
var raw []byte
if err := rows.Scan(&id, &raw); err != nil {
_ = rows.Close()
return nil, err
}
values := map[int]uint64{}
for _, field := range []int{7, 25, 55, 65} {
v, e := packedInts(raw, field)
if e != nil || len(v) > 1 {
_ = rows.Close()
return nil, fmt.Errorf("gamedata: invalid arena pack %d field %d", id, field)
}
if len(v) == 1 {
values[field] = v[0]
}
}
if values[55] != 3 && values[55] != 5 && values[55] != 10 {
continue
}
if id <= 0 || values[25] != uint64(id) {
_ = rows.Close()
return nil, fmt.Errorf("gamedata: invalid field pack identity %d", id)
}
result[id] = FieldPack{ID: uint64(id), Type: values[55], BuyPrice: values[7], UseSchedule: values[65], MapIDs: map[int]bool{}}
}
if err := rows.Err(); err != nil {
_ = rows.Close()
return nil, err
}
if err := rows.Close(); err != nil {
return nil, err
}
rows, err = db.Query("SELECT id,ProtoBuf FROM ContentOpenTable WHERE groupId=1 ORDER BY id")
if err != nil {
return nil, err
}
for rows.Next() {
var id int
var raw []byte
if err := rows.Scan(&id, &raw); err != nil {
_ = rows.Close()
return nil, err
}
pack, exists := result[id]
if !exists {
continue
}
pack.HasOpenRule = true
for field, target := range map[int]*uint64{5: &pack.SquadLevel, 6: &pack.TicketID} {
v, e := packedInts(raw, field)
if e != nil || len(v) > 1 {
_ = rows.Close()
return nil, fmt.Errorf("gamedata: invalid field pack opening %d", id)
}
if len(v) == 1 {
*target = v[0]
}
}
result[id] = pack
}
if err := rows.Err(); err != nil {
_ = rows.Close()
return nil, err
}
if err := rows.Close(); err != nil {
return nil, err
}
rows, err = db.Query("SELECT id,packId FROM MapTable ORDER BY id")
if err != nil {
return nil, err
}
for rows.Next() {
var id, packID int
if err := rows.Scan(&id, &packID); err != nil {
_ = rows.Close()
return nil, err
}
if pack, exists := result[packID]; exists {
pack.MapIDs[id] = true
}
}
if err := rows.Err(); err != nil {
_ = rows.Close()
return nil, err
}
if err := rows.Close(); err != nil {
return nil, err
}
for id, pack := range result {
if len(pack.MapIDs) == 0 {
return nil, fmt.Errorf("gamedata: arena pack %d has no map", id)
}
}
return result, nil
}