Fixed an exception thrown when buying from player stock

Fix issue where malformed stock could shift following shop items
This commit is contained in:
Ceikry 2022-05-02 10:22:36 +00:00 committed by Ryan
parent a5f3f93048
commit 8438ecdbd7
4 changed files with 57 additions and 13 deletions

View file

@ -1025,4 +1025,15 @@ public class Container {
return event; return event;
} }
@Override
public String toString() {
return "Container{" +
"items=" + Arrays.toString(items) +
", capacity=" + capacity +
", sortType=" + sortType +
", type=" + type +
", event=" + event +
", listeners=" + listeners +
'}';
}
} }

View file

@ -246,13 +246,13 @@ class Shop(val title: String, val stock: Array<ShopItem>, val general: Boolean =
sendDialogue(player, "As an ironman, you cannot buy from player stock in shops.") sendDialogue(player, "As an ironman, you cannot buy from player stock in shops.")
return TransactionStatus.Failure("Ironman buying from player stock") return TransactionStatus.Failure("Ironman buying from player stock")
} }
val cont = if (isMainStock) getAttribute<Container?>(player, "shop-cont", null) ?: return TransactionStatus.Failure("Invalid shop-cont attr") else playerStock val cont = if (isMainStock) (getAttribute<Container?>(player, "shop-cont", null) ?: return TransactionStatus.Failure("Invalid shop-cont attr")) else playerStock
val inStock = cont[slot] val inStock = cont[slot]
val item = Item(inStock.id, amount) val item = Item(inStock.id, amount)
if(inStock.amount < amount) if(inStock.amount < amount)
item.amount = inStock.amount item.amount = inStock.amount
if(inStock.amount > stock[slot].amount && !getServerConfig().getBoolean(Shops.personalizedShops, false) && player.ironmanManager.isIronman) if(isMainStock && inStock.amount > stock[slot].amount && !getServerConfig().getBoolean(Shops.personalizedShops, false) && player.ironmanManager.isIronman)
{ {
sendDialogue(player, "As an ironman, you cannot buy overstocked items from shops.") sendDialogue(player, "As an ironman, you cannot buy overstocked items from shops.")
return TransactionStatus.Failure("Ironman overstock purchase") return TransactionStatus.Failure("Ironman overstock purchase")

View file

@ -41,15 +41,6 @@ class Shops : StartupListener, TickListener, InteractionListener, InterfaceListe
{ {
SystemLogger.logInfo("[SHOPS] $msg") SystemLogger.logInfo("[SHOPS] $msg")
} }
}
override fun startup() {
val path = ServerConstants.CONFIG_PATH + "shops.json"
var shopCount = 0
logShop("Using JSON path: $path")
val reader = FileReader(path)
val data = JSONParser().parse(reader) as JSONArray
fun parseStock(stock: String, id: Int): ArrayList<ShopItem>{ fun parseStock(stock: String, id: Int): ArrayList<ShopItem>{
val items = ArrayList<ShopItem>() val items = ArrayList<ShopItem>()
@ -63,13 +54,28 @@ class Shops : StartupListener, TickListener, InteractionListener, InterfaceListe
if(amount == "inf") if(amount == "inf")
amount = "-1" amount = "-1"
val item = tokens[0].toInt() val item = tokens[0].toInt()
if(idsInStock[item] != null) if(idsInStock[item] != null) {
SystemLogger.logWarn("[SHOPS] MALFORMED STOCK IN SHOP ID $id FOR ITEM $item") SystemLogger.logWarn("[SHOPS] MALFORMED STOCK IN SHOP ID $id FOR ITEM $item")
else items.forEach { if(it.itemId == item) {
it.amount += amount.toInt()
return@map
}}
} else {
items.add(ShopItem(item, amount.toInt(), tokens.getOrNull(2)?.toIntOrNull() ?: 100)) items.add(ShopItem(item, amount.toInt(), tokens.getOrNull(2)?.toIntOrNull() ?: 100))
idsInStock[item] = true
}
} }
return items return items
} }
}
override fun startup() {
val path = ServerConstants.CONFIG_PATH + "shops.json"
var shopCount = 0
logShop("Using JSON path: $path")
val reader = FileReader(path)
val data = JSONParser().parse(reader) as JSONArray
for(rawShop in data) for(rawShop in data)
{ {

View file

@ -4,6 +4,8 @@ import org.junit.Assert
import org.junit.jupiter.api.Assertions import org.junit.jupiter.api.Assertions
import org.junit.jupiter.api.Test import org.junit.jupiter.api.Test
import rs09.game.content.global.shops.Shop import rs09.game.content.global.shops.Shop
import rs09.game.content.global.shops.Shops
import rs09.game.system.config.ShopParser
class ShopTests { class ShopTests {
val testPlayer = TestUtils.getMockPlayer("test") val testPlayer = TestUtils.getMockPlayer("test")
@ -114,4 +116,29 @@ class ShopTests {
general.restock() 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.Success()
Assertions.assertDoesNotThrow({
status = general.buy(testPlayer, 36, 1)
}, "Error selling to shop: ${general.playerStock}")
Assertions.assertEquals(true, status is Shop.TransactionStatus.Success)
}
@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)
}
} }