Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Add Event Filters #927

Merged
merged 1 commit into from
Dec 7, 2015
Merged

[WIP] Add Event Filters #927

merged 1 commit into from
Dec 7, 2015

Conversation

Deamon5550
Copy link
Contributor

Impl

Event Filtering

This branch adds annotation based event filtering to assist with reducing the amount of boilerplate necessary while writing event listeners.

Event type Filters

These filters are applied to the method and apply a range of filters based on the event object.

Include

This annotation allows you to listen to a supertype event (such as EntityEvent) and filter it to only receive a specified subset of the event type's subclasses.

    @Listener
    @Include({ InteractBlockEvent.Secondary.class })
    public void include(InteractBlockEvent event) {
        // This listener will only fire if the event is one of the included types
    }
Exclude

The opposite of include, this allows you to listen to a supertype event and filter it to not receive a specified subset of the event type's subclasses.

    @Listener
    @Exclude({ InteractBlockEvent.Secondary.class })
    public void exclude(InteractBlockEvent event) {
        // This listener will only fire if the event is not one of the excluded types
    }
IsCancelled

This will filter the event such that your listener will only be called if the event has been cancelled by a previous event listener. This is essentially the opposite of the ignoreCancelled flag on the Listener annotation.

    @Listener(order = Order.LATE, ignoreCancelled = false)
    @IsCancelled
    public void cancel(InteractBlockEvent.Secondary event) {
        // This listener will only fire if the event was previously cancelled
    }
Parameter Sources

These annotations are applied to additional parameters in the event handler method and specify a source for that parameter. If an object matching the source and type is not found in the cause then your listener is not called.

First

This gets the first object from the event Cause matching the parameter type.

A fairly typical event listener for a player event will go something like the following

    @Listener
    public void onInteract(InteractBlockEvent.Secondary event) {
        Optional<Player> player = event.getCause().first(Player.class);
        if(player.isPresent()) {
            //do something
        }
    }

With the @First annotation this can be simplified to the following

    @Listener
    public void first(InteractBlockEvent.Secondary event, @First Player player) {
        // This listener will fire if the event cause has a player
        // The player parameter will be the first player in the cause chain
    }
Last

Equivalent to First except it calls Cause#last(Class).

All

The All annotation allows you to receive all cause objects of a certain type. It must be applied to an array type and is equivalent to Cause#allOf(Class)

    @Listener
    public void all(InteractBlockEvent.Secondary event, @All Player[] players) {
        // This listener will fire if the event cause has at least one player
        // players will contain all players in the cause chain
    }

By default your listener will be skipped if the returned array would be empty, this can be disabled however by setting the ignoreEmpty flag to false.

    @Listener
    public void all(InteractBlockEvent.Secondary event, @All(ignoreEmpty = false) BiomeTypes[] players) {
        // This listener will always fire, as even if there are no BiomeTypes
        // objects in the cause chain (and there won't be) its set to not ignore
        // empty and therefore will simply return an empty array
    }
Parameter Filters

These filters apply additional conditions to a parameter. These require that the paramter also have a parameter source annotation (see above).

Has

This takes a data manipulator type and checks that the annotated data holder has a data manipulator of the specified type. If the object is not a DataHolder or does not have a matching manipulator then your listener is not called. Equivalent to DataHolder#has(Class).

Supports

Similar to Has except the it is only checked that the DataHolder supports the given data manipulator type. Equivalent to DataHolder#supports(Class).

A full example plugin can be found here

TODO:

  • Add Root cause annotation
  • remove ignoreCancelled from Listener

@Zidane
Copy link
Member

Zidane commented Nov 20, 2015

I'm really onboard with this concept because I can see it being used to cut out a few lines of code :P. I know I'd use it myself.

@ST-DDT
Copy link
Member

ST-DDT commented Nov 20, 2015

i agree although i would prefer if the event filter (subtype or cancelled state) to be applied to the method instead of (or alternativly) the param because its easier to read there.

@stephan-gh
Copy link
Contributor

Not sure if the annotations should be really subclasses, most code styles (including ours) will always import this like @EventTypeFilters.IsCancelled instead of @IsCancelled

@ghost
Copy link

ghost commented Nov 20, 2015

Maybe we should remove the ignoreCancelled value from @Listener and move that whole functionality to Event Filter annotations.

@Deamon5550
Copy link
Contributor Author

@ST-DDT Could do yeah, it would change the target type which would be good because it would prevent you from applying these filters to any other parameters.

@Minecrell Thats a good point I'll move them out.

@Saladoc I thought about that but the two functions are a little different. Although while thinking about it perhaps I could add a tristate to it to specify the three cases NOT_CANCELLED, IGNORE_CANCELLED, and ONLY_CANCELLED.

@Retention(RetentionPolicy.RUNTIME)
public @interface First {

}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing newline at EOF

@stephan-gh stephan-gh changed the title Add Event Filters [WIP] Add Event Filters Nov 28, 2015
@Deamon5550 Deamon5550 force-pushed the feature/event-filter branch 3 times, most recently from 9a87f46 to 214503a Compare December 7, 2015 06:45
Deamon5550 added a commit that referenced this pull request Dec 7, 2015
Deamon5550 added a commit that referenced this pull request Dec 7, 2015
Deamon5550 added a commit that referenced this pull request Dec 7, 2015
@Deamon5550 Deamon5550 merged commit c7a9590 into master Dec 7, 2015
@ST-DDT
Copy link
Member

ST-DDT commented Dec 7, 2015

Nice

@Deamon5550 Deamon5550 deleted the feature/event-filter branch December 19, 2015 20:09
@Azatik
Copy link

Azatik commented Dec 29, 2015

The annotation ignoreCancelled has been removed. Is there an analogue?

@JBYoshi
Copy link
Member

JBYoshi commented Dec 29, 2015

Add @IsCancelled(Tristate.FALSE) before your method in addition to @Listener.

@Azatik
Copy link

Azatik commented Dec 30, 2015

@JBYoshi, i wrote code:

@Listener (order = BEFORE_POST)
@IsCancelled(Tristate.FALSE)
public void onChangeGrave(ChangeBlockEvent.Break event) {
    ...
    event.setCancelled(false);
}

The event will still be canceled.
Note: The old issue: #900

@simon816
Copy link
Contributor

To replicate the old ignoreCancelled you now do @IsCancelled(Tristate.UNDEFINED)

@Azatik
Copy link

Azatik commented Dec 30, 2015

@simon816, thanks. Everything works well.

@gabizou gabizou mentioned this pull request Feb 28, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

8 participants