Add Material Tags
This adds a bunch of useful and missing Tags to be able to identify items that are related to each other by a trait. Co-authored-by: Jake Potrebic <jake.m.potrebic@gmail.com> Co-authored-by: Lena Kolb <lenakolb2204@gmail.com> Co-authored-by: Layla Silbernberg <livsilbernberg@gmail.com> Co-authored-by: Newwind <newwindserver@gmail.com>
This commit is contained in:
184
paper-api/src/main/java/io/papermc/paper/tag/BaseTag.java
Normal file
184
paper-api/src/main/java/io/papermc/paper/tag/BaseTag.java
Normal file
@@ -0,0 +1,184 @@
|
||||
package io.papermc.paper.tag;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import java.util.Collections;
|
||||
import org.bukkit.Keyed;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.Tag;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.EnumSet;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public abstract class BaseTag<T extends Keyed, C extends BaseTag<T, C>> implements Tag<T> {
|
||||
|
||||
protected final NamespacedKey key;
|
||||
protected final Set<T> tagged;
|
||||
private final List<Predicate<T>> globalPredicates;
|
||||
private boolean locked = false;
|
||||
|
||||
public BaseTag(@NotNull Class<T> clazz, @NotNull NamespacedKey key, @NotNull Predicate<T> filter) {
|
||||
this(clazz, key);
|
||||
add(filter);
|
||||
}
|
||||
|
||||
public BaseTag(@NotNull Class<T> clazz, @NotNull NamespacedKey key, @NotNull T...values) {
|
||||
this(clazz, key, Lists.newArrayList(values));
|
||||
}
|
||||
|
||||
public BaseTag(@NotNull Class<T> clazz, @NotNull NamespacedKey key, @NotNull Collection<T> values) {
|
||||
this(clazz, key, values, o -> true);
|
||||
}
|
||||
|
||||
public BaseTag(@NotNull Class<T> clazz, @NotNull NamespacedKey key, @NotNull Collection<T> values, @NotNull Predicate<T>... globalPredicates) {
|
||||
this.key = key;
|
||||
this.tagged = clazz.isEnum() ? createEnumSet(clazz) : new HashSet<>();
|
||||
this.tagged.addAll(values);
|
||||
this.globalPredicates = Lists.newArrayList(globalPredicates);
|
||||
}
|
||||
|
||||
private <E> Set<E> createEnumSet(Class<E> enumClass) {
|
||||
assert enumClass.isEnum();
|
||||
return (Set<E>) EnumSet.noneOf((Class<Enum>) enumClass);
|
||||
}
|
||||
|
||||
public @NotNull C lock() {
|
||||
this.locked = true;
|
||||
return (C) this;
|
||||
}
|
||||
|
||||
public boolean isLocked() {
|
||||
return this.locked;
|
||||
}
|
||||
|
||||
private void checkLock() {
|
||||
if (this.locked) {
|
||||
throw new UnsupportedOperationException("Tag (" + this.key + ") is locked");
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public NamespacedKey getKey() {
|
||||
return key;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Set<T> getValues() {
|
||||
return Collections.unmodifiableSet(tagged);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isTagged(@NotNull T item) {
|
||||
return tagged.contains(item);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public C add(@NotNull Tag<T>...tags) {
|
||||
for (Tag<T> tag : tags) {
|
||||
add(tag.getValues());
|
||||
}
|
||||
return (C) this;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public C add(@NotNull T...values) {
|
||||
this.checkLock();
|
||||
this.tagged.addAll(Lists.newArrayList(values));
|
||||
return (C) this;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public C add(@NotNull Collection<T> collection) {
|
||||
this.checkLock();
|
||||
this.tagged.addAll(collection);
|
||||
return (C) this;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public C add(@NotNull Predicate<T> filter) {
|
||||
return add(getAllPossibleValues().stream().filter(globalPredicates.stream().reduce(Predicate::or).orElse(t -> true)).filter(filter).collect(Collectors.toSet()));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public C contains(@NotNull String with) {
|
||||
return add(value -> getName(value).contains(with));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public C endsWith(@NotNull String with) {
|
||||
return add(value -> getName(value).endsWith(with));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public C startsWith(@NotNull String with) {
|
||||
return add(value -> getName(value).startsWith(with));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public C not(@NotNull Tag<T>...tags) {
|
||||
for (Tag<T> tag : tags) {
|
||||
not(tag.getValues());
|
||||
}
|
||||
return (C) this;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public C not(@NotNull T...values) {
|
||||
this.checkLock();
|
||||
this.tagged.removeAll(Lists.newArrayList(values));
|
||||
return (C) this;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public C not(@NotNull Collection<T> values) {
|
||||
this.checkLock();
|
||||
this.tagged.removeAll(values);
|
||||
return (C) this;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public C not(@NotNull Predicate<T> filter) {
|
||||
not(getAllPossibleValues().stream().filter(globalPredicates.stream().reduce(Predicate::or).orElse(t -> true)).filter(filter).collect(Collectors.toSet()));
|
||||
return (C) this;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public C notContains(@NotNull String with) {
|
||||
return not(value -> getName(value).contains(with));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public C notEndsWith(@NotNull String with) {
|
||||
return not(value -> getName(value).endsWith(with));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public C notStartsWith(@NotNull String with) {
|
||||
return not(value -> getName(value).startsWith(with));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public C ensureSize(@NotNull String label, int size) {
|
||||
long actual = this.tagged.stream().filter(globalPredicates.stream().reduce(Predicate::or).orElse(t -> true)).count();
|
||||
if (size != actual) {
|
||||
throw new IllegalStateException(key.toString() + ": " + label + " - Expected " + size + " values, got " + actual);
|
||||
}
|
||||
return (C) this;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@ApiStatus.Internal
|
||||
protected abstract Set<T> getAllPossibleValues();
|
||||
|
||||
@NotNull
|
||||
@ApiStatus.Internal
|
||||
protected abstract String getName(@NotNull T value);
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package io.papermc.paper.tag;
|
||||
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.entity.EntityType;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Set;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public class EntitySetTag extends BaseTag<EntityType, EntitySetTag> {
|
||||
|
||||
public EntitySetTag(@NotNull NamespacedKey key, @NotNull Predicate<EntityType> filter) {
|
||||
super(EntityType.class, key, filter);
|
||||
}
|
||||
|
||||
public EntitySetTag(@NotNull NamespacedKey key, @NotNull EntityType... values) {
|
||||
super(EntityType.class, key, values);
|
||||
}
|
||||
|
||||
public EntitySetTag(@NotNull NamespacedKey key, @NotNull Collection<EntityType> values) {
|
||||
super(EntityType.class, key, values);
|
||||
}
|
||||
|
||||
public EntitySetTag(@NotNull NamespacedKey key, @NotNull Collection<EntityType> values, @NotNull Predicate<EntityType>... globalPredicates) {
|
||||
super(EntityType.class, key, values, globalPredicates);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected Set<EntityType> getAllPossibleValues() {
|
||||
return Stream.of(EntityType.values()).collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected String getName(@NotNull EntityType value) {
|
||||
return value.name();
|
||||
}
|
||||
}
|
||||
56
paper-api/src/main/java/io/papermc/paper/tag/EntityTags.java
Normal file
56
paper-api/src/main/java/io/papermc/paper/tag/EntityTags.java
Normal file
@@ -0,0 +1,56 @@
|
||||
package io.papermc.paper.tag;
|
||||
|
||||
import org.bukkit.NamespacedKey;
|
||||
|
||||
import static org.bukkit.entity.EntityType.*;
|
||||
|
||||
/**
|
||||
* All tags in this class are unmodifiable, attempting to modify them will throw an
|
||||
* {@link UnsupportedOperationException}.
|
||||
*/
|
||||
public class EntityTags {
|
||||
|
||||
private static NamespacedKey keyFor(String key) {
|
||||
//noinspection deprecation
|
||||
return new NamespacedKey("paper", key + "_settag");
|
||||
}
|
||||
|
||||
/**
|
||||
* Covers undead mobs
|
||||
* @see <a href="https://minecraft.wiki/wiki/Mob#Undead_mobs">https://minecraft.wiki/wiki/Mob#Undead_mobs</a>
|
||||
*/
|
||||
public static final EntitySetTag UNDEADS = new EntitySetTag(keyFor("undeads"))
|
||||
.add(DROWNED, HUSK, PHANTOM, SKELETON, SKELETON_HORSE, STRAY, WITHER, WITHER_SKELETON, ZOGLIN, ZOMBIE, ZOMBIE_HORSE, ZOMBIE_VILLAGER, ZOMBIFIED_PIGLIN, BOGGED)
|
||||
.ensureSize("UNDEADS", 14).lock();
|
||||
|
||||
/**
|
||||
* Covers all horses
|
||||
*/
|
||||
public static final EntitySetTag HORSES = new EntitySetTag(keyFor("horses"))
|
||||
.contains("HORSE")
|
||||
.ensureSize("HORSES", 3).lock();
|
||||
|
||||
/**
|
||||
* Covers all minecarts
|
||||
*/
|
||||
public static final EntitySetTag MINECARTS = new EntitySetTag(keyFor("minecarts"))
|
||||
.contains("MINECART")
|
||||
.ensureSize("MINECARTS", 7).lock();
|
||||
|
||||
/**
|
||||
* Covers mobs that split into smaller mobs
|
||||
*/
|
||||
public static final EntitySetTag SPLITTING_MOBS = new EntitySetTag(keyFor("splitting_mobs"))
|
||||
.add(SLIME, MAGMA_CUBE)
|
||||
.ensureSize("SLIMES", 2).lock();
|
||||
|
||||
/**
|
||||
* Covers all water based mobs
|
||||
* @see <a href="https://minecraft.wiki/wiki/Mob#Aquatic_mobs">https://minecraft.wiki/wiki/Mob#Aquatic_mobs</a>
|
||||
* @deprecated in favour of {@link org.bukkit.Tag#ENTITY_TYPES_AQUATIC}
|
||||
*/
|
||||
@Deprecated
|
||||
public static final EntitySetTag WATER_BASED = new EntitySetTag(keyFor("water_based"))
|
||||
.add(AXOLOTL, DOLPHIN, SQUID, GLOW_SQUID, GUARDIAN, ELDER_GUARDIAN, TURTLE, COD, SALMON, PUFFERFISH, TROPICAL_FISH, TADPOLE)
|
||||
.ensureSize("WATER_BASED", 12).lock();
|
||||
}
|
||||
Reference in New Issue
Block a user