Update many GUI's
Einige Prüfungen sind fehlgeschlagen
SteamWarCI Build failed

Add SimulatorCursor.onPlayerInteract
Dieser Commit ist enthalten in:
yoyosource 2023-10-24 23:05:16 +02:00
Ursprung d09c3548a7
Commit 20b116f228
17 geänderte Dateien mit 207 neuen und 66 gelöschten Zeilen

Datei anzeigen

@ -35,7 +35,7 @@ import org.bukkit.inventory.PlayerInventory;
import java.util.function.Function;
@Linked
// @Linked
public class TNTSimulatorListener implements Listener {
private boolean permissionCheck(Player player) {

Datei anzeigen

@ -22,14 +22,25 @@ package de.steamwar.bausystem.features.simulator2;
import com.comphenix.tinyprotocol.Reflection;
import com.comphenix.tinyprotocol.TinyProtocol;
import de.steamwar.bausystem.BauSystem;
import de.steamwar.bausystem.SWUtils;
import de.steamwar.bausystem.features.simulator2.data.Simulator;
import de.steamwar.bausystem.features.simulator2.data.SimulatorElement;
import de.steamwar.bausystem.features.simulator2.data.SimulatorGroup;
import de.steamwar.bausystem.features.simulator2.data.redstone.RedstoneElement;
import de.steamwar.bausystem.features.simulator2.data.redstone.RedstonePhase;
import de.steamwar.bausystem.features.simulator2.data.tnt.TNTElement;
import de.steamwar.bausystem.features.simulator2.data.tnt.TNTPhase;
import de.steamwar.bausystem.features.simulator2.execute.SimulatorExecutor;
import de.steamwar.bausystem.features.simulator2.gui.SimulatorGroupGui;
import de.steamwar.bausystem.features.simulator2.gui.SimulatorGui;
import de.steamwar.bausystem.features.simulator2.gui.base.SimulatorBaseGui;
import de.steamwar.bausystem.utils.ItemUtils;
import de.steamwar.bausystem.utils.RayTraceUtils;
import de.steamwar.entity.REntity;
import de.steamwar.entity.REntityServer;
import de.steamwar.entity.RFallingBlockEntity;
import de.steamwar.inventory.SWAnvilInv;
import de.steamwar.linkage.Linked;
import de.steamwar.linkage.api.Plain;
import lombok.AllArgsConstructor;
import lombok.Getter;
import org.bukkit.Bukkit;
@ -41,15 +52,21 @@ import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.block.Action;
import org.bukkit.event.player.*;
import org.bukkit.inventory.ItemStack;
import org.bukkit.util.Vector;
import java.util.*;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.stream.Collectors;
@Linked
public class SimulatorCursor implements Plain, Listener {
public class SimulatorCursor implements Listener {
private final World WORLD = Bukkit.getWorlds().get(0);
private Class<?> position = Reflection.getClass("{nms.network.protocol.game}.PacketPlayInFlying$PacketPlayInPosition");
@ -113,8 +130,7 @@ public class SimulatorCursor implements Plain, Listener {
return;
}
if (LAST_SNEAKS.containsKey(player)) {
CursorType type = cursorType.getOrDefault(player, CursorType.TNT).switchType();
cursorType.put(player, type);
cursorType.put(player, cursorType.getOrDefault(player, CursorType.TNT).switchType());
calcCursor(player);
} else {
LAST_SNEAKS.put(player, System.currentTimeMillis());
@ -124,27 +140,32 @@ public class SimulatorCursor implements Plain, Listener {
private void calcCursor(Player player) {
if (!isSimulatorItem(player.getInventory().getItemInMainHand()) && !isSimulatorItem(player.getInventory().getItemInOffHand())) {
removeCursor(player);
SimulatorWatcher.show(null, player);
SWUtils.sendToActionbar(player, "");
return;
}
Simulator simulator = SimulatorStorage.getSimulator(player);
SimulatorWatcher.show(simulator, player);
List<REntity> entities = SimulatorWatcher.getEntitiesOfSimulator(simulator);
RayTraceUtils.RRayTraceResult rayTraceResult = RayTraceUtils.traceREntity(player, player.getLocation(), entities);
if (rayTraceResult == null) {
removeCursor(player);
SWUtils.sendToActionbar(player, "");
return;
}
showCursor(player, rayTraceResult);
showCursor(player, rayTraceResult, simulator != null);
}
private void removeCursor(Player player) {
private synchronized void removeCursor(Player player) {
REntityServer entityServer = cursors.get(player);
if (entityServer != null) {
entityServer.getEntities().forEach(REntity::die);
}
}
private synchronized void showCursor(Player player, RayTraceUtils.RRayTraceResult rayTraceResult) {
private synchronized void showCursor(Player player, RayTraceUtils.RRayTraceResult rayTraceResult, boolean hasSimulatorSelected) {
REntityServer entityServer = cursors.computeIfAbsent(player, __ -> {
REntityServer rEntityServer = new REntityServer();
rEntityServer.addPlayer(player);
@ -173,6 +194,16 @@ public class SimulatorCursor implements Plain, Listener {
rFallingBlockEntity.setGlowing(true);
}
}
if (hasSimulatorSelected) {
if (hitEntity != null) {
SWUtils.sendToActionbar(player, "§eEdit Position");
} else {
SWUtils.sendToActionbar(player, "§eAdd new " + type.name);
}
} else {
SWUtils.sendToActionbar(player, "§eCreate new Simulator");
}
}
public static Vector getPosTNT(Player player, RayTraceUtils.RRayTraceResult result) {
@ -250,12 +281,14 @@ public class SimulatorCursor implements Plain, Listener {
@Getter
@AllArgsConstructor
public enum CursorType {
TNT(Material.TNT, SimulatorCursor::getPosTNT),
REDSTONE_BLOCK(Material.REDSTONE_BLOCK, SimulatorCursor::getPosRedstoneBlock),
TNT(Material.TNT, SimulatorCursor::getPosTNT, "TNT", vector -> new TNTElement(vector).add(new TNTPhase())),
REDSTONE_BLOCK(Material.REDSTONE_BLOCK, SimulatorCursor::getPosRedstoneBlock, "Redstone Block", vector -> new RedstoneElement(vector).add(new RedstonePhase())),
;
private Material material;
private BiFunction<Player, RayTraceUtils.RRayTraceResult, Vector> position;
private String name;
private Function<Vector, SimulatorElement<?>> elementFunction;
public CursorType switchType() {
if (this == TNT) {
@ -264,4 +297,93 @@ public class SimulatorCursor implements Plain, Listener {
return TNT;
}
}
@EventHandler
public void onPlayerInteract(PlayerInteractEvent event) {
if (!ItemUtils.isItem(event.getItem(), "simulator")) {
return;
}
event.setCancelled(true);
Player player = event.getPlayer();
Simulator simulator = SimulatorStorage.getSimulator(player);
if (event.getAction() == Action.LEFT_CLICK_BLOCK || event.getAction() == Action.LEFT_CLICK_AIR) {
if (simulator == null) {
return;
}
SimulatorExecutor.run(simulator);
return;
}
if (event.getAction() != Action.RIGHT_CLICK_BLOCK && event.getAction() != Action.RIGHT_CLICK_AIR) {
return;
}
RayTraceUtils.RRayTraceResult rayTraceResult = RayTraceUtils.traceREntity(player, player.getLocation(), SimulatorWatcher.getEntitiesOfSimulator(simulator));
if (simulator == null) {
if (rayTraceResult == null) {
// TODO: Open Simulator Selection GUI
} else {
SWAnvilInv anvilInv = new SWAnvilInv(player, "Name");
anvilInv.setCallback(s -> {
// TODO: Check if Sim exists then close and message, otherwise create sim and add first tnt open that!
});
anvilInv.open();
}
return;
}
if (rayTraceResult == null) {
new SimulatorGui(player, simulator).open();
return;
}
if (rayTraceResult.getHitEntity() != null) {
REntity hitEntity = rayTraceResult.getHitEntity();
Vector vector = new Vector(hitEntity.getX(), hitEntity.getY(), hitEntity.getZ());
List<SimulatorElement<?>> elements = simulator.getElements().stream().map(SimulatorGroup::getElements).flatMap(List::stream).filter(element -> {
return element.getWorldPos().distanceSquared(vector) < (1 / 16.0) * (1 / 16.0);
}).collect(Collectors.toList());
switch (elements.size()) {
case 0:
return;
case 1:
// Open single element present in Simulator
SimulatorElement<?> element = elements.get(0);
SimulatorGroup group1 = element.getGroup(simulator);
SimulatorBaseGui back = new SimulatorGui(player, simulator);
if (group1.getElements().size() > 1) {
back = new SimulatorGroupGui(player, simulator, group1, back);
}
element.open(player, simulator, group1, back);
break;
default:
// Open multi element present in Simulator
SimulatorGroup group2 = new SimulatorGroup();
group2.setMaterial(null);
group2.getElements().addAll(elements);
SimulatorGui simulatorGui = new SimulatorGui(player, simulator);
new SimulatorGroupGui(player, simulator, group2, simulatorGui).open();
break;
}
return;
}
// Add new Element to current simulator
CursorType type = cursorType.getOrDefault(player, CursorType.TNT);
Vector vector = type.position.apply(player, rayTraceResult);
if (type == CursorType.REDSTONE_BLOCK) {
vector.subtract(new Vector(0.5, 0, 0.5));
}
SimulatorElement<?> element = type.elementFunction.apply(vector);
SimulatorGroup group = new SimulatorGroup().add(element);
simulator.getElements().add(group);
SimulatorGui simulatorGui = new SimulatorGui(player, simulator);
element.open(player, simulator, group, simulatorGui);
SimulatorWatcher.update(simulator);
calcCursor(player);
}
}

Datei anzeigen

@ -60,14 +60,4 @@ public class SimulatorTestCommand extends SWCommand {
public void runCommand(Player player) {
SimulatorExecutor.run(SIMULATOR);
}
@Register("show")
public void showCommand(Player player) {
SimulatorWatcher.show(SIMULATOR, player);
}
@Register("hide")
public void hideCommand(Player player) {
SimulatorWatcher.hide(SIMULATOR, player);
}
}

Datei anzeigen

@ -76,11 +76,14 @@ public class SimulatorWatcher {
@EventHandler
public void onPlayerQuit(PlayerQuitEvent event) {
watchers.remove(event.getPlayer());
hide(event.getPlayer());
show(null, event.getPlayer());
}
}
private REntityServer createSim(REntityServer server, Simulator simulator) {
if (simulator == null) {
return null;
}
Map<Vector, Set<Class<?>>> positionCache = new HashMap<>();
simulator.getElements().stream().map(SimulatorGroup::getElements).flatMap(List::stream).forEach(simulatorElement -> {
boolean wasNotPresent = positionCache.computeIfAbsent(simulatorElement.getPosition(), __ -> new HashSet<>())
@ -95,23 +98,16 @@ public class SimulatorWatcher {
}
public void show(Simulator sim, Player player) {
entityServers.forEach((simulator, rEntityServer) -> {
if (rEntityServer == null) return;
if (rEntityServer.getPlayers().contains(player) && sim != simulator) {
rEntityServer.removePlayer(player);
}
});
if (sim == null) return;
entityServers.computeIfAbsent(sim, __ -> createSim(new REntityServer(), sim)).addPlayer(player);
}
public void hide(Player player) {
entityServers.replaceAll((simulator, rEntityServer) -> {
rEntityServer.removePlayer(player);
return rEntityServer.getPlayers().isEmpty() ? null : rEntityServer;
});
}
public void hide(Simulator sim, Player player) {
entityServers.computeIfPresent(sim, (simulator, rEntityServer) -> {
rEntityServer.removePlayer(player);
return rEntityServer.getPlayers().isEmpty() ? null : rEntityServer;
});
}
List<REntity> getEntitiesOfSimulator(Simulator simulator) {
REntityServer entityServer = entityServers.get(simulator);
if (entityServer == null) {

Datei anzeigen

@ -20,6 +20,7 @@
package de.steamwar.bausystem.features.simulator2.data;
import de.steamwar.bausystem.features.simulator2.execute.SimulatorAction;
import de.steamwar.bausystem.features.simulator2.gui.base.SimulatorBaseGui;
import de.steamwar.inventory.InvCallback;
import de.steamwar.inventory.SWItem;
import lombok.Getter;
@ -103,4 +104,13 @@ public abstract class SimulatorElement<T extends SimulatorPhase> {
phase.toSimulatorActions(actions, position.clone());
});
}
public abstract void open(Player player, Simulator simulator, SimulatorGroup group, SimulatorBaseGui back);
public SimulatorGroup getGroup(Simulator simulator) {
return simulator.getElements().stream()
.filter(simulatorGroup -> simulatorGroup.getElements().contains(this))
.findFirst()
.orElse(null);
}
}

Datei anzeigen

@ -78,7 +78,7 @@ public class SimulatorGroup {
lore.add("");
lore.add("§cDisabled");
}
return new SWItem(material, "§eGroup", lore, disabled, groupCallback);
return new SWItem(material != null ? material : Material.ENDER_CHEST, "§eGroup", lore, disabled, groupCallback);
}
}

Datei anzeigen

@ -34,7 +34,7 @@ public abstract class SimulatorPhase {
protected int tickOffset = 0;
protected int lifetime = 80;
protected int order = 1;
protected int order = 0;
public abstract void toSimulatorActions(Map<Integer, List<SimulatorAction>> actions, Vector position);
}

Datei anzeigen

@ -19,8 +19,13 @@
package de.steamwar.bausystem.features.simulator2.data.redstone;
import de.steamwar.bausystem.features.simulator2.data.Simulator;
import de.steamwar.bausystem.features.simulator2.data.SimulatorElement;
import de.steamwar.bausystem.features.simulator2.data.SimulatorGroup;
import de.steamwar.bausystem.features.simulator2.gui.SimulatorRedstoneGui;
import de.steamwar.bausystem.features.simulator2.gui.base.SimulatorBaseGui;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.util.Vector;
public class RedstoneElement extends SimulatorElement<RedstonePhase> {
@ -43,4 +48,9 @@ public class RedstoneElement extends SimulatorElement<RedstonePhase> {
public Vector getWorldPos() {
return position.clone().add(new Vector(0.5, 0, 0.5));
}
@Override
public void open(Player player, Simulator simulator, SimulatorGroup group, SimulatorBaseGui back) {
new SimulatorRedstoneGui(player, simulator, group, this, back).open();
}
}

Datei anzeigen

@ -51,12 +51,17 @@ public class RedstonePhase extends SimulatorPhase {
.add(new SimulatorAction(0, 1) {
@Override
public void accept(World world) {
// TODO: 0 Tick Pistons not working
Block block = world.getBlockAt(position.getBlockX(), position.getBlockY(), position.getBlockZ());
previousBlockState.set(block.getState());
block.setType(Material.REDSTONE_BLOCK);
previousBlockState.get().update(true, true);
}
});
if (lifetime == 0) {
return;
}
actions.computeIfAbsent(tickOffset + lifetime, __ -> new ArrayList<>())
.add(new SimulatorAction(0, 1) {
@Override

Datei anzeigen

@ -19,7 +19,11 @@
package de.steamwar.bausystem.features.simulator2.data.tnt;
import de.steamwar.bausystem.features.simulator2.data.Simulator;
import de.steamwar.bausystem.features.simulator2.data.SimulatorElement;
import de.steamwar.bausystem.features.simulator2.data.SimulatorGroup;
import de.steamwar.bausystem.features.simulator2.gui.SimulatorTNTGui;
import de.steamwar.bausystem.features.simulator2.gui.base.SimulatorBaseGui;
import de.steamwar.inventory.InvCallback;
import de.steamwar.inventory.SWItem;
import org.bukkit.Material;
@ -77,4 +81,9 @@ public class TNTElement extends SimulatorElement<TNTPhase> {
public Material getWorldMaterial() {
return Material.TNT;
}
@Override
public void open(Player player, Simulator simulator, SimulatorGroup group, SimulatorBaseGui back) {
new SimulatorTNTGui(player, simulator, this, group, back).open();
}
}

Datei anzeigen

@ -49,7 +49,9 @@ public class SimulatorGroupGui extends SimulatorPageGui<SimulatorElement<?>> {
@Override
public void headerAndFooter() {
simulatorGroup.getElements().removeIf(element -> element.getPhases().isEmpty());
if (simulatorGroup.getElements().removeIf(element -> element.getPhases().isEmpty())) {
SimulatorWatcher.update(simulator);
}
if (simulatorGroup.getElements().size() < 2) {
back.open();
return;
@ -62,27 +64,26 @@ public class SimulatorGroupGui extends SimulatorPageGui<SimulatorElement<?>> {
}));
inventory.setItem(4, simulatorGroup.toItem(player, clickType -> {
if (simulatorGroup.getMaterial() == null) return;
new SimulatorMaterialGui(player, simulator, simulatorGroup::getMaterial, simulatorGroup::setMaterial, this).open();
}, clickType -> {
}));
inventory.setItem(48, new SWItem(Material.REPEATER, "§eSettings", clickType -> {
inventory.setItem(simulatorGroup.getMaterial() != null ? 48 : 49, new SWItem(Material.REPEATER, "§eSettings", clickType -> {
new SimulatorGroupSettingsGui(player, simulator, simulatorGroup, this).open();
}));
inventory.setItem(50, new SWItem(simulatorGroup.isDisabled() ? Material.ENDER_PEARL : Material.ENDER_EYE, simulatorGroup.isDisabled() ? "§cDisabled" : "§aEnabled", clickType -> {
simulatorGroup.setDisabled(!simulatorGroup.isDisabled());
SimulatorWatcher.update(simulator);
}));
if (simulatorGroup.getMaterial() != null) {
inventory.setItem(50, new SWItem(simulatorGroup.isDisabled() ? Material.ENDER_PEARL : Material.ENDER_EYE, simulatorGroup.isDisabled() ? "§cDisabled" : "§aEnabled", clickType -> {
simulatorGroup.setDisabled(!simulatorGroup.isDisabled());
SimulatorWatcher.update(simulator);
}));
}
}
@Override
public SWItem convert(SimulatorElement<?> element) {
return element.toItem(player, clickType -> {
if (element instanceof TNTElement) {
new SimulatorTNTGui(player, simulator, (TNTElement) element, simulatorGroup, this).open();
} else if (element instanceof RedstoneElement) {
new SimulatorRedstoneGui(player, simulator, simulatorGroup, (RedstoneElement) element, this).open();
}
element.open(player, simulator, simulatorGroup, this);
});
}
}

Datei anzeigen

@ -59,6 +59,7 @@ public class SimulatorGroupSettingsGui extends SimulatorBaseGui {
// Material Chooser
inventory.setItem(4, simulatorGroup.toItem(player, clickType -> {
if (simulatorGroup.getMaterial() == null) return;
new SimulatorMaterialGui(player, simulator, simulatorGroup::getMaterial, simulatorGroup::setMaterial, this).open();
}, clickType -> {}));

Datei anzeigen

@ -19,6 +19,7 @@
package de.steamwar.bausystem.features.simulator2.gui;
import de.steamwar.bausystem.features.simulator2.SimulatorWatcher;
import de.steamwar.bausystem.features.simulator2.data.Simulator;
import de.steamwar.bausystem.features.simulator2.data.SimulatorElement;
import de.steamwar.bausystem.features.simulator2.data.SimulatorGroup;
@ -42,7 +43,9 @@ public class SimulatorGui extends SimulatorPageGui<SimulatorGroup> {
@Override
public void headerAndFooter() {
simulator.getElements().removeIf(element -> element.getElements().isEmpty() || element.getElements().stream().allMatch(simulatorElement -> simulatorElement.getPhases().isEmpty()));
if (simulator.getElements().removeIf(element -> element.getElements().isEmpty() || element.getElements().stream().allMatch(simulatorElement -> simulatorElement.getPhases().isEmpty()))) {
SimulatorWatcher.update(simulator);
}
inventory.setItem(4, simulator.toItem(player, clickType -> {
new SimulatorMaterialGui(player, simulator, simulator::getMaterial, simulator::setMaterial, this).open();
@ -58,11 +61,7 @@ public class SimulatorGui extends SimulatorPageGui<SimulatorGroup> {
new SimulatorGroupGui(player, simulator, simulatorGroup, this).open();
}, clickType -> {
SimulatorElement<?> element = simulatorGroup.getElements().get(0);
if (element instanceof TNTElement) {
new SimulatorTNTGui(player, simulator, (TNTElement) element, simulatorGroup, this).open();
} else if (element instanceof RedstoneElement) {
new SimulatorRedstoneGui(player, simulator, simulatorGroup, (RedstoneElement) element, this).open();
}
element.open(player, simulator, simulatorGroup, this);
});
}
}

Datei anzeigen

@ -55,6 +55,7 @@ public class SimulatorRedstoneGui extends SimulatorScrollGui<RedstonePhase> {
public void headerAndFooter() {
if (redstone.getPhases().isEmpty()) {
back.open();
SimulatorWatcher.update(simulator);
return;
}
@ -65,10 +66,7 @@ public class SimulatorRedstoneGui extends SimulatorScrollGui<RedstonePhase> {
if (parent.getElements().contains(redstone)) {
back.open();
} else {
SimulatorGroup newParent = simulator.getElements().stream()
.filter(simulatorGroup -> simulatorGroup.getElements().contains(redstone))
.findFirst()
.orElse(null);
SimulatorGroup newParent = redstone.getGroup(simulator);
if (newParent == null) {
player.closeInventory();
return;

Datei anzeigen

@ -109,7 +109,7 @@ public class SimulatorRedstoneSettingsGui extends SimulatorBaseGui {
redstone.move(0, 0, clickType.isShiftClick() ? 5 : 1);
SimulatorWatcher.update(simulator);
});
inventory.setItem(26, new SWItem(Material.PAPER, "§eZ§8:§7" + redstone.getPosition().getBlockZ(), clickType -> {
inventory.setItem(26, new SWItem(Material.PAPER, "§eZ§8:§7 " + redstone.getPosition().getBlockZ(), clickType -> {
}));
inventory.setItem(35, SWItem.getDye(1), "§e-1", Arrays.asList("§7Shift§8: §e-5"), false, clickType -> {
redstone.move(0, 0, clickType.isShiftClick() ? -5 : -1);

Datei anzeigen

@ -55,6 +55,7 @@ public class SimulatorTNTGui extends SimulatorScrollGui<TNTPhase> {
public void headerAndFooter() {
if (tnt.getPhases().isEmpty()) {
back.open();
SimulatorWatcher.update(simulator);
return;
}
@ -65,10 +66,7 @@ public class SimulatorTNTGui extends SimulatorScrollGui<TNTPhase> {
if (parent.getElements().contains(tnt)) {
back.open();
} else {
SimulatorGroup newParent = simulator.getElements().stream()
.filter(simulatorGroup -> simulatorGroup.getElements().contains(tnt))
.findFirst()
.orElse(null);
SimulatorGroup newParent = tnt.getGroup(simulator);
if (newParent == null) {
player.closeInventory();
return;

Datei anzeigen

@ -25,6 +25,7 @@ import de.steamwar.bausystem.features.simulator2.data.SimulatorPhase;
import de.steamwar.bausystem.features.simulator2.data.tnt.TNTElement;
import de.steamwar.bausystem.features.simulator2.data.tnt.TNTPhase;
import de.steamwar.bausystem.features.simulator2.gui.base.SimulatorBaseGui;
import de.steamwar.core.Core;
import de.steamwar.inventory.SWItem;
import org.bukkit.Material;
import org.bukkit.entity.Player;
@ -130,9 +131,10 @@ public class SimulatorTNTPhaseSettingsGui extends SimulatorBaseGui {
SimulatorWatcher.update(simulator);
});
SWItem orderItem = new SWItem(Material.COMPASS, "§eCalculation Order§8:§7 " + order, clickType -> {
Material negativeNumbers = Material.getMaterial(Core.getVersion() >= 19 ? "RECOVERY_COMPASS" : "FIREWORK_STAR");
SWItem orderItem = new SWItem(order >= 0 ? Material.COMPASS : negativeNumbers, "§eCalculation Order§8:§7 " + order, clickType -> {
});
orderItem.getItemStack().setAmount(Math.max(1, Math.min(order, 30)));
orderItem.getItemStack().setAmount(Math.max(1, Math.min(Math.abs(order), 30)));
inventory.setItem(22, orderItem);
inventory.setItem(31, SWItem.getDye(order > -SimulatorPhase.ORDER_LIMIT ? 1 : 8), "§e-1", Arrays.asList("§7Shift§8: §e-5"), false, clickType -> {