Modular Plugins

Place these in any class

Darkan features proprietary plugins which handle triggers activated by the player. Here are the ones which exist in the current revision:

In order to use these in any class just add the @PluginEventHandler annotation...

@PluginEventHandler
public class Lighthouse {

	public static ObjectClickHandler handleEntranceLadders = new ObjectClickHandler(new Object[] { 4383, 4412 }, e -> {
		e.getPlayer().useLadder(e.getObjectId() == 4412 ? WorldTile.of(2510, 3644, 0) : WorldTile.of(2519, 9995, 1));
	});

	public static ObjectClickHandler handleDoors = new ObjectClickHandler(new Object[] { 4545, 4546 }, e -> {
		Doors.handleDoor(e.getPlayer(), e.getObject());
	});

	public static ObjectClickHandler handleLadders = new ObjectClickHandler(new Object[] { 4413, 4485 }, e -> {
		e.getPlayer().useLadder(e.getPlayer().transform(0, e.getObjectId() == 4485 ? 3 : -3, e.getObjectId() == 4485 ? -1 : 1));
	});
}
@PluginEventHandler
public class Catherby {

	public static ObjectClickHandler taverlyDungeonClimbToWaterObelisk = new ObjectClickHandler(new Object[] { 32015 }, new WorldTile[] { WorldTile.of(2842, 9824, 0) }, e -> {
		e.getPlayer().ladder(WorldTile.of(2842, 3423, 0));
	});
}
@PluginEventHandler
public class MelzarsMaze {
	public static ObjectClickHandler handleFrontDoor = new ObjectClickHandler(new Object[] { FRONT_DOOR }, e -> {
		Player p = e.getPlayer();
		GameObject obj = e.getObject();
		if(p.getInventory().containsItem(new Item(MELZAR_MAZE_KEY, 1)))
			handleDoor(p, obj);
		else
			p.startConversation(new Conversation(e.getPlayer()) {
				{
					addPlayer(HeadE.CALM_TALK, "The door seems to need a key...");
					create();
				}
			});
	});

	public static ObjectClickHandler handleExitDoors = new ObjectClickHandler(new Object[] { 2602, 32968 }, e -> {
		Player p = e.getPlayer();
		GameObject obj = e.getObject();
		if(p.getX() >= obj.getX())
			if(p.getX() >= obj.getX()) {
				handleDoor(p, obj);
				return;
			}
		p.startConversation(new Conversation(e.getPlayer()) {
			{
				addPlayer(HeadE.CALM_TALK, "The door seems to be locked from the other side...");
				create();
			}
		});
	});

	static final int MELZAR_BASEMENT_REGION = 11670;
	public static NPCDeathHandler handleBlueKeyDrop = new NPCDeathHandler(ZOMBIE_BLUE_KEY, e -> {
		if(e.getNPC().getRegionId() == MELZAR_BASEMENT_REGION && e.killedByPlayer())
			World.addGroundItem(new Item(BLUE_KEY, 1), WorldTile.of(e.getNPC().getTile()), (Player)e.getKiller());
	});

	public static NPCDeathHandler handleGreenKeyDrop = new NPCDeathHandler(LESSER_DEMON_GREEN_KEY, e -> {
		if(e.getNPC().getRegionId() == MELZAR_BASEMENT_REGION && e.killedByPlayer())
			World.addGroundItem(new Item(GREEN_KEY, 1), WorldTile.of(e.getNPC().getTile()), (Player)e.getKiller());
	});
	//etc...
}

These plugins are children to PluginHandler generic and each are implemented for a specific case in the Darkan World. The header, for example the COUNT_DRAYNOR_ID below is the trigger which is handled by the plugin. These plugins contain the code activated by said trigger of the plugin type/generic. Below is the natural progression of abstraction of an example plugin and its trigger...

	public static ItemOnNPCHandler hammerOnCountDraynor = new ItemOnNPCHandler(COUNT_DRAYNOR_ID, e -> {
		if (e.getItem().getId() != STAKE_HAMMER && e.getItem().getId() != REGULAR_HAMMER)
			return;
		if ((e.getNPC() instanceof CountDraynorBoss boss) && boss.isLocked()) {
			boss.die(e.getPlayer());
			return;
		}
		e.getPlayer().sendMessage("I must weaken him first");
	});
