Fix sidebars, implement vault api, coin pickups, and player respawning
This commit is contained in:
		
							
								
								
									
										8
									
								
								TODO.md
									
									
									
									
									
								
							
							
						
						
									
										8
									
								
								TODO.md
									
									
									
									
									
								
							| @@ -21,7 +21,7 @@ | ||||
| [X] Never hungry | ||||
| [X] Mobs don't drop bomb items | ||||
| [ ] Execute commands on game/wave end | ||||
| [ ] Player Respawning | ||||
| [X] Player Respawning | ||||
|  | ||||
| # QOL | ||||
|  | ||||
| @@ -33,7 +33,7 @@ | ||||
| [ ] Leave game when leaving game world | ||||
| [ ] Bomb and target glow different colors | ||||
| [ ] Play sound once bomb is close to / at target | ||||
| [ ] Expose coins under vault API | ||||
| [X] Expose coins under vault API | ||||
| [ ] Animations framework | ||||
|  | ||||
| # Malloc beta map | ||||
| @@ -60,7 +60,7 @@ | ||||
| [ ] Post-Round summary in chat | ||||
| [X] Clickable join links in /list | ||||
| [X] Sidebar | ||||
| [ ] Coin pickup messages in action bar | ||||
| [X] Coin pickup status in sidebar | ||||
| [ ] Target catches on fire more it is lit | ||||
| [ ] Colored titles | ||||
| [ ] Clickable /leave action | ||||
| @@ -123,7 +123,7 @@ | ||||
| [X] Restore health+hunger on respawn/game start | ||||
| [ ] /restart games | ||||
| [ ] Instancing | ||||
| [ ] Respawn during games | ||||
| [X] Respawn during games | ||||
| [ ] Player revival items | ||||
| [X] Clear inventory on join/leave | ||||
|  | ||||
|   | ||||
							
								
								
									
										6
									
								
								pom.xml
									
									
									
									
									
								
							
							
						
						
									
										6
									
								
								pom.xml
									
									
									
									
									
								
							| @@ -43,6 +43,12 @@ | ||||
