use of com.bergerkiller.bukkit.common.map.MapSession in project BKCommonLib by bergerhealer.
the class CommonMapController method storeDynamicMapId.
/**
* Figures out a new Map Id and prepares the display of a map with this new Id.
* This method is only suitable for dynamically generated map Ids.
*
* @param mapUUID to store
* @return map Id that was assigned
*/
private synchronized short storeDynamicMapId(MapUUID mapUUID) {
// Null safety check
if (mapUUID == null) {
return -1;
}
// If the UUID is static, do not store anything and return the static Id instead
short staticMapid = CommonMapUUIDStore.getStaticMapId(mapUUID.getUUID());
if (staticMapid != -1) {
return staticMapid;
}
// Increment this counter. The Map Id updater task will clean up unused maps every 1000 cycles.
idGenerationCounter++;
// Figure out a free Map Id we can use
for (int mapidValue = 0; mapidValue < Short.MAX_VALUE; mapidValue++) {
if (!mapUUIDById.contains(mapidValue)) {
// Check if the Map Id was changed compared to before
boolean idChanged = mapIdByUUID.containsKey(mapUUID);
// Store in mapping
mapUUIDById.put(mapidValue, mapUUID);
mapIdByUUID.put(mapUUID, Short.valueOf((short) mapidValue));
// Invalidate display if it exists
MapDisplayInfo mapInfo = maps.get(mapUUID.getUUID());
if (mapInfo != null) {
for (MapSession session : mapInfo.sessions) {
session.display.invalidate();
}
}
if (idChanged) {
dirtyMapUUIDSet.add(mapUUID.getUUID());
}
return (short) mapidValue;
}
}
return -1;
}
use of com.bergerkiller.bukkit.common.map.MapSession in project BKCommonLib by bergerhealer.
the class CommonMapController method handleMapShowEvent.
private synchronized void handleMapShowEvent(MapShowEvent event) {
// Check if there are other map displays that should be shown to the player automatically
// This uses the 'isGlobal()' property of the display
MapDisplayInfo info = CommonMapController.this.getInfo(event.getMapUUID());
boolean hasDisplay = false;
if (info != null) {
for (MapSession session : info.sessions) {
if (session.display.isGlobal()) {
session.display.addOwner(event.getPlayer());
hasDisplay = true;
break;
}
}
}
// When defined in the NBT of the item, construct the Map Display automatically
CommonTagCompound tag = ItemUtil.getMetaTag(event.getMapItem(), false);
if (tag != null && !hasDisplay) {
String pluginName = tag.getValue("mapDisplayPlugin", String.class);
String displayClassName = tag.getValue("mapDisplayClass", String.class);
if (pluginName != null && displayClassName != null) {
Plugin plugin = Bukkit.getPluginManager().getPlugin(pluginName);
Class<?> displayClass = null;
if (plugin != null) {
try {
displayClass = plugin.getClass().getClassLoader().loadClass(displayClassName);
if (!MapDisplay.class.isAssignableFrom(displayClass)) {
displayClass = null;
}
} catch (ClassNotFoundException e) {
}
}
if (displayClass != null && !event.hasDisplay()) {
try {
MapDisplay display = (MapDisplay) displayClass.newInstance();
event.setDisplay((JavaPlugin) plugin, display);
;
} catch (InstantiationException | IllegalAccessException e) {
e.printStackTrace();
}
}
}
}
CommonUtil.callEvent(event);
}
use of com.bergerkiller.bukkit.common.map.MapSession in project BKCommonLib by bergerhealer.
the class CommonMapController method onDisable.
/**
* Cleans up all running map displays and de-initializes all map display logic
*/
public void onDisable(CommonPlugin plugin) {
if (this.isEnabled) {
this.isEnabled = false;
// If reloading, save current map id state to avoid glitches
CommonMapReloadFile.save(plugin, reloadFile -> {
// Add static reserved / dynamic map ids
for (Map.Entry<MapUUID, Integer> entry : mapIdByUUID.entrySet()) {
MapUUID mapUUID = entry.getKey();
if (mapUUID.isStaticUUID()) {
reloadFile.staticReservedIds.add(entry.getValue());
} else {
reloadFile.addDynamicMapId(mapUUID, entry.getValue());
}
}
// Add information about all item frames and what display they displayed last
for (Map.Entry<Integer, ItemFrameInfo> entry : itemFrames.entrySet()) {
ItemFrameInfo info = entry.getValue();
if (info.lastMapUUID != null) {
reloadFile.addItemFrameDisplayUUID(entry.getKey().intValue(), info.lastMapUUID);
}
}
});
for (MapDisplayInfo map : this.mapsValues.cloneAsIterable()) {
for (MapSession session : new ArrayList<MapSession>(map.getSessions())) {
session.display.setRunning(false);
}
}
}
}
use of com.bergerkiller.bukkit.common.map.MapSession in project BKCommonLib by bergerhealer.
the class MapDisplayItemMapIdUpdater method updateMapIds.
public void updateMapIds() {
// Remove non-existing maps from the internal mapping
if (controller.idGenerationCounter > GENERATION_COUNTER_CLEANUP_INTERVAL) {
controller.idGenerationCounter = 0;
// Find all map UUIDs that exist on the server
HashSet<MapUUID> validUUIDs = new HashSet<MapUUID>();
for (Set<EntityItemFrameHandle> itemFrameSet : controller.itemFrameEntities.values()) {
for (EntityItemFrameHandle itemFrame : itemFrameSet) {
MapUUID mapUUID = controller.getItemFrameMapUUID(itemFrame);
if (mapUUID != null) {
validUUIDs.add(mapUUID);
}
}
}
for (Player player : Bukkit.getOnlinePlayers()) {
PlayerInventory inv = player.getInventory();
for (int i = 0; i < inv.getSize(); i++) {
ItemStack item = inv.getItem(i);
UUID mapUUID = CommonMapUUIDStore.getMapUUID(item);
if (mapUUID != null) {
validUUIDs.add(new MapUUID(mapUUID));
}
}
}
// Perform the cleanup (synchronized access required!)
controller.cleanupUnusedUUIDs(validUUIDs);
}
// Refresh items known to clients when Map Ids are re-assigned
// Swap around the tmp and main set every tick
final SetMultimap<UUID, MapUUID> dirtyMaps = controller.swapDirtyMapUUIDs();
if (!dirtyMaps.isEmpty()) {
// This will result in new SetItemSlot packets being sent, refreshing the map Id
for (Player player : Bukkit.getOnlinePlayers()) {
PlayerInventory inv = player.getInventory();
for (int i = 0; i < inv.getSize(); i++) {
ItemStack item = inv.getItem(i);
UUID uuid = CommonMapUUIDStore.getMapUUID(item);
if (dirtyMaps.containsKey(uuid)) {
inv.setItem(i, item.clone());
}
}
}
// Refresh all item frames that display this map
// This will result in a new EntityMetadata packets being sent, refreshing the map Id
// After updating all item frames, resend the maps
dirtyMaps.keySet().stream().map(controller.maps::get).filter(Objects::nonNull).forEach(info -> {
// Refresh item of all affected item frames
// This re-sends metadata packets
final Set<MapUUID> mapUUIDs = dirtyMaps.get(info.getUniqueId());
for (ItemFrameInfo itemFrameInfo : info.getItemFrames()) {
if (mapUUIDs.contains(itemFrameInfo.lastMapUUID)) {
itemFrameInfo.itemFrameHandle.refreshItem();
}
}
// Resend map data for all affected tiles
for (MapSession session : info.getSessions()) {
for (MapDisplayTile tile : session.tiles) {
if (mapUUIDs.contains(tile.getMapTileUUID())) {
session.onlineOwners.forEach(o -> o.sendDirtyTile(tile));
}
}
}
});
// Done processing, wipe
dirtyMaps.clear();
}
}
use of com.bergerkiller.bukkit.common.map.MapSession in project BKCommonLib by bergerhealer.
the class MapDisplayInfo method loadTiles.
/**
* Loads the tiles in a Map Display. This also removes tiles in the display
* that don't actually exist.
*
* @param session The session of the map display
* @param initialize Whether the tiles are initialized, and contents are not yet drawn
*/
public void loadTiles(MapSession session, boolean initialize) {
// Collect all tile x/y coordinates into a long hashset
LongHashSet tile_coords = new LongHashSet();
for (ItemFrameInfo itemFrame : this.itemFrames) {
MapUUID uuid = itemFrame.lastMapUUID;
if (uuid != null) {
tile_coords.add(uuid.getTileX(), uuid.getTileY());
}
}
tile_coords.add(0, 0);
if (initialize) {
// Wipe previous tiles when initializing
session.tiles.clear();
} else {
// Remove tiles from the display that are no longer present
// Remove existing tiles from the set at the same time
// We are left with a set containing tiles that must be added
Iterator<MapDisplayTile> iter = session.tiles.iterator();
while (iter.hasNext()) {
MapDisplayTile tile = iter.next();
if (!tile_coords.remove(tile.tileX, tile.tileY)) {
iter.remove();
}
}
}
// Add all remaining tiles to the display
LongHashSet.LongIterator iter = tile_coords.longIterator();
while (iter.hasNext()) {
long coord = iter.next();
MapDisplayTile newTile = new MapDisplayTile(this.uuid, MathUtil.longHashMsw(coord), MathUtil.longHashLsw(coord));
session.tiles.add(newTile);
// Send map packets for the added tile
if (!initialize) {
for (MapSession.Owner owner : session.onlineOwners) {
owner.sendDirtyTile(newTile);
}
}
}
}
Aggregations