Merge branch 'develop' of https://github.com/Mineplex-LLC/Minecraft-PC into feature/party-v2
This commit is contained in:
commit
d9c5e6323a
@ -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)
|
||||
{
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user