Skip to content

Add economy monitoring for dupe and abuse detection - #1148

Open
HarleyGilpin wants to merge 1 commit into
GregHib:mainfrom
HarleyGilpin:feat/economy-monitoring
Open

Add economy monitoring for dupe and abuse detection#1148
HarleyGilpin wants to merge 1 commit into
GregHib:mainfrom
HarleyGilpin:feat/economy-monitoring

Conversation

@HarleyGilpin

@HarleyGilpin HarleyGilpin commented Aug 8, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds configurable economy monitoring (economy.monitor.* in game.properties) to catch item duplication and bug abuse, modeled on how Jagex monitors the GE economy:

  • Trade flagging: flags single trades over a value threshold (TRADE_FLAG_VALUE) and repeated large trades between the same account pair within a sliding window (TRADE_FLAG_PAIR). Hooks the existing TradeConfirm accept flow, valuing offers with Inventory.calculateValue() before the exchange transaction.
  • GE price anomaly detection: flags matched exchanges deviating from ExchangeHistory.marketPrice() beyond a configurable threshold (PRICE_ANOMALY), with a per-item cooldown. Single choke point: a listener list on ExchangeHistory.record().
  • Item census: tracks total counts of watched items (value threshold + explicit watchlist) across three buckets: player inventories (via slotChanged("*"), skipping _-mirror and shop inventories), floor items (spawn/despawn events) and open GE offers (computed from OpenOffers). Periodic snapshots are logged (CENSUS) and persisted; an async reconciliation scan over player saves corrects drift (CENSUS_DRIFT) without blocking the game thread.

All flags write to the existing AuditLog TSVs, so ::logs searches them. When storage.type=database, flags and census snapshots are additionally buffered and flushed to two new append-only tables (economy_flags, economy_census, auto-created by SchemaUtils.create, pruned after economy.monitor.retentionDays) via new default-body Storage methods, FileStorage/SafeStorage untouched.

Everything is content-space except the engine data classes and Storage default methods; zero overhead when disabled (single cached boolean per inventory event). Disabled in WorldTest; hot-reloadable via ::reload settings.

Front-end Preview

Flags

image

Economy Report

image

Test plan

  • Unit: TradeFlagsTest, PriceAnomalyTest, EconomySinkTest
  • WorldTest: TradeFlagsMonitorTest, PriceAnomalyMonitorTest, ItemCensusTest
  • Database (testcontainers): flags/census round-trip + retention prune in DatabaseStorageTest
  • Full engine:test, game:test, database:test green; spotlessApply clean

Three configurable monitors under economy.monitor.*:
- Trade flagging: single trades over a value threshold and repeated
  large trades between the same account pair within a sliding window
- Grand exchange price anomaly detection against market price
- Item census: live per-item counts across player inventories, floor
  and exchange, with periodic snapshots and reconciliation scans of
  player saves to detect drift

All flags are written to the audit log, searchable with ::logs.
When database storage is enabled, flags and census snapshots are also
persisted to append-only economy_flags and economy_census tables
(pruned after economy.monitor.retentionDays) for external reporting.
Disabled in test environments and hot-reloadable via ::reload settings.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant