Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix Invalid Equipment Slots in CondIsWearing #7525

21 changes: 20 additions & 1 deletion src/main/java/ch/njol/skript/conditions/CondIsWearing.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package ch.njol.skript.conditions;

import ch.njol.skript.Skript;
import ch.njol.skript.aliases.ItemType;
import ch.njol.skript.conditions.base.PropertyCondition;
import ch.njol.skript.conditions.base.PropertyCondition.PropertyType;
Expand All @@ -12,7 +13,7 @@
import ch.njol.skript.lang.SkriptParser.ParseResult;
import ch.njol.skript.lang.util.SimpleExpression;
import ch.njol.util.Kleenean;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.*;
import org.bukkit.event.Event;
import org.bukkit.inventory.EntityEquipment;
import org.bukkit.inventory.EquipmentSlot;
Expand All @@ -30,6 +31,9 @@
})
@Since("1.0")
public class CondIsWearing extends Condition {

private static final boolean HAS_CAN_USE_SLOT_METHOD = Skript.methodExists(LivingEntity.class, "canUseEquipmentSlot", EquipmentSlot.class);
private static final boolean HAS_BODY_SLOT = Skript.fieldExists(EquipmentSlot.class, "BODY");

static {
PropertyCondition.register(CondIsWearing.class, "wearing %itemtypes%", "livingentities");
Expand Down Expand Up @@ -59,6 +63,21 @@ public boolean check(Event event) {
return false; // spigot nullability, no identifier as to why this occurs

ItemStack[] contents = Arrays.stream(EquipmentSlot.values())
.filter(slot -> {
// this method was added in 1.20.6
if (HAS_CAN_USE_SLOT_METHOD)
return entity.canUseEquipmentSlot(slot);

// body slot was added in 1.20.5
if (HAS_BODY_SLOT && slot == EquipmentSlot.BODY)
// this may change in the future, but for now this is the only way to figure out
// if the entity can use the body slot
return entity instanceof Horse
|| entity instanceof Wolf
|| entity instanceof Llama;

return true;
})
.map(equipment::getItem)
.toArray(ItemStack[]::new);

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package org.skriptlang.skript.test.tests.regression;

import ch.njol.skript.Skript;
import ch.njol.skript.lang.Condition;
import ch.njol.skript.lang.util.ContextlessEvent;
import ch.njol.skript.test.runner.SkriptJUnitTest;
import ch.njol.skript.variables.Variables;
import org.bukkit.Material;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.bukkit.inventory.EntityEquipment;
import org.bukkit.inventory.EquipmentSlot;
import org.bukkit.inventory.ItemStack;
import org.easymock.EasyMock;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;

public class MissingCheckIfEntityCanUseSlot7524Test extends SkriptJUnitTest {

private static final boolean HAS_CAN_USE_SLOT_METHOD = Skript.methodExists(LivingEntity.class, "canUseEquipmentSlot", EquipmentSlot.class);

private Player player;
private EntityEquipment equipment;
private Condition isWearingCondition;

@Before
public void setup() {
player = EasyMock.niceMock(Player.class);
equipment = EasyMock.niceMock(EntityEquipment.class);

isWearingCondition = Condition.parse("{_player} is wearing diamond chestplate", null);
if (isWearingCondition == null)
throw new IllegalStateException();
}

@Test
public void test() {
ContextlessEvent event = ContextlessEvent.get();
Variables.setVariable("player", player, event, true);

EasyMock.expect(player.isValid()).andStubReturn(true);
EasyMock.expect(player.getEquipment()).andReturn(equipment);

if (HAS_CAN_USE_SLOT_METHOD) {
EasyMock.expect(player.canUseEquipmentSlot(EquipmentSlot.CHEST)).andReturn(true);
EasyMock.expect(player.canUseEquipmentSlot(EquipmentSlot.LEGS)).andReturn(true);
EasyMock.expect(player.canUseEquipmentSlot(EquipmentSlot.FEET)).andReturn(true);
EasyMock.expect(player.canUseEquipmentSlot(EquipmentSlot.HEAD)).andReturn(true);
EasyMock.expect(player.canUseEquipmentSlot(EquipmentSlot.HAND)).andReturn(true);
EasyMock.expect(player.canUseEquipmentSlot(EquipmentSlot.OFF_HAND)).andReturn(true);
EasyMock.expect(player.canUseEquipmentSlot(EquipmentSlot.BODY)).andReturn(false);
}

EasyMock.expect(equipment.getItem(EquipmentSlot.CHEST)).andReturn(new ItemStack(Material.DIAMOND_CHESTPLATE));

EasyMock.replay(player, equipment);

assert isWearingCondition.check(event);

EasyMock.verify(player, equipment);
}

}