|             <version>2.9.2</version> | ||||
|             <scope>provided</scope> | ||||
|         </dependency> | ||||
|         <dependency> | ||||
|             <groupId>com.github.MilkBowl</groupId> | ||||
|             <artifactId>VaultAPI</artifactId> | ||||
|             <version>1.7</version> | ||||
|             <scope>provided</scope> | ||||
|         </dependency> | ||||
|     </dependencies> | ||||
|      | ||||
| </project> | ||||
|   | ||||
							
								
								
									
										198
									
								
								src/main/java/gg/malloc/defense/GameEconomy.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										198
									
								
								src/main/java/gg/malloc/defense/GameEconomy.java
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,198 @@ | ||||
| package gg.malloc.defense; | ||||
|  | ||||
| import net.milkbowl.vault.economy.AbstractEconomy; | ||||
| import net.milkbowl.vault.economy.Economy; | ||||
| import net.milkbowl.vault.economy.EconomyResponse; | ||||
| import net.milkbowl.vault.economy.EconomyResponse.ResponseType; | ||||
|  | ||||
| import org.bukkit.plugin.ServicesManager; | ||||
| import org.bukkit.plugin.ServicePriority; | ||||
| import org.bukkit.entity.Player; | ||||
| import org.bukkit.OfflinePlayer; | ||||
|  | ||||
| import gg.malloc.defense.engine.GameRunner; | ||||
|  | ||||
| import java.util.List; | ||||
| import java.util.ArrayList; | ||||
|  | ||||
| public class GameEconomy extends AbstractEconomy { | ||||
|  | ||||
|   Plugin m_plugin; | ||||
|  | ||||
|   public GameEconomy(Plugin plugin) { | ||||
|     m_plugin = plugin; | ||||
|   } | ||||
|  | ||||
|   public void register() { | ||||
|     ServicesManager manager = m_plugin.getServer().getServicesManager(); | ||||
|     manager.register(Economy.class, this, m_plugin, ServicePriority.Highest); | ||||
|   } | ||||
|  | ||||
|   @Override | ||||
|   public EconomyResponse withdrawPlayer(String playerName, double amount) { | ||||
|     GameRunner runner = m_plugin.getRunnerForPlayer(playerName); | ||||
|     if (runner != null) { | ||||
|       Player p = m_plugin.getServer().getPlayer(playerName); | ||||
|       if (!has(playerName, amount)) { | ||||
|         int newBalance = runner.getState().getPlayerBalance(p); | ||||
|         return new EconomyResponse(amount, newBalance, ResponseType.FAILURE, "Not enough money!"); | ||||
|       } else { | ||||
|         runner.spendMoney(p, (int)Math.floor(amount)); | ||||
|         int newBalance = runner.getState().getPlayerBalance(p); | ||||
|         return new EconomyResponse(amount, newBalance, ResponseType.SUCCESS, ""); | ||||
|       } | ||||
|     } else { | ||||
|       return new EconomyResponse(0, 0, ResponseType.FAILURE, "Not in a game!"); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   @Override | ||||
|   public EconomyResponse depositPlayer(String playerName, double amount) { | ||||
|     GameRunner runner = m_plugin.getRunnerForPlayer(playerName); | ||||
|     if (runner != null) { | ||||
|       Player p = m_plugin.getServer().getPlayer(playerName); | ||||
|       runner.spendMoney(p, -(int)Math.floor(amount)); | ||||
|       int newBalance = runner.getState().getPlayerBalance(p); | ||||
|       return new EconomyResponse(amount, newBalance, ResponseType.SUCCESS, ""); | ||||
|     } else { | ||||
|       return new EconomyResponse(0, 0, ResponseType.FAILURE, "Not in a game!"); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   @Override | ||||
|   public double getBalance(String playerName) { | ||||
|     GameRunner runner = m_plugin.getRunnerForPlayer(playerName); | ||||
|     if (runner != null) { | ||||
|       Player p = m_plugin.getServer().getPlayer(playerName); | ||||
|       return runner.getState().getPlayerBalance(p); | ||||
|     } else { | ||||
|       return 0.0; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   @Override | ||||
|   public double getBalance(String playerName, String worldName) { | ||||
|     return getBalance(playerName); | ||||
|   } | ||||
|   @Override | ||||
|   public boolean isEnabled() { | ||||
|     return true; | ||||
|   } | ||||
|  | ||||
|   @Override | ||||
|   public String getName() { | ||||
|     return "Malloc Defense"; | ||||
|   } | ||||
|  | ||||
|   @Override | ||||
|   public boolean hasBankSupport() { | ||||
|     return false; | ||||
|   } | ||||
|  | ||||
|   @Override | ||||
|   public int fractionalDigits() { | ||||
|     return 0; | ||||
|   } | ||||
|  | ||||
|   @Override | ||||
|   public String format(double amount) { | ||||
|     return amount + " grist"; | ||||
|   } | ||||
|  | ||||
|   @Override | ||||
|   public String currencyNamePlural() { | ||||
|     return "Grist"; | ||||
|   } | ||||
|  | ||||
|   @Override | ||||
|   public String currencyNameSingular() { | ||||
|     return "Grist"; | ||||
|   } | ||||
|  | ||||
|   @Override | ||||
|   public boolean hasAccount(String playerName) { | ||||
|     return true; | ||||
|   } | ||||
|  | ||||
|   @Override | ||||
|   public boolean hasAccount(String playerName, String worldName) { | ||||
|     return hasAccount(playerName); | ||||
|   } | ||||
|  | ||||
|   @Override | ||||
|   public boolean has(String playerName, double amount) { | ||||
|     return getBalance(playerName) >= amount; | ||||
|   } | ||||
|  | ||||
|   @Override | ||||
|   public boolean has(String playerName, String worldName, double amount) { | ||||
|     return has(playerName, amount); | ||||
|   } | ||||
|  | ||||
|   @Override | ||||
|   public EconomyResponse withdrawPlayer(String playerName, String worldName, double amount) { | ||||
|     return withdrawPlayer(playerName, amount); | ||||
|   } | ||||
|  | ||||
|   @Override | ||||
|   public EconomyResponse depositPlayer(String playerName, String worldName, double amount) { | ||||
|     return depositPlayer(playerName, amount); | ||||
|   } | ||||
|  | ||||
|   private static final EconomyResponse NO_IMPL_RESPONSE = new EconomyResponse(0, 0, ResponseType.NOT_IMPLEMENTED, "Not implemented."); | ||||
|  | ||||
|   @Override | ||||
|   public EconomyResponse createBank(String name, String player) { | ||||
|     return NO_IMPL_RESPONSE; | ||||
|   } | ||||
|  | ||||
|   @Override | ||||
|   public EconomyResponse deleteBank(String name) { | ||||
|     return NO_IMPL_RESPONSE; | ||||
|   } | ||||
|  | ||||
|   @Override | ||||
|   public EconomyResponse bankBalance(String name) { | ||||
|     return NO_IMPL_RESPONSE; | ||||
|   } | ||||
|  | ||||
|   @Override | ||||
|   public EconomyResponse bankHas(String name, double amount) { | ||||
|     return NO_IMPL_RESPONSE; | ||||
|   } | ||||
|  | ||||
|   @Override | ||||
|   public EconomyResponse bankWithdraw(String name, double amount) { | ||||
|     return NO_IMPL_RESPONSE; | ||||
|   } | ||||
|  | ||||
|   @Override | ||||
|   public EconomyResponse bankDeposit(String name, double amount) { | ||||
|     return NO_IMPL_RESPONSE; | ||||
|   } | ||||
|  | ||||
|   @Override | ||||
|   public EconomyResponse isBankOwner(String name, String player) { | ||||
|     return NO_IMPL_RESPONSE; | ||||
|   } | ||||
|  | ||||
|   @Override | ||||
|   public EconomyResponse isBankMember(String name, String player) { | ||||
|     return NO_IMPL_RESPONSE; | ||||
|   } | ||||
|  | ||||
|   @Override | ||||
|   public boolean createPlayerAccount(String name) { | ||||
|     return true; | ||||
|   } | ||||
|  | ||||
|   @Override | ||||
|   public boolean createPlayerAccount(String name, String worldName) { | ||||
|     return true; | ||||
|   } | ||||
|  | ||||
|   @Override | ||||
|   public List<String> getBanks() { | ||||
|     return new ArrayList<String>(); | ||||
|   } | ||||
| } | ||||
| @@ -14,10 +14,16 @@ import org.bukkit.event.entity.EntityCombustEvent; | ||||
| import org.bukkit.event.entity.EntityTargetEvent; | ||||
| import org.bukkit.event.entity.FoodLevelChangeEvent; | ||||
| import org.bukkit.event.player.PlayerQuitEvent; | ||||
| import org.bukkit.event.player.PlayerPickupItemEvent; | ||||
| import org.bukkit.event.world.LootGenerateEvent; | ||||
| import org.bukkit.Sound; | ||||
| import org.bukkit.SoundCategory; | ||||
| import org.bukkit.inventory.ItemStack; | ||||
| import org.bukkit.entity.Player; | ||||
|  | ||||
| import de.tr7zw.nbtapi.NBTItem; | ||||
| import de.tr7zw.nbtapi.NBTCompound; | ||||
|  | ||||
| public class GameEventHandler implements Listener { | ||||
|   Collection<GameRunner> m_runners; | ||||
|  | ||||
| @@ -78,4 +84,25 @@ public class GameEventHandler implements Listener { | ||||
|   public void onFoodLevelChange(FoodLevelChangeEvent evt) { | ||||
|     evt.setCancelled(true); | ||||
|   } | ||||
|  | ||||
|   @EventHandler | ||||
|   public void onItemPickup(PlayerPickupItemEvent evt) { | ||||
|     NBTItem nbt = new NBTItem(evt.getItem().getItemStack()); | ||||
|     if (nbt.hasKey("malloc")) { | ||||
|       NBTCompound mallocData = nbt.getCompound("malloc"); | ||||
|       if (mallocData.hasKey("coinValue")) { | ||||
|         evt.setCancelled(true); | ||||
|         Player player = evt.getPlayer(); | ||||
|         int coinValue = mallocData.getInteger("coinValue") * evt.getItem().getItemStack().getAmount(); | ||||
|         player.getWorld().playSound(evt.getPlayer(), Sound.BLOCK_CHAIN_PLACE, SoundCategory.PLAYERS, (float)1.0, (float)1.0); | ||||
|         evt.getItem().remove(); | ||||
|         for(GameRunner runner : m_runners) { | ||||
|           if (runner.getPlayers().contains(player)) { | ||||
|             runner.depositCoins(coinValue); | ||||
|             return; | ||||
|           } | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| } | ||||
|   | ||||
| @@ -48,6 +48,7 @@ public class Plugin extends JavaPlugin { | ||||
|   HashMap<String, GameRunner> m_runningGames = new HashMap<>(); | ||||
|   HashMap<Player, GameRunner> m_playerGames = new HashMap<>(); | ||||
|   GameEventHandler m_handler = new GameEventHandler(); | ||||
|   GameEconomy m_economy = new GameEconomy(this); | ||||
|  | ||||
|   public Collection<String> arenaNames() { | ||||
|     return m_arenas.keySet(); | ||||
| @@ -75,6 +76,9 @@ public class Plugin extends JavaPlugin { | ||||
|  | ||||
|     getServer().getPluginManager().registerEvents(new PlayerQuitHandler(), this); | ||||
|     getServer().getPluginManager().registerEvents(m_handler, this); | ||||
|  | ||||
|     getLogger().info("Registering economy"); | ||||
|     m_economy.register(); | ||||
|   } | ||||
|  | ||||
|   public void onDisable() { | ||||
| @@ -159,6 +163,14 @@ public class Plugin extends JavaPlugin { | ||||
|     p.teleport(lobby.getSpawnLocation(), PlayerTeleportEvent.TeleportCause.PLUGIN); | ||||
|   } | ||||
|  | ||||
|   public GameRunner getRunnerForPlayer(String playerName) { | ||||
|     return getRunnerForPlayer(getServer().getPlayer(playerName)); | ||||
|   } | ||||
|  | ||||
|   public void removePlayerFromGames(Player player) { | ||||
|     m_playerGames.get(player).removePlayer(player); | ||||
|   } | ||||
|  | ||||
|   public GameRunner getRunnerForPlayer(Player p) { | ||||
|     GameRunner ret = null; | ||||
|     if (m_playerGames.containsKey(p)) { | ||||
|   | ||||
| @@ -26,6 +26,7 @@ public class LeaveGameCommand implements CommandExecutor { | ||||
|         return true; | ||||
|       } | ||||
|       runner.removePlayer(player); | ||||
|       m_plugin.removePlayerFromGames(player); | ||||
|       m_plugin.returnPlayerToLobby(player); | ||||
|     } else { | ||||
|       sender.sendMessage("Only players may use this command."); | ||||
|   | ||||
| @@ -66,6 +66,7 @@ public class GameRunner { | ||||
|   TickTask m_lobbyReturnTask; | ||||
|   TickTask m_bombSmokeTask; | ||||
|   TickTask m_bombCrackleTask; | ||||
|   TickTask m_playerRespawnTask; | ||||
|  | ||||
|   BossBars m_bars; | ||||
|   Sidebars m_sidebars; | ||||
| @@ -94,6 +95,10 @@ public class GameRunner { | ||||
|     validateGameRule(GameRule.SPECTATORS_GENERATE_CHUNKS, false); | ||||
|   } | ||||
|  | ||||
|   public GameState getState() { | ||||
|     return m_state; | ||||
|   } | ||||
|  | ||||
|   public GameRunner(Plugin plugin, Game game, Arena arena, World world) { | ||||
|     m_plugin = plugin; | ||||
|     m_game = game; | ||||
| @@ -120,6 +125,19 @@ public class GameRunner { | ||||
|       } | ||||
|     }, 80); | ||||
|  | ||||
|     m_playerRespawnTask = new TickTask(m_plugin, () -> { | ||||
|       m_players.tickRespawnCounters(); | ||||
|       for (Player p : m_players.getPlayers()) { | ||||
|         if (m_players.readyToRespawn(p)) { | ||||
|           if (m_players.requestTransition(p, PlayerManager.State.Playing)) { | ||||
|             sendRespawnTitle(p); | ||||
|             p.teleport(m_world.getSpawnLocation(), PlayerTeleportEvent.TeleportCause.PLUGIN); | ||||
|           } | ||||
|         } | ||||
|       } | ||||
|       m_bars.update(); | ||||
|     }, 20); | ||||
|  | ||||
|     m_countdownTask = new TickTask(m_plugin, () -> { | ||||
|       if (m_warmupCountdown == 0) { | ||||
|         requestTransition(Stage.Playing); | ||||
| @@ -176,6 +194,16 @@ public class GameRunner { | ||||
|     m_mobs.handleEntityRetarget(evt); | ||||
|   } | ||||
|  | ||||
|   public void spendMoney(Player p, int amount) { | ||||
|     m_players.addPlayerExpenses(p, amount); | ||||
|     m_sidebars.update(); | ||||
|   } | ||||
|  | ||||
|   public void depositCoins(int amount) { | ||||
|     m_state.addPickedUpCoins(amount); | ||||
|     m_sidebars.update(); | ||||
|   } | ||||
|  | ||||
|   public void handleEntityDamage(EntityDamageEvent evt) { | ||||
|     m_mobs.handleEntityDamage(evt); | ||||
|     if (m_mobs.bombWasHit() && !m_bombFuse.isExploded()) { | ||||
| @@ -229,6 +257,8 @@ public class GameRunner { | ||||
|     m_fuseTask.stop(); | ||||
|     m_countdownTask.stop(); | ||||
|     m_lobbyReturnTask.stop(); | ||||
|     m_playerRespawnTask.stop(); | ||||
|     m_state.resetBalances(); | ||||
|     return true; | ||||
|   } | ||||
|  | ||||
| @@ -253,6 +283,7 @@ public class GameRunner { | ||||
|       .create(); | ||||
|     broadcastMessage(message); | ||||
|     m_mobs.clear(); | ||||
|     m_playerRespawnTask.start(); | ||||
|     return true; | ||||
|   } | ||||
|  | ||||
| @@ -288,6 +319,7 @@ public class GameRunner { | ||||
|     m_warmupCountdown = 10; | ||||
|     m_bars.setCountdownProgress(1.0); | ||||
|     m_countdownTask.start(); | ||||
|     m_playerRespawnTask.start(); | ||||
|     return true; | ||||
|   } | ||||
|  | ||||
| @@ -302,6 +334,7 @@ public class GameRunner { | ||||
|     } | ||||
|     m_countdownTask.stop(); | ||||
|     m_fuseTask.start(); | ||||
|     m_playerRespawnTask.start(); | ||||
|     spawnNextBatch(); | ||||
|     return true; | ||||
|   } | ||||
| @@ -311,7 +344,7 @@ public class GameRunner { | ||||
|     m_lobbyReturnTask.start(); | ||||
|     m_countdownTask.stop(); | ||||
|     m_fuseTask.stop(); | ||||
|     //m_mobs.clear(); | ||||
|     m_playerRespawnTask.stop(); | ||||
|     return true; | ||||
|   } | ||||
|  | ||||
| @@ -330,7 +363,8 @@ public class GameRunner { | ||||
|   private void handlePlayerDeath(Player player) { | ||||
|     if (m_players.requestTransition(player, PlayerManager.State.Dead)) { | ||||
|       m_world.strikeLightningEffect(player.getLocation()); | ||||
|       if (!m_players.isAnyoneAlive()) { | ||||
|       //if (!m_players.isAnyoneAlive()) { | ||||
|       if (false) { | ||||
|         BaseComponent[] message = new ComponentBuilder() | ||||
|           .append("Everyone is ").color(ChatColor.LIGHT_PURPLE) | ||||
|           .append("DEAD").color(ChatColor.RED).bold(true) | ||||
| @@ -339,6 +373,14 @@ public class GameRunner { | ||||
|         broadcastMessage(message); | ||||
|         requestTransition(Stage.GameOver); | ||||
|       } else { | ||||
|         BaseComponent[] message = new ComponentBuilder() | ||||
|           .append(player.getName()) | ||||
|           .append(" has ").color(ChatColor.LIGHT_PURPLE) | ||||
|           .append("DIED!").color(ChatColor.RED).bold(true) | ||||
|           .append(" :(").color(ChatColor.LIGHT_PURPLE) | ||||
|           .create(); | ||||
|         broadcastMessage(message); | ||||
|         sendDeathTitle(player); | ||||
|         m_log.info("Remaining players " + m_players.remainingPlayers()); | ||||
|       } | ||||
|     } | ||||
| @@ -347,12 +389,15 @@ public class GameRunner { | ||||
|   public void handleEntityDeath(Entity entity) { | ||||
|     boolean wasCarrier = m_mobs.isBombCarrier(entity); | ||||
|     if (m_mobs.killMob(entity)) { | ||||
|       int COIN_STACK_SIZE = 5; | ||||
|       int coinsToDrop = 60; | ||||
|       while(coinsToDrop > 0) { | ||||
|         int droppedCoins = Math.min(coinsToDrop, 5); | ||||
|         int droppedCoins = Math.min(coinsToDrop, COIN_STACK_SIZE); | ||||
|         ItemStack coins = Items.makeCoins(); | ||||
|         coins.setAmount(droppedCoins); | ||||
|         coinsToDrop -= 64; | ||||
|         coinsToDrop -= droppedCoins; | ||||
|         m_state.addDroppedCoins(droppedCoins); | ||||
|         m_sidebars.update(); | ||||
|         m_world.dropItem(entity.getLocation(), coins); | ||||
|       } | ||||
|       m_bars.update(); | ||||
| @@ -433,6 +478,14 @@ public class GameRunner { | ||||
|     return false; | ||||
|   } | ||||
|  | ||||
|   void sendDeathTitle(Player p) { | ||||
|     p.sendTitle(ChatColor.RED.toString() + "You died!", "Wait to respawn..."); | ||||
|   } | ||||
|  | ||||
|   void sendRespawnTitle(Player p) { | ||||
|     p.sendTitle(ChatColor.AQUA.toString() + "Respawn", ""); | ||||
|   } | ||||
|  | ||||
|   void sendStageTitle(Player p) { | ||||
|     switch(m_stage) { | ||||
|       case Warmup: | ||||
| @@ -451,6 +504,7 @@ public class GameRunner { | ||||
|       return; | ||||
|     } | ||||
|     p.getInventory().clear(); | ||||
|     m_sidebars.addPlayer(p); | ||||
|     m_players.addPlayer(p); | ||||
|     m_bars.addPlayer(p); | ||||
|     if (m_stage == Stage.Idle || m_stage == Stage.Warmup) { | ||||
| @@ -471,6 +525,7 @@ public class GameRunner { | ||||
|  | ||||
|   public void removePlayer(Player p) { | ||||
|     p.getInventory().clear(); | ||||
|     m_sidebars.removePlayer(p); | ||||
|     m_bars.removePlayer(p); | ||||
|     m_players.removePlayer(p); | ||||
|     if (m_players.isEmpty()) { | ||||
|   | ||||
| @@ -4,6 +4,8 @@ import gg.malloc.defense.model.Game; | ||||
| import gg.malloc.defense.model.Progress; | ||||
| import gg.malloc.defense.model.State; | ||||
|  | ||||
| import org.bukkit.entity.Player; | ||||
|  | ||||
| public class GameState implements State { | ||||
|   GameRunner m_runner; | ||||
|   WaveManager m_waves; | ||||
| @@ -12,6 +14,9 @@ public class GameState implements State { | ||||
|   BombFuse m_fuse; | ||||
|   PlayerManager m_players; | ||||
|  | ||||
|   int m_coinsDropped; | ||||
|   int m_coinsPickedUp; | ||||
|  | ||||
|   public GameState(GameRunner runner, WaveManager waves, Game game, MobManager mobs, BombFuse fuse, PlayerManager players) { | ||||
|     m_runner = runner; | ||||
|     m_waves = waves; | ||||
| @@ -19,6 +24,47 @@ public class GameState implements State { | ||||
|     m_mobs = mobs; | ||||
|     m_fuse = fuse; | ||||
|     m_players = players; | ||||
|     m_coinsDropped = 0; | ||||
|     m_coinsPickedUp = 0; | ||||
|   } | ||||
|  | ||||
|   public int getRemainingCoins() { | ||||
|     return coinsDropped() - coinsPickedUp(); | ||||
|   } | ||||
|  | ||||
|   public int coinsDropped() { | ||||
|     return m_coinsDropped; | ||||
|   } | ||||
|  | ||||
|   public int coinsPickedUp() { | ||||
|     return m_coinsPickedUp; | ||||
|   } | ||||
|  | ||||
|   int INITIAL_BALANCE = 1500; | ||||
|  | ||||
|   public int getPlayerBalance(Player p) { | ||||
|     return coinsPickedUp() - m_players.getPlayerExpenses(p) + INITIAL_BALANCE; | ||||
|   } | ||||
|  | ||||
|   public void addDroppedCoins(int v) { | ||||
|     m_coinsDropped += v; | ||||
|   } | ||||
|  | ||||
|   public void addPickedUpCoins(int v) { | ||||
|     m_coinsPickedUp += v; | ||||
|   } | ||||
|  | ||||
|   public void resetBalances() { | ||||
|     m_coinsDropped = 0; | ||||
|     m_coinsPickedUp = 0; | ||||
|   } | ||||
|  | ||||
|   public Progress playerRespawnProgress(Player p) { | ||||
|     return m_players.getRespawnProgress(p); | ||||
|   } | ||||
|  | ||||
|   public Progress coinProgress() { | ||||
|     return new StaticProgress(m_coinsPickedUp, m_coinsDropped); | ||||
|   } | ||||
|  | ||||
|   public GameRunner.Stage getStage() { | ||||
|   | ||||
| @@ -16,6 +16,8 @@ import java.util.Collection; | ||||
| public class PlayerManager { | ||||
|   HashMap<Player, State> m_playerStates = new HashMap<>(); | ||||
|   HashMap<Player, Boolean> m_playerReadyStates = new HashMap<>(); | ||||
|   HashMap<Player, Integer> m_playerExpenses = new HashMap<>(); | ||||
|   HashMap<Player, Integer> m_respawnCounters = new HashMap<>(); | ||||
|  | ||||
|   public enum State { | ||||
|     Idle, | ||||
| @@ -68,22 +70,22 @@ public class PlayerManager { | ||||
|  | ||||
|   // Respawn player | ||||
|   public boolean enterPlaying(Player player) { | ||||
|     //m_log.fine("Respawning player " + player); | ||||
|     player.setGameMode(Bukkit.getDefaultGameMode()); | ||||
|     healPlayer(player); | ||||
|     return true; | ||||
|   } | ||||
|  | ||||
|   public boolean enterDead(Player player) { | ||||
|     //m_log.info("Player has died in game" + player); | ||||
|     player.setGameMode(GameMode.SPECTATOR); | ||||
|     m_respawnCounters.put(player, 15); | ||||
|     return true; | ||||
|   } | ||||
|  | ||||
|   public void addPlayer(Player player) { | ||||
|     //m_log.info("Adding player " + player);  | ||||
|     m_playerStates.put(player, State.Idle); | ||||
|     m_playerReadyStates.put(player, false); | ||||
|     m_playerExpenses.put(player, 0); | ||||
|     m_respawnCounters.put(player, 0); | ||||
|   } | ||||
|  | ||||
|   public boolean isReady(Player player) { | ||||
| @@ -111,14 +113,53 @@ public class PlayerManager { | ||||
|       } | ||||
|     } | ||||
|     return true; | ||||
|    | ||||
|   } | ||||
|  | ||||
|   public Progress getRespawnProgress(Player player) { | ||||
|     return new StaticProgress(m_respawnCounters.get(player), 15); | ||||
|   } | ||||
|  | ||||
|   public int getRespawnCounter(Player player) { | ||||
|     if (m_respawnCounters.containsKey(player)) { | ||||
|       return m_respawnCounters.get(player); | ||||
|     } else { | ||||
|       return 0; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   public void tickRespawnCounters() { | ||||
|     for(Player p : m_respawnCounters.keySet()) { | ||||
|       if (m_respawnCounters.get(p) > 0) { | ||||
|         m_respawnCounters.put(p, m_respawnCounters.get(p) - 1); | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   public boolean readyToRespawn(Player player) { | ||||
|     return m_respawnCounters.get(player) == 0 && m_playerStates.get(player) == State.Dead; | ||||
|   } | ||||
|  | ||||
|   public void addPlayerExpenses(Player player, int amount) { | ||||
|     if (m_playerExpenses.containsKey(player)) { | ||||
|       m_playerExpenses.put(player, m_playerExpenses.get(player) + amount); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   public int getPlayerExpenses(Player player) { | ||||
|     if (m_playerExpenses.containsKey(player)) { | ||||
|       return m_playerExpenses.get(player); | ||||
|     } | ||||
|     return 0; | ||||
|   } | ||||
|  | ||||
|   public boolean removePlayer(Player player) { | ||||
|     //m_log.info("Removing player " + player);  | ||||
|     healPlayer(player); | ||||
|     requestTransition(player, State.Idle); | ||||
|     m_playerStates.remove(player); | ||||
|     m_playerReadyStates.remove(player); | ||||
|     m_playerExpenses.remove(player); | ||||
|     m_respawnCounters.remove(player); | ||||
|     return true; | ||||
|   } | ||||
|  | ||||
|   | ||||
| @@ -4,6 +4,9 @@ public interface Progress { | ||||
|  | ||||
|   int value(); | ||||
|   int maximum(); | ||||
|   default int remaining() { | ||||
|     return maximum() - value(); | ||||
|   } | ||||
|   default double toDouble() { | ||||
|     return Math.min(maximum(), Math.max(0.0, value())) / maximum(); | ||||
|   } | ||||
|   | ||||
| @@ -2,6 +2,8 @@ package gg.malloc.defense.model; | ||||
|  | ||||
| import gg.malloc.defense.engine.GameRunner; | ||||
|  | ||||
| import org.bukkit.entity.Player; | ||||
|  | ||||
| public interface State { | ||||
|   GameRunner.Stage getStage(); | ||||
|  | ||||
| @@ -9,4 +11,8 @@ public interface State { | ||||
|   Progress waveProgress(); | ||||
|   Progress mobProgress(); | ||||
|   Progress playerReadyProgress(); | ||||
|   Progress coinProgress(); | ||||
|  | ||||
|   Progress playerRespawnProgress(Player p); | ||||
|   int getPlayerBalance(Player p); | ||||
| } | ||||
|   | ||||
| @@ -2,6 +2,9 @@ package gg.malloc.defense.ui; | ||||
|  | ||||
| import gg.malloc.defense.model.Game; | ||||
| import gg.malloc.defense.model.State; | ||||
| import gg.malloc.defense.model.Progress; | ||||
|  | ||||
| import java.util.HashMap; | ||||
|  | ||||
| import org.bukkit.boss.BossBar; | ||||
| import org.bukkit.boss.BarStyle; | ||||
| @@ -13,6 +16,7 @@ public class BossBars { | ||||
|   BossBar m_gameBar = Bukkit.createBossBar("Malloc Defense", BarColor.PURPLE, BarStyle.SOLID); | ||||
|   BossBar m_waveBar = Bukkit.createBossBar("Malloc Defense", BarColor.PURPLE, BarStyle.SOLID); | ||||
|   BossBar m_bombBar = Bukkit.createBossBar("Bomb Fuse", BarColor.RED, BarStyle.SOLID); | ||||
|   HashMap<Player, BossBar> m_respawnBars = new HashMap<>(); | ||||
|  | ||||
|   State m_gameState; | ||||
|  | ||||
| @@ -33,12 +37,20 @@ public class BossBars { | ||||
|     m_gameBar.addPlayer(p); | ||||
|     m_waveBar.addPlayer(p); | ||||
|     m_bombBar.addPlayer(p); | ||||
|     BossBar respawnBar = Bukkit.createBossBar("Respawn", BarColor.BLUE, BarStyle.SOLID); | ||||
|     respawnBar.addPlayer(p); | ||||
|     respawnBar.setVisible(false); | ||||
|     m_respawnBars.put(p, respawnBar); | ||||
|   } | ||||
|  | ||||
|   public void removePlayer(Player p) { | ||||
|     m_gameBar.removePlayer(p); | ||||
|     m_waveBar.removePlayer(p); | ||||
|     m_bombBar.removePlayer(p); | ||||
|     if (m_respawnBars.containsKey(p)) { | ||||
|       m_respawnBars.get(p).removePlayer(p); | ||||
|       m_respawnBars.remove(p); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   public void update() { | ||||
| @@ -100,5 +112,15 @@ public class BossBars { | ||||
|         m_bombBar.setVisible(false); | ||||
|         break; | ||||
|     } | ||||
|     for (Player p : m_respawnBars.keySet()) { | ||||
|       Progress respawnProgress = m_gameState.playerRespawnProgress(p); | ||||
|       if (respawnProgress.value() > 0) { | ||||
|         m_respawnBars.get(p).setVisible(true); | ||||
|         m_respawnBars.get(p).setProgress(respawnProgress.toDouble()); | ||||
|         m_respawnBars.get(p).setTitle("Respawning in " + respawnProgress.value()); | ||||
|       } else { | ||||
|         m_respawnBars.get(p).setVisible(false); | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| } | ||||
|   | ||||
| @@ -12,6 +12,7 @@ import org.bukkit.scoreboard.DisplaySlot; | ||||
| import org.bukkit.scoreboard.Score; | ||||
| import org.bukkit.scoreboard.Team; | ||||
| import org.bukkit.scoreboard.Objective; | ||||
| import org.bukkit.entity.Player; | ||||
|  | ||||
| public class Sidebar { | ||||
|   Scoreboard m_scoreboard; | ||||
| @@ -19,12 +20,14 @@ public class Sidebar { | ||||
|   ArrayList<String> m_rowKeys; | ||||
|   HashMap<Integer, String> m_rows; | ||||
|   ArrayList<Team> m_teams; | ||||
|   Player m_player; | ||||
|   int m_size; | ||||
|  | ||||
|   State m_state; | ||||
|  | ||||
|   public Sidebar(State state, Scoreboard scoreboard) { | ||||
|   public Sidebar(State state, Scoreboard scoreboard, Player player) { | ||||
|     m_state = state; | ||||
|     m_player = player; | ||||
|     m_scoreboard = scoreboard; | ||||
|     m_objective = m_scoreboard.registerNewObjective("text", "dummy", ChatColor.LIGHT_PURPLE + "" + ChatColor.BOLD + "Malloc Defense"); | ||||
|     m_objective.setDisplaySlot(DisplaySlot.SIDEBAR); | ||||
| @@ -34,6 +37,7 @@ public class Sidebar { | ||||
|     m_rowKeys.add(ChatColor.BLACK + "" + ChatColor.WHITE); | ||||
|     m_rowKeys.add(ChatColor.GOLD+ "" + ChatColor.WHITE); | ||||
|     m_rowKeys.add(ChatColor.WHITE+ "" + ChatColor.WHITE); | ||||
|     m_rowKeys.add(ChatColor.BLACK+ "" + ChatColor.BLACK); | ||||
|     for(String key : m_rowKeys) { | ||||
|       Team team = m_scoreboard.registerNewTeam(key); | ||||
|       team.addEntry(key); | ||||
| @@ -50,20 +54,23 @@ public class Sidebar { | ||||
|       case Warmup: | ||||
|         m_rows.put(0, ChatColor.LIGHT_PURPLE + "Wave " + m_state.waveProgress().value() + " / " + m_state.waveProgress().maximum()); | ||||
|         m_rows.put(1, ChatColor.AQUA + "Get ready!"); | ||||
|         m_rows.put(2, ChatColor.AQUA + "Balance: "); | ||||
|         m_size = 3; | ||||
|         m_rows.put(2, ChatColor.AQUA + "Balance: " + m_state.getPlayerBalance(m_player)); | ||||
|         m_rows.put(3, ChatColor.AQUA + "Coins remaining: " + m_state.coinProgress().remaining()); | ||||
|         m_size = 4; | ||||
|         break; | ||||
|       case Countdown: | ||||
|         m_rows.put(0, ChatColor.LIGHT_PURPLE + "Wave " + m_state.waveProgress().value() + " / " + m_state.waveProgress().maximum()); | ||||
|         m_rows.put(1, ChatColor.GOLD + "Wave incoming!"); | ||||
|         m_rows.put(2, ChatColor.AQUA + "Balance: "); | ||||
|         m_size = 3; | ||||
|         m_rows.put(2, ChatColor.AQUA + "Balance: " + m_state.getPlayerBalance(m_player)); | ||||
|         m_rows.put(3, ChatColor.AQUA + "Coins remaining: " + m_state.coinProgress().remaining()); | ||||
|         m_size = 4; | ||||
|         break; | ||||
|       case Playing: | ||||
|         m_rows.put(0, ChatColor.LIGHT_PURPLE + "Wave " + m_state.waveProgress().value() + " / " + m_state.waveProgress().maximum()); | ||||
|         m_rows.put(1, ChatColor.GREEN + "Mobs remaining: " + (m_state.mobProgress().maximum() - m_state.mobProgress().value())); | ||||
|         m_rows.put(2, ChatColor.AQUA + "Balance: "); | ||||
|         m_size = 3; | ||||
|         m_rows.put(1, ChatColor.GREEN + "Mobs remaining: " + m_state.mobProgress().remaining()); | ||||
|         m_rows.put(2, ChatColor.AQUA + "Balance: " + m_state.getPlayerBalance(m_player)); | ||||
|         m_rows.put(3, ChatColor.AQUA + "Coins remaining: " + m_state.coinProgress().remaining()); | ||||
|         m_size = 4; | ||||
|         break; | ||||
|       case GameOver: | ||||
|         m_rows.put(0, ChatColor.RED + "Game over!"); | ||||
|   | ||||
| @@ -18,7 +18,7 @@ public class Sidebars { | ||||
|   } | ||||
|  | ||||
|   public void addPlayer(Player player) { | ||||
|     m_sidebars.put(player, new Sidebar(m_state, m_scoreboards.getNewScoreboard())); | ||||
|     m_sidebars.put(player, new Sidebar(m_state, m_scoreboards.getNewScoreboard(), player)); | ||||
|     player.setScoreboard(m_sidebars.get(player).getScoreboard()); | ||||
|   } | ||||
|  | ||||
|   | ||||
| @@ -2,7 +2,7 @@ name: Malloc-Defense | ||||
| version: 1.0 | ||||
| api-version: 1.18 | ||||
| main: gg.malloc.defense.Plugin | ||||
| depend:  [] | ||||
| depend:  [Vault] | ||||
| commands: | ||||
|   ready: | ||||
|     description: Mark yourself as ready for the next wave | ||||
|   | ||||
		Reference in New Issue
	
	Block a user