/*
* Copyright or © or Copr. Amaury Carrade (2014 - 2016)
*
* http://amaury.carrade.eu
*
* This software is governed by the CeCILL-B license under French law and
* abiding by the rules of distribution of free software. You can use,
* modify and/ or redistribute the software under the terms of the CeCILL-B
* license as circulated by CEA, CNRS and INRIA at the following URL
* "http://www.cecill.info".
*
* As a counterpart to the access to the source code and rights to copy,
* modify and redistribute granted by the license, users are provided only
* with a limited warranty and the software's author, the holder of the
* economic rights, and the successive licensors have only limited
* liability.
*
* In this respect, the user's attention is drawn to the risks associated
* with loading, using, modifying and/or developing or reproducing the
* software by the user in light of its specific status of free software,
* that may mean that it is complicated to manipulate, and that also
* therefore means that it is reserved for developers and experienced
* professionals having in-depth computer knowledge. Users are therefore
* encouraged to load and test the software's suitability as regards their
* requirements in conditions enabling the security of their systems and/or
* data to be ensured and, more generally, to use and operate it in the
* same conditions as regards security.
*
* The fact that you are presently reading this means that you have had
* knowledge of the CeCILL-B license and that you accept its terms.
*/
package eu.carrade.amaury.UHCReloaded.scoreboard;
import eu.carrade.amaury.UHCReloaded.UHCReloaded;
import eu.carrade.amaury.UHCReloaded.UHConfig;
import eu.carrade.amaury.UHCReloaded.borders.MapShape;
import eu.carrade.amaury.UHCReloaded.borders.worldborders.WorldBorder;
import eu.carrade.amaury.UHCReloaded.game.UHGameManager;
import eu.carrade.amaury.UHCReloaded.misc.Freezer;
import eu.carrade.amaury.UHCReloaded.teams.UHTeam;
import eu.carrade.amaury.UHCReloaded.timers.UHTimer;
import eu.carrade.amaury.UHCReloaded.utils.UHUtils;
import fr.zcraft.zlib.components.i18n.I;
import fr.zcraft.zlib.components.scoreboard.Sidebar;
import fr.zcraft.zlib.components.scoreboard.SidebarMode;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Location;
import org.bukkit.entity.Player;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
public class GameSidebar extends Sidebar
{
private final UHGameManager gameManager;
private final WorldBorder border;
private final boolean EPISODES_ENABLED;
private final boolean EPISODES_IN_SIDEBAR;
private final boolean PLAYERS_IN_SIDEBAR;
private final boolean TEAMS_IN_SIDEBAR;
private final boolean BORDER_IN_SIDEBAR;
private final boolean KILLS_IN_SIDEBAR;
private final boolean TIMER_IN_SIDEBAR;
private final boolean FREEZE_STATUS_IN_SIDEBAR;
private final boolean OWN_TEAM_IN_SIDEBAR;
private final String OWN_TEAM_TITLE_COLOR;
private final boolean OWN_TEAM_TITLE_IS_NAME;
private final boolean OWN_TEAM_DISPLAY_HEARTS;
private final boolean OWN_TEAM_COLOR_WHOLE_NAME;
private final boolean OWN_TEAM_STRIKE_DEAD_PLAYERS;
private final boolean OWN_TEAM_DISPLAY_LOGIN_STATE_ITALIC;
private final String OWN_TEAM_DISPLAY_LOGIN_STATE_SUFFIX;
private final boolean OWN_TEAM_DISPLAY_MET_PLAYERS_ONLY;
private final double OWN_TEAM_DISPLAY_MET_PLAYERS_MIN_DISTANCE_SQUARED;
private final boolean BORDER_DISPLAY_DIAMETER;
private final String FROOZEN_NULL_TIMER_TEXT;
private final String HEART = "\u2764";
private final String sidebarTitle;
private final List<String> sidebarTop = new ArrayList<>();
private final List<String> sidebarBorder = new ArrayList<>();
private final List<String> sidebarTimers = new ArrayList<>();
public GameSidebar()
{
gameManager = UHCReloaded.get().getGameManager();
border = UHCReloaded.get().getBorderManager().getBorderProxy();
EPISODES_ENABLED = UHConfig.EPISODES.ENABLED.get();
EPISODES_IN_SIDEBAR = UHConfig.SCOREBOARD.EPISODE.get();
PLAYERS_IN_SIDEBAR = UHConfig.SCOREBOARD.PLAYERS.get();
TEAMS_IN_SIDEBAR = UHConfig.SCOREBOARD.TEAMS.get();
BORDER_IN_SIDEBAR = UHConfig.SCOREBOARD.BORDER.DISPLAYED.get();
KILLS_IN_SIDEBAR = UHConfig.SCOREBOARD.KILLS.get();
TIMER_IN_SIDEBAR = UHConfig.SCOREBOARD.TIMER.get();
FREEZE_STATUS_IN_SIDEBAR = UHConfig.SCOREBOARD.FREEZE_STATUS.get();
OWN_TEAM_IN_SIDEBAR = UHConfig.SCOREBOARD.OWN_TEAM.ENABLED.get();
OWN_TEAM_TITLE_COLOR = ChatColor.translateAlternateColorCodes('&', UHConfig.SCOREBOARD.OWN_TEAM.TITLE.COLOR.get());
OWN_TEAM_TITLE_IS_NAME = UHConfig.SCOREBOARD.OWN_TEAM.TITLE.USE_TEAM_NAME.get();
OWN_TEAM_DISPLAY_HEARTS = UHConfig.SCOREBOARD.OWN_TEAM.CONTENT.DISPLAY_HEARTS.get();
OWN_TEAM_COLOR_WHOLE_NAME = UHConfig.SCOREBOARD.OWN_TEAM.CONTENT.COLOR_NAME.get();
OWN_TEAM_STRIKE_DEAD_PLAYERS = UHConfig.SCOREBOARD.OWN_TEAM.CONTENT.STRIKE_DEAD_PLAYERS.get();
OWN_TEAM_DISPLAY_LOGIN_STATE_ITALIC = UHConfig.SCOREBOARD.OWN_TEAM.CONTENT.LOGIN_STATE.ITALIC.get();
OWN_TEAM_DISPLAY_LOGIN_STATE_SUFFIX = ChatColor.translateAlternateColorCodes('&', UHConfig.SCOREBOARD.OWN_TEAM.CONTENT.LOGIN_STATE.SUFFIX.get());
OWN_TEAM_DISPLAY_MET_PLAYERS_ONLY = UHConfig.SCOREBOARD.OWN_TEAM.CONTENT.DISPLAY_MET_PLAYERS_ONLY.ENABLED.get();
OWN_TEAM_DISPLAY_MET_PLAYERS_MIN_DISTANCE_SQUARED = Math.pow(UHConfig.SCOREBOARD.OWN_TEAM.CONTENT.DISPLAY_MET_PLAYERS_ONLY.DISPLAYED_WHEN_CLOSER_THAN.get(), 2);
BORDER_DISPLAY_DIAMETER = UHConfig.SCOREBOARD.BORDER.DISPLAY_DIAMETER.get();
FROOZEN_NULL_TIMER_TEXT = new UHTimer("").toString();
setAsync(true);
setAutoRefreshDelay(20);
setContentMode(SidebarMode.PER_PLAYER);
sidebarTitle = ChatColor.translateAlternateColorCodes('&', UHConfig.SCOREBOARD.TITLE.get());
}
@Override
public void preRender()
{
sidebarTop.clear();
sidebarBorder.clear();
sidebarTimers.clear();
// Top sidebar
if (EPISODES_ENABLED && EPISODES_IN_SIDEBAR)
{
/// Current episode in the sidebar
sidebarTop.add(I.t("{gray}Episode {white}{0}",
String.valueOf(gameManager.isGameStarted() ? gameManager.getEpisode() : 0)
));
}
if (!gameManager.isGameStarted())
{
if (PLAYERS_IN_SIDEBAR)
/// Players alive in the sidebar
sidebarTop.add(I.tn("{white}{0}{gray} player", "{white}{0}{gray} players", Bukkit.getOnlinePlayers().size(), Bukkit.getOnlinePlayers().size()));
}
else
{
if (gameManager.isGameWithTeams() && EPISODES_ENABLED && EPISODES_IN_SIDEBAR)
sidebarTop.add("");
if (PLAYERS_IN_SIDEBAR)
/// Players alive in the sidebar
sidebarTop.add(I.tn("{white}{0}{gray} player", "{white}{0}{gray} players", gameManager.getAlivePlayersCount(), gameManager.getAlivePlayersCount()));
if (gameManager.isGameWithTeams() && TEAMS_IN_SIDEBAR)
/// Teams alive in the sidebar
sidebarTop.add(I.tn("{white}{0}{gray} team", "{white}{0}{gray} teams", gameManager.getAliveTeamsCount(), gameManager.getAliveTeamsCount()));
}
// Border part of the sidebar
if (gameManager.isGameStarted())
{
insertBorder(sidebarBorder);
}
// Timers part of the sidebar
insertTimers(sidebarTimers);
if (TIMER_IN_SIDEBAR)
{
if (!gameManager.isGameStarted())
sidebarTimers.add(FROOZEN_NULL_TIMER_TEXT);
else
{
final UHTimer mainTimer = UHCReloaded.get().getTimerManager().getMainTimer();
if (mainTimer != null) sidebarTimers.add(mainTimer.toString());
}
}
}
@Override
public List<String> getContent(Player player)
{
List<String> sidebar = new ArrayList<>();
sidebar.addAll(sidebarTop);
sidebar.add("");
if (OWN_TEAM_IN_SIDEBAR && gameManager.isGameStarted() && gameManager.isGameWithTeams())
{
UHTeam team = UHCReloaded.get().getTeamManager().getTeamForPlayer(player);
if (team != null)
{
sidebar.add(
(OWN_TEAM_TITLE_COLOR.isEmpty() ? team.getColorOrWhite().toChatColor() : OWN_TEAM_TITLE_COLOR)
/// Title of the team section in the sidebar
+ (OWN_TEAM_TITLE_IS_NAME ? ChatColor.BOLD + team.getName() : I.t("{bold}Your team"))
);
Location playerLocation = player.getLocation();
for (UUID teamMember : team.getPlayersUUID())
{
SidebarPlayerCache cache = UHCReloaded.get().getScoreboardManager().getSidebarPlayerCache(teamMember);
// If enabled, we check if the player was already met or is close to this player.
// Only if the damages are on (= 30 seconds after the game start) to avoid false close while
// teleporting.
if(OWN_TEAM_DISPLAY_MET_PLAYERS_ONLY)
{
if(!(teamMember.equals(player.getUniqueId()) || cache.getTeammatesDisplayed().contains(teamMember)))
{
if (gameManager.isGameStarted() && gameManager.isTakingDamage())
{
if (gameManager.isPlayerDead(teamMember))
continue; // dead (spectators don't have to be displayed in the sidebar).
Player teammate = Sidebar.getPlayerAsync(teamMember);
if (teammate == null)
continue; // offline
Location teammateLocation = teammate.getLocation();
// Check if the players are close
if (teammateLocation.getWorld().equals(playerLocation.getWorld()))
{
final double distanceSquared = teammateLocation.distanceSquared(playerLocation);
if (distanceSquared <= OWN_TEAM_DISPLAY_MET_PLAYERS_MIN_DISTANCE_SQUARED)
cache.getTeammatesDisplayed().add(teamMember);
else
continue; // Too far, skipped
}
else
{
continue; // Too far, skipped
}
}
else
{
continue;
}
}
}
final String strike = OWN_TEAM_STRIKE_DEAD_PLAYERS && !cache.isAlive() ? ChatColor.STRIKETHROUGH.toString() : "";
final ChatColor aliveColor = cache.isAlive() ? ChatColor.WHITE : ChatColor.GRAY;
final String heart = OWN_TEAM_DISPLAY_HEARTS ? cache.getHealthColor() + strike + HEART + " " : "";
final String name = (OWN_TEAM_COLOR_WHOLE_NAME ? cache.getHealthColor() : aliveColor)
+ strike
+ (OWN_TEAM_DISPLAY_LOGIN_STATE_ITALIC && !cache.isOnline() ? ChatColor.ITALIC : "")
+ cache.getPlayerName()
+ (!cache.isOnline() ? ChatColor.RESET + "" + (OWN_TEAM_COLOR_WHOLE_NAME ? cache.getHealthColor() : aliveColor) + " " + OWN_TEAM_DISPLAY_LOGIN_STATE_SUFFIX : "");
sidebar.add(heart + name);
}
sidebar.add("");
}
}
sidebar.addAll(sidebarBorder);
if (KILLS_IN_SIDEBAR && gameManager.isGameStarted())
{
SidebarPlayerCache cache = UHCReloaded.get().getScoreboardManager().getSidebarPlayerCache(player.getUniqueId());
/// Kills count in the sidebar
sidebar.add(I.tn("{white}{0}{gray} player killed", "{white}{0}{gray} players killed", cache.getPlayersKilled().size(), cache.getPlayersKilled().size()));
sidebar.add("");
}
sidebar.addAll(sidebarTimers);
if (FREEZE_STATUS_IN_SIDEBAR)
{
insertFreezeStatus(sidebar, player);
}
return sidebar;
}
@Override
public String getTitle(Player player)
{
return sidebarTitle;
}
/**
* Inserts the border status in the given list, to be displayed in the sidebar.
*
* @param sidebar The list representing the sidebar's content.
*/
private void insertBorder(List<String> sidebar)
{
if (BORDER_IN_SIDEBAR)
{
/// Title of the border section in the sidebar
sidebar.add(I.t("{blue}{bold}Border"));
int diameter = (int) Math.ceil(border.getDiameter());
if (BORDER_DISPLAY_DIAMETER || border.getShape() == MapShape.CIRCULAR)
{
if (border.getShape() == MapShape.SQUARED)
/// Border diameter for a squared map in the sidebar
sidebar.add(I.tn("{white}{0} block wide", "{white}{0} blocks wide", diameter, diameter));
else
/// Border diameter for a circular map in the sidebar
sidebar.add(I.tn("{gray}Diameter: {white}{0} block", "{gray}Diameter: {white}{0} blocks", diameter, diameter));
}
else
{
Location center = border.getCenter();
int radius = (int) Math.ceil(diameter / 2);
int minX = center.getBlockX() - radius;
int maxX = center.getBlockX() + radius;
int minZ = center.getBlockZ() - radius;
int maxZ = center.getBlockZ() + radius;
// Same min & max, we can display both at once
if (minX == minZ && maxX == maxZ)
{
/// Min & max coordinates in the sidebar, to locate the border. Ex: "-500 +500". {0} = minimal coord, {1} = maximal coord.
sidebar.add(I.t("{white}{0} {1}", UHUtils.integerToStringWithSign(minX), UHUtils.integerToStringWithSign(maxZ)));
}
else
{
/// Min & max X coordinates in the sidebar, to locate the border. Ex: "X: -500 +500". {0} = minimal coord, {1} = maximal coord.
sidebar.add(I.t("{gray}X: {white}{0} {1}", UHUtils.integerToStringWithSign(minX), UHUtils.integerToStringWithSign(maxX)));
/// Min & max Z coordinates in the sidebar, to locate the border. Ex: "Z: -500 +500". {0} = minimal coord, {1} = maximal coord.
sidebar.add(I.t("{gray}Z: {white}{0} {1}", UHUtils.integerToStringWithSign(minZ), UHUtils.integerToStringWithSign(maxZ)));
}
}
sidebar.add("");
}
}
/**
* Inserts the timers in the given list, to be displayed in the sidebar, at the bottom of the
* list.
*
* @param sidebar The list representing the sidebar's content.
*/
private void insertTimers(List<String> sidebar)
{
for (UHTimer timer : UHCReloaded.get().getTimerManager().getTimers())
{
if (timer.isDisplayed())
{
sidebar.add(timer.getDisplayName());
sidebar.add(timer.toString());
sidebar.add("");
}
}
}
/**
* Inserts the « frozen » text at the bottom of the list, if active globally or for the given
* player.
*
* @param sidebar The list representing the sidebar's content.
*/
private void insertFreezeStatus(List<String> sidebar, Player player)
{
final Freezer freezer = UHCReloaded.get().getFreezer();
if ((freezer.getGlobalFreezeState() && !freezer.isHiddenFreeze()) || freezer.isPlayerFrozen(player))
{
sidebar.add("");
/// Notice displayed at the bottom of the sidebar if the game is paused (/uh freeze all).
sidebar.add(I.t("{darkaqua}Game frozen"));
}
}
}