Skip to content

Commit

Permalink
Update for nullable spawner types, editMeta util (#2514)
Browse files Browse the repository at this point in the history
* Add `ItemProperty#editMeta` util

* Update & cleanup `ItemTag.spawner_type`

* Cleanup `ItemInstrument` and use `editMeta`

* Minor cleanup

* Support unsetting the instrument

* Minor cleanup

* `spawnerType` -> `spawnedType`

* Update `LocationTag` ones, make it 1.20+

* Correct no mech input check

* Use a direct cast

* Remove workaround for now fixed Spigot bug
  • Loading branch information
tal5 committed Aug 5, 2023
1 parent f362b88 commit 890a0b6
Show file tree
Hide file tree
Showing 4 changed files with 79 additions and 115 deletions.
Expand Up @@ -1255,13 +1255,14 @@ public static void register() {
// @mechanism LocationTag.spawner_type
// @group world
// @description
// Returns the type of entity spawned by a mob spawner.
// Returns the type of entity spawned by a mob spawner, if any.
// -->
tagProcessor.registerTag(EntityTag.class, "spawner_type", (attribute, object) -> {
if (!(object.getBlockStateForTag(attribute) instanceof CreatureSpawner)) {
if (!(object.getBlockStateForTag(attribute) instanceof CreatureSpawner spawner)) {
return null;
}
return new EntityTag(DenizenEntityType.getByName(((CreatureSpawner) object.getBlockStateForTag(attribute)).getSpawnedType().name()));
EntityType spawnedType = spawner.getSpawnedType();
return spawnedType != null ? new EntityTag(spawnedType) : null;
});

// <--[tag]
Expand Down Expand Up @@ -4249,6 +4250,31 @@ else if (material.hasModernData() && material.getModernData() instanceof org.buk
return biome != null ? new ElementTag(biome.getDownfallTypeAt(object)) : null;
});
}

// <--[mechanism]
// @object LocationTag
// @name spawner_type
// @input EntityTag
// @description
// Sets the entity that a mob spawner will spawn.
// Provide no input to unset (only on 1.20 and above).
// @tags
// <LocationTag.spawner_type>
// -->
tagProcessor.registerMechanism("spawner_type", false, (object, mechanism) -> {
if (!(object.getBlockState() instanceof CreatureSpawner spawner)) {
mechanism.echoError("Mechanism 'LocationTag.spawner_type' is only valid for spawners.");
return;
}
if (!mechanism.hasValue() && NMSHandler.getVersion().isAtLeast(NMSVersion.v1_20)) {
spawner.setSpawnedType(null);
spawner.update();
}
else if (mechanism.requireObject(EntityTag.class)) {
NMSHandler.blockHelper.setSpawnerSpawnedType(spawner, mechanism.valueAsType(EntityTag.class));
spawner.update();
}
});
}

public static final ObjectTagProcessor<LocationTag> tagProcessor = new ObjectTagProcessor<>();
Expand Down Expand Up @@ -4332,21 +4358,6 @@ public void adjust(Mechanism mechanism) {
spawner.update();
}

// <--[mechanism]
// @object LocationTag
// @name spawner_type
// @input EntityTag
// @description
// Sets the entity that a mob spawner will spawn.
// @tags
// <LocationTag.spawner_type>
// -->
if (mechanism.matches("spawner_type") && mechanism.requireObject(EntityTag.class) && getBlockState() instanceof CreatureSpawner) {
CreatureSpawner spawner = ((CreatureSpawner) getBlockState());
NMSHandler.blockHelper.setSpawnerSpawnedType(spawner, mechanism.valueAsType(EntityTag.class));
spawner.update();
}

