mirror of
https://gitlab.com/2009scape/2009scape.git
synced 2025-12-10 10:20:41 -07:00
Majority of GE work
This commit is contained in:
parent
609702ec27
commit
f36faa0f09
10 changed files with 450 additions and 29 deletions
|
|
@ -32,7 +32,8 @@ dependencies {
|
||||||
"libs/classgraph-4.8.98.jar",
|
"libs/classgraph-4.8.98.jar",
|
||||||
"libs/mysql-connector-java-8.0.21.jar",
|
"libs/mysql-connector-java-8.0.21.jar",
|
||||||
"libs/mordant-jvm-2.0.0-alpha2.jar",
|
"libs/mordant-jvm-2.0.0-alpha2.jar",
|
||||||
"libs/colormath-jvm-2.0.0.jar"
|
"libs/colormath-jvm-2.0.0.jar",
|
||||||
|
"libs/sqlite-jdbc.jar"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@ import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import rs09.game.content.global.GlobalKillCounter;
|
import rs09.game.content.global.GlobalKillCounter;
|
||||||
import rs09.game.ge.GEAutoStock
|
import rs09.game.ge.GEAutoStock
|
||||||
|
import rs09.game.ge.GEDB
|
||||||
import rs09.game.system.SystemLogger
|
import rs09.game.system.SystemLogger
|
||||||
import rs09.game.system.config.ServerConfigParser
|
import rs09.game.system.config.ServerConfigParser
|
||||||
import rs09.game.world.GameWorld
|
import rs09.game.world.GameWorld
|
||||||
|
|
@ -64,6 +65,7 @@ object Server {
|
||||||
SystemLogger.logInfo("Using config file: ${"worldprops" + File.separator + "default.conf"}")
|
SystemLogger.logInfo("Using config file: ${"worldprops" + File.separator + "default.conf"}")
|
||||||
ServerConfigParser.parse("worldprops" + File.separator + "default.conf")
|
ServerConfigParser.parse("worldprops" + File.separator + "default.conf")
|
||||||
}
|
}
|
||||||
|
GEDB.init()
|
||||||
startTime = System.currentTimeMillis()
|
startTime = System.currentTimeMillis()
|
||||||
val t = TimeStamp()
|
val t = TimeStamp()
|
||||||
SystemLogger.logInfo("Initializing Server Store...")
|
SystemLogger.logInfo("Initializing Server Store...")
|
||||||
|
|
|
||||||
155
Server/src/main/kotlin/rs09/game/ge/GEDB.kt
Normal file
155
Server/src/main/kotlin/rs09/game/ge/GEDB.kt
Normal file
|
|
@ -0,0 +1,155 @@
|
||||||
|
package rs09.game.ge
|
||||||
|
|
||||||
|
import core.cache.def.impl.ItemDefinition
|
||||||
|
import core.game.ge.OfferState
|
||||||
|
import core.game.node.entity.player.link.audio.Audio
|
||||||
|
import org.json.simple.JSONArray
|
||||||
|
import org.json.simple.JSONObject
|
||||||
|
import org.json.simple.parser.JSONParser
|
||||||
|
import rs09.ServerConstants
|
||||||
|
import java.io.File
|
||||||
|
import java.io.FileReader
|
||||||
|
import java.lang.Integer.min
|
||||||
|
import java.sql.Connection
|
||||||
|
import java.sql.DriverManager
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Collection of methods for interacting with the grand exchange databases
|
||||||
|
* @author Ceikry
|
||||||
|
*/
|
||||||
|
object GEDB {
|
||||||
|
var pathString = ""
|
||||||
|
|
||||||
|
//This needs to be a separate method, so we can call it after the server config has been parsed
|
||||||
|
fun init()
|
||||||
|
{
|
||||||
|
pathString = ServerConstants.GRAND_EXCHANGE_DATA_PATH + File.separator + "grandexchange.db"
|
||||||
|
|
||||||
|
//Check if the grandexchange.db file already exists. If not, create it and create the tables.
|
||||||
|
if(!File(pathString).exists())
|
||||||
|
generateAndTransfer()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun connect(): Connection
|
||||||
|
{
|
||||||
|
return DriverManager.getConnection("jdbc:sqlite:$pathString")
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun convertJsonArray(arr: JSONArray): String
|
||||||
|
{
|
||||||
|
val sb = StringBuilder()
|
||||||
|
for ((index, data) in arr.withIndex())
|
||||||
|
{
|
||||||
|
val item = data as JSONObject
|
||||||
|
sb.append("$index")
|
||||||
|
sb.append(",")
|
||||||
|
sb.append(item["id"])
|
||||||
|
sb.append(",")
|
||||||
|
sb.append(item["amount"])
|
||||||
|
if(index + 1 < arr.size)
|
||||||
|
sb.append(":")
|
||||||
|
}
|
||||||
|
return sb.toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun generateAndTransfer()
|
||||||
|
{
|
||||||
|
val conn = connect() //for sqlite jdbc, attempting to connect to a non-existing .db file creates it.
|
||||||
|
val statement = conn.createStatement()
|
||||||
|
|
||||||
|
//table for tracking player offers - replaces offer_dispatch.json
|
||||||
|
statement.execute(
|
||||||
|
"CREATE TABLE player_offers(" +
|
||||||
|
"uid INTEGER PRIMARY KEY ASC," +
|
||||||
|
"player_uid INTEGER," +
|
||||||
|
"item_id INTEGER," +
|
||||||
|
"amount_total INTEGER," +
|
||||||
|
"amount_complete INTEGER," +
|
||||||
|
"offered_value INTEGER," +
|
||||||
|
"time_stamp INTEGER," +
|
||||||
|
"offer_state INTEGER," +
|
||||||
|
"is_sale INTEGER," +
|
||||||
|
"withdraw_items STRING ," +
|
||||||
|
"total_coin_xc INTEGER)"
|
||||||
|
)
|
||||||
|
|
||||||
|
//table for tracking bot offers - replaces bot_offers.json
|
||||||
|
statement.execute(
|
||||||
|
"CREATE TABLE bot_offers(" +
|
||||||
|
"item_id INTEGER," +
|
||||||
|
"amount INTEGER)"
|
||||||
|
)
|
||||||
|
|
||||||
|
//table for tracking price index data - replaces gedb.xml
|
||||||
|
statement.execute(
|
||||||
|
"CREATE TABLE price_index(" +
|
||||||
|
"item_id INTEGER," +
|
||||||
|
"value INTEGER," +
|
||||||
|
"total_value INTEGER," +
|
||||||
|
"unique_trades INTEGER," +
|
||||||
|
"last_update INTEGER)"
|
||||||
|
)
|
||||||
|
|
||||||
|
//check if the old .json and .xml files exist, and if they do, read them into the sqlite database and remove them.
|
||||||
|
val playerJson = ServerConstants.GRAND_EXCHANGE_DATA_PATH + "offer_dispatch.json"
|
||||||
|
val botJson = ServerConstants.GRAND_EXCHANGE_DATA_PATH + "bot_offers.json"
|
||||||
|
|
||||||
|
if(File(playerJson).exists())
|
||||||
|
{
|
||||||
|
val parser = JSONParser()
|
||||||
|
val reader = FileReader(playerJson)
|
||||||
|
val saveFile = parser.parse(reader) as JSONObject
|
||||||
|
|
||||||
|
if (saveFile.containsKey("offers")) {
|
||||||
|
val offers = saveFile["offers"] as JSONArray
|
||||||
|
|
||||||
|
for (offer in offers) {
|
||||||
|
val o = offer as JSONObject
|
||||||
|
statement.execute("insert into player_offers(player_uid,item_id,amount_total,amount_complete,offered_value,time_stamp,offer_state,is_sale,withdraw_items,total_coin_xc) " +
|
||||||
|
"values(" +
|
||||||
|
"${o["playerUID"]}," +
|
||||||
|
"${o["itemId"]}," +
|
||||||
|
"${o["amount"]}," +
|
||||||
|
"${o["completedAmount"]}," +
|
||||||
|
"${o["offeredValue"]}," +
|
||||||
|
"${o["timeStamp"]}," +
|
||||||
|
"${o["offerState"]}," +
|
||||||
|
"${if (o["sale"] as Boolean) 1 else 0}," +
|
||||||
|
"'" + convertJsonArray(o["withdrawItems"] as JSONArray) + "'," +
|
||||||
|
"${o["totalCoinExchange"]})"
|
||||||
|
)
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
reader.close()
|
||||||
|
//File(playerJson).delete()
|
||||||
|
}
|
||||||
|
|
||||||
|
if(File(botJson).exists())
|
||||||
|
{
|
||||||
|
val parser = JSONParser()
|
||||||
|
val reader = FileReader(botJson)
|
||||||
|
val saveFile = parser.parse(reader) as JSONObject
|
||||||
|
|
||||||
|
if (saveFile.containsKey("offers")) {
|
||||||
|
val offers = saveFile["offers"] as JSONArray
|
||||||
|
|
||||||
|
for (offer in offers) {
|
||||||
|
val o = offer as JSONObject
|
||||||
|
statement.execute("insert into bot_offers " +
|
||||||
|
"values(${o["item"]},${o["qty"]})")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
reader.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})")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,7 +1,15 @@
|
||||||
package rs09.game.ge
|
package rs09.game.ge
|
||||||
|
|
||||||
|
import api.getItemName
|
||||||
|
import api.sendMessage
|
||||||
|
import core.cache.def.impl.ItemDefinition
|
||||||
|
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 core.game.world.callback.CallBack
|
import core.game.world.callback.CallBack
|
||||||
import rs09.game.system.SystemLogger
|
import rs09.game.system.SystemLogger
|
||||||
|
import rs09.game.world.repository.Repository
|
||||||
import rs09.tools.secondsToTicks
|
import rs09.tools.secondsToTicks
|
||||||
|
|
||||||
object GrandExchange : CallBack {
|
object GrandExchange : CallBack {
|
||||||
|
|
@ -14,15 +22,12 @@ object GrandExchange : CallBack {
|
||||||
* Initializes the offer manager and spawns an update thread.
|
* Initializes the offer manager and spawns an update thread.
|
||||||
* @param local whether or not the GE should be the local in-code server rather than some hypothetical remote implementation.
|
* @param local whether or not the GE should be the local in-code server rather than some hypothetical remote implementation.
|
||||||
*/
|
*/
|
||||||
fun boot(local: Boolean){
|
fun boot(){
|
||||||
if(isRunning) return
|
if(isRunning) return
|
||||||
|
|
||||||
if(!local){
|
|
||||||
TODO("Remote GE server stuff")
|
|
||||||
}
|
|
||||||
|
|
||||||
SystemLogger.logGE("Initializing GE...")
|
SystemLogger.logGE("Initializing GE...")
|
||||||
OfferManager.init()
|
//OfferManager.init()
|
||||||
SystemLogger.logGE("GE Initialized.")
|
SystemLogger.logGE("GE Initialized.")
|
||||||
|
|
||||||
SystemLogger.logGE("Initializing GE Update Worker")
|
SystemLogger.logGE("Initializing GE Update Worker")
|
||||||
|
|
@ -31,11 +36,39 @@ object GrandExchange : CallBack {
|
||||||
Thread.currentThread().name = "GE Update Worker"
|
Thread.currentThread().name = "GE Update Worker"
|
||||||
while(true) {
|
while(true) {
|
||||||
SystemLogger.logGE("Updating offers...")
|
SystemLogger.logGE("Updating offers...")
|
||||||
OfferManager.update()
|
val conn = GEDB.connect()
|
||||||
if(OfferManager.dumpDatabase){
|
val stmt = conn.createStatement()
|
||||||
SystemLogger.logGE("Saving GE...")
|
val buy_offer = stmt.executeQuery("SELECT * from player_offers where is_sale = 0")
|
||||||
OfferManager.save()
|
|
||||||
OfferManager.dumpDatabase = false
|
while(buy_offer.next())
|
||||||
|
{
|
||||||
|
val offer = GrandExchangeOffer.fromQuery(buy_offer)
|
||||||
|
if(offer.isActive)
|
||||||
|
{
|
||||||
|
val sell_offer = stmt.executeQuery("SELECT * from player_offers where is_sale = 1 AND item_id = ${offer.itemID}")
|
||||||
|
while(sell_offer.next())
|
||||||
|
{
|
||||||
|
val otherOffer = GrandExchangeOffer.fromQuery(sell_offer)
|
||||||
|
if(!otherOffer.isActive) continue
|
||||||
|
val before = offer.amountLeft
|
||||||
|
exchange(offer,otherOffer)
|
||||||
|
if(offer.amountLeft != before)
|
||||||
|
SystemLogger.logGE("Purchased ${offer.amountLeft - before}x ${getItemName(offer.itemID)} @ ${offer.offeredValue}/${otherOffer.offeredValue} gp each.")
|
||||||
|
}
|
||||||
|
|
||||||
|
if(offer.amountLeft > 0)
|
||||||
|
{
|
||||||
|
val bot_offer = stmt.executeQuery("SELECT * from bot_offers where item_id = ${offer.itemID}")
|
||||||
|
if(bot_offer.next())
|
||||||
|
{
|
||||||
|
val botOffer = GrandExchangeOffer.fromBotQuery(bot_offer)
|
||||||
|
val before = offer.amountLeft
|
||||||
|
exchange(offer, botOffer)
|
||||||
|
if(offer.amountLeft != before)
|
||||||
|
SystemLogger.logGE("Purchased FROM BOT ${offer.amountLeft - before}x ${getItemName(offer.itemID)}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Thread.sleep(60_000) //sleep for 60 seconds
|
Thread.sleep(60_000) //sleep for 60 seconds
|
||||||
}
|
}
|
||||||
|
|
@ -44,8 +77,68 @@ object GrandExchange : CallBack {
|
||||||
isRunning = true
|
isRunning = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun dispatch(player: Player, offer: GrandExchangeOffer) : Boolean
|
||||||
|
{
|
||||||
|
if ( offer.amount < 1 )
|
||||||
|
sendMessage(player, "You must choose the quantity you wish to buy!").also { return false }
|
||||||
|
|
||||||
|
if ( offer.offeredValue < 1 )
|
||||||
|
sendMessage(player, "You must choose the price you wish to buy for!").also { return false }
|
||||||
|
|
||||||
|
if ( offer.offerState != OfferState.PENDING || offer.uid != 0L )
|
||||||
|
return false
|
||||||
|
|
||||||
|
if ( player.isArtificial )
|
||||||
|
offer.playerUID = PlayerDetails.getDetails("2009scape").uid.also { offer.isBot = true }
|
||||||
|
else
|
||||||
|
offer.playerUID = player.details.uid
|
||||||
|
|
||||||
|
offer.offerState = OfferState.REGISTERED
|
||||||
|
player.playerGrandExchange.update(offer)
|
||||||
|
|
||||||
|
if (offer.sell) {
|
||||||
|
Repository.sendNews(player.username + " just offered " + offer.amount + " " + getItemName(offer.itemID) + " on the GE.")
|
||||||
|
}
|
||||||
|
|
||||||
|
offer.writeNew()
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
fun exchange(offer: GrandExchangeOffer, other: GrandExchangeOffer)
|
||||||
|
{
|
||||||
|
if(offer.sell && other.sell) return //Don't exchange if they are both sell offers
|
||||||
|
val amount = Integer.min(offer.amount - offer.completedAmount, other.amount - other.completedAmount)
|
||||||
|
|
||||||
|
val seller = if(offer.sell) offer else other
|
||||||
|
val buyer = if(offer == seller) other else offer
|
||||||
|
|
||||||
|
//If the buyer is buying for less than the seller is selling for, don't exchange
|
||||||
|
if(seller.offeredValue > buyer.offeredValue) return
|
||||||
|
|
||||||
|
seller.completedAmount += amount
|
||||||
|
buyer.completedAmount += amount
|
||||||
|
|
||||||
|
if(seller.amountLeft < 1 && seller.player != null)
|
||||||
|
seller.player!!.audioManager.send(Audio(4042,1,1))
|
||||||
|
|
||||||
|
seller.addWithdrawItem(995, amount * buyer.offeredValue)
|
||||||
|
buyer.addWithdrawItem(seller.itemID, amount)
|
||||||
|
|
||||||
|
if(seller.offeredValue < buyer.offeredValue)
|
||||||
|
buyer.addWithdrawItem(995, amount * (buyer.offeredValue - seller.offeredValue))
|
||||||
|
|
||||||
|
if(seller.amountLeft < 1)
|
||||||
|
seller.offerState = OfferState.COMPLETED
|
||||||
|
if(buyer.amountLeft < 1)
|
||||||
|
buyer.offerState = OfferState.COMPLETED
|
||||||
|
|
||||||
|
seller.update()
|
||||||
|
buyer.update()
|
||||||
|
}
|
||||||
|
|
||||||
override fun call(): Boolean {
|
override fun call(): Boolean {
|
||||||
boot(true)
|
GEDB.init()
|
||||||
|
boot()
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -4,12 +4,19 @@ import core.cache.def.impl.ItemDefinition
|
||||||
import core.game.ge.OfferState
|
import core.game.ge.OfferState
|
||||||
import core.game.node.entity.player.Player
|
import core.game.node.entity.player.Player
|
||||||
import core.game.node.item.Item
|
import core.game.node.item.Item
|
||||||
|
import core.net.packet.PacketRepository
|
||||||
|
import core.net.packet.context.ContainerContext
|
||||||
|
import core.net.packet.context.GrandExchangeContext
|
||||||
|
import core.net.packet.out.ContainerPacket
|
||||||
|
import core.net.packet.out.GrandExchangePacket
|
||||||
|
import rs09.game.world.repository.Repository
|
||||||
|
import java.sql.ResultSet
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A struct holding all the data for grand exchange offers as stored in json database.
|
* A struct holding all the data for grand exchange offers.
|
||||||
*
|
*
|
||||||
* @author Angle
|
* @author Ceikry
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class GrandExchangeOffer() {
|
class GrandExchangeOffer() {
|
||||||
|
|
@ -27,6 +34,7 @@ class GrandExchangeOffer() {
|
||||||
var player: Player? = null
|
var player: Player? = null
|
||||||
var playerUID = 0
|
var playerUID = 0
|
||||||
var isLimitation = false
|
var isLimitation = false
|
||||||
|
var isBot = false
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the total amount of money entered.
|
* Gets the total amount of money entered.
|
||||||
|
|
@ -49,7 +57,164 @@ class GrandExchangeOffer() {
|
||||||
val isActive: Boolean
|
val isActive: Boolean
|
||||||
get() = offerState != OfferState.ABORTED && offerState != OfferState.PENDING && offerState != OfferState.COMPLETED && offerState != OfferState.REMOVED
|
get() = offerState != OfferState.ABORTED && offerState != OfferState.PENDING && offerState != OfferState.COMPLETED && offerState != OfferState.REMOVED
|
||||||
|
|
||||||
|
fun addWithdrawItem(id: Int, amount: Int)
|
||||||
|
{
|
||||||
|
//loop checking if the item is already present first
|
||||||
|
for(item in withdraw)
|
||||||
|
if(item != null && item.id == id)
|
||||||
|
{
|
||||||
|
item.amount += amount
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
//if we make it to this point, the item was not present. Loop to find first null slot and stick item there.
|
||||||
|
for((index,item) in withdraw.withIndex())
|
||||||
|
if(item == null)
|
||||||
|
{
|
||||||
|
withdraw[index] = Item(id, amount)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
//send container update packet to player if they exist (are online)
|
||||||
|
if ( player != null )
|
||||||
|
PacketRepository.send(ContainerPacket::class.java, ContainerContext(player, -1, -1757, 523 + index, withdraw, false))
|
||||||
|
}
|
||||||
|
|
||||||
|
fun visualize(player: Player)
|
||||||
|
{
|
||||||
|
PacketRepository.send(
|
||||||
|
GrandExchangePacket::class.java,
|
||||||
|
GrandExchangeContext(player, index.toByte(), offerState.ordinal.toByte(), itemID.toShort(),
|
||||||
|
sell, offeredValue, amount, completedAmount, totalCoinExchange)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun update()
|
||||||
|
{
|
||||||
|
val conn = GEDB.connect()
|
||||||
|
|
||||||
|
if(isBot)
|
||||||
|
{
|
||||||
|
val stmt = conn.prepareStatement("UPDATE bot_offers SET amount = ? WHERE item_id = ?")
|
||||||
|
stmt.setInt(0, amountLeft)
|
||||||
|
stmt.setInt(1, itemID)
|
||||||
|
stmt.executeUpdate()
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
val stmt = conn.prepareStatement("UPDATE player_offers SET amount_left = ?, offer_state = ?, total_coin_xc = ?, withdraw_items = ? WHERE uid = ?")
|
||||||
|
stmt.setInt(0, amountLeft)
|
||||||
|
stmt.setInt(1, offerState.ordinal)
|
||||||
|
stmt.setInt(2, totalCoinExchange)
|
||||||
|
stmt.setString(3, encodeWithdraw())
|
||||||
|
stmt.setLong(4, uid)
|
||||||
|
stmt.executeUpdate()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Called when writing a brand new offer to the database. Should not be used under any other circumstance **/
|
||||||
|
fun writeNew()
|
||||||
|
{
|
||||||
|
val conn = GEDB.connect()
|
||||||
|
|
||||||
|
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")
|
||||||
|
}
|
||||||
|
else
|
||||||
|
stmt.executeUpdate("INSERT INTO bot_offers(item_id,amount) values($itemID,$amount)")
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
val stmt = conn.prepareStatement("INSERT INTO player_offers(player_uid, item_id, amount_total, offered_value, time_stamp, offer_state, is_sale) values(?,?,?,?,?,?,?,?)")
|
||||||
|
stmt.setInt(0, playerUID)
|
||||||
|
stmt.setInt(1, itemID)
|
||||||
|
stmt.setInt(2, amount)
|
||||||
|
stmt.setInt(3, offeredValue)
|
||||||
|
stmt.setLong(4, System.currentTimeMillis())
|
||||||
|
stmt.setInt(5, offerState.ordinal)
|
||||||
|
stmt.setInt(6, if(sell) 1 else 0)
|
||||||
|
stmt.executeUpdate()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun encodeWithdraw() : String
|
||||||
|
{
|
||||||
|
val sb = StringBuilder()
|
||||||
|
for((index, item) in withdraw.withIndex())
|
||||||
|
{
|
||||||
|
sb.append(index)
|
||||||
|
sb.append(",")
|
||||||
|
if(item == null)
|
||||||
|
sb.append("null")
|
||||||
|
else
|
||||||
|
sb.append(item.id)
|
||||||
|
sb.append(",")
|
||||||
|
if(item == null)
|
||||||
|
sb.append("null")
|
||||||
|
else
|
||||||
|
sb.append(item.amount)
|
||||||
|
|
||||||
|
if(index + 1 < withdraw.size)
|
||||||
|
sb.append(":")
|
||||||
|
}
|
||||||
|
|
||||||
|
return sb.toString()
|
||||||
|
}
|
||||||
|
|
||||||
override fun toString(): String {
|
override fun toString(): String {
|
||||||
return "[name=" + ItemDefinition.forId(itemID).name + ", itemId=" + itemID + ", amount=" + amount + ", completedAmount=" + completedAmount + ", offeredValue=" + offeredValue + ", index=" + index + ", sell=" + sell + ", state=" + offerState + ", withdraw=" + withdraw.contentToString() + ", totalCoinExchange=" + totalCoinExchange + ", playerUID=" + playerUID + "]"
|
return "[name=" + ItemDefinition.forId(itemID).name + ", itemId=" + itemID + ", amount=" + amount + ", completedAmount=" + completedAmount + ", offeredValue=" + offeredValue + ", index=" + index + ", sell=" + sell + ", state=" + offerState + ", withdraw=" + withdraw.contentToString() + ", totalCoinExchange=" + totalCoinExchange + ", playerUID=" + playerUID + "]"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun fromQuery(result: ResultSet): GrandExchangeOffer
|
||||||
|
{
|
||||||
|
val o = GrandExchangeOffer()
|
||||||
|
o.itemID = result.getInt("item_id")
|
||||||
|
o.amount = result.getInt("amount_total")
|
||||||
|
o.completedAmount = result.getInt("amount_completed")
|
||||||
|
o.offeredValue = result.getInt("offered_value")
|
||||||
|
o.sell = result.getInt("is_sale") == 1
|
||||||
|
o.offerState = OfferState.values()[result.getInt("offer_state")]
|
||||||
|
o.uid = result.getLong("uid")
|
||||||
|
o.timeStamp = result.getLong("time_stamp")
|
||||||
|
|
||||||
|
val itemString = result.getString("withdraw_items")
|
||||||
|
val items = itemString.split(":")
|
||||||
|
for(item in items)
|
||||||
|
{
|
||||||
|
val tokens = item.split(",")
|
||||||
|
val index = tokens[0].toInt()
|
||||||
|
if(tokens[1] == "null") continue //Skip null slots
|
||||||
|
o.withdraw[index] = Item(tokens[1].toInt(), tokens[2].toInt())
|
||||||
|
}
|
||||||
|
|
||||||
|
o.totalCoinExchange = result.getInt("total_coin_xc")
|
||||||
|
o.playerUID = result.getInt("player_uid")
|
||||||
|
|
||||||
|
if(Repository.uid_map[o.playerUID] != null)
|
||||||
|
o.player = Repository.uid_map[o.playerUID]
|
||||||
|
|
||||||
|
return o
|
||||||
|
}
|
||||||
|
|
||||||
|
fun fromBotQuery(result: ResultSet): GrandExchangeOffer
|
||||||
|
{
|
||||||
|
val o = GrandExchangeOffer()
|
||||||
|
o.sell = result.getInt("is_sale") == 1
|
||||||
|
o.amount = result.getInt("amount_total")
|
||||||
|
o.offerState = OfferState.REGISTERED
|
||||||
|
o.itemID = result.getInt("item_id")
|
||||||
|
o.offeredValue = OfferManager.getRecommendedPrice(o.itemID, true)
|
||||||
|
o.isBot = true
|
||||||
|
return o
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -342,16 +342,13 @@ object OfferManager {
|
||||||
fun dispatch(player: Player, offer: GrandExchangeOffer): Boolean {
|
fun dispatch(player: Player, offer: GrandExchangeOffer): Boolean {
|
||||||
if (offer.amount < 1) {
|
if (offer.amount < 1) {
|
||||||
player.packetDispatch.sendMessage("You must choose the quantity you wish to buy!")
|
player.packetDispatch.sendMessage("You must choose the quantity you wish to buy!")
|
||||||
println("amountthing")
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if (offer.offeredValue < 1) {
|
if (offer.offeredValue < 1) {
|
||||||
player.packetDispatch.sendMessage("You must choose the price you wish to buy for!")
|
player.packetDispatch.sendMessage("You must choose the price you wish to buy for!")
|
||||||
println("pricethng")
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if (offer.offerState != OfferState.PENDING || offer.uid != 0L) {
|
if (offer.offerState != OfferState.PENDING || offer.uid != 0L) {
|
||||||
println("pendingthing")
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if (player.isArtificial) {
|
if (player.isArtificial) {
|
||||||
|
|
|
||||||
|
|
@ -296,13 +296,7 @@ class PlayerGrandExchange(private val player: Player) {
|
||||||
* @param offer The offer to update.
|
* @param offer The offer to update.
|
||||||
*/
|
*/
|
||||||
fun update(offer: GrandExchangeOffer?) {
|
fun update(offer: GrandExchangeOffer?) {
|
||||||
if (offer != null) {
|
offer?.visualize(player)
|
||||||
PacketRepository.send(
|
|
||||||
GrandExchangePacket::class.java,
|
|
||||||
GrandExchangeContext(player, offer.index.toByte(), offer.offerState.ordinal.toByte(), offer.itemID.toShort(),
|
|
||||||
offer.sell, offer.offeredValue, offer.amount, offer.completedAmount, offer.totalCoinExchange)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -106,7 +106,7 @@ class LoginParser(
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if(!PlayerParser.parse(player)){
|
if(!PlayerParser.parse(player)){
|
||||||
Repository.players.remove(player)
|
Repository.removePlayer(player)
|
||||||
Repository.LOGGED_IN_PLAYERS.remove(player.username)
|
Repository.LOGGED_IN_PLAYERS.remove(player.username)
|
||||||
Repository.lobbyPlayers.remove(player)
|
Repository.lobbyPlayers.remove(player)
|
||||||
Repository.playerNames.remove(player.name)
|
Repository.playerNames.remove(player.name)
|
||||||
|
|
@ -124,10 +124,10 @@ class LoginParser(
|
||||||
p.clear()
|
p.clear()
|
||||||
Repository.playerNames.remove(p.name)
|
Repository.playerNames.remove(p.name)
|
||||||
Repository.lobbyPlayers.remove(p)
|
Repository.lobbyPlayers.remove(p)
|
||||||
Repository.players.remove(p)
|
Repository.removePlayer(p)
|
||||||
}
|
}
|
||||||
if (!Repository.players.contains(player)) {
|
if (!Repository.players.contains(player)) {
|
||||||
Repository.players.add(player)
|
Repository.addPlayer(player)
|
||||||
}
|
}
|
||||||
player.details.session.setObject(player)
|
player.details.session.setObject(player)
|
||||||
flag(Response.SUCCESSFUL)
|
flag(Response.SUCCESSFUL)
|
||||||
|
|
@ -179,7 +179,7 @@ class LoginParser(
|
||||||
GameWorld.Pulser.submit(object : Pulse(1) {
|
GameWorld.Pulser.submit(object : Pulse(1) {
|
||||||
override fun pulse(): Boolean {
|
override fun pulse(): Boolean {
|
||||||
if (!Repository.players.contains(player)) {
|
if (!Repository.players.contains(player)) {
|
||||||
Repository.players.add(player)
|
Repository.addPlayer(player)
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -55,7 +55,7 @@ class DisconnectionQueue {
|
||||||
}
|
}
|
||||||
Repository.playerNames.remove(player.name)
|
Repository.playerNames.remove(player.name)
|
||||||
Repository.lobbyPlayers.remove(player)
|
Repository.lobbyPlayers.remove(player)
|
||||||
Repository.players.remove(player)
|
Repository.removePlayer(player)
|
||||||
Repository.LOGGED_IN_PLAYERS.remove(player.details.username)
|
Repository.LOGGED_IN_PLAYERS.remove(player.details.username)
|
||||||
SystemLogger.logInfo("Player cleared. Removed ${player.details.username}")
|
SystemLogger.logInfo("Player cleared. Removed ${player.details.username}")
|
||||||
try {
|
try {
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,8 @@ object Repository {
|
||||||
*/
|
*/
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
val players = NodeList<Player>(ServerConstants.MAX_PLAYERS)
|
val players = NodeList<Player>(ServerConstants.MAX_PLAYERS)
|
||||||
|
val uid_map = HashMap<Int,Player>(ServerConstants.MAX_PLAYERS)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents the repository of active npcs.
|
* Represents the repository of active npcs.
|
||||||
*/
|
*/
|
||||||
|
|
@ -129,6 +131,18 @@ object Repository {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun addPlayer(player: Player){
|
||||||
|
players.add(player)
|
||||||
|
uid_map[player.details.uid] = player
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun removePlayer(player: Player){
|
||||||
|
players.remove(player)
|
||||||
|
uid_map.remove(player.details.uid)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Find a non-player character.
|
* Find a non-player character.
|
||||||
* @param npcId The non-player character's id.
|
* @param npcId The non-player character's id.
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue