Merge branch 'develop' of https://github.com/Mineplex-LLC/Minecraft-PC into feature/party-v2

This commit is contained in:
TadahTech 2016-06-22 00:36:23 -05:00
commit d9c5e6323a
3 changed files with 274 additions and 296 deletions

View File

@ -255,6 +255,8 @@ public class MapUtil
@SuppressWarnings({ "rawtypes" })
public static boolean ClearWorldReferences(String worldName)
{
synchronized (RegionFileCache.class)
{
HashMap regionfiles = (HashMap) RegionFileCache.a;
@ -284,6 +286,7 @@ public class MapUtil
return true;
}
}
public static BlockPosition getBlockPos(int x, int y, int z)
{

View File

@ -1,8 +1,13 @@
package nautilus.game.arcade.game.games.uhc;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import mineplex.core.common.util.C;
import mineplex.core.common.util.F;
@ -35,6 +40,19 @@ import nautilus.game.arcade.game.TeamGame;
import nautilus.game.arcade.game.Game.GameState;
import nautilus.game.arcade.kit.Kit;
import net.minecraft.server.v1_8_R3.BiomeCache;
import net.minecraft.server.v1_8_R3.ChunkCoordIntPair;
import net.minecraft.server.v1_8_R3.ChunkProviderServer;
import net.minecraft.server.v1_8_R3.EmptyChunk;
import net.minecraft.server.v1_8_R3.ExceptionWorldConflict;
import net.minecraft.server.v1_8_R3.FileIOThread;
import net.minecraft.server.v1_8_R3.IChunkLoader;
import net.minecraft.server.v1_8_R3.IChunkProvider;
import net.minecraft.server.v1_8_R3.LongHashMap;
import net.minecraft.server.v1_8_R3.MinecraftServer;
import net.minecraft.server.v1_8_R3.NBTTagCompound;
import net.minecraft.server.v1_8_R3.World;
import net.minecraft.server.v1_8_R3.WorldChunkManager;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Chunk;
@ -46,6 +64,9 @@ import org.bukkit.WorldBorder;
import org.bukkit.World.Environment;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.craftbukkit.v1_8_R3.CraftWorld;
import org.bukkit.craftbukkit.v1_8_R3.generator.NormalChunkGenerator;
import org.bukkit.craftbukkit.v1_8_R3.util.LongHash;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
@ -86,6 +107,7 @@ import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionEffectType;
import org.bukkit.scoreboard.DisplaySlot;
import org.bukkit.scoreboard.Objective;
import org.spigotmc.WatchdogThread;
public class UHC extends TeamGame
{
@ -94,11 +116,12 @@ public class UHC extends TeamGame
private NautHashMap<String, Long> _deathTime = new NautHashMap<String, Long>();
// private NautHashMap<String, Long> _combatTime = new NautHashMap<String, Long>();
private boolean _mapLoaded = false;
private double _mapLoadPercent = 0;
private int _chunksPerTick = 1;
private volatile boolean _mapLoaded = false;
private volatile double _mapLoadPercent = 0;
private volatile int _chunksPerTick = 1;
private volatile boolean stopGen = false;
private int _chunkTotal;
private Chunk _chunk = null;
private int _chunkX = 0;
private int _chunkZ = 0;
private int _chunksLoaded = 0;
@ -368,84 +391,6 @@ public class UHC extends TeamGame
return borders;
}
@EventHandler
public void loadMap(UpdateEvent event)
{
if (_mapLoaded)
return;
if (WorldData.World == null)
return;
if (GetState() != GameState.Recruit)
return;
// Print Debug
if (event.getType() == UpdateType.SLOWER)
{
Announce(C.cGreen + C.Bold + "Generating Map: " + C.cWhite + getMapLoadETA() + " Remaining...", false);
TimingManager.endTotal("UHC Generation", true);
return;
}
if (event.getType() != UpdateType.TICK)
return;
// Timings
TimingManager.startTotal("UHC Generation");
for (int i = 0; i < _chunksPerTick ; i++)
{
// Unload Previous
// if (_chunk != null)
// _chunk.unload(true);
// Load Chunks
_chunk = WorldData.World.getChunkAt(_chunkX, _chunkZ);
_chunk.load(true);
// Scan Map
if (_chunkX < _currentBorder / 16)
{
_chunkX++;
}
else if (_chunkZ < _currentBorder / 16)
{
_chunkX = (int) -(_currentBorder / 16);
_chunkZ++;
}
else
{
_mapLoaded = true;
System.out.println("Map Loading Finished!");
generateSpawns();
break;
}
_chunksLoaded++;
}
_mapLoadPercent = (double)_chunksLoaded / (double)_chunkTotal;
// Timings
TimingManager.stopTotal("UHC Generation");
}
@EventHandler
public void chunkUnload(ChunkUnloadEvent event)
{
//Allow unloading after players in
if (IsLive())
return;
if (WorldData.World != null && event.getWorld().equals(WorldData.World))
{
System.out.println("Disallowing Unload of World");
event.setCancelled(true);
}
}
public void generateSpawns()
{
// Wipe Spawns
@ -622,63 +567,183 @@ public class UHC extends TeamGame
}
}
/*@EventHandler
public void WorldBoundaryCheck(UpdateEvent event)
{
if (event.getType() != UpdateType.FASTER)
return;
for (Player player : GetPlayers(true))
{
//Damage
if (Math.abs(player.getLocation().getX()) > _borderSize || Math.abs(player.getLocation().getZ()) > _borderSize)
{
player.damage(0.75);
}
}
}
@EventHandler
public void WorldBoundaryShrink(UpdateEvent event)
public void generateWorld(GameStateChangeEvent event)
{
if (!IsLive())
if (event.GetState() == GameState.Dead)
{
stopGen = true;
return;
if (event.getType() == UpdateType.SLOW)
if (_borderSize > 16)
_borderSize--;
}
//@EventHandler
public void WorldBoundarySet(GameStateChangeEvent event)
{
if (event.GetState() != GameState.Recruit)
return;
long time = System.currentTimeMillis();
this.WorldData.MinX = -_borderSize;
this.WorldData.MaxX = _borderSize;
this.WorldData.MinZ = -_borderSize;
this.WorldData.MaxZ = _borderSize;
this.WorldData.MinY = -1000;
this.WorldData.MaxY = 1000;
//Find Y Max
for (int x=-16 ; x<16 ; x++)
for (int z=-16 ; z<16 ; z++)
{
int y = UtilBlock.getHighest(WorldData.World, x, z).getY();
if (y > _yMax)
_yMax = y;
return;
}
System.out.println("Y Max: " + _yMax);
new Thread(() ->
{
try
{
Field fileIOThreadB = FileIOThread.class.getDeclaredField("b");
fileIOThreadB.setAccessible(true);
System.out.println("Time: " + UtilTime.MakeStr(System.currentTimeMillis() - time));
}*/
// 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) 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();
long last = start;
while (!stopGen)
{
long now = System.currentTimeMillis();
if ((now - last) >= 4000)
{
Announce(C.cGreen + C.Bold + "Generating Map: " + C.cWhite + getMapLoadETA() + " Remaining...", false);
last = now;
}
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;
System.out.println("Map Loading Finished! Took " + TimeUnit.MILLISECONDS.toSeconds(now - start) + " seconds");
break;
}
_chunksLoaded++;
// Clamp it so we don't get 101%
_mapLoadPercent = UtilMath.clamp((double) _chunksLoaded / (double) _chunkTotal, 0.0, 1.0);
_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");
getArcadeManager().runSync(this::generateSpawns);
}
catch (Throwable t)
{
// todo proper exception handling
// maybe force shutdown?
t.printStackTrace();
}
}, "WorldGen Thread").start();
}
@EventHandler
public void WorldBoundaryYLimit(BlockPlaceEvent event)
@ -865,45 +930,6 @@ public class UHC extends TeamGame
event.setLeaveMessage(null);
}
/*
@EventHandler(priority = EventPriority.LOWEST)
public void PlayerQuit(PlayerQuitEvent event)
{
Player player = event.getPlayer();
GameTeam team = GetTeam(player);
if (team == null) return;
if (!team.IsAlive(player))
return;
team.RemovePlayer(player);
if (player.isDead())
return;
if (true)
{
//Announcement
Announce(team.GetColor() + C.Bold + player.getName() + " was killed for disconnecting.");
player.damage(5000);
return;
}
if (_combatTime.containsKey(player.getName()) && !UtilTime.elapsed(_combatTime.get(player.getName()), 15000))
{
//Announcement
Announce(team.GetColor() + C.Bold + player.getName() + " was killed for disconnecting during combat.");
player.damage(5000);
return;
}
}
*/
@EventHandler
public void CreatureCull(UpdateEvent event)
{
@ -1074,37 +1100,6 @@ public class UHC extends TeamGame
}
}
/*
@EventHandler
public void HeadEat(PlayerInteractEvent event)
{
if (UtilGear.isMat(event.getPlayer().getItemInHand(), Material.SKULL_ITEM))
{
UtilPlayer.message(event.getPlayer(), "You ate " + event.getPlayer().getItemInHand().getItemMeta().getDisplayName() + ChatColor.RESET + ".");
(new PotionEffect(PotionEffectType.ABSORPTION, 2400, 0)).apply(event.getPlayer());
(new PotionEffect(PotionEffectType.REGENERATION, 200, 1)).apply(event.getPlayer());
event.getPlayer().setItemInHand(null);
event.setCancelled(true);
}
}
@EventHandler(priority = EventPriority.MONITOR)
public void DamageHealCancel(EntityDamageEvent event)
{
if (event.isCancelled())
return;
if (event.getEntity() instanceof Player)
{
Player player = (Player)event.getEntity();
player.removePotionEffect(PotionEffectType.REGENERATION);
UtilPlayer.message(player, "You took damage and lost " + F.elem(C.cGreen + "Regeneration") + ChatColor.RESET + ".");
}
}*/
@EventHandler
public void ConsumeHeadApple(PlayerItemConsumeEvent event)
{
@ -1139,30 +1134,6 @@ public class UHC extends TeamGame
{
if (event.getMessage().startsWith("/kill"))
event.setCancelled(true);
// if (event.getMessage().startsWith("/uhc time day"))
// {
// this.WorldTimeSet = 4000;
// event.setCancelled(true);
//
// Announce(event.getPlayer().getName() + " set time to Always Day!");
// }
//
// if (event.getMessage().startsWith("/uhc time night"))
// {
// this.WorldTimeSet = 16000;
// event.setCancelled(true);
//
// Announce(event.getPlayer().getName() + " set time to Always Night!");
// }
//
// if (event.getMessage().startsWith("/uhc time cycle"))
// {
// this.WorldTimeSet = -1;
// event.setCancelled(true);
//
// Announce(event.getPlayer().getName() + " set time to Day and Night!");
// }
}
@EventHandler(priority = EventPriority.LOWEST)

View File

@ -416,6 +416,10 @@ public class WorldData
public boolean LoadChunks(long maxMilliseconds)
{
if (Host instanceof UHC)
{
return true;
}
long startTime = System.currentTimeMillis();
for (; CurX <= MaxX; CurX += 16)