From 5719d03e4deb70115d3d5bbd2539e8cba782983a Mon Sep 17 00:00:00 2001 From: Syndromeramo <21965004-syndromeramo@users.noreply.gitlab.com> Date: Tue, 7 Oct 2025 12:46:13 +0000 Subject: [PATCH] Farmed trees will now correctly regrow based on the same timer as other trees, rather than being tied to growth cycles Implemented admin ::instachop command --- .../content/global/skill/farming/Patch.kt | 2 - .../content/global/skill/farming/Stump.kt | 5 ++ .../skill/farming/timers/StumpGrowth.kt | 59 +++++++++++++++++++ .../gather/woodcutting/WoodcuttingListener.kt | 7 ++- .../game/system/command/sets/FunCommandSet.kt | 8 +++ 5 files changed, 77 insertions(+), 4 deletions(-) create mode 100644 Server/src/main/content/global/skill/farming/Stump.kt create mode 100644 Server/src/main/content/global/skill/farming/timers/StumpGrowth.kt diff --git a/Server/src/main/content/global/skill/farming/Patch.kt b/Server/src/main/content/global/skill/farming/Patch.kt index 4fde65b5e..eacc91bde 100644 --- a/Server/src/main/content/global/skill/farming/Patch.kt +++ b/Server/src/main/content/global/skill/farming/Patch.kt @@ -373,8 +373,6 @@ class Patch(val player: Player, val patch: FarmingPatch, var plantable: Plantabl setCurrentState(getCurrentState() + 1) isWatered = false } - - regrowIfTreeStump() } fun regrowIfTreeStump() { diff --git a/Server/src/main/content/global/skill/farming/Stump.kt b/Server/src/main/content/global/skill/farming/Stump.kt new file mode 100644 index 000000000..60c9bab8a --- /dev/null +++ b/Server/src/main/content/global/skill/farming/Stump.kt @@ -0,0 +1,5 @@ +package content.global.skill.farming + +class Stump(val varbit: Int, val TTL: Long) { + +} \ No newline at end of file diff --git a/Server/src/main/content/global/skill/farming/timers/StumpGrowth.kt b/Server/src/main/content/global/skill/farming/timers/StumpGrowth.kt new file mode 100644 index 000000000..616bde43a --- /dev/null +++ b/Server/src/main/content/global/skill/farming/timers/StumpGrowth.kt @@ -0,0 +1,59 @@ +package content.global.skill.farming.timers + +import core.game.node.entity.Entity +import core.game.system.timer.* +import core.game.node.entity.player.Player +import content.global.skill.farming.* +import core.tools.ticksToSeconds +import java.util.concurrent.TimeUnit +import org.json.simple.* + +class StumpGrowth : PersistTimer (1, "farming:stump", isSoft = true) { + val stumps = ArrayList() + lateinit var player: Player + + fun addStump(varbit: Int, ttl: Int){ + stumps.add( + Stump( + varbit, + System.currentTimeMillis() + TimeUnit.SECONDS.toMillis(ticksToSeconds(ttl).toLong()) + ) + ) + } + + override fun onRegister (entity: Entity) { + player = (entity as? Player)!! + } + + override fun run (entity: Entity) : Boolean { + val removeList = ArrayList() + for (stump in stumps) { + if (System.currentTimeMillis() > stump.TTL) { + FarmingPatch.patches[stump.varbit]?.getPatchFor(player)?.regrowIfTreeStump() + removeList.add(stump) + } + } + stumps.removeAll(removeList) + return stumps.isNotEmpty() + } + + override fun save(root: JSONObject, entity: Entity) { + val stumpArray = JSONArray() + for(s in stumps){ + val seed = JSONObject() + seed["patch"] = s.varbit + seed["ttl"] = s.TTL + stumpArray.add(seed) + } + root.put("stumps",stumpArray) + } + + override fun parse(root: JSONObject, entity: Entity) { + (root["stumps"] as JSONArray).forEach { + val s = it as JSONObject + val id = s["patch"].toString().toInt() + val ttl = s["ttl"].toString().toLong() + stumps.add(Stump(id,ttl)) + } + } +} diff --git a/Server/src/main/content/global/skill/gather/woodcutting/WoodcuttingListener.kt b/Server/src/main/content/global/skill/gather/woodcutting/WoodcuttingListener.kt index af8ef7398..87efe8614 100644 --- a/Server/src/main/content/global/skill/gather/woodcutting/WoodcuttingListener.kt +++ b/Server/src/main/content/global/skill/gather/woodcutting/WoodcuttingListener.kt @@ -3,6 +3,7 @@ package content.global.skill.gather.woodcutting import content.data.skill.SkillingTool import content.data.tables.BirdNest import content.global.skill.farming.FarmingPatch.Companion.forObject +import content.global.skill.farming.timers.StumpGrowth import content.global.skill.firemaking.Log import content.global.skill.skillcapeperks.SkillcapePerks import content.global.skill.skillcapeperks.SkillcapePerks.Companion.isActive @@ -71,7 +72,7 @@ class WoodcuttingListener : InteractionListener { if (clockReady(player, Clocks.SKILLING)) { animateWoodcutting(player) - if (!checkReward(player, resource, tool)) + if (!checkReward(player, resource, tool) && !getAttribute(player, "instachop", false)) return delayClock(player, Clocks.SKILLING, 3) val reward = resource.getReward() @@ -156,7 +157,7 @@ class WoodcuttingListener : InteractionListener { //OSRS: https://oldschool.runescape.wiki/w/Woodcutting scroll down to the mechanics section //RS3 : https://runescape.wiki/w/Woodcutting scroll down to the mechanics section, and expand the tree felling chances table if (resource.getRespawnRate() > 0) { - if (RandomFunction.roll(8) || listOf(1, 2, 3, 4, 6).contains(resource.identifier.toInt())){ + if (RandomFunction.roll(8) || listOf(1, 2, 3, 4, 6).contains(resource.identifier.toInt()) || getAttribute(player, "instachop", false)){ if (resource.isFarming()) { val fPatch = forObject(node.asScenery()) if (fPatch != null) { @@ -168,6 +169,8 @@ class WoodcuttingListener : InteractionListener { node.isActive = true return@queueScript stopExecuting(player) } + val stumps = getOrStartTimer (player) + stumps.addStump(fPatch.varbit, resource.respawnDuration) } return true } diff --git a/Server/src/main/core/game/system/command/sets/FunCommandSet.kt b/Server/src/main/core/game/system/command/sets/FunCommandSet.kt index 498fe6ce5..9ebd0ff36 100644 --- a/Server/src/main/core/game/system/command/sets/FunCommandSet.kt +++ b/Server/src/main/core/game/system/command/sets/FunCommandSet.kt @@ -239,6 +239,14 @@ class FunCommandSet : CommandSet(Privilege.ADMIN) { } } + /** + * Toggle instant woodcutting. + */ + define("instachop", Privilege.ADMIN, "", "Fells trees after a single log is gathered."){ player, _ -> + player.setAttribute("instachop", !player.getAttribute("instachop", false)) + notify(player,"Instachop mode " + if (player.getAttribute("instachop", false)) "on." else "off.") + } + } fun bury(player: Player){