/** * This file is part of Skript. * * Skript is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Skript is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Skript. If not, see <http://www.gnu.org/licenses/>. * * * Copyright 2011-2017 Peter Güttinger and contributors */ package ch.njol.skript.classes.data; import java.util.LinkedHashMap; import java.util.Map.Entry; import java.util.Objects; import ch.njol.util.Kleenean; import org.bukkit.Material; import org.bukkit.OfflinePlayer; import org.bukkit.World; import org.bukkit.block.Block; import org.bukkit.command.CommandSender; import org.bukkit.entity.ArmorStand; import org.bukkit.entity.Arrow; import org.bukkit.entity.Boat; import org.bukkit.entity.Chicken; import org.bukkit.entity.Egg; import org.bukkit.entity.EnderPearl; import org.bukkit.entity.Entity; import org.bukkit.entity.FallingBlock; import org.bukkit.entity.Firework; import org.bukkit.entity.Item; import org.bukkit.entity.ItemFrame; import org.bukkit.entity.Minecart; import org.bukkit.entity.Painting; import org.bukkit.entity.Projectile; import org.bukkit.entity.Slime; import org.bukkit.entity.Snowball; import org.bukkit.entity.TNTPrimed; import org.bukkit.entity.ThrownExpBottle; import org.bukkit.entity.ThrownPotion; import org.bukkit.entity.Wither; import org.bukkit.entity.WitherSkull; import org.bukkit.entity.minecart.ExplosiveMinecart; import org.bukkit.entity.minecart.HopperMinecart; import org.bukkit.entity.minecart.RideableMinecart; import org.bukkit.event.entity.EntityDamageEvent.DamageCause; import org.bukkit.inventory.ItemStack; import ch.njol.skript.Skript; import ch.njol.skript.SkriptConfig; import ch.njol.skript.aliases.Aliases; import ch.njol.skript.aliases.ItemData; import ch.njol.skript.aliases.ItemType; import ch.njol.skript.classes.ClassInfo; import ch.njol.skript.classes.Comparator; import ch.njol.skript.entity.BoatData; import ch.njol.skript.entity.EntityData; import ch.njol.skript.registrations.Comparators; import ch.njol.skript.util.Date; import ch.njol.skript.util.PotionEffectUtils; import ch.njol.skript.util.StructureType; import ch.njol.skript.util.Time; import ch.njol.skript.util.Timeperiod; import ch.njol.skript.util.Timespan; import ch.njol.skript.util.slot.Slot; import ch.njol.skript.util.slot.SlotWithIndex; import ch.njol.util.StringUtils; import ch.njol.util.coll.CollectionUtils; @SuppressWarnings({"rawtypes"}) public class DefaultComparators { public DefaultComparators() {} static { // Number - Number Comparators.registerComparator(Number.class, Number.class, new Comparator<Number, Number>() { @Override public Relation compare(final Number n1, final Number n2) { if (n1 instanceof Long && n2 instanceof Long) return Relation.get(n1.longValue() - n2.longValue()); Double d1 = n1.doubleValue(), d2 = n2.doubleValue(); if (d1.isNaN() || d2.isNaN()) { return Relation.SMALLER; } else if (d1.isInfinite() || d2.isInfinite()) { return d1 > d2 ? Relation.GREATER : d1 < d2 ? Relation.SMALLER : Relation.EQUAL; } else { final double diff = d1 - d2; if (Math.abs(diff) < Skript.EPSILON) return Relation.EQUAL; return Relation.get(diff); } } @Override public boolean supportsOrdering() { return true; } }); // Slot - Slot Comparators.registerComparator(Slot.class, Slot.class, new Comparator<Slot, Slot>() { @Override public Relation compare(Slot o1, Slot o2) { if (o1.isSameSlot(o2)) return Relation.EQUAL; return Relation.NOT_EQUAL; } @Override public boolean supportsOrdering() { return false; } }); // Slot - Number Comparators.registerComparator(Slot.class, Number.class, new Comparator<Slot, Number>() { @Override public Relation compare(Slot o1, Number o2) { if (o1 instanceof SlotWithIndex) { boolean same = ((SlotWithIndex) o1).getIndex() == o2.intValue(); if (same) // Slot has index and the index is same with number return Relation.EQUAL; } return Relation.NOT_EQUAL; } @Override public boolean supportsOrdering() { return false; } }); // Slot - ItemType Comparators.registerComparator(Slot.class, ItemType.class, new Comparator<Slot, ItemType>() { @Override public Relation compare(Slot slot, ItemType item) { return Relation.get(item.isOfType(slot.getItem())); } @Override public boolean supportsOrdering() { return false; } }); // ItemStack - ItemType Comparators.registerComparator(ItemStack.class, ItemType.class, new Comparator<ItemStack, ItemType>() { @Override public Relation compare(final ItemStack is, final ItemType it) { return Relation.get(it.isOfType(is)); } @Override public boolean supportsOrdering() { return false; } }); // Block - ItemType Comparators.registerComparator(Block.class, ItemType.class, new Comparator<Block, ItemType>() { @Override public Relation compare(final Block b, final ItemType it) { return Relation.get(it.isOfType(b)); } @Override public boolean supportsOrdering() { return false; } }); // ItemType - ItemType Comparators.registerComparator(ItemType.class, ItemType.class, new Comparator<ItemType, ItemType>() { @Override public Relation compare(final ItemType i1, final ItemType i2) { return Relation.get(i2.isSupertypeOf(i1)); } @Override public boolean supportsOrdering() { return false; } }); // Block - Block Comparators.registerComparator(Block.class, Block.class, new Comparator<Block, Block>() { @Override public Relation compare(final Block b1, final Block b2) { return Relation.get(b1.equals(b2)); } @Override public boolean supportsOrdering() { return false; } }); // Entity - EntityData Comparators.registerComparator(Entity.class, EntityData.class, new Comparator<Entity, EntityData>() { @Override public Relation compare(final Entity e, final EntityData t) { return Relation.get(t.isInstance(e)); } @Override public boolean supportsOrdering() { return false; } }); // EntityData - EntityData Comparators.registerComparator(EntityData.class, EntityData.class, new Comparator<EntityData, EntityData>() { @Override public Relation compare(final EntityData t1, final EntityData t2) { return Relation.get(t2.isSupertypeOf(t1)); } @Override public boolean supportsOrdering() { return false; } }); } // EntityData - ItemType public final static Comparator<EntityData, ItemType> entityItemComparator = new Comparator<EntityData, ItemType>() { @Override public Relation compare(final EntityData e, final ItemType i) { // TODO fix broken comparisions - will probably require updating potion API of Skript if (e instanceof Item) return Relation.get(i.isOfType(((Item) e).getItemStack())); // if (e instanceof ThrownPotion) // return Relation.get(i.isOfType(Material.POTION.getId(), PotionEffectUtils.guessData((ThrownPotion) e))); // if (Skript.classExists("org.bukkit.entity.WitherSkull") && e instanceof WitherSkull) // return Relation.get(i.isOfType(Material.SKULL_ITEM.getId(), (short) 1)); if (e instanceof BoatData) return Relation.get(((BoatData)e).isOfItemType(i)); for (ItemData data : i.getTypes()) { assert data != null; EntityData<?> entity = Aliases.getRelatedEntity(data); if (entity != null && entity.getType().isAssignableFrom(e.getType())) return Relation.EQUAL; } return Relation.NOT_EQUAL; } @Override public boolean supportsOrdering() { return false; } }; static { Comparators.registerComparator(EntityData.class, ItemType.class, entityItemComparator); // Entity - ItemType // This skips (entity -> entitydata) == itemtype // It was not working reliably, because there is a converter chain // entity -> player -> inventoryholder -> block that sometimes takes a priority Comparators.registerComparator(Entity.class, ItemType.class, new Comparator<Entity, ItemType>() { @Override public Relation compare(Entity entity, ItemType item) { return entityItemComparator.compare(EntityData.fromEntity(entity), item); } @Override public boolean supportsOrdering() { return false; } }); } static { // CommandSender - CommandSender Comparators.registerComparator(CommandSender.class, CommandSender.class, new Comparator<CommandSender, CommandSender>() { @Override public Relation compare(final CommandSender s1, final CommandSender s2) { return Relation.get(s1.equals(s2)); } @Override public boolean supportsOrdering() { return false; } }); // OfflinePlayer - OfflinePlayer Comparators.registerComparator(OfflinePlayer.class, OfflinePlayer.class, new Comparator<OfflinePlayer, OfflinePlayer>() { @Override public Relation compare(final OfflinePlayer p1, final OfflinePlayer p2) { return Relation.get(Objects.equals(p1.getName(), p2.getName())); } @Override public boolean supportsOrdering() { return false; } }); // OfflinePlayer - String Comparators.registerComparator(OfflinePlayer.class, String.class, new Comparator<OfflinePlayer, String>() { @Override public Relation compare(final OfflinePlayer p, final String name) { String offlineName = p.getName(); return offlineName == null ? Relation.NOT_EQUAL : Relation.get(offlineName.equalsIgnoreCase(name)); } @Override public boolean supportsOrdering() { return false; } }); // World - String Comparators.registerComparator(World.class, String.class, new Comparator<World, String>() { @Override public Relation compare(final World w, final String name) { return Relation.get(w.getName().equalsIgnoreCase(name)); } @Override public boolean supportsOrdering() { return false; } }); // String - String Comparators.registerComparator(String.class, String.class, new Comparator<String, String>() { @Override public Relation compare(final String s1, final String s2) { return Relation.get(StringUtils.equals(s1, s2, SkriptConfig.caseSensitive.value())); } @Override public boolean supportsOrdering() { return false; } }); // Date - Date Comparators.registerComparator(Date.class, Date.class, new Comparator<Date, Date>() { @Override public Relation compare(final Date d1, final Date d2) { return Relation.get(d1.compareTo(d2)); } @Override public boolean supportsOrdering() { return true; } }); // Time - Time Comparators.registerComparator(Time.class, Time.class, new Comparator<Time, Time>() { @Override public Relation compare(final Time t1, final Time t2) { return Relation.get(t1.getTime() - t2.getTime()); } @Override public boolean supportsOrdering() { return true; } }); // Timespan - Timespan Comparators.registerComparator(Timespan.class, Timespan.class, new Comparator<Timespan, Timespan>() { @Override public Relation compare(final Timespan t1, final Timespan t2) { return Relation.get(t1.getMilliSeconds() - t2.getMilliSeconds()); } @Override public boolean supportsOrdering() { return true; } }); // Time - Timeperiod Comparators.registerComparator(Time.class, Timeperiod.class, new Comparator<Time, Timeperiod>() { @Override public Relation compare(final Time t, final Timeperiod p) { return Relation.get(p.contains(t)); } @Override public boolean supportsOrdering() { return false; } }); // StructureType - StructureType Comparators.registerComparator(StructureType.class, StructureType.class, new Comparator<StructureType, StructureType>() { @Override public Relation compare(final StructureType s1, final StructureType s2) { return Relation.get(CollectionUtils.containsAll(s2.getTypes(), s2.getTypes())); } @Override public boolean supportsOrdering() { return false; } }); // Object - ClassInfo Comparators.registerComparator(Object.class, ClassInfo.class, new Comparator<Object, ClassInfo>() { @Override public Relation compare(final Object o, final ClassInfo c) { return Relation.get(c.getC().isInstance(o) || o instanceof ClassInfo && c.getC().isAssignableFrom(((ClassInfo<?>) o).getC())); } @Override public boolean supportsOrdering() { return false; } }); // DamageCause - ItemType ItemType lava = Aliases.javaItemType("lava"); Comparators.registerComparator(DamageCause.class, ItemType.class, new Comparator<DamageCause, ItemType>() { @Override public Relation compare(final DamageCause dc, final ItemType t) { switch (dc) { case FIRE: return Relation.get(t.isOfType(Material.LAVA)); case LAVA: return Relation.get(t.equals(lava)); case MAGIC: return Relation.get(t.isOfType(Material.POTION)); //$CASES-OMITTED$ default: return Relation.NOT_EQUAL; } } @Override public boolean supportsOrdering() { return false; } }); // DamageCause - EntityData Comparators.registerComparator(DamageCause.class, EntityData.class, new Comparator<DamageCause, EntityData>() { @Override public Relation compare(final DamageCause dc, final EntityData e) { switch (dc) { case ENTITY_ATTACK: return Relation.get(e.isSupertypeOf(EntityData.fromClass(Entity.class))); case PROJECTILE: return Relation.get(e.isSupertypeOf(EntityData.fromClass(Projectile.class))); case WITHER: return Relation.get(e.isSupertypeOf(EntityData.fromClass(Wither.class))); case FALLING_BLOCK: return Relation.get(e.isSupertypeOf(EntityData.fromClass(FallingBlock.class))); //$CASES-OMITTED$ default: return Relation.NOT_EQUAL; } } @Override public boolean supportsOrdering() { return false; } }); } }