Files
bd2/go/internal/server/deck/costume_use.go
T

66 lines
1.7 KiB
Go

package deck
import (
"bd2server/internal/server/wire"
"fmt"
"maps"
"math"
)
func (s *Store) handleCostumeUse(req []byte) (int, []byte, bool, error) {
fail := func(e error) (int, []byte, bool, error) { return 41, nil, true, e }
if e := checkSeq(req); e != nil {
return fail(e)
}
assignments := map[uint64]uint64{}
e := wire.Walk(req, func(f wire.Field) error {
if f.Number != 2 {
return nil
}
if f.Type != 2 {
return fmt.Errorf("deck: invalid costume use entry")
}
cost, _, e := wire.Varint(f.Value, 1)
if e != nil || cost == 0 || cost > math.MaxInt64 {
return fmt.Errorf("deck: invalid costume index")
}
char, _, e := wire.Varint(f.Value, 2)
if e != nil || char == 0 || char > math.MaxInt64 {
return fmt.Errorf("deck: invalid costume character")
}
if _, ok := assignments[char]; ok {
return fmt.Errorf("deck: repeated costume character")
}
assignments[char] = cost
return nil
})
if e != nil {
return fail(e)
}
if len(assignments) == 0 {
return fail(fmt.Errorf("deck: missing costume assignments"))
}
s.mu.Lock()
defer s.mu.Unlock()
if s.characters != nil {
if s.collection == nil {
return fail(fmt.Errorf("deck: costume collection unavailable"))
}
for char, cost := range assignments {
if _, ok := s.characters.Find(char); !ok {
return fail(fmt.Errorf("deck: unknown costume character"))
}
c, ok := s.collection.CostumeByIndex(cost)
if !ok || c.UseChar != char {
return fail(fmt.Errorf("deck: costume not owned by character"))
}
}
if _, e = s.characters.ApplyPresetCostumes(assignments); e != nil {
return fail(e)
}
}
n := clone(s.state)
maps.Copy(n.Costumes, assignments)
return 41, nil, true, s.commit(n)
}