refactor: game funcs moved to controller

This commit is contained in:
Ilia Denisov
2026-01-15 14:42:04 +02:00
parent fe8a8d4150
commit 16aba8435d
47 changed files with 1023 additions and 3093 deletions
+46 -113
View File
@@ -14,8 +14,7 @@ import (
func (c *Cache) CreateShips(ri int, shipTypeName string, planetNumber uint, quantity int) error {
class, _, ok := c.ShipClass(ri, shipTypeName)
if !ok {
return e.NewEntityNotExistsError("ship class %w", shipTypeName)
return e.NewEntityNotExistsError("ship class q", shipTypeName)
}
p, ok := c.Planet(planetNumber)
@@ -26,10 +25,7 @@ func (c *Cache) CreateShips(ri int, shipTypeName string, planetNumber uint, quan
return e.NewEntityNotOwnedError("planet #%d", planetNumber)
}
// FIXME: move maxindex to appendShipGroup
nextIndex := c.ShipGroupMaxIndex(ri) + 1
c.appendShipGroup(ri, class, &game.ShipGroup{
Index: nextIndex,
c.appendShipGroup(ri, &game.ShipGroup{
OwnerID: c.g.Race[ri].ID,
TypeID: class.ID,
Destination: p.Number,
@@ -50,9 +46,10 @@ func (c *Cache) ShipGroup(groupIndex int) *game.ShipGroup {
return &c.g.ShipGroups[groupIndex]
}
func (c *Cache) ShipGroupFleet(groupIndex int, fID *uuid.UUID) {
func (c *Cache) ShipGroupJoinFleet(groupIndex int, fID *uuid.UUID) {
c.validateShipGroupIndex(groupIndex)
c.g.ShipGroups[groupIndex].FleetID = fID
c.invalidateFleetCache()
}
func (c *Cache) ShipGroupShipsNumber(groupIndex int, number uint) {
@@ -85,10 +82,10 @@ func (c *Cache) ShipGroupMaxIndex(ri int) uint {
func (c *Cache) ShipGroupOwnerRaceIndex(groupIndex int) int {
c.validateShipGroupIndex(groupIndex)
if len(c.raceIndexByShipGroupIndex) == 0 {
if len(c.cacheRaceIndexByShipGroupIndex) == 0 {
c.cacheShipsAndGroups()
}
if v, ok := c.raceIndexByShipGroupIndex[groupIndex]; ok {
if v, ok := c.cacheRaceIndexByShipGroupIndex[groupIndex]; ok {
return v
} else {
panic(fmt.Sprintf("ShipGroupRace: group not found by index=%v", groupIndex))
@@ -134,21 +131,25 @@ func (c *Cache) CmdJoinEqualGroups() {
func (c *Cache) JoinEqualGroups(ri int) {
c.validateRaceIndex(ri)
shipGroups := slices.Collect(c.listShipGroups(ri))
origin := len(shipGroups)
raceGroups := make([]game.ShipGroup, 0)
for sg := range c.listShipGroups(ri) {
raceGroups = append(raceGroups, *sg)
}
origin := len(raceGroups)
if origin < 2 {
return
}
for i := 0; i < len(shipGroups)-1; i++ {
for j := len(shipGroups) - 1; j > i; j-- {
if shipGroups[i].Equal(*shipGroups[j]) {
shipGroups[i].Index = maxUint(shipGroups[i].Index, shipGroups[j].Index)
shipGroups[i].Number += shipGroups[j].Number
shipGroups = append(shipGroups[:j], shipGroups[j+1:]...)
for i := 0; i < len(raceGroups)-1; i++ {
for j := len(raceGroups) - 1; j > i; j-- {
if raceGroups[i].Equal(raceGroups[j]) {
raceGroups[i].Index = maxUint(raceGroups[i].Index, raceGroups[j].Index)
raceGroups[i].Number += raceGroups[j].Number
raceGroups = append(raceGroups[:j], raceGroups[j+1:]...)
}
}
}
if len(shipGroups) == origin {
if len(raceGroups) == origin {
return
}
@@ -159,14 +160,16 @@ func (c *Cache) JoinEqualGroups(ri int) {
}
}
// c.g.ShipGroups = slices.DeleteFunc(c.g.ShipGroups, func(v game.ShipGroup) bool { return v.OwnerID == c.g.Race[ri].ID })
slices.Sort(toDelete)
slices.Reverse(toDelete)
for _, idx := range toDelete {
c.unsafeDeleteShipGroup(idx)
}
// c.g.ShipGroups = append(c.g.ShipGroups, shipGroups...)
for i := range shipGroups {
c.g.ShipGroups = append(c.g.ShipGroups, *shipGroups[i])
c.invalidateShipGroupCache()
for i := range raceGroups {
c.appendShipGroup(ri, &raceGroups[i])
}
c.invalidateShipGroupCache()
@@ -202,22 +205,13 @@ func (c *Cache) DisassembleGroup(ri int, groupIndex, quantity uint) error {
return e.NewBeakGroupNumberNotEnoughError("%d<%d", c.ShipGroup(sgi).Number, quantity)
}
p, ok := c.Planet(c.ShipGroup(sgi).Destination)
pl, ok := c.Planet(c.ShipGroup(sgi).Destination)
if !ok {
return e.NewGameStateError("planet #%d", c.ShipGroup(sgi).Destination)
}
// pl := slices.IndexFunc(g.Map.Planet, func(p game.Planet) bool { return p.Number == c.ShipGroup(sgi).Destination })
// if pl < 0 {
// return e.NewGameStateError("planet #%d", c.ShipGroup(sgi).Destination)
// }
p := *pl
st := c.ShipGroupShipClass(sgi)
// var sti int
// if sti = slices.IndexFunc(g.Race[ri].ShipTypes, func(st game.ShipType) bool { return st.ID == c.ShipGroup(sgi).TypeID }); sti < 0 {
// // hard to test, need manual game data invalidation
// return e.NewGameStateError("not found: ShipType ID=%v", c.ShipGroup(sgi).TypeID)
// }
if quantity > 0 && quantity < c.ShipGroup(sgi).Number {
// make new group for disassembly
@@ -234,8 +228,7 @@ func (c *Cache) DisassembleGroup(ri int, groupIndex, quantity uint) error {
switch ct {
case game.CargoColonist:
if p.Owner == c.g.Race[ri].ID {
pn := UnloadColonists(*p, load)
p = &pn
p = game.UnloadColonists(p, load)
}
case game.CargoMaterial:
p.Material += load
@@ -246,9 +239,10 @@ func (c *Cache) DisassembleGroup(ri int, groupIndex, quantity uint) error {
p.Material += c.ShipGroup(sgi).EmptyMass(st)
// g.ShipGroups = append(g.ShipGroups[:sgi], g.ShipGroups[sgi+1:]...)
c.unsafeDeleteShipGroup(sgi)
c.g.Map.Planet[c.MustPlanetIndex(p.Number)] = p
return nil
}
@@ -283,19 +277,11 @@ func (c *Cache) LoadCargo(ri int, groupIndex uint, ct game.CargoType, ships uint
return e.NewGameStateError("planet #%d", c.ShipGroup(sgi).Destination)
}
// pl := slices.IndexFunc(g.Map.Planet, func(p game.Planet) bool { return p.Number == c.ShipGroup(sgi).Destination })
// if pl < 0 {
// return e.NewGameStateError("planet #%d", c.ShipGroup(sgi).Destination)
// }
if p.Owner != uuid.Nil && p.Owner != c.g.Race[ri].ID {
return e.NewEntityNotOwnedError("planet #%d", p.Number)
}
st := c.ShipGroupShipClass(sgi)
// var sti int
// if sti = slices.IndexFunc(g.Race[ri].ShipTypes, func(st game.ShipType) bool { return st.ID == c.ShipGroup(sgi).TypeID }); sti < 0 {
// // hard to test, need manual game data invalidation
// return e.NewGameStateError("not found: ShipType ID=%v", c.ShipGroup(sgi).TypeID)
// }
if st.Cargo < 1 {
return e.NewNoCargoBayError("ship_type %q", st.Name)
}
@@ -366,11 +352,6 @@ func (c *Cache) UnloadCargo(ri int, groupIndex uint, ships uint, quantity float6
return e.NewShipsBusyError()
}
st := c.ShipGroupShipClass(sgi)
// var sti int
// if sti = slices.IndexFunc(g.Race[ri].ShipTypes, func(st game.ShipType) bool { return st.ID == c.ShipGroup(sgi).TypeID }); sti < 0 {
// // hard to test, need manual game data invalidation
// return e.NewGameStateError("not found: ShipType ID=%v", c.ShipGroup(sgi).TypeID)
// }
if st.Cargo < 1 {
return e.NewNoCargoBayError("ship_type %q", st.Name)
}
@@ -382,10 +363,6 @@ func (c *Cache) UnloadCargo(ri int, groupIndex uint, ships uint, quantity float6
if !ok {
return e.NewGameStateError("planet #%d", c.ShipGroup(sgi).Destination)
}
// pl := slices.IndexFunc(g.Map.Planet, func(p game.Planet) bool { return p.Number == c.ShipGroup(sgi).Destination })
// if pl < 0 {
// return e.NewGameStateError("planet #%d", c.ShipGroup(sgi).Destination)
// }
if ct == game.CargoColonist {
if p.Owner != uuid.Nil && p.Owner != c.g.Race[ri].ID {
return e.NewEntityNotOwnedError("planet #%d unload %v", p.Number, ct)
@@ -451,16 +428,11 @@ func (c *Cache) GiveawayGroup(ri, riAccept int, groupIndex, quantity uint) (err
}
st := c.ShipGroupShipClass(sgi)
// var sti int
// if sti = slices.IndexFunc(g.Race[ri].ShipTypes, func(st ShipType) bool { return st.ID == c.ShipGroup(sgi).TypeID }); sti < 0 {
// // hard to test, need manual game data invalidation
// return e.NewGameStateError("not found: ShipType ID=%v", c.ShipGroup(sgi).TypeID)
// }
var stAcc int
if stAcc = slices.IndexFunc(c.g.Race[riAccept].ShipTypes, func(v game.ShipType) bool { return v.Name == st.Name }); stAcc >= 0 &&
!st.Equal(c.g.Race[riAccept].ShipTypes[stAcc]) {
return e.NewGiveawayGroupShipsTypeNotEqualError("race %w, ship type %w", c.g.Race[riAccept].Name, c.g.Race[riAccept].ShipTypes[stAcc].Name)
return e.NewGiveawayGroupShipsTypeNotEqualError("race %q, ship type %q", c.g.Race[riAccept].Name, c.g.Race[riAccept].ShipTypes[stAcc].Name)
}
if stAcc < 0 {
err = c.CreateShipType(riAccept,
@@ -470,55 +442,20 @@ func (c *Cache) GiveawayGroup(ri, riAccept int, groupIndex, quantity uint) (err
st.Weapons,
st.Shields,
st.Cargo)
stAcc = len(c.g.Race[ri].ShipTypes) - 1
if err != nil {
return err
}
stAcc = len(c.g.Race[riAccept].ShipTypes) - 1
}
// maxIndex := c.ShipGroupMaxIndex(riAccept)
// var maxIndex uint
// for sg := range g.listShipGroups(riAccept) {
// if sg.Index > maxIndex {
// maxIndex = sg.Index
// }
// }
c.appendShipGroup(ri, st, &game.ShipGroup{
// Index: maxIndex + 1,
OwnerID: c.g.Race[riAccept].ID,
TypeID: c.g.Race[riAccept].ShipTypes[stAcc].ID,
Number: uint(quantity),
CargoType: c.ShipGroup(sgi).CargoType,
Load: c.ShipGroup(sgi).Load,
Tech: maps.Clone(c.ShipGroup(sgi).Tech),
Destination: c.ShipGroup(sgi).Destination,
StateInSpace: c.ShipGroup(sgi).StateInSpace,
StateUpgrade: c.ShipGroup(sgi).StateUpgrade,
})
// g.ShipGroups = append(g.ShipGroups, game.ShipGroup{
// Index: maxIndex + 1,
// OwnerID: g.Race[riAccept].ID,
// TypeID: g.Race[riAccept].ShipTypes[stAcc].ID,
// Number: uint(quantity),
// CargoType: c.ShipGroup(sgi).CargoType,
// Load: c.ShipGroup(sgi).Load,
// Tech: maps.Clone(c.ShipGroup(sgi).Tech),
// Destination: c.ShipGroup(sgi).Destination,
// StateInSpace: c.ShipGroup(sgi).StateInSpace,
// StateUpgrade: c.ShipGroup(sgi).StateUpgrade,
// })
sg := *(c.ShipGroup(sgi))
sg.TypeID = c.g.Race[riAccept].ShipTypes[stAcc].ID
sg.Number = uint(quantity)
sg.Tech = maps.Clone(sg.Tech)
c.appendShipGroup(riAccept, &sg)
if quantity == 0 || quantity == c.ShipGroup(sgi).Number {
c.unsafeDeleteShipGroup(sgi)
// g.ShipGroups = append(g.ShipGroups[:sgi], g.ShipGroups[sgi+1:]...)
} else {
c.ShipGroup(sgi).Number -= quantity
}
@@ -548,7 +485,7 @@ func (c *Cache) BreakGroup(ri int, groupIndex, quantity uint) error {
}
if quantity == 0 || quantity == c.ShipGroup(sgi).Number {
c.ShipGroupFleet(sgi, nil)
c.ShipGroupJoinFleet(sgi, nil)
} else {
if _, err := c.breakGroupSafe(ri, groupIndex, quantity); err != nil {
return err
@@ -564,33 +501,29 @@ func (c *Cache) breakGroupSafe(ri int, groupIndex uint, newGroupShips uint) (int
if !ok {
return -1, e.NewEntityNotExistsError("group #%d", groupIndex)
}
// maxIndex := c.ShipGroupMaxIndex(ri)
if c.ShipGroup(sgi).Number < newGroupShips {
return -1, e.NewBreakGroupIllegalNumberError("group #%d ships: %d -> %d", c.ShipGroup(sgi).Index, c.ShipGroup(sgi).Number, newGroupShips)
}
newGroup := *c.ShipGroup(sgi)
if c.ShipGroup(sgi).CargoType != nil {
newGroup.Load = c.ShipGroup(sgi).Load / float64(c.ShipGroup(sgi).Number) * float64(newGroupShips)
// c.ShipGroup(sgi).Load -= newGroup.Load
}
newGroup.Number = newGroupShips
c.ShipGroupShipsNumber(sgi, c.ShipGroup(sgi).Number-newGroup.Number)
// c.ShipGroup(sgi).Number -= newGroup.Number
// newGroup.Index = maxIndex + 1
newGroup.FleetID = nil
st := c.ShipGroupShipClass(sgi)
// c.g.ShipGroups = append(c.g.ShipGroups, newGroup)
return c.appendShipGroup(ri, st, &newGroup), nil
return c.appendShipGroup(ri, &newGroup), nil
}
// Internal funcs
func (c *Cache) appendShipGroup(ri int, class *game.ShipType, sg *game.ShipGroup) int {
func (c *Cache) appendShipGroup(ri int, sg *game.ShipGroup) int {
c.validateRaceIndex(ri)
sg.Index = c.ShipGroupMaxIndex(ri) + 1
sg.OwnerID = c.g.Race[ri].ID
sg.FleetID = nil
c.g.ShipGroups = append(c.g.ShipGroups, *sg)
i := len(c.g.ShipGroups) - 1
c.cacheShipGroup(i, ri, class)
c.invalidateShipGroupCache()
return i
}
@@ -630,9 +563,9 @@ func (c *Cache) shipGroupsInUpgrade(planetNumber uint) iter.Seq[*game.ShipGroup]
}
func (c *Cache) unsafeDeleteShipGroup(i int) {
c.validateShipGroupIndex(i)
c.g.ShipGroups = append(c.g.ShipGroups[:i], c.g.ShipGroups[i+1:]...)
delete(c.raceIndexByShipGroupIndex, i)
delete(c.shipClassByShipGroupIndex, i)
c.invalidateShipGroupCache()
}
func (c *Cache) validateShipGroupIndex(i int) {