More progress

This commit is contained in:
Sam 2017-06-30 12:57:20 +01:00
parent a8e1799617
commit 67d792e9d7
9 changed files with 829 additions and 187 deletions

View File

@ -242,7 +242,7 @@ public enum GameType
{
Pair.create(MinecraftVersion.Version1_8, "http://file.mineplex.com/ResStrikeGames18.zip"),
Pair.create(MinecraftVersion.Version1_9, "http://file.mineplex.com/ResStrikeGames19.zip")
}, false),
}, true),
Event(EventGame.class, GameDisplay.Event, new GameType[]{
GameType.BaconBrawl, GameType.Barbarians, GameType.Bridge, GameType.Build, GameType.Build,

View File

@ -16,6 +16,8 @@ import mineplex.core.itemstack.ItemBuilder;
import mineplex.core.recharge.Recharge;
import mineplex.core.updater.UpdateType;
import mineplex.core.updater.event.UpdateEvent;
import mineplex.minecraft.game.core.combat.CombatComponent;
import mineplex.minecraft.game.core.combat.event.CombatDeathEvent;
import mineplex.minecraft.game.core.damage.CustomDamageEvent;
import nautilus.game.arcade.ArcadeManager;
import nautilus.game.arcade.GameType;
@ -29,6 +31,7 @@ import nautilus.game.arcade.game.modules.chest.ChestLootPool;
import nautilus.game.arcade.game.modules.compass.CompassModule;
import nautilus.game.arcade.kit.Kit;
import org.bukkit.Bukkit;
import org.bukkit.Color;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.Sound;
@ -42,9 +45,22 @@ import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.entity.EntityDamageEvent.DamageCause;
import org.bukkit.event.entity.EntityExplodeEvent;
import org.bukkit.event.entity.EntityRegainHealthEvent;
import org.bukkit.event.entity.EntityRegainHealthEvent.RegainReason;
import org.bukkit.event.entity.PlayerDeathEvent;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.event.inventory.InventoryOpenEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.inventory.AnvilInventory;
import org.bukkit.inventory.EnchantingInventory;
import org.bukkit.inventory.FurnaceInventory;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionEffectType;
import org.bukkit.scheduler.BukkitRunnable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
@ -55,27 +71,55 @@ import java.util.concurrent.atomic.AtomicInteger;
public abstract class BattleRoyale extends Game
{
private static final long PREPARE_TIME = TimeUnit.SECONDS.toMillis(20);
private static final long PREPARE_TIME = TimeUnit.SECONDS.toMillis(30);
private static final int MIN_CORD = 100;
private static final int MAX_CORD = 1000;
private static final int SPAWN_Y = 130;
private static final int WORLD_SIZE_BUFFER = 300;
private static final int MIN_DISTANCE_APART_FOR_SPAWNS_SQUARED = 100;
private static final long MIN_DRAGON_TIME = TimeUnit.SECONDS.toMillis(5);
private static final long MAX_DRAGON_TIME = TimeUnit.SECONDS.toMillis(60);
private static final long BORDER_TIME = TimeUnit.MINUTES.toSeconds(20);
protected static final long SUPPLY_DROP_TIME = TimeUnit.MINUTES.toMillis(5);
private static final int MAX_DROPS_PER_GAME = 3;
private final Map<Player, BattleRoyalePlayer> _playerData = new HashMap<>(70);
private static final ItemStack SMALL_BACKPACK = new ItemBuilder(Material.CHEST)
.setTitle(C.cGreen + "Small Backpack")
.addLore("Clicking this will unlock a new row in your inventory!")
.build();
private static final ItemStack LARGE_BACKPACK = new ItemBuilder(Material.ENDER_CHEST)
.setTitle(C.cGreen + "Large Backpack")
.addLore("Clicking this will unlock two new rows in your inventory!")
.build();
private static final ItemStack SMALL_HEALTH_POT = new ItemBuilder(Material.POTION)
.setTitle(C.cGreen + "Small Health Pot")
.addPotionEffect(new PotionEffect(PotionEffectType.HEAL, 1, 0))
.build();
private static final ItemStack LARGE_HEALTH_POT = new ItemBuilder(Material.POTION)
.setTitle(C.cGreen + "Large Health Pot")
.addPotionEffect(new PotionEffect(PotionEffectType.HEAL, 1, 1))
.build();
protected final Map<Player, BattleRoyalePlayer> _playerData = new HashMap<>(70);
protected GunModule _gunModule;
protected WorldBorder _border;
private boolean _colouredMessage;
protected BattleRoyaleSupplyDrop _supplyDrop;
protected long _lastSupplyDrop;
private int _totalDrops;
public BattleRoyale(ArcadeManager manager, GameType gameType, Kit[] kits, String[] gameDesc)
{
super(manager, gameType, kits, gameDesc);
// TODO REMOVE THIS
TeleportsDisqualify = false;
TickPerTeleport = 20;
PrepareTime = PREPARE_TIME;
PrepareFreeze = false;
@ -114,14 +158,23 @@ public abstract class BattleRoyale extends Game
new CompassModule()
.register(this);
manager.GetCreature().SetDisableCustomDrops(true);
}
@Override
public void ParseData()
{
List<Location> chestSpawns = new ArrayList<>(500);
chestSpawns.addAll(WorldData.GetDataLocs("ORANGE"));
chestSpawns.addAll(WorldData.GetDataLocs("GREEN"));
chestSpawns.addAll(WorldData.GetDataLocs("YELLOW"));
chestSpawns.addAll(WorldData.GetDataLocs("BLUE"));
new ChestLootModule()
.destoryAfterOpened(20)
.spawnNearbyDataPoints()
.registerChestType("Standard", WorldData.GetDataLocs("ORANGE"),
.registerChestType("Standard", chestSpawns,
// Guns
new ChestLootPool()
@ -130,22 +183,76 @@ public abstract class BattleRoyale extends Game
.addItem(buildFromGun(GunStats.DEAGLE))
.addItem(buildFromGun(GunStats.P250))
.addItem(buildFromGun(GunStats.P2000))
.addItem(buildFromGun(GunStats.P90), 0.5)
.addItem(buildFromGun(GunStats.PPBIZON), 0.5)
.addItem(buildFromGun(GunStats.GALIL), 0.2)
.addItem(buildFromGun(GunStats.FAMAS), 0.2)
.addItem(buildFromGun(GunStats.AK47), 0.2)
.addItem(buildFromGun(GunStats.M4A4), 0.2)
.addItem(buildFromGun(GunStats.SG553), 0.2)
.addItem(buildFromGun(GunStats.AUG), 0.2)
.addItem(buildFromGun(GunStats.SSG08), 0.2)
.addItem(buildFromGun(GunStats.NOVA), 0.2)
.addItem(buildFromGun(GunStats.XM1014), 0.2)
.setProbability(0.4)
,
// Grenades
new ChestLootPool()
.addItem(buildGrenade(Material.CARROT_ITEM, "Flash Bang"))
.addItem(buildGrenade(Material.APPLE, "High Explosive"))
.addItem(buildGrenade(Material.POTATO_ITEM, "Smoke"))
.addItem(buildGrenade(Material.PORK, "Incendiary"), 0.5)
.addItem(buildGrenade(Material.GRILLED_PORK, "Molotov"), 0.5)
.setProbability(0.2)
,
// Weapons
new ChestLootPool()
.addItem(new ItemStack(Material.WOOD_SWORD))
.addItem(new ItemStack(Material.STONE_SWORD), 0.3)
.setProbability(0.5)
.addItem(new ItemStack(Material.BOW))
.setProbability(0.05)
,
// Ammo
new ChestLootPool()
.addItem(new ItemStack(Material.ARROW), 1, 8)
.setProbability(0.2)
.setAmountsPerChest(1, 3)
,
// Medical
new ChestLootPool()
.addItem(SMALL_HEALTH_POT)
.addItem(LARGE_HEALTH_POT)
.setProbability(0.2)
.setAmountsPerChest(1, 2)
,
// Armour
new ChestLootPool()
.addItem(new ItemStack(Material.LEATHER_HELMET))
.addItem(new ItemStack(Material.LEATHER_CHESTPLATE))
.addItem(new ItemBuilder(Material.LEATHER_HELMET)
.setTitle(C.cRed + "Red Baseball Cap")
.setColor(Color.RED)
.build())
.addItem(new ItemBuilder(Material.LEATHER_HELMET)
.setTitle(C.cAqua + "Blue Baseball Cap")
.setColor(Color.BLUE)
.build())
.addItem(new ItemBuilder(Material.CHAINMAIL_HELMET)
.setTitle(C.cDGreen + "Tactical Helmet")
.build())
.addItem(new ItemBuilder(Material.IRON_HELMET)
.setTitle(C.cDGreen + "Motorcycle Helmet")
.build())
.addItem(new ItemBuilder(Material.LEATHER_CHESTPLATE)
.setTitle(C.cDGreen + "Wooden Body Armour")
.build())
.addItem(new ItemBuilder(Material.CHAINMAIL_CHESTPLATE)
.setTitle(C.cDGreen + "Plated Body Armour")
.build())
.addItem(new ItemBuilder(Material.IRON_CHESTPLATE)
.setTitle(C.cDGreen + "Laminated Tactical Body Armour")
.build())
.addItem(new ItemStack(Material.LEATHER_LEGGINGS))
.addItem(new ItemStack(Material.LEATHER_BOOTS))
,
@ -167,9 +274,59 @@ public abstract class BattleRoyale extends Game
// Misc
new ChestLootPool()
.addItem(new ItemStack(Material.STRING), 1, 2, 0.5)
.addItem(new ItemStack(Material.STICK), 1, 2)
.addItem(new ItemStack(Material.FLINT), 1, 2)
.addItem(new ItemStack(Material.FEATHER), 1, 2)
.addItem(SMALL_BACKPACK, 0.5)
.addItem(LARGE_BACKPACK, 0.2)
.setProbability(0.2)
.setAmountsPerChest(1, 2)
)
.registerChestType("Supply Drop", new ArrayList<>(0),
// Guns
new ChestLootPool()
.addItem(buildFromGun(GunStats.AUG))
.addItem(buildFromGun(GunStats.AK47))
.addItem(buildFromGun(GunStats.M4A4))
.addItem(buildFromGun(GunStats.XM1014))
.addItem(buildFromGun(GunStats.AWP))
.setAmountsPerChest(1, 2)
,
// Backpack
new ChestLootPool()
.addItem(SMALL_BACKPACK)
.addItem(LARGE_BACKPACK)
,
// Armour
new ChestLootPool()
.addItem(new ItemBuilder(Material.IRON_HELMET)
.setTitle(C.cDGreen + "Motorcycle Helmet")
.build())
.addItem(new ItemBuilder(Material.IRON_CHESTPLATE)
.setTitle(C.cDGreen + "Laminated Tactical Body Armour")
.build())
,
// Grenades
new ChestLootPool()
.addItem(buildGrenade(Material.CARROT_ITEM, "Flash Bang"))
.addItem(buildGrenade(Material.APPLE, "High Explosive"))
.addItem(buildGrenade(Material.POTATO_ITEM, "Smoke"))
.addItem(buildGrenade(Material.PORK, "Incendiary"), 0.5)
.addItem(buildGrenade(Material.GRILLED_PORK, "Molotov"), 0.5)
.setAmountsPerChest(1, 2)
,
// Medical
new ChestLootPool()
.addItem(SMALL_HEALTH_POT)
.addItem(LARGE_HEALTH_POT)
.setAmountsPerChest(1, 2)
)
.register(this);
WorldData.MinX = -MAX_CORD;
@ -187,6 +344,19 @@ public abstract class BattleRoyale extends Game
.build();
}
private ItemStack buildGrenade(Material material, String name)
{
return new ItemBuilder(material)
.setTitle(C.cDGreenB + name)
.build();
}
@Override
@EventHandler
public void ScoreboardUpdate(UpdateEvent event)
{
}
@EventHandler
public void prepare(GameStateChangeEvent event)
{
@ -252,7 +422,7 @@ public abstract class BattleRoyale extends Game
index.getAndIncrement();
}
}, 100, 2);
}, 200, 2);
}
private Location getPlayerSpawn(int initialXZ)
@ -296,7 +466,7 @@ public abstract class BattleRoyale extends Game
while (attempts++ < 20)
{
Location location = UtilAlg.getRandomLocation(GetSpectatorLocation(), 200, 0, 200);
Location location = UtilAlg.getRandomLocation(GetSpectatorLocation(), WORLD_SIZE_BUFFER, 0, WORLD_SIZE_BUFFER);
Block block = location.getBlock();
while (!UtilBlock.solid(block))
@ -309,10 +479,7 @@ public abstract class BattleRoyale extends Game
continue;
}
if (UtilBlock.airFoliage(UtilBlock.getHighest(location.getWorld(), location.getBlock())))
{
return location;
}
return location;
}
return SpectatorSpawn;
@ -326,12 +493,23 @@ public abstract class BattleRoyale extends Game
return;
}
_lastSupplyDrop = System.currentTimeMillis();
CreatureAllowOverride = true;
ItemStack locked = new ItemBuilder(Material.STAINED_GLASS_PANE, (byte) 15)
.setTitle(C.cGray + "Locked")
.build();
_playerData.forEach((player, battleRoyalePlayer) ->
{
battleRoyalePlayer.removeCage();
battleRoyalePlayer.spawnDragon();
for (int i = 18; i < player.getInventory().getSize(); i++)
{
player.getInventory().setItem(i, locked);
}
});
CreatureAllowOverride = false;
@ -363,7 +541,7 @@ public abstract class BattleRoyale extends Game
EnderDragon dragon = royalePlayer.getDragon();
Chicken chicken = royalePlayer.getChicken();
if (dragon == null || chicken == null)
if (dragon == null || !dragon.isValid() || chicken == null || !chicken.isValid())
{
continue;
}
@ -371,23 +549,21 @@ public abstract class BattleRoyale extends Game
UtilTextBottom.display((_colouredMessage ? C.cGreenB : C.cWhiteB) + "PRESS YOUR SNEAK KEY TO DISMOUNT YOUR DRAGON", player);
if (dragon.getPassenger() == null || chicken.getPassenger() == null)
{
if (!UtilTime.elapsed(GetStateTime(), 4000))
if (!UtilTime.elapsed(GetStateTime(), MIN_DRAGON_TIME))
{
player.sendMessage(F.main("Game", "Did you accidentally press sneak? Don't worry I'll put you back on your dragon."));
player.sendMessage(F.main("Game", "Did you accidentally press sneak? It's too soon to jump! Don't worry I'll put you back on your dragon."));
dragon.setPassenger(chicken);
chicken.setPassenger(player);
continue;
}
dismountDragon(player, royalePlayer);
iterator.remove();
}
}
if (!Damage && UtilTime.elapsed(GetStateTime(), MAX_DRAGON_TIME))
{
_playerData.forEach(this::dismountDragon);
_playerData.clear();
Announce(C.cRedB + "Grace Period Over!", false);
@ -398,12 +574,17 @@ public abstract class BattleRoyale extends Game
Damage = true;
HungerSet = -1;
_border.setSize(100, BORDER_TIME);
_border.setSize(MIN_CORD, BORDER_TIME);
}
}
private void dismountDragon(Player player, BattleRoyalePlayer royalePlayer)
{
if (!royalePlayer.getDragon().isValid())
{
return;
}
// Recharge this so that players won't take fall damage for the next 10 seconds
Recharge.Instance.useForce(player, "Fall Damage", TimeUnit.SECONDS.toMillis(10));
player.playSound(player.getLocation(), Sound.BLAZE_DEATH, 1, 0.6F);
@ -434,9 +615,241 @@ public abstract class BattleRoyale extends Game
}
}
@Override
public void disable()
{
super.disable();
if (_supplyDrop != null)
{
_supplyDrop.cleanup();
}
}
@EventHandler
public void updateSupplyDrop(UpdateEvent event)
{
if (event.getType() != UpdateType.FAST || !IsLive())
{
return;
}
if (_totalDrops < MAX_DROPS_PER_GAME && UtilTime.elapsed(_lastSupplyDrop, SUPPLY_DROP_TIME))
{
_lastSupplyDrop = System.currentTimeMillis();
List<Location> locations = WorldData.GetDataLocs("RED");
Location location = null;
int attempts = 0;
while (location == null || attempts++ < 20)
{
location = UtilAlg.Random(locations);
if (UtilWorld.inWorldBorder(location))
{
break;
}
}
_supplyDrop = new BattleRoyaleSupplyDrop(this, location);
_totalDrops++;
Announce(C.cGoldB + "A New Supply Drop Will Spawn At " + C.cYellow + UtilWorld.locToStrClean(_supplyDrop.getDropLocation()) + C.cGold + "!");
}
else if (_supplyDrop != null && _supplyDrop.isOpened())
{
_supplyDrop = null;
}
}
@EventHandler
public void playerDeath(CombatDeathEvent event)
{
Player player = (Player) event.GetEvent().getEntity();
CombatComponent killer = event.GetLog().GetKiller();
if (killer.IsPlayer())
{
Player killerPlayer = UtilPlayer.searchExact(killer.getUniqueIdOfEntity());
if (killerPlayer != null)
{
BattleRoyalePlayer royalePlayer = _playerData.get(killerPlayer);
if (royalePlayer != null)
{
royalePlayer.incrementKills();
UtilTextBottom.display(C.cRedB + royalePlayer.getKills() + " Kill" + (royalePlayer.getKills() == 1 ? "" : "s"));
}
}
}
List<CombatComponent> attackers = event.GetLog().GetAttackers();
for (CombatComponent attacker : attackers)
{
if (!attacker.IsPlayer() || killer.equals(attacker))
{
continue;
}
Player attackerPlayer = UtilPlayer.searchExact(attacker.getUniqueIdOfEntity());
if (attackerPlayer == null)
{
continue;
}
BattleRoyalePlayer royalePlayer = _playerData.get(attackerPlayer);
if (royalePlayer != null)
{
attackerPlayer.sendMessage(F.main("Game", "You assisted in killing " + F.name(player.getName()) + "."));
royalePlayer.incrementAssists();
}
}
}
@EventHandler
public void preventLockedInventoryClick(InventoryClickEvent event)
{
Player player = (Player) event.getWhoClicked();
ItemStack itemStack = event.getCurrentItem();
if (event.getClickedInventory() == null || itemStack == null)
{
return;
}
if (itemStack.getType() == Material.STAINED_GLASS_PANE)
{
event.setCancelled(true);
player.playSound(player.getLocation(), Sound.ITEM_BREAK, 1, 0.6F);
}
}
@EventHandler
public void clickBackpack(InventoryClickEvent event)
{
Player player = (Player) event.getWhoClicked();
ItemStack itemStack = event.getCurrentItem();
if (event.getClickedInventory() == null || itemStack == null)
{
return;
}
int slots = 0;
if (itemStack.isSimilar(SMALL_BACKPACK))
{
slots = 9;
}
else if (itemStack.isSimilar(LARGE_BACKPACK))
{
slots = 18;
}
if (slots == 0)
{
return;
}
ItemStack[] items = player.getInventory().getContents();
int removed = 0;
for (int i = 0; i < items.length && removed < slots; i++)
{
ItemStack inventoryItem = items[i];
if (inventoryItem != null && inventoryItem.getType() == Material.STAINED_GLASS_PANE)
{
player.getInventory().setItem(i, null);
removed++;
}
}
event.setCurrentItem(null);
player.playSound(player.getLocation(), Sound.LEVEL_UP, 1, 1);
player.sendMessage(F.main("Game", "You unlocked an additional " + F.elem(removed) + " slots in your inventory."));
}
@EventHandler
public void noHungerRegeneration(EntityRegainHealthEvent event)
{
if (event.getRegainReason() == RegainReason.SATIATED)
{
event.setCancelled(true);
}
}
@EventHandler
public void inventoryOpen(InventoryOpenEvent event)
{
Inventory inventory = event.getInventory();
if (inventory instanceof EnchantingInventory || inventory instanceof AnvilInventory || inventory instanceof FurnaceInventory)
{
event.setCancelled(true);
}
}
@EventHandler
public void damageToLevel(CustomDamageEvent event)
{
event.SetDamageToLevel(false);
}
@EventHandler
public void playerQuit(PlayerQuitEvent event)
{
_playerData.remove(event.getPlayer());
}
@EventHandler
public void removeEmptyPotions(UpdateEvent event)
{
if (event.getType() != UpdateType.FAST)
{
return;
}
for (Player player : GetPlayers(true))
{
player.getInventory().remove(Material.GLASS_BOTTLE);
}
}
@EventHandler
public void playerDeath(PlayerDeathEvent event)
{
if (!IsLive())
{
return;
}
event.getDrops().removeIf(itemStack -> itemStack.getType() == Material.STAINED_GLASS_PANE);
Player player = event.getEntity();
awardTimeGems(player);
}
protected void awardTimeGems(Player player)
{
long timeAlive = Math.min(System.currentTimeMillis() - GetStateTime(), TimeUnit.MINUTES.toMillis(30));
// i.e 1 gem per 10 seconds alive
AddGems(player, timeAlive / TimeUnit.SECONDS.toMillis(10), "Surviving " + UtilTime.MakeStr(timeAlive), false, false);
}
@Override
public double GetKillsGems(Player killer, Player killed, boolean assist)
{
if (assist)
{
return 50;
}
return _border.getSize() == MIN_CORD ? 200 : 100;
}
}

