Skip to content

Commit

Permalink
Add time states for PlayerItemHeldEvent and hotbar slot (#5271)
Browse files Browse the repository at this point in the history
  • Loading branch information
TheLimeGlass authored Jun 27, 2023
1 parent 59b4bb5 commit bb87694
Show file tree
Hide file tree
Showing 2 changed files with 96 additions and 33 deletions.
17 changes: 17 additions & 0 deletions src/main/java/ch/njol/skript/classes/data/BukkitEventValues.java
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@
import org.bukkit.event.player.PlayerItemBreakEvent;
import org.bukkit.event.player.PlayerItemConsumeEvent;
import org.bukkit.event.player.PlayerItemDamageEvent;
import org.bukkit.event.player.PlayerItemHeldEvent;
import org.bukkit.event.player.PlayerItemMendEvent;
import org.bukkit.event.player.PlayerMoveEvent;
import org.bukkit.event.player.PlayerPickupArrowEvent;
Expand Down Expand Up @@ -1650,6 +1651,22 @@ public Location get(LootGenerateEvent event) {
}, EventValues.TIME_NOW);
}

// PlayerItemHeldEvent
EventValues.registerEventValue(PlayerItemHeldEvent.class, Slot.class, new Getter<Slot, PlayerItemHeldEvent>() {
@Override
@Nullable
public Slot get(PlayerItemHeldEvent event) {
return new InventorySlot(event.getPlayer().getInventory(), event.getNewSlot());
}
}, EventValues.TIME_NOW);
EventValues.registerEventValue(PlayerItemHeldEvent.class, Slot.class, new Getter<Slot, PlayerItemHeldEvent>() {
@Override
@Nullable
public Slot get(PlayerItemHeldEvent event) {
return new InventorySlot(event.getPlayer().getInventory(), event.getPreviousSlot());
}
}, EventValues.TIME_PAST);

// PlayerPickupArrowEvent
// This event value is restricted to MC 1.14+ due to an API change which has the return type changed
// which throws a NoSuchMethodError if used in a 1.13 server.
Expand Down
112 changes: 79 additions & 33 deletions src/main/java/ch/njol/skript/expressions/ExprHotbarSlot.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,70 +20,116 @@

import org.bukkit.entity.Player;
import org.bukkit.event.Event;
import org.bukkit.event.player.PlayerItemHeldEvent;
import org.bukkit.inventory.PlayerInventory;
import org.eclipse.jdt.annotation.Nullable;

import ch.njol.skript.classes.Changer;
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.expressions.base.PropertyExpression;
import ch.njol.skript.lang.Expression;
import ch.njol.skript.lang.SkriptParser.ParseResult;
import ch.njol.skript.registrations.EventValues;
import ch.njol.skript.util.Getter;
import ch.njol.skript.util.slot.InventorySlot;
import ch.njol.skript.util.slot.Slot;
import ch.njol.util.Kleenean;

@Name("Hotbar Slot")
@Description({"The currently selected hotbar <a href='./classes.html#slot'>slot</a>. To retrieve its number use <a href='#ExprSlotIndex'>Slot Index</a> expression."})
@Examples({"message \"%player's current hotbar slot%\"",
"set player's selected hotbar slot to slot 4 of player",
"send \"index of player's current hotbar slot = 1\" # second slot from the left"})
@Description({
"The currently selected hotbar <a href='./classes.html#slot'>slot</a>.",
"To retrieve its number use <a href='#ExprSlotIndex'>Slot Index</a> expression.",
"Use future and past tense to grab the previous slot in an item change event, see example."
})
@Examples({
"message \"%player's current hotbar slot%\"",
"set player's selected hotbar slot to slot 4 of player",
"",
"send \"index of player's current hotbar slot = 1\" # second slot from the left",
"",
"on item held change:",
"\tif the selected hotbar slot was a diamond:",
"\t\tset the currently selected hotbar slot to slot 5 of player"
})
@Since("2.2-dev36")
public class ExprHotbarSlot extends SimplePropertyExpression<Player, Slot> {
public class ExprHotbarSlot extends PropertyExpression<Player, Slot> {

static {
register(ExprHotbarSlot.class, Slot.class, "[([currently] selected|current)] hotbar slot", "players");
registerDefault(ExprHotbarSlot.class, Slot.class, "[the] [([current:currently] selected|current:current)] hotbar slot[s]", "players");
}

@Override
@Nullable
public Slot convert(Player p) {
PlayerInventory invi = p.getInventory();
assert invi != null;
return new InventorySlot(invi, invi.getHeldItemSlot());
}


// This exists because time states should not register when the 'currently' tag of the syntax is present.
private boolean current;

@Override
protected String getPropertyName() {
return "hotbar slot";
@SuppressWarnings("unchecked")
public boolean init(Expression<?>[] exprs, int matchedPattern, Kleenean isDelayed, ParseResult parseResult) {
setExpr((Expression<? extends Player>) exprs[0]);
current = parseResult.hasTag("current");
return true;
}

@Override
public Class<? extends Slot> getReturnType() {
return Slot.class;
protected Slot[] get(Event event, Player[] source) {
return get(source, new Getter<Slot, Player>() {
@Override
@Nullable
public Slot get(Player player) {
int time = getTime();
PlayerInventory inventory = player.getInventory();
if (event instanceof PlayerItemHeldEvent && time != EventValues.TIME_NOW) {
PlayerItemHeldEvent switchEvent = (PlayerItemHeldEvent) event;
if (time == EventValues.TIME_FUTURE)
return new InventorySlot(inventory, switchEvent.getNewSlot());
if (time == EventValues.TIME_PAST)
return new InventorySlot(inventory, switchEvent.getPreviousSlot());
}
return new InventorySlot(inventory, inventory.getHeldItemSlot());
}
});
}

@Override
@Nullable
public Class<?>[] acceptChange(Changer.ChangeMode mode) {
if (mode == Changer.ChangeMode.SET)
public Class<?>[] acceptChange(ChangeMode mode) {
if (mode == ChangeMode.SET)
return new Class[] {Slot.class};
return null;
}

@Override
public void change(Event e, @Nullable Object[] delta, Changer.ChangeMode mode) {
public void change(Event event, @Nullable Object[] delta, ChangeMode mode) {
assert delta != null;
Slot slot = (Slot) delta[0];
if (!(slot instanceof InventorySlot))
return; // Only inventory slots can be hotbar slots

int index = ((InventorySlot) slot).getIndex();
if (index > 8) // Only slots in hotbar can be current hotbar slot
return;

for (Player p : getExpr().getArray(e)) {
p.getInventory().setHeldItemSlot(index);
}

for (Player player : getExpr().getArray(event))
player.getInventory().setHeldItemSlot(index);
}


@Override
public boolean setTime(int time) {
if (current)
return super.setTime(time);
return super.setTime(time, getExpr(), PlayerItemHeldEvent.class);
}

@Override
public Class<? extends Slot> getReturnType() {
return Slot.class;
}

@Override
public String toString(@Nullable Event event, boolean debug) {
return "hotbar slot of " + getExpr().toString(event, debug);
}

}

0 comments on commit bb87694

Please sign in to comment.