package com.rs.plugin.handlers;

import java.util.function.Consumer;
import com.rs.plugin.events.ItemOnNPCEvent;

public class ItemOnNPCHandler extends PluginHandler<ItemOnNPCEvent> {
	private boolean checkDistance = true;

	public ItemOnNPCHandler(boolean checkDistance, Object[] namesOrIds, Consumer<ItemOnNPCEvent> handler) {
		super(namesOrIds, handler);
		this.checkDistance = checkDistance;
	}
	
	public ItemOnNPCHandler(int id, Consumer<ItemOnNPCEvent> handler) {
		super(new Object[] { id }, handler);
	}
	
	public ItemOnNPCHandler(String name, Consumer<ItemOnNPCEvent> handler) {
		super(new Object[] { name }, handler);
	}

	public ItemOnNPCHandler(Object[] namesOrIds, Consumer<ItemOnNPCEvent> handler) {
		super(namesOrIds, handler);
	}

	public boolean isCheckDistance() {
		return checkDistance;
	}
}
package com.rs.plugin.handlers;

import java.util.function.Consumer;

import com.rs.plugin.events.PluginEvent;

public abstract class PluginHandler<T extends PluginEvent> {
	protected Object[] keys;
	protected Consumer<T> handler;

	public PluginHandler(Object[] keys, Consumer<T> handler) {
		this.keys = keys;
		this.handler = handler;
	}

	public boolean handleGlobal(T e) {
		return false;
	}
	
	public Object getObj(T e) {
		return null;
	}

	public Object[] keys() {
		return keys;
	}

	public Consumer<T> getHandler() {
		return handler;
	}
}

For every plugin there is an event handler which manages the the event upon trigger, notated as "e" for event. These contain distinct functions which can be used to manipulate the world and player and hold private properties available within the plugin. Compare the above e-> {e.getPlayer()} and others with the below...

public class ItemOnNPCEvent implements PluginEvent {
	//...  
	private Player player;
	private NPC npc;
	private Item item;
	private boolean atNPC;

	public ItemOnNPCEvent(Player player, NPC npc, Item item, boolean atNPC) {
		this.player = player;
		this.npc = npc;
		this.item = item;
		this.atNPC = atNPC;
	}

	public Player getPlayer() {
		return player;
	}

	public NPC getNPC() {
		return npc;
	}

	public Item getItem() {
		return item;
	}

	public boolean isAtNPC() {
		return atNPC;
	}
	//...
}
public class ItemClickEvent implements PluginEvent {
	//...
	private Player player;
	private Item item;
	private String option;
	private boolean isEquipped;
	private int slotId;

	public ItemClickEvent(Player player, Item item, int slotId, String option) {
		this(player, item, slotId, option, false);
	}

	public ItemClickEvent(Player player, Item item, int slotId, String option, boolean isEquipped) {
		this.player = player;
		this.item = item.setSlot(slotId);
		this.option = option;
		this.isEquipped = isEquipped;
		this.slotId = slotId;
	}

	public boolean isEquipped() {
		return isEquipped;
	}

	public String getOption() {
		return option;
	}

	public Player getPlayer() {
		return player;
	}

	public Item getItem() {
		return item;
	}

	public int getSlotId() {
		return slotId;
	}
  //...
}

public class NPCClickEvent implements PluginEvent {
	//...
	private Player player;
	private NPC npc;
	private int opNum;
	private String option;
	private boolean atNPC;

	public NPCClickEvent(Player player, NPC npc, int opNum, boolean atNPC) {
		this.player = player;
		this.npc = npc;
		this.opNum = opNum;
		this.atNPC = atNPC;
		option = npc.getDefinitions(player).getOption(opNum-1);
	}

	public Player getPlayer() {
		return player;
	}

	public NPC getNPC() {
		return npc;
	}

	public int getNPCId() {
		return npc.getId();
	}

	public String getOption() {
		return option;
	}

	public int getOpNum() {
		return opNum;
	}

	public boolean isAtNPC() {
		return atNPC;
	}
	//...
}