From 0ea4eec5dd2122c6704216971eb1249276297867 Mon Sep 17 00:00:00 2001 From: historia <[not public]> Date: Fri, 19 Jun 2026 18:20:26 -0400 Subject: shop fixes, 'toggle' completely removed, movement speed increased --- internal/world/world.go | 506 +----------------------------------------------- 1 file changed, 2 insertions(+), 504 deletions(-) (limited to 'internal/world/world.go') diff --git a/internal/world/world.go b/internal/world/world.go index f918293..3094c54 100644 --- a/internal/world/world.go +++ b/internal/world/world.go @@ -2,40 +2,14 @@ package world import ( "fmt" - "math/rand" "os" "path/filepath" - "sort" "strings" "sync" "gopkg.in/yaml.v3" ) -const DropDespawnTicks = 1000 -const ReserveTicks = 100 - -type GroundItemInfo struct { - ItemID string - Quantity int - ReservedFor string - ReserveTimer int - DespawnTimer int - IsSpawn bool -} - -type groundEntry struct { - itemID string - quantity int - isSpawn bool - respawnTimer int // >0 = counting down to respawn - respawnQty int - respawnDelay int - despawnTimer int // >0 = counting down to despawn (dropped items) - reservedFor string - reserveTimer int // >0 = counting down reservation -} - type World struct { dataDir string mu sync.Mutex @@ -45,255 +19,6 @@ type World struct { objMoves []ObjMove } -type ObjMove struct { - DefID string - Name string - FromRoom int - ToRoom int -} - -type ObjState struct { - Depleted bool - DepleteTimer float64 - DefID string - Name string - Index int - RoomID int - JustRespawned bool - WanderRooms []int - WanderInterval float64 - WanderCounter int - SharedMax float64 - SharedTimer int - Quality float64 -} - -func (w *World) ObjStateKey(roomID int, defID string, index int) string { - return fmt.Sprintf("%d:%s:%d", roomID, defID, index) -} - -func (w *World) objStateKey(roomID int, defID string, index int) string { - return w.ObjStateKey(roomID, defID, index) -} - -func (w *World) EnsureObjectStates(roomID int, defIDs []string) { - w.mu.Lock() - defer w.mu.Unlock() - w.ensureObjectStatesLocked(roomID, defIDs) -} - -func (w *World) ensureObjectStatesLocked(roomID int, defIDs []string) { - if w.objStates == nil { - w.objStates = make(map[string]*ObjState) - } - counts := make(map[string]int) - for _, defID := range defIDs { - idx := counts[defID] - counts[defID]++ - key := w.objStateKey(roomID, defID, idx) - if _, exists := w.objStates[key]; !exists { - w.objStates[key] = &ObjState{ - DefID: defID, - Name: defID, - Index: idx, - RoomID: roomID, - } - } - } -} - -func (w *World) AddObjInstance(roomID int, defID string, quality float64) { - w.mu.Lock() - defer w.mu.Unlock() - if w.objStates == nil { - w.objStates = make(map[string]*ObjState) - } - idx := 0 - for { - key := w.objStateKey(roomID, defID, idx) - if _, exists := w.objStates[key]; !exists { - w.objStates[key] = &ObjState{ - DefID: defID, - Name: defID, - Index: idx, - RoomID: roomID, - Quality: quality, - } - return - } - idx++ - } -} - -func (w *World) RemoveObjInstance(roomID int, defID string) { - w.mu.Lock() - defer w.mu.Unlock() - idx := 0 - for { - key := w.objStateKey(roomID, defID, idx) - if _, exists := w.objStates[key]; !exists { - return - } - delete(w.objStates, key) - idx++ - } -} - -func (w *World) AllFireStates() []*ObjState { - w.mu.Lock() - defer w.mu.Unlock() - var out []*ObjState - for _, st := range w.objStates { - if st.DefID == "fire" && st.Quality > 0 { - out = append(out, st) - } - } - return out -} - -func (w *World) GetObjState(roomID int, defID string, index int) *ObjState { - w.mu.Lock() - defer w.mu.Unlock() - if w.objStates == nil { - return nil - } - return w.objStates[w.objStateKey(roomID, defID, index)] -} - -func (w *World) GetObjStateByKey(key string) *ObjState { - w.mu.Lock() - defer w.mu.Unlock() - if w.objStates == nil { - return nil - } - return w.objStates[key] -} - -func (w *World) AllObjInstances(roomID int) []ObjState { - w.mu.Lock() - defer w.mu.Unlock() - var out []ObjState - for _, st := range w.objStates { - if st.RoomID == roomID { - out = append(out, *st) - } - } - sort.Slice(out, func(i, j int) bool { - if out[i].DefID != out[j].DefID { - return out[i].DefID < out[j].DefID - } - return out[i].Index < out[j].Index - }) - return out -} - -func (w *World) FindObjInstances(roomID int, name string) []ObjState { - w.mu.Lock() - defer w.mu.Unlock() - var out []ObjState - lower := strings.ToLower(name) - for _, st := range w.objStates { - if st.RoomID != roomID { - continue - } - if !wordMatchesObj(lower, st.DefID, st.Name) { - continue - } - out = append(out, ObjState{ - DefID: st.DefID, - Name: st.Name, - Index: st.Index, - RoomID: st.RoomID, - Depleted: st.Depleted, - DepleteTimer: st.DepleteTimer, - SharedMax: st.SharedMax, - SharedTimer: st.SharedTimer, - Quality: st.Quality, - }) - } - sort.Slice(out, func(i, j int) bool { - if out[i].DefID != out[j].DefID { - return out[i].DefID < out[j].DefID - } - return out[i].Index < out[j].Index - }) - return out -} - -func wordMatchesObj(lower, defID, objName string) bool { - if WordPrefixMatch(lower, objName) { - return true - } - inputWords := strings.Fields(strings.ToLower(lower)) - - if strings.HasPrefix(strings.ToLower(defID), lower) || strings.HasPrefix(lower, strings.ToLower(defID)) { - return true - } - for _, part := range strings.Split(defID, "_") { - for _, iw := range inputWords { - pl := strings.ToLower(part) - if strings.HasPrefix(pl, iw) || strings.HasPrefix(iw, pl) { - return true - } - } - } - return false -} - -func (w *World) SetObjName(roomID int, defID string, name string) { - w.mu.Lock() - defer w.mu.Unlock() - for _, st := range w.objStates { - if st.RoomID == roomID && st.DefID == defID { - st.Name = name - } - } -} - -func (w *World) SetObjWander(roomID int, defID string, rooms []int, interval float64) { - w.mu.Lock() - defer w.mu.Unlock() - for _, st := range w.objStates { - if st.RoomID == roomID && st.DefID == defID { - st.WanderRooms = rooms - st.WanderInterval = interval - } - } -} - -func (w *World) SetObjDepleteTimer(roomID int, defID string, max float64) { - w.mu.Lock() - defer w.mu.Unlock() - for _, st := range w.objStates { - if st.RoomID == roomID && st.DefID == defID && st.SharedMax == 0 { - st.SharedMax = max - st.SharedTimer = int(max) - } - } -} - -func (w *World) AllSharedObjStates() []*ObjState { - w.mu.Lock() - defer w.mu.Unlock() - var out []*ObjState - for _, st := range w.objStates { - if st.SharedMax > 0 { - out = append(out, st) - } - } - return out -} - -func (w *World) SetObjDepleted(roomID int, defID string, index int, delay float64) { - w.mu.Lock() - defer w.mu.Unlock() - key := w.objStateKey(roomID, defID, index) - if st, ok := w.objStates[key]; ok { - st.Depleted = true - st.DepleteTimer = delay - } -} - func New(dataDir string) *World { return &World{ dataDir: dataDir, @@ -342,129 +67,6 @@ func (w *World) ResolveExit(input string) ExitDir { return "" } -func (w *World) GroundItemsDetailed(roomID int) []GroundItemInfo { - w.mu.Lock() - defer w.mu.Unlock() - var out []GroundItemInfo - for _, e := range w.groundItems[roomID] { - if e.quantity <= 0 { - continue - } - info := GroundItemInfo{ - ItemID: e.itemID, - Quantity: e.quantity, - DespawnTimer: e.despawnTimer, - IsSpawn: e.isSpawn, - } - if e.reserveTimer > 0 && e.reservedFor != "" { - info.ReservedFor = e.reservedFor - info.ReserveTimer = e.reserveTimer - } - out = append(out, info) - } - return out -} - -func (w *World) GroundItems(roomID int) map[string]int { - w.mu.Lock() - defer w.mu.Unlock() - out := make(map[string]int) - for _, e := range w.groundItems[roomID] { - if e.quantity > 0 { - out[e.itemID] += e.quantity - } - } - return out -} - -func (w *World) AddReservedGroundItem(roomID int, itemID string, qty int, owner string) { - w.mu.Lock() - defer w.mu.Unlock() - e := &groundEntry{ - itemID: itemID, - quantity: qty, - despawnTimer: DropDespawnTicks, - reservedFor: owner, - reserveTimer: ReserveTicks, - } - w.groundItems[roomID] = append(w.groundItems[roomID], e) -} - -func (w *World) AddGroundItem(roomID int, itemID string, qty int) { - w.mu.Lock() - defer w.mu.Unlock() - e := &groundEntry{ - itemID: itemID, - quantity: qty, - despawnTimer: DropDespawnTicks, - } - w.groundItems[roomID] = append(w.groundItems[roomID], e) -} - -func (w *World) RemoveReservedGroundItem(roomID int, itemID string, qty int, owner string) (int, bool) { - w.mu.Lock() - defer w.mu.Unlock() - removed := 0 - remaining := qty - for _, e := range w.groundItems[roomID] { - if remaining <= 0 { - break - } - if !strings.EqualFold(e.itemID, itemID) { - continue - } - if e.quantity <= 0 { - continue - } - if e.reserveTimer > 0 && e.reservedFor != "" && e.reservedFor != owner { - return removed, false - } - take := e.quantity - if take > remaining { - take = remaining - } - e.quantity -= take - removed += take - remaining -= take - if e.isSpawn && e.quantity <= 0 && e.respawnDelay > 0 { - e.respawnTimer = e.respawnDelay - } - } - return removed, true -} - -func (w *World) RemoveGroundItem(roomID int, itemID string, qty int) int { - w.mu.Lock() - defer w.mu.Unlock() - - removed := 0 - remaining := qty - - for _, e := range w.groundItems[roomID] { - if remaining <= 0 { - break - } - if !strings.EqualFold(e.itemID, itemID) { - continue - } - if e.quantity <= 0 { - continue - } - take := e.quantity - if take > remaining { - take = remaining - } - e.quantity -= take - removed += take - remaining -= take - - if e.isSpawn && e.quantity <= 0 && e.respawnDelay > 0 { - e.respawnTimer = e.respawnDelay - } - } - return removed -} - func (w *World) SeedGroundItems(roomID int) { w.mu.Lock() if w.seeded[roomID] { @@ -512,110 +114,6 @@ func (w *World) SeedGroundItems(roomID int) { func (w *World) Tick() { w.mu.Lock() defer w.mu.Unlock() - - for _, entries := range w.groundItems { - for _, e := range entries { - if e.respawnTimer > 0 { - e.respawnTimer-- - if e.respawnTimer <= 0 { - e.quantity = e.respawnQty - for _, other := range entries { - if other != e && other.quantity > 0 && strings.EqualFold(other.itemID, e.itemID) && - (other.reserveTimer <= 0 || other.reservedFor == "") && - other.despawnTimer <= 0 { - e.quantity += other.quantity - other.quantity = 0 - } - } - } - } - if e.despawnTimer > 0 { - e.despawnTimer-- - if e.despawnTimer <= 0 { - e.quantity = 0 - } - } - if e.reserveTimer > 0 { - e.reserveTimer-- - if e.reserveTimer <= 0 { - e.reservedFor = "" - } - } - } - } - - for _, st := range w.objStates { - if st.Depleted && st.DepleteTimer > 0 { - st.DepleteTimer-- - if st.DepleteTimer <= 0 { - st.Depleted = false - st.JustRespawned = true - if st.SharedMax > 0 { - st.SharedTimer = int(st.SharedMax) - } - } - } - } -} - -func (w *World) FlushObjRespawns() []ObjState { - w.mu.Lock() - defer w.mu.Unlock() - var out []ObjState - for _, st := range w.objStates { - if st.JustRespawned { - out = append(out, *st) - st.JustRespawned = false - } - } - return out -} - -func (w *World) TickObjWander() { - w.mu.Lock() - defer w.mu.Unlock() - var moves []struct { - st *ObjState - toRoom int - } - for _, st := range w.objStates { - if len(st.WanderRooms) == 0 || st.WanderInterval <= 0 { - continue - } - st.WanderCounter++ - if float64(st.WanderCounter) < st.WanderInterval { - continue - } - st.WanderCounter = 0 - toRoom := st.WanderRooms[rand.Intn(len(st.WanderRooms))] - if toRoom == st.RoomID { - continue - } - moves = append(moves, struct { - st *ObjState - toRoom int - }{st, toRoom}) - } - for _, m := range moves { - oldKey := w.objStateKey(m.st.RoomID, m.st.DefID, m.st.Index) - fromRoom := m.st.RoomID - m.st.RoomID = m.toRoom - newKey := w.objStateKey(m.st.RoomID, m.st.DefID, m.st.Index) - delete(w.objStates, oldKey) - w.objStates[newKey] = m.st - w.objMoves = append(w.objMoves, ObjMove{ - DefID: m.st.DefID, - Name: m.st.Name, - FromRoom: fromRoom, - ToRoom: m.toRoom, - }) - } -} - -func (w *World) FlushObjMoves() []ObjMove { - w.mu.Lock() - defer w.mu.Unlock() - out := w.objMoves - w.objMoves = nil - return out + w.tickGroundItemsLocked() + w.tickObjStatesLocked() } -- cgit v1.2.3