Fixed regression causing GE to eat noted items

This commit is contained in:
Ceikry 2023-08-12 00:21:25 +00:00 committed by Ryan
parent 418f239261
commit 2e70a9714a
2 changed files with 115 additions and 12 deletions

View file

@ -19,6 +19,7 @@ import core.game.ge.PriceIndex
import core.game.interaction.InterfaceListener import core.game.interaction.InterfaceListener
import core.tools.Log import core.tools.Log
import core.tools.SystemLogger import core.tools.SystemLogger
import kotlin.math.min
/** /**
* Handles the grand exchange interface (Stock Market) * Handles the grand exchange interface (Stock Market)
@ -216,19 +217,28 @@ class StockMarket : InterfaceListener {
offer.visualize(player) offer.visualize(player)
} }
fun confirmOffer(player: Player, offer: GrandExchangeOffer, index: Int) enum class OfferConfirmResult {
Success,
ZeroCoins,
TooManyCoins,
NotEnoughItemsOrCoins,
ItemRemovalFailure,
OfferPlacementError
}
fun confirmOffer(player: Player, offer: GrandExchangeOffer, index: Int) : OfferConfirmResult
{ {
if(offer.offeredValue < 1) if(offer.offeredValue < 1)
{ {
playAudio(player, Audio(4039, 1, 1)) playAudio(player, Audio(4039, 1, 1))
sendMessage(player, "You can't make an offer for 0 coins.") sendMessage(player, "You can't make an offer for 0 coins.")
return return OfferConfirmResult.ZeroCoins
} }
if(offer.amount > Int.MAX_VALUE / offer.offeredValue) if(offer.amount > Int.MAX_VALUE / offer.offeredValue)
{ {
playAudio(player, Audio(4039, 1, 1)) playAudio(player, Audio(4039, 1, 1))
sendMessage(player, "You can't ${if(offer.sell) "sell" else "buy"} this much!") sendMessage(player, "You can't ${if(offer.sell) "sell" else "buy"} this much!")
return return OfferConfirmResult.TooManyCoins
} }
offer.index = index offer.index = index
if(offer.sell) if(offer.sell)
@ -239,21 +249,25 @@ class StockMarket : InterfaceListener {
playAudio(player, Audio(4039, 1, 1)) playAudio(player, Audio(4039, 1, 1))
sendMessage(player, "You do not have enough of this item in your inventory to cover the") sendMessage(player, "You do not have enough of this item in your inventory to cover the")
sendMessage(player, "offer.") sendMessage(player, "offer.")
return return OfferConfirmResult.NotEnoughItemsOrCoins
} }
var item: Item val amountUnnoted = min(amountInInventory(player, offer.itemID), offer.amount)
val amountUnnoted = amountInInventory(player, offer.itemID)
val amountLeft = offer.amount - amountUnnoted val amountLeft = offer.amount - amountUnnoted
val removedUnnoted = removeItem(player, Item(offer.itemID, amountUnnoted).also { item = it }) val removedUnnoted = if (amountUnnoted > 0) removeItem(player, Item(offer.itemID, amountUnnoted)) else true
val removeNoted = if (amountLeft > 0) removeItem(player, Item(itemDefinition(offer.itemID).noteId, amountLeft)) else true val removeNoted = if (amountLeft > 0) removeItem(player, Item(itemDefinition(offer.itemID).noteId, amountLeft)) else true
if (!removedUnnoted || !removeNoted) return if (!removedUnnoted || !removeNoted) return OfferConfirmResult.ItemRemovalFailure
if(GrandExchange.dispatch(player, offer)) if(GrandExchange.dispatch(player, offer))
{ {
player.removeAttribute("ge-temp") player.removeAttribute("ge-temp")
} }
else else
{ {
addItem(player, item.id, item.amount) if (amountUnnoted > 0)
addItem(player, offer.itemID, offer.amount - amountLeft)
if (amountLeft > 0)
addItem(player, itemDefinition(offer.itemID).noteId, amountLeft)
sendMessage(player, "Unable to place GE offer. Please try again.")
return OfferConfirmResult.OfferPlacementError
} }
} }
else else
@ -263,7 +277,7 @@ class StockMarket : InterfaceListener {
{ {
playAudio(player, Audio(4039, 1, 1)) playAudio(player, Audio(4039, 1, 1))
sendMessage(player, "You do not have enough coins to cover the offer.") sendMessage(player, "You do not have enough coins to cover the offer.")
return return OfferConfirmResult.NotEnoughItemsOrCoins
} }
if(GrandExchange.dispatch(player, offer) && removeItem(player, Item(995, total))) if(GrandExchange.dispatch(player, offer) && removeItem(player, Item(995, total)))
{ {
@ -273,6 +287,7 @@ class StockMarket : InterfaceListener {
playAudio(player, Audio(4043, 1, 1)) playAudio(player, Audio(4043, 1, 1))
offer.visualize(player) offer.visualize(player)
toMainInterface(player) toMainInterface(player)
return OfferConfirmResult.Success
} }
fun getInventoryAmount(player: Player, itemId: Int): Int { fun getInventoryAmount(player: Player, itemId: Int): Int {

View file

@ -1,3 +1,4 @@
import content.global.handlers.iface.ge.StockMarket
import core.game.ge.OfferState import core.game.ge.OfferState
import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@ -11,6 +12,8 @@ import core.game.ge.GEDB
import core.game.ge.GrandExchange import core.game.ge.GrandExchange
import core.game.ge.GrandExchangeOffer import core.game.ge.GrandExchangeOffer
import core.game.ge.PriceIndex import core.game.ge.PriceIndex
import core.game.node.item.Item
import org.rs09.consts.Items
import java.io.File import java.io.File
@TestInstance(TestInstance.Lifecycle.PER_CLASS) class ExchangeTests { @TestInstance(TestInstance.Lifecycle.PER_CLASS) class ExchangeTests {
@ -21,10 +24,10 @@ import java.io.File
GEDB.init(TEST_DB_PATH) GEDB.init(TEST_DB_PATH)
} }
fun generateOffer(itemId: Int, amount: Int, price: Int, sale: Boolean, username: String = "test ${System.currentTimeMillis()}") : GrandExchangeOffer { fun generateOffer(itemId: Int, amount: Int, price: Int, sale: Boolean, username: String = "test ${System.currentTimeMillis()}", offerState: OfferState = OfferState.REGISTERED) : GrandExchangeOffer {
val offer = GrandExchangeOffer() val offer = GrandExchangeOffer()
val uid = username.hashCode() // normally this would be the account's uid but in the test we don't have an account val uid = username.hashCode() // normally this would be the account's uid but in the test we don't have an account
offer.offerState = OfferState.REGISTERED offer.offerState = offerState
offer.itemID = itemId offer.itemID = itemId
offer.offeredValue = price offer.offeredValue = price
offer.amount = amount offer.amount = amount
@ -37,6 +40,22 @@ import java.io.File
return offer return offer
} }
fun generateUnsentOffer (itemId: Int, amount: Int, price: Int, sale: Boolean, username: String, offerState: OfferState = OfferState.PENDING) : GrandExchangeOffer {
val offer = GrandExchangeOffer()
val uid = username.hashCode() // normally this would be the account's uid but in the test we don't have an account
offer.offerState = offerState
offer.itemID = itemId
offer.offeredValue = price
offer.amount = amount
offer.timeStamp = System.currentTimeMillis()
offer.index = 0
offer.isBot = false
offer.playerUID = uid
offer.sell = sale
offer.uid = 0L
return offer
}
@AfterAll @JvmStatic fun cleanup() { @AfterAll @JvmStatic fun cleanup() {
File(TEST_DB_PATH).delete() File(TEST_DB_PATH).delete()
} }
@ -115,4 +134,73 @@ import java.io.File
Assertions.assertEquals(false, b.isCancelled) Assertions.assertEquals(false, b.isCancelled)
} }
} }
@Test fun offerWithCombinedNotedAndUnnotedAmountShouldSuceed() {
TestUtils.getMockPlayer("combinedNotendAndUnnotedExcTest").use { p ->
val offer = generateUnsentOffer(4151, 1000, 1500, true, p.name, OfferState.PENDING)
val mkt = StockMarket()
p.inventory.add(Item(Items.ABYSSAL_WHIP_4151, 10))
p.inventory.add(Item(Items.ABYSSAL_WHIP_4152, 990))
Assertions.assertEquals(StockMarket.OfferConfirmResult.Success, mkt.confirmOffer(p, offer, 0))
Assertions.assertEquals(0, p.inventory.getAmount(4151))
Assertions.assertEquals(0, p.inventory.getAmount(4152))
}
}
@Test fun offerWithOnlyNotedAmountShouldSucceed() {
TestUtils.getMockPlayer("onlyNotedOfferSucceed").use { p ->
val offer = generateUnsentOffer(4151, 1000, 1500, true, p.name, OfferState.PENDING)
val mkt = StockMarket()
p.inventory.add(Item(Items.ABYSSAL_WHIP_4152, 1000))
Assertions.assertEquals(StockMarket.OfferConfirmResult.Success, mkt.confirmOffer(p, offer, 0))
Assertions.assertEquals(0, p.inventory.getAmount(4151))
Assertions.assertEquals(0, p.inventory.getAmount(4152))
}
}
@Test fun offerWithMoreUnnotedItemsThanOfferAmountShouldSucceed() {
TestUtils.getMockPlayer("onlyUnnotedOfferWithExtraItemsSucceed").use { p ->
val offer = generateUnsentOffer(4151, 10, 1500, true, p.name, OfferState.PENDING)
val mkt = StockMarket()
p.inventory.add(Item(Items.ABYSSAL_WHIP_4151, 20))
Assertions.assertEquals(StockMarket.OfferConfirmResult.Success, mkt.confirmOffer(p, offer, 0))
Assertions.assertEquals(10, p.inventory.getAmount(4151))
Assertions.assertEquals(0, p.inventory.getAmount(4152))
}
}
@Test fun offerWithOnlyUnnotedAmountShouldSucceed() {
TestUtils.getMockPlayer("onlyUnnotedOfferSucceed").use { p ->
val offer = generateUnsentOffer(4151, 10, 1500, true, p.name, OfferState.PENDING)
val mkt = StockMarket()
p.inventory.add(Item(Items.ABYSSAL_WHIP_4151, 10))
Assertions.assertEquals(StockMarket.OfferConfirmResult.Success, mkt.confirmOffer(p, offer, 0))
Assertions.assertEquals(0, p.inventory.getAmount(4151))
Assertions.assertEquals(0, p.inventory.getAmount(4152))
}
}
@Test fun offerWithNotEnoughNotedItemsShouldFail() {
TestUtils.getMockPlayer("combinedNotedAndUnnotedFailure").use { p ->
val offer = generateUnsentOffer(4151, 1000, 1500, true, p.name, OfferState.PENDING)
val mkt = StockMarket()
p.inventory.add(Item(Items.ABYSSAL_WHIP_4151, 10))
p.inventory.add(Item(Items.ABYSSAL_WHIP_4152, 15))
Assertions.assertEquals(StockMarket.OfferConfirmResult.NotEnoughItemsOrCoins, mkt.confirmOffer(p, offer, 0))
Assertions.assertEquals(10, p.inventory.getAmount(4151))
Assertions.assertEquals(15, p.inventory.getAmount(4152))
}
}
@Test fun offerWithNotEnoughUnnotedItemsShouldFail() {
TestUtils.getMockPlayer("combinedNotedAndUnnotedFailure2").use { p ->
val offer = generateUnsentOffer(4151, 1000, 1500, true, p.name, OfferState.PENDING)
val mkt = StockMarket()
p.inventory.add(Item(Items.ABYSSAL_WHIP_4151, 10))
p.inventory.add(Item(Items.ABYSSAL_WHIP_4152, 900))
Assertions.assertEquals(StockMarket.OfferConfirmResult.NotEnoughItemsOrCoins, mkt.confirmOffer(p, offer, 0))
Assertions.assertEquals(10, p.inventory.getAmount(4151))
Assertions.assertEquals(900, p.inventory.getAmount(4152))
}
}
} }