ZNPCsPlus/plugin/src/main/java/lol/pyr/znpcsplus/ZNpcsPlus.java

323 lines
18 KiB
Java
Raw Normal View History

2023-04-17 16:15:50 +00:00
package lol.pyr.znpcsplus;
import com.github.retrooper.packetevents.PacketEvents;
import com.github.retrooper.packetevents.PacketEventsAPI;
import com.github.retrooper.packetevents.event.PacketListenerPriority;
import com.github.retrooper.packetevents.manager.server.ServerVersion;
import io.github.retrooper.packetevents.factory.spigot.SpigotPacketEventsBuilder;
import lol.pyr.director.adventure.command.CommandContext;
import lol.pyr.director.adventure.command.CommandManager;
2023-05-04 04:07:07 +00:00
import lol.pyr.director.adventure.command.MultiCommand;
2023-05-11 04:41:15 +00:00
import lol.pyr.director.adventure.parse.primitive.BooleanParser;
2023-05-21 04:10:01 +00:00
import lol.pyr.director.adventure.parse.primitive.DoubleParser;
2023-05-10 15:01:14 +00:00
import lol.pyr.director.adventure.parse.primitive.IntegerParser;
import lol.pyr.director.common.message.Message;
2023-05-21 12:45:43 +00:00
import lol.pyr.znpcsplus.api.NpcApiProvider;
2023-05-28 05:32:00 +00:00
import lol.pyr.znpcsplus.api.interaction.InteractionType;
2023-05-09 10:47:43 +00:00
import lol.pyr.znpcsplus.commands.*;
2023-05-21 11:33:45 +00:00
import lol.pyr.znpcsplus.commands.action.ActionAddCommand;
import lol.pyr.znpcsplus.commands.action.ActionDeleteCommand;
2023-05-28 05:32:00 +00:00
import lol.pyr.znpcsplus.commands.action.ActionEditCommand;
2023-05-21 11:33:45 +00:00
import lol.pyr.znpcsplus.commands.action.ActionListCommand;
2023-05-10 13:43:05 +00:00
import lol.pyr.znpcsplus.commands.hologram.*;
2023-06-27 22:31:47 +00:00
import lol.pyr.znpcsplus.commands.property.PropertyRemoveCommand;
import lol.pyr.znpcsplus.commands.property.PropertySetCommand;
2023-06-18 17:33:47 +00:00
import lol.pyr.znpcsplus.commands.storage.ImportCommand;
2023-05-12 07:28:10 +00:00
import lol.pyr.znpcsplus.commands.storage.LoadAllCommand;
import lol.pyr.znpcsplus.commands.storage.SaveAllCommand;
import lol.pyr.znpcsplus.config.ConfigManager;
2023-06-18 17:33:47 +00:00
import lol.pyr.znpcsplus.conversion.DataImporterRegistry;
2023-05-10 13:43:05 +00:00
import lol.pyr.znpcsplus.entity.EntityPropertyImpl;
2023-05-21 15:41:38 +00:00
import lol.pyr.znpcsplus.entity.EntityPropertyRegistryImpl;
import lol.pyr.znpcsplus.interaction.ActionRegistry;
import lol.pyr.znpcsplus.interaction.InteractionPacketListener;
2023-05-21 12:45:43 +00:00
import lol.pyr.znpcsplus.npc.*;
import lol.pyr.znpcsplus.packets.PacketFactory;
import lol.pyr.znpcsplus.packets.V1_17PacketFactory;
import lol.pyr.znpcsplus.packets.V1_19PacketFactory;
import lol.pyr.znpcsplus.packets.V1_8PacketFactory;
2023-05-24 14:07:55 +00:00
import lol.pyr.znpcsplus.parsers.*;
2023-04-29 18:42:04 +00:00
import lol.pyr.znpcsplus.scheduling.FoliaScheduler;
import lol.pyr.znpcsplus.scheduling.SpigotScheduler;
import lol.pyr.znpcsplus.scheduling.TaskScheduler;
2023-06-30 22:14:23 +00:00
import lol.pyr.znpcsplus.skin.cache.MojangSkinCache;
import lol.pyr.znpcsplus.skin.cache.SkinCacheCleanTask;
2023-06-26 20:00:23 +00:00
import lol.pyr.znpcsplus.tasks.HologramRefreshTask;
2023-05-24 20:47:30 +00:00
import lol.pyr.znpcsplus.tasks.NpcProcessorTask;
import lol.pyr.znpcsplus.updater.UpdateChecker;
import lol.pyr.znpcsplus.updater.UpdateNotificationListener;
import lol.pyr.znpcsplus.user.UserListener;
import lol.pyr.znpcsplus.user.UserManager;
2023-06-13 21:57:43 +00:00
import lol.pyr.znpcsplus.util.*;
import net.kyori.adventure.platform.bukkit.BukkitAudiences;
2023-04-26 17:50:40 +00:00
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor;
2023-06-28 00:52:55 +00:00
import net.kyori.adventure.text.format.TextColor;
2023-06-13 21:57:43 +00:00
import net.kyori.adventure.text.minimessage.MiniMessage;
2023-05-11 06:27:28 +00:00
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
2023-04-17 17:36:19 +00:00
import org.bstats.bukkit.Metrics;
2023-06-26 10:51:48 +00:00
import org.bukkit.*;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.PluginManager;
2023-04-17 16:15:50 +00:00
import org.bukkit.plugin.java.JavaPlugin;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.Reader;
import java.nio.file.Files;
import java.nio.file.StandardOpenOption;
2023-05-21 11:33:45 +00:00
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
2023-05-21 11:33:45 +00:00
import java.util.List;
2023-04-17 16:15:50 +00:00
2023-05-21 11:33:45 +00:00
public class ZNpcsPlus extends JavaPlugin {
private final LegacyComponentSerializer textSerializer = LegacyComponentSerializer.builder()
2023-05-11 06:27:28 +00:00
.character('&')
.hexCharacter('#')
.hexColors().build();
2023-04-17 16:15:50 +00:00
2023-05-21 11:33:45 +00:00
private final List<Runnable> shutdownTasks = new ArrayList<>();
private PacketEventsAPI<Plugin> packetEvents;
2023-04-26 17:50:40 +00:00
@Override
public void onLoad() {
packetEvents = SpigotPacketEventsBuilder.build(this);
PacketEvents.setAPI(packetEvents);
packetEvents.getSettings().checkForUpdates(false);
packetEvents.load();
}
private void log(String str) {
Bukkit.getConsoleSender().sendMessage(str);
}
@Override
2023-04-17 16:15:50 +00:00
public void onEnable() {
getDataFolder().mkdirs();
log(ChatColor.YELLOW + " ___ __ __ __");
log(ChatColor.YELLOW + " _/ |\\ | |__) | (__` " + ChatColor.GOLD + "__|__ " + ChatColor.YELLOW + getDescription().getName() + " " + ChatColor.GOLD + "v" + getDescription().getVersion());
log(ChatColor.YELLOW + " /__ | \\| | |__ .__) " + ChatColor.GOLD + " | " + ChatColor.GRAY + "Maintained with " + ChatColor.RED + "\u2764 " + ChatColor.GRAY + " by Pyr#6969");
log("");
PluginManager pluginManager = Bukkit.getPluginManager();
long before = System.currentTimeMillis();
boolean legacy = new File(getDataFolder(), "data.json").isFile() && !new File(getDataFolder(), "data").isDirectory();
if (legacy) try {
Files.move(getDataFolder().toPath(), new File(getDataFolder().getParentFile(), "ZNPCsPlusLegacy").toPath());
} catch (IOException e) {
log(ChatColor.RED + " * Moving legacy files to subfolder failed, plugin will shut down.");
e.printStackTrace();
pluginManager.disablePlugin(this);
return;
}
2023-05-21 11:33:45 +00:00
log(ChatColor.WHITE + " * Initializing libraries...");
2023-05-21 11:33:45 +00:00
packetEvents.init();
2023-05-21 11:33:45 +00:00
BukkitAudiences adventure = BukkitAudiences.create(this);
shutdownTasks.add(adventure::close);
2023-05-21 11:33:45 +00:00
log(ChatColor.WHITE + " * Initializing components...");
2023-05-21 11:33:45 +00:00
TaskScheduler scheduler = FoliaUtil.isFolia() ? new FoliaScheduler(this) : new SpigotScheduler(this);
shutdownTasks.add(scheduler::cancelAll);
ConfigManager configManager = new ConfigManager(getDataFolder());
2023-06-30 22:14:23 +00:00
MojangSkinCache skinCache = new MojangSkinCache(configManager);
2023-05-21 15:41:38 +00:00
EntityPropertyRegistryImpl propertyRegistry = new EntityPropertyRegistryImpl(skinCache);
PacketFactory packetFactory = setupPacketFactory(scheduler, propertyRegistry);
propertyRegistry.registerTypes(packetFactory);
2023-05-21 13:25:21 +00:00
BungeeConnector bungeeConnector = new BungeeConnector(this);
2023-05-21 11:33:45 +00:00
ActionRegistry actionRegistry = new ActionRegistry();
2023-05-21 15:41:38 +00:00
NpcTypeRegistryImpl typeRegistry = new NpcTypeRegistryImpl();
2023-06-18 17:33:47 +00:00
NpcRegistryImpl npcRegistry = new NpcRegistryImpl(configManager, this, packetFactory, actionRegistry,
scheduler, typeRegistry, propertyRegistry, textSerializer);
shutdownTasks.add(npcRegistry::unload);
2023-05-21 11:33:45 +00:00
UserManager userManager = new UserManager();
shutdownTasks.add(userManager::shutdown);
2023-06-18 17:33:47 +00:00
DataImporterRegistry importerRegistry = new DataImporterRegistry(configManager, adventure, bungeeConnector,
scheduler, packetFactory, textSerializer, typeRegistry, getDataFolder().getParentFile(),
propertyRegistry, skinCache);
2023-05-21 11:33:45 +00:00
2023-05-21 11:53:48 +00:00
log(ChatColor.WHITE + " * Registerring components...");
2023-05-21 13:25:21 +00:00
typeRegistry.registerDefault(packetEvents, propertyRegistry);
2023-05-28 05:32:00 +00:00
actionRegistry.registerTypes(scheduler, adventure, bungeeConnector, textSerializer);
2023-05-21 11:33:45 +00:00
packetEvents.getEventManager().registerListener(new InteractionPacketListener(userManager, npcRegistry), PacketListenerPriority.MONITOR);
new Metrics(this, 18244);
pluginManager.registerEvents(new UserListener(userManager), this);
2023-05-21 11:33:45 +00:00
getServer().getMessenger().registerOutgoingPluginChannel(this, "BungeeCord");
2023-06-13 21:57:43 +00:00
2023-06-26 15:32:14 +00:00
registerCommands(npcRegistry, skinCache, adventure, actionRegistry,
typeRegistry, propertyRegistry, importerRegistry, configManager);
2023-05-21 11:33:45 +00:00
log(ChatColor.WHITE + " * Starting tasks...");
if (configManager.getConfig().checkForUpdates()) {
UpdateChecker updateChecker = new UpdateChecker(this.getDescription());
scheduler.runDelayedTimerAsync(updateChecker, 5L, 6000L);
pluginManager.registerEvents(new UpdateNotificationListener(this, adventure, updateChecker), this);
}
2023-05-24 20:47:30 +00:00
scheduler.runDelayedTimerAsync(new NpcProcessorTask(npcRegistry, configManager, propertyRegistry), 60L, 3L);
2023-06-26 20:00:23 +00:00
scheduler.runDelayedTimerAsync(new HologramRefreshTask(npcRegistry), 60L, 20L);
scheduler.runDelayedTimerAsync(new SkinCacheCleanTask(skinCache), 1200, 1200);
2023-05-21 11:33:45 +00:00
log(ChatColor.WHITE + " * Loading data...");
npcRegistry.reload();
if (configManager.getConfig().autoSaveEnabled()) shutdownTasks.add(npcRegistry::save);
if (legacy) {
log(ChatColor.WHITE + " * Converting legacy data...");
try {
Collection<NpcEntryImpl> entries = importerRegistry.getImporter("znpcsplus_legacy").importData();
npcRegistry.registerAll(entries);
} catch (Exception exception) {
log(ChatColor.RED + " * Legacy data conversion failed! Check conversion.log for more info.");
try (PrintWriter writer = new PrintWriter(Files.newBufferedWriter(new File(getDataFolder(), "conversion.log").toPath(), StandardOpenOption.CREATE_NEW))) {
exception.printStackTrace(writer);
} catch (IOException e) {
log(ChatColor.DARK_RED + " * Critical error! Writing to conversion.log failed.");
e.printStackTrace();
}
}
}
2023-06-23 21:12:24 +00:00
NpcApiProvider.register(this, new ZNpcsPlusApi(npcRegistry, typeRegistry, propertyRegistry, skinCache));
log(ChatColor.WHITE + " * Loading complete! (" + (System.currentTimeMillis() - before) + "ms)");
log("");
2023-04-24 16:12:50 +00:00
if (configManager.getConfig().debugEnabled()) {
2023-04-24 16:12:50 +00:00
World world = Bukkit.getWorld("world");
if (world == null) world = Bukkit.getWorlds().get(0);
int i = 0;
2023-06-18 22:20:18 +00:00
for (NpcTypeImpl type : typeRegistry.getAllImpl()) {
2023-05-21 12:45:43 +00:00
NpcEntryImpl entry = npcRegistry.create("debug_npc_" + i, world, type, new NpcLocation(i * 3, 200, 0, 0, 0));
2023-05-04 04:07:07 +00:00
entry.setProcessed(true);
2023-05-04 07:25:05 +00:00
NpcImpl npc = entry.getNpc();
2023-08-05 04:01:00 +00:00
npc.getHologram().addTextLineComponent(Component.text("Hello, World!", TextColor.color(255, 0, 0)));
npc.getHologram().addTextLineComponent(Component.text("Hello, World!", TextColor.color(0, 255, 0)));
npc.getHologram().addTextLineComponent(Component.text("Hello, World!", TextColor.color(0, 0, 255)));
i++;
2023-04-24 16:12:50 +00:00
}
}
2023-04-17 16:15:50 +00:00
}
2023-05-21 11:33:45 +00:00
@Override
public void onDisable() {
2023-05-21 12:45:43 +00:00
NpcApiProvider.unregister();
2023-05-21 11:33:45 +00:00
for (Runnable runnable : shutdownTasks) runnable.run();
2023-08-05 04:01:00 +00:00
shutdownTasks.clear();
PacketEvents.getAPI().terminate();
2023-05-21 11:33:45 +00:00
}
private PacketFactory setupPacketFactory(TaskScheduler scheduler, EntityPropertyRegistryImpl propertyRegistry) {
HashMap<ServerVersion, LazyLoader<? extends PacketFactory>> versions = new HashMap<>();
versions.put(ServerVersion.V_1_8, LazyLoader.of(() -> new V1_8PacketFactory(scheduler, packetEvents, propertyRegistry, textSerializer)));
versions.put(ServerVersion.V_1_17, LazyLoader.of(() -> new V1_17PacketFactory(scheduler, packetEvents, propertyRegistry, textSerializer)));
versions.put(ServerVersion.V_1_19, LazyLoader.of(() -> new V1_19PacketFactory(scheduler, packetEvents, propertyRegistry, textSerializer)));
ServerVersion version = packetEvents.getServerManager().getVersion();
if (versions.containsKey(version)) return versions.get(version).get();
for (ServerVersion v : ServerVersion.reversedValues()) {
if (v.isNewerThan(version)) continue;
if (!versions.containsKey(v)) continue;
return versions.get(v).get();
}
throw new RuntimeException("Unsupported version!");
}
2023-06-30 22:14:23 +00:00
private void registerCommands(NpcRegistryImpl npcRegistry, MojangSkinCache skinCache, BukkitAudiences adventure,
2023-06-18 17:33:47 +00:00
ActionRegistry actionRegistry, NpcTypeRegistryImpl typeRegistry,
2023-06-26 15:32:14 +00:00
EntityPropertyRegistryImpl propertyRegistry, DataImporterRegistry importerRegistry,
ConfigManager configManager) {
2023-06-18 17:33:47 +00:00
2023-05-21 11:33:45 +00:00
Message<CommandContext> incorrectUsageMessage = context -> context.send(Component.text("Incorrect usage: /" + context.getUsage(), NamedTextColor.RED));
CommandManager manager = new CommandManager(this, adventure, incorrectUsageMessage);
2023-05-21 12:45:43 +00:00
manager.registerParser(NpcTypeImpl.class, new NpcTypeParser(incorrectUsageMessage, typeRegistry));
manager.registerParser(NpcEntryImpl.class, new NpcEntryParser(npcRegistry, incorrectUsageMessage));
2023-05-21 13:25:21 +00:00
manager.registerParser(EntityPropertyImpl.class, new EntityPropertyParser(incorrectUsageMessage, propertyRegistry));
manager.registerParser(Integer.class, new IntegerParser(incorrectUsageMessage));
manager.registerParser(Double.class, new DoubleParser(incorrectUsageMessage));
manager.registerParser(Boolean.class, new BooleanParser(incorrectUsageMessage));
manager.registerParser(NamedTextColor.class, new NamedTextColorParser(incorrectUsageMessage));
2023-05-24 14:07:55 +00:00
manager.registerParser(InteractionType.class, new InteractionTypeParser(incorrectUsageMessage));
2023-06-26 10:51:48 +00:00
manager.registerParser(Color.class, new ColorParser(incorrectUsageMessage));
2023-06-27 12:06:42 +00:00
manager.registerParser(Vector3f.class, new Vector3fParser(incorrectUsageMessage));
2023-05-10 15:01:14 +00:00
2023-08-22 21:27:18 +00:00
// TODO: Need to find a better way to do this
registerEnumParser(manager, NpcPose.class, incorrectUsageMessage);
registerEnumParser(manager, DyeColor.class, incorrectUsageMessage);
2023-06-28 13:02:16 +00:00
registerEnumParser(manager, CatVariant.class, incorrectUsageMessage);
2023-06-28 13:28:09 +00:00
registerEnumParser(manager, CreeperState.class, incorrectUsageMessage);
2023-07-02 05:21:54 +00:00
registerEnumParser(manager, ParrotVariant.class, incorrectUsageMessage);
2023-07-03 05:48:33 +00:00
registerEnumParser(manager, SpellType.class, incorrectUsageMessage);
2023-07-03 06:07:56 +00:00
registerEnumParser(manager, FoxVariant.class, incorrectUsageMessage);
2023-07-03 06:16:55 +00:00
registerEnumParser(manager, FrogVariant.class, incorrectUsageMessage);
2023-07-05 11:53:30 +00:00
registerEnumParser(manager, VillagerType.class, incorrectUsageMessage);
registerEnumParser(manager, VillagerProfession.class, incorrectUsageMessage);
registerEnumParser(manager, VillagerLevel.class, incorrectUsageMessage);
2023-08-21 14:39:47 +00:00
registerEnumParser(manager, AxolotlVariant.class, incorrectUsageMessage);
2023-08-22 21:27:18 +00:00
registerEnumParser(manager, HorseType.class, incorrectUsageMessage);
registerEnumParser(manager, HorseStyle.class, incorrectUsageMessage);
registerEnumParser(manager, HorseColor.class, incorrectUsageMessage);
registerEnumParser(manager, HorseArmor.class, incorrectUsageMessage);
2023-09-10 11:15:39 +00:00
registerEnumParser(manager, LlamaVariant.class, incorrectUsageMessage);
2023-06-14 13:30:43 +00:00
manager.registerCommand("npc", new MultiCommand(loadHelpMessage("root"))
2023-05-21 12:45:43 +00:00
.addSubcommand("create", new CreateCommand(npcRegistry, typeRegistry))
2023-06-26 15:32:14 +00:00
.addSubcommand("reloadconfig", new ReloadConfigCommand(configManager))
2023-06-19 13:29:34 +00:00
.addSubcommand("toggle", new ToggleCommand(npcRegistry))
2023-05-21 13:25:21 +00:00
.addSubcommand("skin", new SkinCommand(skinCache, npcRegistry, typeRegistry, propertyRegistry))
.addSubcommand("delete", new DeleteCommand(npcRegistry, adventure))
.addSubcommand("move", new MoveCommand(npcRegistry))
.addSubcommand("teleport", new TeleportCommand(npcRegistry))
.addSubcommand("list", new ListCommand(npcRegistry))
.addSubcommand("near", new NearCommand(npcRegistry))
2023-05-21 12:45:43 +00:00
.addSubcommand("type", new TypeCommand(npcRegistry, typeRegistry))
2023-06-27 22:31:47 +00:00
.addSubcommand("property", new MultiCommand(loadHelpMessage("property"))
.addSubcommand("set", new PropertySetCommand(npcRegistry))
.addSubcommand("remove", new PropertyRemoveCommand(npcRegistry)))
2023-06-14 13:30:43 +00:00
.addSubcommand("storage", new MultiCommand(loadHelpMessage("storage"))
.addSubcommand("save", new SaveAllCommand(npcRegistry))
2023-06-18 17:33:47 +00:00
.addSubcommand("reload", new LoadAllCommand(npcRegistry))
.addSubcommand("import", new ImportCommand(npcRegistry, importerRegistry)))
2023-06-14 13:30:43 +00:00
.addSubcommand("holo", new MultiCommand(loadHelpMessage("holo"))
2023-08-05 04:01:00 +00:00
.addSubcommand("add", new HoloAddCommand(npcRegistry))
.addSubcommand("additem", new HoloAddItemCommand(npcRegistry))
.addSubcommand("delete", new HoloDeleteCommand(npcRegistry))
.addSubcommand("info", new HoloInfoCommand(npcRegistry))
2023-08-05 04:01:00 +00:00
.addSubcommand("insert", new HoloInsertCommand(npcRegistry))
.addSubcommand("insertitem", new HoloInsertItemCommand(npcRegistry))
.addSubcommand("set", new HoloSetCommand(npcRegistry))
.addSubcommand("setitem", new HoloSetItemCommand(npcRegistry))
2023-06-26 20:00:23 +00:00
.addSubcommand("offset", new HoloOffsetCommand(npcRegistry))
.addSubcommand("refreshdelay", new HoloRefreshDelayCommand(npcRegistry)))
2023-06-14 13:30:43 +00:00
.addSubcommand("action", new MultiCommand(loadHelpMessage("action"))
2023-05-28 05:32:00 +00:00
.addSubcommand("add", new ActionAddCommand(npcRegistry, actionRegistry))
2023-05-21 11:33:45 +00:00
.addSubcommand("delete", new ActionDeleteCommand(npcRegistry))
2023-05-28 05:32:00 +00:00
.addSubcommand("edit", new ActionEditCommand(npcRegistry, actionRegistry))
2023-06-07 10:25:04 +00:00
.addSubcommand("list", new ActionListCommand(npcRegistry)))
2023-05-09 10:47:43 +00:00
);
}
2023-06-14 13:30:43 +00:00
private <T extends Enum<T>> void registerEnumParser(CommandManager manager, Class<T> clazz, Message<CommandContext> message) {
manager.registerParser(clazz, new EnumParser<>(clazz, message));
}
2023-06-14 13:30:43 +00:00
private Message<CommandContext> loadHelpMessage(String name) {
Reader reader = getTextResource("help-messages/" + name + ".txt");
if (reader == null) throw new RuntimeException(name + ".txt is missing from the help-messages folder in the ZNPCsPlus jar!");
Component component = MiniMessage.miniMessage().deserialize(FileUtil.dumpReaderAsString(reader));
return context -> context.send(component);
}
2023-04-17 16:15:50 +00:00
}