diff --git a/Server/src/main/java/core/game/ge/GEGuidePrice.java b/Server/src/main/java/core/game/ge/GEGuidePrice.java
index 7500c90e8..b077d94ce 100644
--- a/Server/src/main/java/core/game/ge/GEGuidePrice.java
+++ b/Server/src/main/java/core/game/ge/GEGuidePrice.java
@@ -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]);
}
}
}
diff --git a/Server/src/main/java/core/game/interaction/inter/GrandExchangeInterface.java b/Server/src/main/java/core/game/interaction/inter/GrandExchangeInterface.java
index 87ab55a33..e5714afd8 100644
--- a/Server/src/main/java/core/game/interaction/inter/GrandExchangeInterface.java
+++ b/Server/src/main/java/core/game/interaction/inter/GrandExchangeInterface.java
@@ -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;
diff --git a/Server/src/main/java/core/game/node/entity/npc/drop/NPCDropTables.java b/Server/src/main/java/core/game/node/entity/npc/drop/NPCDropTables.java
index e50428254..cf651066b 100644
--- a/Server/src/main/java/core/game/node/entity/npc/drop/NPCDropTables.java
+++ b/Server/src/main/java/core/game/node/entity/npc/drop/NPCDropTables.java
@@ -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() ? "
" : "") + "You received: " + item.getAmount() + " " + item.getName());
for (Player p : looters) {
diff --git a/Server/src/main/java/core/game/node/item/Item.java b/Server/src/main/java/core/game/node/item/Item.java
index 14c5845d9..39d771ad1 100644
--- a/Server/src/main/java/core/game/node/item/Item.java
+++ b/Server/src/main/java/core/game/node/item/Item.java
@@ -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();
}
diff --git a/Server/src/main/java/core/gui/tab/GrandExchangeTab.java b/Server/src/main/java/core/gui/tab/GrandExchangeTab.java
index 2d4d10c41..c6fe68e39 100644
--- a/Server/src/main/java/core/gui/tab/GrandExchangeTab.java
+++ b/Server/src/main/java/core/gui/tab/GrandExchangeTab.java
@@ -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);
}
}
diff --git a/Server/src/main/kotlin/rs09/game/ge/GrandExchange.kt b/Server/src/main/kotlin/rs09/game/ge/GrandExchange.kt
new file mode 100644
index 000000000..6933fc243
--- /dev/null
+++ b/Server/src/main/kotlin/rs09/game/ge/GrandExchange.kt
@@ -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
+ }
+}
\ No newline at end of file
diff --git a/Server/src/main/kotlin/rs09/game/ge/OfferManager.kt b/Server/src/main/kotlin/rs09/game/ge/OfferManager.kt
index 372b4d04e..9042c7a7a 100644
--- a/Server/src/main/kotlin/rs09/game/ge/OfferManager.kt
+++ b/Server/src/main/kotlin/rs09/game/ge/OfferManager.kt
@@ -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 = HashMap()
+ val OFFERS_BY_ITEMID: MutableMap> = 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 = 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 = HashMap()
- val OFFERS_BY_ITEMID: MutableMap> = 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 = 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 {
+ 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 {
- 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
+ }
}
diff --git a/Server/src/main/kotlin/rs09/game/ge/PlayerGrandExchange.kt b/Server/src/main/kotlin/rs09/game/ge/PlayerGrandExchange.kt
index ad1021b89..867cf6cdc 100644
--- a/Server/src/main/kotlin/rs09/game/ge/PlayerGrandExchange.kt
+++ b/Server/src/main/kotlin/rs09/game/ge/PlayerGrandExchange.kt
@@ -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) {
diff --git a/Server/src/main/kotlin/rs09/game/system/SystemLogger.kt b/Server/src/main/kotlin/rs09/game/system/SystemLogger.kt
index 83d5e372e..61755329d 100644
--- a/Server/src/main/kotlin/rs09/game/system/SystemLogger.kt
+++ b/Server/src/main/kotlin/rs09/game/system/SystemLogger.kt
@@ -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()){
diff --git a/Server/src/main/kotlin/rs09/game/world/callback/CallbackHub.kt b/Server/src/main/kotlin/rs09/game/world/callback/CallbackHub.kt
index cf26afe74..c04369b71 100644
--- a/Server/src/main/kotlin/rs09/game/world/callback/CallbackHub.kt
+++ b/Server/src/main/kotlin/rs09/game/world/callback/CallbackHub.kt
@@ -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()) {