Fixed some error spam about a nullref in animateWoodcutting
Fixed a general script processing oversight that could cause error-throwing scripts to continue executing Scripts being processed now automatically cancel if the interaction-target-node is no longer active (fixes object could not be replaced spam) Fixed the stopExecuting() spam Fixed a CME in the disconnection queue (only affected server shutdown) Future-proofed the ground spawn parser to work with the format Zaros now outputs Added in proper SKILLING global clock for use with the script system - addresses some quirks and brings us closer to authenticity
This commit is contained in:
@@ -2346,6 +2346,28 @@ fun queueScript(entity: Entity, delay: Int = 1, strength: QueueStrength = QueueS
|
||||
entity.scripts.addToQueue(s, strength)
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the clock to the value of WORLD_TICSK + ticks.
|
||||
* @param entity the entity whose clock we are updating
|
||||
* @param clock the clock we are updating. Please use [core.game.interaction.Clocks] for this argument.
|
||||
* @param ticks the number of ticks to delay by
|
||||
* @return always returns false so this can be used as a script return value.
|
||||
**/
|
||||
fun delayClock(entity: Entity, clock: Int, ticks: Int) : Boolean {
|
||||
entity.clocks[clock] = getWorldTicks() + ticks
|
||||
return false
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a clock is ready (have we elapsed any delay put into it)
|
||||
* @param entity the entity whose clock we are checking
|
||||
* @param clock the clock we are checking. Please use [core.game.interaction.Clocks] for this argument.
|
||||
* @return true if we have elapsed the clock's wait
|
||||
**/
|
||||
fun clockReady(entity: Entity, clock: Int) : Boolean {
|
||||
return entity.clocks[clock] <= getWorldTicks()
|
||||
}
|
||||
|
||||
fun delayAttack(entity: Entity, ticks: Int) {
|
||||
entity.properties.combatPulse.delayNextAttack(3)
|
||||
entity.clocks[Clocks.NEXT_ATTACK] = getWorldTicks() + ticks
|
||||
@@ -2389,4 +2411,4 @@ fun modPrayerPoints(player: Player, amount: Double) {
|
||||
else return
|
||||
}
|
||||
|
||||
private class ContentAPI
|
||||
private class ContentAPI
|
||||
|
||||
@@ -8,4 +8,5 @@ object Clocks {
|
||||
@JvmStatic val NEXT_DRINK = 4
|
||||
@JvmStatic val NEXT_ATTACK = 5
|
||||
@JvmStatic val STUN = 6
|
||||
}
|
||||
@JvmStatic val SKILLING = 7
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ import core.game.world.map.path.Pathfinder
|
||||
import core.tools.Log
|
||||
import core.tools.SystemLogger
|
||||
import java.lang.Integer.max
|
||||
import java.io.*
|
||||
|
||||
class ScriptProcessor(val entity: Entity) {
|
||||
private var apScript: Script<*>? = null
|
||||
@@ -182,6 +183,10 @@ class ScriptProcessor(val entity: Entity) {
|
||||
}
|
||||
|
||||
fun processInteractScript(script: Script<*>) {
|
||||
if (interactTarget == null || !interactTarget!!.isActive) {
|
||||
log(this::class.java, Log.FINE, "Interact target $interactTarget no longer active, cancelling interaction.")
|
||||
reset()
|
||||
}
|
||||
if (script.nextExecution < GameWorld.ticks) {
|
||||
val finished = executeScript(script)
|
||||
script.state++
|
||||
@@ -193,11 +198,19 @@ class ScriptProcessor(val entity: Entity) {
|
||||
|
||||
fun executeScript(script: Script<*>) : Boolean {
|
||||
currentScript = script
|
||||
when (script) {
|
||||
is Interaction -> return script.execution.invoke(entity as? Player ?: return true, interactTarget ?: return true, script.state)
|
||||
is UseWithInteraction -> return script.execution.invoke(entity as? Player ?: return true, script.used, script.with, script.state)
|
||||
is QueuedScript -> return script.execution.invoke(script.state)
|
||||
is QueuedUseWith -> return script.execution.invoke(entity as? Player ?: return true, script.used, script.with, script.state)
|
||||
try {
|
||||
when (script) {
|
||||
is Interaction -> return script.execution.invoke(entity as? Player ?: return true, interactTarget ?: return true, script.state)
|
||||
is UseWithInteraction -> return script.execution.invoke(entity as? Player ?: return true, script.used, script.with, script.state)
|
||||
is QueuedScript -> return script.execution.invoke(script.state)
|
||||
is QueuedUseWith -> return script.execution.invoke(entity as? Player ?: return true, script.used, script.with, script.state)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
val sw = StringWriter()
|
||||
val pw = PrintWriter(sw)
|
||||
e.printStackTrace(pw)
|
||||
log(this::class.java, Log.ERR, "Error processing ${script::class.java.simpleName} - stopping the script. Exception follows: $sw")
|
||||
reset()
|
||||
}
|
||||
currentScript = null
|
||||
return true
|
||||
@@ -243,6 +256,8 @@ class ScriptProcessor(val entity: Entity) {
|
||||
}
|
||||
|
||||
fun setInteractionScript(target: Node, script: Script<*>?) {
|
||||
if (apScript != null && script != null && script.execution == apScript!!.execution) return
|
||||
if (opScript != null && script != null && script.execution == opScript!!.execution) return
|
||||
reset()
|
||||
interactTarget = target
|
||||
if (script != null) {
|
||||
@@ -298,4 +313,4 @@ class ScriptProcessor(val entity: Entity) {
|
||||
private fun getActiveInteraction() : Script<*>? {
|
||||
return opScript ?: apScript
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ import core.tools.SystemLogger
|
||||
import core.game.world.GameWorld
|
||||
import core.game.world.repository.Repository
|
||||
import core.tools.Log
|
||||
import java.io.FileReader
|
||||
import java.io.*
|
||||
import java.nio.ByteBuffer
|
||||
|
||||
class GroundSpawnLoader {
|
||||
@@ -26,14 +26,22 @@ class GroundSpawnLoader {
|
||||
reader = FileReader(ServerConstants.CONFIG_PATH + "ground_spawns.json")
|
||||
var configs = parser.parse(reader) as JSONArray
|
||||
for(config in configs){
|
||||
val e = config as JSONObject
|
||||
val datas = e["loc_data"].toString().split("-")
|
||||
val id = e["item_id"].toString().toInt()
|
||||
for(d in datas){
|
||||
val tokens = d.replace("{", "").replace("}", "").split(",".toRegex()).toTypedArray()
|
||||
val spawn = GroundSpawn(tokens[4].toInt(), Item(id, tokens[0].toInt()), Location(Integer.valueOf(tokens[1]), Integer.valueOf(tokens[2]), Integer.valueOf(tokens[3])))
|
||||
spawn.init()
|
||||
count++
|
||||
try {
|
||||
val e = config as JSONObject
|
||||
val datas = e["loc_data"].toString().split("-")
|
||||
val id = e["item_id"].toString().toInt()
|
||||
for(d in datas){
|
||||
if (d.isNullOrEmpty()) continue
|
||||
val tokens = d.replace("{", "").replace("}", "").split(",".toRegex()).toTypedArray()
|
||||
val spawn = GroundSpawn(tokens[4].toInt(), Item(id, tokens[0].toInt()), Location(Integer.valueOf(tokens[1]), Integer.valueOf(tokens[2]), Integer.valueOf(tokens[3])))
|
||||
spawn.init()
|
||||
count++
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
val sw = StringWriter()
|
||||
val pw = PrintWriter(sw)
|
||||
e.printStackTrace(pw)
|
||||
log(this::class.java, Log.ERR, "Error parsing config entry ${config.toString()}: $sw")
|
||||
}
|
||||
}
|
||||
log(this::class.java, Log.FINE, "Initialized $count ground items.")
|
||||
@@ -118,4 +126,4 @@ class GroundSpawnLoader {
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -102,7 +102,7 @@ class DisconnectionQueue {
|
||||
* Clears the queue.
|
||||
*/
|
||||
fun clear() {
|
||||
for (entry in queue.values) {
|
||||
for (entry in queue.values.toTypedArray()) {
|
||||
finish(entry, true)
|
||||
}
|
||||
queue.clear()
|
||||
@@ -139,4 +139,4 @@ class DisconnectionQueue {
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user