Merge remote-tracking branch 'upstream/master'

This commit is contained in:
skelsoft
2021-07-21 07:38:18 +10:00
29 changed files with 993 additions and 627 deletions
+1 -1
View File
@@ -22,7 +22,7 @@ repositories {
dependencies { dependencies {
implementation("com.github.ajalt.mordant:mordant:2.0.0-alpha2") implementation("com.github.ajalt.mordant:mordant:2.0.0-alpha2")
implementation "org.jetbrains:markdown-jvm:0.2.0" implementation "org.jetbrains:markdown-jvm:0.2.4"
implementation 'com.google.guava:guava:29.0-jre' implementation 'com.google.guava:guava:29.0-jre'
implementation 'mysql:mysql-connector-java:8.0.21' implementation 'mysql:mysql-connector-java:8.0.21'
implementation 'io.github.classgraph:classgraph:4.8.98' implementation 'io.github.classgraph:classgraph:4.8.98'
+53 -155
View File
@@ -46329,213 +46329,111 @@
"main": [ "main": [
{ {
"minAmount": "1", "minAmount": "1",
"weight": "50.0", "weight": "0.15",
"id": "1339",
"maxAmount": "1"
},
{
"minAmount": "1",
"weight": "25.0",
"id": "1341",
"maxAmount": "1"
},
{
"minAmount": "1",
"weight": "25.0",
"id": "1119",
"maxAmount": "1"
},
{
"minAmount": "1",
"weight": "25.0",
"id": "1121",
"maxAmount": "1"
},
{
"minAmount": "1",
"weight": "25.0",
"id": "1181",
"maxAmount": "1"
},
{
"minAmount": "1",
"weight": "50.0",
"id": "1141",
"maxAmount": "1"
},
{
"minAmount": "1",
"weight": "5.0",
"id": "1357",
"maxAmount": "1"
},
{
"minAmount": "1",
"weight": "5.0",
"id": "1145",
"maxAmount": "1"
},
{
"minAmount": "1",
"weight": "25.0",
"id": "1161",
"maxAmount": "1"
},
{
"minAmount": "1",
"weight": "25.0",
"id": "1345",
"maxAmount": "1"
},
{
"minAmount": "1",
"weight": "25.0",
"id": "1201", "id": "1201",
"maxAmount": "1" "maxAmount": "1"
}, },
{ {
"minAmount": "1", "minAmount": "1",
"weight": "25.0", "weight": "1.0",
"id": "1161",
"maxAmount": "1"
},
{
"minAmount": "1",
"weight": "1.0",
"id": "1181",
"maxAmount": "1"
},
{
"minAmount": "1",
"weight": "1.0",
"id": "1121",
"maxAmount": "1"
},
{
"minAmount": "1",
"weight": "0.098",
"id": "1347", "id": "1347",
"maxAmount": "1" "maxAmount": "1"
}, },
{ {
"minAmount": "1", "minAmount": "1",
"weight": "25.0", "weight": "1.0",
"id": "3122", "id": "1341",
"maxAmount": "1" "maxAmount": "1"
}, },
{ {
"minAmount": "8", "minAmount": "8",
"weight": "50.0", "weight": "1.0",
"id": "557", "id": "557",
"maxAmount": "60" "maxAmount": "36"
}, },
{ {
"minAmount": "2", "minAmount": "12",
"weight": "25.0", "weight": "0.65",
"id": "563", "id": "563",
"maxAmount": "12" "maxAmount": "12"
}, },
{ {
"minAmount": "7", "minAmount": "7",
"weight": "25.0", "weight": "0.65",
"id": "561", "id": "561",
"maxAmount": "8" "maxAmount": "7"
}, },
{ {
"minAmount": "1", "minAmount": "1",
"weight": "25.0", "weight": "1.0",
"id": "5323",
"maxAmount": "1"
},
{
"minAmount": "1",
"weight": "25.0",
"id": "5280",
"maxAmount": "1"
},
{
"minAmount": "1",
"weight": "50.0",
"id": "5104", "id": "5104",
"maxAmount": "1" "maxAmount": "1"
}, },
{ {
"minAmount": "1", "minAmount": "1",
"weight": "25.0", "weight": "1.0",
"id": "5105",
"maxAmount": "1"
},
{
"minAmount": "1",
"weight": "25.0",
"id": "5100", "id": "5100",
"maxAmount": "1" "maxAmount": "1"
}, },
{ {
"minAmount": "1", "minAmount": "1",
"weight": "50.0", "weight": "0.038",
"id": "5292",
"maxAmount": "1"
},
{
"minAmount": "1",
"weight": "5.0",
"id": "5296",
"maxAmount": "1"
},
{
"minAmount": "1",
"weight": "25.0",
"id": "5295", "id": "5295",
"maxAmount": "1" "maxAmount": "1"
}, },
{
"minAmount": "6",
"weight": "1.0",
"id": "454",
"maxAmount": "6"
},
{ {
"minAmount": "1", "minAmount": "1",
"weight": "50.0", "weight": "1.0",
"id": "203", "id": "1759",
"maxAmount": "1"
},
{
"minAmount": "3",
"weight": "1.0",
"id": "353",
"maxAmount": "3"
},
{
"minAmount": "1",
"weight": "0.098",
"id": "3122",
"maxAmount": "1" "maxAmount": "1"
}, },
{ {
"minAmount": "1", "minAmount": "1",
"weight": "50.0", "weight": "1.0",
"id": "199", "id": "199",
"maxAmount": "1" "maxAmount": "1"
}, },
{ {
"minAmount": "1", "minAmount": "1",
"weight": "50.0", "weight": "1.0",
"id": "201", "id": "201",
"maxAmount": "1" "maxAmount": "1"
},
{
"minAmount": "1",
"weight": "25.0",
"id": "207",
"maxAmount": "1"
},
{
"minAmount": "1",
"weight": "25.0",
"id": "205",
"maxAmount": "1"
},
{
"minAmount": "8",
"weight": "50.0",
"id": "995",
"maxAmount": "200"
},
{
"minAmount": "1",
"weight": "25.0",
"id": "1759",
"maxAmount": "42"
},
{
"minAmount": "3",
"weight": "25.0",
"id": "453",
"maxAmount": "6"
},
{
"minAmount": "3",
"weight": "25.0",
"id": "353",
"maxAmount": "3"
},
{
"minAmount": "5",
"weight": "25.0",
"id": "401",
"maxAmount": "5"
},
{
"minAmount": "6",
"weight": "25.0",
"id": "383",
"maxAmount": "7"
} }
] ]
}, },
+6
View File
@@ -1067,6 +1067,12 @@
"indexId": "365", "indexId": "365",
"borders": "{1792,4352,1855,4415}-{1920,4352,1983,4415}" "borders": "{1792,4352,1855,4415}-{1920,4352,1983,4415}"
}, },
{
"id": "220",
"name": "Island of the Trolls",
"indexId": "441",
"borders": "{2304,3842,2428,3901}"
},
{ {
"id": "241", "id": "241",
"name": "Stagnant", "name": "Stagnant",
+12
View File
@@ -10718,5 +10718,17 @@
{ {
"npc_id": "5517", "npc_id": "5517",
"loc_data": "{2403,3853,0,1,0}-{2328,3830,0,1,0}-{2405,3860,0,1,0}-{2335,3894,0,1,0}" "loc_data": "{2403,3853,0,1,0}-{2328,3830,0,1,0}-{2405,3860,0,1,0}-{2335,3894,0,1,0}"
},
{
"npc_id": "3848",
"loc_data": "{2410,3780,0,1,0}-{2414,3780,0,1,0}"
},
{
"npc_id": "313",
"loc_data":"{2401,3781,0,1,0}"
},
{
"npc_id": "312",
"loc_data": "{2421,3789,0,1,0}"
} }
] ]
@@ -343,6 +343,8 @@ public class GrandExchangeInterface extends ComponentPlugin {
String s = value.toString(); String s = value.toString();
s = s.replace("k","000"); s = s.replace("k","000");
s = s.replace("K","000"); s = s.replace("K","000");
s = s.replace("m","000000");
s = s.replace("M","000000");
setOfferAmount(player, offer, Integer.parseInt(s)); setOfferAmount(player, offer, Integer.parseInt(s));
return Unit.INSTANCE; return Unit.INSTANCE;
}); });
@@ -379,6 +381,8 @@ public class GrandExchangeInterface extends ComponentPlugin {
String s = value.toString(); String s = value.toString();
s = s.replace("k","000"); s = s.replace("k","000");
s = s.replace("K","000"); s = s.replace("K","000");
s = s.replace("m","000000");
s = s.replace("M","000000");
setOfferValue(player, offer, Integer.parseInt(s)); setOfferValue(player, offer, Integer.parseInt(s));
return Unit.INSTANCE; return Unit.INSTANCE;
}); });
@@ -72,6 +72,8 @@ public final class TradeInterfacePlugin extends ComponentPlugin {
String s = value.toString(); String s = value.toString();
s = s.replace("k","000"); s = s.replace("k","000");
s = s.replace("K","000"); s = s.replace("K","000");
s = s.replace("m","000000");
s = s.replace("M","000000");
int val = Integer.parseInt(s); int val = Integer.parseInt(s);
module.getContainer().withdraw(slot, val); module.getContainer().withdraw(slot, val);
return Unit.INSTANCE; return Unit.INSTANCE;
@@ -376,6 +376,8 @@ public final class BankingPlugin extends OptionHandler {
String s = value.toString(); String s = value.toString();
s = s.replace("k","000"); s = s.replace("k","000");
s = s.replace("K","000"); s = s.replace("K","000");
s = s.replace("m","000000");
s = s.replace("M","000000");
int val = Integer.parseInt(s); int val = Integer.parseInt(s);
p.getBank().takeItem(slot, val); p.getBank().takeItem(slot, val);
p.getBank().updateLastAmountX(val); p.getBank().updateLastAmountX(val);
@@ -1,5 +1,6 @@
package core.game.node.entity.player.link.request.trade; package core.game.node.entity.player.link.request.trade;
import api.ContentAPI;
import core.cache.def.impl.ItemDefinition; import core.cache.def.impl.ItemDefinition;
import core.game.container.*; import core.game.container.*;
import core.game.node.entity.player.Player; import core.game.node.entity.player.Player;
@@ -10,6 +11,8 @@ import core.net.packet.PacketRepository;
import core.net.packet.context.ContainerContext; import core.net.packet.context.ContainerContext;
import core.net.packet.out.ContainerPacket; import core.net.packet.out.ContainerPacket;
import static rs09.tools.stringtools.StringToolsKt.colorize;
/** /**
* Represents the container during a trade session. * Represents the container during a trade session.
* @author 'Vexia * @author 'Vexia
@@ -148,10 +151,23 @@ public final class TradeContainer extends Container {
*/ */
private boolean tradeable(final Item item) { private boolean tradeable(final Item item) {
final ItemDefinition definition = ItemDefinition.forId(item.getId()); final ItemDefinition definition = ItemDefinition.forId(item.getId());
Player target = TradeModule.getExtension(player).getTarget();
boolean playerIsBot = player.getAttribute("not_on_highscores",false);
boolean targetIsBot = target.getAttribute("not_on_highscores",false);
String playerIP = player.getDetails().getIpAddress();
String targetIP = target.getDetails().getIpAddress();
String playerMac = player.getDetails().getMacAddress();
String targetMac = target.getDetails().getMacAddress();
String playerHost = player.getDetails().getCompName();
String targetHost = target.getDetails().getCompName();
if (item.getId() == 11174 || item.getId() == 11173 || item.getId() == 759) { if (item.getId() == 11174 || item.getId() == 11173 || item.getId() == 759) {
return true; return true;
} }
if (player.getIronmanManager().isIronman() || TradeModule.getExtension(player).getTarget() != null && TradeModule.getExtension(player).getTarget().getIronmanManager().isIronman()) { if (player.getIronmanManager().isIronman() || target != null && target.getIronmanManager().isIronman()) {
return false;
}
if ((playerIsBot || targetIsBot) && (playerIP.equals(targetIP) || playerMac.equals(targetMac) || playerHost.equals(targetHost))){
ContentAPI.sendMessage(player, colorize("%RYou can not trade items with your own bot accounts."));
return false; return false;
} }
if (item.getName().equals("Coins") && item.getId() != 995) { if (item.getName().equals("Coins") && item.getId() != 995) {
@@ -5,6 +5,7 @@ import core.game.node.entity.player.Player;
import core.game.node.item.Item; import core.game.node.item.Item;
import core.game.world.update.flag.context.Animation; import core.game.world.update.flag.context.Animation;
import core.tools.RandomFunction; import core.tools.RandomFunction;
import org.rs09.consts.Items;
import java.util.HashMap; import java.util.HashMap;
@@ -25,7 +26,9 @@ public enum FishingOption {
BIG_NET(new Item(305), 16, Animation.create(620), null, "net", Fish.MACKEREL, Fish.COD, Fish.BASS, Fish.SEAWEED), BIG_NET(new Item(305), 16, Animation.create(620), null, "net", Fish.MACKEREL, Fish.COD, Fish.BASS, Fish.SEAWEED),
N_HARPOON(new Item(311), 76, Animation.create(618), null, "harpoon", Fish.SHARK), N_HARPOON(new Item(311), 76, Animation.create(618), null, "harpoon", Fish.SHARK),
H_NET(new Item(303), 1, Animation.create(621), null, "net", Fish.MONKFISH), H_NET(new Item(303), 1, Animation.create(621), null, "net", Fish.MONKFISH),
C_CAGE(new Item(301), 85, Animation.create(619), new Item(14943), "cage", Fish.DARK_CRAB); C_CAGE(new Item(301), 85, Animation.create(619), new Item(14943), "cage", Fish.DARK_CRAB),
KBWANJI_NET(new Item(Items.SMALL_FISHING_NET_303), 5, Animation.create(621), null, "net", Fish.KARAMBWANJI),
KARAMBWAN_VES(new Item(Items.KARAMBWAN_VESSEL_3157), 65, Animation.create(1193), new Item(Items.RAW_KARAMBWANJI_3150), "fish", Fish.KARAMBWAN);
public static HashMap<String,FishingOption> nameMap = new HashMap<>(); public static HashMap<String,FishingOption> nameMap = new HashMap<>();
static{ static{
@@ -13,7 +13,9 @@ public enum FishingSpot {
CAGE_HARPOON(new int[] { 312, 321, 324, 333, 405, 1332, 1399, 3804, 5470, 7046}, FishingOption.CAGE, FishingOption.HARPOON), CAGE_HARPOON(new int[] { 312, 321, 324, 333, 405, 1332, 1399, 3804, 5470, 7046}, FishingOption.CAGE, FishingOption.HARPOON),
NET_HARPOON(new int[] { 313, 322, 334, 406, 1191, 1333, 1405, 1406, 3574, 3575, 5471, 7044 }, FishingOption.BIG_NET, FishingOption.N_HARPOON), NET_HARPOON(new int[] { 313, 322, 334, 406, 1191, 1333, 1405, 1406, 3574, 3575, 5471, 7044 }, FishingOption.BIG_NET, FishingOption.N_HARPOON),
HARPOON_NET(new int[] { 3848, 3849 }, FishingOption.HARPOON, FishingOption.H_NET, FishingOption.BARB_HARPOON), HARPOON_NET(new int[] { 3848, 3849 }, FishingOption.HARPOON, FishingOption.H_NET, FishingOption.BARB_HARPOON),
CRAB_CAGE(new int[] {8665}, FishingOption.C_CAGE); CRAB_CAGE(new int[] {8665}, FishingOption.C_CAGE),
SPOT_KBWANJI(new int[] {1174}, FishingOption.KBWANJI_NET),
SPOT_KARAMBWAN(new int[] {1177}, FishingOption.KARAMBWAN_VES);
public static HashMap<Integer,FishingSpot> spotMap = new HashMap<>(); public static HashMap<Integer,FishingSpot> spotMap = new HashMap<>();
@@ -10,7 +10,6 @@ import core.game.node.Node;
import core.game.node.entity.npc.NPC; import core.game.node.entity.npc.NPC;
import core.game.node.entity.player.Player; import core.game.node.entity.player.Player;
import core.game.node.entity.player.info.Rights; import core.game.node.entity.player.info.Rights;
import core.game.node.entity.skill.runecrafting.abyss.AbyssPlugin;
import core.game.node.item.Item; import core.game.node.item.Item;
import core.game.node.object.Scenery; import core.game.node.object.Scenery;
import core.game.system.task.Pulse; import core.game.system.task.Pulse;
@@ -35,7 +34,6 @@ public class RunecraftingPlugin extends OptionHandler {
@Override @Override
public Plugin<Object> newInstance(Object arg) throws Throwable { public Plugin<Object> newInstance(Object arg) throws Throwable {
addNodes(); addNodes();
PluginManager.definePlugin(new AbyssPlugin());
PluginManager.definePlugin(new TiaraPlugin()); PluginManager.definePlugin(new TiaraPlugin());
PluginManager.definePlugin(new RunePouchPlugin()); PluginManager.definePlugin(new RunePouchPlugin());
PluginManager.definePlugin(new EnchantTiaraPlugin()); PluginManager.definePlugin(new EnchantTiaraPlugin());
@@ -1,440 +0,0 @@
package core.game.node.entity.skill.runecrafting.abyss;
import core.cache.def.impl.NPCDefinition;
import core.cache.def.impl.SceneryDefinition;
import core.game.node.entity.skill.gather.SkillingTool;
import core.game.node.entity.skill.runecrafting.Altar;
import core.game.interaction.OptionHandler;
import core.game.node.Node;
import core.game.node.entity.impl.Animator.Priority;
import core.game.node.entity.npc.NPC;
import core.game.node.entity.player.Player;
import core.game.node.object.Scenery;
import core.game.system.task.Pulse;
import rs09.game.world.GameWorld;
import core.game.world.map.Location;
import core.game.world.update.flag.context.Animation;
import core.game.world.update.flag.context.Graphics;
import core.plugin.Plugin;
import rs09.plugin.PluginManager;
import core.tools.RandomFunction;
/**
* A plugin used to handle the abyss.
* @author Vexia
*/
public final class AbyssPlugin extends OptionHandler {
@Override
public Plugin<Object> newInstance(Object arg) throws Throwable {
for (AbbysalObstacle obstacle : AbbysalObstacle.values()) {
for (int i : obstacle.getObjects()) {
SceneryDefinition.forId(i).getHandlers().put("option:" + obstacle.getOption(), this);
}
}
PluginManager.definePlugin(new AbyssalNPC());
PluginManager.definePlugin(new DarkMageDialogue());
SceneryDefinition.setOptionHandler("exit-through", this);
PluginManager.definePlugin(new ZamorakMageDialogue());
NPCDefinition.forId(2259).getHandlers().put("option:teleport", this);
NPCDefinition.forId(2262).getHandlers().put("option:repair-pouches", this);
return null;
}
@Override
public boolean handle(Player player, Node node, String option) {
switch (option) {
case "teleport":
teleport(player, (NPC) node);
break;
case "repair-pouches":
player.getDialogueInterpreter().open(node.getId(), node, true);
break;
case "exit-through":
Altar altar = Altar.forObject((Scenery) node);
if (altar != null) {
altar.enterRift(player);
}
break;
case "mine":
case "chop":
case "squeeze-through":
case "distract":
case "go-through":
case "burn-down":
final AbbysalObstacle obstacle = AbbysalObstacle.forObject(((Scenery) node));
obstacle.handle(player, ((Scenery) node));
break;
}
return true;
}
/**
* Represents the teleporting to the abyss.
* @param player the player.
*/
public static void teleport(final Player player, final NPC npc) {
player.lock(3);
npc.visualize(new Animation(1979), new Graphics(4));
npc.sendChat("Veniens! Sallakar! Rinnesset!");
player.getSkills().decrementPrayerPoints(100);
player.getSkullManager().checkSkull(player);
GameWorld.getPulser().submit(new Pulse(2, player) {
@Override
public boolean pulse() {
player.getProperties().setTeleportLocation(Location.create(3021, 4847, 0));
npc.getUpdateMasks().reset();
return true;
}
});
}
/**
* Represents an obstacle in an abbsyal.
* @author 'Vexia
* @date 02/11/2013
*/
public enum AbbysalObstacle {
BOIL("burn-down", new Location[] { Location.create(3024, 4833, 0), Location.create(3053, 4830, 0) }, 7165) {
@Override
public void handle(final Player player, final Scenery object) {
if (!player.getInventory().contains(590, 1)) {
player.getPacketDispatch().sendMessage("You don't have a tinderbox to burn it.");
return;
}
player.animate(new Animation(733));
player.lock(3);
GameWorld.getPulser().submit(new Pulse(1, player) {
int count = 0;
@Override
public boolean pulse() {
switch (count) {
case 1:
player.getPacketDispatch().sendMessage("You attempt to burn your way through..");
break;
case 4:
if (RandomFunction.random(3) != 1) {
player.getPacketDispatch().sendMessage("...and manage to burn it down and get past.");
player.getProperties().setTeleportLocation(getLocations()[getIndex(object)]);
return true;
} else {
player.getPacketDispatch().sendMessage("You fail to set it on fire.");
return true;
}
}
count++;
return false;
}
@Override
public void stop() {
super.stop();
player.animate(new Animation(-1, Priority.HIGH));
}
});
}
},
MINE("mine", new Location[] { Location.create(3030, 4821, 0), Location.create(3048, 4822, 0) }, 7158, 7153) {
@Override
public void handle(final Player player, final Scenery object) {
final SkillingTool tool = setTool(true, player);
if (tool == null) {
player.getPacketDispatch().sendMessage("You need a pickaxe in order to do that.");
return;
}
player.animate(tool.getAnimation());
player.lock(3);
GameWorld.getPulser().submit(new Pulse(1, player) {
int count = 0;
@Override
public boolean pulse() {
switch (count) {
case 1:
player.getPacketDispatch().sendMessage("You attempt to mine your way through..");
break;
case 4:
if (RandomFunction.random(3) != 1) {
player.getPacketDispatch().sendMessage("...and manage to break through the rock.");
player.getProperties().setTeleportLocation(getLocations()[getIndex(object)]);
return true;
} else {
player.getPacketDispatch().sendMessage("...but fail to break-up the rock.");
return true;
}
}
count++;
return false;
}
@Override
public void stop() {
super.stop();
player.animate(new Animation(-1, Priority.HIGH));
}
});
}
},
CHOP("chop", new Location[] { Location.create(3050, 4824, 0), Location.create(3028, 4824, 0) }, 7161, 7144) {
@Override
public void handle(final Player player, final Scenery object) {
final SkillingTool tool = setTool(false, player);
if (tool == null) {
player.getPacketDispatch().sendMessage("You need an axe in order to do that.");
return;
}
player.animate(tool.getAnimation());
player.lock(3);
GameWorld.getPulser().submit(new Pulse(1, player) {
int count = 0;
@Override
public boolean pulse() {
switch (count) {
case 1:
player.getPacketDispatch().sendMessage("You attempt to chop your way through...");
break;
case 4:
if (RandomFunction.random(3) != 1) {
player.getPacketDispatch().sendMessage("...and manage to chop down the tendrils.");
player.getProperties().setTeleportLocation(getLocations()[getIndex(object)]);
return true;
} else {
player.getPacketDispatch().sendMessage("You fail to cut through the tendrils.");
return true;
}
}
count++;
return false;
}
@Override
public void stop() {
super.stop();
player.animate(new Animation(-1, Priority.HIGH));
}
});
}
},
SQUEEZE("squeeze-through", new Location[] { Location.create(3048, 4842, 0), Location.create(3031, 4842, 0) }, 7164, 7147) {
@Override
public void handle(final Player player, final Scenery object) {
player.animate(new Animation(1331));
player.lock(3);
player.lock(3);
GameWorld.getPulser().submit(new Pulse(1, player) {
int count = 0;
@Override
public boolean pulse() {
switch (count) {
case 1:
player.getPacketDispatch().sendMessage("You attempt to squeeze through the narrow gap...");
break;
case 2:
player.getPacketDispatch().sendMessage("...and you manage to crawl through.");
player.getProperties().setTeleportLocation(getLocations()[getIndex(object)]);
return true;
}
count++;
return false;
}
@Override
public void stop() {
super.stop();
player.animate(new Animation(-1, Priority.HIGH));
}
});
}
},
DISTRACT("distract", new Location[] { Location.create(3029, 4841, 0), Location.create(3051, 4838, 0) }, 7168, 7150) {
@Override
public void handle(final Player player, final Scenery object) {
int[] emotes = { 855, 856, 857, 858, 859, 860, 861, 862, 863, 864, 865, 866, 2113, 2109, 2111, 2106, 2107, 2108, 0x558, 2105, 2110, 2112, 0x84F, 0x850, 1131, 1130, 1129, 1128, 1745, 3544, 3543, 2836 };
int index = RandomFunction.random(emotes.length);
player.animate(new Animation(emotes[index]));
player.lock(3);
GameWorld.getPulser().submit(new Pulse(1, player) {
int count = 0;
@Override
public boolean pulse() {
switch (count) {
case 1:
player.getPacketDispatch().sendMessage("You use your thieving skills to misdirect the eyes...");
break;
case 4:
if (RandomFunction.random(3) != 1) {
player.getPacketDispatch().sendMessage("...and sneak past while they're not looking.");
player.getProperties().setTeleportLocation(getLocations()[getIndex(object)]);
} else {
player.getPacketDispatch().sendMessage("You fail to distract the eyes.");
return true;
}
return true;
}
count++;
return false;
}
@Override
public void stop() {
super.stop();
player.animate(new Animation(-1, Priority.HIGH));
}
});
}
},
PASSAGE("go-through", new Location[] { Location.create(3040, 4844, 0) }, 7154) {
@Override
public void handle(final Player player, final Scenery object) {
player.getProperties().setTeleportLocation(getLocations()[0]);
}
};
/**
* Constructs a new {@code RunecraftingOptionPlugin} {@code Object}.
* @param locations the locations.
* @param objects the objects.
*/
AbbysalObstacle(final String option, Location[] locations, int... objects) {
this.option = option;
this.objects = objects;
this.locations = locations;
this.option = option;
}
/**
* Represents the option.
*/
private String option;
/**
* Represents the corssing location.
*/
private final Location[] locations;
/**
* Represents the object id.
*/
private final int[] objects;
/**
* Gets the locations.
* @return The locations.
*/
public Location[] getLocations() {
return locations;
}
/**
* Gets the objects.
* @return The objects.
*/
public int[] getObjects() {
return objects;
}
/**
* Method used to get the abbysal obstacle.
* @param object the object.
* @return the <code>AbbysalObstacle</code> or <code>Null</code>.
*/
public static AbbysalObstacle forObject(final Scenery object) {
for (AbbysalObstacle obstacle : values()) {
for (int i : obstacle.getObjects()) {
if (i == object.getId()) {
return obstacle;
}
}
}
return null;
}
/**
* Method used to get the index.
* @param object the object.
* @return the index.
*/
public int getIndex(final Scenery object) {
for (int i = 0; i < objects.length; i++) {
if (getObjects()[i] == object.getId()) {
return i;
}
}
return 0;
}
/**
* Methhod used to handle the obstacle.
* @param player the player.
* @param object the object.
*/
public void handle(final Player player, final Scenery object) {
}
/**
* Gets the option.
* @return The option.
*/
public String getOption() {
return option;
}
/**
* Sets the tool used.
*/
private static SkillingTool setTool(final boolean mining, final Player player) {
SkillingTool tool = null;
if (!mining) {
if (checkTool(player, SkillingTool.DRAGON_AXE)) {
tool = SkillingTool.DRAGON_AXE;
} else if (checkTool(player, SkillingTool.RUNE_AXE)) {
tool = SkillingTool.RUNE_AXE;
} else if (checkTool(player, SkillingTool.ADAMANT_AXE)) {
tool = SkillingTool.ADAMANT_AXE;
} else if (checkTool(player, SkillingTool.MITHRIL_AXE)) {
tool = SkillingTool.MITHRIL_AXE;
} else if (checkTool(player, SkillingTool.BLACK_AXE)) {
tool = SkillingTool.BLACK_AXE;
} else if (checkTool(player, SkillingTool.STEEL_AXE)) {
tool = SkillingTool.STEEL_AXE;
} else if (checkTool(player, SkillingTool.IRON_AXE)) {
tool = SkillingTool.IRON_AXE;
} else if (checkTool(player, SkillingTool.BRONZE_AXE)) {
tool = SkillingTool.BRONZE_AXE;
}
} else {
if (checkTool(player, SkillingTool.RUNE_PICKAXE)) {
tool = SkillingTool.RUNE_PICKAXE;
} else if (checkTool(player, SkillingTool.ADAMANT_PICKAXE)) {
tool = SkillingTool.ADAMANT_PICKAXE;
} else if (checkTool(player, SkillingTool.MITHRIL_PICKAXE)) {
tool = SkillingTool.MITHRIL_PICKAXE;
} else if (checkTool(player, SkillingTool.STEEL_PICKAXE)) {
tool = SkillingTool.STEEL_PICKAXE;
} else if (checkTool(player, SkillingTool.IRON_PICKAXE)) {
tool = SkillingTool.IRON_PICKAXE;
} else if (checkTool(player, SkillingTool.BRONZE_PICKAXE)) {
tool = SkillingTool.BRONZE_PICKAXE;
}
}
return tool;
}
/**
* Checks if the player has a tool and if he can use it.
* @param tool The tool.
* @return {@code True} if the tool is usable.
*/
private static boolean checkTool(final Player player, SkillingTool tool) {
if (player.getEquipment().contains(tool.getId(), 1)) {
return true;
}
return player.getInventory().contains(tool.getId(), 1);
}
}
}
@@ -187,7 +187,7 @@ public final class InteractionPacket implements IncomingPacket {
player.debug("spawn=" + npc.getProperties().getSpawnLocation() + "."); player.debug("spawn=" + npc.getProperties().getSpawnLocation() + ".");
player.debug("Varp ID= " + npc.getDefinition().getConfigId() + " Offset=" + npc.getDefinition().getVarbitOffset() + " Size=" + npc.getDefinition().getVarbitSize()); player.debug("Varp ID= " + npc.getDefinition().getConfigId() + " Offset=" + npc.getDefinition().getVarbitOffset() + " Size=" + npc.getDefinition().getVarbitSize());
handleAIPLegion(player, 0, optionIndex, index); handleAIPLegion(player, 0, optionIndex, index);
if(InteractionListeners.run(npc.getId(),2, option.getName(),player,npc)){ if(InteractionListeners.run(shown.getId(),2, option.getName(),player,npc)){
return; return;
} }
if(PluginInteractionManager.handle(player,shown,option)){ if(PluginInteractionManager.handle(player,shown,option)){
@@ -1,5 +1,6 @@
package core.net.packet.in; package core.net.packet.in;
import api.ContentAPI;
import core.game.node.entity.player.Player; import core.game.node.entity.player.Player;
import core.game.node.entity.player.link.RunScript; import core.game.node.entity.player.link.RunScript;
import core.net.packet.IncomingPacket; import core.net.packet.IncomingPacket;
@@ -29,7 +30,11 @@ public class RunScriptPacketHandler implements IncomingPacket {
} else { } else {
value = buffer.getInt(); value = buffer.getInt();
} }
try {
script.invoke(value); script.invoke(value);
} catch (NumberFormatException nfe){
ContentAPI.sendDialogue(player, "That number's a bit large, don't you think?");
}
player.removeAttribute("runscript"); player.removeAttribute("runscript");
} }
} }
@@ -9,6 +9,7 @@ import core.game.content.consumable.Food
import core.game.content.consumable.effects.HealingEffect import core.game.content.consumable.effects.HealingEffect
import core.game.interaction.DestinationFlag import core.game.interaction.DestinationFlag
import core.game.interaction.MovementPulse import core.game.interaction.MovementPulse
import core.game.interaction.Option
import core.game.node.Node import core.game.node.Node
import core.game.node.`object`.Scenery import core.game.node.`object`.Scenery
import core.game.node.entity.Entity import core.game.node.entity.Entity
@@ -31,6 +32,8 @@ import org.rs09.consts.Items
import rs09.game.ai.AIRepository import rs09.game.ai.AIRepository
import rs09.game.ge.GrandExchangeOffer import rs09.game.ge.GrandExchangeOffer
import rs09.game.ge.OfferManager import rs09.game.ge.OfferManager
import rs09.game.interaction.InteractionListener
import rs09.game.interaction.InteractionListeners
import rs09.game.system.SystemLogger import rs09.game.system.SystemLogger
import rs09.game.system.config.ItemConfigParser import rs09.game.system.config.ItemConfigParser
import rs09.game.world.GameWorld import rs09.game.world.GameWorld
@@ -58,6 +61,26 @@ class ScriptAPI(private val bot: Player) {
return sqrt((n1.location.x - n2.location.x.toDouble()).pow(2.0) + (n2.location.y - n1.location.y.toDouble()).pow(2.0)) return sqrt((n1.location.x - n2.location.x.toDouble()).pow(2.0) + (n2.location.y - n1.location.y.toDouble()).pow(2.0))
} }
fun interact(bot: Player, node: Node?, option: String){
if(node == null) return
val type = when(node){
is Scenery -> InteractionListener.SCENERY
is NPC -> InteractionListener.NPC
is Item -> InteractionListener.ITEM
else -> -1
}
val opt: Option? = node.interaction.options.filter {it != null && it.name.equals(option, true) }.firstOrNull()
if(opt == null){
SystemLogger.logWarn("Invalid option name provided: $option")
return
}
if(!InteractionListeners.run(node.id, type, option, bot, node)) node.interaction.handle(bot, opt)
}
/** /**
* Gets the nearest node with name entityName * Gets the nearest node with name entityName
* @param entityName the name of the node to look for * @param entityName the name of the node to look for
@@ -0,0 +1,167 @@
package rs09.game.ai.general.scriptrepository
import api.ContentAPI
import core.game.world.map.zone.ZoneBorders
import rs09.game.ai.general.ScriptAPI
import rs09.game.ai.skillingbot.SkillingBotAssembler
import rs09.game.interaction.InteractionListener
import rs09.game.interaction.InteractionListeners
@PlayerCompatible
@ScriptName("Gnome Agility Course Script")
@ScriptDescription("Start the script while standing front of the balancing log")
@ScriptIdentifier("gnome_agility")
class GnomeAgility : Script() {
var state = State.INIT
val startzone = ZoneBorders(2473,3436,2475,3437,0)
val afterlog = ZoneBorders(2474,3429,2474,3429,0)
val beforefirstnet = ZoneBorders(2473,3426,2474,3427,0)
val afterfirstnet = ZoneBorders(2471,3424,2476,3424,1)
val beforebranchup = ZoneBorders(2473,3423,2473,3423,1)
val afterbranchup = ZoneBorders(2473,3420,2473,3420,2)
val beforerope = ZoneBorders(2477,3420,2477,3420,2)
val afterrope = ZoneBorders(2483,3420,2483,3420,2)
val beforebranchdown = ZoneBorders(2485,3419,2486,3420,2)
val afterbranchdown = ZoneBorders(2487,3420,2487,3420,0)
val beforesecondnet = ZoneBorders(2483,3425,2488,3425,0)
val aftersecondnet = ZoneBorders(2483,3427,2488,3427,0)
val beforepipe = ZoneBorders(2484,3430,2487,3430,0)
val afterpipe = ZoneBorders(2484,3437,2487,3437,0)
var overlay: ScriptAPI.BottingOverlay? = null
var totalLaps = 0
override fun tick() {
when (state) {
State.INIT -> {
overlay = scriptAPI.getOverlay()
overlay!!.init()
overlay!!.setTitle("Agility Course")
overlay!!.setTaskLabel("Laps Run")
overlay!!.setAmount(0)
state = State.START
}
State.START -> {
if(!startzone.insideBorder(bot)){
scriptAPI.walkTo(startzone.randomLoc)
}
if(startzone.insideBorder(bot)){
state = State.LOG
}
}
State.LOG -> {
val log = scriptAPI.getNearestNode("log balance",true)
if(startzone.insideBorder(bot)) {
scriptAPI.interact(bot, log, "walk-across")
}
if(afterlog.insideBorder(bot)){
state = State.FIRSTNET
}
}
State.FIRSTNET -> {
val firstnet = scriptAPI.getNearestNode("obstacle net",true)
if(!beforefirstnet.insideBorder(bot)){
scriptAPI.walkTo(beforefirstnet.randomLoc)
}
if(beforefirstnet.insideBorder(bot)) {
scriptAPI.interact(bot, firstnet, "climb-over")
}
if(afterfirstnet.insideBorder(bot)){
state = State.BRANCHUP
}
}
State.BRANCHUP -> {
val branchup = scriptAPI.getNearestNode("tree branch", true)
if(!beforebranchup.insideBorder(bot) && !afterbranchup.insideBorder(bot)){
scriptAPI.walkTo(beforebranchup.randomLoc)
}
else if(beforebranchup.insideBorder(bot)){
scriptAPI.interact(bot,branchup,"climb")
}
else if(afterbranchup.insideBorder(bot)){
state = State.ROPE
}
}
State.ROPE -> {
val rope = scriptAPI.getNearestNode("balancing rope",true)
if(!beforerope.insideBorder(bot) && !afterrope.insideBorder(bot)){
scriptAPI.walkTo(beforerope.randomLoc)
}
else if(beforerope.insideBorder(bot)){
scriptAPI.interact(bot,rope,"walk-on")
}
else if(afterrope.insideBorder(bot)){
state = State.BRANCHDOWN
}
}
State.BRANCHDOWN -> {
val branchdown = scriptAPI.getNearestNode("tree branch",true)
if(!beforebranchdown.insideBorder(bot) && !afterbranchdown.insideBorder(bot)){
scriptAPI.walkTo(beforebranchdown.randomLoc)
}
else if(beforebranchdown.insideBorder(bot)){
scriptAPI.interact(bot,branchdown,"climb-down")
}
else if(afterbranchdown.insideBorder(bot)){
state = State.SECONDNET
}
}
State.SECONDNET -> {
val secondnet = scriptAPI.getNearestNode("obstacle net",true)
if(!beforesecondnet.insideBorder(bot) && !aftersecondnet.insideBorder(bot)){
scriptAPI.walkTo(beforesecondnet.randomLoc)
}
else if(beforesecondnet.insideBorder(bot)){
scriptAPI.interact(bot,secondnet,"climb-over")
}
else if(aftersecondnet.insideBorder(bot)){
state = State.PIPE
}
}
State.PIPE -> {
val pipe = scriptAPI.getNearestNode("obstacle pipe",true)
if(!beforepipe.insideBorder(bot) && !afterpipe.insideBorder(bot)){
scriptAPI.walkTo((beforepipe.randomLoc))
}
if(beforepipe.insideBorder(bot)){
scriptAPI.interact(bot,pipe,"squeeze-through")
}
if(afterpipe.insideBorder(bot)){
totalLaps += 1
overlay!!.setAmount(totalLaps)
state = State.START
}
}
}
}
override fun newInstance(): Script {
val script = GnomeAgility()
script.bot = SkillingBotAssembler().produce(SkillingBotAssembler.Wealth.POOR,bot.startLocation)
return script
}
enum class State {
START,
LOG,
FIRSTNET,
BRANCHUP,
ROPE,
BRANCHDOWN,
SECONDNET,
PIPE,
INIT
}
}
@@ -0,0 +1,173 @@
package rs09.game.ai.general.scriptrepository
import api.ContentAPI
import core.game.interaction.DestinationFlag
import core.game.interaction.MovementPulse
import core.game.node.entity.skill.crafting.spinning.SpinningItem
import core.game.node.entity.skill.crafting.spinning.SpinningPulse
import core.game.node.item.Item
import core.game.world.map.Location
import core.game.world.map.path.Pathfinder
import core.game.world.map.zone.ZoneBorders
import org.rs09.consts.Items
import rs09.game.ai.general.ScriptAPI
@PlayerCompatible
@ScriptName("Gnome Stronghold Bowstring")
@ScriptDescription("Start in Gnome Stronghold, South of the Agility Course")
@ScriptIdentifier("gnome_bowstring")
class GnomeBowstring : Script() {
var state = State.PICKING
var stage = 0
var bLadderSwitch = false
var sLadderSwitch = false
val flaxzone = ZoneBorders(2457,3391,2493,3413,0)
val bankbottomLadder = ZoneBorders(2444, 3413, 2445, 3414, 0)
val banktopLadder = ZoneBorders(2445, 3415, 2446, 3414, 1)
val spinnerbottomLadder = ZoneBorders (2475, 3400, 2476, 3399, 0)
val spinnertopLadder = ZoneBorders (2474, 3397, 2476, 3399, 1)
val pick = ZoneBorders(2478, 3394, 339, 9)
val bank = ZoneBorders(2447, 3415, 2444, 3434)
var overlay: ScriptAPI.BottingOverlay? = null
override fun tick() {
when(state){
State.INIT -> {
overlay = scriptAPI.getOverlay()
overlay!!.init()
overlay!!.setTitle("Picking")
overlay!!.setTaskLabel("Flax Picked")
overlay!!.setAmount(0)
}
State.PICKING -> {
bot.interfaceManager.close()
if(!flaxzone.insideBorder(bot)){
scriptAPI.walkTo(flaxzone.randomLoc)
} else if(flaxzone.insideBorder(bot)) {
var flax = scriptAPI.getNearestNode(2646, true)
scriptAPI.interact(bot,flax,"pick")
}
if(bot.inventory.getAmount(Items.FLAX_1779) > 27){
sLadderSwitch = true
state = State.TO_SPINNER
}
}
State.TO_SPINNER -> {
if(sLadderSwitch){
if(!spinnerbottomLadder.insideBorder(bot.location)){
scriptAPI.walkTo(spinnerbottomLadder.randomLoc)
} else {
val ladder = scriptAPI.getNearestNode("Staircase", true)
if(ladder != null){
ladder.interaction.handle(bot, ladder.interaction[0])
sLadderSwitch = false
} else {
scriptAPI.walkTo(spinnerbottomLadder.randomLoc)
}
}
}
if(stage == 0)
Pathfinder.find(bot, Location.create(2475,3399, 1)).walk(bot).also { stage++ }
when(bot.location){
Location.create(2475,3399, 1) -> Pathfinder.find(bot, Location.create(2477, 3399,1)).walk(bot)
Location.create(2477,3399, 1) -> Pathfinder.find(bot, Location.create(2477,3398, 1)).walk(bot)
Location.create(2477,3398, 1) -> Pathfinder.find(bot, Location.create(2476,3398, 1)).walk(bot)
Location.create(2476,3398, 1) -> {
val spinner = scriptAPI.getNearestNode(2644, true)
bot.faceLocation(spinner?.location)
bot.pulseManager.run(object: MovementPulse(bot,spinner, DestinationFlag.OBJECT){
override fun pulse(): Boolean {
bot.faceLocation(spinner?.location)
state = State.SPINNING
return true
}
})
}
}
}
State.SPINNING -> {
bot.pulseManager.run(SpinningPulse(bot, Item(Items.FLAX_1779),bot.inventory.getAmount(Items.FLAX_1779),SpinningItem.FLAX))
sLadderSwitch = true
state = State.FIND_BANK
}
State.FIND_BANK -> {
if(sLadderSwitch){
val ladder = scriptAPI.getNearestNode("staircase", true)
if(ladder != null){
ladder.interaction.handle(bot, ladder.interaction[0])
sLadderSwitch = false
}
}
if(!bankbottomLadder.insideBorder(bot.location) && !spinnertopLadder.insideBorder(bot)){
scriptAPI.walkTo(bankbottomLadder.randomLoc)
}else if(bankbottomLadder.insideBorder(bot)){
bLadderSwitch = true
}
if(bLadderSwitch){
val ladder = scriptAPI.getNearestNode("staircase", true)
if(ladder != null){
ladder.interaction.handle(bot, ladder.interaction[0])
bLadderSwitch = false
}
}
if(banktopLadder.insideBorder(bot)){
state = State.BANKING
}
}
State.BANKING -> {
val bank = scriptAPI.getNearestNode(2213, true)
if(bank != null) {
bot.pulseManager.run(object : MovementPulse(bot, bank, DestinationFlag.OBJECT) {
override fun pulse(): Boolean {
bot.faceLocation(bank.location)
scriptAPI.bankItem(Items.BOW_STRING_1777)
return true
}
})
}
if(ContentAPI.freeSlots(bot) > 27){
bLadderSwitch = true
state = State.RETURN_TO_FLAX
}
}
State.RETURN_TO_FLAX -> {
if(!banktopLadder.insideBorder(bot.location) && bLadderSwitch){
scriptAPI.walkTo(banktopLadder.randomLoc)
} else if(bLadderSwitch){
val ladder = scriptAPI.getNearestNode("Staircase", true)
if(ladder != null){
ladder.interaction.handle(bot, ladder.interaction[0])
bLadderSwitch = false
} else {
scriptAPI.walkTo(banktopLadder.randomLoc)
}
}
if(!flaxzone.insideBorder(bot)){
scriptAPI.walkTo(flaxzone.randomLoc)
} else if(flaxzone.insideBorder(bot)){
state = State.PICKING
}
}
}
}
override fun newInstance(): Script {
TODO("Not yet implemented")
}
}
enum class State {
PICKING,
MINING,
SPINNING,
TO_SPINNER,
FIND_BANK,
RETURN_TO_FLAX,
BANKING,
INIT
}
@@ -85,8 +85,7 @@ object RewardChest {
} }
} }
val rewards: MutableList<Item> = ArrayList() val rewards: MutableList<Item> = ArrayList()
var maxRolls = 2 + RandomFunction.random(0,player.savedData.activityData.barrowKills / 3) var maxRolls = 2 + RandomFunction.random(1,4)
if(maxRolls > 6) maxRolls = 6
for (i in 0 until maxRolls) { for (i in 0 until maxRolls) {
rewards.addAll(DROP_TABLE.roll()) rewards.addAll(DROP_TABLE.roll())
} }
@@ -222,14 +222,15 @@ class NedDialogue(player: Player? = null) : DialoguePlugin(player) {
if (diary == null) { if (diary == null) {
diary = player.achievementDiaryManager.getDiary(DiaryType.LUMBRIDGE) diary = player.achievementDiaryManager.getDiary(DiaryType.LUMBRIDGE)
} }
if (diary!!.isComplete(level, false) && !diary!!.isLevelRewarded(level)) { if (diary!!.isComplete(level, true) && !diary!!.isLevelRewarded(level)) {
player("I've done all the hard tasks in my Lumbridge", "Achievement Diary.") player("I've done all the medium tasks in my Lumbridge", "Achievement Diary.")
stage = 950 stage = 950
} }
if (diary!!.isLevelRewarded(level) && diary!!.isComplete(level, true) && !player.hasItem(diary!!.type.getRewards(level)[0])) { else if (diary!!.isLevelRewarded(level) && diary!!.isComplete(level, true) && !player.hasItem(diary!!.type.getRewards(level)[0])) {
player("I've seemed to have lost my explorer's ring...") player("I've seemed to have lost my explorer's ring...")
stage = 960 stage = 960
} }
else {
options( options(
"What is the Achievement Diary?", "What is the Achievement Diary?",
"What are the rewards?", "What are the rewards?",
@@ -238,6 +239,7 @@ class NedDialogue(player: Player? = null) : DialoguePlugin(player) {
) )
stage = 901 stage = 901
} }
}
901 -> when (buttonId) { 901 -> when (buttonId) {
1 -> { 1 -> {
player("What is the Achievement Diary?") player("What is the Achievement Diary?")
@@ -61,7 +61,10 @@ enum class FarmingPatch(val varpIndex: Int, val varpOffset: Int, val type: Patch
//Spirit Tree //Spirit Tree
ETCETERIA_SPIRIT_TREE(507,8,PatchType.SPIRIT_TREE), ETCETERIA_SPIRIT_TREE(507,8,PatchType.SPIRIT_TREE),
PORT_SARIM_SPIRIT_TREE(507,0,PatchType.SPIRIT_TREE), PORT_SARIM_SPIRIT_TREE(507,0,PatchType.SPIRIT_TREE),
KARAMJA_SPIRIT_TREE(507,16,PatchType.SPIRIT_TREE); KARAMJA_SPIRIT_TREE(507,16,PatchType.SPIRIT_TREE),
//Other
DRAYNOR_BELLADONNA(512, 16, PatchType.BELLADONNA);
companion object { companion object {
@JvmField @JvmField
@@ -1,5 +1,6 @@
package rs09.game.node.entity.skill.farming package rs09.game.node.entity.skill.farming
import api.ContentAPI
import core.cache.def.impl.SceneryDefinition import core.cache.def.impl.SceneryDefinition
import core.game.interaction.OptionHandler import core.game.interaction.OptionHandler
import core.game.node.Node import core.game.node.Node
@@ -23,6 +24,7 @@ class FruitAndBerryPicker : OptionHandler() {
SceneryDefinition.setOptionHandler("pick-papaya",this) SceneryDefinition.setOptionHandler("pick-papaya",this)
SceneryDefinition.setOptionHandler("pick-leaf",this) SceneryDefinition.setOptionHandler("pick-leaf",this)
SceneryDefinition.setOptionHandler("pick-from",this) SceneryDefinition.setOptionHandler("pick-from",this)
SceneryDefinition.setOptionHandler("pick-fruit",this)
return this return this
} }
@@ -58,7 +60,7 @@ class FruitAndBerryPicker : OptionHandler() {
player.pulseManager.run(object : Pulse(animation.duration){ player.pulseManager.run(object : Pulse(animation.duration){
override fun pulse(): Boolean { override fun pulse(): Boolean {
player.animator.animate(animation) player.animator.animate(animation)
player.inventory.add(reward) ContentAPI.addItemOrDrop(player,reward.id,reward.amount)
player.skills.addExperience(Skills.FARMING,plantable.harvestXP) player.skills.addExperience(Skills.FARMING,plantable.harvestXP)
patch.setCurrentState(patch.getCurrentState() - 1) patch.setCurrentState(patch.getCurrentState() - 1)
@@ -30,7 +30,10 @@ class HealthChecker : OptionHandler(){
return true return true
} }
if(!patch.isCheckHealth) return true
player.skills.addExperience(Skills.FARMING,patch.plantable?.checkHealthXP ?: 0.0) player.skills.addExperience(Skills.FARMING,patch.plantable?.checkHealthXP ?: 0.0)
patch.isCheckHealth = false
when(type){ when(type){
PatchType.TREE -> patch.setCurrentState(patch.getCurrentState() + 1) PatchType.TREE -> patch.setCurrentState(patch.getCurrentState() + 1)
PatchType.FRUIT_TREE -> patch.setCurrentState(patch.getCurrentState() - 14) PatchType.FRUIT_TREE -> patch.setCurrentState(patch.getCurrentState() - 14)
@@ -42,7 +45,7 @@ class HealthChecker : OptionHandler(){
patch.nextGrowth = TimeUnit.MINUTES.toMillis(45) patch.nextGrowth = TimeUnit.MINUTES.toMillis(45)
} }
patch.isCheckHealth = false patch.update()
return true return true
} }
@@ -53,7 +53,6 @@ class Patch(val player: Player, val patch: FarmingPatch, var plantable: Plantabl
PatchType.BUSH -> player.varpManager.get(patch.varpIndex).setVarbit(patch.varpOffset,250 + (plantable!!.ordinal - Plantable.REDBERRY_SEED.ordinal)) PatchType.BUSH -> player.varpManager.get(patch.varpIndex).setVarbit(patch.varpOffset,250 + (plantable!!.ordinal - Plantable.REDBERRY_SEED.ordinal))
else -> SystemLogger.logWarn("Invalid setting of isCheckHealth for patch type: " + patch.type.name) else -> SystemLogger.logWarn("Invalid setting of isCheckHealth for patch type: " + patch.type.name)
} }
isCheckHealth = false
} else { } else {
when(patch.type){ when(patch.type){
PatchType.ALLOTMENT,PatchType.FLOWER,PatchType.HOPS -> { PatchType.ALLOTMENT,PatchType.FLOWER,PatchType.HOPS -> {
@@ -63,6 +62,7 @@ class Patch(val player: Player, val patch: FarmingPatch, var plantable: Plantabl
PatchType.BUSH -> { PatchType.BUSH -> {
if(isDead) player.varpManager.get(patch.varpIndex).setVarbit(patch.varpOffset,getBushDeathValue()) if(isDead) player.varpManager.get(patch.varpIndex).setVarbit(patch.varpOffset,getBushDeathValue())
else if(isDiseased && !isDead) player.varpManager.get(patch.varpIndex).setVarbit(patch.varpOffset,getBushDiseaseValue()) else if(isDiseased && !isDead) player.varpManager.get(patch.varpIndex).setVarbit(patch.varpOffset,getBushDiseaseValue())
else player.varpManager.get(patch.varpIndex).setVarbit(patch.varpOffset, plantable?.value ?: 0 + currentGrowthStage)
} }
PatchType.TREE -> { PatchType.TREE -> {
if(isDead) player.varpManager.get(patch.varpIndex).setVarbit(patch.varpOffset + 7,1) if(isDead) player.varpManager.get(patch.varpIndex).setVarbit(patch.varpOffset + 7,1)
@@ -72,6 +72,11 @@ class Patch(val player: Player, val patch: FarmingPatch, var plantable: Plantabl
if(isDead) player.varpManager.get(patch.varpIndex).setVarbit(patch.varpOffset,getFruitTreeDeathValue()) if(isDead) player.varpManager.get(patch.varpIndex).setVarbit(patch.varpOffset,getFruitTreeDeathValue())
else if(isDiseased && !isDead) player.varpManager.get(patch.varpIndex).setVarbit(patch.varpOffset, getFruitTreeDiseaseValue()) else if(isDiseased && !isDead) player.varpManager.get(patch.varpIndex).setVarbit(patch.varpOffset, getFruitTreeDiseaseValue())
} }
PatchType.BELLADONNA -> {
if(isDead) player.varpManager.get(patch.varpIndex).setVarbit(patch.varpOffset, getBelladonnaDeathValue())
else if(isDiseased && !isDead) player.varpManager.get(patch.varpIndex).setVarbit(patch.varpOffset, getBelladonnaDiseaseValue())
else player.varpManager.get(patch.varpIndex).setVarbit(patch.varpOffset, (plantable?.value ?: 0) + currentGrowthStage)
}
else -> {} else -> {}
} }
} }
@@ -110,11 +115,19 @@ class Patch(val player: Player, val patch: FarmingPatch, var plantable: Plantabl
} }
private fun getFruitTreeDiseaseValue(): Int { private fun getFruitTreeDiseaseValue(): Int {
return (plantable?.value ?: 0) + currentGrowthStage + 13 return (plantable?.value ?: 0) + currentGrowthStage + 12
} }
private fun getFruitTreeDeathValue(): Int { private fun getFruitTreeDeathValue(): Int {
return (plantable?.value ?: 0) + currentGrowthStage + 19 return (plantable?.value ?: 0) + currentGrowthStage + 18
}
private fun getBelladonnaDiseaseValue(): Int {
return (plantable?.value ?: 0) + currentGrowthStage + 4
}
private fun getBelladonnaDeathValue(): Int {
return (plantable?.value ?: 0) + currentGrowthStage + 7
} }
private fun grow(){ private fun grow(){
@@ -154,7 +167,7 @@ class Patch(val player: Player, val patch: FarmingPatch, var plantable: Plantabl
} }
} }
if(plantable?.stages ?: 0 > currentGrowthStage){ if(plantable?.stages ?: 0 > currentGrowthStage && !isGrown()){
currentGrowthStage++ currentGrowthStage++
setCurrentState(getCurrentState() + 1) setCurrentState(getCurrentState() + 1)
isWatered = false isWatered = false
@@ -8,5 +8,6 @@ enum class PatchType(val stageGrowthTime: Int) {
BUSH(20), BUSH(20),
FLOWER(5), FLOWER(5),
HERB(20), HERB(20),
SPIRIT_TREE(293) SPIRIT_TREE(293),
BELLADONNA(80)
} }
@@ -67,13 +67,16 @@ enum class Plantable(val itemID: Int, val value: Int, val stages: Int, val plant
RANARR_SEED(5295,39,4,27.0,30.5,0.0,32,PatchType.HERB,Items.GRIMY_RANARR_207), RANARR_SEED(5295,39,4,27.0,30.5,0.0,32,PatchType.HERB,Items.GRIMY_RANARR_207),
TOADFLAX_SEED(5296,47,4,34.0,38.5,0.0,38,PatchType.HERB,Items.GRIMY_TOADFLAX_3049), TOADFLAX_SEED(5296,47,4,34.0,38.5,0.0,38,PatchType.HERB,Items.GRIMY_TOADFLAX_3049),
IRIT_SEED(5297,54,4,43.0,48.5,0.0,44,PatchType.HERB,Items.GRIMY_IRIT_209), IRIT_SEED(5297,54,4,43.0,48.5,0.0,44,PatchType.HERB,Items.GRIMY_IRIT_209),
AVANTOE_SEED(5298,61,4,54.5,61.5,0.0,50,PatchType.HERB,Items.GRIMY_AVANTOE_211), AVANTOE_SEED(5298,204,4,54.5,61.5,0.0,50,PatchType.HERB,Items.GRIMY_AVANTOE_211),
KWUARM_SEED(5299,68,4,69.0,78.0,0.0,56,PatchType.HERB,Items.GRIMY_KWUARM_213), KWUARM_SEED(5299,68,4,69.0,78.0,0.0,56,PatchType.HERB,Items.GRIMY_KWUARM_213),
SNAPDRAGON_SEED(5300,75,4,87.5,98.5,0.0,62,PatchType.HERB,Items.GRIMY_SNAPDRAGON_3051), SNAPDRAGON_SEED(5300,75,4,87.5,98.5,0.0,62,PatchType.HERB,Items.GRIMY_SNAPDRAGON_3051),
CADANTINE_SEED(5301,82,4,106.5,120.0,0.0,67,PatchType.HERB,Items.GRIMY_CADANTINE_215), CADANTINE_SEED(5301,82,4,106.5,120.0,0.0,67,PatchType.HERB,Items.GRIMY_CADANTINE_215),
LANTADYME_SEED(5302,89,4,134.5,151.5,0.0,73,PatchType.HERB,Items.GRIMY_LANTADYME_2485), LANTADYME_SEED(5302,89,4,134.5,151.5,0.0,73,PatchType.HERB,Items.GRIMY_LANTADYME_2485),
DWARF_WEED_SEED(5303,96,4,170.5,192.0,0.0,79,PatchType.HERB,Items.GRIMY_DWARF_WEED_217), DWARF_WEED_SEED(5303,96,4,170.5,192.0,0.0,79,PatchType.HERB,Items.GRIMY_DWARF_WEED_217),
TORSTOL_SEED(5304,103,4,199.5,224.5,0.0,85,PatchType.HERB,Items.GRIMY_TORSTOL_219) TORSTOL_SEED(5304,103,4,199.5,224.5,0.0,85,PatchType.HERB,Items.GRIMY_TORSTOL_219),
//Other
BELLADONNA_SEED(5281, 4, 4, 91.0, 128.0, 0.0, 63, PatchType.BELLADONNA, Items.CAVE_NIGHTSHADE_2398)
; ;
constructor(itemID: Int, value: Int, stages: Int, plantingXP: Double, harvestXP: Double, checkHealthXP: Double, requiredLevel: Int, applicablePatch: PatchType, harvestItem: Int, protectionFlower: Plantable) constructor(itemID: Int, value: Int, stages: Int, plantingXP: Double, harvestXP: Double, checkHealthXP: Double, requiredLevel: Int, applicablePatch: PatchType, harvestItem: Int, protectionFlower: Plantable)
@@ -35,6 +35,7 @@ class GatheringSkillOptionListeners : InteractionListener() {
on(NPC,"bait"){player,node -> return@on fish(player,node,"bait")} on(NPC,"bait"){player,node -> return@on fish(player,node,"bait")}
on(NPC,"harpoon"){player,node -> return@on fish(player,node,"harpoon")} on(NPC,"harpoon"){player,node -> return@on fish(player,node,"harpoon")}
on(NPC,"cage"){player,node -> return@on fish(player,node,"cage")} on(NPC,"cage"){player,node -> return@on fish(player,node,"cage")}
on(NPC,"fish"){player, node -> return@on fish(player,node,"fish") }
} }
fun fish(player: Player, node: Node, opt: String): Boolean{ fun fish(player: Player, node: Node, opt: String): Boolean{
@@ -0,0 +1,468 @@
package core.game.node.entity.skill.runecrafting.abyss
import api.ContentAPI
import rs09.plugin.PluginManager.definePlugin
import rs09.tools.stringtools.colorize
import rs09.game.system.SystemLogger.logInfo
import core.game.node.`object`.Scenery
import core.game.node.entity.impl.Animator
import core.game.node.entity.npc.NPC
import core.game.node.entity.player.Player
import core.game.node.entity.skill.Skills
import core.game.node.entity.skill.gather.SkillingTool
import core.game.node.entity.skill.runecrafting.Altar
import core.game.system.task.Pulse
import core.game.world.map.Location
import core.game.world.update.flag.context.Animation
import core.game.world.update.flag.context.Graphics
import core.tools.RandomFunction
import org.rs09.consts.NPCs
import rs09.game.interaction.InteractionListener
import rs09.game.world.GameWorld
/**
* A plugin used to handle the abyss.
* @author cfunny
*/
class AbyssPlugin : InteractionListener() {
val OBSTACLE = AbbysalObstacle.values().filter { it != AbbysalObstacle.MINE && it != AbbysalObstacle.SQUEEZE }.map { it.option }.toTypedArray()
val miningObstacle = 7158
val agilityObstacle = 7164
override fun defineListeners() {
definePlugin(AbyssalNPC())
definePlugin(DarkMageDialogue())
definePlugin(ZamorakMageDialogue())
on(NPCs.MAGE_OF_ZAMORAK_2259, NPC, "teleport"){ player, node ->
teleport(player, node as NPC)
return@on true
}
on(NPCs.DARK_MAGE_2262, NPC, "repair-pouches"){ player, node ->
player.dialogueInterpreter.open(node.id, node, true)
return@on true
}
on(SCENERY, "exit-through"){ player, node ->
val altar = Altar.forObject(node as Scenery)
altar?.enterRift(player)
return@on true
}
on(SCENERY, *OBSTACLE){ player, node ->
val obstacle = AbbysalObstacle.forObject(node as Scenery)
obstacle!!.handle(player, node as Scenery)
return@on true
}
on(miningObstacle, SCENERY, "mine"){ player, node ->
val obstacle = AbbysalObstacle.forObject(node as Scenery)
obstacle!!.handle(player, node as Scenery)
return@on true
}
on(agilityObstacle, SCENERY, "squeeze-through"){ player, node ->
val obstacle = AbbysalObstacle.forObject(node as Scenery)
obstacle!!.handle(player, node as Scenery)
return@on true
}
}
/**
* Represents an obstacle in an abbsyal.
* @author cfunny
* @date 02/11/2013
*/
enum class AbbysalObstacle(
/**
* Represents the option.
*/
var option: String,
/**
* Represents the corssing location.
*/
val locations: Array<Location>,
/**
* Represents the object id.
*/
vararg val objects: Int
) {
BOIL("burn-down", arrayOf(Location.create(3024, 4833, 0), Location.create(3053, 4830, 0)), 7165) {
override fun handle(player: Player, `object`: Scenery?) {
`object` ?: return
if (!ContentAPI.inInventory(player, 590, 1)) {
ContentAPI.sendMessage(player, "You don't have a tinderbox to burn it.")
return
}
player.animate(Animation(733))
player.lock()
GameWorld.Pulser.submit(object : Pulse(1, player) {
var count = 0
override fun pulse(): Boolean {
when (count) {
1 -> ContentAPI.sendMessage(player, "You attempt to burn your way through..")
4 -> return if (RandomFunction.random(100) < ContentAPI.getStatLevel(
player,
Skills.FIREMAKING
)
) {
ContentAPI.sendMessage(
player,
colorize("%G...and manage to burn it down and get past.")
)
player.properties.teleportLocation = locations[getIndex(`object`)]
player.unlock()
true
} else {
ContentAPI.sendMessage(player, colorize("%RYou fail to set it on fire."))
player.unlock()
true
}
}
count++
return false
}
override fun stop() {
super.stop()
player.animate(Animation(-1, Animator.Priority.HIGH))
}
})
}
},
MINE("mine", arrayOf(Location.create(3030, 4821, 0), Location.create(3048, 4822, 0)), 7158, 7153) {
override fun handle(player: Player, `object`: Scenery?) {
`object` ?: return
logInfo("handled abyss mine")
val tool: SkillingTool = ContentAPI.getTool(player, true) ?: return
if (tool == null) {
ContentAPI.sendMessage(player, "You need a pickaxe in order to do that.")
return
}
player.animate(tool.getAnimation())
player.lock()
GameWorld.Pulser.submit(object : Pulse(1, player) {
var count = 0
override fun pulse(): Boolean {
when (count) {
1 -> ContentAPI.sendMessage(player, "You attempt to mine your way through..")
4 -> return if (RandomFunction.random(100) < ContentAPI.getStatLevel(
player,
Skills.MINING
)
) {
ContentAPI.sendMessage(player, colorize("%G...and manage to break through the rock."))
player.properties.teleportLocation = locations[getIndex(`object`)]
player.unlock()
true
} else {
ContentAPI.sendMessage(player, colorize("%R...but fail to break-up the rock."))
player.unlock()
true
}
}
count++
return false
}
override fun stop() {
super.stop()
player.animate(Animation(-1, Animator.Priority.HIGH))
}
})
}
},
CHOP("chop", arrayOf(Location.create(3050, 4824, 0), Location.create(3028, 4824, 0)), 7161, 7144) {
override fun handle(player: Player, `object`: Scenery?) {
`object` ?: return
val tool: SkillingTool? = setTool(false, player)
if (tool == null) {
player.packetDispatch.sendMessage("You need an axe in order to do that.")
return
}
player.animate(tool.getAnimation())
player.lock()
GameWorld.Pulser.submit(object : Pulse(1, player) {
var count = 0
override fun pulse(): Boolean {
when (count) {
1 -> ContentAPI.sendMessage(player, "You attempt to chop your way through...")
4 -> return if (RandomFunction.random(100) < ContentAPI.getStatLevel(
player,
Skills.WOODCUTTING
)
) {
ContentAPI.sendMessage(player, colorize("%G...and manage to chop down the tendrils."))
player.properties.teleportLocation = locations[getIndex(`object`)]
player.unlock()
true
} else {
ContentAPI.sendMessage(player, colorize("%RYou fail to cut through the tendrils."))
player.unlock()
true
}
}
count++
return false
}
override fun stop() {
super.stop()
player.animate(Animation(-1, Animator.Priority.HIGH))
}
})
}
},
SQUEEZE(
"squeeze-through",
arrayOf(Location.create(3048, 4842, 0), Location.create(3031, 4842, 0)),
7164,
7147
) {
override fun handle(player: Player, `object`: Scenery?) {
`object` ?: return
player.animate(Animation(1331))
player.lock()
GameWorld.Pulser.submit(object : Pulse(1, player) {
var count = 0
override fun pulse(): Boolean {
when (count) {
1 -> ContentAPI.sendMessage(player, "You attempt to squeeze through the narrow gap...")
4 -> return if (RandomFunction.random(100) < ContentAPI.getStatLevel(
player,
Skills.AGILITY
)
) {
ContentAPI.sendMessage(player, colorize("%G...and you manage to crawl through."))
player.properties.teleportLocation = locations[getIndex(`object`)]
player.unlock()
true
} else {
ContentAPI.sendMessage(player, colorize("%RYou fail to squeeze through the narrow gap"))
player.unlock()
true
}
}
count++
return false
}
override fun stop() {
super.stop()
player.animate(Animation(-1, Animator.Priority.HIGH))
}
})
}
},
DISTRACT("distract", arrayOf(Location.create(3029, 4841, 0), Location.create(3051, 4838, 0)), 7168, 7150) {
override fun handle(player: Player, `object`: Scenery?) {
`object` ?: return
val emotes = intArrayOf(
855,
856,
857,
858,
859,
860,
861,
862,
863,
864,
865,
866,
2113,
2109,
2111,
2106,
2107,
2108,
0x558,
2105,
2110,
2112,
0x84F,
0x850,
1131,
1130,
1129,
1128,
1745,
3544,
3543,
2836
)
val index: Int = RandomFunction.random(emotes.size)
player.animate(Animation(emotes[index]))
player.lock()
GameWorld.Pulser.submit(object : Pulse(1, player) {
var count = 0
override fun pulse(): Boolean {
when (count) {
1 -> ContentAPI.sendMessage(player, "You use your thieving skills to misdirect the eyes...")
4 -> return if (RandomFunction.random(100) < ContentAPI.getStatLevel(
player,
Skills.THIEVING
)
) {
ContentAPI.sendMessage(
player,
colorize("%G...and sneak past while they're not looking.")
)
player.properties.teleportLocation = locations[getIndex(`object`)]
player.unlock()
true
} else {
ContentAPI.sendMessage(player, colorize("%RYou fail to distract the eyes."))
player.unlock()
true
}
}
count++
return false
}
override fun stop() {
super.stop()
player.animate(Animation(-1, Animator.Priority.HIGH))
}
})
}
},
PASSAGE("go-through", arrayOf(Location.create(3040, 4844, 0)), 7154) {
override fun handle(player: Player, `object`: Scenery?) {
player.properties.teleportLocation = locations[0]
}
};
/**
* Gets the option.
* @return The option.
*/
/**
* Gets the locations.
* @return The locations.
*/
/**
* Gets the objects.
* @return The objects.
*/
/**
* Method used to get the index.
* @param object the object.
* @return the index.
*/
fun getIndex(`object`: Scenery): Int {
for (i in objects.indices) {
if (objects[i] == `object`.getId()) {
return i
}
}
return 0
}
/**
* Method used to handle the obstacle.
* @param player the player.
* @param object the object.
*/
open fun handle(player: Player, `object`: Scenery?) {}
companion object {
/**
* Method used to get the abbysal obstacle.
* @param object the object.
* @return the `AbbysalObstacle` or `Null`.
*/
fun forObject(`object`: Scenery): AbbysalObstacle? {
for (obstacle in values()) {
for (i in obstacle.objects) {
if (i == `object`.getId()) {
return obstacle
}
}
}
return null
}
/**
* Sets the tool used.
*/
private fun setTool(mining: Boolean, player: Player): SkillingTool? {
var tool: SkillingTool? = null
if (!mining) {
if (checkTool(player, SkillingTool.DRAGON_AXE)) {
tool = SkillingTool.DRAGON_AXE
} else if (checkTool(player, SkillingTool.RUNE_AXE)) {
tool = SkillingTool.RUNE_AXE
} else if (checkTool(player, SkillingTool.ADAMANT_AXE)) {
tool = SkillingTool.ADAMANT_AXE
} else if (checkTool(player, SkillingTool.MITHRIL_AXE)) {
tool = SkillingTool.MITHRIL_AXE
} else if (checkTool(player, SkillingTool.BLACK_AXE)) {
tool = SkillingTool.BLACK_AXE
} else if (checkTool(player, SkillingTool.STEEL_AXE)) {
tool = SkillingTool.STEEL_AXE
} else if (checkTool(player, SkillingTool.IRON_AXE)) {
tool = SkillingTool.IRON_AXE
} else if (checkTool(player, SkillingTool.BRONZE_AXE)) {
tool = SkillingTool.BRONZE_AXE
}
} else {
if (checkTool(player, SkillingTool.RUNE_PICKAXE)) {
tool = SkillingTool.RUNE_PICKAXE
} else if (checkTool(player, SkillingTool.ADAMANT_PICKAXE)) {
tool = SkillingTool.ADAMANT_PICKAXE
} else if (checkTool(player, SkillingTool.MITHRIL_PICKAXE)) {
tool = SkillingTool.MITHRIL_PICKAXE
} else if (checkTool(player, SkillingTool.STEEL_PICKAXE)) {
tool = SkillingTool.STEEL_PICKAXE
} else if (checkTool(player, SkillingTool.IRON_PICKAXE)) {
tool = SkillingTool.IRON_PICKAXE
} else if (checkTool(player, SkillingTool.BRONZE_PICKAXE)) {
tool = SkillingTool.BRONZE_PICKAXE
}
}
return tool
}
/**
* Checks if the player has a tool and if he can use it.
* @param tool The tool.
* @return `True` if the tool is usable.
*/
private fun checkTool(player: Player, tool: SkillingTool): Boolean {
return if (player.equipment.contains(tool.getId(), 1)) {
true
} else player.inventory.contains(tool.getId(), 1)
}
}
/**
* Constructs a new `RunecraftingOptionPlugin` `Object`.
* @param locations the locations.
* @param objects the objects.
*/
init {
option = option
}
}
companion object {
/**
* Represents the teleporting to the abyss.
* @param player the player.
*/
fun teleport(player: Player, npc: NPC) {
player.lock(3)
npc.visualize(Animation(1979), Graphics(4))
npc.sendChat("Veniens! Sallakar! Rinnesset!")
player.skills.decrementPrayerPoints(100.0)
player.skullManager.checkSkull(player)
GameWorld.Pulser.submit(object : Pulse(2, player) {
override fun pulse(): Boolean {
player.properties.teleportLocation = Location.create(3021, 4847, 0)
npc.updateMasks.reset()
return true
}
})
}
}
}
@@ -113,7 +113,7 @@ class FarmingState(player: Player? = null) : State(player) {
} }
} }
if((savedState - (patch?.plantable?.value ?: 0)) > patch.plantable?.value ?: 0 + patch.currentGrowthStage){ if((savedState - (patch?.plantable?.value ?: 0)) > patch.currentGrowthStage){
patch.setCurrentState(savedState) patch.setCurrentState(savedState)
} else { } else {
patch.setCurrentState((patch.plantable?.value ?: 0) + patch.currentGrowthStage) patch.setCurrentState((patch.plantable?.value ?: 0) + patch.currentGrowthStage)
@@ -29,7 +29,7 @@ object PacketWriteQueue {
@JvmStatic @JvmStatic
fun flush(){ fun flush(){
while(!PacketsToWrite.isEmpty()){ while(!PacketsToWrite.isEmpty()){
val p = PacketsToWrite.poll() val p = PacketsToWrite.poll() ?: continue
write(p.out,p.context) write(p.out,p.context)
} }
} }