diff --git a/Plugins/Mineplex.Core/src/mineplex/core/MiniPlugin.java b/Plugins/Mineplex.Core/src/mineplex/core/MiniPlugin.java index 80c128715..02e063daf 100644 --- a/Plugins/Mineplex.Core/src/mineplex/core/MiniPlugin.java +++ b/Plugins/Mineplex.Core/src/mineplex/core/MiniPlugin.java @@ -13,6 +13,7 @@ import org.bukkit.event.HandlerList; import org.bukkit.event.Listener; import org.bukkit.plugin.PluginManager; import org.bukkit.plugin.java.JavaPlugin; +import org.bukkit.scheduler.BukkitRunnable; import org.bukkit.scheduler.BukkitScheduler; import org.bukkit.scheduler.BukkitTask; @@ -151,11 +152,21 @@ public abstract class MiniPlugin implements Listener return _plugin.getServer().getScheduler().runTaskLater(_plugin, runnable, delay); } + public BukkitTask runSyncLater(BukkitRunnable runnable, long delay) + { + return runnable.runTaskLater(_plugin, delay); + } + public BukkitTask runSyncTimer(Runnable runnable, long delay, long period) { return _plugin.getServer().getScheduler().runTaskTimer(_plugin, runnable, delay, period); } + public BukkitTask runSyncTimer(BukkitRunnable runnable, long delay, long period) + { + return runnable.runTaskTimer(_plugin, delay, period); + } + protected T require(Class clazz) { return Managers.require(clazz); diff --git a/Plugins/Mineplex.Core/src/mineplex/core/antihack/AntiHack.java b/Plugins/Mineplex.Core/src/mineplex/core/antihack/AntiHack.java index b8bd978f1..b5f56ca2e 100644 --- a/Plugins/Mineplex.Core/src/mineplex/core/antihack/AntiHack.java +++ b/Plugins/Mineplex.Core/src/mineplex/core/antihack/AntiHack.java @@ -143,8 +143,6 @@ public class AntiHack extends MiniPlugin private List _guardians = new ArrayList<>(); - private Predicate _filter = player -> true; - private Set _pendingBan = new HashSet<>(); // These are the GWEN checks to ignore when handling PlayerViolationEvent @@ -276,8 +274,7 @@ public class AntiHack extends MiniPlugin Rank.LT ), player -> !_stalking.contains(player.getUniqueId()), - player -> _stalkingCooldown.getIfPresent(player.getUniqueId()) == null, - _filter + player -> _stalkingCooldown.getIfPresent(player.getUniqueId()) == null )); while (_stalking.size() < MAX_STALKED_PLAYERS && targets.size() > 0) @@ -444,18 +441,6 @@ public class AntiHack extends MiniPlugin ); } - public void registerFilter(Predicate filter) - { - if (filter == null) - { - this._filter = player -> true; - } - else - { - this._filter = filter; - } - } - public void registerGuardian(AntiHackGuardian guardian) { this._guardians.add(guardian); diff --git a/Plugins/Mineplex.Core/src/mineplex/core/command/CommandBase.java b/Plugins/Mineplex.Core/src/mineplex/core/command/CommandBase.java index 2aafb6cb9..c93bd9e2d 100644 --- a/Plugins/Mineplex.Core/src/mineplex/core/command/CommandBase.java +++ b/Plugins/Mineplex.Core/src/mineplex/core/command/CommandBase.java @@ -54,6 +54,11 @@ public abstract class CommandBase implements ICom { return _requiredRank; } + + public void setRequiredRank(Rank rank) + { + this._requiredRank = rank; + } public Rank[] GetSpecificRanks() { diff --git a/Plugins/Nautilus.Game.Arcade.UHC.WorldGen/plugin.yml b/Plugins/Nautilus.Game.Arcade.UHC.WorldGen/plugin.yml new file mode 100644 index 000000000..66259a492 --- /dev/null +++ b/Plugins/Nautilus.Game.Arcade.UHC.WorldGen/plugin.yml @@ -0,0 +1,3 @@ +name: UHC-WorldGen +main: nautilus.game.arcade.uhc.WorldGen +version: 0.1 \ No newline at end of file diff --git a/Plugins/Nautilus.Game.Arcade.UHC.WorldGen/pom.xml b/Plugins/Nautilus.Game.Arcade.UHC.WorldGen/pom.xml new file mode 100644 index 000000000..52ebd07c0 --- /dev/null +++ b/Plugins/Nautilus.Game.Arcade.UHC.WorldGen/pom.xml @@ -0,0 +1,28 @@ + + 4.0.0 + + + com.mineplex + mineplex-plugin + dev-SNAPSHOT + ../plugin.xml + + + UHC WorldGen + nautilus-game-arcade-uhc-worldgen + + + + com.mineplex + spigot + 1.8.8-1.9-SNAPSHOT + compile + + + org.zeroturnaround + zt-zip + 1.9 + + + diff --git a/Plugins/Nautilus.Game.Arcade.UHC.WorldGen/src/nautilus/game/arcade/uhc/WorldGen.java b/Plugins/Nautilus.Game.Arcade.UHC.WorldGen/src/nautilus/game/arcade/uhc/WorldGen.java new file mode 100644 index 000000000..2dd1a54be --- /dev/null +++ b/Plugins/Nautilus.Game.Arcade.UHC.WorldGen/src/nautilus/game/arcade/uhc/WorldGen.java @@ -0,0 +1,245 @@ +package nautilus.game.arcade.uhc; + +import net.minecraft.server.v1_8_R3.BiomeBase; +import org.apache.commons.io.FileUtils; +import org.bukkit.Bukkit; +import org.bukkit.Difficulty; +import org.bukkit.World; +import org.bukkit.WorldCreator; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.player.AsyncPlayerPreLoginEvent; +import org.bukkit.plugin.java.JavaPlugin; +import org.spigotmc.WatchdogThread; +import org.zeroturnaround.zip.ZipEntrySource; +import org.zeroturnaround.zip.ZipUtil; + +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.ThreadLocalRandom; +import java.util.logging.Level; +import java.util.zip.ZipEntry; + +public class WorldGen extends JavaPlugin implements Runnable, Listener +{ + private static final int MIN_X = -1000; + private static final int MIN_Z = -1000; + private static final int MAX_X = 1000; + private static final int MAX_Z = 1000; + private static final int VIEW_DISTANCE = 5; + + @Override + public void onEnable() + { + BiomeBase.getBiomes()[BiomeBase.OCEAN.id] = BiomeBase.PLAINS; + BiomeBase.getBiomes()[BiomeBase.DEEP_OCEAN.id] = BiomeBase.PLAINS; + BiomeBase.getBiomes()[BiomeBase.SWAMPLAND.id] = BiomeBase.PLAINS; + BiomeBase.getBiomes()[BiomeBase.RIVER.id] = BiomeBase.PLAINS; + + WatchdogThread.doStop(); + + getServer().getScheduler().runTaskTimer(this, this, 20L, 20L * 5L); + getServer().getPluginManager().registerEvents(this, this); + } + + @EventHandler + public void onJoin(AsyncPlayerPreLoginEvent event) + { + event.setLoginResult(AsyncPlayerPreLoginEvent.Result.KICK_OTHER); + event.setKickMessage("Shoo, go away"); + } + + @Override + public void run() + { + File root = new File("."); + + if (!root.exists()) + { + getLogger().severe("Root folder does not exist. Aborting"); + getServer().shutdown(); + return; + } + + File outputDirectory = new File(root, "output"); + if (!outputDirectory.exists()) + { + if (!outputDirectory.mkdir()) + { + getLogger().severe("Could not create output folder. Aborting"); + getServer().shutdown(); + return; + } + } + + long seed = ThreadLocalRandom.current().nextLong(); + + File outputFile = new File(outputDirectory, "UHC_Map" + seed + ".zip"); + + if (outputFile.exists()) + { + getLogger().info("Seed " + seed + " has already been generated. Skipping"); + return; + } + + try + { + if (!outputFile.createNewFile()) + { + getLogger().severe("Could not create new output file. Aborting"); + getServer().shutdown(); + return; + } + } + catch (IOException e) + { + getLogger().log(Level.SEVERE, "Could not create new output file. Aborting", e); + getServer().shutdown(); + return; + } + + getLogger().info("Generating world seed " + seed); + + World world = new WorldCreator("generating") + .environment(World.Environment.NORMAL) + .seed(seed) + .createWorld(); + world.setDifficulty(Difficulty.HARD); + world.setKeepSpawnInMemory(false); + + int minChunkX = (MIN_X >> 4) - VIEW_DISTANCE; + int minChunkZ = (MIN_Z >> 4) - VIEW_DISTANCE; + int maxChunkX = (MAX_X >> 4) + VIEW_DISTANCE; + int maxChunkZ = (MAX_Z >> 4) + VIEW_DISTANCE; + + for (int x = minChunkX; x <= maxChunkX; x++) + { + getLogger().info("Generating x coord " + x); + for (int z = minChunkZ; z <= maxChunkZ; z++) + { + world.getChunkAt(x, z).load(true); + } + } + + for (int x = minChunkX; x <= maxChunkX; x++) + { + getLogger().info("Unloading x coord " + x); + for (int z = minChunkZ; z <= maxChunkZ; z++) + { + world.getChunkAt(x, z).unload(true, false); + } + } + + getLogger().info("Unloading and saving world"); + + Bukkit.unloadWorld(world, true); + + getLogger().info("Finished unloading and saving world"); + + StringBuilder worldconfig = new StringBuilder(); + worldconfig.append("MAP_NAME:UHC World").append(System.lineSeparator()); + worldconfig.append("MAP_AUTHOR:Mineplex").append(System.lineSeparator()); + worldconfig.append("MIN_X:").append(MIN_X).append(System.lineSeparator()); + worldconfig.append("MIN_Z:").append(MIN_Z).append(System.lineSeparator()); + worldconfig.append("MAX_X:").append(MAX_X).append(System.lineSeparator()); + worldconfig.append("MAX_Z:").append(MAX_Z).append(System.lineSeparator()); + for (int i = 1; i <= 60; i++) + { + worldconfig.append("TEAM_NAME:").append(i).append(System.lineSeparator()); + worldconfig.append("TEAM_SPAWNS:0,0,0").append(System.lineSeparator()); + } + + File worldFolder = new File(root, "generating"); + + File regionFolder = new File(worldFolder, "region"); + + File[] regionFiles = regionFolder.listFiles(); + + if (regionFiles == null) + { + getLogger().severe("Unexpected null region files. Aborting"); + getServer().shutdown(); + return; + } + + List zipEntrySourceList = new ArrayList<>(); + zipEntrySourceList.add(new ZipEntrySource() + { + @Override + public String getPath() + { + return "WorldConfig.dat"; + } + + @Override + public ZipEntry getEntry() + { + return new ZipEntry(getPath()); + } + + @Override + public InputStream getInputStream() throws IOException + { + return new ByteArrayInputStream(worldconfig.toString().getBytes(StandardCharsets.UTF_8)); + } + }); + + + for (File file : regionFiles) + { + zipEntrySourceList.add(new ZipEntrySource() + { + @Override + public String getPath() + { + return "region/" + file.getName(); + } + + @Override + public ZipEntry getEntry() + { + return new ZipEntry(getPath()); + } + + @Override + public InputStream getInputStream() throws IOException + { + return new FileInputStream(file); + } + }); + } + + zipEntrySourceList.add(new ZipEntrySource() + { + @Override + public String getPath() + { + return "level.dat"; + } + + @Override + public ZipEntry getEntry() + { + return new ZipEntry(getPath()); + } + + @Override + public InputStream getInputStream() throws IOException + { + return new FileInputStream(new File(worldFolder, "level.dat")); + } + }); + + ZipUtil.pack(zipEntrySourceList.toArray(new ZipEntrySource[zipEntrySourceList.size()]), outputFile); + + FileUtils.deleteQuietly(worldFolder); + + getLogger().info("Finished generating world seed " + seed); + } +} diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/Arcade.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/Arcade.java index 2a9f9b518..9e27c871f 100644 --- a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/Arcade.java +++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/Arcade.java @@ -201,12 +201,6 @@ public class Arcade extends JavaPlugin MinecraftServer.getServer().getPropertyManager().setProperty("debug", false); SpigotConfig.debug = false; - - // Remove nasty biomes from natural terrain generation, used for UHC - BiomeBase.getBiomes()[BiomeBase.OCEAN.id] = BiomeBase.PLAINS; - BiomeBase.getBiomes()[BiomeBase.DEEP_OCEAN.id] = BiomeBase.PLAINS; - BiomeBase.getBiomes()[BiomeBase.SWAMPLAND.id] = BiomeBase.PLAINS; - BiomeBase.getBiomes()[BiomeBase.RIVER.id] = BiomeBase.PLAINS; } @Override diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/ArcadeManager.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/ArcadeManager.java index bb9ca2417..ecfbcc9af 100644 --- a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/ArcadeManager.java +++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/ArcadeManager.java @@ -494,23 +494,20 @@ public class ArcadeManager extends MiniPlugin implements IRelation @Override public void draw(MineplexScoreboard scoreboard) { - if (GetGame() != null && GetGame().GetCountdown() >= 0) + if (GetGame() != null) { if (GetGame().GetCountdown() > 0) scoreboard.setSidebarName(C.Bold + "§lStarting in " + C.cGreen + "§l" + GetGame().GetCountdown() + (GetGame().GetCountdown() == 1 ? " Second" : " Seconds")); else if (GetGame().GetCountdown() == 0) scoreboard.setSidebarName(ChatColor.WHITE + "§lIn Progress..."); + else if (GetGame().GetState() == GameState.Recruit) + scoreboard.setSidebarName(ChatColor.GREEN + "§l" + "Waiting for players"); + else if (GetGame().GetState() == GameState.Loading) + scoreboard.setSidebarName(ChatColor.GREEN + "§l" + "Loading..."); } else { - if (GetGame() instanceof UHC && !((UHC) GetGame()).isMapLoaded()) - { - scoreboard.setSidebarName(((UHC) GetGame()).getObjectiveName(_gameLobbyManager.getColorTick())); - } - else - { - scoreboard.setSidebarName(ChatColor.GREEN + "§l" + "Waiting for Players"); - } + scoreboard.setSidebarName(ChatColor.GREEN + "§l" + "Waiting for game"); } scoreboard.get(ArcadeScoreboardLine.PLAYERS_VALUE).write( _gameManager.getValidPlayersForGameStart().size() + "/" + GetPlayerFull()); @@ -931,11 +928,7 @@ public class ArcadeManager extends MiniPlugin implements IRelation // { // event.setMotd(ChatColor.GREEN + "Recruiting" + extrainformation); // } - //UHC Timed - if (_game != null && (_game.GetType() == GameType.UHC || _game.getClass().getSuperclass().equals(UHC.class))) - { - event.setMotd(((UHC) _game).getMotdStatus() + extrainformation); - } + //Recruiting else if (_game == null || _game.GetState() == GameState.Recruit) { diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/DebugCommand.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/DebugCommand.java new file mode 100644 index 000000000..fec572ef5 --- /dev/null +++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/DebugCommand.java @@ -0,0 +1,17 @@ +package nautilus.game.arcade.game; + +import mineplex.core.Managers; +import mineplex.core.command.CommandBase; +import mineplex.core.common.Rank; +import nautilus.game.arcade.ArcadeManager; +import org.bukkit.entity.Player; + +public abstract class DebugCommand extends CommandBase +{ + public DebugCommand(String commandName, Rank requiredRank, Rank... specificRanks) + { + super(Managers.get(ArcadeManager.class), requiredRank, specificRanks, commandName); + } + + public abstract void Execute(Player caller, String[] args); +} diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/Game.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/Game.java index f1739e81a..351c336e6 100644 --- a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/Game.java +++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/Game.java @@ -48,6 +48,8 @@ import com.mojang.authlib.GameProfile; import mineplex.core.Managers; import mineplex.core.antihack.AntiHack; +import mineplex.core.command.CommandCenter; +import mineplex.core.common.Rank; import mineplex.core.common.util.C; import mineplex.core.common.util.F; import mineplex.core.common.util.NautHashMap; @@ -380,6 +382,7 @@ public abstract class Game implements Listener private Map, Module> _modules = new HashMap<>(); private HashMap>> _playerPastLocs = new HashMap<>(); + private Set _debugCommands = new HashSet<>(); public Game(ArcadeManager manager, GameType gameType, Kit[] kits, String[] gameDesc) { @@ -467,14 +470,14 @@ public abstract class Game implements Listener System.out.println("Loading " + GetName() + "..."); } - public T registerModule(T module) + // You should never use this so please don't. Use Module.register instead + public final void registerModule(Module module) { if (!_modules.containsKey(module.getClass())) { _modules.put(module.getClass(), module); UtilServer.RegisterEvents(module); module.initialize(this); - return module; } else { @@ -492,6 +495,23 @@ public abstract class Game implements Listener } } + public void registerDebugCommand(DebugCommand debugCommand) + { + if (UtilServer.isTestServer()) + { + debugCommand.setRequiredRank(Rank.SNR_MODERATOR); + } + _debugCommands.add(debugCommand); + for (String string : debugCommand.Aliases()) + { + if (CommandCenter.getCommands().containsKey(string.toLowerCase())) + { + throw new IllegalArgumentException("Existing command: " + string.toLowerCase()); + } + } + CommandCenter.Instance.addCommand(debugCommand); + } + public void setKits(Kit[] kits) { _kits = kits; @@ -655,6 +675,68 @@ public abstract class Game implements Listener return _gameState; } + public void prepareToRecruit() + { + generateTeams(); + recruit(); + } + + public void recruit() + { + SetState(GameState.Recruit); + } + + + public void generateTeams() + { + int count = 1; + + for (String team : WorldData.SpawnLocs.keySet()) + { + ChatColor color; + + if (team.equalsIgnoreCase("RED")) color = ChatColor.RED; + else if (team.equalsIgnoreCase("YELLOW")) color = ChatColor.YELLOW; + else if (team.equalsIgnoreCase("GREEN")) color = ChatColor.GREEN; + else if (team.equalsIgnoreCase("BLUE")) color = ChatColor.AQUA; + else + { + color = ChatColor.DARK_GREEN; + + if (GetTeamList().size()%14 == 0) if (WorldData.SpawnLocs.size() > 1) color = ChatColor.RED; + if (GetTeamList().size()%14 == 1) color = ChatColor.YELLOW; + if (GetTeamList().size()%14 == 2) color = ChatColor.GREEN; + if (GetTeamList().size()%14 == 3) color = ChatColor.AQUA; + if (GetTeamList().size()%14 == 4) color = ChatColor.GOLD; + if (GetTeamList().size()%14 == 5) color = ChatColor.LIGHT_PURPLE; + if (GetTeamList().size()%14 == 6) color = ChatColor.DARK_BLUE; + if (GetTeamList().size()%14 == 7) color = ChatColor.WHITE; + if (GetTeamList().size()%14 == 8) color = ChatColor.BLUE; + if (GetTeamList().size()%14 == 9) color = ChatColor.DARK_GREEN; + if (GetTeamList().size()%14 == 10) color = ChatColor.DARK_PURPLE; + if (GetTeamList().size()%14 == 11) color = ChatColor.DARK_RED; + if (GetTeamList().size()%14 == 12) color = ChatColor.DARK_AQUA; + } + + //Random Names + String teamName = team; + if (WorldData.SpawnLocs.size() > 12) + { + teamName = String.valueOf(count); + count++; + } + + GameTeam newTeam = new GameTeam(this, teamName, color, WorldData.SpawnLocs.get(team)); + AddTeam(newTeam); + } + + //Restrict Kits + RestrictKits(); + + //Parse Data + ParseData(); + } + public void SetState(GameState state) { _gameState = state; @@ -663,29 +745,10 @@ public abstract class Game implements Listener if (this._gameState == Game.GameState.Prepare) { Managers.get(AntiHack.class).enableNewAnticheat(); - if (this instanceof HideSeek) - { - Managers.get(AntiHack.class).registerFilter(player -> - { - if (GetTeam(player) == ((HideSeek) this).getHiders()) - { - return false; - } - return true; - }); - } - else if (this instanceof SurvivalGames || this instanceof Minestrike || this instanceof SneakyAssassins || this instanceof UHC || this instanceof WitherGame) - { - Managers.get(AntiHack.class).registerFilter(player -> - { - return false; - }); - } } else if (this._gameState == Game.GameState.End) { Managers.get(AntiHack.class).disableNewAnticheat(); - Managers.get(AntiHack.class).registerFilter(null); } @@ -766,14 +829,15 @@ public abstract class Game implements Listener { ProgressingKit progressingKit = (ProgressingKit) kit; - if(!progressingKit.hasUpgrades()) + if (!progressingKit.hasUpgrades()) { - for(Perk perk : progressingKit.getNonUpgradePerks()) + for (Perk perk : progressingKit.getNonUpgradePerks()) { UtilServer.RegisterEvents(perk); perk.registeredEvents(); } - } else + } + else { for (Perk[] upgradePerks : progressingKit.getPerks()) { @@ -827,6 +891,29 @@ public abstract class Game implements Listener // Use this to parse in extra location data from maps } + public boolean loadNecessaryChunks(long maxMilliseconds) + { + long endTime = System.currentTimeMillis() + maxMilliseconds; + + int minX = WorldData.MinX >> 4; + int minZ = WorldData.MinZ >> 4; + int maxX = WorldData.MaxX >> 4; + int maxZ = WorldData.MaxZ >> 4; + + for (int x = minX; x <= maxX; x++) + { + for (int z = minZ; z <= maxZ; z++) + { + if (System.currentTimeMillis() >= endTime) + return false; + + WorldData.World.getChunkAt(x, z); + } + } + + return true; + } + public void SetPlayerTeam(Player player, GameTeam team, boolean in) { // Clean Old Team @@ -2319,6 +2406,12 @@ public abstract class Game implements Listener this._modules.clear(); } + public void cleanupCommands() + { + this._debugCommands.forEach(command -> CommandCenter.Instance.removeCommand(command)); + this._debugCommands.clear(); + } + public T getModule(Class clazz) { return clazz.cast(_modules.get(clazz)); diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/build/modes/TeamBuild.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/build/modes/TeamBuild.java index ef5e41c08..db22e8d4c 100644 --- a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/build/modes/TeamBuild.java +++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/build/modes/TeamBuild.java @@ -42,7 +42,7 @@ public class TeamBuild extends Build TeamMode = true; - registerModule(new TeamModule()); + new TeamModule().register(this); TeamPerSpawn = true; FillTeamsInOrderToCount = 2; diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/quiver/QuiverTeamBase.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/quiver/QuiverTeamBase.java index da2343c21..09a48d225 100644 --- a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/quiver/QuiverTeamBase.java +++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/quiver/QuiverTeamBase.java @@ -85,7 +85,7 @@ public class QuiverTeamBase extends TeamGame getQuiverTeamModule(ModuleSpawnBarrier.class); getQuiverTeamModule(ModuleKillstreak.class); - registerModule(new VersionModule(MinecraftVersion.Version1_9, "One in the Quiver Payload requires Minecraft 1.9!")); + new VersionModule(MinecraftVersion.Version1_9, "One in the Quiver Payload requires Minecraft 1.9!").register(this); // if (WorldData.GetCustomLocs(CUSTOM_LOCATION_GAME_KOTH) != null) // { diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/skyfall/Skyfall.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/skyfall/Skyfall.java index 374fa3cc0..ab27d1ecb 100644 --- a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/skyfall/Skyfall.java +++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/skyfall/Skyfall.java @@ -181,7 +181,7 @@ public class Skyfall extends SoloGame BlankLine ); - registerModule(new VersionModule(MinecraftVersion.Version1_9, "Skyfall requires Minecraft 1.9!")); + new VersionModule(MinecraftVersion.Version1_9, "Skyfall requires Minecraft 1.9!").register(this); // Disable specific GWEN checks for this game AntiHack antiHack = Managers.get(AntiHack.class); diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/skywars/TeamSkywars.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/skywars/TeamSkywars.java index 74ed0a76a..540054617 100644 --- a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/skywars/TeamSkywars.java +++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/skywars/TeamSkywars.java @@ -68,7 +68,7 @@ public class TeamSkywars extends Skywars TeamMode = true; TeamPerSpawn = true; - registerModule(new TeamModule()); + new TeamModule().register(this); } @Override diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/smash/TeamSuperSmash.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/smash/TeamSuperSmash.java index c6414d5fd..47ccbf32b 100644 --- a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/smash/TeamSuperSmash.java +++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/smash/TeamSuperSmash.java @@ -46,7 +46,7 @@ public class TeamSuperSmash extends SuperSmash TeamMode = true; - registerModule(new TeamModule()); + new TeamModule().register(this); registerStatTrackers(new WinWithoutDyingStatTracker(this, "MLGPro"), new FreeKitWinStatTracker(this), new OneVThreeStatTracker(this), new KillFastStatTracker(this, 3, 10, "TripleKill"), new RecoveryMasterStatTracker(this)); diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/survivalgames/TeamSurvivalGames.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/survivalgames/TeamSurvivalGames.java index f6c6b1820..4e232331f 100644 --- a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/survivalgames/TeamSurvivalGames.java +++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/survivalgames/TeamSurvivalGames.java @@ -49,7 +49,7 @@ public class TeamSurvivalGames extends SurvivalGames DontAllowOverfill = true; TeamMode = true; - registerModule(new TeamModule()); + new TeamModule().register(this); registerStatTrackers(new WinWithoutWearingArmorStatTracker(this), new KillsWithinTimeLimitStatTracker(this, 3, 60, "Bloodlust"), diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/uhc/UHC.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/uhc/UHC.java index 9c086a1aa..bfc686152 100644 --- a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/uhc/UHC.java +++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/uhc/UHC.java @@ -1,6 +1,5 @@ package nautilus.game.arcade.game.games.uhc; -import com.mineplex.spigot.ChunkPreLoadEvent; import mineplex.core.account.CoreClient; import mineplex.core.boosters.event.BoosterItemGiveEvent; import mineplex.core.common.Pair; @@ -20,46 +19,45 @@ import mineplex.core.common.util.UtilTextMiddle; import mineplex.core.common.util.UtilTime; import mineplex.core.itemstack.ItemBuilder; import mineplex.core.itemstack.ItemStackFactory; -import mineplex.core.monitor.LagMeter; import mineplex.core.recharge.Recharge; -import mineplex.core.timing.TimingManager; import mineplex.core.updater.UpdateType; import mineplex.core.updater.event.UpdateEvent; import mineplex.minecraft.game.core.combat.CombatLog; import mineplex.minecraft.game.core.combat.event.CombatDeathEvent; + import nautilus.game.arcade.ArcadeManager; import nautilus.game.arcade.GameType; import nautilus.game.arcade.events.GamePrepareCountdownCommence; import nautilus.game.arcade.events.GameStateChangeEvent; import nautilus.game.arcade.events.PlayerPrepareTeleportEvent; +import nautilus.game.arcade.game.DebugCommand; import nautilus.game.arcade.game.Game; import nautilus.game.arcade.game.GameTeam; import nautilus.game.arcade.game.TeamGame; -import nautilus.game.arcade.game.games.uhc.helpers.ChunkLoadingThread; -import nautilus.game.arcade.game.games.uhc.helpers.WorldGenThread; import nautilus.game.arcade.game.modules.AntiExpOrbModule; import nautilus.game.arcade.game.modules.OreVeinEditorModule; +import nautilus.game.arcade.game.modules.PlayerHeadModule; +import nautilus.game.arcade.game.modules.SafezoneModule; import nautilus.game.arcade.game.modules.TeamModule; import nautilus.game.arcade.game.modules.combatlog.CombatLogModule; import nautilus.game.arcade.game.modules.combatlog.CombatLogNPC; import nautilus.game.arcade.kit.Kit; + import net.minecraft.server.v1_8_R3.MinecraftServer; import net.minecraft.server.v1_8_R3.WorldServer; + import org.bukkit.Bukkit; -import org.bukkit.ChatColor; import org.bukkit.Chunk; -import org.bukkit.Difficulty; import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.Sound; +import org.bukkit.World; import org.bukkit.World.Environment; import org.bukkit.WorldBorder; import org.bukkit.block.Block; import org.bukkit.block.BlockFace; -import org.bukkit.block.BlockState; import org.bukkit.craftbukkit.v1_8_R3.CraftWorld; import org.bukkit.craftbukkit.v1_8_R3.util.CraftMagicNumbers; -import org.bukkit.enchantments.Enchantment; import org.bukkit.entity.Entity; import org.bukkit.entity.EntityType; import org.bukkit.entity.Ghast; @@ -68,10 +66,6 @@ import org.bukkit.entity.Monster; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; -import org.bukkit.event.HandlerList; -import org.bukkit.event.block.Action; -import org.bukkit.event.block.BlockGrowEvent; -import org.bukkit.event.block.BlockPistonExtendEvent; import org.bukkit.event.block.BlockPlaceEvent; import org.bukkit.event.entity.EntityDamageEvent; import org.bukkit.event.entity.EntityDamageEvent.DamageCause; @@ -83,58 +77,41 @@ import org.bukkit.event.entity.PlayerDeathEvent; import org.bukkit.event.inventory.InventoryClickEvent; import org.bukkit.event.inventory.PrepareItemCraftEvent; import org.bukkit.event.player.PlayerCommandPreprocessEvent; -import org.bukkit.event.player.PlayerInteractEvent; -import org.bukkit.event.player.PlayerItemConsumeEvent; import org.bukkit.event.player.PlayerKickEvent; -import org.bukkit.event.player.PlayerPickupItemEvent; import org.bukkit.event.player.PlayerPortalEvent; import org.bukkit.event.player.PlayerQuitEvent; import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause; -import org.bukkit.event.world.ChunkLoadEvent; -import org.bukkit.event.world.ChunkPopulateEvent; import org.bukkit.event.world.ChunkUnloadEvent; -import org.bukkit.event.world.StructureGrowEvent; import org.bukkit.inventory.CraftingInventory; import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.ShapedRecipe; import org.bukkit.inventory.ShapelessRecipe; -import org.bukkit.inventory.meta.SkullMeta; -import org.bukkit.material.MaterialData; import org.bukkit.potion.PotionEffect; import org.bukkit.potion.PotionEffectType; +import org.bukkit.scheduler.BukkitRunnable; import org.bukkit.scoreboard.DisplaySlot; import org.bukkit.scoreboard.Objective; +import java.nio.charset.StandardCharsets; import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; import java.util.List; import java.util.Map; -import java.util.Set; import java.util.UUID; import java.util.concurrent.atomic.AtomicInteger; +import java.util.stream.Collectors; +import java.util.stream.Stream; public class UHC extends TeamGame { - // The view distance of UHC. The amount of time and ram needed grows polynomially - public static final int VIEW_DISTANCE = 5; + private static int _gamesRun = 0; - // The number of threads to use for reading chunks from disk - public static final int THREADS_FOR_CHUNK_LOADING = 4; + public static final int VIEW_DISTANCE = 5; // The number of minutes after which PVP should be enabled public static final int SAFE_TIME_IN_MINUTES = 11; - // The number of chunks to unload per tick - public static final int CHUNKS_UNLOAD_PER_TICK = 1; - - // The number of ticks to delay chunk unloading by - public static final long CHUNKS_UNLOAD_DELAY = 5 * 20L; - - // The number of ticks to wait between each chunk unload period - public static final long CHUNKS_UNLOAD_PERIOD = 2 * 20L; - // This is the region in which nothing can be done (block placing, flowing, etc) public static final int SAFE_REGION = 36; @@ -144,21 +121,6 @@ public class UHC extends TeamGame // The number of ticks to delay before teleporting each player public static final long DELAY_BETWEEN_PLAYER_TELEPORT = 5L; - // The centers of the spawn for each team - private Map _teamCenter = new HashMap<>(); - - // The thread responsible for generating the world - private final WorldGenThread _worldGenThread = new WorldGenThread(this); - - // The thread responsible for loading and decorating the world - private final ChunkLoadingThread _chunkLoadingThread = new ChunkLoadingThread(this); - - // The chunks which we have prevented unloading - private final Set _loadedChunks = new HashSet<>(); - - // The task which will unload chunks periodically - private int _chunkUnloadTaskId = -1; - // The number of minutes passed in this game private int _minutesSinceStart = 0; @@ -174,11 +136,13 @@ public class UHC extends TeamGame // Border private int _secondsSinceStart; - private HashMap _borderPositions = new HashMap(); + private Map _borderPositions = new HashMap<>(); private double _currentBorder = 1000; private double _previousBorder = 1000; private long _borderStartedMoving; + private boolean _hasPvpStarted = false; + public UHC(ArcadeManager manager) { this(manager, GameType.UHC); @@ -191,17 +155,16 @@ public class UHC extends TeamGame DamageDealt ); - registerModule( - new OreVeinEditorModule() - .removeNonAirVeins() - ); - registerModule(new AntiExpOrbModule()); + new OreVeinEditorModule() + .removeNonAirVeins() + .register(this); + new AntiExpOrbModule() + .register(this); } public UHC(ArcadeManager manager, GameType type) { super(manager, type, - new Kit[] { new KitUHC(manager) @@ -283,37 +246,287 @@ public class UHC extends TeamGame _healthObjective = Scoreboard.getScoreboard().registerNewObjective("Health", "health"); _healthObjective.setDisplaySlot(DisplaySlot.PLAYER_LIST); - registerModule(new TeamModule()); + new TeamModule().register(this); + new PlayerHeadModule().register(this); + new SafezoneModule() + .filter(location -> + location.getX() <= SAFE_REGION && location.getX() >= -SAFE_REGION && + location.getZ() <= SAFE_REGION && location.getZ() >= -SAFE_REGION) + .register(this); + + registerDebugCommand(new DebugCommand("startpvp", Rank.ADMIN) + { + @Override + public void Execute(Player caller, String[] args) + { + if (GetState() != GameState.Live) + { + UtilPlayer.message(caller, F.main("Debug", "You can't start the game right now!")); + return; + } + if (_hasPvpStarted) + { + UtilPlayer.message(caller, F.main("Debug", "PvP has already been started!")); + return; + } + _minutesSinceStart = SAFE_TIME_IN_MINUTES + 1; + startPvp(); + UtilPlayer.message(caller, F.main("Debug", "Started PvP")); + } + }); + + registerDebugCommand(new DebugCommand("worldinfo", Rank.ADMIN) + { + @Override + public void Execute(Player caller, String[] args) + { + if (args == null || args.length == 0) + { + UtilPlayer.message(caller, F.main("Debug", "Loaded worlds:")); + UtilPlayer.message(caller, F.desc("Bukkit Worlds", Bukkit.getWorlds().stream().map(World::getName).collect(Collectors.joining(", ")))); + UtilPlayer.message(caller, F.desc("NMS Worlds", MinecraftServer.getServer().worlds.stream() + .map(net.minecraft.server.v1_8_R3.WorldServer::getWorldData) + .map(net.minecraft.server.v1_8_R3.WorldData::getName) + .collect(Collectors.joining(", ")))); + return; + } + if (args[0].equals("info")) + { + if (args.length > 1) + { + String worldName = args[1]; + World targetWorld = null; + + if (worldName.startsWith("b:")) + { + targetWorld = Bukkit.getWorlds().stream().filter(world -> world.getName().replace(" ", "").equals(worldName.substring(2))).findAny().orElse(null); + } + else if (worldName.startsWith("n:")) + { + WorldServer world = MinecraftServer.getServer().worlds.stream().filter(ws -> ws.getWorldData().getName().replace(" ", "").equals(worldName.substring(2))).findAny().orElse(null); + if (world != null) + { + targetWorld = world.getWorld(); + } + } + else + { + UtilPlayer.message(caller, F.main("Debug", "No world type specified")); + return; + } + + if (targetWorld != null) + { + WorldServer nmsWorld = ((CraftWorld) targetWorld).getHandle(); + Chunk[] chunks = targetWorld.getLoadedChunks(); + UtilPlayer.message(caller, F.main("Debug", "World info for " + targetWorld.getName())); + UtilPlayer.message(caller, F.desc("Chunks", String.valueOf(chunks.length))); + UtilPlayer.message(caller, F.desc("Entities", String.valueOf(targetWorld.getEntities().size()))); + UtilPlayer.message(caller, F.desc("Tile Entities", String.valueOf(Arrays.stream(chunks).map(Chunk::getTileEntities).map(Arrays::asList).flatMap(Collection::stream).count()))); + UtilPlayer.message(caller, F.desc("View Distance", String.valueOf(nmsWorld.spigotConfig.viewDistance))); + UtilPlayer.message(caller, F.desc("Unload queue size", String.valueOf(nmsWorld.chunkProviderServer.unloadQueue.size()))); + } + else + { + UtilPlayer.message(caller, F.main("Debug", "That world was not found")); + } + } + else + { + UtilPlayer.message(caller, F.main("Debug", "No world specified")); + } + } + else if (args[0].equals("chunks")) + { + + if (args.length > 1) + { + String worldName = args[1]; + World targetWorld = null; + + if (worldName.startsWith("b:")) + { + targetWorld = Bukkit.getWorlds().stream().filter(world -> world.getName().replace(" ", "").equals(worldName.substring(2))).findAny().orElse(null); + } + else if (worldName.startsWith("n:")) + { + WorldServer world = MinecraftServer.getServer().worlds.stream().filter(ws -> ws.getWorldData().getName().replace(" ", "").equals(worldName.substring(2))).findAny().orElse(null); + if (world != null) + { + targetWorld = world.getWorld(); + } + } + else + { + UtilPlayer.message(caller, F.main("Debug", "No world type specified")); + return; + } + + if (targetWorld != null) + { + String message = Arrays.stream(targetWorld.getLoadedChunks()).map(chunk -> "(" + chunk.getX() + "," + chunk.getZ() + ")").collect(Collectors.joining(",")); + System.out.println("Chunks: " + message); + if (message.getBytes(StandardCharsets.UTF_8).length < 32767) + { + caller.sendMessage(message); + } + } + else + { + UtilPlayer.message(caller, F.main("Debug", "That world was not found")); + } + } + else + { + UtilPlayer.message(caller, F.main("Debug", "No world specified")); + } + } + return; + } + }); + registerDebugCommand(new DebugCommand("uhcgames", Rank.ADMIN) + { + @Override + public void Execute(Player caller, String[] args) + { + UtilPlayer.message(caller, F.main("Debug", "As of now, there have been " + _gamesRun + " games played")); + } + }); + registerDebugCommand(new DebugCommand("uhcgc", Rank.DEVELOPER) + { + @Override + public void Execute(Player caller, String[] args) + { + System.gc(); + UtilPlayer.message(caller, F.main("Debug", "Cleaned up!")); + } + }); } - @EventHandler - public void onLoad(ChunkLoadEvent event) + + @Override + public void recruit() { - if (event.getChunk().getWorld().equals(WorldData.World) && _isTeleporting) + // todo load chunks sync here if necessary + Location spawn = GetRandomSpawn(WorldData.World.getSpawnLocation(), true); + WorldData.World.setSpawnLocation(spawn.getBlockX(), spawn.getBlockY(), spawn.getBlockZ()); + + WorldServer worldServer = ((CraftWorld) WorldData.World).getHandle(); + + // Update view distance + worldServer.spigotConfig.viewDistance = VIEW_DISTANCE; + worldServer.getPlayerChunkMap().a(VIEW_DISTANCE); + + // Wipe Spawns + for (GameTeam team : this.GetTeamList()) { - new Exception(event.getChunk().getX() + " " + event.getChunk().getZ()).printStackTrace(); + team.GetSpawns().clear(); } - } - @EventHandler - public void onPopulate(ChunkPopulateEvent event) - { - if (event.getChunk().getWorld().equals(WorldData.World) && _isTeleporting) + // Solo Game + if (this._teamList.size() == 1) { - new Exception(event.getChunk().getX() + " " + event.getChunk().getZ()).printStackTrace(); + getArcadeManager().runSyncTimer(new BukkitRunnable() + { + @Override + public void run() + { + if (GetTeamList().get(0).GetSpawns().size() < GetPlayers(true).size()) + { + Location loc = GetRandomSpawn(null, false); + + // Dynamically scale distance requirement based on how many teams need to fit + double dist = (2 * _currentBorder) / (Math.sqrt(GetPlayers(true).size()) + 3); + + // Ensure distance between Teams - 500 Attempts + for (int i = 0; i < 500; i++) + { + boolean clash = false; + + for (Location otherSpawn : GetTeamList().get(0).GetSpawns()) + { + if (UtilMath.offset(loc, otherSpawn) < dist) + { + clash = true; + break; + } + } + + if (!clash) + break; + + loc = GetRandomSpawn(null, false); + } + + GetTeamList().get(0).GetSpawns().add(loc); + } + else + { + cancel(); + SetState(GameState.Recruit); + } + } + }, 0L, 1L); + } + else + { + getArcadeManager().runSyncTimer(new BukkitRunnable() + { + AtomicInteger currentTeamId = new AtomicInteger(); + + @Override + public void run() + { + GameTeam team = _teamList.get(currentTeamId.get()); + + Location loc = GetRandomSpawn(null, false); + + // Dynamically scale distance requirement based on how many teams need to fit + double dist = (2 * _currentBorder) / (Math.sqrt(GetTeamList().size()) + 3); + + // Ensure distance between Teams - 500 Attempts + for (int i = 0; i < 500; i++) + { + boolean clash = false; + + for (GameTeam otherTeam : GetTeamList()) + { + if (otherTeam.GetSpawns().isEmpty()) + continue; + + if (UtilMath.offset(loc, otherTeam.GetSpawn()) < dist) + { + clash = true; + break; + } + } + + if (!clash) + break; + + loc = GetRandomSpawn(null, false); + } + + while (team.GetSpawns().size() < 20) + { + team.GetSpawns().add(GetRandomSpawn(loc, true)); + } + + currentTeamId.getAndIncrement(); + + if (currentTeamId.get() >= _teamList.size()) + { + cancel(); + SetState(GameState.Recruit); + } + } + }, 0L, 1L); } } @Override public void ParseData() { - WorldData.World.setDifficulty(Difficulty.HARD); - - WorldData.MinX = -1000; - WorldData.MinZ = -1000; - WorldData.MaxX = 1000; - WorldData.MaxZ = 1000; - int i = 0; for (double border : buildBorders(1000, 1000, 32)) @@ -327,6 +540,14 @@ public class UHC extends TeamGame border.setDamageBuffer(-99); border.setWarningDistance(-99); border.setWarningTime(-99); + + WorldData.World.getEntities().forEach(Entity::remove); + } + + @Override + public boolean loadNecessaryChunks(long timeout) + { + return true; } @EventHandler @@ -445,11 +666,11 @@ public class UHC extends TeamGame } } - private ArrayList buildBorders(int seconds, double border, double leaveRemaining) + private List buildBorders(int seconds, double border, double leaveRemaining) { double totalNumber = Math.pow(seconds, 1.9D) + (seconds * 50); - ArrayList borders = new ArrayList(); + List borders = new ArrayList<>(); for (int i = 0; i <= seconds; i++) { @@ -459,112 +680,6 @@ public class UHC extends TeamGame return borders; } - public void generateSpawns() - { - // Wipe Spawns - for (GameTeam team : this.GetTeamList()) - { - team.GetSpawns().clear(); - } - - TimingManager.start("UHC Spawn Generation"); - - // Solo Game - if (this.GetTeamList().size() == 1) - { - while (GetTeamList().get(0).GetSpawns().size() < this.GetPlayers(true).size()) - { - Location loc = GetRandomSpawn(null, false); - - // Dynamically scale distance requirement based on how many teams need to fit - double dist = (2 * _currentBorder) / (Math.sqrt(this.GetPlayers(true).size()) + 3); - - // Ensure distance between Teams - 500 Attempts - for (int i = 0; i < 500; i++) - { - boolean clash = false; - - for (Location otherSpawn : GetTeamList().get(0).GetSpawns()) - { - if (UtilMath.offset(loc, otherSpawn) < dist) - { - clash = true; - break; - } - } - - if (!clash) - break; - - loc = GetRandomSpawn(null, false); - } - - GetTeamList().get(0).GetSpawns().add(loc); - } - } - // Team Game - else - { - for (GameTeam team : GetTeamList()) - { - Location loc = GetRandomSpawn(null, false); - - // Dynamically scale distance requirement based on how many teams need to fit - double dist = (2 * _currentBorder) / (Math.sqrt(GetTeamList().size()) + 3); - - // Ensure distance between Teams - 500 Attempts - for (int i = 0; i < 500; i++) - { - boolean clash = false; - - for (GameTeam otherTeam : GetTeamList()) - { - if (otherTeam.GetSpawns().isEmpty()) - continue; - - if (UtilMath.offset(loc, otherTeam.GetSpawn()) < dist) - { - clash = true; - break; - } - } - - if (!clash) - break; - - loc = GetRandomSpawn(null, false); - } - - _teamCenter.put(team, loc); - team.GetSpawns().add(loc); - } - } - - TimingManager.stop("UHC Spawn Generation"); - - Location spawn = GetRandomSpawn(WorldData.World.getSpawnLocation(), true); - WorldData.World.setSpawnLocation(spawn.getBlockX(), spawn.getBlockY(), spawn.getBlockZ()); - - WorldServer worldServer = ((CraftWorld) WorldData.World).getHandle(); - - // Update view distance - worldServer.spigotConfig.viewDistance = VIEW_DISTANCE; - worldServer.getPlayerChunkMap().a(VIEW_DISTANCE); - - if (Runtime.getRuntime().maxMemory() / 1024 / 1024 < 1536) - { - Announce(C.cGreen + C.Bold + "Skipping spawn pregeneration", false); - // Allow game to start - _chunkLoadingThread.flagDone(); - return; - } - - // Ensures the server does not tick us - worldServer.getMinecraftServer().worlds.remove(worldServer); - - _chunkLoadingThread.start(); - } - @EventHandler public void endPortalTransfer(final PlayerPortalEvent event) { @@ -589,78 +704,92 @@ public class UHC extends TeamGame } else if (_minutesSinceStart == SAFE_TIME_IN_MINUTES) { - UtilTextMiddle.display(null, "PvP has been enabled!", 5, 80, 5); - - for (Player player : UtilServer.getPlayers()) - player.playSound(player.getLocation(), Sound.ENDERDRAGON_GROWL, 1f, 1f); - - this.DamagePvP = true; - this.CompassGiveItem = true; - this.RejoinTime = 300000; // 5 minutes - registerModule(new CombatLogModule()) - .setSpawnForCreative(false) - .setCombatLogTime(300000) - .setOnDeathAction(npc -> - { - if (npc.getLastDamager() instanceof Player) - { - Player killer = (Player) npc.getLastDamager(); - Announce(npc.getPlayerInfo().getTeamColor() + C.Bold + npc.getPlayerInfo().getName() - + C.cGray + C.Bold + " was killed by " + getArcadeManager().GetColor(killer) - + C.Bold + npc.getLastDamager().getName() + C.cGray + C.Bold + " while logged out."); - } - else - { - String cause = UtilParser.parseDamageCause(npc.getLastDamageCause()); - if (npc.getLastDamager() != null) - { - cause = npc.getLastDamager().getName(); - } - Announce(npc.getPlayerInfo().getTeamColor() + C.Bold + npc.getPlayerInfo().getName() - + C.cGray + C.Bold + " was killed by " + cause + " while logged out."); - } - - ItemStack stack = new ItemBuilder(Material.SKULL_ITEM) - .setData((byte) 3) - .setTitle(npc.getPlayerInfo().getTeamColor() + npc.getPlayerInfo().getName() + "'s Head") - .build(); - - SkullMeta meta = (SkullMeta) stack.getItemMeta(); - meta.setOwner(npc.getPlayerInfo().getName()); - stack.setItemMeta(meta); - - npc.getNPC().getWorld().dropItemNaturally(npc.getNPC().getLocation(), stack); - - Location location = npc.getNPC().getLocation(); - - for (ItemStack item : npc.getPlayerInfo().getItems()) - { - location.getWorld().dropItemNaturally(location, item); - } - }) - .setOnExpireAction(npc -> - { - ItemStack stack = new ItemBuilder(Material.SKULL_ITEM) - .setData((byte) 3) - .setTitle(npc.getPlayerInfo().getTeamColor() + npc.getPlayerInfo().getName() + "'s Head") - .build(); - - SkullMeta meta = (SkullMeta) stack.getItemMeta(); - meta.setOwner(npc.getPlayerInfo().getName()); - stack.setItemMeta(meta); - - npc.getNPC().getWorld().dropItemNaturally(npc.getNPC().getLocation(), stack); - - Location location = npc.getNPC().getLocation(); - - for (ItemStack item : npc.getPlayerInfo().getItems()) - { - location.getWorld().dropItemNaturally(location, item); - } - }); + startPvp(); } } + private void startPvp() + { + if (_hasPvpStarted) + return; + + _hasPvpStarted = true; + UtilTextMiddle.display(null, "PvP has been enabled!", 5, 80, 5); + + for (Player player : UtilServer.getPlayers()) + player.playSound(player.getLocation(), Sound.ENDERDRAGON_GROWL, 1f, 1f); + + this.DamagePvP = true; + this.RejoinTime = 300000; // 5 minutes + this.CompassGiveItem = true; + new CombatLogModule() + .setSpawnForCreative(false) + .setCombatLogTime(300000) + .setOnDeathAction(npc -> + { + if (npc.getLastDamager() instanceof Player) + { + Player killer = (Player) npc.getLastDamager(); + Announce(npc.getPlayerInfo().getTeamColor() + C.Bold + npc.getPlayerInfo().getName() + + C.cGray + C.Bold + " was killed by " + getArcadeManager().GetColor(killer) + + C.Bold + npc.getLastDamager().getName() + C.cGray + C.Bold + " while logged out."); + } + else + { + String cause = UtilParser.parseDamageCause(npc.getLastDamageCause()); + if (npc.getLastDamager() != null) + { + cause = npc.getLastDamager().getName(); + } + Announce(npc.getPlayerInfo().getTeamColor() + C.Bold + npc.getPlayerInfo().getName() + + C.cGray + C.Bold + " was killed by " + cause + " while logged out."); + } + + ItemStack stack = new ItemBuilder(Material.SKULL_ITEM) + .setData((byte) 3) + .setTitle(npc.getPlayerInfo().getTeamColor() + npc.getPlayerInfo().getName() + "'s Head") + .setPlayerHead(npc.getPlayerInfo().getName()) + .build(); + + npc.getNPC().getWorld().dropItemNaturally(npc.getNPC().getLocation(), stack); + + Location location = npc.getNPC().getLocation(); + + for (ItemStack item : npc.getPlayerInfo().getItems()) + { + location.getWorld().dropItemNaturally(location, item); + } + + RejoinTimes.remove(npc.getPlayerInfo().getName()); + RejoinKit.remove(npc.getPlayerInfo().getName()); + RejoinTeam.remove(npc.getPlayerInfo().getName()); + RejoinHealth.remove(npc.getPlayerInfo().getName()); + }) + .setOnExpireAction(npc -> + { + ItemStack stack = new ItemBuilder(Material.SKULL_ITEM) + .setData((byte) 3) + .setTitle(npc.getPlayerInfo().getTeamColor() + npc.getPlayerInfo().getName() + "'s Head") + .setPlayerHead(npc.getPlayerInfo().getName()) + .build(); + + npc.getNPC().getWorld().dropItemNaturally(npc.getNPC().getLocation(), stack); + + Location location = npc.getNPC().getLocation(); + + for (ItemStack item : npc.getPlayerInfo().getItems()) + { + location.getWorld().dropItemNaturally(location, item); + } + + RejoinTimes.remove(npc.getPlayerInfo().getName()); + RejoinKit.remove(npc.getPlayerInfo().getName()); + RejoinTeam.remove(npc.getPlayerInfo().getName()); + RejoinHealth.remove(npc.getPlayerInfo().getName()); + }) + .register(this); + } + @EventHandler public void EarlyGameUpdate(UpdateEvent event) { @@ -708,57 +837,12 @@ public class UHC extends TeamGame } } - @EventHandler - public void generateWorld(GameStateChangeEvent event) - { - if (event.GetState() == GameState.Dead) - { - _worldGenThread.flagStop(); - _chunkLoadingThread.flagStop(); - if (!_chunkLoadingThread.isDone()) - { - MinecraftServer.getServer().worlds.add(((CraftWorld) WorldData.World).getHandle()); - } - HandlerList.unregisterAll(_chunkLoadingThread); - -// if (_chunkUnloadTaskId != -1) -// { -// Bukkit.getScheduler().cancelTask(_chunkUnloadTaskId); -// } -// -// Iterator iterator = _loadedChunks.iterator(); -// while (iterator.hasNext()) -// { -// Chunk chunk = iterator.next(); -// WorldData.World.unloadChunk(chunk.getX(), chunk.getZ()); -// iterator.remove(); -// } - - return; - } - - if (event.GetState() == GameState.Recruit) - { - _worldGenThread.start(); - } - } - @EventHandler(priority = EventPriority.MONITOR) public void on(ChunkUnloadEvent event) { if (!IsLive()) { event.setCancelled(true); -// _loadedChunks.add(event.getChunk()); - } - } - - @EventHandler - public void on(ChunkPreLoadEvent event) - { - if (_isTeleporting) - { - new Exception("WARNING: TRIED TO LOAD CHUNK WHILE TELEPORTING: " + event.getX() + " " + event.getZ()).printStackTrace(); } } @@ -789,14 +873,6 @@ public class UHC extends TeamGame if (event.GetState() != GameState.Prepare) return; - for (Map.Entry entries : _teamCenter.entrySet()) - { - while (entries.getKey().GetSpawns().size() < 20) - { - entries.getKey().GetSpawns().add(GetRandomSpawn(entries.getValue(), true)); - } - } - Manager.GetChat().Silence(1000 * 120, false); _isTeleporting = true; @@ -837,98 +913,70 @@ public class UHC extends TeamGame Map teleportedLocations = new HashMap<>(); - AtomicInteger id = new AtomicInteger(); - id.set(UtilServer.getServer().getScheduler().runTaskTimer(Manager.getPlugin(), () -> + getArcadeManager().runSyncTimer(new BukkitRunnable() { - _teleportedPlayers++; - if (_teleportedPlayers >= players.size()) + @Override + public void run() { - Announce(C.cGreen + C.Bold + "The game will start in 5 seconds", false); - Manager.runSyncLater(() -> + _teleportedPlayers++; + if (_teleportedPlayers >= players.size()) { - try + Announce(C.cGreen + C.Bold + "The game will start in 5 seconds", false); + Manager.runSyncLater(() -> { - for (Player player : players) + try { - GameTeam team = game.GetTeam(player); - if (team != null) + for (Player player : players) { - if (teleportedLocations.get(player.getUniqueId()) != null) + GameTeam team = game.GetTeam(player); + if (team != null) { - team.SpawnTeleport(player, teleportedLocations.get(player.getUniqueId())); + if (teleportedLocations.get(player.getUniqueId()) != null) + { + team.SpawnTeleport(player, teleportedLocations.get(player.getUniqueId())); + } } + + // Heal + player.setHealth(player.getMaxHealth()); + // Resistance and regen + player.addPotionEffect(new PotionEffect(PotionEffectType.REGENERATION, 10 * 20, 128), true); + player.addPotionEffect(new PotionEffect(PotionEffectType.DAMAGE_RESISTANCE, 10 * 20, 128), true); } - // Heal - player.setHealth(player.getMaxHealth()); - // Resistance and regen - player.addPotionEffect(new PotionEffect(PotionEffectType.REGENERATION, 10 * 20, 128), true); - player.addPotionEffect(new PotionEffect(PotionEffectType.DAMAGE_RESISTANCE, 10 * 20, 128), true); - } - - teleportedLocations.clear(); - } - finally - { - game.AnnounceGame(); - game.StartPrepareCountdown(); - - //Event - GamePrepareCountdownCommence gamePrepareCountdownCommence = new GamePrepareCountdownCommence(game); - UtilServer.getServer().getPluginManager().callEvent(gamePrepareCountdownCommence); - - _isTeleporting = false; - - Manager.runSyncLater(() -> + teleportedLocations.clear(); + } finally { - WorldData.World.setAutoSave(true); + game.AnnounceGame(); + game.StartPrepareCountdown(); -// _chunkUnloadTaskId = Bukkit.getScheduler().runTaskTimer(getArcadeManager().getPlugin(), () -> -// { -// Iterator iterator = _loadedChunks.iterator(); -// int amount = 0; -// -// while (amount < CHUNKS_UNLOAD_PER_TICK && iterator.hasNext()) -// { -// if (WorldData == null || WorldData.World == null) -// { -// Bukkit.getScheduler().cancelTask(_chunkUnloadTaskId); -// return; -// } -// -// Chunk next = iterator.next(); -// WorldData.World.unloadChunkRequest(next.getX(), next.getZ()); -// iterator.remove(); -// amount++; -// } -// -// if (_loadedChunks.size() == 0) -// { -// Bukkit.getScheduler().cancelTask(_chunkUnloadTaskId); -// } -// }, CHUNKS_UNLOAD_DELAY, CHUNKS_UNLOAD_PERIOD).getTaskId(); - }, 10 * 20L); - } - }, 5 * 20L); - Bukkit.getServer().getScheduler().cancelTask(id.get()); - return; + //Event + GamePrepareCountdownCommence gamePrepareCountdownCommence = new GamePrepareCountdownCommence(game); + UtilServer.getServer().getPluginManager().callEvent(gamePrepareCountdownCommence); + + _isTeleporting = false; + } + }, 5 * 20L); + cancel(); + return; + } + + Player player = players.get(_teleportedPlayers); + GameTeam team = game.GetTeam(player); + + // This could happen if the player left (and rejoined) while teleporting + // Team maps based on player as a key + if (team != null) + { + // Save where they teleported + teleportedLocations.put(player.getUniqueId(), team.SpawnTeleport(player)); + + //Event + PlayerPrepareTeleportEvent playerStateEvent = new PlayerPrepareTeleportEvent(game, player); + UtilServer.getServer().getPluginManager().callEvent(playerStateEvent); + } } - - Player player = players.get(_teleportedPlayers); - GameTeam team = game.GetTeam(player); - - // This could happen if the player left (and rejoined) while teleporting - // Team maps based on player as a key - if (team != null) - { - // Save where they teleported - teleportedLocations.put(player.getUniqueId(), team.SpawnTeleport(player)); - - //Event - PlayerPrepareTeleportEvent playerStateEvent = new PlayerPrepareTeleportEvent(game, player); - UtilServer.getServer().getPluginManager().callEvent(playerStateEvent); - } - }, 5 * 20L, DELAY_BETWEEN_PLAYER_TELEPORT).getTaskId()); + }, 5 * 20L, DELAY_BETWEEN_PLAYER_TELEPORT); //Spectators Move for (Player player : UtilServer.getPlayers()) @@ -960,84 +1008,6 @@ public class UHC extends TeamGame return SpectatorSpawn; } - // fixme flowing water and stuff - - @EventHandler - public void preventBlockPlacement(BlockPlaceEvent event) - { - if (isInSafeZone(event.getBlock().getLocation())) - { - UtilPlayer.message(event.getPlayer(), F.main("Game", "You cannot build this high near center of map.")); - event.setCancelled(true); - } - } - - @EventHandler - public void preventStructureGrow(StructureGrowEvent event) - { - Iterator blocks = event.getBlocks().iterator(); - while (blocks.hasNext()) - { - BlockState next = blocks.next(); - if (isInSafeZone(next.getLocation())) - { - blocks.remove(); - } - } - } - - @EventHandler - public void preventBlockGrow(BlockGrowEvent event) - { - if (isInSafeZone(event.getBlock().getLocation())) - { - event.setCancelled(true); - } - } - - @EventHandler - public void preventBoneMeal(PlayerInteractEvent event) - { - if (event.getAction() == Action.RIGHT_CLICK_BLOCK) - { - boolean isIllegal = false; - if (!isIllegal) - { - isIllegal = event.getPlayer().getItemInHand().getType() == Material.INK_SACK && - event.getPlayer().getItemInHand().getData().getData() == (byte) 15; - } - - if (isIllegal && isInSafeZone(event.getClickedBlock().getLocation())) - { - event.setCancelled(true); - } - } - } - - @EventHandler - public void preventPistons(BlockPistonExtendEvent event) - { - boolean willBeUnsafe = false; - for (Block block : event.getBlocks()) - { - if (isInSafeZone(block.getRelative(event.getDirection()).getLocation())) - { - willBeUnsafe = true; - break; - } - } - if (willBeUnsafe) - { - event.setCancelled(true); - } - } - - private boolean isInSafeZone(Location location) - { - return location.getX() <= SAFE_REGION && location.getX() >= -SAFE_REGION - && location.getZ() <= SAFE_REGION && location.getZ() >= -SAFE_REGION; - } - private Location GetRandomSpawn(Location around, boolean sameChunk) { int tries = 0; @@ -1121,35 +1091,6 @@ public class UHC extends TeamGame } } - @EventHandler(priority = EventPriority.LOWEST) - public void PlayerQuitDropItems(PlayerQuitEvent event) - { - Player player = event.getPlayer(); - - GameTeam team = GetTeam(player); - if (team == null) - return; - - if (!IsAlive(player)) - return; - - if (!QuitOut) - return; - - // Drop Items - UtilInv.drop(player, true); - - // Skull Drop - ItemStack stack = ItemStackFactory.Instance.CreateStack(Material.SKULL_ITEM, (byte) 3, 1, - team.GetColor() + player.getName() + "'s Head"); - - SkullMeta meta = (SkullMeta) stack.getItemMeta(); - meta.setOwner(player.getName()); - stack.setItemMeta(meta); - - event.getPlayer().getWorld().dropItemNaturally(player.getEyeLocation(), stack); - } - @EventHandler public void PlayerDeath(PlayerDeathEvent event) { @@ -1159,16 +1100,6 @@ public class UHC extends TeamGame if (team == null) return; - // Skull Drop - ItemStack stack = ItemStackFactory.Instance.CreateStack(Material.SKULL_ITEM, (byte) 3, 1, - team.GetColor() + player.getName() + "'s Head"); - - SkullMeta meta = (SkullMeta) stack.getItemMeta(); - meta.setOwner(player.getName()); - stack.setItemMeta(meta); - - event.getDrops().add(stack); - // Lightning Location loc = player.getLocation(); loc.setY(-150); @@ -1268,71 +1199,6 @@ public class UHC extends TeamGame goldMelon.addIngredient(1, Material.MELON); goldMelon.addIngredient(1, Material.GOLD_BLOCK); UtilServer.getServer().addRecipe(goldMelon); - - ShapedRecipe headApple2 = new ShapedRecipe(new ItemStack(Material.GOLDEN_APPLE, 1)); - headApple2.shape("GGG", "GHG", "GGG"); - headApple2.setIngredient('G', Material.GOLD_INGOT); - headApple2.setIngredient('H', new MaterialData(Material.SKULL_ITEM, (byte) 3)); - UtilServer.getServer().addRecipe(headApple2); - } - - @EventHandler(priority = EventPriority.HIGH) - public void CraftGoldenAppleDeny(PrepareItemCraftEvent event) - { - if (event.getRecipe().getResult() == null) - return; - - Material type = event.getRecipe().getResult().getType(); - - if (type != Material.GOLDEN_APPLE) - return; - - if (!(event.getInventory() instanceof CraftingInventory)) - return; - - CraftingInventory inv = (CraftingInventory) event.getInventory(); - - for (ItemStack item : inv.getMatrix()) - if (item != null && item.getType() != Material.AIR) - if (item.getType() == Material.GOLD_INGOT) - return; - - inv.setResult(null); - } - - @EventHandler(priority = EventPriority.HIGH) - public void CraftGoldenAppleHead(PrepareItemCraftEvent event) - { - if (event.getRecipe().getResult() == null) - return; - - Material type = event.getRecipe().getResult().getType(); - - if (type != Material.GOLDEN_APPLE) - return; - - if (!(event.getInventory() instanceof CraftingInventory)) - return; - - CraftingInventory inv = (CraftingInventory) event.getInventory(); - - for (ItemStack item : inv.getMatrix()) - if (item != null && item.getType() != Material.AIR) - if (item.getType() == Material.SKULL_ITEM || item.getType() == Material.SKULL) - { - if (item.getItemMeta() == null) - continue; - - if (item.getItemMeta().getDisplayName() == null) - continue; - - ItemStack apple = ItemStackFactory.Instance.CreateStack(Material.GOLDEN_APPLE, (byte) 0, 1, item - .getItemMeta().getDisplayName() + ChatColor.AQUA + " Golden Apple"); - apple.addUnsafeEnchantment(Enchantment.ARROW_DAMAGE, 1); - - inv.setResult(apple); - return; - } } @EventHandler(priority = EventPriority.HIGH) @@ -1346,10 +1212,7 @@ public class UHC extends TeamGame if (type != Material.SPECKLED_MELON) return; - if (!(event.getInventory() instanceof CraftingInventory)) - return; - - CraftingInventory inv = (CraftingInventory) event.getInventory(); + CraftingInventory inv = event.getInventory(); // Allow FULL BLOCK Gold Melon for (ItemStack item : inv.getMatrix()) @@ -1367,47 +1230,6 @@ public class UHC extends TeamGame event.setCancelled(true); } - @EventHandler - public void HeadPlaceCancel(BlockPlaceEvent event) - { - if (event.getItemInHand().getType() == Material.SKULL || event.getItemInHand().getType() == Material.SKULL_ITEM) - event.setCancelled(true); - } - - @EventHandler(priority = EventPriority.MONITOR) - public void HeadPickup(PlayerPickupItemEvent event) - { - if (!IsLive()) - return; - - if (event.isCancelled()) - return; - - if (event.getItem().getItemStack().getType() == Material.SKULL_ITEM) - { - UtilPlayer.message(event.getPlayer(), " "); - UtilPlayer.message(event.getPlayer(), C.cGreen + C.Bold + "You picked up a Player Head!"); - UtilPlayer.message(event.getPlayer(), C.cWhite + "Craft a Golden Head Apple with it for ultimate healing."); - UtilPlayer.message(event.getPlayer(), C.cWhite + "Use the recipe for Golden Apple, but Head replaces Apple."); - UtilPlayer.message(event.getPlayer(), " "); - } - } - - @EventHandler - public void ConsumeHeadApple(PlayerItemConsumeEvent event) - { - if (event.getItem().getItemMeta().getDisplayName() == null) - return; - - if (!event.getItem().getItemMeta().getDisplayName().contains("Head")) - return; - - UtilPlayer.message(event.getPlayer(), "You ate " + event.getItem().getItemMeta().getDisplayName()); - - (new PotionEffect(PotionEffectType.ABSORPTION, 2400, 0)).apply(event.getPlayer()); - (new PotionEffect(PotionEffectType.REGENERATION, 200, 1)).apply(event.getPlayer()); - } - @EventHandler public void NetherObsidianCancel(BlockPlaceEvent event) { @@ -1492,17 +1314,12 @@ public class UHC extends TeamGame } else { - ArrayList teamsAlive = new ArrayList(); - // Online Teams - for (GameTeam team : this.GetTeamList()) - if (team.GetPlayers(true).size() > 0) - teamsAlive.add(team); + List teamsAlive = this.GetTeamList().stream().filter(team -> team.GetPlayers(true).size() > 0).collect(Collectors.toList()); // Offline Player Team - if (!QuitOut) - for (GameTeam team : RejoinTeam.values()) - teamsAlive.add(team); + if (teamsAlive.size() > 1) + teamsAlive.addAll(RejoinTeam.values()); if (teamsAlive.size() <= 1) { @@ -1535,13 +1352,7 @@ public class UHC extends TeamGame if (event != null && event.getType() != UpdateType.FAST) return; - ScoreboardWrite(); - } - - public void ScoreboardWrite() - { Scoreboard.reset(); - Scoreboard.writeNewLine(); // Solo @@ -1549,7 +1360,7 @@ public class UHC extends TeamGame { if (GetPlayers(true).size() < 8) { - Scoreboard.writeGroup(GetPlayers(true), player -> Pair.create(player.getName(), GetHealth(player)), true); + Scoreboard.writeGroup(GetPlayers(true), player -> Pair.create(player.getName(), (int) Math.ceil(player.getHealth())), true); } else { @@ -1560,20 +1371,14 @@ public class UHC extends TeamGame // Team else { - ArrayList aliveList = new ArrayList(); - - for (GameTeam team : GetTeamList()) - if (team.IsTeamAlive()) - aliveList.add(team); - if (GetPlayers(true).size() < 8) { - Scoreboard.writeGroup(GetPlayers(true), player -> Pair.create(GetTeam(player).GetColor() + player.getName(), GetHealth(player)), true); + Scoreboard.writeGroup(GetPlayers(true), player -> Pair.create(GetTeam(player).GetColor() + player.getName(), (int) Math.ceil(player.getHealth())), true); } else { Scoreboard.write(C.cYellow + C.Bold + "Teams"); - Scoreboard.write(aliveList.size() + " Alive"); + Scoreboard.write(GetTeamList().stream().filter(GameTeam::IsTeamAlive).count() + " Alive"); } } @@ -1606,11 +1411,6 @@ public class UHC extends TeamGame } } - public int GetHealth(Player player) - { - return (int) Math.ceil(player.getHealth()); - } - @Override public boolean CanJoinTeam(GameTeam team) { @@ -1624,14 +1424,14 @@ public class UHC extends TeamGame GameTeam team = null; // Random Team - for (int i = 0; i < _teamList.size(); i++) + for (GameTeam gameTeam : _teamList) { - if (_teamList.get(i).GetSize() == 1) - return _teamList.get(i); + if (gameTeam.GetSize() == 1) + return gameTeam; - if (team == null || _teamList.get(i).GetSize() < team.GetSize()) + if (team == null || gameTeam.GetSize() < team.GetSize()) { - team = _teamList.get(i); + team = gameTeam; } } @@ -1724,103 +1524,4 @@ public class UHC extends TeamGame } } } - - public String getMotdStatus() - { - // In Progress - if (InProgress()) - { - return ChatColor.YELLOW + "In Progress"; - } - - // Ended - if (GetState() == GameState.End || GetState() == GameState.Dead) - { - return ChatColor.YELLOW + "In Progress"; - } - - if (!_worldGenThread.isMapLoaded()) - { - return ChatColor.GREEN + "Generating Map (" + C.cWhite + _worldGenThread.getProgress() + C.cGreen + ")"; - } - - if (!_chunkLoadingThread.isDone()) - { - return ChatColor.GREEN + "Generating Spawns (" + C.cWhite + _chunkLoadingThread.getProgress() + C.cGreen + ")"; - } - - return ChatColor.GREEN + "Recruiting"; - } - - public boolean isMapLoaded() - { - return _worldGenThread.isMapLoaded() && _chunkLoadingThread.isDone(); - } - - public String getObjectiveName(boolean _colorTick) - { - if (!_worldGenThread.isMapLoaded()) - { - return _worldGenThread.getProgress() + " " + (_colorTick ? ChatColor.GREEN : ChatColor.YELLOW) + "§l" + "Generating Map"; - } - else - { - return _chunkLoadingThread.getProgress() + " " + (_colorTick ? ChatColor.GREEN : ChatColor.YELLOW) + "§l" + "Generating Spawns"; - } - } - - private static int _gamesRun = 0; - - @EventHandler - public void on(PlayerCommandPreprocessEvent event) - { - if (event.getMessage().equals("/uhcgc")) - { - CoreClient client = getArcadeManager().GetClients().Get(event.getPlayer()); - if (client.GetRank().has(Rank.DEVELOPER)) - { - System.gc(); - event.getPlayer().sendMessage("Cleaned up"); - event.setCancelled(true); - } - } - else if (event.getMessage().equals("/uhcworlds")) - { - CoreClient client = getArcadeManager().GetClients().Get(event.getPlayer()); - if (client.GetRank().has(Rank.DEVELOPER)) - { - MinecraftServer minecraftServer = MinecraftServer.getServer(); - - int nms = minecraftServer.worlds.size(); - int bukkit = Bukkit.getWorlds().size(); - - if (nms != bukkit) - { - event.getPlayer().sendMessage(ChatColor.RED + "Bukkit and NMS world counts don't match: " + nms + " vs " + bukkit); - } - - for (org.bukkit.World world : Bukkit.getWorlds()) - { - WorldServer worldServer = ((CraftWorld) world).getHandle(); - event.getPlayer().sendMessage("Bukkit world: " + worldServer.getWorldData().getName() + " loaded chunks: " + worldServer.chunkProviderServer.chunks.size() + " saving: " + worldServer.savingDisabled + " unload queue: " + worldServer.chunkProviderServer.unloadQueue.size()); - } - - for (WorldServer worldServer : minecraftServer.worlds) - { - event.getPlayer().sendMessage("NMS world: " + worldServer.getWorldData().getName() + " loaded chunks: " + worldServer.chunkProviderServer.chunks.size() + " saving: " + worldServer.savingDisabled + " unload queue: " + worldServer.chunkProviderServer.unloadQueue.size()); - } - - event.setCancelled(true); - } - } - else if (event.getMessage().equals("/uhcgames")) - { - CoreClient client = getArcadeManager().GetClients().Get(event.getPlayer()); - if (client.GetRank().has(Rank.DEVELOPER)) - { - event.getPlayer().sendMessage("Games run: " + _gamesRun); - event.setCancelled(true); - } - } - } } \ No newline at end of file diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/uhc/helpers/ChunkLoadingThread.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/uhc/helpers/ChunkLoadingThread.java deleted file mode 100644 index 7521c0360..000000000 --- a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/uhc/helpers/ChunkLoadingThread.java +++ /dev/null @@ -1,385 +0,0 @@ -package nautilus.game.arcade.game.games.uhc.helpers; - -import mineplex.core.common.util.UtilMath; -import mineplex.core.common.util.UtilServer; -import mineplex.core.timing.TimingManager; -import nautilus.game.arcade.game.Game; -import nautilus.game.arcade.game.GameTeam; -import nautilus.game.arcade.game.games.uhc.UHC; -import net.minecraft.server.v1_8_R3.Chunk; -import net.minecraft.server.v1_8_R3.ChunkProviderServer; -import net.minecraft.server.v1_8_R3.ChunkRegionLoader; -import net.minecraft.server.v1_8_R3.NBTTagCompound; -import net.minecraft.server.v1_8_R3.WorldServer; -import org.bukkit.Location; -import org.bukkit.craftbukkit.v1_8_R3.CraftWorld; -import org.bukkit.craftbukkit.v1_8_R3.entity.CraftEntity; -import org.bukkit.craftbukkit.v1_8_R3.util.LongHash; -import org.bukkit.event.EventHandler; -import org.bukkit.event.Listener; -import org.bukkit.event.entity.CreatureSpawnEvent; -import org.bukkit.event.entity.EntitySpawnEvent; -import org.bukkit.event.world.ChunkLoadEvent; -import org.spigotmc.AsyncCatcher; - -import java.lang.reflect.Field; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicInteger; - -import static nautilus.game.arcade.game.games.uhc.UHC.VIEW_DISTANCE; - -public class ChunkLoadingThread extends Thread implements Listener -{ - private Game _game; - - private volatile boolean _isDecorating = false; - private AtomicInteger _actual = new AtomicInteger(); - private AtomicInteger _expected = new AtomicInteger(23000); // Most likely it'll be around 23000 - - private Set _entities = new HashSet<>(); - - public ChunkLoadingThread(Game game) - { - super("Chunk Loader"); - this._game = game; - UtilServer.RegisterEvents(this); - } - - public void run() - { - WorldServer worldServer = ((CraftWorld) _game.WorldData.World).getHandle(); - Location spawn = _game.WorldData.World.getSpawnLocation(); - - Map loaded = new ConcurrentHashMap<>(); - Map compounds = new ConcurrentHashMap<>(); - - try - { - TimingManager.start("UHC Chunk Loading"); - - ChunkProviderServer chunkProviderServer = worldServer.chunkProviderServer; - - Field chunkLoaderField = chunkProviderServer.getClass().getDeclaredField("chunkLoader"); - chunkLoaderField.setAccessible(true); - - ChunkRegionLoader loader = (ChunkRegionLoader) chunkLoaderField.get(chunkProviderServer); - - // Step 1: Read all the required chunks from the disk - // We're going to read all the required chunks from disk async - { - Set coordPairs = new HashSet<>(); - - // Special case for 0, 0 - { - int x = spawn.getBlockX() >> 4; - int z = spawn.getBlockZ() >> 4; - - for (int dx = -VIEW_DISTANCE; dx <= VIEW_DISTANCE; dx++) - { - for (int dz = -VIEW_DISTANCE; dz <= VIEW_DISTANCE; dz++) - { - coordPairs.add(LongHash.toLong(x + dx, z + dz)); - } - } - } - - // All the team spawns - { - for (int i = 0; i < _game.GetTeamList().size(); i++) - { - GameTeam team = _game.GetTeamList().get(i); - for (Location l : team.GetSpawns()) - { - int x = l.getChunk().getX(); - int z = l.getChunk().getZ(); - - for (int dx = -VIEW_DISTANCE; dx <= VIEW_DISTANCE; dx++) - { - for (int dz = -VIEW_DISTANCE; dz <= VIEW_DISTANCE; dz++) - { - coordPairs.add(LongHash.toLong(x + dx, z + dz)); - } - } - } - } - } - - AtomicBoolean lockCompleted = new AtomicBoolean(false); - Object lock = new Object(); - - // Hop back onto the main thread - _game.getArcadeManager().runSync(() -> - { - for (Chunk chunk : new ArrayList<>(chunkProviderServer.chunks.values())) - { - chunk.bukkitChunk.unload(true, false); - } - lockCompleted.set(true); - synchronized(lock) - { - lock.notifyAll(); - } - }); - if (!lockCompleted.get()) - { - synchronized (lock) - { - lock.wait(); - } - } - if (!lockCompleted.get()) - { - throw new IllegalStateException("Lock was not completed"); - } - - - // Sigh... I don't want this to be here but it needs to be set somewhere... - // Multiply by 3 because there are 3 stages - _expected.set(coordPairs.size() * 3); - - // Load them now - ExecutorService chunkLoaders = Executors.newFixedThreadPool(UHC.THREADS_FOR_CHUNK_LOADING); - - for (long coord : coordPairs) - { - chunkLoaders.submit(() -> - { - int x = LongHash.msw(coord); - int z = LongHash.lsw(coord); - try - { - Object[] data = loader.loadChunk(worldServer, x, z); - if (data != null) - { - NBTTagCompound compound = (NBTTagCompound) data[1]; - net.minecraft.server.v1_8_R3.Chunk chunk = (net.minecraft.server.v1_8_R3.Chunk) data[0]; - loaded.put(coord, chunk); - compounds.put(coord, compound); - } - else - { - System.out.println("Failed to load chunk " + x + "," + z); - } - } - catch (Throwable t) - { - t.printStackTrace(); - } - finally - { - _actual.getAndIncrement(); - } - }); - } - - chunkLoaders.shutdown(); - - // We've got plenty of time to wait - System.out.println("Finished submitting tasks to executor, waiting..."); - chunkLoaders.awaitTermination(1, TimeUnit.DAYS); - - System.out.println("Loaded: " + loaded.size() + " and coords: " + coordPairs.size()); - coordPairs.clear(); - } - - // Step 2: Recreate structures, update neighbors, load entities - // This step should be super quick so there's no point in scheduling it elsewhere - // Code is plain copypasted from ChunkIOProvider - { - for (net.minecraft.server.v1_8_R3.Chunk chunk : loaded.values()) - { - NBTTagCompound compound = compounds.get(LongHash.toLong(chunk.locX, chunk.locZ)); - loader.loadEntities(chunk, compound.getCompound("Level"), worldServer); - chunk.setLastSaved(chunkProviderServer.world.getTime()); - if (chunkProviderServer.chunkProvider != null) - { - chunkProviderServer.chunkProvider.recreateStructures(chunk, chunk.locX, chunk.locZ); - } - - for (int x = -2; x < 3; ++x) - { - for (int z = -2; z < 3; ++z) - { - if (x != 0 || z != 0) - { - net.minecraft.server.v1_8_R3.Chunk neighbor = loaded.get(LongHash.toLong(chunk.locX + x, chunk.locZ + z)); - if (neighbor != null) - { - neighbor.setNeighborLoaded(-x, -z); - chunk.setNeighborLoaded(x, z); - } - } - } - } - _actual.getAndIncrement(); - } - } - - AtomicBoolean lockCompleted = new AtomicBoolean(false); - Object lock = new Object(); - - // Hop back onto the main thread - _game.getArcadeManager().runSync(() -> - { - // We want to add all the chunks to the chunkmap so that the server is not out of sync - for (Map.Entry ent : loaded.entrySet()) - { - ent.getValue().addEntities(); - chunkProviderServer.chunks.put(ent.getKey(), ent.getValue()); - ChunkLoadEvent event = new ChunkLoadEvent(ent.getValue().bukkitChunk, true); - UtilServer.CallEvent(event); - } - lockCompleted.set(true); - synchronized (lock) - { - lock.notifyAll(); - } - }); - - if (!lockCompleted.get()) - { - synchronized (lock) - { - lock.wait(); - } - } - if (!lockCompleted.get()) - { - throw new IllegalStateException("Lock was not completed"); - } - - - // Step 3: Decorate the chunks. This step must be performed async as otherwise the server lags way too hard - // Notes: Do not allow the server to tick the world. If this is allowed EntityTracker will raise CME - // NextTickList will also raise errors - // And worst case the server will crash - { - // Live life on the edge - AsyncCatcher.enabled = false; - _isDecorating = true; - int ct = 0; - for (net.minecraft.server.v1_8_R3.Chunk chunk : loaded.values()) - { - chunk.loadNearby(chunkProviderServer, chunkProviderServer, chunk.locX, chunk.locZ); - ct++; - if (ct % 100 == 0) - { - System.out.println(ct); - } - _actual.getAndIncrement(); - } - - TimingManager.stop("UHC Chunk Loading"); - _isDecorating = false; - AsyncCatcher.enabled = true; - - System.out.println("Expected: " + _expected.get() + ", actual: " + _actual.get()); - - _game.getArcadeManager().runSync(() -> - { - - for (Chunk chunk : chunkProviderServer.chunks.values()) - { - // Clear - for (int x = -2; x < 3; x++) { - for (int z = -2; z < 3; z++) { - if (x == 0 && z == 0) { - continue; - } - chunk.setNeighborUnloaded(x, z); - } - } - } - - for (Chunk chunk : chunkProviderServer.chunks.values()) - { - // Refresh - for (int x = -2; x < 3; x++) { - for (int z = -2; z < 3; z++) { - if (x == 0 && z == 0) { - continue; - } - - Chunk neighbor = chunkProviderServer.getChunkIfLoaded(chunk.locX + x, chunk.locZ + z); - if (neighbor != null) { - neighbor.setNeighborLoaded(-x, -z); - chunk.setNeighborLoaded(x, z); - } - } - } - } - - for (net.minecraft.server.v1_8_R3.Entity entity : _entities) - { - entity.dead = false; - worldServer.addEntity(entity, CreatureSpawnEvent.SpawnReason.CHUNK_GEN); - } - - _entities.clear(); - - // You may tick again - worldServer.getMinecraftServer().worlds.add(worldServer); - - // Well, if they're not equal, not much we can do. We've hit the end - _actual.set(_expected.get()); - }); - } - - loaded.clear(); - compounds.clear(); - - UtilServer.Unregister(this); - } - catch (Throwable t) - { - t.printStackTrace(); - } - } - - @EventHandler - public void on(EntitySpawnEvent event) - { - // Don't allow entity spawns while decorating, period - if (_isDecorating) - { - if (event.getLocation().getWorld().getUID() == _game.WorldData.World.getUID()) - { - _entities.add(((CraftEntity) event.getEntity()).getHandle()); - event.setCancelled(true); - } - } - } - - public void flagDone() - { - _actual.set(_expected.get()); - } - - public boolean isDone() - { - return _actual.get() == _expected.get(); - } - - public int getPercentageComplete() - { - return UtilMath.clamp((int) ((_actual.get() * 1.0 / _expected.get()) * 100), 0, 100); - } - - public String getProgress() - { - return getPercentageComplete() + "%"; - } - - public void flagStop() - { - this.interrupt(); - } -} diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/uhc/helpers/WorldGenThread.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/uhc/helpers/WorldGenThread.java deleted file mode 100644 index c019c337b..000000000 --- a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/uhc/helpers/WorldGenThread.java +++ /dev/null @@ -1,225 +0,0 @@ -package nautilus.game.arcade.game.games.uhc.helpers; - -import mineplex.core.common.util.C; -import mineplex.core.common.util.UtilMath; -import mineplex.core.common.util.UtilTime; -import mineplex.core.timing.TimingManager; -import nautilus.game.arcade.game.Game; -import nautilus.game.arcade.game.games.uhc.UHC; -import net.minecraft.server.v1_8_R3.BiomeCache; -import net.minecraft.server.v1_8_R3.ChunkProviderServer; -import net.minecraft.server.v1_8_R3.FileIOThread; -import net.minecraft.server.v1_8_R3.IChunkProvider; -import net.minecraft.server.v1_8_R3.MinecraftServer; -import net.minecraft.server.v1_8_R3.WorldChunkManager; -import org.bukkit.craftbukkit.v1_8_R3.CraftWorld; -import org.bukkit.craftbukkit.v1_8_R3.util.LongHash; - -import java.lang.reflect.Field; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.TimeUnit; - -public class WorldGenThread extends Thread -{ - private UHC _game; - - private volatile boolean _mapLoaded = false; - private volatile int _chunksPerTick = 1; - private volatile boolean _stopGen = false; - - private int _chunkTotal; - private int _chunkX = 0; - private int _chunkZ = 0; - private int _chunksLoaded = 0; - - private int _currentBorder = 1000; - - - public WorldGenThread(UHC game) - { - super("WorldGen Thread"); - this._game = game; - - - _chunkX = (int) -(_currentBorder / 16); - _chunkZ = (int) -(_currentBorder / 16); - _chunkTotal = (int) ((_currentBorder * 2 / 16) * (_currentBorder * 2 / 16)); - } - - public void run() - { - try - { - Field fileIOThreadB = FileIOThread.class.getDeclaredField("b"); - fileIOThreadB.setAccessible(true); - - // This list is the list of chunks to be saved on the File IO Thread - List list = (List) fileIOThreadB.get(FileIOThread.a()); - - net.minecraft.server.v1_8_R3.WorldServer worldServer = ((CraftWorld) _game.WorldData.World).getHandle(); - - WorldChunkManager manager = worldServer.getWorldChunkManager(); - - Field biomeCacheField = manager.getClass().getDeclaredField("d"); - biomeCacheField.setAccessible(true); - - // A thread safe BiomeCache - // The implementation is literally a copy/paste from the original BiomeCache, but with some synchronization - // Reason being while the server is ticking the world (for some reason, if you want to dig through the entire Arcade codebase go for it) - // it stores stuff in the BiomeCache, and chunk gen needs that BiomeCache info too - // Causing desynchronization in the cache - biomeCacheField.set(manager, new BiomeCache(manager) - { - private final Object _lock = new Object(); - - private long _lastCleanTime; // b -> _lastCleanTime - private Map _blockByCoord = new HashMap<>(); // LongHashMap -> HashMap, c -> _blockByCoord - private List _blocks = new ArrayList<>(); // d -> _blocks - - @Override - public BiomeCache.BiomeCacheBlock a(int x, int z) - { - x >>= 4; - z >>= 4; - long var3 = hash(x, z); - BiomeCache.BiomeCacheBlock var5 = this._blockByCoord.get(var3); - if (var5 == null) - { - var5 = new BiomeCache.BiomeCacheBlock(x, z); - synchronized (_lock) - { - this._blockByCoord.put(var3, var5); - this._blocks.add(var5); - } - } - - var5.e = MinecraftServer.az(); - return var5; - } - - @Override - public void a() - { - long currentTime = MinecraftServer.az(); - long deltaTime = currentTime - this._lastCleanTime; - if (deltaTime > 7500L || deltaTime < 0L) - { - this._lastCleanTime = currentTime; - - synchronized (_lock) - { - for (int i = 0; i < this._blocks.size(); ++i) - { - BiomeCache.BiomeCacheBlock biomeCacheBlock = (BiomeCache.BiomeCacheBlock) this._blocks.get(i); - long var7 = currentTime - biomeCacheBlock.e; - if (var7 > 30000L || var7 < 0L) - { - this._blocks.remove(i--); - this._blockByCoord.remove(hash(biomeCacheBlock.c, biomeCacheBlock.d)); - } - } - } - } - } - - private long hash(int x, int z) - { - return (long) x & 4294967295L | ((long) z & 4294967295L) << 32; - } - }); - - ChunkProviderServer cps = worldServer.chunkProviderServer; - IChunkProvider icp = cps.chunkProvider; - System.out.println("Using chunk provider " + icp.getClass()); - - TimingManager.start("Map Generation"); - - long start = System.currentTimeMillis(); - - while (!_stopGen) - { - long now = System.currentTimeMillis(); - - long hash = LongHash.toLong(_chunkX, _chunkZ); - - // This is just a shortcut to how the Minecraft server would have generated a chunk if it doesn't exist. - // This should always create a chunk because we're not loading any chunks beforehand... - // /me looks at new maintainer - net.minecraft.server.v1_8_R3.Chunk chunk = icp.getOrCreateChunk(_chunkX, _chunkZ); - - // Run the copypasted code for chunk saving. - cps.saveChunk(chunk); - cps.saveChunkNOP(chunk); - cps.unloadQueue.remove(_chunkX, _chunkZ); - cps.chunks.remove(hash); - - if (_chunkX < _currentBorder / 16) - { - _chunkX++; - } - else if (_chunkZ < _currentBorder / 16) - { - _chunkX = (int) -(_currentBorder / 16); - _chunkZ++; - } - else - { - _mapLoaded = true; - break; - } - - _chunksLoaded++; - - _chunksPerTick = (int) (_chunksLoaded / ((now - start) / 50.0)); - } - - TimingManager.stop("Map Generation"); - - if (_stopGen) - { - return; - } - - TimingManager.start("Map Saving"); - - // Wait for all the chunks to save (but do we need this?) - while (!list.isEmpty()) - { - Thread.sleep(100); - } - - TimingManager.stop("Map Saving"); - - _game.getArcadeManager().runSync(_game::generateSpawns); - } - catch (Throwable t) - { - // todo proper exception handling - // maybe force shutdown? - t.printStackTrace(); - } - } - - public void flagStop() - { - this._stopGen = true; - } - - public boolean isMapLoaded() - { - return this._mapLoaded; - } - - public int getPercentageComplete() - { - return UtilMath.clamp((int) ((_chunksLoaded * 1.0 / _chunkTotal) * 100), 0, 100); - } - - public String getProgress() - { - return getPercentageComplete() + "%"; - } -} diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/uhc/modes/CutClean.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/uhc/modes/CutClean.java index 9cce1ec01..470fb1a6e 100644 --- a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/uhc/modes/CutClean.java +++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/uhc/modes/CutClean.java @@ -24,7 +24,7 @@ public class CutClean extends UHC { super(manager, GameType.Brawl); - registerModule(new CutCleanModule() + new CutCleanModule() .associateBlockDrop( Material.GOLD_ORE, new ItemBuilder(Material.GOLD_INGOT).build() @@ -53,11 +53,11 @@ public class CutClean extends UHC Material.RABBIT, new ItemBuilder(Material.COOKED_RABBIT).build() ) - ); + .register(this); - registerModule(new ItemGiverModule() + new ItemGiverModule() .withItem(new ItemStack(Material.COOKED_BEEF, STEAK_AMOUNT)) - ); + .register(this); } @Override diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/uhc/modes/GodBattles.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/uhc/modes/GodBattles.java index 12b6906a9..f722a0a7b 100644 --- a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/uhc/modes/GodBattles.java +++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/uhc/modes/GodBattles.java @@ -43,18 +43,18 @@ public class GodBattles extends UHC { super(manager, GameType.Brawl); - registerModule(new CutCleanModule() + new CutCleanModule() .associateBlockDrop( Material.GOLD_ORE, new ItemBuilder(Material.GOLD_BLOCK).build() ) - ); + .register(this); - registerModule(new ItemGiverModule() + new ItemGiverModule() .withItem(UtilItem.makeUnbreakable(new ItemStack(Material.DIAMOND_PICKAXE))) - ); + .register(this); - registerModule(new OreVeinEditorModule() + new OreVeinEditorModule() .useFilter(block -> ORE_MATERIALS.contains(block.getType())) .useEditor(vein -> { @@ -68,7 +68,7 @@ public class GodBattles extends UHC } } }) - ); + .register(this); } @Override diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/modules/Module.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/modules/Module.java index bff9ae688..2aed67d39 100644 --- a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/modules/Module.java +++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/modules/Module.java @@ -1,24 +1,26 @@ package nautilus.game.arcade.game.modules; import com.google.gson.JsonElement; +import mineplex.core.Managers; +import nautilus.game.arcade.ArcadeManager; import nautilus.game.arcade.game.Game; import nautilus.game.arcade.game.TeamGame; import org.bukkit.event.Listener; -/* +/** * This is a Module - * + *

* A Module represents something which will enhance or change the way games can be played. * Modules should function independent of which specific gamemode is being played. - * If you need game-specific features, put it into that Game implementation or refactor it into a separate class (not a module). - * + * If you need game-specific features, put it into that Game implementation or refactor it into a separate class (not a module). + *

* Modules should never directly access other Modules via the Game instance. - * Instead, the game which requires cross-contamination should do so itself. - * + * Instead, the game which requires cross-contamination should do so itself. + *

* Modules should be associated per-game. Do not make them static - * + *

* If your module is able to accept custom configuration, override the configure(JsonElement) method - * You can define the format of the json you wish to use. + * You can define the format of the json you wish to use. * This custom configuration will be used to dynamically adjust gamemodes via Redis if needed */ public abstract class Module implements Listener @@ -26,10 +28,10 @@ public abstract class Module implements Listener // The game this module belongs to private Game _game; - /* + /** * Initializes this module with the specific game instance. You should never do this as {@link Game} does it for you */ - public void initialize(Game game) + public final void initialize(Game game) { if (_game != null) { @@ -39,33 +41,35 @@ public abstract class Module implements Listener this.setup(); } - /* - * This method is called once initialization is complete. Do whatever you need to do with the {@link Game} here + /** + * This method is called once initialization is complete. Do whatever you need to do with the {@link Game} here. + * + * All modules should have been configured before this method is called */ protected void setup() { } - /* + /** * If this module can be configured via a JsonObject/JsonPrimitive, then override this method - * to implement that feature - * + * to implement that feature + *

* You can define how the JsonElement should be formatted. - * + *

* It is recommended to have a "force" boolean which will reset this module to a clean state - * (to allow extensive customization using json) + * (to allow extensive customization using json) */ public void configure(JsonElement element) { } - /* + /** * This method is called once this module is no longer needed. - * This could be because the game is over - * Or because this module was unregistered - * + * This could be because the game is over + * Or because this module was unregistered + *

* The {@link Game} will unregister this module as a listener for you. * All you need to do is clean up after yourself */ @@ -74,11 +78,16 @@ public abstract class Module implements Listener } - /* + /** * Gets the game this module is associated with */ public Game getGame() { return this._game; } + + public final void register(Game instance) + { + instance.registerModule(this); + } } diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/modules/PlayerHeadModule.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/modules/PlayerHeadModule.java new file mode 100644 index 000000000..3553a357c --- /dev/null +++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/modules/PlayerHeadModule.java @@ -0,0 +1,167 @@ +package nautilus.game.arcade.game.modules; + +import mineplex.core.common.util.C; +import mineplex.core.common.util.UtilPlayer; +import mineplex.core.common.util.UtilServer; +import mineplex.core.itemstack.ItemBuilder; +import mineplex.core.itemstack.ItemStackFactory; +import nautilus.game.arcade.game.GameTeam; +import org.bukkit.ChatColor; +import org.bukkit.Material; +import org.bukkit.enchantments.Enchantment; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.block.BlockPlaceEvent; +import org.bukkit.event.entity.PlayerDeathEvent; +import org.bukkit.event.inventory.PrepareItemCraftEvent; +import org.bukkit.event.player.PlayerItemConsumeEvent; +import org.bukkit.event.player.PlayerPickupItemEvent; +import org.bukkit.inventory.CraftingInventory; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.ShapedRecipe; +import org.bukkit.inventory.meta.SkullMeta; +import org.bukkit.material.MaterialData; +import org.bukkit.potion.PotionEffect; +import org.bukkit.potion.PotionEffectType; + +public class PlayerHeadModule extends Module +{ + private boolean _disableCraftingRegularApples = true; + private boolean _disableHeadPlace = true; + + @Override + protected void setup() + { + ShapedRecipe headApple2 = new ShapedRecipe(new ItemStack(Material.GOLDEN_APPLE, 1)); + headApple2.shape("GGG", "GHG", "GGG"); + headApple2.setIngredient('G', Material.GOLD_INGOT); + headApple2.setIngredient('H', new MaterialData(Material.SKULL_ITEM, (byte) 3)); + UtilServer.getServer().addRecipe(headApple2); + } + + public PlayerHeadModule enableCraftingRegularApples() + { + this._disableCraftingRegularApples = false; + return this; + } + + public PlayerHeadModule enableHeadPlace() + { + this._disableHeadPlace = false; + return this; + } + + @EventHandler + public void disableHeadPlace(BlockPlaceEvent event) + { + if ((event.getItemInHand().getType() == Material.SKULL || event.getItemInHand().getType() == Material.SKULL_ITEM) && + this._disableHeadPlace) + event.setCancelled(true); + } + + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + public void headPickup(PlayerPickupItemEvent event) + { + if (!getGame().IsLive()) + return; + + if (event.getItem().getItemStack().getType() == Material.SKULL_ITEM) + { + UtilPlayer.message(event.getPlayer(), " "); + UtilPlayer.message(event.getPlayer(), C.cGreen + C.Bold + "You picked up a Player Head!"); + UtilPlayer.message(event.getPlayer(), C.cWhite + "Craft a Golden Head Apple with it for ultimate healing."); + UtilPlayer.message(event.getPlayer(), C.cWhite + "Use the recipe for Golden Apple, but Head replaces Apple."); + UtilPlayer.message(event.getPlayer(), " "); + } + } + + + @EventHandler + public void PlayerDeath(PlayerDeathEvent event) + { + Player player = event.getEntity(); + + GameTeam team = getGame().GetTeam(player); + if (team == null) + return; + + // Skull Drop + ItemStack stack = new ItemBuilder(Material.SKULL_ITEM) + .setData((short) 3) + .setAmount(1) + .setTitle(team.GetColor() + player.getName() + "'s Head") + .setPlayerHead(player.getName()) + .build(); + + event.getDrops().add(stack); + } + + @EventHandler + public void eatHeadApple(PlayerItemConsumeEvent event) + { + if (event.getItem().getItemMeta().getDisplayName() == null) + return; + + if (!event.getItem().getItemMeta().getDisplayName().contains("Head")) + return; + + UtilPlayer.message(event.getPlayer(), "You ate " + event.getItem().getItemMeta().getDisplayName()); + + (new PotionEffect(PotionEffectType.ABSORPTION, 2400, 0)).apply(event.getPlayer()); + (new PotionEffect(PotionEffectType.REGENERATION, 200, 1)).apply(event.getPlayer()); + } + + @EventHandler(priority = EventPriority.HIGH) + public void denyGoldApple(PrepareItemCraftEvent event) + { + if (event.getRecipe().getResult() == null) + return; + + Material type = event.getRecipe().getResult().getType(); + + if (type != Material.GOLDEN_APPLE) + return; + + CraftingInventory inv = event.getInventory(); + + for (ItemStack item : inv.getMatrix()) + if (item != null && item.getType() != Material.AIR) + if (item.getType() == Material.GOLD_INGOT) + return; + + inv.setResult(null); + } + + @EventHandler(priority = EventPriority.HIGH) + public void craftHeadApple(PrepareItemCraftEvent event) + { + if (event.getRecipe().getResult() == null) + return; + + Material type = event.getRecipe().getResult().getType(); + + if (type != Material.GOLDEN_APPLE) + return; + + CraftingInventory inv = event.getInventory(); + + for (ItemStack item : inv.getMatrix()) + if (item != null && item.getType() != Material.AIR) + if (item.getType() == Material.SKULL_ITEM || item.getType() == Material.SKULL) + { + if (item.getItemMeta() == null) + continue; + + if (item.getItemMeta().getDisplayName() == null) + continue; + + ItemStack apple = ItemStackFactory.Instance.CreateStack(Material.GOLDEN_APPLE, (byte) 0, 1, item + .getItemMeta().getDisplayName() + ChatColor.AQUA + " Golden Apple"); + apple.addUnsafeEnchantment(Enchantment.ARROW_DAMAGE, 1); + + inv.setResult(apple); + return; + } + } +} diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/modules/SafezoneModule.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/modules/SafezoneModule.java new file mode 100644 index 000000000..40a5e8622 --- /dev/null +++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/modules/SafezoneModule.java @@ -0,0 +1,236 @@ +package nautilus.game.arcade.game.modules; + +import mineplex.core.common.util.F; +import mineplex.core.common.util.UtilPlayer; +import net.minecraft.server.v1_8_R3.BlockPosition; +import net.minecraft.server.v1_8_R3.Entity; +import net.minecraft.server.v1_8_R3.EntityHuman; +import net.minecraft.server.v1_8_R3.IWorldAccess; +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.World; +import org.bukkit.block.Block; +import org.bukkit.block.BlockState; +import org.bukkit.craftbukkit.v1_8_R3.CraftWorld; +import org.bukkit.event.EventHandler; +import org.bukkit.event.block.Action; +import org.bukkit.event.block.BlockGrowEvent; +import org.bukkit.event.block.BlockPistonExtendEvent; +import org.bukkit.event.block.BlockPistonRetractEvent; +import org.bukkit.event.block.BlockPlaceEvent; +import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.event.world.StructureGrowEvent; +import org.bukkit.event.world.WorldLoadEvent; + +import java.util.Iterator; +import java.util.function.Predicate; + +public class SafezoneModule extends Module +{ + private Predicate _isInSafezone = location -> true; + + public SafezoneModule filter(Predicate predicate) + { + this._isInSafezone = predicate; + return this; + } + + @Override + public void setup() + { + for (World world : Bukkit.getWorlds()) + { + registerWorldAccess(world); + } + } + + @EventHandler + public void onWorldLoad(WorldLoadEvent event) + { + registerWorldAccess(event.getWorld()); + } + + private void registerWorldAccess(World world) + { + IWorldAccess access = new IWorldAccess() + { + @Override + public void a(BlockPosition blockPosition) + { + Location location = new Location(world, blockPosition.getX(), blockPosition.getY(), blockPosition.getZ()); + if (isInSafeZone(location)) + { + Block block = location.getBlock(); + if (block.getType() == Material.COBBLESTONE || block.getType() == Material.OBSIDIAN || block.getType() == Material.STONE) + { + block.setType(Material.AIR); + } + } + } + + @Override + public void b(BlockPosition blockPosition) + { + + } + + @Override + public void a(int i, int i1, int i2, int i3, int i4, int i5) + { + + } + + @Override + public void a(String s, double v, double v1, double v2, float v3, float v4) + { + + } + + @Override + public void a(EntityHuman entityHuman, String s, double v, double v1, double v2, float v3, float v4) + { + + } + + @Override + public void a(int i, boolean b, double v, double v1, double v2, double v3, double v4, double v5, int... ints) + { + + } + + @Override + public void a(Entity entity) + { + + } + + @Override + public void b(Entity entity) + { + + } + + @Override + public void a(String s, BlockPosition blockPosition) + { + + } + + @Override + public void a(int i, BlockPosition blockPosition, int i1) + { + + } + + @Override + public void a(EntityHuman entityHuman, int i, BlockPosition blockPosition, int i1) + { + + } + + @Override + public void b(int i, BlockPosition blockPosition, int i1) + { + + } + }; + +// ((CraftWorld) world).getHandle().u.add(access); + } + + // fixme flowing water and stuff + + @EventHandler + public void preventBlockPlacement(BlockPlaceEvent event) + { + if (isInSafeZone(event.getBlock().getLocation())) + { + UtilPlayer.message(event.getPlayer(), F.main("Game", "You cannot build this high near center of map.")); + event.setCancelled(true); + } + } + + @EventHandler + public void preventStructureGrow(StructureGrowEvent event) + { + Iterator blocks = event.getBlocks().iterator(); + while (blocks.hasNext()) + { + BlockState next = blocks.next(); + if (isInSafeZone(next.getLocation())) + { + blocks.remove(); + } + } + } + + @EventHandler + public void preventBlockGrow(BlockGrowEvent event) + { + if (isInSafeZone(event.getBlock().getLocation())) + { + event.setCancelled(true); + } + } + + @EventHandler + public void preventBoneMeal(PlayerInteractEvent event) + { + if (event.getAction() == Action.RIGHT_CLICK_BLOCK) + { + boolean isIllegal = false; + if (!isIllegal) + { + isIllegal = event.getPlayer().getItemInHand().getType() == Material.INK_SACK && + event.getPlayer().getItemInHand().getData().getData() == (byte) 15; + } + + if (isIllegal && isInSafeZone(event.getClickedBlock().getLocation())) + { + event.setCancelled(true); + } + } + } + + @EventHandler + public void preventPistons(BlockPistonExtendEvent event) + { + boolean willBeUnsafe = false; + for (Block block : event.getBlocks()) + { + if (isInSafeZone(block.getRelative(event.getDirection()).getLocation())) + { + willBeUnsafe = true; + break; + } + } + if (willBeUnsafe) + { + event.setCancelled(true); + } + } + + @EventHandler + public void preventPistons(BlockPistonRetractEvent event) + { + boolean willBeUnsafe = false; + for (Block block : event.getBlocks()) + { + if (isInSafeZone(block.getLocation())) + { + willBeUnsafe = true; + break; + } + } + if (willBeUnsafe) + { + event.setCancelled(true); + } + } + + private boolean isInSafeZone(Location location) + { + return _isInSafezone.test(location); + } +} diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/modules/combatlog/CombatLogModule.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/modules/combatlog/CombatLogModule.java index 9fd3f2f81..508650927 100644 --- a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/modules/combatlog/CombatLogModule.java +++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/modules/combatlog/CombatLogModule.java @@ -218,18 +218,6 @@ public class CombatLogModule extends Module { _killedBy.put(logoutNpc.getPlayerInfo().getUniqueId(), UtilParser.parseDamageCause(logoutNpc.getLastDamageCause())); } - - - if (getGame() instanceof TeamGame) - { - TeamGame teamGame = (TeamGame) getGame(); - teamGame.RejoinTimes.remove(logoutNpc.getPlayerInfo().getName()); - teamGame.RejoinKit.remove(logoutNpc.getPlayerInfo().getName()); - teamGame.RejoinTeam.remove(logoutNpc.getPlayerInfo().getName()); - teamGame.RejoinHealth.remove(logoutNpc.getPlayerInfo().getName()); - } - - _logoutNpcs.remove(logoutNpc.getPlayerInfo().getUniqueId()); } @EventHandler(ignoreCancelled = true) diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/managers/GameCreationManager.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/managers/GameCreationManager.java index eaa309225..c078afda9 100644 --- a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/managers/GameCreationManager.java +++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/managers/GameCreationManager.java @@ -107,6 +107,7 @@ public class GameCreationManager implements Listener Game game = gameIterator.next(); game.cleanupModules(); + game.cleanupCommands(); game.disable(); HandlerList.unregisterAll(game); diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/managers/GameManager.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/managers/GameManager.java index d9d272557..6232df942 100644 --- a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/managers/GameManager.java +++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/managers/GameManager.java @@ -371,9 +371,6 @@ public class GameManager implements Listener public void StateCountdown(Game game, int timer, boolean force) { - if (game instanceof UHC && !((UHC)game).isMapLoaded()) - return; - if (Manager.GetGameHostManager().isPrivateServer() && Manager.GetGameHostManager().isVoteInProgress()) return; @@ -481,61 +478,6 @@ public class GameManager implements Listener game.GetScoreboard().updateTitle(); } - @EventHandler(priority = EventPriority.LOWEST) //BEFORE PARSE DATA - public void TeamGeneration(GameStateChangeEvent event) - { - if (event.GetState() != GameState.Recruit) - return; - - Game game = event.GetGame(); - int count = 1; - - for (String team : game.WorldData.SpawnLocs.keySet()) - { - ChatColor color; - - if (team.equalsIgnoreCase("RED")) color = ChatColor.RED; - else if (team.equalsIgnoreCase("YELLOW")) color = ChatColor.YELLOW; - else if (team.equalsIgnoreCase("GREEN")) color = ChatColor.GREEN; - else if (team.equalsIgnoreCase("BLUE")) color = ChatColor.AQUA; - else - { - color = ChatColor.DARK_GREEN; - - if (game.GetTeamList().size()%14 == 0) if (game.WorldData.SpawnLocs.size() > 1) color = ChatColor.RED; - if (game.GetTeamList().size()%14 == 1) color = ChatColor.YELLOW; - if (game.GetTeamList().size()%14 == 2) color = ChatColor.GREEN; - if (game.GetTeamList().size()%14 == 3) color = ChatColor.AQUA; - if (game.GetTeamList().size()%14 == 4) color = ChatColor.GOLD; - if (game.GetTeamList().size()%14 == 5) color = ChatColor.LIGHT_PURPLE; - if (game.GetTeamList().size()%14 == 6) color = ChatColor.DARK_BLUE; - if (game.GetTeamList().size()%14 == 7) color = ChatColor.WHITE; - if (game.GetTeamList().size()%14 == 8) color = ChatColor.BLUE; - if (game.GetTeamList().size()%14 == 9) color = ChatColor.DARK_GREEN; - if (game.GetTeamList().size()%14 == 10) color = ChatColor.DARK_PURPLE; - if (game.GetTeamList().size()%14 == 11) color = ChatColor.DARK_RED; - if (game.GetTeamList().size()%14 == 12) color = ChatColor.DARK_AQUA; - } - - //Random Names - String teamName = team; - if (game.WorldData.SpawnLocs.size() > 12) - { - teamName = "" + count; - count++; - } - - GameTeam newTeam = new GameTeam(game, teamName, color, game.WorldData.SpawnLocs.get(team)); - game.AddTeam(newTeam); - } - - //Restrict Kits - game.RestrictKits(); - - //Parse Data - game.ParseData(); - } - public void TeamPreferenceJoin(Game game) { //Preferred Team No Longer Full diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/managers/GameWorldManager.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/managers/GameWorldManager.java index 43a654f57..364d43cd5 100644 --- a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/managers/GameWorldManager.java +++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/managers/GameWorldManager.java @@ -6,7 +6,6 @@ import java.util.Iterator; import mineplex.core.updater.UpdateType; import mineplex.core.updater.event.UpdateEvent; import nautilus.game.arcade.ArcadeManager; -import nautilus.game.arcade.game.Game.GameState; import nautilus.game.arcade.world.WorldData; import org.bukkit.event.EventHandler; @@ -47,9 +46,9 @@ public class GameWorldManager implements Listener { worldIterator.remove(); } - else if (worldData.LoadChunks(timeLeft)) + else if (worldData.Host.loadNecessaryChunks(timeLeft)) { - worldData.Host.SetState(GameState.Recruit); + worldData.Host.prepareToRecruit(); worldIterator.remove(); } } diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/world/WorldData.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/world/WorldData.java index cb93be658..00f103353 100644 --- a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/world/WorldData.java +++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/world/WorldData.java @@ -44,9 +44,7 @@ public class WorldData public int MinZ = 0; public int MaxX = 0; public int MaxZ = 0; - public int CurX = 0; - public int CurZ = 0; - + public int MinY = -1; public int MaxY = 256; @@ -87,35 +85,9 @@ public class WorldData public void run() { TimingManager.start("WorldData loading world."); - //Start World - - if (Host instanceof UHC) - { - //Delete Old World - File dir = new File(GetFolder() + "/data"); - FileUtil.DeleteFolder(dir); - - dir = new File(GetFolder() + "/region"); - FileUtil.DeleteFolder(dir); - - dir = new File(GetFolder() + "/level.dat"); - if (dir.exists()) - dir.delete(); - - //Create Fresh World with Random Seed - WorldCreator creator = new WorldCreator(GetFolder()); - creator.seed(UtilMath.r(999999999)); - creator.environment(Environment.NORMAL); - creator.generateStructures(true); - - World = WorldUtil.LoadWorld(creator); - } - else - { - WorldCreator creator = new WorldCreator(GetFolder()); - creator.generator(new WorldGenCleanRoom()); - World = WorldUtil.LoadWorld(creator); - } + WorldCreator creator = new WorldCreator(GetFolder()); + creator.generator(new WorldGenCleanRoom()); + World = WorldUtil.LoadWorld(creator); TimingManager.stop("WorldData loading world."); World.setDifficulty(Difficulty.HARD); @@ -325,7 +297,6 @@ public class WorldData try { MinX = Integer.parseInt(tokens[1]); - CurX = MinX; } catch (Exception e) { @@ -349,7 +320,6 @@ public class WorldData try { MinZ = Integer.parseInt(tokens[1]); - CurZ = MinZ; } catch (Exception e) { @@ -422,30 +392,6 @@ public class WorldData return null; } - public boolean LoadChunks(long maxMilliseconds) - { - if (Host instanceof UHC) - { - return true; - } - long startTime = System.currentTimeMillis(); - - for (; CurX <= MaxX; CurX += 16) - { - for (; CurZ <= MaxZ; CurZ += 16) - { - if (System.currentTimeMillis() - startTime >= maxMilliseconds) - return false; - - World.getChunkAt(new Location(World, CurX, 0, CurZ)); - } - - CurZ = MinZ; - } - - return true; - } - public void Uninitialize() { if (World == null) diff --git a/Plugins/pom.xml b/Plugins/pom.xml index 905d6e24b..2dcbcb11d 100644 --- a/Plugins/pom.xml +++ b/Plugins/pom.xml @@ -35,7 +35,8 @@ Mineplex.ServerMonitor Mineplex.StaffServer Nautilus.Game.Arcade - + Nautilus.Game.Arcade.UHC.WorldGen + mavericks-review-hub