View File

@ -5,7 +5,6 @@ import mineplex.core.common.util.MapUtil;
import mineplex.core.common.util.UtilColor;
import mineplex.core.common.util.UtilEnt;
import nautilus.game.arcade.ArcadeManager;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.craftbukkit.v1_8_R3.entity.CraftEnderDragon;
@ -27,8 +26,10 @@ class BattleRoyalePlayer
private final Set<Location> _cageBlocks;
private EnderDragon _dragon;
private Chicken _chicken;
private int _kills;
private int _assists;
public BattleRoyalePlayer(ArcadeManager manager, Player player, Location location, Location goal)
BattleRoyalePlayer(ArcadeManager manager, Player player, Location location, Location goal)
{
_player = player;
_location = location;
@ -129,4 +130,24 @@ class BattleRoyalePlayer
{
return _chicken;
}
public void incrementKills()
{
_kills++;
}
public int getKills()
{
return _kills;
}
public void incrementAssists()
{
_assists++;
}
public int getAssists()
{
return _assists;
}
}

View File

@ -1,6 +1,9 @@
package nautilus.game.arcade.game.games.battleroyale;
import mineplex.core.common.util.C;
import mineplex.core.common.util.UtilMath;
import mineplex.core.common.util.UtilTime;
import mineplex.core.common.util.UtilWorld;
import mineplex.core.updater.UpdateType;
import mineplex.core.updater.event.UpdateEvent;
import nautilus.game.arcade.ArcadeManager;
@ -8,11 +11,14 @@ import nautilus.game.arcade.GameType;
import nautilus.game.arcade.events.GameStateChangeEvent;
import nautilus.game.arcade.game.GameTeam;
import nautilus.game.arcade.game.games.moba.kit.KitPlayer;
import nautilus.game.arcade.game.modules.CustomScoreboardModule;
import nautilus.game.arcade.kit.Kit;
import nautilus.game.arcade.scoreboard.GameScoreboard;
import org.bukkit.ChatColor;
import org.bukkit.Location;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import java.util.ArrayList;
import java.util.Collections;
@ -27,55 +33,157 @@ public class BattleRoyaleSolo extends BattleRoyale
private GameTeam _players;
// Scoreboard data
private final String _playersAliveTitle = C.cYellowB + "Players";
private String _playersAlive;
private final String _statsTitle = C.cYellowB + "Stats";
private String _supplyDropTitle = C.cGoldB + "Supply Drop";
private String _supplyDropLocation;
private String _supplyDropState;
private final String _borderTitle = C.cRedB + "World Border";
private String _borderCenter;
private String _borderSize;
private boolean _showBorderCenter;
public BattleRoyaleSolo(ArcadeManager manager)
{
super(manager, GameType.BattleRoyale, new Kit[] {new KitPlayer(manager)}, DESCRIPTION);
super(manager, GameType.BattleRoyale, new Kit[]{new KitPlayer(manager)}, DESCRIPTION);
new CustomScoreboardModule()
.setSidebar((player, scoreboard) ->
{
switch (GetState())
{
case Prepare:
writePrepare(player, scoreboard);
break;
case Live:
writeLive(player, scoreboard);
break;
}
})
.setPrefix((perspective, subject) ->
{
if (!IsAlive(subject))
{
return C.cGray;
}
return perspective.equals(subject) ? C.cGreen : C.cRed;
})
.register(this);
}
@EventHandler
public void customTeamGeneration(GameStateChangeEvent event)
{
if (event.GetState() != GameState.Recruit)
{
return;
}
_players = GetTeamList().get(0);
_players.SetColor(ChatColor.YELLOW);
_players.SetName("Players");
}
@Override
@EventHandler
public void ScoreboardUpdate(UpdateEvent event)
// LOW so that this is run before the scoreboards are updated
@EventHandler(priority = EventPriority.LOW)
public void scoreboardDataUpdate(UpdateEvent event)
{
if (event.getType() != UpdateType.FAST || !InProgress())
if (event.getType() != UpdateType.FAST || _border == null)
{
return;
}
Scoreboard.writeNewLine();
// Due to many players being in this game and the fact that the scoreboard module scales O(n^2)
// we can optimise this by storing global variables that all players would see on their scoreboard
// regardless of their state.
_playersAlive = GetPlayers(true).size() + " Alive";
Scoreboard.write(C.cYellow + C.Bold + "Players");
if (_players.GetPlayers(true).size() > 10)
if (_supplyDrop != null)
{
Scoreboard.write(String.valueOf( _players.GetPlayers(true).size()));
_supplyDropLocation = UtilWorld.locToStrClean(_supplyDrop.getDropLocation());
_supplyDropState = _supplyDrop.getScoreboardString();
}
else
{
for (Player player : _players.GetPlayers(true))
{
Scoreboard.write(player.getName());
}
_supplyDropLocation = "";
_supplyDropState = UtilTime.MakeStr(_lastSupplyDrop + BattleRoyale.SUPPLY_DROP_TIME - System.currentTimeMillis());
}
Scoreboard.writeNewLine();
int size = (int) _border.getSize();
Location center = _border.getCenter();
Scoreboard.write(C.cRedB + "World Border");
Scoreboard.write("(" + center.getBlockX() + ", " + center.getBlockZ() + ")");
Scoreboard.write(size + " Blocks Wide");
Scoreboard.draw();
if (size < 1000 && !_showBorderCenter)
{
_showBorderCenter = true;
Announce(C.cRedB + "The Center Of The Border Is Now Visible!");
}
if (_showBorderCenter)
{
_borderCenter = "(" + center.getBlockX() + ", " + center.getBlockZ() + ")";
}
else
{
_borderCenter = "Center Unknown";
}
_borderSize = size + " Blocks Wide";
}
public void writePrepare(Player player, GameScoreboard scoreboard)
{
scoreboard.writeNewLine();
scoreboard.write(_playersAliveTitle);
scoreboard.write(_playersAlive);
scoreboard.writeNewLine();
}
public void writeLive(Player player, GameScoreboard scoreboard)
{
BattleRoyalePlayer royalePlayer = _playerData.get(player);
scoreboard.writeNewLine();
scoreboard.write(_playersAliveTitle);
scoreboard.write(_playersAlive);
scoreboard.writeNewLine();
if (royalePlayer != null)
{
scoreboard.write(_statsTitle);
scoreboard.write("Kills: " + C.cGreen + royalePlayer.getKills());
scoreboard.write("Assists: " + C.cGreen + royalePlayer.getAssists());
scoreboard.writeNewLine();
}
scoreboard.write(_supplyDropTitle);
if (_supplyDrop != null)
{
scoreboard.write(_supplyDropLocation);
}
if (_supplyDropState != null)
{
scoreboard.write(_supplyDropState);
}
else if (_supplyDrop != null && IsAlive(player))
{
int dist = (int) UtilMath.offset2d(_supplyDrop.getDropLocation(), player.getLocation());
scoreboard.write(dist + " Blocks Away");
}
scoreboard.writeNewLine();
scoreboard.write(_borderTitle);
scoreboard.write(_borderCenter);
scoreboard.write(_borderSize);
}
@Override
@ -86,8 +194,12 @@ public class BattleRoyaleSolo extends BattleRoyale
return;
}
if (GetPlayers(true).size() <= 1)
List<Player> alive = GetPlayers(true);
if (alive.size() <= 1)
{
alive.forEach(this::awardTimeGems);
List<Player> places = _players.GetPlacements(true);
AnnounceEnd(places);
@ -105,14 +217,6 @@ public class BattleRoyaleSolo extends BattleRoyale
AddGems(places.get(2), 10, "3rd Place", false, false);
}
for (Player player : GetPlayers(false))
{
if (player.isOnline())
{
AddGems(player, 10, "Participation", false, false);
}
}
_border.setSize(10000);
SetState(GameState.End);
}
@ -126,12 +230,18 @@ public class BattleRoyaleSolo extends BattleRoyale
List<Player> places = _players.GetPlacements(true);
if (places.isEmpty() || !places.get(0).isOnline())
{
return new ArrayList<>(0);
}
else
{
return Collections.singletonList(places.get(0));
}
}
else
{
return null;
}
}
@Override

