Merge pull request #83 from D3v1s0m/2.X

action delay and fallback skin server
This commit is contained in:
Pyr 2023-08-18 00:50:48 +02:00 committed by GitHub
commit 6e6cef56f6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 139 additions and 57 deletions

@ -6,12 +6,14 @@ import java.util.UUID;
public abstract class InteractionAction {
private final UUID id;
private final long cooldown;
private final long delay;
private final InteractionType interactionType;
protected InteractionAction(long delay, InteractionType interactionType) {
protected InteractionAction(long cooldown, long delay, InteractionType interactionType) {
this.interactionType = interactionType;
this.id = UUID.randomUUID();
this.cooldown = cooldown;
this.delay = delay;
}
@ -20,6 +22,10 @@ public abstract class InteractionAction {
}
public long getCooldown() {
return cooldown;
}
public long getDelay() {
return delay;
}

@ -149,7 +149,7 @@ public class ZNpcsPlus extends JavaPlugin {
typeRegistry.registerDefault(packetEvents, propertyRegistry);
actionRegistry.registerTypes(scheduler, adventure, bungeeConnector, textSerializer);
packetEvents.getEventManager().registerListener(new InteractionPacketListener(userManager, npcRegistry), PacketListenerPriority.MONITOR);
packetEvents.getEventManager().registerListener(new InteractionPacketListener(userManager, npcRegistry, scheduler), PacketListenerPriority.MONITOR);
new Metrics(this, 18244);
pluginManager.registerEvents(new UserListener(userManager), this);
getServer().getMessenger().registerOutgoingPluginChannel(this, "BungeeCord");

@ -153,18 +153,18 @@ public class ZNpcImporter implements DataImporter {
throw new IllegalArgumentException("Couldn't adapt znpcs click type: " + clickType);
}
private InteractionActionImpl adaptAction(String type, InteractionType clickType, String parameter, int delay) {
private InteractionActionImpl adaptAction(String type, InteractionType clickType, String parameter, int cooldown) {
switch (type.toLowerCase()) {
case "cmd":
return new PlayerCommandAction(taskScheduler, parameter, clickType, delay * 1000L);
return new PlayerCommandAction(taskScheduler, parameter, clickType, cooldown * 1000L, 0);
case "console":
return new ConsoleCommandAction(taskScheduler, parameter, clickType, delay * 1000L);
return new ConsoleCommandAction(taskScheduler, parameter, clickType, cooldown * 1000L, 0);
case "chat":
return new PlayerChatAction(taskScheduler, parameter, clickType, delay * 1000L);
return new PlayerChatAction(taskScheduler, parameter, clickType, cooldown * 1000L, 0);
case "message":
return new MessageAction(adventure, parameter, clickType, textSerializer, delay * 1000L);
return new MessageAction(adventure, parameter, clickType, textSerializer, cooldown * 1000L, 0);
case "server":
return new SwitchServerAction(bungeeConnector, parameter, clickType, delay * 1000L);
return new SwitchServerAction(bungeeConnector, parameter, clickType, cooldown * 1000L, 0);
}
throw new IllegalArgumentException("Couldn't adapt znpcs click action: " + type);
}

@ -6,8 +6,8 @@ import lol.pyr.znpcsplus.api.interaction.InteractionType;
import net.kyori.adventure.text.Component;
public abstract class InteractionActionImpl extends InteractionAction {
protected InteractionActionImpl(long delay, InteractionType interactionType) {
super(delay, interactionType);
protected InteractionActionImpl(long cooldown, long delay, InteractionType interactionType) {
super(cooldown, delay, interactionType);
}
public abstract Component getInfo(String id, int index, CommandContext context);

@ -10,6 +10,7 @@ import lol.pyr.znpcsplus.api.interaction.InteractionType;
import lol.pyr.znpcsplus.npc.NpcEntryImpl;
import lol.pyr.znpcsplus.npc.NpcImpl;
import lol.pyr.znpcsplus.npc.NpcRegistryImpl;
import lol.pyr.znpcsplus.scheduling.TaskScheduler;
import lol.pyr.znpcsplus.user.User;
import lol.pyr.znpcsplus.user.UserManager;
import org.bukkit.Bukkit;
@ -18,10 +19,12 @@ import org.bukkit.entity.Player;
public class InteractionPacketListener implements PacketListener {
private final UserManager userManager;
private final NpcRegistryImpl npcRegistry;
private final TaskScheduler scheduler;
public InteractionPacketListener(UserManager userManager, NpcRegistryImpl npcRegistry) {
public InteractionPacketListener(UserManager userManager, NpcRegistryImpl npcRegistry, TaskScheduler scheduler) {
this.userManager = userManager;
this.npcRegistry = npcRegistry;
this.scheduler = scheduler;
}
@Override
@ -46,7 +49,7 @@ public class InteractionPacketListener implements PacketListener {
for (InteractionAction action : npc.getActions()) {
if (action.getInteractionType() != InteractionType.ANY_CLICK && action.getInteractionType() != type) continue;
if (action.getCooldown() > 0 && !user.actionCooldownCheck(action)) continue;
action.run(player);
scheduler.runLaterAsync(() -> action.run(player), action.getDelay());
}
}

@ -16,8 +16,8 @@ public class ConsoleCommandAction extends InteractionActionImpl {
private final TaskScheduler scheduler;
private final String command;
public ConsoleCommandAction(TaskScheduler scheduler, String command, InteractionType interactionType, long delay) {
super(delay, interactionType);
public ConsoleCommandAction(TaskScheduler scheduler, String command, InteractionType interactionType, long cooldown, long delay) {
super(cooldown, delay, interactionType);
this.scheduler = scheduler;
this.command = command;
}
@ -35,7 +35,7 @@ public class ConsoleCommandAction extends InteractionActionImpl {
.hoverEvent(HoverEvent.hoverEvent(HoverEvent.Action.SHOW_TEXT,
Component.text("Click to edit this action", NamedTextColor.GRAY)))
.clickEvent(ClickEvent.clickEvent(ClickEvent.Action.SUGGEST_COMMAND,
"/" + context.getLabel() + " action edit " + id + " " + index + " consolecommand " + getInteractionType().name() + " " + getCooldown()/1000 + " " + command))
"/" + context.getLabel() + " action edit " + id + " " + index + " consolecommand " + getInteractionType().name() + " " + getCooldown()/1000 + " " + getDelay() + " " + command))
.append(Component.text(" | ", NamedTextColor.GRAY))
.append(Component.text("[DELETE]", NamedTextColor.RED)
.hoverEvent(HoverEvent.hoverEvent(HoverEvent.Action.SHOW_TEXT,
@ -45,7 +45,7 @@ public class ConsoleCommandAction extends InteractionActionImpl {
.append(Component.text(" | ", NamedTextColor.GRAY))
.append(Component.text("Console Command: ", NamedTextColor.GREEN)
.hoverEvent(HoverEvent.hoverEvent(HoverEvent.Action.SHOW_TEXT,
Component.text("Click Type: " + getInteractionType().name() + " Cooldown: " + getCooldown()/1000, NamedTextColor.GREEN))))
Component.text("Click Type: " + getInteractionType().name() + " Cooldown: " + getCooldown()/1000 + " Delay: " + getDelay(), NamedTextColor.GRAY))))
.append(Component.text(command, NamedTextColor.WHITE)));
}

@ -22,14 +22,14 @@ public class ConsoleCommandActionType implements InteractionActionType<ConsoleCo
@Override
public String serialize(ConsoleCommandAction obj) {
return Base64.getEncoder().encodeToString(obj.getCommand().getBytes(StandardCharsets.UTF_8)) + ";" + obj.getCooldown() + ";" + obj.getInteractionType().name();
return Base64.getEncoder().encodeToString(obj.getCommand().getBytes(StandardCharsets.UTF_8)) + ";" + obj.getCooldown() + ";" + obj.getInteractionType().name() + ";" + obj.getDelay();
}
@Override
public ConsoleCommandAction deserialize(String str) {
String[] split = str.split(";");
InteractionType type = split.length > 2 ? InteractionType.valueOf(split[2]) : InteractionType.ANY_CLICK;
return new ConsoleCommandAction(scheduler, new String(Base64.getDecoder().decode(split[0]), StandardCharsets.UTF_8), type, Long.parseLong(split[1]));
return new ConsoleCommandAction(scheduler, new String(Base64.getDecoder().decode(split[0]), StandardCharsets.UTF_8), type, Long.parseLong(split[1]), Long.parseLong(split.length > 3 ? split[3] : "0"));
}
@Override
@ -44,21 +44,23 @@ public class ConsoleCommandActionType implements InteractionActionType<ConsoleCo
@Override
public void appendUsage(CommandContext context) {
context.setUsage(context.getUsage() + " " + getSubcommandName() + " <id> <click type> <cooldown seconds> <server>");
context.setUsage(context.getUsage() + " " + getSubcommandName() + " <id> <click type> <cooldown seconds> <delay ticks> <server>");
}
@Override
public InteractionActionImpl parse(CommandContext context) throws CommandExecutionException {
InteractionType type = context.parse(InteractionType.class);
long cooldown = (long) (context.parse(Double.class) * 1000D);
long delay = (long) (context.parse(Integer.class) * 1D);
String command = context.dumpAllArgs();
return new ConsoleCommandAction(scheduler, command, type, cooldown);
return new ConsoleCommandAction(scheduler, command, type, cooldown, delay);
}
@Override
public List<String> suggest(CommandContext context) throws CommandExecutionException {
if (context.argSize() == 1) return context.suggestEnum(InteractionType.values());
if (context.argSize() == 2) return context.suggestLiteral("1");
if (context.argSize() == 3) return context.suggestLiteral("0");
return Collections.emptyList();
}
}

@ -17,8 +17,8 @@ public class MessageAction extends InteractionActionImpl {
private final String message;
private final LegacyComponentSerializer textSerializer;
public MessageAction(BukkitAudiences adventure, String message, InteractionType interactionType, LegacyComponentSerializer textSerializer, long delay) {
super(delay, interactionType);
public MessageAction(BukkitAudiences adventure, String message, InteractionType interactionType, LegacyComponentSerializer textSerializer, long cooldown, long delay) {
super(cooldown, delay, interactionType);
this.adventure = adventure;
this.message = message;
this.textSerializer = textSerializer;
@ -38,7 +38,7 @@ public class MessageAction extends InteractionActionImpl {
.hoverEvent(HoverEvent.hoverEvent(HoverEvent.Action.SHOW_TEXT,
Component.text("Click to edit this action", NamedTextColor.GRAY)))
.clickEvent(ClickEvent.clickEvent(ClickEvent.Action.SUGGEST_COMMAND,
"/" + context.getLabel() + " action edit " + id + " " + index + " message " + getInteractionType().name() + " " + getCooldown()/1000 + " " + message))
"/" + context.getLabel() + " action edit " + id + " " + index + " message " + getInteractionType().name() + " " + getCooldown()/1000 + " " + getDelay() + " " + message))
.append(Component.text(" | ", NamedTextColor.GRAY))
.append(Component.text("[DELETE]", NamedTextColor.RED)
.hoverEvent(HoverEvent.hoverEvent(HoverEvent.Action.SHOW_TEXT,
@ -48,7 +48,7 @@ public class MessageAction extends InteractionActionImpl {
.append(Component.text(" | ", NamedTextColor.GRAY))
.append(Component.text("Message: ", NamedTextColor.GREEN)
.hoverEvent(HoverEvent.hoverEvent(HoverEvent.Action.SHOW_TEXT,
Component.text("Click Type: " + getInteractionType().name() + " Cooldown: " + getCooldown()/1000, NamedTextColor.GREEN))))
Component.text("Click Type: " + getInteractionType().name() + " Cooldown: " + getCooldown()/1000 + " Delay: " + getDelay(), NamedTextColor.GRAY))))
.append(Component.text(message, NamedTextColor.WHITE)));
}

@ -25,14 +25,14 @@ public class MessageActionType implements InteractionActionType<MessageAction>,
@Override
public String serialize(MessageAction obj) {
return Base64.getEncoder().encodeToString(obj.getMessage().getBytes(StandardCharsets.UTF_8)) + ";" + obj.getCooldown() + ";" + obj.getInteractionType().name();
return Base64.getEncoder().encodeToString(obj.getMessage().getBytes(StandardCharsets.UTF_8)) + ";" + obj.getCooldown() + ";" + obj.getInteractionType().name() + ";" + obj.getDelay();
}
@Override
public MessageAction deserialize(String str) {
String[] split = str.split(";");
InteractionType type = split.length > 2 ? InteractionType.valueOf(split[2]) : InteractionType.ANY_CLICK;
return new MessageAction(adventure, new String(Base64.getDecoder().decode(split[0]), StandardCharsets.UTF_8), type, textSerializer, Long.parseLong(split[1]));
return new MessageAction(adventure, new String(Base64.getDecoder().decode(split[0]), StandardCharsets.UTF_8), type, textSerializer, Long.parseLong(split[1]), Long.parseLong(split.length > 3 ? split[3] : "0"));
}
@Override
@ -47,21 +47,23 @@ public class MessageActionType implements InteractionActionType<MessageAction>,
@Override
public void appendUsage(CommandContext context) {
context.setUsage(context.getUsage() + " " + getSubcommandName() + " <id> <click type> <cooldown seconds> <message>");
context.setUsage(context.getUsage() + " " + getSubcommandName() + " <id> <click type> <cooldown seconds> <delay ticks> <message>");
}
@Override
public InteractionActionImpl parse(CommandContext context) throws CommandExecutionException {
InteractionType type = context.parse(InteractionType.class);
long cooldown = (long) (context.parse(Double.class) * 1000D);
long delay = (long) (context.parse(Integer.class) * 1D);
String message = context.dumpAllArgs();
return new MessageAction(adventure, message, type, textSerializer, cooldown);
return new MessageAction(adventure, message, type, textSerializer, cooldown, delay);
}
@Override
public List<String> suggest(CommandContext context) throws CommandExecutionException {
if (context.argSize() == 1) return context.suggestEnum(InteractionType.values());
if (context.argSize() == 2) return context.suggestLiteral("1");
if (context.argSize() == 3) return context.suggestLiteral("0");
return Collections.emptyList();
}
}

@ -14,8 +14,8 @@ public class PlayerChatAction extends InteractionActionImpl {
private final String message;
private final TaskScheduler scheduler;
public PlayerChatAction(TaskScheduler scheduler, String message, InteractionType interactionType, long delay) {
super(delay, interactionType);
public PlayerChatAction(TaskScheduler scheduler, String message, InteractionType interactionType, long cooldown, long delay) {
super(cooldown, delay, interactionType);
this.message = message;
this.scheduler = scheduler;
}
@ -33,7 +33,7 @@ public class PlayerChatAction extends InteractionActionImpl {
.hoverEvent(HoverEvent.hoverEvent(HoverEvent.Action.SHOW_TEXT,
Component.text("Click to edit this action", NamedTextColor.GRAY)))
.clickEvent(ClickEvent.clickEvent(ClickEvent.Action.SUGGEST_COMMAND,
"/" + context.getLabel() + " action edit " + id + " " + index + " playerchat " + getInteractionType().name() + " " + getCooldown()/1000 + " " + message))
"/" + context.getLabel() + " action edit " + id + " " + index + " playerchat " + getInteractionType().name() + " " + getCooldown()/1000 + " " + getDelay() + " " + message))
.append(Component.text(" | ", NamedTextColor.GRAY))
.append(Component.text("[DELETE]", NamedTextColor.RED)
.hoverEvent(HoverEvent.hoverEvent(HoverEvent.Action.SHOW_TEXT,
@ -43,7 +43,7 @@ public class PlayerChatAction extends InteractionActionImpl {
.append(Component.text(" | ", NamedTextColor.GRAY))
.append(Component.text("Player Chat: ", NamedTextColor.GREEN)
.hoverEvent(HoverEvent.hoverEvent(HoverEvent.Action.SHOW_TEXT,
Component.text("Click Type: " + getInteractionType().name() + " Cooldown: " + getCooldown()/1000, NamedTextColor.GREEN))))
Component.text("Click Type: " + getInteractionType().name() + " Cooldown: " + getCooldown()/1000 + " Delay: " + getDelay(), NamedTextColor.GRAY))))
.append(Component.text(message, NamedTextColor.WHITE)));
}

@ -22,13 +22,13 @@ public class PlayerChatActionType implements InteractionActionType<PlayerChatAct
@Override
public String serialize(PlayerChatAction obj) {
return Base64.getEncoder().encodeToString(obj.getMessage().getBytes(StandardCharsets.UTF_8)) + ";" + obj.getCooldown() + ";" + obj.getInteractionType().name();
return Base64.getEncoder().encodeToString(obj.getMessage().getBytes(StandardCharsets.UTF_8)) + ";" + obj.getCooldown() + ";" + obj.getInteractionType().name() + ";" + obj.getDelay();
}
@Override
public PlayerChatAction deserialize(String str) {
String[] split = str.split(";");
return new PlayerChatAction(scheduler, new String(Base64.getDecoder().decode(split[0]), StandardCharsets.UTF_8), InteractionType.valueOf(split[2]), Long.parseLong(split[1]));
return new PlayerChatAction(scheduler, new String(Base64.getDecoder().decode(split[0]), StandardCharsets.UTF_8), InteractionType.valueOf(split[2]), Long.parseLong(split[1]), Long.parseLong(split.length > 3 ? split[3] : "0"));
}
@Override
@ -43,21 +43,23 @@ public class PlayerChatActionType implements InteractionActionType<PlayerChatAct
@Override
public void appendUsage(CommandContext context) {
context.setUsage(context.getUsage() + " " + getSubcommandName() + " <id> <click type> <cooldown seconds> <server>");
context.setUsage(context.getUsage() + " " + getSubcommandName() + " <id> <click type> <cooldown seconds> <delay ticks> <server>");
}
@Override
public InteractionActionImpl parse(CommandContext context) throws CommandExecutionException {
InteractionType type = context.parse(InteractionType.class);
long cooldown = (long) (context.parse(Double.class) * 1000D);
long delay = (long) (context.parse(Integer.class) * 1D);
String message = context.dumpAllArgs();
return new PlayerChatAction(scheduler, message, type, cooldown);
return new PlayerChatAction(scheduler, message, type, cooldown, delay);
}
@Override
public List<String> suggest(CommandContext context) throws CommandExecutionException {
if (context.argSize() == 1) return context.suggestEnum(InteractionType.values());
if (context.argSize() == 2) return context.suggestLiteral("1");
if (context.argSize() == 3) return context.suggestLiteral("0");
return Collections.emptyList();
}
}

@ -15,8 +15,8 @@ public class PlayerCommandAction extends InteractionActionImpl {
private final TaskScheduler scheduler;
private final String command;
public PlayerCommandAction(TaskScheduler scheduler, String command, InteractionType interactionType, long delay) {
super(delay, interactionType);
public PlayerCommandAction(TaskScheduler scheduler, String command, InteractionType interactionType, long cooldown, long delay) {
super(cooldown, delay, interactionType);
this.scheduler = scheduler;
this.command = command;
}
@ -34,7 +34,7 @@ public class PlayerCommandAction extends InteractionActionImpl {
.hoverEvent(HoverEvent.hoverEvent(HoverEvent.Action.SHOW_TEXT,
Component.text("Click to edit this action", NamedTextColor.GRAY)))
.clickEvent(ClickEvent.clickEvent(ClickEvent.Action.SUGGEST_COMMAND,
"/" + context.getLabel() + " action edit " + id + " " + index + " playercommand " + getInteractionType().name() + " " + getCooldown()/1000 + " " + command))
"/" + context.getLabel() + " action edit " + id + " " + index + " playercommand " + getInteractionType().name() + " " + getCooldown()/1000 + " " + getDelay() + " " + command))
.append(Component.text(" | ", NamedTextColor.GRAY))
.append(Component.text("[DELETE]", NamedTextColor.RED)
.hoverEvent(HoverEvent.hoverEvent(HoverEvent.Action.SHOW_TEXT,
@ -44,7 +44,7 @@ public class PlayerCommandAction extends InteractionActionImpl {
.append(Component.text(" | ", NamedTextColor.GRAY))
.append(Component.text("Player Command: ", NamedTextColor.GREEN)
.hoverEvent(HoverEvent.hoverEvent(HoverEvent.Action.SHOW_TEXT,
Component.text("Click Type: " + getInteractionType().name() + " Cooldown: " + getCooldown()/1000, NamedTextColor.GREEN))))
Component.text("Click Type: " + getInteractionType().name() + " Cooldown: " + getCooldown()/1000 + " Delay: " + getDelay(), NamedTextColor.GRAY))))
.append(Component.text(command, NamedTextColor.WHITE)));
}

@ -22,14 +22,14 @@ public class PlayerCommandActionType implements InteractionActionType<PlayerComm
@Override
public String serialize(PlayerCommandAction obj) {
return Base64.getEncoder().encodeToString(obj.getCommand().getBytes(StandardCharsets.UTF_8)) + ";" + obj.getCooldown() + ";" + obj.getInteractionType().name();
return Base64.getEncoder().encodeToString(obj.getCommand().getBytes(StandardCharsets.UTF_8)) + ";" + obj.getCooldown() + ";" + obj.getInteractionType().name() + ";" + obj.getDelay();
}
@Override
public PlayerCommandAction deserialize(String str) {
String[] split = str.split(";");
InteractionType type = split.length > 2 ? InteractionType.valueOf(split[2]) : InteractionType.ANY_CLICK;
return new PlayerCommandAction(scheduler, new String(Base64.getDecoder().decode(split[0]), StandardCharsets.UTF_8), type, Long.parseLong(split[1]));
return new PlayerCommandAction(scheduler, new String(Base64.getDecoder().decode(split[0]), StandardCharsets.UTF_8), type, Long.parseLong(split[1]), Long.parseLong(split.length > 3 ? split[3] : "0"));
}
@Override
@ -44,21 +44,23 @@ public class PlayerCommandActionType implements InteractionActionType<PlayerComm
@Override
public void appendUsage(CommandContext context) {
context.setUsage(context.getUsage() + " " + getSubcommandName() + " <id> <click type> <cooldown seconds> <command>");
context.setUsage(context.getUsage() + " " + getSubcommandName() + " <id> <click type> <cooldown seconds> <delay ticks> <command>");
}
@Override
public InteractionActionImpl parse(CommandContext context) throws CommandExecutionException {
InteractionType type = context.parse(InteractionType.class);
long cooldown = (long) (context.parse(Double.class) * 1000D);
long delay = (long) (context.parse(Integer.class) * 1D);
String command = context.dumpAllArgs();
return new PlayerCommandAction(scheduler, command, type, cooldown);
return new PlayerCommandAction(scheduler, command, type, cooldown, delay);
}
@Override
public List<String> suggest(CommandContext context) throws CommandExecutionException {
if (context.argSize() == 1) return context.suggestEnum(InteractionType.values());
if (context.argSize() == 2) return context.suggestLiteral("1");
if (context.argSize() == 3) return context.suggestLiteral("0");
return Collections.emptyList();
}
}

@ -14,8 +14,8 @@ public class SwitchServerAction extends InteractionActionImpl {
private final BungeeConnector bungeeConnector;
private final String server;
public SwitchServerAction(BungeeConnector bungeeConnector, String server, InteractionType interactionType, long delay) {
super(delay, interactionType);
public SwitchServerAction(BungeeConnector bungeeConnector, String server, InteractionType interactionType, long cooldown, long delay) {
super(cooldown, delay, interactionType);
this.bungeeConnector = bungeeConnector;
this.server = server;
}
@ -32,7 +32,7 @@ public class SwitchServerAction extends InteractionActionImpl {
.hoverEvent(HoverEvent.hoverEvent(HoverEvent.Action.SHOW_TEXT,
Component.text("Click to edit this action", NamedTextColor.GRAY)))
.clickEvent(ClickEvent.clickEvent(ClickEvent.Action.SUGGEST_COMMAND,
"/" + context.getLabel() + " action edit " + id + " " + index + " switcserver " + getInteractionType().name() + " " + getCooldown()/1000 + " " + server))
"/" + context.getLabel() + " action edit " + id + " " + index + " switcserver " + getInteractionType().name() + " " + getCooldown()/1000 + " " + getDelay() + " " + server))
.append(Component.text(" | ", NamedTextColor.GRAY))
.append(Component.text("[DELETE]", NamedTextColor.RED)
.hoverEvent(HoverEvent.hoverEvent(HoverEvent.Action.SHOW_TEXT,
@ -42,7 +42,7 @@ public class SwitchServerAction extends InteractionActionImpl {
.append(Component.text(" | ", NamedTextColor.GRAY))
.append(Component.text("Switch Server: ", NamedTextColor.GREEN)
.hoverEvent(HoverEvent.hoverEvent(HoverEvent.Action.SHOW_TEXT,
Component.text("Click Type: " + getInteractionType().name() + " Cooldown: " + getCooldown()/1000, NamedTextColor.GREEN))))
Component.text("Click Type: " + getInteractionType().name() + " Cooldown: " + getCooldown()/1000 + " Delay: " + getDelay(), NamedTextColor.GRAY))))
.append(Component.text(server, NamedTextColor.WHITE)));
}

@ -22,14 +22,14 @@ public class SwitchServerActionType implements InteractionActionType<SwitchServe
@Override
public String serialize(SwitchServerAction obj) {
return Base64.getEncoder().encodeToString(obj.getServer().getBytes(StandardCharsets.UTF_8)) + ";" + obj.getCooldown() + ";" + obj.getInteractionType().name();
return Base64.getEncoder().encodeToString(obj.getServer().getBytes(StandardCharsets.UTF_8)) + ";" + obj.getCooldown() + ";" + obj.getInteractionType().name() + ";" + obj.getDelay();
}
@Override
public SwitchServerAction deserialize(String str) {
String[] split = str.split(";");
InteractionType type = split.length > 2 ? InteractionType.valueOf(split[2]) : InteractionType.ANY_CLICK;
return new SwitchServerAction(bungeeConnector, new String(Base64.getDecoder().decode(split[0]), StandardCharsets.UTF_8), type, Long.parseLong(split[1]));
return new SwitchServerAction(bungeeConnector, new String(Base64.getDecoder().decode(split[0]), StandardCharsets.UTF_8), type, Long.parseLong(split[1]), Long.parseLong(split.length > 3 ? split[3] : "0"));
}
@Override
@ -44,21 +44,23 @@ public class SwitchServerActionType implements InteractionActionType<SwitchServe
@Override
public void appendUsage(CommandContext context) {
context.setUsage(context.getUsage() + " " + getSubcommandName() + " <id> <click type> <cooldown seconds> <server>");
context.setUsage(context.getUsage() + " " + getSubcommandName() + " <id> <click type> <cooldown seconds> <delay ticks> <server>");
}
@Override
public InteractionActionImpl parse(CommandContext context) throws CommandExecutionException {
InteractionType type = context.parse(InteractionType.class);
long cooldown = (long) (context.parse(Double.class) * 1000D);
long delay = (long) (context.parse(Integer.class) * 1D);
String server = context.dumpAllArgs();
return new SwitchServerAction(bungeeConnector, server, type, cooldown);
return new SwitchServerAction(bungeeConnector, server, type, cooldown, delay);
}
@Override
public List<String> suggest(CommandContext context) throws CommandExecutionException {
if (context.argSize() == 1) return context.suggestEnum(InteractionType.values());
if (context.argSize() == 2) return context.suggestLiteral("1");
if (context.argSize() == 3) return context.suggestLiteral("0");
return Collections.emptyList();
}
}

@ -169,6 +169,14 @@ public final class Reflections {
.setStrict(FoliaUtil.isFolia())
.toMethodReflection();
public static final ReflectionLazyLoader<Method> FOLIA_RUN_NOW_ASYNC =
new ReflectionBuilder(ASYNC_SCHEDULER_CLASS)
.withMethodName("runNow")
.withParameterTypes(Plugin.class, Consumer.class)
.withExpectResult(SCHEDULED_TASK_CLASS)
.setStrict(FoliaUtil.isFolia())
.toMethodReflection();
public static final ReflectionLazyLoader<Method> FOLIA_RUN_DELAYED_ASYNC =
new ReflectionBuilder(ASYNC_SCHEDULER_CLASS)
.withMethodName("runDelayed")

@ -43,6 +43,16 @@ public class FoliaScheduler extends TaskScheduler {
}
}
@Override
public void runAsyncGlobal(Runnable runnable) {
try {
Object scheduler = Reflections.FOLIA_GET_ASYNC_SCHEDULER.get().invoke(null);
Reflections.FOLIA_RUN_NOW_ASYNC.get().invoke(scheduler, plugin, (Consumer<Object>) o -> runnable.run());
} catch (IllegalAccessException | InvocationTargetException e) {
throw new RuntimeException(e);
}
}
@Override
public void runLaterAsync(Runnable runnable, long delay) {
try {

@ -24,6 +24,11 @@ public class SpigotScheduler extends TaskScheduler {
Bukkit.getScheduler().runTask(plugin, runnable);
}
@Override
public void runAsyncGlobal(Runnable runnable) {
Bukkit.getScheduler().runTaskAsynchronously(plugin, runnable);
}
@Override
public void runLaterAsync(Runnable runnable, long delay) {
Bukkit.getScheduler().runTaskLaterAsynchronously(plugin, runnable, delay);

@ -13,6 +13,7 @@ public abstract class TaskScheduler {
public abstract void schedulePlayerChat(Player player, String message);
public abstract void schedulePlayerCommand(Player player, String command);
public abstract void runSyncGlobal(Runnable runnable);
public abstract void runAsyncGlobal(Runnable runnable);
public abstract void runLaterAsync(Runnable runnable, long delay);
public abstract void runDelayedTimerAsync(Runnable runnable, long delay, long interval);
public abstract void cancelAll();

@ -42,7 +42,7 @@ public class MojangSkinCache {
Player player = Bukkit.getPlayerExact(name);
if (player != null && player.isOnline()) return CompletableFuture.completedFuture(getFromPlayer(player));
if (cache.containsKey(name.toLowerCase())) return fetchByUUID(idCache.get(name.toLowerCase()).getId());
if (idCache.containsKey(name.toLowerCase())) return fetchByUUID(idCache.get(name.toLowerCase()).getId());
return CompletableFuture.supplyAsync(() -> {
URL url = parseUrl("https://api.mojang.com/users/profiles/minecraft/" + name);
@ -52,14 +52,52 @@ public class MojangSkinCache {
connection.setRequestMethod("GET");
try (Reader reader = new InputStreamReader(connection.getInputStream(), StandardCharsets.UTF_8)) {
JsonObject obj = JsonParser.parseReader(reader).getAsJsonObject();
if (obj.has("errorMessage")) return null;
if (obj.has("errorMessage")) return fetchByNameFallback(name).join();
String id = obj.get("id").getAsString();
idCache.put(name.toLowerCase(), new CachedId(id));
return fetchByUUID(id).join();
Skin skin = fetchByUUID(id).join();
if (skin == null) return fetchByNameFallback(name).join();
return skin;
}
} catch (IOException exception) {
if (!configManager.getConfig().disableSkinFetcherWarnings()) {
logger.warning("Failed to get uuid from player name:");
logger.warning("Failed to get uuid from player name, trying to use fallback server:");
exception.printStackTrace();
}
return fetchByNameFallback(name).join();
} finally {
if (connection != null) connection.disconnect();
}
});
}
public CompletableFuture<Skin> fetchByNameFallback(String name) {
Player player = Bukkit.getPlayerExact(name);
if (player != null && player.isOnline()) return CompletableFuture.completedFuture(getFromPlayer(player));
if (idCache.containsKey(name.toLowerCase())) return fetchByUUID(idCache.get(name.toLowerCase()).getId());
return CompletableFuture.supplyAsync(() -> {
URL url = parseUrl("https://api.ashcon.app/mojang/v2/user/" + name);
HttpURLConnection connection = null;
try {
connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
try (Reader reader = new InputStreamReader(connection.getInputStream(), StandardCharsets.UTF_8)) {
JsonObject obj = JsonParser.parseReader(reader).getAsJsonObject();
if (obj.has("error")) return null;
String uuid = obj.get("uuid").getAsString();
idCache.put(name.toLowerCase(), new CachedId(uuid));
JsonObject textures = obj.get("textures").getAsJsonObject();
String value = textures.get("raw").getAsJsonObject().get("value").getAsString();
String signature = textures.get("raw").getAsJsonObject().get("signature").getAsString();
Skin skin = new Skin(value, signature);
cache.put(uuid, skin);
return skin;
}
} catch (IOException exception) {
if (!configManager.getConfig().disableSkinFetcherWarnings()) {
logger.warning("Failed to fetch skin from fallback server:");
exception.printStackTrace();
}
} finally {
@ -105,13 +143,14 @@ public class MojangSkinCache {
connection.setRequestMethod("GET");
try (Reader reader = new InputStreamReader(connection.getInputStream(), StandardCharsets.UTF_8)) {
JsonObject obj = JsonParser.parseReader(reader).getAsJsonObject();
if (obj.has("errorMessage")) return null;
Skin skin = new Skin(obj);
cache.put(uuid, skin);
return skin;
}
} catch (IOException exception) {
if (!configManager.getConfig().disableSkinFetcherWarnings()) {
logger.warning("Failed to fetch skin:");
logger.warning("Failed to fetch skin, trying to use fallback server:");
exception.printStackTrace();
}
} finally {