refactor: group uuid instead of index
This commit is contained in:
@@ -10,43 +10,8 @@ import (
|
||||
"github.com/google/uuid"
|
||||
e "github.com/iliadenisov/galaxy/internal/error"
|
||||
"github.com/iliadenisov/galaxy/internal/model/game"
|
||||
"github.com/iliadenisov/galaxy/internal/number"
|
||||
)
|
||||
|
||||
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 q", shipTypeName)
|
||||
}
|
||||
|
||||
p, ok := c.Planet(planetNumber)
|
||||
if !ok {
|
||||
return e.NewEntityNotExistsError("planet #%d", planetNumber)
|
||||
}
|
||||
if !p.OwnedBy(c.g.Race[ri].ID) {
|
||||
return e.NewEntityNotOwnedError("planet #%d", planetNumber)
|
||||
}
|
||||
|
||||
c.createShipsUnsafe(ri, class.ID, p.Number, uint(quantity))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Cache) createShipsUnsafe(ri int, classID uuid.UUID, planet uint, quantity uint) {
|
||||
c.appendShipGroup(ri, &game.ShipGroup{
|
||||
OwnerID: c.g.Race[ri].ID,
|
||||
TypeID: classID,
|
||||
Destination: planet,
|
||||
Number: uint(quantity),
|
||||
Tech: map[game.Tech]game.Float{
|
||||
game.TechDrive: game.F(c.g.Race[ri].TechLevel(game.TechDrive)),
|
||||
game.TechWeapons: game.F(c.g.Race[ri].TechLevel(game.TechWeapons)),
|
||||
game.TechShields: game.F(c.g.Race[ri].TechLevel(game.TechShields)),
|
||||
game.TechCargo: game.F(c.g.Race[ri].TechLevel(game.TechCargo)),
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
// ShipGroup is a proxy func, nothing to cache
|
||||
func (c *Cache) ShipGroup(groupIndex int) *game.ShipGroup {
|
||||
c.validateShipGroupIndex(groupIndex)
|
||||
@@ -77,16 +42,6 @@ func (c *Cache) ShipGroupsIndex() iter.Seq[int] {
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Cache) ShipGroupMaxIndex(ri int) uint {
|
||||
var max uint = 0
|
||||
for i := range c.g.ShipGroups {
|
||||
if r := c.ShipGroupOwnerRaceIndex(i); r == ri && c.ShipGroup(i).Index > max {
|
||||
max = c.ShipGroup(i).Index
|
||||
}
|
||||
}
|
||||
return max
|
||||
}
|
||||
|
||||
func (c *Cache) ShipGroupOwnerRaceIndex(groupIndex int) int {
|
||||
c.validateShipGroupIndex(groupIndex)
|
||||
if len(c.cacheRaceIndexByShipGroupIndex) == 0 {
|
||||
@@ -167,7 +122,7 @@ func (c *Cache) shipGroupMerge(ri int) {
|
||||
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 = number.Max(raceGroups[i].Index, raceGroups[j].Index)
|
||||
raceGroups[i].ID = raceGroups[j].ID
|
||||
raceGroups[i].Number += raceGroups[j].Number
|
||||
raceGroups = append(raceGroups[:j], raceGroups[j+1:]...)
|
||||
}
|
||||
@@ -195,7 +150,7 @@ func (c *Cache) shipGroupMerge(ri int) {
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Cache) shipGroupDismantle(ri int, groupIndex, quantity uint) error {
|
||||
func (c *Cache) shipGroupDismantle(ri int, groupIndex uuid.UUID, quantity uint) error {
|
||||
sgi, ok := c.raceShipGroupIndex(ri, groupIndex)
|
||||
if !ok {
|
||||
return e.NewEntityNotExistsError("group #%d", groupIndex)
|
||||
@@ -253,13 +208,13 @@ func (c *Cache) shipGroupDismantle(ri int, groupIndex, quantity uint) error {
|
||||
// Корабль может нести только один тип груза одновременно.
|
||||
// Возможные типы груза - это колонисты, сырье и промышленность.
|
||||
// Груз может быть доставлен на борт корабля с Вашей или не занятой планеты, на которой он имеется.
|
||||
func (c *Cache) shipGroupLoad(ri int, groupIndex uint, ct game.CargoType, ships uint, quantity float64) error {
|
||||
func (c *Cache) shipGroupLoad(ri int, groupID uuid.UUID, ct game.CargoType, ships uint, quantity float64) error {
|
||||
if ships == 0 && quantity > 0 {
|
||||
return e.NewCargoQuantityWithoutGroupBreakError()
|
||||
}
|
||||
sgi, ok := c.raceShipGroupIndex(ri, groupIndex)
|
||||
sgi, ok := c.raceShipGroupIndex(ri, groupID)
|
||||
if !ok {
|
||||
return e.NewEntityNotExistsError("group #%d", groupIndex)
|
||||
return e.NewEntityNotExistsError("group %s", groupID)
|
||||
}
|
||||
if state := c.ShipGroup(sgi).State(); state != game.StateInOrbit {
|
||||
return e.NewShipsBusyError("state: %s", state)
|
||||
@@ -281,7 +236,7 @@ func (c *Cache) shipGroupLoad(ri int, groupIndex uint, ct game.CargoType, ships
|
||||
return e.NewCargoLoadNotEqualError("cargo: %v", *c.ShipGroup(sgi).CargoType)
|
||||
}
|
||||
if ships > 0 && ships < c.ShipGroup(sgi).Number {
|
||||
nsgi, err := c.breakGroupSafe(ri, groupIndex, ships)
|
||||
nsgi, err := c.breakGroupSafe(ri, groupID, ships)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -323,14 +278,14 @@ func (c *Cache) shipGroupLoad(ri int, groupIndex uint, ct game.CargoType, ships
|
||||
|
||||
// Промышленность и Сырье могут быть выгружены на любой планете.
|
||||
// Колонисты могут быть высажены только на планеты, принадлежащие Вам или на необитаемые планеты.
|
||||
func (c *Cache) shipGroupUnload(ri int, groupIndex uint, ships uint, quantity float64) error {
|
||||
func (c *Cache) shipGroupUnload(ri int, groupID uuid.UUID, ships uint, quantity float64) error {
|
||||
c.validateRaceIndex(ri)
|
||||
if ships == 0 && quantity > 0 {
|
||||
return e.NewCargoQuantityWithoutGroupBreakError()
|
||||
}
|
||||
sgi, ok := c.raceShipGroupIndex(ri, groupIndex)
|
||||
sgi, ok := c.raceShipGroupIndex(ri, groupID)
|
||||
if !ok {
|
||||
return e.NewEntityNotExistsError("group #%d", groupIndex)
|
||||
return e.NewEntityNotExistsError("group %s", groupID)
|
||||
}
|
||||
if state := c.ShipGroup(sgi).State(); state != game.StateInOrbit {
|
||||
return e.NewShipsBusyError("state: %s", state)
|
||||
@@ -350,7 +305,7 @@ func (c *Cache) shipGroupUnload(ri int, groupIndex uint, ships uint, quantity fl
|
||||
return e.NewEntityNotOwnedError("planet #%d unload %v", p.Number, ct)
|
||||
}
|
||||
if ships > 0 && ships < c.ShipGroup(sgi).Number {
|
||||
nsgi, err := c.breakGroupSafe(ri, groupIndex, ships)
|
||||
nsgi, err := c.breakGroupSafe(ri, groupID, ships)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -405,13 +360,13 @@ func (c *Cache) unsafeUnloadCargo(sgi int, q float64) {
|
||||
p.UnpackCapital()
|
||||
}
|
||||
|
||||
func (c *Cache) shipGroupTransfer(ri, riAccept int, groupIndex, quantity uint) (err error) {
|
||||
func (c *Cache) shipGroupTransfer(ri, riAccept int, groupID uuid.UUID, quantity uint) (err error) {
|
||||
if ri == riAccept {
|
||||
return e.NewSameRaceError(c.g.Race[riAccept].Name)
|
||||
}
|
||||
sgi, ok := c.raceShipGroupIndex(ri, groupIndex)
|
||||
sgi, ok := c.raceShipGroupIndex(ri, groupID)
|
||||
if !ok {
|
||||
return e.NewEntityNotExistsError("group #%d", groupIndex)
|
||||
return e.NewEntityNotExistsError("group %s", groupID)
|
||||
}
|
||||
sg := c.ShipGroup(sgi)
|
||||
state := sg.State()
|
||||
@@ -444,6 +399,7 @@ func (c *Cache) shipGroupTransfer(ri, riAccept int, groupIndex, quantity uint) (
|
||||
}
|
||||
|
||||
newGroup := *(sg)
|
||||
newGroup.ID = uuid.New()
|
||||
newGroup.TypeID = c.g.Race[riAccept].ShipTypes[stAcc].ID
|
||||
newGroup.Tech = maps.Clone(sg.Tech)
|
||||
if state == game.StateLaunched {
|
||||
@@ -451,6 +407,7 @@ func (c *Cache) shipGroupTransfer(ri, riAccept int, groupIndex, quantity uint) (
|
||||
}
|
||||
|
||||
if quantity == 0 || quantity == sg.Number {
|
||||
// FIXME: remove fleet & invalidate cache?
|
||||
c.unsafeDeleteShipGroup(sgi)
|
||||
} else {
|
||||
newGroup.Number = quantity
|
||||
@@ -462,17 +419,11 @@ func (c *Cache) shipGroupTransfer(ri, riAccept int, groupIndex, quantity uint) (
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Cache) ShipGroupBreak(ri int, groupIndex, quantity uint) error {
|
||||
func (c *Cache) ShipGroupBreak(ri int, groupID uuid.UUID, quantity uint) error {
|
||||
c.validateRaceIndex(ri)
|
||||
sgi := -1
|
||||
for i := range c.ShipGroupsIndex() {
|
||||
if c.ShipGroupOwnerRaceIndex(i) == ri && c.ShipGroup(i).Index == groupIndex {
|
||||
sgi = i
|
||||
break
|
||||
}
|
||||
}
|
||||
if sgi < 0 {
|
||||
return e.NewEntityNotExistsError("group #%d", groupIndex)
|
||||
sgi, ok := c.raceShipGroupIndex(ri, groupID)
|
||||
if !ok {
|
||||
return e.NewEntityNotExistsError("group %s", groupID)
|
||||
}
|
||||
|
||||
if state := c.ShipGroup(sgi).State(); state != game.StateInOrbit {
|
||||
@@ -486,7 +437,7 @@ func (c *Cache) ShipGroupBreak(ri int, groupIndex, quantity uint) error {
|
||||
if quantity == 0 || quantity == c.ShipGroup(sgi).Number {
|
||||
c.internalShipGroupJoinFleet(sgi, nil)
|
||||
} else {
|
||||
if _, err := c.breakGroupSafe(ri, groupIndex, quantity); err != nil {
|
||||
if _, err := c.breakGroupSafe(ri, groupID, quantity); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@@ -494,14 +445,14 @@ func (c *Cache) ShipGroupBreak(ri int, groupIndex, quantity uint) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Cache) breakGroupSafe(ri int, groupIndex uint, newGroupShips uint) (int, error) {
|
||||
func (c *Cache) breakGroupSafe(ri int, groupID uuid.UUID, newGroupShips uint) (int, error) {
|
||||
c.validateRaceIndex(ri)
|
||||
sgi, ok := c.raceShipGroupIndex(ri, groupIndex)
|
||||
sgi, ok := c.raceShipGroupIndex(ri, groupID)
|
||||
if !ok {
|
||||
return -1, e.NewEntityNotExistsError("group #%d", groupIndex)
|
||||
return -1, e.NewEntityNotExistsError("group %s", groupID)
|
||||
}
|
||||
if c.ShipGroup(sgi).Number < newGroupShips {
|
||||
return -1, e.NewBreakGroupIllegalNumberError("group #%d ships: %d -> %d", c.ShipGroup(sgi).Index, c.ShipGroup(sgi).Number, newGroupShips)
|
||||
return -1, e.NewBreakGroupIllegalNumberError("group=%s ships: %d -> %d", c.ShipGroup(sgi).ID, c.ShipGroup(sgi).Number, newGroupShips)
|
||||
}
|
||||
return c.breakGroupUnsafe(ri, sgi, newGroupShips), nil
|
||||
}
|
||||
@@ -519,35 +470,35 @@ func (c *Cache) breakGroupUnsafe(ri, sgi int, newGroupShips uint) int {
|
||||
|
||||
// Internal funcs
|
||||
|
||||
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.invalidateShipGroupCache()
|
||||
return i
|
||||
}
|
||||
|
||||
func (c *Cache) raceShipGroupIndex(ri int, index uint) (int, bool) {
|
||||
func (c *Cache) raceShipGroupIndex(ri int, id uuid.UUID) (int, bool) {
|
||||
c.validateRaceIndex(ri)
|
||||
for i := range c.ShipGroupsIndex() {
|
||||
if c.ShipGroupOwnerRaceIndex(i) == ri && c.ShipGroup(i).Index == index {
|
||||
if c.ShipGroupOwnerRaceIndex(i) == ri && c.ShipGroup(i).ID == id {
|
||||
return i, true
|
||||
}
|
||||
}
|
||||
return -1, false
|
||||
}
|
||||
|
||||
func (c *Cache) listShipGroupIdx(ri int) iter.Seq[int] {
|
||||
c.validateRaceIndex(ri)
|
||||
return func(yield func(int) bool) {
|
||||
for i := range c.g.ShipGroups {
|
||||
if ri == c.ShipGroupOwnerRaceIndex(i) {
|
||||
if !yield(i) {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Cache) listShipGroups(ri int) iter.Seq[*game.ShipGroup] {
|
||||
c.validateRaceIndex(ri)
|
||||
return func(yield func(*game.ShipGroup) bool) {
|
||||
for i := range c.g.ShipGroups {
|
||||
if ri == c.ShipGroupOwnerRaceIndex(i) {
|
||||
if !yield(&c.g.ShipGroups[i]) {
|
||||
return
|
||||
}
|
||||
for sgi := range c.listShipGroupIdx(ri) {
|
||||
if !yield(c.ShipGroup(sgi)) {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -584,3 +535,29 @@ func (c *Cache) validateShipGroupIndex(i int) {
|
||||
panic(fmt.Sprintf("group index out of range: %d >= %d", i, len(c.g.ShipGroups)))
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Cache) createShipsUnsafe(ri int, classID uuid.UUID, planet uint, quantity uint) {
|
||||
c.appendShipGroup(ri, &game.ShipGroup{
|
||||
OwnerID: c.g.Race[ri].ID,
|
||||
TypeID: classID,
|
||||
Destination: planet,
|
||||
Number: uint(quantity),
|
||||
Tech: map[game.Tech]game.Float{
|
||||
game.TechDrive: game.F(c.g.Race[ri].TechLevel(game.TechDrive)),
|
||||
game.TechWeapons: game.F(c.g.Race[ri].TechLevel(game.TechWeapons)),
|
||||
game.TechShields: game.F(c.g.Race[ri].TechLevel(game.TechShields)),
|
||||
game.TechCargo: game.F(c.g.Race[ri].TechLevel(game.TechCargo)),
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func (c *Cache) appendShipGroup(ri int, sg *game.ShipGroup) int {
|
||||
c.validateRaceIndex(ri)
|
||||
sg.ID = uuid.New()
|
||||
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.invalidateShipGroupCache()
|
||||
return i
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user