All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.spongepowered.api.event.entity.DamageEntityEvent Maven / Gradle / Ivy

There is a newer version: 9.0.0
Show newest version
/*
 * This file is part of SpongeAPI, licensed under the MIT License (MIT).
 *
 * Copyright (c) SpongePowered 
 * Copyright (c) contributors
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
package org.spongepowered.api.event.entity;

import com.google.common.collect.ImmutableMap;
import org.spongepowered.api.block.entity.carrier.Dispenser;
import org.spongepowered.api.entity.Entity;
import org.spongepowered.api.entity.living.monster.skeleton.Skeleton;
import org.spongepowered.api.entity.living.player.Player;
import org.spongepowered.api.entity.projectile.arrow.ArrowEntity;
import org.spongepowered.api.event.Cancellable;
import org.spongepowered.api.event.Cause;
import org.spongepowered.api.event.Event;
import org.spongepowered.api.event.cause.entity.damage.DamageFunction;
import org.spongepowered.api.event.cause.entity.damage.DamageModifier;
import org.spongepowered.api.event.cause.entity.damage.DamageModifier.Builder;
import org.spongepowered.api.event.cause.entity.damage.DamageModifierType;
import org.spongepowered.api.event.cause.entity.damage.DamageType;
import org.spongepowered.api.event.cause.entity.damage.source.DamageSource;
import org.spongepowered.api.event.impl.entity.AbstractDamageEntityEvent;
import org.spongepowered.api.item.ItemTypes;
import org.spongepowered.api.item.inventory.ItemStack;
import org.spongepowered.api.util.Tuple;
import org.spongepowered.api.util.annotation.eventgen.ImplementedBy;
import org.spongepowered.api.util.annotation.eventgen.PropertySettings;
import org.spongepowered.api.world.World;
import org.spongepowered.api.world.difficulty.Difficulties;
import org.spongepowered.api.world.difficulty.Difficulty;

import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.DoubleUnaryOperator;

/**
 * Represents the base event for when an {@link Entity} is being "attacked".
 * The uniqueness of this event is that all {@link DamageSource}s can deal
 * varying amounts of damage with varying modifiers based on various reasons.
 * Due to this ambiguous variety of information that is possible to provide,
 * the {@link DamageEntityEvent} can be summarized as so:
 *
 * 

An {@link ArrowEntity}, * that was shot by a {@link Skeleton}, * with an enchanted {@link ItemTypes#BOW} {@link ItemStack}, * when the {@link World} {@link Difficulty} was set to * {@link Difficulties#HARD}, * will deal possibly "5" damage to any {@link Entity} it hits. *

* *

The issue with representing this type of "logic flow" is that a * particular amount of damage from a {@link DamageSource}, even if specified * to a particular {@link DamageType}, has no static finalized amount of damage * to deal to a particular {@link Entity}. To properly represent this, * a {@link DamageSource} has various "states" such as: * {@link DamageSource#isAbsolute()}, or {@link DamageSource#isBypassingArmor()}. * Quite simply, the {@link DamageSource} will always be the "first" element * within a {@link Cause} that can be retrieved from {@link #cause()}.

* *

Next, any additional "aides" in attacking the {@link Entity} will * be included in order of "priority of relation" to "attacking" the entity. In * short, if another {@link Entity} is considered a "team member" to the * attacking {@link Entity}, the "team member" may be a second element within * the {@link Cause}. The same can be said if an {@link ArrowEntity} was shot from * a {@link Dispenser} that was triggered by a {@link Player} flipping a * switch.

* *

Continuing with the notion of "modifiers" to damage, the "base" damage * is modified or added onto after various unknown methods are called or * processed on the damage. Optimally, these modifiers can be traced to a * particular object, be it an {@link ItemStack}, {@link Difficulty}, or * simply an an attribute. The interesting part is that these "modifiers" * do not just define a static value to add to the "base" damage, they * are usually a loose form of a {@link DamageFunction} that are applied to * the "base" damage. Given that {@link Cause} has a unique capability of * storing any and every {@link Object} willing to be passed into it, we * can easily represent these "sources" of "modifiers" in a {@link Cause}. * Now, knowning the "source" will not provide enough information, so a * {@link DamageModifierType} is provided with a {@link DamageModifier} to * paint the fullest picture of "explaining" the {@link DamageModifier} as to * why it is present, and why it is "modifying" the "base" damage. Finally, * we can associate a {@link DamageModifier} with a {@link DamageFunction} that is * passed the current "damage" into {@link DoubleUnaryOperator#applyAsDouble(double)} * , being added * to the current "damage". After all {@link DamageModifier} {@link DamageFunction}s * are "applied", the overall "damage" is now the final damage to actually * throw a {@link DamageEntityEvent}.

* *

Note that due to the mechanics of the game, {@link DamageModifier}s * are always ordered in the order of which they apply their modifier onto * the "base" damage. The implementation for {@link #finalDamage()} can be * exemplified like so:

* *
{@code
 * double damage = this.baseDamage;
* for (Map.Entry> entry : this.modifierFunctions.entrySet()) { * damage += checkNotNull(entry.getValue().apply(damage)); * } * return damage; * }
* *

After which, the "final" damage is simply the summation of the * "base" damage and all "modified damage" for each {@link DamageModifier} * provided in this event.

* *

Coming forward, it is possible to further customize not only the "base" * damage, but override pre-existing {@link DamageModifier} {@link DamageFunction}s * by calling {@link #setDamage(DamageModifier, DoubleUnaryOperator)} at which point the * end result may be undefined. However, if a custom {@link DamageModifier} * that aims to alter the "final" damage based on some custom circumstances, * calling {@link #setDamage(DamageModifier, DoubleUnaryOperator)} on a new * {@link DamageModifier} instance, easily created from the * {@link org.spongepowered.api.event.cause.entity.damage.DamageModifier.Builder}, * the provided pairing will be added at the * "end" of the list for "modifying" the "base" damage.

* *

Note that this event is intended for processing incoming damage to * an {@link Entity} prior to any {@link DamageModifier}s associated with * the {@link #entity()}. The {@link DamageEntityEvent} is used * to process the various {@link DamageModifier}s of which originate or are * associated with the targeted {@link Entity}.

*/ @ImplementedBy(AbstractDamageEntityEvent.class) public interface DamageEntityEvent extends Event, Cancellable { /** * Gets the {@link Entity}. * * @return The entity */ Entity entity(); /** * Gets the original "raw" amount of damage to deal to the targeted * {@link Entity}. * * @return The original "raw" damage */ double originalDamage(); /** * Gets the original "final" amount of damage after all original * {@link DamageModifier}s are applied to {@link #originalDamage()}. * The "final" damage is considered the amount of health being lost by * the {@link Entity}, if health is tracked. * * @return The final amount of damage to originally deal */ @PropertySettings(requiredParameter = false, generateMethods = false) double originalFinalDamage(); /** * Gets an {@link ImmutableMap} of all original {@link DamageModifier}s * and their associated "modified" damage. Note that ordering is not * retained. * * @return An immutable map of the original modified damages */ @PropertySettings(requiredParameter = false, generateMethods = false) Map originalDamages(); /** * Gets the original damage for the provided {@link DamageModifier}. If * the provided {@link DamageModifier} was not included in * {@link #originalDamages()}, an {@link IllegalArgumentException} is * thrown. * * @param damageModifier The original damage modifier * @return The original damage change */ double originalModifierDamage(DamageModifier damageModifier); /** * Gets the original {@link List} of {@link DamageModifier} to * {@link DamageFunction} that was originally passed into the event. * * @return The list of damage modifier functions */ List originalFunctions(); /** * Gets the "base" damage to deal to the targeted {@link Entity}. The * "base" damage is the original value before passing along the chain of * {@link DamageFunction}s for all known {@link DamageModifier}s. * * @return The base damage */ @PropertySettings(requiredParameter = false, generateMethods = false) double baseDamage(); /** * Sets the "base" damage to deal to the targeted {@link Entity}. The * "base" damage is the original value before passing along the chain of * {@link DamageFunction}s for all known {@link DamageModifier}s. * * @param baseDamage The base damage */ void setBaseDamage(double baseDamage); /** * Gets the final damage that will be passed into the proceeding * {@link DamageEntityEvent}. The final damage is the end result of the * {@link #baseDamage()} being applied in {@link DoubleUnaryOperator#applyAsDouble(double)} * available from all the {@link Tuple}s of {@link DamageModifier} to * {@link DamageFunction} in {@link #originalFunctions()}. * * @return The final damage to deal */ @PropertySettings(requiredParameter = false, generateMethods = false) double finalDamage(); /** * Checks whether the provided {@link DamageModifier} is applicable to the * current available {@link DamageModifier}s. * * @param damageModifier The damage modifier to check * @return True if the damage modifier is relevant to this event */ boolean isModifierApplicable(DamageModifier damageModifier); /** * Gets the damage for the provided {@link DamageModifier}. Providing that * {@link #isModifierApplicable(DamageModifier)} returns true, * the cached "damage" for the {@link DamageModifier} is returned. * * @param damageModifier The damage modifier to get the damage for * @return The modifier */ double damage(DamageModifier damageModifier); /** * Sets the provided {@link DamageFunction} to be used for the given * {@link DamageModifier}. If the {@link DamageModifier} is already * included in {@link #modifiers()}, the {@link DoubleUnaryOperator} replaces * the existing function. If there is no {@link Tuple} for the * {@link DamageModifier}, a new one is created and added to the end * of the list of {@link DoubleUnaryOperator}s to be applied to the * {@link #baseDamage()}. * *

If needing to create a custom {@link DamageModifier} is required, * usage of the {@link Builder} is recommended.

* * @param damageModifier The damage modifier * @param function The function to map to the modifier */ void setDamage(DamageModifier damageModifier, DoubleUnaryOperator function); /** * Adds the provided {@link DamageModifier} and {@link DoubleUnaryOperator} to the * list of modifiers, such that the {@link Set} containing * {@link DamageModifierType}s provided in {@code before} will appear * after the provided damage modifier. * * @param damageModifier The damage modifier to add * @param function The associated function * @param before The set containing the modifier types to come after * the provided modifier */ void addDamageModifierBefore(DamageModifier damageModifier, DoubleUnaryOperator function, Set before); /** * Adds the provided {@link DamageModifier} and {@link DoubleUnaryOperator} to the list * of modifiers, such that the modifier will appear in order after any * current modifiers whose type are included in the provided {@link Set} of * {@link DamageModifierType}s. * * @param damageModifier The damage modifier to add * @param function The associated function * @param after The set of modifier types to come before the new modifier */ void addModifierAfter(DamageModifier damageModifier, DoubleUnaryOperator function, Set after); /** * Gets a list of simple {@link Tuple}s of {@link DamageModifier} keyed to * their representative {@link DamageFunction}s. All {@link DamageModifier}s are * applicable to the entity based on the {@link DamageSource} and any * possible invulnerabilities due to the {@link DamageSource}. * * @return A list of damage modifiers to functions */ @PropertySettings(requiredParameter = false, generateMethods = false) List modifiers(); /** * Returns whether or not this event will cause the entity to die if the * event is not cancelled. Only supported for living entities, returns false * if {@link #entity()} is not a living entity. * * @return Whether the entity will die */ @PropertySettings(requiredParameter = false, generateMethods = false) boolean willCauseDeath(); }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy