From 40307576f94ed405adbcb8d59637004bedd3d562 Mon Sep 17 00:00:00 2001 From: sovdee <10354869+sovdeeth@users.noreply.github.com> Date: Mon, 1 Jul 2024 14:41:36 +0200 Subject: [PATCH 1/7] fix exception when removing air from slot (#6836) * fix exception when removing air from slot * Update 6830-remove air from slot.sk --- .../ch/njol/skript/bukkitutil/ItemUtils.java | 35 +++++++++++++------ .../regressions/6830-remove air from slot.sk | 4 +++ 2 files changed, 29 insertions(+), 10 deletions(-) create mode 100644 src/test/skript/tests/regressions/6830-remove air from slot.sk diff --git a/src/main/java/ch/njol/skript/bukkitutil/ItemUtils.java b/src/main/java/ch/njol/skript/bukkitutil/ItemUtils.java index 31bf99c2d56..216be44b918 100644 --- a/src/main/java/ch/njol/skript/bukkitutil/ItemUtils.java +++ b/src/main/java/ch/njol/skript/bukkitutil/ItemUtils.java @@ -42,9 +42,17 @@ public class ItemUtils { * @return Damage. */ public static int getDamage(ItemStack itemStack) { - ItemMeta meta = itemStack.getItemMeta(); - if (meta instanceof Damageable) - return ((Damageable) meta).getDamage(); + return getDamage(itemStack.getItemMeta()); + } + + /** + * Gets damage/durability of an itemmeta, or 0 if it does not have damage. + * @param itemMeta ItemMeta. + * @return Damage. + */ + public static int getDamage(ItemMeta itemMeta) { + if (itemMeta instanceof Damageable) + return ((Damageable) itemMeta).getDamage(); return 0; // Non damageable item } @@ -143,15 +151,22 @@ public static Material asItem(Material type) { /** * Tests whether two item stacks are of the same type, i.e. it ignores the amounts. * - * @param is1 - * @param is2 + * @param itemStack1 + * @param itemStack2 * @return Whether the item stacks are of the same type */ - public static boolean itemStacksEqual(final @Nullable ItemStack is1, final @Nullable ItemStack is2) { - if (is1 == null || is2 == null) - return is1 == is2; - return is1.getType() == is2.getType() && ItemUtils.getDamage(is1) == ItemUtils.getDamage(is2) - && is1.getItemMeta().equals(is2.getItemMeta()); + public static boolean itemStacksEqual(@Nullable ItemStack itemStack1, @Nullable ItemStack itemStack2) { + if (itemStack1 == null || itemStack2 == null) + return itemStack1 == itemStack2; + if (itemStack1.getType() != itemStack2.getType()) + return false; + + ItemMeta itemMeta1 = itemStack1.getItemMeta(); + ItemMeta itemMeta2 = itemStack2.getItemMeta(); + if (itemMeta1 == null || itemMeta2 == null) + return itemMeta1 == itemMeta2; + + return itemStack1.getItemMeta().equals(itemStack2.getItemMeta()); } // Only 1.15 and versions after have Material#isAir method diff --git a/src/test/skript/tests/regressions/6830-remove air from slot.sk b/src/test/skript/tests/regressions/6830-remove air from slot.sk new file mode 100644 index 00000000000..13eaa29b1d3 --- /dev/null +++ b/src/test/skript/tests/regressions/6830-remove air from slot.sk @@ -0,0 +1,4 @@ +test "remove air from air slot": + set {_chest} to chest inventory with 3 rows + # throws exception if not fixed + remove 1 of (slot 0 of {_chest}) from (slot 0 of {_chest}) From 1e23d7f670c8d4d6f52111ccd0aea9d80d0cde81 Mon Sep 17 00:00:00 2001 From: Shane Bee Date: Mon, 1 Jul 2024 05:49:22 -0700 Subject: [PATCH 2/7] default.lang - add MC 1.21 attributes (#6791) Co-authored-by: sovdee <10354869+sovdeeth@users.noreply.github.com> --- src/main/resources/lang/default.lang | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/main/resources/lang/default.lang b/src/main/resources/lang/default.lang index 90a37eb9e32..af2d90e64b0 100644 --- a/src/main/resources/lang/default.lang +++ b/src/main/resources/lang/default.lang @@ -2168,6 +2168,8 @@ attribute types: generic_attack_damage: generic attack damage, attack damage generic_attack_knockback: generic attack knockback, attack knockback generic_attack_speed: generic attack speed, attack speed + generic_burning_time: generic burning time, burning time + generic_explosion_knockback_resistance: generic explosion knockback resistance, explosion knockback resistance generic_flying_speed: generic flying speed, flying speed generic_follow_range: generic follow range, follow range generic_gravity: generic gravity, gravity @@ -2176,15 +2178,22 @@ attribute types: generic_luck: generic luck, luck generic_max_absorption: generic max absorption, max absorption generic_max_health: generic max health, max health + generic_movement_efficiency: generic movement efficiency, movement efficiency generic_movement_speed: generic movement speed, movement speed + generic_oxygen_bonus: generic oxygen bonus, oxygen bonus generic_safe_fall_distance: generic safe fall distance, safe fall distance generic_fall_damage_multiplier: generic fall damage multiplier, fall damage multiplier generic_scale: generic scale, scale generic_step_height: generic step height, step height + generic_water_movement_efficiency: generic water movement efficiency, water movement efficiency horse_jump_strength: horse jump strength player_block_break_speed: player block break speed, block break speed player_block_interaction_range: player block interaction range, block interaction range player_entity_interaction_range: player entity interaction range, entity interaction range + player_mining_efficiency: player mining efficiency, mining efficiency + player_sneaking_speed: player sneaking speed, sneaking speed + player_submerged_mining_speed: player submerged mining speed, submerged mining speed + player_sweeping_damage_ratio: player sweeping damage ratio, sweeping damage ratio zombie_spawn_reinforcements: zombie spawn reinforcements # -- Environments -- From 9f625868680f068f0de7e21d154045f4c1fa4a21 Mon Sep 17 00:00:00 2001 From: Shane Bee Date: Mon, 1 Jul 2024 06:01:42 -0700 Subject: [PATCH 3/7] ExprLastDamage - fix everything (#6797) * ExprLastDamage - fix everything * HealthUtils set last damage manually * ExprLastDamage - add test --------- Co-authored-by: sovdee <10354869+sovdeeth@users.noreply.github.com> --- .../njol/skript/bukkitutil/HealthUtils.java | 9 ++-- .../skript/expressions/ExprLastDamage.java | 46 ++++++++----------- .../syntaxes/expressions/ExprLastDamage.sk | 15 ++++++ 3 files changed, 39 insertions(+), 31 deletions(-) create mode 100644 src/test/skript/tests/syntaxes/expressions/ExprLastDamage.sk diff --git a/src/main/java/ch/njol/skript/bukkitutil/HealthUtils.java b/src/main/java/ch/njol/skript/bukkitutil/HealthUtils.java index 20b5120a0f1..be8675ccabb 100644 --- a/src/main/java/ch/njol/skript/bukkitutil/HealthUtils.java +++ b/src/main/java/ch/njol/skript/bukkitutil/HealthUtils.java @@ -26,13 +26,13 @@ import org.bukkit.damage.DamageSource; import org.bukkit.damage.DamageType; import org.bukkit.entity.Damageable; +import org.bukkit.entity.LivingEntity; import org.bukkit.event.entity.EntityDamageEvent; import org.bukkit.event.entity.EntityDamageEvent.DamageCause; import org.jetbrains.annotations.Nullable; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; public class HealthUtils { @@ -112,8 +112,11 @@ public static double getFinalDamage(EntityDamageEvent e) { return e.getFinalDamage() / 2; } - public static void setDamage(EntityDamageEvent e, double damage) { - e.setDamage(damage * 2); + public static void setDamage(EntityDamageEvent event, double damage) { + event.setDamage(damage * 2); + // Set last damage manually as Bukkit doesn't appear to do that + if (event.getEntity() instanceof LivingEntity) + ((LivingEntity) event.getEntity()).setLastDamage(damage * 2); } @Nullable diff --git a/src/main/java/ch/njol/skript/expressions/ExprLastDamage.java b/src/main/java/ch/njol/skript/expressions/ExprLastDamage.java index 0b62cd60a9d..ede427b156f 100644 --- a/src/main/java/ch/njol/skript/expressions/ExprLastDamage.java +++ b/src/main/java/ch/njol/skript/expressions/ExprLastDamage.java @@ -19,47 +19,34 @@ */ package ch.njol.skript.expressions; -import org.bukkit.entity.LivingEntity; -import org.bukkit.event.Event; -import org.eclipse.jdt.annotation.Nullable; - import ch.njol.skript.classes.Changer.ChangeMode; import ch.njol.skript.doc.Description; import ch.njol.skript.doc.Examples; import ch.njol.skript.doc.Name; import ch.njol.skript.doc.Since; import ch.njol.skript.expressions.base.SimplePropertyExpression; -import ch.njol.skript.lang.Expression; -import ch.njol.skript.lang.SkriptParser; -import ch.njol.util.Kleenean; import ch.njol.util.coll.CollectionUtils; +import org.bukkit.entity.LivingEntity; +import org.bukkit.event.Event; +import org.jetbrains.annotations.Nullable; @Name("Last Damage") @Description("The last damage that was done to an entity. Note that changing it doesn't deal more/less damage.") @Examples({"set last damage of event-entity to 2"}) @Since("2.5.1") public class ExprLastDamage extends SimplePropertyExpression { - + static { register(ExprLastDamage.class, Number.class, "last damage", "livingentities"); } - - @Nullable - private ExprDamage damageExpr; - - @Override - public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelayed, SkriptParser.ParseResult parseResult) { - damageExpr = new ExprDamage(); - return true; - } - + @Nullable @Override @SuppressWarnings("null") public Number convert(LivingEntity livingEntity) { - return damageExpr.get(livingEntity.getLastDamageCause())[0]; + return livingEntity.getLastDamage() / 2; } - + @Nullable @Override public Class[] acceptChange(ChangeMode mode) { @@ -72,35 +59,38 @@ public Class[] acceptChange(ChangeMode mode) { return null; } } - + + @SuppressWarnings("ConstantValue") @Override public void change(Event e, @Nullable Object[] delta, ChangeMode mode) { - if (delta != null) { + if (delta != null && delta[0] instanceof Number) { + double damage = ((Number) delta[0]).doubleValue() * 2; + switch (mode) { case SET: for (LivingEntity entity : getExpr().getArray(e)) - entity.setLastDamage((Long) delta[0]); + entity.setLastDamage(damage); break; case REMOVE: - delta[0] = (Long) delta[0] * -1; + damage = damage * -1; case ADD: for (LivingEntity entity : getExpr().getArray(e)) - entity.setLastDamage((Long) delta[0] + entity.getLastDamage()); + entity.setLastDamage(damage + entity.getLastDamage()); break; default: assert false; } } } - + @Override public Class getReturnType() { return Number.class; } - + @Override protected String getPropertyName() { return "last damage"; } - + } diff --git a/src/test/skript/tests/syntaxes/expressions/ExprLastDamage.sk b/src/test/skript/tests/syntaxes/expressions/ExprLastDamage.sk new file mode 100644 index 00000000000..0ed3f3f3e4c --- /dev/null +++ b/src/test/skript/tests/syntaxes/expressions/ExprLastDamage.sk @@ -0,0 +1,15 @@ +test "last damage": + set {_l} to location 0.5 above highest block at location(1,1,1) + spawn a sheep at {_l} + set {_e} to last spawned entity + + assert last damage of {_e} = 0 with "last damage of newly spawned entity should be 0" + + damage {_e} by 1 + assert last damage of {_e} = 1 with "last damage of entity should be 1 after damaging it by 1" + + set last damage of {_e} to 3 + assert last damage of {_e} = 3 with "last damage of entity should be 3 after setting to 3" + + # thank you for your service + delete entity in {_e} From 6ee4628d324e4f499319b40c7fd493d912d7f538 Mon Sep 17 00:00:00 2001 From: _Mads <75088349+TFSMads@users.noreply.github.com> Date: Mon, 1 Jul 2024 15:08:59 +0200 Subject: [PATCH 4/7] Added holder instanceof DoubleChest check to converter (#6823) * Added holder instanceof DoubleChest check to IntentoryHolder - Location converter * Apply suggestions from code review Co-authored-by: sovdee <10354869+sovdeeth@users.noreply.github.com> * Change ternary to if statements * Fix indentation in test * Address reviews Co-authored-by: _tud <98935832+UnderscoreTud@users.noreply.github.com> * Update src/main/java/ch/njol/skript/classes/data/DefaultConverters.java Co-authored-by: _tud <98935832+UnderscoreTud@users.noreply.github.com> --------- Co-authored-by: sovdee <10354869+sovdeeth@users.noreply.github.com> Co-authored-by: Pikachu920 <28607612+Pikachu920@users.noreply.github.com> Co-authored-by: _tud <98935832+UnderscoreTud@users.noreply.github.com> --- .../classes/data/DefaultConverters.java | 8 ++++++++ ...1-inventory-holder-location-doublechest.sk | 20 +++++++++++++++++++ 2 files changed, 28 insertions(+) create mode 100644 src/test/skript/tests/regressions/6811-inventory-holder-location-doublechest.sk diff --git a/src/main/java/ch/njol/skript/classes/data/DefaultConverters.java b/src/main/java/ch/njol/skript/classes/data/DefaultConverters.java index 00f419f4901..a90de6957d3 100644 --- a/src/main/java/ch/njol/skript/classes/data/DefaultConverters.java +++ b/src/main/java/ch/njol/skript/classes/data/DefaultConverters.java @@ -176,6 +176,14 @@ public DefaultConverters() {} return ((Block) holder).getLocation(); if (holder instanceof BlockState) return BlockUtils.getLocation(((BlockState) holder).getBlock()); + if (holder instanceof DoubleChest) { + DoubleChest doubleChest = (DoubleChest) holder; + if (doubleChest.getLeftSide() != null) { + return BlockUtils.getLocation(((BlockState) doubleChest.getLeftSide()).getBlock()); + } else if (((DoubleChest) holder).getRightSide() != null) { + return BlockUtils.getLocation(((BlockState) doubleChest.getRightSide()).getBlock()); + } + } return null; }); diff --git a/src/test/skript/tests/regressions/6811-inventory-holder-location-doublechest.sk b/src/test/skript/tests/regressions/6811-inventory-holder-location-doublechest.sk new file mode 100644 index 00000000000..f46d4b52794 --- /dev/null +++ b/src/test/skript/tests/regressions/6811-inventory-holder-location-doublechest.sk @@ -0,0 +1,20 @@ +test "inventory holder location double chest": + set {_b::1} to the block at spawn of world "world" + set {_b::2} to the block north of {_b::1} + set {_prev::1} to type of block at {_b::1} + set {_prev::2} to type of block at {_b::2} + + set block at {_b::1} to chest[facing=east;type=right] + set block at {_b::2} to chest[facing=east;type=left] + + set {_inv} to inventory of {_b::1} + set {_holder} to holder of {_inv} + + set {_a-loc} to location of {_holder} + set {_b-loc::*} to location of {_b::1} and location of {_b::2} + + # clean up first in case assert fails + set block at {_b::1} to {_prev::1} + set block at {_b::2} to {_prev::2} + + assert {_b-loc::*} contains {_a-loc} with "holder location of double chest differs from block location" From 333b5fb4641c9943a6adbbd21fb366d79c4e2022 Mon Sep 17 00:00:00 2001 From: Moderocky Date: Mon, 1 Jul 2024 14:35:33 +0100 Subject: [PATCH 5/7] Add tests for item syntaxes. (#6164) * Add 'with custom model data' test. * Add 'amount of items' test. * Add 'items in' test. * Make safe for 1.13.2. * Update src/test/skript/tests/syntaxes/expressions/ExprItemsIn.sk Co-authored-by: sovdee <10354869+sovdeeth@users.noreply.github.com> --------- Co-authored-by: sovdee <10354869+sovdeeth@users.noreply.github.com> --- .../syntaxes/expressions/ExprAmountOfItems.sk | 14 ++++++++++ .../ExprItemWithCustomModelData.sk | 13 +++++++++ .../tests/syntaxes/expressions/ExprItemsIn.sk | 27 +++++++++++++++++++ 3 files changed, 54 insertions(+) create mode 100644 src/test/skript/tests/syntaxes/expressions/ExprAmountOfItems.sk create mode 100644 src/test/skript/tests/syntaxes/expressions/ExprItemWithCustomModelData.sk diff --git a/src/test/skript/tests/syntaxes/expressions/ExprAmountOfItems.sk b/src/test/skript/tests/syntaxes/expressions/ExprAmountOfItems.sk new file mode 100644 index 00000000000..9e40ff707ca --- /dev/null +++ b/src/test/skript/tests/syntaxes/expressions/ExprAmountOfItems.sk @@ -0,0 +1,14 @@ +test "amount of items": + set {_inventory} to a hopper inventory named "test" + assert the amount of stone in {_inventory} is 0 with "default amount failed" + add stone to {_inventory} + assert the amount of stone in {_inventory} is 1 with "single amount failed" + add stone named "bread" to {_inventory} + assert the amount of stone in {_inventory} is 2 with "different named items amount failed" + add 100 of iron ingot to {_inventory} + assert the amount of stone in {_inventory} is 2 with "add different item amount failed" + assert the amount of iron ingot in {_inventory} is 100 with "add 100 item amount failed" + remove stone from {_inventory} + assert the amount of stone in {_inventory} is 1 with "removed one amount failed" + remove stone from {_inventory} + assert the amount of stone in {_inventory} is 0 with "removed all amount failed" diff --git a/src/test/skript/tests/syntaxes/expressions/ExprItemWithCustomModelData.sk b/src/test/skript/tests/syntaxes/expressions/ExprItemWithCustomModelData.sk new file mode 100644 index 00000000000..098cda9abee --- /dev/null +++ b/src/test/skript/tests/syntaxes/expressions/ExprItemWithCustomModelData.sk @@ -0,0 +1,13 @@ +test "item with custom model data" when minecraft version is not "1.13.2": + set {_i} to stone + assert the custom model data of {_i} is 0 with "default model data failed" + set {_i} to stone with custom model data 5 + assert the custom model data of {_i} is 5 with "simple model data set failed" + set {_i} to stone with custom model data -1 + assert the custom model data of {_i} is -1 with "negative model data set failed" + set {_i} to {_i} with custom model data 2 + assert the custom model data of {_i} is 2 with "existing item model data set failed" + set {_i} to {_i} with custom model data 3.3 + assert the custom model data of {_i} is 3 with "decimal item model data set failed" + set {_i} to {_i} with custom model data 3.999 + assert the custom model data of {_i} is 3 with "close decimal item model data set failed" diff --git a/src/test/skript/tests/syntaxes/expressions/ExprItemsIn.sk b/src/test/skript/tests/syntaxes/expressions/ExprItemsIn.sk index 9b2c90fb25f..a18bef586af 100644 --- a/src/test/skript/tests/syntaxes/expressions/ExprItemsIn.sk +++ b/src/test/skript/tests/syntaxes/expressions/ExprItemsIn.sk @@ -1,3 +1,29 @@ + +test "items in (inventory)": + set {_inventory} to a hopper inventory named "test" + add stone to {_inventory} + add stone named "bread" to {_inventory} + add 100 of iron ingot to {_inventory} + loop items in {_inventory}: + if loop-value is stone: + continue + else if loop-value is iron ingot: + continue + else: + assert true is false with "unexpected item in the inventory area: %loop-value%" + set {_list::*} to items in {_inventory} + assert size of {_list::*} is 4 with "size of items in failed" + assert {_list::1} is stone with "first item failed" + assert {_list::2} is stone named "bread" with "second item failed" + assert {_list::3} is 64 of iron ingot with "third item failed" + assert {_list::4} is 36 of iron ingot with "split fourth item failed" + remove stone from {_inventory} + set {_list::*} to items in {_inventory} + assert size of {_list::*} is 3 with "size of second items in failed" + assert {_list::1} is stone named "bread" with "new first item failed" + assert {_list::2} is 64 of iron ingot with "new second item failed" + assert {_list::3} is 36 of iron ingot with "new third item failed" + test "filtering ExprItemsIn": set {_world} to random world out of all worlds set block at spawn of {_world} to chest @@ -19,3 +45,4 @@ test "unfiltered ExprItemsIn": set slot 3 of {_inv} to bucket assert all items in inventory {_inv} are dirt, stone or bucket with "found correct items with ExprItemsIn##get" assert (all items in inventory {_inv} where [true is true]) are dirt, stone or bucket with "found correct items with ExprItemsIn##iterator" + From 585e8d15be016f9a87a38c59cd7f43885d5fdc57 Mon Sep 17 00:00:00 2001 From: Patrick Miller Date: Mon, 1 Jul 2024 11:54:52 -0400 Subject: [PATCH 6/7] 1.21 Support (#6798) * Update Paper API to 1.21 * Patch up aliases * Update 5491-xp orb merge overwrite.sk --------- Co-authored-by: sovdee <10354869+sovdeeth@users.noreply.github.com> --- build.gradle | 4 +- gradle.properties | 2 +- .../njol/skript/aliases/AliasesProvider.java | 11 ++- .../java/ch/njol/skript/aliases/ItemData.java | 98 +++++++++++-------- .../java/ch/njol/skript/aliases/ItemType.java | 36 +++++-- .../skript/bukkitutil/block/BlockCompat.java | 3 + .../bukkitutil/block/NewBlockCompat.java | 7 ++ .../skript/classes/data/BukkitClasses.java | 1 + .../environments/java21/paper-1.21.0.json | 17 ++++ .../5491-xp orb merge overwrite.sk | 4 + .../tests/syntaxes/effects/EffGlowingText.sk | 2 +- 11 files changed, 128 insertions(+), 57 deletions(-) create mode 100644 src/test/skript/environments/java21/paper-1.21.0.json diff --git a/build.gradle b/build.gradle index 161d3dd3daf..0826a6af81d 100644 --- a/build.gradle +++ b/build.gradle @@ -29,7 +29,7 @@ dependencies { shadow group: 'org.bstats', name: 'bstats-bukkit', version: '3.0.2' shadow group: 'net.kyori', name: 'adventure-text-serializer-bungeecord', version: '4.3.2' - implementation group: 'io.papermc.paper', name: 'paper-api', version: '1.20.6-R0.1-SNAPSHOT' + implementation group: 'io.papermc.paper', name: 'paper-api', version: '1.21-R0.1-SNAPSHOT' implementation group: 'org.eclipse.jdt', name: 'org.eclipse.jdt.annotation', version: '2.2.700' implementation group: 'com.google.code.findbugs', name: 'findbugs', version: '3.0.1' implementation group: 'com.sk89q.worldguard', name: 'worldguard-legacy', version: '7.0.0-SNAPSHOT' @@ -235,7 +235,7 @@ def java21 = 21 def java17 = 17 def java8 = 8 -def latestEnv = 'java21/paper-1.20.6.json' +def latestEnv = 'java21/paper-1.21.0.json' def latestJava = java21 def oldestJava = java8 diff --git a/gradle.properties b/gradle.properties index f78ae1766eb..469d1e072ce 100644 --- a/gradle.properties +++ b/gradle.properties @@ -7,5 +7,5 @@ groupid=ch.njol name=skript version=2.8.7 jarName=Skript.jar -testEnv=java21/paper-1.20.6 +testEnv=java21/paper-1.21.0 testEnvJavaVersion=21 diff --git a/src/main/java/ch/njol/skript/aliases/AliasesProvider.java b/src/main/java/ch/njol/skript/aliases/AliasesProvider.java index a3b8b215b75..cccf91618ed 100644 --- a/src/main/java/ch/njol/skript/aliases/AliasesProvider.java +++ b/src/main/java/ch/njol/skript/aliases/AliasesProvider.java @@ -304,16 +304,19 @@ public void addAlias(AliasName name, String id, @Nullable Map ta } // Apply (NBT) tags to item stack - ItemStack stack = new ItemStack(material); + ItemStack stack = null; int itemFlags = 0; - if (tags != null) { - itemFlags = applyTags(stack, new HashMap<>(tags)); + if (material.isItem()) { + stack = new ItemStack(material); + if (tags != null) { + itemFlags = applyTags(stack, new HashMap<>(tags)); + } } // Parse block state to block values BlockValues blockValues = BlockCompat.INSTANCE.createBlockValues(material, blockStates, stack, itemFlags); - ItemData data = new ItemData(stack, blockValues); + ItemData data = stack != null ? new ItemData(stack, blockValues) : new ItemData(material, blockValues); data.isAlias = true; data.itemFlags = itemFlags; diff --git a/src/main/java/ch/njol/skript/aliases/ItemData.java b/src/main/java/ch/njol/skript/aliases/ItemData.java index 32323c57e6f..0f68279f43a 100644 --- a/src/main/java/ch/njol/skript/aliases/ItemData.java +++ b/src/main/java/ch/njol/skript/aliases/ItemData.java @@ -37,7 +37,7 @@ import org.bukkit.inventory.ItemFlag; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.ItemMeta; -import org.eclipse.jdt.annotation.Nullable; +import org.jetbrains.annotations.Nullable; import java.io.IOException; import java.io.NotSerializableException; @@ -91,11 +91,6 @@ public static class OldItemData { @Deprecated public static final boolean itemDataValues = false; - /** - * ItemStack, which is used for everything but serialization. - */ - transient ItemStack stack; - /** * Type of the item as Bukkit material. Serialized manually. */ @@ -105,14 +100,18 @@ public static class OldItemData { * If this represents all possible items. */ boolean isAnything; - + + /** + * ItemStack, which is used for everything but serialization. + */ + transient @Nullable ItemStack stack; + /** * When this ItemData represents a block, this contains information to * allow comparing it against other blocks. */ - @Nullable - BlockValues blockValues; - + @Nullable BlockValues blockValues; + /** * Whether this represents an item (that definitely cannot have * block states) or a block, which might have them. @@ -140,9 +139,10 @@ public static class OldItemData { public ItemData(Material type, @Nullable String tags) { this.type = type; - - this.stack = new ItemStack(type); - this.blockValues = BlockCompat.INSTANCE.getBlockValues(stack); + + if (type.isItem()) + this.stack = new ItemStack(type); + this.blockValues = BlockCompat.INSTANCE.getBlockValues(type); if (tags != null) { applyTags(tags); } @@ -150,8 +150,9 @@ public ItemData(Material type, @Nullable String tags) { public ItemData(Material type, int amount) { this.type = type; - this.stack = new ItemStack(type, Math.abs(amount)); - this.blockValues = BlockCompat.INSTANCE.getBlockValues(stack); + if (type.isItem()) + this.stack = new ItemStack(type, Math.abs(amount)); + this.blockValues = BlockCompat.INSTANCE.getBlockValues(type); } public ItemData(Material type) { @@ -159,13 +160,18 @@ public ItemData(Material type) { } public ItemData(ItemData data) { - this.stack = data.stack.clone(); + this.stack = data.stack != null ? data.stack.clone() : null; this.type = data.type; this.blockValues = data.blockValues; this.isAlias = data.isAlias; this.plain = data.plain; this.itemFlags = data.itemFlags; } + + public ItemData(Material material, @Nullable BlockValues values) { + this.type = material; + this.blockValues = values; + } public ItemData(ItemStack stack, @Nullable BlockValues values) { this.stack = stack; @@ -200,7 +206,8 @@ public ItemData(BlockState blockState) { public ItemData(BlockData blockData) { this.type = blockData.getMaterial(); - this.stack = new ItemStack(type); + if (type.isItem()) + this.stack = new ItemStack(type); this.blockValues = BlockCompat.INSTANCE.getBlockValues(blockData); } @@ -227,13 +234,12 @@ public boolean isOfType(@Nullable ItemStack item) { if (type != item.getType()) return false; // Obvious mismatch - if (itemFlags != 0) { // Either stack has tags (or durability) + if (stack != null && itemFlags != 0) { // Either stack has tags (or durability) if (ItemUtils.getDamage(stack) != ItemUtils.getDamage(item)) return false; // On 1.12 and below, damage is not in meta if (stack.hasItemMeta() == item.hasItemMeta()) // Compare ItemMeta as in isSimilar() of ItemStack - return stack.hasItemMeta() ? itemFactory.equals(stack.getItemMeta(), item.getItemMeta()) : true; - else - return false; + return !stack.hasItemMeta() || itemFactory.equals(stack.getItemMeta(), item.getItemMeta()); + return false; } return true; } @@ -249,7 +255,7 @@ public String toString() { public String toString(final boolean debug, final boolean plural) { StringBuilder builder = new StringBuilder(Aliases.getMaterialName(this, plural)); - ItemMeta meta = stack.getItemMeta(); + ItemMeta meta = stack != null ? stack.getItemMeta() : null; if (meta != null && meta.hasDisplayName()) { builder.append(" ").append(m_named).append(" "); builder.append(meta.getDisplayName()); @@ -282,7 +288,7 @@ public boolean equals(final @Nullable Object obj) { @Override public int hashCode() { int hash = type.hashCode(); // Has collisions, but probably not too many of them - if (blockValues == null || (blockValues != null && blockValues.isDefault())) { + if (blockValues == null || blockValues.isDefault()) { hash = hash * 37 + 1; } return hash; @@ -351,7 +357,7 @@ public MatchQuality matchAlias(ItemData item) { } // See if we need to compare item metas (excluding durability) - if (quality.isAtLeast(MatchQuality.SAME_ITEM) && stack.hasItemMeta() || item.stack.hasItemMeta()) { // Item meta checks could lower this + if (quality.isAtLeast(MatchQuality.SAME_ITEM) && this.hasItemMeta() || item.hasItemMeta()) { // Item meta checks could lower this MatchQuality metaQuality = compareItemMetas(getItemMeta(), item.getItemMeta()); // If given item doesn't care about meta, promote to SAME_ITEM @@ -489,9 +495,13 @@ public ItemData intersection(final ItemData other) { * It is not a copy, so please be careful. * @return Item stack. */ - public ItemStack getStack() { + public @Nullable ItemStack getStack() { return stack; } + + private boolean hasItemMeta() { + return stack != null && stack.hasItemMeta(); + } @Override public ItemData clone() { @@ -508,7 +518,7 @@ public BlockValues getBlockValues() { } public ItemMeta getItemMeta() { - ItemMeta meta = stack.getItemMeta(); + ItemMeta meta = stack != null ? stack.getItemMeta() : null; if (meta == null) { // AIR has null item meta! meta = itemFactory.getItemMeta(Material.STONE); } @@ -517,6 +527,8 @@ public ItemMeta getItemMeta() { } public void setItemMeta(ItemMeta meta) { + if (stack == null) + return; stack.setItemMeta(meta); isAlias = false; // This is no longer exact alias plain = false; // This is no longer a plain item @@ -524,10 +536,14 @@ public void setItemMeta(ItemMeta meta) { } public int getDurability() { + if (stack == null) + return 0; // no damage? return ItemUtils.getDamage(stack); } public void setDurability(int durability) { + if (stack == null) + return; ItemUtils.setDamage(stack, durability); isAlias = false; // Change happened plain = false; // This is no longer a plain item @@ -567,7 +583,7 @@ public boolean matchPlain(ItemData other) { public Fields serialize() throws NotSerializableException { Fields fields = new Fields(this); // ItemStack is transient, will be ignored fields.putPrimitive("id", type.ordinal()); - fields.putObject("meta", stack.getItemMeta()); + fields.putObject("meta", stack != null ? stack.getItemMeta() : null); return fields; } @@ -579,8 +595,10 @@ public void deserialize(Fields fields) throws StreamCorruptedException, NotSeria ItemMeta meta = fields.getAndRemoveObject("meta", ItemMeta.class); // Initialize ItemStack - this.stack = new ItemStack(type); - stack.setItemMeta(meta); // Just set meta to it + if (meta != null && type.isItem()) { + this.stack = new ItemStack(type); + stack.setItemMeta(meta); // Just set meta to it + } fields.setFields(this); // Everything but ItemStack and Material } @@ -598,17 +616,17 @@ public void deserialize(Fields fields) throws StreamCorruptedException, NotSeria */ public ItemData aliasCopy() { ItemData data = new ItemData(); - data.stack = new ItemStack(type, 1); - - if (stack.hasItemMeta()) { - ItemMeta meta = stack.getItemMeta(); // Creates a copy - meta.setDisplayName(null); // Clear display name - if (!itemFactory.getItemMeta(type).equals(meta)) // there may be different tags (e.g. potions) - data.itemFlags |= ItemFlags.CHANGED_TAGS; - data.stack.setItemMeta(meta); + if (stack != null) { + data.stack = new ItemStack(type, 1); + if (stack.hasItemMeta()) { + ItemMeta meta = stack.getItemMeta(); // Creates a copy + meta.setDisplayName(null); // Clear display name + if (!itemFactory.getItemMeta(type).equals(meta)) // there may be different tags (e.g. potions) + data.itemFlags |= ItemFlags.CHANGED_TAGS; + data.stack.setItemMeta(meta); + } + ItemUtils.setDamage(data.stack, 0); // Set to undamaged } - ItemUtils.setDamage(data.stack, 0); // Set to undamaged - data.type = type; data.blockValues = blockValues; data.itemForm = itemForm; @@ -620,6 +638,8 @@ public ItemData aliasCopy() { * @param tags Tags in Mojang's JSON format. */ public void applyTags(String tags) { + if (stack == null) + return; BukkitUnsafe.modifyItemStack(stack, tags); itemFlags |= ItemFlags.CHANGED_TAGS; } diff --git a/src/main/java/ch/njol/skript/aliases/ItemType.java b/src/main/java/ch/njol/skript/aliases/ItemType.java index 7341667fa91..0b47617ef5c 100644 --- a/src/main/java/ch/njol/skript/aliases/ItemType.java +++ b/src/main/java/ch/njol/skript/aliases/ItemType.java @@ -68,6 +68,7 @@ import java.util.Random; import java.util.RandomAccess; import java.util.Set; +import java.util.stream.Collectors; @ContainerType(ItemStack.class) public class ItemType implements Unit, Iterable, Container, YggdrasilExtendedSerializable { @@ -315,7 +316,7 @@ public boolean isOfType(Material id, @Nullable String tags) { public boolean isOfType(Material id) { // TODO avoid object creation - return isOfType(new ItemData(id, null)); + return isOfType(new ItemData(id, (String) null)); } /** @@ -343,7 +344,7 @@ public ItemType getBlock() { */ public boolean hasItem() { for (ItemData d : types) { - if (!d.type.isBlock()) + if (d.type.isItem()) return true; } return false; @@ -487,9 +488,13 @@ public boolean hasNext() { @Override public ItemStack next() { - if (!hasNext()) - throw new NoSuchElementException(); - ItemStack is = iter.next().getStack().clone(); + ItemStack is = null; + while (is == null) { + if (!hasNext()) + throw new NoSuchElementException(); + is = iter.next().getStack(); + } + is = is.clone(); is.setAmount(getAmount()); return is; } @@ -588,10 +593,17 @@ public ItemType clone() { * @see #removeFrom(ItemStack) * @see #removeFrom(List...) */ - public ItemStack getRandom() { - int numItems = types.size(); + public @Nullable ItemStack getRandom() { + List datas = types.stream() + .filter(data -> data.stack != null) + .collect(Collectors.toList()); + if (datas.isEmpty()) + return null; + int numItems = datas.size(); int index = random.nextInt(numItems); - ItemStack is = types.get(index).getStack().clone(); + ItemStack is = datas.get(index).getStack(); + assert is != null; // verified above + is = is.clone(); is.setAmount(getAmount()); return is; } @@ -869,7 +881,9 @@ public final boolean removeFrom(boolean replaceWithNull, List... list */ public void addTo(final List list) { if (!isAll()) { - list.add(getItem().getRandom()); + ItemStack random = getItem().getRandom(); + if (random != null) + list.add(getItem().getRandom()); return; } for (final ItemStack is : getItem().getAll()) @@ -936,7 +950,9 @@ private static boolean addTo(@Nullable ItemStack is, ItemStack[] buf) { public boolean addTo(final ItemStack[] buf) { if (!isAll()) { - return addTo(getItem().getRandom(), buf); + ItemStack random = getItem().getRandom(); + if (random != null) + return addTo(getItem().getRandom(), buf); } boolean ok = true; for (ItemStack is : getItem().getAll()) { diff --git a/src/main/java/ch/njol/skript/bukkitutil/block/BlockCompat.java b/src/main/java/ch/njol/skript/bukkitutil/block/BlockCompat.java index eef0866a01b..87bc45a6ec8 100644 --- a/src/main/java/ch/njol/skript/bukkitutil/block/BlockCompat.java +++ b/src/main/java/ch/njol/skript/bukkitutil/block/BlockCompat.java @@ -65,6 +65,9 @@ default BlockValues getBlockValues(Block block) { return getBlockValues(block.getBlockData()); } + @Nullable + BlockValues getBlockValues(Material material); + @Nullable BlockValues getBlockValues(BlockData blockData); diff --git a/src/main/java/ch/njol/skript/bukkitutil/block/NewBlockCompat.java b/src/main/java/ch/njol/skript/bukkitutil/block/NewBlockCompat.java index 2a0ecd36da8..e5cf9c0567b 100644 --- a/src/main/java/ch/njol/skript/bukkitutil/block/NewBlockCompat.java +++ b/src/main/java/ch/njol/skript/bukkitutil/block/NewBlockCompat.java @@ -336,6 +336,13 @@ public BlockValues getBlockValues(BlockState blockState) { return getBlockValues(blockState.getBlockData()); } + @Override + public @Nullable BlockValues getBlockValues(Material material) { + if (material.isBlock()) + return new NewBlockValues(material, Bukkit.createBlockData(material), false); + return null; + } + @Nullable @Override public BlockValues getBlockValues(BlockData blockData) { diff --git a/src/main/java/ch/njol/skript/classes/data/BukkitClasses.java b/src/main/java/ch/njol/skript/classes/data/BukkitClasses.java index 25000a2390d..168585cf801 100644 --- a/src/main/java/ch/njol/skript/classes/data/BukkitClasses.java +++ b/src/main/java/ch/njol/skript/classes/data/BukkitClasses.java @@ -930,6 +930,7 @@ public String toVariableNameString(InventoryHolder holder) { .since("1.0") .after("number") .supplier(() -> Arrays.stream(Material.values()) + .filter(Material::isItem) .map(ItemStack::new) .iterator()) .parser(new Parser() { diff --git a/src/test/skript/environments/java21/paper-1.21.0.json b/src/test/skript/environments/java21/paper-1.21.0.json new file mode 100644 index 00000000000..22a72e3a73b --- /dev/null +++ b/src/test/skript/environments/java21/paper-1.21.0.json @@ -0,0 +1,17 @@ +{ + "name": "paper-1.21.0", + "resources": [ + {"source": "server.properties.generic", "target": "server.properties"} + ], + "paperDownloads": [ + { + "version": "1.21", + "target": "paperclip.jar" + } + ], + "skriptTarget": "plugins/Skript.jar", + "commandLine": [ + "-Dcom.mojang.eula.agree=true", + "-jar", "paperclip.jar", "--nogui" + ] +} diff --git a/src/test/skript/tests/regressions/5491-xp orb merge overwrite.sk b/src/test/skript/tests/regressions/5491-xp orb merge overwrite.sk index ca5b9b46d6e..c925f51c590 100644 --- a/src/test/skript/tests/regressions/5491-xp orb merge overwrite.sk +++ b/src/test/skript/tests/regressions/5491-xp orb merge overwrite.sk @@ -1,6 +1,10 @@ test "spawn xp orb overwriting merged value" when running minecraft "1.14.4": # 1.13.2 seems not to merge xp orbs in the same way, so this test is skipped + # 1.21 also does not merge orbs, so this test is disabled. + # TODO: figure out how to force the orbs to merge on 1.21+ + running below minecraft "1.21" + # sanitize kill all xp orbs set {_spawn} to spawn of world "world" diff --git a/src/test/skript/tests/syntaxes/effects/EffGlowingText.sk b/src/test/skript/tests/syntaxes/effects/EffGlowingText.sk index b43a5786755..d39b3e6988a 100644 --- a/src/test/skript/tests/syntaxes/effects/EffGlowingText.sk +++ b/src/test/skript/tests/syntaxes/effects/EffGlowingText.sk @@ -10,7 +10,7 @@ test "glowing sign blocks" when running minecraft "1.17.1": set block at {_loc} to {_original block} test "glowing sign items" when running minecraft "1.17.1": - set {_sign} to sign + set {_sign} to floor sign assert {_sign} doesn't have glowing text with "Sign had glowing text erroneously (1)" make {_sign} have glowing text assert {_sign} has glowing text with "Sign had normal text erroneously" From 2f629f138676486025729921b4fca13e60905561 Mon Sep 17 00:00:00 2001 From: Moderocky Date: Mon, 1 Jul 2024 17:23:58 +0100 Subject: [PATCH 7/7] Attempt to estimate world in teleport when it's not specified. (#6611) --- .../ch/njol/skript/effects/EffTeleport.java | 26 ++++++++++++++++--- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/src/main/java/ch/njol/skript/effects/EffTeleport.java b/src/main/java/ch/njol/skript/effects/EffTeleport.java index 3ba06d7d150..990e1aa7ec1 100644 --- a/src/main/java/ch/njol/skript/effects/EffTeleport.java +++ b/src/main/java/ch/njol/skript/effects/EffTeleport.java @@ -19,7 +19,6 @@ package ch.njol.skript.effects; import ch.njol.skript.Skript; -import ch.njol.skript.sections.EffSecSpawn; import ch.njol.skript.sections.EffSecSpawn.SpawnEvent; import ch.njol.skript.bukkitutil.EntityUtils; import ch.njol.skript.doc.Description; @@ -31,7 +30,6 @@ import ch.njol.skript.lang.SkriptParser.ParseResult; import ch.njol.skript.lang.Trigger; import ch.njol.skript.lang.TriggerItem; -import ch.njol.skript.lang.TriggerSection; import ch.njol.skript.timings.SkriptTimings; import ch.njol.skript.util.Direction; import ch.njol.skript.variables.Variables; @@ -53,7 +51,7 @@ "which may cause lag spikes or server crashes when using this effect to teleport entities to unloaded chunks." }) @Examples({ - "teleport the player to {homes.%player%}", + "teleport the player to {homes::%player%}", "teleport the attacker to the victim" }) @Since("1.0") @@ -101,6 +99,7 @@ protected TriggerItem walk(Event e) { Location loc = location.getSingle(e); if (loc == null) return next; + boolean unknownWorld = !loc.isWorldLoaded(); Entity[] entityArray = entities.getArray(e); // We have to fetch this before possible async execution to avoid async local variable access. if (entityArray.length == 0) @@ -108,11 +107,17 @@ protected TriggerItem walk(Event e) { if (!delayed) { if (e instanceof PlayerRespawnEvent && entityArray.length == 1 && entityArray[0].equals(((PlayerRespawnEvent) e).getPlayer())) { + if (unknownWorld) + return next; ((PlayerRespawnEvent) e).setRespawnLocation(loc); return next; } if (e instanceof PlayerMoveEvent && entityArray.length == 1 && entityArray[0].equals(((PlayerMoveEvent) e).getPlayer())) { + if (unknownWorld) { // we can approximate the world + loc = loc.clone(); + loc.setWorld(((PlayerMoveEvent) e).getFrom().getWorld()); + } ((PlayerMoveEvent) e).setTo(loc); return next; } @@ -125,6 +130,19 @@ protected TriggerItem walk(Event e) { return next; } + if (unknownWorld) { // we can't fetch the chunk without a world + if (entityArray.length == 1) { // if there's 1 thing we can borrow its world + Entity entity = entityArray[0]; + if (entity == null) + return next; + // assume it's a local teleport, use the first entity we find as a reference + loc = loc.clone(); + loc.setWorld(entity.getWorld()); + } else { + return next; // no entities = no chunk = nobody teleporting + } + } + final Location fixed = loc; Delay.addDelayedEvent(e); Object localVars = Variables.removeLocals(e); @@ -132,7 +150,7 @@ protected TriggerItem walk(Event e) { PaperLib.getChunkAtAsync(loc).thenAccept(chunk -> { // The following is now on the main thread for (Entity entity : entityArray) { - EntityUtils.teleport(entity, loc); + EntityUtils.teleport(entity, fixed); } // Re-set local variables