UHC rewrite

This commit is contained in:
samczsun 2016-09-05 22:03:00 -04:00
parent 7a0fba3027
commit e7b744f527
30 changed files with 1340 additions and 1586 deletions

View File

@ -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 extends MiniPlugin> T require(Class<T> clazz)
{
return Managers.require(clazz);

View File

@ -143,8 +143,6 @@ public class AntiHack extends MiniPlugin
private List<AntiHackGuardian> _guardians = new ArrayList<>();
private Predicate<Player> _filter = player -> true;
private Set<Player> _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<Player> filter)
{
if (filter == null)
{
this._filter = player -> true;
}
else
{
this._filter = filter;
}
}
public void registerGuardian(AntiHackGuardian guardian)
{
this._guardians.add(guardian);

View File

@ -55,6 +55,11 @@ public abstract class CommandBase<PluginType extends MiniPlugin> implements ICom
return _requiredRank;
}
public void setRequiredRank(Rank rank)
{
this._requiredRank = rank;
}
public Rank[] GetSpecificRanks()
{
return _specificRank;

View File

@ -0,0 +1,3 @@
name: UHC-WorldGen
main: nautilus.game.arcade.uhc.WorldGen
version: 0.1

View File

@ -0,0 +1,28 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.mineplex</groupId>
<artifactId>mineplex-plugin</artifactId>
<version>dev-SNAPSHOT</version>
<relativePath>../plugin.xml</relativePath>
</parent>
<name>UHC WorldGen</name>
<artifactId>nautilus-game-arcade-uhc-worldgen</artifactId>
<dependencies>
<dependency>
<groupId>com.mineplex</groupId>
<artifactId>spigot</artifactId>
<version>1.8.8-1.9-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.zeroturnaround</groupId>
<artifactId>zt-zip</artifactId>
<version>1.9</version>
</dependency>
</dependencies>
</project>

View File

@ -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<ZipEntrySource> 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);
}
}

View File

@ -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

View File

@ -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)
{

View File

@ -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<ArcadeManager>
{
public DebugCommand(String commandName, Rank requiredRank, Rank... specificRanks)
{
super(Managers.get(ArcadeManager.class), requiredRank, specificRanks, commandName);
}
public abstract void Execute(Player caller, String[] args);
}

View File

@ -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<Class<? extends Module>, Module> _modules = new HashMap<>();
private HashMap<UUID, LinkedList<Triple<Double, Double, Double>>> _playerPastLocs = new HashMap<>();
private Set<DebugCommand> _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 extends Module> 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 extends Module> T getModule(Class<T> clazz)
{
return clazz.cast(_modules.get(clazz));

View File

@ -42,7 +42,7 @@ public class TeamBuild extends Build
TeamMode = true;
registerModule(new TeamModule());
new TeamModule().register(this);
TeamPerSpawn = true;
FillTeamsInOrderToCount = 2;

View File

@ -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)
// {

View File

@ -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);

View File

@ -68,7 +68,7 @@ public class TeamSkywars extends Skywars
TeamMode = true;
TeamPerSpawn = true;
registerModule(new TeamModule());
new TeamModule().register(this);
}
@Override

View File

@ -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));

View File

@ -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"),

View File

@ -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<net.minecraft.server.v1_8_R3.Entity> _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<Long, Chunk> loaded = new ConcurrentHashMap<>();
Map<Long, NBTTagCompound> 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<Long> 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<Long, net.minecraft.server.v1_8_R3.Chunk> 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();
}
}

View File

@ -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<Long, BiomeCacheBlock> _blockByCoord = new HashMap<>(); // LongHashMap -> HashMap, c -> _blockByCoord
private List<BiomeCache.BiomeCacheBlock> _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() + "%";
}
}

View File

@ -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

View File

@ -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

View File

@ -1,22 +1,24 @@
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
*
* <p>
* 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).
*
* <p>
* Modules should never directly access other Modules via the Game instance.
* Instead, the game which requires cross-contamination should do so itself.
*
* <p>
* Modules should be associated per-game. Do not make them static
*
* <p>
* 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.
* This custom configuration will be used to dynamically adjust gamemodes via Redis if needed
@ -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,20 +41,22 @@ 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
*
* <p>
* You can define how the JsonElement should be formatted.
*
* <p>
* It is recommended to have a "force" boolean which will reset this module to a clean state
* (to allow extensive customization using json)
*/
@ -61,11 +65,11 @@ public abstract class Module implements Listener
}
/*
/**
* 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
*
* <p>
* 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);
}
}

View File

@ -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;
}
}
}

View File

@ -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<Location> _isInSafezone = location -> true;
public SafezoneModule filter(Predicate<Location> 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<BlockState> 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);
}
}

View File

@ -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)

View File

@ -107,6 +107,7 @@ public class GameCreationManager implements Listener
Game game = gameIterator.next();
game.cleanupModules();
game.cleanupCommands();
game.disable();
HandlerList.unregisterAll(game);

View File

@ -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

View File

@ -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();
}
}

View File

@ -44,8 +44,6 @@ 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);
}
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)

View File

@ -35,6 +35,7 @@
<module>Mineplex.ServerMonitor</module>
<module>Mineplex.StaffServer</module>
<module>Nautilus.Game.Arcade</module>
<module>Nautilus.Game.Arcade.UHC.WorldGen</module>
<module>mavericks-review-hub</module>
</modules>