use of com.bergerkiller.bukkit.common.map.MapDisplayTile 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.MapDisplayTile 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);
}
}
}
}
use of com.bergerkiller.bukkit.common.map.MapDisplayTile in project BKCommonLib by bergerhealer.
the class MapDisplayInfo method addTileIfMissing.
/**
* Adds a new display tile to already running displays.
* Does nothing if the display is going to be reset, or no display sessions exist.
* Since tile 0,0 is always added by the display, that tile is ignored.
*
* @param tileX
* @param tileY
*/
public void addTileIfMissing(int tileX, int tileY) {
if (this.sessions.isEmpty() || (tileX == 0 && tileY == 0)) {
return;
}
if ((tileX << 7) >= this.desiredWidth) {
return;
}
if ((tileY << 7) >= this.desiredHeight) {
return;
}
for (MapSession session : this.sessions) {
if (session.refreshResolutionRequested) {
continue;
}
if (session.display.containsTile(tileX, tileY)) {
continue;
}
MapDisplayTile newTile = new MapDisplayTile(this.uuid, tileX, tileY);
session.tiles.add(newTile);
for (MapSession.Owner owner : session.onlineOwners) {
owner.sendDirtyTile(newTile);
}
}
}
use of com.bergerkiller.bukkit.common.map.MapDisplayTile in project BKCommonLib by bergerhealer.
the class MapDisplayMarkers method synchronize.
public void synchronize(MapSession session) {
if (markersByTile.isEmpty()) {
// skip
return;
}
for (MapDisplayTile displayedTile : session.tiles) {
MapDisplayMarkerTile tile = markersByTile.get(displayedTile.tile);
if (tile == null || !tile.isChanged()) {
continue;
}
// Has changes, verify whether all owners have received them
MapDisplayTile.Update mapUpdate = null;
for (MapSession.Owner owner : session.onlineOwners) {
// Already synchronized during map content update
if (tile.isSynchronized(owner.player)) {
continue;
}
// Requires update, ask the tile to do this
if (mapUpdate == null) {
mapUpdate = new MapDisplayTile.Update(displayedTile.tile, displayedTile.getMapId());
APPLIER.apply(mapUpdate.packet.getRaw(), tile);
} else {
mapUpdate = mapUpdate.clone();
}
// Send to this player
PacketUtil.sendPacket(owner.player, mapUpdate.packet, false);
}
}
// Go by all tiles and clean them up
Iterator<MapDisplayMarkerTile> iter = markersByTile.values().iterator();
while (iter.hasNext()) {
MapDisplayMarkerTile tile = iter.next();
if (tile.isEmpty()) {
iter.remove();
} else {
tile.setChanged(false);
}
}
}
Aggregations