View File

@ -0,0 +1,185 @@
package nautilus.game.arcade.game.games.battleroyale;
import mineplex.core.common.Pair;
import mineplex.core.common.util.MapUtil;
import mineplex.core.common.util.UtilAlg;
import mineplex.core.common.util.UtilBlock;
import mineplex.core.common.util.UtilEnt;
import mineplex.core.common.util.UtilFirework;
import mineplex.core.common.util.UtilMath;
import mineplex.core.common.util.UtilServer;
import mineplex.core.common.util.UtilTime;
import mineplex.core.updater.UpdateType;
import mineplex.core.updater.event.UpdateEvent;
import nautilus.game.arcade.game.modules.chest.ChestLootModule;
import org.bukkit.Color;
import org.bukkit.FireworkEffect;
import org.bukkit.FireworkEffect.Type;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.entity.ArmorStand;
import org.bukkit.entity.Chicken;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.inventory.ItemStack;
import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionEffectType;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;
class BattleRoyaleSupplyDrop implements Listener
{
private static final int DRAGON_Y = 120;
private static long DROP_WAIT = TimeUnit.MINUTES.toMillis(2);
private static final ItemStack CHEST = new ItemStack(Material.CHEST);
private static final FireworkEffect FIREWORK_EFFECT = FireworkEffect.builder()
.with(Type.BALL_LARGE)
.withColor(Color.YELLOW)
.withFlicker()
.build();
private final BattleRoyale _host;
private final long _start;
private final Set<Block> _beaconBlocks;
private Location _dropLocation;
private ArmorStand _chest;
private Chicken _seat;
private final List<Chicken> _chute;
private boolean _dropped;
private boolean _opened;
private boolean _landed;
private long _openedAt;
BattleRoyaleSupplyDrop(BattleRoyale host, Location dropLocation)
{
_host = host;
_dropLocation = dropLocation;
_start = System.currentTimeMillis();
_beaconBlocks = new HashSet<>();
_chute = new ArrayList<>();
// Construct a beacon
for (Pair<Location, Pair<Material, Byte>> pair : UtilBlock.getBeaconBlocks(_dropLocation, (byte) 0))
{
// Look it's like a maze
_beaconBlocks.add(pair.getLeft().getBlock());
host.getArcadeManager().GetBlockRestore().add(pair.getLeft().getBlock(), pair.getRight().getLeft().getId(), pair.getRight().getRight(), Long.MAX_VALUE);
}
_dropLocation.setY(DRAGON_Y);
UtilServer.RegisterEvents(this);
}
@EventHandler
public void updateDrop(UpdateEvent event)
{
if (event.getType() != UpdateType.FAST)
{
return;
}
if (UtilTime.elapsed(_start, DROP_WAIT) && !_dropped)
{
_dropped = true;
_host.CreatureAllowOverride = true;
UtilFirework.playFirework(_dropLocation, FIREWORK_EFFECT);
_chest = _dropLocation.getWorld().spawn(_dropLocation, ArmorStand.class);
_chest.setGravity(false);
_chest.setVisible(false);
_chest.setHelmet(CHEST);
_seat = _dropLocation.getWorld().spawn(_dropLocation, Chicken.class);
UtilEnt.vegetate(_seat);
UtilEnt.ghost(_seat, true, true);
UtilEnt.silence(_seat, true);
_seat.addPotionEffect(new PotionEffect(PotionEffectType.INVISIBILITY, Integer.MAX_VALUE, 0, false, false));
_seat.setPassenger(_chest);
for (int i = 0; i < 6; i++)
{
Chicken chicken = _dropLocation.getWorld().spawn(UtilAlg.getRandomLocation(_dropLocation, 2, 0.5, 2).add(0, 5, 0), Chicken.class);
UtilEnt.vegetate(chicken);
UtilEnt.ghost(chicken, true, false);
chicken.setLeashHolder(_seat);
_chute.add(chicken);
}
_host.CreatureAllowOverride = false;
}
else if (_dropped && !_landed && UtilEnt.isGrounded(_seat))
{
_landed = true;
Location chest = _seat.getLocation();
UtilFirework.playFirework(chest, FIREWORK_EFFECT);
MapUtil.QuickChangeBlockAt(chest, Material.CHEST);
_dropLocation = chest;
ChestLootModule lootModule = _host.getModule(ChestLootModule.class);
lootModule.addChestLocation("Supply Drop", chest);
_beaconBlocks.forEach(block -> _host.getArcadeManager().GetBlockRestore().restore(block));
_chest.remove();
_seat.remove();
_chute.forEach(Chicken::remove);
}
}
@EventHandler(priority = EventPriority.MONITOR)
public void playerInteract(PlayerInteractEvent event)
{
if (event.isCancelled())
{
return;
}
Block block = event.getClickedBlock();
if (block == null || block.getType() != Material.CHEST)
{
return;
}
if (UtilMath.offsetSquared(block.getLocation(), _dropLocation) < 4)
{
_opened = true;
_openedAt = System.currentTimeMillis();
cleanup();
}
}
public void cleanup()
{
_chute.clear();
UtilServer.Unregister(this);
}
public Location getDropLocation()
{
return _dropLocation;
}
public boolean isOpened()
{
return _opened;
}
public String getScoreboardString()
{
return _dropped ? null : UtilTime.MakeStr(_start + DROP_WAIT - System.currentTimeMillis());
}
}

