mirror of
https://gitlab.com/2009scape/2009scape.git
synced 2025-12-10 10:20:41 -07:00
Merge branch 'ge-improvements' into 'master'
GE Improvements See merge request 2009scape/2009scape!158
This commit is contained in:
commit
bdaf707983
10 changed files with 523 additions and 486 deletions
|
|
@ -3,6 +3,7 @@ package core.game.ge;
|
|||
import core.game.component.Component;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.tools.StringUtils;
|
||||
import rs09.game.ge.OfferManager;
|
||||
|
||||
/**
|
||||
* Represents the glass used to open the guide prices for the different type of
|
||||
|
|
@ -139,7 +140,7 @@ public final class GEGuidePrice {
|
|||
player.getPacketDispatch().sendInterfaceConfig(642, i, false);
|
||||
}
|
||||
for (GuideItem item : getItems()) {
|
||||
player.getPacketDispatch().sendString("" + GrandExchangeDatabase.getDatabase().get(item.getItem()).getValue() + " gp", COMPONENT.getId(), item.getChildData()[0]);
|
||||
player.getPacketDispatch().sendString("" + OfferManager.getRecommendedPrice(item.item, false) + " gp", COMPONENT.getId(), item.getChildData()[0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ import core.plugin.Initializable;
|
|||
import core.plugin.Plugin;
|
||||
import kotlin.Unit;
|
||||
import rs09.game.ge.GrandExchangeOffer;
|
||||
import rs09.game.ge.OfferManager;
|
||||
import rs09.game.ge.PlayerGrandExchange;
|
||||
import rs09.game.interaction.npc.BogrogPouchSwapper;
|
||||
import rs09.game.world.GameWorld;
|
||||
|
|
@ -69,7 +70,7 @@ public class GrandExchangeInterface extends ComponentPlugin {
|
|||
if (offer == null || value < 1 || offer.getOfferState() != OfferState.PENDING) {
|
||||
return;
|
||||
}
|
||||
if (value == GrandExchangeDatabase.getDatabase().get(offer.getItemID()).getValue()) {
|
||||
if (value == OfferManager.getRecommendedPrice(offer.getItemID(), false)) {
|
||||
player.getAudioManager().send(new Audio(4043, 1, 1));
|
||||
} else if (value > offer.getOfferedValue()) {
|
||||
player.getAudioManager().send(new Audio(4041, 1, 1));
|
||||
|
|
@ -77,7 +78,7 @@ public class GrandExchangeInterface extends ComponentPlugin {
|
|||
player.getAudioManager().send(new Audio(4045, 1, 1));
|
||||
}
|
||||
offer.setOfferedValue(value);
|
||||
player.getConfigManager().send(1111, offer.getOfferedValue());
|
||||
player.varpManager.get(1111).setVarbit(0,offer.getOfferedValue()).send(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -348,14 +349,14 @@ public class GrandExchangeInterface extends ComponentPlugin {
|
|||
return false;
|
||||
case 180:
|
||||
if (offer != null) {
|
||||
setOfferValue(player, offer, GrandExchangeDatabase.getDatabase().get(offer.getItemID()).getValue());
|
||||
setOfferValue(player, offer, OfferManager.getRecommendedPrice(offer.getItemID(), false));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
case 177: // mid - 5% value
|
||||
case 183: // mid + 5% value
|
||||
if (offer != null) {
|
||||
setOfferValue(player, offer, (int) (GrandExchangeDatabase.getDatabase().get(offer.getItemID()).getValue() * (button == 177 ? 0.95 : 1.05)));
|
||||
setOfferValue(player, offer, (int) (OfferManager.getRecommendedPrice(offer.getItemID(), false) * (button == 177 ? 0.95 : 1.05)));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ import rs09.game.ai.AIPlayer;
|
|||
import rs09.game.ai.AIRepository;
|
||||
import rs09.game.ai.general.GeneralBotCreator;
|
||||
import rs09.game.content.global.NPCDropTable;
|
||||
import rs09.game.ge.OfferManager;
|
||||
import rs09.game.system.config.ItemConfigParser;
|
||||
import rs09.game.world.repository.Repository;
|
||||
|
||||
|
|
@ -177,7 +178,7 @@ public final class NPCDropTables {
|
|||
}
|
||||
}
|
||||
player.sendMessage(player.getInterfaceManager().isResizable()+"");
|
||||
int price = item.getName().endsWith("charm") ? 100 : GrandExchangeDatabase.getDatabase().get(itemId).getValue();
|
||||
int price = item.getName().endsWith("charm") ? 100 : OfferManager.getRecommendedPrice(itemId, false);
|
||||
looter.getGlobalData().setLootSharePoints(looter.getGlobalData().getLootSharePoints() - (price) + ((price / looters.size())));
|
||||
looter.sendMessage((player.getInterfaceManager().isResizable() ? "<col=32CD32>" : "<col=009900>") + "You received: " + item.getAmount() + " " + item.getName());
|
||||
for (Player p : looters) {
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import core.game.interaction.Interaction;
|
|||
import core.game.interaction.OptionHandler;
|
||||
import core.game.node.Node;
|
||||
import core.game.node.entity.combat.equipment.DegradableEquipment;
|
||||
import rs09.game.ge.OfferManager;
|
||||
|
||||
/**
|
||||
* Represents an item.
|
||||
|
|
@ -99,10 +100,7 @@ public class Item extends Node{
|
|||
*/
|
||||
public long getValue() {
|
||||
long value = 1;
|
||||
GrandExchangeEntry entry = GrandExchangeDatabase.getDatabase().get(getId());
|
||||
if (entry != null) {
|
||||
value = entry.getValue();
|
||||
}
|
||||
value = OfferManager.getRecommendedPrice(getId(), false);
|
||||
if (definition.getValue() > value) {
|
||||
value = definition.getValue();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -161,7 +161,7 @@ public class GrandExchangeTab extends ConsoleTab {
|
|||
} catch (NumberFormatException e) {
|
||||
|
||||
}
|
||||
for (GrandExchangeOffer o : OfferManager.Companion.getOffersForItem(itemId)) {
|
||||
for (GrandExchangeOffer o : OfferManager.getOffersForItem(itemId)) {
|
||||
if (o == null) {
|
||||
continue;
|
||||
}
|
||||
|
|
@ -184,7 +184,7 @@ public class GrandExchangeTab extends ConsoleTab {
|
|||
JOptionPane.showMessageDialog(null, "Error! No data in DB yet. Press load.");
|
||||
return;
|
||||
}
|
||||
for (GrandExchangeOffer offer : OfferManager.Companion.getOFFER_MAPPING().values()) {
|
||||
for (GrandExchangeOffer offer : OfferManager.getOFFER_MAPPING().values()) {
|
||||
model.addElement(offer);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
46
Server/src/main/kotlin/rs09/game/ge/GrandExchange.kt
Normal file
46
Server/src/main/kotlin/rs09/game/ge/GrandExchange.kt
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
package rs09.game.ge
|
||||
|
||||
import core.game.world.callback.CallBack
|
||||
import rs09.game.system.SystemLogger
|
||||
import rs09.tools.secondsToTicks
|
||||
|
||||
object GrandExchange : CallBack {
|
||||
/**
|
||||
* Fallback safety check to make sure we don't start the GE twice under any circumstance
|
||||
*/
|
||||
var isRunning = false
|
||||
|
||||
/**
|
||||
* 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){
|
||||
if(isRunning) return
|
||||
|
||||
if(!local){
|
||||
TODO("Remote GE server stuff")
|
||||
}
|
||||
|
||||
SystemLogger.logGE("Initializing GE...")
|
||||
OfferManager.init()
|
||||
SystemLogger.logGE("GE Initialized.")
|
||||
|
||||
SystemLogger.logGE("Initializing GE Update Worker")
|
||||
|
||||
val t = Thread {
|
||||
Thread.currentThread().name = "GE Update Worker"
|
||||
while(true) {
|
||||
SystemLogger.logGE("Updating offers...")
|
||||
OfferManager.update()
|
||||
Thread.sleep(60_000) //sleep for 60 seconds
|
||||
}
|
||||
}.start()
|
||||
|
||||
isRunning = true
|
||||
}
|
||||
|
||||
override fun call(): Boolean {
|
||||
boot(true)
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
package rs09.game.ge
|
||||
|
||||
import api.ContentAPI
|
||||
import rs09.ServerConstants
|
||||
import core.cache.def.impl.ItemDefinition
|
||||
import core.game.content.eco.EcoStatus
|
||||
|
|
@ -23,524 +24,507 @@ import org.json.simple.JSONArray
|
|||
import org.json.simple.JSONObject
|
||||
import org.json.simple.parser.JSONParser
|
||||
import rs09.game.ai.AIPlayer
|
||||
import rs09.game.system.config.ItemConfigParser
|
||||
import java.io.File
|
||||
import java.io.FileReader
|
||||
import java.io.FileWriter
|
||||
import java.io.IOException
|
||||
import java.lang.Integer.max
|
||||
import java.lang.Integer.min
|
||||
import java.util.*
|
||||
import java.util.concurrent.locks.ReentrantLock
|
||||
import javax.script.ScriptEngineManager
|
||||
import kotlin.collections.ArrayList
|
||||
|
||||
class OfferManager : Pulse(), CallBack {
|
||||
object OfferManager {
|
||||
/**
|
||||
* How often in ticks should ge offers that hit the buying limit be reprocessed?
|
||||
* The update notification.
|
||||
*/
|
||||
private val RESET_BUYING_LIMIT_INTERVAL = 24000
|
||||
private const val UPDATE_NOTIFICATION = "One or more of your grand exchange offers have been updated."
|
||||
|
||||
/**
|
||||
* How often should the database be saved to disk?
|
||||
* The database path.
|
||||
*/
|
||||
private val SAVE_EVERY = ServerConstants.GE_AUTOSAVE_FREQUENCY
|
||||
private val DB_PATH = ServerConstants.GRAND_EXCHANGE_DATA_PATH + "offer_dispatch.json"
|
||||
|
||||
override fun call(): Boolean {
|
||||
init()
|
||||
delay = 1
|
||||
GameWorld.Pulser.submit(this)
|
||||
/**
|
||||
* Bot DB path
|
||||
*/
|
||||
private val BOT_DB_PATH = ServerConstants.GRAND_EXCHANGE_DATA_PATH + "bot_offers.json"
|
||||
|
||||
/**
|
||||
* The offset of the offer UIDs.
|
||||
*/
|
||||
private var offsetUID: Long = 1
|
||||
|
||||
/**
|
||||
* The mapping of all current offers. Stored in multiple maps.
|
||||
*
|
||||
* First map is offsetID, Offer
|
||||
* Second is itemID, offsetID, Offer
|
||||
* Final is playerID, offsetID, Offer
|
||||
*/
|
||||
@JvmStatic
|
||||
val OFFER_MAPPING: MutableMap<Long, GrandExchangeOffer> = HashMap()
|
||||
val OFFERS_BY_ITEMID: MutableMap<Int, MutableList<GrandExchangeOffer>> = HashMap()
|
||||
private val GE_OFFER_LOCK = ReentrantLock()
|
||||
|
||||
/**
|
||||
* Bot offers are sorted by itemID.
|
||||
* the second int shows the offer amount. Negative is buying positive selling.
|
||||
*/
|
||||
public val BOT_OFFERS: HashMap<Int, Int> = HashMap()
|
||||
|
||||
/**
|
||||
* If the database should be dumped.
|
||||
*/
|
||||
public var dumpDatabase = false
|
||||
|
||||
/**
|
||||
* Initializes the Grand Exchange.
|
||||
*/
|
||||
fun init() {
|
||||
GE_OFFER_LOCK.lock()
|
||||
val file = File(DB_PATH)
|
||||
|
||||
if(file.exists() && file.length() != 0L) {
|
||||
val parser = JSONParser()
|
||||
val reader: FileReader? = FileReader(DB_PATH)
|
||||
val saveFile = parser.parse(reader) as JSONObject
|
||||
|
||||
offsetUID = saveFile["offsetUID"].toString().toLong()
|
||||
|
||||
if (saveFile.containsKey("offers")) {
|
||||
val offers = saveFile["offers"] as JSONArray
|
||||
for (offer in offers) {
|
||||
val o = offer as JSONObject
|
||||
// Copy all the bot offers from the file
|
||||
if (o["playerUID"].toString().toInt() == 0) {
|
||||
addBotOffer(o["itemId"].toString().toInt(), o["amount"].toString().toInt() - o["completedAmount"].toString().toInt())
|
||||
}
|
||||
val no = GrandExchangeOffer()
|
||||
no.itemID = o["itemId"].toString().toInt()
|
||||
no.sell = o["sale"] as Boolean
|
||||
no.offeredValue = o["offeredValue"].toString().toInt()
|
||||
no.amount = o["amount"].toString().toInt()
|
||||
no.timeStamp = o["timeStamp"].toString().toLong()
|
||||
no.uid = o["uid"].toString().toLong()
|
||||
no.completedAmount = o["completedAmount"].toString().toInt()
|
||||
no.playerUID = o["playerUID"].toString().toInt()
|
||||
no.offerState = OfferState.values()[o["offerState"].toString().toInt()]
|
||||
no.totalCoinExchange = o["totalCoinExchange"].toString().toInt()
|
||||
val withdrawData = o["withdrawItems"] as JSONArray
|
||||
for ((index, data) in withdrawData.withIndex()) {
|
||||
val item = data as JSONObject
|
||||
val it = Item(item["id"].toString().toInt(), item["amount"].toString().toInt())
|
||||
no.withdraw[index] = it
|
||||
}
|
||||
addEntry(no)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(File(BOT_DB_PATH).exists()) {
|
||||
try {
|
||||
val botReader: FileReader? = FileReader(BOT_DB_PATH)
|
||||
val botSave = JSONParser().parse(botReader) as JSONObject
|
||||
if (botSave.containsKey("offers")) {
|
||||
val offers = botSave["offers"] as JSONArray
|
||||
for (offer in offers) {
|
||||
val o = offer as JSONObject
|
||||
addBotOffer(o["item"].toString().toInt(), o["qty"].toString().toInt())
|
||||
}
|
||||
}
|
||||
} catch (e: IOException) {
|
||||
SystemLogger.logWarn("Unable to load bot offers. Perhaps it doesn't exist?")
|
||||
}
|
||||
}
|
||||
GE_OFFER_LOCK.unlock()
|
||||
}
|
||||
|
||||
fun update(){
|
||||
for (offer in OFFER_MAPPING.values) {
|
||||
if (offer.isActive) {
|
||||
updateOffer(offer)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun buyFromBots(offer: GrandExchangeOffer) {
|
||||
if (BOT_OFFERS[offer.itemID] == null) {
|
||||
return
|
||||
}
|
||||
val botPrice = getRecommendedPrice(offer.itemID, true)
|
||||
if (offer.offeredValue < botPrice) {
|
||||
return
|
||||
}
|
||||
val amount = min(BOT_OFFERS[offer.itemID]!!, getBuylimitAmount(offer))
|
||||
val botOffer = GrandExchangeOffer()
|
||||
botOffer.sell = true
|
||||
botOffer.amount = amount
|
||||
botOffer.offerState = OfferState.REGISTERED
|
||||
botOffer.offeredValue = botPrice
|
||||
exchange(offer, botOffer)
|
||||
BOT_OFFERS[offer.itemID] = BOT_OFFERS[offer.itemID]!! - amount
|
||||
}
|
||||
|
||||
private fun buyFromBotsWithItem(itemID: Int) {
|
||||
if (OFFERS_BY_ITEMID[itemID] == null || BOT_OFFERS[itemID] == null) {
|
||||
return
|
||||
}
|
||||
for (trade in OFFERS_BY_ITEMID[itemID]!!) {
|
||||
if (!trade.sell) {
|
||||
buyFromBots(trade)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun addBotOffer(itemID: Int, qty: Int): Boolean {
|
||||
if (GrandExchangeDatabase.getDatabase()[itemID] == null) {
|
||||
SystemLogger.logWarn("Bot attempted to sell invalid item $itemID")
|
||||
return false
|
||||
}
|
||||
|
||||
if (BOT_OFFERS[itemID] == null) {
|
||||
BOT_OFFERS[itemID] = qty
|
||||
} else {
|
||||
BOT_OFFERS[itemID] = (qty + BOT_OFFERS[itemID]!!)
|
||||
}
|
||||
buyFromBotsWithItem(itemID)
|
||||
return true
|
||||
}
|
||||
|
||||
override fun pulse(): Boolean {
|
||||
// TODO: Update offers code
|
||||
if (GameWorld.ticks % RESET_BUYING_LIMIT_INTERVAL == 0) {
|
||||
BuyingLimitation.clear()
|
||||
for (offer in OFFER_MAPPING.values) {
|
||||
if (offer.isActive && offer.isLimitation) {
|
||||
updateOffer(offer)
|
||||
}
|
||||
}
|
||||
fun amtBotsSelling(itemID: Int): Int {
|
||||
if (BOT_OFFERS[itemID] == null) {
|
||||
return 0
|
||||
}
|
||||
|
||||
if (dumpDatabase && (GameWorld.ticks % SAVE_EVERY == 0)) {
|
||||
//save()
|
||||
dumpDatabase = false
|
||||
if (BOT_OFFERS[itemID]!! <= 0) {
|
||||
return 0
|
||||
}
|
||||
|
||||
return false
|
||||
return BOT_OFFERS[itemID]!!
|
||||
}
|
||||
|
||||
fun setIndex(offerID: Long, idx: Int) {
|
||||
if (!OFFER_MAPPING.containsKey(offerID)) {
|
||||
println("ERROR. GE Entry $offerID not found in database. Playerdata may be corrupted.")
|
||||
return
|
||||
}
|
||||
OFFER_MAPPING[offerID]!!.index = idx
|
||||
}
|
||||
|
||||
companion object {
|
||||
/**
|
||||
* The update notification.
|
||||
*/
|
||||
private const val UPDATE_NOTIFICATION = "One or more of your grand exchange offers have been updated."
|
||||
|
||||
/**
|
||||
* The database path.
|
||||
*/
|
||||
private val DB_PATH = ServerConstants.GRAND_EXCHANGE_DATA_PATH + "offer_dispatch.json"
|
||||
|
||||
/**
|
||||
* Bot DB path
|
||||
*/
|
||||
private val BOT_DB_PATH = ServerConstants.GRAND_EXCHANGE_DATA_PATH + "bot_offers.json"
|
||||
|
||||
/**
|
||||
* The offset of the offer UIDs.
|
||||
*/
|
||||
private var offsetUID: Long = 1
|
||||
|
||||
/**
|
||||
* The mapping of all current offers. Stored in multiple maps.
|
||||
*
|
||||
* First map is offsetID, Offer
|
||||
* Second is itemID, offsetID, Offer
|
||||
* Final is playerID, offsetID, Offer
|
||||
*/
|
||||
val OFFER_MAPPING: MutableMap<Long, GrandExchangeOffer> = HashMap()
|
||||
val OFFERS_BY_ITEMID: MutableMap<Int, MutableList<GrandExchangeOffer>> = HashMap()
|
||||
private val GE_OFFER_LOCK = ReentrantLock()
|
||||
|
||||
/**
|
||||
* Bot offers are sorted by itemID.
|
||||
* the second int shows the offer amount. Negative is buying positive selling.
|
||||
*/
|
||||
public val BOT_OFFERS: HashMap<Int, Int> = HashMap()
|
||||
|
||||
/**
|
||||
* If the database should be dumped.
|
||||
*/
|
||||
public var dumpDatabase = false
|
||||
|
||||
/**
|
||||
* Initializes the Grand Exchange.
|
||||
*/
|
||||
fun init() {
|
||||
GE_OFFER_LOCK.lock()
|
||||
val file = File(DB_PATH)
|
||||
|
||||
if(file.exists() && file.length() != 0L) {
|
||||
val parser = JSONParser()
|
||||
val reader: FileReader? = FileReader(DB_PATH)
|
||||
val saveFile = parser.parse(reader) as JSONObject
|
||||
|
||||
offsetUID = saveFile["offsetUID"].toString().toLong()
|
||||
|
||||
if (saveFile.containsKey("offers")) {
|
||||
val offers = saveFile["offers"] as JSONArray
|
||||
for (offer in offers) {
|
||||
val o = offer as JSONObject
|
||||
// Copy all the bot offers from the file
|
||||
if (o["playerUID"].toString().toInt() == 0) {
|
||||
addBotOffer(o["itemId"].toString().toInt(), o["amount"].toString().toInt() - o["completedAmount"].toString().toInt())
|
||||
}
|
||||
val no = GrandExchangeOffer()
|
||||
no.itemID = o["itemId"].toString().toInt()
|
||||
no.sell = o["sale"] as Boolean
|
||||
no.offeredValue = o["offeredValue"].toString().toInt()
|
||||
no.amount = o["amount"].toString().toInt()
|
||||
no.timeStamp = o["timeStamp"].toString().toLong()
|
||||
no.uid = o["uid"].toString().toLong()
|
||||
no.completedAmount = o["completedAmount"].toString().toInt()
|
||||
no.playerUID = o["playerUID"].toString().toInt()
|
||||
no.offerState = OfferState.values()[o["offerState"].toString().toInt()]
|
||||
no.totalCoinExchange = o["totalCoinExchange"].toString().toInt()
|
||||
val withdrawData = o["withdrawItems"] as JSONArray
|
||||
for ((index, data) in withdrawData.withIndex()) {
|
||||
val item = data as JSONObject
|
||||
val it = Item(item["id"].toString().toInt(), item["amount"].toString().toInt())
|
||||
no.withdraw[index] = it
|
||||
}
|
||||
addEntry(no)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(File(BOT_DB_PATH).exists()) {
|
||||
try {
|
||||
val botReader: FileReader? = FileReader(BOT_DB_PATH)
|
||||
val botSave = JSONParser().parse(botReader) as JSONObject
|
||||
if (botSave.containsKey("offers")) {
|
||||
val offers = botSave["offers"] as JSONArray
|
||||
for (offer in offers) {
|
||||
val o = offer as JSONObject
|
||||
addBotOffer(o["item"].toString().toInt(), o["qty"].toString().toInt())
|
||||
}
|
||||
}
|
||||
} catch (e: IOException) {
|
||||
SystemLogger.logWarn("Unable to load bot offers. Perhaps it doesn't exist?")
|
||||
}
|
||||
}
|
||||
fun removeEntry(offer: GrandExchangeOffer): Boolean{
|
||||
println("REMOVING ENTRY of ID " + offer.itemID)
|
||||
GE_OFFER_LOCK.lock()
|
||||
if (!OFFER_MAPPING.containsKey(offer.uid)){
|
||||
GE_OFFER_LOCK.unlock()
|
||||
return false
|
||||
}
|
||||
OFFER_MAPPING.remove(offer.uid)
|
||||
OFFERS_BY_ITEMID[offer.itemID]!!.remove(offer)
|
||||
GE_OFFER_LOCK.unlock()
|
||||
return true
|
||||
}
|
||||
|
||||
fun buyFromBots(offer: GrandExchangeOffer) {
|
||||
if (BOT_OFFERS[offer.itemID] == null) {
|
||||
return
|
||||
}
|
||||
val botPrice = BotPrices.getPrice(offer.itemID)
|
||||
if (offer.offeredValue < botPrice) {
|
||||
return
|
||||
}
|
||||
val amount = min(BOT_OFFERS[offer.itemID]!!, getBuylimitAmount(offer))
|
||||
val botOffer = GrandExchangeOffer()
|
||||
botOffer.sell = true
|
||||
botOffer.amount = amount
|
||||
botOffer.offerState = OfferState.REGISTERED
|
||||
botOffer.offeredValue = botPrice
|
||||
exchange(offer, botOffer)
|
||||
BOT_OFFERS[offer.itemID] = BOT_OFFERS[offer.itemID]!! - amount
|
||||
fun addEntry(offer: GrandExchangeOffer){
|
||||
GE_OFFER_LOCK.lock()
|
||||
OFFER_MAPPING[offer.uid] = offer
|
||||
if (!OFFERS_BY_ITEMID.containsKey(offer.itemID)) {
|
||||
OFFERS_BY_ITEMID[offer.itemID] = mutableListOf()
|
||||
}
|
||||
OFFERS_BY_ITEMID[offer.itemID]!!.add(offer)
|
||||
GE_OFFER_LOCK.unlock()
|
||||
}
|
||||
|
||||
private fun buyFromBotsWithItem(itemID: Int) {
|
||||
if (OFFERS_BY_ITEMID[itemID] == null || BOT_OFFERS[itemID] == null) {
|
||||
return
|
||||
}
|
||||
for (trade in OFFERS_BY_ITEMID[itemID]!!) {
|
||||
if (!trade.sell) {
|
||||
buyFromBots(trade)
|
||||
}
|
||||
fun getQuantitySoldForItem(item: Int): Int {
|
||||
var qty = 0
|
||||
val offs = getOffersForItem(item)
|
||||
for (o in offs) {
|
||||
if (o.sell) {
|
||||
qty += o.amountLeft
|
||||
}
|
||||
}
|
||||
qty += amtBotsSelling(item)
|
||||
return qty
|
||||
}
|
||||
|
||||
fun addBotOffer(itemID: Int, qty: Int): Boolean {
|
||||
if (GrandExchangeDatabase.getDatabase()[itemID] == null) {
|
||||
SystemLogger.logWarn("Bot attempted to sell invalid item $itemID")
|
||||
return false
|
||||
}
|
||||
@JvmStatic
|
||||
fun getOffersForItem(item: Int): MutableList<GrandExchangeOffer> {
|
||||
if (OFFERS_BY_ITEMID.containsKey(item)) {
|
||||
return OFFERS_BY_ITEMID[item]!!
|
||||
}
|
||||
return mutableListOf()
|
||||
}
|
||||
|
||||
if (BOT_OFFERS[itemID] == null) {
|
||||
BOT_OFFERS[itemID] = qty
|
||||
} else {
|
||||
BOT_OFFERS[itemID] = (qty + BOT_OFFERS[itemID]!!)
|
||||
}
|
||||
buyFromBotsWithItem(itemID)
|
||||
return true
|
||||
@JvmStatic
|
||||
fun save(){
|
||||
GE_OFFER_LOCK.lock()
|
||||
val root = JSONObject()
|
||||
val offers = JSONArray()
|
||||
|
||||
if(OFFER_MAPPING.isEmpty() && BOT_OFFERS.isEmpty()){
|
||||
return
|
||||
}
|
||||
|
||||
fun amtBotsSelling(itemID: Int): Int {
|
||||
if (BOT_OFFERS[itemID] == null) {
|
||||
return 0
|
||||
for(entry in OFFER_MAPPING){
|
||||
val offer = entry.value
|
||||
if (offer.offerState == OfferState.REMOVED || entry.value.playerUID == PlayerDetails.getDetails("2009scape").uid) {
|
||||
continue
|
||||
}
|
||||
if (BOT_OFFERS[itemID]!! <= 0) {
|
||||
return 0
|
||||
val o = JSONObject()
|
||||
o["uid"] = entry.key.toString()
|
||||
o["itemId"] = offer.itemID.toString()
|
||||
o["sale"] = offer.sell
|
||||
o["amount"] = offer.amount.toString()
|
||||
o["completedAmount"] = offer.completedAmount.toString()
|
||||
o["offeredValue"] = offer.offeredValue.toString()
|
||||
o["timeStamp"] = offer.timeStamp.toString()
|
||||
o["offerState"] = offer.offerState.ordinal.toString()
|
||||
o["totalCoinExchange"] = offer.totalCoinExchange.toString()
|
||||
o["playerUID"] = offer.playerUID.toString()
|
||||
val withdrawItems = JSONArray()
|
||||
for(item in offer.withdraw){
|
||||
item ?: continue
|
||||
val it = JSONObject()
|
||||
it["id"] = item.id.toString()
|
||||
it["amount"] = item.amount.toString()
|
||||
withdrawItems.add(it)
|
||||
}
|
||||
return BOT_OFFERS[itemID]!!
|
||||
o["withdrawItems"] = withdrawItems
|
||||
offers.add(o)
|
||||
}
|
||||
root["offsetUID"] = offsetUID.toString()
|
||||
root["offers"] = offers
|
||||
|
||||
fun setIndex(offerID: Long, idx: Int) {
|
||||
if (!OFFER_MAPPING.containsKey(offerID)) {
|
||||
println("ERROR. GE Entry $offerID not found in database. Playerdata may be corrupted.")
|
||||
return
|
||||
}
|
||||
OFFER_MAPPING[offerID]!!.index = idx
|
||||
val manager = ScriptEngineManager()
|
||||
val scriptEngine = manager.getEngineByName("JavaScript")
|
||||
scriptEngine.put("jsonString", root.toJSONString())
|
||||
scriptEngine.eval("result = JSON.stringify(JSON.parse(jsonString), null, 2)")
|
||||
val prettyPrintedJson = scriptEngine["result"] as String
|
||||
|
||||
val botRoot = JSONObject()
|
||||
val botOffers = JSONArray()
|
||||
|
||||
for ((item, qty) in BOT_OFFERS) {
|
||||
val o = JSONObject()
|
||||
o["item"] = item
|
||||
o["qty"] = qty
|
||||
botOffers.add(o)
|
||||
}
|
||||
botRoot["offers"] = botOffers
|
||||
|
||||
fun removeEntry(offer: GrandExchangeOffer): Boolean{
|
||||
println("REMOVING ENTRY of ID " + offer.itemID)
|
||||
GE_OFFER_LOCK.lock()
|
||||
if (!OFFER_MAPPING.containsKey(offer.uid)){
|
||||
GE_OFFER_LOCK.unlock()
|
||||
return false
|
||||
scriptEngine.put("jsonString", botRoot.toJSONString())
|
||||
scriptEngine.eval("result = JSON.stringify(JSON.parse(jsonString), null, 2)")
|
||||
val botJson = scriptEngine["result"] as String
|
||||
|
||||
|
||||
try {
|
||||
FileWriter(DB_PATH).use { file ->
|
||||
file.write(prettyPrintedJson)
|
||||
file.flush()
|
||||
file.close()
|
||||
}
|
||||
OFFER_MAPPING.remove(offer.uid)
|
||||
OFFERS_BY_ITEMID[offer.itemID]!!.remove(offer)
|
||||
GE_OFFER_LOCK.unlock()
|
||||
return true
|
||||
FileWriter(BOT_DB_PATH).use { file ->
|
||||
file.write(botJson)
|
||||
file.flush()
|
||||
file.close()
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
GE_OFFER_LOCK.unlock()
|
||||
}
|
||||
|
||||
fun addEntry(offer: GrandExchangeOffer){
|
||||
GE_OFFER_LOCK.lock()
|
||||
OFFER_MAPPING[offer.uid] = offer
|
||||
if (!OFFERS_BY_ITEMID.containsKey(offer.itemID)) {
|
||||
OFFERS_BY_ITEMID[offer.itemID] = mutableListOf()
|
||||
}
|
||||
OFFERS_BY_ITEMID[offer.itemID]!!.add(offer)
|
||||
GE_OFFER_LOCK.unlock()
|
||||
/**
|
||||
* Dispatches an offer.
|
||||
* @param player The player.
|
||||
* @param offer The grand exchange offer.
|
||||
* @return `True` if successful.
|
||||
*/
|
||||
@JvmStatic
|
||||
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
|
||||
}
|
||||
|
||||
fun getQuantitySoldForItem(item: Int): Int {
|
||||
var qty = 0
|
||||
val offs = getOffersForItem(item)
|
||||
for (o in offs) {
|
||||
if (o.sell) {
|
||||
qty += o.amountLeft
|
||||
}
|
||||
}
|
||||
qty += amtBotsSelling(item)
|
||||
return qty
|
||||
if (offer.offeredValue < 1) {
|
||||
player.packetDispatch.sendMessage("You must choose the price you wish to buy for!")
|
||||
println("pricethng")
|
||||
return false
|
||||
}
|
||||
|
||||
fun getOffersForItem(item: Int): MutableList<GrandExchangeOffer> {
|
||||
if (OFFERS_BY_ITEMID.containsKey(item)) {
|
||||
return OFFERS_BY_ITEMID[item]!!
|
||||
}
|
||||
return mutableListOf()
|
||||
if (offer.offerState != OfferState.PENDING || offer.uid != 0L) {
|
||||
println("pendingthing")
|
||||
return false
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun save(){
|
||||
GE_OFFER_LOCK.lock()
|
||||
val root = JSONObject()
|
||||
val offers = JSONArray()
|
||||
|
||||
if(OFFER_MAPPING.isEmpty() && BOT_OFFERS.isEmpty()){
|
||||
return
|
||||
}
|
||||
|
||||
for(entry in OFFER_MAPPING){
|
||||
val offer = entry.value
|
||||
if (offer.offerState == OfferState.REMOVED || entry.value.playerUID == PlayerDetails.getDetails("2009scape").uid) {
|
||||
continue
|
||||
}
|
||||
val o = JSONObject()
|
||||
o["uid"] = entry.key.toString()
|
||||
o["itemId"] = offer.itemID.toString()
|
||||
o["sale"] = offer.sell
|
||||
o["amount"] = offer.amount.toString()
|
||||
o["completedAmount"] = offer.completedAmount.toString()
|
||||
o["offeredValue"] = offer.offeredValue.toString()
|
||||
o["timeStamp"] = offer.timeStamp.toString()
|
||||
o["offerState"] = offer.offerState.ordinal.toString()
|
||||
o["totalCoinExchange"] = offer.totalCoinExchange.toString()
|
||||
o["playerUID"] = offer.playerUID.toString()
|
||||
val withdrawItems = JSONArray()
|
||||
for(item in offer.withdraw){
|
||||
item ?: continue
|
||||
val it = JSONObject()
|
||||
it["id"] = item.id.toString()
|
||||
it["amount"] = item.amount.toString()
|
||||
withdrawItems.add(it)
|
||||
}
|
||||
o["withdrawItems"] = withdrawItems
|
||||
offers.add(o)
|
||||
}
|
||||
root["offsetUID"] = offsetUID.toString()
|
||||
root["offers"] = offers
|
||||
|
||||
val manager = ScriptEngineManager()
|
||||
val scriptEngine = manager.getEngineByName("JavaScript")
|
||||
scriptEngine.put("jsonString", root.toJSONString())
|
||||
scriptEngine.eval("result = JSON.stringify(JSON.parse(jsonString), null, 2)")
|
||||
val prettyPrintedJson = scriptEngine["result"] as String
|
||||
|
||||
val botRoot = JSONObject()
|
||||
val botOffers = JSONArray()
|
||||
|
||||
for ((item, qty) in BOT_OFFERS) {
|
||||
val o = JSONObject()
|
||||
o["item"] = item
|
||||
o["qty"] = qty
|
||||
botOffers.add(o)
|
||||
}
|
||||
botRoot["offers"] = botOffers
|
||||
|
||||
scriptEngine.put("jsonString", botRoot.toJSONString())
|
||||
scriptEngine.eval("result = JSON.stringify(JSON.parse(jsonString), null, 2)")
|
||||
val botJson = scriptEngine["result"] as String
|
||||
|
||||
|
||||
try {
|
||||
FileWriter(DB_PATH).use { file ->
|
||||
file.write(prettyPrintedJson)
|
||||
file.flush()
|
||||
file.close()
|
||||
}
|
||||
FileWriter(BOT_DB_PATH).use { file ->
|
||||
file.write(botJson)
|
||||
file.flush()
|
||||
file.close()
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
GE_OFFER_LOCK.unlock()
|
||||
if (player.isArtificial) {
|
||||
offer.playerUID = PlayerDetails.getDetails("2009scape").uid
|
||||
// Repository.sendNews("2009scape wants " + offer.amount + " " + ItemDefinition.forId(offer.itemID).name.toLowerCase() + " for " + offer.offeredValue + "each.")
|
||||
} else {
|
||||
offer.playerUID = player.details.uid
|
||||
}
|
||||
|
||||
/**
|
||||
* Dispatches an offer.
|
||||
* @param player The player.
|
||||
* @param offer The grand exchange offer.
|
||||
* @return `True` if successful.
|
||||
*/
|
||||
@JvmStatic
|
||||
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) {
|
||||
offer.playerUID = PlayerDetails.getDetails("2009scape").uid
|
||||
// Repository.sendNews("2009scape wants " + offer.amount + " " + ItemDefinition.forId(offer.itemID).name.toLowerCase() + " for " + offer.offeredValue + "each.")
|
||||
} else {
|
||||
offer.playerUID = player.details.uid
|
||||
}
|
||||
offer.uid = nextUID()
|
||||
offer.offerState = OfferState.REGISTERED
|
||||
addEntry(offer)
|
||||
offer.timeStamp = System.currentTimeMillis()
|
||||
player.playerGrandExchange.update(offer)
|
||||
if (offer.sell) {
|
||||
Repository.sendNews(player.username + " just offered " + offer.amount + " " + ItemDefinition.forId(offer.itemID).name.toLowerCase() + " on the GE.")
|
||||
}
|
||||
if(player !is AIPlayer) {
|
||||
SystemLogger.logTrade("[GE] ${player.username} ${if (offer.sell) "listed for sale" else "listed buy offer for"} ${offer.amount} ${ItemDefinition.forId(offer.itemID).name.toLowerCase()}")
|
||||
}
|
||||
dumpDatabase = true
|
||||
return true
|
||||
offer.uid = nextUID()
|
||||
offer.offerState = OfferState.REGISTERED
|
||||
addEntry(offer)
|
||||
offer.timeStamp = System.currentTimeMillis()
|
||||
player.playerGrandExchange.update(offer)
|
||||
if (offer.sell) {
|
||||
Repository.sendNews(player.username + " just offered " + offer.amount + " " + ItemDefinition.forId(offer.itemID).name.toLowerCase() + " on the GE.")
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the offer.
|
||||
* @param offer The G.E. offer to update.
|
||||
*/
|
||||
@JvmStatic
|
||||
fun updateOffer(offer: GrandExchangeOffer) {
|
||||
if (!offer.isActive) {
|
||||
return
|
||||
}
|
||||
GE_OFFER_LOCK.lock()
|
||||
for (o in OFFERS_BY_ITEMID[offer.itemID]!!) {
|
||||
if (o.sell != offer.sell && o.isActive) {
|
||||
exchange(offer, o)
|
||||
if (offer.offerState == OfferState.COMPLETED) {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
buyFromBots(offer)
|
||||
GE_OFFER_LOCK.unlock()
|
||||
if(player !is AIPlayer) {
|
||||
SystemLogger.logTrade("[GE] ${player.username} ${if (offer.sell) "listed for sale" else "listed buy offer for"} ${offer.amount} ${ItemDefinition.forId(offer.itemID).name.toLowerCase()}")
|
||||
}
|
||||
dumpDatabase = true
|
||||
return true
|
||||
}
|
||||
|
||||
private fun getBuylimitAmount(offer: GrandExchangeOffer): Int {
|
||||
var left = offer.amountLeft
|
||||
if (!offer.sell && left > 0) {
|
||||
val maximum = BuyingLimitation.getMaximumBuy(offer.itemID, offer.playerUID)
|
||||
if (left >= maximum) {
|
||||
left = maximum
|
||||
offer.isLimitation = true
|
||||
}
|
||||
}
|
||||
return left
|
||||
/**
|
||||
* Updates the offer.
|
||||
* @param offer The G.E. offer to update.
|
||||
*/
|
||||
@JvmStatic
|
||||
fun updateOffer(offer: GrandExchangeOffer) {
|
||||
if (!offer.isActive) {
|
||||
return
|
||||
}
|
||||
|
||||
/**
|
||||
* Exchanges between 2 offers.
|
||||
* @param offer The grand exchange offer to update.
|
||||
* @param o The other offer to exchange with.
|
||||
*/
|
||||
private fun exchange(offer: GrandExchangeOffer, o: GrandExchangeOffer) {
|
||||
if (o.sell == offer.sell) {
|
||||
return
|
||||
}
|
||||
if (offer.sell && o.offeredValue < offer.offeredValue || !offer.sell && o.offeredValue > offer.offeredValue) {
|
||||
return
|
||||
}
|
||||
var amount = min(getBuylimitAmount(offer), getBuylimitAmount(o))
|
||||
if (amount < 1) {
|
||||
return
|
||||
}
|
||||
var coinDifference = if (offer.sell) o.offeredValue - offer.offeredValue else offer.offeredValue - o.offeredValue
|
||||
if (coinDifference < 0) {
|
||||
return
|
||||
}
|
||||
if (EconomyManagement.getEcoState() == EcoStatus.DRAINING) {
|
||||
coinDifference *= (1.0 - EconomyManagement.getModificationRate()).toInt()
|
||||
}
|
||||
offer.completedAmount = offer.completedAmount + amount
|
||||
o.completedAmount = o.completedAmount + amount
|
||||
offer.offerState = if (offer.amountLeft < 1) OfferState.COMPLETED else OfferState.UPDATED
|
||||
o.offerState = if (o.amountLeft < 1) OfferState.COMPLETED else OfferState.UPDATED
|
||||
if (offer.sell) {
|
||||
if (offer.amountLeft < 1 && offer.player != null) {
|
||||
offer.player!!.audioManager.send(Audio(4042, 1, 1))
|
||||
}
|
||||
addWithdraw(offer,995, amount * offer.offeredValue)
|
||||
addWithdraw(o, o.itemID, amount)
|
||||
BuyingLimitation.updateBoughtAmount(o.itemID, o.playerUID, amount)
|
||||
} else {
|
||||
if (o.amountLeft < 1 && o.player != null) {
|
||||
o.player!!.audioManager.send(Audio(4042, 1, 1))
|
||||
}
|
||||
addWithdraw(offer, offer.itemID, amount)
|
||||
addWithdraw(o, 995, amount * o.offeredValue)
|
||||
BuyingLimitation.updateBoughtAmount(offer.itemID, offer.playerUID, amount)
|
||||
}
|
||||
if (coinDifference > 0) {
|
||||
if (offer.sell) {
|
||||
addWithdraw(o, 995, coinDifference * amount)
|
||||
} else {
|
||||
addWithdraw(offer, 995, coinDifference * amount)
|
||||
}
|
||||
}
|
||||
GrandExchangeDatabase.getDatabase()[o.itemID]?.influenceValue(o.offeredValue)
|
||||
offer.player?.packetDispatch?.sendMessage(UPDATE_NOTIFICATION)
|
||||
o.player?.packetDispatch?.sendMessage(UPDATE_NOTIFICATION)
|
||||
o.player?.playerGrandExchange?.update(o)
|
||||
offer.player?.playerGrandExchange?.update(offer)
|
||||
dumpDatabase = true
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a new item to withdraw.
|
||||
* @param itemId The item id.
|
||||
* @param amount The amount to add.
|
||||
* @param abort If the item is added due to abort.
|
||||
*/
|
||||
fun addWithdraw(offer: GrandExchangeOffer, itemId: Int, amount: Int, abort: Boolean = false) {
|
||||
if (!abort) {
|
||||
if (offer.sell) {
|
||||
if (itemId == 995) {
|
||||
offer.totalCoinExchange += amount
|
||||
}
|
||||
} else {
|
||||
if (itemId == 995) {
|
||||
offer.totalCoinExchange -= amount
|
||||
} else {
|
||||
offer.totalCoinExchange += offer.offeredValue * amount
|
||||
}
|
||||
}
|
||||
}
|
||||
for (i in offer.withdraw.indices) {
|
||||
if (offer.withdraw[i] == null) {
|
||||
offer.withdraw[i] = Item(itemId, amount)
|
||||
break
|
||||
}
|
||||
if (offer.withdraw[i]!!.id == itemId) {
|
||||
offer.withdraw[i]!!.amount = offer.withdraw[i]!!.amount + amount
|
||||
GE_OFFER_LOCK.lock()
|
||||
for (o in OFFERS_BY_ITEMID[offer.itemID]!!) {
|
||||
if (o.sell != offer.sell && o.isActive) {
|
||||
exchange(offer, o)
|
||||
if (offer.offerState == OfferState.COMPLETED) {
|
||||
break
|
||||
}
|
||||
}
|
||||
if (offer.player != null) {
|
||||
PacketRepository.send(
|
||||
ContainerPacket::class.java,
|
||||
ContainerContext(offer.player, -1, -1757, 523 + offer.index, offer.withdraw, false)
|
||||
)
|
||||
}
|
||||
buyFromBots(offer)
|
||||
GE_OFFER_LOCK.unlock()
|
||||
}
|
||||
|
||||
private fun getBuylimitAmount(offer: GrandExchangeOffer): Int {
|
||||
var left = offer.amountLeft
|
||||
if (!offer.sell && left > 0) {
|
||||
val maximum = BuyingLimitation.getMaximumBuy(offer.itemID, offer.playerUID)
|
||||
if (left >= maximum) {
|
||||
left = maximum
|
||||
offer.isLimitation = true
|
||||
}
|
||||
}
|
||||
return left
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the next UID.
|
||||
* @return The UID.
|
||||
*/
|
||||
private fun nextUID(): Long {
|
||||
val id = offsetUID++
|
||||
return if (id == 0L) {
|
||||
nextUID()
|
||||
} else id
|
||||
/**
|
||||
* Exchanges between 2 offers.
|
||||
* @param offer The grand exchange offer to update.
|
||||
* @param o The other offer to exchange with.
|
||||
*/
|
||||
private fun exchange(offer: GrandExchangeOffer, o: GrandExchangeOffer) {
|
||||
if (o.sell == offer.sell) {
|
||||
return
|
||||
}
|
||||
if (offer.sell && o.offeredValue < offer.offeredValue || !offer.sell && o.offeredValue > offer.offeredValue) {
|
||||
return
|
||||
}
|
||||
var amount = min(getBuylimitAmount(offer), getBuylimitAmount(o))
|
||||
if (amount < 1) {
|
||||
return
|
||||
}
|
||||
var coinDifference = if (offer.sell) o.offeredValue - offer.offeredValue else offer.offeredValue - o.offeredValue
|
||||
if (coinDifference < 0) {
|
||||
return
|
||||
}
|
||||
if (EconomyManagement.getEcoState() == EcoStatus.DRAINING) {
|
||||
coinDifference *= (1.0 - EconomyManagement.getModificationRate()).toInt()
|
||||
}
|
||||
offer.completedAmount = offer.completedAmount + amount
|
||||
o.completedAmount = o.completedAmount + amount
|
||||
offer.offerState = if (offer.amountLeft < 1) OfferState.COMPLETED else OfferState.UPDATED
|
||||
o.offerState = if (o.amountLeft < 1) OfferState.COMPLETED else OfferState.UPDATED
|
||||
if (offer.sell) {
|
||||
if (offer.amountLeft < 1 && offer.player != null) {
|
||||
offer.player!!.audioManager.send(Audio(4042, 1, 1))
|
||||
}
|
||||
addWithdraw(offer,995, amount * offer.offeredValue)
|
||||
addWithdraw(o, o.itemID, amount)
|
||||
BuyingLimitation.updateBoughtAmount(o.itemID, o.playerUID, amount)
|
||||
} else {
|
||||
if (o.amountLeft < 1 && o.player != null) {
|
||||
o.player!!.audioManager.send(Audio(4042, 1, 1))
|
||||
}
|
||||
addWithdraw(offer, offer.itemID, amount)
|
||||
addWithdraw(o, 995, amount * o.offeredValue)
|
||||
BuyingLimitation.updateBoughtAmount(offer.itemID, offer.playerUID, amount)
|
||||
}
|
||||
if (coinDifference > 0) {
|
||||
if (offer.sell) {
|
||||
addWithdraw(o, 995, coinDifference * amount)
|
||||
} else {
|
||||
addWithdraw(offer, 995, coinDifference * amount)
|
||||
}
|
||||
}
|
||||
GrandExchangeDatabase.getDatabase()[o.itemID]?.influenceValue(o.offeredValue)
|
||||
offer.player?.packetDispatch?.sendMessage(UPDATE_NOTIFICATION)
|
||||
o.player?.packetDispatch?.sendMessage(UPDATE_NOTIFICATION)
|
||||
o.player?.playerGrandExchange?.update(o)
|
||||
offer.player?.playerGrandExchange?.update(offer)
|
||||
dumpDatabase = true
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a new item to withdraw.
|
||||
* @param itemId The item id.
|
||||
* @param amount The amount to add.
|
||||
* @param abort If the item is added due to abort.
|
||||
*/
|
||||
fun addWithdraw(offer: GrandExchangeOffer, itemId: Int, amount: Int, abort: Boolean = false) {
|
||||
if (!abort) {
|
||||
if (offer.sell) {
|
||||
if (itemId == 995) {
|
||||
offer.totalCoinExchange += amount
|
||||
}
|
||||
} else {
|
||||
if (itemId == 995) {
|
||||
offer.totalCoinExchange -= amount
|
||||
} else {
|
||||
offer.totalCoinExchange += offer.offeredValue * amount
|
||||
}
|
||||
}
|
||||
}
|
||||
for (i in offer.withdraw.indices) {
|
||||
if (offer.withdraw[i] == null) {
|
||||
offer.withdraw[i] = Item(itemId, amount)
|
||||
break
|
||||
}
|
||||
if (offer.withdraw[i]!!.id == itemId) {
|
||||
offer.withdraw[i]!!.amount = offer.withdraw[i]!!.amount + amount
|
||||
break
|
||||
}
|
||||
}
|
||||
if (offer.player != null) {
|
||||
PacketRepository.send(
|
||||
ContainerPacket::class.java,
|
||||
ContainerContext(offer.player, -1, -1757, 523 + offer.index, offer.withdraw, false)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the next UID.
|
||||
* @return The UID.
|
||||
*/
|
||||
private fun nextUID(): Long {
|
||||
val id = offsetUID++
|
||||
return if (id == 0L) {
|
||||
nextUID()
|
||||
} else id
|
||||
}
|
||||
|
||||
private fun getItemDefPrice(itemID: Int): Int {
|
||||
return max(ContentAPI.itemDefinition(itemID).getConfiguration(ItemConfigParser.GE_PRICE) ?: 0, ContentAPI.itemDefinition(itemID).value)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun getRecommendedPrice(itemID: Int, from_bot: Boolean = false): Int {
|
||||
val base = max(GrandExchangeDatabase.getDatabase()[itemID]?.value ?: 0, getItemDefPrice(itemID))
|
||||
return if(from_bot) (base + (base * 0.1).toInt())
|
||||
else base
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
package rs09.game.ge
|
||||
|
||||
import api.ContentAPI
|
||||
import core.cache.def.impl.ItemDefinition
|
||||
import core.game.component.CloseEvent
|
||||
import core.game.component.Component
|
||||
|
|
@ -27,8 +28,6 @@ import core.net.packet.out.GrandExchangePacket
|
|||
import org.json.simple.JSONArray
|
||||
import org.json.simple.JSONObject
|
||||
import org.rs09.consts.Components
|
||||
import rs09.game.ge.OfferManager.Companion.dispatch
|
||||
import rs09.game.ge.OfferManager.Companion.updateOffer
|
||||
import rs09.game.system.SystemLogger
|
||||
import java.text.DecimalFormat
|
||||
import java.text.NumberFormat
|
||||
|
|
@ -319,13 +318,13 @@ class PlayerGrandExchange(private val player: Player) {
|
|||
temporaryOffer!!.itemID = itemId
|
||||
temporaryOffer!!.sell = false
|
||||
var itemDb = GrandExchangeDatabase.getDatabase()[itemId]
|
||||
if (itemDb == null) {
|
||||
if (itemDb == null || !ContentAPI.itemDefinition(itemId).isTradeable) {
|
||||
player.packetDispatch.sendMessage("This item has been blacklisted from the Grand Exchange.")
|
||||
return
|
||||
}
|
||||
temporaryOffer!!.player = player
|
||||
temporaryOffer!!.amount = 1
|
||||
temporaryOffer!!.offeredValue = itemDb.value
|
||||
temporaryOffer!!.offeredValue = OfferManager.getRecommendedPrice(itemId)
|
||||
temporaryOffer!!.index = openedIndex
|
||||
sendConfiguration(temporaryOffer, false)
|
||||
}
|
||||
|
|
@ -350,7 +349,7 @@ class PlayerGrandExchange(private val player: Player) {
|
|||
id = item.noteChange
|
||||
}
|
||||
var itemDb = GrandExchangeDatabase.getDatabase()[id]
|
||||
if (itemDb == null) {
|
||||
if (itemDb == null || !item.definition.isTradeable) {
|
||||
player.packetDispatch.sendMessage("This item can't be sold on the Grand Exchange.")
|
||||
return
|
||||
}
|
||||
|
|
@ -358,7 +357,7 @@ class PlayerGrandExchange(private val player: Player) {
|
|||
temporaryOffer!!.itemID = id
|
||||
temporaryOffer!!.sell = true
|
||||
temporaryOffer!!.player = player
|
||||
temporaryOffer!!.offeredValue = itemDb.value
|
||||
temporaryOffer!!.offeredValue = OfferManager.getRecommendedPrice(id)
|
||||
temporaryOffer!!.amount = item.amount
|
||||
temporaryOffer!!.index = openedIndex
|
||||
sendConfiguration(temporaryOffer, true)
|
||||
|
|
@ -425,9 +424,9 @@ class PlayerGrandExchange(private val player: Player) {
|
|||
return
|
||||
}
|
||||
}
|
||||
if (dispatch(player, temporaryOffer!!)) {
|
||||
if (OfferManager.dispatch(player, temporaryOffer!!)) {
|
||||
offers[openedIndex] = temporaryOffer
|
||||
updateOffer(temporaryOffer!!)
|
||||
OfferManager.updateOffer(temporaryOffer!!)
|
||||
}
|
||||
} else {
|
||||
val total: Int = temporaryOffer!!.amount * temporaryOffer!!.offeredValue
|
||||
|
|
@ -436,9 +435,9 @@ class PlayerGrandExchange(private val player: Player) {
|
|||
player.packetDispatch.sendMessage("You do not have enough coins to cover the offer.")
|
||||
return
|
||||
}
|
||||
if (dispatch(player, temporaryOffer!!) && player.inventory.remove(Item(995, total))) {
|
||||
if (OfferManager.dispatch(player, temporaryOffer!!) && player.inventory.remove(Item(995, total))) {
|
||||
offers[openedIndex] = temporaryOffer
|
||||
updateOffer(temporaryOffer!!)
|
||||
OfferManager.updateOffer(temporaryOffer!!)
|
||||
}
|
||||
}
|
||||
player.monitor.log(
|
||||
|
|
@ -546,7 +545,7 @@ class PlayerGrandExchange(private val player: Player) {
|
|||
val botSales = OfferManager.amtBotsSelling(offer.itemID)
|
||||
if (botSales > 0) {
|
||||
foundAmounts.add(botSales)
|
||||
foundOffers.add(BotPrices.getPrice(offer.itemID))
|
||||
foundOffers.add(OfferManager.getRecommendedPrice(offer.itemID, true))
|
||||
count++
|
||||
}
|
||||
if (foundOffers.isNotEmpty()) {
|
||||
|
|
@ -564,16 +563,17 @@ class PlayerGrandExchange(private val player: Player) {
|
|||
player.packetDispatch.sendString(if (offer != null && !offer.sell) text.toString() else examine, 105, 142)
|
||||
var lowPrice = 0
|
||||
var highPrice = 0
|
||||
val recommendedPrice = OfferManager.getRecommendedPrice(entry?.itemId ?: 0)
|
||||
if (entry != null) {
|
||||
lowPrice = (entry.value * 0.95).toInt()
|
||||
highPrice = (entry.value * 1.05).toInt()
|
||||
lowPrice = (recommendedPrice * 0.95).toInt()
|
||||
highPrice = (recommendedPrice * 1.05).toInt()
|
||||
}
|
||||
player.varpManager.get(1109).setVarbit(0, offer?.itemID ?: -1).send(player)
|
||||
player.varpManager.get(1110).setVarbit(0, offer?.amount ?: 0).send(player)
|
||||
player.varpManager.get(1111).setVarbit(0, offer?.offeredValue ?: 0).send(player)
|
||||
player.varpManager.get(1112).setVarbit(0, openedIndex).send(player)
|
||||
player.varpManager.get(1113).setVarbit(0, if (sell) 1 else 0).send(player)
|
||||
player.varpManager.get(1114).setVarbit(0, entry?.value ?: 0).send(player)
|
||||
player.varpManager.get(1114).setVarbit(0, recommendedPrice).send(player)
|
||||
player.varpManager.get(1115).setVarbit(0, lowPrice).send(player)
|
||||
player.varpManager.get(1116).setVarbit(0, highPrice).send(player)
|
||||
if (offer != null) {
|
||||
|
|
|
|||
|
|
@ -69,6 +69,11 @@ object SystemLogger {
|
|||
if(message.isNotBlank()) t.println("${getTime()}: ${TextColors.gray("[RAND] $message")}")
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun logGE(message: String){
|
||||
if(message.isNotBlank()) t.println("${getTime()}: ${TextColors.gray("[ GE] $message")}")
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun logTrade(message: String){
|
||||
if(message.isNotBlank()){
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package rs09.game.world.callback
|
|||
import core.game.node.entity.skill.hunter.ImpetuousImpulses
|
||||
import core.game.world.callback.CallBack
|
||||
import core.game.world.map.zone.ZoneBuilder
|
||||
import rs09.game.ge.GrandExchange
|
||||
import rs09.game.ge.OfferManager
|
||||
import rs09.game.system.SystemLogger
|
||||
import java.util.*
|
||||
|
|
@ -16,7 +17,7 @@ object CallbackHub {
|
|||
|
||||
fun call(): Boolean {
|
||||
calls.add(ZoneBuilder())
|
||||
calls.add(OfferManager())
|
||||
calls.add(GrandExchange)
|
||||
calls.add(ImpetuousImpulses())
|
||||
for (call in calls) {
|
||||
if (!call.call()) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue