Merge branch 'ge-improvements' into 'master'

GE Improvements

See merge request 2009scape/2009scape!158
This commit is contained in:
Ceikry
2021-07-13 15:26:20 +00:00
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);
}
}
@@ -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,54 +24,19 @@ 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 {
/**
* How often in ticks should ge offers that hit the buying limit be reprocessed?
*/
private val RESET_BUYING_LIMIT_INTERVAL = 24000
/**
* How often should the database be saved to disk?
*/
private val SAVE_EVERY = ServerConstants.GE_AUTOSAVE_FREQUENCY
override fun call(): Boolean {
init()
delay = 1
GameWorld.Pulser.submit(this)
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)
}
}
}
if (dumpDatabase && (GameWorld.ticks % SAVE_EVERY == 0)) {
//save()
dumpDatabase = false
}
return false
}
companion object {
object OfferManager {
/**
* The update notification.
*/
@@ -98,6 +64,7 @@ class OfferManager : Pulse(), CallBack {
* 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()
@@ -175,11 +142,19 @@ class OfferManager : Pulse(), CallBack {
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 = BotPrices.getPrice(offer.itemID)
val botPrice = getRecommendedPrice(offer.itemID, true)
if (offer.offeredValue < botPrice) {
return
}
@@ -272,6 +247,7 @@ class OfferManager : Pulse(), CallBack {
return qty
}
@JvmStatic
fun getOffersForItem(item: Int): MutableList<GrandExchangeOffer> {
if (OFFERS_BY_ITEMID.containsKey(item)) {
return OFFERS_BY_ITEMID[item]!!
@@ -540,7 +516,15 @@ class OfferManager : Pulse(), CallBack {
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()) {