View File

@ -832,14 +832,6 @@ public class Bridge extends TeamGame implements OreObsfucation
if (!_bridgesDown)
{
_bridgesDown = true;
// WorldBorderModule borderModule = getModule(WorldBorderModule.class);
//
// for (Player player : GetPlayers(true))
// {
// borderModule.setSize(player, 10000);
// }
Manager.GetExplosion().SetLiquidDamage(true);
Announce(C.cRedB + "ALERT: " + C.Reset + C.Bold + "THE BRIDGES ARE SPAWNING!");
UtilTextMiddle.display(C.cRedB + "ALERT", "The BRIDGES ARE SPAWNING!");

View File

@ -82,6 +82,7 @@ public class CustomScoreboardModule extends Module
}
setupScoreboard(player);
refreshAsSubject(player);
}
/**

View File

@ -1,116 +0,0 @@
package nautilus.game.arcade.game.modules;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import org.bukkit.Location;
import org.bukkit.craftbukkit.v1_8_R3.CraftWorld;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import mineplex.core.common.Pair;
import mineplex.core.common.util.UtilPlayer;
import mineplex.core.packethandler.IPacketHandler;
import mineplex.core.packethandler.PacketHandler;
import mineplex.core.packethandler.PacketInfo;
import nautilus.game.arcade.events.GameStateChangeEvent;
import nautilus.game.arcade.game.Game.GameState;
import net.minecraft.server.v1_8_R3.PacketPlayOutWorldBorder;
import net.minecraft.server.v1_8_R3.PacketPlayOutWorldBorder.EnumWorldBorderAction;
import net.minecraft.server.v1_8_R3.WorldBorder;
public class WorldBorderModule extends Module implements IPacketHandler
{
private PacketHandler _packetHandler;
private Map<UUID, Double> _sizeToSet;
private Map<UUID, Pair<Double, Double>> _centerToSet;
@Override
protected void setup()
{
_packetHandler = getGame().getArcadeManager().getPacketHandler();
_sizeToSet = new HashMap<>();
_centerToSet = new HashMap<>();
}
@EventHandler(priority = EventPriority.LOWEST)
public void live(GameStateChangeEvent event)
{
if (event.GetState() != GameState.Prepare)
{
return;
}
_packetHandler.addPacketHandler(this, PacketPlayOutWorldBorder.class);
}
@Override
public void handle(PacketInfo packetInfo)
{
UUID player = packetInfo.getPlayer().getUniqueId();
PacketPlayOutWorldBorder packet = (PacketPlayOutWorldBorder) packetInfo.getPacket();
try
{
Field actionField = packet.getClass().getDeclaredField("a");
actionField.setAccessible(true);
EnumWorldBorderAction action = (EnumWorldBorderAction) actionField.get(packet);
if (action == EnumWorldBorderAction.SET_SIZE)
{
Field sizeField = packet.getClass().getDeclaredField("e");
sizeField.setAccessible(true);
double newSize = _sizeToSet.get(player);
sizeField.set(packet, newSize);
}
else if (action == EnumWorldBorderAction.SET_CENTER)
{
Field xField = packet.getClass().getDeclaredField("c");
Field zField = packet.getClass().getDeclaredField("d");
xField.setAccessible(true);
zField.setAccessible(true);
Pair<Double, Double> pair = _centerToSet.get(player);
xField.set(packet, pair.getLeft());
zField.set(packet, pair.getRight());
}
}
catch (Exception e)
{
e.printStackTrace();
}
}
@Override
public void cleanup()
{
_packetHandler.removePacketHandler(this);
}
public void setSize(Player player, double size)
{
_sizeToSet.put(player.getUniqueId(), size);
sendPacket(player, EnumWorldBorderAction.SET_SIZE);
}
public void setCenter(Player player, Location location)
{
_centerToSet.put(player.getUniqueId(), Pair.create(location.getX(), location.getZ()));
sendPacket(player, EnumWorldBorderAction.SET_CENTER);
}
private void sendPacket(Player player, EnumWorldBorderAction action)
{
WorldBorder border = ((CraftWorld) player.getWorld()).getHandle().getWorldBorder();
UtilPlayer.sendPacket(player, new PacketPlayOutWorldBorder(border, action));
}
}

View File

@ -1,5 +1,6 @@
package nautilus.game.arcade.game.modules.chest;
import mineplex.core.common.util.MapUtil;
import mineplex.core.common.util.UtilAlg;
import mineplex.core.common.util.UtilBlock;
import mineplex.core.common.util.UtilEvent;
@ -21,12 +22,12 @@ import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.player.PlayerInteractEvent;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.TimeUnit;
@ -40,7 +41,6 @@ public class ChestLootModule extends Module
BlockFace.EAST
};
private final List<ChestType> _chestTypes;
private final Map<ChestType, Set<ChestMetadata>> _chests;
private long _destroyAfterOpened;
@ -50,7 +50,6 @@ public class ChestLootModule extends Module
public ChestLootModule()
{
_chestTypes = new ArrayList<>();
_chests = new HashMap<>();
}
@ -61,7 +60,7 @@ public class ChestLootModule extends Module
public ChestLootModule registerChestType(String name, List<Location> chestLocations, double spawnChance, ChestLootPool... pools)
{
_chestTypes.add(new ChestType(name, chestLocations, spawnChance, pools));
_chests.put(new ChestType(name, chestLocations, spawnChance, pools), new HashSet<>());
return this;
}
@ -90,6 +89,38 @@ public class ChestLootModule extends Module
return this;
}
public void addChestLocation(String typeName, Location location)
{
for (Entry<ChestType, Set<ChestMetadata>> entry : _chests.entrySet())
{
if (!entry.getKey().Name.equals(typeName))
{
continue;
}
entry.getValue().add(new ChestMetadata(location.getBlock(), entry.getKey()));
return;
}
}
public void refill()
{
_chests.forEach((type, metadataSet) -> metadataSet.forEach(metadata -> metadata.Opened = false));
}
public void refill(String typeName)
{
_chests.forEach((type, metadataSet) ->
{
if (!type.Name.equals(typeName))
{
return;
}
metadataSet.forEach(metadata -> metadata.Opened = false);
});
}
@EventHandler(priority = EventPriority.HIGHEST)
public void populateChests(GameStateChangeEvent event)
{
@ -98,14 +129,16 @@ public class ChestLootModule extends Module
return;
}
for (ChestType chestType : _chestTypes)
for (Entry<ChestType, Set<ChestMetadata>> entry : _chests.entrySet())
{
ChestType chestType = entry.getKey();
if (chestType.ChestSpawns == null)
{
continue;
}
Set<ChestMetadata> metadataSet = new HashSet<>();
Set<ChestMetadata> metadataSet = entry.getValue();
for (Location location : chestType.ChestSpawns)
{
@ -186,8 +219,9 @@ public class ChestLootModule extends Module
{
Block block = metadata.Chest;
Location location = block.getLocation();
location.getWorld().playEffect(location.add(0.5, 0.5, 0.5), Effect.STEP_SOUND, block.getType(), block.getData());
block.setType(Material.AIR);
location.getWorld().playEffect(location.add(0.5, 0.5, 0.5), Effect.STEP_SOUND, block.getType());
((Chest) block.getState()).getBlockInventory().clear();
MapUtil.QuickChangeBlockAt(location, Material.AIR);
return true;
}
@ -258,10 +292,10 @@ public class ChestLootModule extends Module
private class ChestMetadata
{
Block Chest;
ChestType Type;
long OpenedAt;
boolean Opened;
Block Chest;
ChestType Type;
long OpenedAt;
boolean Opened;
ChestMetadata(Block chest, ChestType type)
{
@ -271,6 +305,8 @@ public class ChestLootModule extends Module
void populateChest(Chest chest)
{
chest.getBlockInventory().clear();
for (ChestLootPool pool : Type.Pools)
{
if (pool.getProbability() == 1 || Math.random() < pool.getProbability())