package eu.thog.uhcrun.game;
import com.connorlinfoot.titleapi.TitleAPI;
import eu.thog.uhcrun.UHCRun;
import eu.thog.uhcrun.compatibility.*;
import eu.thog.uhcrun.listener.ChunkListener;
import eu.thog.uhcrun.task.GameLoop;
import eu.thog.uhcrun.utils.Colors;
import eu.thog.uhcrun.utils.Metadatas;
import net.minecraft.server.v1_8_R3.MinecraftServer;
import net.minecraft.server.v1_8_R3.SpawnerCreature;
import org.bukkit.*;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Firework;
import org.bukkit.entity.Player;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerLoginEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.inventory.meta.FireworkMeta;
import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionEffectType;
import org.bukkit.scheduler.BukkitTask;
import org.bukkit.scoreboard.DisplaySlot;
import org.bukkit.scoreboard.Objective;
import org.bukkit.scoreboard.Scoreboard;
import java.util.*;
/**
* This file is a part of the UHCRun Project CodeBase
* Created by Thog
* (C) Copyright Thomas Guillemard 2016
* All rights reserved.
*/
public abstract class AbstractGame
{
protected final UHCRun plugin;
protected final GameAdaptator adaptator;
protected final Server server;
protected final List<Location> spawnPoints;
protected final HashMap<UUID, UHCPlayer> gamePlayers;
private final int preparingTime;
private final int deathMatchSize;
private final int reductionTime;
private final GameProperties properties;
private GameLoop gameLoop;
private Scoreboard scoreboard;
private boolean pvpEnabled;
private BukkitTask mainTask;
private boolean damages;
private Status status;
private BukkitTask beginTimer;
private MessageManager messageManager;
public AbstractGame(UHCRun plugin, GameProperties properties)
{
this.status = Status.STARTING;
this.plugin = plugin;
this.adaptator = plugin.getAdaptator();
this.server = plugin.getServer();
this.spawnPoints = new ArrayList<>();
this.gamePlayers = new HashMap<>();
this.beginTimer = Bukkit.getScheduler().runTaskTimerAsynchronously(plugin, new eu.thog.uhcrun.compatibility.TimerTask(this), 20L, 20L);
this.messageManager = new MessageManager(this);
UHCPlayer.setGame(this);
this.properties = properties;
this.preparingTime = ((Double) plugin.getProperties().getOption("preparingTime", 20D)).intValue();
this.deathMatchSize = ((Double) plugin.getProperties().getOption("deathMatchSize", 400D)).intValue();
this.reductionTime = ((Double) plugin.getProperties().getOption("reductionTime", 10D)).intValue();
}
public void postInit(World world)
{
this.scoreboard = server.getScoreboardManager().getMainScoreboard();
this.gameLoop = new GameLoop(this, plugin, server);
this.disableDamages();
this.computeLocations(world);
}
private void computeLocations(World world)
{
spawnPoints.add(new Location(world, 0, 150, 200));
spawnPoints.add(new Location(world, 0, 150, 400));
spawnPoints.add(new Location(world, 200, 150, 0));
spawnPoints.add(new Location(world, 400, 150, 0));
spawnPoints.add(new Location(world, 400, 150, 200));
spawnPoints.add(new Location(world, 200, 150, 400));
spawnPoints.add(new Location(world, 400, 150, 400));
spawnPoints.add(new Location(world, 200, 150, 200));
spawnPoints.add(new Location(world, 0, 150, -200));
spawnPoints.add(new Location(world, 0, 150, -400));
spawnPoints.add(new Location(world, -200, 150, 0));
spawnPoints.add(new Location(world, -400, 150, 0));
spawnPoints.add(new Location(world, -400, 150, -200));
spawnPoints.add(new Location(world, -200, 150, -400));
spawnPoints.add(new Location(world, -400, 150, -400));
spawnPoints.add(new Location(world, -200, 150, -200));
spawnPoints.add(new Location(world, 400, 150, -200));
spawnPoints.add(new Location(world, -400, 150, 200));
spawnPoints.add(new Location(world, 200, 150, -400));
spawnPoints.add(new Location(world, -200, 150, 400));
spawnPoints.add(new Location(world, -400, 150, 400));
spawnPoints.add(new Location(world, 400, 150, -400));
spawnPoints.add(new Location(world, 200, 150, -200));
Collections.shuffle(spawnPoints);
}
protected void removeFromGame(UUID uuid)
{
UHCPlayer player = this.gamePlayers.get(uuid);
if (player != null)
{
player.setSpectator();
}
}
public UHCRun getPlugin()
{
return plugin;
}
public void startGame()
{
setStatus(Status.IN_GAME);
this.beginTimer.cancel();
adaptator.removeSpawn();
Objective displayNameLife = scoreboard.getObjective("vie") == null ? scoreboard.registerNewObjective("vie", "health") : scoreboard.getObjective("vie");
Objective playerListLife = scoreboard.getObjective("vieb") == null ? scoreboard.registerNewObjective("vieb", "health") : scoreboard.getObjective("vieb");
playerListLife.setDisplayName(ChatColor.RED + "♥");
displayNameLife.setDisplayName("HP");
displayNameLife.setDisplaySlot(DisplaySlot.BELOW_NAME);
playerListLife.setDisplaySlot(DisplaySlot.PLAYER_LIST);
this.mainTask = server.getScheduler().runTaskTimer(plugin, gameLoop, 20, 20);
teleport();
for (UUID uuid : getOnlineInGamePlayers().keySet())
{
Player player = server.getPlayer(uuid);
if (player == null)
{
gamePlayers.remove(uuid);
continue;
}
player.setGameMode(GameMode.SURVIVAL);
player.setFoodLevel(20);
player.setScoreboard(scoreboard);
displayNameLife.getScore(player.getName()).setScore(20);
playerListLife.getScore(player.getName()).setScore(20);
player.setLevel(0);
player.getInventory().clear();
player.addPotionEffect(new PotionEffect(PotionEffectType.SPEED, 24000, 0));
ObjectiveSign sign = new ObjectiveSign("gameside", ChatColor.GOLD + "" + ChatColor.ITALIC + ChatColor.BOLD + "= UHCRun =", player);
gameLoop.addPlayer(player.getUniqueId(), sign);
}
server.getPluginManager().registerEvents(new ChunkListener(plugin), plugin);
SpawnerCreature spawner = new SpawnerCreature();
for (int i = 0; i < 3; i++)
{
spawner.a(MinecraftServer.getServer().getWorldServer(0), false, true, true); // Force spawning of passive annimals
}
}
public void rejoin(Player thePlayer)
{
if (thePlayer != null)
{
server.getScheduler().runTaskLater(plugin, () -> {
thePlayer.setScoreboard(this.scoreboard);
ObjectiveSign sign = new ObjectiveSign("gameside", ChatColor.GOLD + "" + ChatColor.ITALIC + ChatColor.BOLD + "= UHCRun =", thePlayer);
this.gameLoop.addPlayer(thePlayer.getUniqueId(), sign);
}, 10L);
}
}
public void stumpPlayer(Player player, boolean logout)
{
if (this.status == Status.IN_GAME)
{
Object lastDamager = Metadatas.getMetadata(plugin, player, "lastDamager");
Player killer = null;
if (lastDamager != null && lastDamager instanceof Player)
{
killer = (Player) lastDamager;
if (killer.isOnline() && this.isInGame(killer.getUniqueId()))
{
this.getPlayer(killer.getUniqueId()).addKill();
killer.addPotionEffect(new PotionEffect(PotionEffectType.ABSORPTION, 400, 1));
} else
{
killer = null;
}
}
if (logout)
{
messageManager.writeReconnectRemainTimeout(player);
} else if (killer != null)
{
server.broadcastMessage(this.getTag() + " " + player.getDisplayName() + ChatColor.GOLD + " a été tué par " + killer.getDisplayName());
} else
{
server.broadcastMessage(this.getTag() + " " + player.getDisplayName() + ChatColor.GOLD + " est mort.");
}
this.checkStump(player);
removeFromGame(player.getUniqueId());
if (!logout)
{
TitleAPI.sendTitle(player, 5, 70, 5, ChatColor.RED + "Vous êtes mort !", ChatColor.GOLD + "Vous êtes maintenant spectateur.");
player.setGameMode(GameMode.SPECTATOR);
player.setHealth(20.0D);
}
}
}
public boolean isInGame(UUID uniqueId)
{
return this.gamePlayers.containsKey(uniqueId) && !this.gamePlayers.get(uniqueId).isSpectator();
}
public abstract void checkStump(Player player);
protected abstract void teleport();
public abstract void teleportDeathMatch();
public int getPreparingTime()
{
return preparingTime;
}
public int getDeathMatchSize()
{
return deathMatchSize;
}
public int getReductionTime()
{
return reductionTime;
}
public void enablePVP()
{
this.pvpEnabled = true;
}
public boolean isPvpEnabled()
{
return pvpEnabled;
}
public void enableDamages()
{
this.damages = true;
}
public void disableDamages()
{
this.damages = false;
}
public boolean isDamagesEnabled()
{
return damages;
}
public GameLoop getGameLoop()
{
return gameLoop;
}
public void effectsOnWinner(Player player)
{
server.getScheduler().scheduleSyncRepeatingTask(plugin, new Runnable()
{
int timer = 0;
@Override
public void run()
{
if (this.timer < 20)
{
Firework fw = (Firework) player.getWorld().spawnEntity(player.getPlayer().getLocation(), EntityType.FIREWORK);
FireworkMeta fwm = fw.getFireworkMeta();
Random r = new Random();
int rt = r.nextInt(4) + 1;
FireworkEffect.Type type = FireworkEffect.Type.BALL;
if (rt == 1)
{
type = FireworkEffect.Type.BALL;
}
if (rt == 2)
{
type = FireworkEffect.Type.BALL_LARGE;
}
if (rt == 3)
{
type = FireworkEffect.Type.BURST;
}
if (rt == 4)
{
type = FireworkEffect.Type.CREEPER;
}
if (rt == 5)
{
type = FireworkEffect.Type.STAR;
}
int r1i = r.nextInt(15) + 1;
int r2i = r.nextInt(15) + 1;
Color c1 = Colors.getColor(r1i);
Color c2 = Colors.getColor(r2i);
FireworkEffect effect = FireworkEffect.builder().flicker(r.nextBoolean()).withColor(c1).withFade(c2).with(type).trail(r.nextBoolean()).build();
fwm.addEffect(effect);
int rp = r.nextInt(2) + 1;
fwm.setPower(rp);
fw.setFireworkMeta(fwm);
this.timer++;
}
}
}, 5L, 5L);
}
public void handleGameEnd()
{
this.interrupt();
}
public void interrupt()
{
this.mainTask.cancel();
server.getScheduler().runTaskLater(plugin, server::shutdown, 200L);
}
public GameProperties getGameProperties()
{
return properties;
}
public Status getStatus()
{
return status;
}
public void setStatus(Status status)
{
this.status = status;
}
public UHCPlayer getPlayer(UUID player)
{
return this.gamePlayers.get(player);
}
public Map<UUID, UHCPlayer> getOnlineInGamePlayers()
{
Map<UUID, UHCPlayer> result = new HashMap<>();
for (UUID uuid : this.gamePlayers.keySet())
{
final UHCPlayer uhcPlayer = this.gamePlayers.get(uuid);
if (!uhcPlayer.isSpectator())
{
result.put(uuid, uhcPlayer);
}
}
return result;
}
public String getTag()
{
return ChatColor.DARK_AQUA + "[" + ChatColor.AQUA + "UHCRun" + ChatColor.DARK_AQUA + "]" + ChatColor.RESET;
}
public boolean isGameStarted()
{
return this.status == Status.IN_GAME;
}
public BukkitTask getBeginTimer()
{
return beginTimer;
}
public MessageManager getMessageManager()
{
return messageManager;
}
public void handleJoin(PlayerJoinEvent event)
{
if (status == Status.WAITING_FOR_PLAYERS)
{
UHCPlayer player = new UHCPlayer(event.getPlayer());
this.gamePlayers.put(player.getUUID(), player);
player.handleLogin(event.getPlayer(), false);
} else if (this.isInGame(event.getPlayer().getUniqueId()))
{
this.getPlayer(event.getPlayer().getUniqueId()).handleLogin(event.getPlayer(), true);
}
}
public void handleLogin(PlayerLoginEvent event)
{
if (status == Status.WAITING_FOR_PLAYERS || this.isInGame(event.getPlayer().getUniqueId()))
{
event.allow();
} else
{
event.disallow(PlayerLoginEvent.Result.KICK_OTHER, "La partie est en cours!");
}
}
public void handleLogout(PlayerQuitEvent event)
{
UHCPlayer uhcPlayer = getPlayer(event.getPlayer().getUniqueId());
if (uhcPlayer != null)
{
uhcPlayer.handleLogout();
}
if (status != Status.IN_GAME)
{
this.gamePlayers.remove(event.getPlayer().getUniqueId());
}
}
}