package de.fanta.lobby;
import de.cubeside.nmsutils.NMSUtils;
import de.cubeside.nmsutils.nbt.CompoundTag;
import de.fanta.challenge.Challenge;
import de.fanta.challengeutils.Color;
import de.fanta.lobby.adventure.AdventureMapsConfig;
import de.fanta.lobby.adventure.CategoriesConfig;
import de.fanta.lobby.adventure.ui.AnvilAddUserGui;
import de.fanta.lobby.commands.AdventureCommand.AdventureAddCategoryCommand;
import de.fanta.lobby.commands.AdventureCommand.AdventureAddMapCommand;
import de.fanta.lobby.commands.AdventureCommand.AdventureClearSavesCommand;
import de.fanta.lobby.commands.AdventureCommand.AdventureConvertMapCommand;
import de.fanta.lobby.commands.AdventureCommand.AdventureLoadCommand;
import de.fanta.lobby.commands.AdventureCommand.AdventureLoadMapIconsCommand;
import de.fanta.lobby.commands.AdventureCommand.AdventureMapsCommand;
import de.fanta.lobby.commands.AdventureCommand.AdventureStartEventServerCommand;
import de.fanta.lobby.commands.AdventureCommand.AdventureTempCommand;
import de.fanta.lobby.commands.AdventureCommand.AdventureTestMapCommand;
import de.fanta.lobby.commands.AdventureCommand.ChallengesRemovePlayerServer;
import de.fanta.lobby.commands.ChallengesCommand.ChallengeClearSavesCommand;
import de.fanta.lobby.commands.ChallengesCommand.ChallengeListUserStatsCommand;
import de.fanta.lobby.commands.ChallengesCommand.ChallengeLoadCommand;
import de.fanta.lobby.commands.ChallengesCommand.ChallengeSetStatsCommand;
import de.fanta.lobby.commands.ChallengesCommand.ChallengesStatsCommand;
import de.fanta.lobby.commands.PiglinCommand.AddEntityCommand;
import de.fanta.lobby.commands.PiglinCommand.Entitytphere;
import de.fanta.lobby.commands.PiglinCommand.InfoPiglinCommand;
import de.fanta.lobby.commands.PiglinCommand.ListPiglinCommand;
import de.fanta.lobby.commands.PiglinCommand.RemoveEntityCommand;
import de.fanta.lobby.commands.PiglinCommand.SetEntitySpawnLocationCommand;
import de.fanta.lobby.commands.PiglinCommand.HangableDataPiglinCommand;
import de.fanta.lobby.commands.PiglinCommand.ToggleArenaCommand;
import de.fanta.lobby.listeners.AnvilGuiListener;
import de.fanta.lobby.listeners.ChallengesEventListener;
import de.fanta.lobby.listeners.EntityListener;
import de.fanta.lobby.listeners.PlayerListener;
import de.fanta.lobby.utils.ComponentUtil;
import de.fanta.lobby.utils.Statistics;
import de.iani.cubesidestats.api.CubesideStatisticsAPI;
import de.iani.cubesideutils.bukkit.commands.CommandRouter;
import de.iani.playerUUIDCache.PlayerUUIDCache;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.TextComponent;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.block.data.Rotatable;
import org.bukkit.configuration.file.YamlConfiguration;
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.io.File;
import java.io.IOException;
import java.nio.file.Path;
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 Lobby extends JavaPlugin {
private TextComponent prefixComponent;
private Component ADVENTUREGUIPREFIX;
private Component CHALLENGEGUIPREFIX;
private static Lobby 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;
private Path challengeSavePath;
private Path adventureSavePath;
private Path aventureMapsPath;
private Path serverJarsPath;
private Path serverFolderPath;
private File saveAccessFile;
private YamlConfiguration saveAccessConfig;
private ComponentUtil componentUtil;
private final HashMap<UUID, AnvilAddUserGui> anvilInputGuis = new HashMap<>();
public Lobby() {
this.entityData = new HashMap<>();
this.entityServerMapping = new HashMap<>();
this.availableServers = new HashSet<>();
this.eventServerPlayerList = new ArrayList<>();
}
public static Lobby getPlugin() {
return plugin;
}
@Override
public void onLoad() {
plugin = this;
File oldPluginFolder = new File("plugins/ChallengesJoinEntities");
if (oldPluginFolder.isDirectory()) {
if (!oldPluginFolder.renameTo(new File("plugins/Lobby"))) {
getLogger().severe("ChallengesJoinEntities Ordner konnte nicht in Lobby umgenannt werden!");
plugin.getServer().shutdown();
}
}
}
@Override
public void onEnable() {
this.componentUtil = new ComponentUtil();
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);
}
prefixComponent = Component.text("[").color(Color.BLUE).append(Component.text("Lobby").color(Color.GREEN)).append(Component.text("] ").color(Color.BLUE));
ADVENTUREGUIPREFIX = Component.text("Adventure", Color.GREEN);
CHALLENGEGUIPREFIX = Component.text("Challenge", Color.GREEN);
this.globalDataHelper = new ChallengesGlobalDataHelper(this);
this.config = new Config(this);
if (!saveAccessFile.exists()) {
try {
saveAccessFile.createNewFile();
} catch (IOException e) {
getLogger().log(Level.SEVERE, "SaveAccessFile konnte nicht erstellt werden!", e);
}
}
saveAccessConfig = YamlConfiguration.loadConfiguration(saveAccessFile);
loadCategoriesAndMaps();
if (Bukkit.getPluginManager().getPlugin("Challenge") != 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 InfoPiglinCommand(this), "info");
router.addCommandMapping(new HangableDataPiglinCommand(this), "hangabledata");
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(this, plugin.getStatistics()), "stats");
challengesrouter.addCommandMapping(new ChallengeSetStatsCommand(plugin), "setstats");
challengesrouter.addCommandMapping(new ChallengeClearSavesCommand(plugin), "clearoldsaves");
challengesrouter.addCommandMapping(new ChallengeListUserStatsCommand(plugin), "listuserstats");
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(plugin), "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(new AnvilGuiListener(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, null, 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, @Nullable HangableData hangableData, boolean saveToConfig) {
addPiglin(piglinUUID, serverName, null, gpLocationName, serverDisplayName, hangableData, saveToConfig);
}
public void addPiglin(UUID piglinUUID, String serverName, @Nullable Integer mapVersion, String gpLocationName, String serverDisplayName, @Nullable HangableData hangableData, boolean saveToConfig) {
JoinEntityData entityData = new JoinEntityData(serverName, mapVersion, piglinUUID, gpLocationName, serverDisplayName, JoinEntityData.ServerStatus.OFFLINE, JoinEntityData.EventStatus.NORMAL, 0, 0);
if (hangableData != null) {
entityData.setHangableData(hangableData);
}
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;
}
Component customName = data.createCustomEntityName();
entity.customName(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();
HangableData hangableData = data.getHangableData();
boolean isHangable = false;
if (hangableData != null) {
isHangable = hangableData.isHangable();
}
if (isHangable) {
Location location = piglin.getLocation().clone();
location.setPitch(0);
piglin.teleport(location);
}
if (hangableData != null && hangableData.getOfflineBlockLocation() != null && hangableData.getOnlineBlockLocation() != null) {
Block onlineBlock = hangableData.getOnlineBlockLocation().getBlock();
onlineBlock.setType(Material.PLAYER_HEAD);
String nbt = hangableData.getOnlineBlockNbt();
Integer version = hangableData.getOnlineBlockNbtVersion();
if (nbt != null && version != null) {
CompoundTag tag = plugin.nmsUtils.getNbtUtils().updateBlockEntity(plugin.nmsUtils.getNbtUtils().parseString(nbt), version);
plugin.nmsUtils.getNbtUtils().setBlockEntityNbt(onlineBlock, tag);
Block offlineBlock = hangableData.getOfflineBlockLocation().getBlock();
offlineBlock.setType(Material.AIR);
}
BlockFace blockFacing = hangableData.getOnlineBlockFacing();
if (blockFacing != null) {
if (onlineBlock.getBlockData() instanceof Rotatable rotatable) {
rotatable.setRotation(blockFacing);
onlineBlock.setBlockData(rotatable);
}
}
if (piglin.isLeashed()) {
Entity entity = piglin.getLeashHolder();
piglin.setLeashHolder(null);
entity.remove();
}
}
if (nmsUtils != null) {
nmsUtils.getEntityUtils().setPiglinDancing(piglin, true);
}
}
case OFFLINE -> {
if (nmsUtils != null) {
nmsUtils.getEntityUtils().setPiglinDancing(piglin, false);
}
HangableData hangableData = data.getHangableData();
boolean isHangable = false;
if (hangableData != null) {
isHangable = hangableData.isHangable();
}
if (isHangable) {
Location location = piglin.getLocation().clone();
location.setPitch(45);
piglin.teleport(location);
} else {
piglin.getEquipment().setItemInOffHand(new ItemStack(Material.GOLD_INGOT));
}
if (hangableData != null && hangableData.getOfflineBlockLocation() != null && hangableData.getOnlineBlockLocation() != null) {
Block offlineBlock = hangableData.getOfflineBlockLocation().getBlock();
offlineBlock.setType(Material.PLAYER_HEAD);
String nbt = hangableData.getOfflineBlockNbt();
Integer version = hangableData.getOfflineBlockNbtVersion();
if (nbt != null && version != null) {
CompoundTag tag = plugin.nmsUtils.getNbtUtils().updateBlockEntity(plugin.nmsUtils.getNbtUtils().parseString(nbt), version);
plugin.nmsUtils.getNbtUtils().setBlockEntityNbt(offlineBlock, tag);
Block onlineBlock = hangableData.getOnlineBlockLocation().getBlock();
onlineBlock.setType(Material.AIR);
}
BlockFace blockFacing = hangableData.getOfflineBlockFacing();
if (blockFacing != null) {
if (offlineBlock.getBlockData() instanceof Rotatable rotatable) {
rotatable.setRotation(blockFacing);
offlineBlock.setBlockData(rotatable);
}
}
Location fenceLocation = hangableData.getFenceLocation();
if (fenceLocation != null && !piglin.isLeashed()) {
Entity leashKnot = fenceLocation.getWorld().spawnEntity(fenceLocation, EntityType.LEASH_KNOT);
leashKnot.setPersistent(false);
piglin.setLeashHolder(leashKnot);
}
}
}
case RUNNING -> {
piglin.getEquipment().clear();
if (nmsUtils != null) {
nmsUtils.getEntityUtils().setPiglinDancing(piglin, false);
}
}
}
} else { // server is full
piglin.getEquipment().clear();
if (nmsUtils != null) {
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;
}
public Path getChallengeSavePath() {
return challengeSavePath;
}
public void setChallengeSavePath(Path challengeSavePath) {
this.challengeSavePath = challengeSavePath;
}
public Path getAdventureSavePath() {
return adventureSavePath;
}
public void setAdventureSavePath(Path adventureSavePath) {
this.adventureSavePath = adventureSavePath;
}
public Path getAdventureMapsPath() {
return aventureMapsPath;
}
public void setAventureMapsPath(Path aventureMapsPath) {
this.aventureMapsPath = aventureMapsPath;
}
public Path getServerJarsPath() {
return serverJarsPath;
}
public void setServerJarsPath(Path serverJarsPath) {
this.serverJarsPath = serverJarsPath;
}
public Path getServerFolderPath() {
return serverFolderPath;
}
public void setServerFolderPath(Path serverFolderPath) {
this.serverFolderPath = serverFolderPath;
}
public void setSaveAccessFile(File saveAccessFile) {
this.saveAccessFile = saveAccessFile;
}
public File getSaveAccessFile() {
return saveAccessFile;
}
public YamlConfiguration getSaveAccessConfig() {
return saveAccessConfig;
}
public void saveSaveAccessConfig() {
try {
saveAccessConfig.save(saveAccessFile);
} catch (IOException e) {
Challenge.getPlugin().getLogger().log(Level.SEVERE, "Could not save SaveAccess config", e);
}
}
public HashMap<UUID, AnvilAddUserGui> getAnvilInputGuis() {
return anvilInputGuis;
}
public TextComponent getPrefixComponent() {
return prefixComponent;
}
public Component getADVENTUREGUIPREFIX() {
return ADVENTUREGUIPREFIX;
}
public Component getCHALLENGEGUIPREFIX() {
return CHALLENGEGUIPREFIX;
}
public ComponentUtil getComponentUtil() {
return componentUtil;
}
}