add User, delete a bunch of stuff we're not using anymore

This commit is contained in:
Pyrbu 2023-04-25 17:57:18 +01:00
parent 499780bd24
commit 6f9bcb5d0b
57 changed files with 150 additions and 3607 deletions

@ -1,77 +0,0 @@
package io.github.znetworkw.znpcservers.commands;
import com.google.common.collect.Iterables;
import io.github.znetworkw.znpcservers.exception.CommandException;
import io.github.znetworkw.znpcservers.exception.CommandExecuteException;
import io.github.znetworkw.znpcservers.exception.CommandPermissionException;
import io.github.znetworkw.znpcservers.reflection.Reflections;
import org.bukkit.ChatColor;
import org.bukkit.command.CommandSender;
import org.bukkit.command.defaults.BukkitCommand;
import java.lang.reflect.Method;
import java.util.*;
public class Command extends BukkitCommand {
private final Map<CommandInformation, CommandInvoker> subCommands;
public Command(String name) {
super(name);
this.subCommands = new HashMap<>();
load();
}
private void load() {
Reflections.COMMAND_MAP_FIELD.get().register(getName(), this);
for (Method method : getClass().getMethods()) {
if (method.isAnnotationPresent(CommandInformation.class)) {
CommandInformation cmdInfo = method.getAnnotation(CommandInformation.class);
this.subCommands.put(cmdInfo, new CommandInvoker(this, method, cmdInfo.permission()));
}
}
}
private Map<String, String> loadArgs(CommandInformation subCommand, Iterable<String> args) {
int size = Iterables.size(args);
int subCommandsSize = (subCommand.arguments()).length;
Map<String, String> argsMap = new HashMap<>();
if (size > 1) if (subCommand.isMultiple()) {
argsMap.put(Iterables.get(args, 1), String.join(" ", Iterables.skip(args, 2)));
} else {
for (int i = 0; i < Math.min(subCommandsSize, size); i++) {
int fixedLength = i + 1;
if (size > fixedLength) {
String input = Iterables.get(args, fixedLength);
if (fixedLength == subCommandsSize)
input = String.join(" ", Iterables.skip(args, subCommandsSize));
argsMap.put(subCommand.arguments()[i], input);
}
}
}
return argsMap;
}
public Set<CommandInformation> getCommands() {
return this.subCommands.keySet();
}
public boolean execute(CommandSender sender, String commandLabel, String[] args) {
Optional<Map.Entry<CommandInformation, CommandInvoker>> subCommandOptional = this.subCommands.entrySet().stream().filter(command -> command.getKey().name().contentEquals((args.length > 0) ? args[0] : "")).findFirst();
if (subCommandOptional.isEmpty()) {
sender.sendMessage(ChatColor.RED + "Unable to locate the following command: " + commandLabel + ".");
return false;
}
try {
Map.Entry<CommandInformation, CommandInvoker> subCommand = subCommandOptional.get();
subCommand.getValue().execute(new io.github.znetworkw.znpcservers.commands.CommandSender(sender), loadArgs(subCommand.getKey(), Arrays.asList(args)));
} catch (CommandExecuteException e) {
sender.sendMessage(ChatColor.RED + "Cannot execute this command or this command execution has failed.");
e.printStackTrace();
} catch (CommandPermissionException e) {
sender.sendMessage(ChatColor.RED + "You do not have permission to execute this command.");
} catch (CommandException e) {
sender.sendMessage(ChatColor.RED + e.getMessage());
}
return true;
}
}

@ -1,18 +0,0 @@
package io.github.znetworkw.znpcservers.commands;
import java.lang.annotation.*;
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface CommandInformation {
String[] arguments();
String[] help() default {};
String name();
String permission();
boolean isMultiple() default false;
}

@ -1,37 +0,0 @@
package io.github.znetworkw.znpcservers.commands;
import io.github.znetworkw.znpcservers.exception.CommandException;
import io.github.znetworkw.znpcservers.exception.CommandExecuteException;
import io.github.znetworkw.znpcservers.exception.CommandPermissionException;
import org.bukkit.entity.Player;
import java.lang.reflect.Method;
public class CommandInvoker {
private final Command command;
private final Method commandMethod;
private final String permission;
public CommandInvoker(Command command, Method commandMethod, String permission) {
this.command = command;
this.commandMethod = commandMethod;
this.permission = permission;
}
public void execute(CommandSender sender, Object command) throws CommandException {
// Check if the sender is not a player
if (!(sender.getCommandSender() instanceof Player player))
throw new CommandException("Only players may execute this command.");
// Check if the permission is not empty and the player does not have the permission
if (this.permission.length() > 0 && !player.hasPermission(this.permission))
throw new CommandPermissionException("You cannot execute this command.");
try {
// Command execution
this.commandMethod.invoke(this.command, sender, command);
} catch (IllegalAccessException | java.lang.reflect.InvocationTargetException e) {
throw new CommandExecuteException(e.getMessage(), e.getCause());
}
}
}

@ -1,61 +0,0 @@
package io.github.znetworkw.znpcservers.commands;
import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import lol.pyr.znpcsplus.ZNPCsPlus;
import net.kyori.adventure.text.TextComponent;
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
import org.bukkit.entity.Player;
import java.util.Arrays;
import java.util.stream.Collectors;
public class CommandSender {
static final Joiner LINE_SEPARATOR_JOINER = Joiner.on("\n");
private static final ImmutableList<String> HELP_PREFIX = ImmutableList.of("&6&lEXAMPLES&r:");
private final org.bukkit.command.CommandSender commandSender;
private final SenderType type;
public CommandSender(org.bukkit.command.CommandSender commandSender) {
this.commandSender = commandSender;
this.type = (commandSender instanceof Player) ? SenderType.PLAYER : SenderType.CONSOLE;
}
public void sendMessage(String message) {
sendMessage(message, null);
}
public void sendMessage(CommandInformation subCommand) {
sendMessage(" &7\u00BB &6/&eznpcs " + subCommand.name() + " " +
Arrays.stream(subCommand.arguments())
.map(s -> "<" + s + ">")
.collect(Collectors.joining(" ")),
Arrays.asList(subCommand.help()));
}
public void sendMessage(String message, Iterable<String> hover) {
message = message.replace(LegacyComponentSerializer.SECTION_CHAR, LegacyComponentSerializer.AMPERSAND_CHAR);
LegacyComponentSerializer serializer = LegacyComponentSerializer.legacyAmpersand();
TextComponent textComponent = serializer.deserialize(message);
if (hover != null) textComponent = textComponent.hoverEvent(serializer.deserialize(LINE_SEPARATOR_JOINER.join(Iterables.concat(HELP_PREFIX, hover))));
ZNPCsPlus.ADVENTURE.player(getPlayer()).sendMessage(textComponent);
}
public Player getPlayer() {
if (this.type != SenderType.PLAYER)
throw new IllegalStateException("The following sender is not a player.");
return (Player) getCommandSender();
}
public org.bukkit.command.CommandSender getCommandSender() {
return this.commandSender;
}
enum SenderType {
PLAYER, CONSOLE
}
}

@ -1,573 +0,0 @@
package io.github.znetworkw.znpcservers.commands.list;
import com.github.retrooper.packetevents.protocol.player.EquipmentSlot;
import com.google.common.base.Joiner;
import com.google.common.base.Splitter;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.primitives.Doubles;
import com.google.common.primitives.Ints;
import io.github.znetworkw.znpcservers.commands.Command;
import io.github.znetworkw.znpcservers.commands.CommandInformation;
import io.github.znetworkw.znpcservers.commands.CommandSender;
import io.github.znetworkw.znpcservers.commands.list.inventory.ConversationGUI;
import io.github.znetworkw.znpcservers.configuration.Configuration;
import io.github.znetworkw.znpcservers.configuration.ConfigurationConstants;
import io.github.znetworkw.znpcservers.configuration.ConfigurationValue;
import io.github.znetworkw.znpcservers.npc.*;
import io.github.znetworkw.znpcservers.npc.conversation.Conversation;
import io.github.znetworkw.znpcservers.npc.conversation.ConversationModel;
import io.github.znetworkw.znpcservers.user.ZUser;
import io.github.znetworkw.znpcservers.utility.location.ZLocation;
import lol.pyr.znpcsplus.ZNPCsPlus;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.event.ClickEvent;
import net.kyori.adventure.text.event.HoverEvent;
import net.kyori.adventure.text.format.NamedTextColor;
import net.kyori.adventure.text.format.TextDecoration;
import net.md_5.bungee.api.ChatColor;
import org.bukkit.entity.Player;
import java.lang.reflect.Method;
import java.util.List;
import java.util.Map;
import java.util.Objects;
@SuppressWarnings({"UnstableApiUsage", "deprecation"})
public class DefaultCommand extends Command {
private static final Splitter SPACE_SPLITTER = Splitter.on(" ");
private static final Joiner SPACE_JOINER = Joiner.on(" ");
private static final SkinFunction DO_APPLY_SKIN = (sender, npc, skin) -> NPCSkin.forName(skin, (npcSkin, ex) -> {
if (ex != null) {
Configuration.MESSAGES.sendMessage(sender, ConfigurationValue.CANT_GET_SKIN, skin);
ZNPCsPlus.LOGGER.warning("Failed to fetch skin:");
ex.printStackTrace();
return;
}
npc.changeSkin(npcSkin);
Configuration.MESSAGES.sendMessage(sender, ConfigurationValue.GET_SKIN);
});
public DefaultCommand() {
super("znpcs");
}
@CommandInformation(arguments = {}, name = "", permission = "")
public void defaultCommand(CommandSender sender, Map<String, String> args) {
sender.sendMessage("&6&m------------------------------------------");
sender.sendMessage("&b&lZNPCsPlus &8\u00BB &7ZNetwork & Pyr");
sender.sendMessage("&6https://www.spigotmc.org/resources/znpcsplus.109380/");
Objects.requireNonNull(sender);
getCommands().forEach(sender::sendMessage);
sender.sendMessage(ChatColor.DARK_GRAY + "Hover over the commands to view command arguments.");
sender.sendMessage("&6&m------------------------------------------");
}
@CommandInformation(arguments = {"id", "type", "name"}, name = "create", permission = "znpcs.cmd.create", help = {" &f&l* &e/znpcs create <npc_id> PLAYER Steve"})
public void createNPC(CommandSender sender, Map<String, String> args) {
if (args.size() < 3) {
Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.INCORRECT_USAGE);
return;
}
Integer id = Ints.tryParse(args.get("id"));
if (id == null) {
Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.INVALID_NUMBER);
return;
}
boolean foundNPC = ConfigurationConstants.NPC_LIST.stream().anyMatch(npc -> (npc.getId() == id));
if (foundNPC) {
Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.NPC_FOUND);
return;
}
String name = args.get("name").trim();
if (name.length() < 3 || name.length() > 16) {
Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.INVALID_NAME_LENGTH);
return;
}
NPCType npcType = NPCType.valueOf(args.get("type").toUpperCase());
if (npcType.getConstructor() == null && !npcType.equals(NPCType.PLAYER)) {
Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.NOT_SUPPORTED_NPC_TYPE);
return;
}
// ZNPCsPlus.createNPC(id, npcType, sender.getPlayer().getLocation(), name);
Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.SUCCESS);
}
@CommandInformation(arguments = {"id"}, name = "delete", permission = "znpcs.cmd.delete", help = {" &f&l* &e/znpcs delete <npc_id>"})
public void deleteNPC(CommandSender sender, Map<String, String> args) {
if (args.size() < 1) {
Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.INCORRECT_USAGE);
return;
}
Integer id = Ints.tryParse(args.get("id"));
if (id == null) {
Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.INVALID_NUMBER);
return;
}
NPC foundNPC = NPC.find(id);
if (foundNPC == null) {
Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.NPC_NOT_FOUND);
return;
}
// ZNPCsPlus.deleteNPC(id);
Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.SUCCESS);
}
@CommandInformation(arguments = {}, name = "list", permission = "znpcs.cmd.list")
public void list(CommandSender sender, Map<String, String> args) {
if (ConfigurationConstants.NPC_LIST.isEmpty()) {
Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.NO_NPC_FOUND);
} else {
sender.sendMessage(ChatColor.DARK_GREEN + "NPC list:");
for (NPCModel npcModel : ConfigurationConstants.NPC_LIST)
ZNPCsPlus.ADVENTURE.player(sender.getPlayer()).sendMessage(Component.text("-", NamedTextColor.GREEN)
.append(Component.text(" " + npcModel.getId(), npcModel.getShouldSpawn() ? NamedTextColor.GREEN : NamedTextColor.RED))
.append(Component.text(" " + npcModel.getHologramLines().toString() +
" (" + npcModel.getLocation().getWorldName() + " " + (int) npcModel.getLocation().getX() + " " +
(int) npcModel.getLocation().getY() + " " + (int) npcModel.getLocation().getZ() + ") ", NamedTextColor.GREEN))
.append(Component.text("[TELEPORT]", NamedTextColor.DARK_GREEN, TextDecoration.BOLD)
.clickEvent(ClickEvent.runCommand("/znpcs teleport " + npcModel.getId()))
.hoverEvent(HoverEvent.showText(Component.text("Click to teleport to this NPC."))))
.append(Component.text(" [DELETE]", NamedTextColor.RED, TextDecoration.BOLD)
.clickEvent(ClickEvent.runCommand("/znpcs delete " + npcModel.getId()))
.hoverEvent(HoverEvent.showText(Component.text("Click to delete this NPC.")))));
}
}
@CommandInformation(arguments = {"id", "skin"}, name = "skin", permission = "znpcs.cmd.skin", help = {" &f&l* &e/znpcs skin <npc_id> Notch"})
public void setSkin(CommandSender sender, Map<String, String> args) {
if (args.size() < 1) {
Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.INCORRECT_USAGE);
return;
}
Integer id = Ints.tryParse(args.get("id"));
if (id == null) {
Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.INVALID_NUMBER);
return;
}
NPC foundNPC = NPC.find(id);
if (foundNPC == null) {
Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.NPC_NOT_FOUND);
return;
}
String skin = args.get("skin");
Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.FETCHING_SKIN, skin);
DO_APPLY_SKIN.apply(sender.getPlayer(), foundNPC, args.get("skin"));
}
@CommandInformation(arguments = {"id", "slot"}, name = "equip", permission = "znpcs.cmd.equip", help = {" &f&l* &e/znpcs equip <npc_id> [HAND/OFFHAND/HELMET/CHESTPLATE/LEGGINGS/BOOTS]", "&8(You need to have the item in your hand)."})
public void equip(CommandSender sender, Map<String, String> args) {
if (args.size() < 2) {
Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.INCORRECT_USAGE);
return;
}
Integer id = Ints.tryParse(args.get("id"));
if (id == null) {
Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.INVALID_NUMBER);
return;
}
NPC foundNPC = NPC.find(id);
if (foundNPC == null) {
Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.NPC_NOT_FOUND);
return;
}
foundNPC.getNpcPojo().getNpcEquip().put(EquipmentSlot.valueOf(args.get("slot").toUpperCase()), sender.getPlayer().getInventory().getItemInHand());
foundNPC.getPackets().flushCache("equipPackets");
Objects.requireNonNull(foundNPC);
foundNPC.getViewers().forEach(foundNPC::sendEquipPackets);
Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.SUCCESS);
}
@CommandInformation(arguments = {"id", "lines"}, name = "lines", permission = "znpcs.cmd.lines", help = {" &f&l* &e/znpcs lines <npc_id> First Second Third-Space"})
public void changeLines(CommandSender sender, Map<String, String> args) {
if (args.size() < 2) {
Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.INCORRECT_USAGE);
return;
}
Integer id = Ints.tryParse(args.get("id"));
if (id == null) {
Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.INVALID_NUMBER);
return;
}
NPC foundNPC = NPC.find(id);
if (foundNPC == null) {
Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.NPC_NOT_FOUND);
return;
}
foundNPC.getNpcPojo().setHologramLines(Lists.reverse(SPACE_SPLITTER.splitToList(args.get("lines"))));
foundNPC.getHologram().createHologram();
Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.SUCCESS);
}
@CommandInformation(arguments = {"id"}, name = "move", permission = "znpcs.cmd.move", help = {" &f&l* &e/znpcs move <npc_id>"})
public void move(CommandSender sender, Map<String, String> args) {
if (args.size() < 1) {
Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.INCORRECT_USAGE);
return;
}
Integer id = Ints.tryParse(args.get("id"));
if (id == null) {
Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.INVALID_NUMBER);
return;
}
NPC foundNPC = NPC.find(id);
if (foundNPC == null) {
Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.NPC_NOT_FOUND);
return;
}
foundNPC.getNpcPojo().setLocation(new ZLocation(sender.getPlayer().getLocation()));
foundNPC.changeType(foundNPC.getNpcPojo().getNpcType());
Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.SUCCESS);
}
@CommandInformation(arguments = {"id", "type"}, name = "type", permission = "znpcs.cmd.type", help = {" &f&l* &e/znpcs type <npc_id> ZOMBIE"})
public void changeType(CommandSender sender, Map<String, String> args) {
if (args.size() < 2) {
Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.INCORRECT_USAGE);
return;
}
Integer id = Ints.tryParse(args.get("id"));
if (id == null) {
Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.INVALID_NUMBER);
return;
}
NPC foundNPC = NPC.find(id);
if (foundNPC == null) {
Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.NPC_NOT_FOUND);
return;
}
NPCType npcType = NPCType.valueOf(args.get("type").toUpperCase());
if (npcType != NPCType.PLAYER && npcType.getConstructor() == null) {
Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.UNSUPPORTED_ENTITY);
return;
}
foundNPC.changeType(npcType);
Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.SUCCESS);
}
@CommandInformation(arguments = {"add", "remove", "cooldown", "list"}, name = "action", isMultiple = true, permission = "znpcs.cmd.action", help = {" &f&l* &e/znpcs action add <npc_id> SERVER survival", " &f&l* &e/znpcs action add <npc_id> CMD spawn", " &f&l* &e/znpcs action remove <npc_id> <action_id>", " &f&l* &e/znpcs action cooldown <npc_id> <action_id> <delay_in_seconds>", " &f&l* &e/znpcs action list <npc_id>"})
public void action(CommandSender sender, Map<String, String> args) {
if (args.size() < 1) {
Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.INCORRECT_USAGE);
return;
}
if (args.containsKey("add")) {
List<String> split = SPACE_SPLITTER.splitToList(args.get("add"));
if (split.size() < 3) {
Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.ACTION_ADD_INCORRECT_USAGE);
return;
}
Integer id = Ints.tryParse(split.get(0));
if (id == null) {
Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.INVALID_NUMBER);
return;
}
NPC foundNPC = NPC.find(id);
if (foundNPC == null) {
Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.NPC_NOT_FOUND);
return;
}
foundNPC.getNpcPojo().getClickActions().add(new NPCAction(split.get(1).toUpperCase(), SPACE_JOINER.join(Iterables.skip(split, 2))));
Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.SUCCESS);
} else if (args.containsKey("remove")) {
List<String> split = SPACE_SPLITTER.splitToList(args.get("remove"));
Integer id = Ints.tryParse(split.get(0));
if (id == null) {
Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.INVALID_NUMBER);
return;
}
NPC foundNPC = NPC.find(id);
if (foundNPC == null) {
Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.NPC_NOT_FOUND);
return;
}
Integer actionId = Ints.tryParse(split.get(1));
if (actionId == null) {
Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.INVALID_NUMBER);
} else {
if (actionId >= foundNPC.getNpcPojo().getClickActions().size()) {
Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.NO_ACTION_FOUND);
return;
}
foundNPC.getNpcPojo().getClickActions().remove(actionId.intValue());
Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.SUCCESS);
}
} else if (args.containsKey("cooldown")) {
List<String> split = SPACE_SPLITTER.splitToList(args.get("cooldown"));
if (split.size() < 2) {
Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.ACTION_DELAY_INCORRECT_USAGE);
return;
}
Integer id = Ints.tryParse(split.get(0));
if (id == null) {
Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.INVALID_NUMBER);
return;
}
NPC foundNPC = NPC.find(id);
if (foundNPC == null) {
Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.NPC_NOT_FOUND);
return;
}
Integer actionId = Ints.tryParse(split.get(1));
Integer actionDelay = Ints.tryParse(split.get(2));
if (actionId == null || actionDelay == null) {
Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.INVALID_NUMBER);
} else {
if (actionId >= foundNPC.getNpcPojo().getClickActions().size()) {
Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.NO_ACTION_FOUND);
return;
}
foundNPC.getNpcPojo().getClickActions().get(actionId).setDelay(actionDelay);
Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.SUCCESS);
}
} else if (args.containsKey("list")) {
Integer id = Ints.tryParse(args.get("list"));
if (id == null) {
Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.INVALID_NUMBER);
return;
}
NPC foundNPC = NPC.find(id);
if (foundNPC == null) {
Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.NPC_NOT_FOUND);
return;
}
if (foundNPC.getNpcPojo().getClickActions().isEmpty()) {
Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.NO_ACTION_FOUND);
} else {
foundNPC.getNpcPojo().getClickActions().forEach(s -> sender.sendMessage("&8(&a" + foundNPC.getNpcPojo().getClickActions().indexOf(s) + "&8) &6" + s.toString()));
}
}
}
@CommandInformation(arguments = {"id", "type", "value"}, name = "toggle", permission = "znpcs.cmd.toggle", help = {" &f&l* &e/znpcs toggle <npc_id> look"})
public void toggle(CommandSender sender, Map<String, String> args) {
if (args.size() < 2) {
Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.INCORRECT_USAGE);
return;
}
Integer id = Ints.tryParse(args.get("id"));
if (id == null) {
Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.INVALID_NUMBER);
return;
}
NPC foundNPC = NPC.find(id);
if (foundNPC == null) {
Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.NPC_NOT_FOUND);
return;
}
NPCFunction npcFunction = FunctionFactory.findFunctionForName(args.get("type"));
if (npcFunction.getName().equalsIgnoreCase("glow")) {
npcFunction.doRunFunction(foundNPC, new FunctionContext.ContextWithValue(foundNPC, args.get("value") != null ? args.get("value").toUpperCase() : "WHITE"));
} else {
npcFunction.doRunFunction(foundNPC, new FunctionContext.DefaultContext(foundNPC));
}
Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.SUCCESS);
}
@CommandInformation(arguments = {"id", "customizeValues"}, name = "customize", permission = "znpcs.cmd.customize", help = {" &f&l* &e/znpcs customize <npc_id> <customization>"})
public void customize(CommandSender sender, Map<String, String> args) {
Integer id = Ints.tryParse(args.get("id"));
if (id == null) {
Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.INVALID_NUMBER);
return;
}
NPC foundNPC = NPC.find(id);
if (foundNPC == null) {
Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.NPC_NOT_FOUND);
return;
}
NPCType npcType = foundNPC.getNpcPojo().getNpcType();
if (args.get("customizeValues") == null) {
Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.INCORRECT_USAGE);
for (Map.Entry<String, Method> method : npcType.getCustomizationLoader().getMethods().entrySet())
sender.sendMessage(ChatColor.YELLOW + method.getKey() + " " + SPACE_JOINER.join(method.getValue().getParameterTypes()));
return;
}
List<String> customizeOptions = SPACE_SPLITTER.splitToList(args.get("customizeValues"));
String methodName = customizeOptions.get(0);
if (npcType.getCustomizationLoader().contains(methodName)) {
Method method = npcType.getCustomizationLoader().getMethods().get(methodName);
Iterable<String> split = Iterables.skip(customizeOptions, 1);
if (Iterables.size(split) < (method.getParameterTypes()).length) {
Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.TOO_FEW_ARGUMENTS);
return;
}
split = Iterables.transform(split, String::toUpperCase);
String[] values = Iterables.toArray(split, String.class);
try {
npcType.updateCustomization(foundNPC, methodName, values);
foundNPC.getNpcPojo().getCustomizationMap().put(methodName, values);
Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.SUCCESS);
}catch (Exception e) {
Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.INVALID_CUSTOMIZE_ARGUMENTS);
if (ConfigurationConstants.DEBUG_ENABLED) {
e.printStackTrace();
}
}
} else {
Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.METHOD_NOT_FOUND);
for (Map.Entry<String, Method> method : npcType.getCustomizationLoader().getMethods().entrySet())
sender.sendMessage(ChatColor.YELLOW + method.getKey() + " " + SPACE_JOINER.join(method.getValue().getParameterTypes()));
}
}
@CommandInformation(arguments = {"set", "create", "exit", "path", "list"}, name = "path", isMultiple = true, permission = "znpcs.cmd.path", help = {" &f&l* &e/znpcs path create name", " &f&l* &e/znpcs path set <npc_id> name"})
public void path(CommandSender sender, Map<String, String> args) {
if (args.size() < 1) {
Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.INCORRECT_USAGE);
return;
}
ZUser znpcUser = ZUser.find(sender.getPlayer());
if (znpcUser == null)
return;
if (args.containsKey("set")) {
List<String> split = SPACE_SPLITTER.splitToList(args.get("set"));
if (split.size() < 2) {
Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.PATH_SET_INCORRECT_USAGE);
return;
}
Integer id = Ints.tryParse(split.get(0));
if (id == null) {
Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.INVALID_NUMBER);
return;
}
NPC foundNPC = NPC.find(id);
if (foundNPC == null) {
Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.NPC_NOT_FOUND);
return;
}
foundNPC.setPath(NPCPath.AbstractTypeWriter.find(split.get(1)));
Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.SUCCESS);
} else if (args.containsKey("create")) {
String pathName = args.get("create");
if (pathName.length() < 3 || pathName.length() > 16) {
Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.INVALID_NAME_LENGTH);
return;
}
if (NPCPath.AbstractTypeWriter.find(pathName) != null) {
Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.PATH_FOUND);
return;
}
if (znpcUser.isHasPath()) {
sender.getPlayer().sendMessage(ChatColor.RED + "You already have a path creator active! To remove it, type " + ChatColor.WHITE + "/znpcs path exit" + ChatColor.RED + ".");
return;
}
NPCPath.AbstractTypeWriter.forCreation(pathName, znpcUser, NPCPath.AbstractTypeWriter.TypeWriter.MOVEMENT);
Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.PATH_START);
} else if (args.containsKey("exit")) {
znpcUser.setHasPath(false);
Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.EXIT_PATH);
} else if (args.containsKey("list")) {
if (NPCPath.AbstractTypeWriter.getPaths().isEmpty()) {
Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.NO_PATH_FOUND);
} else {
NPCPath.AbstractTypeWriter.getPaths().forEach(path -> sender.getPlayer().sendMessage(ChatColor.GREEN + path.getName()));
}
}
}
@CommandInformation(arguments = {"id"}, name = "teleport", permission = "znpcs.cmd.teleport", help = {" &f&l* &e/znpcs teleport <npc_id>"})
public void teleport(CommandSender sender, Map<String, String> args) {
if (args.size() < 1) {
Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.INCORRECT_USAGE);
return;
}
Integer id = Ints.tryParse(args.get("id"));
if (id == null) {
Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.INVALID_NUMBER);
return;
}
NPC foundNPC = NPC.find(id);
if (foundNPC == null) {
Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.NPC_NOT_FOUND);
return;
}
sender.getPlayer().teleport(foundNPC.getLocation());
}
@CommandInformation(arguments = {"id", "height"}, name = "height", permission = "znpcs.cmd.height", help = {" &f&l* &e/znpcs height <npc_id> 2", "&8Set a greater or lesser distance of a hologram from the NPC."})
public void changeHologramHeight(CommandSender sender, Map<String, String> args) {
if (args.size() < 2) {
Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.INCORRECT_USAGE);
return;
}
Integer id = Ints.tryParse(args.get("id"));
if (id == null) {
Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.INVALID_NUMBER);
return;
}
NPC foundNPC = NPC.find(id);
if (foundNPC == null) {
Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.NPC_NOT_FOUND);
return;
}
Double givenHeight = Doubles.tryParse(args.get("height"));
if (givenHeight == null) {
Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.INVALID_NUMBER);
return;
}
foundNPC.getNpcPojo().setHologramHeight(givenHeight);
foundNPC.getHologram().createHologram();
Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.SUCCESS);
}
@CommandInformation(arguments = {"create", "remove", "gui", "set"}, name = "conversation", isMultiple = true, permission = "znpcs.cmd.conversation", help = {" &f&l* &e/znpcs conversation create first", " &f&l* &e/znpcs conversation remove first", " &f&l* &e/znpcs conversation set <npc_id> first [CLICK/RADIUS]", " &f&l* &e/znpcs conversation gui &8(&7Opens a GUI to manage conversations&8)", "&8RADIUS: &7Activates when the player is near the NPC", "&8CLICK: &7Activates when the player interacts with the NPC"})
public void conversations(CommandSender sender, Map<String, String> args) {
if (args.size() < 1) {
Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.INCORRECT_USAGE);
return;
}
if (args.containsKey("create")) {
String conversationName = args.get("create");
if (Conversation.exists(conversationName)) {
Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.CONVERSATION_FOUND);
return;
}
if (conversationName.length() < 3 || conversationName.length() > 16) {
Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.INVALID_NAME_LENGTH);
return;
}
ConfigurationConstants.NPC_CONVERSATIONS.add(new Conversation(conversationName));
Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.SUCCESS);
} else if (args.containsKey("remove")) {
String conversationName = args.get("remove");
if (!Conversation.exists(conversationName)) {
Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.NO_CONVERSATION_FOUND);
return;
}
ConfigurationConstants.NPC_CONVERSATIONS.remove(Conversation.forName(conversationName));
Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.SUCCESS);
} else if (args.containsKey("gui")) {
sender.getPlayer().openInventory((new ConversationGUI(sender.getPlayer())).build());
} else if (args.containsKey("set")) {
List<String> split = SPACE_SPLITTER.splitToList(args.get("set"));
if (split.size() < 2) {
Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.CONVERSATION_SET_INCORRECT_USAGE);
return;
}
Integer id = Ints.tryParse(split.get(0));
if (id == null) {
Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.INVALID_NUMBER);
return;
}
NPC foundNPC = NPC.find(id);
if (foundNPC == null) {
Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.NPC_NOT_FOUND);
return;
}
String conversationName = split.get(1);
if (Conversation.exists(conversationName)) {
foundNPC.getNpcPojo().setConversation(new ConversationModel(conversationName, (split.size() > 1) ? split.get(2) : "CLICK"));
} else {
foundNPC.getNpcPojo().setConversation(null);
}
Configuration.MESSAGES.sendMessage(sender.getCommandSender(), ConfigurationValue.SUCCESS);
}
}
interface SkinFunction {
void apply(Player param1Player, NPC param1NPC, String param1String);
}
}

