Random Events should now spawn correctly
Fixed an issue that was causing tick event hooks to not fire
This commit is contained in:
@@ -2,6 +2,7 @@ package core.game.node.entity;
|
|||||||
|
|
||||||
import api.events.Event;
|
import api.events.Event;
|
||||||
import api.events.EventHook;
|
import api.events.EventHook;
|
||||||
|
import api.events.TickEvent;
|
||||||
import core.game.content.holiday.HolidayEvent;
|
import core.game.content.holiday.HolidayEvent;
|
||||||
import core.game.interaction.DestinationFlag;
|
import core.game.interaction.DestinationFlag;
|
||||||
import core.game.node.Node;
|
import core.game.node.Node;
|
||||||
@@ -216,6 +217,7 @@ public abstract class Entity extends Node {
|
|||||||
* This methods gets called before the {@link #update()} method.
|
* This methods gets called before the {@link #update()} method.
|
||||||
*/
|
*/
|
||||||
public void tick() {
|
public void tick() {
|
||||||
|
dispatch(new TickEvent(GameWorld.getTicks()));
|
||||||
skills.pulse();
|
skills.pulse();
|
||||||
walkingQueue.update();
|
walkingQueue.update();
|
||||||
updateMasks.prepare(this);
|
updateMasks.prepare(this);
|
||||||
|
|||||||
@@ -70,6 +70,9 @@ public final class WalkingQueue {
|
|||||||
boolean isPlayer = entity instanceof Player;
|
boolean isPlayer = entity instanceof Player;
|
||||||
this.walkDir = -1;
|
this.walkDir = -1;
|
||||||
this.runDir = -1;
|
this.runDir = -1;
|
||||||
|
if(entity.getLocation() == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (updateTeleport()) {
|
if (updateTeleport()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,4 +13,4 @@ data class InteractionEvent(val target: Node, val option: String) : Event
|
|||||||
data class ButtonClickedEvent(val iface: Int, val buttonId: Int) : Event
|
data class ButtonClickedEvent(val iface: Int, val buttonId: Int) : Event
|
||||||
data class UsedWithEvent(val used: Int, val with: Int) : Event
|
data class UsedWithEvent(val used: Int, val with: Int) : Event
|
||||||
data class SelfDeath(val killer: Entity) : Event
|
data class SelfDeath(val killer: Entity) : Event
|
||||||
data class TickEvent(val source: Entity) : Event
|
data class TickEvent(val worldTicks: Int) : Event
|
||||||
@@ -14,9 +14,6 @@ import rs09.game.system.SystemLogger
|
|||||||
import rs09.game.world.GameWorld
|
import rs09.game.world.GameWorld
|
||||||
import kotlin.random.Random
|
import kotlin.random.Random
|
||||||
|
|
||||||
private const val AVG_DELAY_TICKS = 6000 // 60 minutes
|
|
||||||
private const val MIN_DELAY_TICKS = AVG_DELAY_TICKS / 2
|
|
||||||
private const val MAX_DELAY_TICKS = MIN_DELAY_TICKS + AVG_DELAY_TICKS // window of 60 min centered on 60 min (30 to 90 min)
|
|
||||||
class RandomEventManager(val player: Player? = null) : LoginListener, EventHook<TickEvent> {
|
class RandomEventManager(val player: Player? = null) : LoginListener, EventHook<TickEvent> {
|
||||||
var event: RandomEventNPC? = null
|
var event: RandomEventNPC? = null
|
||||||
var enabled: Boolean = false
|
var enabled: Boolean = false
|
||||||
@@ -47,7 +44,7 @@ class RandomEventManager(val player: Player? = null) : LoginListener, EventHook<
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (getAttribute<RandomEventNPC?>(player, "re-npc", null) != null) return
|
if (getAttribute<RandomEventNPC?>(player, "re-npc", null) != null) return
|
||||||
val currentAction = player.pulseManager.current.toString()
|
val currentAction = player.pulseManager.current?.toString() ?: "None"
|
||||||
val ame: RandomEvents = if(currentAction.contains("WoodcuttingSkillPulse") && Random.nextBoolean()){
|
val ame: RandomEvents = if(currentAction.contains("WoodcuttingSkillPulse") && Random.nextBoolean()){
|
||||||
RandomEvents.TREE_SPIRIT
|
RandomEvents.TREE_SPIRIT
|
||||||
} else if(currentAction.contains("FishingPulse") && Random.nextBoolean()){
|
} else if(currentAction.contains("FishingPulse") && Random.nextBoolean()){
|
||||||
@@ -62,6 +59,7 @@ class RandomEventManager(val player: Player? = null) : LoginListener, EventHook<
|
|||||||
event = ame.npc.create(player,ame.loot,ame.type)
|
event = ame.npc.create(player,ame.loot,ame.type)
|
||||||
if (event!!.spawnLocation == null) {
|
if (event!!.spawnLocation == null) {
|
||||||
nextSpawn = GameWorld.ticks + 3000
|
nextSpawn = GameWorld.ticks + 3000
|
||||||
|
SystemLogger.logWarn("Tried to spawn random event for ${player.username} but spawn location was null!")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
event!!.init()
|
event!!.init()
|
||||||
@@ -74,6 +72,10 @@ class RandomEventManager(val player: Player? = null) : LoginListener, EventHook<
|
|||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
const val AVG_DELAY_TICKS = 6000 // 60 minutes
|
||||||
|
const val MIN_DELAY_TICKS = AVG_DELAY_TICKS / 2
|
||||||
|
const val MAX_DELAY_TICKS = MIN_DELAY_TICKS + AVG_DELAY_TICKS // window of 60 min centered on 60 min (30 to 90 min)
|
||||||
|
|
||||||
@JvmStatic fun getInstance(player: Player): RandomEventManager?
|
@JvmStatic fun getInstance(player: Player): RandomEventManager?
|
||||||
{
|
{
|
||||||
return getAttribute(player, "random-manager", null)
|
return getAttribute(player, "random-manager", null)
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import core.tools.RandomFunction
|
|||||||
import org.rs09.consts.Items
|
import org.rs09.consts.Items
|
||||||
import rs09.game.content.ame.RandomEventNPC
|
import rs09.game.content.ame.RandomEventNPC
|
||||||
import rs09.game.content.global.WeightBasedTable
|
import rs09.game.content.global.WeightBasedTable
|
||||||
|
import java.lang.Integer.max
|
||||||
|
|
||||||
val ids = 2463..2468
|
val ids = 2463..2468
|
||||||
|
|
||||||
@@ -18,7 +19,7 @@ class EvilChickenNPC(override var loot: WeightBasedTable? = null) : RandomEventN
|
|||||||
|
|
||||||
override fun init() {
|
override fun init() {
|
||||||
super.init()
|
super.init()
|
||||||
val index = (player.properties.combatLevel / 20) - 1
|
val index = max(0, (player.properties.combatLevel / 20) - 1)
|
||||||
val id = ids.toList()[index]
|
val id = ids.toList()[index]
|
||||||
this.transform(id)
|
this.transform(id)
|
||||||
this.attack(player)
|
this.attack(player)
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ class UpdateSequence
|
|||||||
playersList = renderablePlayers
|
playersList = renderablePlayers
|
||||||
npcList = Repository.renderableNpcs
|
npcList = Repository.renderableNpcs
|
||||||
lobbyList!!.map{ PacketRepository.send(ClearMinimapFlag::class.java, PlayerContext(it)) }
|
lobbyList!!.map{ PacketRepository.send(ClearMinimapFlag::class.java, PlayerContext(it)) }
|
||||||
playersList!!.forEach(Player::tick)
|
renderablePlayers.forEach(Player::tick)
|
||||||
npcList!!.forEach(NPC::tick)
|
npcList!!.forEach(NPC::tick)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,18 +11,21 @@ import org.rs09.consts.Items
|
|||||||
import rs09.ServerConstants
|
import rs09.ServerConstants
|
||||||
import rs09.game.content.global.shops.Shop
|
import rs09.game.content.global.shops.Shop
|
||||||
import rs09.game.content.global.shops.ShopItem
|
import rs09.game.content.global.shops.ShopItem
|
||||||
|
import rs09.game.system.SystemLogger
|
||||||
import rs09.game.system.config.ConfigParser
|
import rs09.game.system.config.ConfigParser
|
||||||
import rs09.game.system.config.ServerConfigParser
|
import rs09.game.system.config.ServerConfigParser
|
||||||
import rs09.game.world.GameWorld
|
import rs09.game.world.GameWorld
|
||||||
import rs09.game.world.repository.Repository
|
import rs09.game.world.repository.Repository
|
||||||
|
import rs09.game.world.update.UpdateSequence
|
||||||
import java.nio.ByteBuffer
|
import java.nio.ByteBuffer
|
||||||
|
|
||||||
object TestUtils {
|
object TestUtils {
|
||||||
fun getMockPlayer(name: String, ironman: IronmanMode = IronmanMode.NONE): Player {
|
fun getMockPlayer(name: String, ironman: IronmanMode = IronmanMode.NONE): Player {
|
||||||
val p = Player(PlayerDetails(name))
|
val p = MockPlayer(name)
|
||||||
p.details.session = MockSession()
|
|
||||||
p.ironmanManager.mode = ironman
|
p.ironmanManager.mode = ironman
|
||||||
Repository.addPlayer(p)
|
Repository.addPlayer(p)
|
||||||
|
//Update sequence has a separate list of players for some reason...
|
||||||
|
UpdateSequence.renderablePlayers.add(p)
|
||||||
return p
|
return p
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -53,12 +56,23 @@ object TestUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun advanceTicks(amount: Int) {
|
fun advanceTicks(amount: Int) {
|
||||||
|
SystemLogger.logInfo("Advancing ticks by $amount.")
|
||||||
for(i in 0 until amount) {
|
for(i in 0 until amount) {
|
||||||
GameWorld.majorUpdateWorker.handleTickActions()
|
GameWorld.majorUpdateWorker.handleTickActions()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class MockPlayer(name: String) : Player(PlayerDetails(name)) {
|
||||||
|
init {
|
||||||
|
this.details.session = MockSession()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun update() {
|
||||||
|
//do nothing. This is for rendering stuff. We don't render a mock player. Not until the spaghetti is less spaghetti.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class MockSession : IoSession(null, null) {
|
class MockSession : IoSession(null, null) {
|
||||||
val receivedPackets = ArrayList<Packet>()
|
val receivedPackets = ArrayList<Packet>()
|
||||||
var disconnected = false
|
var disconnected = false
|
||||||
|
|||||||
@@ -0,0 +1,36 @@
|
|||||||
|
package content
|
||||||
|
|
||||||
|
import TestUtils
|
||||||
|
import org.junit.jupiter.api.Assertions
|
||||||
|
import org.junit.jupiter.api.Test
|
||||||
|
import rs09.game.world.GameWorld
|
||||||
|
|
||||||
|
class RandomEventManager {
|
||||||
|
companion object {init {
|
||||||
|
TestUtils.preTestSetup()
|
||||||
|
}}
|
||||||
|
|
||||||
|
@Test fun loginShouldEnableManager() {
|
||||||
|
val p = TestUtils.getMockPlayer("Bill")
|
||||||
|
rs09.game.content.ame.RandomEventManager().login(p)
|
||||||
|
val manager = rs09.game.content.ame.RandomEventManager.getInstance(p)
|
||||||
|
Assertions.assertNotNull(manager)
|
||||||
|
Assertions.assertEquals(true, manager!!.enabled)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test fun loginShouldSetNextSpawn() {
|
||||||
|
val p = TestUtils.getMockPlayer("Bill")
|
||||||
|
rs09.game.content.ame.RandomEventManager().login(p)
|
||||||
|
val manager = rs09.game.content.ame.RandomEventManager.getInstance(p)
|
||||||
|
Assertions.assertNotNull(manager)
|
||||||
|
Assertions.assertEquals(true, manager!!.nextSpawn > GameWorld.ticks)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test fun shouldSpawnRandomEventWithinMAXTICKSGivenNoRestrictions() {
|
||||||
|
val p = TestUtils.getMockPlayer("Bill")
|
||||||
|
p.setAttribute("tutorial:complete", true) //tutorial has to be complete to spawn randoms
|
||||||
|
rs09.game.content.ame.RandomEventManager().login(p)
|
||||||
|
TestUtils.advanceTicks(rs09.game.content.ame.RandomEventManager.MAX_DELAY_TICKS + 5)
|
||||||
|
Assertions.assertNotNull(p.getAttribute("re-npc", null))
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user