/** * 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.entity; import java.util.Arrays; import org.bukkit.Bukkit; import org.bukkit.Material; import org.bukkit.block.data.BlockData; import org.bukkit.entity.Enderman; import org.bukkit.inventory.ItemStack; import org.bukkit.material.MaterialData; import org.eclipse.jdt.annotation.Nullable; import ch.njol.skript.Skript; import ch.njol.skript.aliases.ItemType; import ch.njol.skript.lang.Literal; import ch.njol.skript.lang.SkriptParser.ParseResult; import ch.njol.skript.lang.util.SimpleExpression; import ch.njol.skript.localization.ArgsMessage; import ch.njol.skript.registrations.Classes; import ch.njol.util.Checker; import ch.njol.util.coll.CollectionUtils; @SuppressWarnings("deprecation") public class EndermanData extends EntityData<Enderman> { static { EntityData.register(EndermanData.class, "enderman", Enderman.class, "enderman"); } /** * Spigot 1.13 introduced new block data API, which must be used instead * of the old one if targeting API version 1.13. */ static final boolean useBlockData = Skript.isRunningMinecraft(1, 13); @Nullable private ItemType[] hand = null; @SuppressWarnings("unchecked") @Override protected boolean init(final Literal<?>[] exprs, final int matchedPattern, final ParseResult parseResult) { if (exprs[0] != null) hand = ((Literal<ItemType>) exprs[0]).getAll(); return true; } @Override protected boolean init(final @Nullable Class<? extends Enderman> c, final @Nullable Enderman e) { if (e != null) { if (useBlockData) { BlockData data = e.getCarriedBlock(); if (data != null) { Material type = data.getMaterial(); assert type != null; hand = new ItemType[] {new ItemType(type)}; } } else { MaterialData m = e.getCarriedMaterial(); if (m != null) { final ItemStack i = m.toItemStack(1); if (i == null) return false; hand = new ItemType[] {new ItemType(i)}; } } } return true; } @Override public void set(final Enderman entity) { if (hand != null) { final ItemType t = CollectionUtils.getRandom(hand); assert t != null; final ItemStack i = t.getBlock().getRandom(); if (i != null) { if (useBlockData) { // 1.13: item->block usually keeps only material entity.setCarriedBlock(Bukkit.createBlockData(i.getType())); } else { MaterialData data = i.getData(); assert data != null; entity.setCarriedMaterial(data); } } } } @Override public boolean match(final Enderman entity) { return hand == null || SimpleExpression.check(hand, new Checker<ItemType>() { @SuppressWarnings("null") @Override public boolean check(final @Nullable ItemType t) { // TODO {Block/Material}Data -> Material conversion is not 100% accurate, needs a better solution if (useBlockData) return t != null && t.isOfType(entity.getCarriedBlock().getMaterial()); else return t != null && t.isOfType(entity.getCarriedMaterial().getItemType()); } }, false, false); } @Override public Class<Enderman> getType() { return Enderman.class; } private final static ArgsMessage format = new ArgsMessage("entities.enderman.format"); @Override public String toString(final int flags) { final ItemType[] hand = this.hand; if (hand == null) return super.toString(flags); return format.toString(super.toString(flags), Classes.toString(hand, false)); } @Override protected int hashCode_i() { return Arrays.hashCode(hand); } @Override protected boolean equals_i(final EntityData<?> obj) { if (!(obj instanceof EndermanData)) return false; final EndermanData other = (EndermanData) obj; return Arrays.equals(hand, other.hand); } // if (hand == null) // return ""; // final StringBuilder b = new StringBuilder(); // for (final ItemType h : hand) { // final Pair<String, String> s = Classes.serialize(h); // if (s == null) // return null; // if (b.length() != 0) // b.append(","); // b.append(s.first); // b.append(":"); // b.append(s.second.replace(",", ",,").replace(":", "::")); // } // return b.toString(); @SuppressWarnings("null") @Override @Deprecated protected boolean deserialize(final String s) { if (s.isEmpty()) return true; final String[] split = s.split("(?<!,),(?!,)"); hand = new ItemType[split.length]; for (int i = 0; i < hand.length; i++) { final String[] t = split[i].split("(?<!:):(?::)"); if (t.length != 2) return false; final Object o = Classes.deserialize(t[0], t[1].replace(",,", ",").replace("::", ":")); if (o == null || !(o instanceof ItemType)) return false; hand[i] = (ItemType) o; } return false; } private boolean isSubhand(final @Nullable ItemType[] sub) { if (hand != null) return sub != null && ItemType.isSubset(hand, sub); return true; } @Override public boolean isSupertypeOf(final EntityData<?> e) { if (e instanceof EndermanData) return isSubhand(((EndermanData) e).hand); return false; } @Override public EntityData getSuperType() { return new EndermanData(); } }