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/ground.go | 189 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 189 insertions(+) create mode 100644 internal/world/ground.go (limited to 'internal/world/ground.go') diff --git a/internal/world/ground.go b/internal/world/ground.go new file mode 100644 index 0000000..6c3ecf3 --- /dev/null +++ b/internal/world/ground.go @@ -0,0 +1,189 @@ +package world + +import ( + "strings" +) + +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 +} + +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) tickGroundItemsLocked() { + for _, entries := range w.groundItems { + for _, e := range entries { + if e.respawnTimer > 0 { + e.respawnTimer-- + if e.respawnTimer <= 0 { + e.quantity = e.respawnQty + w.mergeNearbyItemsLocked(entries, e) + } + } + 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 = "" + } + } + } + } +} + +func (w *World) mergeNearbyItemsLocked(entries []*groundEntry, target *groundEntry) { + for _, other := range entries { + if other != target && other.quantity > 0 && strings.EqualFold(other.itemID, target.itemID) && + (other.reserveTimer <= 0 || other.reservedFor == "") && + other.despawnTimer <= 0 { + target.quantity += other.quantity + other.quantity = 0 + } + } +} -- cgit v1.2.3