@ -2,28 +2,9 @@ package io.github.znetworkw.znpcservers.commands.list.inventory;
import com.google.common.base.Joiner; import com.google.common.base.Joiner;
import com.google.common.base.Splitter; import com.google.common.base.Splitter;
import com.google.common.collect.Iterables;
import com.google.common.primitives.Ints;
import io.github.znetworkw.znpcservers.configuration.Configuration;
import io.github.znetworkw.znpcservers.configuration.ConfigurationConstants;
import io.github.znetworkw.znpcservers.configuration.ConfigurationValue;
import io.github.znetworkw.znpcservers.npc.NPCAction;
import io.github.znetworkw.znpcservers.npc.conversation.Conversation;
import io.github.znetworkw.znpcservers.npc.conversation.ConversationKey;
import io.github.znetworkw.znpcservers.user.EventService;
import io.github.znetworkw.znpcservers.user.ZUser;
import io.github.znetworkw.znpcservers.utility.Utils;
import io.github.znetworkw.znpcservers.utility.inventory.ZInventory; import io.github.znetworkw.znpcservers.utility.inventory.ZInventory;
import io.github.znetworkw.znpcservers.utility.inventory.ZInventoryPage; import io.github.znetworkw.znpcservers.utility.inventory.ZInventoryPage;
import io.github.znetworkw.znpcservers.utility.itemstack.ItemStackBuilder;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.event.inventory.ClickType;
import org.bukkit.event.player.AsyncPlayerChatEvent;
import java.util.Collections;
import java.util.List;
public class ConversationGUI extends ZInventory { public class ConversationGUI extends ZInventory {
private static final Splitter SPACE_SPLITTER = Splitter.on(" "); private static final Splitter SPACE_SPLITTER = Splitter.on(" ");
@ -34,8 +15,16 @@ public class ConversationGUI extends ZInventory {
this.setCurrentPage(new MainPage(this)); this.setCurrentPage(new MainPage(this));
} }
@SuppressWarnings({"UnstableApiUsage", "deprecation"})
static class MainPage extends ZInventoryPage { static class MainPage extends ZInventoryPage {
public MainPage(ZInventory inventory) {
super(inventory, "Conversations", 6);
}
@Override
public void update() {
}
/*
int pageID = 1; int pageID = 1;
@ -79,7 +68,7 @@ public class ConversationGUI extends ZInventory {
this.addItem(ItemStackBuilder.forMaterial(Material.PAPER).setName(ChatColor.GREEN + conversation.getName()).setLore("&7this conversation has &b" + conversation.getTexts().size() + " &7texts,", "&7it will activate when a player is on a &b" + conversation.getRadius() + "x" + conversation.getRadius() + " &7radius,", "&7or when a player interacts with an npc.", "&7when the conversation is finish, there is a &b" + conversation.getDelay() + "s &7delay to start again.", "&f&lUSES", " &bLeft-click &7to manage texts.", " &bRight-click &7to add a new text.", " &bQ &7to change the radius.", " &bMiddle-click &7to change the cooldown.").build(), i - ((getRows() - 9) * (pageID - 1)), clickEvent -> { this.addItem(ItemStackBuilder.forMaterial(Material.PAPER).setName(ChatColor.GREEN + conversation.getName()).setLore("&7this conversation has &b" + conversation.getTexts().size() + " &7texts,", "&7it will activate when a player is on a &b" + conversation.getRadius() + "x" + conversation.getRadius() + " &7radius,", "&7or when a player interacts with an npc.", "&7when the conversation is finish, there is a &b" + conversation.getDelay() + "s &7delay to start again.", "&f&lUSES", " &bLeft-click &7to manage texts.", " &bRight-click &7to add a new text.", " &bQ &7to change the radius.", " &bMiddle-click &7to change the cooldown.").build(), i - ((getRows() - 9) * (pageID - 1)), clickEvent -> {
if (clickEvent.getClick() == ClickType.DROP) { if (clickEvent.getClick() == ClickType.DROP) {
Utils.sendTitle(this.getPlayer(), "&b&lCHANGE RADIUS", "&7Type the new radius..."); Utils.sendTitle(this.getPlayer(), "&b&lCHANGE RADIUS", "&7Type the new radius...");
EventService.addService(ZUser.find(this.getPlayer()), AsyncPlayerChatEvent.class).addConsumer(event -> { EventService.addService(User.get(this.getPlayer()), AsyncPlayerChatEvent.class).addConsumer(event -> {
if (!ConfigurationConstants.NPC_CONVERSATIONS.contains(conversation)) { if (!ConfigurationConstants.NPC_CONVERSATIONS.contains(conversation)) {
Configuration.MESSAGES.sendMessage(this.getPlayer(), ConfigurationValue.NO_CONVERSATION_FOUND); Configuration.MESSAGES.sendMessage(this.getPlayer(), ConfigurationValue.NO_CONVERSATION_FOUND);
} else { } else {
@ -96,7 +85,7 @@ public class ConversationGUI extends ZInventory {
}).addConsumer(event -> this.openInventory()); }).addConsumer(event -> this.openInventory());
} else if (clickEvent.isRightClick()) { } else if (clickEvent.isRightClick()) {
Utils.sendTitle(this.getPlayer(), "&e&lADD LINE", "&7Type the new line..."); Utils.sendTitle(this.getPlayer(), "&e&lADD LINE", "&7Type the new line...");
EventService.addService(ZUser.find(this.getPlayer()), AsyncPlayerChatEvent.class).addConsumer(event -> { EventService.addService(User.get(this.getPlayer()), AsyncPlayerChatEvent.class).addConsumer(event -> {
if (!ConfigurationConstants.NPC_CONVERSATIONS.contains(conversation)) { if (!ConfigurationConstants.NPC_CONVERSATIONS.contains(conversation)) {
Configuration.MESSAGES.sendMessage(this.getPlayer(), ConfigurationValue.NO_CONVERSATION_FOUND); Configuration.MESSAGES.sendMessage(this.getPlayer(), ConfigurationValue.NO_CONVERSATION_FOUND);
} else { } else {
@ -108,7 +97,7 @@ public class ConversationGUI extends ZInventory {
new EditConversationPage(this.getInventory(), conversation).openInventory(); new EditConversationPage(this.getInventory(), conversation).openInventory();
} else if (clickEvent.getClick() == ClickType.MIDDLE) { } else if (clickEvent.getClick() == ClickType.MIDDLE) {
Utils.sendTitle(this.getPlayer(), "&6&lCHANGE COOLDOWN", "&7Type the new cooldown..."); Utils.sendTitle(this.getPlayer(), "&6&lCHANGE COOLDOWN", "&7Type the new cooldown...");
EventService.addService(ZUser.find(this.getPlayer()), AsyncPlayerChatEvent.class).addConsumer(event -> { EventService.addService(User.get(this.getPlayer()), AsyncPlayerChatEvent.class).addConsumer(event -> {
if (!ConfigurationConstants.NPC_CONVERSATIONS.contains(conversation)) { if (!ConfigurationConstants.NPC_CONVERSATIONS.contains(conversation)) {
Configuration.MESSAGES.sendMessage(this.getPlayer(), ConfigurationValue.NO_CONVERSATION_FOUND); Configuration.MESSAGES.sendMessage(this.getPlayer(), ConfigurationValue.NO_CONVERSATION_FOUND);
} else { } else {
@ -182,7 +171,7 @@ public class ConversationGUI extends ZInventory {
} }
this.addItem(ItemStackBuilder.forMaterial(Material.EMERALD).setName(ChatColor.AQUA + "ADD A NEW ACTION").setLore("&7click here...").build(), this.getRows() - 5, clickEvent -> { this.addItem(ItemStackBuilder.forMaterial(Material.EMERALD).setName(ChatColor.AQUA + "ADD A NEW ACTION").setLore("&7click here...").build(), this.getRows() - 5, clickEvent -> {
Utils.sendTitle(this.getPlayer(), "&d&lADD ACTION", "&7Type the new action..."); Utils.sendTitle(this.getPlayer(), "&d&lADD ACTION", "&7Type the new action...");
EventService.addService(ZUser.find(this.getPlayer()), AsyncPlayerChatEvent.class).addConsumer(event -> { EventService.addService(User.get(this.getPlayer()), AsyncPlayerChatEvent.class).addConsumer(event -> {
if (ConfigurationConstants.NPC_CONVERSATIONS.contains(this.conversation) && this.conversation.getTexts().contains(this.conversationKey)) { if (ConfigurationConstants.NPC_CONVERSATIONS.contains(this.conversation) && this.conversation.getTexts().contains(this.conversationKey)) {
List<String> stringList = SPACE_SPLITTER.splitToList(event.getMessage()); List<String> stringList = SPACE_SPLITTER.splitToList(event.getMessage());
if (stringList.size() < 2) { if (stringList.size() < 2) {
@ -199,7 +188,7 @@ public class ConversationGUI extends ZInventory {
} }
} }
@SuppressWarnings({"deprecation", "UnstableApiUsage"}) @SuppressWarnings({"UnstableApiUsage"})
static class EditConversationPage extends ZInventoryPage { static class EditConversationPage extends ZInventoryPage {
private final Conversation conversation; private final Conversation conversation;
@ -240,7 +229,7 @@ public class ConversationGUI extends ZInventory {
this.addItem(ItemStackBuilder.forMaterial(Material.NAME_TAG).setName(ChatColor.AQUA + conversationKey.getTextFormatted() + "....").setLore("&7this conversation text has a delay of &b" + conversationKey.getDelay() + "s &7to be executed,", "&7the sound for the text is &b" + (conversationKey.getSoundName() == null ? "NONE" : conversationKey.getSoundName()) + "&7,", "&7before sending the text there is a delay of &b" + conversationKey.getDelay() + "s", "&7the index for the text is &b" + i + "&7,", "&7and the conversation has currently &b" + conversationKey.getActions().size() + " actions&7.", "&f&lUSES", " &bLeft-click &7to change the position.", " &bRight-click &7to remove text.", " &bLeft-Shift-click &7to change the sound.", " &bMiddle-click &7to change the delay.", " &bRight-Shift-click &7to edit the text.", " &bQ &7to manage actions.").build(), i, clickEvent -> { this.addItem(ItemStackBuilder.forMaterial(Material.NAME_TAG).setName(ChatColor.AQUA + conversationKey.getTextFormatted() + "....").setLore("&7this conversation text has a delay of &b" + conversationKey.getDelay() + "s &7to be executed,", "&7the sound for the text is &b" + (conversationKey.getSoundName() == null ? "NONE" : conversationKey.getSoundName()) + "&7,", "&7before sending the text there is a delay of &b" + conversationKey.getDelay() + "s", "&7the index for the text is &b" + i + "&7,", "&7and the conversation has currently &b" + conversationKey.getActions().size() + " actions&7.", "&f&lUSES", " &bLeft-click &7to change the position.", " &bRight-click &7to remove text.", " &bLeft-Shift-click &7to change the sound.", " &bMiddle-click &7to change the delay.", " &bRight-Shift-click &7to edit the text.", " &bQ &7to manage actions.").build(), i, clickEvent -> {
if (clickEvent.getClick() == ClickType.SHIFT_LEFT) { if (clickEvent.getClick() == ClickType.SHIFT_LEFT) {
Utils.sendTitle(this.getPlayer(), "&c&lCHANGE SOUND", "&7Type the new sound..."); Utils.sendTitle(this.getPlayer(), "&c&lCHANGE SOUND", "&7Type the new sound...");
EventService.addService(ZUser.find(this.getPlayer()), AsyncPlayerChatEvent.class).addConsumer(event -> { EventService.addService(User.get(this.getPlayer()), AsyncPlayerChatEvent.class).addConsumer(event -> {
if (ConfigurationConstants.NPC_CONVERSATIONS.contains(this.conversation) && this.conversation.getTexts().contains(conversationKey)) { if (ConfigurationConstants.NPC_CONVERSATIONS.contains(this.conversation) && this.conversation.getTexts().contains(conversationKey)) {
String sound = event.getMessage().trim(); String sound = event.getMessage().trim();
conversationKey.setSoundName(sound); conversationKey.setSoundName(sound);
@ -251,7 +240,7 @@ public class ConversationGUI extends ZInventory {
}).addConsumer(event -> this.openInventory()); }).addConsumer(event -> this.openInventory());
} else if (clickEvent.getClick() == ClickType.SHIFT_RIGHT) { } else if (clickEvent.getClick() == ClickType.SHIFT_RIGHT) {
Utils.sendTitle(this.getPlayer(), "&a&lEDIT TEXT", "&7Type the new text..."); Utils.sendTitle(this.getPlayer(), "&a&lEDIT TEXT", "&7Type the new text...");
EventService.addService(ZUser.find(this.getPlayer()), AsyncPlayerChatEvent.class).addConsumer(event -> { EventService.addService(User.get(this.getPlayer()), AsyncPlayerChatEvent.class).addConsumer(event -> {
if (ConfigurationConstants.NPC_CONVERSATIONS.contains(this.conversation) && this.conversation.getTexts().contains(conversationKey)) { if (ConfigurationConstants.NPC_CONVERSATIONS.contains(this.conversation) && this.conversation.getTexts().contains(conversationKey)) {
conversationKey.getLines().clear(); conversationKey.getLines().clear();
conversationKey.getLines().addAll(SPACE_SPLITTER.splitToList(event.getMessage())); conversationKey.getLines().addAll(SPACE_SPLITTER.splitToList(event.getMessage()));
@ -262,7 +251,7 @@ public class ConversationGUI extends ZInventory {
}).addConsumer(event -> this.openInventory()); }).addConsumer(event -> this.openInventory());
} else if (clickEvent.isLeftClick()) { } else if (clickEvent.isLeftClick()) {
Utils.sendTitle(this.getPlayer(), "&e&lCHANGE POSITION &a>=0&c<=" + this.conversation.getTexts().size(), "&7Type the new position..."); Utils.sendTitle(this.getPlayer(), "&e&lCHANGE POSITION &a>=0&c<=" + this.conversation.getTexts().size(), "&7Type the new position...");
EventService.addService(ZUser.find(this.getPlayer()), AsyncPlayerChatEvent.class).addConsumer(event -> { EventService.addService(User.get(this.getPlayer()), AsyncPlayerChatEvent.class).addConsumer(event -> {
if (ConfigurationConstants.NPC_CONVERSATIONS.contains(this.conversation) && this.conversation.getTexts().contains(conversationKey)) { if (ConfigurationConstants.NPC_CONVERSATIONS.contains(this.conversation) && this.conversation.getTexts().contains(conversationKey)) {
Integer position = Ints.tryParse(event.getMessage()); Integer position = Ints.tryParse(event.getMessage());
if (position == null) { if (position == null) {
@ -283,7 +272,7 @@ public class ConversationGUI extends ZInventory {
this.openInventory(); this.openInventory();
} else if (clickEvent.getClick() == ClickType.MIDDLE) { } else if (clickEvent.getClick() == ClickType.MIDDLE) {
Utils.sendTitle(this.getPlayer(), "&d&lCHANGE DELAY", "&7Type the new delay..."); Utils.sendTitle(this.getPlayer(), "&d&lCHANGE DELAY", "&7Type the new delay...");
EventService.addService(ZUser.find(this.getPlayer()), AsyncPlayerChatEvent.class).addConsumer(event -> { EventService.addService(User.get(this.getPlayer()), AsyncPlayerChatEvent.class).addConsumer(event -> {
if (ConfigurationConstants.NPC_CONVERSATIONS.contains(this.conversation) && this.conversation.getTexts().contains(conversationKey)) { if (ConfigurationConstants.NPC_CONVERSATIONS.contains(this.conversation) && this.conversation.getTexts().contains(conversationKey)) {
Integer delay = Ints.tryParse(event.getMessage()); Integer delay = Ints.tryParse(event.getMessage());
if (delay == null) { if (delay == null) {
@ -310,5 +299,6 @@ public class ConversationGUI extends ZInventory {
return super.getPageName() + " - " + pageID + "/" + (int) (Math.ceil((double) conversation.getTexts().size() / (double) 45)); return super.getPageName() + " - " + pageID + "/" + (int) (Math.ceil((double) conversation.getTexts().size() / (double) 45));
} }
} }
*/
} }
} }

