/**
  * @param types
  * @param type
  * @param worlds worlds or null for all
  * @return All entities of this type in the given worlds
  */
 @SuppressWarnings({"null", "unchecked"})
 public static final <E extends Entity> E[] getAll(
     final EntityData<?>[] types, final Class<E> type, @Nullable World[] worlds) {
   assert types.length > 0;
   if (type == Player.class) {
     if (worlds == null
         && types.length == 1
         && types[0] instanceof PlayerData
         && ((PlayerData) types[0]).op == 0) return (E[]) Bukkit.getOnlinePlayers();
     final List<Player> list = new ArrayList<Player>();
     for (final Player p : Bukkit.getOnlinePlayers()) {
       if (worlds != null && !CollectionUtils.contains(worlds, p.getWorld())) continue;
       for (final EntityData<?> t : types) {
         if (t.isInstance(p)) {
           list.add(p);
           break;
         }
       }
     }
     return (E[]) list.toArray(new Player[list.size()]);
   }
   final List<E> list = new ArrayList<E>();
   if (worlds == null) worlds = Bukkit.getWorlds().toArray(new World[0]);
   for (final World w : worlds) {
     for (final E e : w.getEntitiesByClass(type)) {
       for (final EntityData<?> t : types) {
         if (t.isInstance(e)) {
           list.add(e);
           break;
         }
       }
     }
   }
   return list.toArray((E[]) Array.newInstance(type, list.size()));
 }
 //		return getInfo((Class<? extends EntityData<?>>) d.getClass()).codeName + ":" +
 // d.serialize();
 @SuppressWarnings("null")
 @Override
 @Deprecated
 @Nullable
 public EntityData deserialize(final String s) {
   final String[] split = s.split(":", 2);
   if (split.length != 2) return null;
   final EntityDataInfo<?> i = getInfo(split[0]);
   if (i == null) return null;
   EntityData<?> d;
   try {
     d = i.c.newInstance();
   } catch (final Exception e) {
     Skript.exception(e, "Can't create an instance of " + i.c.getCanonicalName());
     return null;
   }
   if (!d.deserialize(split[1])) return null;
   return d;
 }
 @Override
 protected EntityData deserialize(final Fields fields)
     throws StreamCorruptedException, NotSerializableException {
   final String codeName = fields.getAndRemoveObject("codeName", String.class);
   if (codeName == null) throw new StreamCorruptedException();
   final EntityDataInfo<?> info = getInfo(codeName);
   if (info == null)
     throw new StreamCorruptedException("Invalid EntityData code name " + codeName);
   try {
     final EntityData<?> d = info.c.newInstance();
     d.deserialize(fields);
     return d;
   } catch (final InstantiationException e) {
     Skript.exception(e);
   } catch (final IllegalAccessException e) {
     Skript.exception(e);
   }
   throw new StreamCorruptedException();
 }
 private static <E extends Entity> EntityData<? super E> getData(
     final @Nullable Class<E> c, final @Nullable E e) {
   assert c == null ^ e == null;
   assert c == null || c.isInterface();
   for (final EntityDataInfo<?> info : infos) {
     if (info.entityClass != Entity.class
         && (e == null ? info.entityClass.isAssignableFrom(c) : info.entityClass.isInstance(e))) {
       try {
         @SuppressWarnings("unchecked")
         final EntityData<E> d = (EntityData<E>) info.c.newInstance();
         if (d.init(c, e)) return d;
       } catch (final Exception ex) {
         throw Skript.exception(ex);
       }
     }
   }
   if (e != null) {
     return new SimpleEntityData(e);
   } else {
     assert c != null;
     return new SimpleEntityData(c);
   }
 }
 @Override
 public Fields serialize(final EntityData o) throws NotSerializableException {
   final Fields f = o.serialize();
   f.putObject("codeName", o.info.codeName);
   return f;
 }