package com.github.jamesnorris.ablockalypse.aspect; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import org.bukkit.Bukkit; import org.bukkit.ChatColor; import org.bukkit.Chunk; import org.bukkit.GameMode; import org.bukkit.Location; import org.bukkit.entity.Entity; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; import org.bukkit.potion.PotionEffect; import org.bukkit.potion.PotionEffectType; import com.github.jamesnorris.ablockalypse.Ablockalypse; import com.github.jamesnorris.ablockalypse.ItemManager; import com.github.jamesnorris.ablockalypse.enumerated.PlayerStatus; import com.github.jamesnorris.ablockalypse.enumerated.PowerupType; import com.github.jamesnorris.ablockalypse.enumerated.Setting; import com.github.jamesnorris.ablockalypse.enumerated.ZAPerk; import com.github.jamesnorris.ablockalypse.enumerated.ZASound; import com.github.jamesnorris.ablockalypse.event.LastStandEvent; import com.github.jamesnorris.ablockalypse.event.PlayerJoinGameEvent; import com.github.jamesnorris.ablockalypse.event.bukkit.PlayerJoin; import com.github.jamesnorris.ablockalypse.threading.inherent.LastStandFallenTask; import com.github.jamesnorris.ablockalypse.utility.BuyableItemData; import com.github.jamesnorris.ablockalypse.utility.SerialLocation; public class ZAPlayer extends ZACharacter { private Player player; private Game game; private PlayerStatus status = PlayerStatus.NORMAL; private List<ZAPerk> perks = new ArrayList<ZAPerk>(); private double pointGainModifier = 1, pointLossModifier = 1; private PlayerState beforeGame, beforeLS; private int points, kills; private boolean sentIntoGame, instakill, removed; @SuppressWarnings("unchecked") public ZAPlayer(Map<String, Object> savings) { super(savings); player = super.getPlayer(); game = super.getGame(); status = super.getStatus(); Map<String, Object> beforeGameState = (Map<String, Object>) savings.get("before_game_state"); if (beforeGameState != null) { beforeGame = new PlayerState(beforeGameState); } Map<String, Object> beforeLSState = (Map<String, Object>) savings.get("before_last_stand_state"); if (beforeLSState != null) { beforeLS = new PlayerState(beforeLSState); } if (!player.isOnline()) { PlayerJoin.queuePlayer(this, SerialLocation.returnLocation((SerialLocation) savings.get("player_in_game_location")), savings); return; } removed = false; loadSavedVersion(savings); } public ZAPlayer(Player player, Game game) { super(player, game); this.player = player; this.game = game; } public void addKills(int kills) { this.kills += kills; } public void addPerk(ZAPerk perk) { if (hasPerk(perk)) { return;// prevents recursion } perks.add(perk); perk.givePerk(this); } public void addPoints(int points) { this.points += points * pointGainModifier; } public void clearPerks() { for (ZAPerk perk : perks) { perk.removePerk(this); } perks.clear(); } public void decrementKills() { subtractKills(1); } public int getKills() { return kills; } @Override public int getLoadPriority() { return 1; } public List<ZAPerk> getPerks() { return perks; } public double getPointGainModifier() { return pointGainModifier; } public double getPointLossModifier() { return pointLossModifier; } public int getPoints() { return points; } @Override public Map<String, Object> getSave() { Map<String, Object> savings = new HashMap<String, Object>(); savings.put("uuid", getUUID()); savings.put("game_name", game.getName()); savings.put("points", points); savings.put("kills", kills); savings.put("point_gain_modifier", pointGainModifier); savings.put("point_loss_modifier", pointLossModifier); if (beforeGame != null) { savings.put("before_game_state", beforeGame.getSave()); } if (beforeLS != null) { savings.put("before_last_stand_state", beforeLS.getSave()); } List<Integer> perkIds = new ArrayList<Integer>(); for (ZAPerk perk : perks) { perkIds.add(perk.getId()); } savings.put("perk_ids", perkIds); savings.put("has_been_sent_into_the_game", sentIntoGame); savings.put("has_instakill", instakill); savings.put("player_in_game_location", player == null ? null : new SerialLocation(player.getLocation())); savings.putAll(super.getSave()); return savings; } public void giveItem(ItemStack item) { Ablockalypse.getExternal().getItemFileManager().giveItem(player, item); } public void givePowerup(PowerupType type, Entity cause) { type.play(game, player, cause, data); } public boolean hasBeenSentIntoGame() { return sentIntoGame; } public boolean hasInstaKill() { return instakill; } public boolean hasPerk(ZAPerk perk) { return perks.contains(perk); } public void incrementKills() { addKills(1); } public boolean isInLastStand() { return status == PlayerStatus.LAST_STAND; } public boolean isInLimbo() { return status == PlayerStatus.LIMBO; } public boolean isTeleporting() { return status == PlayerStatus.TELEPORTING; } public void loadPlayerToGame(String name, boolean showMessages) { /* Use an old game to add the player to the game */ if (data.isGame(name)) { Game zag = data.getGame(name, false); PlayerJoinGameEvent GPJE = new PlayerJoinGameEvent(this, zag); Bukkit.getPluginManager().callEvent(GPJE); if (!GPJE.isCancelled()) { int max = (Integer) Setting.MAX_PLAYERS.getSetting(); if (zag.getPlayers().size() < max) { if (game.getMainframe() == null) { Teleporter newMainframe = new Teleporter(game, player.getLocation().clone().subtract(0, 1, 0)); game.setMainframe(newMainframe); newMainframe.setBlinking(false); } removed = false; zag.addPlayer(player); prepare(); sendToMainframe(showMessages ? ChatColor.GRAY + "Teleporting to mainframe..." : null, "Loading player to a game"); if (showMessages) { player.sendMessage(ChatColor.GRAY + "You have joined the game: " + name); } return; } else { if (showMessages) { player.sendMessage(ChatColor.RED + "This game has " + max + "/" + max + " players!"); } } } } else if (showMessages) { player.sendMessage(ChatColor.RED + "That game does not exist!"); } } public void loadSavedVersion(Map<String, Object> savings) { points = (Integer) savings.get("points"); kills = (Integer) savings.get("kills"); pointGainModifier = (Integer) savings.get("point_gain_modifier"); pointLossModifier = (Integer) savings.get("point_loss_modifier"); List<ItemStack> stacks = new ArrayList<ItemStack>(); @SuppressWarnings("unchecked") List<Map<String, Object>> serialStacks = (List<Map<String, Object>>) savings.get("inventory"); for (Map<String, Object> serialStack : serialStacks) { stacks.add(ItemStack.deserialize(serialStack)); } player.getInventory().setContents(stacks.toArray(new ItemStack[stacks.size()])); List<ZAPerk> loadedPerks = new ArrayList<ZAPerk>(); @SuppressWarnings("unchecked") List<Integer> perkIds = (List<Integer>) savings.get("perk_ids"); for (Integer id : perkIds) { loadedPerks.add(ZAPerk.getById(id)); } perks = loadedPerks; sentIntoGame = (Boolean) savings.get("has_been_sent_into_the_game"); instakill = (Boolean) savings.get("has_instakill"); } @Override public void onGameEnd() { player.sendMessage(ChatColor.BOLD + "" + ChatColor.GRAY + "The game has ended. You made it to level " + game.getLevel()); ZASound.END.play(player.getLocation()); game.removePlayer(player); } @Override public void onLevelEnd() { ZASound.PREV_LEVEL.play(player.getLocation()); //@formatter:off player.sendMessage(ChatColor.BOLD + "Level " + ChatColor.RESET + ChatColor.RED + game.getLevel() + ChatColor.RESET + ChatColor.BOLD + " over... Next level: " + ChatColor.RED + (game.getLevel() + 1) + "\n" + ChatColor.RESET + ChatColor.BOLD + "Time to next level: " + ChatColor.RED + Setting.LEVEL_TRANSITION_TIME.getSetting() + ChatColor.RESET + ChatColor.BOLD + " seconds."); //@formatter:on // showPoints();//with the new scoreboard, there is not longer any need } @Override public void onNextLevel() { int level = game.getLevel(); if (level != 0) { player.setLevel(level); player.sendMessage(ChatColor.BOLD + "Level " + ChatColor.RESET + ChatColor.RED + level + ChatColor.RESET + ChatColor.BOLD + " has started."); if (level != 1) { showPoints(); } } } @Override public void remove() { if (removed) { return;// prevents recursion with ZAMob.kill(), which calls game.removeObject(), which calls this, which calls ZAMob.kill()... you get the idea } restoreStatus(); game = null; super.remove(); removed = true; } public void removeFromGame() { if (removed) { return;// prevents recursion with remove() } remove(); } public void removePerk(ZAPerk perk) { if (!hasPerk(perk)) { return;// prevents recursion } perks.remove(perk); perk.removePerk(this); } @Override public void sendToMainframe(String message, String reason) { if (message != null) { player.sendMessage(message); } Location loc = game.getMainframe().getLocation().clone().add(0, 1, 0); Chunk c = loc.getChunk(); if (!c.isLoaded()) { c.load(); } player.teleport(loc); if (!sentIntoGame) { ZASound.START.play(loc); sentIntoGame = true; } else { ZASound.TELEPORT.play(loc); } if ((Boolean) Setting.DEBUG.getSetting()) { System.out.println("[Ablockalypse] [DEBUG] Mainframe TP reason: (" + game.getName() + ") " + reason); } } public void setInstaKill(boolean instakill) { this.instakill = instakill; } public void setKills(int kills) { this.kills = kills; } public void setPointGainModifier(double modifier) { pointGainModifier = modifier; } public void setPointLossModifier(double modifier) { pointLossModifier = modifier; } public void setPoints(int points) { double modifier = 1; if (points > this.points) { modifier = pointGainModifier; } else if (points < this.points) { modifier = pointLossModifier; } this.points = (int) Math.round(points * modifier); } public void setSentIntoGame(boolean sent) { sentIntoGame = sent; } public void showPoints() { for (ZAPlayer zap2 : game.getPlayers()) { Player p2 = zap2.getPlayer(); player.sendMessage(ChatColor.RED + p2.getName() + ChatColor.RESET + " - " + ChatColor.GRAY + zap2.getPoints()); } } public void subtractKills(int kills) { if (this.kills < kills) { this.kills = 0; return; } this.kills -= kills; } public void subtractPoints(int points) { if (this.points < points * pointLossModifier) { this.points = 0; return; } this.points -= points * pointLossModifier; } public void toggleLastStand() { if (status != PlayerStatus.LAST_STAND) { sitDown(); } else { pickUp(); } } private void pickUp() { LastStandEvent lse = new LastStandEvent(player, this, false); Bukkit.getServer().getPluginManager().callEvent(lse); if (!lse.isCancelled()) { beforeLS.update(); player.sendMessage(ChatColor.GRAY + "You have been picked up!"); game.broadcast(ChatColor.RED + player.getName() + ChatColor.GRAY + " has been revived.", player); status = PlayerStatus.NORMAL; // Breakable.setSitting(player, false); getSeat().removePassenger(); getSeat().remove(); player.setCanPickupItems(true); if (player.getVehicle() != null) { player.getVehicle().remove(); } player.setFoodLevel(20); Entity v = player.getVehicle(); if (v != null) { v.remove(); } } } /* Saving the player status, so when the player is removed from the game, they are set back to where they were before. */ @SuppressWarnings("deprecation") private void prepare() { beforeGame = new PlayerState(player); ZASound.START.play(player.getLocation()); player.setGameMode(GameMode.SURVIVAL); player.getInventory().clear(); player.setLevel(game.getLevel()); player.setExp(0); player.setHealth(20); player.setFoodLevel(20); player.setSaturation(0); player.getActivePotionEffects().clear(); player.getInventory().setArmorContents(null); player.setSleepingIgnored(true); player.setFireTicks(0); player.setFallDistance(0F); player.setExhaustion(0F); ItemManager itemManager = Ablockalypse.getExternal().getItemFileManager(); if (itemManager != null && itemManager.getStartingItemsMap() != null) { Map<Integer, BuyableItemData> startingItems = itemManager.getStartingItemsMap(); for (int id : startingItems.keySet()) { itemManager.giveItem(player, startingItems.get(id).toItemStack()); } } rename("", player.getName(), "0"); player.updateInventory(); } /* Restoring the player status to the last saved status before the game. */ private void restoreStatus() { if (status == PlayerStatus.LAST_STAND) { toggleLastStand(); } for (PotionEffect pe : player.getActivePotionEffects()) { PotionEffectType pet = pe.getType(); player.removePotionEffect(pet); } player.setDisplayName(player.getName()); if (beforeGame != null) { beforeGame.update(); } } private void sitDown() { LastStandEvent lse = new LastStandEvent(player, this, true); Bukkit.getServer().getPluginManager().callEvent(lse); if (!lse.isCancelled()) { player.sendMessage(ChatColor.GRAY + "You have been knocked down!"); if (getGame().getRemainingPlayers().size() < 1 && (Boolean) Setting.END_ON_LAST_PLAYER_LAST_STAND.getSetting()) { removeFromGame(); return; } beforeLS = new PlayerState(player); status = PlayerStatus.LAST_STAND; Entity v = player.getVehicle(); if (v != null) { v.remove(); } rename("", player.getName(), "[LS]"); player.setFoodLevel(0); player.setHealth((Double) Setting.LAST_STAND_HEALTH_THRESHOLD.getSetting()); ZASound.LAST_STAND.play(player.getLocation()); getSeat().moveLocation(player.getLocation()); getSeat().sit(player); player.getInventory().clear(); player.setCanPickupItems(false); game.broadcast(ChatColor.RED + player.getName() + ChatColor.GRAY + " is down and needs revival", player); new LastStandFallenTask(this, true); if ((Boolean) Setting.LOSE_PERKS_ON_LAST_STAND.getSetting()) { clearPerks(); } } } }