@ -1,23 +1,8 @@
package io.github.znetworkw.znpcservers.configuration; package io.github.znetworkw.znpcservers.configuration;
import io.github.znetworkw.znpcservers.npc.NPCModel;
import io.github.znetworkw.znpcservers.npc.conversation.Conversation;
import java.util.List;
public final class ConfigurationConstants { public final class ConfigurationConstants {
public static final String SPACE_SYMBOL = Configuration.CONFIGURATION.getValue(ConfigurationValue.REPLACE_SYMBOL); public static final String SPACE_SYMBOL = Configuration.CONFIGURATION.getValue(ConfigurationValue.REPLACE_SYMBOL);
public static final boolean DEBUG_ENABLED = Configuration.CONFIGURATION.getValue(ConfigurationValue.DEBUG_ENABLED); public static final boolean DEBUG_ENABLED = Configuration.CONFIGURATION.getValue(ConfigurationValue.DEBUG_ENABLED);
public static final int VIEW_DISTANCE = Configuration.CONFIGURATION.<Integer>getValue(ConfigurationValue.VIEW_DISTANCE); public static final int VIEW_DISTANCE = Configuration.CONFIGURATION.<Integer>getValue(ConfigurationValue.VIEW_DISTANCE);
public static final int SAVE_DELAY = Configuration.CONFIGURATION.<Integer>getValue(ConfigurationValue.SAVE_NPCS_DELAY_SECONDS);
public static final boolean RGB_ANIMATION = Configuration.CONFIGURATION.<Boolean>getValue(ConfigurationValue.ANIMATION_RGB);
public static final List<NPCModel> NPC_LIST = Configuration.DATA.getValue(ConfigurationValue.NPC_LIST);
public static final List<Conversation> NPC_CONVERSATIONS = Configuration.CONVERSATIONS.getValue(ConfigurationValue.CONVERSATION_LIST);
public static final boolean CHECK_FOR_UPDATES = Configuration.CONFIGURATION.getValue(ConfigurationValue.CHECK_FOR_UPDATES); public static final boolean CHECK_FOR_UPDATES = Configuration.CONFIGURATION.getValue(ConfigurationValue.CHECK_FOR_UPDATES);
static {
NPC_LIST.stream()
.map(io.github.znetworkw.znpcservers.npc.NPC::new)
.forEach(io.github.znetworkw.znpcservers.npc.task.NPCLoadTask::new);
}
} }