// <--[mechanism]
// @object LocationTag
// @name spawner_delay_data
Expand Down
Expand Up @@ -15,9 +15,10 @@ public class ItemInstrument extends ItemProperty<ElementTag> {
// @name instrument
// @input ElementTag
// @description
// Sets the instrument of a goat horn.
// Here is a list of valid instruments: admire_goat_horn, call_goat_horn, dream_goat_horn, feel_goat_horn, ponder_goat_horn, seek_goat_horn, sing_goat_horn, yearn_goat_horn.
// Instruments added by datapacks, plugins, etc. are also valid as a namespaced key.
// A goat horn's instrument, if any.
// Goat horns will default to playing "ponder_goat_horn" when the instrument is unset, although this is effectively random and shouldn't be relied on.
// Valid instruments are: admire_goat_horn, call_goat_horn, dream_goat_horn, feel_goat_horn, ponder_goat_horn, seek_goat_horn, sing_goat_horn, yearn_goat_horn.
// For the mechanism: provide no input to unset the instrument.
// @example
// # This can narrate: "This horn has the ponder_goat_horn instrument!"
// - narrate "This horn has the <player.item_in_hand.instrument> instrument!"
Expand All @@ -28,45 +29,34 @@ public class ItemInstrument extends ItemProperty<ElementTag> {
// -->

public static boolean describes(ItemTag item) {
return item.getBukkitMaterial() == Material.GOAT_HORN;
return item.getItemMeta() instanceof MusicInstrumentMeta;
}

@Override
public ElementTag getPropertyValue() {
MusicInstrument instrument = getMusicInstrument();
MusicInstrument instrument = ((MusicInstrumentMeta) getItemMeta()).getInstrument();
if (instrument != null) {
return new ElementTag(Utilities.namespacedKeyToString(instrument.getKey()));
}
return null;
}

@Override
public void setPropertyValue(ElementTag param, Mechanism mechanism) {
MusicInstrument instrument = MusicInstrument.getByKey(Utilities.parseNamespacedKey(param.asString()));
if (instrument == null) {
mechanism.echoError("Invalid horn instrument: '" + param.asString() + "'!");
public void setPropertyValue(ElementTag value, Mechanism mechanism) {
MusicInstrument instrument = value != null ? MusicInstrument.getByKey(Utilities.parseNamespacedKey(value.asString())) : null;
if (value != null && instrument == null) {
mechanism.echoError("Invalid instrument: " + value);
return;
}
setMusicInstrument(instrument);
editMeta(MusicInstrumentMeta.class, meta -> meta.setInstrument(instrument));
}

@Override
public String getPropertyId() {
return "instrument";
}

public MusicInstrument getMusicInstrument() {
MusicInstrumentMeta itemMeta = (MusicInstrumentMeta) getItemMeta();
return itemMeta.getInstrument();
}

public void setMusicInstrument(MusicInstrument instrument) {
MusicInstrumentMeta itemMeta = (MusicInstrumentMeta) getItemMeta();
itemMeta.setInstrument(instrument);
setItemMeta(itemMeta);
}

public static void register() {
autoRegister("instrument", ItemInstrument.class, ElementTag.class, false);
autoRegisterNullable("instrument", ItemInstrument.class, ElementTag.class, false);
}
}
Expand Up @@ -8,6 +8,8 @@
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;

import java.util.function.Consumer;

public abstract class ItemProperty<TData extends ObjectTag> extends ObjectProperty<ItemTag, TData> {

public MaterialTag getMaterialTag() {
Expand All @@ -33,4 +35,10 @@ public void setItemStack(ItemStack item) {
public void setItemMeta(ItemMeta meta) {
object.setItemMeta(meta);
}

public <T extends ItemMeta> void editMeta(Class<T> metaType, Consumer<T> editor) {
T meta = (T) getItemMeta();
editor.accept(meta);
setItemMeta(meta);
}
}
@@ -1,100 +1,55 @@
package com.denizenscript.denizen.objects.properties.item;

import com.denizenscript.denizen.nms.NMSHandler;
import com.denizenscript.denizen.nms.NMSVersion;
import com.denizenscript.denizen.objects.EntityTag;
import com.denizenscript.denizen.objects.ItemTag;
import com.denizenscript.denizencore.objects.Mechanism;
import com.denizenscript.denizencore.objects.ObjectTag;
import com.denizenscript.denizencore.objects.properties.Property;
import com.denizenscript.denizencore.tags.Attribute;
import org.bukkit.block.CreatureSpawner;
import org.bukkit.entity.EntityType;
import org.bukkit.inventory.meta.BlockStateMeta;

public class ItemSpawnerType implements Property {
public class ItemSpawnerType extends ItemProperty<EntityTag> {

public static boolean describes(ObjectTag item) {
return item instanceof ItemTag
&& ((ItemTag) item).getItemMeta() instanceof BlockStateMeta
&& ((BlockStateMeta) ((ItemTag) item).getItemMeta()).getBlockState() instanceof CreatureSpawner;
}
// <--[property]
// @object ItemTag
// @name spawner_type
// @input EntityTag
// @description
// The entity type a spawner item will spawn, if any.
// For the mechanism: provide no input to unset the type.
// Note that the type can only be unset on 1.20 and above.
// -->

public static ItemSpawnerType getFrom(ObjectTag _item) {
if (!describes(_item)) {
return null;
}
else {
return new ItemSpawnerType((ItemTag) _item);
}
public static boolean describes(ItemTag item) {
return item.getItemMeta() instanceof BlockStateMeta meta && meta.getBlockState() instanceof CreatureSpawner;
}

public static final String[] handledTags = new String[] {
"spawner_type"
};

public static final String[] handledMechs = new String[] {
"spawner_type"
};

public ItemSpawnerType(ItemTag _item) {
item = _item;
}

ItemTag item;

@Override
public ObjectTag getObjectAttribute(Attribute attribute) {

if (attribute == null) {
return null;
}

// <--[tag]
// @attribute <ItemTag.spawner_type>
// @returns EntityTag
// @mechanism ItemTag.spawner_type
// @group properties
// @description
// Returns the spawn type for a spawner block item.
// -->
if (attribute.startsWith("spawner_type")) {
BlockStateMeta meta = (BlockStateMeta) item.getItemMeta();
CreatureSpawner state = (CreatureSpawner) meta.getBlockState();
return new EntityTag(state.getSpawnedType())
.getObjectAttribute(attribute.fulfill(1));
}

return null;
public EntityTag getPropertyValue() {
EntityType spawnedType = ((CreatureSpawner) ((BlockStateMeta) getItemMeta()).getBlockState()).getSpawnedType();
return spawnedType != null ? new EntityTag(spawnedType) : null;
}

@Override
public String getPropertyString() {
BlockStateMeta meta = (BlockStateMeta) item.getItemMeta();
CreatureSpawner state = (CreatureSpawner) meta.getBlockState();
return state.getSpawnedType().name();
public void setPropertyValue(EntityTag entity, Mechanism mechanism) {
if (entity == null && NMSHandler.getVersion().isAtMost(NMSVersion.v1_19)) {
mechanism.echoError("must have input of type 'EntityTag', but none was given.");
return;
}
editMeta(BlockStateMeta.class, meta -> {
CreatureSpawner spawner = (CreatureSpawner) meta.getBlockState();
spawner.setSpawnedType(entity != null ? entity.getBukkitEntityType() : null);
meta.setBlockState(spawner);
});
}

@Override
public String getPropertyId() {
return "spawner_type";
}

@Override
public void adjust(Mechanism mechanism) {

// <--[mechanism]
// @object ItemTag
// @name spawner_type
// @input EntityTag
// @description
// Sets the spawn type of a spawner block item.
// @tags
// <ItemTag.spawner_type>
// -->
if (mechanism.matches("spawner_type") && mechanism.requireObject(EntityTag.class)) {
BlockStateMeta meta = (BlockStateMeta) item.getItemMeta();
CreatureSpawner state = (CreatureSpawner) meta.getBlockState();
state.setSpawnedType(mechanism.valueAsType(EntityTag.class).getBukkitEntityType());
meta.setBlockState(state);
item.setItemMeta(meta);
}
public static void register() {
autoRegisterNullable("spawner_type", ItemSpawnerType.class, EntityTag.class, false);
}
}

0 comments on commit 890a0b6

Please sign in to comment.