Skip to content

Commit 414cc38

Browse files
authored
Merge branch 'dev/feature' into feature/preinit
2 parents d316afc + 3042582 commit 414cc38

34 files changed

Lines changed: 517 additions & 160 deletions

gradle.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ org.gradle.parallel=true
55

66
groupid=ch.njol
77
name=skript
8-
version=2.11.0-pre1
8+
version=2.11.0
99
jarName=Skript.jar
1010
testEnv=java21/paper-1.21.4
1111
testEnvJavaVersion=21

skript-aliases

src/main/java/ch/njol/skript/ScriptLoader.java

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1002,14 +1002,15 @@ public static ArrayList<TriggerItem> loadItems(SectionNode node) {
10021002
break find_section;
10031003
Collection<LogEntry> errors = handler.getErrors();
10041004

1005-
// restore the failure log
1006-
if (errors.isEmpty()) {
1005+
// restore the failure log if:
1006+
// 1. there are no errors from the statement parse
1007+
// 2. the error message is the default one from the statement parse
1008+
// 3. the backup log contains a message about the section being claimed
1009+
if (errors.isEmpty()
1010+
|| errors.iterator().next().getMessage().contains("Can't understand this condition/effect:")
1011+
|| backup.getErrors().iterator().next().getMessage().contains("tried to claim the current section, but it was already claimed by")
1012+
) {
10071013
handler.restore(backup);
1008-
} else { // We specifically want these two errors in preference to the section error!
1009-
String firstError = errors.iterator().next().getMessage();
1010-
if (!firstError.contains("is a valid statement but cannot function as a section (:)")
1011-
&& !firstError.contains("You cannot have two section-starters in the same line"))
1012-
handler.restore(backup);
10131014
}
10141015
continue;
10151016
} finally {

src/main/java/ch/njol/skript/aliases/ItemData.java

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -564,7 +564,7 @@ public boolean matchPlain(ItemData other) {
564564
@Override
565565
public Fields serialize() throws NotSerializableException {
566566
Fields fields = new Fields(this); // ItemStack is transient, will be ignored
567-
fields.putPrimitive("id", type.ordinal());
567+
fields.putObject("key", type.getKey().toString());
568568
fields.putObject("meta", stack != null ? stack.getItemMeta() : null);
569569
return fields;
570570
}
@@ -573,7 +573,16 @@ public Fields serialize() throws NotSerializableException {
573573

574574
@Override
575575
public void deserialize(Fields fields) throws StreamCorruptedException, NotSerializableException {
576-
this.type = materials[fields.getAndRemovePrimitive("id", int.class)];
576+
if (fields.hasField("key")) {
577+
String key = fields.getAndRemoveObject("key", String.class);
578+
if (key == null)
579+
throw new StreamCorruptedException("Material key is null");
580+
this.type = Material.matchMaterial(key);
581+
} else {
582+
// attempt back compat deserialization, though using ordinals is not reliable
583+
this.type = materials[fields.getAndRemovePrimitive("id", int.class)];
584+
}
585+
577586
ItemMeta meta = fields.getAndRemoveObject("meta", ItemMeta.class);
578587

579588
// Initialize ItemStack

src/main/java/ch/njol/skript/aliases/ItemType.java

Lines changed: 43 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,7 @@
2121
import ch.njol.yggdrasil.Fields;
2222
import ch.njol.yggdrasil.Fields.FieldContext;
2323
import ch.njol.yggdrasil.YggdrasilSerializable.YggdrasilExtendedSerializable;
24-
import org.bukkit.Location;
25-
import org.bukkit.Material;
26-
import org.bukkit.OfflinePlayer;
27-
import org.bukkit.Tag;
28-
import org.bukkit.Bukkit;
24+
import org.bukkit.*;
2925
import org.bukkit.block.Block;
3026
import org.bukkit.block.BlockState;
3127
import org.bukkit.block.Skull;
@@ -35,6 +31,7 @@
3531
import org.bukkit.inventory.Inventory;
3632
import org.bukkit.inventory.ItemStack;
3733
import org.bukkit.inventory.PlayerInventory;
34+
import org.bukkit.inventory.meta.BlockStateMeta;
3835
import org.bukkit.inventory.meta.ItemMeta;
3936
import org.bukkit.inventory.meta.SkullMeta;
4037
import org.jetbrains.annotations.NotNull;
@@ -43,19 +40,8 @@
4340
import java.io.NotSerializableException;
4441
import java.io.StreamCorruptedException;
4542
import java.lang.reflect.Field;
46-
import java.util.ArrayList;
47-
import java.util.Arrays;
48-
import java.util.Collection;
49-
import java.util.Collections;
50-
import java.util.HashSet;
51-
import java.util.Iterator;
52-
import java.util.List;
53-
import java.util.Map;
43+
import java.util.*;
5444
import java.util.Map.Entry;
55-
import java.util.NoSuchElementException;
56-
import java.util.Random;
57-
import java.util.RandomAccess;
58-
import java.util.Set;
5945
import java.util.stream.Collectors;
6046

6147
@ContainerType(ItemStack.class)
@@ -390,8 +376,8 @@ public boolean setBlock(Block block, boolean applyPhysics) {
390376

391377
ItemMeta itemMeta = getItemMeta();
392378

393-
if (itemMeta instanceof SkullMeta) {
394-
OfflinePlayer offlinePlayer = ((SkullMeta) itemMeta).getOwningPlayer();
379+
if (itemMeta instanceof SkullMeta skullMeta) {
380+
OfflinePlayer offlinePlayer = skullMeta.getOwningPlayer();
395381
if (offlinePlayer == null)
396382
continue;
397383
Skull skull = (Skull) block.getState();
@@ -407,11 +393,49 @@ public boolean setBlock(Block block, boolean applyPhysics) {
407393
skull.update(false, applyPhysics);
408394
}
409395

396+
// https://github.com/SkriptLang/Skript/issues/7735
397+
// No method exists to copy general BlockStateMeta data to a block, so we have to do it manually for now
398+
copyContainerState(block, itemMeta);
399+
410400
return true;
411401
}
412402
return false;
413403
}
414404

405+
/**
406+
* Copies the container state from the item meta to the block state
407+
* @param block The block to copy the state to
408+
* @param itemMeta The item meta to copy the state from
409+
*/
410+
private void copyContainerState(@NotNull Block block, @NotNull ItemMeta itemMeta) {
411+
// ensure the item has a block state
412+
if (!(itemMeta instanceof BlockStateMeta blockStateMeta) || !blockStateMeta.hasBlockState())
413+
return;
414+
415+
// only care about container -> container copying
416+
if (!(blockStateMeta.getBlockState() instanceof org.bukkit.block.Container itemContainer)
417+
|| !(block.getState() instanceof org.bukkit.block.Container blockContainer))
418+
return;
419+
420+
// copy inventory from item to block
421+
copyInventories(itemContainer.getSnapshotInventory(), blockContainer.getSnapshotInventory());
422+
blockContainer.update();
423+
}
424+
425+
/**
426+
* Copies the contents of one inventory to another, maintaining slot positions and making clones.
427+
* @param from The inventory to copy from
428+
* @param to The inventory to copy to
429+
*/
430+
private void copyInventories(@NotNull Inventory from, @NotNull Inventory to) {
431+
for (int i = 0; i < from.getSize(); i++) {
432+
ItemStack item = from.getItem(i);
433+
if (item != null) {
434+
to.setItem(i, item.clone());
435+
}
436+
}
437+
}
438+
415439
/**
416440
* Send a block change to a player
417441
* <p>This will send a fake block change to the player, and will not change the block on the server.</p>

src/main/java/ch/njol/skript/bukkitutil/BukkitUtils.java

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
package ch.njol.skript.bukkitutil;
22

33
import ch.njol.skript.Skript;
4+
import com.google.common.collect.BiMap;
5+
import com.google.common.collect.HashBiMap;
46
import org.bukkit.Registry;
7+
import org.bukkit.inventory.EquipmentSlot;
58
import org.bukkit.potion.PotionEffectType;
69
import org.jetbrains.annotations.Nullable;
710

@@ -10,6 +13,16 @@
1013
*/
1114
public class BukkitUtils {
1215

16+
private static final BiMap<EquipmentSlot, Integer> BUKKIT_EQUIPMENT_SLOT_INDICES = HashBiMap.create();
17+
18+
static {
19+
BUKKIT_EQUIPMENT_SLOT_INDICES.put(EquipmentSlot.FEET, 36);
20+
BUKKIT_EQUIPMENT_SLOT_INDICES.put(EquipmentSlot.LEGS, 37);
21+
BUKKIT_EQUIPMENT_SLOT_INDICES.put(EquipmentSlot.CHEST, 38);
22+
BUKKIT_EQUIPMENT_SLOT_INDICES.put(EquipmentSlot.HEAD, 39);
23+
BUKKIT_EQUIPMENT_SLOT_INDICES.put(EquipmentSlot.OFF_HAND, 40);
24+
}
25+
1326
/**
1427
* Check if a registry exists
1528
*
@@ -36,4 +49,22 @@ public static boolean registryExists(String registry) {
3649
return null;
3750
}
3851

52+
/**
53+
* Get the inventory slot index of the {@link EquipmentSlot}
54+
* @param equipmentSlot The equipment slot to get the index of
55+
* @return The equipment slot index of the provided slot, otherwise null if invalid
56+
*/
57+
public static Integer getEquipmentSlotIndex(EquipmentSlot equipmentSlot) {
58+
return BUKKIT_EQUIPMENT_SLOT_INDICES.get(equipmentSlot);
59+
}
60+
61+
/**
62+
* Get the {@link EquipmentSlot} represented by the inventory slot index
63+
* @param slotIndex The index of the equipment slot
64+
* @return The equipment slot the provided slot index, otherwise null if invalid
65+
*/
66+
public static EquipmentSlot getEquipmentSlotFromIndex(int slotIndex) {
67+
return BUKKIT_EQUIPMENT_SLOT_INDICES.inverse().get(slotIndex);
68+
}
69+
3970
}

src/main/java/ch/njol/skript/classes/data/BukkitClasses.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1424,7 +1424,7 @@ public String toVariableNameString(EnchantmentOffer eo) {
14241424
.name("Wolf Variant")
14251425
.description("Represents the variant of a wolf entity.",
14261426
"NOTE: Minecraft namespaces are supported, ex: 'minecraft:ashen'.")
1427-
.since("@VERSION")
1427+
.since("2.10")
14281428
.requiredPlugins("Minecraft 1.21+")
14291429
.documentationId("WolfVariant"));
14301430

src/main/java/ch/njol/skript/classes/data/BukkitEventValues.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -764,6 +764,21 @@ else if (hand == EquipmentSlot.OFF_HAND)
764764
EventValues.registerEventValue(WorldBorderCenterChangeEvent.class, Location.class, WorldBorderCenterChangeEvent::getNewCenter);
765765
EventValues.registerEventValue(WorldBorderCenterChangeEvent.class, Location.class, WorldBorderCenterChangeEvent::getOldCenter, EventValues.TIME_PAST);
766766
}
767+
768+
if (Skript.classExists("org.bukkit.event.block.VaultDisplayItemEvent")) {
769+
EventValues.registerEventValue(VaultDisplayItemEvent.class, ItemStack.class, new EventConverter<>() {
770+
@Override
771+
public void set(VaultDisplayItemEvent event, @Nullable ItemStack itemStack) {
772+
event.setDisplayItem(itemStack);
773+
}
774+
775+
@Override
776+
public @Nullable ItemStack convert(VaultDisplayItemEvent event) {
777+
return event.getDisplayItem();
778+
}
779+
});
780+
}
781+
767782
}
768783

769784
}

src/main/java/ch/njol/skript/doc/JSONGenerator.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ public class JSONGenerator extends DocumentationGenerator {
3636
/**
3737
* The current version of the JSON generator
3838
*/
39-
public static final Version JSON_VERSION = new Version(1, 0);
39+
public static final Version JSON_VERSION = new Version(1, 1);
4040

4141
private static final Gson GSON = new GsonBuilder()
4242
.disableHtmlEscaping()
@@ -200,6 +200,10 @@ private static JsonArray getEventValues(SkriptEventInfo<?> info) {
200200
}
201201
}
202202

203+
if (eventValues.isEmpty()) {
204+
return null;
205+
}
206+
203207
JsonArray array = new JsonArray();
204208
for (JsonObject eventValue : eventValues) {
205209
array.add(eventValue);

src/main/java/ch/njol/skript/events/EvtPlayerArmorChange.java

Lines changed: 29 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,19 @@
1010
import ch.njol.skript.util.Utils;
1111
import ch.njol.skript.util.slot.Slot;
1212
import com.destroystokyo.paper.event.player.PlayerArmorChangeEvent;
13+
import com.destroystokyo.paper.event.player.PlayerArmorChangeEvent.SlotType;
1314
import org.bukkit.event.Event;
1415
import org.bukkit.inventory.EquipmentSlot;
1516
import org.bukkit.inventory.ItemStack;
1617
import org.jetbrains.annotations.Nullable;
18+
import org.skriptlang.skript.lang.converter.Converter;
1719

18-
import java.util.concurrent.CompletionException;
20+
import java.util.Map;
1921

2022
public class EvtPlayerArmorChange extends SkriptEvent {
2123

22-
private static boolean BODY_SLOT_EXISTS;
24+
private static final boolean BODY_SLOT_EXISTS = Skript.fieldExists(EquipmentSlot.class, "BODY");
25+
private static Converter<PlayerArmorChangeEvent, EquipmentSlot> GET_SLOT;
2326

2427
static {
2528
if (Skript.classExists("com.destroystokyo.paper.event.player.PlayerArmorChangeEvent")) {
@@ -36,22 +39,30 @@ public class EvtPlayerArmorChange extends SkriptEvent {
3639
)
3740
.since("2.5, 2.11 (equipment slots)");
3841

39-
EquipmentSlot bodySlot = null;
40-
try {
41-
bodySlot = EquipmentSlot.valueOf("BODY");
42-
} catch (IllegalArgumentException | NoSuchFieldError | CompletionException ignored) {};
43-
BODY_SLOT_EXISTS = bodySlot != null;
42+
// get slot function is dependent on version. 1.21.4+ has a new method.
43+
if (Skript.methodExists(PlayerArmorChangeEvent.class, "getSlot")) {
44+
GET_SLOT = PlayerArmorChangeEvent::getSlot;
45+
} else {
46+
//noinspection deprecation
47+
Map<SlotType, EquipmentSlot> slotTypeMap = Map.of(
48+
Enum.valueOf(SlotType.class, "HEAD"), EquipmentSlot.HEAD,
49+
Enum.valueOf(SlotType.class, "CHEST"), EquipmentSlot.CHEST,
50+
Enum.valueOf(SlotType.class, "LEGS"), EquipmentSlot.LEGS,
51+
Enum.valueOf(SlotType.class, "FEET"), EquipmentSlot.FEET);
52+
GET_SLOT = event -> {
53+
//noinspection deprecation
54+
return slotTypeMap.get(event.getSlotType());
55+
};
56+
}
4457

45-
EventValues.registerEventValue(PlayerArmorChangeEvent.class, EquipmentSlot.class,
46-
event -> switch (event.getSlotType()) {
47-
case HEAD -> EquipmentSlot.HEAD;
48-
case CHEST -> EquipmentSlot.CHEST;
49-
case LEGS -> EquipmentSlot.LEGS;
50-
case FEET -> EquipmentSlot.FEET;
51-
});
52-
EventValues.registerEventValue(PlayerArmorChangeEvent.class, ItemStack.class, PlayerArmorChangeEvent::getOldItem, EventValues.TIME_PAST);
53-
EventValues.registerEventValue(PlayerArmorChangeEvent.class, ItemStack.class, PlayerArmorChangeEvent::getNewItem, EventValues.TIME_FUTURE);
54-
EventValues.registerEventValue(PlayerArmorChangeEvent.class, Slot.class, event -> new ch.njol.skript.util.slot.EquipmentSlot(event.getPlayer().getEquipment(), event.getSlot()));
58+
// Register event values
59+
EventValues.registerEventValue(PlayerArmorChangeEvent.class, EquipmentSlot.class, GET_SLOT);
60+
EventValues.registerEventValue(PlayerArmorChangeEvent.class, ItemStack.class,
61+
PlayerArmorChangeEvent::getOldItem, EventValues.TIME_PAST);
62+
EventValues.registerEventValue(PlayerArmorChangeEvent.class, ItemStack.class,
63+
PlayerArmorChangeEvent::getNewItem, EventValues.TIME_FUTURE);
64+
EventValues.registerEventValue(PlayerArmorChangeEvent.class, Slot.class,
65+
event -> new ch.njol.skript.util.slot.EquipmentSlot(event.getPlayer().getEquipment(), event.getSlot()));
5566
}
5667
}
5768

@@ -76,13 +87,7 @@ public boolean check(Event event) {
7687
PlayerArmorChangeEvent changeEvent = (PlayerArmorChangeEvent) event;
7788
if (slot == null)
7889
return true;
79-
EquipmentSlot changedSlot = switch (changeEvent.getSlotType()) {
80-
case HEAD -> EquipmentSlot.HEAD;
81-
case CHEST -> EquipmentSlot.CHEST;
82-
case LEGS -> EquipmentSlot.LEGS;
83-
case FEET -> EquipmentSlot.FEET;
84-
};
85-
return slot == changedSlot;
90+
return slot == GET_SLOT.convert(changeEvent);
8691
}
8792

8893
@Override

0 commit comments

Comments
 (0)