374d6ec478
Items that cannot be traded can no longer be sold to stores
344 lines
16 KiB
Kotlin
344 lines
16 KiB
Kotlin
import core.game.node.entity.player.link.IronmanMode
|
|
import core.game.node.item.Item
|
|
import org.junit.jupiter.api.Assertions
|
|
import org.junit.jupiter.api.BeforeEach
|
|
import org.junit.jupiter.api.Test
|
|
import org.rs09.consts.Items
|
|
import rs09.game.content.global.shops.Shop
|
|
import rs09.game.content.global.shops.Shops
|
|
import kotlin.math.min
|
|
import kotlin.math.roundToInt
|
|
|
|
class ShopTests {
|
|
companion object {
|
|
init {TestUtils.preTestSetup()}
|
|
}
|
|
|
|
private val testPlayer = TestUtils.getMockPlayer("test")
|
|
private val testIronman = TestUtils.getMockPlayer("test2", IronmanMode.STANDARD)
|
|
private var nonGeneral = TestUtils.getMockShop("Not General", false, false, Item(4151, 1))
|
|
private var general = TestUtils.getMockShop("General", true, false, Item(4151, 1))
|
|
private var highAlch = TestUtils.getMockShop("High(af) Alch", true, true, Item(4151, 1))
|
|
private var tokkulShop = TestUtils.getMockTokkulShop("Tokkul", Item(Items.DEATH_RUNE_560, 10))
|
|
|
|
@BeforeEach fun beforeEach() {
|
|
val testPlayers = arrayOf(testPlayer, testIronman)
|
|
for (player in testPlayers) {
|
|
player.inventory.clear()
|
|
player.attributes.remove("shop-cont")
|
|
}
|
|
nonGeneral.playerStock.clear()
|
|
general.playerStock.clear()
|
|
highAlch.playerStock.clear()
|
|
tokkulShop.playerStock.clear()
|
|
}
|
|
|
|
private fun assertTransactionSuccess(status: Shop.TransactionStatus) {
|
|
Assertions.assertEquals(true, status is Shop.TransactionStatus.Success, "Transaction failure: ${if(status is Shop.TransactionStatus.Failure) status.reason else ""}")
|
|
}
|
|
|
|
@Test fun shouldSellItemToStore() {
|
|
testPlayer.inventory.add(Item(4151, 1))
|
|
testPlayer.setAttribute("shop-cont", general.getContainer(testPlayer))
|
|
val status = general.sell(testPlayer, 0, 1)
|
|
assertTransactionSuccess(status)
|
|
}
|
|
|
|
@Test fun shouldNotSellUnstockedItemToStandardStore() {
|
|
testPlayer.inventory.add(Item(1511, 1))
|
|
testPlayer.setAttribute("shop-cont", nonGeneral.getContainer(testPlayer))
|
|
val status = nonGeneral.sell(testPlayer, 0, 1)
|
|
Assertions.assertEquals(true, status is Shop.TransactionStatus.Failure)
|
|
}
|
|
|
|
@Test fun shouldSellUnstockedItemToGeneralStore() {
|
|
testPlayer.inventory.add(Item(1511, 1))
|
|
testPlayer.setAttribute("shop-cont", general.getContainer(testPlayer))
|
|
val status = general.sell(testPlayer, 0, 1)
|
|
assertTransactionSuccess(status)
|
|
}
|
|
|
|
@Test fun shouldNotSellDestroyable() {
|
|
testPlayer.inventory.add(Item(1, 795))
|
|
testPlayer.setAttribute("shop-cont", general.getContainer(testPlayer))
|
|
val status = general.sell(testPlayer, 0, 1)
|
|
Assertions.assertEquals(true, status is Shop.TransactionStatus.Failure)
|
|
}
|
|
|
|
@Test fun shouldNotSellUntradeable() {
|
|
testPlayer.inventory.add(Item(1, 1799))
|
|
testPlayer.setAttribute("shop-cont", general.getContainer(testPlayer))
|
|
val status = general.sell(testPlayer, 0, 1)
|
|
Assertions.assertEquals(true, status is Shop.TransactionStatus.Failure)
|
|
}
|
|
|
|
@Test fun shouldSellUnstockedItemToGeneralStoreUsingLowAlchBaseValue() {
|
|
//starts at 40% value - a.k.a. low alch price
|
|
//drops 3% value per item stocked
|
|
//bottoms out at 10% value (25% of the low alch price) after 10 items stocked
|
|
val saleItemId = Items.RUNE_MED_HELM_1147
|
|
val shopContainer = general.getContainer(testPlayer)
|
|
Assertions.assertFalse(shopContainer.containItems(saleItemId), "Pre-assertion, shop container should not have the unstocked item to begin with.")
|
|
testPlayer.setAttribute("shop-cont", shopContainer)
|
|
val playerStock = general.playerStock
|
|
Assertions.assertFalse(playerStock.containItems(saleItemId), "Pre-assertion, player stock should not have the unstocked item to begin with.")
|
|
val saleItem = Item(saleItemId, 1)
|
|
val alchValue = saleItem.definition.getAlchemyValue(false)
|
|
val value = saleItem.definition.value
|
|
Assertions.assertEquals((value * 0.4).roundToInt(), alchValue, "Pre-assertion, low alch value should be 40% value.")
|
|
|
|
for (i in 0..14) {
|
|
val expectedCoins = (alchValue.toDouble() - value * min(0.03 * i, 0.30)).roundToInt()
|
|
testPlayer.inventory.add(saleItem.copy())
|
|
Assertions.assertEquals(saleItemId, testPlayer.inventory.getId(0), "Pre-assertion, should have item in inventory slot 0.")
|
|
|
|
val status = general.sell(testPlayer, 0, 1)
|
|
|
|
assertTransactionSuccess(status)
|
|
val coinItem = testPlayer.inventory[0]
|
|
Assertions.assertEquals(Items.COINS_995, coinItem.id)
|
|
Assertions.assertEquals(
|
|
expectedCoins,
|
|
coinItem.amount,
|
|
"Selling item $i should yield the expected price."
|
|
)
|
|
testPlayer.inventory.clear()
|
|
}
|
|
}
|
|
|
|
@Test fun shouldSellUnstockedItemToHighAlchStoreUsingHighAlchBaseValue() {
|
|
//starts at 60% value - a.k.a. high alch price
|
|
//drops 3% value per item stocked
|
|
//bottoms out at 30% value (50% of the high alch price) after 10 items stocked
|
|
val saleItemId = Items.RUNE_MED_HELM_1147
|
|
val shopContainer = highAlch.getContainer(testPlayer)
|
|
Assertions.assertFalse(shopContainer.containItems(saleItemId), "Pre-assertion, shop container should not have the unstocked item to begin with.")
|
|
testPlayer.setAttribute("shop-cont", shopContainer)
|
|
val playerStock = highAlch.playerStock
|
|
Assertions.assertFalse(playerStock.containItems(saleItemId), "Pre-assertion, player stock should not have the unstocked item to begin with.")
|
|
val saleItem = Item(saleItemId, 1)
|
|
val alchValue = saleItem.definition.getAlchemyValue(true)
|
|
val value = saleItem.definition.value
|
|
Assertions.assertEquals((value * 0.6).roundToInt(), alchValue, "Pre-assertion, high alch value should be 60% value.")
|
|
|
|
for (i in 0..14) {
|
|
val expectedCoins = (alchValue.toDouble() - value * min(0.03 * i, 0.30)).roundToInt()
|
|
testPlayer.inventory.add(saleItem.copy())
|
|
Assertions.assertEquals(saleItemId, testPlayer.inventory.getId(0), "Pre-assertion, should have item in inventory slot 0.")
|
|
|
|
val status = highAlch.sell(testPlayer, 0, 1)
|
|
|
|
assertTransactionSuccess(status)
|
|
val coinItem = testPlayer.inventory[0]
|
|
Assertions.assertEquals(Items.COINS_995, coinItem.id)
|
|
Assertions.assertEquals(
|
|
expectedCoins,
|
|
coinItem.amount,
|
|
"Selling item $i should yield the expected price."
|
|
)
|
|
testPlayer.inventory.clear()
|
|
}
|
|
}
|
|
|
|
@Test fun shouldSellNotedUnstockedItemForSamePriceAsUnnoted() {
|
|
val saleItemId = Items.RUNE_MED_HELM_1147
|
|
var notedSaleItemId = Items.RUNE_MED_HELM_1148
|
|
val shopContainer = highAlch.getContainer(testPlayer)
|
|
Assertions.assertFalse(shopContainer.containItems(saleItemId), "Pre-assertion, shop container should not have the unstocked item to begin with.")
|
|
testPlayer.setAttribute("shop-cont", shopContainer)
|
|
val playerStock = highAlch.playerStock
|
|
Assertions.assertFalse(playerStock.containItems(saleItemId), "Pre-assertion, player stock should not have the unstocked item to begin with.")
|
|
testPlayer.inventory.add(Item(saleItemId, 1))
|
|
var status = highAlch.sell(testPlayer, 0, 1)
|
|
assertTransactionSuccess(status)
|
|
testPlayer.inventory.clear()
|
|
val notedSaleItem = Item(notedSaleItemId, 1)
|
|
testPlayer.inventory.add(notedSaleItem)
|
|
val alchValue = notedSaleItem.definition.getAlchemyValue(true)
|
|
val value = notedSaleItem.definition.value
|
|
status = highAlch.sell(testPlayer, 0, 1)
|
|
assertTransactionSuccess(status)
|
|
val expectedCoins = (alchValue.toDouble() - value * 0.03).roundToInt()
|
|
|
|
val coinItem = testPlayer.inventory[0]
|
|
Assertions.assertEquals(Items.COINS_995, coinItem.id)
|
|
Assertions.assertEquals(
|
|
expectedCoins,
|
|
coinItem.amount,
|
|
"Selling noted item should yield the same devalued price as base item."
|
|
)
|
|
}
|
|
|
|
@Test fun minimumSellPriceShouldBe1Coin() {
|
|
testPlayer.inventory.add(Item(Items.EMPTY_POT_1931, 1))
|
|
testPlayer.setAttribute("shop-cont", general.getContainer(testPlayer))
|
|
val status = general.sell(testPlayer, 0, 1)
|
|
assertTransactionSuccess(status)
|
|
val coinItem = testPlayer.inventory[0]
|
|
Assertions.assertEquals(Items.COINS_995, coinItem.id)
|
|
Assertions.assertEquals(
|
|
1,
|
|
coinItem.amount,
|
|
"1 coin should be the minimum selling price."
|
|
)
|
|
}
|
|
|
|
@Test fun tokkulShouldBe10xLessValuableWhenSellingAStockedItem() {
|
|
val startingTokkul = 5000
|
|
testPlayer.inventory.add(Item(Items.TOKKUL_6529, startingTokkul))
|
|
testPlayer.setAttribute("shop-cont", tokkulShop.getContainer(testPlayer))
|
|
testPlayer.setAttribute("shop-main", true)
|
|
var status = tokkulShop.buy(testPlayer, 0, 1) // 1 death rune
|
|
assertTransactionSuccess(status)
|
|
Assertions.assertEquals(Items.TOKKUL_6529, testPlayer.inventory[0].id, "Pre-assertion: First item should still be the currency used.")
|
|
val cost = startingTokkul - testPlayer.inventory[0].amount
|
|
status = tokkulShop.sell(testPlayer, 1, 1) // back to starting stock
|
|
assertTransactionSuccess(status)
|
|
testPlayer.inventory.clear()
|
|
testPlayer.inventory.add(Item(Items.DEATH_RUNE_560, 1))
|
|
|
|
status = tokkulShop.sell(testPlayer, 0, 1) // sell 1 death rune to fresh shop
|
|
assertTransactionSuccess(status)
|
|
|
|
Assertions.assertEquals(Items.TOKKUL_6529, testPlayer.inventory[0].id, "Expected same currency back.")
|
|
Assertions.assertEquals((cost / 10.0).toInt(), testPlayer.inventory[0].amount, "Expected 10 times less for selling than for cost of buying.")
|
|
}
|
|
|
|
@Test fun shouldSellUnstockedItemToGeneralStoreAsIronman() {
|
|
testIronman.inventory.add(Item(1511, 1))
|
|
testIronman.setAttribute("shop-cont", general.getContainer(testIronman))
|
|
val status = general.sell(testIronman, 0, 1)
|
|
assertTransactionSuccess(status)
|
|
}
|
|
|
|
@Test fun shouldSellStackOfUnstockedItemsToPlayerStock() {
|
|
testPlayer.inventory.add(Item(1512, 20))
|
|
testPlayer.setAttribute("shop-cont", general.getContainer(testPlayer))
|
|
val status = general.sell(testPlayer, 0, 20)
|
|
assertTransactionSuccess(status)
|
|
}
|
|
|
|
@Test fun shouldPutSoldUnstockedItemsInPlayerStock() {
|
|
testPlayer.inventory.add(Item(2,1))
|
|
testPlayer.setAttribute("shop-cont", general.getContainer(testPlayer))
|
|
val status = general.sell(testPlayer, 0, 1)
|
|
assertTransactionSuccess(status)
|
|
Assertions.assertEquals(1, general.playerStock.getAmount(2))
|
|
Assertions.assertEquals(0, general.getContainer(testPlayer).getAmount(2))
|
|
}
|
|
|
|
@Test fun shouldAllowStandardPlayerToBuy() {
|
|
testPlayer.inventory.add(Item(995, 100000))
|
|
testPlayer.setAttribute("shop-cont", general.getContainer(testPlayer))
|
|
testPlayer.setAttribute("shop-main", true)
|
|
val status = general.buy(testPlayer, 0, 1)
|
|
assertTransactionSuccess(status)
|
|
}
|
|
|
|
@Test fun shouldAllowStandardPlayerToBuyOverstock() {
|
|
testPlayer.inventory.add(Item(995, 100000))
|
|
testPlayer.setAttribute("shop-cont", general.getContainer(testPlayer))
|
|
testPlayer.setAttribute("shop-main", true)
|
|
general.getContainer(testPlayer).add(Item(4151, 100))
|
|
val status = general.buy(testPlayer, 0, 1)
|
|
assertTransactionSuccess(status)
|
|
}
|
|
|
|
@Test fun shouldAllowStandardPlayerToBuyPlayerStock() {
|
|
testPlayer.inventory.add(Item(995, 100000))
|
|
testPlayer.setAttribute("shop-cont", general.getContainer(testPlayer))
|
|
testPlayer.setAttribute("shop-main", false)
|
|
general.playerStock.add(Item(4151, 100))
|
|
val status = general.buy(testPlayer, 0, 1)
|
|
assertTransactionSuccess(status)
|
|
}
|
|
|
|
@Test fun shouldNotAllowIronmanToBuyOverstock() {
|
|
testIronman.inventory.add(Item(995, 100000))
|
|
testIronman.setAttribute("shop-cont", general.getContainer(testIronman))
|
|
testIronman.setAttribute("shop-main", true)
|
|
general.getContainer(testIronman).add(Item(4151, 100))
|
|
val status = general.buy(testIronman, 0, 1)
|
|
Assertions.assertEquals(true, status is Shop.TransactionStatus.Failure)
|
|
}
|
|
|
|
@Test fun shouldNotAllowIronmanToBuyPlayerStock() {
|
|
testIronman.inventory.add(Item(995, 100000))
|
|
testIronman.setAttribute("shop-cont", general.playerStock)
|
|
testIronman.setAttribute("shop-main", false)
|
|
general.playerStock.add(Item(4151, 1))
|
|
val status = general.buy(testIronman, 0, 1)
|
|
Assertions.assertEquals(true, status is Shop.TransactionStatus.Failure)
|
|
}
|
|
|
|
@Test fun openShopShouldNotThrowException() {
|
|
Assertions.assertDoesNotThrow {
|
|
general.openFor(testPlayer)
|
|
}
|
|
}
|
|
|
|
@Test fun shouldNotThrowExceptionWhenRestockingStockWithNullSlot() {
|
|
Assertions.assertDoesNotThrow {
|
|
general.getContainer(testPlayer).add(Item(1, 100))
|
|
general.getContainer(testPlayer).add(Item(2, 100))
|
|
general.getContainer(testPlayer).replace(null, 0) //replace item in slot 0 with null
|
|
for ((k,_) in general.stockInstances) general.needsUpdate[k] = true
|
|
general.restock()
|
|
}
|
|
}
|
|
|
|
@Test fun playerStockShouldNeverBeNull() {
|
|
Assertions.assertNotNull(general.playerStock)
|
|
}
|
|
|
|
@Test fun shouldAllowBuyingFromPlayerStockOnMultipleRows() {
|
|
for(i in 0 until 100) {
|
|
general.playerStock.add(Item(i + 3100, 1)) //make sure we populate several rows of items
|
|
}
|
|
testPlayer.inventory.add(Item(995, 100000))
|
|
testPlayer.setAttribute("shop-cont", general.getContainer(testPlayer))
|
|
testPlayer.setAttribute("shop-main", false)
|
|
var status: Shop.TransactionStatus = Shop.TransactionStatus.Failure("Test did not assign transaction status.")
|
|
Assertions.assertDoesNotThrow({
|
|
status = general.buy(testPlayer, 36, 1)
|
|
}, "Error selling to shop: ${general.playerStock}")
|
|
assertTransactionSuccess(status)
|
|
}
|
|
|
|
@Test fun invalidStockJsonShouldNotCauseItemShift() {
|
|
val invalidJson = "{1277,10,100}-{1277,10,100}-{1279,10,100}"
|
|
val stock = Shops.parseStock(invalidJson, -1)
|
|
Assertions.assertEquals(2, stock.size)
|
|
Assertions.assertEquals(20, stock[0].amount)
|
|
}
|
|
|
|
@Test fun buying0StockItemFromNormalStockShouldNotSucceedNorDeductGold() {
|
|
testPlayer.inventory.clear()
|
|
testPlayer.inventory.add(Item(995, Integer.MAX_VALUE))
|
|
testPlayer.setAttribute("shop-cont", general.getContainer(testPlayer))
|
|
testPlayer.setAttribute("shop-main", true)
|
|
val inStockAmount = general.getContainer(testPlayer).get(0).amount
|
|
|
|
//Buy out existing stock
|
|
var status: Shop.TransactionStatus = Shop.TransactionStatus.Success()
|
|
|
|
Assertions.assertDoesNotThrow {
|
|
status = general.buy(testPlayer, 0, inStockAmount)
|
|
}
|
|
Assertions.assertEquals(true, status is Shop.TransactionStatus.Success, "Transaction failure: ${if(status is Shop.TransactionStatus.Failure) (status as Shop.TransactionStatus.Failure).reason else ""}")
|
|
Assertions.assertEquals(0, general.getContainer(testPlayer).getAmount(0), "Buying all stock didn't... buy all stock.")
|
|
|
|
testPlayer.inventory.replace(null, 1) //Remove the items we purchased
|
|
|
|
val remainingGP = testPlayer.inventory.getAmount(995)
|
|
|
|
Assertions.assertDoesNotThrow {
|
|
status = general.buy(testPlayer, 0, 10)
|
|
}
|
|
|
|
Assertions.assertEquals(true, status is Shop.TransactionStatus.Failure, "Status was not Failure for buying 0-stock item!")
|
|
Assertions.assertEquals(remainingGP, testPlayer.inventory.getAmount(995), "Coins were deducted for buying 0-stock item!")
|
|
Assertions.assertNull(testPlayer.inventory.get(1), "Player received purchased item despite being 0-stock!")
|
|
}
|
|
}
|