Improved the GE database access to use a basic reference counter for the connection that automatically closes the connection when no one is using it anymore
Grand Exchange now uses the GE sqlite database's price index table to track price changes Removed the old price index (confusingly called GrandExchangeDatabase.java) Grand Exchange prices are now dynamic and influenced by trades (weighted stepping average price) Fixed GE interfaces not loading on login
This commit is contained in:
@@ -13,6 +13,9 @@ import java.math.BigInteger
|
||||
class ServerConstants {
|
||||
companion object {
|
||||
@JvmField
|
||||
var BOTS_INFLUENCE_PRICE_INDEX = true
|
||||
|
||||
@JvmField
|
||||
var SHUTDOWN_HOOK: Thread = Thread(SystemShutdownHook())
|
||||
|
||||
@JvmField
|
||||
|
||||
@@ -6,6 +6,7 @@ import org.json.simple.JSONObject
|
||||
import org.json.simple.parser.JSONParser
|
||||
import org.sqlite.SQLiteDataSource
|
||||
import rs09.ServerConstants
|
||||
import rs09.game.system.SystemLogger
|
||||
import java.io.File
|
||||
import java.io.FileReader
|
||||
import java.sql.Connection
|
||||
@@ -16,7 +17,9 @@ import java.sql.Connection
|
||||
*/
|
||||
object GEDB {
|
||||
private var pathString = ""
|
||||
private var connection: Connection? = null
|
||||
public var connection: Connection? = null
|
||||
private var initialized = false
|
||||
private var connectionRefs = 0
|
||||
|
||||
fun init() {
|
||||
init(File(ServerConstants.GRAND_EXCHANGE_DATA_PATH + "grandexchange.db").absolutePath)
|
||||
@@ -25,13 +28,24 @@ object GEDB {
|
||||
//This needs to be a separate method, so we can call it after the server config has been parsed
|
||||
fun init(path: String)
|
||||
{
|
||||
if(initialized) return
|
||||
pathString = path
|
||||
//Check if the grandexchange.db file already exists. If not, create it and create the tables.
|
||||
if(!File(path).exists())
|
||||
generateAndTransfer()
|
||||
}
|
||||
|
||||
fun connect(): Connection
|
||||
@JvmStatic fun run(closure: (conn: Connection) -> Unit) {
|
||||
connectionRefs++
|
||||
val con = connect()
|
||||
closure.invoke(con)
|
||||
connectionRefs--
|
||||
if(connectionRefs == 0) {
|
||||
con.close()
|
||||
}
|
||||
}
|
||||
|
||||
private fun connect(): Connection
|
||||
{
|
||||
if (connection == null || connection!!.isClosed)
|
||||
{
|
||||
@@ -152,14 +166,14 @@ object GEDB {
|
||||
}
|
||||
reader.close()
|
||||
}
|
||||
statement.close()
|
||||
|
||||
|
||||
//price index isn't worth transferring, so we're just going to make a new one.
|
||||
ItemDefinition.getDefinitions().values.forEach { def ->
|
||||
if(def.isTradeable){
|
||||
statement.execute("insert into price_index(item_id, value) values(${def.id},${def.value})")
|
||||
PriceIndex.allowItem(def.id)
|
||||
}
|
||||
}
|
||||
statement.close()
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,11 @@
|
||||
package rs09.game.ge
|
||||
|
||||
import api.*
|
||||
import core.game.ge.GrandExchangeDatabase
|
||||
import core.game.ge.OfferState
|
||||
import core.game.node.entity.player.Player
|
||||
import core.game.node.entity.player.info.PlayerDetails
|
||||
import core.game.node.entity.player.link.audio.Audio
|
||||
import rs09.ServerConstants
|
||||
import rs09.game.system.SystemLogger
|
||||
import rs09.game.system.command.Privilege
|
||||
import rs09.game.system.config.ItemConfigParser
|
||||
@@ -40,9 +40,7 @@ class GrandExchange : StartupListener, Commands {
|
||||
val t = Thread {
|
||||
Thread.currentThread().name = "GE Update Worker"
|
||||
while(true) {
|
||||
with(GEDB.connect()) {
|
||||
val conn = this
|
||||
|
||||
GEDB.run { conn ->
|
||||
val botStmt = conn.createStatement()
|
||||
val botOffers = botStmt.executeQuery("SELECT * from bot_offers")
|
||||
while(botOffers.next()) {
|
||||
@@ -90,19 +88,30 @@ class GrandExchange : StartupListener, Commands {
|
||||
addBotOffer(id, amount)
|
||||
notify(player, "Added ${amount}x ${getItemName(id)} to the bot offers.")
|
||||
}
|
||||
|
||||
define("bange", Privilege.ADMIN) {player, strings ->
|
||||
val id = strings[1].toInt()
|
||||
PriceIndex.banItem(id)
|
||||
notify(player, "Banned ${getItemName(id)} from GE trade.")
|
||||
}
|
||||
|
||||
define("allowge", Privilege.ADMIN) {player, strings ->
|
||||
val id = strings[1].toInt()
|
||||
PriceIndex.allowItem(id)
|
||||
notify(player, "Allowed ${getItemName(id)} for GE trade.")
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun processOffer(offer: GrandExchangeOffer)
|
||||
{
|
||||
with (GEDB.connect()) {
|
||||
val conn = this
|
||||
GEDB.run { conn ->
|
||||
if(offer.isActive) {
|
||||
val stmt = conn.createStatement()
|
||||
val olderOffers = stmt.executeQuery("SELECT * FROM player_offers WHERE item_id = ${offer.itemID} AND is_sale = ${!offer.sell} AND offer_state < 4 AND NOT offer_state = 2 AND time_stamp < ${offer.timeStamp}")
|
||||
if(tryOffers(offer, olderOffers, true)) return
|
||||
if(tryOffers(offer, olderOffers, true)) return@run
|
||||
val newerOffers = stmt.executeQuery("SELECT * FROM player_offers WHERE item_id = ${offer.itemID} AND is_sale = ${!offer.sell} AND offer_state < 4 AND NOT offer_state = 2 AND time_stamp >= ${offer.timeStamp}")
|
||||
if(tryOffers(offer, newerOffers, false)) return
|
||||
if(tryOffers(offer, newerOffers, false)) return@run
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -135,7 +144,7 @@ class GrandExchange : StartupListener, Commands {
|
||||
|
||||
@JvmStatic
|
||||
fun getRecommendedPrice(itemID: Int, from_bot: Boolean = false): Int {
|
||||
var base = max(GrandExchangeDatabase.getDatabase()[itemID]?.value ?: 0, getItemDefPrice(itemID))
|
||||
var base = max(PriceIndex.getValue(itemID), getItemDefPrice(itemID))
|
||||
if (from_bot) base = (max(BotPrices.getPrice(itemID), base) * 1.10).toInt()
|
||||
return base
|
||||
}
|
||||
@@ -147,69 +156,71 @@ class GrandExchange : StartupListener, Commands {
|
||||
@JvmStatic
|
||||
fun getOfferStats(itemID: Int, sale: Boolean) : String
|
||||
{
|
||||
val conn = GEDB.connect()
|
||||
|
||||
var foundOffers = 0
|
||||
var totalAmount = 0
|
||||
var bestPrice = 0
|
||||
val sb = StringBuilder()
|
||||
var stmt = conn.createStatement()
|
||||
|
||||
if(!sale)
|
||||
{
|
||||
var botAmt = 0
|
||||
var botPrice = 0
|
||||
val player_offers = stmt.executeQuery("SELECT * from player_offers where item_id = $itemID AND is_sale = 1 AND offer_state < 4 AND NOT offer_state = 2")
|
||||
GEDB.run { conn ->
|
||||
var foundOffers = 0
|
||||
var totalAmount = 0
|
||||
var bestPrice = 0
|
||||
var stmt = conn.createStatement()
|
||||
|
||||
while(player_offers.next())
|
||||
if(!sale)
|
||||
{
|
||||
val o = GrandExchangeOffer.fromQuery(player_offers)
|
||||
++foundOffers
|
||||
totalAmount += o.amountLeft
|
||||
if(o.offeredValue < bestPrice || bestPrice == 0)
|
||||
bestPrice = o.offeredValue
|
||||
var botAmt = 0
|
||||
var botPrice = 0
|
||||
val player_offers = stmt.executeQuery("SELECT * from player_offers where item_id = $itemID AND is_sale = 1 AND offer_state < 4 AND NOT offer_state = 2")
|
||||
|
||||
while(player_offers.next())
|
||||
{
|
||||
val o = GrandExchangeOffer.fromQuery(player_offers)
|
||||
++foundOffers
|
||||
totalAmount += o.amountLeft
|
||||
if(o.offeredValue < bestPrice || bestPrice == 0)
|
||||
bestPrice = o.offeredValue
|
||||
}
|
||||
|
||||
stmt.close()
|
||||
stmt = conn.createStatement()
|
||||
val bot_offers = stmt.executeQuery("SELECT * from bot_offers where item_id = $itemID")
|
||||
if(bot_offers.next())
|
||||
{
|
||||
val o = GrandExchangeOffer.fromBotQuery(bot_offers)
|
||||
botAmt = o.amount
|
||||
botPrice = getRecommendedPrice(itemID, true)
|
||||
}
|
||||
|
||||
sb.append("Player Stock: <col=FFFFFF>$totalAmount ")
|
||||
sb.append("</col> Lowest Price: <col=FFFFFF>$bestPrice<br>")
|
||||
sb.append("-".repeat(50))
|
||||
sb.append("</col><br>Bot Stock: <col=FFFFFF>$botAmt ")
|
||||
sb.append("</col> Bot Price: <col=FFFFFF>$botPrice")
|
||||
}
|
||||
else
|
||||
{
|
||||
val buy_offers = stmt.executeQuery("SELECT * from player_offers where item_id = $itemID AND is_sale = 0 AND offer_state < 4 AND NOT offer_state = 2")
|
||||
|
||||
while(buy_offers.next())
|
||||
{
|
||||
val o = GrandExchangeOffer.fromQuery(buy_offers)
|
||||
++foundOffers
|
||||
totalAmount += o.amountLeft
|
||||
if(o.offeredValue > bestPrice)
|
||||
bestPrice = o.offeredValue
|
||||
}
|
||||
|
||||
sb.append("Buy Offers: <col=FFFFFF>$totalAmount ")
|
||||
sb.append("</col>Highest Offer: <col=FFFFFF>$bestPrice</col>")
|
||||
}
|
||||
|
||||
stmt.close()
|
||||
stmt = conn.createStatement()
|
||||
val bot_offers = stmt.executeQuery("SELECT * from bot_offers where item_id = $itemID")
|
||||
if(bot_offers.next())
|
||||
{
|
||||
val o = GrandExchangeOffer.fromBotQuery(bot_offers)
|
||||
botAmt = o.amount
|
||||
botPrice = getRecommendedPrice(itemID, true)
|
||||
}
|
||||
|
||||
sb.append("Player Stock: <col=FFFFFF>$totalAmount ")
|
||||
sb.append("</col> Lowest Price: <col=FFFFFF>$bestPrice<br>")
|
||||
sb.append("-".repeat(50))
|
||||
sb.append("</col><br>Bot Stock: <col=FFFFFF>$botAmt ")
|
||||
sb.append("</col> Bot Price: <col=FFFFFF>$botPrice")
|
||||
}
|
||||
else
|
||||
{
|
||||
val buy_offers = stmt.executeQuery("SELECT * from player_offers where item_id = $itemID AND is_sale = 0 AND offer_state < 4 AND NOT offer_state = 2")
|
||||
|
||||
while(buy_offers.next())
|
||||
{
|
||||
val o = GrandExchangeOffer.fromQuery(buy_offers)
|
||||
++foundOffers
|
||||
totalAmount += o.amountLeft
|
||||
if(o.offeredValue > bestPrice)
|
||||
bestPrice = o.offeredValue
|
||||
}
|
||||
|
||||
sb.append("Buy Offers: <col=FFFFFF>$totalAmount ")
|
||||
sb.append("</col>Highest Offer: <col=FFFFFF>$bestPrice</col>")
|
||||
}
|
||||
|
||||
stmt.close()
|
||||
return sb.toString()
|
||||
}
|
||||
|
||||
fun addBotOffer(itemID: Int, amount: Int): Boolean
|
||||
{
|
||||
if (GrandExchangeDatabase.getDatabase()[itemID] == null)
|
||||
if (!PriceIndex.canTrade(itemID))
|
||||
return false
|
||||
|
||||
val offer = GrandExchangeOffer.createBotOffer(itemID, amount)
|
||||
@@ -278,8 +289,13 @@ class GrandExchange : StartupListener, Commands {
|
||||
if(buyer.amountLeft < 1)
|
||||
buyer.offerState = OfferState.COMPLETED
|
||||
|
||||
seller.totalCoinExchange += if(sellerBias) buyer.offeredValue else seller.offeredValue * amount
|
||||
buyer.totalCoinExchange += if(sellerBias) buyer.offeredValue else seller.offeredValue * amount
|
||||
val totalCoinXC = (if(sellerBias) buyer.offeredValue else seller.offeredValue) * amount
|
||||
|
||||
seller.totalCoinExchange += totalCoinXC
|
||||
buyer.totalCoinExchange += totalCoinXC
|
||||
|
||||
if(canUpdatePriceIndex(seller, buyer))
|
||||
PriceIndex.addTrade(offer.itemID, amount, (totalCoinXC / amount))
|
||||
|
||||
seller.update()
|
||||
val sellerPlayer = Repository.uid_map[seller.playerUID]
|
||||
@@ -289,35 +305,44 @@ class GrandExchange : StartupListener, Commands {
|
||||
GrandExchangeRecords.getInstance(buyerPlayer).visualizeRecords()
|
||||
}
|
||||
|
||||
private fun canUpdatePriceIndex(seller: GrandExchangeOffer, buyer: GrandExchangeOffer): Boolean {
|
||||
if(seller.playerUID == buyer.playerUID) return false
|
||||
if(!ServerConstants.BOTS_INFLUENCE_PRICE_INDEX && (seller.isBot || buyer.isBot)) return false;
|
||||
return true
|
||||
}
|
||||
|
||||
fun getValidOffers(): List<GrandExchangeOffer>
|
||||
{
|
||||
val conn = GEDB.connect()
|
||||
val stmt = conn.createStatement()
|
||||
val offers = ArrayList<GrandExchangeOffer>()
|
||||
|
||||
val results = stmt.executeQuery("SELECT * FROM player_offers WHERE offer_state < 4 AND NOT offer_state = 2")
|
||||
while(results.next())
|
||||
{
|
||||
val o = GrandExchangeOffer.fromQuery(results)
|
||||
offers.add(o)
|
||||
GEDB.run { conn ->
|
||||
val stmt = conn.createStatement()
|
||||
|
||||
val results =
|
||||
stmt.executeQuery("SELECT * FROM player_offers WHERE offer_state < 4 AND NOT offer_state = 2")
|
||||
while (results.next()) {
|
||||
val o = GrandExchangeOffer.fromQuery(results)
|
||||
offers.add(o)
|
||||
}
|
||||
stmt.close()
|
||||
}
|
||||
stmt.close()
|
||||
return offers
|
||||
}
|
||||
|
||||
fun getBotOffers(): List<GrandExchangeOffer>
|
||||
{
|
||||
val conn = GEDB.connect()
|
||||
val stmt = conn.createStatement()
|
||||
val offers = ArrayList<GrandExchangeOffer>()
|
||||
|
||||
val results = stmt.executeQuery("SELECT item_id,amount FROM bot_offers WHERE amount > 0")
|
||||
while(results.next())
|
||||
{
|
||||
val o = GrandExchangeOffer.fromBotQuery(results)
|
||||
offers.add(o)
|
||||
GEDB.run { conn ->
|
||||
val stmt = conn.createStatement()
|
||||
|
||||
val results = stmt.executeQuery("SELECT item_id,amount FROM bot_offers WHERE amount > 0")
|
||||
while (results.next()) {
|
||||
val o = GrandExchangeOffer.fromBotQuery(results)
|
||||
offers.add(o)
|
||||
}
|
||||
stmt.close()
|
||||
}
|
||||
stmt.close()
|
||||
return offers
|
||||
}
|
||||
|
||||
|
||||
@@ -95,61 +95,57 @@ class GrandExchangeOffer() {
|
||||
|
||||
fun update()
|
||||
{
|
||||
val conn = GEDB.connect()
|
||||
|
||||
if(isBot)
|
||||
{
|
||||
val stmt = conn.prepareStatement("UPDATE bot_offers SET amount = ? WHERE item_id = ?")
|
||||
stmt.setInt(1, amountLeft)
|
||||
stmt.setInt(2, itemID)
|
||||
stmt.executeUpdate()
|
||||
stmt.close()
|
||||
}
|
||||
else
|
||||
{
|
||||
val stmt = conn.prepareStatement("UPDATE player_offers SET amount_complete = ?, offer_state = ?, total_coin_xc = ?, withdraw_items = ?, slot_index = ? WHERE uid = ?")
|
||||
stmt.setInt(1, completedAmount)
|
||||
stmt.setInt(2, offerState.ordinal)
|
||||
stmt.setInt(3, totalCoinExchange)
|
||||
stmt.setString(4, encodeWithdraw())
|
||||
stmt.setInt(5, index)
|
||||
stmt.setLong(6, uid)
|
||||
stmt.executeUpdate()
|
||||
stmt.close()
|
||||
GEDB.run {conn ->
|
||||
if(isBot)
|
||||
{
|
||||
val stmt = conn.prepareStatement("UPDATE bot_offers SET amount = ? WHERE item_id = ?")
|
||||
stmt.setInt(1, amountLeft)
|
||||
stmt.setInt(2, itemID)
|
||||
stmt.executeUpdate()
|
||||
stmt.close()
|
||||
}
|
||||
else
|
||||
{
|
||||
val stmt = conn.prepareStatement("UPDATE player_offers SET amount_complete = ?, offer_state = ?, total_coin_xc = ?, withdraw_items = ?, slot_index = ? WHERE uid = ?")
|
||||
stmt.setInt(1, completedAmount)
|
||||
stmt.setInt(2, offerState.ordinal)
|
||||
stmt.setInt(3, totalCoinExchange)
|
||||
stmt.setString(4, encodeWithdraw())
|
||||
stmt.setInt(5, index)
|
||||
stmt.setLong(6, uid)
|
||||
stmt.executeUpdate()
|
||||
stmt.close()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Called when writing a brand new offer to the database. Should not be used under any other circumstance **/
|
||||
fun writeNew()
|
||||
{
|
||||
val conn = GEDB.connect()
|
||||
GEDB.run { conn ->
|
||||
if (isBot) {
|
||||
val stmt = conn.createStatement()
|
||||
val result = stmt.executeQuery("SELECT * from bot_offers where item_id = $itemID")
|
||||
val isExists = result.next()
|
||||
|
||||
if(isBot)
|
||||
{
|
||||
val stmt = conn.createStatement()
|
||||
val result = stmt.executeQuery("SELECT * from bot_offers where item_id = $itemID")
|
||||
val isExists = result.next()
|
||||
|
||||
if(isExists)
|
||||
{
|
||||
val oldAmount = result.getInt("amount")
|
||||
stmt.executeUpdate("UPDATE bot_offers set amount = ${oldAmount + amount} where item_id = $itemID")
|
||||
if (isExists) {
|
||||
val oldAmount = result.getInt("amount")
|
||||
stmt.executeUpdate("UPDATE bot_offers set amount = ${oldAmount + amount} where item_id = $itemID")
|
||||
} else
|
||||
stmt.executeUpdate("INSERT INTO bot_offers(item_id,amount) values($itemID,$amount)")
|
||||
stmt.close()
|
||||
} else {
|
||||
val stmt = conn.createStatement()
|
||||
stmt.executeUpdate(
|
||||
"INSERT INTO player_offers(player_uid, item_id, amount_total, offered_value, time_stamp, offer_state, is_sale, slot_index) " +
|
||||
"values($playerUID,$itemID,$amount,$offeredValue,${System.currentTimeMillis()},${offerState.ordinal},${if (sell) 1 else 0}, $index)"
|
||||
)
|
||||
val nowuid = stmt.executeQuery("SELECT last_insert_rowid()")
|
||||
uid = nowuid.getLong(1)
|
||||
visualize(player)
|
||||
stmt.close()
|
||||
}
|
||||
else
|
||||
stmt.executeUpdate("INSERT INTO bot_offers(item_id,amount) values($itemID,$amount)")
|
||||
stmt.close()
|
||||
}
|
||||
else
|
||||
{
|
||||
val stmt = conn.createStatement()
|
||||
stmt.executeUpdate("INSERT INTO player_offers(player_uid, item_id, amount_total, offered_value, time_stamp, offer_state, is_sale, slot_index) " +
|
||||
"values($playerUID,$itemID,$amount,$offeredValue,${System.currentTimeMillis()},${offerState.ordinal},${if(sell) 1 else 0}, $index)")
|
||||
val nowuid = stmt.executeQuery("SELECT last_insert_rowid()")
|
||||
uid = nowuid.getLong(1)
|
||||
visualize(player)
|
||||
stmt.close()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private fun encodeWithdraw() : String
|
||||
|
||||
@@ -26,7 +26,6 @@ class GrandExchangeRecords(private val player: Player? = null) : PersistPlayer,
|
||||
|
||||
override fun login(player: Player) {
|
||||
val instance = GrandExchangeRecords(player)
|
||||
instance.init()
|
||||
player.setAttribute("ge-records", instance)
|
||||
}
|
||||
|
||||
@@ -51,21 +50,22 @@ class GrandExchangeRecords(private val player: Player? = null) : PersistPlayer,
|
||||
/**
|
||||
* Read offers from the database
|
||||
*/
|
||||
val conn = GEDB.connect()
|
||||
val stmt = conn.createStatement()
|
||||
val offer_records = stmt.executeQuery("SELECT * from player_offers where player_uid = ${player.details.uid} AND offer_state < 6")
|
||||
val needsIndex = ArrayDeque<GrandExchangeOffer>()
|
||||
val instance = getInstance(player)
|
||||
|
||||
val needsIndex = ArrayDeque<GrandExchangeOffer>()
|
||||
GEDB.run { conn ->
|
||||
val stmt = conn.createStatement()
|
||||
val offer_records = stmt.executeQuery("SELECT * from player_offers where player_uid = ${player.details.uid} AND offer_state < 6")
|
||||
|
||||
while (offer_records.next()) {
|
||||
val offer = GrandExchangeOffer.fromQuery(offer_records)
|
||||
if (offer.index == -1) //used to index old (converted from JSON) offers
|
||||
needsIndex.push(offer)
|
||||
else
|
||||
instance.offerRecords[offer.index] = OfferRecord(offer.uid, offer.index)
|
||||
while (offer_records.next()) {
|
||||
val offer = GrandExchangeOffer.fromQuery(offer_records)
|
||||
if (offer.index == -1) //used to index old (converted from JSON) offers
|
||||
needsIndex.push(offer)
|
||||
else
|
||||
instance.offerRecords[offer.index] = OfferRecord(offer.uid, offer.index)
|
||||
}
|
||||
stmt.close()
|
||||
}
|
||||
stmt.close()
|
||||
|
||||
if (needsIndex.isNotEmpty()) {
|
||||
for ((index, offer) in offerRecords.withIndex()) {
|
||||
@@ -85,7 +85,7 @@ class GrandExchangeRecords(private val player: Player? = null) : PersistPlayer,
|
||||
}
|
||||
}
|
||||
|
||||
instance.visualizeRecords()
|
||||
instance.init()
|
||||
}
|
||||
|
||||
override fun savePlayer(player: Player, save: JSONObject) {
|
||||
@@ -128,22 +128,22 @@ class GrandExchangeRecords(private val player: Player? = null) : PersistPlayer,
|
||||
|
||||
fun visualizeRecords()
|
||||
{
|
||||
val conn = GEDB.connect()
|
||||
val stmt = conn.createStatement()
|
||||
GEDB.run { conn ->
|
||||
val stmt = conn.createStatement()
|
||||
|
||||
for (record in offerRecords) {
|
||||
if (record != null) {
|
||||
val offer_raw = stmt.executeQuery("select * from player_offers where uid = ${record.uid}")
|
||||
if(offer_raw.next())
|
||||
{
|
||||
val offer = GrandExchangeOffer.fromQuery(offer_raw)
|
||||
if(offer.offerState == OfferState.REMOVED) continue
|
||||
offer.index = record.slot
|
||||
offer.visualize(player)
|
||||
for (record in offerRecords) {
|
||||
if (record != null) {
|
||||
val offer_raw = stmt.executeQuery("select * from player_offers where uid = ${record.uid}")
|
||||
if (offer_raw.next()) {
|
||||
val offer = GrandExchangeOffer.fromQuery(offer_raw)
|
||||
if (offer.offerState == OfferState.REMOVED) continue
|
||||
offer.index = record.slot
|
||||
offer.visualize(player)
|
||||
}
|
||||
}
|
||||
}
|
||||
stmt.close()
|
||||
}
|
||||
stmt.close()
|
||||
}
|
||||
|
||||
fun getOffer(index: Int) : GrandExchangeOffer?
|
||||
@@ -155,18 +155,19 @@ class GrandExchangeRecords(private val player: Player? = null) : PersistPlayer,
|
||||
fun getOffer(record: OfferRecord?) : GrandExchangeOffer?
|
||||
{
|
||||
record ?: return null
|
||||
val conn = GEDB.connect()
|
||||
val stmt = conn.createStatement()
|
||||
val offer_raw = stmt.executeQuery("select * from player_offers where uid = ${record.uid}")
|
||||
if(offer_raw.next())
|
||||
{
|
||||
val offer = GrandExchangeOffer.fromQuery(offer_raw)
|
||||
offer.index = record.slot
|
||||
var offerToReturn: GrandExchangeOffer? = null
|
||||
GEDB.run { conn ->
|
||||
val stmt = conn.createStatement()
|
||||
val offer_raw = stmt.executeQuery("select * from player_offers where uid = ${record.uid}")
|
||||
if (offer_raw.next()) {
|
||||
val offer = GrandExchangeOffer.fromQuery(offer_raw)
|
||||
offer.index = record.slot
|
||||
stmt.close()
|
||||
offerToReturn = offer
|
||||
}
|
||||
stmt.close()
|
||||
return offer
|
||||
}
|
||||
stmt.close()
|
||||
return null
|
||||
return offerToReturn
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,135 @@
|
||||
package rs09.game.ge
|
||||
|
||||
import api.itemDefinition
|
||||
import java.sql.ResultSet
|
||||
|
||||
object PriceIndex {
|
||||
@JvmStatic fun canTrade(id: Int): Boolean {
|
||||
var canTrade = false
|
||||
|
||||
GEDB.run {conn ->
|
||||
val stmt = conn.prepareStatement(EXISTS_QUERY)
|
||||
stmt.setInt(1, id)
|
||||
val res = stmt.executeQuery()
|
||||
if(res.next()) {
|
||||
canTrade = res.getInt(1) == 1
|
||||
}
|
||||
}
|
||||
|
||||
return canTrade
|
||||
}
|
||||
|
||||
fun banItem(id: Int) {
|
||||
GEDB.run { conn ->
|
||||
val stmt = conn.prepareStatement(REMOVE_QUERY)
|
||||
stmt.setInt(1, id)
|
||||
stmt.execute()
|
||||
}
|
||||
}
|
||||
|
||||
fun allowItem(id: Int) {
|
||||
GEDB.run { conn ->
|
||||
val stmt = conn.prepareStatement(INSERT_QUERY)
|
||||
stmt.setInt(1, id)
|
||||
stmt.setInt(2, itemDefinition(id).getAlchemyValue(true))
|
||||
stmt.setInt(3, itemDefinition(id).getAlchemyValue(true))
|
||||
stmt.setInt(4, 0)
|
||||
stmt.setInt(5, 0)
|
||||
stmt.execute()
|
||||
}
|
||||
}
|
||||
|
||||
fun getValue(id: Int): Int {
|
||||
var value = itemDefinition(id).getAlchemyValue(true)
|
||||
GEDB.run { conn ->
|
||||
val stmt = conn.prepareStatement(GET_VALUE_QUERY)
|
||||
stmt.setInt(1, id)
|
||||
val res = stmt.executeQuery()
|
||||
if(res.next()) {
|
||||
value = res.getInt(1)
|
||||
}
|
||||
}
|
||||
return value
|
||||
}
|
||||
|
||||
fun addTrade(id: Int, amount: Int, pricePerUnit: Int) {
|
||||
val oldInfo = getInfo(id) ?: return
|
||||
val newInfo = oldInfo.copy()
|
||||
|
||||
val volumeResetThreshold =
|
||||
if (pricePerUnit >= 1000000) 500
|
||||
else if (pricePerUnit >= 100000) 1000
|
||||
else if (pricePerUnit >= 25000) 2500
|
||||
else 10000
|
||||
|
||||
newInfo.totalValue += (amount * pricePerUnit)
|
||||
newInfo.uniqueTrades += amount
|
||||
newInfo.lastUpdate = System.currentTimeMillis()
|
||||
newInfo.currentValue = (newInfo.totalValue / newInfo.uniqueTrades).toInt()
|
||||
|
||||
if (newInfo.uniqueTrades > volumeResetThreshold) {
|
||||
val newAmt = (0.1 * volumeResetThreshold).toInt()
|
||||
newInfo.uniqueTrades = newAmt
|
||||
newInfo.totalValue = newAmt.toLong() * newInfo.currentValue
|
||||
}
|
||||
|
||||
updateInfo(newInfo)
|
||||
}
|
||||
|
||||
private fun updateInfo(newInfo: PriceInfo) {
|
||||
GEDB.run { conn ->
|
||||
val stmt = conn.prepareStatement(UPDATE_QUERY)
|
||||
stmt.setInt(1, newInfo.currentValue)
|
||||
stmt.setLong(2, newInfo.totalValue)
|
||||
stmt.setInt(3, newInfo.uniqueTrades)
|
||||
stmt.setLong(4, newInfo.lastUpdate)
|
||||
stmt.setInt(5, newInfo.itemId)
|
||||
stmt.execute()
|
||||
}
|
||||
}
|
||||
|
||||
private fun getInfo(id: Int): PriceInfo? {
|
||||
var priceInfo: PriceInfo? = null
|
||||
|
||||
GEDB.run { conn ->
|
||||
val stmt = conn.prepareStatement(SELECT_QUERY)
|
||||
stmt.setInt(1, id)
|
||||
val res = stmt.executeQuery()
|
||||
if(res.next()) {
|
||||
priceInfo = PriceInfo.fromQuery(res)
|
||||
}
|
||||
}
|
||||
|
||||
return priceInfo
|
||||
}
|
||||
|
||||
const val SELECT_QUERY = "SELECT * FROM price_index WHERE item_id = ?;"
|
||||
const val UPDATE_QUERY = "UPDATE price_index SET value = ?, total_value = ?, unique_trades = ?, last_update = ? WHERE item_id = ?;"
|
||||
const val EXISTS_QUERY = "SELECT EXISTS(SELECT 1 FROM price_index WHERE item_id = ?);"
|
||||
const val REMOVE_QUERY = "DELETE FROM price_index WHERE item_id = ?;"
|
||||
const val INSERT_QUERY = "INSERT INTO price_index (item_id, value, total_value, unique_trades, last_update) VALUES (?,?,?,?,?);"
|
||||
const val GET_VALUE_QUERY = "SELECT value FROM price_index WHERE item_id = ?;"
|
||||
}
|
||||
|
||||
data class PriceInfo(
|
||||
var itemId: Int,
|
||||
var currentValue: Int,
|
||||
var totalValue: Long,
|
||||
var uniqueTrades: Int,
|
||||
var lastUpdate: Long
|
||||
) {
|
||||
fun copy() : PriceInfo {
|
||||
return PriceInfo(itemId, currentValue, totalValue, uniqueTrades, lastUpdate)
|
||||
}
|
||||
companion object {
|
||||
fun fromQuery(result: ResultSet) : PriceInfo {
|
||||
return PriceInfo(
|
||||
result.getInt(1),
|
||||
result.getInt(2),
|
||||
result.getLong(3),
|
||||
result.getInt(4),
|
||||
result.getLong(5)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,8 +3,6 @@ package rs09.game.interaction.inter.ge
|
||||
import api.*
|
||||
import core.game.component.Component
|
||||
import core.game.container.access.BitregisterAssembler
|
||||
import core.game.ge.GrandExchangeDatabase
|
||||
import core.game.ge.GrandExchangeEntry
|
||||
import core.game.ge.OfferState
|
||||
import core.game.node.entity.player.Player
|
||||
import core.game.node.entity.player.link.audio.Audio
|
||||
@@ -18,6 +16,7 @@ import org.rs09.consts.Components
|
||||
import rs09.game.ge.GrandExchange
|
||||
import rs09.game.ge.GrandExchangeOffer
|
||||
import rs09.game.ge.GrandExchangeRecords
|
||||
import rs09.game.ge.PriceIndex
|
||||
import rs09.game.interaction.InterfaceListener
|
||||
import rs09.game.system.SystemLogger
|
||||
|
||||
@@ -69,8 +68,7 @@ class StockMarket : InterfaceListener {
|
||||
var id = item.id
|
||||
if(!item.definition.isUnnoted)
|
||||
id = item.noteChange
|
||||
val itemDb = GrandExchangeDatabase.getDatabase()[id]
|
||||
if(itemDb == null || !item.definition.isTradeable)
|
||||
if(!PriceIndex.canTrade(id))
|
||||
{
|
||||
sendMessage(player, "This item can't be sold on the Grand Exchange.")
|
||||
return@on true
|
||||
@@ -316,11 +314,10 @@ class StockMarket : InterfaceListener {
|
||||
fun updateVarbits(player: Player, offer: GrandExchangeOffer?, index: Int, sale: Boolean? = null)
|
||||
{
|
||||
val isSale = sale ?: offer?.sell ?: false
|
||||
val entry: GrandExchangeEntry? = GrandExchangeDatabase.getDatabase()[offer?.itemID ?: -1]
|
||||
var lowPrice = 0
|
||||
var highPrice = 0
|
||||
val recommendedPrice = GrandExchange.getRecommendedPrice(entry?.itemId ?: 0)
|
||||
if (entry != null) {
|
||||
val recommendedPrice = GrandExchange.getRecommendedPrice(offer?.itemID ?: 0)
|
||||
if (PriceIndex.canTrade(offer?.itemID ?: 0)) {
|
||||
lowPrice = (recommendedPrice * 0.95).toInt()
|
||||
highPrice = (recommendedPrice * 1.05).toInt()
|
||||
}
|
||||
|
||||
@@ -570,7 +570,7 @@ class MiscCommandSet : CommandSet(Privilege.ADMIN){
|
||||
val offerAmounts = HashMap<Int,Int>()
|
||||
val offerPrice = HashMap<Int,Int>()
|
||||
|
||||
val offers = GrandExchange.getBotOffers().filter { getItemName(it.itemID).contains(searchTerm, true) }
|
||||
val offers = GrandExchange.getBotOffers().filter { getItemName(it.itemID).contains(searchTerm, true) || getItemName(it.itemID).equals(searchTerm, true) }
|
||||
|
||||
for(offer in offers)
|
||||
{
|
||||
@@ -682,7 +682,7 @@ class MiscCommandSet : CommandSet(Privilege.ADMIN){
|
||||
}
|
||||
|
||||
fun showOffers(player: Player, searchTerm: String){
|
||||
val offers = GrandExchange.getValidOffers().filter { getItemName(it.itemID).contains(searchTerm, true) }
|
||||
val offers = GrandExchange.getValidOffers().filter { getItemName(it.itemID).contains(searchTerm, true) || getItemName(it.itemID).equals(searchTerm, true) }
|
||||
val buyingAmount = HashMap<Int, Int>()
|
||||
val buyingHighest = HashMap<Int, Int>()
|
||||
val sellingAmount = HashMap<Int,Int>()
|
||||
|
||||
@@ -114,6 +114,7 @@ object ServerConfigParser {
|
||||
ServerConstants.CELEDT_DATA_PATH = data.getPath("paths.cele_drop_table_path")
|
||||
ServerConstants.SERVER_GE_NAME = data.getString("world.name_ge") ?: ServerConstants.SERVER_NAME
|
||||
ServerConstants.RULES_AND_INFO_ENABLED = data.getBoolean("world.show_rules", true)
|
||||
ServerConstants.BOTS_INFLUENCE_PRICE_INDEX = data.getBoolean("world.bots_influence_ge_price", true)
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user