diff options
| author | historia <[not public]> | 2026-06-29 18:13:33 -0400 |
|---|---|---|
| committer | historia <[not public]> | 2026-06-29 18:13:33 -0400 |
| commit | 7d76673fa0707d204c7d084c8f90c8133c22a31a (patch) | |
| tree | 6fc832b9f3fde6ed455abb535f6e28b0e5db1fd9 /internal/game/production_index.go | |
| parent | feb80b7dde200d4121cd9f9c583a08f9869c5588 (diff) | |
| download | thehouseoficarus-7d76673fa0707d204c7d084c8f90c8133c22a31a.tar.gz | |
feat: migrated map (and bfs) to full 3D instead of individual 2D maps on different planes.
Diffstat (limited to 'internal/game/production_index.go')
| -rw-r--r-- | internal/game/production_index.go | 234 |
1 files changed, 234 insertions, 0 deletions
diff --git a/internal/game/production_index.go b/internal/game/production_index.go new file mode 100644 index 0000000..648ccc8 --- /dev/null +++ b/internal/game/production_index.go @@ -0,0 +1,234 @@ +package game + +import ( + "sync" + + "thehouseoficarus/internal/item" +) + +type CraftIndex struct { + mu sync.RWMutex + byType map[string][]*item.ItemDef + byInput map[string][]*item.ItemDef + byStation map[string][]*item.ItemDef +} + +func NewCraftIndex() *CraftIndex { + return &CraftIndex{ + byType: make(map[string][]*item.ItemDef), + byInput: make(map[string][]*item.ItemDef), + byStation: make(map[string][]*item.ItemDef), + } +} + +func (idx *CraftIndex) Build(items []*item.ItemDef) { + idx.mu.Lock() + defer idx.mu.Unlock() + + idx.byType = make(map[string][]*item.ItemDef) + idx.byInput = make(map[string][]*item.ItemDef) + idx.byStation = make(map[string][]*item.ItemDef) + + for _, def := range items { + if len(def.Craft) == 0 { + continue + } + for ci := range def.Craft { + craft := &def.Craft[ci] + t := craft.Type + if t == "" { + t = "combine" + } + idx.byType[t] = appendUnique(idx.byType[t], def) + + for _, e := range craft.Consume { + for _, id := range e.Items { + idx.byInput[id] = appendUnique(idx.byInput[id], def) + } + } + + for _, sid := range craft.Station { + idx.byStation[sid] = appendUnique(idx.byStation[sid], def) + } + } + } +} + +func appendUnique(items []*item.ItemDef, item *item.ItemDef) []*item.ItemDef { + for _, existing := range items { + if existing == item { + return items + } + } + return append(items, item) +} + +func (idx *CraftIndex) ByType(craftType string) []*item.ItemDef { + idx.mu.RLock() + defer idx.mu.RUnlock() + items := idx.byType[craftType] + out := make([]*item.ItemDef, len(items)) + copy(out, items) + return out +} + +func (idx *CraftIndex) ByStation(stationDefID string) []*item.ItemDef { + idx.mu.RLock() + defer idx.mu.RUnlock() + items := idx.byStation[stationDefID] + out := make([]*item.ItemDef, len(items)) + copy(out, items) + return out +} + +func (idx *CraftIndex) ByInput(itemID string) []*item.ItemDef { + idx.mu.RLock() + defer idx.mu.RUnlock() + items := idx.byInput[itemID] + out := make([]*item.ItemDef, len(items)) + copy(out, items) + return out +} + +func (idx *CraftIndex) FindByTwoInputs(itemA, itemB string) []*item.ItemDef { + idx.mu.RLock() + defer idx.mu.RUnlock() + + candidatesA := idx.byInput[itemA] + if len(candidatesA) == 0 { + return nil + } + + candidateSetB := make(map[string]bool) + for _, def := range idx.byInput[itemB] { + candidateSetB[def.ID] = true + } + + var results []*item.ItemDef + for _, def := range candidatesA { + if !candidateSetB[def.ID] { + continue + } + for _, craft := range def.Craft { + entryA := craftEntry(craft, itemA) + entryB := craftEntry(craft, itemB) + if entryA >= 0 && entryB >= 0 && entryA != entryB { + results = append(results, def) + break + } + } + } + return results +} + +func (idx *CraftIndex) FindByStationInput(stationDefID, itemID string) []*item.ItemDef { + idx.mu.RLock() + defer idx.mu.RUnlock() + + var results []*item.ItemDef + for _, def := range idx.byStation[stationDefID] { + for _, craft := range def.Craft { + if craftMatchesEntry(&craft, itemID) { + results = append(results, def) + break + } + } + } + return results +} + +func craftEntryFor(def *item.ItemDef, itemID string) int { + for _, craft := range def.Craft { + if ei := craftEntry(craft, itemID); ei >= 0 { + return ei + } + } + return -1 +} + +func craftEntry(craft item.CraftDef, itemID string) int { + for ei, e := range craft.Consume { + for _, id := range e.Items { + if id == itemID { + return ei + } + } + } + return -1 +} + +func craftMatchesEntry(c *item.CraftDef, itemID string) bool { + if c == nil { + return false + } + for _, e := range c.Consume { + for _, id := range e.Items { + if id == itemID { + return true + } + } + } + return false +} + +func craftHasAllItems(c *item.CraftDef, hasItem func(string) bool) bool { + if c == nil { + return false + } + for _, e := range c.Consume { + found := false + for _, id := range e.Items { + if hasItem(id) { + found = true + break + } + } + if !found { + return false + } + } + return true +} + +func craftHasAllItemsQty(c *item.CraftDef, countItem func(string) int) bool { + if c == nil { + return false + } + for _, e := range c.Consume { + found := false + for _, id := range e.Items { + qty := e.Quantity + if qty <= 0 { + qty = 1 + } + if countItem(id) >= qty { + found = true + break + } + } + if !found { + return false + } + } + return true +} + +func craftConsumeAll(c *item.CraftDef, hasItem func(string) bool, removeItem func(string, int) bool) bool { + if c == nil { + return false + } + for _, e := range c.Consume { + found := false + for _, id := range e.Items { + if hasItem(id) { + removeItem(id, e.Quantity) + found = true + break + } + } + if !found { + return false + } + } + return true +} |
