mirror of
https://gitlab.com/2009scape/2009scape.git
synced 2025-12-09 16:45:44 -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/mysql-connector-java-8.0.21.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 rs09.game.content.global.GlobalKillCounter;
|
||||
import rs09.game.ge.GEAutoStock
|
||||
import rs09.game.ge.GEDB
|
||||
import rs09.game.system.SystemLogger
|
||||
import rs09.game.system.config.ServerConfigParser
|
||||
import rs09.game.world.GameWorld
|
||||
|
|
@ -64,6 +65,7 @@ object Server {
|
|||
SystemLogger.logInfo("Using config file: ${"worldprops" + File.separator + "default.conf"}")
|
||||
ServerConfigParser.parse("worldprops" + File.separator + "default.conf")
|
||||
}
|
||||
GEDB.init()
|
||||
startTime = System.currentTimeMillis()
|
||||
val t = TimeStamp()
|
||||
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
|
||||
|
||||
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 rs09.game.system.SystemLogger
|
||||
import rs09.game.world.repository.Repository
|
||||
import rs09.tools.secondsToTicks
|
||||
|
||||
object GrandExchange : CallBack {
|
||||
|
|
@ -14,15 +22,12 @@ object GrandExchange : CallBack {
|
|||
* 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.
|
||||
*/
|
||||
fun boot(local: Boolean){
|
||||
fun boot(){
|
||||
if(isRunning) return
|
||||
|
||||
if(!local){
|
||||
TODO("Remote GE server stuff")
|
||||
}
|
||||
|
||||
SystemLogger.logGE("Initializing GE...")
|
||||
OfferManager.init()
|
||||
//OfferManager.init()
|
||||
SystemLogger.logGE("GE Initialized.")
|
||||
|
||||
SystemLogger.logGE("Initializing GE Update Worker")
|
||||
|
|
@ -31,11 +36,39 @@ object GrandExchange : CallBack {
|
|||
Thread.currentThread().name = "GE Update Worker"
|
||||
while(true) {
|
||||
SystemLogger.logGE("Updating offers...")
|
||||
OfferManager.update()
|
||||
if(OfferManager.dumpDatabase){
|
||||
SystemLogger.logGE("Saving GE...")
|
||||
OfferManager.save()
|
||||
OfferManager.dumpDatabase = false
|
||||
val conn = GEDB.connect()
|
||||
val stmt = conn.createStatement()
|
||||
val buy_offer = stmt.executeQuery("SELECT * from player_offers where is_sale = 0")
|
||||
|
||||
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
|
||||
}
|
||||
|
|
@ -44,8 +77,68 @@ object GrandExchange : CallBack {
|
|||
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 {
|
||||
boot(true)
|
||||
GEDB.init()
|
||||
boot()
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
|
@ -4,12 +4,19 @@ import core.cache.def.impl.ItemDefinition
|
|||
import core.game.ge.OfferState
|
||||
import core.game.node.entity.player.Player
|
||||
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() {
|
||||
|
|
@ -27,6 +34,7 @@ class GrandExchangeOffer() {
|
|||
var player: Player? = null
|
||||
var playerUID = 0
|
||||
var isLimitation = false
|
||||
var isBot = false
|
||||
|
||||
/**
|
||||
* Gets the total amount of money entered.
|
||||
|
|
@ -49,7 +57,164 @@ class GrandExchangeOffer() {
|
|||
val isActive: Boolean
|
||||
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 {
|
||||
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 {
|
||||
if (offer.amount < 1) {
|
||||
player.packetDispatch.sendMessage("You must choose the quantity you wish to buy!")
|
||||
println("amountthing")
|
||||
return false
|
||||
}
|
||||
if (offer.offeredValue < 1) {
|
||||
player.packetDispatch.sendMessage("You must choose the price you wish to buy for!")
|
||||
println("pricethng")
|
||||
return false
|
||||
}
|
||||
if (offer.offerState != OfferState.PENDING || offer.uid != 0L) {
|
||||
println("pendingthing")
|
||||
return false
|
||||
}
|
||||
if (player.isArtificial) {
|
||||
|
|
|
|||
|
|
@ -296,13 +296,7 @@ class PlayerGrandExchange(private val player: Player) {
|
|||
* @param offer The offer to update.
|
||||
*/
|
||||
fun update(offer: GrandExchangeOffer?) {
|
||||
if (offer != null) {
|
||||
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)
|
||||
)
|
||||
}
|
||||
offer?.visualize(player)
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -106,7 +106,7 @@ class LoginParser(
|
|||
return
|
||||
}
|
||||
if(!PlayerParser.parse(player)){
|
||||
Repository.players.remove(player)
|
||||
Repository.removePlayer(player)
|
||||
Repository.LOGGED_IN_PLAYERS.remove(player.username)
|
||||
Repository.lobbyPlayers.remove(player)
|
||||
Repository.playerNames.remove(player.name)
|
||||
|
|
@ -124,10 +124,10 @@ class LoginParser(
|
|||
p.clear()
|
||||
Repository.playerNames.remove(p.name)
|
||||
Repository.lobbyPlayers.remove(p)
|
||||
Repository.players.remove(p)
|
||||
Repository.removePlayer(p)
|
||||
}
|
||||
if (!Repository.players.contains(player)) {
|
||||
Repository.players.add(player)
|
||||
Repository.addPlayer(player)
|
||||
}
|
||||
player.details.session.setObject(player)
|
||||
flag(Response.SUCCESSFUL)
|
||||
|
|
@ -179,7 +179,7 @@ class LoginParser(
|
|||
GameWorld.Pulser.submit(object : Pulse(1) {
|
||||
override fun pulse(): Boolean {
|
||||
if (!Repository.players.contains(player)) {
|
||||
Repository.players.add(player)
|
||||
Repository.addPlayer(player)
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ class DisconnectionQueue {
|
|||
}
|
||||
Repository.playerNames.remove(player.name)
|
||||
Repository.lobbyPlayers.remove(player)
|
||||
Repository.players.remove(player)
|
||||
Repository.removePlayer(player)
|
||||
Repository.LOGGED_IN_PLAYERS.remove(player.details.username)
|
||||
SystemLogger.logInfo("Player cleared. Removed ${player.details.username}")
|
||||
try {
|
||||
|
|
|
|||
|
|
@ -19,6 +19,8 @@ object Repository {
|
|||
*/
|
||||
@JvmStatic
|
||||
val players = NodeList<Player>(ServerConstants.MAX_PLAYERS)
|
||||
val uid_map = HashMap<Int,Player>(ServerConstants.MAX_PLAYERS)
|
||||
|
||||
/**
|
||||
* Represents the repository of active npcs.
|
||||
*/
|
||||
|
|
@ -129,6 +131,18 @@ object Repository {
|
|||
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.
|
||||
* @param npcId The non-player character's id.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue