[WIP] Refactor and implement ChangeDataHolderEvent.ValueChange#1695
Closed
Aaron1011 wants to merge 7 commits into
Closed
[WIP] Refactor and implement ChangeDataHolderEvent.ValueChange#1695Aaron1011 wants to merge 7 commits into
Aaron1011 wants to merge 7 commits into
Conversation
This was referenced Nov 19, 2017
kashike
reviewed
Nov 19, 2017
| * @param <E> The type of value | ||
| * @return The created event, if available | ||
| */ | ||
| <E> Optional<ChangeDataHolderEvent.ValueChange> offerWithEvent(Key<? extends BaseValue<E>> key, E value, Cause cause); |
liach
reviewed
Nov 19, 2017
| /** | ||
| * Represents values that were successfully offered to the {@link DataHolder} | ||
| */ | ||
| SUCCESSFUL, |
Contributor
Author
There was a problem hiding this comment.
This corresponds to #getSuccessfulData, so it should be called SUCCESSFUL
Contributor
There was a problem hiding this comment.
Does it also refer to the succeed data after replacement?
liach
reviewed
Nov 19, 2017
| /** | ||
| * The id of the {@link Key} to use. This <b>must</b> be registered when the corresponding event listener | ||
| * for this annotation is registered. | ||
| * @return |
liach
reviewed
Nov 19, 2017
| * with {@link ChangeDataHolderEvent.ValueChange} | ||
| * @return | ||
| */ | ||
| DataTransactionResult.DataCategory [] from() default {DataTransactionResult.DataCategory.SUCCESSFUL}; |
|
Please excuse me if this is a stupid question, but would the As an example: // Prevent entities that aren't called Fred from being tamed
void onEntityTame(TameEntityEvent event, @GetKey("DISPLAY_NAME") Text name) {
if (!name.toPlain().equals("Fred")) { event.setCancelled(true); }
}I know you said "[the] event filter can also be used with a |
Contributor
|
Going to close this for now due to #1728 and SpongePowered/Sponge#1670 which provide a method of implementing and listening to the event. If you'd like to make other changes, open a new PR with those in relation to what is now in the API and implementation. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
SpongeAPI | SpongeCommon | SpongeForge
This pull request implements
ChangeDataHolderEvent.ValueChange, and extends the Data API to better support plugins using the event.Overview
This PR makes three main sets of changes: Improvements to
ChangeDataHolderEvent.ValueChange, the addition of a new event filter@GetKey, and the addition of extra utility methods to the Data API.ChangeDataHolderEvent.ValueChange
For consistency with other events, this event now follows the
getOriginalXXX,getXXX,setXXXformat for its methods.To give maximum flexibility to plugins, the previous
DataTransactionResultis completely replaced when callingsetChanges. Plugins wishing to preserve existing changes can useDataTransactionResult$Builder#absorbResultto combine their desired changes with previous changes.@GetKeyevent filterAs demonstrated in the attached demonstration plugin, the event can be somewhat cumbersome to use. To make it easier for plugins to listen for data changes, a new event filter
@GetKeyis added. Using the specified key id, this event filter sets the annotated parameter to the value retrieved from either aChangeDataHolderEvent.ValueChange, or aDataHolder.For example, this listener:
will be called with
foodLevelset to the value associated withKeys.FOOD_LEVEL. If a value forKeys.FOOD_LEVELis not present in the event, the listener will not be called. The parameter can be specified as the underlying value (e.g.int), aValue, or anImmutableValue.As described in the javadocs for
@GetKey, this event filter can also be used with aDataHolder.Data API Changes
To support the usage of this event, several changes have been made to the Data API. The most significant of these is
DataHolder#offerWithEvent. This method is used by the implementation (and optionally by plugins) to fire aChangeDataHolderEvent.ValueChangeevent. This method retrieves the current value from theDataHolder, constructs aDataTransactionResultcontaining the old and new values, and fires theChangeDataHolderEvent.ValueChangeevent. If the event is not cancelled, theSUCCESSvalues will be actually offered to theDataHolder.However, this method isn't sufficient to make
ChangeDataHolderEvent.ValueChangeeasily usable for plugins. To makeDataTransactionResulteasier to use even without the event filter, a new enumDataCategoryis added. This enum can be used with@GetKey, as well as the newly addedgetandgetKeymethods onDataTransactionResult, to lookup a value from the sucessful, rejected, or replaced set of values. (It also has the advantage of greatly simplifying the implementation of@GetKey)getDefault and getDefaultValue
Finally, two methods are added to
ValueContainer-getDefaultandgetDefaultValue. These methods solve the problem of creating a new value wrapper (a subtype ofValueorImmutableValue) given the underlying object.For example, consider
Keys.FOOD_LEVEL. Since this is aMutableBoundedValue, it has extra information associated with it - a minimum and a maximum value. These pieces of additional information may vary depending on theDataHolderthe value came from. If a plugin wants to create a newMutableBoundedValuefor a food level - if it wants to add it to aChangeDataHolderEvent.ValueChange, for instance - it must first get access to an existing value from the properDataHolder. Otherwise, it has no way of knowing the proper minimum and maximum values.Unfortunately, the current Data API only allows retrieving a
ValueorImmutableValuewhen it is already stored in aDataContainer. WhileFOOD_LEVELwill always exist on a player, this will not be the case for other values. The newgetDefaultandgetDefaultValuesallow a plugin to create such a value - crucially, with all additional data (e.g. minimum and maximum values) filled in. This ensures that a plugin can always add a properImmutableValueto aChangeDataHolderEvent.ValueChangeevent, even if it doesn't yet exist on the targetDataHolder.TODO
This pull request is not yet complete. There are still many unresolved issues that need to be addressed:
ChangeDataHolderEvent.ValueChange, as the name suggests, only deals with values. Does it make sense to have an event forDataManipulatorchanges?BaseValueinto either aValueorImmutableValue. While these are the only subclasses that currently exist, the API provides no guarantee that this will always be the case. Should we add convenience methods for getting a concreteValue/ImmutableValuefrom aBaseValue, or do we not want to commit to this in the API?DataTransactionResult#getis inefficient, as it iterates over the entire list of values each time. Should we require that there can only be oneImmutableValueper key in a givenDataCategory? Are the any circumstances where this would pose an issue?DataCategoryonDataTransactionResultsort of behaves like an immutableValueContainer. Would it make sense to implement this interface on a 'view' into aDataTransactionResult?DataTransactionResult#absorbResulthas very little documentation, and (to me) gives unintuitive results. Is this method the right one to use when dealing with aChangeDataHolderEvent.ValueChange? If not, what should be used instead? Under what circumstances would a plugin call this method?DataHolder#offerWithEventbe:offerthrough the API?offer?Demonstration plugin
To demonstrate how these changes will work in practice, I've added support for firing
ChangeDataHolderEvent.ValueChangefor changes to food level (Keys.FOOD_LEVEL). This plugin shows how to use the event: