From 62be2e837dc2a6ac0ee07c0d428631fb79f4ba7c Mon Sep 17 00:00:00 2001 From: Ceikry Date: Thu, 11 Mar 2021 17:00:47 -0600 Subject: [PATCH] New Option listener system + rewritten bone grinder + fix for attribute.get --- .../bonegrinder/BoneGrinderOptionHandler.kt | 241 ++++++++++++++++++ .../Server/core/game/interaction/Listeners.kt | 20 ++ .../core/game/interaction/OptionListener.kt | 14 + .../game/node/entity/impl/GameAttributes.java | 1 + .../core/net/packet/in/InteractionPacket.java | 21 +- .../java/Server/core/plugin/PluginManager.kt | 5 +- 6 files changed, 297 insertions(+), 5 deletions(-) create mode 100644 Server/src/main/java/Server/core/game/content/zone/phasmatys/bonegrinder/BoneGrinderOptionHandler.kt create mode 100644 Server/src/main/java/Server/core/game/interaction/Listeners.kt create mode 100644 Server/src/main/java/Server/core/game/interaction/OptionListener.kt diff --git a/Server/src/main/java/Server/core/game/content/zone/phasmatys/bonegrinder/BoneGrinderOptionHandler.kt b/Server/src/main/java/Server/core/game/content/zone/phasmatys/bonegrinder/BoneGrinderOptionHandler.kt new file mode 100644 index 000000000..0a52ab290 --- /dev/null +++ b/Server/src/main/java/Server/core/game/content/zone/phasmatys/bonegrinder/BoneGrinderOptionHandler.kt @@ -0,0 +1,241 @@ +package core.game.content.zone.phasmatys.bonegrinder + +import core.game.content.global.Bones +import core.game.interaction.OptionListener +import core.game.node.entity.player.Player +import core.game.node.item.Item +import core.game.system.task.Pulse +import core.game.world.GameWorld.Pulser +import core.game.world.map.Location +import core.game.world.update.flag.context.Animation +import core.tools.Items + +private const val LOADER = 11162 +private const val BONE_GRINDER = 11163 +private const val BIN = 11164 +private const val LOADED_BONE_KEY = "/save:bonegrinder-bones" +private const val BONE_HOPPER_KEY = "/save:bonegrinder-hopper" +private const val BONE_BIN_KEY = "/save:bonegrinder-bin" +private val FILL_ANIM = Animation(1649) +private val WIND_ANIM = Animation(1648) +private val SCOOP_ANIM = Animation(1650) + +class BoneGrinderOptionHandler : OptionListener() { + + override fun defineListeners() { + + /** + * Handle the bone loader/hopper fill option + */ + on(LOADER,OBJECT,"fill"){player, _ -> + handleFill(player) + } + + /** + * Handle the wheel's wind option + */ + on(BONE_GRINDER,OBJECT,"wind"){player,_ -> + handleWind(player) + } + + /** + * Handle the wheel's status option + */ + on(BONE_GRINDER,OBJECT,"status"){player,_ -> + handleStatus(player) + } + + /** + * Handle the bin's empty option + */ + on(BIN,OBJECT,"empty"){player,_ -> + handleEmpty(player) + } + + } + + fun handleFill(player: Player): Boolean{ + val bone = getBone(player) + if(bone == null){ + player.sendMessage("You have no bones to grind.") + return true + } + if(player.getAttribute(BONE_HOPPER_KEY,false) != false){ + player.sendMessage("You already have some bones in the hopper.") + return true + } + if(player.getAttribute(BONE_BIN_KEY,false) != false){ + player.sendMessage("You already have some bonemeal that needs to be collected.") + return true + } + + val fillPulse = object: Pulse(){ + var stage = 0 + override fun pulse(): Boolean { + when(stage++){ + 0 -> { + player.lock() + player.animator.animate(FILL_ANIM) + } + FILL_ANIM.duration -> { + player.sendMessage("You fill the hopper with bones.") + player.unlock() + player.inventory.remove(Item(bone.itemId)) + player.setAttribute(LOADED_BONE_KEY,bone.ordinal) + player.setAttribute(BONE_HOPPER_KEY,true) + return true + } + } + return false + } + } + + if(player.inventory.getAmount(bone.itemId) > 0){ + player.pulseManager.run(object : Pulse(){ + var stage = 0 + override fun pulse(): Boolean { + when(stage++){ + 0 -> Pulser.submit(fillPulse).also { delay = FILL_ANIM.duration + 1} + 1 -> { + player.walkingQueue.reset() + player.walkingQueue.addPath(3659,3524,true) + delay = 2 + } + 2 -> { + player.faceLocation(Location.create(3659, 3526, 1)) + handleWind(player) + delay = WIND_ANIM.duration + 1 + } + 3 -> { + player.walkingQueue.reset() + player.walkingQueue.addPath(3658,3524,true) + delay = 2 + } + 4 -> { + player.faceLocation(Location.create(3658, 3525, 1)) + if(!player.inventory.contains(Items.EMPTY_POT_1931,1)){ + return handleEmpty(player) + } else { + handleEmpty(player) + delay = SCOOP_ANIM.duration + 1 + } + } + 5 -> { + player.walkingQueue.reset() + player.walkingQueue.addPath(3660,3524,true) + delay = 4 + } + 6 -> { + player.faceLocation(Location.create(3660,3526)) + handleFill(player) + return true + } + } + return false + } + }) + } else { + Pulser.submit(fillPulse) + } + return true + } + + fun handleWind(player: Player): Boolean{ + if(!player.getAttribute(BONE_HOPPER_KEY,false)){ + player.sendMessage("You have no bones loaded to grind.") + return true + } + + if(player.getAttribute(BONE_BIN_KEY,false)){ + player.sendMessage("You already have some bonemeal which you need to collect.") + return true + } + + Pulser.submit(object : Pulse(){ + var stage = 0 + override fun pulse(): Boolean { + when(stage++){ + 0 -> { + player.lock() + player.animator.animate(WIND_ANIM) + player.sendMessage("You wind the handle.") + } + WIND_ANIM.duration -> { + player.unlock() + player.sendMessage("The bonemeal falls into the bin.") + player.setAttribute(BONE_HOPPER_KEY,false) + player.setAttribute(BONE_BIN_KEY,true) + return true + } + } + return false + } + }) + return true + } + + fun handleStatus(player: Player): Boolean{ + val bonesLoaded = player.getAttribute(BONE_HOPPER_KEY,false) + val boneMealReady = player.getAttribute(BONE_BIN_KEY,false) + + if(bonesLoaded) player.sendMessage("There are bones waiting in the hopper.") + if(boneMealReady) player.sendMessage("There is bonemeal waiting in the bin to be collected.") + + if(!bonesLoaded && !boneMealReady){ + player.sendMessage("There is nothing loaded into the machine.") + } + + return true + } + + fun handleEmpty(player: Player): Boolean{ + if(!player.getAttribute(BONE_BIN_KEY,false)){ + player.sendMessage("You have no bonemeal to collect.") + return true + } + + if(player.getAttribute(BONE_HOPPER_KEY,false) && !player.getAttribute(BONE_BIN_KEY,false)){ + player.sendMessage("You need to wind the wheel to grind the bones.") + return true + } + + if(!player.inventory.contains(Items.EMPTY_POT_1931,1)){ + player.sendMessage("You don't have any pots to take the bonemeal with.") + return true + } + + val bone = Bones.values()[player.getAttribute(LOADED_BONE_KEY,-1)] + + Pulser.submit(object : Pulse(){ + var stage = 0 + override fun pulse(): Boolean { + when(stage++){ + 0 -> { + player.lock() + player.animator.animate(SCOOP_ANIM) + } + SCOOP_ANIM.duration -> { + player.unlock() + if(player.inventory.remove(Item(Items.EMPTY_POT_1931))){ + player.inventory.add(bone.boneMeal) + player.setAttribute(BONE_BIN_KEY,false) + player.setAttribute(BONE_HOPPER_KEY,false) + player.setAttribute(LOADED_BONE_KEY,-1) + } + return true + } + } + return false + } + }) + + return true + } + + fun getBone(player: Player): Bones? { + for(bone in Bones.values()){ + if(player.inventory.contains(bone.itemId,1)) return bone + } + return null + } +} \ No newline at end of file diff --git a/Server/src/main/java/Server/core/game/interaction/Listeners.kt b/Server/src/main/java/Server/core/game/interaction/Listeners.kt new file mode 100644 index 000000000..d2d9c4295 --- /dev/null +++ b/Server/src/main/java/Server/core/game/interaction/Listeners.kt @@ -0,0 +1,20 @@ +package core.game.interaction + +import core.game.node.Node +import core.game.node.entity.player.Player +import core.tools.StringUtils + +object Listeners { + private val listeners = HashMap Boolean>() + + @JvmStatic + fun add(id: Int, type: Int, option: String, method: (Player,Node) -> Boolean){ + val key = (StringUtils.stringToLong(option.toLowerCase()) + id) shl type + listeners[key] = method + } + + @JvmStatic + fun get(id: Int, type: Int, option: String): ((Player,Node) -> Boolean)?{ + return listeners[(StringUtils.stringToLong(option.toLowerCase()) + id) shl type] + } +} \ No newline at end of file diff --git a/Server/src/main/java/Server/core/game/interaction/OptionListener.kt b/Server/src/main/java/Server/core/game/interaction/OptionListener.kt new file mode 100644 index 000000000..d3e95e833 --- /dev/null +++ b/Server/src/main/java/Server/core/game/interaction/OptionListener.kt @@ -0,0 +1,14 @@ +package core.game.interaction + +import core.game.node.Node +import core.game.node.entity.player.Player + +abstract class OptionListener { + val ITEM = 0 + val OBJECT = 1 + val NPC = 2 + abstract fun defineListeners() + fun on(id: Int, type: Int, option: String,handler: (Player, Node) -> Boolean){ + Listeners.add(id,type,option,handler) + } +} \ No newline at end of file diff --git a/Server/src/main/java/Server/core/game/node/entity/impl/GameAttributes.java b/Server/src/main/java/Server/core/game/node/entity/impl/GameAttributes.java index c2214f0ba..db629a03a 100644 --- a/Server/src/main/java/Server/core/game/node/entity/impl/GameAttributes.java +++ b/Server/src/main/java/Server/core/game/node/entity/impl/GameAttributes.java @@ -159,6 +159,7 @@ public final class GameAttributes { */ @SuppressWarnings("unchecked") public T getAttribute(String string, T fail) { + string = string.replace("/save:",""); Object object = attributes.get(string); if (object != null) { return (T) object; diff --git a/Server/src/main/java/Server/core/net/packet/in/InteractionPacket.java b/Server/src/main/java/Server/core/net/packet/in/InteractionPacket.java index 0854e203b..7c74eb526 100644 --- a/Server/src/main/java/Server/core/net/packet/in/InteractionPacket.java +++ b/Server/src/main/java/Server/core/net/packet/in/InteractionPacket.java @@ -3,14 +3,12 @@ package core.net.packet.in; import core.ServerConstants; import core.cache.def.impl.ObjectDefinition; import core.cache.def.impl.VarbitDefinition; -import core.game.interaction.Interaction; -import core.game.interaction.MovementPulse; -import core.game.interaction.Option; -import core.game.interaction.SpecialGroundItems; +import core.game.interaction.*; import core.game.node.Node; import core.game.node.entity.npc.NPC; import core.game.node.entity.player.Player; import core.game.system.SystemLogger; +import core.game.system.task.Pulse; import plugin.ai.AIPlayer; import core.game.node.item.GroundItem; import core.game.node.item.GroundItemManager; @@ -267,6 +265,21 @@ public final class InteractionPacket implements IncomingPacket { player.debug("Object handler: " + option.getHandler().getClass().getSimpleName()); } handleAIPLegion(player, 1, optionIndex, x, y, objectId); + + if(Listeners.get(object.getId(),1, option.getName()) != null){ + GameObject finalObject = object; + player.getPulseManager().run(new MovementPulse(player, finalObject,DestinationFlag.OBJECT) { + @Override + public boolean pulse() { + player.faceLocation(finalObject.getLocation()); + if(!Listeners.get(finalObject.getId(),1,option.getName()).invoke(player, finalObject)){ + player.sendMessage("Nothing interesting happens."); + } + return true; + } + }); + return; + } if(PluginInteractionManager.handle(player,object)){ return; } diff --git a/Server/src/main/java/Server/core/plugin/PluginManager.kt b/Server/src/main/java/Server/core/plugin/PluginManager.kt index ca8470fc0..e735aa0d4 100644 --- a/Server/src/main/java/Server/core/plugin/PluginManager.kt +++ b/Server/src/main/java/Server/core/plugin/PluginManager.kt @@ -10,6 +10,7 @@ import core.game.content.activity.ActivityManager import core.game.content.activity.ActivityPlugin import core.game.system.command.Command import core.game.content.dialogue.DialoguePlugin +import core.game.interaction.OptionListener import java.lang.Exception import java.util.* import java.util.function.Consumer @@ -65,11 +66,13 @@ object PluginManager { } }) result.getSubclasses("core.game.system.command.Command").forEach { - System.out.println("E") try { definePlugin(it.loadClass().newInstance() as Plugin).also { System.out.println("Initializing $it") } } catch (e: Exception) {e.printStackTrace()} } + result.getSubclasses("core.game.interaction.OptionListener").forEach { + (it.loadClass().newInstance() as OptionListener).defineListeners() + } } /**