2017-12-30 08:36:36 +01:00
|
|
|
package net.citizensnpcs;
|
|
|
|
|
2018-06-07 10:59:52 +02:00
|
|
|
import java.io.File;
|
2021-02-04 03:10:48 +01:00
|
|
|
import java.util.Arrays;
|
2018-06-07 10:59:52 +02:00
|
|
|
import java.util.Iterator;
|
2020-07-18 15:10:55 +02:00
|
|
|
import java.util.List;
|
2018-06-07 10:59:52 +02:00
|
|
|
import java.util.Locale;
|
|
|
|
import java.util.Map;
|
2019-02-10 05:17:15 +01:00
|
|
|
import java.util.UUID;
|
2023-02-26 08:51:59 +01:00
|
|
|
import java.util.regex.Pattern;
|
2018-06-07 10:59:52 +02:00
|
|
|
|
|
|
|
import org.bukkit.Bukkit;
|
2023-01-05 13:05:15 +01:00
|
|
|
import org.bukkit.OfflinePlayer;
|
|
|
|
import org.bukkit.command.BlockCommandSender;
|
2018-06-07 10:59:52 +02:00
|
|
|
import org.bukkit.command.CommandSender;
|
2023-01-05 13:05:15 +01:00
|
|
|
import org.bukkit.entity.Entity;
|
2022-06-11 19:37:38 +02:00
|
|
|
import org.bukkit.entity.Player;
|
2021-07-18 13:30:45 +02:00
|
|
|
import org.bukkit.event.HandlerList;
|
2022-06-11 19:37:38 +02:00
|
|
|
import org.bukkit.event.inventory.InventoryType;
|
2022-06-12 13:49:21 +02:00
|
|
|
import org.bukkit.inventory.Inventory;
|
2022-06-11 19:37:38 +02:00
|
|
|
import org.bukkit.inventory.InventoryView;
|
2019-02-05 11:12:02 +01:00
|
|
|
import org.bukkit.inventory.meta.SkullMeta;
|
2018-06-07 10:59:52 +02:00
|
|
|
import org.bukkit.plugin.Plugin;
|
|
|
|
import org.bukkit.plugin.RegisteredServiceProvider;
|
|
|
|
import org.bukkit.plugin.java.JavaPlugin;
|
|
|
|
|
2023-03-26 07:28:23 +02:00
|
|
|
import com.comphenix.protocol.ProtocolLibrary;
|
2017-12-30 08:36:36 +01:00
|
|
|
import com.google.common.collect.Iterables;
|
2020-07-18 15:18:53 +02:00
|
|
|
import com.google.common.collect.Lists;
|
2017-12-30 08:36:36 +01:00
|
|
|
import com.google.common.collect.Maps;
|
2019-02-05 11:12:02 +01:00
|
|
|
import com.mojang.authlib.GameProfile;
|
2018-06-07 10:59:52 +02:00
|
|
|
|
2023-06-11 10:51:28 +02:00
|
|
|
import ch.ethz.globis.phtree.PhTreeHelper;
|
2022-11-13 05:50:45 +01:00
|
|
|
import net.byteflux.libby.BukkitLibraryManager;
|
|
|
|
import net.byteflux.libby.Library;
|
2022-11-13 09:02:17 +01:00
|
|
|
import net.byteflux.libby.LibraryManager;
|
|
|
|
import net.byteflux.libby.logging.LogLevel;
|
2017-12-30 08:36:36 +01:00
|
|
|
import net.citizensnpcs.Settings.Setting;
|
|
|
|
import net.citizensnpcs.api.CitizensAPI;
|
|
|
|
import net.citizensnpcs.api.CitizensPlugin;
|
2022-12-03 14:32:58 +01:00
|
|
|
import net.citizensnpcs.api.LocationLookup;
|
2023-01-05 13:05:15 +01:00
|
|
|
import net.citizensnpcs.api.NMSHelper;
|
2023-04-20 17:42:48 +02:00
|
|
|
import net.citizensnpcs.api.ai.speech.SpeechContext;
|
2017-12-30 08:36:36 +01:00
|
|
|
import net.citizensnpcs.api.command.CommandManager;
|
|
|
|
import net.citizensnpcs.api.command.Injector;
|
2018-06-07 10:59:52 +02:00
|
|
|
import net.citizensnpcs.api.event.CitizensDisableEvent;
|
|
|
|
import net.citizensnpcs.api.event.CitizensEnableEvent;
|
|
|
|
import net.citizensnpcs.api.event.CitizensPreReloadEvent;
|
|
|
|
import net.citizensnpcs.api.event.CitizensReloadEvent;
|
|
|
|
import net.citizensnpcs.api.event.DespawnReason;
|
2017-12-30 08:36:36 +01:00
|
|
|
import net.citizensnpcs.api.exception.NPCLoadException;
|
2023-04-25 17:11:20 +02:00
|
|
|
import net.citizensnpcs.api.npc.NPC;
|
2017-12-30 08:36:36 +01:00
|
|
|
import net.citizensnpcs.api.npc.NPCDataStore;
|
|
|
|
import net.citizensnpcs.api.npc.NPCRegistry;
|
|
|
|
import net.citizensnpcs.api.npc.SimpleNPCDataStore;
|
|
|
|
import net.citizensnpcs.api.scripting.EventRegistrar;
|
|
|
|
import net.citizensnpcs.api.scripting.ObjectProvider;
|
|
|
|
import net.citizensnpcs.api.scripting.ScriptCompiler;
|
2023-04-25 17:11:20 +02:00
|
|
|
import net.citizensnpcs.api.trait.Trait;
|
2017-12-30 08:36:36 +01:00
|
|
|
import net.citizensnpcs.api.trait.TraitFactory;
|
2022-12-03 14:32:58 +01:00
|
|
|
import net.citizensnpcs.api.trait.TraitInfo;
|
2018-06-07 10:59:52 +02:00
|
|
|
import net.citizensnpcs.api.util.Messaging;
|
2023-02-26 08:51:59 +01:00
|
|
|
import net.citizensnpcs.api.util.Placeholders;
|
2023-10-01 11:27:38 +02:00
|
|
|
import net.citizensnpcs.api.util.SpigotUtil;
|
2018-06-07 10:59:52 +02:00
|
|
|
import net.citizensnpcs.api.util.Storage;
|
|
|
|
import net.citizensnpcs.api.util.Translator;
|
|
|
|
import net.citizensnpcs.api.util.YamlStorage;
|
|
|
|
import net.citizensnpcs.commands.AdminCommands;
|
|
|
|
import net.citizensnpcs.commands.EditorCommands;
|
|
|
|
import net.citizensnpcs.commands.NPCCommands;
|
|
|
|
import net.citizensnpcs.commands.TemplateCommands;
|
|
|
|
import net.citizensnpcs.commands.TraitCommands;
|
|
|
|
import net.citizensnpcs.commands.WaypointCommands;
|
2017-12-30 08:36:36 +01:00
|
|
|
import net.citizensnpcs.editor.Editor;
|
|
|
|
import net.citizensnpcs.npc.CitizensNPCRegistry;
|
|
|
|
import net.citizensnpcs.npc.CitizensTraitFactory;
|
|
|
|
import net.citizensnpcs.npc.NPCSelector;
|
2022-12-11 14:28:39 +01:00
|
|
|
import net.citizensnpcs.npc.Template;
|
2017-12-30 08:36:36 +01:00
|
|
|
import net.citizensnpcs.npc.profile.ProfileFetcher;
|
|
|
|
import net.citizensnpcs.npc.skin.Skin;
|
2023-02-26 08:51:59 +01:00
|
|
|
import net.citizensnpcs.trait.ClickRedirectTrait;
|
|
|
|
import net.citizensnpcs.trait.CommandTrait;
|
2022-07-26 17:50:28 +02:00
|
|
|
import net.citizensnpcs.trait.ShopTrait;
|
2018-06-07 10:59:52 +02:00
|
|
|
import net.citizensnpcs.util.Messages;
|
|
|
|
import net.citizensnpcs.util.NMS;
|
|
|
|
import net.citizensnpcs.util.PlayerUpdateTask;
|
2023-10-01 11:27:38 +02:00
|
|
|
import net.citizensnpcs.util.SkinProperty;
|
2018-06-07 10:59:52 +02:00
|
|
|
import net.citizensnpcs.util.Util;
|
2017-12-30 08:36:36 +01:00
|
|
|
import net.milkbowl.vault.economy.Economy;
|
|
|
|
|
|
|
|
public class Citizens extends JavaPlugin implements CitizensPlugin {
|
2020-07-18 15:18:53 +02:00
|
|
|
private final List<NPCRegistry> anonymousRegistries = Lists.newArrayList();
|
2021-02-04 03:10:48 +01:00
|
|
|
private final List<NPCRegistry> citizensBackedRegistries = Lists.newArrayList();
|
2017-12-30 08:36:36 +01:00
|
|
|
private final CommandManager commands = new CommandManager();
|
|
|
|
private Settings config;
|
2021-07-15 13:41:03 +02:00
|
|
|
private boolean enabled;
|
2023-01-05 13:05:15 +01:00
|
|
|
private LocationLookup locationLookup;
|
|
|
|
private final NMSHelper nmsHelper = new NMSHelper() {
|
|
|
|
private boolean SUPPORT_OWNER_PROFILE = true;
|
2022-06-12 13:49:21 +02:00
|
|
|
|
2022-06-11 19:37:38 +02:00
|
|
|
@Override
|
2023-01-05 13:05:15 +01:00
|
|
|
public OfflinePlayer getPlayer(BlockCommandSender sender) {
|
|
|
|
Entity entity = NMS.getSource(sender);
|
2023-11-05 13:58:37 +01:00
|
|
|
return entity instanceof OfflinePlayer ? (OfflinePlayer) entity : null;
|
2022-06-11 19:37:38 +02:00
|
|
|
}
|
2023-01-02 05:54:19 +01:00
|
|
|
|
2019-02-05 11:12:02 +01:00
|
|
|
@Override
|
|
|
|
public String getTexture(SkullMeta meta) {
|
2023-10-01 11:27:38 +02:00
|
|
|
SkinProperty sp = SkinProperty.fromMojangProfile(NMS.getProfile(meta));
|
|
|
|
return sp == null ? null : sp.value;
|
2019-02-05 11:12:02 +01:00
|
|
|
}
|
|
|
|
|
2023-01-05 13:05:15 +01:00
|
|
|
@Override
|
|
|
|
public InventoryView openAnvilInventory(Player player, Inventory inventory, String title) {
|
|
|
|
return NMS.openAnvilInventory(player, inventory, title);
|
|
|
|
}
|
|
|
|
|
2019-02-05 11:12:02 +01:00
|
|
|
@Override
|
2023-01-03 13:55:27 +01:00
|
|
|
public void setTexture(String texture, SkullMeta meta) {
|
2023-01-02 05:54:19 +01:00
|
|
|
GameProfile profile = NMS.getProfile(meta);
|
|
|
|
if (profile == null) {
|
|
|
|
if (SUPPORT_OWNER_PROFILE) {
|
|
|
|
try {
|
|
|
|
profile = new GameProfile(meta.getOwnerProfile().getUniqueId(),
|
|
|
|
meta.getOwnerProfile().getName());
|
|
|
|
} catch (Exception e) {
|
|
|
|
SUPPORT_OWNER_PROFILE = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (profile == null) {
|
|
|
|
profile = new GameProfile(UUID.randomUUID(), null);
|
|
|
|
}
|
|
|
|
}
|
2023-10-01 11:27:38 +02:00
|
|
|
profile.getProperties().put("textures",
|
|
|
|
new com.mojang.authlib.properties.Property("textures", texture, null));
|
2023-01-02 05:54:19 +01:00
|
|
|
NMS.setProfile(meta, profile);
|
2019-02-05 11:12:02 +01:00
|
|
|
}
|
2023-01-05 13:05:15 +01:00
|
|
|
|
|
|
|
@Override
|
|
|
|
public void updateInventoryTitle(Player player, InventoryView view, String newTitle) {
|
|
|
|
if (view.getTopInventory().getType() == InventoryType.CRAFTING
|
|
|
|
|| view.getTopInventory().getType() == InventoryType.CREATIVE
|
|
|
|
|| view.getTopInventory().getType() == InventoryType.PLAYER)
|
|
|
|
return;
|
|
|
|
NMS.updateInventoryTitle(player, view, newTitle);
|
|
|
|
}
|
2019-02-05 11:12:02 +01:00
|
|
|
};
|
2023-01-05 13:05:15 +01:00
|
|
|
private CitizensNPCRegistry npcRegistry;
|
|
|
|
private ProtocolLibListener protocolListener;
|
|
|
|
private boolean saveOnDisable = true;
|
|
|
|
private NPCDataStore saves;
|
|
|
|
private NPCSelector selector;
|
|
|
|
private StoredShops shops;
|
2017-12-30 08:36:36 +01:00
|
|
|
private final Map<String, NPCRegistry> storedRegistries = Maps.newHashMap();
|
|
|
|
private CitizensTraitFactory traitFactory;
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public NPCRegistry createAnonymousNPCRegistry(NPCDataStore store) {
|
2020-07-18 15:10:55 +02:00
|
|
|
CitizensNPCRegistry anon = new CitizensNPCRegistry(store, "anonymous-" + UUID.randomUUID().toString());
|
|
|
|
anonymousRegistries.add(anon);
|
|
|
|
return anon;
|
2017-12-30 08:36:36 +01:00
|
|
|
}
|
|
|
|
|
2021-02-04 03:10:48 +01:00
|
|
|
@Override
|
|
|
|
public NPCRegistry createCitizensBackedNPCRegistry(NPCDataStore store) {
|
|
|
|
CitizensNPCRegistry anon = new CitizensNPCRegistry(store, "anonymous-citizens-" + UUID.randomUUID().toString());
|
|
|
|
citizensBackedRegistries.add(anon);
|
|
|
|
return anon;
|
|
|
|
}
|
|
|
|
|
2017-12-30 08:36:36 +01:00
|
|
|
@Override
|
|
|
|
public NPCRegistry createNamedNPCRegistry(String name, NPCDataStore store) {
|
2020-07-17 03:52:00 +02:00
|
|
|
NPCRegistry created = new CitizensNPCRegistry(store, name);
|
2017-12-30 08:36:36 +01:00
|
|
|
storedRegistries.put(name, created);
|
|
|
|
return created;
|
|
|
|
}
|
|
|
|
|
|
|
|
private NPCDataStore createStorage(File folder) {
|
2024-02-10 18:13:49 +01:00
|
|
|
Storage saves = new YamlStorage(new File(folder, Setting.STORAGE_FILE.asString()), "Citizens NPC Storage");
|
2017-12-30 08:36:36 +01:00
|
|
|
if (!saves.load())
|
|
|
|
return null;
|
2023-10-28 20:09:08 +02:00
|
|
|
|
2017-12-30 08:36:36 +01:00
|
|
|
return SimpleNPCDataStore.create(saves);
|
|
|
|
}
|
|
|
|
|
2021-02-04 03:10:48 +01:00
|
|
|
private void despawnNPCs(boolean save) {
|
2022-03-09 20:17:27 +01:00
|
|
|
for (NPCRegistry registry : Iterables.concat(Arrays.asList(npcRegistry), citizensBackedRegistries)) {
|
2023-11-05 13:58:37 +01:00
|
|
|
if (registry == null) {
|
2022-03-09 20:17:27 +01:00
|
|
|
continue;
|
2023-11-05 13:58:37 +01:00
|
|
|
}
|
2021-02-04 03:10:48 +01:00
|
|
|
if (save) {
|
2022-12-03 11:21:46 +01:00
|
|
|
if (registry == npcRegistry) {
|
|
|
|
storeNPCs(false);
|
|
|
|
} else {
|
|
|
|
registry.saveToStore();
|
|
|
|
}
|
2017-12-30 08:36:36 +01:00
|
|
|
}
|
2022-03-09 20:17:27 +01:00
|
|
|
registry.despawnNPCs(DespawnReason.RELOAD);
|
2017-12-30 08:36:36 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-09-07 21:01:39 +02:00
|
|
|
@Override
|
|
|
|
public CommandManager getCommandManager() {
|
|
|
|
return commands;
|
2017-12-30 08:36:36 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public net.citizensnpcs.api.npc.NPCSelector getDefaultNPCSelector() {
|
|
|
|
return selector;
|
|
|
|
}
|
|
|
|
|
2022-12-03 14:32:58 +01:00
|
|
|
@Override
|
|
|
|
public LocationLookup getLocationLookup() {
|
|
|
|
return locationLookup;
|
|
|
|
}
|
|
|
|
|
2017-12-30 08:36:36 +01:00
|
|
|
@Override
|
|
|
|
public NPCRegistry getNamedNPCRegistry(String name) {
|
2020-07-17 03:52:00 +02:00
|
|
|
if (name.equals(npcRegistry.getName()))
|
|
|
|
return npcRegistry;
|
2017-12-30 08:36:36 +01:00
|
|
|
return storedRegistries.get(name);
|
|
|
|
}
|
|
|
|
|
2023-01-05 13:05:15 +01:00
|
|
|
@Override
|
|
|
|
public NMSHelper getNMSHelper() {
|
|
|
|
return nmsHelper;
|
|
|
|
}
|
|
|
|
|
2017-12-30 08:36:36 +01:00
|
|
|
@Override
|
|
|
|
public Iterable<NPCRegistry> getNPCRegistries() {
|
2023-11-05 13:58:37 +01:00
|
|
|
return () -> new Iterator<NPCRegistry>() {
|
|
|
|
Iterator<NPCRegistry> stored;
|
2017-12-30 08:36:36 +01:00
|
|
|
|
2023-11-05 13:58:37 +01:00
|
|
|
@Override
|
|
|
|
public boolean hasNext() {
|
|
|
|
return stored == null ? true : stored.hasNext();
|
|
|
|
}
|
2017-12-30 08:36:36 +01:00
|
|
|
|
2023-11-05 13:58:37 +01:00
|
|
|
@Override
|
|
|
|
public NPCRegistry next() {
|
|
|
|
if (stored == null) {
|
|
|
|
stored = Iterables.concat(storedRegistries.values(), anonymousRegistries, citizensBackedRegistries)
|
|
|
|
.iterator();
|
|
|
|
return npcRegistry;
|
|
|
|
}
|
|
|
|
return stored.next();
|
|
|
|
}
|
2017-12-30 08:36:36 +01:00
|
|
|
|
2023-11-05 13:58:37 +01:00
|
|
|
@Override
|
|
|
|
public void remove() {
|
|
|
|
throw new UnsupportedOperationException();
|
2017-12-30 08:36:36 +01:00
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public NPCRegistry getNPCRegistry() {
|
|
|
|
return npcRegistry;
|
|
|
|
}
|
|
|
|
|
|
|
|
public NPCSelector getNPCSelector() {
|
|
|
|
return selector;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public ClassLoader getOwningClassLoader() {
|
|
|
|
return getClassLoader();
|
|
|
|
}
|
|
|
|
|
2023-12-21 19:21:18 +01:00
|
|
|
public ProtocolLibListener getProtocolLibListener() {
|
|
|
|
return protocolListener;
|
|
|
|
}
|
|
|
|
|
2022-12-18 18:44:16 +01:00
|
|
|
public StoredShops getShops() {
|
|
|
|
return shops;
|
|
|
|
}
|
|
|
|
|
2017-12-30 08:36:36 +01:00
|
|
|
@Override
|
|
|
|
public TraitFactory getTraitFactory() {
|
|
|
|
return traitFactory;
|
|
|
|
}
|
|
|
|
|
2022-11-13 05:50:45 +01:00
|
|
|
private void loadMavenLibraries() {
|
2022-11-14 16:53:14 +01:00
|
|
|
getLogger().info("Loading external libraries");
|
2022-11-13 12:32:02 +01:00
|
|
|
|
2022-11-13 09:02:17 +01:00
|
|
|
LibraryManager lib = new BukkitLibraryManager(this);
|
2022-11-13 05:50:45 +01:00
|
|
|
lib.addMavenCentral();
|
2022-11-13 09:02:17 +01:00
|
|
|
lib.setLogLevel(LogLevel.WARN);
|
2022-11-13 05:50:45 +01:00
|
|
|
// Unfortunately, transitive dependency management is not supported in this library.
|
2023-11-17 17:50:35 +01:00
|
|
|
lib.loadLibrary(Library.builder().groupId("ch{}ethz{}globis{}phtree").artifactId("phtree").version("2.8.0")
|
2022-11-13 05:50:45 +01:00
|
|
|
.relocate("ch{}ethz{}globis{}phtree", "clib{}phtree").build());
|
|
|
|
lib.loadLibrary(Library.builder().groupId("net{}sf{}trove4j").artifactId("trove4j").version("3.0.3")
|
|
|
|
.relocate("gnu{}trove", "clib{}trove").build());
|
|
|
|
lib.loadLibrary(Library.builder().groupId("net{}kyori").artifactId("adventure-text-minimessage")
|
2023-12-21 19:21:18 +01:00
|
|
|
.version("4.15.0").relocate("net{}kyori", "clib{}net{}kyori").build());
|
|
|
|
lib.loadLibrary(Library.builder().groupId("net{}kyori").artifactId("adventure-api").version("4.15.0")
|
2022-11-13 05:50:45 +01:00
|
|
|
.relocate("net{}kyori", "clib{}net{}kyori").build());
|
2023-12-21 19:21:18 +01:00
|
|
|
lib.loadLibrary(Library.builder().groupId("net{}kyori").artifactId("adventure-key").version("4.15.0")
|
2022-11-13 05:50:45 +01:00
|
|
|
.relocate("net{}kyori", "clib{}net{}kyori").build());
|
2023-10-13 15:49:21 +02:00
|
|
|
lib.loadLibrary(Library.builder().groupId("net{}kyori").artifactId("examination-api").version("1.3.0")
|
2022-11-13 05:50:45 +01:00
|
|
|
.relocate("net{}kyori", "clib{}net{}kyori").build());
|
2023-10-13 15:49:21 +02:00
|
|
|
lib.loadLibrary(Library.builder().groupId("net{}kyori").artifactId("examination-string").version("1.3.0")
|
|
|
|
.relocate("net{}kyori", "clib{}net{}kyori").build());
|
2023-12-21 19:21:18 +01:00
|
|
|
lib.loadLibrary(Library.builder().groupId("net{}kyori").artifactId("adventure-platform-bukkit").version("4.3.2")
|
2023-10-13 15:49:21 +02:00
|
|
|
.relocate("net{}kyori", "clib{}net{}kyori").build());
|
2023-12-21 19:21:18 +01:00
|
|
|
lib.loadLibrary(Library.builder().groupId("net{}kyori").artifactId("adventure-platform-api").version("4.3.2")
|
2022-11-13 05:50:45 +01:00
|
|
|
.relocate("net{}kyori", "clib{}net{}kyori").build());
|
|
|
|
lib.loadLibrary(Library.builder().groupId("net{}kyori").artifactId("adventure-text-serializer-bungeecord")
|
2023-12-21 19:21:18 +01:00
|
|
|
.version("4.3.2").relocate("net{}kyori", "clib{}net{}kyori").build());
|
2022-11-13 05:50:45 +01:00
|
|
|
lib.loadLibrary(Library.builder().groupId("net{}kyori").artifactId("adventure-text-serializer-legacy")
|
2023-10-13 15:49:21 +02:00
|
|
|
.version("4.13.1").relocate("net{}kyori", "clib{}net{}kyori").build());
|
|
|
|
lib.loadLibrary(Library.builder().groupId("net{}kyori").artifactId("adventure-nbt").version("4.13.1")
|
|
|
|
.relocate("net{}kyori", "clib{}net{}kyori").build());
|
2022-11-13 05:50:45 +01:00
|
|
|
lib.loadLibrary(Library.builder().groupId("net{}kyori").artifactId("adventure-text-serializer-gson")
|
2023-10-13 15:49:21 +02:00
|
|
|
.version("4.13.1").relocate("net{}kyori", "clib{}net{}kyori").build());
|
2022-11-13 05:50:45 +01:00
|
|
|
lib.loadLibrary(Library.builder().groupId("net{}kyori").artifactId("adventure-text-serializer-gson-legacy-impl")
|
2023-10-13 15:49:21 +02:00
|
|
|
.version("4.13.1").relocate("net{}kyori", "clib{}net{}kyori").build());
|
2023-12-21 19:21:18 +01:00
|
|
|
lib.loadLibrary(Library.builder().groupId("net{}kyori").artifactId("adventure-platform-facet").version("4.3.2")
|
2022-11-13 05:50:45 +01:00
|
|
|
.relocate("net{}kyori", "clib{}net{}kyori").build());
|
2023-10-13 15:49:21 +02:00
|
|
|
lib.loadLibrary(Library.builder().groupId("net{}kyori").artifactId("adventure-platform-viaversion")
|
2023-12-21 19:21:18 +01:00
|
|
|
.version("4.3.2").relocate("net{}kyori", "clib{}net{}kyori").build());
|
2023-03-26 07:28:23 +02:00
|
|
|
try {
|
|
|
|
Class.forName("org.joml.Vector3f");
|
|
|
|
} catch (Throwable t) {
|
|
|
|
lib.loadLibrary(Library.builder().groupId("org{}joml").artifactId("joml").version("1.10.5").build());
|
|
|
|
}
|
2023-06-11 10:51:28 +02:00
|
|
|
PhTreeHelper.enablePooling(false);
|
2022-11-13 05:50:45 +01:00
|
|
|
}
|
|
|
|
|
2017-12-30 08:36:36 +01:00
|
|
|
@Override
|
|
|
|
public boolean onCommand(CommandSender sender, org.bukkit.command.Command command, String cmdName, String[] args) {
|
2022-09-07 21:01:39 +02:00
|
|
|
Object[] methodArgs = { sender, selector == null ? null : selector.getSelected(sender) };
|
2017-12-30 08:36:36 +01:00
|
|
|
return commands.executeSafe(command, args, sender, methodArgs);
|
|
|
|
}
|
|
|
|
|
2021-07-25 02:52:03 +02:00
|
|
|
public void onDependentPluginDisable() {
|
2023-06-18 20:27:13 +02:00
|
|
|
if (enabled) {
|
|
|
|
storeNPCs(false);
|
|
|
|
saveOnDisable = false;
|
|
|
|
}
|
2021-07-25 02:52:03 +02:00
|
|
|
}
|
|
|
|
|
2017-12-30 08:36:36 +01:00
|
|
|
@Override
|
|
|
|
public void onDisable() {
|
2023-06-18 20:27:13 +02:00
|
|
|
if (!enabled)
|
2021-07-15 13:41:03 +02:00
|
|
|
return;
|
2023-06-18 20:27:13 +02:00
|
|
|
|
2021-07-15 13:41:03 +02:00
|
|
|
Bukkit.getPluginManager().callEvent(new CitizensDisableEvent());
|
|
|
|
Editor.leaveAll();
|
2021-07-21 12:51:04 +02:00
|
|
|
despawnNPCs(saveOnDisable);
|
2021-07-18 13:30:45 +02:00
|
|
|
HandlerList.unregisterAll(this);
|
2021-07-15 13:41:03 +02:00
|
|
|
npcRegistry = null;
|
2022-12-03 14:32:58 +01:00
|
|
|
locationLookup = null;
|
2021-07-15 13:41:03 +02:00
|
|
|
enabled = false;
|
2021-07-21 12:51:04 +02:00
|
|
|
saveOnDisable = true;
|
2023-03-05 17:28:44 +01:00
|
|
|
ProfileFetcher.shutdown();
|
|
|
|
Skin.clearCache();
|
2022-12-11 14:28:39 +01:00
|
|
|
Template.shutdown();
|
2021-07-25 02:52:03 +02:00
|
|
|
NMS.shutdown();
|
2021-07-15 13:41:03 +02:00
|
|
|
CitizensAPI.shutdown();
|
2017-12-30 08:36:36 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onEnable() {
|
2022-11-13 05:50:45 +01:00
|
|
|
loadMavenLibraries();
|
|
|
|
|
2018-06-29 16:35:13 +02:00
|
|
|
CitizensAPI.setImplementation(this);
|
2018-06-07 10:59:52 +02:00
|
|
|
config = new Settings(getDataFolder());
|
2017-12-30 08:36:36 +01:00
|
|
|
setupTranslator();
|
|
|
|
// Disable if the server is not using the compatible Minecraft version
|
2023-10-01 11:27:38 +02:00
|
|
|
String mcVersion = SpigotUtil.getMinecraftPackage();
|
2017-12-30 08:36:36 +01:00
|
|
|
try {
|
|
|
|
NMS.loadBridge(mcVersion);
|
|
|
|
} catch (Exception e) {
|
|
|
|
if (Messaging.isDebugging()) {
|
|
|
|
e.printStackTrace();
|
|
|
|
}
|
|
|
|
Messaging.severeTr(Messages.CITIZENS_INCOMPATIBLE, getDescription().getVersion(), mcVersion);
|
2023-06-18 20:27:13 +02:00
|
|
|
NMS.shutdown();
|
|
|
|
CitizensAPI.shutdown();
|
2020-04-30 18:26:17 +02:00
|
|
|
Bukkit.getPluginManager().disablePlugin(this);
|
2017-12-30 08:36:36 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
registerScriptHelpers();
|
|
|
|
|
|
|
|
saves = createStorage(getDataFolder());
|
2022-12-03 14:32:58 +01:00
|
|
|
shops = new StoredShops(new YamlStorage(new File(getDataFolder(), "shops.yml")));
|
|
|
|
if (saves == null || !shops.loadFromDisk()) {
|
2017-12-30 08:36:36 +01:00
|
|
|
Messaging.severeTr(Messages.FAILED_LOAD_SAVES);
|
2020-04-30 18:26:17 +02:00
|
|
|
Bukkit.getPluginManager().disablePlugin(this);
|
2017-12-30 08:36:36 +01:00
|
|
|
return;
|
|
|
|
}
|
2022-12-03 14:32:58 +01:00
|
|
|
locationLookup = new LocationLookup();
|
2023-01-01 14:33:25 +01:00
|
|
|
locationLookup.runTaskTimer(CitizensAPI.getPlugin(), 0, 5);
|
2022-12-03 14:32:58 +01:00
|
|
|
|
2020-07-18 15:10:55 +02:00
|
|
|
npcRegistry = new CitizensNPCRegistry(saves, "citizens");
|
2023-03-05 17:28:44 +01:00
|
|
|
traitFactory = new CitizensTraitFactory(this);
|
2023-11-05 13:58:37 +01:00
|
|
|
traitFactory.registerTrait(TraitInfo.create(ShopTrait.class).withSupplier(() -> new ShopTrait(shops)));
|
2017-12-30 08:36:36 +01:00
|
|
|
selector = new NPCSelector(this);
|
2023-03-28 19:28:08 +02:00
|
|
|
|
2023-09-03 17:41:38 +02:00
|
|
|
Bukkit.getPluginManager().registerEvents(new EventListen(), this);
|
2023-02-26 08:51:59 +01:00
|
|
|
Bukkit.getPluginManager().registerEvents(new Placeholders(), this);
|
|
|
|
Placeholders.registerNPCPlaceholder(Pattern.compile("command_[a-zA-Z_0-9]+"), (npc, sender, input) -> {
|
|
|
|
npc = npc.hasTrait(ClickRedirectTrait.class) ? npc.getTraitNullable(ClickRedirectTrait.class).getNPC()
|
|
|
|
: npc;
|
|
|
|
CommandTrait trait = npc.getTraitNullable(CommandTrait.class);
|
|
|
|
return trait == null ? "" : trait.fillPlaceholder(sender, input);
|
|
|
|
});
|
2023-03-26 07:28:23 +02:00
|
|
|
|
2023-01-07 16:08:37 +01:00
|
|
|
Plugin papi = Bukkit.getPluginManager().getPlugin("PlaceholderAPI");
|
|
|
|
if (papi != null && papi.isEnabled()) {
|
2022-07-26 21:27:49 +02:00
|
|
|
new CitizensPlaceholders(selector).register();
|
|
|
|
}
|
2022-07-21 17:13:51 +02:00
|
|
|
setupEconomy();
|
2017-12-30 08:36:36 +01:00
|
|
|
|
|
|
|
registerCommands();
|
|
|
|
NMS.load(commands);
|
2022-12-11 14:28:39 +01:00
|
|
|
Template.migrate();
|
2020-04-30 18:26:17 +02:00
|
|
|
Bukkit.getMessenger().registerOutgoingPluginChannel(this, "BungeeCord");
|
2019-11-12 08:17:54 +01:00
|
|
|
commands.registerTabCompletion(this);
|
2017-12-30 08:36:36 +01:00
|
|
|
|
|
|
|
// Setup NPCs after all plugins have been enabled (allows for multiworld
|
|
|
|
// support and for NPCs to properly register external settings)
|
2020-11-15 13:32:16 +01:00
|
|
|
if (getServer().getScheduler().scheduleSyncDelayedTask(this, new CitizensLoadTask(), 1) == -1) {
|
2017-12-30 08:36:36 +01:00
|
|
|
Messaging.severeTr(Messages.LOAD_TASK_NOT_SCHEDULED);
|
2020-04-30 18:26:17 +02:00
|
|
|
Bukkit.getPluginManager().disablePlugin(this);
|
2017-12-30 08:36:36 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onImplementationChanged() {
|
|
|
|
Messaging.severeTr(Messages.CITIZENS_IMPLEMENTATION_DISABLED);
|
|
|
|
Bukkit.getPluginManager().disablePlugin(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
public void registerCommandClass(Class<?> clazz) {
|
|
|
|
try {
|
|
|
|
commands.register(clazz);
|
|
|
|
} catch (Throwable ex) {
|
|
|
|
Messaging.logTr(Messages.CITIZENS_INVALID_COMMAND_CLASS);
|
|
|
|
ex.printStackTrace();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private void registerCommands() {
|
|
|
|
commands.setInjector(new Injector(this));
|
|
|
|
// Register command classes
|
|
|
|
commands.register(AdminCommands.class);
|
|
|
|
commands.register(EditorCommands.class);
|
|
|
|
commands.register(NPCCommands.class);
|
|
|
|
commands.register(TemplateCommands.class);
|
|
|
|
commands.register(TraitCommands.class);
|
|
|
|
commands.register(WaypointCommands.class);
|
|
|
|
}
|
|
|
|
|
|
|
|
private void registerScriptHelpers() {
|
|
|
|
ScriptCompiler compiler = CitizensAPI.getScriptCompiler();
|
|
|
|
compiler.registerGlobalContextProvider(new EventRegistrar(this));
|
|
|
|
compiler.registerGlobalContextProvider(new ObjectProvider("plugin", this));
|
|
|
|
}
|
|
|
|
|
|
|
|
public void reload() throws NPCLoadException {
|
|
|
|
Editor.leaveAll();
|
|
|
|
config.reload();
|
2021-02-04 03:10:48 +01:00
|
|
|
despawnNPCs(false);
|
2017-12-30 08:36:36 +01:00
|
|
|
ProfileFetcher.reset();
|
|
|
|
Skin.clearCache();
|
2023-03-14 13:55:33 +01:00
|
|
|
|
2017-12-30 08:36:36 +01:00
|
|
|
getServer().getPluginManager().callEvent(new CitizensPreReloadEvent());
|
2023-04-19 19:35:44 +02:00
|
|
|
|
2018-03-23 11:13:51 +01:00
|
|
|
saves.reloadFromSource();
|
2017-12-30 08:36:36 +01:00
|
|
|
saves.loadInto(npcRegistry);
|
|
|
|
|
2022-12-03 14:32:58 +01:00
|
|
|
shops.loadFromDisk();
|
2022-07-26 17:50:28 +02:00
|
|
|
shops.load();
|
|
|
|
|
2022-12-11 14:28:39 +01:00
|
|
|
Template.shutdown();
|
|
|
|
|
2017-12-30 08:36:36 +01:00
|
|
|
getServer().getPluginManager().callEvent(new CitizensReloadEvent());
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void removeNamedNPCRegistry(String name) {
|
|
|
|
storedRegistries.remove(name);
|
|
|
|
}
|
|
|
|
|
|
|
|
private void scheduleSaveTask(int delay) {
|
2020-11-15 13:32:16 +01:00
|
|
|
Bukkit.getScheduler().scheduleSyncRepeatingTask(this, new CitizensSaveTask(), delay, delay);
|
2017-12-30 08:36:36 +01:00
|
|
|
}
|
|
|
|
|
2019-01-17 18:55:31 +01:00
|
|
|
@Override
|
|
|
|
public void setDefaultNPCDataStore(NPCDataStore store) {
|
2023-11-05 13:58:37 +01:00
|
|
|
if (store == null)
|
2019-01-17 18:56:47 +01:00
|
|
|
throw new IllegalArgumentException("must be non-null");
|
2021-02-04 03:10:48 +01:00
|
|
|
despawnNPCs(true);
|
2023-11-05 13:58:37 +01:00
|
|
|
saves = store;
|
|
|
|
npcRegistry = new CitizensNPCRegistry(saves, "citizens-global-" + UUID.randomUUID().toString());
|
2021-02-04 03:10:48 +01:00
|
|
|
saves.loadInto(npcRegistry);
|
2019-01-17 18:55:31 +01:00
|
|
|
}
|
|
|
|
|
2017-12-30 08:36:36 +01:00
|
|
|
private void setupEconomy() {
|
|
|
|
try {
|
|
|
|
RegisteredServiceProvider<Economy> provider = Bukkit.getServicesManager().getRegistration(Economy.class);
|
|
|
|
if (provider != null && provider.getProvider() != null) {
|
|
|
|
Economy economy = provider.getProvider();
|
|
|
|
Bukkit.getPluginManager().registerEvents(new PaymentListener(economy), this);
|
|
|
|
}
|
2022-06-08 08:07:33 +02:00
|
|
|
Messaging.logTr(Messages.LOADED_ECONOMY);
|
2017-12-30 08:36:36 +01:00
|
|
|
} catch (NoClassDefFoundError e) {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private void setupTranslator() {
|
|
|
|
Locale locale = Locale.getDefault();
|
|
|
|
String setting = Setting.LOCALE.asString();
|
|
|
|
if (!setting.isEmpty()) {
|
|
|
|
String[] parts = setting.split("[\\._]");
|
|
|
|
switch (parts.length) {
|
|
|
|
case 1:
|
|
|
|
locale = new Locale(parts[0]);
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
locale = new Locale(parts[0], parts[1]);
|
|
|
|
break;
|
|
|
|
case 3:
|
|
|
|
locale = new Locale(parts[0], parts[1], parts[2]);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Translator.setInstance(new File(getDataFolder(), "lang"), locale);
|
|
|
|
}
|
|
|
|
|
|
|
|
private void startMetrics() {
|
|
|
|
try {
|
2020-05-06 12:08:12 +02:00
|
|
|
Metrics metrics = new Metrics(this, 2463);
|
2023-04-25 17:11:20 +02:00
|
|
|
metrics.addCustomChart(new Metrics.SingleLineChart("total_npcs", () -> {
|
|
|
|
if (npcRegistry == null)
|
|
|
|
return 0;
|
|
|
|
return Iterables.size(npcRegistry);
|
|
|
|
}));
|
2023-11-05 14:04:01 +01:00
|
|
|
metrics.addCustomChart(new Metrics.SingleLineChart("using_templates",
|
|
|
|
() -> Math.min(1, Iterables.size(Template.getTemplates()))));
|
2023-11-01 16:58:49 +01:00
|
|
|
metrics.addCustomChart(new Metrics.SimplePie("locale", () -> Locale.getDefault().getLanguage()));
|
2023-04-25 17:11:20 +02:00
|
|
|
metrics.addCustomChart(new Metrics.AdvancedPie("traits", () -> {
|
|
|
|
Map<String, Integer> res = Maps.newHashMap();
|
|
|
|
for (NPC npc : npcRegistry) {
|
|
|
|
for (Trait trait : npc.getTraits()) {
|
|
|
|
if (traitFactory.trackStats(trait)) {
|
|
|
|
res.put(trait.getName(), res.getOrDefault(trait.getName(), 0) + 1);
|
|
|
|
}
|
|
|
|
}
|
2017-12-30 08:36:36 +01:00
|
|
|
}
|
2023-04-25 17:11:20 +02:00
|
|
|
return res;
|
2018-04-18 16:22:38 +02:00
|
|
|
}));
|
|
|
|
} catch (Exception e) {
|
2017-12-30 08:36:36 +01:00
|
|
|
Messaging.logTr(Messages.METRICS_ERROR_NOTIFICATION, e.getMessage());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public void storeNPCs() {
|
2022-07-26 17:50:28 +02:00
|
|
|
storeNPCs(false);
|
|
|
|
}
|
|
|
|
|
|
|
|
public void storeNPCs(boolean async) {
|
2017-12-30 08:36:36 +01:00
|
|
|
if (saves == null)
|
|
|
|
return;
|
2019-05-24 12:32:51 +02:00
|
|
|
saves.storeAll(npcRegistry);
|
2023-02-14 22:36:51 +01:00
|
|
|
shops.storeShops();
|
2017-12-30 08:36:36 +01:00
|
|
|
if (async) {
|
2022-07-26 17:50:28 +02:00
|
|
|
new Thread(() -> {
|
2022-12-03 14:32:58 +01:00
|
|
|
shops.saveToDisk();
|
2023-02-14 22:36:51 +01:00
|
|
|
saves.saveToDiskImmediate();
|
2022-07-26 17:50:28 +02:00
|
|
|
}).start();
|
2017-12-30 08:36:36 +01:00
|
|
|
} else {
|
2022-12-03 14:32:58 +01:00
|
|
|
shops.saveToDisk();
|
2017-12-30 08:36:36 +01:00
|
|
|
saves.saveToDiskImmediate();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-04-20 17:42:48 +02:00
|
|
|
@Override
|
|
|
|
public void talk(SpeechContext context) {
|
|
|
|
Util.talk(context);
|
|
|
|
}
|
|
|
|
|
2020-11-15 13:32:16 +01:00
|
|
|
private class CitizensLoadTask implements Runnable {
|
|
|
|
@Override
|
|
|
|
public void run() {
|
2023-03-26 07:28:23 +02:00
|
|
|
Plugin plib = Bukkit.getPluginManager().getPlugin("ProtocolLib");
|
2023-10-28 20:09:08 +02:00
|
|
|
if (Setting.HOOK_PROTOCOLLIB.asBoolean() && plib != null && plib.isEnabled()
|
|
|
|
&& ProtocolLibrary.getProtocolManager() != null) {
|
2023-03-26 07:28:23 +02:00
|
|
|
try {
|
|
|
|
protocolListener = new ProtocolLibListener(Citizens.this);
|
|
|
|
} catch (Throwable t) {
|
|
|
|
Messaging.severe("ProtocolLib support not enabled: enable debug to see error");
|
|
|
|
if (Messaging.isDebugging()) {
|
|
|
|
t.printStackTrace();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2020-11-15 13:32:16 +01:00
|
|
|
saves.loadInto(npcRegistry);
|
2022-12-03 14:32:58 +01:00
|
|
|
shops.load();
|
2022-07-26 18:19:47 +02:00
|
|
|
|
2020-11-15 13:32:16 +01:00
|
|
|
Messaging.logTr(Messages.NUM_LOADED_NOTIFICATION, Iterables.size(npcRegistry), "?");
|
|
|
|
startMetrics();
|
2024-02-10 18:13:49 +01:00
|
|
|
scheduleSaveTask(Setting.SAVE_TASK_FREQUENCY.asTicks());
|
2020-11-15 13:32:16 +01:00
|
|
|
Bukkit.getPluginManager().callEvent(new CitizensEnableEvent());
|
|
|
|
new PlayerUpdateTask().runTaskTimer(Citizens.this, 0, 1);
|
2021-07-15 13:41:03 +02:00
|
|
|
enabled = true;
|
2020-11-15 13:32:16 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private class CitizensSaveTask implements Runnable {
|
|
|
|
@Override
|
|
|
|
public void run() {
|
2022-07-26 17:50:28 +02:00
|
|
|
storeNPCs(false);
|
2020-11-15 13:32:16 +01:00
|
|
|
}
|
|
|
|
}
|
2017-12-30 08:36:36 +01:00
|
|
|
}
|