Skip to content

Commit

Permalink
Add support for spawning dropped items (#6746)
Browse files Browse the repository at this point in the history
* add support for spawning dropped items 1.17+

* requested changes

* Update DroppedItemData.java

* requested changes

* Update src/main/java/ch/njol/skript/sections/EffSecSpawn.java

Co-authored-by: Patrick Miller <apickledwalrus@gmail.com>

---------

Co-authored-by: Moderocky <admin@moderocky.com>
Co-authored-by: Patrick Miller <apickledwalrus@gmail.com>
  • Loading branch information
3 people authored May 31, 2024
1 parent a4a72d0 commit 4f3ace9
Show file tree
Hide file tree
Showing 3 changed files with 95 additions and 45 deletions.
126 changes: 83 additions & 43 deletions src/main/java/ch/njol/skript/entity/DroppedItemData.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,16 @@
*/
package ch.njol.skript.entity;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.function.Consumer;

import ch.njol.skript.Skript;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.entity.Item;
import org.bukkit.inventory.ItemStack;
import org.eclipse.jdt.annotation.Nullable;

import ch.njol.skript.aliases.ItemType;
import ch.njol.skript.lang.Literal;
Expand All @@ -32,71 +37,76 @@
import ch.njol.skript.localization.Noun;
import ch.njol.skript.registrations.Classes;
import ch.njol.util.coll.CollectionUtils;
import org.jetbrains.annotations.Nullable;

/**
* @author Peter Güttinger
*/
public class DroppedItemData extends EntityData<Item> {

private static final boolean HAS_JAVA_CONSUMER_DROP = Skript.methodExists(World.class, "dropItem", Location.class, ItemStack.class, Consumer.class);
private static @Nullable Method BUKKIT_CONSUMER_DROP;

static {
EntityData.register(DroppedItemData.class, "dropped item", Item.class, "dropped item");

try {
BUKKIT_CONSUMER_DROP = World.class.getDeclaredMethod("dropItem", Location.class, ItemStack.class, org.bukkit.util.Consumer.class);
} catch (NoSuchMethodException | SecurityException ignored) {}
}

private final static Adjective m_adjective = new Adjective("entities.dropped item.adjective");

@Nullable
private ItemType[] types;

private ItemType @Nullable [] types;

public DroppedItemData() {}

public DroppedItemData(@Nullable ItemType[] types) {
public DroppedItemData(ItemType @Nullable [] types) {
this.types = types;
}

@Override
protected boolean init(final Literal<?>[] exprs, final int matchedPattern, final ParseResult parseResult) {
if (exprs.length > 0 && exprs[0] != null)
types = (ItemType[]) exprs[0].getAll();
protected boolean init(Literal<?>[] expressions, int matchedPattern, ParseResult parseResult) {
if (expressions.length > 0 && expressions[0] != null)
types = (ItemType[]) expressions[0].getAll();
return true;
}

@Override
protected boolean init(final @Nullable Class<? extends Item> c, final @Nullable Item e) {
if (e != null) {
final ItemStack i = e.getItemStack();
protected boolean init(@Nullable Class<? extends Item> clazz, @Nullable Item itemEntity) {
if (itemEntity != null) {
final ItemStack i = itemEntity.getItemStack();
types = new ItemType[] {new ItemType(i)};
}
return true;
}

@Override
protected boolean match(final Item entity) {
protected boolean match(Item entity) {
if (types != null) {
for (final ItemType t : types) {
for (ItemType t : types) {
if (t.isOfType(entity.getItemStack()))
return true;
}
return false;
} else {
return true;
}
return true;
}

@Override
public void set(final Item entity) {
if (types == null)
return;
final ItemType t = CollectionUtils.getRandom(types);
assert t != null;
ItemStack stack = t.getItem().getRandom();
if (stack != null)
entity.setItemStack(stack);
entity.setItemStack(stack);
}

@Override
public boolean isSupertypeOf(final EntityData<?> e) {
if (!(e instanceof DroppedItemData))
public boolean isSupertypeOf(EntityData<?> otherData) {
if (!(otherData instanceof DroppedItemData))
return false;
final DroppedItemData d = (DroppedItemData) e;
DroppedItemData otherItemData = (DroppedItemData) otherData;
if (types != null)
return d.types != null && ItemType.isSubset(types, d.types);
return otherItemData.types != null && ItemType.isSubset(types, otherItemData.types);
return true;
}

Expand All @@ -111,36 +121,66 @@ public EntityData getSuperType() {
}

@Override
public String toString(final int flags) {
final ItemType[] types = this.types;
public String toString(int flags) {
if (types == null)
return super.toString(flags);
final StringBuilder b = new StringBuilder();
b.append(Noun.getArticleWithSpace(types[0].getTypes().get(0).getGender(), flags));
b.append(m_adjective.toString(types[0].getTypes().get(0).getGender(), flags));
b.append(" ");
b.append(Classes.toString(types, flags & Language.NO_ARTICLE_MASK, false));
return "" + b.toString();
int gender = types[0].getTypes().get(0).getGender();
return Noun.getArticleWithSpace(gender, flags) +
m_adjective.toString(gender, flags) +
" " +
Classes.toString(types, flags & Language.NO_ARTICLE_MASK, false);
}

// return ItemType.serialize(types);

@Override
@Deprecated
protected boolean deserialize(final String s) {
protected boolean deserialize(String s) {
throw new UnsupportedOperationException("old serialization is no longer supported");
// if (s.isEmpty())
// return true;
// types = ItemType.deserialize(s);
// return types != null;
}

@Override
protected boolean equals_i(final EntityData<?> obj) {
if (!(obj instanceof DroppedItemData))
protected boolean equals_i(EntityData<?> otherData) {
if (!(otherData instanceof DroppedItemData))
return false;
return Arrays.equals(types, ((DroppedItemData) obj).types);
return Arrays.equals(types, ((DroppedItemData) otherData).types);
}


@Override
public boolean canSpawn(@Nullable World world) {
return types != null && types.length > 0 && world != null;
}

@Override
public @Nullable Item spawn(Location location, @Nullable Consumer<Item> consumer) {
World world = location.getWorld();
if (!canSpawn(world))
return null;
assert types != null && types.length > 0;

final ItemType itemType = CollectionUtils.getRandom(types);
assert itemType != null;
ItemStack stack = itemType.getItem().getRandom();

Item item;
if (consumer == null) {
item = world.dropItem(location, stack);
} else if (HAS_JAVA_CONSUMER_DROP) {
item = world.dropItem(location, stack, consumer);
} else if (BUKKIT_CONSUMER_DROP != null) {
try {
// noinspection deprecation
item = (Item) BUKKIT_CONSUMER_DROP.invoke(world, location, stack, (org.bukkit.util.Consumer<Item>) consumer::accept);
} catch (InvocationTargetException | IllegalAccessException e) {
if (Skript.testing())
Skript.exception(e, "Can't spawn " + this.getName());
return null;
}
} else {
item = world.dropItem(location, stack);
consumer.accept(item);
}
return item;
}

@Override
protected int hashCode_i() {
return Arrays.hashCode(types);
Expand Down
5 changes: 3 additions & 2 deletions src/main/java/ch/njol/skript/sections/EffSecSpawn.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Consumer;

import ch.njol.skript.doc.RequiredPlugins;
import org.bukkit.Location;
import org.bukkit.entity.Entity;
import org.bukkit.event.Event;
Expand Down Expand Up @@ -58,9 +59,9 @@
"spawn 3 creepers at the targeted block",
"spawn a ghast 5 meters above the player",
"spawn a zombie at the player:",
"\tset name of the zombie to \"\""
"\tset name of the zombie to \"\""
})
@Since("1.0, 2.6.1 (with section)")
@Since("1.0, 2.6.1 (with section), INSERT VERSION (dropped items)")
public class EffSecSpawn extends EffectSection {

public static class SpawnEvent extends Event {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
test "spawn dropped item":
spawn dropped stone at spawn of world "world":
set {_e} to entity
assert {_e} is set with "failed to spawn dropped stone"
delete entity within {_e}

spawn dropped item at spawn of world "world":
set {_e2} to entity
assert {_e2} is not set with "spawned `dropped item` despite undefined item type"

0 comments on commit 4f3ace9

Please sign in to comment.