@ -1,23 +1,17 @@
package io.github.znetworkw.znpcservers.configuration; package io.github.znetworkw.znpcservers.configuration;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
import io.github.znetworkw.znpcservers.npc.NPCModel;
import io.github.znetworkw.znpcservers.npc.NamingType;
import io.github.znetworkw.znpcservers.npc.conversation.Conversation;
import io.github.znetworkw.znpcservers.utility.GuavaCollectors; import io.github.znetworkw.znpcservers.utility.GuavaCollectors;
import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Map; import java.util.Map;
import java.util.stream.Collectors; import java.util.stream.Collectors;
public enum ConfigurationValue { public enum ConfigurationValue {
NPC_LIST("data", new ArrayList<>(), NPCModel.class),
VIEW_DISTANCE("config", 32, Integer.class), VIEW_DISTANCE("config", 32, Integer.class),
REPLACE_SYMBOL("config", "-", String.class), REPLACE_SYMBOL("config", "-", String.class),
SAVE_NPCS_DELAY_SECONDS("config", 600, Integer.class), SAVE_NPCS_DELAY_SECONDS("config", 600, Integer.class),
MAX_PATH_LOCATIONS("config", 500, Integer.class), MAX_PATH_LOCATIONS("config", 500, Integer.class),
NAMING_METHOD("config", NamingType.DEFAULT, NamingType.class),
DEBUG_ENABLED("config", false, Boolean.class), DEBUG_ENABLED("config", false, Boolean.class),
LINE_SPACING("config", 0.3D, Double.class), LINE_SPACING("config", 0.3D, Double.class),
ANIMATION_RGB("config", false, Boolean.class), ANIMATION_RGB("config", false, Boolean.class),
@ -51,9 +45,7 @@ public enum ConfigurationValue {
FETCHING_SKIN("messages", "&aFetching skin for name: &f%s&a. Please wait...", String.class), FETCHING_SKIN("messages", "&aFetching skin for name: &f%s&a. Please wait...", String.class),
CANT_GET_SKIN("messages", "&cCould not fetch skin for name: %s.", String.class), CANT_GET_SKIN("messages", "&cCould not fetch skin for name: %s.", String.class),
GET_SKIN("messages", "&aSkin successfully fetched!", String.class), GET_SKIN("messages", "&aSkin successfully fetched!", String.class),
NOT_SUPPORTED_NPC_TYPE("messages", "&cThis NPC type doesn't exists or is not supported in your current server version.", String.class), NOT_SUPPORTED_NPC_TYPE("messages", "&cThis NPC type doesn't exists or is not supported in your current server version.", String.class);
INVALID_CUSTOMIZE_ARGUMENTS("messages", "&cThe argument(s) you have specified is/are invalid. Type &f/znpcs&c or view our documentation for a list/examples of existing arguments.", String.class),
CONVERSATION_LIST("conversations" /* Leave this lowercase or it will break */, new ArrayList<>(), Conversation.class);
public static final Map<String, ImmutableSet<ConfigurationValue>> VALUES_BY_NAME; public static final Map<String, ImmutableSet<ConfigurationValue>> VALUES_BY_NAME;

@ -1,23 +0,0 @@
package io.github.znetworkw.znpcservers.exception;
import com.google.common.collect.ImmutableList;
import java.util.List;
public class ChannelRegistrationException extends Throwable {
private final Throwable throwable;
private final List<String> channelNames;
public ChannelRegistrationException(Throwable t, List<String> channelNames) {
this.throwable = t;
this.channelNames = new ImmutableList.Builder<String>().addAll(channelNames).build();
}
public Throwable getThrowable() {
return throwable;
}
public List<String> getChannelNames() {
return channelNames;
}
}

@ -1,133 +0,0 @@
package io.github.znetworkw.znpcservers.hologram;
import com.github.retrooper.packetevents.PacketEvents;
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerDestroyEntities;
import io.github.znetworkw.znpcservers.UnexpectedCallException;
import io.github.znetworkw.znpcservers.reflection.Reflections;
import io.github.znetworkw.znpcservers.configuration.Configuration;
import io.github.znetworkw.znpcservers.configuration.ConfigurationConstants;
import io.github.znetworkw.znpcservers.configuration.ConfigurationValue;
import io.github.znetworkw.znpcservers.npc.NPC;
import io.github.znetworkw.znpcservers.hologram.replacer.LineReplacer;
import io.github.znetworkw.znpcservers.user.ZUser;
import io.github.znetworkw.znpcservers.utility.Utils;
import org.bukkit.Location;
import javax.annotation.Nullable;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.List;
public class Hologram {
private static final boolean NEW_METHOD = (Utils.BUKKIT_VERSION > 12);
private static final double LINE_SPACING = Configuration.CONFIGURATION.getValue(ConfigurationValue.LINE_SPACING);
private final List<HologramLine> hologramLines = new ArrayList<>();
private final NPC npc;
public Hologram(NPC npc) {
this.npc = npc;
}
public void createHologram() {
this.npc.getViewers().forEach(this::delete);
try {
this.hologramLines.clear();
double y = 0.0D;
Location location = this.npc.getLocation();
for (String line : this.npc.getNpcPojo().getHologramLines()) {
boolean visible = !line.equalsIgnoreCase("%space%");
Object armorStand = Reflections.ENTITY_CONSTRUCTOR.get().newInstance(Reflections.GET_HANDLE_WORLD_METHOD.get().invoke(location.getWorld()),
location.getX(), location.getY() - 0.15D + y, location.getZ());
if (visible) {
Reflections.SET_CUSTOM_NAME_VISIBLE_METHOD.get().invoke(armorStand, true);
updateLine(line, armorStand, null);
}
Reflections.SET_INVISIBLE_METHOD.get().invoke(armorStand, true);
this.hologramLines.add(new HologramLine(line.replace(ConfigurationConstants.SPACE_SYMBOL, " "), armorStand, (Integer) Reflections.GET_ENTITY_ID
.get().invoke(armorStand)));
y += LINE_SPACING;
}
setLocation(location, 0.0D);
this.npc.getPackets().flushCache("createArmorStandSpawnPacket");
this.npc.getViewers().forEach(this::spawn);
} catch (ReflectiveOperationException operationException) {
throw new UnexpectedCallException(operationException);
}
}
public void spawn(ZUser user) {
this.hologramLines.forEach(hologramLine -> {
try {
Object entityPlayerPacketSpawn = this.npc.getPackets().getNms().createArmorStandSpawnPacket(hologramLine.armorStand);
Utils.sendPackets(user, entityPlayerPacketSpawn);
} catch (ReflectiveOperationException operationException) {
delete(user);
}
});
}
public void delete(ZUser user) {
this.hologramLines.forEach(hologramLine -> PacketEvents.getAPI().getPlayerManager().sendPacket(user.toPlayer(), new WrapperPlayServerDestroyEntities(hologramLine.id)));
}
public void updateNames(ZUser user) {
for (HologramLine hologramLine : this.hologramLines) {
try {
updateLine(hologramLine.line, hologramLine.armorStand, user);
Object metaData = this.npc.getPackets().getNms().createMetadataPacket(hologramLine.id, hologramLine.armorStand);
Utils.sendPackets(user, metaData);
} catch (ReflectiveOperationException operationException) {
throw new UnexpectedCallException(operationException);
}
}
}
public void updateLocation() {
this.hologramLines.forEach(hologramLine -> {
try {
Object packet = Reflections.PACKET_PLAY_OUT_ENTITY_TELEPORT_CONSTRUCTOR.get().newInstance(hologramLine.armorStand);
this.npc.getViewers().forEach(player -> Utils.sendPackets(player, packet));
}
catch (ReflectiveOperationException operationException) {
throw new UnexpectedCallException(operationException);
}
});
}
public void setLocation(Location location, double height) {
location = location.clone().add(0.0, height, 0.0);
try {
double y = this.npc.getNpcPojo().getHologramHeight();
for (HologramLine hologramLine : this.hologramLines) {
Reflections.SET_LOCATION_METHOD.get().invoke(hologramLine.armorStand, location.getX(), location.getY() - 0.15 + y, location.getZ(), location.getYaw(), location.getPitch());
y += LINE_SPACING;
}
this.updateLocation();
}
catch (ReflectiveOperationException operationException) {
throw new UnexpectedCallException(operationException);
}
}
private void updateLine(String line, Object armorStand, @Nullable ZUser user) throws InvocationTargetException, IllegalAccessException {
if (NEW_METHOD) {
Reflections.SET_CUSTOM_NAME_NEW_METHOD.get().invoke(armorStand, Reflections.CRAFT_CHAT_MESSAGE_METHOD.get().invoke(null, LineReplacer.makeAll(user, line)));
} else {
Reflections.SET_CUSTOM_NAME_OLD_METHOD.get().invoke(armorStand, LineReplacer.makeAll(user, line));
}
}
private static class HologramLine {
private final String line;
private final Object armorStand;
private final int id;
protected HologramLine(String line, Object armorStand, int id) {
this.line = line;
this.armorStand = armorStand;
this.id = id;
}
}
}

@ -1,21 +0,0 @@
package io.github.znetworkw.znpcservers.hologram.replacer;
import com.google.common.collect.ImmutableList;
import io.github.znetworkw.znpcservers.user.ZUser;
import io.github.znetworkw.znpcservers.utility.Utils;
public interface LineReplacer {
ImmutableList<LineReplacer> LINE_REPLACERS = ImmutableList.of(new RGBLine());
static String makeAll(ZUser user, String string) {
for (LineReplacer lineReplacer : LINE_REPLACERS) {
if (!lineReplacer.isSupported()) continue;
string = lineReplacer.make(string);
}
return Utils.toColor((Utils.PLACEHOLDER_SUPPORT && user != null) ? Utils.getWithPlaceholders(string, user.toPlayer()) : string);
}
String make(String paramString);
boolean isSupported();
}

@ -1,37 +0,0 @@
package io.github.znetworkw.znpcservers.hologram.replacer;
import io.github.znetworkw.znpcservers.configuration.ConfigurationConstants;
import io.github.znetworkw.znpcservers.utility.Utils;
import net.md_5.bungee.api.ChatColor;
import java.util.concurrent.ThreadLocalRandom;
public class RGBLine implements LineReplacer {
public String make(String string) {
String rgbString = string;
for (int i = 0; i < rgbString.length(); i++) {
char charAt = rgbString.charAt(i);
if (charAt == '#') {
int endIndex = i + 6 + 1;
boolean success = true;
StringBuilder hexCodeStringBuilder = new StringBuilder();
for (int i2 = i; i2 < endIndex; i2++) {
if (rgbString.length() - 1 < i2) {
success = false;
break;
}
char hexCode = rgbString.charAt(i2);
hexCodeStringBuilder.append((ConfigurationConstants.RGB_ANIMATION && hexCode != '#') ? Integer.toHexString(ThreadLocalRandom.current().nextInt(16)) : Character.valueOf(hexCode));
}
if (success) try {
rgbString = rgbString.substring(0, i) + ChatColor.of(hexCodeStringBuilder.toString()) + rgbString.substring(endIndex);
} catch (Exception ignored) {}
}
}
return rgbString;
}
public boolean isSupported() {
return (Utils.BUKKIT_VERSION > 15);
}
}

@ -1,47 +0,0 @@
package io.github.znetworkw.znpcservers.listeners;
import io.github.znetworkw.znpcservers.npc.conversation.ConversationModel;
import io.github.znetworkw.znpcservers.npc.interaction.NPCInteractEvent;
import io.github.znetworkw.znpcservers.user.EventService;
import io.github.znetworkw.znpcservers.user.ZUser;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.player.AsyncPlayerChatEvent;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.plugin.Plugin;
public class PlayerListener implements Listener {
public PlayerListener(Plugin serversNPC) {
serversNPC.getServer().getPluginManager().registerEvents(this, serversNPC);
}
@EventHandler
public void onJoin(PlayerJoinEvent event) {
ZUser.find(event.getPlayer());
}
@EventHandler
public void onQuit(PlayerQuitEvent event) {
ZUser.unregister(event.getPlayer());
}
@EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR)
public void onTalk(AsyncPlayerChatEvent event) {
ZUser zUser = ZUser.find(event.getPlayer());
if (EventService.hasService(zUser, AsyncPlayerChatEvent.class)) {
event.setCancelled(true);
EventService<AsyncPlayerChatEvent> eventService = EventService.findService(zUser, AsyncPlayerChatEvent.class);
eventService.runAll(event);
zUser.getEventServices().remove(eventService);
}
}
@EventHandler
public void onConversation(NPCInteractEvent event) {
ConversationModel conversationStorage = event.getNpc().getNpcPojo().getConversation();
if (conversationStorage == null || conversationStorage.getConversationType() != ConversationModel.ConversationType.CLICK) return;
event.getNpc().tryStartConversation(event.getPlayer());
}
}

@ -1,72 +0,0 @@
package io.github.znetworkw.znpcservers.nms;
import com.google.common.collect.ImmutableList;
import com.mojang.authlib.GameProfile;
import io.github.znetworkw.znpcservers.npc.FunctionFactory;
import io.github.znetworkw.znpcservers.npc.NPC;
import io.github.znetworkw.znpcservers.npc.NPCType;
import io.github.znetworkw.znpcservers.reflection.Reflections;
import io.github.znetworkw.znpcservers.utility.ReflectionUtils;
import io.github.znetworkw.znpcservers.utility.Utils;
import java.util.Collection;
public interface NMS {
int version();
@PacketValue(keyName = "playerPacket")
Object createPlayer(Object paramObject, GameProfile paramGameProfile) throws ReflectiveOperationException;
Object createMetadataPacket(int paramInt, Object paramObject) throws ReflectiveOperationException;
@PacketValue(keyName = "hologramSpawnPacket", valueType = ValueType.ARGUMENTS)
Object createArmorStandSpawnPacket(Object paramObject) throws ReflectiveOperationException;
@SuppressWarnings("unchecked")
@PacketValue(keyName = "scoreboardPackets")
default ImmutableList<Object> updateScoreboard(NPC npc) throws ReflectiveOperationException {
ImmutableList.Builder<Object> builder = ImmutableList.builder();
boolean isVersion17 = (Utils.BUKKIT_VERSION > 16);
boolean isVersion9 = (Utils.BUKKIT_VERSION > 8);
Object scoreboardTeamPacket = isVersion17 ? Reflections.SCOREBOARD_TEAM_CONSTRUCTOR.get().newInstance(null, npc.getGameProfile().getName()) : Reflections.PACKET_PLAY_OUT_SCOREBOARD_TEAM_CONSTRUCTOR_OLD.get().newInstance();
if (!isVersion17) {
Utils.setValue(scoreboardTeamPacket, "a", npc.getGameProfile().getName());
Utils.setValue(scoreboardTeamPacket, isVersion9 ? "i" : "h", 1);
}
builder.add(isVersion17 ? Reflections.PACKET_PLAY_OUT_SCOREBOARD_TEAM_CREATE_V1.get().invoke(null, scoreboardTeamPacket) : scoreboardTeamPacket);
if (isVersion17) {
scoreboardTeamPacket = Reflections.SCOREBOARD_TEAM_CONSTRUCTOR.get().newInstance(null, npc.getGameProfile().getName());
if (Utils.BUKKIT_VERSION > 17) {
Utils.setValue(scoreboardTeamPacket, "d", npc.getGameProfile().getName());
ReflectionUtils.findFieldForClassAndSet(scoreboardTeamPacket, Reflections.ENUM_TAG_VISIBILITY, Reflections.ENUM_TAG_VISIBILITY_NEVER_FIELD.get());
Utils.setValue(scoreboardTeamPacket, "m", Reflections.ENUM_CHAT_FORMAT_FIND.get().invoke(null, "DARK_GRAY"));
} else {
Utils.setValue(scoreboardTeamPacket, "e", npc.getGameProfile().getName());
Utils.setValue(scoreboardTeamPacket, "l", Reflections.ENUM_TAG_VISIBILITY_NEVER_FIELD.get());
}
} else {
scoreboardTeamPacket = Reflections.PACKET_PLAY_OUT_SCOREBOARD_TEAM_CONSTRUCTOR_OLD.get().newInstance();
Utils.setValue(scoreboardTeamPacket, "a", npc.getGameProfile().getName());
Utils.setValue(scoreboardTeamPacket, "e", "never");
Utils.setValue(scoreboardTeamPacket, isVersion9 ? "i" : "h", 0);
}
Collection<String> collection = isVersion17 ? (Collection<String>) Reflections.SCOREBOARD_PLAYER_LIST.get().invoke(scoreboardTeamPacket) : (Collection<String>) Utils.getValue(scoreboardTeamPacket, isVersion9 ? "h" : "g");
if (npc.getNpcPojo().getNpcType() == NPCType.PLAYER) {
collection.add(npc.getGameProfile().getName());
} else {
collection.add(npc.getUUID().toString());
}
if (allowsGlowColor() && FunctionFactory.isTrue(npc, "glow"))
updateGlow(npc, scoreboardTeamPacket);
builder.add(isVersion17 ? Reflections.PACKET_PLAY_OUT_SCOREBOARD_TEAM_CREATE.get().invoke(null, scoreboardTeamPacket, Boolean.TRUE) : scoreboardTeamPacket);
return builder.build();
}
void updateGlow(NPC paramNPC, Object paramObject) throws ReflectiveOperationException;
boolean allowsGlowColor();
default void update(PacketCache packetCache) throws ReflectiveOperationException {
packetCache.flushCache("scoreboardPackets");
}
}

@ -1,19 +0,0 @@
package io.github.znetworkw.znpcservers.nms;
import com.google.common.collect.ImmutableSet;
import io.github.znetworkw.znpcservers.utility.Utils;
import java.util.Comparator;
public final class NMSFactory {
public static final ImmutableSet<NMS> ALL = ImmutableSet.of(new NMSV8(), new NMSV9(), new NMSV17(), new NMSV18(), new NMSV19());
public static final NMS NMS_FOR_CURRENT_VERSION = findPacketForVersion(Utils.BUKKIT_VERSION);
public static NMS findPacketForVersion(int version) {
return ALL.stream()
.filter(NMS -> (version >= NMS.version()))
.max(Comparator.comparing(NMS::version))
.orElseThrow(() -> new IllegalArgumentException("No NMS instance found for version: " + version));
}
}

@ -1,21 +0,0 @@
package io.github.znetworkw.znpcservers.nms;
import com.mojang.authlib.GameProfile;
import io.github.znetworkw.znpcservers.reflection.Reflections;
import io.github.znetworkw.znpcservers.npc.NPC;
import io.github.znetworkw.znpcservers.utility.Utils;
import org.bukkit.Bukkit;
public class NMSV17 extends NMSV9 {
public int version() {
return 17;
}
public Object createPlayer(Object nmsWorld, GameProfile gameProfile) throws ReflectiveOperationException {
return Reflections.PLAYER_CONSTRUCTOR_NEW.get().newInstance(Reflections.GET_SERVER_METHOD.get().invoke(Bukkit.getServer()), nmsWorld, gameProfile);
}
public void updateGlow(NPC npc, Object packet) throws ReflectiveOperationException {
Utils.setValue(packet, "n", Reflections.ENUM_CHAT_FORMAT_FIND.get().invoke(null, npc.getNpcPojo().getGlowName()));
}
}

@ -1,15 +0,0 @@
package io.github.znetworkw.znpcservers.nms;
import io.github.znetworkw.znpcservers.reflection.Reflections;
import io.github.znetworkw.znpcservers.npc.NPC;
import io.github.znetworkw.znpcservers.utility.Utils;
public class NMSV18 extends NMSV17 {
public int version() {
return 18;
}
public void updateGlow(NPC npc, Object packet) throws ReflectiveOperationException {
Utils.setValue(packet, "m", Reflections.ENUM_CHAT_FORMAT_FIND.get().invoke(null, npc.getNpcPojo().getGlowName()));
}
}

@ -1,19 +0,0 @@
package io.github.znetworkw.znpcservers.nms;
import com.mojang.authlib.GameProfile;
import io.github.znetworkw.znpcservers.reflection.Reflections;
import org.bukkit.Bukkit;
public class NMSV19 extends NMSV18 {
public int version() {
return 19;
}
public Object createPlayer(Object nmsWorld, GameProfile gameProfile) throws ReflectiveOperationException {
try {
return Reflections.PLAYER_CONSTRUCTOR_NEW_1.get().newInstance(Reflections.GET_SERVER_METHOD.get().invoke(Bukkit.getServer()), nmsWorld, gameProfile, null);
} catch (Throwable e) {
return Reflections.PLAYER_CONSTRUCTOR_NEW_2.get().newInstance(Reflections.GET_SERVER_METHOD.get().invoke(Bukkit.getServer()), nmsWorld, gameProfile);
}
}
}

@ -1,42 +0,0 @@
package io.github.znetworkw.znpcservers.nms;
import com.mojang.authlib.GameProfile;
import io.github.znetworkw.znpcservers.npc.NPC;
import io.github.znetworkw.znpcservers.reflection.Reflections;
import io.github.znetworkw.znpcservers.utility.Utils;
import org.bukkit.Bukkit;
import java.lang.reflect.Constructor;
public class NMSV8 implements NMS {
public int version() {
return 8;
}
public Object createPlayer(Object nmsWorld, GameProfile gameProfile) throws ReflectiveOperationException {
Constructor<?> constructor = (Utils.BUKKIT_VERSION > 13) ? Reflections.PLAYER_INTERACT_MANAGER_NEW_CONSTRUCTOR.get() : Reflections.PLAYER_INTERACT_MANAGER_OLD_CONSTRUCTOR.get();
return Reflections.PLAYER_CONSTRUCTOR_OLD.get().newInstance(Reflections.GET_SERVER_METHOD
.get().invoke(Bukkit.getServer()), nmsWorld, gameProfile, constructor.newInstance(nmsWorld));
}
public Object createMetadataPacket(int entityId, Object nmsEntity) throws ReflectiveOperationException {
Object dataWatcher = Reflections.GET_DATA_WATCHER_METHOD.get().invoke(nmsEntity);
try {
return Reflections.PACKET_PLAY_OUT_ENTITY_META_DATA_CONSTRUCTOR.get().newInstance(entityId, dataWatcher, true);
} catch (Exception e2) {
return Reflections.PACKET_PLAY_OUT_ENTITY_META_DATA_CONSTRUCTOR_V1.get().newInstance(entityId, Reflections.GET_DATAWATCHER_B_LIST.get().invoke(dataWatcher));
}
}
public Object createArmorStandSpawnPacket(Object armorStand) throws ReflectiveOperationException {
return Reflections.PACKET_PLAY_OUT_SPAWN_ENTITY_CONSTRUCTOR.get().newInstance(armorStand);
}
public void updateGlow(NPC npc, Object packet) throws ReflectiveOperationException {
throw new IllegalStateException("Glow color is not supported for 1.8 version.");
}
public boolean allowsGlowColor() {
return false;
}
}

@ -1,26 +0,0 @@
package io.github.znetworkw.znpcservers.nms;
import io.github.znetworkw.znpcservers.npc.NPC;
import io.github.znetworkw.znpcservers.reflection.Reflections;
import io.github.znetworkw.znpcservers.utility.Utils;
public class NMSV9 extends NMSV8 {
public int version() {
return 9;
}
public void updateGlow(NPC npc, Object packet) throws ReflectiveOperationException {
Object enumChatString = Reflections.ENUM_CHAT_TO_STRING_METHOD.get().invoke(npc.getGlowColor());
if (Utils.BUKKIT_VERSION > 12) {
Utils.setValue(packet, npc.getGlowColor(), Reflections.ENUM_CHAT_CLASS);
Utils.setValue(packet, "c", Reflections.I_CHAT_BASE_COMPONENT_A_CONSTRUCTOR.get().newInstance(enumChatString));
} else {
Utils.setValue(packet, "g", Reflections.GET_ENUM_CHAT_ID_METHOD.get().invoke(npc.getGlowColor()));
Utils.setValue(packet, "c", enumChatString);
}
}
public boolean allowsGlowColor() {
return true;
}
}

@ -1,89 +0,0 @@
package io.github.znetworkw.znpcservers.nms;
import com.google.common.collect.ImmutableMap;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
@SuppressWarnings("unused")
public class PacketCache {
protected static final ImmutableMap<Method, PacketValue> VALUE_LOOKUP_BY_NAME;
static {
ImmutableMap.Builder<Method, PacketValue> methodPacketValueBuilder = ImmutableMap.builder();
for (Method method : NMS.class.getMethods()) {
if (method.isAnnotationPresent(PacketValue.class))
methodPacketValueBuilder.put(method, method.getAnnotation(PacketValue.class));
}
VALUE_LOOKUP_BY_NAME = methodPacketValueBuilder.build();
}
private final Map<String, Object> packetResultCache = new ConcurrentHashMap<>();
private final NMS nms;
public PacketCache(NMS NMS) {
this.nms = newNMSInstance(NMS);
}
public PacketCache() {
this(NMSFactory.NMS_FOR_CURRENT_VERSION);
}
public NMS getNms() {
return this.nms;
}
protected NMS newNMSInstance(NMS NMS) {
return (NMS) Proxy.newProxyInstance(NMS
.getClass().getClassLoader(), new Class[]{NMS.class}, new PacketHandler(this, NMS));
}
private Object getOrCache(NMS instance, Method method, Object[] args) {
if (!VALUE_LOOKUP_BY_NAME.containsKey(method))
throw new IllegalStateException("value not found for method: " + method.getName());
PacketValue packetValue = VALUE_LOOKUP_BY_NAME.get(method);
assert packetValue != null;
String keyString = packetValue.valueType().resolve(packetValue.keyName(), args);
return this.packetResultCache.computeIfAbsent(keyString, o -> {
try {
return method.invoke(instance, args);
} catch (InvocationTargetException | IllegalAccessException operationException) {
throw new AssertionError("can't invoke method: " + method.getName(), operationException);
}
});
}
public void flushCache(String... strings) {
Set<Map.Entry<String, Object>> set = this.packetResultCache.entrySet();
for (String string : strings)
set.removeIf(entry -> entry.getKey().startsWith(string));
}
public void flushCache() {
flushCache(VALUE_LOOKUP_BY_NAME.values().stream()
.map(PacketValue::keyName).toArray(String[]::new));
}
private static class PacketHandler implements InvocationHandler {
private final PacketCache packetCache;
private final NMS packets;
public PacketHandler(PacketCache packetCache, NMS packets) {
this.packetCache = packetCache;
this.packets = packets;
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (PacketCache.VALUE_LOOKUP_BY_NAME.containsKey(method))
return this.packetCache.getOrCache(this.packets, method, args);
return method.invoke(this.packets, args);
}
}
}

@ -1,14 +0,0 @@
package io.github.znetworkw.znpcservers.nms;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface PacketValue {
String keyName();
ValueType valueType() default ValueType.DEFAULT;
}

@ -1,20 +0,0 @@
package io.github.znetworkw.znpcservers.nms;
import java.util.Arrays;
public enum ValueType {
ARGUMENTS {
String resolve(String keyName, Object[] args) {
if (args.length == 0)
throw new IllegalArgumentException("invalid size, must be > 0");
return keyName + Arrays.hashCode(args);
}
},
DEFAULT {
String resolve(String keyName, Object[] args) {
return keyName;
}
};
abstract String resolve(String paramString, Object[] paramArrayOfObject);
}

@ -1,48 +0,0 @@
package io.github.znetworkw.znpcservers.npc;
import com.google.common.collect.Iterables;
import io.github.znetworkw.znpcservers.reflection.ReflectionBuilder;
import io.github.znetworkw.znpcservers.reflection.ReflectionPackage;
import io.github.znetworkw.znpcservers.reflection.types.EnumReflection;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
public class CustomizationLoader {
private final Class<? extends Entity> entityClass;
private final Map<String, Method> methods;
public CustomizationLoader(EntityType entityType, Iterable<String> methodsName) {
this(entityType.getEntityClass(), methodsName);
}
protected CustomizationLoader(Class<? extends Entity> entityClass, Iterable<String> methodsName) {
this.entityClass = entityClass;
this.methods = loadMethods(methodsName);
}
protected Map<String, Method> loadMethods(Iterable<String> iterable) {
Map<String, Method> builder = new HashMap<>();
for (Method method : this.entityClass.getMethods()) {
if (builder.containsKey(method.getName()) || !Iterables.contains(iterable, method.getName())) continue;
for (Class<?> parameter : method.getParameterTypes()) {
PrimitivePropertyType primitivePropertyType = PrimitivePropertyType.forType(parameter);
if (primitivePropertyType != null || !parameter.isEnum()) continue;
new EnumReflection(new ReflectionBuilder(ReflectionPackage.MINECRAFT).withClassName(parameter)).get();
}
builder.put(method.getName(), method);
}
return builder;
}
public boolean contains(String name) {
return this.methods.containsKey(name);
}
public Map<String, Method> getMethods() {
return this.methods;
}
}

@ -1,34 +0,0 @@
package io.github.znetworkw.znpcservers.npc;
public interface FunctionContext {
NPC getNPC();
interface WithValue extends FunctionContext {
String getValue();
}
class DefaultContext implements FunctionContext {
private final NPC npc;
public DefaultContext(NPC npc) {
this.npc = npc;
}
public NPC getNPC() {
return this.npc;
}
}
class ContextWithValue extends DefaultContext implements WithValue {
private final String value;
public ContextWithValue(NPC npc, String value) {
super(npc);
this.value = value;
}
public String getValue() {
return this.value;
}
}
}

@ -1,31 +0,0 @@
package io.github.znetworkw.znpcservers.npc;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import io.github.znetworkw.znpcservers.npc.function.GlowFunction;
import io.github.znetworkw.znpcservers.utility.GuavaCollectors;
public final class FunctionFactory {
public static ImmutableList<NPCFunction> WITHOUT_FUNCTION = ImmutableList.of(new NPCFunction.WithoutFunction("look"), new NPCFunction.WithoutFunctionSelfUpdate("holo"), new NPCFunction.WithoutFunctionSelfUpdate("mirror"));
public static ImmutableList<NPCFunction> WITH_FUNCTION = ImmutableList.of(new GlowFunction());
public static ImmutableList<NPCFunction> ALL = new ImmutableList.Builder<NPCFunction>().addAll(WITHOUT_FUNCTION).addAll(WITH_FUNCTION).build();
public static ImmutableMap<String, NPCFunction> BY_NAME = ALL.stream().collect(GuavaCollectors.toImmutableMap(NPCFunction::getName, function -> function));
public static NPCFunction findFunctionForName(String name) {
return BY_NAME.get(name);
}
public static ImmutableList<NPCFunction> findFunctionsForNpc(NPC npc) {
return ALL.stream()
.filter(function -> isTrue(npc, function))
.collect(GuavaCollectors.toImmutableList());
}
public static boolean isTrue(NPC npc, NPCFunction function) {
return npc.getNpcPojo().getFunctions().getOrDefault(function.getName(), false);
}
public static boolean isTrue(NPC npc, String function) {
return isTrue(npc, findFunctionForName(function));
}
}

@ -1,363 +0,0 @@
package io.github.znetworkw.znpcservers.npc;
import com.github.retrooper.packetevents.PacketEvents;
import com.github.retrooper.packetevents.manager.server.ServerVersion;
import com.github.retrooper.packetevents.protocol.entity.data.EntityData;
import com.github.retrooper.packetevents.protocol.entity.data.EntityDataTypes;
import com.github.retrooper.packetevents.protocol.entity.type.EntityType;
import com.github.retrooper.packetevents.protocol.player.Equipment;
import com.github.retrooper.packetevents.protocol.player.UserProfile;
import com.github.retrooper.packetevents.util.Vector3d;
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
import com.github.retrooper.packetevents.wrapper.play.server.*;
import com.google.common.collect.ImmutableList;
import com.mojang.authlib.GameProfile;
import com.mojang.authlib.properties.Property;
import com.mojang.authlib.properties.PropertyMap;
import io.github.retrooper.packetevents.util.SpigotConversionUtil;
import io.github.znetworkw.znpcservers.UnexpectedCallException;
import io.github.znetworkw.znpcservers.configuration.ConfigurationConstants;
import io.github.znetworkw.znpcservers.hologram.Hologram;
import io.github.znetworkw.znpcservers.nms.PacketCache;
import io.github.znetworkw.znpcservers.npc.conversation.ConversationModel;
import io.github.znetworkw.znpcservers.reflection.Reflections;
import io.github.znetworkw.znpcservers.user.ZUser;
import io.github.znetworkw.znpcservers.utility.Utils;
import io.github.znetworkw.znpcservers.utility.location.ZLocation;
import lol.pyr.znpcsplus.ZNPCsPlus;
import org.bukkit.Location;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
public class NPC {
private static final ConcurrentMap<Integer, NPC> NPC_MAP = new ConcurrentHashMap<>();
private final Set<ZUser> viewers = new HashSet<>();
private final PacketCache packets = new PacketCache();
private final NPCModel npcPojo;
private final Hologram hologram;
private final String npcName;
private final NPCSkin npcSkin;
private long lastMove = -1L;
private int entityID;
private Object glowColor;
private Object tabConstructor;
private Object updateTabConstructor;
private Object nmsEntity;
private Object bukkitEntity;
private UUID uuid;
private GameProfile gameProfile;
private NPCPath.PathInitializer npcPath;
public NPC(NPCModel npcModel, boolean load) {
this.npcPojo = npcModel;
this.hologram = new Hologram(this);
this.npcName = NamingType.DEFAULT.resolve(this);
this.npcSkin = NPCSkin.forValues(npcModel.getSkin(), npcModel.getSignature());
this.uuid = npcModel.getUuid();
if (load) onLoad();
}
public NPC(NPCModel npcModel) {
this(npcModel, false);
}
public static NPC find(int id) {
return NPC_MAP.get(id);
}
public static void unregister(int id) {
NPC npc = find(id);
if (npc == null) throw new IllegalStateException("can't find npc with id " + id);
NPC_MAP.remove(id);
npc.deleteViewers();
}
public static Collection<NPC> all() {
return NPC_MAP.values();
}
public void onLoad() {
if (NPC_MAP.containsKey(getNpcPojo().getId())) throw new IllegalStateException("npc with id " + getNpcPojo().getId() + " already exists.");
this.gameProfile = new GameProfile(this.uuid, "[ZNPC] " + this.npcName);
this.gameProfile.getProperties().put("textures", new Property("textures", this.npcPojo.getSkin(), this.npcPojo.getSignature()));
if (this.npcPojo.getNpcType().getConstructor() == null && !this.npcPojo.getNpcType().equals(NPCType.PLAYER)) {
this.npcPojo.setShouldSpawn(false);
if (ConfigurationConstants.DEBUG_ENABLED) {
ZNPCsPlus.LOGGER.warning("The NPC Type " + npcPojo.getNpcType().name() + " does not exist or is not supported in this version.");
}
} else {
this.npcPojo.setShouldSpawn(true);
changeType(this.npcPojo.getNpcType());
updateProfile(this.gameProfile.getProperties());
setLocation(getNpcPojo().getLocation().toBukkitLocation(), false);
this.hologram.createHologram();
if (this.npcPojo.getPathName() != null) setPath(NPCPath.AbstractTypeWriter.find(this.npcPojo.getPathName()));
this.npcPojo.getCustomizationMap().forEach((key, value) -> this.npcPojo.getNpcType().updateCustomization(this, key, value));
}
NPC_MAP.put(getNpcPojo().getId(), this);
}
public NPCModel getNpcPojo() {
return this.npcPojo;
}
public UUID getUUID() {
return this.uuid;
}
public int getEntityID() {
return this.entityID;
}
public Object getBukkitEntity() {
return this.bukkitEntity;
}
public Object getNmsEntity() {
return this.nmsEntity;
}
public Object getGlowColor() {
return this.glowColor;
}
public void setGlowColor(Object glowColor) {
this.glowColor = glowColor;
}
public GameProfile getGameProfile() {
return this.gameProfile;
}
public NPCPath.PathInitializer getNpcPath() {
return this.npcPath;
}
public Hologram getHologram() {
return this.hologram;
}
public Set<ZUser> getViewers() {
return this.viewers;
}
public PacketCache getPackets() {
return this.packets;
}
public void setLocation(Location location, boolean updateTime) {
try {
if (this.npcPath == null) {
lookAt(null, location, true);
if (updateTime) this.lastMove = System.nanoTime();
this.npcPojo.setLocation(new ZLocation(location = new Location(location.getWorld(), location.getBlockX() + 0.5D, location.getY(), location.getBlockZ() + 0.5D, location.getYaw(), location.getPitch())));
}
Reflections.SET_LOCATION_METHOD.get().invoke(this.nmsEntity, location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch());
Object npcTeleportPacket = Reflections.PACKET_PLAY_OUT_ENTITY_TELEPORT_CONSTRUCTOR.get().newInstance(this.nmsEntity);
this.viewers.forEach(player -> Utils.sendPackets(player, npcTeleportPacket));
this.hologram.setLocation(location, this.npcPojo.getNpcType().getHoloHeight());
} catch (ReflectiveOperationException operationException) {
throw new UnexpectedCallException(operationException);
}
}
public void changeSkin(NPCSkin skinFetch) {
this.npcPojo.setSkin(skinFetch.getTexture());
this.npcPojo.setSignature(skinFetch.getSignature());
this.gameProfile.getProperties().clear();
this.gameProfile.getProperties().put("textures", new Property("textures", this.npcPojo.getSkin(), this.npcPojo.getSignature()));
updateProfile(this.gameProfile.getProperties());
deleteViewers();
}
public void setSecondLayerSkin() {
try {
Object dataWatcherObject = Reflections.GET_DATA_WATCHER_METHOD.get().invoke(this.nmsEntity);
if (Utils.versionNewer(9)) Reflections.SET_DATA_WATCHER_METHOD.get().invoke(dataWatcherObject, Reflections.DATA_WATCHER_OBJECT_CONSTRUCTOR.get()
.newInstance(this.npcSkin.getLayerIndex(), Reflections.DATA_WATCHER_REGISTER_FIELD.get()), (byte) 127);
else Reflections.WATCH_DATA_WATCHER_METHOD.get().invoke(dataWatcherObject, 10, (byte) 127);
} catch (ReflectiveOperationException operationException) {
throw new UnexpectedCallException(operationException);
}
}
public synchronized void changeType(NPCType npcType) {
deleteViewers();
try {
Object nmsWorld = Reflections.GET_HANDLE_WORLD_METHOD.get().invoke(getLocation().getWorld());
boolean isPlayer = (npcType == NPCType.PLAYER);
this.nmsEntity = isPlayer ? this.packets.getNms().createPlayer(nmsWorld, this.gameProfile) : (Utils.versionNewer(14) ? npcType.getConstructor().newInstance(npcType.getNmsEntityType(), nmsWorld) : npcType.getConstructor().newInstance(nmsWorld));
this.bukkitEntity = Reflections.GET_BUKKIT_ENTITY_METHOD.get().invoke(this.nmsEntity);
this.uuid = (UUID) Reflections.GET_UNIQUE_ID_METHOD.get().invoke(this.nmsEntity, new Object[0]);
if (isPlayer) {
try {
this.tabConstructor = Reflections.PACKET_PLAY_OUT_PLAYER_INFO_CONSTRUCTOR.get().newInstance(Reflections.ADD_PLAYER_FIELD.get(), Collections.singletonList(this.nmsEntity));
} catch (Throwable e) {
this.tabConstructor = Reflections.PACKET_PLAY_OUT_PLAYER_INFO_CONSTRUCTOR.get().newInstance(Reflections.ADD_PLAYER_FIELD.get(), this.nmsEntity);
this.updateTabConstructor = Reflections.PACKET_PLAY_OUT_PLAYER_INFO_CONSTRUCTOR.get().newInstance(Reflections.UPDATE_LISTED_FIELD.get(), this.nmsEntity);
}
setSecondLayerSkin();
}
this.npcPojo.setNpcType(npcType);
setLocation(getLocation(), false);
this.packets.flushCache("spawnPacket", "removeTab");
this.entityID = (Integer) Reflections.GET_ENTITY_ID.get().invoke(this.nmsEntity, new Object[0]);
FunctionFactory.findFunctionsForNpc(this).forEach(function -> function.resolve(this));
getPackets().getNms().update(this.packets);
this.hologram.createHologram();
} catch (ReflectiveOperationException operationException) {
throw new UnexpectedCallException(operationException);
}
}
public synchronized void spawn(ZUser user) {
if (this.viewers.contains(user)) {
return;
}
if (!getNpcPojo().getShouldSpawn()) {
return;
}
try {
this.viewers.add(user);
boolean npcIsPlayer = (this.npcPojo.getNpcType() == NPCType.PLAYER);
if (FunctionFactory.isTrue(this, "glow") || npcIsPlayer) {
ImmutableList<Object> scoreboardPackets = this.packets.getNms().updateScoreboard(this);
scoreboardPackets.forEach(p -> Utils.sendPackets(user, p));
}
ZLocation location = npcPojo.getLocation();
Player player = user.toPlayer();
if (npcIsPlayer) {
if (FunctionFactory.isTrue(this, "mirror")) updateProfile(user.getGameProfile().getProperties());
Utils.sendPackets(user, this.tabConstructor, this.updateTabConstructor);
ZNPCsPlus.SCHEDULER.runNextTick(() -> {
PacketEvents.getAPI().getPlayerManager().sendPacket(player, new WrapperPlayServerSpawnPlayer(entityID,
this.gameProfile.getId(), SpigotConversionUtil.fromBukkitLocation(location.toBukkitLocation())));
PacketEvents.getAPI().getPlayerManager().sendPacket(player, new WrapperPlayServerEntityMetadata(entityID,
List.of(new EntityData(NPCSkin.SkinLayerValues.findLayerByVersion(), EntityDataTypes.BYTE, Byte.MAX_VALUE))));
PacketEvents.getAPI().getPlayerManager().sendPacket(player, new WrapperPlayServerEntityHeadLook(entityID, location.getYaw()));
});
}
else {
ServerVersion version = PacketEvents.getAPI().getServerManager().getVersion();
EntityType type = SpigotConversionUtil.fromBukkitEntityType(((Entity) bukkitEntity).getType());
if (version.isNewerThanOrEquals(ServerVersion.V_1_14)) PacketEvents.getAPI().getPlayerManager().sendPacket(
player, new WrapperPlayServerSpawnEntity(entityID, Optional.of(uuid), type, location.toVector3d(),
location.getPitch(), location.getYaw(), location.getYaw(), 0, Optional.empty()));
else PacketEvents.getAPI().getPlayerManager().sendPacket(player, new WrapperPlayServerSpawnLivingEntity(
entityID, uuid, type, location.toVector3d(), location.getYaw(), location.getPitch(),
location.getPitch(), new Vector3d(), List.of()));
}
if (FunctionFactory.isTrue(this, "holo")) this.hologram.spawn(user);
updateMetadata(Collections.singleton(user));
sendEquipPackets(user);
lookAt(user, getLocation(), true);
if (npcIsPlayer) ZNPCsPlus.SCHEDULER.runTaskLaterSync(() -> {
removeFromTab(player);
Utils.sendPackets(user, this.updateTabConstructor);
}, 60);
} catch (ReflectiveOperationException operationException) {
delete(user);
throw new UnexpectedCallException(operationException);
}
}
private void removeFromTab(Player player) {
PacketWrapper<?> packet;
if (PacketEvents.getAPI().getServerManager().getVersion().isNewerThanOrEquals(ServerVersion.V_1_19_3)) packet = new WrapperPlayServerPlayerInfoRemove(gameProfile.getId());
else packet = new WrapperPlayServerPlayerInfo(WrapperPlayServerPlayerInfo.Action.REMOVE_PLAYER, new WrapperPlayServerPlayerInfo.PlayerData(null, new UserProfile(gameProfile.getId(), gameProfile.getName()), null, 1));
PacketEvents.getAPI().getPlayerManager().sendPacket(player, packet);
}
public synchronized void delete(ZUser user) {
if (!this.viewers.contains(user)) throw new IllegalStateException(user.getUUID().toString() + " is not a viewer.");
this.viewers.remove(user);
handleDelete(user);
}
private void handleDelete(ZUser user) {
Player player = user.toPlayer();
this.hologram.delete(user);
if (this.npcPojo.getNpcType() == NPCType.PLAYER) removeFromTab(player);
PacketEvents.getAPI().getPlayerManager().sendPacket(player, new WrapperPlayServerDestroyEntities(this.entityID));
}
public void lookAt(ZUser player, Location location, boolean rotation) {
long lastMoveNanos = System.nanoTime() - this.lastMove;
if (this.lastMove > 1L && lastMoveNanos < 1000000000L) return;
Location direction = rotation ? location : this.npcPojo.getLocation().pointingTo(location);
try {
Object lookPacket = Reflections.PACKET_PLAY_OUT_ENTITY_LOOK_CONSTRUCTOR.get().newInstance(this.entityID, (byte) (int) (direction.getYaw() * 256.0F / 360.0F), (byte) (int) (direction.getPitch() * 256.0F / 360.0F), true);
Object headRotationPacket = Reflections.PACKET_PLAY_OUT_ENTITY_HEAD_ROTATION_CONSTRUCTOR.get().newInstance(this.nmsEntity, (byte) (int) (direction.getYaw() * 256.0F / 360.0F));
if (player != null) Utils.sendPackets(player, lookPacket, headRotationPacket);
else this.viewers.forEach(players -> Utils.sendPackets(players, headRotationPacket));
} catch (ReflectiveOperationException operationException) {
throw new UnexpectedCallException(operationException);
}
}
public void deleteViewers() {
for (ZUser user : this.viewers) handleDelete(user);
this.viewers.clear();
}
protected void updateMetadata(Iterable<ZUser> users) {
try {
Object metaData = this.packets.getNms().createMetadataPacket(this.entityID, this.nmsEntity);
for (ZUser user : users) Utils.sendPackets(user, metaData);
} catch (ReflectiveOperationException operationException) {
operationException.getCause().printStackTrace();
operationException.printStackTrace();
}
}
public void updateProfile(PropertyMap propertyMap) {
if (this.npcPojo.getNpcType() != NPCType.PLAYER) return;
try {
Object gameProfile = Reflections.GET_PROFILE_METHOD.get().invoke(this.nmsEntity);
Utils.setValue(gameProfile, "name", this.gameProfile.getName());
Utils.setValue(gameProfile, "id", this.gameProfile.getId());
Utils.setValue(gameProfile, "properties", propertyMap);
} catch (ReflectiveOperationException operationException) {
throw new UnexpectedCallException(operationException);
}
}
public void sendEquipPackets(ZUser zUser) {
if (this.npcPojo.getNpcEquip().isEmpty()) return;
List<Equipment> equipment = npcPojo.getNpcEquip().entrySet().stream()
.filter(entry -> Objects.nonNull(entry.getKey()))
.filter(entry -> Objects.nonNull(entry.getValue()))
.map(entry -> new Equipment(entry.getKey(), SpigotConversionUtil.fromBukkitItemStack(entry.getValue())))
.toList();
if (Utils.versionNewer(16)) PacketEvents.getAPI().getPlayerManager().sendPacket(zUser.toPlayer(), new WrapperPlayServerEntityEquipment(entityID, equipment));
else for (Equipment e : equipment) PacketEvents.getAPI().getPlayerManager().sendPacket(zUser.toPlayer(), new WrapperPlayServerEntityEquipment(entityID, List.of(e)));
}
public void setPath(NPCPath.AbstractTypeWriter typeWriter) {
if (typeWriter == null) {
this.npcPath = null;
this.npcPojo.setPathName("none");
} else {
this.npcPath = typeWriter.getPath(this);
this.npcPojo.setPathName(typeWriter.getName());
}
}
public void tryStartConversation(Player player) {
ConversationModel conversation = this.npcPojo.getConversation();
if (conversation == null) throw new IllegalStateException("can't find conversation");
conversation.startConversation(this, player);
}
public Location getLocation() {
if (this.npcPath != null && this.npcPath.getLocation() != null) return this.npcPath.getLocation().toBukkitLocation();
return this.npcPojo.getLocation().toBukkitLocation();
}
}

@ -1,94 +0,0 @@
package io.github.znetworkw.znpcservers.npc;
import com.google.common.base.MoreObjects;
import lol.pyr.znpcsplus.ZNPCsPlus;
import io.github.znetworkw.znpcservers.npc.interaction.ClickType;
import io.github.znetworkw.znpcservers.user.ZUser;
import io.github.znetworkw.znpcservers.utility.Utils;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
public class NPCAction {
private final ActionType actionType;
private final ClickType clickType;
private final String action;
private int delay;
public NPCAction(ActionType actionType, ClickType clickType, String action, int delay) {
this.actionType = actionType;
this.clickType = clickType;
this.action = action;
this.delay = delay;
}
public NPCAction(String actionType, String action) {
this(ActionType.valueOf(actionType), ClickType.DEFAULT, action, 0);
}
public ActionType getActionType() {
return this.actionType;
}
public ClickType getClickType() {
return this.clickType;
}
public String getAction() {
return this.action;
}
public int getDelay() {
return this.delay;
}
public void setDelay(int delay) {
this.delay = delay;
}
public long getFixedDelay() {
return 1000000000L * this.delay;
}
public void run(ZUser user, String action) {
this.actionType.run(user, Utils.PLACEHOLDER_SUPPORT ? Utils.getWithPlaceholders(action, user.toPlayer()) : action);
}
public String toString() {
return MoreObjects.toStringHelper(this)
.add("actionType", this.actionType)
.add("clickType", this.clickType)
.add("action", this.action)
.add("delay", this.delay)
.toString();
}
enum ActionType {
CMD {
public void run(ZUser user, String actionValue) {
user.toPlayer().performCommand(actionValue);
}
},
CONSOLE {
public void run(ZUser user, String actionValue) {
Bukkit.dispatchCommand(Bukkit.getConsoleSender(), actionValue);
}
},
CHAT {
public void run(ZUser user, String actionValue) {
user.toPlayer().chat(actionValue);
}
},
MESSAGE {
public void run(ZUser user, String actionValue) {
user.toPlayer().sendMessage(ChatColor.translateAlternateColorCodes('&', actionValue));
}
},
SERVER {
public void run(ZUser user, String actionValue) {
ZNPCsPlus.BUNGEE_UTILS.sendPlayerToServer(user.toPlayer(), actionValue);
}
};
public abstract void run(ZUser param1ZUser, String param1String);
}
}

@ -1,66 +0,0 @@
package io.github.znetworkw.znpcservers.npc;
public abstract class NPCFunction {
private final String name;
public NPCFunction(String name) {
this.name = name;
}
public String getName() {
return this.name;
}
protected abstract boolean allow(NPC paramNPC);
protected abstract ResultType runFunction(NPC paramNPC, FunctionContext paramFunctionContext);
public void doRunFunction(NPC npc, FunctionContext functionContext) {
if (!allow(npc))
return;
ResultType resultType = runFunction(npc, functionContext);
if (resultType == ResultType.SUCCESS)
npc.getNpcPojo().getFunctions().put(getName(), !isTrue(npc));
}
protected ResultType resolve(NPC npc) {
throw new IllegalStateException("resolve is not implemented.");
}
public boolean isTrue(NPC npc) {
return FunctionFactory.isTrue(npc, this);
}
public enum ResultType {
SUCCESS, FAIL
}
public static class WithoutFunction extends NPCFunction {
public WithoutFunction(String name) {
super(name);
}
protected NPCFunction.ResultType runFunction(NPC npc, FunctionContext functionContext) {
return NPCFunction.ResultType.SUCCESS;
}
protected boolean allow(NPC npc) {
return true;
}
protected NPCFunction.ResultType resolve(NPC npc) {
return NPCFunction.ResultType.SUCCESS;
}
}
public static class WithoutFunctionSelfUpdate extends WithoutFunction {
public WithoutFunctionSelfUpdate(String name) {
super(name);
}
protected NPCFunction.ResultType runFunction(NPC npc, FunctionContext functionContext) {
npc.deleteViewers();
return NPCFunction.ResultType.SUCCESS;
}
}
}

@ -1,247 +0,0 @@
package io.github.znetworkw.znpcservers.npc;
import com.github.retrooper.packetevents.protocol.player.EquipmentSlot;
import io.github.znetworkw.znpcservers.npc.conversation.ConversationModel;
import io.github.znetworkw.znpcservers.utility.location.ZLocation;
import org.bukkit.inventory.ItemStack;
import java.util.*;
@SuppressWarnings("unused")
public class NPCModel {
private int id;
private UUID uuid;
private double hologramHeight;
private String skin;
private String signature;
private String pathName;
private String glowName;
private ConversationModel conversation;
private ZLocation location;
private NPCType npcType;
private boolean shouldSpawn;
private List<String> hologramLines;
private List<NPCAction> clickActions;
private Map<EquipmentSlot, ItemStack> npcEquip;
private Map<String, Boolean> npcFunctions;
private Map<String, String[]> customizationMap;
public NPCModel(int id) {
this.id = id;
this.uuid = UUID.randomUUID();
this.skin = "";
this.signature = "";
this.npcType = NPCType.PLAYER;
this.shouldSpawn = true;
this.hologramLines = Collections.singletonList("/znpcs lines");
this.clickActions = new ArrayList<>();
this.npcEquip = new HashMap<>();
this.customizationMap = new HashMap<>();
this.npcFunctions = new HashMap<>();
this.npcFunctions.put("holo", Boolean.TRUE);
}
public int getId() {
return this.id;
}
public void setId(int id) {
this.id = id;
}
public NPCModel withId(int id) {
setId(id);
return this;
}
public UUID getUuid() {
if (this.uuid == null) this.uuid = UUID.randomUUID();
return this.uuid;
}
public void setUuid(UUID uuid) {
this.uuid = uuid;
}
public double getHologramHeight() {
return this.hologramHeight;
}
public void setHologramHeight(double hologramHeight) {
this.hologramHeight = hologramHeight;
}
public NPCModel withHologramHeight(double hologramHeight) {
setHologramHeight(hologramHeight);
return this;
}
public String getSkin() {
return this.skin;
}
public void setSkin(String skin) {
this.skin = skin;
}
public NPCModel withSkin(String skin) {
setSkin(skin);
return this;
}
public String getSignature() {
return this.signature;
}
public void setSignature(String signature) {
this.signature = signature;
}
public NPCModel withSignature(String signature) {
setSignature(signature);
return this;
}
public String getPathName() {
return this.pathName;
}
public void setPathName(String pathName) {
this.pathName = pathName;
}
public NPCModel withPathName(String pathName) {
setPathName(pathName);
return this;
}
public String getGlowName() {
return this.glowName;
}
public void setGlowName(String glowName) {
this.glowName = glowName;
}
public NPCModel withGlowName(String glowName) {
setGlowName(this.pathName);
return this;
}
public ConversationModel getConversation() {
return this.conversation;
}
public void setConversation(ConversationModel conversation) {
this.conversation = conversation;
}
public NPCModel withConversation(ConversationModel conversation) {
setConversation(conversation);
return this;
}
public List<String> getHologramLines() {
return this.hologramLines;
}
public void setHologramLines(List<String> hologramLines) {
this.hologramLines = hologramLines;
}
public NPCModel withHologramLines(List<String> hologramLines) {
setHologramLines(hologramLines);
return this;
}
public ZLocation getLocation() {
return this.location;
}
public void setLocation(ZLocation location) {
this.location = location;
}
public NPCModel withLocation(ZLocation location) {
setLocation(location);
return this;
}
public NPCType getNpcType() {
return this.npcType;
}
public void setNpcType(NPCType npcType) {
this.npcType = npcType;
}
public NPCModel withNpcType(NPCType npcType) {
setNpcType(npcType);
return this;
}
public boolean getShouldSpawn() {
return this.shouldSpawn;
}
public void setShouldSpawn(boolean shouldSpawn) {
this.shouldSpawn = shouldSpawn;
}
public NPCModel withShouldSpawn(boolean shouldSpawn) {
setShouldSpawn(shouldSpawn);
return this;
}
public List<NPCAction> getClickActions() {
return this.clickActions;
}
public void setClickActions(List<NPCAction> clickActions) {
this.clickActions = clickActions;
}
public NPCModel withClickActions(List<NPCAction> clickActions) {
setClickActions(clickActions);
return this;
}
public Map<EquipmentSlot, ItemStack> getNpcEquip() {
return this.npcEquip;
}
public void setNpcEquip(Map<EquipmentSlot, ItemStack> npcEquip) {
this.npcEquip = npcEquip;
}
public NPCModel withNpcEquip(Map<EquipmentSlot, ItemStack> npcEquip) {
setNpcEquip(npcEquip);
return this;
}
public Map<String, String[]> getCustomizationMap() {
return this.customizationMap;
}
public void setCustomizationMap(Map<String, String[]> customizationMap) {
this.customizationMap = customizationMap;
}
public NPCModel withCustomizationMap(Map<String, String[]> customizationMap) {
setCustomizationMap(customizationMap);
return this;
}
public Map<String, Boolean> getFunctions() {
return this.npcFunctions;
}
public void setFunctions(Map<String, Boolean> npcFunctions) {
this.npcFunctions = npcFunctions;
}
public NPCModel withFunctionValues(Map<String, Boolean> npcFunctions) {
setFunctions(npcFunctions);
return this;
}
}

@ -1,263 +0,0 @@
package io.github.znetworkw.znpcservers.npc;
import io.github.znetworkw.znpcservers.configuration.Configuration;
import io.github.znetworkw.znpcservers.configuration.ConfigurationValue;
import io.github.znetworkw.znpcservers.user.ZUser;
import io.github.znetworkw.znpcservers.utility.location.ZLocation;
import lol.pyr.znpcsplus.ZNPCsPlus;
import org.bukkit.Location;
import org.bukkit.scheduler.BukkitTask;
import org.bukkit.util.Vector;
import java.io.*;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
@SuppressWarnings("ALL")
public interface NPCPath {
void initialize(DataInputStream paramDataInputStream) throws IOException;
void write(DataOutputStream paramDataOutputStream) throws IOException;
void start();
PathInitializer getPath(NPC paramNPC);
interface PathInitializer {
void handle();
ZLocation getLocation();
abstract class AbstractPath implements PathInitializer {
private final NPC npc;
private final NPCPath.AbstractTypeWriter typeWriter;
private ZLocation location;
public AbstractPath(NPC npc, NPCPath.AbstractTypeWriter typeWriter) {
this.npc = npc;
this.typeWriter = typeWriter;
}
public NPC getNpc() {
return this.npc;
}
public NPCPath.AbstractTypeWriter getPath() {
return this.typeWriter;
}
public ZLocation getLocation() {
return this.location;
}
public void setLocation(ZLocation location) {
this.location = location;
}
}
}
class ZNPCPathDelegator {
private final File file;
protected ZNPCPathDelegator(File file) {
this.file = file;
}
public static ZNPCPathDelegator forFile(File file) {
return new ZNPCPathDelegator(file);
}
public static ZNPCPathDelegator forPath(NPCPath.AbstractTypeWriter pathAbstract) {
return new ZNPCPathDelegator(pathAbstract.getFile());
}
public DataOutputStream getOutputStream() throws IOException {
return new DataOutputStream(new FileOutputStream(this.file));
}
public DataInputStream getInputStream() throws IOException {
return new DataInputStream(new FileInputStream(this.file));
}
}
abstract class AbstractTypeWriter implements NPCPath {
private static final ConcurrentMap<String, AbstractTypeWriter> PATH_TYPES = new ConcurrentHashMap<>();
private final TypeWriter typeWriter;
private final File file;
private final List<ZLocation> locationList;
public AbstractTypeWriter(TypeWriter typeWriter, File file) {
this.typeWriter = typeWriter;
this.file = file;
this.locationList = new ArrayList<>();
}
public AbstractTypeWriter(TypeWriter typeWriter, String pathName) {
this(typeWriter, new File(ZNPCsPlus.PATH_FOLDER, pathName + ".path"));
}
public static AbstractTypeWriter forCreation(String pathName, ZUser user, TypeWriter typeWriter) {
if (typeWriter == TypeWriter.MOVEMENT) return new TypeMovement(pathName, user);
throw new IllegalStateException("can't find type writer for: " + typeWriter.name());
}
public static AbstractTypeWriter forFile(File file, TypeWriter typeWriter) {
if (typeWriter == TypeWriter.MOVEMENT) return new TypeMovement(file);
throw new IllegalStateException("can't find type writer for: " + typeWriter.name());
}
public static void register(AbstractTypeWriter abstractZNPCPath) {
PATH_TYPES.put(abstractZNPCPath.getName(), abstractZNPCPath);
}
public static AbstractTypeWriter find(String name) {
return PATH_TYPES.get(name);
}
public static Collection<AbstractTypeWriter> getPaths() {
return PATH_TYPES.values();
}
public void load() {
try (DataInputStream reader = NPCPath.ZNPCPathDelegator.forFile(this.file).getInputStream()) {
initialize(reader);
register(this);
} catch (IOException e) {
ZNPCsPlus.LOGGER.warning("[AbstractTypeWriter] " + String.format("The path %s could not be loaded", this.file.getName()));
e.printStackTrace();
}
}
public void write() {
try (DataOutputStream writer = NPCPath.ZNPCPathDelegator.forFile(getFile()).getOutputStream()) {
write(writer);
if (writer != null) writer.close();
} catch (IOException e) {
ZNPCsPlus.LOGGER.warning("[AbstractTypeWriter] " + String.format("Path %s could not be created", getName()));
e.printStackTrace();
}
}
public File getFile() {
return this.file;
}
public List<ZLocation> getLocationList() {
return this.locationList;
}
public String getName() {
return this.file.getName().substring(0, this.file.getName().lastIndexOf('.'));
}
public enum TypeWriter {
MOVEMENT
}
private static class TypeMovement extends AbstractTypeWriter {
private static final int MAX_LOCATIONS = ((Integer) Configuration.CONFIGURATION.getValue(ConfigurationValue.MAX_PATH_LOCATIONS)).intValue();
private ZUser npcUser;
private BukkitTask bukkitTask;
public TypeMovement(File file) {
super(NPCPath.AbstractTypeWriter.TypeWriter.MOVEMENT, file);
}
public TypeMovement(String fileName, ZUser npcUser) {
super(NPCPath.AbstractTypeWriter.TypeWriter.MOVEMENT, fileName);
this.npcUser = npcUser;
start();
}
public void initialize(DataInputStream dataInputStream) throws IOException {
while (dataInputStream.available() > 0) {
String worldName = dataInputStream.readUTF();
double x = dataInputStream.readDouble();
double y = dataInputStream.readDouble();
double z = dataInputStream.readDouble();
float yaw = dataInputStream.readFloat();
float pitch = dataInputStream.readFloat();
getLocationList().add(new ZLocation(worldName, x, y, z, yaw, pitch));
}
}
public void write(DataOutputStream dataOutputStream) throws IOException {
if (getLocationList().isEmpty()) return;
Iterator<ZLocation> locationIterator = getLocationList().iterator();
while (locationIterator.hasNext()) {
ZLocation location = locationIterator.next();
dataOutputStream.writeUTF(location.getWorldName());
dataOutputStream.writeDouble(location.getX());
dataOutputStream.writeDouble(location.getY());
dataOutputStream.writeDouble(location.getZ());
dataOutputStream.writeFloat(location.getYaw());
dataOutputStream.writeFloat(location.getPitch());
if (!locationIterator.hasNext()) register(this);
}
}
public void start() {
this.npcUser.setHasPath(true);
this.bukkitTask = ZNPCsPlus.SCHEDULER.runTaskTimerAsynchronously(() -> {
if (this.npcUser.toPlayer() != null && this.npcUser.isHasPath() && MAX_LOCATIONS > getLocationList().size()) {
Location location = this.npcUser.toPlayer().getLocation();
if (isValid(location))
getLocationList().add(new ZLocation(location));
} else {
this.bukkitTask.cancel();
this.npcUser.setHasPath(false);
write();
}
}, 1, 1);
}
public MovementPath getPath(NPC npc) {
return new MovementPath(npc, this);
}
protected boolean isValid(Location location) {
if (getLocationList().isEmpty())
return true;
ZLocation last = getLocationList().get(getLocationList().size() - 1);
double xDiff = Math.abs(last.getX() - location.getX());
double yDiff = Math.abs(last.getY() - location.getY());
double zDiff = Math.abs(last.getZ() - location.getZ());
return (xDiff + yDiff + zDiff > 0.01D);
}
protected static class MovementPath extends NPCPath.PathInitializer.AbstractPath {
private int currentEntryPath = 0;
private boolean pathReverse = false;
public MovementPath(NPC npc, NPCPath.AbstractTypeWriter.TypeMovement path) {
super(npc, path);
}
public void handle() {
updatePathLocation(getPath().getLocationList().get(this.currentEntryPath = getNextLocation()));
int nextIndex = getNextLocation();
if (nextIndex < 1) {
this.pathReverse = false;
} else if (nextIndex >= getPath().getLocationList().size() - 1) {
this.pathReverse = true;
}
}
private int getNextLocation() {
return this.pathReverse ? (this.currentEntryPath - 1) : (this.currentEntryPath + 1);
}
protected void updatePathLocation(ZLocation location) {
setLocation(location);
ZLocation next = getPath().getLocationList().get(getNextLocation());
Vector vector = next.toVector().add(new Vector(0.0D, location.getY() - next.getY(), 0.0D));
Location direction = next.toBukkitLocation().clone().setDirection(location.toVector().subtract(vector)
.multiply(new Vector(-1, 0, -1)));
getNpc().setLocation(direction, false);
getNpc().lookAt(null, direction, true);
}
}
}
}
}

@ -1,63 +0,0 @@
package io.github.znetworkw.znpcservers.npc;
import io.github.znetworkw.znpcservers.skin.SkinFetcherBuilder;
import io.github.znetworkw.znpcservers.skin.SkinFetcherResult;
import io.github.znetworkw.znpcservers.utility.Utils;
public class NPCSkin {
private static final int LAYER_INDEX = SkinLayerValues.findLayerByVersion();
private final String texture;
private final String signature;
public NPCSkin(String texture, String signature) {
this.texture = texture;
this.signature = signature;
}
public static NPCSkin forValues(String... values) {
return new NPCSkin(values[0], (values.length > 1) ? values[1] : null);
}
public static void forName(String skin, SkinFetcherResult skinFetcherResult) {
SkinFetcherBuilder.withName(skin).toSkinFetcher().doReadSkin(skinFetcherResult);
}
public String getTexture() {
return this.texture;
}
public String getSignature() {
return this.signature;
}
public int getLayerIndex() {
return LAYER_INDEX;
}
enum SkinLayerValues {
V8(8, 12),
V9(10, 13),
V14(14, 15),
V16(15, 16),
V17(17, 17),
V18(18, 17);
final int minVersion;
final int layerValue;
SkinLayerValues(int minVersion, int layerValue) {
this.minVersion = minVersion;
this.layerValue = layerValue;
}
static int findLayerByVersion() {
int value = V8.layerValue;
for (SkinLayerValues skinLayerValue : values()) {
if (Utils.BUKKIT_VERSION >= skinLayerValue.minVersion)
value = skinLayerValue.layerValue;
}
return value;
}
}
}

@ -1,18 +1,12 @@
package io.github.znetworkw.znpcservers.npc; package io.github.znetworkw.znpcservers.npc;
import io.github.znetworkw.znpcservers.UnexpectedCallException;
import io.github.znetworkw.znpcservers.reflection.EnumPropertyCache;
import io.github.znetworkw.znpcservers.utility.Utils; import io.github.znetworkw.znpcservers.utility.Utils;
import org.bukkit.entity.EntityType;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Optional;
import static io.github.znetworkw.znpcservers.reflection.Reflections.*; import static io.github.znetworkw.znpcservers.reflection.Reflections.*;
/**
* Delete after information transferred
*/
@SuppressWarnings("unused") @SuppressWarnings("unused")
public enum NPCType { public enum NPCType {
ALLAY(ENTITY_ALLAY_CLASS, -1.14), ALLAY(ENTITY_ALLAY_CLASS, -1.14),
@ -96,79 +90,9 @@ public enum NPCType {
ZOMBIFIED_PIGLIN(Utils.versionNewer(16) ? ENTITY_ZOMBIFIED_PIGLIN_CLASS : null, 0.135, "setBaby"), ZOMBIFIED_PIGLIN(Utils.versionNewer(16) ? ENTITY_ZOMBIFIED_PIGLIN_CLASS : null, 0.135, "setBaby"),
PIG_ZOMBIE(Utils.versionNewer(16) ? null : ENTITY_ZOMBIFIED_PIGLIN_CLASS, 0.135); PIG_ZOMBIE(Utils.versionNewer(16) ? null : ENTITY_ZOMBIFIED_PIGLIN_CLASS, 0.135);
private final double holoHeight;
private final CustomizationLoader customizationLoader;
private final Constructor<?> constructor;
private EntityType bukkitEntityType;
private Object nmsEntityType;
@SuppressWarnings("OptionalGetWithoutIsPresent")
NPCType(Class<?> entityClass, String newName, double holoHeight, String ... methods) { NPCType(Class<?> entityClass, String newName, double holoHeight, String ... methods) {
this.holoHeight = holoHeight;
if (entityClass == null) {
customizationLoader = null;
} else {
this.bukkitEntityType = EntityType.valueOf(newName.length() > 0 ? newName : this.name());
customizationLoader = new CustomizationLoader(this.bukkitEntityType, Arrays.asList(methods));
}
if (entityClass == null || entityClass.isAssignableFrom(ENTITY_PLAYER_CLASS)) {
this.constructor = null;
return;
}
try {
if (Utils.versionNewer(14)) {
this.nmsEntityType = ((Optional<?>) ENTITY_TYPES_A_METHOD.get().invoke(null, this.bukkitEntityType.getKey().getKey().toLowerCase())).get();
this.constructor = entityClass.getConstructor(ENTITY_TYPES_CLASS, WORLD_CLASS);
} else {
this.constructor = entityClass.getConstructor(WORLD_CLASS);
}
}
catch (ReflectiveOperationException operationException) {
throw new UnexpectedCallException(operationException);
}
} }
NPCType(Class<?> entityClass, double holoHeight, String ... customization) { NPCType(Class<?> entityClass, double holoHeight, String ... customization) {
this(entityClass, "", holoHeight, customization);
}
public double getHoloHeight() {
return this.holoHeight;
}
public Constructor<?> getConstructor() {
return this.constructor;
}
public Object getNmsEntityType() {
return this.nmsEntityType;
}
public CustomizationLoader getCustomizationLoader() {
return this.customizationLoader;
}
public static Object[] collectArguments(String[] strings, Method method) {
Class<?>[] methodParameterTypes = method.getParameterTypes();
Object[] newArray = new Object[methodParameterTypes.length];
for (int i = 0; i < methodParameterTypes.length; ++i) {
PrimitivePropertyType primitivePropertyType = PrimitivePropertyType.forType(methodParameterTypes[i]);
newArray[i] = primitivePropertyType != null ? primitivePropertyType.getFunction().apply(strings[i]) : EnumPropertyCache.find(strings[i], methodParameterTypes[i]);
}
return newArray;
}
public void updateCustomization(NPC npc, String name, String[] values) {
if (!this.customizationLoader.contains(name)) {
return;
}
try {
Method method = this.customizationLoader.getMethods().get(name);
method.invoke(npc.getBukkitEntity(), NPCType.collectArguments(values, method));
npc.updateMetadata(npc.getViewers());
}
catch (IllegalAccessException | InvocationTargetException e) {
throw new IllegalStateException("can't invoke method: " + name, e);
}
} }
} }

@ -1,13 +0,0 @@
package io.github.znetworkw.znpcservers.npc;
import io.github.znetworkw.znpcservers.utility.Utils;
public enum NamingType {
DEFAULT {
public String resolve(NPC npc) {
return Utils.randomString(6);
}
};
public abstract String resolve(NPC paramNPC);
}

@ -1,34 +0,0 @@
package io.github.znetworkw.znpcservers.npc;
import java.util.function.Function;
public enum PrimitivePropertyType {
STRING(String::toString),
BOOLEAN(Boolean::parseBoolean),
INT(Integer::parseInt),
DOUBLE(Double::parseDouble),
FLOAT(Float::parseFloat),
SHORT(Short::parseShort),
LONG(Long::parseLong);
private final Function<String, ?> function;
PrimitivePropertyType(Function<String, ?> function) {
this.function = function;
}
public static PrimitivePropertyType forType(Class<?> primitiveType) {
if (primitiveType == String.class) return STRING;
if (primitiveType == boolean.class) return BOOLEAN;
if (primitiveType == int.class) return INT;
if (primitiveType == double.class) return DOUBLE;
if (primitiveType == float.class) return FLOAT;
if (primitiveType == short.class) return SHORT;
if (primitiveType == long.class) return LONG;
return null;
}
public Function<String, ?> getFunction() {
return this.function;
}
}

@ -1,58 +0,0 @@
package io.github.znetworkw.znpcservers.npc.conversation;
import io.github.znetworkw.znpcservers.configuration.ConfigurationConstants;
import java.util.ArrayList;
import java.util.List;
public class Conversation {
private final String name;
private final List<ConversationKey> texts;
private int radius = 5;
private int delay = 10;
public Conversation(String name) {
this(name, new ArrayList<>());
}
protected Conversation(String name, List<ConversationKey> text) {
this.name = name;
this.texts = text;
}
public static Conversation forName(String name) {
return ConfigurationConstants.NPC_CONVERSATIONS.stream()
.filter(conversation -> conversation.getName().equalsIgnoreCase(name))
.findFirst()
.orElse(null);
}
public static boolean exists(String name) {
return ConfigurationConstants.NPC_CONVERSATIONS.stream()
.anyMatch(conversation -> conversation.getName().equalsIgnoreCase(name));
}
public String getName() {
return this.name;
}
public List<ConversationKey> getTexts() {
return this.texts;
}
public int getDelay() {
return this.delay;
}
public void setDelay(int delay) {
this.delay = delay;
}
public int getRadius() {
return this.radius;
}
public void setRadius(int radius) {
this.radius = radius;
}
}

@ -1,57 +0,0 @@
package io.github.znetworkw.znpcservers.npc.conversation;
import com.google.common.base.Splitter;
import io.github.znetworkw.znpcservers.npc.NPCAction;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;
public class ConversationKey {
private static final Splitter SPACE_SPLITTER = Splitter.on(" ");
private final List<String> lines;
private final List<NPCAction> actions;
private int delay = 1;
private String soundName;
public ConversationKey(String line) {
this(SPACE_SPLITTER.split(line));
}
public ConversationKey(Iterable<String> line) {
this.lines = StreamSupport.stream(line.spliterator(), false).map(String::toString).collect(Collectors.toList());
this.actions = new ArrayList<>();
}
public List<String> getLines() {
return this.lines;
}
public int getDelay() {
return this.delay;
}
public void setDelay(int delay) {
this.delay = delay;
}
public String getSoundName() {
return this.soundName;
}
public void setSoundName(String soundName) {
this.soundName = soundName;
}
public List<NPCAction> getActions() {
return this.actions;
}
public String getTextFormatted() {
if (this.lines.isEmpty()) return "";
String text = this.lines.iterator().next();
int fixedLength = Math.min(text.length(), 28);
return text.substring(0, fixedLength);
}
}

@ -1,73 +0,0 @@
package io.github.znetworkw.znpcservers.npc.conversation;
import io.github.znetworkw.znpcservers.npc.NPC;
import org.bukkit.entity.Player;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.stream.Stream;
public class ConversationModel {
private final transient Map<UUID, Long> lastStarted = new HashMap<>();
private String conversationName;
private ConversationType conversationType;
public ConversationModel(String conversationName, String conversationType) {
this.conversationName = conversationName;
try {
this.conversationType = ConversationType.valueOf(conversationType.toUpperCase());
} catch (IllegalArgumentException exception) {
throw new IllegalStateException("can't find conversation type " + conversationType);
}
}
@SuppressWarnings("unused")
private ConversationModel() {
}
public String getConversationName() {
return this.conversationName;
}
public ConversationType getConversationType() {
return this.conversationType;
}
public Conversation getConversation() {
return Conversation.forName(this.conversationName);
}
public void startConversation(NPC npc, Player player) {
if (!Conversation.exists(this.conversationName)) throw new IllegalStateException("can't find conversation " + this.conversationName);
if (ConversationProcessor.isPlayerConversing(player.getUniqueId())) return;
if (this.lastStarted.containsKey(player.getUniqueId())) {
long lastConversationNanos = System.nanoTime() - this.lastStarted.get(player.getUniqueId());
if (lastConversationNanos < 1000000000L * getConversation().getDelay()) return;
}
this.lastStarted.remove(player.getUniqueId());
if (this.conversationType.canStart(npc, getConversation(), player)) {
new ConversationProcessor(npc, this, player);
this.lastStarted.put(player.getUniqueId(), System.nanoTime());
}
}
public boolean canRun(NPC npc, Player player) {
return Stream.of(ConversationType.values()).anyMatch(conversationType1 -> !conversationType1.canStart(npc, getConversation(), player));
}
public enum ConversationType {
RADIUS {
public boolean canStart(NPC npc, Conversation conversation, Player player) {
return (player.getWorld() == npc.getLocation().getWorld() && player.getLocation().distance(npc.getLocation()) <= conversation.getRadius());
}
},
CLICK {
public boolean canStart(NPC npc, Conversation conversation, Player player) {
return true;
}
};
abstract boolean canStart(NPC param1NPC, Conversation param1Conversation, Player param1Player);
}
}

@ -1,70 +0,0 @@
package io.github.znetworkw.znpcservers.npc.conversation;
import lol.pyr.znpcsplus.ZNPCsPlus;
import io.github.znetworkw.znpcservers.configuration.ConfigurationConstants;
import io.github.znetworkw.znpcservers.npc.NPC;
import io.github.znetworkw.znpcservers.hologram.replacer.LineReplacer;
import io.github.znetworkw.znpcservers.user.ZUser;
import org.bukkit.Bukkit;
import org.bukkit.Sound;
import org.bukkit.entity.Player;
import org.bukkit.scheduler.BukkitRunnable;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
public class ConversationProcessor {
private static final Map<UUID, String> RUNNING_CONVERSATIONS = new HashMap<>();
private final NPC npc;
private final ConversationModel conversationModel;
private final Player player;
private int conversationIndex = 0;
private long conversationIndexDelay = System.nanoTime();
public ConversationProcessor(NPC npc, ConversationModel conversationModel, Player player) {
if (conversationModel.getConversation().getTexts().isEmpty())
throw new IllegalStateException("conversation should have a text.");
this.npc = npc;
this.conversationModel = conversationModel;
this.player = player;
RUNNING_CONVERSATIONS.put(player.getUniqueId(), conversationModel.getConversationName());
start();
}
public static boolean isPlayerConversing(UUID uuid) {
return RUNNING_CONVERSATIONS.containsKey(uuid);
}
private void start() {
ZNPCsPlus.SCHEDULER.runTaskTimer(new BukkitRunnable() {
public void run() {
if (Bukkit.getPlayer(ConversationProcessor.this.player.getUniqueId()) == null || ConversationProcessor.this
.conversationIndex > ConversationProcessor.this.conversationModel.getConversation().getTexts().size() - 1 || ConversationProcessor.this
.conversationModel.canRun(ConversationProcessor.this.npc, ConversationProcessor.this.player)) {
ConversationProcessor.RUNNING_CONVERSATIONS.remove(ConversationProcessor.this.player.getUniqueId());
cancel();
return;
}
ConversationKey conversationKey = ConversationProcessor.this.conversationModel.getConversation().getTexts().get(ConversationProcessor.this.conversationIndex);
long conversationDelayNanos = System.nanoTime() - ConversationProcessor.this.conversationIndexDelay;
if (ConversationProcessor.this.conversationIndex != 0 && conversationDelayNanos < 1000000000L * conversationKey
.getDelay())
return;
ZUser user = ZUser.find(ConversationProcessor.this.player);
conversationKey.getLines().forEach(s -> ConversationProcessor.this.player.sendMessage(LineReplacer.makeAll(user, s).replace(ConfigurationConstants.SPACE_SYMBOL, " ")));
if (conversationKey.getActions().size() > 0)
conversationKey.getActions().forEach(action -> action.run(user, action.getAction()));
if (conversationKey.getSoundName() != null && conversationKey
.getSoundName().length() > 0)
try {
Sound sound = Sound.valueOf(conversationKey.getSoundName().toUpperCase());
ConversationProcessor.this.player.playSound(ConversationProcessor.this.player.getLocation(), sound, 0.2F, 1.0F);
} catch (IllegalArgumentException ignored) {
}
ConversationProcessor.this.conversationIndexDelay = System.nanoTime();
ConversationProcessor.this.conversationIndex++;
}
}, 5, 20);
}
}

@ -1,44 +0,0 @@
package io.github.znetworkw.znpcservers.npc.function;
import io.github.znetworkw.znpcservers.reflection.Reflections;
import io.github.znetworkw.znpcservers.npc.FunctionContext;
import io.github.znetworkw.znpcservers.npc.FunctionFactory;
import io.github.znetworkw.znpcservers.npc.NPC;
import io.github.znetworkw.znpcservers.npc.NPCFunction;
public class GlowFunction extends NPCFunction {
public GlowFunction() {
super("glow");
}
protected NPCFunction.ResultType runFunction(NPC npc, FunctionContext functionContext) {
if (!(functionContext instanceof FunctionContext.ContextWithValue))
throw new IllegalStateException("invalid context type, " + functionContext.getClass().getSimpleName() + ", expected ContextWithValue.");
String glowColorName = ((FunctionContext.ContextWithValue) functionContext).getValue();
try {
Object glowColor = Reflections.ENUM_CHAT_FORMAT_FIND.get().invoke(null, (
glowColorName == null || glowColorName.length() == 0) ? "WHITE" : glowColorName);
if (glowColor == null)
return NPCFunction.ResultType.FAIL;
npc.getNpcPojo().setGlowName(glowColorName);
npc.setGlowColor(glowColor);
Reflections.SET_DATA_WATCHER_METHOD.get().invoke(Reflections.GET_DATA_WATCHER_METHOD
.get().invoke(npc.getNmsEntity()), Reflections.DATA_WATCHER_OBJECT_CONSTRUCTOR
.get().newInstance(0, Reflections.DATA_WATCHER_REGISTER_FIELD
.get()), (byte) (!FunctionFactory.isTrue(npc, this) ? 64 : 0));
npc.getPackets().getNms().update(npc.getPackets());
npc.deleteViewers();
return NPCFunction.ResultType.SUCCESS;
} catch (ReflectiveOperationException operationException) {
return NPCFunction.ResultType.FAIL;
}
}
protected boolean allow(NPC npc) {
return npc.getPackets().getNms().allowsGlowColor();
}
public NPCFunction.ResultType resolve(NPC npc) {
return runFunction(npc, new FunctionContext.ContextWithValue(npc, npc.getNpcPojo().getGlowName()));
}
}

@ -1,11 +0,0 @@
package io.github.znetworkw.znpcservers.npc.interaction;
public enum ClickType {
RIGHT, LEFT, DEFAULT;
public static ClickType forName(String clickName) {
if (clickName.startsWith("INTERACT")) return RIGHT;
if (clickName.startsWith("ATTACK")) return LEFT;
return DEFAULT;
}
}

@ -1,48 +0,0 @@
package io.github.znetworkw.znpcservers.npc.interaction;
import io.github.znetworkw.znpcservers.npc.NPC;
import org.bukkit.entity.Player;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
@SuppressWarnings("unused")
public class NPCInteractEvent extends Event {
private static final HandlerList handlerList = new HandlerList();
private final Player player;
private final ClickType clickType;
private final NPC npc;
public NPCInteractEvent(Player player, ClickType clickType, NPC npc) {
this.player = player;
this.clickType = clickType;
this.npc = npc;
}
public NPCInteractEvent(Player player, String clickType, NPC npc) {
this(player, ClickType.forName(clickType), npc);
}
public static HandlerList getHandlerList() {
return handlerList;
}
public Player getPlayer() {
return this.player;
}
public NPC getNpc() {
return this.npc;
}
public boolean isRightClick() {
return (this.clickType == ClickType.RIGHT);
}
public boolean isLeftClick() {
return (this.clickType == ClickType.LEFT);
}
public HandlerList getHandlers() {
return handlerList;
}
}

@ -1,29 +0,0 @@
package io.github.znetworkw.znpcservers.npc.task;
import lol.pyr.znpcsplus.ZNPCsPlus;
import io.github.znetworkw.znpcservers.npc.NPC;
import org.bukkit.Bukkit;
import org.bukkit.World;
import org.bukkit.scheduler.BukkitRunnable;
public class NPCLoadTask extends BukkitRunnable {
private final NPC npc;
private int tries = 0;
public NPCLoadTask(NPC npc) {
this.npc = npc;
ZNPCsPlus.SCHEDULER.runTaskTimer(this, 40);
}
public void run() {
if (this.tries++ > 10) {
cancel();
return;
}
World world = Bukkit.getWorld(this.npc.getNpcPojo().getLocation().getWorldName());
if (world == null) return;
cancel();
this.npc.onLoad();
}
}

@ -1,28 +0,0 @@
package io.github.znetworkw.znpcservers.npc.task;
import io.github.znetworkw.znpcservers.npc.FunctionFactory;
import io.github.znetworkw.znpcservers.npc.NPC;
import io.github.znetworkw.znpcservers.user.ZUser;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.plugin.Plugin;
import org.bukkit.scheduler.BukkitRunnable;
public class NPCPositionTask extends BukkitRunnable {
public NPCPositionTask(Plugin serversNPC) {
runTaskTimerAsynchronously(serversNPC, 60L, 1L);
}
public void run() {
for (NPC npc : NPC.all()) {
if (npc.getNpcPath() != null) {
npc.getNpcPath().handle();
}
else if (FunctionFactory.isTrue(npc, "look")) for (Player player : Bukkit.getOnlinePlayers()) {
if (!player.getWorld().equals(npc.getLocation().getWorld())) continue;
ZUser user = ZUser.find(player);
if (npc.getViewers().contains(user)) npc.lookAt(user, player.getLocation(), false);
}
}
}
}

@ -1,15 +0,0 @@
package io.github.znetworkw.znpcservers.npc.task;
import io.github.znetworkw.znpcservers.configuration.Configuration;
import org.bukkit.plugin.Plugin;
import org.bukkit.scheduler.BukkitRunnable;
public class NPCSaveTask extends BukkitRunnable {
public NPCSaveTask(Plugin serversNPC, int seconds) {
runTaskTimerAsynchronously(serversNPC, 200L, seconds);
}
public void run() {
Configuration.SAVE_CONFIGURATIONS.forEach(Configuration::save);
}
}

@ -1,63 +0,0 @@
package io.github.znetworkw.znpcservers.skin;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import io.github.znetworkw.znpcservers.npc.NPCSkin;
import java.io.DataOutputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class SkinFetcher {
private static final ExecutorService SKIN_EXECUTOR_SERVICE = Executors.newCachedThreadPool();
private final SkinFetcherBuilder builder;
public SkinFetcher(SkinFetcherBuilder builder) {
this.builder = builder;
}
public CompletableFuture<JsonObject> doReadSkin(SkinFetcherResult skinFetcherResult) {
CompletableFuture<JsonObject> completableFuture = new CompletableFuture<>();
SKIN_EXECUTOR_SERVICE.submit(() -> {
try {
HttpURLConnection connection = (HttpURLConnection) (new URL(this.builder.getAPIServer().getURL() + getData())).openConnection();
connection.setRequestMethod(this.builder.getAPIServer().getMethod());
if (this.builder.isUrlType()) {
connection.setDoOutput(true);
try (DataOutputStream outputStream = new DataOutputStream(connection.getOutputStream())) {
outputStream.writeBytes("url=" + URLEncoder.encode(this.builder.getData(), StandardCharsets.UTF_8));
}
}
try (Reader reader = new InputStreamReader(connection.getInputStream(), StandardCharsets.UTF_8)) {
completableFuture.complete(JsonParser.parseReader(reader).getAsJsonObject());
} finally {
connection.disconnect();
}
} catch (Throwable throwable) {
throwable.printStackTrace();
completableFuture.completeExceptionally(throwable);
}
});
completableFuture.whenComplete((response, throwable) -> {
if (completableFuture.isCompletedExceptionally()) {
skinFetcherResult.onDone(null, throwable);
} else {
JsonObject jsonObject = response.getAsJsonObject(this.builder.getAPIServer().getValueKey());
JsonObject properties = jsonObject.getAsJsonObject(this.builder.getAPIServer().getSignatureKey());
skinFetcherResult.onDone(new NPCSkin(properties.get("value").getAsString(), properties.get("signature").getAsString()), null);
}
});
return completableFuture;
}
private String getData() {
return this.builder.isProfileType() ? ("/" + this.builder.getData()) : "";
}
}

@ -1,76 +0,0 @@
package io.github.znetworkw.znpcservers.skin;
public class SkinFetcherBuilder {
private final SkinServer apiServer;
private final String name;
protected SkinFetcherBuilder(SkinServer apiServer, String name) {
this.apiServer = apiServer;
this.name = name;
}
public static SkinFetcherBuilder create(SkinServer skinAPIURL, String name) {
return new SkinFetcherBuilder(skinAPIURL, name);
}
public static SkinFetcherBuilder withName(String name) {
return create(name.startsWith("http") ? SkinServer.GENERATE_API : SkinServer.PROFILE_API, name);
}
public SkinServer getAPIServer() {
return this.apiServer;
}
public String getData() {
return this.name;
}
public boolean isUrlType() {
return (this.apiServer == SkinServer.GENERATE_API);
}
public boolean isProfileType() {
return (this.apiServer == SkinServer.PROFILE_API);
}
public SkinFetcher toSkinFetcher() {
return new SkinFetcher(this);
}
public enum SkinServer {
PROFILE_API("GET", "https://api.ashcon.app/mojang/v2/user", "textures", "raw"),
GENERATE_API("POST", "https://api.mineskin.org/generate/url", "data", "texture");
private final String method;
private final String url;
private final String valueKey;
private final String signatureKey;
SkinServer(String method, String url, String valueKey, String signatureKey) {
this.method = method;
this.url = url;
this.valueKey = valueKey;
this.signatureKey = signatureKey;
}
public String getMethod() {
return this.method;
}
public String getURL() {
return this.url;
}
public String getValueKey() {
return this.valueKey;
}
public String getSignatureKey() {
return this.signatureKey;
}
}
}

@ -1,7 +0,0 @@
package io.github.znetworkw.znpcservers.skin;
import io.github.znetworkw.znpcservers.npc.NPCSkin;
public interface SkinFetcherResult {
void onDone(NPCSkin npcSkin, Throwable paramThrowable);
}

@ -1,6 +1,7 @@
package io.github.znetworkw.znpcservers.user; package io.github.znetworkw.znpcservers.user;
import lol.pyr.znpcsplus.ZNPCsPlus; import lol.pyr.znpcsplus.ZNPCsPlus;
import lol.pyr.znpcsplus.user.User;
import org.bukkit.event.Event; import org.bukkit.event.Event;
import java.util.ArrayList; import java.util.ArrayList;
@ -34,21 +35,21 @@ public class EventService<T extends Event> {
ZNPCsPlus.SCHEDULER.runNextTick(() -> this.eventConsumers.forEach(consumer -> consumer.accept(event))); ZNPCsPlus.SCHEDULER.runNextTick(() -> this.eventConsumers.forEach(consumer -> consumer.accept(event)));
} }
public static <T extends Event> EventService<T> addService(ZUser user, Class<T> eventClass) { public static <T extends Event> EventService<T> addService(User user, Class<T> eventClass) {
if (EventService.hasService(user, eventClass)) throw new IllegalStateException(eventClass.getSimpleName() + " is already register for " + user.getUUID().toString()); if (EventService.hasService(user, eventClass)) throw new IllegalStateException(eventClass.getSimpleName() + " is already register for " + user.getUuid().toString());
EventService<T> service = new EventService<>(eventClass, new ArrayList<>()); EventService<T> service = new EventService<>(eventClass, new ArrayList<>());
user.getEventServices().add(service); user.getEventServices().add(service);
user.toPlayer().closeInventory(); user.getPlayer().closeInventory();
return service; return service;
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public static <T extends Event> EventService<T> findService(ZUser user, Class<T> eventClass) { public static <T extends Event> EventService<T> findService(User user, Class<T> eventClass) {
Objects.requireNonNull(EventService.class); Objects.requireNonNull(EventService.class);
return user.getEventServices().stream().filter(eventService -> eventService.getEventClass().isAssignableFrom(eventClass)).map(EventService.class::cast).findFirst().orElse(null); return user.getEventServices().stream().filter(eventService -> eventService.getEventClass().isAssignableFrom(eventClass)).map(EventService.class::cast).findFirst().orElse(null);
} }
public static boolean hasService(ZUser user, Class<? extends Event> eventClass) { public static boolean hasService(User user, Class<? extends Event> eventClass) {
return user.getEventServices().stream().anyMatch(eventService -> eventService.getEventClass() == eventClass); return user.getEventServices().stream().anyMatch(eventService -> eventService.getEventClass() == eventClass);
} }
} }

@ -1,99 +0,0 @@
package io.github.znetworkw.znpcservers.user;
import com.mojang.authlib.GameProfile;
import io.github.znetworkw.znpcservers.npc.NPC;
import io.github.znetworkw.znpcservers.reflection.Reflections;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import java.lang.reflect.InvocationTargetException;
import java.util.*;
public class ZUser {
private static final Map<UUID, ZUser> USER_MAP = new HashMap<>();
private final Map<Integer, Long> lastClicked;
private final List<EventService<?>> eventServices;
private final UUID uuid;
private final GameProfile gameProfile;
private final Object playerConnection;
private boolean hasPath = false;
private long lastInteract = 0L;
public ZUser(UUID uuid) {
this.uuid = uuid;
this.lastClicked = new HashMap<>();
this.eventServices = new ArrayList<>();
try {
Object playerHandle = Reflections.GET_HANDLE_PLAYER_METHOD.get().invoke(toPlayer());
this.gameProfile = (GameProfile) Reflections.GET_PROFILE_METHOD.get().invoke(playerHandle, new Object[0]);
this.playerConnection = Reflections.PLAYER_CONNECTION_FIELD.get().get(playerHandle);
} catch (IllegalAccessException | InvocationTargetException e) {
throw new IllegalStateException("can't create user for player " + uuid.toString(), e.getCause());
}
}
public static ZUser find(UUID uuid) {
return USER_MAP.computeIfAbsent(uuid, ZUser::new);
}
public static ZUser find(Player player) {
return find(player.getUniqueId());
}
public static void unregister(Player player) {
ZUser zUser = USER_MAP.get(player.getUniqueId());
if (zUser == null)
throw new IllegalStateException("can't find user " + player.getUniqueId());
USER_MAP.remove(player.getUniqueId());
NPC.all().stream()
.filter(npc -> npc.getViewers().contains(zUser))
.forEach(npc -> npc.delete(zUser));
}
public UUID getUUID() {
return this.uuid;
}
public GameProfile getGameProfile() {
return this.gameProfile;
}
public Object getPlayerConnection() {
return this.playerConnection;
}
public boolean isHasPath() {
return this.hasPath;
}
public void setHasPath(boolean hasPath) {
this.hasPath = hasPath;
}
public List<EventService<?>> getEventServices() {
return this.eventServices;
}
public Player toPlayer() {
return Bukkit.getPlayer(this.uuid);
}
public long getLastInteract() {
return lastInteract;
}
public Map<Integer, Long> getLastClicked() {
return lastClicked;
}
public void updateLastInteract() {
this.lastInteract = System.nanoTime();
}
}

@ -1,137 +0,0 @@
package io.github.znetworkw.znpcservers.utility.location;
import com.github.retrooper.packetevents.util.Vector3d;
import com.google.common.base.Preconditions;
import com.google.gson.*;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.util.NumberConversions;
import org.bukkit.util.Vector;
import java.lang.reflect.Type;
public class ZLocation {
public static final ZLocationSerializer SERIALIZER = new ZLocationSerializer();
private final String worldName;
private final double x;
private final double y;
private final double z;
private final float yaw;
private final float pitch;
public ZLocation(String worldName, double x, double y, double z, float yaw, float pitch) {
this.worldName = worldName;
this.x = x;
this.y = y;
this.z = z;
this.yaw = yaw;
this.pitch = pitch;
}
public ZLocation(Location location) {
this(Preconditions.checkNotNull(location.getWorld()).getName(), location
.getX(), location
.getY(), location
.getZ(), location
.getYaw(), location
.getPitch());
}
public String getWorldName() {
return this.worldName;
}
public World getWorld() {
return Bukkit.getWorld(this.worldName);
}
public double getX() {
return this.x;
}
public double getY() {
return this.y;
}
public double getZ() {
return this.z;
}
public float getYaw() {
return this.yaw;
}
public float getPitch() {
return this.pitch;
}
public Location toBukkitLocation() {
return new Location(getWorld(), this.x, this.y, this.z, this.yaw, this.pitch);
}
public Vector toVector() {
return new Vector(x, y, z);
}
public Vector3d toVector3d() {
return new Vector3d(x, y, z);
}
private static final double _2PI = 2 * Math.PI;
public Location pointingTo(Location loc) {
return pointingTo(new ZLocation(loc)).toBukkitLocation();
}
public ZLocation pointingTo(ZLocation loc) {
/*
* Sin = Opp / Hyp
* Cos = Adj / Hyp
* Tan = Opp / Adj
*
* x = -Opp
* z = Adj
*/
final double x = loc.getX() - this.x;
final double z = loc.getZ() - this.z;
final double y = loc.getY() - this.y;
if (x == 0 && z == 0) {
return new ZLocation(worldName, this.x, this.y, this.z, this.yaw, y > 0 ? -90 : 90);
}
double x2 = NumberConversions.square(x);
double z2 = NumberConversions.square(z);
double xz = Math.sqrt(x2 + z2);
double theta = Math.atan2(-x, z);
float yaw = (float) Math.toDegrees((theta + _2PI) % _2PI);
float pitch = (float) Math.toDegrees(Math.atan(-y / xz));
return new ZLocation(worldName, this.x, this.y, this.z, yaw, pitch);
}
static class ZLocationSerializer implements JsonSerializer<ZLocation>, JsonDeserializer<ZLocation> {
public JsonElement serialize(ZLocation src, Type typeOfSrc, JsonSerializationContext context) {
JsonObject jsonObject = new JsonObject();
jsonObject.addProperty("world", src.getWorldName());
jsonObject.addProperty("x", src.getX());
jsonObject.addProperty("y", src.getY());
jsonObject.addProperty("z", src.getZ());
jsonObject.addProperty("yaw", src.getYaw());
jsonObject.addProperty("pitch", src.getPitch());
return jsonObject;
}
public ZLocation deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
JsonObject jsonObject = json.getAsJsonObject();
return new ZLocation(jsonObject.get("world").getAsString(), jsonObject
.get("x").getAsDouble(), jsonObject
.get("y").getAsDouble(), jsonObject
.get("z").getAsDouble(), jsonObject
.get("yaw").getAsFloat(), jsonObject
.get("pitch").getAsFloat());
}
}
}

@ -6,19 +6,14 @@ import com.github.retrooper.packetevents.protocol.entity.type.EntityTypes;
import com.google.gson.Gson; import com.google.gson.Gson;
import com.google.gson.GsonBuilder; import com.google.gson.GsonBuilder;
import io.github.retrooper.packetevents.factory.spigot.SpigotPacketEventsBuilder; import io.github.retrooper.packetevents.factory.spigot.SpigotPacketEventsBuilder;
import io.github.znetworkw.znpcservers.commands.list.DefaultCommand;
import io.github.znetworkw.znpcservers.configuration.Configuration; import io.github.znetworkw.znpcservers.configuration.Configuration;
import io.github.znetworkw.znpcservers.configuration.ConfigurationConstants; import io.github.znetworkw.znpcservers.configuration.ConfigurationConstants;
import io.github.znetworkw.znpcservers.listeners.InventoryListener; import io.github.znetworkw.znpcservers.listeners.InventoryListener;
import io.github.znetworkw.znpcservers.listeners.PlayerListener;
import io.github.znetworkw.znpcservers.npc.NPCPath;
import io.github.znetworkw.znpcservers.npc.interaction.InteractionPacketListener;
import io.github.znetworkw.znpcservers.user.ZUser;
import io.github.znetworkw.znpcservers.utility.BungeeUtils; import io.github.znetworkw.znpcservers.utility.BungeeUtils;
import io.github.znetworkw.znpcservers.utility.SchedulerUtils; import io.github.znetworkw.znpcservers.utility.SchedulerUtils;
import io.github.znetworkw.znpcservers.utility.itemstack.ItemStackSerializer; import io.github.znetworkw.znpcservers.utility.itemstack.ItemStackSerializer;
import io.github.znetworkw.znpcservers.utility.location.ZLocation;
import lol.pyr.znpcsplus.entity.PacketLocation; import lol.pyr.znpcsplus.entity.PacketLocation;
import lol.pyr.znpcsplus.interaction.InteractionPacketListener;
import lol.pyr.znpcsplus.npc.NPC; import lol.pyr.znpcsplus.npc.NPC;
import lol.pyr.znpcsplus.npc.NPCProperty; import lol.pyr.znpcsplus.npc.NPCProperty;
import lol.pyr.znpcsplus.npc.NPCRegistry; import lol.pyr.znpcsplus.npc.NPCRegistry;
@ -31,6 +26,8 @@ import lol.pyr.znpcsplus.skin.descriptor.PrefetchedDescriptor;
import lol.pyr.znpcsplus.tasks.NPCVisibilityTask; import lol.pyr.znpcsplus.tasks.NPCVisibilityTask;
import lol.pyr.znpcsplus.updater.UpdateChecker; import lol.pyr.znpcsplus.updater.UpdateChecker;
import lol.pyr.znpcsplus.updater.UpdateNotificationListener; import lol.pyr.znpcsplus.updater.UpdateNotificationListener;
import lol.pyr.znpcsplus.user.User;
import lol.pyr.znpcsplus.user.UserListener;
import net.kyori.adventure.platform.bukkit.BukkitAudiences; import net.kyori.adventure.platform.bukkit.BukkitAudiences;
import net.kyori.adventure.text.format.NamedTextColor; import net.kyori.adventure.text.format.NamedTextColor;
import org.apache.commons.io.FileUtils; import org.apache.commons.io.FileUtils;
@ -50,7 +47,6 @@ public class ZNPCsPlus extends JavaPlugin {
public static File PLUGIN_FOLDER; public static File PLUGIN_FOLDER;
public static File PATH_FOLDER; public static File PATH_FOLDER;
public static final Gson GSON = new GsonBuilder() public static final Gson GSON = new GsonBuilder()
.registerTypeAdapter(ZLocation.class, ZLocation.SERIALIZER)
.registerTypeHierarchyAdapter(ItemStack.class, new ItemStackSerializer()) .registerTypeHierarchyAdapter(ItemStack.class, new ItemStackSerializer())
.setPrettyPrinting() .setPrettyPrinting()
.disableHtmlEscaping() .disableHtmlEscaping()
@ -115,22 +111,18 @@ public class ZNPCsPlus extends JavaPlugin {
PLUGIN_FOLDER.mkdirs(); PLUGIN_FOLDER.mkdirs();
PATH_FOLDER.mkdirs(); PATH_FOLDER.mkdirs();
log(ChatColor.WHITE + " * Loading paths...");
loadAllPaths();
log(ChatColor.WHITE + " * Registering components..."); log(ChatColor.WHITE + " * Registering components...");
getServer().getMessenger().registerOutgoingPluginChannel(this, "BungeeCord"); getServer().getMessenger().registerOutgoingPluginChannel(this, "BungeeCord");
new Metrics(this, PLUGIN_ID); new Metrics(this, PLUGIN_ID);
new DefaultCommand();
SCHEDULER = new SchedulerUtils(this); SCHEDULER = new SchedulerUtils(this);
BUNGEE_UTILS = new BungeeUtils(this); BUNGEE_UTILS = new BungeeUtils(this);
Bukkit.getOnlinePlayers().forEach(ZUser::find); Bukkit.getOnlinePlayers().forEach(User::get);
log(ChatColor.WHITE + " * Starting tasks..."); log(ChatColor.WHITE + " * Starting tasks...");
new NPCVisibilityTask(this); new NPCVisibilityTask(this);
new PlayerListener(this);
new InventoryListener(this); new InventoryListener(this);
new SkinCacheCleanTask(this); new SkinCacheCleanTask(this);
new UserListener(this);
if (ConfigurationConstants.CHECK_FOR_UPDATES) new UpdateNotificationListener(this, new UpdateChecker(this)); if (ConfigurationConstants.CHECK_FOR_UPDATES) new UpdateNotificationListener(this, new UpdateChecker(this));
enabled = true; enabled = true;
@ -171,18 +163,9 @@ public class ZNPCsPlus extends JavaPlugin {
public void onDisable() { public void onDisable() {
if (!enabled) return; if (!enabled) return;
Configuration.SAVE_CONFIGURATIONS.forEach(Configuration::save); Configuration.SAVE_CONFIGURATIONS.forEach(Configuration::save);
Bukkit.getOnlinePlayers().forEach(ZUser::unregister); Bukkit.getOnlinePlayers().forEach(User::remove);
ADVENTURE.close(); ADVENTURE.close();
ADVENTURE = null; ADVENTURE = null;
} }
public void loadAllPaths() {
File[] files = PATH_FOLDER.listFiles();
if (files == null) return;
for (File file : files) {
if (!file.getName().endsWith(".path")) continue;
NPCPath.AbstractTypeWriter abstractTypeWriter = NPCPath.AbstractTypeWriter.forFile(file, NPCPath.AbstractTypeWriter.TypeWriter.MOVEMENT);
abstractTypeWriter.load();
}
}
} }

@ -1,15 +1,16 @@
package io.github.znetworkw.znpcservers.npc.interaction; package lol.pyr.znpcsplus.interaction;
import com.github.retrooper.packetevents.event.PacketListener; import com.github.retrooper.packetevents.event.PacketListener;
import com.github.retrooper.packetevents.event.PacketReceiveEvent; import com.github.retrooper.packetevents.event.PacketReceiveEvent;
import com.github.retrooper.packetevents.protocol.packettype.PacketType; import com.github.retrooper.packetevents.protocol.packettype.PacketType;
import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientInteractEntity; import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientInteractEntity;
import io.github.znetworkw.znpcservers.npc.NPC;
import io.github.znetworkw.znpcservers.npc.NPCAction;
import io.github.znetworkw.znpcservers.user.ZUser;
import lol.pyr.znpcsplus.ZNPCsPlus; import lol.pyr.znpcsplus.ZNPCsPlus;
import lol.pyr.znpcsplus.npc.NPC;
import lol.pyr.znpcsplus.npc.NPCRegistry;
import lol.pyr.znpcsplus.user.User;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.event.inventory.ClickType;
import java.util.List; import java.util.List;
@ -20,16 +21,12 @@ public class InteractionPacketListener implements PacketListener {
Player player = (Player) event.getPlayer(); Player player = (Player) event.getPlayer();
WrapperPlayClientInteractEntity packet = new WrapperPlayClientInteractEntity(event); WrapperPlayClientInteractEntity packet = new WrapperPlayClientInteractEntity(event);
ZUser user = ZUser.find(player); User user = User.get(player);
if (!user.canInteract()) return;
long lastInteract = System.nanoTime() - user.getLastInteract(); NPC npc = NPCRegistry.getByEntityId(packet.getEntityId());
if (user.getLastInteract() != 0L && lastInteract < 1000000000L) return;
NPC npc = NPC.all().stream().filter(n -> n.getEntityID() == packet.getEntityId()).findFirst().orElse(null);
if (npc == null) return; if (npc == null) return;
ClickType clickType = ClickType.forName(packet.getAction().name());
user.updateLastInteract();
ZNPCsPlus.SCHEDULER.runNextTick(() -> { ZNPCsPlus.SCHEDULER.runNextTick(() -> {
Bukkit.getServer().getPluginManager().callEvent(new NPCInteractEvent(player, clickType, npc)); Bukkit.getServer().getPluginManager().callEvent(new NPCInteractEvent(player, clickType, npc));
List<NPCAction> actions = npc.getNpcPojo().getClickActions(); List<NPCAction> actions = npc.getNpcPojo().getClickActions();

@ -12,6 +12,8 @@ import java.util.Map;
import java.util.Set; import java.util.Set;
public class NPC { public class NPC {
protected static final Set<NPC> _ALL_NPCS = new HashSet<>();
private final Set<Player> viewers = new HashSet<>(); private final Set<Player> viewers = new HashSet<>();
private final String worldName; private final String worldName;
private PacketEntity entity; private PacketEntity entity;
@ -25,6 +27,8 @@ public class NPC {
this.type = type; this.type = type;
this.location = location; this.location = location;
entity = new PacketEntity(this, type.getType(), location); entity = new PacketEntity(this, type.getType(), location);
_ALL_NPCS.add(this);
} }
public void setType(NPCType type) { public void setType(NPCType type) {
@ -56,6 +60,7 @@ public class NPC {
} }
public void delete() { public void delete() {
_ALL_NPCS.remove(this);
_hideAll(); _hideAll();
viewers.clear(); viewers.clear();
} }

@ -12,7 +12,15 @@ public class NPCRegistry {
} }
public static Collection<NPC> all() { public static Collection<NPC> all() {
return npcMap.values(); return NPC._ALL_NPCS;
}
public static NPC getByEntityId(int id) {
return all().stream().filter(npc -> npc.getEntity().getEntityId() == id).findFirst().orElse(null);
}
public static Collection<String> ids() {
return npcMap.keySet();
} }
public static void register(String id, NPC npc) { public static void register(String id, NPC npc) {

@ -0,0 +1,55 @@
package lol.pyr.znpcsplus.user;
import io.github.znetworkw.znpcservers.user.EventService;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import java.util.*;
public class User {
private final static Map<UUID, User> USER_MAP = new HashMap<>();
public static User get(Player player) {
return get(player.getUniqueId());
}
public static User get(UUID uuid) {
return USER_MAP.computeIfAbsent(uuid, User::new);
}
public static void remove(Player player) {
remove(player.getUniqueId());
}
public static void remove(UUID uuid) {
USER_MAP.remove(uuid);
}
private final UUID uuid;
private long lastNPCInteraction;
private final List<EventService<?>> eventServices = new ArrayList<>();
public User(UUID uuid) {
this.uuid = uuid;
}
public Player getPlayer() {
return Bukkit.getPlayer(uuid);
}
public boolean canInteract() {
if (System.currentTimeMillis() - lastNPCInteraction > 1000L) {
lastNPCInteraction = System.currentTimeMillis();
return true;
}
return false;
}
public List<EventService<?>> getEventServices() {
return eventServices;
}
public UUID getUuid() {
return uuid;
}
}

@ -0,0 +1,38 @@
package lol.pyr.znpcsplus.user;
import io.github.znetworkw.znpcservers.user.EventService;
import lol.pyr.znpcsplus.ZNPCsPlus;
import org.bukkit.Bukkit;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.player.AsyncPlayerChatEvent;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerQuitEvent;
public class UserListener implements Listener {
public UserListener(ZNPCsPlus plugin) {
Bukkit.getPluginManager().registerEvents(this, plugin);
}
@EventHandler
public void onJoin(PlayerJoinEvent event) {
User.get(event.getPlayer());
}
@EventHandler
public void onQuit(PlayerQuitEvent event) {
User.remove(event.getPlayer().getUniqueId());
}
@EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR)
public void onTalk(AsyncPlayerChatEvent event) {
User zUser = User.get(event.getPlayer());
if (EventService.hasService(zUser, AsyncPlayerChatEvent.class)) {
event.setCancelled(true);
EventService<AsyncPlayerChatEvent> eventService = EventService.findService(zUser, AsyncPlayerChatEvent.class);
eventService.runAll(event);
zUser.getEventServices().remove(eventService);
}
}
}