Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -253,8 +253,9 @@ class GrandExchange(
// if offer has more or same as other
val required = offer.amount - offer.completed
val available = open.remaining
val buyer = if (offer.sell) open.account else account
var traded = if (required >= available) available else required
val limit = limits.limit(if (offer.sell) open.account else account, offer.item)
val limit = if (buyer.isEmpty()) -1 else limits.limit(buyer, offer.item)
if (limit != -1) {
traded = traded.coerceAtMost(limit)
if (traded <= 0) {
Expand All @@ -270,8 +271,10 @@ class GrandExchange(
}
claim(open.id, open.account, offer.item, traded, traderPrice, offer.price, !offer.sell)
// Record the successful exchange
limits.record(account, offer.item, traded)
history.record(offer.item, traded, offer.price)
if (buyer.isNotEmpty()) {
limits.record(buyer, offer.item, traded)
}
history.record(offer.item, traded, traderPrice)
return true
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -206,12 +206,11 @@ class GrandExchangeControls : Script {
fun Player.totalItems(): Int {
val item = Item(get("grand_exchange_item", ""))
val noted = item.noted
var total = 0
if (noted != null) {
total += inventory.count(noted.id)
var total = inventory.count(item.id).toLong()
if (noted != null && noted.id != item.id) {
total += inventory.count(noted.id).toLong()
}
total += inventory.count(item.id)
return total
return total.coerceAtMost(Int.MAX_VALUE.toLong()).toInt()
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ class BuyLimits {
}
val now = epochMilliseconds()
for ((player, limit) in limits) {
if (TimeUnit.MILLISECONDS.toHours(now - limit.timestamp) > hours) {
if (TimeUnit.MILLISECONDS.toHours(now - limit.timestamp) >= hours) {
limits.remove(player)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@ import npcOption
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
import org.koin.test.get
import world.gregs.voidps.cache.definition.Params
import world.gregs.voidps.engine.client.ui.dialogue.Dialogues
import world.gregs.voidps.engine.data.Settings
import world.gregs.voidps.engine.data.definition.ItemDefinitions
import world.gregs.voidps.engine.data.exchange.ExchangeOffer
import world.gregs.voidps.engine.data.exchange.OfferState
import world.gregs.voidps.engine.entity.character.npc.NPC
Expand Down Expand Up @@ -46,6 +48,61 @@ class GrandExchangeTest : WorldTest() {
clerk = createNPC("grand_exchange_clerk_short", Tile(3164, 3488))
}

@Test
fun `Edit sell quantity with a large stack of unnoteable items`() {
val seller = createPlayer(Tile(3164, 3487), "seller")
seller.inventory.add("fire_rune", 2_140_000_000)

sell(seller, "fire_rune")
seller.interfaceOption("grand_exchange", "add_x", "Edit Quantity")
(seller.suspension as Suspension.IntEntry).resume(100_000)

assertEquals(100_000, seller.get<Int>("grand_exchange_quantity"))
tick()
seller.interfaceOption("grand_exchange", "add_x", "Edit Quantity")
(seller.suspension as Suspension.IntEntry).resume(Int.MAX_VALUE)
assertEquals(2_140_000_000, seller.get<Int>("grand_exchange_quantity"))
}

@Test
fun `Combined noted and unnoted sell quantities saturate at integer maximum`() {
val seller = createPlayer(Tile(3164, 3487), "seller")
seller.inventory.add("rune_longsword_noted", Int.MAX_VALUE)
seller.inventory.add("rune_longsword")

sell(seller, "rune_longsword")
seller.interfaceOption("grand_exchange", "add_x", "Edit Quantity")
(seller.suspension as Suspension.IntEntry).resume(100_000)

assertEquals(100_000, seller.get<Int>("grand_exchange_quantity"))
tick()
seller.interfaceOption("grand_exchange", "add_x", "Edit Quantity")
(seller.suspension as Suspension.IntEntry).resume(Int.MAX_VALUE)
assertEquals(Int.MAX_VALUE, seller.get<Int>("grand_exchange_quantity"))
}

@Test
fun `Instant sells do not share a synthetic buyer limit`() {
Settings.load(mapOf("grandExchange.instantOffer" to "true", "grandExchange.instantSellUnderMarketPrice" to "0.0"))
val definition = ItemDefinitions.get("rune_longsword")
val originalParams = definition.params
definition.params = (originalParams ?: emptyMap()) + (Params.LIMIT to 1)
try {
for (name in listOf("sellerone", "sellertwo")) {
val seller = createPlayer(Tile(3164, 3487), name)
seller.inventory.add("rune_longsword")
sell(seller, "rune_longsword")
confirm(seller)
tick()
val offer = seller.offers[1]
assertEquals(OfferState.CompletedSell, offer.state)
assertEquals(1, offer.completed)
}
} finally {
definition.params = originalParams
}
}

@Test
fun `Sell item mid price using coins in bank`() {
val seller = createPlayer(Tile(3164, 3487), "seller")
Expand Down