parent
45e6cb902f
commit
808e506911
@ -1,30 +1,26 @@
|
||||
package mineplex.game.clans.clans.map;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.*;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.*;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import mineplex.core.common.util.*;
|
||||
import mineplex.game.clans.tutorial.TutorialManager;
|
||||
import mineplex.game.clans.tutorial.map.TutorialMapManager;
|
||||
import net.minecraft.server.v1_8_R3.*;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.craftbukkit.v1_8_R3.CraftChunk;
|
||||
import org.bukkit.craftbukkit.v1_8_R3.CraftWorld;
|
||||
import org.bukkit.craftbukkit.v1_8_R3.util.LongHash;
|
||||
import org.bukkit.craftbukkit.v1_8_R3.util.LongObjectHashMap;
|
||||
import org.bukkit.entity.ItemFrame;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.block.Action;
|
||||
import org.bukkit.event.entity.ItemSpawnEvent;
|
||||
import org.bukkit.event.entity.PlayerDeathEvent;
|
||||
@ -35,6 +31,8 @@ import org.bukkit.event.player.PlayerItemHeldEvent;
|
||||
import org.bukkit.event.player.PlayerJoinEvent;
|
||||
import org.bukkit.event.player.PlayerQuitEvent;
|
||||
import org.bukkit.event.player.PlayerTeleportEvent;
|
||||
import org.bukkit.event.world.ChunkLoadEvent;
|
||||
import org.bukkit.event.world.ChunkUnloadEvent;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.map.MapRenderer;
|
||||
@ -46,13 +44,6 @@ import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.Multisets;
|
||||
|
||||
import mineplex.core.MiniPlugin;
|
||||
import mineplex.core.common.util.C;
|
||||
import mineplex.core.common.util.F;
|
||||
import mineplex.core.common.util.UtilInv;
|
||||
import mineplex.core.common.util.UtilPlayer;
|
||||
import mineplex.core.common.util.UtilServer;
|
||||
import mineplex.core.common.util.UtilTextBottom;
|
||||
import mineplex.core.common.util.UtilTime;
|
||||
import mineplex.core.common.util.UtilTime.TimeUnit;
|
||||
import mineplex.core.itemstack.ItemBuilder;
|
||||
import mineplex.core.portal.ServerTransferEvent;
|
||||
@ -62,82 +53,119 @@ import mineplex.game.clans.clans.ClansManager;
|
||||
import mineplex.game.clans.clans.ClansUtility;
|
||||
import mineplex.game.clans.clans.map.events.PlayerGetMapEvent;
|
||||
import mineplex.game.clans.clans.worldevent.WorldEventManager;
|
||||
import net.minecraft.server.v1_8_R3.Block;
|
||||
import net.minecraft.server.v1_8_R3.BlockPosition;
|
||||
import net.minecraft.server.v1_8_R3.Blocks;
|
||||
import net.minecraft.server.v1_8_R3.IBlockData;
|
||||
import net.minecraft.server.v1_8_R3.MaterialMapColor;
|
||||
import net.minecraft.server.v1_8_R3.PersistentCollection;
|
||||
|
||||
/*
|
||||
* This class manages what the Clans map will show.
|
||||
* It will scan all relevant chunks (eg players nearby) every <x> ticks
|
||||
*/
|
||||
public class ItemMapManager extends MiniPlugin
|
||||
{
|
||||
private int _blocksScan = 16 * 3;
|
||||
// Every BLOCK_SCAN_INTERVAL we add as a new region to scan
|
||||
private static final int BLOCK_SCAN_INTERVAL = 16 * 3;
|
||||
// 1536 is the width of the entire world from one borderland to the other
|
||||
private static final int HALF_WORLD_SIZE = 1536 / 2;
|
||||
// This slot is where the Clans Map will go by default
|
||||
private static final int CLANS_MAP_SLOT = 8;
|
||||
|
||||
private static final String[] ZOOM_INFO;
|
||||
|
||||
static
|
||||
{
|
||||
ZOOM_INFO = new String[4];
|
||||
for (int zoomLevel = 0; zoomLevel <= 3; zoomLevel++)
|
||||
{
|
||||
StringBuilder progressBar = new StringBuilder(C.cBlue);
|
||||
|
||||
boolean colorChange = false;
|
||||
for (int i = 2; i >= 0; i--)
|
||||
{
|
||||
if (!colorChange && i < zoomLevel)
|
||||
{
|
||||
progressBar.append(C.cGray);
|
||||
colorChange = true;
|
||||
}
|
||||
char c;
|
||||
switch (i)
|
||||
{
|
||||
case 0:
|
||||
c = '█';
|
||||
break;
|
||||
case 1:
|
||||
c = '▆';
|
||||
break;
|
||||
default:
|
||||
c = '▄';
|
||||
break;
|
||||
}
|
||||
for (int a = 0; a < 4; a++)
|
||||
{
|
||||
progressBar.append(c);
|
||||
}
|
||||
|
||||
if (i > 0)
|
||||
{
|
||||
progressBar.append(" ");
|
||||
}
|
||||
}
|
||||
ZOOM_INFO[zoomLevel] = progressBar.toString();
|
||||
}
|
||||
}
|
||||
|
||||
private ClansUtility _clansUtility;
|
||||
private Comparator<Entry<Integer, Integer>> _comparator;
|
||||
private int _halfMapSize = 1536 / 2;
|
||||
private int[][] _heightMap = new int[(_halfMapSize * 2) + 16][];
|
||||
private boolean _loadWorld = true;
|
||||
private int[][] _heightMap = new int[(HALF_WORLD_SIZE * 2) + 16][];
|
||||
private HashMap<Integer, Byte[][]> _map = new HashMap<Integer, Byte[][]>();
|
||||
private short _mapId = -1;
|
||||
private HashMap<String, MapInfo> _mapInfo = new HashMap<String, MapInfo>();
|
||||
private HashMap<Integer, Integer> _scale = new HashMap<Integer, Integer>();
|
||||
private ArrayList<Entry<Integer, Integer>> _scanList = new ArrayList<Entry<Integer, Integer>>();
|
||||
// Use LinkedList because operations are either add(Entry) which is O(1) and remove(0) which is O(1) on LinkedList but O(n) on ArrayList
|
||||
private LinkedList<Entry<Integer, Integer>> _scanList = new LinkedList<Entry<Integer, Integer>>();
|
||||
private World _world;
|
||||
private WorldServer _nmsWorld;
|
||||
private ChunkProviderServer _chunkProviderServer;
|
||||
private ChunkRegionLoader _chunkRegionLoader;
|
||||
private WorldEventManager _eventManager;
|
||||
private TutorialManager _tutorial;
|
||||
|
||||
public ItemMapManager(ClansManager clansManager, TutorialManager tutorial, WorldEventManager eventManager)
|
||||
{
|
||||
super("ItemMapManager", clansManager.getPlugin());
|
||||
|
||||
|
||||
_clansUtility = clansManager.getClanUtility();
|
||||
_eventManager = eventManager;
|
||||
_tutorial = tutorial;
|
||||
|
||||
_comparator = new Comparator<Entry<Integer, Integer>>()
|
||||
_comparator = (o1, o2) ->
|
||||
{
|
||||
// Render the places outside the map first to speed up visual errors fixing
|
||||
int outsideMap = Boolean.compare(o1.getValue() < -HALF_WORLD_SIZE, o2.getValue() < -HALF_WORLD_SIZE);
|
||||
|
||||
@Override
|
||||
public int compare(Entry<Integer, Integer> o1, Entry<Integer, Integer> o2)
|
||||
if (outsideMap != 0)
|
||||
{
|
||||
// Render the places outside the map first to speed up visual errors fixing
|
||||
int outsideMap = Boolean.compare(o1.getValue() < -_halfMapSize, o2.getValue() < -_halfMapSize);
|
||||
return -outsideMap;
|
||||
}
|
||||
|
||||
if (outsideMap != 0)
|
||||
{
|
||||
return -outsideMap;
|
||||
}
|
||||
double dist1 = 0;
|
||||
double dist2 = 0;
|
||||
|
||||
double dist1 = 0;
|
||||
double dist2 = 0;
|
||||
|
||||
for (Player player : UtilServer.getPlayers())
|
||||
{
|
||||
dist1 += getDistance(o1, player.getLocation().getX(), player.getLocation().getZ());
|
||||
dist2 += getDistance(o2, player.getLocation().getX(), player.getLocation().getZ());
|
||||
}
|
||||
|
||||
if (dist1 != dist2)
|
||||
{
|
||||
return Double.compare(dist1, dist2);
|
||||
}
|
||||
|
||||
dist1 = getDistance(o1, 0, 0);
|
||||
dist2 = getDistance(o2, 0, 0);
|
||||
for (Player player : UtilServer.getPlayers())
|
||||
{
|
||||
dist1 += getDistance(o1, player.getLocation().getX(), player.getLocation().getZ());
|
||||
dist2 += getDistance(o2, player.getLocation().getX(), player.getLocation().getZ());
|
||||
}
|
||||
|
||||
if (dist1 != dist2)
|
||||
{
|
||||
return Double.compare(dist1, dist2);
|
||||
|
||||
}
|
||||
|
||||
dist1 = getDistance(o1, 0, 0);
|
||||
dist2 = getDistance(o2, 0, 0);
|
||||
|
||||
return Double.compare(dist1, dist2);
|
||||
|
||||
};
|
||||
|
||||
for (int x = -_halfMapSize; x < _halfMapSize; x += _blocksScan)
|
||||
{
|
||||
for (int z = -_halfMapSize - 16; z < _halfMapSize; z += (z < -_halfMapSize ? 16 : _blocksScan))
|
||||
{
|
||||
_scanList.add(new HashMap.SimpleEntry(x, z));
|
||||
}
|
||||
}
|
||||
|
||||
_scale.put(0, 1);
|
||||
// _scale.put(1, 2);
|
||||
_scale.put(1, 4);
|
||||
@ -147,7 +175,7 @@ public class ItemMapManager extends MiniPlugin
|
||||
|
||||
for (Entry<Integer, Integer> entry : _scale.entrySet())
|
||||
{
|
||||
int size = (_halfMapSize * 2) / entry.getValue();
|
||||
int size = (HALF_WORLD_SIZE * 2) / entry.getValue();
|
||||
Byte[][] bytes = new Byte[size][];
|
||||
|
||||
for (int i = 0; i < size; i++)
|
||||
@ -165,6 +193,23 @@ public class ItemMapManager extends MiniPlugin
|
||||
|
||||
_world = Bukkit.getWorld("world");
|
||||
|
||||
try
|
||||
{
|
||||
Field chunkLoader = ChunkProviderServer.class.getDeclaredField("chunkLoader");
|
||||
chunkLoader.setAccessible(true);
|
||||
_nmsWorld = ((CraftWorld) _world).getHandle();
|
||||
_chunkProviderServer = _nmsWorld.chunkProviderServer;
|
||||
_chunkRegionLoader = (ChunkRegionLoader) chunkLoader.get(_chunkProviderServer);
|
||||
if (_chunkRegionLoader == null)
|
||||
{
|
||||
throw new RuntimeException("Did not expect null chunkLoader");
|
||||
}
|
||||
}
|
||||
catch (ReflectiveOperationException e)
|
||||
{
|
||||
throw new RuntimeException("Could not reflectively access ChunkRegionLoader", e);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
File file = new File("world/clans_map_id");
|
||||
@ -238,6 +283,58 @@ public class ItemMapManager extends MiniPlugin
|
||||
}
|
||||
|
||||
rebuildScan();
|
||||
initialScan();
|
||||
}
|
||||
|
||||
private void initialScan()
|
||||
{
|
||||
System.out.println("Beginning initial scan. There are " + _scanList.size() + " regions to scan");
|
||||
|
||||
// How many regions before logging an update (Currently set to every 20%)
|
||||
int logPer = _scanList.size() / 5;
|
||||
|
||||
while (!_scanList.isEmpty())
|
||||
{
|
||||
Entry<Integer, Integer> entry = _scanList.remove(0);
|
||||
if (_scanList.size() % logPer == 0)
|
||||
{
|
||||
System.out.println("Running initial render... " + _scanList.size() + " sections to go");
|
||||
}
|
||||
|
||||
int startingX = entry.getKey();
|
||||
int startingZ = entry.getValue();
|
||||
|
||||
boolean outsideMap = startingZ < -HALF_WORLD_SIZE;
|
||||
|
||||
scanWorldMap(startingX, startingZ, !outsideMap, true);
|
||||
|
||||
if (outsideMap)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
for (int scale = 1; scale < _scale.size(); scale++)
|
||||
{
|
||||
if (scale == 3)
|
||||
continue;
|
||||
|
||||
drawWorldScale(scale, startingX, startingZ);
|
||||
colorWorldHeight(scale, startingX, startingZ);
|
||||
}
|
||||
|
||||
colorWorldHeight(0, startingX, startingZ);
|
||||
}
|
||||
|
||||
for (int x = -HALF_WORLD_SIZE; x < HALF_WORLD_SIZE; x += BLOCK_SCAN_INTERVAL)
|
||||
{
|
||||
for (int z = -HALF_WORLD_SIZE; z < HALF_WORLD_SIZE; z += BLOCK_SCAN_INTERVAL)
|
||||
{
|
||||
drawWorldScale(3, x, z);
|
||||
colorWorldHeight(3, x, z);
|
||||
}
|
||||
}
|
||||
|
||||
System.out.println("Finished first map scan and render");
|
||||
}
|
||||
|
||||
private void setupRenderer(MapView view)
|
||||
@ -256,10 +353,7 @@ public class ItemMapManager extends MiniPlugin
|
||||
if (!(event.getRightClicked() instanceof ItemFrame))
|
||||
return;
|
||||
|
||||
ItemStack item = event.getPlayer().getItemInHand();
|
||||
|
||||
if (item == null || item.getType() != Material.MAP || item.getDurability() < _mapId
|
||||
|| item.getDurability() > _mapId + 100)
|
||||
if (!isItemClansMap(event.getPlayer().getItemInHand()))
|
||||
return;
|
||||
|
||||
event.setCancelled(true);
|
||||
@ -270,7 +364,7 @@ public class ItemMapManager extends MiniPlugin
|
||||
*/
|
||||
public int calcMapCenter(int zoom, int cord)
|
||||
{
|
||||
int mapSize = _halfMapSize / zoom; // This is how large the map is in pixels
|
||||
int mapSize = HALF_WORLD_SIZE / zoom; // This is how large the map is in pixels
|
||||
|
||||
int mapCord = cord / zoom; // This is pixels from true center of map, not held map
|
||||
|
||||
@ -309,7 +403,7 @@ public class ItemMapManager extends MiniPlugin
|
||||
Byte[][] map = _map.get(scale);
|
||||
int zoom = getZoom(scale);
|
||||
|
||||
for (int x = startingX; x < startingX + _blocksScan; x += zoom)
|
||||
for (int x = startingX; x < startingX + BLOCK_SCAN_INTERVAL; x += zoom)
|
||||
{
|
||||
double d0 = 0;
|
||||
|
||||
@ -319,10 +413,10 @@ public class ItemMapManager extends MiniPlugin
|
||||
{
|
||||
for (int addZ = 0; addZ < zoom; addZ++)
|
||||
{
|
||||
int hX = x + addX + _halfMapSize;
|
||||
int hZ = (startingZ - zoom) + addZ + _halfMapSize;
|
||||
int hX = x + addX + HALF_WORLD_SIZE;
|
||||
int hZ = (startingZ - zoom) + addZ + HALF_WORLD_SIZE;
|
||||
|
||||
if (hX >= _halfMapSize * 2 || hZ >= _halfMapSize * 2)
|
||||
if (hX >= HALF_WORLD_SIZE * 2 || hZ >= HALF_WORLD_SIZE * 2)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@ -331,7 +425,7 @@ public class ItemMapManager extends MiniPlugin
|
||||
}
|
||||
}
|
||||
|
||||
for (int z = startingZ; z < startingZ + _blocksScan; z += zoom)
|
||||
for (int z = startingZ; z < startingZ + BLOCK_SCAN_INTERVAL; z += zoom)
|
||||
{
|
||||
// Water depth colors not included
|
||||
double d1 = 0;
|
||||
@ -340,10 +434,10 @@ public class ItemMapManager extends MiniPlugin
|
||||
{
|
||||
for (int addZ = 0; addZ < zoom; addZ++)
|
||||
{
|
||||
int hX = x + addX + _halfMapSize;
|
||||
int hZ = z + addZ + _halfMapSize;
|
||||
int hX = x + addX + HALF_WORLD_SIZE;
|
||||
int hZ = z + addZ + HALF_WORLD_SIZE;
|
||||
|
||||
if (hX >= _halfMapSize * 2 || hZ >= _halfMapSize * 2)
|
||||
if (hX >= HALF_WORLD_SIZE * 2 || hZ >= HALF_WORLD_SIZE * 2)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@ -370,7 +464,7 @@ public class ItemMapManager extends MiniPlugin
|
||||
b0 = 0;
|
||||
}
|
||||
|
||||
int origColor = map[(x + _halfMapSize) / zoom][(z + _halfMapSize) / zoom] - 1;
|
||||
int origColor = map[(x + HALF_WORLD_SIZE) / zoom][(z + HALF_WORLD_SIZE) / zoom] - 1;
|
||||
|
||||
/*if (color < 4)
|
||||
{
|
||||
@ -388,7 +482,7 @@ public class ItemMapManager extends MiniPlugin
|
||||
}*/
|
||||
|
||||
byte color = (byte) (origColor + b0);
|
||||
map[(x + _halfMapSize) / zoom][(z + _halfMapSize) / zoom] = color;
|
||||
map[(x + HALF_WORLD_SIZE) / zoom][(z + HALF_WORLD_SIZE) / zoom] = color;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -399,9 +493,9 @@ public class ItemMapManager extends MiniPlugin
|
||||
Byte[][] second = _map.get(scale);
|
||||
int zoom = getZoom(scale);
|
||||
|
||||
for (int x = startingX; x < startingX + _blocksScan; x += zoom)
|
||||
for (int x = startingX; x < startingX + BLOCK_SCAN_INTERVAL; x += zoom)
|
||||
{
|
||||
for (int z = startingZ; z < startingZ + _blocksScan; z += zoom)
|
||||
for (int z = startingZ; z < startingZ + BLOCK_SCAN_INTERVAL; z += zoom)
|
||||
{
|
||||
HashMultiset<Byte> hashmultiset = HashMultiset.create();
|
||||
|
||||
@ -409,8 +503,8 @@ public class ItemMapManager extends MiniPlugin
|
||||
{
|
||||
for (int addZ = 0; addZ < zoom; addZ++)
|
||||
{
|
||||
int pX = x + addX + _halfMapSize;
|
||||
int pZ = z + addZ + _halfMapSize;
|
||||
int pX = x + addX + HALF_WORLD_SIZE;
|
||||
int pZ = z + addZ + HALF_WORLD_SIZE;
|
||||
|
||||
if (pX >= first.length || pZ >= first.length)
|
||||
{
|
||||
@ -432,7 +526,7 @@ public class ItemMapManager extends MiniPlugin
|
||||
{
|
||||
color = (byte) 0;
|
||||
}
|
||||
second[(x + _halfMapSize) / zoom][(z + _halfMapSize) / zoom] = color;
|
||||
second[(x + HALF_WORLD_SIZE) / zoom][(z + HALF_WORLD_SIZE) / zoom] = color;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -440,25 +534,16 @@ public class ItemMapManager extends MiniPlugin
|
||||
@EventHandler
|
||||
public void dropItem(ItemSpawnEvent event)
|
||||
{
|
||||
ItemStack item = event.getEntity().getItemStack();
|
||||
|
||||
if (item != null && item.getType() == Material.MAP && item.getDurability() >= _mapId
|
||||
&& item.getDurability() <= _mapId + 100)
|
||||
{
|
||||
if (isItemClansMap(event.getEntity().getItemStack()))
|
||||
event.getEntity().remove();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void removeMap(Player player)
|
||||
{
|
||||
for (int slot = 0; slot < player.getInventory().getSize(); slot++)
|
||||
{
|
||||
ItemStack item = player.getInventory().getItem(slot);
|
||||
|
||||
if (item != null && item.getType() == Material.MAP && item.getDurability() >= _mapId && item.getDurability() <= _mapId + 100)
|
||||
{
|
||||
if (isItemClansMap(player.getInventory().getItem(slot)))
|
||||
player.getInventory().setItem(slot, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -477,7 +562,7 @@ public class ItemMapManager extends MiniPlugin
|
||||
|
||||
private double getDistance(Entry<Integer, Integer> entry, double x1, double z1)
|
||||
{
|
||||
return getDistance(x1, z1, entry.getKey() + (_blocksScan / 2), entry.getValue() + (_blocksScan / 2));
|
||||
return getDistance(x1, z1, entry.getKey() + (BLOCK_SCAN_INTERVAL / 2), entry.getValue() + (BLOCK_SCAN_INTERVAL / 2));
|
||||
}
|
||||
|
||||
public Byte[][] getMap(int scale)
|
||||
@ -492,7 +577,7 @@ public class ItemMapManager extends MiniPlugin
|
||||
|
||||
public int getMapSize()
|
||||
{
|
||||
return _halfMapSize;
|
||||
return HALF_WORLD_SIZE;
|
||||
}
|
||||
|
||||
public int getZoom(int scale)
|
||||
@ -500,35 +585,7 @@ public class ItemMapManager extends MiniPlugin
|
||||
return _scale.get(scale);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void preventMapMoveInventories(InventoryClickEvent event)
|
||||
{
|
||||
Inventory inv = event.getClickedInventory();
|
||||
|
||||
if (inv == null)
|
||||
return;
|
||||
|
||||
// Yeah, the loop looks a little weird..
|
||||
for (ItemStack item : new ItemStack[]
|
||||
{
|
||||
event.getCurrentItem(), event.getCursor()
|
||||
})
|
||||
{
|
||||
if (item == null || item.getType() != Material.MAP || item.getDurability() < _mapId
|
||||
|| item.getDurability() > _mapId + 100)
|
||||
continue;
|
||||
|
||||
if (inv.getHolder() instanceof Player ? !event.isShiftClick() : Objects.equal(event.getCurrentItem(), item))
|
||||
continue;
|
||||
|
||||
event.setCancelled(true);
|
||||
|
||||
UtilPlayer.message(event.getWhoClicked(),
|
||||
F.main("Inventory", "You cannot move " + F.item("Clans Map") + " between inventories."));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
//fixme So what appears to happen is that after you die, if your map is is the same then the map is frozen
|
||||
@EventHandler
|
||||
public void onDeath(PlayerDeathEvent event)
|
||||
{
|
||||
@ -542,14 +599,10 @@ public class ItemMapManager extends MiniPlugin
|
||||
{
|
||||
Player player = event.getPlayer();
|
||||
|
||||
ItemStack item = player.getInventory().getItem(event.getNewSlot());
|
||||
|
||||
if (item == null || item.getType() != Material.MAP || item.getDurability() < _mapId
|
||||
|| item.getDurability() > _mapId + 100)
|
||||
if (!isItemClansMap(player.getInventory().getItem(event.getNewSlot())))
|
||||
return;
|
||||
|
||||
showZoom(player, getMap(player));
|
||||
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
@ -558,10 +611,7 @@ public class ItemMapManager extends MiniPlugin
|
||||
if (event.getAction() == Action.PHYSICAL)
|
||||
return;
|
||||
|
||||
ItemStack item = event.getItem();
|
||||
|
||||
if (item == null || item.getType() != Material.MAP || item.getDurability() < _mapId
|
||||
|| item.getDurability() > _mapId + 100)
|
||||
if (!isItemClansMap(event.getItem()))
|
||||
return;
|
||||
|
||||
event.setCancelled(true);
|
||||
@ -666,36 +716,11 @@ public class ItemMapManager extends MiniPlugin
|
||||
|
||||
private void rebuildScan()
|
||||
{
|
||||
for (int x = -_halfMapSize; x < _halfMapSize; x += _blocksScan)
|
||||
for (int x = -HALF_WORLD_SIZE; x < HALF_WORLD_SIZE; x += BLOCK_SCAN_INTERVAL)
|
||||
{
|
||||
for (int z = -_halfMapSize - 16; z < _halfMapSize; z += (z < -_halfMapSize ? 16 : _blocksScan))
|
||||
for (int z = -HALF_WORLD_SIZE - 16; z < HALF_WORLD_SIZE; z += (z < -HALF_WORLD_SIZE ? 16 : BLOCK_SCAN_INTERVAL))
|
||||
{
|
||||
_scanList.add(new HashMap.SimpleEntry(x, z));
|
||||
}
|
||||
}
|
||||
|
||||
if (!_loadWorld)
|
||||
{
|
||||
Iterator<Entry<Integer, Integer>> itel = _scanList.iterator();
|
||||
|
||||
while (itel.hasNext())
|
||||
{
|
||||
Entry<Integer, Integer> entry = itel.next();
|
||||
boolean removeEntry = true;
|
||||
|
||||
for (Player player : UtilServer.getPlayers())
|
||||
{
|
||||
if (Math.sqrt(getDistance(entry, player.getLocation().getX(), player.getLocation().getZ())) < 200)
|
||||
{
|
||||
removeEntry = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (removeEntry)
|
||||
{
|
||||
itel.remove();
|
||||
}
|
||||
_scanList.add(new HashMap.SimpleEntry<>(x, z));
|
||||
}
|
||||
}
|
||||
|
||||
@ -744,101 +769,117 @@ public class ItemMapManager extends MiniPlugin
|
||||
if (event.getType() != UpdateType.FAST)
|
||||
return;
|
||||
|
||||
if (_scanList.isEmpty())
|
||||
if (_scanList.isEmpty() && UtilServer.getPlayers().length > 0)
|
||||
{
|
||||
if (_loadWorld)
|
||||
{
|
||||
for (int x = -_halfMapSize; x < _halfMapSize; x += _blocksScan)
|
||||
{
|
||||
for (int z = -_halfMapSize; z < _halfMapSize; z += _blocksScan)
|
||||
{
|
||||
drawWorldScale(3, x, z);
|
||||
colorWorldHeight(3, x, z);
|
||||
}
|
||||
}
|
||||
|
||||
System.out.print("Finished first map scan and render");
|
||||
}
|
||||
|
||||
_loadWorld = false;
|
||||
|
||||
if (UtilServer.getPlayers().length == 0)
|
||||
return;
|
||||
|
||||
rebuildScan();
|
||||
}
|
||||
else if (_scanList.size() % 20 == 0)
|
||||
|
||||
if (_scanList.size() % 20 == 0)
|
||||
{
|
||||
Collections.sort(_scanList, _comparator);
|
||||
}
|
||||
|
||||
|
||||
if (_scanList.isEmpty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Entry<Integer, Integer> entry = _scanList.remove(0);
|
||||
|
||||
int startingX = entry.getKey();
|
||||
int startingZ = entry.getValue();
|
||||
|
||||
boolean outsideMap = startingZ < -_halfMapSize;
|
||||
boolean outsideMap = startingZ < -HALF_WORLD_SIZE;
|
||||
|
||||
scanWorldMap(startingX, startingZ, !outsideMap, false);
|
||||
|
||||
scanWorldMap(startingX, startingZ, !outsideMap);
|
||||
|
||||
if (outsideMap)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (int scale = 1; scale < _scale.size(); scale++)
|
||||
{
|
||||
if (scale == 3 && _loadWorld)
|
||||
continue;
|
||||
|
||||
if (!outsideMap)
|
||||
{
|
||||
drawWorldScale(scale, startingX, startingZ);
|
||||
}
|
||||
|
||||
drawWorldScale(scale, startingX, startingZ);
|
||||
colorWorldHeight(scale, startingX, startingZ);
|
||||
}
|
||||
|
||||
|
||||
colorWorldHeight(0, startingX, startingZ);
|
||||
}
|
||||
|
||||
public void scanWorldMap(int startingX, int startingZ, boolean setColors)
|
||||
|
||||
// Let's not create hundreds of thousands of BlockPositions
|
||||
// Single thread = should be thread safe
|
||||
private BlockPosition.MutableBlockPosition _blockPosition = new BlockPosition.MutableBlockPosition();
|
||||
|
||||
// Maps the cached chunks which were loaded from disk to save IO operations
|
||||
private LongObjectHashMap<Chunk> _chunkCache = new LongObjectHashMap<>();
|
||||
|
||||
/*
|
||||
* Remove the cached chunks when the real chunks are loaded in
|
||||
*/
|
||||
@EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR)
|
||||
public void LoadChunk(ChunkLoadEvent event)
|
||||
{
|
||||
_chunkCache.remove(LongHash.toLong(event.getChunk().getX(), event.getChunk().getZ()));
|
||||
}
|
||||
|
||||
/*
|
||||
* Given a particular coordinate, this method will scan up to BLOCK_SCAN_INTERVAL and record the color of ever 16th block
|
||||
* If a chunk has not been loaded, the following steps will be taken:
|
||||
* * Attempt to load the chunk from disk.
|
||||
* * If the chunk could not be loaded, generate it froms scratch
|
||||
* Otherwise, the loaded chunk will be used
|
||||
*/
|
||||
public void scanWorldMap(int startingX, int startingZ, boolean setColors, boolean isFirstScan)
|
||||
{
|
||||
Byte[][] map = _map.get(0);
|
||||
|
||||
for (int beginX = startingX; beginX < startingX + _blocksScan; beginX += 16)
|
||||
for (int beginX = startingX; beginX < startingX + BLOCK_SCAN_INTERVAL; beginX += 16)
|
||||
{
|
||||
for (int beginZ = startingZ - (startingZ > -_halfMapSize ? 16 : 0); beginZ < startingZ
|
||||
+ (setColors ? _blocksScan : 16); beginZ += 16)
|
||||
for (int beginZ = startingZ - (startingZ > -HALF_WORLD_SIZE ? 16 : 0); beginZ < startingZ
|
||||
+ (setColors ? BLOCK_SCAN_INTERVAL : 16); beginZ += 16)
|
||||
{
|
||||
Chunk chunk = _world.getChunkAt(beginX / 16, beginZ / 16);
|
||||
boolean loaded = false;
|
||||
|
||||
if (!chunk.isLoaded())
|
||||
int chunkX = beginX / 16;
|
||||
int chunkZ = beginZ / 16;
|
||||
net.minecraft.server.v1_8_R3.Chunk nmsChunk = _chunkProviderServer.getChunkIfLoaded(chunkX, chunkZ);
|
||||
if (nmsChunk == null)
|
||||
{
|
||||
if (_loadWorld)
|
||||
long key = LongHash.toLong(chunkX, chunkZ);
|
||||
nmsChunk = _chunkCache.get(key);
|
||||
if (nmsChunk == null)
|
||||
{
|
||||
loaded = chunk.load();
|
||||
}
|
||||
else
|
||||
{
|
||||
continue;
|
||||
if (!isFirstScan)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
try
|
||||
{
|
||||
Object[] data = _chunkRegionLoader.loadChunk(_nmsWorld, chunkX, chunkZ);
|
||||
if (data == null)
|
||||
{
|
||||
// Something is wrong with the chunk
|
||||
System.out.println("Chunk is not generated or missing level/block data. Regenerating (" + chunkX + "," + chunkZ + ")");
|
||||
nmsChunk = ((CraftChunk) _world.getChunkAt(chunkX, chunkZ)).getHandle();
|
||||
}
|
||||
else
|
||||
{
|
||||
nmsChunk = (net.minecraft.server.v1_8_R3.Chunk) data[0];
|
||||
}
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
throw new RuntimeException("Chunk is corrupt or not readable!", e);
|
||||
}
|
||||
_chunkCache.put(key, nmsChunk);
|
||||
}
|
||||
}
|
||||
|
||||
net.minecraft.server.v1_8_R3.Chunk nmsChunk = ((CraftChunk) chunk).getHandle();
|
||||
|
||||
for (int x = beginX; x < beginX + 16; x++)
|
||||
if (!nmsChunk.isEmpty())
|
||||
{
|
||||
for (int z = beginZ; z < beginZ + 16; z++)
|
||||
for (int x = beginX; x < beginX + 16; x++)
|
||||
{
|
||||
int color = 0;
|
||||
|
||||
if (!nmsChunk.isEmpty())
|
||||
for (int z = beginZ; z < beginZ + 16; z++)
|
||||
{
|
||||
int color = 0;
|
||||
|
||||
int k3 = x & 0xF;
|
||||
int l3 = z & 0xF;
|
||||
|
||||
@ -850,7 +891,8 @@ public class ItemMapManager extends MiniPlugin
|
||||
do
|
||||
{
|
||||
l4--;
|
||||
iblockdata= nmsChunk.getBlockData(new BlockPosition(k3, l4, l3));
|
||||
_blockPosition.c(k3, l4, l3);
|
||||
iblockdata = nmsChunk.getBlockData(_blockPosition);
|
||||
}
|
||||
while (iblockdata.getBlock().g(iblockdata) == MaterialMapColor.b && (l4 > 0));
|
||||
|
||||
@ -860,34 +902,31 @@ public class ItemMapManager extends MiniPlugin
|
||||
Block block1;
|
||||
do
|
||||
{
|
||||
block1 = nmsChunk.getType(new BlockPosition(k3, j5--, l3));
|
||||
_blockPosition.c(k3, j5--, l3);
|
||||
block1 = nmsChunk.getType(_blockPosition);
|
||||
}
|
||||
while ((j5 > 0) && (block1.getMaterial().isLiquid()));
|
||||
}
|
||||
}
|
||||
|
||||
_heightMap[x + _halfMapSize + 16][z + _halfMapSize + 16] = l4;
|
||||
_heightMap[x + HALF_WORLD_SIZE + 16][z + HALF_WORLD_SIZE + 16] = l4;
|
||||
|
||||
if (setColors)
|
||||
{
|
||||
//color = block.f(i5).M;
|
||||
IBlockData data = nmsChunk.getBlockData(new BlockPosition(k3, l4, l3));
|
||||
_blockPosition.c(k3, l4, l3);
|
||||
IBlockData data = nmsChunk.getBlockData(_blockPosition);
|
||||
color = data.getBlock().g(data).M;
|
||||
|
||||
color = (byte) ((color * 4) + 1);
|
||||
}
|
||||
}
|
||||
|
||||
if (setColors && beginZ >= startingZ)
|
||||
{
|
||||
map[x + _halfMapSize][z + _halfMapSize] = (byte) color;
|
||||
if (setColors && beginZ >= startingZ)
|
||||
{
|
||||
map[x + HALF_WORLD_SIZE][z + HALF_WORLD_SIZE] = (byte) color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (loaded)
|
||||
{
|
||||
chunk.unload();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -898,10 +937,10 @@ public class ItemMapManager extends MiniPlugin
|
||||
PlayerGetMapEvent event = UtilServer.CallEvent(new PlayerGetMapEvent(player));
|
||||
if (event.isCancelled())
|
||||
return;
|
||||
|
||||
|
||||
for (ItemStack item : UtilInv.getItems(player))
|
||||
{
|
||||
if (item.getType() == Material.MAP && (item.getDurability() >= _mapId && item.getDurability() <= _mapId + 100))
|
||||
if (isItemClansMap(item))
|
||||
{
|
||||
return;
|
||||
}
|
||||
@ -909,62 +948,38 @@ public class ItemMapManager extends MiniPlugin
|
||||
|
||||
ItemStack item = new ItemBuilder(Material.MAP, 1, (short) getMap(player).getMap()).setTitle("Clans Map").build();
|
||||
|
||||
int slot = player.getInventory().firstEmpty();
|
||||
int slot = CLANS_MAP_SLOT;
|
||||
|
||||
ItemStack mapSlot = player.getInventory().getItem(slot);
|
||||
if (mapSlot != null && mapSlot.getType() != Material.AIR)
|
||||
{
|
||||
slot = player.getInventory().firstEmpty();
|
||||
}
|
||||
|
||||
if (slot >= 0)
|
||||
{
|
||||
ItemStack mapSlot = player.getInventory().getItem(8);
|
||||
|
||||
if (mapSlot == null || mapSlot.getType() == Material.AIR)
|
||||
{
|
||||
slot = 8;
|
||||
}
|
||||
|
||||
player.getInventory().setItem(slot, item);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Displays the action bar to a player given their zoom level. Implementation may change
|
||||
*/
|
||||
private void showZoom(Player player, MapInfo info)
|
||||
{
|
||||
String progressBar = C.cBlue + "";
|
||||
|
||||
boolean colorChange = false;
|
||||
|
||||
for (int i = 2; i >= 0; i--)
|
||||
{
|
||||
if (!colorChange && i < info.getScale())
|
||||
{
|
||||
progressBar += C.cGray;
|
||||
colorChange = true;
|
||||
}
|
||||
|
||||
char c;
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 0:
|
||||
c = '█';
|
||||
break;
|
||||
case 1:
|
||||
c = '▆';
|
||||
break;
|
||||
default:
|
||||
c = '▄';
|
||||
break;
|
||||
}
|
||||
|
||||
for (int a = 0; a < 4; a++)
|
||||
{
|
||||
progressBar += c;
|
||||
}
|
||||
|
||||
if (i > 0)
|
||||
{
|
||||
progressBar += " ";
|
||||
}
|
||||
}
|
||||
|
||||
UtilTextBottom.display(progressBar, player);
|
||||
UtilTextBottom.display(ZOOM_INFO[info.getScale()], player);
|
||||
}
|
||||
|
||||
/*
|
||||
* Check whether an {@link ItemStack} is also a Clans Map
|
||||
*
|
||||
* @param itemStack The {@link ItemStack} to check
|
||||
* @returns Whether the {@link ItemStack} is also a Clans Map
|
||||
*/
|
||||
private boolean isItemClansMap(ItemStack itemStack)
|
||||
{
|
||||
return UtilItem.matchesMaterial(itemStack, Material.MAP)
|
||||
&& itemStack.getDurability() >= _mapId
|
||||
&& itemStack.getDurability() <= _mapId + 100;
|
||||
}
|
||||
}
|
||||
|
@ -143,7 +143,7 @@ public class ItemMapRenderer extends MapRenderer
|
||||
if (_manager.getClansUtility().relPT(player, chunk) == ClansUtility.ClanRelation.SAFE)
|
||||
clanColor2 = new Color(50, 150, 255);
|
||||
}
|
||||
else if (owningClan.getName().equals("Spawn"))
|
||||
else if (owningClan.getName().equals("Spawn"))
|
||||
{
|
||||
clanColor = Color.WHITE;
|
||||
clanColor2 = new Color(0, 255, 100);
|
||||
|
@ -4,6 +4,9 @@ import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.Event;
|
||||
import org.bukkit.event.HandlerList;
|
||||
|
||||
/*
|
||||
* This event is called when a Player is about to receive a Clans Map
|
||||
*/
|
||||
public class PlayerGetMapEvent extends Event
|
||||
{
|
||||
private static final HandlerList handlers = new HandlerList();
|
||||
|
@ -197,18 +197,7 @@ public class ClansRegions extends MiniPlugin
|
||||
{
|
||||
int x = chunkX + xOffset;
|
||||
int z = chunkZ + zOffset;
|
||||
Chunk chunk;
|
||||
try
|
||||
{ //Corrupted chunk will hold up whole server
|
||||
chunk = location.getWorld().getChunkAt(x, z);
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
System.out.println("UNABLE TO LOAD CHUNK AT " + x + " , " + z);
|
||||
e.printStackTrace();
|
||||
continue;
|
||||
}
|
||||
String chunkStr = UtilWorld.chunkToStr(chunk);
|
||||
String chunkStr = location.getWorld().getName() + "," + x + "," + z;
|
||||
|
||||
if (addNegative)
|
||||
{
|
||||
|
@ -2,6 +2,7 @@ package mineplex.game.clans.tutorial;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.LinkedList;
|
||||
import java.util.Stack;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
@ -25,7 +26,7 @@ public class TutorialWorldManager extends MiniPlugin
|
||||
|
||||
private final World _tutorialWorld;
|
||||
private final Schematic _schematic;
|
||||
private Stack<TutorialRegion> _regionStack;
|
||||
private LinkedList<TutorialRegion> _regionStack;
|
||||
private TutorialRegion _centerRegion;
|
||||
|
||||
public TutorialWorldManager(JavaPlugin plugin, String worldName, String schematicName) throws IOException
|
||||
@ -56,7 +57,7 @@ public class TutorialWorldManager extends MiniPlugin
|
||||
|
||||
private void populateRegionStack()
|
||||
{
|
||||
_regionStack = new Stack<>();
|
||||
_regionStack = new LinkedList<>();
|
||||
|
||||
// Populate the stack with 100 available tutorial regions
|
||||
for (int x = 0; x < 10; x++)
|
||||
|
Loading…
Reference in New Issue
Block a user