package com.rs2.event; import com.google.common.base.Preconditions; import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.Multimap; import com.rs2.game.players.Player; import com.rs2.util.ClassUtils; import java.util.Collection; import java.util.Optional; import java.util.function.Consumer; /** * A universal event provider which posts, provides and deprives subscribers. * * @author Ryley Kimmel */ public final class UniversalEventProvider implements EventProvider { /** * A {@link Multimap} of {@link Event} classes to subscribers. */ private final Multimap, EventSubscriber> events = ArrayListMultimap.create(); /** * The universal context of this event provider. */ private final EventContext context = new UniversalEventContext(); @SuppressWarnings("unchecked") @Override public void provideSubscriber(EventSubscriber subscriber) { checkSubscriber(subscriber, annotation -> events.put(annotation.value(), (EventSubscriber) subscriber)); } @SuppressWarnings("unchecked") @Override public void depriveSubscriber(EventSubscriber subscriber) { checkSubscriber(subscriber, annotation -> events.remove(annotation.value(), (EventSubscriber) subscriber)); } private void checkSubscriber(EventSubscriber subscriber, Consumer consumer) { Optional optional = ClassUtils.getAnnotation(subscriber.getClass(), SubscribesTo.class); Preconditions.checkArgument(optional.isPresent(), String.format("%s is not annotated with @SubscribesTo", subscriber.getClass())); consumer.accept(optional.get()); } @Override public void post(Player player, E event) { Collection> subscribers = events.get(event.getClass()); for (EventSubscriber subscriber : subscribers) { /* Check to be sure we can subscribe to the event. */ if (subscriber.test(event)) { subscriber.subscribe(context, player, event); /* If the chain is broken, don't continue parsing subscribers. */ if (context.isChainBroken()) { break; } } } context.repairSubscriberChain(); } public Multimap, EventSubscriber> getEvents() { return events; } }