package de.fanta.challengesjoinentities;
import de.cubeside.nmsutils.NMSUtils;
import de.cubeside.npcs.CubesideNPCs;
import de.fanta.challengesjoinentities.adventure.AdventureMapsConfig;
import de.fanta.challengesjoinentities.adventure.CategoriesConfig;
import de.fanta.challengesjoinentities.commands.AdventureCommand.AdventureAddCategoryCommand;
import de.fanta.challengesjoinentities.commands.AdventureCommand.AdventureAddMapCommand;
import de.fanta.challengesjoinentities.commands.AdventureCommand.AdventureClearSavesCommand;
import de.fanta.challengesjoinentities.commands.AdventureCommand.AdventureConvertMapCommand;
import de.fanta.challengesjoinentities.commands.AdventureCommand.AdventureLoadCommand;
import de.fanta.challengesjoinentities.commands.AdventureCommand.AdventureLoadMapIconsCommand;
import de.fanta.challengesjoinentities.commands.AdventureCommand.AdventureMapsCommand;
import de.fanta.challengesjoinentities.commands.AdventureCommand.AdventureStartEventServerCommand;
import de.fanta.challengesjoinentities.commands.AdventureCommand.AdventureTempCommand;
import de.fanta.challengesjoinentities.commands.AdventureCommand.AdventureTestMapCommand;
import de.fanta.challengesjoinentities.commands.AdventureCommand.ChallengeClearSavesCommand;
import de.fanta.challengesjoinentities.commands.AdventureCommand.ChallengesRemovePlayerServer;
import de.fanta.challengesjoinentities.commands.ChallengesCommand.ChallengeLoadCommand;
import de.fanta.challengesjoinentities.commands.ChallengesCommand.ChallengeSetStatsCommand;
import de.fanta.challengesjoinentities.commands.ChallengesCommand.ChallengesStatsCommand;
import de.fanta.challengesjoinentities.commands.PiglinCommand.AddEntityCommand;
import de.fanta.challengesjoinentities.commands.PiglinCommand.Entitytphere;
import de.fanta.challengesjoinentities.commands.PiglinCommand.ListPiglinCommand;
import de.fanta.challengesjoinentities.commands.PiglinCommand.RemoveEntityCommand;
import de.fanta.challengesjoinentities.commands.PiglinCommand.SetEntitySpawnLocationCommand;
import de.fanta.challengesjoinentities.commands.PiglinCommand.ToggleArenaCommand;
import de.fanta.challengesjoinentities.listeners.ChallengesEventListener;
import de.fanta.challengesjoinentities.listeners.EntityListener;
import de.fanta.challengesjoinentities.listeners.PlayerListener;
import de.fanta.challengesjoinentities.utils.Statistics;
import de.iani.cubesidestats.api.CubesideStatisticsAPI;
import de.iani.cubesideutils.bukkit.commands.CommandRouter;
import de.iani.playerUUIDCache.PlayerUUIDCache;
import fr.cleymax.signgui.SignManager;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.TextComponent;
import net.kyori.adventure.text.format.TextColor;
import net.md_5.bungee.api.ChatColor;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Piglin;
import org.bukkit.event.entity.CreatureSpawnEvent;
import org.bukkit.inventory.ItemStack;
import org.bukkit.plugin.java.JavaPlugin;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.logging.Level;
public class ChallengesJoinEntities extends JavaPlugin {
public static final String PREFIX = ChatUtil.BLUE + "[" + ChatUtil.GREEN + "Lobby" + ChatUtil.BLUE + "]";
public static final String ADVENTUREGUIPREFIX = ChatColor.of("#2d8745") + "Adventure";
public static final String CHALLENGEGUIPREFIX = ChatColor.of("#2d8745") + "Challenge";
private static final TextColor BRACKETS = TextColor.fromHexString("#87f7ea");
public static final TextComponent PREFIX_COMPONENT = Component.text("[", BRACKETS).append(Component.text("Lobby", TextColor.fromHexString("#52ff9d"))).append(Component.text("] ", BRACKETS));
private static ChallengesJoinEntities plugin;
private final Map<String, JoinEntityData> entityData;
private final Map<UUID, String> entityServerMapping;
private final Set<String> availableServers;
public NMSUtils nmsUtils;
private Config config;
private ChallengesGlobalDataHelper globalDataHelper;
private CategoriesConfig categoriesConfig;
private AdventureMapsConfig adventureMapsConfig;
private PlayerUUIDCache playerUUIDCache;
private CubesideStatisticsAPI cubesideStatistics;
private Statistics statistics;
private static SignManager signManager;
private final List<UUID> eventServerPlayerList;
public ChallengesJoinEntities() {
this.entityData = new HashMap<>();
this.entityServerMapping = new HashMap<>();
this.availableServers = new HashSet<>();
this.eventServerPlayerList = new ArrayList<>();
}
public static ChallengesJoinEntities getPlugin() {
return plugin;
}
@Override
public void onEnable() {
plugin = this;
playerUUIDCache = (PlayerUUIDCache) getServer().getPluginManager().getPlugin("PlayerUUIDCache");
nmsUtils = getServer().getServicesManager().load(NMSUtils.class);
if (getServer().getPluginManager().isPluginEnabled("CubesideStatistics")) {
cubesideStatistics = getServer().getServicesManager().load(CubesideStatisticsAPI.class);
statistics = new Statistics(this);
}
if (getServer().getPluginManager().isPluginEnabled("SignGUI")) {
signManager = new SignManager(this);
signManager.init();
}
this.globalDataHelper = new ChallengesGlobalDataHelper(this);
this.config = new Config(this);
loadCategoriesAndMaps();
if (Bukkit.getPluginManager().getPlugin("Challenges") != null) { // Challenge server -> listen on Challenge events
Bukkit.getPluginManager().registerEvents(new ChallengesEventListener(this), this);
} else { // Lobby server -> register commands
CommandRouter router = new CommandRouter(getCommand("piglins"));
router.addCommandMapping(new AddEntityCommand(this), "spawn");
router.addCommandMapping(new RemoveEntityCommand(this), "remove");
router.addCommandMapping(new Entitytphere(this), "tphere");
router.addCommandMapping(new ListPiglinCommand(this), "list");
router.addCommandMapping(new SetEntitySpawnLocationCommand(this), "setlocation");
router.addCommandMapping(new ToggleArenaCommand(this, true), "enable");
router.addCommandMapping(new ToggleArenaCommand(this, false), "disable");
CommandRouter challengesrouter = new CommandRouter(getCommand("challenges"));
challengesrouter.addCommandMapping(new ChallengeLoadCommand(this), "load");
challengesrouter.addCommandMapping(new ChallengesStatsCommand(plugin.getStatistics()), "stats");
challengesrouter.addCommandMapping(new ChallengeSetStatsCommand(plugin), "setstats");
challengesrouter.addCommandMapping(new ChallengeClearSavesCommand(), "clearoldsaves");
CommandRouter adventurerouter = new CommandRouter(getCommand("adventure"));
adventurerouter.addCommandMapping(new AdventureLoadCommand(this), "load");
adventurerouter.addCommandMapping(new AdventureAddCategoryCommand(this), "addcategory");
adventurerouter.addCommandMapping(new AdventureAddMapCommand(this), "addmap");
adventurerouter.addCommandMapping(new AdventureMapsCommand(this), "maps");
adventurerouter.addCommandMapping(new AdventureTestMapCommand(this), "testmap");
adventurerouter.addCommandMapping(new ChallengesRemovePlayerServer(this), "removeplayerfromserver");
adventurerouter.addCommandMapping(new AdventureConvertMapCommand(this), "convertmap");
adventurerouter.addCommandMapping(new AdventureLoadMapIconsCommand(this), "loadmapicons");
adventurerouter.addCommandMapping(new AdventureClearSavesCommand(), "clearoldsaves");
adventurerouter.addCommandMapping(new AdventureTempCommand(this), "temp");
adventurerouter.addCommandMapping(new AdventureStartEventServerCommand(this), "starteventserver");
Bukkit.getPluginManager().registerEvents(new EntityListener(this), this);
Bukkit.getPluginManager().registerEvents(new PlayerListener(this), this);
}
Bukkit.getPluginManager().registerEvents(globalDataHelper, this);
}
@Override
public void onDisable() {
saveCategoriesAndMaps();
getPluginConfig().getChallengeServers().forEach(Server::despawnPiglin);
getPluginConfig().getAdventureServers().forEach(Server::despawnPiglin);
}
public void spawnPiglin(Location location, String serverName, @Nullable Integer serverVersion, String gpLocationName, String serverDisplayName) {
spawnPiglin(location, serverName, serverVersion, gpLocationName, serverDisplayName, true);
}
public void spawnPiglin(Location location, String serverName, @Nullable Integer serverVersion, String gpLocationName, String serverDisplayName, boolean saveToConfig) {
if (entityData.containsKey(serverName)) {
despawnPiglin(entityData.get(serverName).getEntityUUID(), serverName);
}
Piglin piglin = (Piglin) location.getWorld().spawnEntity(location, EntityType.PIGLIN, CreatureSpawnEvent.SpawnReason.CUSTOM, t -> ((Piglin) t).getEquipment().clear());
piglin.setAI(false);
piglin.setSilent(true);
piglin.setRemoveWhenFarAway(false);
piglin.setPersistent(true);
piglin.setCustomNameVisible(true);
addPiglin(piglin.getUniqueId(), serverName, serverVersion, gpLocationName, serverDisplayName, saveToConfig);
globalDataHelper.requestInitialData(serverName);
}
public void despawnPiglin(UUID piglinUUID, String serverName) {
Entity piglin = Bukkit.getEntity(piglinUUID);
if (piglin != null) {
piglin.remove();
removePiglin(serverName);
}
}
public void despawnPiglin(String serverName) {
if (entityData.get(serverName) != null) {
despawnPiglin(entityData.get(serverName).getEntityUUID(), serverName);
}
}
public void spawnNPC(Location location, String serverName, String gpLocationName, String serverDisplayName, boolean saveToConfig) {
if (entityData.containsKey(serverName)) {
despawnNPC(entityData.get(serverName).getEntityUUID(), serverDisplayName);
}
if (plugin.getServer().getPluginManager().getPlugin("CubesideNPCs") == null) {
return;
}
addPiglin(CubesideNPCs.getPlugin().spawnNPC(serverDisplayName, location), serverName, gpLocationName, serverDisplayName, saveToConfig);
globalDataHelper.requestInitialData(serverName);
}
public void despawnNPC(String serverName) {
if (entityData.get(serverName) != null) {
despawnNPC(entityData.get(serverName).getEntityUUID(), serverName);
}
}
public void despawnNPC(UUID piglinUUID, String serverName) {
if (plugin.getServer().getPluginManager().getPlugin("CubesideNPCs") == null) {
return;
}
CubesideNPCs.getPlugin().removeNPC(piglinUUID);
removePiglin(serverName);
}
public void addPiglin(UUID piglinUUID, String serverName, String gpLocationName, String serverDisplayName, boolean saveToConfig) {
addPiglin(piglinUUID, serverName, null, gpLocationName, serverDisplayName, saveToConfig);
}
public void addPiglin(UUID piglinUUID, String serverName, @Nullable Integer mapVersion, String gpLocationName, String serverDisplayName, boolean saveToConfig) {
JoinEntityData entityData = new JoinEntityData(serverName, mapVersion, piglinUUID, gpLocationName, serverDisplayName, JoinEntityData.ServerStatus.OFFLINE, JoinEntityData.EventStatus.NORMAL, 0, 0);
this.entityData.put(serverName, entityData);
this.entityServerMapping.put(piglinUUID, serverName);
if (saveToConfig) {
this.config.savePiglin(entityData);
}
}
public void removePiglin(String serverName) {
JoinEntityData data = this.entityData.remove(serverName);
if (data != null) {
this.entityServerMapping.remove(data.getEntityUUID());
}
this.config.removePiglin(serverName);
}
public void updateTimerStatus(String serverName, boolean running) {
JoinEntityData data = entityData.get(serverName);
if (data != null) {
data.setServerStatus(running ? JoinEntityData.ServerStatus.RUNNING : JoinEntityData.ServerStatus.ONLINE);
updatePiglinCustomName(serverName);
updatePiglinBehaviour(serverName);
}
}
public void updateEventStatus(String serverName, boolean event) {
JoinEntityData data = entityData.get(serverName);
if (data != null) {
data.setEventStatus(event ? JoinEntityData.EventStatus.EVENT : JoinEntityData.EventStatus.NORMAL);
updatePiglinCustomName(serverName);
updatePiglinBehaviour(serverName);
}
}
public void updateServerStatus(String serverName, boolean online) {
JoinEntityData data = entityData.get(serverName);
if (data != null) {
data.setServerStatus(online ? JoinEntityData.ServerStatus.ONLINE : JoinEntityData.ServerStatus.OFFLINE);
updatePiglinCustomName(serverName);
updatePiglinBehaviour(serverName);
}
}
public void updatePlayerCount(String serverName, int count, int maxPlayers) {
JoinEntityData data = entityData.get(serverName);
if (data != null) {
data.setPlayerCount(count);
data.setMaxPlayers(maxPlayers);
updatePiglinCustomName(serverName);
updatePiglinBehaviour(serverName);
}
}
public Piglin getPiglinForServerName(String serverName) {
JoinEntityData data = entityData.get(serverName);
if (data != null) {
Entity piglin = Bukkit.getEntity(data.getEntityUUID());
if (piglin instanceof Piglin) {
return (Piglin) piglin;
}
}
return null;
}
public void updatePiglinCustomName(String serverName) {
Entity entity = getPiglinForServerName(serverName);
JoinEntityData data = entityData.get(serverName);
if (entity == null) {
return;
}
if (data == null) {
return;
}
String customName = data.createCustomEntityName();
entity.setCustomName(customName);
}
public void updatePiglinBehaviour(String serverName) {
Piglin piglin = getPiglinForServerName(serverName);
JoinEntityData data = entityData.get(serverName);
if (piglin != null && data != null) {
if (data.getPlayerCount() < data.getMaxPlayers()) {
switch (data.getServerStatus()) {
case ONLINE -> {
piglin.getEquipment().clear();
nmsUtils.getEntityUtils().setPiglinDancing(piglin, true);
}
case OFFLINE -> {
nmsUtils.getEntityUtils().setPiglinDancing(piglin, false);
piglin.getEquipment().setItemInOffHand(new ItemStack(Material.GOLD_INGOT));
}
case RUNNING -> {
piglin.getEquipment().clear();
nmsUtils.getEntityUtils().setPiglinDancing(piglin, false);
}
}
} else { // server is full
piglin.getEquipment().clear();
nmsUtils.getEntityUtils().setPiglinDancing(piglin, false);
}
}
}
public void saveCategoriesAndMaps() {
this.adventureMapsConfig.save();
this.categoriesConfig.save();
}
public void loadCategoriesAndMaps() {
this.categoriesConfig = new CategoriesConfig(this);
this.adventureMapsConfig = new AdventureMapsConfig(this);
this.adventureMapsConfig.load();
this.categoriesConfig.load();
}
public void reloadCategoriesAndMaps() {
getLogger().log(Level.INFO, "Maps werden gespeichert und neu geladen.");
saveCategoriesAndMaps();
loadCategoriesAndMaps();
getLogger().log(Level.INFO, "Maps wurden neu geladen.");
}
public PlayerUUIDCache getPlayerUUIDCache() {
return playerUUIDCache;
}
public AdventureMapsConfig getAdventureMapsConfig() {
return this.adventureMapsConfig;
}
public CategoriesConfig getCategoriesConfig() {
return this.categoriesConfig;
}
public Config getPluginConfig() {
return config;
}
public ChallengesGlobalDataHelper getGlobalDataHelper() {
return globalDataHelper;
}
public boolean isJoinEntity(Entity entity) {
return entityServerMapping.containsKey(entity.getUniqueId());
}
public JoinEntityData getEntityData(String serverName) {
return entityData.get(serverName);
}
public String getServerNameForEntity(UUID entityUUID) {
return entityServerMapping.get(entityUUID);
}
public Map<String, JoinEntityData> getEntityData() {
return entityData;
}
public Set<String> getAvailableServers() {
return availableServers;
}
public CubesideStatisticsAPI getCubesideStatistics() {
return cubesideStatistics;
}
public Statistics getStatistics() {
return statistics;
}
public SignManager getSignManager() {
return signManager;
}
public List<UUID> getEventServerPlayerList() {
return eventServerPlayerList;
}
}