denizenType, DataComponentType.Valued componentType, String name) {
+ super(componentType, denizenType, name);
+ }
+
+ public abstract D toDenizen(P value);
+
+ public abstract P fromDenizen(D value, Mechanism mechanism);
+
+ @Override
+ public D getValue(ItemStack item) {
+ P data = item.getData(componentType);
+ return data != null ? toDenizen(data) : null;
+ }
+
+ @Override
+ public void setValue(ItemStack item, D value, Mechanism mechanism) {
+ P converted = fromDenizen(value, mechanism);
+ if (converted != null) {
+ item.setData(componentType, converted);
+ }
+ }
+ }
+
+ public class Property extends ItemProperty {
+
+ private static DataComponentAdapter, ?> currentlyRegisteringComponentAdapter;
+
+ public Property(ItemTag item) {
+ this.object = item;
+ }
+
+ @Override
+ public D getPropertyValue() {
+ return getValue(getItemStack());
+ }
+
+ @Override
+ public D getPropertyValueNoDefault() {
+ if (!getItemStack().isDataOverridden(componentType)) {
+ return null;
+ }
+ return super.getPropertyValueNoDefault();
+ }
+
+ @Override
+ public boolean isDefaultValue(D value) {
+ return DataComponentAdapter.this.isDefaultValue(value);
+ }
+
+ @Override
+ public void setPropertyValue(D value, Mechanism mechanism) {
+ if (value == null) {
+ getItemStack().resetData(componentType);
+ return;
+ }
+ setValue(getItemStack(), value, mechanism);
+ }
+
+ @Override
+ public String getPropertyId() {
+ return name;
+ }
+
+ public static void register() {
+ autoRegisterNullable(currentlyRegisteringComponentAdapter.name, DataComponentAdapter.Property.class, currentlyRegisteringComponentAdapter.denizenType, false);
+ }
+ }
+}
diff --git a/paper/src/main/java/com/denizenscript/denizen/paper/datacomponents/FoodAdapter.java b/paper/src/main/java/com/denizenscript/denizen/paper/datacomponents/FoodAdapter.java
new file mode 100644
index 0000000000..4f6710f1fd
--- /dev/null
+++ b/paper/src/main/java/com/denizenscript/denizen/paper/datacomponents/FoodAdapter.java
@@ -0,0 +1,46 @@
+package com.denizenscript.denizen.paper.datacomponents;
+
+import com.denizenscript.denizencore.objects.Mechanism;
+import com.denizenscript.denizencore.objects.core.ElementTag;
+import com.denizenscript.denizencore.objects.core.MapTag;
+import io.papermc.paper.datacomponent.DataComponentTypes;
+import io.papermc.paper.datacomponent.item.FoodProperties;
+
+public class FoodAdapter extends DataComponentAdapter.Valued {
+
+ // <--[property]
+ // @object ItemTag
+ // @name food
+ // @input MapTag
+ // @description
+ // Controls an item's food <@link language Item Components>.
+ // The map includes keys:
+ // - "nutrition", ElementTag(Number) representing the amount of food points restored by this item.
+ // - "saturation", ElementTag(Decimal) representing the amount of saturation points restored by this item.
+ // - "can_always_eat", ElementTag(Boolean) controlling whether the item can always be eaten, even if the player isn't hungry.
+ // @mechanism
+ // Provide no input to reset the item to its default value.
+ // -->
+
+ public FoodAdapter() {
+ super(MapTag.class, DataComponentTypes.FOOD, "food");
+ }
+
+ @Override
+ public MapTag toDenizen(FoodProperties value) {
+ MapTag foodData = new MapTag();
+ foodData.putObject("nutrition", new ElementTag(value.nutrition()));
+ foodData.putObject("saturation", new ElementTag(value.saturation()));
+ foodData.putObject("can_always_eat", new ElementTag(value.canAlwaysEat()));
+ return foodData;
+ }
+
+ @Override
+ public FoodProperties fromDenizen(MapTag value, Mechanism mechanism) {
+ FoodProperties.Builder builder = FoodProperties.food();
+ setIfValid(builder::nutrition, value, "nutrition", ElementTag.class, ElementTag::isInt, ElementTag::asInt, "number", mechanism);
+ setIfValid(builder::saturation, value, "saturation", ElementTag.class, ElementTag::isFloat, ElementTag::asFloat, "decimal number", mechanism);
+ setIfValid(builder::canAlwaysEat, value, "can_always_eat", ElementTag.class, ElementTag::isBoolean, ElementTag::asBoolean, "boolean", mechanism);
+ return builder.build();
+ }
+}
diff --git a/paper/src/main/java/com/denizenscript/denizen/paper/datacomponents/GliderAdapter.java b/paper/src/main/java/com/denizenscript/denizen/paper/datacomponents/GliderAdapter.java
new file mode 100644
index 0000000000..838f02ca72
--- /dev/null
+++ b/paper/src/main/java/com/denizenscript/denizen/paper/datacomponents/GliderAdapter.java
@@ -0,0 +1,20 @@
+package com.denizenscript.denizen.paper.datacomponents;
+
+import io.papermc.paper.datacomponent.DataComponentTypes;
+
+public class GliderAdapter extends DataComponentAdapter.NonValued {
+
+ // <--[property]
+ // @object ItemTag
+ // @name glider
+ // @input ElementTag(Boolean)
+ // @description
+ // Controls whether an item can be used to glide when equipped (like elytras by default), see <@link language Item Components>.
+ // @mechanism
+ // Provide no input to reset the item to its default value.
+ // -->
+
+ public GliderAdapter() {
+ super(DataComponentTypes.GLIDER, "glider");
+ }
+}
diff --git a/paper/src/main/java/com/denizenscript/denizen/paper/datacomponents/ItemModelAdapter.java b/paper/src/main/java/com/denizenscript/denizen/paper/datacomponents/ItemModelAdapter.java
new file mode 100644
index 0000000000..f9eb15acbd
--- /dev/null
+++ b/paper/src/main/java/com/denizenscript/denizen/paper/datacomponents/ItemModelAdapter.java
@@ -0,0 +1,36 @@
+package com.denizenscript.denizen.paper.datacomponents;
+
+import com.denizenscript.denizen.utilities.Utilities;
+import com.denizenscript.denizencore.objects.Mechanism;
+import com.denizenscript.denizencore.objects.core.ElementTag;
+import io.papermc.paper.datacomponent.DataComponentTypes;
+import net.kyori.adventure.key.Key;
+
+public class ItemModelAdapter extends DataComponentAdapter.Valued {
+
+ // <--[property]
+ // @object ItemTag
+ // @name item_model
+ // @input ElementTag
+ // @description
+ // Controls an item's model <@link language Item Components> in namespaced key format.
+ // The default namespace is "minecraft", so for example an input of "stone" becomes "minecraft:stone", and will set the item model to a stone block.
+ // This can also be used to display item models from your own custom resource packs.
+ // @mechanism
+ // Provide no input to reset the item to its default value.
+ // -->
+
+ public ItemModelAdapter() {
+ super(ElementTag.class, DataComponentTypes.ITEM_MODEL, "item_model");
+ }
+
+ @Override
+ public ElementTag toDenizen(Key value) {
+ return new ElementTag(value.asMinimalString(), true);
+ }
+
+ @Override
+ public Key fromDenizen(ElementTag value, Mechanism mechanism) {
+ return Utilities.parseNamespacedKey(value.asString());
+ }
+}
diff --git a/paper/src/main/java/com/denizenscript/denizen/paper/datacomponents/MaxDurabilityAdapter.java b/paper/src/main/java/com/denizenscript/denizen/paper/datacomponents/MaxDurabilityAdapter.java
new file mode 100644
index 0000000000..cc021bda08
--- /dev/null
+++ b/paper/src/main/java/com/denizenscript/denizen/paper/datacomponents/MaxDurabilityAdapter.java
@@ -0,0 +1,34 @@
+package com.denizenscript.denizen.paper.datacomponents;
+
+import com.denizenscript.denizencore.objects.Mechanism;
+import com.denizenscript.denizencore.objects.core.ElementTag;
+import io.papermc.paper.datacomponent.DataComponentTypes;
+
+public class MaxDurabilityAdapter extends DataComponentAdapter.Valued {
+
+ // <--[property]
+ // @object ItemTag
+ // @name max_durability
+ // @input ElementTag(Number)
+ // @description
+ // Controls the maximum durability (number of uses) of this item.
+ // For use with <@link tag ItemTag.durability> and <@link mechanism ItemTag.durability>.
+ // See also <@link language Item Components>.
+ // @mechanism
+ // Provide no input to reset the item to its default value.
+ // -->
+
+ public MaxDurabilityAdapter() {
+ super(ElementTag.class, DataComponentTypes.MAX_DAMAGE, "max_durability");
+ }
+
+ @Override
+ public ElementTag toDenizen(Integer value) {
+ return new ElementTag(value);
+ }
+
+ @Override
+ public Integer fromDenizen(ElementTag value, Mechanism mechanism) {
+ return mechanism.requireInteger() ? value.asInt() : null;
+ }
+}
diff --git a/paper/src/main/java/com/denizenscript/denizen/paper/datacomponents/MaxStackSizeAdapter.java b/paper/src/main/java/com/denizenscript/denizen/paper/datacomponents/MaxStackSizeAdapter.java
new file mode 100644
index 0000000000..c9365207dd
--- /dev/null
+++ b/paper/src/main/java/com/denizenscript/denizen/paper/datacomponents/MaxStackSizeAdapter.java
@@ -0,0 +1,32 @@
+package com.denizenscript.denizen.paper.datacomponents;
+
+import com.denizenscript.denizencore.objects.Mechanism;
+import com.denizenscript.denizencore.objects.core.ElementTag;
+import io.papermc.paper.datacomponent.DataComponentTypes;
+
+public class MaxStackSizeAdapter extends DataComponentAdapter.Valued {
+
+ // <--[property]
+ // @object ItemTag
+ // @name max_stack_size
+ // @input ElementTag(Number)
+ // @description
+ // Controls an item's max stack size <@link language Item Components>.
+ // @mechanism
+ // Provide no input to reset the item to its default value.
+ // -->
+
+ public MaxStackSizeAdapter() {
+ super(ElementTag.class, DataComponentTypes.MAX_STACK_SIZE, "max_stack_size");
+ }
+
+ @Override
+ public ElementTag toDenizen(Integer value) {
+ return new ElementTag(value);
+ }
+
+ @Override
+ public Integer fromDenizen(ElementTag value, Mechanism mechanism) {
+ return mechanism.requireInteger() ? value.asInt() : null;
+ }
+}
diff --git a/paper/src/main/java/com/denizenscript/denizen/paper/datacomponents/RarityAdapter.java b/paper/src/main/java/com/denizenscript/denizen/paper/datacomponents/RarityAdapter.java
new file mode 100644
index 0000000000..9772fd51bf
--- /dev/null
+++ b/paper/src/main/java/com/denizenscript/denizen/paper/datacomponents/RarityAdapter.java
@@ -0,0 +1,34 @@
+package com.denizenscript.denizen.paper.datacomponents;
+
+import com.denizenscript.denizencore.objects.Mechanism;
+import com.denizenscript.denizencore.objects.core.ElementTag;
+import io.papermc.paper.datacomponent.DataComponentTypes;
+import org.bukkit.inventory.ItemRarity;
+
+public class RarityAdapter extends DataComponentAdapter.Valued {
+
+ // <--[property]
+ // @object ItemTag
+ // @name rarity
+ // @input ElementTag
+ // @description
+ // Controls an item's rarity <@link language Item Components>.
+ // See <@link url https://jd.papermc.io/paper/org/bukkit/inventory/ItemRarity.html> for valid rarity values.
+ // @mechanism
+ // Provide no input to reset the item to its default value.
+ // -->
+
+ public RarityAdapter() {
+ super(ElementTag.class, DataComponentTypes.RARITY, "rarity");
+ }
+
+ @Override
+ public ElementTag toDenizen(ItemRarity value) {
+ return new ElementTag(value);
+ }
+
+ @Override
+ public ItemRarity fromDenizen(ElementTag value, Mechanism mechanism) {
+ return mechanism.requireEnum(ItemRarity.class) ? value.asEnum(ItemRarity.class) : null;
+ }
+}
diff --git a/paper/src/main/java/com/denizenscript/denizen/paper/events/AnvilBlockDamagedScriptEvent.java b/paper/src/main/java/com/denizenscript/denizen/paper/events/AnvilBlockDamagedScriptEvent.java
index effc8f9e27..5f4268d66b 100644
--- a/paper/src/main/java/com/denizenscript/denizen/paper/events/AnvilBlockDamagedScriptEvent.java
+++ b/paper/src/main/java/com/denizenscript/denizen/paper/events/AnvilBlockDamagedScriptEvent.java
@@ -36,7 +36,7 @@ public class AnvilBlockDamagedScriptEvent extends BukkitScriptEvent implements L
//
// @Determine
// "STATE:" to set the anvil's new damage state.
- // "BREAK:" to set weather the anvil will break.
+ // "BREAK:" to set whether the anvil will break.
// -->
public AnvilBlockDamagedScriptEvent() {
diff --git a/paper/src/main/java/com/denizenscript/denizen/paper/events/PlayerNameEntityScriptEvent.java b/paper/src/main/java/com/denizenscript/denizen/paper/events/PlayerNamesEntityScriptEvent.java
similarity index 88%
rename from paper/src/main/java/com/denizenscript/denizen/paper/events/PlayerNameEntityScriptEvent.java
rename to paper/src/main/java/com/denizenscript/denizen/paper/events/PlayerNamesEntityScriptEvent.java
index 41d421bd78..81627cd96c 100644
--- a/paper/src/main/java/com/denizenscript/denizen/paper/events/PlayerNameEntityScriptEvent.java
+++ b/paper/src/main/java/com/denizenscript/denizen/paper/events/PlayerNamesEntityScriptEvent.java
@@ -13,7 +13,7 @@
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
-public class PlayerNameEntityScriptEvent extends BukkitScriptEvent implements Listener {
+public class PlayerNamesEntityScriptEvent extends BukkitScriptEvent implements Listener {
// <--[event]
// @Events
@@ -43,16 +43,16 @@ public class PlayerNameEntityScriptEvent extends BukkitScriptEvent implements Li
//
// -->
- public PlayerNameEntityScriptEvent() {
+ public PlayerNamesEntityScriptEvent() {
registerCouldMatcher("player names ");
- this.registerOptionalDetermination("persistent", ElementTag.class, (evt, context, determination) -> {
+ this.registerOptionalDetermination("persistent", ElementTag.class, (evt, context, determination) -> {
if (determination.isBoolean()) {
evt.event.setPersistent(determination.asBoolean());
return true;
}
return false;
});
- this.registerDetermination("name", ElementTag.class, (evt, context, determination) -> {
+ this.registerDetermination("name", ElementTag.class, (evt, context, determination) -> {
evt.event.setName(PaperModule.parseFormattedText(determination.toString(), ChatColor.WHITE));
});
}
diff --git a/paper/src/main/java/com/denizenscript/denizen/paper/events/PlayerReceivesLinksScriptEvent.java b/paper/src/main/java/com/denizenscript/denizen/paper/events/PlayerReceivesLinksScriptEvent.java
new file mode 100644
index 0000000000..90bd7d51e8
--- /dev/null
+++ b/paper/src/main/java/com/denizenscript/denizen/paper/events/PlayerReceivesLinksScriptEvent.java
@@ -0,0 +1,69 @@
+package com.denizenscript.denizen.paper.events;
+
+import com.denizenscript.denizen.events.BukkitScriptEvent;
+import com.denizenscript.denizen.objects.PlayerTag;
+import com.denizenscript.denizen.utilities.Utilities;
+import com.denizenscript.denizen.utilities.implementation.BukkitScriptEntryData;
+import com.denizenscript.denizencore.objects.core.ListTag;
+import com.denizenscript.denizencore.scripts.ScriptEntryData;
+import io.papermc.paper.connection.PlayerConfigurationConnection;
+import io.papermc.paper.connection.PlayerGameConnection;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.Listener;
+import org.bukkit.event.player.PlayerLinksSendEvent;
+
+public class PlayerReceivesLinksScriptEvent extends BukkitScriptEvent implements Listener {
+
+ // <--[event]
+ // @Events
+ // player receives links
+ //
+ // @Group Paper
+ //
+ // @Plugin Paper
+ //
+ // @Triggers when a player receives a list of server links.
+ //
+ // @Determine
+ // "LINKS:" to set the links sent to the player. Each item in the list must be a MapTag in <@link language Server Links Format>.
+ // "ADD_LINKS:" to send additional links to the player. Each item in the list must be a MapTag in <@link language Server Links Format>.
+ //
+ // @Player Always.
+ //
+ // @Warning this may fire early in the player login process, during which the linked player is essentially an offline player.
+ //
+ // -->
+
+ public PlayerLinksSendEvent event;
+ public PlayerTag player;
+
+ public PlayerReceivesLinksScriptEvent() {
+ registerCouldMatcher("player receives links");
+ this.registerDetermination("links", ListTag.class, (evt, context, value) -> {
+ Utilities.replaceServerLinks(evt.event.getLinks(), value, context);
+ });
+ this.registerDetermination("add_links", ListTag.class, (evt, context, value) -> {
+ Utilities.fillServerLinks(evt.event.getLinks(), value, context);
+ });
+ }
+
+ @Override
+ public ScriptEntryData getScriptEntryData() {
+ return new BukkitScriptEntryData(player, null);
+ }
+
+ @EventHandler
+ public void onPlayerLinksSend(PlayerLinksSendEvent event) {
+ if (event.getConnection() instanceof PlayerGameConnection gameConnection) {
+ player = new PlayerTag(gameConnection.getPlayer());
+ }
+ else if (event.getConnection() instanceof PlayerConfigurationConnection configConnection) {
+ player = new PlayerTag(configConnection.getProfile().getId());
+ }
+ else {
+ throw new IllegalStateException("Links send event fired with unknown connection type! " + event.getConnection() + " / " + event.getConnection().getClass().getName());
+ }
+ this.event = event;
+ fire(event);
+ }
+}
diff --git a/paper/src/main/java/com/denizenscript/denizen/paper/events/ServerListPingScriptEventPaperImpl.java b/paper/src/main/java/com/denizenscript/denizen/paper/events/ServerListPingScriptEventPaperImpl.java
index 6ea097a13d..af4af93b2b 100644
--- a/paper/src/main/java/com/denizenscript/denizen/paper/events/ServerListPingScriptEventPaperImpl.java
+++ b/paper/src/main/java/com/denizenscript/denizen/paper/events/ServerListPingScriptEventPaperImpl.java
@@ -15,6 +15,7 @@
import com.destroystokyo.paper.profile.PlayerProfile;
import com.destroystokyo.paper.profile.ProfileProperty;
import net.md_5.bungee.api.ChatColor;
+import org.apache.commons.lang3.mutable.MutableInt;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.profile.PlayerTextures;
@@ -70,6 +71,17 @@ public ServerListPingScriptEventPaperImpl() {
ListedPlayersEditor.setListedPlayerInfo(evt.getEvent(), text);
return true;
});
+ this.registerOptionalDetermination("player_count", ElementTag.class, (evt, context, input) -> {
+ if (!CoreConfiguration.allowRestrictedActions) {
+ Debug.echoError("Cannot use 'player_count' in list ping event: 'Allow restricted actions' is disabled in Denizen config.yml.");
+ return false;
+ }
+ if (input.isInt()) {
+ evt.getEvent().setNumPlayers(input.asInt());
+ return true;
+ }
+ return false;
+ });
}
public PaperServerListPingEvent getEvent() {
@@ -86,7 +98,18 @@ public static void setListedPlayerInfo(PaperServerListPingEvent event, List exclude) {
- event.getListedPlayers().removeIf(listedPlayerInfo -> exclude.contains(listedPlayerInfo.id()));
+ int size = event.getListedPlayers().size();
+ MutableInt counter = new MutableInt();
+ event.getListedPlayers().removeIf(listedPlayerInfo -> {
+ if (exclude.contains(listedPlayerInfo.id())) {
+ counter.increment();
+ return true;
+ }
+ return false;
+ });
+ if (size == event.getNumPlayers()) {
+ event.setNumPlayers(event.getNumPlayers() - counter.intValue());
+ }
}
}
diff --git a/paper/src/main/java/com/denizenscript/denizen/paper/events/VaultChangesStateScriptEvent.java b/paper/src/main/java/com/denizenscript/denizen/paper/events/VaultChangesStateScriptEvent.java
new file mode 100644
index 0000000000..33100459ab
--- /dev/null
+++ b/paper/src/main/java/com/denizenscript/denizen/paper/events/VaultChangesStateScriptEvent.java
@@ -0,0 +1,74 @@
+package com.denizenscript.denizen.paper.events;
+
+import com.denizenscript.denizen.events.BukkitScriptEvent;
+import com.denizenscript.denizen.objects.LocationTag;
+import com.denizenscript.denizen.utilities.implementation.BukkitScriptEntryData;
+import com.denizenscript.denizencore.objects.ObjectTag;
+import com.denizenscript.denizencore.objects.core.ElementTag;
+import com.denizenscript.denizencore.scripts.ScriptEntryData;
+import io.papermc.paper.event.block.VaultChangeStateEvent;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.Listener;
+
+public class VaultChangesStateScriptEvent extends BukkitScriptEvent implements Listener {
+
+ // <--[event]
+ // @Events
+ // vault changes state
+ //
+ // @Plugin Paper
+ //
+ // @Group Block
+ //
+ // @Cancellable true
+ //
+ // @Location true
+ //
+ // @Triggers when a vault block's state changes. A list of states can be found at <@link url https://jd.papermc.io/paper/org/bukkit/block/data/type/Vault.State.html>.
+ //
+ // @Context
+ // returns the LocationTag of the vault block.
+ // returns the vault state before the change.
+ // returns the vault state after the change.
+ //
+ // @Player when the change is triggered by a player.
+ //
+ // -->
+
+ public VaultChangesStateScriptEvent() {
+ registerCouldMatcher("vault changes state");
+ }
+
+ public LocationTag location;
+ public VaultChangeStateEvent event;
+
+ @Override
+ public boolean matches(ScriptPath path) {
+ if (!runInCheck(path, location)) {
+ return false;
+ }
+ return super.matches(path);
+ }
+
+ @Override
+ public ScriptEntryData getScriptEntryData() {
+ return new BukkitScriptEntryData(event.getPlayer());
+ }
+
+ @Override
+ public ObjectTag getContext(String name) {
+ return switch (name) {
+ case "old_state" -> new ElementTag(event.getCurrentState());
+ case "new_state" -> new ElementTag(event.getNewState());
+ case "location" -> location;
+ default -> super.getContext(name);
+ };
+ }
+
+ @EventHandler
+ public void onVaultChangesStateEvent(VaultChangeStateEvent event) {
+ location = new LocationTag(event.getBlock().getLocation());
+ this.event = event;
+ fire(event);
+ }
+}
diff --git a/paper/src/main/java/com/denizenscript/denizen/paper/events/WorldGameRuleChangeScriptEvent.java b/paper/src/main/java/com/denizenscript/denizen/paper/events/WorldGameRuleChangeScriptEvent.java
index faf88722fd..64fc3dbe05 100644
--- a/paper/src/main/java/com/denizenscript/denizen/paper/events/WorldGameRuleChangeScriptEvent.java
+++ b/paper/src/main/java/com/denizenscript/denizen/paper/events/WorldGameRuleChangeScriptEvent.java
@@ -7,6 +7,7 @@
import com.denizenscript.denizen.objects.PlayerTag;
import com.denizenscript.denizen.objects.WorldTag;
import com.denizenscript.denizen.utilities.implementation.BukkitScriptEntryData;
+import com.denizenscript.denizen.utilities.world.GameRuleReflect;
import com.denizenscript.denizencore.objects.ObjectTag;
import com.denizenscript.denizencore.objects.core.ElementTag;
import com.denizenscript.denizencore.scripts.ScriptEntryData;
@@ -69,7 +70,7 @@ public boolean matches(ScriptPath path) {
if (path.eventArgLowerAt(2).equals("in") && !path.tryArgObject(3, world)) {
return false;
}
- if (!runGenericSwitchCheck(path, "gamerule", event.getGameRule().getName())) {
+ if (!runGenericSwitchCheck(path, "gamerule", GameRuleReflect.getName(event.getGameRule()))) {
return false;
}
return super.matches(path);
@@ -78,7 +79,7 @@ public boolean matches(ScriptPath path) {
@Override
public ObjectTag getContext(String name) {
return switch (name) {
- case "gamerule" -> new ElementTag(event.getGameRule().getName(), true);
+ case "gamerule" -> new ElementTag(GameRuleReflect.getName(event.getGameRule()), true);
case "value" -> new ElementTag(event.getValue(), true);
case "source_type" -> getSourceType();
case "command_block_location" -> getCommandBlock();
diff --git a/paper/src/main/java/com/denizenscript/denizen/paper/properties/ItemRemovedComponents.java b/paper/src/main/java/com/denizenscript/denizen/paper/properties/ItemRemovedComponents.java
new file mode 100644
index 0000000000..cd272bdda8
--- /dev/null
+++ b/paper/src/main/java/com/denizenscript/denizen/paper/properties/ItemRemovedComponents.java
@@ -0,0 +1,86 @@
+package com.denizenscript.denizen.paper.properties;
+
+import com.denizenscript.denizen.objects.ItemTag;
+import com.denizenscript.denizen.objects.properties.item.ItemProperty;
+import com.denizenscript.denizen.paper.datacomponents.DataComponentAdapter;
+import com.denizenscript.denizencore.objects.Mechanism;
+import com.denizenscript.denizencore.objects.core.ElementTag;
+import com.denizenscript.denizencore.objects.core.ListTag;
+import com.denizenscript.denizencore.objects.properties.PropertyParser;
+import io.papermc.paper.datacomponent.DataComponentType;
+
+public class ItemRemovedComponents extends ItemProperty {
+
+ // <--[property]
+ // @object ItemTag
+ // @name removed_components
+ // @input ListTag
+ // @description
+ // Controls the item components explicitly removed from an item.
+ // This can be used to remove item's default behavior, such as making consumable items non-consumable.
+ // Alternatively, use <@link mechanism ItemTag.remove_component> to remove a single component.
+ // See <@link language Item Components> for more information.
+ // -->
+
+ public static boolean describes(ItemTag item) {
+ return !item.getItemStack().isEmpty();
+ }
+
+ public boolean isRemoved(DataComponentType componentType) {
+ return getItemStack().isDataOverridden(componentType) && !getItemStack().hasData(componentType);
+ }
+
+ @Override
+ public ListTag getPropertyValue() {
+ return new ListTag(getMaterial().getDefaultDataTypes(), this::isRemoved, componentType -> new ElementTag(componentType.key().asMinimalString(), true));
+ }
+
+ @Override
+ public boolean isDefaultValue(ListTag value) {
+ return value.isEmpty();
+ }
+
+ @Override
+ public void setPropertyValue(ListTag value, Mechanism mechanism) {
+ for (DataComponentType componentType : getMaterial().getDefaultDataTypes()) {
+ if (isRemoved(componentType)) {
+ getItemStack().resetData(componentType);
+ }
+ }
+ for (String input : value) {
+ DataComponentType componentType = DataComponentAdapter.getComponentType(input);
+ if (componentType == null) {
+ mechanism.echoError("Invalid type to remove '" + input + "' specified: must be a valid property or item component name.");
+ continue;
+ }
+ getItemStack().unsetData(componentType);
+ }
+ }
+
+ @Override
+ public String getPropertyId() {
+ return "removed_components";
+ }
+
+ public static void register() {
+ autoRegister("removed_components", ItemRemovedComponents.class, ListTag.class, false);
+
+ // <--[mechanism]
+ // @object ItemTag
+ // @name remove_component
+ // @input ElementTag
+ // @description
+ // Removes the specified item component from the item, see <@link language Item Components> for more information.
+ // This can be used to remove item's default behavior, such as making consumable items non-consumable.
+ // See also <@link property ItemTag.removed_components>.
+ // -->
+ PropertyParser.registerMechanism(ItemRemovedComponents.class, ElementTag.class, "remove_component", (prop, mechanism, input) -> {
+ DataComponentType componentType = DataComponentAdapter.getComponentType(input.asString());
+ if (componentType == null) {
+ mechanism.echoError("Invalid type to remove specified: must be a valid property or item component name.");
+ return;
+ }
+ prop.getItemStack().unsetData(componentType);
+ });
+ }
+}
diff --git a/paper/src/main/java/com/denizenscript/denizen/paper/properties/PaperElementExtensions.java b/paper/src/main/java/com/denizenscript/denizen/paper/properties/PaperElementExtensions.java
index 090124e434..86a512797c 100644
--- a/paper/src/main/java/com/denizenscript/denizen/paper/properties/PaperElementExtensions.java
+++ b/paper/src/main/java/com/denizenscript/denizen/paper/properties/PaperElementExtensions.java
@@ -19,7 +19,7 @@ public static void register() {
// @Plugin Paper
// @group paper
// @description
- // Returns the element with all MiniMessage tags parsed, see <@link url https://docs.adventure.kyori.net/minimessage/format.html> for more information.
+ // Returns the element with all MiniMessage tags parsed, see <@link url https://docs.papermc.io/adventure/minimessage/format/> for more information.
// This may be useful for reading data from external plugins, but should not be used in normal scripts.
// -->
ElementTag.tagProcessor.registerTag(ElementTag.class, "parse_minimessage", (attribute, object) -> {
diff --git a/paper/src/main/java/com/denizenscript/denizen/paper/properties/PaperEntityExtensions.java b/paper/src/main/java/com/denizenscript/denizen/paper/properties/PaperEntityExtensions.java
index 94bcb7f641..bc2f6a5870 100644
--- a/paper/src/main/java/com/denizenscript/denizen/paper/properties/PaperEntityExtensions.java
+++ b/paper/src/main/java/com/denizenscript/denizen/paper/properties/PaperEntityExtensions.java
@@ -13,6 +13,7 @@
import org.bukkit.entity.Entity;
import org.bukkit.entity.ExperienceOrb;
import org.bukkit.entity.Goat;
+import org.bukkit.entity.Villager;
import org.bukkit.inventory.EquipmentSlot;
import java.util.UUID;
@@ -187,6 +188,26 @@ public static void register() {
object.getLivingEntity().damageItemStack(slot.asEnum(EquipmentSlot.class), amount.asInt());
});
+ if (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_21)) {
+
+ // <--[mechanism]
+ // @object EntityTag
+ // @name restock_trades
+ // @input None
+ // @Plugin Paper
+ // @group paper
+ // @description
+ // Restocks a villager's trades.
+ // Note: this mechanism will fire the <@link event villager replenishes trade> event for every trade the villager is offering.
+ // This mechanism also updates the villager's demand for offers, which may cause item trade prices to rise or fall.
+ // -->
+ EntityTag.registerSpawnedOnlyMechanism("restock_trades", false, (object, mechanism) -> {
+ if (object.getBukkitEntity() instanceof Villager villager) {
+ villager.restock();
+ }
+ });
+ }
+
// <--[mechanism]
// @object EntityTag
// @name shear
diff --git a/paper/src/main/java/com/denizenscript/denizen/paper/properties/PaperItemExtensions.java b/paper/src/main/java/com/denizenscript/denizen/paper/properties/PaperItemExtensions.java
index f2829a34fe..0dd4e809b4 100644
--- a/paper/src/main/java/com/denizenscript/denizen/paper/properties/PaperItemExtensions.java
+++ b/paper/src/main/java/com/denizenscript/denizen/paper/properties/PaperItemExtensions.java
@@ -1,5 +1,7 @@
package com.denizenscript.denizen.paper.properties;
+import com.denizenscript.denizen.nms.NMSHandler;
+import com.denizenscript.denizen.nms.NMSVersion;
import com.denizenscript.denizen.objects.ItemTag;
import com.denizenscript.denizencore.objects.core.ElementTag;
@@ -7,16 +9,10 @@ public class PaperItemExtensions {
public static void register() {
- // <--[tag]
- // @attribute
- // @returns ElementTag
- // @group paper
- // @Plugin Paper
- // @description
- // Returns the rarity of an item, as "common", "uncommon", "rare", or "epic".
- // -->
- ItemTag.tagProcessor.registerTag(ElementTag.class, "rarity", (attribute, item) -> {
- return new ElementTag(item.getItemStack().getRarity());
- });
+ if (NMSHandler.getVersion().isAtMost(NMSVersion.v1_20)) {
+ ItemTag.tagProcessor.registerTag(ElementTag.class, "rarity", (attribute, item) -> {
+ return new ElementTag(item.getItemStack().getRarity());
+ });
+ }
}
}
diff --git a/paper/src/main/java/com/denizenscript/denizen/paper/utilities/PaperAPIToolsImpl.java b/paper/src/main/java/com/denizenscript/denizen/paper/utilities/PaperAPIToolsImpl.java
index c468235626..2b648d75a1 100644
--- a/paper/src/main/java/com/denizenscript/denizen/paper/utilities/PaperAPIToolsImpl.java
+++ b/paper/src/main/java/com/denizenscript/denizen/paper/utilities/PaperAPIToolsImpl.java
@@ -6,11 +6,13 @@
import com.denizenscript.denizen.objects.ItemTag;
import com.denizenscript.denizen.paper.PaperModule;
import com.denizenscript.denizen.scripts.commands.entity.TeleportCommand;
+import com.denizenscript.denizen.scripts.commands.world.SignCommand;
import com.denizenscript.denizen.scripts.containers.core.ItemScriptContainer;
import com.denizenscript.denizen.scripts.containers.core.ItemScriptHelper;
import com.denizenscript.denizen.utilities.FormattedTextHelper;
import com.denizenscript.denizen.utilities.PaperAPITools;
import com.denizenscript.denizencore.DenizenCore;
+import com.denizenscript.denizencore.objects.Mechanism;
import com.denizenscript.denizencore.objects.core.ElementTag;
import com.denizenscript.denizencore.tags.TagContext;
import com.denizenscript.denizencore.utilities.CoreUtilities;
@@ -20,17 +22,16 @@
import com.destroystokyo.paper.profile.ProfileProperty;
import io.papermc.paper.entity.TeleportFlag;
import io.papermc.paper.potion.PotionMix;
+import io.papermc.paper.world.WeatheringCopperState;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.minimessage.MiniMessage;
import net.md_5.bungee.api.ChatColor;
import net.md_5.bungee.api.chat.BaseComponent;
import org.bukkit.*;
import org.bukkit.block.Sign;
+import org.bukkit.block.sign.Side;
import org.bukkit.command.CommandSender;
-import org.bukkit.entity.Entity;
-import org.bukkit.entity.LivingEntity;
-import org.bukkit.entity.Player;
-import org.bukkit.entity.TextDisplay;
+import org.bukkit.entity.*;
import org.bukkit.event.entity.CreatureSpawnEvent;
import org.bukkit.event.entity.PlayerDeathEvent;
import org.bukkit.event.inventory.InventoryType;
@@ -41,6 +42,7 @@
import org.bukkit.scoreboard.Team;
import org.bukkit.util.Consumer;
+import java.net.URI;
import java.util.*;
import java.util.function.Predicate;
import java.util.stream.Collectors;
@@ -101,18 +103,28 @@ public String getPlayerListName(Player player) {
}
@Override
- public String[] getSignLines(Sign sign) {
- String[] output = new String[4];
- int i = 0;
- for (Component component : sign.lines()) {
- output[i++] = PaperModule.stringifyComponent(component);
- }
- return output;
+ public List getSignLines(Sign sign) {
+ return PaperModule.stringifyComponentList(SignCommand.SIGN_SIDES_SUPPORTED ? sign.getSide(Side.FRONT).lines() : sign.lines());
+ }
+
+ @Override
+ public List getSignBackLines(Sign sign) {
+ return PaperModule.stringifyComponentList(sign.getSide(Side.BACK).lines());
}
@Override
public void setSignLine(Sign sign, int line, String text) {
- sign.line(line, PaperModule.parseFormattedText(text == null ? "" : text, ChatColor.BLACK));
+ if (SignCommand.SIGN_SIDES_SUPPORTED) {
+ sign.getSide(Side.FRONT).line(line, PaperModule.parseFormattedText(text == null ? "" : text, ChatColor.BLACK));
+ }
+ else {
+ sign.line(line, PaperModule.parseFormattedText(text == null ? "" : text, ChatColor.BLACK));
+ }
+ }
+
+ @Override
+ public void setSignBackLine(Sign sign, int line, String text) {
+ sign.getSide(Side.BACK).line(line, PaperModule.parseFormattedText(text == null ? "" : text, ChatColor.BLACK));
}
@Override
@@ -409,4 +421,26 @@ public void setMaterialTags(Material type, Set tags) {
}
BlockTagsSetter.INSTANCE.setTags(type, tags);
}
+
+ @Override
+ public void addLink(ServerLinks links, String display, URI uri) {
+ links.addLink(PaperModule.parseFormattedText(display, ChatColor.WHITE), uri);
+ }
+
+ @Override
+ public double[] getRecentTps() {
+ return Bukkit.getTPS();
+ }
+
+ @Override
+ public String getCopperGolemState(CopperGolem copperGolem) {
+ return copperGolem.getWeatheringState().name();
+ }
+
+ @Override
+ public void setCopperGolemState(ElementTag variant, CopperGolem copperGolem, Mechanism mechanism) {
+ if (mechanism.requireEnum(WeatheringCopperState.class)) {
+ copperGolem.setWeatheringState(variant.asEnum(WeatheringCopperState.class));
+ }
+ }
}
diff --git a/plugin/pom.xml b/plugin/pom.xml
index 50400c64ce..b9ba8f0938 100644
--- a/plugin/pom.xml
+++ b/plugin/pom.xml
@@ -5,7 +5,7 @@
com.denizenscript
denizen
- 1.3.1-SNAPSHOT
+ 1.3.3-SNAPSHOT
Denizen
Scriptable Minecraft and Citizens2
@@ -30,7 +30,7 @@
org.spigotmc
spigot-api
- 1.21.8-R0.1-SNAPSHOT
+ 26.2-R0.1-SNAPSHOT
jar
provided
@@ -44,7 +44,7 @@
net.citizensnpcs
citizens-main
- 2.0.38-SNAPSHOT
+ 2.0.42-SNAPSHOT
jar
provided
@@ -70,7 +70,7 @@
net.kyori
adventure-nbt
- 4.23.0
+ 4.26.1
diff --git a/plugin/src/main/java/com/denizenscript/denizen/Denizen.java b/plugin/src/main/java/com/denizenscript/denizen/Denizen.java
index 9060b805b9..65ee2cf9aa 100644
--- a/plugin/src/main/java/com/denizenscript/denizen/Denizen.java
+++ b/plugin/src/main/java/com/denizenscript/denizen/Denizen.java
@@ -147,22 +147,17 @@ else if (javaVersion.startsWith("17")) {
Debug.log("Running on fully supported Java 17.");
}
else if (javaVersion.startsWith("18") || javaVersion.startsWith("19")) {
- getLogger().warning("Running unreliable Java version. modern Minecraft versions are built for Java 21 or 17. Other Java versions are not guaranteed to function properly.");
+ getLogger().warning("Running unreliable Java version. modern Minecraft versions are built for Java 25, 21, or 17. Other Java versions are not guaranteed to function properly.");
}
else if (javaVersion.startsWith("21")) {
Debug.log("Running on fully supported Java 21.");
}
+ else if (javaVersion.startsWith("25")) {
+ Debug.log("Running on fully supported Java 25.");
+ }
else {
Debug.log("Running on unrecognized (future?) Java version. May or may not work.");
}
- if (!NMSHandler.initialize(this)) {
- getLogger().warning("-------------------------------------");
- getLogger().warning("This build of Denizen is not compatible with this Spigot version! Deactivating Denizen!");
- getLogger().warning("-------------------------------------");
- getServer().getPluginManager().disablePlugin(this);
- startedSuccessful = false;
- return;
- }
try {
if (Class.forName("com.destroystokyo.paper.PaperConfig") != null) {
supportsPaper = true;
@@ -174,6 +169,14 @@ else if (javaVersion.startsWith("21")) {
catch (Throwable ex) {
Debug.echoError(ex);
}
+ if (!NMSHandler.initialize(this)) {
+ getLogger().warning("-------------------------------------");
+ getLogger().warning("This build of Denizen is not compatible with this Spigot version! Deactivating Denizen!");
+ getLogger().warning("-------------------------------------");
+ getServer().getPluginManager().disablePlugin(this);
+ startedSuccessful = false;
+ return;
+ }
if (!NMSHandler.instance.isExactServerVersionMatch()) {
String serverSoftware = supportsPaper ? "Paper" : "Spigot";
getLogger().warning("""
diff --git a/plugin/src/main/java/com/denizenscript/denizen/events/ScriptEventRegistry.java b/plugin/src/main/java/com/denizenscript/denizen/events/ScriptEventRegistry.java
index a3e71d4ec1..ea2764e4b1 100644
--- a/plugin/src/main/java/com/denizenscript/denizen/events/ScriptEventRegistry.java
+++ b/plugin/src/main/java/com/denizenscript/denizen/events/ScriptEventRegistry.java
@@ -80,14 +80,23 @@ public static void registerMainEvents() {
ScriptEvent.registerScriptEvent(BlockShearEntityScriptEvent.class);
ScriptEvent.registerScriptEvent(BlockSpreadsScriptEvent.class);
ScriptEvent.registerScriptEvent(BrewingStandFueledScriptEvent.class);
+ if (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_19)) {
+ ScriptEvent.registerScriptEvent(BrewingStartsScriptEvent.class);
+ }
ScriptEvent.registerScriptEvent(BrewsScriptEvent.class);
ScriptEvent.registerScriptEvent(CauldronLevelChangeScriptEvent.class);
+ if (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_21)) {
+ ScriptEvent.registerScriptEvent(CrafterCraftsScriptEvent.class);
+ }
ScriptEvent.registerScriptEvent(DragonEggMovesScriptEvent.class);
ScriptEvent.registerScriptEvent(FurnaceBurnsItemScriptEvent.class);
ScriptEvent.registerScriptEvent(FurnaceStartsSmeltingScriptEvent.class);
ScriptEvent.registerScriptEvent(LeafDecaysScriptEvent.class);
ScriptEvent.registerScriptEvent(LiquidLevelChangeScriptEvent.class);
ScriptEvent.registerScriptEvent(LiquidSpreadScriptEvent.class);
+ if (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_21)) {
+ ScriptEvent.registerScriptEvent(LootDispensesFromBlockScriptEvent.class);
+ }
ScriptEvent.registerScriptEvent(MoistureChangeScriptEvent.class);
ScriptEvent.registerScriptEvent(NoteBlockPlaysNoteScriptEvent.class);
ScriptEvent.registerScriptEvent(PistonExtendsScriptEvent.class);
@@ -95,11 +104,10 @@ public static void registerMainEvents() {
ScriptEvent.registerScriptEvent(RedstoneScriptEvent.class);
ScriptEvent.registerScriptEvent(SpongeAbsorbsScriptEvent.class);
if (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_19)) {
- ScriptEvent.registerScriptEvent(BrewingStartsScriptEvent.class);
ScriptEvent.registerScriptEvent(TNTPrimesScriptEvent.class);
}
if (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_21)) {
- ScriptEvent.registerScriptEvent(CrafterCraftsScriptEvent.class);
+ ScriptEvent.registerScriptEvent(VaultDisplaysItemScriptEvent.class);
}
// Entity events
diff --git a/plugin/src/main/java/com/denizenscript/denizen/events/block/BlockDispensesScriptEvent.java b/plugin/src/main/java/com/denizenscript/denizen/events/block/BlockDispensesScriptEvent.java
index 60e44ac303..3d287a092b 100644
--- a/plugin/src/main/java/com/denizenscript/denizen/events/block/BlockDispensesScriptEvent.java
+++ b/plugin/src/main/java/com/denizenscript/denizen/events/block/BlockDispensesScriptEvent.java
@@ -22,7 +22,7 @@ public class BlockDispensesScriptEvent extends BukkitScriptEvent implements List
//
// @Cancellable true
//
- // @Triggers when a block dispenses an item.
+ // @Triggers when a block dispenses a single item.
//
// @Context
// returns the LocationTag of the dispenser.
diff --git a/plugin/src/main/java/com/denizenscript/denizen/events/block/BrewingStandFueledScriptEvent.java b/plugin/src/main/java/com/denizenscript/denizen/events/block/BrewingStandFueledScriptEvent.java
index cc6732dceb..8c1a68708e 100644
--- a/plugin/src/main/java/com/denizenscript/denizen/events/block/BrewingStandFueledScriptEvent.java
+++ b/plugin/src/main/java/com/denizenscript/denizen/events/block/BrewingStandFueledScriptEvent.java
@@ -3,6 +3,7 @@
import com.denizenscript.denizen.events.BukkitScriptEvent;
import com.denizenscript.denizen.objects.ItemTag;
import com.denizenscript.denizen.objects.LocationTag;
+import com.denizenscript.denizen.utilities.BukkitImplDeprecations;
import com.denizenscript.denizencore.objects.ObjectTag;
import com.denizenscript.denizencore.objects.core.ElementTag;
import org.bukkit.event.EventHandler;
@@ -31,13 +32,30 @@ public class BrewingStandFueledScriptEvent extends BukkitScriptEvent implements
//
// @Determine
// "FUEL_POWER:" to set the fuel power level to be added.
- // "CONSUMING" to indicate that the fuel item should be consumed.
- // "NOT_CONSUMING" to indicate that the fuel item should not be consumed.
+ // "CONSUMING:" to indicate whether the fuel item should be consumed.
//
// -->
public BrewingStandFueledScriptEvent() {
registerCouldMatcher("brewing stand fueled (with - )");
+ this.registerOptionalDetermination("fuel_power", ElementTag.class, (evt, context, power) -> {
+ if (power.isInt()) {
+ evt.event.setFuelPower(power.asInt());
+ return true;
+ }
+ return false;
+ });
+ this.registerOptionalDetermination("consuming", ElementTag.class, (evt, context, value) -> {
+ if (value.isBoolean()) {
+ evt.event.setConsuming(value.asBoolean());
+ return true;
+ }
+ return false;
+ });
+ this.registerTextDetermination("not_consuming", (evt) -> {
+ BukkitImplDeprecations.brewingStandConsumeDetermination.warn();
+ evt.event.setConsuming(false);
+ });
}
public LocationTag location;
@@ -55,35 +73,15 @@ public boolean matches(ScriptPath path) {
return super.matches(path);
}
- @Override
- public boolean applyDetermination(ScriptPath path, ObjectTag determinationObj) {
- if (determinationObj instanceof ElementTag element) {
- String val = element.asString();
- if (val.startsWith("fuel_power:")) {
- event.setFuelPower(Integer.parseInt(val.substring("fuel_power:".length())));
- return true;
- }
- else if (val.equalsIgnoreCase("consuming")) {
- event.setConsuming(true);
- return true;
- }
- else if (val.equalsIgnoreCase("not_consuming")) {
- event.setConsuming(false);
- return true;
- }
- }
- return super.applyDetermination(path, determinationObj);
- }
-
@Override
public ObjectTag getContext(String name) {
- switch (name) {
- case "location": return location;
- case "item": return item;
- case "fuel_power": return new ElementTag(event.getFuelPower());
- case "consuming": return new ElementTag(event.isConsuming());
- }
- return super.getContext(name);
+ return switch (name) {
+ case "location" -> location;
+ case "item" -> item;
+ case "fuel_power" -> new ElementTag(event.getFuelPower());
+ case "consuming" -> new ElementTag(event.isConsuming());
+ default -> super.getContext(name);
+ };
}
@EventHandler
diff --git a/plugin/src/main/java/com/denizenscript/denizen/events/block/CauldronLevelChangeScriptEvent.java b/plugin/src/main/java/com/denizenscript/denizen/events/block/CauldronLevelChangeScriptEvent.java
index a6134f62c9..599cc491c1 100644
--- a/plugin/src/main/java/com/denizenscript/denizen/events/block/CauldronLevelChangeScriptEvent.java
+++ b/plugin/src/main/java/com/denizenscript/denizen/events/block/CauldronLevelChangeScriptEvent.java
@@ -5,6 +5,9 @@
import com.denizenscript.denizen.objects.LocationTag;
import com.denizenscript.denizencore.objects.ObjectTag;
import com.denizenscript.denizencore.objects.core.ElementTag;
+import org.bukkit.Material;
+import org.bukkit.block.BlockState;
+import org.bukkit.block.data.Levelled;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.block.CauldronLevelChangeEvent;
@@ -39,10 +42,37 @@ public class CauldronLevelChangeScriptEvent extends BukkitScriptEvent implements
public CauldronLevelChangeScriptEvent() {
registerCouldMatcher("cauldron level changes|raises|lowers");
registerSwitches("cause");
+ this.registerOptionalDetermination(null, ElementTag.class, (evt, context, value) -> {
+ if (!value.isInt()) {
+ return false;
+ }
+ int level = value.asInt();
+ BlockState cauldronState = evt.event.getNewState();
+ if (level <= 0) {
+ cauldronState.setType(Material.CAULDRON);
+ return true;
+ }
+ if (level > 3) {
+ return false;
+ }
+ if (cauldronState.getType() != Material.WATER_CAULDRON && cauldronState.getType() != Material.LAVA_CAULDRON) {
+ cauldronState.setType(cauldronType);
+ }
+ if (cauldronState.getBlockData() instanceof Levelled levelled) {
+ levelled.setLevel(level);
+ cauldronState.setBlockData(levelled);
+ evt.newLevel = level;
+ return true;
+ }
+ return false;
+ });
}
public LocationTag location;
public CauldronLevelChangeEvent event;
+ public Material cauldronType;
+ public int oldLevel;
+ public int newLevel;
@Override
public boolean matches(ScriptPath path) {
@@ -54,12 +84,12 @@ public boolean matches(ScriptPath path) {
}
String changeType = path.eventArgLowerAt(2);
if (changeType.equals("raises")) {
- if (event.getNewLevel() <= event.getOldLevel()) {
+ if (newLevel <= oldLevel) {
return false;
}
}
else if (changeType.equals("lowers")) {
- if (event.getNewLevel() >= event.getOldLevel()) {
+ if (newLevel >= oldLevel) {
return false;
}
}
@@ -69,33 +99,24 @@ else if (!changeType.equals("changes")) {
return super.matches(path);
}
- @Override
- public boolean applyDetermination(ScriptPath path, ObjectTag determinationObj) {
- if (determinationObj instanceof ElementTag element && element.isInt()) {
- event.setNewLevel(element.asInt());
- }
- return super.applyDetermination(path, determinationObj);
- }
-
@Override
public ObjectTag getContext(String name) {
- switch (name) {
- case "location": return location;
- case "cause": return new ElementTag(event.getReason());
- case "old_level": return new ElementTag(event.getOldLevel());
- case "new_level": return new ElementTag(event.getNewLevel());
- case "entity":
- if (event.getEntity() != null) {
- return new EntityTag(event.getEntity()).getDenizenObject();
- }
- break;
- }
- return super.getContext(name);
+ return switch (name) {
+ case "location" -> location;
+ case "cause" -> new ElementTag(event.getReason());
+ case "old_level" -> new ElementTag(oldLevel);
+ case "new_level" -> new ElementTag(newLevel);
+ case "entity" -> event.getEntity() != null ? new EntityTag(event.getEntity()).getDenizenObject() : null;
+ default -> super.getContext(name);
+ };
}
@EventHandler
public void onCauldronLevelChange(CauldronLevelChangeEvent event) {
location = new LocationTag(event.getBlock().getLocation());
+ cauldronType = event.getBlock().getType();
+ oldLevel = event.getBlock().getBlockData() instanceof Levelled levelled ? levelled.getLevel() : 0;
+ newLevel = event.getNewState().getBlockData() instanceof Levelled levelled ? levelled.getLevel() : 0;
this.event = event;
fire(event);
}
diff --git a/plugin/src/main/java/com/denizenscript/denizen/events/block/FurnaceBurnsItemScriptEvent.java b/plugin/src/main/java/com/denizenscript/denizen/events/block/FurnaceBurnsItemScriptEvent.java
index fe34ed02b7..82c69cdf00 100644
--- a/plugin/src/main/java/com/denizenscript/denizen/events/block/FurnaceBurnsItemScriptEvent.java
+++ b/plugin/src/main/java/com/denizenscript/denizen/events/block/FurnaceBurnsItemScriptEvent.java
@@ -35,6 +35,17 @@ public class FurnaceBurnsItemScriptEvent extends BukkitScriptEvent implements Li
public FurnaceBurnsItemScriptEvent() {
registerCouldMatcher("furnace burns
- ");
+ this.registerOptionalDetermination(null, ObjectTag.class, (evt, context, time) -> {
+ if (time instanceof ElementTag elementTag && elementTag.isInt()) { // Backwards compatibility for non-duration tick input
+ evt.event.setBurnTime(elementTag.asInt());
+ return true;
+ }
+ else if (time.canBeType(DurationTag.class)) {
+ evt.event.setBurnTime(time.asType(DurationTag.class, context).getTicksAsInt());
+ return true;
+ }
+ return false;
+ });
}
public ItemTag item;
@@ -52,30 +63,17 @@ public boolean matches(ScriptPath path) {
return super.matches(path);
}
- @Override
- public boolean applyDetermination(ScriptPath path, ObjectTag determinationObj) {
- if (determinationObj instanceof ElementTag element && element.isInt()) {
- event.setBurnTime(element.asInt());
- return true;
- }
- else if (determinationObj.canBeType(DurationTag.class)) {
- event.setBurnTime(determinationObj.asType(DurationTag.class, getTagContext(path)).getTicksAsInt());
- return true;
- }
- return super.applyDetermination(path, determinationObj);
- }
-
@Override
public ObjectTag getContext(String name) {
- switch (name) {
- case "location": return location;
- case "item": return item;
- }
- return super.getContext(name);
+ return switch (name) {
+ case "location" -> location;
+ case "item" -> item;
+ default -> super.getContext(name);
+ };
}
@EventHandler
- public void onBrews(FurnaceBurnEvent event) {
+ public void onFurnaceBurns(FurnaceBurnEvent event) {
location = new LocationTag(event.getBlock().getLocation());
item = new ItemTag(event.getFuel());
this.event = event;
diff --git a/plugin/src/main/java/com/denizenscript/denizen/events/block/FurnaceStartsSmeltingScriptEvent.java b/plugin/src/main/java/com/denizenscript/denizen/events/block/FurnaceStartsSmeltingScriptEvent.java
index 0e4d82c441..498f5f4c72 100644
--- a/plugin/src/main/java/com/denizenscript/denizen/events/block/FurnaceStartsSmeltingScriptEvent.java
+++ b/plugin/src/main/java/com/denizenscript/denizen/events/block/FurnaceStartsSmeltingScriptEvent.java
@@ -31,19 +31,13 @@ public class FurnaceStartsSmeltingScriptEvent extends BukkitScriptEvent implemen
// @Determine
// DurationTag to set the total cook time for the item being smelted.
//
- // @Example
- // # Sets the total cook time of every item to always be 2 seconds.
- // on furnace starts smelting item:
- // - determine 2s
- //
- // @Example
- // # Sets the total cook time of iron ore to be 2 seconds.
- // on furnace starts smelting iron_ore:
- // - determine 2s
// -->
public FurnaceStartsSmeltingScriptEvent() {
registerCouldMatcher("furnace starts smelting
- ");
+ this.registerDetermination(null, DurationTag.class, (evt, context, time) -> {
+ evt.event.setTotalCookTime(time.getTicksAsInt());
+ });
}
public ItemTag item;
@@ -61,24 +55,15 @@ public boolean matches(ScriptPath path) {
return super.matches(path);
}
- @Override
- public boolean applyDetermination(ScriptPath path, ObjectTag determinationObj) {
- if (determinationObj.canBeType(DurationTag.class)) {
- event.setTotalCookTime(determinationObj.asType(DurationTag.class, getTagContext(path)).getTicksAsInt());
- return true;
- }
- return super.applyDetermination(path, determinationObj);
- }
-
@Override
public ObjectTag getContext(String name) {
- switch (name) {
- case "location": return location;
- case "item": return item;
- case "recipe_id": return new ElementTag(event.getRecipe().getKey().toString());
- case "total_cook_time": return new DurationTag((long) event.getTotalCookTime());
- }
- return super.getContext(name);
+ return switch (name) {
+ case "location" -> location;
+ case "item" -> item;
+ case "recipe_id" -> new ElementTag(event.getRecipe().getKey().toString(), true);
+ case "total_cook_time" -> new DurationTag((long) event.getTotalCookTime());
+ default -> super.getContext(name);
+ };
}
@EventHandler
diff --git a/plugin/src/main/java/com/denizenscript/denizen/events/block/LeafDecaysScriptEvent.java b/plugin/src/main/java/com/denizenscript/denizen/events/block/LeafDecaysScriptEvent.java
index 6d6a4993be..447af73882 100644
--- a/plugin/src/main/java/com/denizenscript/denizen/events/block/LeafDecaysScriptEvent.java
+++ b/plugin/src/main/java/com/denizenscript/denizen/events/block/LeafDecaysScriptEvent.java
@@ -52,11 +52,11 @@ public boolean matches(ScriptPath path) {
@Override
public ObjectTag getContext(String name) {
- switch (name) {
- case "location": return location;
- case "material": return material;
- }
- return super.getContext(name);
+ return switch (name) {
+ case "location" -> location;
+ case "material" -> material;
+ default -> super.getContext(name);
+ };
}
@EventHandler
diff --git a/plugin/src/main/java/com/denizenscript/denizen/events/block/LiquidLevelChangeScriptEvent.java b/plugin/src/main/java/com/denizenscript/denizen/events/block/LiquidLevelChangeScriptEvent.java
index d3fdc67897..63d0e1e3c5 100644
--- a/plugin/src/main/java/com/denizenscript/denizen/events/block/LiquidLevelChangeScriptEvent.java
+++ b/plugin/src/main/java/com/denizenscript/denizen/events/block/LiquidLevelChangeScriptEvent.java
@@ -62,12 +62,12 @@ public boolean matches(ScriptPath path) {
@Override
public ObjectTag getContext(String name) {
- switch (name) {
- case "location": return location;
- case "old_material": return old_material;
- case "new_material": return new MaterialTag(event.getNewData());
- }
- return super.getContext(name);
+ return switch (name) {
+ case "location" -> location;
+ case "old_material" -> old_material;
+ case "new_material" -> new MaterialTag(event.getNewData());
+ default -> super.getContext(name);
+ };
}
@EventHandler
diff --git a/plugin/src/main/java/com/denizenscript/denizen/events/block/LootDispensesFromBlockScriptEvent.java b/plugin/src/main/java/com/denizenscript/denizen/events/block/LootDispensesFromBlockScriptEvent.java
new file mode 100644
index 0000000000..d8c2e4671f
--- /dev/null
+++ b/plugin/src/main/java/com/denizenscript/denizen/events/block/LootDispensesFromBlockScriptEvent.java
@@ -0,0 +1,89 @@
+package com.denizenscript.denizen.events.block;
+
+import com.denizenscript.denizen.events.BukkitScriptEvent;
+import com.denizenscript.denizen.objects.*;
+import com.denizenscript.denizen.utilities.implementation.BukkitScriptEntryData;
+import com.denizenscript.denizencore.objects.ObjectTag;
+import com.denizenscript.denizencore.objects.core.ListTag;
+import com.denizenscript.denizencore.scripts.ScriptEntryData;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.Listener;
+import org.bukkit.event.block.BlockDispenseLootEvent;
+import org.bukkit.inventory.ItemStack;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class LootDispensesFromBlockScriptEvent extends BukkitScriptEvent implements Listener {
+
+ // <--[event]
+ // @Events
+ // loot dispenses from
+ //
+ // @Group Block
+ //
+ // @Location true
+ //
+ // @Cancellable true
+ //
+ // @Player when the loot dispensing is triggered by a player.
+ //
+ // @Triggers when a block dispenses loot containing multiple items.
+ //
+ // @Context
+ // returns a ListTag(ItemTag) of loot items.
+ // returns a LocationTag of the block that is dispensing the items.
+ //
+ // @Determine
+ // "LOOT:" to set the loot items being dispensed.
+ //
+ // -->
+
+ public LootDispensesFromBlockScriptEvent() {
+ registerCouldMatcher("loot dispenses from ");
+ this.registerDetermination("loot", ListTag.class, (evt, context, input) -> {
+ List items = new ArrayList<>(input.size());
+ for (ItemTag item : input.filter(ItemTag.class, context)) {
+ items.add(item.getItemStack());
+ }
+ evt.event.setDispensedLoot(items);
+ });
+ }
+
+ public MaterialTag block;
+ public LocationTag location;
+ public BlockDispenseLootEvent event;
+
+ @Override
+ public boolean matches(ScriptPath path) {
+ if (!path.tryArgObject(3, block)) {
+ return false;
+ }
+ if (!runInCheck(path, location)) {
+ return false;
+ }
+ return super.matches(path);
+ }
+
+ @Override
+ public ScriptEntryData getScriptEntryData() {
+ return new BukkitScriptEntryData(event.getPlayer());
+ }
+
+ @Override
+ public ObjectTag getContext(String name) {
+ return switch (name) {
+ case "loot" -> new ListTag(event.getDispensedLoot(), ItemTag::new);
+ case "location" -> location;
+ default -> super.getContext(name);
+ };
+ }
+
+ @EventHandler
+ public void onLootDispensesFromBlock(BlockDispenseLootEvent event) {
+ block = new MaterialTag(event.getBlock().getType());
+ location = new LocationTag(event.getBlock().getLocation());
+ this.event = event;
+ fire(event);
+ }
+}
diff --git a/plugin/src/main/java/com/denizenscript/denizen/events/block/NoteBlockPlaysNoteScriptEvent.java b/plugin/src/main/java/com/denizenscript/denizen/events/block/NoteBlockPlaysNoteScriptEvent.java
index d0743dc37b..53ab43d02a 100644
--- a/plugin/src/main/java/com/denizenscript/denizen/events/block/NoteBlockPlaysNoteScriptEvent.java
+++ b/plugin/src/main/java/com/denizenscript/denizen/events/block/NoteBlockPlaysNoteScriptEvent.java
@@ -62,55 +62,39 @@ public Sound getSound() {
if (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_20)) {
return event.getInstrument().getSound();
}
- switch (event.getInstrument()) {
- case PIANO:
- return Sound.BLOCK_NOTE_BLOCK_HARP;
- case BASS_DRUM:
- return Sound.BLOCK_NOTE_BLOCK_BASEDRUM;
- case SNARE_DRUM:
- return Sound.BLOCK_NOTE_BLOCK_SNARE;
- case STICKS:
- return Sound.BLOCK_NOTE_BLOCK_HAT;
- case BASS_GUITAR:
- return Sound.BLOCK_NOTE_BLOCK_BASS;
- case FLUTE:
- return Sound.BLOCK_NOTE_BLOCK_FLUTE;
- case BELL:
- return Sound.BLOCK_NOTE_BLOCK_BELL;
- case GUITAR:
- return Sound.BLOCK_NOTE_BLOCK_GUITAR;
- case CHIME:
- return Sound.BLOCK_NOTE_BLOCK_CHIME;
- case XYLOPHONE:
- return Sound.BLOCK_NOTE_BLOCK_XYLOPHONE;
- case IRON_XYLOPHONE:
- return Sound.BLOCK_NOTE_BLOCK_IRON_XYLOPHONE;
- case COW_BELL:
- return Sound.BLOCK_NOTE_BLOCK_COW_BELL;
- case DIDGERIDOO:
- return Sound.BLOCK_NOTE_BLOCK_DIDGERIDOO;
- case BIT:
- return Sound.BLOCK_NOTE_BLOCK_BIT;
- case BANJO:
- return Sound.BLOCK_NOTE_BLOCK_BANJO;
- case PLING:
- return Sound.BLOCK_NOTE_BLOCK_PLING;
- }
- return null;
+ return switch (event.getInstrument()) {
+ case PIANO -> Sound.BLOCK_NOTE_BLOCK_HARP;
+ case BASS_DRUM -> Sound.BLOCK_NOTE_BLOCK_BASEDRUM;
+ case SNARE_DRUM -> Sound.BLOCK_NOTE_BLOCK_SNARE;
+ case STICKS -> Sound.BLOCK_NOTE_BLOCK_HAT;
+ case BASS_GUITAR -> Sound.BLOCK_NOTE_BLOCK_BASS;
+ case FLUTE -> Sound.BLOCK_NOTE_BLOCK_FLUTE;
+ case BELL -> Sound.BLOCK_NOTE_BLOCK_BELL;
+ case GUITAR -> Sound.BLOCK_NOTE_BLOCK_GUITAR;
+ case CHIME -> Sound.BLOCK_NOTE_BLOCK_CHIME;
+ case XYLOPHONE -> Sound.BLOCK_NOTE_BLOCK_XYLOPHONE;
+ case IRON_XYLOPHONE -> Sound.BLOCK_NOTE_BLOCK_IRON_XYLOPHONE;
+ case COW_BELL -> Sound.BLOCK_NOTE_BLOCK_COW_BELL;
+ case DIDGERIDOO -> Sound.BLOCK_NOTE_BLOCK_DIDGERIDOO;
+ case BIT -> Sound.BLOCK_NOTE_BLOCK_BIT;
+ case BANJO -> Sound.BLOCK_NOTE_BLOCK_BANJO;
+ case PLING -> Sound.BLOCK_NOTE_BLOCK_PLING;
+ default -> null;
+ };
}
@Override
public ObjectTag getContext(String name) {
- switch (name) {
- case "location": return location;
- case "instrument": return new ElementTag(event.getInstrument());
- case "sound": return Utilities.enumLikeToLegacyElement(getSound());
- case "tone": return new ElementTag(event.getNote().getTone());
- case "octave": return new ElementTag(event.getNote().getOctave());
- case "sharp": return new ElementTag(event.getNote().isSharped());
- case "pitch": return new ElementTag(Math.pow(2.0, (double) (event.getNote().getId() - 12) / 12.0)); // based on minecraft source
- }
- return super.getContext(name);
+ return switch (name) {
+ case "location" -> location;
+ case "instrument" -> new ElementTag(event.getInstrument());
+ case "sound" -> Utilities.enumLikeToLegacyElement(getSound());
+ case "tone" -> new ElementTag(event.getNote().getTone());
+ case "octave" -> new ElementTag(event.getNote().getOctave());
+ case "sharp" -> new ElementTag(event.getNote().isSharped());
+ case "pitch" -> new ElementTag(Math.pow(2.0, (double) (event.getNote().getId() - 12) / 12.0)); // based on minecraft source
+ default -> super.getContext(name);
+ };
}
@EventHandler
diff --git a/plugin/src/main/java/com/denizenscript/denizen/events/block/PistonExtendsScriptEvent.java b/plugin/src/main/java/com/denizenscript/denizen/events/block/PistonExtendsScriptEvent.java
index f544ce7200..eaf1dccd83 100644
--- a/plugin/src/main/java/com/denizenscript/denizen/events/block/PistonExtendsScriptEvent.java
+++ b/plugin/src/main/java/com/denizenscript/denizen/events/block/PistonExtendsScriptEvent.java
@@ -6,7 +6,6 @@
import com.denizenscript.denizencore.objects.core.ElementTag;
import com.denizenscript.denizencore.objects.core.ListTag;
import com.denizenscript.denizencore.objects.ObjectTag;
-import org.bukkit.block.Block;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.block.BlockPistonExtendEvent;
@@ -59,22 +58,16 @@ public boolean matches(ScriptPath path) {
@Override
public ObjectTag getContext(String name) {
- switch (name) {
- case "location": return location;
- case "material": return material;
- case "sticky": return new ElementTag(event.isSticky());
- case "direction": return new LocationTag(event.getDirection().getDirection());
- case "relative": return new LocationTag(event.getBlock().getRelative(event.getDirection()).getLocation()); // Silently deprecated
- case "blocks": {
- ListTag blocks = new ListTag();
- for (Block block : event.getBlocks()) {
- blocks.addObject(new LocationTag(block.getLocation()));
- }
- return blocks;
- }
- case "length": return new ElementTag(event.getBlocks().size());
- }
- return super.getContext(name);
+ return switch (name) {
+ case "location" -> location;
+ case "material" -> material;
+ case "sticky" -> new ElementTag(event.isSticky());
+ case "direction" -> new LocationTag(event.getDirection().getDirection());
+ case "relative" -> new LocationTag(event.getBlock().getRelative(event.getDirection()).getLocation()); // Silently deprecated
+ case "blocks" -> new ListTag(event.getBlocks(), block -> new LocationTag(block.getLocation()));
+ case "length" -> new ElementTag(event.getBlocks().size());
+ default -> super.getContext(name);
+ };
}
@EventHandler
diff --git a/plugin/src/main/java/com/denizenscript/denizen/events/block/PistonRetractsScriptEvent.java b/plugin/src/main/java/com/denizenscript/denizen/events/block/PistonRetractsScriptEvent.java
index 88ae3d2a0a..f048b60963 100644
--- a/plugin/src/main/java/com/denizenscript/denizen/events/block/PistonRetractsScriptEvent.java
+++ b/plugin/src/main/java/com/denizenscript/denizen/events/block/PistonRetractsScriptEvent.java
@@ -6,7 +6,6 @@
import com.denizenscript.denizencore.objects.core.ElementTag;
import com.denizenscript.denizencore.objects.core.ListTag;
import com.denizenscript.denizencore.objects.ObjectTag;
-import org.bukkit.block.Block;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.block.BlockPistonRetractEvent;
@@ -59,22 +58,16 @@ public boolean matches(ScriptPath path) {
@Override
public ObjectTag getContext(String name) {
- switch (name) {
- case "location": return location;
- case "material": return material;
- case "sticky": return new ElementTag(event.isSticky());
- case "direction": return new LocationTag(event.getDirection().getDirection());
- case "relative": return new LocationTag(event.getBlock().getRelative(event.getDirection().getOppositeFace()).getLocation()); // Silently deprecated
- case "blocks": {
- ListTag blocks = new ListTag();
- for (Block block : event.getBlocks()) {
- blocks.addObject(new LocationTag(block.getLocation()));
- }
- return blocks;
- }
- case "retract_location": return new LocationTag(event.getBlock().getRelative(event.getDirection().getOppositeFace(), 2).getLocation());
- }
- return super.getContext(name);
+ return switch (name) {
+ case "location" -> location;
+ case "material" -> material;
+ case "sticky" -> new ElementTag(event.isSticky());
+ case "direction" -> new LocationTag(event.getDirection().getDirection());
+ case "relative" -> new LocationTag(event.getBlock().getRelative(event.getDirection().getOppositeFace()).getLocation()); // Silently deprecated
+ case "blocks" -> new ListTag(event.getBlocks(), block -> new LocationTag(block.getLocation()));
+ case "retract_location" -> new LocationTag(event.getBlock().getRelative(event.getDirection().getOppositeFace(), 2).getLocation());
+ default -> super.getContext(name);
+ };
}
@EventHandler
diff --git a/plugin/src/main/java/com/denizenscript/denizen/events/block/RedstoneScriptEvent.java b/plugin/src/main/java/com/denizenscript/denizen/events/block/RedstoneScriptEvent.java
index be845be4ae..ccc981d329 100644
--- a/plugin/src/main/java/com/denizenscript/denizen/events/block/RedstoneScriptEvent.java
+++ b/plugin/src/main/java/com/denizenscript/denizen/events/block/RedstoneScriptEvent.java
@@ -28,15 +28,21 @@ public class RedstoneScriptEvent extends BukkitScriptEvent implements Listener {
// returns what the redstone power level is becoming.
//
// @Determine
- // ElementTag (Number) set the current value to a specific value.
+ // ElementTag(Number) set the current value to a specific value.
//
// -->
public RedstoneScriptEvent() {
registerCouldMatcher("redstone recalculated");
+ this.registerOptionalDetermination(null, ElementTag.class, (evt, context, power) -> {
+ if (power.isInt()) {
+ evt.event.setNewCurrent(power.asInt());
+ return true;
+ }
+ return false;
+ });
}
-
public LocationTag location;
public BlockRedstoneEvent event;
@@ -48,23 +54,14 @@ public boolean matches(ScriptPath path) {
return super.matches(path);
}
- @Override
- public boolean applyDetermination(ScriptPath path, ObjectTag determinationObj) {
- if (determinationObj instanceof ElementTag element && element.isInt()) {
- event.setNewCurrent(element.asInt());
- return true;
- }
- return super.applyDetermination(path, determinationObj);
- }
-
@Override
public ObjectTag getContext(String name) {
- switch (name) {
- case "location": return location;
- case "old_current": return new ElementTag(event.getOldCurrent());
- case "new_current": return new ElementTag(event.getNewCurrent());
- }
- return super.getContext(name);
+ return switch (name) {
+ case "location" -> location;
+ case "old_current" -> new ElementTag(event.getOldCurrent());
+ case "new_current" -> new ElementTag(event.getNewCurrent());
+ default -> super.getContext(name);
+ };
}
@EventHandler
diff --git a/plugin/src/main/java/com/denizenscript/denizen/events/block/VaultDisplaysItemScriptEvent.java b/plugin/src/main/java/com/denizenscript/denizen/events/block/VaultDisplaysItemScriptEvent.java
new file mode 100644
index 0000000000..eaec0a9c93
--- /dev/null
+++ b/plugin/src/main/java/com/denizenscript/denizen/events/block/VaultDisplaysItemScriptEvent.java
@@ -0,0 +1,72 @@
+package com.denizenscript.denizen.events.block;
+
+import com.denizenscript.denizen.events.BukkitScriptEvent;
+import com.denizenscript.denizen.objects.ItemTag;
+import com.denizenscript.denizen.objects.LocationTag;
+import com.denizenscript.denizencore.objects.ObjectTag;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.Listener;
+import org.bukkit.event.block.VaultDisplayItemEvent;
+
+public class VaultDisplaysItemScriptEvent extends BukkitScriptEvent implements Listener {
+
+ // <--[event]
+ // @Events
+ // vault displays
-
+ //
+ // @Group Block
+ //
+ // @Location true
+ //
+ // @Cancellable true
+ //
+ // @Triggers when a vault block displays an item.
+ //
+ // @Context
+ // returns the LocationTag of the vault block.
+ // returns the ItemTag being displayed.
+ //
+ // @Determine
+ // "ITEM:" to set the item being displayed.
+ //
+ // -->
+
+ public VaultDisplaysItemScriptEvent() {
+ registerCouldMatcher("vault displays
- ");
+ this.registerDetermination("item", ItemTag.class, (evt, context, input) -> {
+ evt.event.setDisplayItem(input.getItemStack());
+ });
+ }
+
+ public LocationTag location;
+ public VaultDisplayItemEvent event;
+ public ItemTag item;
+
+ @Override
+ public boolean matches(ScriptPath path) {
+ if (!runInCheck(path, location)) {
+ return false;
+ }
+ if (!path.tryArgObject(2, item)) {
+ return false;
+ }
+ return super.matches(path);
+ }
+
+ @Override
+ public ObjectTag getContext(String name) {
+ return switch (name) {
+ case "item" -> new ItemTag(event.getDisplayItem());
+ case "location" -> location;
+ default -> super.getContext(name);
+ };
+ }
+
+ @EventHandler
+ public void onVaultDisplayItemEvent(VaultDisplayItemEvent event) {
+ location = new LocationTag(event.getBlock().getLocation());
+ item = new ItemTag(event.getDisplayItem());
+ this.event = event;
+ fire(event);
+ }
+}
diff --git a/plugin/src/main/java/com/denizenscript/denizen/events/entity/AreaEnterExitScriptEvent.java b/plugin/src/main/java/com/denizenscript/denizen/events/entity/AreaEnterExitScriptEvent.java
index f9fb2c4ba0..99aead67d9 100644
--- a/plugin/src/main/java/com/denizenscript/denizen/events/entity/AreaEnterExitScriptEvent.java
+++ b/plugin/src/main/java/com/denizenscript/denizen/events/entity/AreaEnterExitScriptEvent.java
@@ -1,9 +1,10 @@
package com.denizenscript.denizen.events.entity;
import com.denizenscript.denizen.events.BukkitScriptEvent;
-import com.denizenscript.denizen.objects.*;
+import com.denizenscript.denizen.objects.AreaContainmentObject;
+import com.denizenscript.denizen.objects.EntityTag;
+import com.denizenscript.denizen.objects.LocationTag;
import com.denizenscript.denizen.utilities.NotedAreaTracker;
-import com.denizenscript.denizencore.utilities.debugging.Debug;
import com.denizenscript.denizen.utilities.implementation.BukkitScriptEntryData;
import com.denizenscript.denizencore.flags.AbstractFlagTracker;
import com.denizenscript.denizencore.flags.FlaggableObject;
@@ -13,6 +14,7 @@
import com.denizenscript.denizencore.objects.notable.NoteManager;
import com.denizenscript.denizencore.scripts.ScriptEntryData;
import com.denizenscript.denizencore.utilities.CoreUtilities;
+import com.denizenscript.denizencore.utilities.debugging.Debug;
import org.bukkit.Location;
import org.bukkit.entity.Entity;
import org.bukkit.event.Event;
@@ -53,7 +55,6 @@ public AreaEnterExitScriptEvent() {
registerCouldMatcher(" enters|exits ");
}
-
public EntityTag currentEntity;
public AreaContainmentObject area;
public boolean isEntering;
@@ -87,52 +88,48 @@ public ScriptEntryData getScriptEntryData() {
@Override
public ObjectTag getContext(String name) {
- if (name.equals("area")) {
- return area;
- }
- else if (name.equals("cause")) {
- String cause;
- if (currentEvent instanceof PlayerJoinEvent) {
- cause = "JOIN";
- }
- else if (currentEvent instanceof PlayerQuitEvent) {
- cause = "QUIT";
- }
- else if (currentEvent instanceof PlayerChangedWorldEvent) {
- cause = "WORLD_CHANGE";
- }
- else if (currentEvent instanceof PlayerTeleportEvent) {
- cause = "TELEPORT";
- }
- else if (currentEvent instanceof VehicleMoveEvent) {
- cause = "VEHICLE";
- }
- else if (currentEvent instanceof PlayerMoveEvent) {
- cause = "WALK";
- }
- else {
- cause = "UNKNOWN";
- }
- return new ElementTag(cause);
- }
- else if (name.equals("to") && to != null) {
- return new LocationTag(to);
- }
- else if (name.equals("from")) {
- if (currentEvent instanceof PlayerMoveEvent) {
- return new LocationTag(((PlayerMoveEvent) currentEvent).getFrom());
- }
- else if (currentEvent instanceof VehicleMoveEvent) {
- return new LocationTag(((VehicleMoveEvent) currentEvent).getFrom());
+ return switch (name) {
+ case "area" -> area;
+ case "cause" -> {
+ String cause;
+ if (currentEvent instanceof PlayerJoinEvent) {
+ cause = "JOIN";
+ }
+ else if (currentEvent instanceof PlayerQuitEvent) {
+ cause = "QUIT";
+ }
+ else if (currentEvent instanceof PlayerChangedWorldEvent) {
+ cause = "WORLD_CHANGE";
+ }
+ else if (currentEvent instanceof PlayerTeleportEvent) {
+ cause = "TELEPORT";
+ }
+ else if (currentEvent instanceof VehicleMoveEvent) {
+ cause = "VEHICLE";
+ }
+ else if (currentEvent instanceof PlayerMoveEvent) {
+ cause = "WALK";
+ }
+ else {
+ cause = "UNKNOWN";
+ }
+ yield new ElementTag(cause, true);
}
- else {
- return new LocationTag(currentEntity.getLocation());
+ case "to" -> to != null ? new LocationTag(to) : null;
+ case "from" -> {
+ if (currentEvent instanceof PlayerMoveEvent playerMove) {
+ yield new LocationTag(playerMove.getFrom());
+ }
+ else if (currentEvent instanceof VehicleMoveEvent vehicleMove) {
+ yield new LocationTag(vehicleMove.getFrom());
+ }
+ else {
+ yield new LocationTag(currentEntity.getLocation());
+ }
}
- }
- else if (name.equals("entity")) {
- return currentEntity.getDenizenObject();
- }
- return super.getContext(name);
+ case "entity" -> currentEntity.getDenizenObject();
+ default -> super.getContext(name);
+ };
}
public void registerCorrectClass() {
@@ -178,7 +175,7 @@ else if (!needsMatchers && (matcher instanceof ExactMatchHelper)) {
}
exactTracked = needsMatchers ? null : exacts.toArray(new String[0]);
matchers = needsMatchers ? matchList.toArray(new MatchHelper[0]) : null;
- flagTracked = flags.size() > 0 ? flags.toArray(new String[0]) : null;
+ flagTracked = !flags.isEmpty() ? flags.toArray(new String[0]) : null;
registerCorrectClass();
}
@@ -258,7 +255,7 @@ public void processNewPosition(EntityTag entity, Location pos, Event eventCause)
if (doTrackAll || matchers != null || flagTracked != null) {
if (pos != null) {
NotedAreaTracker.forEachAreaThatContains(new LocationTag(pos), (a) -> {
- if (a instanceof FlaggableObject && anyMatch(a.getNoteName(), (FlaggableObject) a)) {
+ if (a instanceof FlaggableObject flaggable && anyMatch(a.getNoteName(), flaggable)) {
processSingle(a, entity, inAreas, pos, eventCause);
}
});
@@ -279,11 +276,11 @@ public void processNewPosition(EntityTag entity, Location pos, Event eventCause)
else {
for (String name : exactTracked) {
Notable obj = NoteManager.getSavedObject(name);
- if (!(obj instanceof AreaContainmentObject)) {
+ if (!(obj instanceof AreaContainmentObject areaObject)) {
Debug.echoError("Invalid area enter/exit event area '" + name + "'");
continue;
}
- processSingle((AreaContainmentObject) obj, entity, inAreas, pos, eventCause);
+ processSingle(areaObject, entity, inAreas, pos, eventCause);
}
}
if (inAreas != null && inAreas.isEmpty()) {
diff --git a/plugin/src/main/java/com/denizenscript/denizen/events/entity/CreeperPoweredScriptEvent.java b/plugin/src/main/java/com/denizenscript/denizen/events/entity/CreeperPoweredScriptEvent.java
index 3eaee2ea7a..5c81f08581 100644
--- a/plugin/src/main/java/com/denizenscript/denizen/events/entity/CreeperPoweredScriptEvent.java
+++ b/plugin/src/main/java/com/denizenscript/denizen/events/entity/CreeperPoweredScriptEvent.java
@@ -53,16 +53,12 @@ public boolean matches(ScriptPath path) {
@Override
public ObjectTag getContext(String name) {
- if (name.equals("entity")) {
- return entity;
- }
- else if (name.equals("lightning") && lightning != null) {
- return lightning;
- }
- else if (name.equals("cause")) {
- return cause;
- }
- return super.getContext(name);
+ return switch (name) {
+ case "entity" -> entity;
+ case "lightning" -> lightning;
+ case "cause" -> cause;
+ default -> super.getContext(name);
+ };
}
@EventHandler
diff --git a/plugin/src/main/java/com/denizenscript/denizen/events/entity/EntityBreaksHangingScriptEvent.java b/plugin/src/main/java/com/denizenscript/denizen/events/entity/EntityBreaksHangingScriptEvent.java
index aa4a142ce0..3a9b087522 100644
--- a/plugin/src/main/java/com/denizenscript/denizen/events/entity/EntityBreaksHangingScriptEvent.java
+++ b/plugin/src/main/java/com/denizenscript/denizen/events/entity/EntityBreaksHangingScriptEvent.java
@@ -88,17 +88,13 @@ public ScriptEntryData getScriptEntryData() {
@Override
public ObjectTag getContext(String name) {
- switch (name) {
- case "cause":
- return cause;
- case "breaker":
- return breaker;
- case "hanging":
- return hanging;
- case "location":
- return location;
- }
- return super.getContext(name);
+ return switch (name) {
+ case "cause" -> cause;
+ case "breaker" -> breaker.getDenizenObject();
+ case "hanging" -> hanging;
+ case "location" -> location;
+ default -> super.getContext(name);
+ };
}
@EventHandler
diff --git a/plugin/src/main/java/com/denizenscript/denizen/events/entity/EntityChangesBlockScriptEvent.java b/plugin/src/main/java/com/denizenscript/denizen/events/entity/EntityChangesBlockScriptEvent.java
index 873ccd4de9..93b1641206 100644
--- a/plugin/src/main/java/com/denizenscript/denizen/events/entity/EntityChangesBlockScriptEvent.java
+++ b/plugin/src/main/java/com/denizenscript/denizen/events/entity/EntityChangesBlockScriptEvent.java
@@ -42,8 +42,8 @@ public EntityChangesBlockScriptEvent() {
public EntityTag entity;
public LocationTag location;
- public MaterialTag old_material;
- public MaterialTag new_material;
+ public MaterialTag oldMaterial;
+ public MaterialTag newMaterial;
public EntityChangeBlockEvent event;
@Override
@@ -52,7 +52,7 @@ public boolean matches(ScriptPath path) {
if (!entity.tryAdvancedMatcher(entName, path.context)) {
return false;
}
- if (!path.tryArgObject(2, old_material)) {
+ if (!path.tryArgObject(2, oldMaterial)) {
return false;
}
if (path.eventArgLowerAt(3).equals("into")) {
@@ -61,7 +61,7 @@ public boolean matches(ScriptPath path) {
Debug.echoError("Invalid event material [" + getName() + "]: '" + path.event + "' for " + path.container.getName());
return false;
}
- else if (!new_material.tryAdvancedMatcher(mat2, path.context)) {
+ else if (!newMaterial.tryAdvancedMatcher(mat2, path.context)) {
return false;
}
}
@@ -78,25 +78,21 @@ public ScriptEntryData getScriptEntryData() {
@Override
public ObjectTag getContext(String name) {
- switch (name) {
- case "entity":
- return entity;
- case "location":
- return location;
- case "new_material":
- return new_material;
- case "old_material":
- return old_material;
- }
- return super.getContext(name);
+ return switch (name) {
+ case "entity" -> entity.getDenizenObject();
+ case "location" -> location;
+ case "new_material" -> newMaterial;
+ case "old_material" -> oldMaterial;
+ default -> super.getContext(name);
+ };
}
@EventHandler
public void onEntityChangesBlock(EntityChangeBlockEvent event) {
entity = new EntityTag(event.getEntity());
location = new LocationTag(event.getBlock().getLocation());
- old_material = new MaterialTag(location.getBlock());
- new_material = new MaterialTag(event.getTo());
+ oldMaterial = new MaterialTag(location.getBlock());
+ newMaterial = new MaterialTag(event.getTo());
this.event = event;
fire(event);
}
diff --git a/plugin/src/main/java/com/denizenscript/denizen/events/entity/EntityChangesPoseScriptEvent.java b/plugin/src/main/java/com/denizenscript/denizen/events/entity/EntityChangesPoseScriptEvent.java
index a543c74c62..ed6906b1e3 100644
--- a/plugin/src/main/java/com/denizenscript/denizen/events/entity/EntityChangesPoseScriptEvent.java
+++ b/plugin/src/main/java/com/denizenscript/denizen/events/entity/EntityChangesPoseScriptEvent.java
@@ -68,15 +68,12 @@ public ScriptEntryData getScriptEntryData() {
@Override
public ObjectTag getContext(String name) {
- switch (name) {
- case "entity":
- return entity;
- case "old_pose":
- return new ElementTag(oldPose);
- case "new_pose":
- return new ElementTag(event.getPose());
- }
- return super.getContext(name);
+ return switch (name) {
+ case "entity" -> entity.getDenizenObject();
+ case "old_pose" -> new ElementTag(oldPose);
+ case "new_pose" -> new ElementTag(event.getPose());
+ default -> super.getContext(name);
+ };
}
@EventHandler
diff --git a/plugin/src/main/java/com/denizenscript/denizen/events/entity/EntityCombustsScriptEvent.java b/plugin/src/main/java/com/denizenscript/denizen/events/entity/EntityCombustsScriptEvent.java
index 74f951aabf..4813091b89 100644
--- a/plugin/src/main/java/com/denizenscript/denizen/events/entity/EntityCombustsScriptEvent.java
+++ b/plugin/src/main/java/com/denizenscript/denizen/events/entity/EntityCombustsScriptEvent.java
@@ -80,32 +80,24 @@ public ScriptEntryData getScriptEntryData() {
@Override
public ObjectTag getContext(String name) {
- switch (name) {
- case "entity":
- return entity.getDenizenObject();
- case "duration":
- return new DurationTag(event.getDuration());
- case "source":
- if (event instanceof EntityCombustByEntityEvent) {
- return new EntityTag(((EntityCombustByEntityEvent) event).getCombuster()).getDenizenObject();
+ return switch (name) {
+ case "entity" -> entity.getDenizenObject();
+ case "duration" -> new DurationTag(event.getDuration());
+ case "source" -> {
+ if (event instanceof EntityCombustByEntityEvent byEntityEvent) {
+ yield new EntityTag(byEntityEvent.getCombuster()).getDenizenObject();
}
- else if (event instanceof EntityCombustByBlockEvent) {
- Block combuster = ((EntityCombustByBlockEvent) event).getCombuster();
+ else if (event instanceof EntityCombustByBlockEvent byBlockEvent) {
+ Block combuster = byBlockEvent.getCombuster();
if (combuster != null) {
- return new LocationTag(combuster.getLocation());
+ yield new LocationTag(combuster.getLocation());
}
}
- break;
- case "source_type":
- if (event instanceof EntityCombustByEntityEvent) {
- return new ElementTag("ENTITY");
- }
- else if (event instanceof EntityCombustByBlockEvent) {
- return new ElementTag("LOCATION");
- }
- return new ElementTag("NONE");
- }
- return super.getContext(name);
+ yield null;
+ }
+ case "source_type" -> new ElementTag(event instanceof EntityCombustByEntityEvent ? "ENTITY" : (event instanceof EntityCombustByBlockEvent ? "LOCATION" : "NONE"));
+ default -> super.getContext(name);
+ };
}
@EventHandler
diff --git a/plugin/src/main/java/com/denizenscript/denizen/events/entity/EntityCreatePortalScriptEvent.java b/plugin/src/main/java/com/denizenscript/denizen/events/entity/EntityCreatePortalScriptEvent.java
index b07b613933..2a18c24c7c 100644
--- a/plugin/src/main/java/com/denizenscript/denizen/events/entity/EntityCreatePortalScriptEvent.java
+++ b/plugin/src/main/java/com/denizenscript/denizen/events/entity/EntityCreatePortalScriptEvent.java
@@ -1,14 +1,13 @@
package com.denizenscript.denizen.events.entity;
-import com.denizenscript.denizen.objects.EntityTag;
-import com.denizenscript.denizen.utilities.implementation.BukkitScriptEntryData;
import com.denizenscript.denizen.events.BukkitScriptEvent;
+import com.denizenscript.denizen.objects.EntityTag;
import com.denizenscript.denizen.objects.LocationTag;
-import com.denizenscript.denizencore.objects.core.ElementTag;
+import com.denizenscript.denizen.utilities.implementation.BukkitScriptEntryData;
import com.denizenscript.denizencore.objects.ObjectTag;
+import com.denizenscript.denizencore.objects.core.ElementTag;
import com.denizenscript.denizencore.objects.core.ListTag;
import com.denizenscript.denizencore.scripts.ScriptEntryData;
-import org.bukkit.block.BlockState;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.entity.EntityCreatePortalEvent;
@@ -61,19 +60,12 @@ public ScriptEntryData getScriptEntryData() {
@Override
public ObjectTag getContext(String name) {
- switch (name) {
- case "entity":
- return entity;
- case "portal_type":
- return new ElementTag(event.getPortalType().toString());
- case "blocks":
- ListTag blocks = new ListTag();
- for (BlockState block : event.getBlocks()) {
- blocks.add(new LocationTag(block.getBlock().getLocation()).identifySimple());
- }
- return blocks;
- }
- return super.getContext(name);
+ return switch (name) {
+ case "entity" -> entity.getDenizenObject();
+ case "portal_type" -> new ElementTag(event.getPortalType());
+ case "blocks" -> new ListTag(event.getBlocks(), block -> new LocationTag(block.getLocation()));
+ default -> super.getContext(name);
+ };
}
@EventHandler
diff --git a/plugin/src/main/java/com/denizenscript/denizen/events/entity/EntityDespawnScriptEvent.java b/plugin/src/main/java/com/denizenscript/denizen/events/entity/EntityDespawnScriptEvent.java
index e39a215822..ab32db8e67 100644
--- a/plugin/src/main/java/com/denizenscript/denizen/events/entity/EntityDespawnScriptEvent.java
+++ b/plugin/src/main/java/com/denizenscript/denizen/events/entity/EntityDespawnScriptEvent.java
@@ -63,12 +63,10 @@ public ScriptEntryData getScriptEntryData() {
@Override
public ObjectTag getContext(String name) {
- if (name.equals("entity")) {
- return entity;
- }
- else if (name.equals("cause")) {
- return cause;
- }
- return super.getContext(name);
+ return switch (name) {
+ case "entity" -> entity;
+ case "cause" -> cause;
+ default -> super.getContext(name);
+ };
}
}
diff --git a/plugin/src/main/java/com/denizenscript/denizen/events/entity/EntityDropsItemScriptEvent.java b/plugin/src/main/java/com/denizenscript/denizen/events/entity/EntityDropsItemScriptEvent.java
index 21942ffb38..55184b440a 100644
--- a/plugin/src/main/java/com/denizenscript/denizen/events/entity/EntityDropsItemScriptEvent.java
+++ b/plugin/src/main/java/com/denizenscript/denizen/events/entity/EntityDropsItemScriptEvent.java
@@ -68,17 +68,13 @@ public ScriptEntryData getScriptEntryData() {
@Override
public ObjectTag getContext(String name) {
- switch (name) {
- case "item":
- return item;
- case "entity":
- return itemEntity;
- case "dropped_by":
- return dropper.getDenizenObject();
- case "location":
- return location;
- }
- return super.getContext(name);
+ return switch (name) {
+ case "item" -> item;
+ case "entity" -> itemEntity;
+ case "dropped_by" -> dropper.getDenizenObject();
+ case "location" -> location;
+ default -> super.getContext(name);
+ };
}
@EventHandler
diff --git a/plugin/src/main/java/com/denizenscript/denizen/events/entity/EntityEntersPortalScriptEvent.java b/plugin/src/main/java/com/denizenscript/denizen/events/entity/EntityEntersPortalScriptEvent.java
index 40799e70a8..e08bb23c75 100644
--- a/plugin/src/main/java/com/denizenscript/denizen/events/entity/EntityEntersPortalScriptEvent.java
+++ b/plugin/src/main/java/com/denizenscript/denizen/events/entity/EntityEntersPortalScriptEvent.java
@@ -59,13 +59,11 @@ public ScriptEntryData getScriptEntryData() {
@Override
public ObjectTag getContext(String name) {
- if (name.equals("entity")) {
- return entity;
- }
- else if (name.equals("location")) {
- return location;
- }
- return super.getContext(name);
+ return switch (name) {
+ case "entity" -> entity.getDenizenObject();
+ case "location" -> location;
+ default -> super.getContext(name);
+ };
}
@EventHandler
diff --git a/plugin/src/main/java/com/denizenscript/denizen/events/entity/EntityEntersVehicleScriptEvent.java b/plugin/src/main/java/com/denizenscript/denizen/events/entity/EntityEntersVehicleScriptEvent.java
index 6fefc81e8f..dae5c17519 100644
--- a/plugin/src/main/java/com/denizenscript/denizen/events/entity/EntityEntersVehicleScriptEvent.java
+++ b/plugin/src/main/java/com/denizenscript/denizen/events/entity/EntityEntersVehicleScriptEvent.java
@@ -79,13 +79,11 @@ public ScriptEntryData getScriptEntryData() {
@Override
public ObjectTag getContext(String name) {
- if (name.equals("vehicle")) {
- return vehicle.getDenizenObject();
- }
- else if (name.equals("entity")) {
- return entity.getDenizenObject();
- }
- return super.getContext(name);
+ return switch (name) {
+ case "vehicle" -> vehicle.getDenizenObject();
+ case "entity" -> entity.getDenizenObject();
+ default -> super.getContext(name);
+ };
}
@Override
diff --git a/plugin/src/main/java/com/denizenscript/denizen/events/entity/EntityExitsPortalScriptEvent.java b/plugin/src/main/java/com/denizenscript/denizen/events/entity/EntityExitsPortalScriptEvent.java
index 211b259437..6bcaf28b5e 100644
--- a/plugin/src/main/java/com/denizenscript/denizen/events/entity/EntityExitsPortalScriptEvent.java
+++ b/plugin/src/main/java/com/denizenscript/denizen/events/entity/EntityExitsPortalScriptEvent.java
@@ -59,13 +59,11 @@ public ScriptEntryData getScriptEntryData() {
@Override
public ObjectTag getContext(String name) {
- if (name.equals("entity")) {
- return entity;
- }
- else if (name.equals("location")) {
- return location;
- }
- return super.getContext(name);
+ return switch (name) {
+ case "entity" -> entity.getDenizenObject();
+ case "location" -> location;
+ default -> super.getContext(name);
+ };
}
@EventHandler
diff --git a/plugin/src/main/java/com/denizenscript/denizen/events/entity/EntityExitsVehicleScriptEvent.java b/plugin/src/main/java/com/denizenscript/denizen/events/entity/EntityExitsVehicleScriptEvent.java
index 01902181df..5af1f56a4a 100644
--- a/plugin/src/main/java/com/denizenscript/denizen/events/entity/EntityExitsVehicleScriptEvent.java
+++ b/plugin/src/main/java/com/denizenscript/denizen/events/entity/EntityExitsVehicleScriptEvent.java
@@ -63,13 +63,11 @@ public ScriptEntryData getScriptEntryData() {
@Override
public ObjectTag getContext(String name) {
- if (name.equals("vehicle")) {
- return vehicle.getDenizenObject();
- }
- else if (name.equals("entity")) {
- return entity.getDenizenObject();
- }
- return super.getContext(name);
+ return switch (name) {
+ case "vehicle" -> vehicle.getDenizenObject();
+ case "entity" -> entity.getDenizenObject();
+ default -> super.getContext(name);
+ };
}
@Override
diff --git a/plugin/src/main/java/com/denizenscript/denizen/events/entity/EntityExplosionPrimesScriptEvent.java b/plugin/src/main/java/com/denizenscript/denizen/events/entity/EntityExplosionPrimesScriptEvent.java
index 930b99010f..d135e460b7 100644
--- a/plugin/src/main/java/com/denizenscript/denizen/events/entity/EntityExplosionPrimesScriptEvent.java
+++ b/plugin/src/main/java/com/denizenscript/denizen/events/entity/EntityExplosionPrimesScriptEvent.java
@@ -2,9 +2,8 @@
import com.denizenscript.denizen.objects.EntityTag;
import com.denizenscript.denizen.events.BukkitScriptEvent;
-import com.denizenscript.denizencore.objects.Argument;
+import com.denizenscript.denizen.utilities.BukkitImplDeprecations;
import com.denizenscript.denizencore.objects.core.ElementTag;
-import com.denizenscript.denizencore.objects.ArgumentHelper;
import com.denizenscript.denizencore.objects.ObjectTag;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
@@ -25,13 +24,36 @@ public class EntityExplosionPrimesScriptEvent extends BukkitScriptEvent implemen
// @Triggers when an entity decides to explode.
//
// @Context
- // returns the EntityTag.
- // returns an ElementTag of the explosion's radius.
- // returns an ElementTag with a value of "true" if the explosion will create fire and "false" otherwise.
+ // returns an EntityTag of the exploding entity.
+ // returns the explosion's radius.
+ // returns whether the explosion will create fire.
+ //
+ // @Determine
+ // ElementTag(Decimal) to change the explosion radius.
+ // "FIRE:" to set whether the explosion will produce fire.
// -->
public EntityExplosionPrimesScriptEvent() {
registerCouldMatcher(" explosion primes");
+ this.registerOptionalDetermination(null, ElementTag.class, (evt, context, value) -> {
+ if (value.isFloat()) {
+ evt.event.setRadius(value.asFloat());
+ return true;
+ }
+ if (value.isBoolean()) {
+ BukkitImplDeprecations.explosionPrimeDetermination.warn();
+ evt.event.setFire(value.asBoolean());
+ return true;
+ }
+ return false;
+ });
+ this.registerOptionalDetermination("fire", ElementTag.class, (evt, context, value) -> {
+ if (value.isBoolean()) {
+ evt.event.setFire(value.asBoolean());
+ return true;
+ }
+ return false;
+ });
}
public EntityTag entity;
@@ -48,31 +70,14 @@ public boolean matches(ScriptPath path) {
return super.matches(path);
}
- @Override
- public boolean applyDetermination(ScriptPath path, ObjectTag determinationObj) {
- String determination = determinationObj.toString();
- if (ArgumentHelper.matchesDouble(determination)) {
- event.setRadius(Float.parseFloat(determination));
- return true;
- }
- if (Argument.valueOf(determination).matchesBoolean()) {
- event.setFire(determination.equalsIgnoreCase("true"));
- return true;
- }
- return super.applyDetermination(path, determinationObj);
- }
-
@Override
public ObjectTag getContext(String name) {
- switch (name) {
- case "entity":
- return entity;
- case "radius":
- return new ElementTag(event.getRadius());
- case "fire":
- return new ElementTag(event.getFire());
- }
- return super.getContext(name);
+ return switch (name) {
+ case "entity" -> entity.getDenizenObject();
+ case "radius" -> new ElementTag(event.getRadius());
+ case "fire" -> new ElementTag(event.getFire());
+ default -> super.getContext(name);
+ };
}
@EventHandler
diff --git a/plugin/src/main/java/com/denizenscript/denizen/events/entity/EntityFormsBlockScriptEvent.java b/plugin/src/main/java/com/denizenscript/denizen/events/entity/EntityFormsBlockScriptEvent.java
index b55d57fdc7..c282dbf1b1 100644
--- a/plugin/src/main/java/com/denizenscript/denizen/events/entity/EntityFormsBlockScriptEvent.java
+++ b/plugin/src/main/java/com/denizenscript/denizen/events/entity/EntityFormsBlockScriptEvent.java
@@ -1,10 +1,10 @@
package com.denizenscript.denizen.events.entity;
+import com.denizenscript.denizen.events.BukkitScriptEvent;
import com.denizenscript.denizen.objects.EntityTag;
import com.denizenscript.denizen.objects.LocationTag;
import com.denizenscript.denizen.objects.MaterialTag;
import com.denizenscript.denizen.utilities.implementation.BukkitScriptEntryData;
-import com.denizenscript.denizen.events.BukkitScriptEvent;
import com.denizenscript.denizencore.objects.ObjectTag;
import com.denizenscript.denizencore.scripts.ScriptEntryData;
import org.bukkit.event.EventHandler;
@@ -27,8 +27,8 @@ public class EntityFormsBlockScriptEvent extends BukkitScriptEvent implements Li
// For example, when a snowman forms snow.
//
// @Context
- // returns the LocationTag the block.
- // returns the MaterialTag of the block.
+ // returns the LocationTag of the block.
+ // returns the MaterialTag of what the block will become.
// returns the EntityTag that formed the block.
//
// -->
@@ -63,21 +63,18 @@ public ScriptEntryData getScriptEntryData() {
@Override
public ObjectTag getContext(String name) {
- switch (name) {
- case "location":
- return location;
- case "material":
- return material;
- case "entity":
- return entity;
- }
- return super.getContext(name);
+ return switch (name) {
+ case "location" -> location;
+ case "material" -> material;
+ case "entity" -> entity;
+ default -> super.getContext(name);
+ };
}
@EventHandler
public void onEntityFormsBlock(EntityBlockFormEvent event) {
location = new LocationTag(event.getBlock().getLocation());
- material = new MaterialTag(event.getBlock());
+ material = new MaterialTag(event.getNewState());
entity = new EntityTag(event.getEntity());
this.event = event;
fire(event);
diff --git a/plugin/src/main/java/com/denizenscript/denizen/events/entity/EntityGlideScriptEvent.java b/plugin/src/main/java/com/denizenscript/denizen/events/entity/EntityGlideScriptEvent.java
index b88c3103d2..c139c128cc 100644
--- a/plugin/src/main/java/com/denizenscript/denizen/events/entity/EntityGlideScriptEvent.java
+++ b/plugin/src/main/java/com/denizenscript/denizen/events/entity/EntityGlideScriptEvent.java
@@ -66,13 +66,11 @@ public ScriptEntryData getScriptEntryData() {
@Override
public ObjectTag getContext(String name) {
- if (name.equals("entity")) {
- return entity;
- }
- else if (name.equals("state")) {
- return new ElementTag(state);
- }
- return super.getContext(name);
+ return switch (name) {
+ case "entity" -> entity.getDenizenObject();
+ case "state" -> new ElementTag(state);
+ default -> super.getContext(name);
+ };
}
@EventHandler
diff --git a/plugin/src/main/java/com/denizenscript/denizen/events/entity/EntityGoesIntoBlockScriptEvent.java b/plugin/src/main/java/com/denizenscript/denizen/events/entity/EntityGoesIntoBlockScriptEvent.java
index 957a336fd3..6acd83ccbf 100644
--- a/plugin/src/main/java/com/denizenscript/denizen/events/entity/EntityGoesIntoBlockScriptEvent.java
+++ b/plugin/src/main/java/com/denizenscript/denizen/events/entity/EntityGoesIntoBlockScriptEvent.java
@@ -63,12 +63,12 @@ public ScriptEntryData getScriptEntryData() {
@Override
public ObjectTag getContext(String name) {
- switch (name) {
- case "entity": return entity.getDenizenObject();
- case "location": return location;
- case "material": return material;
- }
- return super.getContext(name);
+ return switch (name) {
+ case "entity" -> entity.getDenizenObject();
+ case "location" -> location;
+ case "material" -> material;
+ default -> super.getContext(name);
+ };
}
@EventHandler
diff --git a/plugin/src/main/java/com/denizenscript/denizen/events/entity/EntityInteractScriptEvent.java b/plugin/src/main/java/com/denizenscript/denizen/events/entity/EntityInteractScriptEvent.java
index 404cf77b40..8c433ab55c 100644
--- a/plugin/src/main/java/com/denizenscript/denizen/events/entity/EntityInteractScriptEvent.java
+++ b/plugin/src/main/java/com/denizenscript/denizen/events/entity/EntityInteractScriptEvent.java
@@ -61,13 +61,11 @@ public ScriptEntryData getScriptEntryData() {
@Override
public ObjectTag getContext(String name) {
- if (name.equals("entity")) {
- return entity;
- }
- else if (name.equals("location")) {
- return location;
- }
- return super.getContext(name);
+ return switch (name) {
+ case "entity" -> entity.getDenizenObject();
+ case "location" -> location;
+ default -> super.getContext(name);
+ };
}
@EventHandler
diff --git a/plugin/src/main/java/com/denizenscript/denizen/events/entity/EntitySpawnScriptEvent.java b/plugin/src/main/java/com/denizenscript/denizen/events/entity/EntitySpawnScriptEvent.java
index 0ac74a8b35..6ca957840a 100644
--- a/plugin/src/main/java/com/denizenscript/denizen/events/entity/EntitySpawnScriptEvent.java
+++ b/plugin/src/main/java/com/denizenscript/denizen/events/entity/EntitySpawnScriptEvent.java
@@ -1,11 +1,11 @@
package com.denizenscript.denizen.events.entity;
+import com.denizenscript.denizen.events.BukkitScriptEvent;
import com.denizenscript.denizen.objects.EntityTag;
import com.denizenscript.denizen.objects.LocationTag;
import com.denizenscript.denizen.utilities.implementation.BukkitScriptEntryData;
-import com.denizenscript.denizen.events.BukkitScriptEvent;
-import com.denizenscript.denizencore.objects.core.ElementTag;
import com.denizenscript.denizencore.objects.ObjectTag;
+import com.denizenscript.denizencore.objects.core.ElementTag;
import com.denizenscript.denizencore.scripts.ScriptEntryData;
import org.bukkit.entity.Entity;
import org.bukkit.event.EventHandler;
@@ -79,19 +79,13 @@ public ScriptEntryData getScriptEntryData() {
@Override
public ObjectTag getContext(String name) {
- if (name.equals("entity")) {
- return entity;
- }
- else if (name.equals("location")) {
- return location;
- }
- else if (name.equals("reason")) {
- return reason;
- }
- else if (name.equals("spawner_location") && event instanceof SpawnerSpawnEvent) {
- return new LocationTag(((SpawnerSpawnEvent) event).getSpawner().getLocation());
- }
- return super.getContext(name);
+ return switch (name) {
+ case "entity" -> entity;
+ case "location" -> location;
+ case "reason" -> reason;
+ case "spawner_location" -> event instanceof SpawnerSpawnEvent spawnerEvent ? new LocationTag(spawnerEvent.getSpawner().getLocation()) : null;
+ default -> super.getContext(name);
+ };
}
@EventHandler
@@ -99,8 +93,8 @@ public void onEntitySpawn(EntitySpawnEvent event) {
Entity entity = event.getEntity();
this.entity = new EntityTag(entity);
location = new LocationTag(event.getLocation());
- if (event instanceof CreatureSpawnEvent) {
- CreatureSpawnEvent.SpawnReason creatureReason = ((CreatureSpawnEvent) event).getSpawnReason();
+ if (event instanceof CreatureSpawnEvent creatureSpawnEvent) {
+ CreatureSpawnEvent.SpawnReason creatureReason = creatureSpawnEvent.getSpawnReason();
if (creatureReason == CreatureSpawnEvent.SpawnReason.SPAWNER) {
return; // Let the SpawnerSpawnEvent happen and handle it instead
}
diff --git a/plugin/src/main/java/com/denizenscript/denizen/events/entity/EntitySwimScriptEvent.java b/plugin/src/main/java/com/denizenscript/denizen/events/entity/EntitySwimScriptEvent.java
index f189083ad9..9f9199d0af 100644
--- a/plugin/src/main/java/com/denizenscript/denizen/events/entity/EntitySwimScriptEvent.java
+++ b/plugin/src/main/java/com/denizenscript/denizen/events/entity/EntitySwimScriptEvent.java
@@ -66,13 +66,11 @@ public ScriptEntryData getScriptEntryData() {
@Override
public ObjectTag getContext(String name) {
- if (name.equals("entity")) {
- return entity;
- }
- else if (name.equals("state")) {
- return new ElementTag(state);
- }
- return super.getContext(name);
+ return switch (name) {
+ case "entity" -> entity.getDenizenObject();
+ case "state" -> new ElementTag(state);
+ default -> super.getContext(name);
+ };
}
@EventHandler
diff --git a/plugin/src/main/java/com/denizenscript/denizen/events/entity/EntityTamesScriptEvent.java b/plugin/src/main/java/com/denizenscript/denizen/events/entity/EntityTamesScriptEvent.java
index 10881babc4..8c287f3983 100644
--- a/plugin/src/main/java/com/denizenscript/denizen/events/entity/EntityTamesScriptEvent.java
+++ b/plugin/src/main/java/com/denizenscript/denizen/events/entity/EntityTamesScriptEvent.java
@@ -19,8 +19,6 @@ public class EntityTamesScriptEvent extends BukkitScriptEvent implements Listene
// player tames entity
// player tames
//
- // @Regex ^on [^\s]+ (tames [^\s]+|tamed)$
- //
// @Group Entity
//
// @Location true
@@ -33,28 +31,19 @@ public class EntityTamesScriptEvent extends BukkitScriptEvent implements Listene
// returns a EntityTag of the tamed entity.
// returns a EntityTag of the owner.
//
- // @Player when a player tames an entity and using the 'players tames entity' event.
+ // @Player when a player is what tamed the entity.
//
// -->
public EntityTamesScriptEvent() {
+ registerCouldMatcher(" tamed");
+ registerCouldMatcher("player tames ");
}
public EntityTag entity;
public EntityTag owner;
public EntityTameEvent event;
- @Override
- public boolean couldMatch(ScriptPath path) {
- if (!path.eventArgLowerAt(1).equals("tames") && !path.eventArgLowerAt(1).equals("tamed")) {
- return false;
- }
- if (!couldMatchEntity(path.eventArgLowerAt(0))) {
- return false;
- }
- return true;
- }
-
@Override
public boolean matches(ScriptPath path) {
String cmd = path.eventArgLowerAt(1);
@@ -76,13 +65,11 @@ public ScriptEntryData getScriptEntryData() {
@Override
public ObjectTag getContext(String name) {
- if (name.equals("entity")) {
- return entity;
- }
- else if (name.equals("owner")) {
- return owner;
- }
- return super.getContext(name);
+ return switch (name) {
+ case "entity" -> entity;
+ case "owner" -> owner.getDenizenObject();
+ default -> super.getContext(name);
+ };
}
@EventHandler
diff --git a/plugin/src/main/java/com/denizenscript/denizen/events/player/PlayerPreparesEnchantScriptEvent.java b/plugin/src/main/java/com/denizenscript/denizen/events/player/PlayerPreparesEnchantScriptEvent.java
index af97ebd94b..f6a75c4125 100644
--- a/plugin/src/main/java/com/denizenscript/denizen/events/player/PlayerPreparesEnchantScriptEvent.java
+++ b/plugin/src/main/java/com/denizenscript/denizen/events/player/PlayerPreparesEnchantScriptEvent.java
@@ -77,6 +77,10 @@ public boolean applyDetermination(ScriptPath path, ObjectTag determinationObj) {
}
for (int i = 0; i < offers.size(); i++) {
MapTag map = MapTag.getMapFor(offers.getObject(i), getTagContext(path));
+ if (map.isEmpty()) {
+ event.getOffers()[i] = null;
+ continue;
+ }
event.getOffers()[i].setCost(map.getElement("cost").asInt());
EnchantmentTag enchantment = map.getObjectAs("enchantment_type", EnchantmentTag.class, getTagContext(path));
if (enchantment == null) {
@@ -108,6 +112,10 @@ public ObjectTag getContext(String name) {
case "offers":
ListTag output = new ListTag();
for (EnchantmentOffer offer : event.getOffers()) {
+ if (offer == null) {
+ output.addObject(new MapTag());
+ continue;
+ }
MapTag map = new MapTag();
map.putObject("cost", new ElementTag(offer.getCost()));
map.putObject("enchantment", new ElementTag(offer.getEnchantment().getKey().getKey()));
diff --git a/plugin/src/main/java/com/denizenscript/denizen/events/player/PlayerRaiseLowerItemScriptEvent.java b/plugin/src/main/java/com/denizenscript/denizen/events/player/PlayerRaiseLowerItemScriptEvent.java
index 0d17a6c1ed..c727a00188 100644
--- a/plugin/src/main/java/com/denizenscript/denizen/events/player/PlayerRaiseLowerItemScriptEvent.java
+++ b/plugin/src/main/java/com/denizenscript/denizen/events/player/PlayerRaiseLowerItemScriptEvent.java
@@ -1,6 +1,8 @@
package com.denizenscript.denizen.events.player;
import com.denizenscript.denizen.events.BukkitScriptEvent;
+import com.denizenscript.denizen.nms.NMSHandler;
+import com.denizenscript.denizen.nms.NMSVersion;
import com.denizenscript.denizen.objects.ItemTag;
import com.denizenscript.denizen.objects.PlayerTag;
import com.denizenscript.denizen.utilities.implementation.BukkitScriptEntryData;
@@ -9,19 +11,14 @@
import com.denizenscript.denizencore.objects.core.ElementTag;
import com.denizenscript.denizencore.scripts.ScriptEntryData;
import org.bukkit.Material;
+import org.bukkit.Tag;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.entity.PlayerDeathEvent;
-import org.bukkit.event.player.PlayerDropItemEvent;
-import org.bukkit.event.player.PlayerItemHeldEvent;
-import org.bukkit.event.player.PlayerQuitEvent;
-import org.bukkit.event.player.PlayerSwapHandItemsEvent;
+import org.bukkit.event.player.*;
-import java.util.EnumSet;
-import java.util.HashSet;
-import java.util.Set;
-import java.util.UUID;
+import java.util.*;
public class PlayerRaiseLowerItemScriptEvent extends BukkitScriptEvent implements Listener {
@@ -29,7 +26,7 @@ public class PlayerRaiseLowerItemScriptEvent extends BukkitScriptEvent implement
// @Events
// player raises|lowers|toggles
-
//
- // @Synonyms player raises shield, player raises spyglass
+ // @Synonyms player raises shield, player raises spyglass, player raises spear
//
// @Group Player
//
@@ -55,6 +52,12 @@ public class PlayerRaiseLowerItemScriptEvent extends BukkitScriptEvent implement
public static final EnumSet raisableItems = EnumSet.of(Material.SHIELD, Material.CROSSBOW, Material.BOW, Material.TRIDENT, Material.SPYGLASS);
+ static {
+ if (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_21)) {
+ raisableItems.addAll(Tag.ITEMS_SPEARS.getValues());
+ }
+ }
+
public PlayerRaiseLowerItemScriptEvent() {
registerCouldMatcher("player raises|lowers|toggles
- ");
registerSwitches("reason");
diff --git a/plugin/src/main/java/com/denizenscript/denizen/events/server/ListPingScriptEvent.java b/plugin/src/main/java/com/denizenscript/denizen/events/server/ListPingScriptEvent.java
index 0e8e554d2c..5f704f67c8 100644
--- a/plugin/src/main/java/com/denizenscript/denizen/events/server/ListPingScriptEvent.java
+++ b/plugin/src/main/java/com/denizenscript/denizen/events/server/ListPingScriptEvent.java
@@ -48,6 +48,7 @@ public class ListPingScriptEvent extends BukkitScriptEvent implements Listener {
// "VERSION_NAME:" to change the server's version name (only on Paper).
// "EXCLUDE_PLAYERS:" to exclude a set of players from showing in the player count or preview of online players (only on Paper).
// "ALTERNATE_PLAYER_TEXT:" to set custom text for the player list section of the server status (only on Paper). (Requires "Allow restricted actions" in Denizen/config.yml). Usage of this to present lines that look like player names (but aren't) is forbidden.
+ // "PLAYER_COUNT:" to set the amount of players that are online (only on Paper). (Requires "Allow restricted actions" in Denizen/config.yml). Usage of this to display a higher number of players than are actually connected is forbidden.
// "MOTD:" to change the MOTD that will show.
//
// -->
diff --git a/plugin/src/main/java/com/denizenscript/denizen/nms/NMSVersion.java b/plugin/src/main/java/com/denizenscript/denizen/nms/NMSVersion.java
index 8b75de4b81..22a7edece8 100644
--- a/plugin/src/main/java/com/denizenscript/denizen/nms/NMSVersion.java
+++ b/plugin/src/main/java/com/denizenscript/denizen/nms/NMSVersion.java
@@ -7,7 +7,9 @@ public enum NMSVersion {
v1_18("1.18"),
v1_19("1.19"),
v1_20("1.20"),
- v1_21("1.21");
+ v1_21("1.21"),
+ v26_1("26.1"),
+ v26_2("26.2");
final String minecraftVersion;
diff --git a/plugin/src/main/java/com/denizenscript/denizen/nms/abstracts/ImprovedOfflinePlayer.java b/plugin/src/main/java/com/denizenscript/denizen/nms/abstracts/ImprovedOfflinePlayer.java
index 6e6b834478..f031a63c31 100644
--- a/plugin/src/main/java/com/denizenscript/denizen/nms/abstracts/ImprovedOfflinePlayer.java
+++ b/plugin/src/main/java/com/denizenscript/denizen/nms/abstracts/ImprovedOfflinePlayer.java
@@ -204,7 +204,7 @@ public void setAbsorptionAmount(float input) {
}
public void setBedSpawnLocation(Location location) {
- if (location == null && !compound.keySet().contains("SpawnDimension")) {
+ if (location == null && !compound.contains("SpawnDimension")) {
return;
}
CompoundBinaryTag.Builder builder = CompoundBinaryTag.builder().put(compound);
diff --git a/plugin/src/main/java/com/denizenscript/denizen/nms/interfaces/EntityHelper.java b/plugin/src/main/java/com/denizenscript/denizen/nms/interfaces/EntityHelper.java
index 0501930cd7..f18202f90e 100644
--- a/plugin/src/main/java/com/denizenscript/denizen/nms/interfaces/EntityHelper.java
+++ b/plugin/src/main/java/com/denizenscript/denizen/nms/interfaces/EntityHelper.java
@@ -5,6 +5,7 @@
import com.denizenscript.denizen.objects.EntityTag;
import com.denizenscript.denizen.objects.LocationTag;
import com.denizenscript.denizen.utilities.Utilities;
+import com.denizenscript.denizen.objects.properties.entity.EntityState;
import com.denizenscript.denizencore.objects.core.ElementTag;
import com.denizenscript.denizencore.objects.core.MapTag;
import net.kyori.adventure.nbt.CompoundBinaryTag;
@@ -514,4 +515,12 @@ public void onEntityMount(EntityDismountEvent event) {
public Class extends EntityExitsVehicleScriptEvent> getExitsVehicleEventImpl() { // TODO: once 1.20 is the minimum supported version, implement in the ScriptEvent class as usual
return EntityExitsVehicleScriptEventImpl.class;
}
+
+ public EntityState.ArmadilloState getArmadilloState(Armadillo entity) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void setArmadilloState(Armadillo entity, EntityState.ArmadilloState state) {
+ throw new UnsupportedOperationException();
+ }
}
diff --git a/plugin/src/main/java/com/denizenscript/denizen/nms/interfaces/ItemHelper.java b/plugin/src/main/java/com/denizenscript/denizen/nms/interfaces/ItemHelper.java
index 4ae68a5f7f..f14e1255d6 100644
--- a/plugin/src/main/java/com/denizenscript/denizen/nms/interfaces/ItemHelper.java
+++ b/plugin/src/main/java/com/denizenscript/denizen/nms/interfaces/ItemHelper.java
@@ -85,8 +85,7 @@ public CompoundBinaryTag getEntityData(ItemStack item) { // TODO: once 1.20 is t
public ItemStack setEntityData(ItemStack item, CompoundBinaryTag entityNbt, EntityType entityType) { // TODO: once 1.20 is the minimum supported version, remove default impl
boolean shouldRemove = entityNbt == null || entityNbt.isEmpty();
CompoundBinaryTag nbt = getNbtData(item);
- // TODO: adventure-nbt: contains
- if (shouldRemove && !nbt.keySet().contains("EntityTag")) {
+ if (shouldRemove && !nbt.contains("EntityTag")) {
return item;
}
if (shouldRemove) {
diff --git a/plugin/src/main/java/com/denizenscript/denizen/objects/BiomeTag.java b/plugin/src/main/java/com/denizenscript/denizen/objects/BiomeTag.java
index d0f02e6750..e8b2e53caa 100644
--- a/plugin/src/main/java/com/denizenscript/denizen/objects/BiomeTag.java
+++ b/plugin/src/main/java/com/denizenscript/denizen/objects/BiomeTag.java
@@ -508,7 +508,7 @@ else if (attribute.startsWith("water", 2)) {
});
}
- public static final ObjectTagProcessor tagProcessor = new ObjectTagProcessor<>();
+ public static ObjectTagProcessor tagProcessor = new ObjectTagProcessor<>();
@Override
public ObjectTag getObjectAttribute(Attribute attribute) {
diff --git a/plugin/src/main/java/com/denizenscript/denizen/objects/ChunkTag.java b/plugin/src/main/java/com/denizenscript/denizen/objects/ChunkTag.java
index d2b8ba213b..28819cb6cf 100644
--- a/plugin/src/main/java/com/denizenscript/denizen/objects/ChunkTag.java
+++ b/plugin/src/main/java/com/denizenscript/denizen/objects/ChunkTag.java
@@ -1,14 +1,13 @@
package com.denizenscript.denizen.objects;
+import com.denizenscript.denizen.nms.NMSHandler;
import com.denizenscript.denizen.nms.NMSVersion;
import com.denizenscript.denizen.utilities.BukkitImplDeprecations;
-import com.denizenscript.denizencore.utilities.debugging.Debug;
import com.denizenscript.denizen.utilities.flags.DataPersistenceFlagTracker;
import com.denizenscript.denizen.utilities.flags.LocationFlagSearchHelper;
import com.denizenscript.denizencore.flags.AbstractFlagTracker;
import com.denizenscript.denizencore.flags.FlaggableObject;
import com.denizenscript.denizencore.objects.*;
-import com.denizenscript.denizen.nms.NMSHandler;
import com.denizenscript.denizencore.objects.core.DurationTag;
import com.denizenscript.denizencore.objects.core.ElementTag;
import com.denizenscript.denizencore.objects.core.ListTag;
@@ -16,6 +15,7 @@
import com.denizenscript.denizencore.tags.ObjectTagProcessor;
import com.denizenscript.denizencore.tags.TagContext;
import com.denizenscript.denizencore.utilities.CoreUtilities;
+import com.denizenscript.denizencore.utilities.debugging.Debug;
import org.bukkit.Chunk;
import org.bukkit.ChunkSnapshot;
import org.bukkit.Location;
@@ -26,7 +26,8 @@
import org.bukkit.entity.Player;
import org.bukkit.plugin.Plugin;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.List;
public class ChunkTag implements ObjectTag, Adjustable, FlaggableObject {
@@ -889,15 +890,21 @@ public void adjust(Mechanism mechanism) {
// <--[mechanism]
// @object ChunkTag
// @name regenerate
+ // @deprecated functionality was removed from Spigot and Paper as of MC 1.21.
// @input None
// @description
+ // Deprecated on MC 1.21+.
// Causes the chunk to be entirely deleted and reformed from the world's seed.
- // At time of writing this method only works as expected on Paper, and will error on Spigot.
// @example
// - adjust regenerate
// -->
if (mechanism.matches("regenerate")) {
- getBukkitWorld().regenerateChunk(getX(), getZ());
+ if (NMSHandler.getVersion().isAtMost(NMSVersion.v1_20)) {
+ getBukkitWorld().regenerateChunk(getX(), getZ());
+ }
+ else {
+ BukkitImplDeprecations.chunkRegeneration.warn(mechanism.context);
+ }
}
// <--[mechanism]
diff --git a/plugin/src/main/java/com/denizenscript/denizen/objects/EntityTag.java b/plugin/src/main/java/com/denizenscript/denizen/objects/EntityTag.java
index 81a797a550..a31fef84f7 100644
--- a/plugin/src/main/java/com/denizenscript/denizen/objects/EntityTag.java
+++ b/plugin/src/main/java/com/denizenscript/denizen/objects/EntityTag.java
@@ -100,6 +100,7 @@ public class EntityTag implements ObjectTag, Adjustable, EntityFormObject, Flagg
// "projectile" plaintext: matches for any projectile type (arrow, trident, fish hook, snowball, etc).
// "hanging" plaintext: matches for any hanging type (painting, item_frame, etc).
// "monster" plaintext: matches for any monster type (creepers, zombies, etc).
+ // "enemy" plaintext: matches for any hostile entities (zombies, shulkers, ect).
// "animal" plaintext: matches for any animal type (pigs, cows, etc).
// "mob" plaintext: matches for any mob type (creepers, pigs, etc).
// "living" plaintext: matches for any living type (players, pigs, creepers, etc).
@@ -610,6 +611,13 @@ public boolean isMonsterType() {
return getBukkitEntity() instanceof Monster;
}
+ public boolean isEnemyType() {
+ if (getBukkitEntity() == null && entity_type != null) {
+ return Enemy.class.isAssignableFrom(entity_type.getBukkitEntityType().getEntityClass());
+ }
+ return getBukkitEntity() instanceof Enemy;
+ }
+
public boolean isMobType() {
if (getBukkitEntity() == null && entity_type != null) {
return Mob.class.isAssignableFrom(entity_type.getBukkitEntityType().getEntityClass());
@@ -2372,6 +2380,20 @@ else if (object.getBukkitEntity() instanceof Hanging hanging) {
return new ElementTag(object.isMonsterType());
});
+ if (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_19)) {
+
+ // <--[tag]
+ // @attribute
+ // @returns ElementTag(Boolean)
+ // @group data
+ // @description
+ // Returns whether the entity type is an enemy. See <@link url https://hub.spigotmc.org/javadocs/spigot/org/bukkit/entity/Enemy.html>
+ // -->
+ tagProcessor.registerTag(ElementTag.class, "is_enemy", (attribute, object) -> {
+ return new ElementTag(object.isEnemyType());
+ });
+ }
+
// <--[tag]
// @attribute
// @returns ElementTag(Boolean)
@@ -3223,6 +3245,29 @@ else if (object.getBukkitEntity() instanceof Hanging hanging) {
fox.setSleeping(input.asBoolean());
});
+ // <--[mechanism]
+ // @object EntityTag
+ // @name detonate
+ // @input None
+ // @description
+ // If the entity is a firework, creeper, or wind charge, detonates it.
+ // -->
+ tagProcessor.registerMechanism("detonate", false, (object, mechanism) -> {
+ Entity entity = object.getBukkitEntity();
+ if (entity instanceof Firework firework) {
+ firework.detonate();
+ }
+ else if (entity instanceof Creeper creeper) {
+ creeper.explode();
+ }
+ else if (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_21) && entity instanceof AbstractWindCharge windCharge) {
+ windCharge.explode();
+ }
+ else {
+ mechanism.echoError("Cannot detonate entity of type '" + object.getEntityType() + "'.");
+ }
+ });
+
if (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_20)) {
// <--[mechanism]
@@ -4130,28 +4175,6 @@ public void adjust(Mechanism mechanism) {
getLivingEntity().setSwimming(mechanism.getValue().asBoolean());
}
- // <--[mechanism]
- // @object EntityTag
- // @name detonate
- // @input None
- // @description
- // If the entity is a firework, creeper, or wind charge, detonates it.
- // -->
- if (mechanism.matches("detonate")) {
- if (getBukkitEntity() instanceof Firework firework) {
- firework.detonate();
- }
- else if (getBukkitEntity() instanceof Creeper creeper) {
- creeper.explode();
- }
- else if (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_21) && getBukkitEntity() instanceof WindCharge windCharge) {
- windCharge.explode();
- }
- else {
- Debug.echoError("Cannot detonate entity of type '" + getBukkitEntityType().name() + "'.");
- }
- }
-
// <--[mechanism]
// @object EntityTag
// @name ignite
@@ -4586,6 +4609,8 @@ public final boolean trySpecialEntityMatcher(String text, boolean isNPC) {
return isMobType();
case "animal":
return isAnimalType();
+ case "enemy":
+ return isEnemyType();
}
return false;
}
diff --git a/plugin/src/main/java/com/denizenscript/denizen/objects/ItemTag.java b/plugin/src/main/java/com/denizenscript/denizen/objects/ItemTag.java
index f6143fa045..87b2d98b98 100644
--- a/plugin/src/main/java/com/denizenscript/denizen/objects/ItemTag.java
+++ b/plugin/src/main/java/com/denizenscript/denizen/objects/ItemTag.java
@@ -856,12 +856,13 @@ public boolean advancedMatches(String matcher, TagContext context) {
return BukkitScriptEvent.coreFlaggedCheck(matcher.substring("item_flagged:".length()), getFlagTracker());
}
else if (matcherLow.startsWith("item_enchanted:")) {
- String enchMatcher = matcher.substring("item_enchanted:".length());
+ String enchMatcherStr = matcher.substring("item_enchanted:".length());
if (getBukkitMaterial().isAir() || !getItemMeta().hasEnchants()) {
return false;
}
+ ScriptEvent.MatchHelper enchMatcher = ScriptEvent.createMatcher(enchMatcherStr);
for (Enchantment enchant : getItemMeta().getEnchants().keySet()) {
- if (BukkitScriptEvent.runGenericCheck(enchMatcher, enchant.getKey().getKey())) {
+ if (enchMatcher.doesMatch(enchant.getKey().getKey()) || enchMatcher.doesMatch(enchant.getKey().toString())) {
return true;
}
}
diff --git a/plugin/src/main/java/com/denizenscript/denizen/objects/LocationTag.java b/plugin/src/main/java/com/denizenscript/denizen/objects/LocationTag.java
index e686ef7c92..eff8b59faf 100644
--- a/plugin/src/main/java/com/denizenscript/denizen/objects/LocationTag.java
+++ b/plugin/src/main/java/com/denizenscript/denizen/objects/LocationTag.java
@@ -11,6 +11,7 @@
import com.denizenscript.denizen.objects.properties.material.MaterialDirectional;
import com.denizenscript.denizen.objects.properties.material.MaterialDistance;
import com.denizenscript.denizen.objects.properties.material.MaterialHalf;
+import com.denizenscript.denizen.scripts.commands.world.SignCommand;
import com.denizenscript.denizen.scripts.commands.world.SwitchCommand;
import com.denizenscript.denizen.utilities.*;
import com.denizenscript.denizen.utilities.blocks.SpawnableHelper;
@@ -40,6 +41,7 @@
import org.bukkit.block.banner.PatternType;
import org.bukkit.block.data.BlockData;
import org.bukkit.block.data.Directional;
+import org.bukkit.block.sign.Side;
import org.bukkit.block.structure.Mirror;
import org.bukkit.block.structure.StructureRotation;
import org.bukkit.block.structure.UsageMode;
@@ -52,8 +54,8 @@
import org.bukkit.material.MaterialData;
import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionEffectType;
-import org.bukkit.util.Vector;
import org.bukkit.util.*;
+import org.bukkit.util.Vector;
import java.lang.ref.WeakReference;
import java.util.*;
@@ -1249,14 +1251,14 @@ public static void register() {
// @group world
// @description
// Returns a list of lines on a sign.
+ // For MC 1.20+, this returns the contents on the front of the sign.
+ // To get the contents on the back, see <@link tag LocationTag.sign_back_contents>.
// -->
tagProcessor.registerTag(ListTag.class, "sign_contents", (attribute, object) -> {
- if (object.getBlockStateForTag(attribute) instanceof Sign) {
- return new ListTag(Arrays.asList(PaperAPITools.instance.getSignLines(((Sign) object.getBlockStateForTag(attribute)))));
- }
- else {
- return null;
+ if (object.getBlockStateForTag(attribute) instanceof Sign sign) {
+ return new ListTag(PaperAPITools.instance.getSignLines(sign), true);
}
+ return null;
});
// <--[tag]
@@ -4156,14 +4158,15 @@ else if (material.hasModernData() && material.getModernData() instanceof org.buk
// @group world
// @description
// Returns whether the location is a Sign block that is glowing.
+ // For MC 1.20+, this returns the glowing status of the front of the sign.
+ // To get the glowing state of the back, see <@link tag LocationTag.sign_back_glowing>.
// -->
tagProcessor.registerTag(ElementTag.class, "sign_glowing", (attribute, object) -> {
- BlockState state = object.getBlockStateForTag(attribute);
- if (!(state instanceof Sign)) {
+ if (!(object.getBlockStateForTag(attribute) instanceof Sign sign)) {
attribute.echoError("Location is not a valid Sign block.");
return null;
}
- return new ElementTag(((Sign) state).isGlowingText());
+ return new ElementTag(SignCommand.SIGN_SIDES_SUPPORTED ? sign.getSide(Side.FRONT).isGlowingText() : sign.isGlowingText());
});
// <--[tag]
@@ -4172,16 +4175,17 @@ else if (material.hasModernData() && material.getModernData() instanceof org.buk
// @mechanism LocationTag.sign_glow_color
// @group world
// @description
- // Returns the name of the glow-color of the sign at the location.
+ // Returns the name of the glow color of the sign at the location.
+ // For MC 1.20+, this returns the color on the front of the sign.
+ // To get the color of the back, see <@link tag LocationTag.sign_back_glow_color>.
// See also <@link tag LocationTag.sign_glowing>
// -->
tagProcessor.registerTag(ElementTag.class, "sign_glow_color", (attribute, object) -> {
- BlockState state = object.getBlockStateForTag(attribute);
- if (!(state instanceof Sign)) {
+ if (!(object.getBlockStateForTag(attribute) instanceof Sign sign)) {
attribute.echoError("Location is not a valid Sign block.");
return null;
}
- return new ElementTag(((Sign) state).getColor());
+ return new ElementTag(SignCommand.SIGN_SIDES_SUPPORTED ? sign.getSide(Side.FRONT).getColor() : sign.getColor());
});
// <--[tag]
@@ -4507,6 +4511,193 @@ else if (material.hasModernData() && material.getModernData() instanceof org.buk
}
return new ElementTag(chiseledBookshelf.getSlot(input.toVector()) + 1);
});
+
+ // <--[tag]
+ // @attribute
+ // @returns ListTag
+ // @mechanism LocationTag.disabled_slots
+ // @group world
+ // @description
+ // Returns which slots in a crafter are disabled.
+ // The slots are arranged from left to right, top to bottom.
+ // -->
+ tagProcessor.registerTag(ListTag.class, "disabled_slots", (attribute, object) -> {
+ if (!(object.getBlockStateForTag(attribute) instanceof Crafter crafter)) {
+ attribute.echoError("The 'LocationTag.disabled_slots' tag can only be called on a crafter block.");
+ return null;
+ }
+ ListTag slots = new ListTag();
+ for (int i = 0; i <= 8; i++) {
+ if (crafter.isSlotDisabled(i)) {
+ slots.addObject(new ElementTag(i + 1));
+ }
+ }
+ return slots;
+ });
+
+ // <--[mechanism]
+ // @object LocationTag
+ // @name disabled_slots
+ // @input ListTag
+ // @description
+ // Sets which slots in a crafter are disabled.
+ // The slots are arranged from left to right, top to bottom.
+ // Provide no input to enable all slots.
+ // @tags
+ //
+ // @example
+ // # Disables the slots in the top left and middle right
+ // - adjustblock <[location]> disabled_slots:1|6
+ // -->
+ tagProcessor.registerMechanism("disabled_slots", false, ListTag.class, (object, mechanism, input) -> {
+ if (!(object.getBlockState() instanceof Crafter crafter)) {
+ mechanism.echoError("The 'LocationTag.disabled_slots' mechanism can only be called on a crafter block.");
+ return;
+ }
+ for (int i = 0; i <= 8; i++) {
+ crafter.setSlotDisabled(i, false);
+ }
+ for (String slot : input) {
+ ElementTag element = new ElementTag(slot);
+ if (!element.isInt()) {
+ mechanism.echoError("Invalid slot '" + slot + "' specified: must be an integer.");
+ continue;
+ }
+ int value = element.asInt();
+ if (value < 1 || value > 9) {
+ mechanism.echoError("Invalid slot '" + slot + "' specified: must between 1 and 9.");
+ continue;
+ }
+ crafter.setSlotDisabled(value - 1, true);
+ }
+ crafter.update();
+ });
+
+ // <--[tag]
+ // @attribute
+ // @returns ListTag
+ // @mechanism LocationTag.sign_back_contents
+ // @group world
+ // @description
+ // Returns the contents on the back of a sign block.
+ // For the contents on the front, see <@link tag LocationTag.sign_contents>.
+ // -->
+ tagProcessor.registerTag(ListTag.class, "sign_back_contents", (attribute, object) -> {
+ if (object.getBlockStateForTag(attribute) instanceof Sign sign) {
+ return new ListTag(PaperAPITools.instance.getSignBackLines(sign), true);
+ }
+ return null;
+ });
+
+ // <--[mechanism]
+ // @object LocationTag
+ // @name sign_back_contents
+ // @input ListTag
+ // @description
+ // Sets the contents on the back of a sign block.
+ // To set the contents of the front, see <@link mechanism LocationTag.sign_contents>.
+ // @tags
+ //
+ // -->
+ tagProcessor.registerMechanism("sign_back_contents", false, ListTag.class, (object, mechanism, input) -> {
+ if (!(object.getBlockState() instanceof Sign sign)) {
+ mechanism.echoError("This mechanism is only valid for Sign blocks.");
+ return;
+ }
+ for (int i = 0; i < 4; i++) {
+ PaperAPITools.instance.setSignBackLine(sign, i, "");
+ }
+ CoreUtilities.fixNewLinesToListSeparation(input);
+ if (input.size() > 4) {
+ mechanism.echoError("Sign can only hold four lines!");
+ }
+ else {
+ for (int i = 0; i < input.size(); i++) {
+ PaperAPITools.instance.setSignBackLine(sign, i, input.get(i));
+ }
+ }
+ sign.update();
+ });
+
+ // <--[tag]
+ // @attribute
+ // @returns ElementTag(Boolean)
+ // @mechanism LocationTag.sign_back_glowing
+ // @group world
+ // @description
+ // Returns whether the back of a Sign block at this location is glowing.
+ // To get the glowing state of the front, see <@link tag LocationTag.sign_glowing>.
+ // -->
+ tagProcessor.registerTag(ElementTag.class, "sign_back_glowing", (attribute, object) -> {
+ if (!(object.getBlockStateForTag(attribute) instanceof Sign sign)) {
+ attribute.echoError("Location is not a valid Sign block.");
+ return null;
+ }
+ return new ElementTag(sign.getSide(Side.BACK).isGlowingText());
+ });
+
+ // <--[mechanism]
+ // @object LocationTag
+ // @name sign_back_glowing
+ // @input ElementTag(Boolean)
+ // @description
+ // Changes whether the back of the sign at the location is glowing.
+ // To set the glowing state of the front, see <@link mechanism LocationTag.sign_glowing>.
+ // @tags
+ //
+ //
+ // -->
+ tagProcessor.registerMechanism("sign_back_glowing", false, ElementTag.class, (object, mechanism, input) -> {
+ if (!(object.getBlockState() instanceof Sign sign)) {
+ mechanism.echoError("This mechanism can only be called on Sign blocks.");
+ }
+ else if (mechanism.requireBoolean()) {
+ sign.getSide(Side.BACK).setGlowingText(input.asBoolean());
+ sign.update();
+ }
+ });
+
+ // <--[tag]
+ // @attribute
+ // @returns ElementTag
+ // @mechanism LocationTag.sign_back_glow_color
+ // @group world
+ // @description
+ // Returns the name of the glow color on the back of the sign at the location.
+ // To get the color of the front, see <@link tag LocationTag.sign_glow_color>.
+ // See also <@link tag LocationTag.sign_back_glowing>.
+ // -->
+ tagProcessor.registerTag(ElementTag.class, "sign_back_glow_color", (attribute, object) -> {
+ if (!(object.getBlockStateForTag(attribute) instanceof Sign sign)) {
+ attribute.echoError("Location is not a valid Sign block.");
+ return null;
+ }
+ return new ElementTag(sign.getSide(Side.BACK).getColor());
+ });
+
+ // <--[mechanism]
+ // @object LocationTag
+ // @name sign_back_glow_color
+ // @input ElementTag
+ // @description
+ // Changes the glow color on the back of a sign.
+ // For the list of possible colors, see <@link url https://hub.spigotmc.org/javadocs/spigot/org/bukkit/DyeColor.html>.
+ // Use <@link mechanism LocationTag.sign_back_glowing> to toggle whether the sign is glowing.
+ // If a sign is not glowing, this is equivalent to applying a chat color to the sign.
+ // To set the color of the front, see <@link mechanism LocationTag.sign_glow_color>.
+ // @tags
+ //
+ //
+ // -->
+ tagProcessor.registerMechanism("sign_back_glow_color", false, ElementTag.class, (object, mechanism, input) -> {
+ if (!(object.getBlockState() instanceof Sign sign)) {
+ mechanism.echoError("This mechanism can only be called on Sign blocks.");
+ }
+ else if (mechanism.requireEnum(DyeColor.class)) {
+ sign.getSide(Side.BACK).setColor(input.asEnum(DyeColor.class));
+ sign.update();
+ }
+ });
}
// <--[mechanism]
@@ -4574,9 +4765,101 @@ else if (mechanism.requireObject(EntityTag.class)) {
mechanism.echoError("The 'LocationTag.page' mechanism can only be called on a lectern block.");
}
});
+
+ // <--[mechanism]
+ // @object LocationTag
+ // @name sign_contents
+ // @input ListTag
+ // @description
+ // Sets the contents of a sign block.
+ // For MC 1.20+, this sets the contents on the front of the sign.
+ // To set the contents of the back, see <@link mechanism LocationTag.sign_back_contents>.
+ // @tags
+ //
+ // -->
+ tagProcessor.registerMechanism("sign_contents", false, ListTag.class, (object, mechanism, value) -> {
+ if (!(object.getBlockState() instanceof Sign sign)) {
+ mechanism.echoError("This mechanism is only valid for Sign blocks.");
+ return;
+ }
+ for (int i = 0; i < 4; i++) {
+ PaperAPITools.instance.setSignLine(sign, i, "");
+ }
+ CoreUtilities.fixNewLinesToListSeparation(value);
+ if (value.size() > 4) {
+ mechanism.echoError("Sign can only hold four lines!");
+ }
+ else {
+ for (int i = 0; i < value.size(); i++) {
+ PaperAPITools.instance.setSignLine(sign, i, value.get(i));
+ }
+ }
+ sign.update();
+ });
+
+ // <--[mechanism]
+ // @object LocationTag
+ // @name sign_glowing
+ // @input ElementTag(Boolean)
+ // @description
+ // Changes whether the sign at the location is glowing.
+ // For MC 1.20+, this sets the glowing status on the front of the sign.
+ // To set the glowing status of the back, see <@link mechanism LocationTag.sign_back_glowing>.
+ // @tags
+ //
+ //
+ // -->
+ tagProcessor.registerMechanism("sign_glowing", false, ElementTag.class, (object, mechanism, input) -> {
+ if (!mechanism.requireBoolean()) {
+ return;
+ }
+ if (!(object.getBlockState() instanceof Sign sign)) {
+ mechanism.echoError("This mechanism can only be called on Sign blocks.");
+ return;
+ }
+ if (SignCommand.SIGN_SIDES_SUPPORTED) {
+ sign.getSide(Side.FRONT).setGlowingText(input.asBoolean());
+ }
+ else {
+ sign.setGlowingText(input.asBoolean());
+ }
+ sign.update();
+ });
+
+ // <--[mechanism]
+ // @object LocationTag
+ // @name sign_glow_color
+ // @input ElementTag
+ // @description
+ // Changes the glow color of a sign.
+ // For the list of possible colors, see <@link url https://hub.spigotmc.org/javadocs/spigot/org/bukkit/DyeColor.html>.
+ // If a sign is not glowing, this is equivalent to applying a chat color to the sign.
+ // Use <@link mechanism LocationTag.sign_glowing> to toggle whether the sign is glowing.
+ // For MC 1.20+, this sets the color on the front of the sign.
+ // To set the color of the back, see <@link mechanism LocationTag.sign_back_glow_color>.
+ // @tags
+ //
+ //
+ // -->
+ tagProcessor.registerMechanism("sign_glow_color", false, ElementTag.class, (object, mechanism, input) -> {
+ if (!mechanism.requireEnum(DyeColor.class)) {
+ return;
+ }
+ if (!(object.getBlockState() instanceof Sign sign)) {
+ mechanism.echoError("This mechanism can only be called on Sign blocks.");
+ return;
+ }
+ if (SignCommand.SIGN_SIDES_SUPPORTED) {
+ sign.getSide(Side.FRONT).setColor(input.asEnum(DyeColor.class));
+ }
+ else {
+ sign.setColor(input.asEnum(DyeColor.class));
+ }
+ sign.update();
+ });
}
- public static final ObjectTagProcessor tagProcessor = new ObjectTagProcessor<>();
+ public static ObjectTagProcessor tagProcessor = new ObjectTagProcessor<>();
@Override
public ObjectTag getObjectAttribute(Attribute attribute) {
@@ -4769,33 +5052,6 @@ public void adjust(Mechanism mechanism) {
state.update();
}
- // <--[mechanism]
- // @object LocationTag
- // @name sign_contents
- // @input ListTag
- // @description
- // Sets the contents of a sign block.
- // @tags
- //
- // -->
- if (mechanism.matches("sign_contents") && getBlockState() instanceof Sign) {
- Sign state = (Sign) getBlockState();
- for (int i = 0; i < 4; i++) {
- PaperAPITools.instance.setSignLine(state, i, "");
- }
- ListTag list = mechanism.valueAsType(ListTag.class);
- CoreUtilities.fixNewLinesToListSeparation(list);
- if (list.size() > 4) {
- mechanism.echoError("Sign can only hold four lines!");
- }
- else {
- for (int i = 0; i < list.size(); i++) {
- PaperAPITools.instance.setSignLine(state, i, list.get(i));
- }
- }
- state.update();
- }
-
// <--[mechanism]
// @object LocationTag
// @name skull_skin
@@ -5442,53 +5698,6 @@ else if (state instanceof Dropper) {
}
}
- // <--[mechanism]
- // @object LocationTag
- // @name sign_glowing
- // @input ElementTag(Boolean)
- // @description
- // Changes whether the sign at the location is glowing.
- // @tags
- //
- //
- // -->
- if (mechanism.matches("sign_glowing") && mechanism.requireBoolean()) {
- BlockState state = getBlockState();
- if (!(state instanceof Sign)) {
- mechanism.echoError("'sign_glowing' mechanism can only be called on Sign blocks.");
- }
- else {
- Sign sign = (Sign) state;
- sign.setGlowingText(mechanism.getValue().asBoolean());
- sign.update();
- }
- }
-
- // <--[mechanism]
- // @object LocationTag
- // @name sign_glow_color
- // @input ElementTag
- // @description
- // Changes the glow color of a sign.
- // For the list of possible colors, see <@link url https://hub.spigotmc.org/javadocs/spigot/org/bukkit/DyeColor.html>.
- // If a sign is not glowing, this is equivalent to applying a chat color to the sign.
- // Use <@link mechanism LocationTag.sign_glowing> to toggle whether the sign is glowing.
- // @tags
- //
- //
- // -->
- if (mechanism.matches("sign_glow_color") && mechanism.requireEnum(DyeColor.class)) {
- BlockState state = getBlockState();
- if (!(state instanceof Sign)) {
- mechanism.echoError("'sign_glow_color' mechanism can only be called on Sign blocks.");
- }
- else {
- Sign sign = (Sign) state;
- sign.setColor(mechanism.getValue().asEnum(DyeColor.class));
- sign.update();
- }
- }
-
// <--[mechanism]
// @object LocationTag
// @name structure_block_data
diff --git a/plugin/src/main/java/com/denizenscript/denizen/objects/NPCTag.java b/plugin/src/main/java/com/denizenscript/denizen/objects/NPCTag.java
index a99fa9ec70..74e6bc5e56 100644
--- a/plugin/src/main/java/com/denizenscript/denizen/objects/NPCTag.java
+++ b/plugin/src/main/java/com/denizenscript/denizen/objects/NPCTag.java
@@ -501,7 +501,7 @@ public static void register() {
// -->
tagProcessor.registerTag(ElementTag.class, "nickname", (attribute, object) -> {
return new ElementTag(object.getCitizen().hasTrait(NicknameTrait.class) ? object.getCitizen().getOrAddTrait(NicknameTrait.class)
- .getNickname() : object.getName());
+ .getNickname() : object.getName(), true);
});
// Documented in EntityTag
@@ -510,16 +510,16 @@ public static void register() {
BukkitImplDeprecations.npcNicknameTag.warn(attribute.context);
attribute.fulfill(1);
return new ElementTag(object.getCitizen().hasTrait(NicknameTrait.class) ? object.getCitizen().getOrAddTrait(NicknameTrait.class)
- .getNickname() : object.getName());
+ .getNickname() : object.getName(), true);
}
- return new ElementTag(object.getName());
+ return new ElementTag(object.getName(), true);
});
// <--[tag]
// @attribute
// @returns ListTag
// @description
- // Returns a list of all of the NPC's traits.
+ // Returns a list of all the NPC's traits.
// -->
tagProcessor.registerTag(ListTag.class, "traits", (attribute, object) -> {
List list = new ArrayList<>();
@@ -535,14 +535,9 @@ public static void register() {
// @description
// Returns whether the NPC has a specified trait.
// -->
- tagProcessor.registerTag(ElementTag.class, "has_trait", (attribute, object) -> {
- if (attribute.hasParam()) {
- Class extends Trait> trait = CitizensAPI.getTraitFactory().getTraitClass(attribute.getParam());
- if (trait != null) {
- return new ElementTag(object.getCitizen().hasTrait(trait));
- }
- }
- return null;
+ tagProcessor.registerTag(ElementTag.class, ElementTag.class, "has_trait", (attribute, object, param) -> {
+ Class extends Trait> trait = CitizensAPI.getTraitFactory().getTraitClass(param.asString());
+ return trait != null ? new ElementTag(object.getCitizen().hasTrait(trait)) : null;
});
// <--[tag]
@@ -561,15 +556,12 @@ public static void register() {
// @description
// Returns whether the NPC has a specified trigger.
// -->
- tagProcessor.registerTag(ElementTag.class, "has_trigger", (attribute, object) -> {
- if (!attribute.hasParam()) {
- return null;
- }
+ tagProcessor.registerTag(ElementTag.class, ElementTag.class, "has_trigger", (attribute, object, param) -> {
if (!object.getCitizen().hasTrait(TriggerTrait.class)) {
return new ElementTag(false);
}
TriggerTrait trait = object.getCitizen().getOrAddTrait(TriggerTrait.class);
- return new ElementTag(trait.hasTrigger(attribute.getParam()));
+ return new ElementTag(trait.hasTrigger(param.asString()));
});
// <--[tag]
@@ -579,7 +571,7 @@ public static void register() {
// Returns whether the NPC has anchors assigned.
// -->
tagProcessor.registerTag(ElementTag.class, "has_anchors", (attribute, object) -> {
- return (new ElementTag(object.getCitizen().getOrAddTrait(Anchors.class).getAnchors().size() > 0));
+ return new ElementTag(!object.getCitizen().getOrAddTrait(Anchors.class).getAnchors().isEmpty());
});
// <--[tag]
@@ -589,11 +581,7 @@ public static void register() {
// Returns a list of anchor names currently assigned to the NPC.
// -->
tagProcessor.registerTag(ListTag.class, "list_anchors", (attribute, object) -> {
- ListTag list = new ListTag();
- for (Anchor anchor : object.getCitizen().getOrAddTrait(Anchors.class).getAnchors()) {
- list.add(anchor.getName());
- }
- return list;
+ return new ListTag(object.getCitizen().getOrAddTrait(Anchors.class).getAnchors(), anchor -> new ElementTag(anchor.getName(), true));
});
// <--[tag]
@@ -606,22 +594,18 @@ public static void register() {
Anchors trait = object.getCitizen().getOrAddTrait(Anchors.class);
if (attribute.hasParam()) {
Anchor anchor = trait.getAnchor(attribute.getParam());
- if (anchor != null) {
- return new LocationTag(anchor.getLocation());
- }
- else {
- attribute.echoError("NPC Anchor '" + attribute.getParam() + "' is not defined.");
- return null;
- }
+ if (anchor != null) {
+ return new LocationTag(anchor.getLocation());
+ }
+ else {
+ attribute.echoError("NPC Anchor '" + attribute.getParam() + "' is not defined.");
+ return null;
+ }
}
else if (attribute.startsWith("list", 2)) {
attribute.fulfill(1);
BukkitImplDeprecations.npcAnchorListTag.warn(attribute.context);
- ListTag list = new ListTag();
- for (Anchor anchor : trait.getAnchors()) {
- list.add(anchor.getName());
- }
- return list;
+ return new ListTag(trait.getAnchors(), anchor -> new ElementTag(anchor.getName(), true));
}
else {
attribute.echoError("npc.anchor[...] tag must have an input.");
@@ -635,18 +619,14 @@ else if (attribute.startsWith("list", 2)) {
// @description
// Returns the specified constant from the NPC.
// -->
- tagProcessor.registerTag(ElementTag.class, "constant", (attribute, object) -> {
- if (attribute.hasParam()) {
- if (object.getCitizen().hasTrait(ConstantsTrait.class)
- && object.getCitizen().getOrAddTrait(ConstantsTrait.class).getConstant(attribute.getParam()) != null) {
- return new ElementTag(object.getCitizen().getOrAddTrait(ConstantsTrait.class)
- .getConstant(attribute.getParam()));
- }
- else {
- return null;
- }
+ tagProcessor.registerTag(ElementTag.class, ElementTag.class, "constant", (attribute, object, param) -> {
+ if (object.getCitizen().hasTrait(ConstantsTrait.class)
+ && object.getCitizen().getOrAddTrait(ConstantsTrait.class).getConstant(param.asString()) != null) {
+ return new ElementTag(object.getCitizen().getOrAddTrait(ConstantsTrait.class).getConstant(param.asString()), true);
+ }
+ else {
+ return null;
}
- return null;
});
// <--[tag]
@@ -655,13 +635,8 @@ else if (attribute.startsWith("list", 2)) {
// @description
// Returns true if the NPC has the specified pose, otherwise returns false.
// -->
- tagProcessor.registerTag(ElementTag.class, "has_pose", (attribute, object) -> {
- if (attribute.hasParam()) {
- return new ElementTag(object.getCitizen().getOrAddTrait(Poses.class).hasPose(attribute.getParam()));
- }
- else {
- return null;
- }
+ tagProcessor.registerTag(ElementTag.class, ElementTag.class, "has_pose", (attribute, object, param) -> {
+ return new ElementTag(object.getCitizen().getOrAddTrait(Poses.class).hasPose(param.asString()));
});
// <--[tag]
@@ -671,14 +646,9 @@ else if (attribute.startsWith("list", 2)) {
// Returns the pose as a LocationTag with x, y, and z set to 0, and the world set to the first
// possible available world Bukkit knows about.
// -->
- tagProcessor.registerTag(LocationTag.class, "pose", (attribute, object) -> {
- if (attribute.hasParam()) {
- Pose pose = object.getCitizen().getOrAddTrait(Poses.class).getPose(attribute.getParam());
- return new LocationTag(org.bukkit.Bukkit.getWorlds().get(0), 0, 0, 0, pose.getYaw(), pose.getPitch());
- }
- else {
- return null;
- }
+ tagProcessor.registerTag(LocationTag.class, ElementTag.class, "pose", (attribute, object, param) -> {
+ Pose pose = object.getCitizen().getOrAddTrait(Poses.class).getPose(param.asString());
+ return new LocationTag(Bukkit.getWorlds().get(0), 0, 0, 0, pose.getYaw(), pose.getPitch());
}, "get_pose");
// <--[tag]
@@ -716,11 +686,7 @@ else if (attribute.startsWith("list", 2)) {
if (stands == null || stands.isEmpty()) {
return null;
}
- ListTag output = new ListTag();
- for (Entity stand : stands) {
- output.addObject(new EntityTag(stand).getDenizenObject());
- }
- return output;
+ return new ListTag(stands, stand -> new EntityTag(stand).getDenizenObject());
});
// <--[tag]
@@ -865,7 +831,7 @@ else if (attribute.startsWith("list", 2)) {
if (skin.getSignature() != null) {
sign = ";" + skin.getSignature();
}
- return new ElementTag(tex + sign);
+ return new ElementTag(tex + sign, true);
}
return null;
});
@@ -883,7 +849,7 @@ else if (attribute.startsWith("list", 2)) {
return null;
}
SkinTrait skin = object.getCitizen().getOrAddTrait(SkinTrait.class);
- return new ElementTag(skin.getSkinName() + "|" + skin.getTexture());
+ return new ElementTag(skin.getSkinName() + "|" + skin.getTexture(), true);
});
// <--[tag]
@@ -895,7 +861,7 @@ else if (attribute.startsWith("list", 2)) {
// -->
tagProcessor.registerTag(ElementTag.class, "skin", (attribute, object) -> {
if (object.getCitizen().hasTrait(SkinTrait.class)) {
- return new ElementTag(object.getCitizen().getOrAddTrait(SkinTrait.class).getSkinName());
+ return new ElementTag(object.getCitizen().getOrAddTrait(SkinTrait.class).getSkinName(), true);
}
return null;
});
@@ -1044,13 +1010,7 @@ else if (attribute.startsWith("list", 2)) {
return null;
}
else {
- ListTag result = new ListTag();
- for (AssignmentScriptContainer container : citizen.getOrAddTrait(AssignmentTrait.class).containerCache) {
- if (container != null) {
- result.addObject(new ScriptTag(container));
- }
- }
- return result;
+ return new ListTag(citizen.getOrAddTrait(AssignmentTrait.class).containerCache, Objects::nonNull, ScriptTag::new);
}
});
@@ -1139,7 +1099,7 @@ else if (attribute.startsWith("list", 2)) {
// Not related to Sentinel combat.
// -->
tagProcessor.registerTag(ElementTag.class, "attack_strategy", (attribute, object) -> {
- return new ElementTag(object.getNavigator().getLocalParameters().attackStrategy().toString());
+ return new ElementTag(object.getNavigator().getLocalParameters().attackStrategy().toString(), true);
});
// <--[tag]
@@ -1224,7 +1184,7 @@ else if (attribute.startsWith("list", 2)) {
if (object.getNavigator().getTargetType() == null) {
return null;
}
- return new ElementTag(object.getNavigator().getTargetType().toString());
+ return new ElementTag(object.getNavigator().getTargetType().toString(), true);
});
// <--[tag]
@@ -1247,7 +1207,7 @@ else if (attribute.startsWith("list", 2)) {
// Returns the name of the registry this NPC came from.
// -->
tagProcessor.registerTag(ElementTag.class, "registry_name", (attribute, object) -> {
- return new ElementTag(object.getCitizen().getOwningRegistry().getName());
+ return new ElementTag(object.getCitizen().getOwningRegistry().getName(), true);
});
// <--[tag]
@@ -1256,15 +1216,9 @@ else if (attribute.startsWith("list", 2)) {
// @description
// Returns the value of a Citizens NPC metadata key.
// -->
- tagProcessor.registerTag(ElementTag.class, "citizens_data", (attribute, object) -> {
- if (!attribute.hasParam()) {
- return null;
- }
- Object val = object.getCitizen().data().get(attribute.getParam());
- if (val == null) {
- return null;
- }
- return new ElementTag(val.toString());
+ tagProcessor.registerTag(ElementTag.class, ElementTag.class, "citizens_data", (attribute, object, param) -> {
+ Object val = object.getCitizen().data().get(param.asString());
+ return val != null ? new ElementTag(val.toString(), true) : null;
});
// <--[tag]
@@ -1343,6 +1297,16 @@ else if (attribute.startsWith("list", 2)) {
return null;
});
+ // <--[tag]
+ // @attribute ]>
+ // @returns ElementTag(Boolean)
+ // @description
+ // Returns whether an NPC can navigate to a specified location.
+ // -->
+ tagProcessor.registerTag(ElementTag.class, LocationTag.class, "can_navigate_to", (attribute, object, param) -> {
+ return new ElementTag(object.getCitizen().getNavigator().canNavigateTo(param));
+ });
+
// <--[mechanism]
// @object NPCTag
// @name hologram_lines
@@ -1454,29 +1418,6 @@ else if (attribute.startsWith("list", 2)) {
mechanism.echoError("Must set waypoint_provider to 'wander' before setting wander_yrange!");
}
});
- }
-
- public static ObjectTagProcessor tagProcessor = new ObjectTagProcessor<>();
-
- @Override
- public ObjectTag getObjectAttribute(Attribute attribute) {
- return tagProcessor.getObjectAttribute(this, attribute);
- }
-
- @Override
- public ObjectTag getNextObjectTypeDown() {
- if (getEntity() != null) {
- return new EntityTag(this);
- }
- return new ElementTag(identify());
- }
-
- public void applyProperty(Mechanism mechanism) {
- mechanism.echoError("Cannot apply properties to an NPC!");
- }
-
- @Override
- public void adjust(Mechanism mechanism) {
// TODO: For all the mechanism tags, add the @Mechanism link!
@@ -1489,11 +1430,11 @@ public void adjust(Mechanism mechanism) {
// @tags
//
// -->
- if (mechanism.matches("set_assignment") && mechanism.requireObject(ScriptTag.class)) {
- AssignmentTrait trait = getCitizen().getOrAddTrait(AssignmentTrait.class);
+ tagProcessor.registerMechanism("set_assignment", false, ScriptTag.class, (object, mechanism, input) -> {
+ AssignmentTrait trait = object.getCitizen().getOrAddTrait(AssignmentTrait.class);
trait.clearAssignments(null);
- trait.addAssignmentScript((AssignmentScriptContainer) mechanism.valueAsType(ScriptTag.class).getContainer(), null);
- }
+ trait.addAssignmentScript((AssignmentScriptContainer) input.getContainer(), null);
+ });
// <--[mechanism]
// @object NPCTag
@@ -1504,9 +1445,9 @@ public void adjust(Mechanism mechanism) {
// @tags
//
// -->
- if (mechanism.matches("add_assignment") && mechanism.requireObject(ScriptTag.class)) {
- getCitizen().getOrAddTrait(AssignmentTrait.class).addAssignmentScript((AssignmentScriptContainer) mechanism.valueAsType(ScriptTag.class).getContainer(), null);
- }
+ tagProcessor.registerMechanism("add_assignment", false, ScriptTag.class, (object, mechanism, input) -> {
+ object.getCitizen().getOrAddTrait(AssignmentTrait.class).addAssignmentScript((AssignmentScriptContainer) input.getContainer(), null);
+ });
// <--[mechanism]
// @object NPCTag
@@ -1517,20 +1458,21 @@ public void adjust(Mechanism mechanism) {
// @tags
//
// -->
- if (mechanism.matches("remove_assignment")) {
- if (npc.hasTrait(AssignmentTrait.class)) {
- if (mechanism.hasValue()) {
- AssignmentTrait trait = getCitizen().getOrAddTrait(AssignmentTrait.class);
- trait.removeAssignmentScript(mechanism.getValue().asString(), null);
- trait.checkAutoRemove();
- }
- else {
- BukkitImplDeprecations.assignmentRemove.warn(mechanism.context);
- getCitizen().getOrAddTrait(AssignmentTrait.class).clearAssignments(null);
- npc.removeTrait(AssignmentTrait.class);
- }
+ tagProcessor.registerMechanism("remove_assignment", false, (object, mechanism) -> {
+ if (!object.getCitizen().hasTrait(AssignmentTrait.class)) {
+ return;
}
- }
+ if (mechanism.hasValue()) {
+ AssignmentTrait trait = object.getCitizen().getOrAddTrait(AssignmentTrait.class);
+ trait.removeAssignmentScript(mechanism.getValue().asString(), null);
+ trait.checkAutoRemove();
+ }
+ else {
+ BukkitImplDeprecations.assignmentRemove.warn(mechanism.context);
+ object.getCitizen().getOrAddTrait(AssignmentTrait.class).clearAssignments(null);
+ object.getCitizen().removeTrait(AssignmentTrait.class);
+ }
+ });
// <--[mechanism]
// @object NPCTag
@@ -1541,12 +1483,12 @@ public void adjust(Mechanism mechanism) {
// @tags
//
// -->
- if (mechanism.matches("clear_assignments")) {
- if (npc.hasTrait(AssignmentTrait.class)) {
- getCitizen().getOrAddTrait(AssignmentTrait.class).clearAssignments(null);
- npc.removeTrait(AssignmentTrait.class);
+ tagProcessor.registerMechanism("clear_assignments", false, (object, mechanism) -> {
+ if (object.getCitizen().hasTrait(AssignmentTrait.class)) {
+ object.getCitizen().getOrAddTrait(AssignmentTrait.class).clearAssignments(null);
+ object.getCitizen().removeTrait(AssignmentTrait.class);
}
- }
+ });
// <--[mechanism]
// @object NPCTag
@@ -1558,11 +1500,13 @@ public void adjust(Mechanism mechanism) {
// @tags
//
// -->
- if (mechanism.matches("hologram_direction")) { // && mechanism.requireEnum(HologramTrait.HologramDirection.class)
+ tagProcessor.registerMechanism("hologram_direction", false, (object, mechanism) -> {
+ //if (mechanism.requireEnum(HologramTrait.HologramDirection.class)) {
+ //HologramTrait hologram = object.getCitizen().getOrAddTrait(HologramTrait.class);
+ //hologram.setDirection(HologramTrait.HologramDirection.valueOf(param.asString().toUpperCase()));
+ //}
BukkitImplDeprecations.npcHologramDirection.warn(mechanism.context);
- //HologramTrait hologram = getCitizen().getOrAddTrait(HologramTrait.class);
- //hologram.setDirection(HologramTrait.HologramDirection.valueOf(mechanism.getValue().asString().toUpperCase()));
- }
+ });
// <--[mechanism]
// @object NPCTag
@@ -1573,10 +1517,11 @@ public void adjust(Mechanism mechanism) {
// @tags
//
// -->
- if (mechanism.matches("hologram_line_height") && mechanism.requireDouble()) {
- HologramTrait hologram = getCitizen().getOrAddTrait(HologramTrait.class);
- hologram.setLineHeight(mechanism.getValue().asDouble());
- }
+ tagProcessor.registerMechanism("hologram_line_height", false, ElementTag.class, (object, mechanism, input) -> {
+ if (mechanism.requireDouble()) {
+ object.getCitizen().getOrAddTrait(HologramTrait.class).setLineHeight(input.asDouble());
+ }
+ });
// <--[mechanism]
// @object NPCTag
@@ -1587,9 +1532,9 @@ public void adjust(Mechanism mechanism) {
// @tags
//
// -->
- if (mechanism.matches("set_nickname")) {
- getNicknameTrait().setNickname(mechanism.getValue().asString());
- }
+ tagProcessor.registerMechanism("set_nickname", false, ElementTag.class, (object, mechanism, input) -> {
+ object.getNicknameTrait().setNickname(input.asString());
+ });
// <--[mechanism]
// @object NPCTag
@@ -1600,9 +1545,9 @@ public void adjust(Mechanism mechanism) {
// @tags
//
// -->
- if (mechanism.matches("remove_nickname")) {
- getNicknameTrait().removeNickname();
- }
+ tagProcessor.registerMechanism("remove_nickname", false, (object, mechanism) -> {
+ object.getNicknameTrait().removeNickname();
+ });
// <--[mechanism]
// @object NPCTag
@@ -1613,9 +1558,9 @@ public void adjust(Mechanism mechanism) {
// @tags
//
// -->
- if (mechanism.matches("set_entity_type") && mechanism.requireObject(EntityTag.class)) {
- getCitizen().setBukkitEntityType(mechanism.valueAsType(EntityTag.class).getBukkitEntityType());
- }
+ tagProcessor.registerMechanism("set_entity_type", false, EntityTag.class, (object, mechanism, input) -> {
+ object.getCitizen().setBukkitEntityType(input.getBukkitEntityType());
+ });
// <--[mechanism]
// @object NPCTag
@@ -1626,27 +1571,22 @@ public void adjust(Mechanism mechanism) {
// @tags
//
// -->
- if (mechanism.matches("name") || mechanism.matches("set_name")) {
- getCitizen().setName(mechanism.getValue().asString().length() > 256 ? mechanism.getValue().asString().substring(0, 256) : mechanism.getValue().asString());
- }
+ tagProcessor.registerMechanism("name", false, ElementTag.class, (object, mechanism, input) -> {
+ object.getCitizen().setName(input.asString().length() > 256 ? input.asString().substring(0, 256) : input.asString());
+ }, "set_name");
// <--[mechanism]
// @object NPCTag
// @name owner
// @input PlayerTag
// @description
- // Sets the owner of the NPC.
+ // Sets the owner of the NPC. Provide no input to set the server as the owner.
// @tags
//
// -->
- if (mechanism.matches("owner")) {
- if (PlayerTag.matches(mechanism.getValue().asString())) {
- getCitizen().getOrAddTrait(Owner.class).setOwner(mechanism.valueAsType(PlayerTag.class).getPlayerEntity());
- }
- else {
- getCitizen().getOrAddTrait(Owner.class).setOwner(mechanism.getValue().asString());
- }
- }
+ tagProcessor.registerMechanism("owner", false, (object, mechanism) -> {
+ object.getCitizen().getOrAddTrait(Owner.class).setOwner(mechanism.getValue().canBeType(PlayerTag.class) ? mechanism.valueAsType(PlayerTag.class).getUUID() : null);
+ });
// <--[mechanism]
// @object NPCTag
@@ -1659,29 +1599,29 @@ public void adjust(Mechanism mechanism) {
// @tags
//
// -->
- if (mechanism.matches("skin_blob")) {
+ tagProcessor.registerMechanism("skin_blob", false, (object, mechanism) -> {
if (!mechanism.hasValue()) {
- if (getCitizen().hasTrait(SkinTrait.class)) {
- getCitizen().getOrAddTrait(SkinTrait.class).clearTexture();
- if (getCitizen().isSpawned()) {
- getCitizen().despawn(DespawnReason.PENDING_RESPAWN);
- getCitizen().spawn(getCitizen().getStoredLocation());
+ if (object.getCitizen().hasTrait(SkinTrait.class)) {
+ object.getCitizen().getOrAddTrait(SkinTrait.class).clearTexture();
+ if (object.getCitizen().isSpawned()) {
+ object.getCitizen().despawn(DespawnReason.PENDING_RESPAWN);
+ object.getCitizen().spawn(object.getCitizen().getStoredLocation());
}
}
}
else {
- SkinTrait skinTrait = getCitizen().getOrAddTrait(SkinTrait.class);
+ SkinTrait skinTrait = object.getCitizen().getOrAddTrait(SkinTrait.class);
String[] dat = mechanism.getValue().asString().split(";");
if (dat.length < 2) {
Debug.echoError("Invalid skin_blob input. Must specify texture;signature;name in full.");
return;
}
skinTrait.setSkinPersistent(dat.length > 2 ? dat[2] : UUID.randomUUID().toString(), dat[1], dat[0]);
- if (getCitizen().isSpawned() && getCitizen().getEntity() instanceof SkinnableEntity) {
- ((SkinnableEntity) getCitizen().getEntity()).getSkinTracker().notifySkinChange(true);
+ if (object.getCitizen().isSpawned() && object.getCitizen().getEntity() instanceof SkinnableEntity skinnable) {
+ skinnable.getSkinTracker().notifySkinChange(true);
}
}
- }
+ });
// <--[mechanism]
// @object NPCTag
@@ -1694,21 +1634,21 @@ public void adjust(Mechanism mechanism) {
// @tags
//
// -->
- if (mechanism.matches("skin")) {
+ tagProcessor.registerMechanism("skin", false, (object, mechanism) -> {
if (!mechanism.hasValue()) {
- if (getCitizen().hasTrait(SkinTrait.class)) {
- getCitizen().getOrAddTrait(SkinTrait.class).clearTexture();
+ if (object.getCitizen().hasTrait(SkinTrait.class)) {
+ object.getCitizen().getOrAddTrait(SkinTrait.class).clearTexture();
}
}
else {
- SkinTrait skinTrait = getCitizen().getOrAddTrait(SkinTrait.class);
+ SkinTrait skinTrait = object.getCitizen().getOrAddTrait(SkinTrait.class);
skinTrait.setSkinName(mechanism.getValue().asString());
}
- if (getCitizen().isSpawned()) {
- getCitizen().despawn(DespawnReason.PENDING_RESPAWN);
- getCitizen().spawn(getCitizen().getStoredLocation());
+ if (object.getCitizen().isSpawned()) {
+ object.getCitizen().despawn(DespawnReason.PENDING_RESPAWN);
+ object.getCitizen().spawn(object.getCitizen().getStoredLocation());
}
- }
+ });
// <--[mechanism]
// @object NPCTag
@@ -1720,9 +1660,11 @@ public void adjust(Mechanism mechanism) {
// @tags
//
// -->
- if (mechanism.matches("auto_update_skin") && mechanism.requireBoolean()) {
- getCitizen().getOrAddTrait(SkinTrait.class).setShouldUpdateSkins(mechanism.getValue().asBoolean());
- }
+ tagProcessor.registerMechanism("auto_update_skin", false, ElementTag.class, (object, mechanism, input) -> {
+ if (mechanism.requireBoolean()) {
+ object.getCitizen().getOrAddTrait(SkinTrait.class).setShouldUpdateSkins(input.asBoolean());
+ }
+ });
// <--[mechanism]
// @object NPCTag
@@ -1731,10 +1673,10 @@ public void adjust(Mechanism mechanism) {
// @description
// Sets the item type of the item.
// -->
- if (mechanism.matches("item_type") && mechanism.requireObject(ItemTag.class)) {
- ItemTag item = mechanism.valueAsType(ItemTag.class);
- Material mat = item.getMaterial().getMaterial();
- Entity npcEntity = getEntity();
+ tagProcessor.registerMechanism("item_type", false, ItemTag.class, (object, mechanism, input) -> {
+ Material mat = input.getBukkitMaterial();
+ Entity npcEntity = object.getEntity();
+ NPC citizen = object.getCitizen();
if (npcEntity instanceof Item droppedItem) {
droppedItem.getItemStack().setType(mat);
}
@@ -1742,27 +1684,27 @@ else if (npcEntity instanceof ItemFrame itemFrame) {
itemFrame.getItem().setType(mat);
}
else if (npcEntity instanceof FallingBlock) {
- getCitizen().data().setPersistent(NPC.Metadata.ITEM_ID, mat.name());
- getCitizen().data().setPersistent(NPC.Metadata.ITEM_DATA, 0);
+ citizen.data().setPersistent(NPC.Metadata.ITEM_ID, mat.name());
+ citizen.data().setPersistent(NPC.Metadata.ITEM_DATA, 0);
}
else {
Debug.echoError("NPC is the not an item type!");
}
- if (getCitizen().isSpawned()) {
- getCitizen().despawn();
- getCitizen().spawn(getCitizen().getStoredLocation());
+ if (citizen.isSpawned()) {
+ citizen.despawn();
+ citizen.spawn(citizen.getStoredLocation());
}
- }
+ });
- if (mechanism.matches("spawn")) {
+ tagProcessor.registerMechanism("spawn", false, (object, mechanism) -> {
BukkitImplDeprecations.npcSpawnMechanism.warn(mechanism.context);
if (mechanism.requireObject("Invalid LocationTag specified. Assuming last known NPC location.", LocationTag.class)) {
- getCitizen().spawn(mechanism.valueAsType(LocationTag.class));
+ object.getCitizen().spawn(mechanism.valueAsType(LocationTag.class));
}
else {
- getCitizen().spawn(getCitizen().getStoredLocation());
+ object.getCitizen().spawn(object.getCitizen().getStoredLocation());
}
- }
+ });
// <--[mechanism]
// @object NPCTag
@@ -1773,10 +1715,12 @@ else if (npcEntity instanceof FallingBlock) {
// @tags
//
// -->
- if (mechanism.matches("range") && mechanism.requireFloat()) {
- getCitizen().getNavigator().getDefaultParameters().range(mechanism.getValue().asFloat());
- getCitizen().getNavigator().getLocalParameters().range(mechanism.getValue().asFloat());
- }
+ tagProcessor.registerMechanism("range", false, ElementTag.class, (object, mechanism, input) -> {
+ if (mechanism.requireFloat()) {
+ object.getCitizen().getNavigator().getDefaultParameters().range(input.asFloat());
+ object.getCitizen().getNavigator().getLocalParameters().range(input.asFloat());
+ }
+ });
// <--[mechanism]
// @object NPCTag
@@ -1787,10 +1731,12 @@ else if (npcEntity instanceof FallingBlock) {
// @tags
//
// -->
- if (mechanism.matches("attack_range") && mechanism.requireFloat()) {
- getCitizen().getNavigator().getDefaultParameters().attackRange(mechanism.getValue().asFloat());
- getCitizen().getNavigator().getLocalParameters().attackRange(mechanism.getValue().asFloat());
- }
+ tagProcessor.registerMechanism("attack_range", false, ElementTag.class, (object, mechanism, input) -> {
+ if (mechanism.requireFloat()) {
+ object.getCitizen().getNavigator().getDefaultParameters().attackRange(input.asFloat());
+ object.getCitizen().getNavigator().getLocalParameters().attackRange(input.asFloat());
+ }
+ });
// <--[mechanism]
// @object NPCTag
@@ -1801,15 +1747,17 @@ else if (npcEntity instanceof FallingBlock) {
// @tags
//
// -->
- if (mechanism.matches("speed") && mechanism.requireFloat()) {
- getCitizen().getNavigator().getDefaultParameters().speedModifier(mechanism.getValue().asFloat());
- getCitizen().getNavigator().getLocalParameters().speedModifier(mechanism.getValue().asFloat());
- }
+ tagProcessor.registerMechanism("speed", false, ElementTag.class, (object, mechanism, input) -> {
+ if (mechanism.requireFloat()) {
+ object.getCitizen().getNavigator().getDefaultParameters().speedModifier(input.asFloat());
+ object.getCitizen().getNavigator().getLocalParameters().speedModifier(input.asFloat());
+ }
+ });
- if (mechanism.matches("despawn")) {
+ tagProcessor.registerMechanism("despawn", false, (object, mechanism) -> {
BukkitImplDeprecations.npcDespawnMech.warn(mechanism.context);
- getCitizen().despawn(DespawnReason.PLUGIN);
- }
+ object.getCitizen().despawn(DespawnReason.PLUGIN);
+ });
// <--[mechanism]
// @object NPCTag
@@ -1820,18 +1768,18 @@ else if (npcEntity instanceof FallingBlock) {
// @tags
//
// -->
- if (mechanism.matches("set_sneaking") && mechanism.requireBoolean()) {
- if (!getCitizen().hasTrait(SneakingTrait.class)) {
- getCitizen().addTrait(SneakingTrait.class);
+ tagProcessor.registerMechanism("set_sneaking", false, ElementTag.class, (object, mechanism, input) -> {
+ if (!mechanism.requireBoolean()) {
+ return;
}
- SneakingTrait trait = getCitizen().getOrAddTrait(SneakingTrait.class);
- if (trait.isSneaking() && !mechanism.getValue().asBoolean()) {
+ SneakingTrait trait = object.getCitizen().getOrAddTrait(SneakingTrait.class);
+ if (trait.isSneaking() && !input.asBoolean()) {
trait.stand();
}
- else if (!trait.isSneaking() && mechanism.getValue().asBoolean()) {
+ else if (!trait.isSneaking() && input.asBoolean()) {
trait.sneak();
}
- }
+ });
// <--[mechanism]
// @object NPCTag
@@ -1842,9 +1790,11 @@ else if (!trait.isSneaking() && mechanism.getValue().asBoolean()) {
// @tags
//
// -->
- if (mechanism.matches("set_protected") && mechanism.requireBoolean()) {
- getCitizen().setProtected(mechanism.getValue().asBoolean());
- }
+ tagProcessor.registerMechanism("set_protected", false, ElementTag.class, (object, mechanism, input) -> {
+ if (mechanism.requireBoolean()) {
+ object.getCitizen().setProtected(input.asBoolean());
+ }
+ });
// <--[mechanism]
// @object NPCTag
@@ -1855,9 +1805,11 @@ else if (!trait.isSneaking() && mechanism.getValue().asBoolean()) {
// @tags
//
// -->
- if (mechanism.matches("lookclose") && mechanism.requireBoolean()) {
- getLookCloseTrait().lookClose(mechanism.getValue().asBoolean());
- }
+ tagProcessor.registerMechanism("lookclose", false, ElementTag.class, (object, mechanism, input) -> {
+ if (mechanism.requireBoolean()) {
+ object.getLookCloseTrait().lookClose(input.asBoolean());
+ }
+ });
// <--[mechanism]
// @object NPCTag
@@ -1868,9 +1820,11 @@ else if (!trait.isSneaking() && mechanism.getValue().asBoolean()) {
// @tags
//
// -->
- if (mechanism.matches("controllable") && mechanism.requireBoolean()) {
- getCitizen().getOrAddTrait(Controllable.class).setEnabled(mechanism.getValue().asBoolean());
- }
+ tagProcessor.registerMechanism("controllable", false, ElementTag.class, (object, mechanism, input) -> {
+ if (mechanism.requireBoolean()) {
+ object.getCitizen().getOrAddTrait(Controllable.class).setEnabled(input.asBoolean());
+ }
+ });
// <--[mechanism]
// @object NPCTag
@@ -1881,9 +1835,11 @@ else if (!trait.isSneaking() && mechanism.getValue().asBoolean()) {
// @tags
//
// -->
- if (mechanism.matches("targetable") && mechanism.requireBoolean()) {
- getCitizen().getOrAddTrait(TargetableTrait.class).setTargetable(mechanism.getValue().asBoolean());
- }
+ tagProcessor.registerMechanism("targetable", false, ElementTag.class, (object, mechanism, input) -> {
+ if (mechanism.requireBoolean()) {
+ object.getCitizen().getOrAddTrait(TargetableTrait.class).setTargetable(input.asBoolean());
+ }
+ });
// <--[mechanism]
// @object NPCTag
@@ -1894,14 +1850,11 @@ else if (!trait.isSneaking() && mechanism.getValue().asBoolean()) {
// @tags
//
// -->
- if (mechanism.matches("teleport_on_stuck") && mechanism.requireBoolean()) {
- if (mechanism.getValue().asBoolean()) {
- getNavigator().getDefaultParameters().stuckAction(TeleportStuckAction.INSTANCE);
+ tagProcessor.registerMechanism("teleport_on_stuck", false, ElementTag.class, (object, mechanism, input) -> {
+ if (mechanism.requireBoolean()) {
+ object.getNavigator().getDefaultParameters().stuckAction(input.asBoolean() ? TeleportStuckAction.INSTANCE : null);
}
- else {
- getNavigator().getDefaultParameters().stuckAction(null);
- }
- }
+ });
// <--[mechanism]
// @object NPCTag
@@ -1912,10 +1865,12 @@ else if (!trait.isSneaking() && mechanism.getValue().asBoolean()) {
// @tags
//
// -->
- if ((mechanism.matches("distance_margin") || mechanism.matches("set_distance")) && mechanism.requireDouble()) {
- getNavigator().getDefaultParameters().distanceMargin(mechanism.getValue().asDouble());
- getNavigator().getLocalParameters().distanceMargin(mechanism.getValue().asDouble());
- }
+ tagProcessor.registerMechanism("distance_margin", false, ElementTag.class, (object, mechanism, input) -> {
+ if (mechanism.requireDouble()) {
+ object.getNavigator().getDefaultParameters().distanceMargin(input.asDouble());
+ object.getNavigator().getLocalParameters().distanceMargin(input.asDouble());
+ }
+ }, "set_distance");
// <--[mechanism]
// @object NPCTag
@@ -1926,10 +1881,12 @@ else if (!trait.isSneaking() && mechanism.getValue().asBoolean()) {
// @tags
//
// -->
- if (mechanism.matches("path_distance_margin") && mechanism.requireDouble()) {
- getNavigator().getDefaultParameters().pathDistanceMargin(mechanism.getValue().asDouble());
- getNavigator().getLocalParameters().pathDistanceMargin(mechanism.getValue().asDouble());
- }
+ tagProcessor.registerMechanism("path_distance_margin", false, ElementTag.class, (object, mechanism, input) -> {
+ if (mechanism.requireDouble()) {
+ object.getNavigator().getDefaultParameters().pathDistanceMargin(input.asDouble());
+ object.getNavigator().getLocalParameters().pathDistanceMargin(input.asDouble());
+ }
+ });
// <--[mechanism]
// @object NPCTag
@@ -1941,9 +1898,11 @@ else if (!trait.isSneaking() && mechanism.getValue().asBoolean()) {
// @tags
//
// -->
- if (mechanism.matches("use_new_finder") && mechanism.requireBoolean()) {
- getNavigator().getDefaultParameters().useNewPathfinder(mechanism.getValue().asBoolean());
- }
+ tagProcessor.registerMechanism("use_new_finder", false, ElementTag.class, (object, mechanism, input) -> {
+ if (mechanism.requireBoolean()) {
+ object.getNavigator().getDefaultParameters().useNewPathfinder(input.asBoolean());
+ }
+ });
// <--[mechanism]
// @object NPCTag
@@ -1956,15 +1915,15 @@ else if (!trait.isSneaking() && mechanism.getValue().asBoolean()) {
// @tags
//
// -->
- if (mechanism.matches("navigator_look_at")) {
+ tagProcessor.registerMechanism("navigator_look_at", false, (object, mechanism) -> {
if (mechanism.hasValue() && mechanism.requireObject(LocationTag.class)) {
final LocationTag loc = mechanism.valueAsType(LocationTag.class);
- getNavigator().getLocalParameters().lookAtFunction((n) -> loc);
+ object.getNavigator().getLocalParameters().lookAtFunction((n) -> loc);
}
else {
- getNavigator().getLocalParameters().lookAtFunction(null);
+ object.getNavigator().getLocalParameters().lookAtFunction(null);
}
- }
+ });
// <--[mechanism]
// @object NPCTag
@@ -1975,9 +1934,9 @@ else if (!trait.isSneaking() && mechanism.getValue().asBoolean()) {
// @tags
// TODO
// -->
- if (mechanism.matches("name_visible")) {
- getCitizen().data().setPersistent(NPC.Metadata.NAMEPLATE_VISIBLE, mechanism.getValue().asString());
- }
+ tagProcessor.registerMechanism("name_visible", false, ElementTag.class, (object, mechanism, input) -> {
+ object.getCitizen().data().setPersistent(NPC.Metadata.NAMEPLATE_VISIBLE, input.asString());
+ });
// <--[mechanism]
// @object NPCTag
@@ -1988,9 +1947,11 @@ else if (!trait.isSneaking() && mechanism.getValue().asBoolean()) {
// @tags
// TODO
// -->
- if (mechanism.matches("glow_color") && mechanism.requireEnum(ChatColor.class)) {
- getCitizen().getOrAddTrait(ScoreboardTrait.class).setColor(ChatColor.valueOf(mechanism.getValue().asString().toUpperCase()));
- }
+ tagProcessor.registerMechanism("glow_color", false, ElementTag.class, (object, mechanism, input) -> {
+ if (mechanism.requireEnum(ChatColor.class)) {
+ object.getCitizen().getOrAddTrait(ScoreboardTrait.class).setColor(input.asEnum(ChatColor.class));
+ }
+ });
// <--[mechanism]
// @object NPCTag
@@ -2001,19 +1962,18 @@ else if (!trait.isSneaking() && mechanism.getValue().asBoolean()) {
// @tags
// TODO
// -->
- if (mechanism.matches("clear_waypoints")) {
- Waypoints wp = getCitizen().getOrAddTrait(Waypoints.class);
- if ((wp.getCurrentProvider() instanceof WaypointProvider.EnumerableWaypointProvider)) {
- ((List) ((WaypointProvider.EnumerableWaypointProvider) wp.getCurrentProvider()).waypoints()).clear();
+ tagProcessor.registerMechanism("clear_waypoints", false, (object, mechanism) -> {
+ Waypoints wp = object.getCitizen().getOrAddTrait(Waypoints.class);
+ if (wp.getCurrentProvider() instanceof WaypointProvider.EnumerableWaypointProvider provider) {
+ ((List) provider.waypoints()).clear();
}
- else if ((wp.getCurrentProvider() instanceof WanderWaypointProvider)) {
- List locs = ((WanderWaypointProvider) wp.getCurrentProvider()).getRegionCentres();
+ else if (wp.getCurrentProvider() instanceof WanderWaypointProvider provider) {
+ List locs = provider.getRegionCentres();
for (Location loc : locs) {
locs.remove(loc); // Manual clear to ensure recalculation for the forwarding list
}
-
}
- }
+ });
// <--[mechanism]
// @object NPCTag
@@ -2024,22 +1984,39 @@ else if ((wp.getCurrentProvider() instanceof WanderWaypointProvider)) {
// @tags
// TODO
// -->
- if (mechanism.matches("add_waypoint") && mechanism.requireObject(LocationTag.class)) {
- Location target = mechanism.valueAsType(LocationTag.class).clone();
- Waypoints wp = getCitizen().getOrAddTrait(Waypoints.class);
- if ((wp.getCurrentProvider() instanceof LinearWaypointProvider)) {
- ((LinearWaypointProvider) wp.getCurrentProvider()).addWaypoint(new Waypoint(target));
+ tagProcessor.registerMechanism("add_waypoint", false, LocationTag.class, (object, mechanism, input) -> {
+ Waypoints wp = object.getCitizen().getOrAddTrait(Waypoints.class);
+ if (wp.getCurrentProvider() instanceof LinearWaypointProvider provider) {
+ provider.addWaypoint(new Waypoint(input));
}
- else if ((wp.getCurrentProvider() instanceof WaypointProvider.EnumerableWaypointProvider)) {
- ((List) ((WaypointProvider.EnumerableWaypointProvider) wp.getCurrentProvider()).waypoints()).add(new Waypoint(target));
+ else if (wp.getCurrentProvider() instanceof WaypointProvider.EnumerableWaypointProvider provider) {
+ ((List) provider.waypoints()).add(new Waypoint(input));
}
- else if ((wp.getCurrentProvider() instanceof WanderWaypointProvider)) {
- ((WanderWaypointProvider) wp.getCurrentProvider()).getRegionCentres().add(target);
+ else if (wp.getCurrentProvider() instanceof WanderWaypointProvider provider) {
+ provider.getRegionCentres().add(input);
}
- }
+ });
+ }
- tagProcessor.processMechanism(this, mechanism);
+ public static ObjectTagProcessor tagProcessor = new ObjectTagProcessor<>();
+
+ @Override
+ public ObjectTag getObjectAttribute(Attribute attribute) {
+ return tagProcessor.getObjectAttribute(this, attribute);
+ }
+ @Override
+ public ObjectTag getNextObjectTypeDown() {
+ return getEntity() != null ? new EntityTag(this) : new ElementTag(identify());
+ }
+
+ public void applyProperty(Mechanism mechanism) {
+ mechanism.echoError("Cannot apply properties to an NPC!");
+ }
+
+ @Override
+ public void adjust(Mechanism mechanism) {
+ tagProcessor.processMechanism(this, mechanism);
// Pass along to EntityTag mechanism handler if not already handled.
if (!mechanism.fulfilled()) {
if (isSpawned()) {
diff --git a/plugin/src/main/java/com/denizenscript/denizen/objects/PlayerTag.java b/plugin/src/main/java/com/denizenscript/denizen/objects/PlayerTag.java
index eae5750277..0649efa9ed 100644
--- a/plugin/src/main/java/com/denizenscript/denizen/objects/PlayerTag.java
+++ b/plugin/src/main/java/com/denizenscript/denizen/objects/PlayerTag.java
@@ -2679,6 +2679,33 @@ else if (mechanism.requireObject(LocationTag.class)) {
object.getNBTEditor().setSpawnForced(input.asBoolean());
}
});
+
+ if (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_21)) {
+
+ // <--[mechanism]
+ // @object PlayerTag
+ // @name links
+ // @input ListTag(MapTag)
+ // @description
+ // Sends the specified list of server links to the player. This will override existing links player has.
+ // Each item in the list must be a MapTag in <@link language Server Links Format>.
+ // Generally prefer <@link mechanism PlayerTag.add_links>.
+ // -->
+ registerOnlineOnlyMechanism("links", ListTag.class, (player, mechanism, input) -> {
+ player.getPlayerEntity().sendLinks(Utilities.replaceServerLinks(Bukkit.getServerLinks().copy(), input, mechanism.context));
+ });
+
+ // <--[mechanism]
+ // @object PlayerTag
+ // @name add_links
+ // @input ListTag(MapTag)
+ // @description
+ // Adds the specified list of server links to the player. Each item in the list must be a MapTag in <@link language Server Links Format>.
+ // -->
+ registerOnlineOnlyMechanism("add_links", ListTag.class, (player, mechanism, input) -> {
+ player.getPlayerEntity().sendLinks(Utilities.fillServerLinks(Bukkit.getServerLinks().copy(), input, mechanism.context));
+ });
+ }
}
public static ObjectTagProcessor tagProcessor = new ObjectTagProcessor<>();
diff --git a/plugin/src/main/java/com/denizenscript/denizen/objects/WorldTag.java b/plugin/src/main/java/com/denizenscript/denizen/objects/WorldTag.java
index 1106a9a84c..e6690210cc 100644
--- a/plugin/src/main/java/com/denizenscript/denizen/objects/WorldTag.java
+++ b/plugin/src/main/java/com/denizenscript/denizen/objects/WorldTag.java
@@ -6,6 +6,7 @@
import com.denizenscript.denizen.nms.abstracts.BiomeNMS;
import com.denizenscript.denizen.utilities.BukkitImplDeprecations;
import com.denizenscript.denizen.utilities.flags.WorldFlagHandler;
+import com.denizenscript.denizen.utilities.world.GameRuleReflect;
import com.denizenscript.denizencore.flags.AbstractFlagTracker;
import com.denizenscript.denizencore.flags.FlaggableObject;
import com.denizenscript.denizencore.objects.Adjustable;
@@ -177,7 +178,7 @@ public T getGameRuleOrDefault(GameRule gameRule) {
if (value == null) {
value = world.getGameRuleDefault(gameRule);
if (value == null) {
- throw new IllegalStateException("World " + world_name + " contains no GameRule " + gameRule.getName());
+ throw new IllegalStateException("World " + world_name + " contains no GameRule " + GameRuleReflect.getName(gameRule));
}
}
return value;
@@ -852,16 +853,19 @@ else if (time >= 12500) {
// @returns ElementTag
// @description
// Returns the current value of the specified gamerule in the world.
- // Note that the name is case-sensitive... so "doFireTick" is correct, but "dofiretick" is not.
// -->
registerTag(ElementTag.class, "gamerule", (attribute, object) -> {
if (!attribute.hasParam()) {
attribute.echoError("The tag 'worldtag.gamerule[...]' must have an input value.");
return null;
}
- GameRule rule = GameRule.getByName(attribute.getParam());
- Object result = object.getWorld().getGameRuleValue(rule);
- return new ElementTag(result == null ? "null" : result.toString());
+ GameRule> rule = GameRuleReflect.getByName(attribute.getParam());
+ if (rule == null) {
+ attribute.echoError("Invalid game rule specified: " + attribute.getParam() + '.');
+ return null;
+ }
+ Object result = GameRuleReflect.getValue(object.getWorld(), rule);
+ return new ElementTag(String.valueOf(result), true);
});
// <--[tag]
@@ -872,10 +876,10 @@ else if (time >= 12500) {
// -->
registerTag(MapTag.class, "gamerule_map", (attribute, object) -> {
MapTag map = new MapTag();
- for (GameRule rule : GameRule.values()) {
- Object result = object.getWorld().getGameRuleValue(rule);
+ for (GameRule> rule : GameRuleReflect.values()) {
+ Object result = GameRuleReflect.getValue(object.getWorld(), rule);
if (result != null) {
- map.putObject(rule.getName(), new ElementTag(result.toString()));
+ map.putObject(GameRuleReflect.getName(rule), new ElementTag(result.toString(), true));
}
}
return map;
@@ -987,7 +991,7 @@ else if (time >= 12500) {
// @description
// Returns whether enough players are sleeping to prepare for the night to advance.
// Typically used before checking <@link tag WorldTag.enough_deep_sleeping>
- // By default, automatically checks the playersSleepingPercentage gamerule,
+ // By default, automatically checks the players_sleeping_percentage gamerule,
// but this can optionally be overridden by specifying a percentage integer.
// Any integer above 100 will always yield 'false'. Requires at least one player to be sleeping to return 'true'.
// -->
@@ -1008,7 +1012,7 @@ else if (time >= 12500) {
// @description
// Returns whether enough players have been in bed long enough for the night to advance (generally 100 ticks).
// Loops through all online players, so is typically used after checking <@link tag WorldTag.enough_sleeping>
- // By default, automatically checks the playersSleepingPercentage gamerule,
+ // By default, automatically checks the players_sleeping_percentage gamerule,
// but this can optionally be overridden by specifying a percentage integer.
// Any integer above 100 will always yield 'false'. Requires at least one player to be sleeping to return 'true'.
// -->
@@ -1092,7 +1096,12 @@ else if (time >= 12500) {
mechanism.echoError("Provided world is not an end world!");
return;
}
- battle.initiateRespawn();
+ if (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_20)) { // workaround for upstream bug
+ battle.initiateRespawn(List.of());
+ }
+ else {
+ battle.initiateRespawn();
+ }
});
// <--[mechanism]
@@ -1509,7 +1518,7 @@ else if (time >= 12500) {
// @input None
// @description
// Skips to the next day as if enough players slept through the night.
- // NOTE: This ignores the doDaylightCycle gamerule!
+ // NOTE: This ignores the advance_time gamerule!
// -->
tagProcessor.registerMechanism("skip_night", false, (object, mechanism) -> {
// general logic from NMS world tick
@@ -1525,7 +1534,7 @@ else if (time >= 12500) {
NMSHandler.worldHelper.wakeUpAllPlayers(world);
}
// minor change: prior to 1.18, hasStorm/isRaining was not checked
- if (object.getGameRuleOrDefault(GameRule.DO_WEATHER_CYCLE) && world.hasStorm()) {
+ if (object.getGameRuleOrDefault(GameRuleReflect.WEATHER_CYCLE_GAMERULE) && world.hasStorm()) {
NMSHandler.worldHelper.clearWeather(world);
}
});
diff --git a/plugin/src/main/java/com/denizenscript/denizen/objects/properties/PropertyRegistry.java b/plugin/src/main/java/com/denizenscript/denizen/objects/properties/PropertyRegistry.java
index 477c8bb129..b4339b1773 100644
--- a/plugin/src/main/java/com/denizenscript/denizen/objects/properties/PropertyRegistry.java
+++ b/plugin/src/main/java/com/denizenscript/denizen/objects/properties/PropertyRegistry.java
@@ -173,6 +173,9 @@ public static void registerMainProperties() {
}
PropertyParser.registerProperty(EntitySpeed.class, EntityTag.class);
PropertyParser.registerProperty(EntitySpell.class, EntityTag.class);
+ if (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_20)) {
+ PropertyParser.registerProperty(EntityState.class, EntityTag.class);
+ }
if (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_19)) {
PropertyParser.registerProperty(EntityStepHeight.class, EntityTag.class);
}
@@ -260,6 +263,7 @@ public static void registerMainProperties() {
PropertyParser.registerProperty(ItemScript.class, ItemTag.class);
PropertyParser.registerProperty(ItemSignContents.class, ItemTag.class); // Special case handling in ItemComponentsPatch
if (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_20)) {
+ PropertyParser.registerProperty(ItemSignBackContents.class, ItemTag.class); // Special case handling in ItemComponentsPatch
PropertyParser.registerProperty(ItemSignIsWaxed.class, ItemTag.class); // Special case handling in ItemComponentsPatch
}
registerItemProperty(ItemSkullskin.class, "profile");
@@ -296,6 +300,9 @@ public static void registerMainProperties() {
PropertyParser.registerProperty(MaterialLightable.class, MaterialTag.class);
PropertyParser.registerProperty(MaterialMode.class, MaterialTag.class);
PropertyParser.registerProperty(MaterialNote.class, MaterialTag.class);
+ if (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_21)) {
+ PropertyParser.registerProperty(MaterialOminous.class, MaterialTag.class);
+ }
PropertyParser.registerProperty(MaterialPersistent.class, MaterialTag.class);
PropertyParser.registerProperty(MaterialPower.class, MaterialTag.class);
PropertyParser.registerProperty(MaterialShape.class, MaterialTag.class);
diff --git a/plugin/src/main/java/com/denizenscript/denizen/objects/properties/entity/EntityColor.java b/plugin/src/main/java/com/denizenscript/denizen/objects/properties/entity/EntityColor.java
index 75fbf49b06..3e858feff3 100644
--- a/plugin/src/main/java/com/denizenscript/denizen/objects/properties/entity/EntityColor.java
+++ b/plugin/src/main/java/com/denizenscript/denizen/objects/properties/entity/EntityColor.java
@@ -259,6 +259,9 @@ public String getColor(boolean includeDeprecated) {
case CAT -> {
Cat cat = as(Cat.class);
// TODO once 1.21 is the minimum supported version, replace with direct registry-based handling
+ if (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_21)) {
+ yield Utilities.namespacedKeyToString(cat.getCatType().getKey()) + "|" + cat.getCollarColor().name();
+ }
yield cat.getCatType() + "|" + cat.getCollarColor().name();
}
case PANDA -> {
diff --git a/plugin/src/main/java/com/denizenscript/denizen/objects/properties/entity/EntityItem.java b/plugin/src/main/java/com/denizenscript/denizen/objects/properties/entity/EntityItem.java
index 36fa15c2f7..80d0cbc86f 100644
--- a/plugin/src/main/java/com/denizenscript/denizen/objects/properties/entity/EntityItem.java
+++ b/plugin/src/main/java/com/denizenscript/denizen/objects/properties/entity/EntityItem.java
@@ -4,19 +4,11 @@
import com.denizenscript.denizen.nms.NMSVersion;
import com.denizenscript.denizen.objects.EntityTag;
import com.denizenscript.denizen.objects.ItemTag;
-import com.denizenscript.denizen.utilities.BukkitImplDeprecations;
import com.denizenscript.denizencore.objects.Mechanism;
-import com.denizenscript.denizencore.objects.ObjectTag;
-import com.denizenscript.denizencore.objects.properties.Property;
-import com.denizenscript.denizencore.objects.properties.PropertyParser;
-import com.denizenscript.denizencore.tags.TagContext;
import net.citizensnpcs.api.npc.NPC;
-import org.bukkit.Material;
-import org.bukkit.block.data.BlockData;
import org.bukkit.entity.*;
-import org.bukkit.inventory.ItemStack;
-public class EntityItem implements Property {
+public class EntityItem extends EntityProperty {
// <--[property]
// @object EntityTag
@@ -30,118 +22,66 @@ public class EntityItem implements Property {
// - an eye-of-ender's item, which is both displayed and dropped.
// - a fireball's display item.
// - an item display's display item.
+ // - an ominous item spawner's display item.
// -->
- public static boolean describes(ObjectTag object) {
- if (!(object instanceof EntityTag)) {
- return false;
- }
- Entity entity = ((EntityTag) object).getBukkitEntity();
+ public static boolean describes(EntityTag object) {
+ Entity entity = object.getBukkitEntity();
return entity instanceof Item
|| entity instanceof Enderman
|| entity instanceof SizedFireball
|| entity instanceof ThrowableProjectile
|| entity instanceof EnderSignal
- || (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_19) && entity instanceof ItemDisplay);
- }
-
- public static EntityItem getFrom(ObjectTag entity) {
- if (!describes(entity)) {
- return null;
- }
- else {
- return new EntityItem((EntityTag) entity);
- }
+ || (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_19) && entity instanceof ItemDisplay)
+ || (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_21) && entity instanceof OminousItemSpawner);
}
- public static final String[] handledMechs = new String[] {
- "item"
- };
-
- public EntityItem(EntityTag entity) {
- item = entity;
- }
-
- EntityTag item;
-
- public ItemTag getItem(boolean includeDeprecated, TagContext context) {
- if (isDroppedItem()) {
- return new ItemTag(getDroppedItem().getItemStack());
+ @Override
+ public ItemTag getPropertyValue() {
+ if (getEntity() instanceof Item item) {
+ return new ItemTag(item.getItemStack());
}
- else if (includeDeprecated && isEnderman()) {
- BukkitImplDeprecations.entityItemEnderman.warn(context);
- BlockData data = getEnderman().getCarriedBlock();
- if (data == null) {
- return new ItemTag(Material.AIR);
- }
- return new ItemTag(data.getMaterial());
+ else if (getEntity() instanceof SizedFireball fireball) {
+ return new ItemTag(fireball.getDisplayItem());
}
- else if (isFireball()) {
- return new ItemTag(getFireball().getDisplayItem());
+ else if (getEntity() instanceof ThrowableProjectile projectile) {
+ return new ItemTag(projectile.getItem());
}
- else if (isThrowableProjectile()) {
- return new ItemTag(getThrowableProjectile().getItem());
+ else if (getEntity() instanceof EnderSignal signal) {
+ return new ItemTag(signal.getItem());
}
- else if (isEnderSignal()) {
- return new ItemTag(getEnderSignal().getItem());
+ else if (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_19) && getEntity() instanceof ItemDisplay itemDisplay) {
+ return new ItemTag(itemDisplay.getItemStack());
}
- else if (isDisplay()) { // TODO: 1.19: when 1.19 is minimum, make a 'getDisplay'
- return new ItemTag(((ItemDisplay) item.getBukkitEntity()).getItemStack());
+ else if (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_21) && getEntity() instanceof OminousItemSpawner ominousItemSpawner) {
+ return new ItemTag(ominousItemSpawner.getItem());
}
return null;
}
- public boolean isDroppedItem() {
- return item.getBukkitEntity() instanceof Item;
- }
-
- public boolean isEnderman() {
- return item.getBukkitEntity() instanceof Enderman;
- }
-
- public boolean isFireball() {
- return item.getBukkitEntity() instanceof SizedFireball;
- }
-
- public boolean isThrowableProjectile() {
- return item.getBukkitEntity() instanceof ThrowableProjectile;
- }
-
- public boolean isEnderSignal() {
- return item.getBukkitEntity() instanceof EnderSignal;
- }
-
- public boolean isDisplay() {
- return NMSHandler.getVersion().isAtLeast(NMSVersion.v1_19) && item.getBukkitEntity() instanceof Display;
- }
-
- public Item getDroppedItem() {
- return (Item) item.getBukkitEntity();
- }
-
- public Enderman getEnderman() {
- return (Enderman) item.getBukkitEntity();
- }
-
- public EnderSignal getEnderSignal() {
- return (EnderSignal) item.getBukkitEntity();
- }
-
- public ThrowableProjectile getThrowableProjectile() {
- return (ThrowableProjectile) item.getBukkitEntity();
- }
-
- public SizedFireball getFireball() {
- return (SizedFireball) item.getBukkitEntity();
- }
-
@Override
- public String getPropertyString() {
- ItemTag item = getItem(false, null);
- if (item.getBukkitMaterial() != Material.AIR) {
- return item.identify();
+ public void setPropertyValue(ItemTag item, Mechanism mechanism) {
+ if (object.isCitizensNPC()) {
+ object.getDenizenNPC().getCitizen().data().setPersistent(NPC.Metadata.ITEM_ID, item.getBukkitMaterial().name());
+ }
+ if (getEntity() instanceof Item droppedItem) {
+ droppedItem.setItemStack(item.getItemStack());
+ }
+ else if (getEntity() instanceof SizedFireball fireball) {
+ fireball.setDisplayItem(item.getItemStack());
+ }
+ else if (getEntity() instanceof ThrowableProjectile projectile) {
+ projectile.setItem(item.getItemStack());
+ }
+ else if (getEntity() instanceof EnderSignal signal) {
+ signal.setItem(item.getItemStack());
+ }
+ else if (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_19) && getEntity() instanceof ItemDisplay itemDisplay) {
+ itemDisplay.setItemStack(item.getItemStack());
+ }
+ else if (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_21) && getEntity() instanceof OminousItemSpawner ominousItemSpawner) {
+ ominousItemSpawner.setItem(item.getItemStack());
}
- return null;
}
@Override
@@ -150,37 +90,6 @@ public String getPropertyId() {
}
public static void register() {
- PropertyParser.registerTag(EntityItem.class, ItemTag.class, "item", (attribute, object) -> {
- return object.getItem(true, attribute.context);
- });
- }
-
- @Override
- public void adjust(Mechanism mechanism) {
- if (mechanism.matches("item") && mechanism.requireObject(ItemTag.class)) {
- ItemStack itemStack = mechanism.valueAsType(ItemTag.class).getItemStack();
- if (item.isCitizensNPC()) {
- item.getDenizenNPC().getCitizen().data().setPersistent(NPC.Metadata.ITEM_ID, itemStack.getType().name());
- }
- if (isDroppedItem()) {
- getDroppedItem().setItemStack(itemStack);
- }
- else if (isEnderman()) {
- BukkitImplDeprecations.entityItemEnderman.warn(mechanism.context);
- getEnderman().setCarriedBlock(itemStack.getType().createBlockData());
- }
- else if (isFireball()) {
- getFireball().setDisplayItem(itemStack);
- }
- else if (isThrowableProjectile()) {
- getThrowableProjectile().setItem(itemStack);
- }
- else if (isEnderSignal()) {
- getEnderSignal().setItem(itemStack);
- }
- else if (isDisplay()) { // TODO: 1.19: when 1.19 is minimum, make a 'getDisplay'
- ((ItemDisplay) item.getBukkitEntity()).setItemStack(itemStack);
- }
- }
+ autoRegister("item", EntityItem.class, ItemTag.class, false);
}
}
diff --git a/plugin/src/main/java/com/denizenscript/denizen/objects/properties/entity/EntityProfession.java b/plugin/src/main/java/com/denizenscript/denizen/objects/properties/entity/EntityProfession.java
index 478f6e9f56..66adee6d3b 100644
--- a/plugin/src/main/java/com/denizenscript/denizen/objects/properties/entity/EntityProfession.java
+++ b/plugin/src/main/java/com/denizenscript/denizen/objects/properties/entity/EntityProfession.java
@@ -2,117 +2,57 @@
import com.denizenscript.denizen.objects.EntityTag;
import com.denizenscript.denizen.utilities.Utilities;
-import com.denizenscript.denizencore.objects.core.ElementTag;
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 com.denizenscript.denizencore.utilities.CoreUtilities;
-import org.bukkit.entity.EntityType;
+import com.denizenscript.denizencore.objects.core.ElementTag;
import org.bukkit.entity.Villager;
import org.bukkit.entity.ZombieVillager;
-public class EntityProfession implements Property {
+public class EntityProfession extends EntityProperty {
- // TODO This technically has registries on all supported versions
- public static boolean describes(ObjectTag entity) {
- if (!(entity instanceof EntityTag)) {
- return false;
- }
- return ((EntityTag) entity).getBukkitEntityType() == EntityType.VILLAGER
- || ((EntityTag) entity).getBukkitEntityType() == EntityType.ZOMBIE_VILLAGER;
+ // <--[property]
+ // @object EntityTag
+ // @name profession
+ // @input ElementTag
+ // @description
+ // Controls the profession of a villager or zombie villager.
+ // For the list of possible professions, refer to <@link url https://hub.spigotmc.org/javadocs/spigot/org/bukkit/entity/Villager.Profession.html>
+ // -->
+
+ public static boolean describes(EntityTag entity) {
+ return entity.getBukkitEntity() instanceof Villager
+ || entity.getBukkitEntity() instanceof ZombieVillager;
}
- public static EntityProfession getFrom(ObjectTag entity) {
- if (!describes(entity)) {
- return null;
+ @Override
+ public ElementTag getPropertyValue() {
+ if (getEntity() instanceof Villager villager) {
+ return Utilities.enumlikeToElement(villager.getProfession());
}
- else {
- return new EntityProfession((EntityTag) entity);
+ else if (getEntity() instanceof ZombieVillager zombieVillager) {
+ return Utilities.enumlikeToElement(zombieVillager.getVillagerProfession());
}
+ return null;
}
- public static final String[] handledTags = new String[] {
- "profession"
- };
-
- public static final String[] handledMechs = new String[] {
- "profession"
- };
-
- public EntityProfession(EntityTag entity) {
- professional = entity;
- }
-
- EntityTag professional;
-
- public Villager.Profession getProfession() {
- if (professional.getBukkitEntityType() == EntityType.ZOMBIE_VILLAGER) {
- return ((ZombieVillager) professional.getBukkitEntity()).getVillagerProfession();
+ @Override
+ public void setPropertyValue(ElementTag value, Mechanism mechanism) {
+ if (!mechanism.requireEnum(Villager.Profession.class)) {
+ return;
}
- return ((Villager) professional.getBukkitEntity()).getProfession();
- }
-
- public void setProfession(Villager.Profession profession) {
- if (professional.getBukkitEntityType() == EntityType.ZOMBIE_VILLAGER) {
- ((ZombieVillager) professional.getBukkitEntity()).setVillagerProfession(profession);
+ if (getEntity() instanceof Villager villager) {
+ villager.setProfession(value.asEnum(Villager.Profession.class));
}
- else {
- ((Villager) professional.getBukkitEntity()).setProfession(profession);
+ else if (getEntity() instanceof ZombieVillager zombieVillager) {
+ zombieVillager.setVillagerProfession(value.asEnum(Villager.Profession.class));
}
}
- @Override
- public String getPropertyString() {
- return CoreUtilities.toLowerCase(String.valueOf(getProfession()));
- }
-
@Override
public String getPropertyId() {
return "profession";
}
- @Override
- public ObjectTag getObjectAttribute(Attribute attribute) {
-
- if (attribute == null) {
- return null;
- }
-
- // <--[tag]
- // @attribute
- // @returns ElementTag
- // @mechanism EntityTag.profession
- // @group properties
- // @description
- // If the entity can have professions, returns the entity's profession.
- // Currently, only Villager-type and infected zombie entities can have professions.
- // For the list of possible professions, refer to <@link url https://hub.spigotmc.org/javadocs/spigot/org/bukkit/entity/Villager.Profession.html>
- // -->
- if (attribute.startsWith("profession")) {
- return new ElementTag(String.valueOf(getProfession()), true)
- .getObjectAttribute(attribute.fulfill(1));
- }
-
- return null;
- }
-
- @Override
- public void adjust(Mechanism mechanism) {
-
- // <--[mechanism]
- // @object EntityTag
- // @name profession
- // @input ElementTag
- // @description
- // Changes the entity's profession.
- // Currently, only Villager-type entities can have professions.
- // For the list of possible professions, refer to <@link url https://hub.spigotmc.org/javadocs/spigot/org/bukkit/entity/Villager.Profession.html>
- // @tags
- //
- // -->
- if (mechanism.matches("profession") && Utilities.requireEnumlike(mechanism, Villager.Profession.class)) {
- setProfession(Utilities.elementToEnumlike(mechanism.getValue(), Villager.Profession.class));
- }
+ public static void register() {
+ autoRegister("profession", EntityProfession.class, ElementTag.class, false);
}
}
diff --git a/plugin/src/main/java/com/denizenscript/denizen/objects/properties/entity/EntitySize.java b/plugin/src/main/java/com/denizenscript/denizen/objects/properties/entity/EntitySize.java
index e821a24dbc..6c58c4fab9 100644
--- a/plugin/src/main/java/com/denizenscript/denizen/objects/properties/entity/EntitySize.java
+++ b/plugin/src/main/java/com/denizenscript/denizen/objects/properties/entity/EntitySize.java
@@ -1,53 +1,68 @@
package com.denizenscript.denizen.objects.properties.entity;
+import com.denizenscript.denizen.nms.NMSHandler;
+import com.denizenscript.denizen.nms.NMSVersion;
import com.denizenscript.denizen.objects.EntityTag;
+import com.denizenscript.denizencore.objects.Mechanism;
import com.denizenscript.denizencore.objects.core.ElementTag;
-import com.denizenscript.denizencore.objects.ObjectTag;
-import com.denizenscript.denizencore.objects.properties.Property;
-import com.denizenscript.denizencore.objects.properties.PropertyParser;
-import org.bukkit.entity.Phantom;
-import org.bukkit.entity.PufferFish;
-import org.bukkit.entity.Slime;
-
-public class EntitySize implements Property {
-
- public static boolean describes(ObjectTag entity) {
- return entity instanceof EntityTag &&
- (((EntityTag) entity).getBukkitEntity() instanceof Slime
- || ((EntityTag) entity).getBukkitEntity() instanceof Phantom
- || ((EntityTag) entity).getBukkitEntity() instanceof PufferFish);
+import org.bukkit.entity.*;
+
+public class EntitySize extends EntityProperty {
+ // TODO: once 26.2 is the minimum supported version, remove Slime usage in favor of AbstractCubeMob
+
+ // <--[property]
+ // @object EntityTag
+ // @name size
+ // @input ElementTag
+ // @description
+ // Controls the size of an entity.
+ // Cube-type (slime, magma cube, sulfur cube) mob sizes are between 1 and 127.
+ // Phantom mob sizes are between 0 and 64.
+ // Pufferfish mob sizes are between 0 and 2.
+ // -->
+
+ public static boolean describes(EntityTag entityTag) {
+ Entity entity = entityTag.getBukkitEntity();
+ return entity instanceof Phantom
+ || entity instanceof PufferFish
+ || entity instanceof Slime
+ || (NMSHandler.getVersion().isAtLeast(NMSVersion.v26_2) && entity instanceof AbstractCubeMob);
}
- public static EntitySize getFrom(ObjectTag entity) {
- if (!describes(entity)) {
- return null;
- }
- else {
- return new EntitySize((EntityTag) entity);
+ @Override
+ public ElementTag getPropertyValue() {
+ if (getEntity() instanceof Phantom phantom) {
+ return new ElementTag(phantom.getSize());
}
- }
-
- public EntitySize(EntityTag ent) {
- entity = ent;
- }
-
- EntityTag entity;
-
- public int getSize() {
- if (isSlime()) {
- return getSlime().getSize();
+ else if (getEntity() instanceof PufferFish pufferfish) {
+ return new ElementTag(pufferfish.getPuffState());
}
- else if (isPhantom()) {
- return getPhantom().getSize();
+ else if (getEntity() instanceof Slime slime) {
+ return new ElementTag(slime.getSize());
}
- else {
- return getPufferFish().getPuffState();
+ else if (NMSHandler.getVersion().isAtLeast(NMSVersion.v26_2) && getEntity() instanceof AbstractCubeMob cube) {
+ return new ElementTag(cube.getSize());
}
+ return null;
}
@Override
- public String getPropertyString() {
- return String.valueOf(getSize());
+ public void setPropertyValue(ElementTag value, Mechanism mechanism) {
+ if (!mechanism.requireInteger()) {
+ return;
+ }
+ if (getEntity() instanceof Phantom phantom) {
+ phantom.setSize(value.asInt());
+ }
+ else if (getEntity() instanceof PufferFish pufferfish) {
+ pufferfish.setPuffState(value.asInt());
+ }
+ else if (getEntity() instanceof Slime slime) {
+ slime.setSize(value.asInt());
+ }
+ else if (NMSHandler.getVersion().isAtLeast(NMSVersion.v26_2) && getEntity() instanceof AbstractCubeMob cube) {
+ cube.setSize(value.asInt());
+ }
}
@Override
@@ -56,63 +71,6 @@ public String getPropertyId() {
}
public static void register() {
-
- // <--[tag]
- // @attribute
- // @returns ElementTag(Number)
- // @mechanism EntityTag.size
- // @group properties
- // @description
- // Returns the size of a slime-type entity or a Phantom (1-120).
- // If the entity is a PufferFish it returns the puff state (0-3).
- // -->
- PropertyParser.registerTag(EntitySize.class, ElementTag.class, "size", (attribute, object) -> {
- return new ElementTag(object.getSize());
- });
-
-
- // <--[mechanism]
- // @object EntityTag
- // @name size
- // @input ElementTag(Number)
- // @description
- // Sets the size of a slime-type entity or a Phantom (1-120).
- // If the entity is a PufferFish it sets the puff state (0-3).
- // @tags
- //
- // -->
- PropertyParser.registerMechanism(EntitySize.class, ElementTag.class, "size", (object, mechanism, input) -> {
- if (mechanism.requireInteger()) {
- if (object.isSlime()) {
- object.getSlime().setSize(input.asInt());
- }
- else if (object.isPhantom()) {
- object.getPhantom().setSize(input.asInt());
- }
- else {
- object.getPufferFish().setPuffState(input.asInt());
- }
- }
- });
- }
-
- public boolean isSlime() {
- return entity.getBukkitEntity() instanceof Slime;
- }
-
- public boolean isPhantom() {
- return entity.getBukkitEntity() instanceof Phantom;
- }
-
- public Slime getSlime() {
- return (Slime) entity.getBukkitEntity();
- }
-
- public Phantom getPhantom() {
- return (Phantom) entity.getBukkitEntity();
- }
-
- public PufferFish getPufferFish() {
- return (PufferFish) entity.getBukkitEntity();
+ autoRegister("size", EntitySize.class, ElementTag.class, false);
}
}
diff --git a/plugin/src/main/java/com/denizenscript/denizen/objects/properties/entity/EntityState.java b/plugin/src/main/java/com/denizenscript/denizen/objects/properties/entity/EntityState.java
new file mode 100644
index 0000000000..e68ce63ea6
--- /dev/null
+++ b/plugin/src/main/java/com/denizenscript/denizen/objects/properties/entity/EntityState.java
@@ -0,0 +1,54 @@
+package com.denizenscript.denizen.objects.properties.entity;
+
+import com.denizenscript.denizen.nms.NMSHandler;
+import com.denizenscript.denizen.objects.EntityTag;
+import com.denizenscript.denizencore.objects.Mechanism;
+import com.denizenscript.denizencore.objects.core.ElementTag;
+import org.bukkit.entity.Armadillo;
+
+public class EntityState extends EntityProperty {
+
+ // <--[property]
+ // @object EntityTag
+ // @name state
+ // @input ElementTag
+ // @description
+ // Controls the current state of an armadillo.
+ // Valid states are IDLE, ROLLING, SCARED, and UNROLLING.
+ // The entity may roll or unroll due to normal vanilla conditions. If this is not desired, disable <@link property EntityTag.has_ai>.
+ // -->
+
+ public static boolean describes(EntityTag entity) {
+ return entity.getBukkitEntity() instanceof Armadillo;
+ }
+
+ public enum ArmadilloState {
+ IDLE, ROLLING, SCARED, UNROLLING
+ }
+
+ @Override
+ public boolean isDefaultValue(ElementTag val) {
+ return val.asEnum(ArmadilloState.class).equals(ArmadilloState.IDLE);
+ }
+
+ @Override
+ public ElementTag getPropertyValue() {
+ return new ElementTag(NMSHandler.entityHelper.getArmadilloState(as(Armadillo.class)));
+ }
+
+ @Override
+ public void setPropertyValue(ElementTag param, Mechanism mechanism) {
+ if (mechanism.requireEnum(ArmadilloState.class)) {
+ NMSHandler.entityHelper.setArmadilloState(as(Armadillo.class), param.asEnum(ArmadilloState.class));
+ }
+ }
+
+ @Override
+ public String getPropertyId() {
+ return "state";
+ }
+
+ public static void register() {
+ autoRegister("state", EntityState.class, ElementTag.class, false);
+ }
+}
diff --git a/plugin/src/main/java/com/denizenscript/denizen/objects/properties/entity/EntityVariant.java b/plugin/src/main/java/com/denizenscript/denizen/objects/properties/entity/EntityVariant.java
index 4ded567281..5b50f1c822 100644
--- a/plugin/src/main/java/com/denizenscript/denizen/objects/properties/entity/EntityVariant.java
+++ b/plugin/src/main/java/com/denizenscript/denizen/objects/properties/entity/EntityVariant.java
@@ -3,15 +3,13 @@
import com.denizenscript.denizen.nms.NMSHandler;
import com.denizenscript.denizen.nms.NMSVersion;
import com.denizenscript.denizen.objects.EntityTag;
+import com.denizenscript.denizen.utilities.PaperAPITools;
import com.denizenscript.denizen.utilities.Utilities;
import com.denizenscript.denizencore.objects.Mechanism;
import com.denizenscript.denizencore.objects.core.ElementTag;
import com.denizenscript.denizencore.utilities.ReflectionHelper;
import com.denizenscript.denizencore.utilities.debugging.Debug;
-import org.bukkit.entity.Chicken;
-import org.bukkit.entity.Cow;
-import org.bukkit.entity.Pig;
-import org.bukkit.entity.Wolf;
+import org.bukkit.entity.*;
import java.lang.invoke.MethodHandle;
@@ -37,18 +35,23 @@ public class EntityVariant extends EntityProperty {
// @name variant
// @input ElementTag
// @description
- // Controls which variant a chicken, cow, pig, or wolf is.
+ // Controls which variant a chicken, copper golem, cow, pig, wolf, or zombie nautilus is.
// A list of valid chicken variants can be found at <@link url https://hub.spigotmc.org/javadocs/spigot/org/bukkit/entity/Chicken.Variant.html>.
+ // A list of valid copper golem variants can be found at <@link url https://hub.spigotmc.org/javadocs/spigot/org/bukkit/entity/CopperGolem.CopperWeatherState.html>.
// A list of valid cow variants can be found at <@link url https://hub.spigotmc.org/javadocs/spigot/org/bukkit/entity/Cow.Variant.html>.
// A list of valid pig variants can be found at <@link url https://hub.spigotmc.org/javadocs/spigot/org/bukkit/entity/Pig.Variant.html>.
// A list of valid wolf variants can be found at <@link url https://hub.spigotmc.org/javadocs/spigot/org/bukkit/entity/Wolf.Variant.html>.
+ // A list of valid zombie nautilus variants can be found at <@link url https://hub.spigotmc.org/javadocs/spigot/org/bukkit/entity/ZombieNautilus.Variant.html>.
// -->
- public static boolean describes(EntityTag entity) {
- return entity.getBukkitEntity() instanceof Wolf
- || (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_21) && entity.getBukkitEntity() instanceof Chicken)
- || (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_21) && entity.getBukkitEntity() instanceof Cow)
- || (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_21) && entity.getBukkitEntity() instanceof Pig);
+ public static boolean describes(EntityTag entityTag) {
+ Entity entity = entityTag.getBukkitEntity();
+ return entity instanceof Wolf
+ || (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_21) && (entity instanceof Chicken
+ || entity instanceof CopperGolem
+ || entity instanceof Cow
+ || entity instanceof Pig
+ || entity instanceof ZombieNautilus));
}
@Override
@@ -56,20 +59,28 @@ public ElementTag getPropertyValue() {
if (getEntity() instanceof Wolf wolf) {
return new ElementTag(Utilities.namespacedKeyToString(wolf.getVariant().getKey()), true);
}
- else if (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_21) && getEntity() instanceof Chicken chicken) {
- return new ElementTag(Utilities.namespacedKeyToString(chicken.getVariant().getKey()), true);
- }
- else if (COW_GET_VARIANT != null && getEntity() instanceof Cow cow) {
- try {
- return new ElementTag(Utilities.namespacedKeyToString(((Cow.Variant) COW_GET_VARIANT.invoke(cow)).getKey()), true);
+ else if (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_21)) {
+ if (getEntity() instanceof Chicken chicken) {
+ return new ElementTag(Utilities.namespacedKeyToString(chicken.getVariant().getKey()), true);
}
- catch (Throwable e) {
- Debug.echoError(e);
- return null;
+ else if (getEntity() instanceof CopperGolem copperGolem) {
+ return new ElementTag(PaperAPITools.instance.getCopperGolemState(copperGolem), true);
+ }
+ else if (COW_GET_VARIANT != null && getEntity() instanceof Cow cow) {
+ try {
+ return new ElementTag(Utilities.namespacedKeyToString(((Cow.Variant) COW_GET_VARIANT.invoke(cow)).getKey()), true);
+ }
+ catch (Throwable e) {
+ Debug.echoError(e);
+ return null;
+ }
+ }
+ else if (getEntity() instanceof Pig pig) {
+ return new ElementTag(Utilities.namespacedKeyToString(pig.getVariant().getKey()), true);
+ }
+ else if (getEntity() instanceof ZombieNautilus zombieNautilus) {
+ return new ElementTag(Utilities.namespacedKeyToString(zombieNautilus.getVariant().getKey()), true);
}
- }
- else if (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_21) && getEntity() instanceof Pig pig) {
- return new ElementTag(Utilities.namespacedKeyToString(pig.getVariant().getKey()), true);
}
return null;
}
@@ -82,27 +93,38 @@ public void setPropertyValue(ElementTag variant, Mechanism mechanism) {
wolf.setVariant(wolfVariant);
}
}
- else if (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_21) && getEntity() instanceof Chicken chicken) {
- Chicken.Variant chickenVariant = Utilities.elementToRequiredEnumLike(variant, Chicken.Variant.class, mechanism);
- if (chickenVariant != null) {
- chicken.setVariant(chickenVariant);
+ else if (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_21)) {
+ if (getEntity() instanceof Chicken chicken) {
+ Chicken.Variant chickenVariant = Utilities.elementToRequiredEnumLike(variant, Chicken.Variant.class, mechanism);
+ if (chickenVariant != null) {
+ chicken.setVariant(chickenVariant);
+ }
}
- }
- else if (COW_SET_VARIANT != null && getEntity() instanceof Cow cow) {
- Cow.Variant cowVariant = Utilities.elementToRequiredEnumLike(variant, Cow.Variant.class, mechanism);
- if (cowVariant != null) {
- try {
- COW_SET_VARIANT.invoke(cow, cowVariant);
+ else if (getEntity() instanceof CopperGolem copperGolem) {
+ PaperAPITools.instance.setCopperGolemState(variant, copperGolem, mechanism);
+ }
+ else if (COW_SET_VARIANT != null && getEntity() instanceof Cow cow) {
+ Cow.Variant cowVariant = Utilities.elementToRequiredEnumLike(variant, Cow.Variant.class, mechanism);
+ if (cowVariant != null) {
+ try {
+ COW_SET_VARIANT.invoke(cow, cowVariant);
+ }
+ catch (Throwable e) {
+ Debug.echoError(e);
+ }
}
- catch (Throwable e) {
- Debug.echoError(e);
+ }
+ else if (getEntity() instanceof Pig pig) {
+ Pig.Variant pigVariant = Utilities.elementToRequiredEnumLike(variant, Pig.Variant.class, mechanism);
+ if (pigVariant != null) {
+ pig.setVariant(pigVariant);
}
}
- }
- else if (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_21) && getEntity() instanceof Pig pig) {
- Pig.Variant pigVariant = Utilities.elementToRequiredEnumLike(variant, Pig.Variant.class, mechanism);
- if (pigVariant != null) {
- pig.setVariant(pigVariant);
+ else if (getEntity() instanceof ZombieNautilus zombieNautilus) {
+ ZombieNautilus.Variant zombieNautilusVariant = Utilities.elementToRequiredEnumLike(variant, ZombieNautilus.Variant.class, mechanism);
+ if (zombieNautilusVariant != null) {
+ zombieNautilus.setVariant(zombieNautilusVariant);
+ }
}
}
}
diff --git a/plugin/src/main/java/com/denizenscript/denizen/objects/properties/item/ItemArmorPose.java b/plugin/src/main/java/com/denizenscript/denizen/objects/properties/item/ItemArmorPose.java
index 306baff5cb..f6521e0f0c 100644
--- a/plugin/src/main/java/com/denizenscript/denizen/objects/properties/item/ItemArmorPose.java
+++ b/plugin/src/main/java/com/denizenscript/denizen/objects/properties/item/ItemArmorPose.java
@@ -78,8 +78,7 @@ public void setPropertyValue(MapTag param, Mechanism mechanism) {
if (entityNbt == null) {
return;
}
- // TODO: adventure-nbt: contains
- if (!(entityNbt.get("Pose") instanceof CompoundBinaryTag)) {
+ if (!entityNbt.contains("Pose", BinaryTagTypes.COMPOUND)) {
return;
}
entityNbt = entityNbt.remove("Pose");
diff --git a/plugin/src/main/java/com/denizenscript/denizen/objects/properties/item/ItemCustomModel.java b/plugin/src/main/java/com/denizenscript/denizen/objects/properties/item/ItemCustomModel.java
index c47897271e..e97bea7df7 100644
--- a/plugin/src/main/java/com/denizenscript/denizen/objects/properties/item/ItemCustomModel.java
+++ b/plugin/src/main/java/com/denizenscript/denizen/objects/properties/item/ItemCustomModel.java
@@ -15,6 +15,7 @@ public class ItemCustomModel extends ItemProperty {
// @description
// Controls the custom model data ID number of the item.
// Use with no input to remove the custom model data.
+ // Prefer <@link property ItemTag.item_model> on MC 1.21+.
// See also <@link tag ItemTag.has_custom_model_data>
// -->
public static boolean describes(ItemTag item) {
@@ -56,6 +57,7 @@ public static void register() {
// @group properties
// @description
// Returns whether the item has a custom model data ID number set on it.
+ // Prefer <@link property ItemTag.item_model> on MC 1.21+.
// See also <@link tag ItemTag.custom_model_data>.
// -->
PropertyParser.registerTag(ItemCustomModel.class, ElementTag.class, "has_custom_model_data", (attribute, prop) -> {
diff --git a/plugin/src/main/java/com/denizenscript/denizen/objects/properties/item/ItemDurability.java b/plugin/src/main/java/com/denizenscript/denizen/objects/properties/item/ItemDurability.java
index ddd46aa1fb..a8a8b3847d 100644
--- a/plugin/src/main/java/com/denizenscript/denizen/objects/properties/item/ItemDurability.java
+++ b/plugin/src/main/java/com/denizenscript/denizen/objects/properties/item/ItemDurability.java
@@ -58,14 +58,7 @@ public ObjectTag getObjectAttribute(Attribute attribute) {
.getObjectAttribute(attribute.fulfill(1));
}
- // <--[tag]
- // @attribute
- // @returns ElementTag(Number)
- // @group properties
- // @description
- // Returns the maximum durability (number of uses) of this item.
- // For use with <@link tag ItemTag.durability> and <@link mechanism ItemTag.durability>.
- // -->
+ // replaced by paper->MaxDurabilityAdapter
if (attribute.startsWith("max_durability")) {
return new ElementTag(item.getMaterial().getMaterial().getMaxDurability())
.getObjectAttribute(attribute.fulfill(1));
diff --git a/plugin/src/main/java/com/denizenscript/denizen/objects/properties/item/ItemRawNBT.java b/plugin/src/main/java/com/denizenscript/denizen/objects/properties/item/ItemRawNBT.java
index 719addec44..578cc1526c 100644
--- a/plugin/src/main/java/com/denizenscript/denizen/objects/properties/item/ItemRawNBT.java
+++ b/plugin/src/main/java/com/denizenscript/denizen/objects/properties/item/ItemRawNBT.java
@@ -153,11 +153,10 @@ public static CompoundBinaryTag compoundOrEmpty(CompoundBinaryTag compoundTag) {
public static BinaryTag convertObjectToNbt(ObjectTag inputObject, TagContext context, String path) {
if (inputObject.canBeType(MapTag.class)) {
MapTag map = inputObject.asType(MapTag.class, context);
- // TODO: adventure-nbt: builders initial size
- Map result = new HashMap<>(map.size());
+ CompoundBinaryTag.Builder resultBuilder = CompoundBinaryTag.builder(map.size());
for (Map.Entry entry : map.entrySet()) {
try {
- result.put(entry.getKey().str, convertObjectToNbt(entry.getValue(), context, path + "." + entry.getKey().str));
+ resultBuilder.put(entry.getKey().str, convertObjectToNbt(entry.getValue(), context, path + "." + entry.getKey().str));
}
catch (Exception ex) {
Debug.echoError("Object NBT interpretation failed for key '" + path + "." + entry.getKey().str + "'.");
@@ -165,15 +164,14 @@ public static BinaryTag convertObjectToNbt(ObjectTag inputObject, TagContext con
return null;
}
}
- return CompoundBinaryTag.from(result);
+ return resultBuilder.build();
}
else if (!HAS_NBT_LIST_TYPES && inputObject.shouldBeType(ListTag.class)) {
ListTag list = inputObject.asType(ListTag.class, context);
- // TODO: adventure-nbt: builders initial size
- List result = new ArrayList<>(list.size());
+ ListBinaryTag.Builder resultBuilder = ListBinaryTag.heterogeneousListBinaryTag(list.size());
for (int i = 0; i < list.size(); i++) {
try {
- result.add(convertObjectToNbt(list.getObject(i), context, path + '[' + i + ']'));
+ resultBuilder.add(convertObjectToNbt(list.getObject(i), context, path + '[' + i + ']'));
}
catch (Exception ex) {
Debug.echoError("Object NBT interpretation failed for list key '" + path + "' at index " + i + '.');
@@ -181,7 +179,7 @@ else if (!HAS_NBT_LIST_TYPES && inputObject.shouldBeType(ListTag.class)) {
return null;
}
}
- return ListBinaryTag.listBinaryTag(BinaryTagTypes.LIST_WILDCARD, result);
+ return resultBuilder.build();
}
String input = inputObject.identify();
if (input.equals("end")) {
diff --git a/plugin/src/main/java/com/denizenscript/denizen/objects/properties/item/ItemSignBackContents.java b/plugin/src/main/java/com/denizenscript/denizen/objects/properties/item/ItemSignBackContents.java
new file mode 100644
index 0000000000..3371e133b0
--- /dev/null
+++ b/plugin/src/main/java/com/denizenscript/denizen/objects/properties/item/ItemSignBackContents.java
@@ -0,0 +1,70 @@
+package com.denizenscript.denizen.objects.properties.item;
+
+import com.denizenscript.denizen.objects.ItemTag;
+import com.denizenscript.denizen.utilities.PaperAPITools;
+import com.denizenscript.denizencore.objects.Mechanism;
+import com.denizenscript.denizencore.objects.core.ListTag;
+import com.denizenscript.denizencore.utilities.CoreUtilities;
+import org.bukkit.block.Sign;
+import org.bukkit.inventory.meta.BlockStateMeta;
+
+public class ItemSignBackContents extends ItemProperty {
+
+ // <--[property]
+ // @object ItemTag
+ // @name sign_back_contents
+ // @input ListTag
+ // @description
+ // Controls the contents on the back of a sign item.
+ // For the front of the sign, see <@link property ItemTag.sign_contents>.
+ // -->
+
+ public static boolean describes(ItemTag item) {
+ return item.getItemMeta() instanceof BlockStateMeta blockStateMeta
+ && blockStateMeta.getBlockState() instanceof Sign;
+ }
+
+ @Override
+ public ListTag getPropertyValue() {
+ return new ListTag(PaperAPITools.instance.getSignBackLines((Sign) as(BlockStateMeta.class).getBlockState()), true);
+ }
+
+ @Override
+ public boolean isDefaultValue(ListTag value) {
+ for (String line : value) {
+ if (!line.isEmpty()) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ @Override
+ public void setPropertyValue(ListTag value, Mechanism mechanism) {
+ BlockStateMeta blockStateMeta = as(BlockStateMeta.class);
+ Sign sign = (Sign) blockStateMeta.getBlockState();
+ for (int i = 0; i < 4; i++) {
+ PaperAPITools.instance.setSignBackLine(sign, i, "");
+ }
+ CoreUtilities.fixNewLinesToListSeparation(value);
+ if (value.size() > 4) {
+ mechanism.echoError("Sign can only hold four lines!");
+ }
+ else {
+ for (int i = 0; i < value.size(); i++) {
+ PaperAPITools.instance.setSignBackLine(sign, i, value.get(i));
+ }
+ }
+ blockStateMeta.setBlockState(sign);
+ setItemMeta(blockStateMeta);
+ }
+
+ @Override
+ public String getPropertyId() {
+ return "sign_back_contents";
+ }
+
+ public static void register() {
+ autoRegister("sign_back_contents", ItemSignBackContents.class, ListTag.class, false);
+ }
+}
diff --git a/plugin/src/main/java/com/denizenscript/denizen/objects/properties/item/ItemSignContents.java b/plugin/src/main/java/com/denizenscript/denizen/objects/properties/item/ItemSignContents.java
index 9774eccaf2..c307452885 100644
--- a/plugin/src/main/java/com/denizenscript/denizen/objects/properties/item/ItemSignContents.java
+++ b/plugin/src/main/java/com/denizenscript/denizen/objects/properties/item/ItemSignContents.java
@@ -1,84 +1,63 @@
package com.denizenscript.denizen.objects.properties.item;
-import com.denizenscript.denizen.utilities.PaperAPITools;
-import com.denizenscript.denizencore.utilities.debugging.Debug;
import com.denizenscript.denizen.objects.ItemTag;
+import com.denizenscript.denizen.utilities.PaperAPITools;
import com.denizenscript.denizencore.objects.Mechanism;
import com.denizenscript.denizencore.objects.core.ListTag;
-import com.denizenscript.denizencore.objects.ObjectTag;
-import com.denizenscript.denizencore.objects.properties.Property;
-import com.denizenscript.denizencore.tags.Attribute;
import com.denizenscript.denizencore.utilities.CoreUtilities;
import org.bukkit.block.Sign;
import org.bukkit.inventory.meta.BlockStateMeta;
-import java.util.Arrays;
-
-public class ItemSignContents implements Property {
-
- public static boolean describes(ObjectTag item) {
- return item instanceof ItemTag
- && ((ItemTag) item).getItemMeta() instanceof BlockStateMeta
- && ((BlockStateMeta) ((ItemTag) item).getItemMeta()).getBlockState() instanceof Sign;
+public class ItemSignContents extends ItemProperty {
+
+ // <--[property]
+ // @object ItemTag
+ // @name sign_contents
+ // @input ListTag
+ // @description
+ // Controls the contents of a sign item.
+ // For MC 1.20+, this is the contents on the front of the sign.
+ // For the back of the sign, see <@link property ItemTag.sign_back_contents>.
+ // -->
+
+ public static boolean describes(ItemTag item) {
+ return item.getItemMeta() instanceof BlockStateMeta blockStateMeta
+ && blockStateMeta.getBlockState() instanceof Sign;
}
- public static ItemSignContents getFrom(ObjectTag _item) {
- if (!describes(_item)) {
- return null;
- }
- else {
- return new ItemSignContents((ItemTag) _item);
- }
- }
-
- public static final String[] handledTags = new String[] {
- "sign_contents"
- };
-
- public static final String[] handledMechs = new String[] {
- "sign_contents"
- };
-
- public ListTag getSignContents() {
- return new ListTag(Arrays.asList(PaperAPITools.instance.getSignLines((Sign) ((BlockStateMeta) item.getItemMeta()).getBlockState())), true);
- }
-
- public ItemSignContents(ItemTag _item) {
- item = _item;
+ @Override
+ public ListTag getPropertyValue() {
+ return new ListTag(PaperAPITools.instance.getSignLines((Sign) as(BlockStateMeta.class).getBlockState()), true);
}
- ItemTag item;
-
@Override
- public ObjectTag getObjectAttribute(Attribute attribute) {
-
- if (attribute == null) {
- return null;
- }
-
- // <--[tag]
- // @attribute
- // @returns ListTag
- // @mechanism ItemTag.sign_contents
- // @group properties
- // @description
- // Returns a list of lines on a sign item.
- // -->
- if (attribute.startsWith("sign_contents")) {
- return getSignContents().getObjectAttribute(attribute.fulfill(1));
+ public boolean isDefaultValue(ListTag value) {
+ for (String line : value) {
+ if (!line.isEmpty()) {
+ return false;
+ }
}
-
- return null;
+ return true;
}
@Override
- public String getPropertyString() {
- for (String line : getSignContents()) {
- if (line.length() > 0) {
- return getSignContents().identify();
+ public void setPropertyValue(ListTag value, Mechanism mechanism) {
+ BlockStateMeta blockStateMeta = as(BlockStateMeta.class);
+ Sign sign = (Sign) blockStateMeta.getBlockState();
+ for (int i = 0; i < 4; i++) {
+ PaperAPITools.instance.setSignLine(sign, i, "");
+ }
+ CoreUtilities.fixNewLinesToListSeparation(value);
+ if (value.size() > 4) {
+ mechanism.echoError("Sign can only hold four lines!");
+ }
+ else {
+ for (int i = 0; i < value.size(); i++) {
+ PaperAPITools.instance.setSignLine(sign, i, value.get(i));
}
}
- return null;
+ blockStateMeta.setBlockState(sign);
+ setItemMeta(blockStateMeta);
}
@Override
@@ -86,36 +65,7 @@ public String getPropertyId() {
return "sign_contents";
}
- @Override
- public void adjust(Mechanism mechanism) {
-
- // <--[mechanism]
- // @object ItemTag
- // @name sign_contents
- // @input ListTag
- // @description
- // Sets the contents of a sign item.
- // @tags
- //
- // -->
- if (mechanism.matches("sign_contents")) {
- BlockStateMeta bsm = ((BlockStateMeta) item.getItemMeta());
- Sign sign = (Sign) bsm.getBlockState();
- for (int i = 0; i < 4; i++) {
- PaperAPITools.instance.setSignLine(sign, i, "");
- }
- ListTag list = mechanism.valueAsType(ListTag.class);
- CoreUtilities.fixNewLinesToListSeparation(list);
- if (list.size() > 4) {
- Debug.echoError("Sign can only hold four lines!");
- }
- else {
- for (int i = 0; i < list.size(); i++) {
- PaperAPITools.instance.setSignLine(sign, i, list.get(i));
- }
- }
- bsm.setBlockState(sign);
- item.setItemMeta(bsm);
- }
+ public static void register() {
+ autoRegister("sign_contents", ItemSignContents.class, ListTag.class, false);
}
}
diff --git a/plugin/src/main/java/com/denizenscript/denizen/objects/properties/material/MaterialCount.java b/plugin/src/main/java/com/denizenscript/denizen/objects/properties/material/MaterialCount.java
index 398d1c5b27..dd69b8ef8a 100644
--- a/plugin/src/main/java/com/denizenscript/denizen/objects/properties/material/MaterialCount.java
+++ b/plugin/src/main/java/com/denizenscript/denizen/objects/properties/material/MaterialCount.java
@@ -4,63 +4,98 @@
import com.denizenscript.denizen.nms.NMSVersion;
import com.denizenscript.denizen.objects.MaterialTag;
import com.denizenscript.denizencore.objects.Mechanism;
-import com.denizenscript.denizencore.objects.ObjectTag;
import com.denizenscript.denizencore.objects.core.ElementTag;
-import com.denizenscript.denizencore.objects.properties.Property;
import com.denizenscript.denizencore.objects.properties.PropertyParser;
import org.bukkit.block.data.BlockData;
import org.bukkit.block.data.type.*;
-public class MaterialCount implements Property {
+public class MaterialCount extends MaterialProperty {
+ // TODO: once 1.21 is the minimum supported version, remove PinkPetals usage in favor of FlowerBed
- public static boolean describes(ObjectTag material) {
- if (!(material instanceof MaterialTag mat)) {
- return false;
- }
- if (!mat.hasModernData()) {
- return false;
- }
- BlockData data = mat.getModernData();
+ // <--[property]
+ // @object MaterialTag
+ // @name count
+ // @input ElementTag(Number)
+ // @description
+ // Controls the amount of pickles in a Sea Pickle material, eggs in a Turtle Egg material, charges in a Respawn Anchor material, candles in a Candle material, flowers in a flower bed, or leaves in a leaf litter.
+ // -->
+
+ public static boolean describes(MaterialTag material) {
+ BlockData data = material.getModernData();
return data instanceof SeaPickle
|| data instanceof TurtleEgg
|| data instanceof RespawnAnchor
|| data instanceof Candle
- || (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_19) && data instanceof PinkPetals);
+ || (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_19) && data instanceof PinkPetals)
+ || (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_21) && (data instanceof FlowerBed
+ || data instanceof LeafLitter));
}
- public static MaterialCount getFrom(ObjectTag _material) {
- if (!describes(_material)) {
- return null;
+ @Override
+ public ElementTag getPropertyValue() {
+ if (getBlockData() instanceof SeaPickle seaPickle) {
+ return new ElementTag(seaPickle.getPickles());
+ }
+ else if (getBlockData() instanceof TurtleEgg turtleEgg) {
+ return new ElementTag(turtleEgg.getEggs());
+ }
+ else if (getBlockData() instanceof RespawnAnchor respawnAnchor) {
+ return new ElementTag(respawnAnchor.getCharges());
}
- else {
- return new MaterialCount((MaterialTag) _material);
+ else if (getBlockData() instanceof Candle candle) {
+ return new ElementTag(candle.getCandles());
}
+ else if (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_19) && getBlockData() instanceof PinkPetals pinkPetals) {
+ return new ElementTag(pinkPetals.getFlowerAmount());
+ }
+ else if (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_21) && getBlockData() instanceof FlowerBed flowerBed) {
+ return new ElementTag(flowerBed.getFlowerAmount());
+ }
+ else if (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_21) && getBlockData() instanceof LeafLitter leafLitter) {
+ return new ElementTag(leafLitter.getSegmentAmount());
+ }
+ return null;
}
- public static final String[] handledMechs = new String[] {
- "count", "pickle_count"
- };
-
- public MaterialCount(MaterialTag _material) {
- material = _material;
+ @Override
+ public void setPropertyValue(ElementTag value, Mechanism mechanism) {
+ if (mechanism.requireInteger()) {
+ int count = value.asInt();
+ if (count < getMin() || count > getMax()) {
+ mechanism.echoError("Material count mechanism value '" + count + "' is not valid. Must be between " + getMin() + " and " + getMax() + ".");
+ return;
+ }
+ if (getBlockData() instanceof SeaPickle seaPickle) {
+ seaPickle.setPickles(count);
+ }
+ else if (getBlockData() instanceof TurtleEgg turtleEgg) {
+ turtleEgg.setEggs(count);
+ }
+ else if (getBlockData() instanceof RespawnAnchor respawnAnchor) {
+ respawnAnchor.setCharges(count);
+ }
+ else if (getBlockData() instanceof Candle candle) {
+ candle.setCandles(count);
+ }
+ else if (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_19) && getBlockData() instanceof PinkPetals pinkPetals) {
+ pinkPetals.setFlowerAmount(count);
+ }
+ else if (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_21) && getBlockData() instanceof FlowerBed flowerBed) {
+ flowerBed.setFlowerAmount(count);
+ }
+ else if (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_21) && getBlockData() instanceof LeafLitter leafLitter) {
+ leafLitter.setSegmentAmount(count);
+ }
+ }
}
- MaterialTag material;
+ @Override
+ public String getPropertyId() {
+ return "count";
+ }
public static void register() {
- // <--[tag]
- // @attribute
- // @returns ElementTag(Number)
- // @mechanism MaterialTag.count
- // @group properties
- // @description
- // Returns the amount of pickles in a Sea Pickle material, eggs in a Turtle Egg material, charges in a Respawn Anchor material, candles in a Candle material, or petals in a Pink Petals material.
- // -->
- PropertyParser.registerStaticTag(MaterialCount.class, ElementTag.class, "count", (attribute, material) -> {
- return new ElementTag(material.getCurrent());
- }, "pickle_count");
-
// <--[tag]
// @attribute
// @returns ElementTag(Number)
@@ -84,142 +119,57 @@ public static void register() {
PropertyParser.registerStaticTag(MaterialCount.class, ElementTag.class, "count_min", (attribute, material) -> {
return new ElementTag(material.getMin());
}, "pickle_min");
- }
-
- public boolean isSeaPickle() {
- return material.getModernData() instanceof SeaPickle;
- }
-
- public boolean isTurtleEgg() {
- return material.getModernData() instanceof TurtleEgg;
- }
- public boolean isRespawnAnchor() {
- return material.getModernData() instanceof RespawnAnchor;
- }
-
- public boolean isCandle() {
- return material.getModernData() instanceof Candle;
- }
-
- public TurtleEgg getTurtleEgg() {
- return (TurtleEgg) material.getModernData();
- }
-
- public SeaPickle getSeaPickle() {
- return (SeaPickle) material.getModernData();
- }
-
- public RespawnAnchor getRespawnAnchor() {
- return (RespawnAnchor) material.getModernData();
- }
-
- public Candle getCandle() {
- return (Candle) material.getModernData();
- }
-
- public int getCurrent() {
- if (isSeaPickle()) {
- return getSeaPickle().getPickles();
- }
- else if (isTurtleEgg()) {
- return getTurtleEgg().getEggs();
- }
- else if (isRespawnAnchor()) {
- return getRespawnAnchor().getCharges();
- }
- else if (isCandle()) {
- return getCandle().getCandles();
- }
- else if (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_19) && material.getModernData() instanceof PinkPetals pinkPetals) {
- return pinkPetals.getFlowerAmount();
- }
- throw new UnsupportedOperationException();
+ autoRegister("count", MaterialCount.class, ElementTag.class, false, "pickle_count");
}
public int getMax() {
- if (isSeaPickle()) {
- return getSeaPickle().getMaximumPickles();
+ if (getBlockData() instanceof SeaPickle seaPickle) {
+ return seaPickle.getMaximumPickles();
}
- else if (isTurtleEgg()) {
- return getTurtleEgg().getMaximumEggs();
+ else if (getBlockData() instanceof TurtleEgg turtleEgg) {
+ return turtleEgg.getMaximumEggs();
}
- else if (isRespawnAnchor()) {
- return getRespawnAnchor().getMaximumCharges();
+ else if (getBlockData() instanceof RespawnAnchor respawnAnchor) {
+ return respawnAnchor.getMaximumCharges();
}
- else if (isCandle()) {
- return getCandle().getMaximumCandles();
+ else if (getBlockData() instanceof Candle candle) {
+ return candle.getMaximumCandles();
}
- else if (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_19) && material.getModernData() instanceof PinkPetals pinkPetals) {
+ else if (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_19) && getBlockData() instanceof PinkPetals pinkPetals) {
return pinkPetals.getMaximumFlowerAmount();
}
+ else if (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_21) && getBlockData() instanceof FlowerBed flowerBed) {
+ return flowerBed.getMaximumFlowerAmount();
+ }
+ else if (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_21) && getBlockData() instanceof LeafLitter leafLitter) {
+ return leafLitter.getMaximumSegmentAmount();
+ }
throw new UnsupportedOperationException();
}
public int getMin() {
- if (isSeaPickle()) {
- return getSeaPickle().getMinimumPickles();
+ if (getBlockData() instanceof SeaPickle seaPickle) {
+ return seaPickle.getMinimumPickles();
}
- else if (isTurtleEgg()) {
- return getTurtleEgg().getMinimumEggs();
+ else if (getBlockData() instanceof TurtleEgg turtleEgg) {
+ return turtleEgg.getMinimumEggs();
}
- else if (isRespawnAnchor()) {
+ else if (getBlockData() instanceof RespawnAnchor) {
return 0;
}
- else if (isCandle()) {
+ else if (getBlockData() instanceof Candle) {
return 1;
}
- else if (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_19) && material.getModernData() instanceof PinkPetals) {
+ else if (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_19) && getBlockData() instanceof PinkPetals) {
return 1;
}
- throw new UnsupportedOperationException();
- }
-
- @Override
- public String getPropertyString() {
- return String.valueOf(getCurrent());
- }
-
- @Override
- public String getPropertyId() {
- return "count";
- }
-
- @Override
- public void adjust(Mechanism mechanism) {
-
- // <--[mechanism]
- // @object MaterialTag
- // @name count
- // @input ElementTag(Number)
- // @description
- // Sets the amount of pickles in a Sea Pickle material, eggs in a Turtle Egg material, charges in a Respawn Anchor material, candles in a Candle material, or petals in a Pink Petals material.
- // @tags
- //
- //
- //
- // -->
- if ((mechanism.matches("count") || (mechanism.matches("pickle_count"))) && mechanism.requireInteger()) {
- int count = mechanism.getValue().asInt();
- if (count < getMin() || count > getMax()) {
- mechanism.echoError("Material count mechanism value '" + count + "' is not valid. Must be between " + getMin() + " and " + getMax() + ".");
- return;
- }
- if (isSeaPickle()) {
- getSeaPickle().setPickles(count);
- }
- else if (isTurtleEgg()) {
- getTurtleEgg().setEggs(count);
- }
- else if (isRespawnAnchor()) {
- getRespawnAnchor().setCharges(count);
- }
- else if (isCandle()) {
- getCandle().setCandles(count);
- }
- else if (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_19) && material.getModernData() instanceof PinkPetals pinkPetals) {
- pinkPetals.setFlowerAmount(count);
- }
+ else if (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_21) && getBlockData() instanceof FlowerBed) {
+ return 1;
}
+ else if (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_21) && getBlockData() instanceof LeafLitter) {
+ return 1;
+ }
+ throw new UnsupportedOperationException();
}
}
diff --git a/plugin/src/main/java/com/denizenscript/denizen/objects/properties/material/MaterialLevel.java b/plugin/src/main/java/com/denizenscript/denizen/objects/properties/material/MaterialLevel.java
index 054573c513..08b3bff668 100644
--- a/plugin/src/main/java/com/denizenscript/denizen/objects/properties/material/MaterialLevel.java
+++ b/plugin/src/main/java/com/denizenscript/denizen/objects/properties/material/MaterialLevel.java
@@ -9,10 +9,7 @@
import org.bukkit.block.data.BlockData;
import org.bukkit.block.data.Brushable;
import org.bukkit.block.data.Levelled;
-import org.bukkit.block.data.type.Beehive;
-import org.bukkit.block.data.type.Cake;
-import org.bukkit.block.data.type.Farmland;
-import org.bukkit.block.data.type.Snow;
+import org.bukkit.block.data.type.*;
public class MaterialLevel extends MaterialProperty {
@@ -32,6 +29,7 @@ public class MaterialLevel extends MaterialProperty {
// For farmland, this is the moisture level.
// For composters, this is the amount of compost.
// For brushable blocks (also referred to as "suspicious blocks"), this is the level of dusting. 1.20+ only.
+ // For dried ghasts, this is the level of hydration. 1.21+ only.
// See also <@link tag MaterialTag.maximum_level> and <@link tag MaterialTag.minimum_level>.
// -->
@@ -42,12 +40,34 @@ public static boolean describes(MaterialTag material) {
|| data instanceof Snow
|| data instanceof Farmland
|| data instanceof Beehive
- || (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_20) && data instanceof Brushable);
+ || (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_20) && data instanceof Brushable)
+ || (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_21) && data instanceof DriedGhast);
}
@Override
public ElementTag getPropertyValue() {
- return new ElementTag(getCurrent());
+ if (getBlockData() instanceof Cake cake) {
+ return new ElementTag(cake.getBites());
+ }
+ else if (getBlockData() instanceof Snow snow) {
+ return new ElementTag(snow.getLayers());
+ }
+ else if (getBlockData() instanceof Beehive beehive) {
+ return new ElementTag(beehive.getHoneyLevel());
+ }
+ else if (getBlockData() instanceof Farmland farmland) {
+ return new ElementTag(farmland.getMoisture());
+ }
+ else if (getBlockData() instanceof Levelled levelled) {
+ return new ElementTag(levelled.getLevel());
+ }
+ else if (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_20) && getBlockData() instanceof Brushable brushable) {
+ return new ElementTag(brushable.getDusted());
+ }
+ else if (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_21) && getBlockData() instanceof DriedGhast driedGhast) {
+ return new ElementTag(driedGhast.getHydration());
+ }
+ return null;
}
@Override
@@ -65,7 +85,27 @@ public void setPropertyValue(ElementTag value, Mechanism mechanism) {
mechanism.echoError("Level value '" + level + "' is not valid. Must be between " + getMin() + " and " + getMax() + " for material '" + getBlockData().getMaterial().name() + "'.");
return;
}
- setCurrent(level);
+ if (getBlockData() instanceof Cake cake) {
+ cake.setBites(level);
+ }
+ else if (getBlockData() instanceof Snow snow) {
+ snow.setLayers(level);
+ }
+ else if (getBlockData() instanceof Beehive beehive) {
+ beehive.setHoneyLevel(level);
+ }
+ else if (getBlockData() instanceof Farmland farmland) {
+ farmland.setMoisture(level);
+ }
+ else if (getBlockData() instanceof Levelled levelled) {
+ levelled.setLevel(level);
+ }
+ else if (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_20) && getBlockData() instanceof Brushable brushable) {
+ brushable.setDusted(level);
+ }
+ else if (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_21) && getBlockData() instanceof DriedGhast driedGhast) {
+ driedGhast.setHydration(level);
+ }
}
public static void register() {
@@ -96,112 +136,35 @@ public static void register() {
autoRegister("level", MaterialLevel.class, ElementTag.class, false);
}
- public Levelled getLevelled() {
- return (Levelled) getBlockData();
- }
-
- public boolean isCake() {
- return getBlockData() instanceof Cake;
- }
-
- public Cake getCake() {
- return (Cake) getBlockData();
- }
-
- public boolean isSnow() {
- return getBlockData() instanceof Snow;
- }
-
- public Snow getSnow() {
- return (Snow) getBlockData();
- }
-
- public boolean isHive() {
- return getBlockData() instanceof Beehive;
- }
-
- public Beehive getHive() {
- return (Beehive) getBlockData();
- }
-
- public boolean isFarmland() {
- return getBlockData() instanceof Farmland;
- }
-
- public Farmland getFarmland() {
- return (Farmland) getBlockData();
- }
-
- public boolean isBrushable() {
- return NMSHandler.getVersion().isAtLeast(NMSVersion.v1_20) && getBlockData() instanceof Brushable;
- }
-
- public int getCurrent() {
- if (isCake()) {
- return getCake().getBites();
- }
- else if (isSnow()) {
- return getSnow().getLayers();
- }
- else if (isHive()) {
- return getHive().getHoneyLevel();
- }
- else if (isFarmland()) {
- return getFarmland().getMoisture();
+ public int getMax() {
+ if (getBlockData() instanceof Cake cake) {
+ return cake.getMaximumBites();
}
- else if (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_20) && isBrushable()) {
- return ((Brushable) getBlockData()).getDusted();
+ else if (getBlockData() instanceof Snow snow) {
+ return snow.getMaximumLayers();
}
- return getLevelled().getLevel();
- }
-
- public int getMax() {
- if (isCake()) {
- return getCake().getMaximumBites();
+ else if (getBlockData() instanceof Beehive beehive) {
+ return beehive.getMaximumHoneyLevel();
}
- else if (isSnow()) {
- return getSnow().getMaximumLayers();
+ else if (getBlockData() instanceof Farmland farmland) {
+ return farmland.getMaximumMoisture();
}
- else if (isHive()) {
- return getHive().getMaximumHoneyLevel();
+ else if (getBlockData() instanceof Levelled levelled) {
+ return levelled.getMaximumLevel();
}
- else if (isFarmland()) {
- return getFarmland().getMaximumMoisture();
+ else if (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_20) && getBlockData() instanceof Brushable brushable) {
+ return brushable.getMaximumDusted();
}
- else if (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_20) && isBrushable()) {
- return ((Brushable) getBlockData()).getMaximumDusted();
+ else if (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_21) && getBlockData() instanceof DriedGhast driedGhast) {
+ return driedGhast.getMaximumHydration();
}
- return getLevelled().getMaximumLevel();
+ throw new UnsupportedOperationException();
}
public int getMin() {
- if (isSnow()) {
- return getSnow().getMinimumLayers();
+ if (getBlockData() instanceof Snow snow) {
+ return snow.getMinimumLayers();
}
return 0;
}
-
- public void setCurrent(int level) {
- if (isCake()) {
- getCake().setBites(level);
- return;
- }
- else if (isSnow()) {
- getSnow().setLayers(level);
- return;
- }
- else if (isHive()) {
- getHive().setHoneyLevel(level);
- return;
- }
- else if (isFarmland()) {
- getFarmland().setMoisture(level);
- return;
- }
- else if (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_20) && isBrushable()) {
- ((Brushable) getBlockData()).setDusted(level);
- return;
- }
- getLevelled().setLevel(level);
- }
}
diff --git a/plugin/src/main/java/com/denizenscript/denizen/objects/properties/material/MaterialMode.java b/plugin/src/main/java/com/denizenscript/denizen/objects/properties/material/MaterialMode.java
index 3dfb61c2cc..68f720512a 100644
--- a/plugin/src/main/java/com/denizenscript/denizen/objects/properties/material/MaterialMode.java
+++ b/plugin/src/main/java/com/denizenscript/denizen/objects/properties/material/MaterialMode.java
@@ -4,271 +4,175 @@
import com.denizenscript.denizen.nms.NMSVersion;
import com.denizenscript.denizen.objects.MaterialTag;
import com.denizenscript.denizencore.objects.Mechanism;
-import com.denizenscript.denizencore.objects.ObjectTag;
import com.denizenscript.denizencore.objects.core.ElementTag;
-import com.denizenscript.denizencore.objects.properties.Property;
-import com.denizenscript.denizencore.objects.properties.PropertyParser;
-import com.denizenscript.denizencore.utilities.CoreUtilities;
import org.bukkit.block.data.BlockData;
import org.bukkit.block.data.type.*;
-public class MaterialMode implements Property {
-
- public static boolean describes(ObjectTag material) {
- if (!(material instanceof MaterialTag)) {
- return false;
- }
- MaterialTag mat = (MaterialTag) material;
- if (!mat.hasModernData()) {
- return false;
- }
- BlockData data = mat.getModernData();
- return data instanceof Comparator
- || data instanceof PistonHead
+public class MaterialMode extends MaterialProperty {
+
+ // <--[property]
+ // @object MaterialTag
+ // @name mode
+ // @input ElementTag
+ // @description
+ // Controls a block's mode.
+ // For big_dripleafs, modes are FULL, NONE, PARTIAL, and UNSTABLE.
+ // For bubble_columns, modes are NORMAL and DRAG.
+ // For command_blocks, modes are CONDITIONAL and NORMAL.
+ // For comparators, modes are COMPARE and SUBTRACT.
+ // For creaking_hearts, modes are AWAKE, DORMANT, and UPROOTED.
+ // For daylight_detectors, modes are INVERTED and NORMAL.
+ // For potent_sulfur, modes are CONTINUOUS, DORMANT, DRY, ERUPTING, and WET.
+ // For piston_heads, modes are NORMAL and SHORT.
+ // For sculk_catalysts, modes are BLOOM and NORMAL.
+ // For sculk_sensors, modes are ACTIVE, COOLDOWN, and INACTIVE.
+ // For sculk_shriekers, modes are SHRIEKING and NORMAL.
+ // For structure_blocks, modes are CORNER, DATA, LOAD, and SAVE.
+ // For tripwires, modes are ARMED and DISARMED.
+ // For trial_spawners, modes are ACTIVE, COOLDOWN, EJECTING_REWARD, INACTIVE, WAITING_FOR_PLAYERS, and WAITING_FOR_REWARD_EJECTION.
+ // For vaults, modes are ACTIVE, EJECTING, INACTIVE, and UNLOCKING.
+ // -->
+
+ public static boolean describes(MaterialTag material) {
+ BlockData data = material.getModernData();
+ return data instanceof BigDripleaf
|| data instanceof BubbleColumn
- || data instanceof StructureBlock
- || data instanceof DaylightDetector
|| data instanceof CommandBlock
+ || data instanceof Comparator
+ || data instanceof DaylightDetector
+ || data instanceof PistonHead
|| data instanceof SculkSensor
- || data instanceof BigDripleaf
+ || data instanceof StructureBlock
|| data instanceof Tripwire
|| (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_19) && (data instanceof SculkCatalyst
- || data instanceof SculkShrieker));
+ || data instanceof SculkShrieker))
+ || (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_21) && (data instanceof CreakingHeart
+ || data instanceof TrialSpawner
+ || data instanceof Vault))
+ || (NMSHandler.getVersion().isAtLeast(NMSVersion.v26_2) && data instanceof PotentSulfur);
}
- public static MaterialMode getFrom(ObjectTag _material) {
- if (!describes(_material)) {
- return null;
+ @Override
+ public ElementTag getPropertyValue() {
+ if (getBlockData() instanceof BigDripleaf bigDripleaf) {
+ return new ElementTag(bigDripleaf.getTilt());
}
- else {
- return new MaterialMode((MaterialTag) _material);
+ else if (getBlockData() instanceof BubbleColumn bubbleColumn) {
+ return new ElementTag(bubbleColumn.isDrag() ? "DRAG" : "NORMAL", true);
}
- }
-
- public static final String[] handledMechs = new String[] {
- "mode"
- };
-
- public MaterialMode(MaterialTag _material) {
- material = _material;
- }
-
- public MaterialTag material;
-
- public static void register() {
-
- // <--[tag]
- // @attribute
- // @returns ElementTag
- // @mechanism MaterialTag.mode
- // @group properties
- // @description
- // Returns a block's mode.
- // For comparators, output is COMPARE or SUBTRACT.
- // For piston_heads, output is NORMAL or SHORT.
- // For bubble_columns, output is NORMAL or DRAG.
- // For structure_blocks, output is CORNER, DATA, LOAD, or SAVE.
- // For sculk_sensors, output is ACTIVE, COOLDOWN, or INACTIVE.
- // For daylight_detectors, output is INVERTED or NORMAL.
- // For command_blocks, output is CONDITIONAL or NORMAL.
- // For big_dripleafs, output is FULL, NONE, PARTIAL, or UNSTABLE.
- // For sculk_catalysts, output is BLOOM or NORMAL.
- // For sculk_shriekers, output is SHRIEKING or NORMAL.
- // For tripwires, output is ARMED or DISARMED.
- // -->
- PropertyParser.registerStaticTag(MaterialMode.class, ElementTag.class, "mode", (attribute, material) -> {
- return new ElementTag(material.getPropertyString());
- });
- }
-
- public boolean isComparator() {
- return material.getModernData() instanceof Comparator;
- }
-
- public boolean isPistonHead() {
- return material.getModernData() instanceof PistonHead;
- }
-
- public boolean isBubbleColumn() {
- return material.getModernData() instanceof BubbleColumn;
- }
-
- public boolean isStructureBlock() {
- return material.getModernData() instanceof StructureBlock;
- }
-
- public boolean isDaylightDetector() {
- return material.getModernData() instanceof DaylightDetector;
- }
-
- public boolean isCommandBlock() {
- return material.getModernData() instanceof CommandBlock;
- }
-
- public boolean isSculkSensor() {
- return material.getModernData() instanceof SculkSensor;
- }
-
- public boolean isBigDripleaf() {
- return material.getModernData() instanceof BigDripleaf;
- }
-
- public boolean isTripwire() {
- return material.getModernData() instanceof Tripwire;
- }
-
- public boolean isSculkCatalyst() {
- return NMSHandler.getVersion().isAtLeast(NMSVersion.v1_19) && material.getModernData() instanceof SculkCatalyst;
- }
-
- public boolean isSculkShrieker() {
- return NMSHandler.getVersion().isAtLeast(NMSVersion.v1_19) && material.getModernData() instanceof SculkShrieker;
- }
-
- public Comparator getComparator() {
- return (Comparator) material.getModernData();
- }
-
- public PistonHead getPistonHead() {
- return (PistonHead) material.getModernData();
- }
-
- public BubbleColumn getBubbleColumn() {
- return (BubbleColumn) material.getModernData();
- }
-
- public StructureBlock getStructureBlock() {
- return (StructureBlock) material.getModernData();
- }
-
- public DaylightDetector getDaylightDetector() {
- return (DaylightDetector) material.getModernData();
- }
-
- public CommandBlock getCommandBlock() {
- return (CommandBlock) material.getModernData();
- }
-
- public SculkSensor getSculkSensor() {
- return (SculkSensor) material.getModernData();
- }
-
- public BigDripleaf getBigDripleaf() {
- return (BigDripleaf) material.getModernData();
- }
-
- public Tripwire getTripwire() {
- return (Tripwire) material.getModernData();
- }
-
- /*public SculkCatalyst getSculkCatalyst() { // TODO: 1.19
- return (SculkCatalyst) material.getModernData();
- }
-
- public SculkShrieker getSculkShrieker() {
- return (SculkShrieker) material.getModernData();
- }*/
-
- @Override
- public String getPropertyString() {
- if (isComparator()) {
- return getComparator().getMode().name();
+ else if (getBlockData() instanceof CommandBlock cmdBlock) {
+ return new ElementTag(cmdBlock.isConditional() ? "CONDITIONAL" : "NORMAL", true);
}
- else if (isBubbleColumn()) {
- return getBubbleColumn().isDrag() ? "DRAG" : "NORMAL";
+ else if (getBlockData() instanceof Comparator comparator) {
+ return new ElementTag(comparator.getMode());
}
- else if (isPistonHead()) {
- return getPistonHead().isShort() ? "SHORT" : "NORMAL";
+ else if (getBlockData() instanceof DaylightDetector daylightDetector) {
+ return new ElementTag(daylightDetector.isInverted() ? "INVERTED" : "NORMAL", true);
}
- else if (isStructureBlock()) {
- return getStructureBlock().getMode().name();
+ else if (getBlockData() instanceof PistonHead pistonHead) {
+ return new ElementTag(pistonHead.isShort() ? "SHORT" : "NORMAL", true);
}
- else if (isDaylightDetector()) {
- return getDaylightDetector().isInverted() ? "INVERTED" : "NORMAL";
+ else if (getBlockData() instanceof SculkSensor sculkSensor) {
+ return new ElementTag(sculkSensor.getPhase());
}
- else if (isCommandBlock()) {
- return getCommandBlock().isConditional() ? "CONDITIONAL" : "NORMAL";
+ else if (getBlockData() instanceof StructureBlock structureBlock) {
+ return new ElementTag(structureBlock.getMode());
}
- else if (isSculkSensor()) {
- return getSculkSensor().getPhase().name();
+ else if (getBlockData() instanceof Tripwire tripwire) {
+ return new ElementTag(tripwire.isDisarmed() ? "DISARMED" : "ARMED", true);
}
- else if (isBigDripleaf()) {
- return getBigDripleaf().getTilt().name();
+ else if (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_19) && getBlockData() instanceof SculkCatalyst sculkCatalyst) {
+ return new ElementTag(sculkCatalyst.isBloom() ? "BLOOM" : "NORMAL", true);
}
- else if (isTripwire()) {
- return getTripwire().isDisarmed() ? "DISARMED" : "ARMED";
+ else if (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_19) && getBlockData() instanceof SculkShrieker sculkShrieker) {
+ return new ElementTag(sculkShrieker.isShrieking() ? "SHRIEKING" : "NORMAL", true);
}
- else if (isSculkCatalyst()) {
- return ((SculkCatalyst) material.getModernData()).isBloom() ? "BLOOM" : "NORMAL"; // TODO: 1.19
+ else if (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_21) && getBlockData() instanceof CreakingHeart creakingHeart) {
+ return new ElementTag(creakingHeart.getCreakingHeartState().name(), true); // TODO: once 1.21 is the minimum supported version, use the enum constructor
}
- else if (isSculkShrieker()) {
- return ((SculkShrieker) material.getModernData()).isShrieking() ? "SHRIEKING" : "NORMAL"; // TODO: 1.19
+ else if (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_21) && getBlockData() instanceof TrialSpawner trialSpawner) {
+ return new ElementTag(trialSpawner.getTrialSpawnerState().name(), true); // TODO: once 1.21 is the minimum supported version, use the enum constructor
}
- return null; // Unreachable
- }
-
- @Override
- public String getPropertyId() {
- return "mode";
+ else if (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_21) && getBlockData() instanceof Vault vault) {
+ return new ElementTag(vault.getVaultState().name(), true); // TODO: once 1.21 is the minimum supported version, use the enum constructor
+ }
+ else if (NMSHandler.getVersion().isAtLeast(NMSVersion.v26_2) && getBlockData() instanceof PotentSulfur potentSulfur) {
+ return new ElementTag(potentSulfur.getPotentSulfurState().name(), true); // TODO: once 26.2 is the minimum supported version, use the enum constructor
+ }
+ return null;
}
@Override
- public void adjust(Mechanism mechanism) {
-
- // <--[mechanism]
- // @object MaterialTag
- // @name mode
- // @input ElementTag
- // @description
- // Set a block's mode.
- // For comparators, input is COMPARE or SUBTRACT.
- // For piston_heads, input is NORMAL or SHORT.
- // For bubble_columns, input is NORMAL or DRAG.
- // For structure_blocks, input is CORNER, DATA, LOAD, or SAVE.
- // For sculk_sensors, input is ACTIVE, COOLDOWN, or INACTIVE.
- // For daylight_detectors, input is INVERTED or NORMAL.
- // For command_blocks, input is CONDITIONAL or NORMAL.
- // For big_dripleafs, input is FULL, NONE, PARTIAL, or UNSTABLE.
- // For sculk_catalysts, input is BLOOM or NORMAL.
- // For sculk_shriekers, input is SHRIEKING or NORMAL.
- // For tripwires, input is ARMED or DISARMED.
- // @tags
- //
- // -->
- if (mechanism.matches("mode")) {
- if (isComparator() && mechanism.requireEnum(Comparator.Mode.class)) {
- getComparator().setMode(Comparator.Mode.valueOf(mechanism.getValue().asString().toUpperCase()));
- }
- else if (isBubbleColumn()) {
- getBubbleColumn().setDrag(CoreUtilities.equalsIgnoreCase(mechanism.getValue().asString(), "drag"));
+ public void setPropertyValue(ElementTag value, Mechanism mechanism) {
+ if (getBlockData() instanceof BigDripleaf bigDripleaf) {
+ if (mechanism.requireEnum(BigDripleaf.Tilt.class)) {
+ bigDripleaf.setTilt(value.asEnum(BigDripleaf.Tilt.class));
}
- else if (isPistonHead()) {
- getPistonHead().setShort(CoreUtilities.equalsIgnoreCase(mechanism.getValue().asString(), "short"));
- }
- else if (isStructureBlock() && mechanism.requireEnum(StructureBlock.Mode.class)) {
- getStructureBlock().setMode(StructureBlock.Mode.valueOf(mechanism.getValue().asString().toUpperCase()));
- }
- else if (isDaylightDetector()) {
- getDaylightDetector().setInverted(CoreUtilities.equalsIgnoreCase(mechanism.getValue().asString(), "inverted"));
+ }
+ else if (getBlockData() instanceof BubbleColumn bubbleColumn) {
+ bubbleColumn.setDrag(value.asLowerString().equals("drag"));
+ }
+ else if (getBlockData() instanceof CommandBlock cmdBlock) {
+ cmdBlock.setConditional(value.asLowerString().equals("conditional"));
+ }
+ else if (getBlockData() instanceof Comparator comparator) {
+ if (mechanism.requireEnum(Comparator.Mode.class)) {
+ comparator.setMode(value.asEnum(Comparator.Mode.class));
}
- else if (isCommandBlock()) {
- getCommandBlock().setConditional(CoreUtilities.equalsIgnoreCase(mechanism.getValue().asString(), "conditional"));
+ }
+ else if (getBlockData() instanceof DaylightDetector daylightDetector) {
+ daylightDetector.setInverted(value.asLowerString().equals("inverted"));
+ }
+ else if (getBlockData() instanceof PistonHead pistonHead) {
+ pistonHead.setShort(value.asLowerString().equals("short"));
+ }
+ else if (getBlockData() instanceof SculkSensor sculkSensor) {
+ if (mechanism.requireEnum(SculkSensor.Phase.class)) {
+ sculkSensor.setPhase(value.asEnum(SculkSensor.Phase.class));
}
- else if (isSculkSensor() && mechanism.requireEnum(SculkSensor.Phase.class)) {
- getSculkSensor().setPhase(SculkSensor.Phase.valueOf(mechanism.getValue().asString().toUpperCase()));
+ }
+ else if (getBlockData() instanceof StructureBlock structureBlock) {
+ if (mechanism.requireEnum(StructureBlock.Mode.class)) {
+ structureBlock.setMode(value.asEnum(StructureBlock.Mode.class));
}
- else if (isBigDripleaf() && mechanism.requireEnum(BigDripleaf.Tilt.class)) {
- getBigDripleaf().setTilt(BigDripleaf.Tilt.valueOf(mechanism.getValue().asString().toUpperCase()));
+ }
+ else if (getBlockData() instanceof Tripwire tripwire) {
+ tripwire.setDisarmed(value.asLowerString().equals("disarmed"));
+ }
+ else if (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_19) && getBlockData() instanceof SculkCatalyst sculkCatalyst) {
+ sculkCatalyst.setBloom(value.asLowerString().equals("bloom"));
+ }
+ else if (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_19) && getBlockData() instanceof SculkShrieker sculkShrieker) {
+ sculkShrieker.setShrieking(value.asLowerString().equals("shrieking"));
+ }
+ else if (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_21) && getBlockData() instanceof CreakingHeart creakingHeart) {
+ if (mechanism.requireEnum(CreakingHeart.State.class)) {
+ creakingHeart.setCreakingHeartState(value.asEnum(CreakingHeart.State.class));
}
- else if (isTripwire()) {
- getTripwire().setDisarmed(CoreUtilities.equalsIgnoreCase(mechanism.getValue().asString(), "disarmed"));
+ }
+ else if (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_21) && getBlockData() instanceof TrialSpawner trialSpawner) {
+ if (mechanism.requireEnum(TrialSpawner.State.class)) {
+ trialSpawner.setTrialSpawnerState(value.asEnum(TrialSpawner.State.class));
}
- else if (isSculkCatalyst()) {
- ((SculkCatalyst) material.getModernData()).setBloom(CoreUtilities.equalsIgnoreCase(mechanism.getValue().asString(), "bloom")); // TODO: 1.19
+ }
+ else if (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_21) && getBlockData() instanceof Vault vault) {
+ if (mechanism.requireEnum(Vault.State.class)) {
+ vault.setVaultState(value.asEnum(Vault.State.class));
}
- else if (isSculkShrieker()) {
- ((SculkShrieker) material.getModernData()).setShrieking(CoreUtilities.equalsIgnoreCase(mechanism.getValue().asString(), "shrieking")); // TODO: 1.19
+ }
+ else if (NMSHandler.getVersion().isAtLeast(NMSVersion.v26_2) && getBlockData() instanceof PotentSulfur potentSulfur) {
+ if (mechanism.requireEnum(PotentSulfur.State.class)) {
+ potentSulfur.setPotentSulfurState(value.asEnum(PotentSulfur.State.class));
}
}
}
+
+ @Override
+ public String getPropertyId() {
+ return "mode";
+ }
+
+ public static void register() {
+ autoRegister("mode", MaterialMode.class, ElementTag.class, false);
+ }
}
diff --git a/plugin/src/main/java/com/denizenscript/denizen/objects/properties/material/MaterialOminous.java b/plugin/src/main/java/com/denizenscript/denizen/objects/properties/material/MaterialOminous.java
new file mode 100644
index 0000000000..5f40b316e0
--- /dev/null
+++ b/plugin/src/main/java/com/denizenscript/denizen/objects/properties/material/MaterialOminous.java
@@ -0,0 +1,53 @@
+package com.denizenscript.denizen.objects.properties.material;
+
+import com.denizenscript.denizen.objects.MaterialTag;
+import com.denizenscript.denizencore.objects.Mechanism;
+import com.denizenscript.denizencore.objects.core.ElementTag;
+import org.bukkit.block.data.type.TrialSpawner;
+import org.bukkit.block.data.type.Vault;
+
+public class MaterialOminous extends MaterialProperty {
+
+ // <--[property]
+ // @object MaterialTag
+ // @name ominous
+ // @input ElementTag(Boolean)
+ // @description
+ // Controls whether a trial spawner or vault is in ominous mode.
+ // -->
+
+ public static boolean describes(MaterialTag material) {
+ return material.getModernData() instanceof TrialSpawner
+ || material.getModernData() instanceof Vault;
+ }
+
+ @Override
+ public ElementTag getPropertyValue() {
+ if (getBlockData() instanceof TrialSpawner trialSpawner) {
+ return new ElementTag(trialSpawner.isOminous());
+ }
+ return new ElementTag(as(Vault.class).isOminous());
+ }
+
+ @Override
+ public void setPropertyValue(ElementTag value, Mechanism mechanism) {
+ if (!mechanism.requireBoolean()) {
+ return;
+ }
+ if (getBlockData() instanceof TrialSpawner trialSpawner) {
+ trialSpawner.setOminous(value.asBoolean());
+ }
+ else {
+ as(Vault.class).setOminous(value.asBoolean());
+ }
+ }
+
+ @Override
+ public String getPropertyId() {
+ return "ominous";
+ }
+
+ public static void register() {
+ autoRegister("ominous", MaterialOminous.class, ElementTag.class, false);
+ }
+}
diff --git a/plugin/src/main/java/com/denizenscript/denizen/objects/properties/material/MaterialProperty.java b/plugin/src/main/java/com/denizenscript/denizen/objects/properties/material/MaterialProperty.java
index 4cbb516800..2f6046bbe2 100644
--- a/plugin/src/main/java/com/denizenscript/denizen/objects/properties/material/MaterialProperty.java
+++ b/plugin/src/main/java/com/denizenscript/denizen/objects/properties/material/MaterialProperty.java
@@ -17,4 +17,8 @@ public MaterialProperty(MaterialTag material) {
public BlockData getBlockData() {
return object.getModernData();
}
+
+ public T as(Class dataType) {
+ return (T) getBlockData();
+ }
}
diff --git a/plugin/src/main/java/com/denizenscript/denizen/objects/properties/material/MaterialSides.java b/plugin/src/main/java/com/denizenscript/denizen/objects/properties/material/MaterialSides.java
index 7da3aeb2a3..137b5671b7 100644
--- a/plugin/src/main/java/com/denizenscript/denizen/objects/properties/material/MaterialSides.java
+++ b/plugin/src/main/java/com/denizenscript/denizen/objects/properties/material/MaterialSides.java
@@ -1,118 +1,110 @@
package com.denizenscript.denizen.objects.properties.material;
+import com.denizenscript.denizen.nms.NMSHandler;
+import com.denizenscript.denizen.nms.NMSVersion;
import com.denizenscript.denizen.objects.MaterialTag;
import com.denizenscript.denizencore.objects.Mechanism;
-import com.denizenscript.denizencore.objects.ObjectTag;
+import com.denizenscript.denizencore.objects.core.ElementTag;
import com.denizenscript.denizencore.objects.core.ListTag;
-import com.denizenscript.denizencore.objects.properties.Property;
-import com.denizenscript.denizencore.objects.properties.PropertyParser;
import com.denizenscript.denizencore.utilities.CoreUtilities;
+import com.denizenscript.denizencore.utilities.debugging.DebugInternals;
import org.bukkit.block.BlockFace;
-import org.bukkit.block.data.*;
+import org.bukkit.block.data.BlockData;
+import org.bukkit.block.data.type.MossyCarpet;
import org.bukkit.block.data.type.RedstoneWire;
import org.bukkit.block.data.type.Wall;
-public class MaterialSides implements Property {
-
- public static boolean describes(ObjectTag material) {
- if (!(material instanceof MaterialTag)) {
- return false;
- }
- MaterialTag mat = (MaterialTag) material;
- if (!mat.hasModernData()) {
- return false;
- }
- BlockData data = mat.getModernData();
- if (!(data instanceof Wall) && !(data instanceof RedstoneWire)) {
- return false;
- }
- return true;
- }
-
- public static MaterialSides getFrom(ObjectTag _material) {
- if (!describes(_material)) {
- return null;
- }
- else {
- return new MaterialSides((MaterialTag) _material);
- }
- }
-
- public static final String[] handledMechs = new String[] {
- "sides", "heights"
- };
-
- public MaterialSides(MaterialTag _material) {
- material = _material;
- }
-
- MaterialTag material;
-
- public static void register() {
-
- // <--[tag]
- // @attribute
- // @returns ListTag
- // @mechanism MaterialTag.heights
- // @group properties
- // @deprecated Use 'sides'
- // @description
- // Deprecated in favor of <@link tag MaterialTag.sides>
- // -->
- // <--[tag]
- // @attribute
- // @returns ListTag
- // @mechanism MaterialTag.sides
- // @group properties
- // @description
- // Returns the list of heights for a wall block, or connections for a redstone wire, in order North|East|South|West|Vertical.
- // For wall blocks: For n/e/s/w, can be "tall", "low", or "none". For vertical, can be "tall" or "none".
- // For redstone wires: For n/e/s/w, can be "none", "side", or "up". No vertical.
- // -->
- PropertyParser.registerStaticTag(MaterialSides.class, ListTag.class, "sides", (attribute, material) -> {
- return material.getSidesList();
- }, "heights");
- }
-
- public boolean isWall() {
- return material.getModernData() instanceof Wall;
- }
-
- public Wall getWall() {
- return (Wall) material.getModernData();
+import java.util.function.BiConsumer;
+
+public class MaterialSides extends MaterialProperty {
+
+ // <--[property]
+ // @object MaterialTag
+ // @name sides
+ // @input ListTag
+ // @description
+ // Controls the heights for a wall block or mossy carpet, or connections for a redstone wire, in order North|East|South|West|Vertical.
+ // For wall blocks: For n/e/s/w, can be "tall", "low", or "none". For vertical, can be "tall" or "none".
+ // For redstone wires: For n/e/s/w, can be "none", "side", or "up". No vertical.
+ // For mossy carpets: For n/e/s/w, can be "tall", "low", or "none". Vertical controls the bottom, and can either be "bottom" or "none".
+ // -->
+
+ public static boolean describes(MaterialTag material) {
+ BlockData data = material.getModernData();
+ return data instanceof Wall
+ || data instanceof RedstoneWire
+ || (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_21) && data instanceof MossyCarpet);
}
- public boolean isWire() {
- return material.getModernData() instanceof RedstoneWire;
- }
-
- public RedstoneWire getWire() {
- return (RedstoneWire) material.getModernData();
- }
-
- public ListTag getSidesList() {
+ @Override
+ public ListTag getPropertyValue() {
ListTag list = new ListTag(5);
- if (isWall()) {
- Wall wall = getWall();
+ if (getBlockData() instanceof Wall wall) {
list.add(wall.getHeight(BlockFace.NORTH).name());
list.add(wall.getHeight(BlockFace.EAST).name());
list.add(wall.getHeight(BlockFace.SOUTH).name());
list.add(wall.getHeight(BlockFace.WEST).name());
list.add(wall.isUp() ? "TALL" : "NONE");
}
- else if (isWire()) {
- RedstoneWire wire = getWire();
+ else if (getBlockData() instanceof RedstoneWire wire) {
list.add(wire.getFace(BlockFace.NORTH).name());
list.add(wire.getFace(BlockFace.EAST).name());
list.add(wire.getFace(BlockFace.SOUTH).name());
list.add(wire.getFace(BlockFace.WEST).name());
}
+ else if (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_21) && getBlockData() instanceof MossyCarpet carpet) {
+ list.add(carpet.getHeight(BlockFace.NORTH).name());
+ list.add(carpet.getHeight(BlockFace.EAST).name());
+ list.add(carpet.getHeight(BlockFace.SOUTH).name());
+ list.add(carpet.getHeight(BlockFace.WEST).name());
+ list.add(carpet.isBottom() ? "BOTTOM" : "NONE");
+ }
return list;
}
@Override
- public String getPropertyString() {
- return getSidesList().identify();
+ public void setPropertyValue(ListTag list, Mechanism mechanism) {
+ if (getBlockData() instanceof Wall wall) {
+ if (list.size() != 5) {
+ mechanism.echoError("Invalid sides list, size must be 5.");
+ return;
+ }
+ setSide(wall::setHeight, Wall.Height.class, BlockFace.NORTH, list, 0, mechanism);
+ setSide(wall::setHeight, Wall.Height.class, BlockFace.EAST, list, 1, mechanism);
+ setSide(wall::setHeight, Wall.Height.class, BlockFace.SOUTH, list, 2, mechanism);
+ setSide(wall::setHeight, Wall.Height.class, BlockFace.WEST, list, 3, mechanism);
+ wall.setUp(CoreUtilities.equalsIgnoreCase(list.get(4), "tall"));
+ }
+ else if (getBlockData() instanceof RedstoneWire wire) {
+ if (list.size() != 4) {
+ mechanism.echoError("Invalid sides list, size must be 4.");
+ return;
+ }
+ setSide(wire::setFace, RedstoneWire.Connection.class, BlockFace.NORTH, list, 0, mechanism);
+ setSide(wire::setFace, RedstoneWire.Connection.class, BlockFace.EAST, list, 1, mechanism);
+ setSide(wire::setFace, RedstoneWire.Connection.class, BlockFace.SOUTH, list, 2, mechanism);
+ setSide(wire::setFace, RedstoneWire.Connection.class, BlockFace.WEST, list, 3, mechanism);
+ }
+ else if (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_21) && getBlockData() instanceof MossyCarpet carpet) {
+ if (list.size() != 5) {
+ mechanism.echoError("Invalid sides list, size must be 5.");
+ return;
+ }
+ setSide(carpet::setHeight, MossyCarpet.Height.class, BlockFace.NORTH, list, 0, mechanism);
+ setSide(carpet::setHeight, MossyCarpet.Height.class, BlockFace.EAST, list, 1, mechanism);
+ setSide(carpet::setHeight, MossyCarpet.Height.class, BlockFace.SOUTH, list, 2, mechanism);
+ setSide(carpet::setHeight, MossyCarpet.Height.class, BlockFace.WEST, list, 3, mechanism);
+ carpet.setBottom(CoreUtilities.equalsIgnoreCase(list.get(4), "bottom"));
+ }
+ }
+
+ public static > void setSide(BiConsumer consumer, Class type, BlockFace face, ListTag list, int index, Mechanism mechanism) {
+ T value = new ElementTag(list.get(index)).asEnum(type);
+ if (value == null) {
+ mechanism.echoError("'" + list.get(index) + "' is not a valid " + DebugInternals.getClassNameOpti(type) + ".");
+ return;
+ }
+ consumer.accept(face, value);
}
@Override
@@ -120,55 +112,28 @@ public String getPropertyId() {
return "sides";
}
- @Override
- public void adjust(Mechanism mechanism) {
+ // <--[tag]
+ // @attribute
+ // @returns ListTag
+ // @mechanism MaterialTag.heights
+ // @group properties
+ // @deprecated use 'sides'
+ // @description
+ // Deprecated in favor of <@link property MaterialTag.sides>
+ // -->
+
+ // <--[mechanism]
+ // @object MaterialTag
+ // @name heights
+ // @input ElementTag
+ // @deprecated use 'sides'
+ // @description
+ // Deprecated in favor of <@link property MaterialTag.sides>
+ // @tags
+ //
+ // -->
- // <--[mechanism]
- // @object MaterialTag
- // @name heights
- // @input ElementTag
- // @deprecated Use 'sides'
- // @description
- // Deprecated in favor of <@link mechanism MaterialTag.sides>
- // @tags
- //
- // -->
- // <--[mechanism]
- // @object MaterialTag
- // @name sides
- // @input ElementTag
- // @description
- // Sets the list of heights for a wall block, or connections for a redstone wire, in order North|East|South|West|Vertical.
- // For wall blocks: For n/e/s/w, can be "tall", "low", or "none". For vertical, can be "tall" or "none".
- // For redstone wires: For n/e/s/w, can be "none", "side", or "up". No vertical.
- // @tags
- //
- // -->
- if ((mechanism.matches("sides") || mechanism.matches("heights")) && mechanism.requireObject(ListTag.class)) {
- ListTag list = mechanism.valueAsType(ListTag.class);
- if (isWall()) {
- if (list.size() != 5) {
- mechanism.echoError("Invalid sides list, size must be 5.");
- return;
- }
- Wall wall = getWall();
- wall.setHeight(BlockFace.NORTH, Wall.Height.valueOf(list.get(0).toUpperCase()));
- wall.setHeight(BlockFace.EAST, Wall.Height.valueOf(list.get(1).toUpperCase()));
- wall.setHeight(BlockFace.SOUTH, Wall.Height.valueOf(list.get(2).toUpperCase()));
- wall.setHeight(BlockFace.WEST, Wall.Height.valueOf(list.get(3).toUpperCase()));
- wall.setUp(CoreUtilities.toLowerCase(list.get(4)).equals("tall"));
- }
- else if (isWire()) {
- if (list.size() != 4) {
- mechanism.echoError("Invalid sides list, size must be 4.");
- return;
- }
- RedstoneWire wire = getWire();
- wire.setFace(BlockFace.NORTH, RedstoneWire.Connection.valueOf(list.get(0).toUpperCase()));
- wire.setFace(BlockFace.EAST, RedstoneWire.Connection.valueOf(list.get(1).toUpperCase()));
- wire.setFace(BlockFace.SOUTH, RedstoneWire.Connection.valueOf(list.get(2).toUpperCase()));
- wire.setFace(BlockFace.WEST, RedstoneWire.Connection.valueOf(list.get(3).toUpperCase()));
- }
- }
+ public static void register() {
+ autoRegister("sides", MaterialSides.class, ListTag.class, false, "heights");
}
}
diff --git a/plugin/src/main/java/com/denizenscript/denizen/scripts/commands/BukkitCommandRegistry.java b/plugin/src/main/java/com/denizenscript/denizen/scripts/commands/BukkitCommandRegistry.java
index 63be0127f2..6e06ceaef5 100644
--- a/plugin/src/main/java/com/denizenscript/denizen/scripts/commands/BukkitCommandRegistry.java
+++ b/plugin/src/main/java/com/denizenscript/denizen/scripts/commands/BukkitCommandRegistry.java
@@ -68,9 +68,9 @@ public static void registerCitizensCommands() {
registerCommand(FishCommand.class);
registerCommand(LookcloseCommand.class);
registerCommand(PauseCommand.class);
- registerCommand(PauseCommand.ResumeCommand.class);
registerCommand(PoseCommand.class);
registerCommand(PushableCommand.class);
+ registerCommand(ResumeCommand.class);
registerCommand(SitCommand.class);
registerCommand(SleepCommand.class);
registerCommand(StandCommand.class);
diff --git a/plugin/src/main/java/com/denizenscript/denizen/scripts/commands/item/InventoryCommand.java b/plugin/src/main/java/com/denizenscript/denizen/scripts/commands/item/InventoryCommand.java
index 1bac8fa481..fe00ec1e52 100644
--- a/plugin/src/main/java/com/denizenscript/denizen/scripts/commands/item/InventoryCommand.java
+++ b/plugin/src/main/java/com/denizenscript/denizen/scripts/commands/item/InventoryCommand.java
@@ -442,7 +442,8 @@ else if (destination.getIdHolder() instanceof EntityTag entity && entity.getLivi
}
ItemTag toAdjust = new ItemTag(destination.getInventory().getItem(slotId));
Argument mechanismArgument = new Argument(dataAction);
- toAdjust.safeAdjust(new Mechanism(mechanismArgument.getPrefix().getValue(), mechanismArgument.object, scriptEntry.getContext()));
+ boolean hasValue = mechanismArgument.hasPrefix();
+ toAdjust.safeAdjust(new Mechanism(hasValue ? mechanismArgument.getPrefix().getValue() : mechanismArgument.getValue(), hasValue ? mechanismArgument.object : null, scriptEntry.getContext()));
NMSHandler.itemHelper.setInventoryItem(destination.getInventory(), toAdjust.getItemStack(), slotId);
break;
case FLAG:
diff --git a/plugin/src/main/java/com/denizenscript/denizen/scripts/commands/item/MapCommand.java b/plugin/src/main/java/com/denizenscript/denizen/scripts/commands/item/MapCommand.java
index aec090b8ce..bf48201523 100644
--- a/plugin/src/main/java/com/denizenscript/denizen/scripts/commands/item/MapCommand.java
+++ b/plugin/src/main/java/com/denizenscript/denizen/scripts/commands/item/MapCommand.java
@@ -98,7 +98,7 @@ public static void autoExecute(ScriptEntry scriptEntry,
@ArgName("resize") boolean resize,
@ArgName("script") @ArgPrefixed @ArgDefaultNull ScriptTag script,
@ArgName("dot") @ArgPrefixed @ArgDefaultNull ColorTag dot,
- @ArgName("radius") @ArgPrefixed @ArgDefaultText("-1") int radius,
+ @ArgName("radius") @ArgPrefixed @ArgDefaultText("1") int radius,
@ArgName("x") @ArgPrefixed @ArgDefaultText("0") double x,
@ArgName("y") @ArgPrefixed @ArgDefaultText("0") double y,
@ArgName("width") @ArgPrefixed @ArgDefaultText("-1") int width,
diff --git a/plugin/src/main/java/com/denizenscript/denizen/scripts/commands/npc/PauseCommand.java b/plugin/src/main/java/com/denizenscript/denizen/scripts/commands/npc/PauseCommand.java
index 7b33411c51..682be06d73 100644
--- a/plugin/src/main/java/com/denizenscript/denizen/scripts/commands/npc/PauseCommand.java
+++ b/plugin/src/main/java/com/denizenscript/denizen/scripts/commands/npc/PauseCommand.java
@@ -2,12 +2,13 @@
import com.denizenscript.denizen.Denizen;
import com.denizenscript.denizen.utilities.Utilities;
+import com.denizenscript.denizencore.exceptions.InvalidArgumentsRuntimeException;
+import com.denizenscript.denizencore.scripts.commands.generator.ArgDefaultNull;
+import com.denizenscript.denizencore.scripts.commands.generator.ArgLinear;
+import com.denizenscript.denizencore.scripts.commands.generator.ArgName;
import com.denizenscript.denizencore.utilities.debugging.Debug;
import com.denizenscript.denizen.objects.NPCTag;
-import com.denizenscript.denizencore.exceptions.InvalidArgumentsException;
-import com.denizenscript.denizencore.objects.Argument;
import com.denizenscript.denizencore.objects.core.DurationTag;
-import com.denizenscript.denizencore.objects.core.ElementTag;
import com.denizenscript.denizencore.scripts.ScriptEntry;
import com.denizenscript.denizencore.scripts.commands.AbstractCommand;
import net.citizensnpcs.trait.waypoint.Waypoints;
@@ -17,19 +18,12 @@
public class PauseCommand extends AbstractCommand {
- public static class ResumeCommand extends PauseCommand {
-
- public ResumeCommand() {
- setName("resume");
- setSyntax("resume [waypoints/activity] ()");
- }
- }
-
public PauseCommand() {
setName("pause");
setSyntax("pause [waypoints/activity] ()");
setRequiredArguments(1, 2);
isProcedural = false;
+ autoCompile();
}
// <--[command]
@@ -68,101 +62,53 @@ public PauseCommand() {
// - resume waypoints
// -->
- // <--[command]
- // @Name Resume
- // @Syntax resume [waypoints/activity] ()
- // @Required 1
- // @Plugin Citizens
- // @Short Resumes an NPC's waypoint navigation or goal activity temporarily or indefinitely.
- // @Group npc
- //
- // @Description
- // The resume command resumes an NPC's waypoint navigation or goal activity temporarily or indefinitely.
- // This works along side <@link command pause>.
- // See the documentation of the pause command for more details.
- //
- // @Tags
- //
- //
- // @Usage
- // Use to pause an NPC's waypoint navigation and then resume it.
- // - pause waypoints
- // - resume waypoints
- // -->
+ public static final Map durations = new HashMap<>();
- private Map durations = new HashMap<>();
+ public enum Type { ACTIVITY, WAYPOINTS, NAVIGATION }
- enum PauseType {ACTIVITY, WAYPOINTS, NAVIGATION}
-
- @Override
- public void parseArgs(ScriptEntry scriptEntry) throws InvalidArgumentsException {
- for (Argument arg : scriptEntry) {
- if (arg.matchesArgumentType(DurationTag.class)
- && !scriptEntry.hasObject("duration")) {
- scriptEntry.addObject("duration", arg.asType(DurationTag.class));
- }
- else if (!scriptEntry.hasObject("pause_type")
- && arg.matchesEnum(PauseType.class)) {
- scriptEntry.addObject("pause_type", arg.asElement());
- }
- else {
- arg.reportUnhandled();
- }
- }
- if (!scriptEntry.hasObject("pause_type")) {
- throw new InvalidArgumentsException("Must specify a pause type!");
- }
+ public static void autoExecute(ScriptEntry scriptEntry,
+ @ArgName("action") Type type,
+ @ArgName("duration") @ArgLinear @ArgDefaultNull DurationTag duration) {
+ executeToggle(scriptEntry, type, duration, true);
}
- @Override
- public void execute(ScriptEntry scriptEntry) {
- DurationTag duration = scriptEntry.getObjectTag("duration");
- ElementTag pauseTypeElement = scriptEntry.getElement("pause_type");
- PauseType pauseType = PauseType.valueOf(pauseTypeElement.asString().toUpperCase());
- if (scriptEntry.dbCallShouldDebug()) {
- Debug.report(scriptEntry, getName(), duration, pauseTypeElement);
- }
- NPCTag npc = null;
- if (Utilities.getEntryNPC(scriptEntry) != null) {
- npc = Utilities.getEntryNPC(scriptEntry);
+ public static void executeToggle(ScriptEntry scriptEntry, Type type, DurationTag duration, boolean pause) {
+ if (!Utilities.entryHasNPC(scriptEntry)) {
+ throw new InvalidArgumentsRuntimeException("Need to provide an NPC");
}
- pause(npc, pauseType, !scriptEntry.getCommandName().equalsIgnoreCase("RESUME"));
+ NPCData data = new NPCData(Utilities.getEntryNPC(scriptEntry), type);
+ toggle(data, pause);
if (duration != null) {
- if (durations.containsKey(npc.getCitizen().getId() + pauseType.name())) {
+ if (durations.containsKey(data)) {
try {
- Denizen.getInstance().getServer().getScheduler().cancelTask(durations.get(npc.getCitizen().getId() + pauseType.name()));
+ Denizen.getInstance().getServer().getScheduler().cancelTask(durations.get(data));
}
catch (Exception e) {
Debug.echoError(scriptEntry, "There was an error pausing that!");
Debug.echoError(scriptEntry, e);
}
}
- Debug.echoDebug(scriptEntry, "Running delayed task: Unpause " + pauseType);
- final NPCTag theNpc = npc;
- final ScriptEntry se = scriptEntry;
- durations.put(npc.getId() + pauseType.name(), Denizen.getInstance()
+ durations.put(data, Denizen.getInstance()
.getServer().getScheduler().scheduleSyncDelayedTask(Denizen.getInstance(),
() -> {
- Debug.echoDebug(se, "Running delayed task: Pausing " + pauseType);
- pause(theNpc, pauseType, false);
-
+ Debug.echoDebug(scriptEntry, "Running delayed task: " + (!pause ? "Pausing" : "Resuming") + " " + type);
+ toggle(data, !pause);
}, duration.getTicks()));
}
}
- public void pause(NPCTag denizen, PauseType pauseType, boolean pause) {
- switch (pauseType) {
- case WAYPOINTS:
- denizen.getCitizen().getOrAddTrait(Waypoints.class).getCurrentProvider().setPaused(pause);
+ public static void toggle(NPCData data, boolean pause) {
+ switch (data.type) {
+ case WAYPOINTS -> {
+ data.npc.getCitizen().getOrAddTrait(Waypoints.class).getCurrentProvider().setPaused(pause);
if (pause) {
- denizen.getNavigator().cancelNavigation();
+ data.npc.getNavigator().cancelNavigation();
}
- return;
- case ACTIVITY:
- denizen.getCitizen().getDefaultGoalController().setPaused(pause);
- return;
- case NAVIGATION:
- // TODO: Finish this
+ }
+ case ACTIVITY -> data.npc.getCitizen().getDefaultBehaviorController().setPaused(pause);
+ case NAVIGATION -> { /* TODO IMPLEMENT */ }
}
}
+
+ public record NPCData(NPCTag npc, Type type) { }
}
diff --git a/plugin/src/main/java/com/denizenscript/denizen/scripts/commands/npc/ResumeCommand.java b/plugin/src/main/java/com/denizenscript/denizen/scripts/commands/npc/ResumeCommand.java
new file mode 100644
index 0000000000..0bc01e013e
--- /dev/null
+++ b/plugin/src/main/java/com/denizenscript/denizen/scripts/commands/npc/ResumeCommand.java
@@ -0,0 +1,47 @@
+package com.denizenscript.denizen.scripts.commands.npc;
+
+import com.denizenscript.denizencore.objects.core.DurationTag;
+import com.denizenscript.denizencore.scripts.ScriptEntry;
+import com.denizenscript.denizencore.scripts.commands.AbstractCommand;
+import com.denizenscript.denizencore.scripts.commands.generator.ArgDefaultNull;
+import com.denizenscript.denizencore.scripts.commands.generator.ArgLinear;
+import com.denizenscript.denizencore.scripts.commands.generator.ArgName;
+
+public class ResumeCommand extends AbstractCommand {
+
+ public ResumeCommand() {
+ setName("resume");
+ setSyntax("resume [waypoints/activity] ()");
+ setRequiredArguments(1, 2);
+ isProcedural = false;
+ autoCompile();
+ }
+
+ // <--[command]
+ // @Name Resume
+ // @Syntax resume [waypoints/activity] ()
+ // @Required 1
+ // @Plugin Citizens
+ // @Short Resumes an NPC's waypoint navigation or goal activity temporarily or indefinitely.
+ // @Group npc
+ //
+ // @Description
+ // The resume command resumes an NPC's waypoint navigation or goal activity temporarily or indefinitely.
+ // This works along side <@link command pause>.
+ // See the documentation of the pause command for more details.
+ //
+ // @Tags
+ //
+ //
+ // @Usage
+ // Use to pause an NPC's waypoint navigation and then resume it.
+ // - pause waypoints
+ // - resume waypoints
+ // -->
+
+ public static void autoExecute(ScriptEntry scriptEntry,
+ @ArgName("action") PauseCommand.Type type,
+ @ArgName("duration") @ArgLinear @ArgDefaultNull DurationTag duration) {
+ PauseCommand.executeToggle(scriptEntry, type, duration, false);
+ }
+}
diff --git a/plugin/src/main/java/com/denizenscript/denizen/scripts/commands/player/ChatCommand.java b/plugin/src/main/java/com/denizenscript/denizen/scripts/commands/player/ChatCommand.java
index 552a8c2de2..8fcb71877f 100644
--- a/plugin/src/main/java/com/denizenscript/denizen/scripts/commands/player/ChatCommand.java
+++ b/plugin/src/main/java/com/denizenscript/denizen/scripts/commands/player/ChatCommand.java
@@ -18,6 +18,7 @@
import com.denizenscript.denizencore.tags.TagContext;
import com.denizenscript.denizencore.tags.TagManager;
import com.denizenscript.denizencore.utilities.debugging.Debug;
+import net.citizensnpcs.api.CitizensAPI;
import net.citizensnpcs.api.ai.speech.Talkable;
import net.citizensnpcs.api.ai.speech.TalkableEntity;
import net.citizensnpcs.api.ai.speech.event.NPCSpeechEvent;
@@ -137,7 +138,7 @@ public static void autoExecute(ScriptEntry scriptEntry,
public static void speak(DenizenSpeechContext speechContext) {
Entity talker = speechContext.getTalker().getEntity();
if (EntityTag.isCitizensNPC(talker)) {
- NPCSpeechEvent event = new NPCSpeechEvent(speechContext);
+ NPCSpeechEvent event = new NPCSpeechEvent(CitizensAPI.getNPCRegistry().getNPC(talker), speechContext);
Bukkit.getPluginManager().callEvent(event);
if (event.isCancelled()) {
return;
diff --git a/plugin/src/main/java/com/denizenscript/denizen/scripts/commands/player/DebugBlockCommand.java b/plugin/src/main/java/com/denizenscript/denizen/scripts/commands/player/DebugBlockCommand.java
index 5d8312f97e..defcfd3b8f 100644
--- a/plugin/src/main/java/com/denizenscript/denizen/scripts/commands/player/DebugBlockCommand.java
+++ b/plugin/src/main/java/com/denizenscript/denizen/scripts/commands/player/DebugBlockCommand.java
@@ -5,15 +5,15 @@
import com.denizenscript.denizen.objects.PlayerTag;
import com.denizenscript.denizen.utilities.BukkitImplDeprecations;
import com.denizenscript.denizen.utilities.Utilities;
-import com.denizenscript.denizencore.objects.core.ColorTag;
-import com.denizenscript.denizencore.utilities.debugging.Debug;
import com.denizenscript.denizencore.exceptions.InvalidArgumentsException;
import com.denizenscript.denizencore.objects.Argument;
+import com.denizenscript.denizencore.objects.core.ColorTag;
import com.denizenscript.denizencore.objects.core.DurationTag;
import com.denizenscript.denizencore.objects.core.ElementTag;
import com.denizenscript.denizencore.objects.core.ListTag;
import com.denizenscript.denizencore.scripts.ScriptEntry;
import com.denizenscript.denizencore.scripts.commands.AbstractCommand;
+import com.denizenscript.denizencore.utilities.debugging.Debug;
import java.util.Collections;
import java.util.List;
@@ -43,6 +43,12 @@ public DebugBlockCommand() {
//
// If arguments are unspecified, the default color is white, the default player is the linked player, the default name is none, and the default duration is 10 seconds.
//
+ // Note that on MC 1.21+ this has limitations (within Minecraft itself), namely:
+ // - the color is always green.
+ // - the duration is always 10 seconds.
+ // - the name can only be a LocationTag and defaults to the debug block's location if unspecified.
+ // - debug blocks can't be cleared.
+ //
// @Tags
// None
//
diff --git a/plugin/src/main/java/com/denizenscript/denizen/scripts/commands/player/TitleCommand.java b/plugin/src/main/java/com/denizenscript/denizen/scripts/commands/player/TitleCommand.java
index b503b62aa7..0e85ea309f 100644
--- a/plugin/src/main/java/com/denizenscript/denizen/scripts/commands/player/TitleCommand.java
+++ b/plugin/src/main/java/com/denizenscript/denizen/scripts/commands/player/TitleCommand.java
@@ -2,19 +2,16 @@
import com.denizenscript.denizen.tags.BukkitTagContext;
import com.denizenscript.denizen.utilities.Utilities;
+import com.denizenscript.denizencore.scripts.commands.generator.*;
+import com.denizenscript.denizencore.tags.ParseableTag;
import com.denizenscript.denizencore.utilities.debugging.Debug;
import com.denizenscript.denizen.nms.NMSHandler;
import com.denizenscript.denizen.objects.PlayerTag;
-import com.denizenscript.denizencore.exceptions.InvalidArgumentsException;
-import com.denizenscript.denizencore.objects.*;
import com.denizenscript.denizencore.objects.core.DurationTag;
-import com.denizenscript.denizencore.objects.core.ElementTag;
-import com.denizenscript.denizencore.objects.core.ListTag;
import com.denizenscript.denizencore.scripts.ScriptEntry;
import com.denizenscript.denizencore.scripts.commands.AbstractCommand;
import com.denizenscript.denizencore.tags.TagManager;
-import java.util.Collections;
import java.util.List;
public class TitleCommand extends AbstractCommand {
@@ -23,8 +20,9 @@ public TitleCommand() {
setName("title");
setSyntax("title (title:) (subtitle:) (fade_in:/{1s}) (stay:/{3s}) (fade_out:/{1s}) (targets:|...) (per_player)");
setRequiredArguments(1, 7);
- setParseArgs(false);
+ addRemappedPrefixes("targets", "target");
isProcedural = false;
+ autoCompile();
}
// <--[command]
@@ -58,83 +56,45 @@ public TitleCommand() {
// - title "title:Tatooine" "subtitle:What a desolate place this is."
// -->
- @Override
- public void parseArgs(ScriptEntry scriptEntry) throws InvalidArgumentsException {
- for (Argument arg : ArgumentHelper.interpret(scriptEntry, scriptEntry.getOriginalArguments())) {
- if (arg.matchesPrefix("title")) {
- scriptEntry.addObject("title", arg.asElement());
- }
- else if (arg.matchesPrefix("subtitle")) {
- scriptEntry.addObject("subtitle", arg.asElement());
- }
- else if (arg.matchesPrefix("fade_in")) {
- String argStr = TagManager.tag(arg.getValue(), scriptEntry.getContext());
- scriptEntry.addObject("fade_in", DurationTag.valueOf(argStr, scriptEntry.context));
- }
- else if (arg.matchesPrefix("stay")) {
- String argStr = TagManager.tag(arg.getValue(), scriptEntry.getContext());
- scriptEntry.addObject("stay", DurationTag.valueOf(argStr, scriptEntry.context));
- }
- else if (arg.matchesPrefix("fade_out")) {
- String argStr = TagManager.tag(arg.getValue(), scriptEntry.getContext());
- scriptEntry.addObject("fade_out", DurationTag.valueOf(argStr, scriptEntry.context));
- }
- else if (arg.matchesPrefix("targets", "target")) {
- scriptEntry.addObject("targets", ListTag.getListFor(TagManager.tagObject(arg.getValue(), scriptEntry.getContext()), scriptEntry.getContext()).filter(PlayerTag.class, scriptEntry));
+ public static void autoExecute(ScriptEntry scriptEntry,
+ @ArgName("title") @ArgPrefixed @ArgUnparsed @ArgDefaultNull String strTitle,
+ @ArgName("subtitle") @ArgPrefixed @ArgUnparsed @ArgDefaultNull String strSubTitle,
+ @ArgName("fade_in") @ArgPrefixed @ArgDefaultText("1s") DurationTag fadeIn,
+ @ArgName("stay") @ArgPrefixed @ArgDefaultText("3s") DurationTag stay,
+ @ArgName("fade_out") @ArgPrefixed @ArgDefaultText("1s") DurationTag fadeOut,
+ @ArgName("targets") @ArgPrefixed @ArgDefaultNull @ArgSubType(PlayerTag.class) List players,
+ @ArgName("per_player") boolean perPlayer) {
+ if (strTitle == null && strSubTitle == null) {
+ Debug.echoError("Must have a title or subtitle!");
+ return;
+ }
+ if (players == null) {
+ if (!Utilities.entryHasPlayer(scriptEntry)) {
+ Debug.echoError("Must specify target(s).");
+ return;
}
- else if (!scriptEntry.hasObject("per_player")
- && arg.matches("per_player")) {
- scriptEntry.addObject("per_player", new ElementTag(true));
+ players = List.of(Utilities.getEntryPlayer(scriptEntry));
+ }
+ BukkitTagContext context = perPlayer ? new BukkitTagContext((BukkitTagContext) scriptEntry.getContext()) : (BukkitTagContext) scriptEntry.getContext();
+ ParseableTag parseableTitle = TagManager.parseTextToTag(strTitle, context);
+ ParseableTag parseableSubTitle = TagManager.parseTextToTag(strSubTitle, context);
+ String parsedTitle = perPlayer ? null : parse(parseableTitle, context);
+ String parsedSubTitle = perPlayer ? null : parse(parseableSubTitle, context);
+ for (PlayerTag player : players) {
+ if (!player.isOnline()) {
+ Debug.echoDebug(scriptEntry, "Player is offline, can't send title to them. Skipping.");
+ continue;
}
- else {
- arg.reportUnhandled();
+ if (perPlayer) {
+ context.player = player;
+ parsedTitle = parse(parseableTitle, context);
+ parsedSubTitle = parse(parseableSubTitle, context);
}
+ NMSHandler.packetHelper.showTitle(player.getPlayerEntity(), parsedTitle, parsedSubTitle, fadeIn.getTicksAsInt(), stay.getTicksAsInt(), fadeOut.getTicksAsInt());
}
- if (!scriptEntry.hasObject("title") && !scriptEntry.hasObject("subtitle")) {
- throw new InvalidArgumentsException("Must have a title or subtitle!");
- }
- scriptEntry.defaultObject("fade_in", new DurationTag(1)).defaultObject("stay", new DurationTag(3))
- .defaultObject("fade_out", new DurationTag(1))
- .defaultObject("targets", Collections.singletonList(Utilities.getEntryPlayer(scriptEntry)))
- .defaultObject("subtitle", new ElementTag("")).defaultObject("title", new ElementTag(""));
}
- @Override
- public void execute(ScriptEntry scriptEntry) {
- String title = scriptEntry.getElement("title").asString();
- String subtitle = scriptEntry.getElement("subtitle").asString();
- DurationTag fade_in = scriptEntry.getObjectTag("fade_in");
- DurationTag stay = scriptEntry.getObjectTag("stay");
- DurationTag fade_out = scriptEntry.getObjectTag("fade_out");
- List targets = (List) scriptEntry.getObject("targets");
- ElementTag perPlayerObj = scriptEntry.getElement("per_player");
- boolean perPlayer = perPlayerObj != null && perPlayerObj.asBoolean();
- BukkitTagContext context = (BukkitTagContext) scriptEntry.getContext();
- if (!perPlayer) {
- title = TagManager.tag(title, context);
- subtitle = TagManager.tag(subtitle, context);
- }
- if (scriptEntry.dbCallShouldDebug()) {
- Debug.report(scriptEntry, getName(), db("title", title), db("subtitle", subtitle), fade_in, stay, fade_out, db("targets", targets), perPlayerObj);
- }
- for (PlayerTag player : targets) {
- if (player != null) {
- if (!player.isOnline()) {
- Debug.echoDebug(scriptEntry, "Player is offline, can't send title to them. Skipping.");
- continue;
- }
- String personalTitle = title;
- String personalSubtitle = subtitle;
- if (perPlayer) {
- context.player = player;
- personalTitle = TagManager.tag(personalTitle, context);
- personalSubtitle = TagManager.tag(personalSubtitle, context);
- }
- NMSHandler.packetHelper.showTitle(player.getPlayerEntity(), personalTitle, personalSubtitle, fade_in.getTicksAsInt(), stay.getTicksAsInt(), fade_out.getTicksAsInt());
- }
- else {
- Debug.echoError("Sent title to non-existent player!?");
- }
- }
+ public static String parse(ParseableTag tag, BukkitTagContext context) {
+ return tag == null ? "" : tag.parse(context).toString();
}
}
diff --git a/plugin/src/main/java/com/denizenscript/denizen/scripts/commands/world/CopyBlockCommand.java b/plugin/src/main/java/com/denizenscript/denizen/scripts/commands/world/CopyBlockCommand.java
index 05e42edccb..b0f939b657 100644
--- a/plugin/src/main/java/com/denizenscript/denizen/scripts/commands/world/CopyBlockCommand.java
+++ b/plugin/src/main/java/com/denizenscript/denizen/scripts/commands/world/CopyBlockCommand.java
@@ -1,17 +1,18 @@
package com.denizenscript.denizen.scripts.commands.world;
+import com.denizenscript.denizen.objects.LocationTag;
import com.denizenscript.denizen.utilities.PaperAPITools;
import com.denizenscript.denizen.utilities.blocks.FullBlockData;
-import com.denizenscript.denizencore.utilities.debugging.Debug;
-import com.denizenscript.denizen.objects.LocationTag;
import com.denizenscript.denizencore.exceptions.InvalidArgumentsException;
import com.denizenscript.denizencore.objects.Argument;
import com.denizenscript.denizencore.objects.core.ElementTag;
import com.denizenscript.denizencore.scripts.ScriptEntry;
import com.denizenscript.denizencore.scripts.commands.AbstractCommand;
+import com.denizenscript.denizencore.utilities.debugging.Debug;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.block.*;
+import org.bukkit.block.sign.Side;
import org.bukkit.inventory.InventoryHolder;
import java.util.ArrayList;
@@ -110,6 +111,12 @@ else if (sourceState instanceof Sign) {
for (String line : ((Sign) sourceState).getLines()) {
PaperAPITools.instance.setSignLine(((Sign) updateState), n++, line);
}
+ if (SignCommand.SIGN_SIDES_SUPPORTED) {
+ n = 0;
+ for (String line : ((Sign) sourceState).getSide(Side.BACK).getLines()) {
+ PaperAPITools.instance.setSignBackLine(((Sign) updateState), n++, line);
+ }
+ }
}
else if (sourceState instanceof Skull) {
((Skull) updateState).setSkullType(((Skull) sourceState).getSkullType());
diff --git a/plugin/src/main/java/com/denizenscript/denizen/scripts/commands/world/GameRuleCommand.java b/plugin/src/main/java/com/denizenscript/denizen/scripts/commands/world/GameRuleCommand.java
index 4a2e65b188..3efb74c13d 100644
--- a/plugin/src/main/java/com/denizenscript/denizen/scripts/commands/world/GameRuleCommand.java
+++ b/plugin/src/main/java/com/denizenscript/denizen/scripts/commands/world/GameRuleCommand.java
@@ -1,17 +1,18 @@
package com.denizenscript.denizen.scripts.commands.world;
-import com.denizenscript.denizencore.utilities.debugging.Debug;
import com.denizenscript.denizen.objects.WorldTag;
+import com.denizenscript.denizen.utilities.world.GameRuleReflect;
import com.denizenscript.denizencore.exceptions.InvalidArgumentsException;
import com.denizenscript.denizencore.objects.Argument;
import com.denizenscript.denizencore.objects.core.ElementTag;
import com.denizenscript.denizencore.scripts.ScriptEntry;
import com.denizenscript.denizencore.scripts.commands.AbstractCommand;
+import com.denizenscript.denizencore.utilities.debugging.Debug;
+import com.denizenscript.denizencore.utilities.debugging.DebugInternals;
import org.bukkit.Bukkit;
+import org.bukkit.GameRule;
import org.bukkit.generator.WorldInfo;
-import java.util.stream.Collectors;
-
public class GameRuleCommand extends AbstractCommand {
public GameRuleCommand() {
@@ -31,24 +32,25 @@ public GameRuleCommand() {
//
// @Description
// Sets a gamerule on the world. A list of valid gamerules can be found here: <@link url https://minecraft.wiki/w/Game_rule>
- // Note: Be careful, gamerules are CASE SENSITIVE.
//
// @Tags
// ]>
//
// @Usage
// Use to disable fire spreading in world "Adventure".
- // - gamerule Adventure doFireTick false
+ // - gamerule Adventure fire_spread_radius_around_player 0
//
// @Usage
// Use to avoid mobs from destroying blocks (creepers, endermen...) and picking items up (zombies, skeletons...) in world "Adventure".
- // - gamerule Adventure mobGriefing false
+ // - gamerule Adventure mob_griefing false
// -->
@Override
public void addCustomTabCompletions(TabCompletionsBuilder tab) {
- tab.add(Bukkit.getWorlds().get(0).getGameRules());
- tab.add(Bukkit.getWorlds().stream().map(WorldInfo::getName).collect(Collectors.toSet()));
+ for (GameRule> gameRule : GameRuleReflect.values()) {
+ tab.add(GameRuleReflect.getName(gameRule));
+ }
+ tab.add(Bukkit.getWorlds().stream().map(WorldInfo::getName).toList());
}
@Override
@@ -82,12 +84,37 @@ else if (!scriptEntry.hasObject("value")) {
@Override
public void execute(ScriptEntry scriptEntry) {
WorldTag world = scriptEntry.getObjectTag("world");
- ElementTag gamerule = scriptEntry.getElement("gamerule");
- ElementTag value = scriptEntry.getElement("value");
+ ElementTag gameRuleInput = scriptEntry.getElement("gamerule");
+ ElementTag valueInput = scriptEntry.getElement("value");
if (scriptEntry.dbCallShouldDebug()) {
- Debug.report(scriptEntry, getName(), world, gamerule, value);
+ Debug.report(scriptEntry, getName(), world, gameRuleInput, valueInput);
+ }
+ GameRule gameRule = GameRuleReflect.getByName(gameRuleInput.asString());
+ if (gameRule == null) {
+ Debug.echoError("Invalid game rule specified: " + gameRuleInput.asString() + '.');
+ return;
+ }
+ Class> gameRuleType = GameRuleReflect.getType(gameRule);
+ Object convertedValue;
+ if (gameRuleType == Integer.class) {
+ if (!valueInput.isInt()) {
+ Debug.echoError("Invalid value specified: must be a number.");
+ return;
+ }
+ convertedValue = valueInput.asInt();
+ }
+ else if (gameRuleType == Boolean.class) {
+ if (!valueInput.isBoolean()) {
+ Debug.echoError("Invalid value specified: must be a boolean.");
+ return;
+ }
+ convertedValue = valueInput.asBoolean();
+ }
+ else {
+ Debug.echoError("Unrecognized game rule type '" + DebugInternals.getFullClassNameOpti(gameRuleType) + "'! Please report this to the developers.");
+ return;
}
- if (!world.getWorld().setGameRuleValue(gamerule.asString(), value.asString())) {
+ if (!world.getWorld().setGameRule(gameRule, convertedValue)) {
Debug.echoError(scriptEntry, "Invalid gamerule!");
}
}
diff --git a/plugin/src/main/java/com/denizenscript/denizen/scripts/commands/world/SignCommand.java b/plugin/src/main/java/com/denizenscript/denizen/scripts/commands/world/SignCommand.java
index 5623bdc060..2904ef64ce 100644
--- a/plugin/src/main/java/com/denizenscript/denizen/scripts/commands/world/SignCommand.java
+++ b/plugin/src/main/java/com/denizenscript/denizen/scripts/commands/world/SignCommand.java
@@ -1,16 +1,18 @@
package com.denizenscript.denizen.scripts.commands.world;
+import com.denizenscript.denizen.nms.NMSHandler;
+import com.denizenscript.denizen.nms.NMSVersion;
+import com.denizenscript.denizen.objects.LocationTag;
import com.denizenscript.denizen.objects.MaterialTag;
import com.denizenscript.denizen.objects.properties.material.MaterialDirectional;
import com.denizenscript.denizen.utilities.Utilities;
-import com.denizenscript.denizencore.utilities.debugging.Debug;
-import com.denizenscript.denizen.objects.LocationTag;
import com.denizenscript.denizencore.exceptions.InvalidArgumentsException;
import com.denizenscript.denizencore.objects.Argument;
import com.denizenscript.denizencore.objects.core.ElementTag;
import com.denizenscript.denizencore.objects.core.ListTag;
import com.denizenscript.denizencore.scripts.ScriptEntry;
import com.denizenscript.denizencore.scripts.commands.AbstractCommand;
+import com.denizenscript.denizencore.utilities.debugging.Debug;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
@@ -19,6 +21,8 @@
public class SignCommand extends AbstractCommand {
+ public static final boolean SIGN_SIDES_SUPPORTED = NMSHandler.getVersion().isAtLeast(NMSVersion.v1_20);
+
public SignCommand() {
setName("sign");
setSyntax("sign (type:{automatic}/sign_post/wall_sign) (material:) [|...] [] (direction:north/east/south/west)");
diff --git a/plugin/src/main/java/com/denizenscript/denizen/scripts/containers/core/ItemScriptHelper.java b/plugin/src/main/java/com/denizenscript/denizen/scripts/containers/core/ItemScriptHelper.java
index 2a416d20b0..c57b5f43cf 100644
--- a/plugin/src/main/java/com/denizenscript/denizen/scripts/containers/core/ItemScriptHelper.java
+++ b/plugin/src/main/java/com/denizenscript/denizen/scripts/containers/core/ItemScriptHelper.java
@@ -60,14 +60,17 @@ public static void removeDenizenRecipes() {
Iterator recipeIterator = Bukkit.recipeIterator();
ArrayList keys = new ArrayList<>();
while (recipeIterator.hasNext()) {
- if (recipeIterator.next() instanceof Keyed keyed && keyed.getKey().getNamespace().equals("denizen")) {
- if (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_21)) {
- keys.add(keyed.getKey());
- }
- else {
- recipeIterator.remove();
+ try {
+ if (recipeIterator.next() instanceof Keyed keyed && keyed.getKey().getNamespace().equals("denizen")) {
+ if (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_21)) {
+ keys.add(keyed.getKey());
+ }
+ else {
+ recipeIterator.remove();
+ }
}
}
+ catch (AbstractMethodError ignored) {} // TODO: 26.1: work around Spigot bug
}
if (!keys.isEmpty()) {
NMSHandler.itemHelper.removeRecipes(keys);
diff --git a/plugin/src/main/java/com/denizenscript/denizen/tags/core/ServerTagBase.java b/plugin/src/main/java/com/denizenscript/denizen/tags/core/ServerTagBase.java
index f8bda93241..08122dc15d 100644
--- a/plugin/src/main/java/com/denizenscript/denizen/tags/core/ServerTagBase.java
+++ b/plugin/src/main/java/com/denizenscript/denizen/tags/core/ServerTagBase.java
@@ -14,6 +14,7 @@
import com.denizenscript.denizen.utilities.*;
import com.denizenscript.denizen.utilities.depends.Depends;
import com.denizenscript.denizen.utilities.inventory.SlotHelper;
+import com.denizenscript.denizen.utilities.world.GameRuleReflect;
import com.denizenscript.denizencore.DenizenCore;
import com.denizenscript.denizencore.events.ScriptEvent;
import com.denizenscript.denizencore.objects.Mechanism;
@@ -639,11 +640,7 @@ else if (param.shouldBeType(EntityTag.class)) {
// Returns a list of all available gamerules on the server.
// -->
tagProcessor.registerStaticTag(ListTag.class, "gamerules", (attribute, object) -> {
- ListTag gamerules = new ListTag();
- for (GameRule> rule : GameRule.values()) {
- gamerules.add(rule.getName());
- }
- return gamerules;
+ return new ListTag(Arrays.asList(GameRuleReflect.values()), gameRule -> new ElementTag(GameRuleReflect.getName(gameRule), true));
});
// <--[tag]
@@ -1123,6 +1120,16 @@ else if (param.shouldBeType(EntityTag.class)) {
return new ElementTag(Denizen.versionTag);
});
+ // <--[tag]
+ // @attribute
+ // @returns ElementTag
+ // @description
+ // Returns the name of the Bukkit platform, such as "Paper".
+ // -->
+ tagProcessor.registerStaticTag(ElementTag.class, "bukkit_name", (attribute, object) -> {
+ return new ElementTag(Bukkit.getName());
+ });
+
// <--[tag]
// @attribute
// @returns ElementTag
@@ -1660,7 +1667,7 @@ else if (nameLow.startsWith(matchInput) && (newMatch.isOnline() == matchPlayer.i
// -->
tagProcessor.registerTag(ListTag.class, "recent_tps", (attribute, object) -> {
ListTag recentTPS = new ListTag(3);
- for (double tps : NMSHandler.instance.getRecentTps()) {
+ for (double tps : PaperAPITools.instance.getRecentTps()) {
recentTPS.addObject(new ElementTag(tps));
}
return recentTPS;
@@ -2025,6 +2032,32 @@ else if (nameLow.startsWith(matchInput) && (newMatch.isOnline() == matchPlayer.i
}
});
+ if (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_21)) {
+
+ // <--[mechanism]
+ // @object server
+ // @name links
+ // @input ListTag(MapTag)
+ // @description
+ // Sets the default server links. Each item in the list must be a MapTag in <@link language Server Links Format>.
+ // Generally prefer <@link mechanism server.add_links>.
+ // -->
+ tagProcessor.registerMechanism("links", false, ListTag.class, (object, mechanism, input) -> {
+ Utilities.replaceServerLinks(Bukkit.getServerLinks(), input, mechanism.context);
+ });
+
+ // <--[mechanism]
+ // @object server
+ // @name add_links
+ // @input ListTag(MapTag)
+ // @description
+ // Adds links to the default server links. Each item in the list must be a MapTag in <@link language Server Links Format>.
+ // -->
+ tagProcessor.registerMechanism("add_links", false, ListTag.class, (object, mechanism, input) -> {
+ Utilities.fillServerLinks(Bukkit.getServerLinks(), input, mechanism.context);
+ });
+ }
+
// <--[mechanism]
// @object server
// @name default_colors
diff --git a/plugin/src/main/java/com/denizenscript/denizen/utilities/BukkitImplDeprecations.java b/plugin/src/main/java/com/denizenscript/denizen/utilities/BukkitImplDeprecations.java
index 8c862c1172..19cd68ef9d 100644
--- a/plugin/src/main/java/com/denizenscript/denizen/utilities/BukkitImplDeprecations.java
+++ b/plugin/src/main/java/com/denizenscript/denizen/utilities/BukkitImplDeprecations.java
@@ -230,11 +230,6 @@ public class BukkitImplDeprecations {
public static Warning itemEnchantmentsLegacy = new Warning("itemEnchantmentsLegacy", "The tag 'ItemTag.enchantments' is deprecated: use enchantment_map, or enchantment_types.");
public static Warning echantmentTagUpdate = new Warning("echantmentTagUpdate", "Several legacy enchantment-related tags are deprecated in favor of using EnchantmentTag.");
- // Added 2022/01/30, made very-slow 2022/12/31, made slow 2024/01/02, made normal 2025/01/15.
- // 2023-year-end commonality: #29
- // Safe to remove now.
- public static Warning entityItemEnderman = new Warning("entityItemEnderman", "The property 'entity.item' for endermen has been replaced by 'entity.material' due to usage of block materials.");
-
// Added 2021/06/19, made very-slow 2022/12/31, made slow 2024/01/02, made normal 2025/01/15.
public static Warning entityMapTraceTag = new Warning("entityMapTraceTag", "The tag 'EntityTag.map_trace' is deprecated in favor of EntityTag.trace_framed_map");
@@ -267,6 +262,9 @@ public class BukkitImplDeprecations {
// Added 2025/07/10
public static Warning entityKnockback = new Warning("entityKnockback", "The 'EntityTag.knockback' property is deprecated. You should adjust the knockback enchantment on the weapon itself.");
+ // Added 2025/10/24
+ public static Warning explosionPrimeDetermination = new Warning("explosionPrimeDetermination", "The determination to control fire in the ' explosion primes' event is now formatted as 'FIRE:'.");
+
// ==================== SLOW deprecations ====================
// These aren't spammed, but will show up repeatedly until fixed. Server owners will probably notice them.
@@ -485,11 +483,17 @@ public class BukkitImplDeprecations {
// Added 2025/08/23
public static Warning advancementBackgroundFormat = new FutureWarning("advancementBackgroundFormat", "The 'background:' input in the advancement command no longer uses the 'textures/' path or '.png' suffix, so for example 'minecraft:textures/gui/advancements/backgrounds/stone.png' would be 'minecraft:gui/advancements/backgrounds/stone'.");
+ // Added 2025/09/07
+ public static Warning brewingStandConsumeDetermination = new FutureWarning("brewingStandConsumeDetermination", "The 'consuming' and 'not_consuming' determinations in the 'brewing stand fueled' event have been deprecated in favor of 'CONSUMING:'.");
+
// Added 2025/09/22
public static Warning playerSteerEntityEvent = new FutureWarning("playerSteerEntityEvent", "The 'player steers ' event is deprecated in favor of the 'player input' event in MC 1.21+.");
// ==================== PAST deprecations of things that are already gone but still have a warning left behind ====================
+ // Removed upstream 2025/02/15
+ public static Warning chunkRegeneration = new StrongWarning("chunkRegeneration", "'ChunkTag.regenerate' is deprecated: support for chunk regeneration has been removed upstream.");
+
// Removed upstream 2023/10/29 without warning.
public static Warning npcHologramDirection = new StrongWarning("npcHologramDirection", "NPCTag's 'hologram_direction' is deprecated: it was removed from Citizens. Ask in the Citizens channel on the Discord if you need it.");
diff --git a/plugin/src/main/java/com/denizenscript/denizen/utilities/FormattedTextHelper.java b/plugin/src/main/java/com/denizenscript/denizen/utilities/FormattedTextHelper.java
index 67392b5fa9..f253ece61c 100644
--- a/plugin/src/main/java/com/denizenscript/denizen/utilities/FormattedTextHelper.java
+++ b/plugin/src/main/java/com/denizenscript/denizen/utilities/FormattedTextHelper.java
@@ -19,6 +19,8 @@
import net.md_5.bungee.chat.ComponentSerializer;
import net.md_5.bungee.chat.VersionedComponentSerializer;
+import java.net.URI;
+import java.net.URISyntaxException;
import java.util.List;
public class FormattedTextHelper {
@@ -798,13 +800,18 @@ else if (code == 'o' || code == 'O') {
started = i + 1;
}
else if (i + "https://a.".length() < chars.length && chars[i] == 'h' && chars[i + 1] == 't' && chars[i + 2] == 't' && chars[i + 3] == 'p') {
- String subStr = str.substring(i, i + "https://a.".length());
- if (subStr.startsWith("https://") || subStr.startsWith("http://")) {
- int nextSpace = CoreUtilities.indexOfAny(str, i, ' ', '\t', '\n', ChatColor.COLOR_CHAR);
- if (nextSpace == -1) {
- nextSpace = str.length();
+ if (str.startsWith("https://", i) || str.startsWith("http://", i)) {
+ int urlEnd = indexOfUrlEnd(chars, i);
+ if (urlEnd - i < "https://a.".length()) {
+ continue;
+ }
+ String url = str.substring(i, urlEnd);
+ try {
+ new URI(url);
+ }
+ catch (URISyntaxException ignored) {
+ continue;
}
- String url = str.substring(i, nextSpace);
nextText.setText(nextText.getText() + str.substring(started, i));
base.addExtra(nextText);
lastText = nextText;
@@ -813,8 +820,8 @@ else if (i + "https://a.".length() < chars.length && chars[i] == 'h' && chars[i
TextComponent clickableText = new TextComponent(url);
clickableText.setClickEvent(new ClickEvent(ClickEvent.Action.OPEN_URL, url));
lastText.addExtra(clickableText);
- i = nextSpace - 1;
- started = nextSpace;
+ i = urlEnd - 1;
+ started = urlEnd;
continue;
}
}
@@ -826,6 +833,17 @@ else if (i + "https://a.".length() < chars.length && chars[i] == 'h' && chars[i
return new BaseComponent[] { cleanBase && !optimize ? root : base };
}
+ public static final AsciiMatcher URL_VALID = new AsciiMatcher(AsciiMatcher.LETTERS_LOWER + AsciiMatcher.LETTERS_UPPER + AsciiMatcher.DIGITS + "-._~:/?#@!$&'()*+,;=%");
+
+ public static int indexOfUrlEnd(char[] chars, int start) {
+ for (int i = start; i < chars.length; i++) {
+ if (!URL_VALID.isMatch(chars[i])) {
+ return i;
+ }
+ }
+ return chars.length;
+ }
+
public static int indexOfLastColorBlockStart(String text) {
int result = text.lastIndexOf(ChatColor.COLOR_CHAR + "[");
if (result == -1 || text.indexOf(']', result + 2) != -1) {
diff --git a/plugin/src/main/java/com/denizenscript/denizen/utilities/MultiVersionHelper1_19.java b/plugin/src/main/java/com/denizenscript/denizen/utilities/MultiVersionHelper1_19.java
index e649c9aec1..7413b4dbdf 100644
--- a/plugin/src/main/java/com/denizenscript/denizen/utilities/MultiVersionHelper1_19.java
+++ b/plugin/src/main/java/com/denizenscript/denizen/utilities/MultiVersionHelper1_19.java
@@ -20,7 +20,7 @@ public static boolean colorIsApplicable(EntityType type) {
// TODO Frog variants technically have registries on all supported versions
public static String getColor(Entity entity, boolean includeDeprecated) {
if (entity instanceof Frog frog) {
- return String.valueOf(frog.getVariant());
+ return Utilities.keyedToString(frog.getVariant());
}
else if (entity instanceof Boat boat) {
if (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_21)) {
diff --git a/plugin/src/main/java/com/denizenscript/denizen/utilities/PaperAPITools.java b/plugin/src/main/java/com/denizenscript/denizen/utilities/PaperAPITools.java
index 2625cc5ced..1c516f02cd 100644
--- a/plugin/src/main/java/com/denizenscript/denizen/utilities/PaperAPITools.java
+++ b/plugin/src/main/java/com/denizenscript/denizen/utilities/PaperAPITools.java
@@ -3,18 +3,19 @@
import com.denizenscript.denizen.nms.NMSHandler;
import com.denizenscript.denizen.nms.NMSVersion;
import com.denizenscript.denizen.scripts.commands.entity.TeleportCommand;
+import com.denizenscript.denizen.scripts.commands.world.SignCommand;
import com.denizenscript.denizen.scripts.containers.core.ItemScriptContainer;
import com.denizenscript.denizen.utilities.packets.NetworkInterceptHelper;
+import com.denizenscript.denizencore.objects.Mechanism;
+import com.denizenscript.denizencore.objects.core.ElementTag;
import com.denizenscript.denizencore.utilities.ReflectionHelper;
import com.denizenscript.denizencore.utilities.debugging.Debug;
import net.md_5.bungee.api.chat.BaseComponent;
import org.bukkit.*;
import org.bukkit.block.Sign;
+import org.bukkit.block.sign.Side;
import org.bukkit.command.CommandSender;
-import org.bukkit.entity.Entity;
-import org.bukkit.entity.LivingEntity;
-import org.bukkit.entity.Player;
-import org.bukkit.entity.TextDisplay;
+import org.bukkit.entity.*;
import org.bukkit.event.entity.CreatureSpawnEvent;
import org.bukkit.event.entity.PlayerDeathEvent;
import org.bukkit.event.inventory.InventoryType;
@@ -25,6 +26,8 @@
import org.bukkit.util.Consumer;
import java.lang.invoke.MethodHandle;
+import java.net.URI;
+import java.util.Arrays;
import java.util.List;
import java.util.Set;
import java.util.function.Predicate;
@@ -84,12 +87,25 @@ public String getPlayerListName(Player player) {
return player.getPlayerListName();
}
- public String[] getSignLines(Sign sign) {
- return sign.getLines();
+ public List getSignLines(Sign sign) {
+ return Arrays.asList(SignCommand.SIGN_SIDES_SUPPORTED ? sign.getSide(Side.FRONT).getLines() : sign.getLines());
+ }
+
+ public List