Skip to content

Custom Events

Hempfest edited this page Nov 16, 2021 · 11 revisions

About

Labyrinth provides you with an honest and true custom event system with subscription modularity and event handling. No parent interface required for listeners, and less restriction to static methods!

Listening to events

The @Subscribe annotation

Subscribe marks methods to be used as event handlers. It can be applied to any public method with one parameter that extends Vent. The method may be a void method but also can have a return type, that can be automatically processed (read further!). The annotation has the following parameters:

@Subscribe(priority = MEDIUM, processCancelled = true, resultProcessors = {"foo"})

priority = [optional] the priorisation this method will have in concurrency with other listeners processCancelled = [optional] whether cancelled events may be passed to this method or not resultProcessors = [optional] if this method has a return type, the result will be automatically passed to all extend-annotated methods with any contained identifier.

The @Extend annotation

Extend marks methods to work as consumer or function which is automatically bound via a key.

@Extend(identifier = "foo", resultProcessors = {"bar"})

identifier = [obligatory] the key by which this method will be recognised. resultProcessors = [optional] same purpose as @Subscribe#resultProcessors()

Example of usage:
public class TestListener {

	private final String[] list = new String[]{"Hempfest", "Boops", "Beeps"};
	private final Set<String> toCheck = new HashSet<>():

	@Subscribe(priority = Vent.Priority.HIGH, resultProcessors = {"registerLoginAttempt"})
	public String onJoin(DefaultEvent.Join e) {
		Player p = e.getPlayer();
		if (Arrays.stream(list).noneMatch(s -> p.getName().equals(s))) {
			e.setCancelled(true);
			e.setKickMessage("You are not whitelisted.");
		}
		return p.getName();
	}
	
	@Extend(identifier = "registerLoginAttempt")
	public void registerPotentialNewPlayer(String playerName) {
	    toCheck.add(playerName);
	}
	


	@Subscribe
	public void onCommunicate(DefaultEvent.Communication e) {
		DefaultEvent.Communication.Type type = e.getCommunicationType();
		Player p = e.getPlayer();
		switch (type) {
			case COMMAND:
				e.getCommand().ifPresent(c -> {
					String label = c.getText();
					if (label.equals("test")) {
						p.sendMessage("It works!");
						e.setCancelled(true);
					}
				});
				break;
			case CHAT:
				e.getMessage().ifPresent(m -> {
					BaseComponent[] b = new BaseComponent[]{TextLib.getInstance().textHoverable("", "&6&l" + p.getName(), "&7:&r " + m.getMessage().toLegacyText(), "&fHello!")};
					m.set(b);
				});
				break;

		}
	}
}

Registering listeners

You have options on how you wish to listen to labyrinth events. You either can either use classes that hold the methods and register one or multiple instances. Be careful that you only should register one instance of every class with annotated static methods. The other option uses so-called subscriptions.

Using objects and methods

You need to register a listener instance to the Vent service.

LabyrinthProvider.getInstance().getEventMap().subscribe(Plugin plugin, Object listener);
Using Subscriptions

Sample registration of two listeners

// #finish automatically registers the listener
Vent.Subscription.Builder.target(DefaultEvent.Join.class).assign(Vent.Priority.HIGH).from(Plugin plugin).use((event, subscription) -> {}).finish();

// Or you just can register it manually after manipulating it
Subscription<DefaultEvent.Join> sub = new Vent.Subscription(DefaultEvent.Join.class, Plugin plugin, Vent.Priority.HIGH, (event, subscription) -> {});
LabyrinthProvider.getInstance().getEventMap().subscribe(sub);

Creating events

Creating events is simple and only requires an extension of the Vent class.

public class PlayerTestEvent extends Vent {

	private final Player p;

	public PlayerTestEvent(Player p) {
		super(false);
		this.p = p;
	}

	public Player getPlayer() {
		return p;
	}

	
}

Calling events

Calling the events is pretty easy and works via Vent.Call instances. You can run the event synchronously via #run or async via #complete Or you can just pass the runtime type via#run(Runtime) Both methods somehow return the processed event object.

		PlayerTestEvent event = new Vent.Call<>(new PlayerTestEvent(player)).run();
        //further process the event
		if (!event.isCancelled()) {
			// do stuff.
		}

Full example

Will be published soon™

Clone this wiki locally