From d5b97106cd23f7bf6d13d2c541045453cc91c24f Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Sun, 2 Jan 2022 09:52:11 -0800 Subject: [PATCH] Introduce VanishState This state keeps track of the extra options and enables a simpler usage of 'simple vanish' vs customizations of vanish. Signed-off-by: Gabriel Harris-Rouquette --- .../java/org/spongepowered/api/data/Keys.java | 22 +- .../spongepowered/api/effect/VanishState.java | 225 ++++++++++++++++++ .../org/spongepowered/api/entity/Entity.java | 18 +- .../api/entity/living/player/User.java | 8 + 4 files changed, 270 insertions(+), 3 deletions(-) create mode 100644 src/main/java/org/spongepowered/api/effect/VanishState.java diff --git a/src/main/java/org/spongepowered/api/data/Keys.java b/src/main/java/org/spongepowered/api/data/Keys.java index 6dc6803bd7..deac2786bb 100644 --- a/src/main/java/org/spongepowered/api/data/Keys.java +++ b/src/main/java/org/spongepowered/api/data/Keys.java @@ -92,6 +92,7 @@ import org.spongepowered.api.data.value.SetValue; import org.spongepowered.api.data.value.Value; import org.spongepowered.api.data.value.WeightedCollectionValue; +import org.spongepowered.api.effect.VanishState; import org.spongepowered.api.effect.particle.ParticleEffect; import org.spongepowered.api.effect.particle.ParticleOption; import org.spongepowered.api.effect.particle.ParticleType; @@ -1388,7 +1389,7 @@ public final class Keys { * Whether an {@link Entity} is currently invisible. * This will only simply render the entity as vanished, * but not prevent any entity updates being sent to clients. - * To fully "vanish" an {@link Entity}, use {@link #VANISH}. + * To fully "vanish" an {@link Entity}, use {@link #VANISH_STATE}. */ public static final Key> IS_INVISIBLE = Keys.key(ResourceKey.sponge("is_invisible"), Boolean.class); @@ -2629,6 +2630,19 @@ public final class Keys { */ public static final Key> UPDATE_GAME_PROFILE = Keys.key(ResourceKey.sponge("update_game_profile"), Boolean.class); + /** + * The {@link VanishState} of an {@link Entity}. + * + *

The presence of a vanished entity will not be made known to a client; + * no packets pertaining to this entity are sent. Client-side, this entity + * will cease to exist. Server-side it may still be targeted by hostile + * entities or collide with other entities.

+ * + *

Vanishing an {@link Entity} ridden by other entities (see + * {@link #PASSENGERS} will cause problems.

+ */ + public static final Key> VANISH_STATE = Keys.key(ResourceKey.sponge("vanish"), VanishState.class); + /** * Whether an {@link Entity} is vanished. * @@ -2639,7 +2653,9 @@ public final class Keys { * *

Vanishing an {@link Entity} ridden by other entities (see * {@link #PASSENGERS} will cause problems.

+ * @deprecated use {@link #VANISH_STATE} */ + @Deprecated public static final Key> VANISH = Keys.key(ResourceKey.sponge("vanish"), Boolean.class); /** @@ -2647,7 +2663,9 @@ public final class Keys { * *

This state will be ignored if the {@link Entity} is not also * vanished as per {@link #VANISH}.

+ * @deprecated use {@link #VANISH_STATE} */ + @Deprecated public static final Key> VANISH_IGNORES_COLLISION = Keys.key(ResourceKey.sponge("vanish_ignores_collision"), Boolean.class); /** @@ -2657,7 +2675,9 @@ public final class Keys { * *

This state will be ignored if the {@link Entity} is not also * vanished as per {@link #VANISH}.}.

+ * @deprecated use {@link #VANISH_STATE} */ + @Deprecated public static final Key> VANISH_PREVENTS_TARGETING = Keys.key(ResourceKey.sponge("vanish_prevents_targeting"), Boolean.class); /** diff --git a/src/main/java/org/spongepowered/api/effect/VanishState.java b/src/main/java/org/spongepowered/api/effect/VanishState.java new file mode 100644 index 0000000000..4678fd8c80 --- /dev/null +++ b/src/main/java/org/spongepowered/api/effect/VanishState.java @@ -0,0 +1,225 @@ +/* + * 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.effect; + +import org.spongepowered.api.Sponge; +import org.spongepowered.api.entity.Entity; + +/** + * Represents the state of an {@link Entity}'s vanish state. + * Accessible through {@link org.spongepowered.api.data.Keys#VANISH_STATE} + */ +public interface VanishState { + + /** + * Gets a vanished state via {@link Factory#vanish()} with the following + * defaults: + *
    + *
  • {@link VanishState#invisible()} = {@code true}
  • + *
  • {@link VanishState#affectsMonsterSpawning()} = {@code false}
  • + *
  • {@link VanishState#untargetable()} = {@code true}
  • + *
  • {@link VanishState#createsSounds()} = {@code false}
  • + *
  • {@link VanishState#createsParticles()} = {@code false}
  • + *
+ * + * @return A vanished state with the provided defaults + */ + static VanishState vanished() { + return Sponge.game().factoryProvider().provide(VanishState.Factory.class).vanished(); + } + + /** + * A {@link VanishState} that is invisible with the following defaults: + *
    + *
  • {@link VanishState#invisible()} = {@code false}
  • + *
  • {@link VanishState#affectsMonsterSpawning()} = {@code true}
  • + *
  • {@link VanishState#untargetable()} = {@code false}
  • + *
  • {@link VanishState#createsSounds()} = {@code true}
  • + *
  • {@link VanishState#createsParticles()} = {@code true}
  • + *
+ * + * @return A visible state with the provided defaults + */ + static VanishState unvanished() { + return Sponge.game().factoryProvider().provide(VanishState.Factory.class).unvanished(); + } + + /** + * Gets whether the state is visible. If an {@link Entity} is visible, then + * other aspects of this state will be ignored, such as + * {@link #ignoresCollisions()}, {@link #untargetable()}, etc. + * + * @return Whether the {@link Entity} is visible + */ + boolean invisible(); + + /** + * Gets a vanished {@link VanishState state} with {@link #ignoresCollisions()} + * and {@link #untargetable()} set to {@code true}. If the state is already + * {@link #invisible()}, then the same state is returned. + * + * @return The vanished state + */ + VanishState vanish(); + + /** + * Gets a visible state {@link VanishState} with {@link #ignoresCollisions()} + * and {@link #untargetable()} set to {@code false}. If the state is already + * {@link #invisible()} being {@code false}, then the same state is returned. + * + * @return The visible state + */ + VanishState unvanish(); + + /** + * Gets if the {@link Entity} will ignore collisions. In cases where + * {@link #invisible()} is {@code false}, this will return {@code false}. + * + * @return Whether collisions will be ignored + */ + boolean ignoresCollisions(); + + /** + * If {@link #invisible()} returns true, this will return the + * {@link VanishState} with the desired flag of + * {@link #ignoresCollisions()}. + * + * @param ignoresCollisions Whether collisions will be ignored + * @return The new VanishState, the value changed + */ + VanishState ignoreCollisions(boolean ignoresCollisions); + + /** + * Gets if the {@link Entity} will be untargetable by entity ai. In cases + * where {@link #invisible()} is {@code false}, this will return + * {@code false}. + * + * @return Whether the {@link Entity} will be untargetable + */ + boolean untargetable(); + + /** + * If {@link #invisible()} returns true, this will return the + * {@link VanishState} with the desired flag of + * {@link #ignoresCollisions()}. + * + * @param untargetable Whether the entity can be targeted by AI + * @return The new VanishState, the value changed + */ + VanishState untargetable(boolean untargetable); + + /** + * Gets if {@link #affectsMonsterSpawning()} returns {@code false}, the + * vanished {@link Entity} will not spawn monsters or affect near by monster + * spawners. + *

Note that this flag works in conjunction with + * {@link org.spongepowered.api.data.Keys#AFFECTS_SPAWNING} such that either + * one being {@code false} will disable spawning.

+ * + * @return Whether the {@link Entity} will affect monster spawning + */ + boolean affectsMonsterSpawning(); + + /** + * If {@link #invisible()} returns true, this will return the + * {@link VanishState} with the desired flag. + *

Note that this flag works in conjunction with + * {@link org.spongepowered.api.data.Keys#AFFECTS_SPAWNING} such that either + * one being false will disable spawning.

+ * + * @param affectsMonsterSpawning Whether the {@link Entity} will affect + * monster spawning + * @return The new VanishState + */ + VanishState affectMonsterSpawning(boolean affectsMonsterSpawning); + + /** + * Gets if the {@link Entity} will produce sounds from various actions that + * occur while {@link #invisible()} is {@code true}. + * + * @return Whether the {@link Entity} will produce sounds while invisible + */ + boolean createsSounds(); + + /** + * If {@link #invisible()} returns true, this will return the + * {@link VanishState} with the desired flag of + * {@link #createsSounds()}. + * + * @param createSounds Whether the {@link Entity} will produce sounds + * @return The new VanishState + */ + VanishState createSounds(boolean createSounds); + + /** + * Gets if the {@link Entity} will produce particles from various actions + * that occur while {@link #invisible()} is {@code true}. + * + * @return Whether the {@link Entity} will produce particles while invisible + */ + boolean createsParticles(); + + /** + * If {@link #invisible()} returns true, this will return the + * {@link VanishState} with the desired flag of + * {@link #createsParticles()}. + * + * @param createParticles Whether the {@link Entity} will produce particles + * @return The new VanishState + */ + VanishState createParticles(boolean createParticles); + + interface Factory { + + /** + * Creates a {@link VanishState} that is invisible with the following + * defaults: + *
    + *
  • {@link VanishState#invisible()} = {@code true}
  • + *
  • {@link VanishState#affectsMonsterSpawning()} = {@code false}
  • + *
  • {@link VanishState#untargetable()} = {@code true}
  • + *
  • {@link VanishState#createsSounds()} = {@code false}
  • + *
  • {@link VanishState#createsParticles()} = {@code false}
  • + *
+ * + * @return A newly created invisible {@link VanishState} + */ + VanishState vanished(); + + /** + * A {@link VanishState} that is visible with the following defaults: + *
    + *
  • {@link VanishState#invisible()} = {@code false}
  • + *
  • {@link VanishState#affectsMonsterSpawning()} = {@code true}
  • + *
  • {@link VanishState#untargetable()} = {@code false}
  • + *
  • {@link VanishState#createsSounds()} = {@code true}
  • + *
  • {@link VanishState#createsParticles()} = {@code true}
  • + *
+ * + * @return A newly created visible {@link VanishState} + */ + VanishState unvanished(); + } +} diff --git a/src/main/java/org/spongepowered/api/entity/Entity.java b/src/main/java/org/spongepowered/api/entity/Entity.java index 727d73507f..218e4b155d 100644 --- a/src/main/java/org/spongepowered/api/entity/Entity.java +++ b/src/main/java/org/spongepowered/api/entity/Entity.java @@ -33,6 +33,7 @@ import org.spongepowered.api.data.value.ListValue; import org.spongepowered.api.data.value.SetValue; import org.spongepowered.api.data.value.Value; +import org.spongepowered.api.effect.VanishState; import org.spongepowered.api.event.cause.entity.damage.source.DamageSource; import org.spongepowered.api.projectile.source.EntityProjectileSource; import org.spongepowered.api.util.AABB; @@ -75,6 +76,7 @@ * *

Blocks and items (when they are in inventories) are not entities.

*/ +@SuppressWarnings("deprecation") @DoNotStore public interface Entity extends Identifiable, HoverEventSource, Locatable, EntityProjectileSource, Sound.Emitter, SerializableDataHolder.Mutable, RandomProvider { @@ -325,8 +327,8 @@ default Collection nearbyEntities(final double distance, final */ default boolean canSee(final Entity entity) { Objects.requireNonNull(entity, "Entity cannot be null"); - final Optional optional = entity.get(Keys.VANISH); - return !optional.isPresent() || !optional.get(); + final Optional optional = entity.get(Keys.VANISH_STATE); + return !optional.map(VanishState::invisible).orElse(false); } /** @@ -606,10 +608,20 @@ default SetValue.Mutable scoreboardTags() { return this.requireValue(Keys.SCOREBOARD_TAGS).asMutable(); } + /** + * {@link Keys#VANISH_STATE} + * + * @return The current vanish state of the entity + */ + default Value.Mutable vanishState() { + return this.requireValue(Keys.VANISH_STATE).asMutable(); + } + /** * {@link Keys#VANISH} * * @return Whether the entity is vanished + * @deprecated Use {@link #vanishState() VanishState} instead */ default Value.Mutable vanish() { return this.requireValue(Keys.VANISH).asMutable(); @@ -619,6 +631,7 @@ default Value.Mutable vanish() { * {@link Keys#VANISH_IGNORES_COLLISION} * * @return Whether the entity ignores collision with other entities + * @deprecated Use {@link #vanishState()} instead */ default Value.Mutable vanishIgnoresCollision() { return this.requireValue(Keys.VANISH_IGNORES_COLLISION).asMutable(); @@ -628,6 +641,7 @@ default Value.Mutable vanishIgnoresCollision() { * {@link Keys#VANISH_PREVENTS_TARGETING} * * @return Whether the entity can be targeted for attack by another entity + * @deprecated Use {@link #vanishState()} instead */ default Value.Mutable vanishPreventsTargeting() { return this.requireValue(Keys.VANISH_PREVENTS_TARGETING).asMutable(); diff --git a/src/main/java/org/spongepowered/api/entity/living/player/User.java b/src/main/java/org/spongepowered/api/entity/living/player/User.java index 3744e63554..a9c9ea8b73 100644 --- a/src/main/java/org/spongepowered/api/entity/living/player/User.java +++ b/src/main/java/org/spongepowered/api/entity/living/player/User.java @@ -30,6 +30,7 @@ import org.spongepowered.api.data.Keys; import org.spongepowered.api.data.value.MapValue; import org.spongepowered.api.data.value.Value; +import org.spongepowered.api.effect.VanishState; import org.spongepowered.api.entity.Entity; import org.spongepowered.api.entity.Tamer; import org.spongepowered.api.entity.living.player.server.ServerPlayer; @@ -198,11 +199,16 @@ default Value.Mutable invisible() { return this.requireValue(Keys.IS_INVISIBLE).asMutable(); } + default Value.Mutable vanishState() { + return this.requireValue(Keys.VANISH_STATE).asMutable(); + } + /** * {@link Keys#VANISH} * * @return Whether the user is vanished */ + @Deprecated default Value.Mutable vanish() { return this.requireValue(Keys.VANISH).asMutable(); } @@ -212,6 +218,7 @@ default Value.Mutable vanish() { * * @return Whether the user ignores collision with other entities */ + @Deprecated default Value.Mutable vanishIgnoresCollision() { return this.requireValue(Keys.VANISH_IGNORES_COLLISION).asMutable(); } @@ -221,6 +228,7 @@ default Value.Mutable vanishIgnoresCollision() { * * @return Whether the user can be targeted for attack by another entity */ + @Deprecated default Value.Mutable vanishPreventsTargeting() { return this.requireValue(Keys.VANISH_PREVENTS_TARGETING).asMutable(); }