use of com.bergerkiller.bukkit.common.map.util.MapUUID in project BKCommonLib by bergerhealer.
the class CommonMapController method onPacketSend.
@Override
@SuppressWarnings({ "unchecked", "rawtypes" })
public synchronized void onPacketSend(PacketSendEvent event) {
// Check if any virtual single maps are attached to this map
if (event.getType() == PacketType.OUT_MAP) {
int itemid = event.getPacket().read(PacketType.OUT_MAP.itemId);
MapUUID mapUUID = mapUUIDById.get(itemid);
if (mapUUID == null) {
this.storeStaticMapId((short) itemid);
} else if (CommonMapUUIDStore.getStaticMapId(mapUUID.getUUID()) == -1) {
event.setCancelled(true);
}
}
// This is always tile 0,0 (held map)
if (event.getType() == PacketType.OUT_WINDOW_ITEMS) {
List<ItemStack> items = event.getPacket().read(PacketType.OUT_WINDOW_ITEMS.items);
ListIterator<ItemStack> iter = items.listIterator();
while (iter.hasNext()) {
ItemStack newItem = this.handleItemSync(iter.next(), 0, 0);
if (newItem != null) {
iter.set(newItem);
}
}
}
if (event.getType() == PacketType.OUT_WINDOW_SET_SLOT) {
ItemStack oldItem = event.getPacket().read(PacketType.OUT_WINDOW_SET_SLOT.item);
ItemStack newItem = this.handleItemSync(oldItem, 0, 0);
if (newItem != null) {
if (disableMapItemChanges.get()) {
event.setCancelled(true);
} else {
event.getPacket().write(PacketType.OUT_WINDOW_SET_SLOT.item, newItem);
}
}
}
// Correct the ItemStack displayed in Item Frames
if (event.getType() == PacketType.OUT_ENTITY_METADATA) {
int entityId = event.getPacket().read(PacketType.OUT_ENTITY_METADATA.entityId);
Entity entity = WorldHandle.fromBukkit(event.getPlayer().getWorld()).getEntityById(entityId);
if (!(entity instanceof ItemFrame)) {
return;
}
ItemFrameInfo frameInfo = this.itemFrames.get(entity.getEntityId());
if (frameInfo == null) {
// no information available
return;
}
frameInfo.updateItem();
if (frameInfo.lastMapUUID == null) {
// not a map
return;
}
frameInfo.sentToPlayers = true;
if (disableMapItemChanges.get()) {
event.setCancelled(true);
// map changes are suppressed
return;
}
short staticMapId = CommonMapUUIDStore.getStaticMapId(frameInfo.lastMapUUID.getUUID());
if (staticMapId != -1) {
this.storeStaticMapId(staticMapId);
// static Id, not dynamic, no re-assignment
return;
}
// Map Id is dynamically assigned, adjust metadata items to use this new Id
// Avoid using any Bukkit or Wrapper types here for performance reasons
short newMapId = this.getMapId(frameInfo.lastMapUUID);
List<DataWatcher.Item<Object>> items = event.getPacket().read(PacketType.OUT_ENTITY_METADATA.watchedObjects);
if (items != null) {
ListIterator<DataWatcher.Item<Object>> itemsIter = items.listIterator();
while (itemsIter.hasNext()) {
DataWatcher.Item<ItemStack> item = itemsIter.next().translate(EntityItemFrameHandle.DATA_ITEM);
if (item == null) {
continue;
}
ItemStack metaItem = item.getValue();
if (metaItem == null || metaItem.getDurability() == newMapId) {
continue;
}
ItemStack newMapItem = ItemUtil.cloneItem(metaItem);
newMapItem.setDurability(newMapId);
item = item.clone();
item.setValue(newMapItem, item.isChanged());
itemsIter.set((DataWatcher.Item<Object>) (DataWatcher.Item) item);
}
}
}
}
use of com.bergerkiller.bukkit.common.map.util.MapUUID in project BKCommonLib by bergerhealer.
the class CommonMapController method handleItemSync.
/**
* Adjusts the internal remapping from UUID to Map Id taking into account the new item
* being synchronized to the player. If the item is that of a virtual map, the map Id
* of the item is updated. NBT data that should not be synchronized is dropped.
*
* @param item
* @param tileX the X-coordinate of the tile in which the item is displayed
* @param tileY the Y-coordinate of the tile in which the item is displayed
* @return True if the item was changed and needs to be updated in the packet
*/
public ItemStack handleItemSync(ItemStack item, int tileX, int tileY) {
if (item == null || item.getType() != Material.MAP) {
return null;
}
// When a map UUID is specified, use that to dynamically allocate a map Id to use
CommonTagCompound tag = ItemUtil.getMetaTag(item, false);
if (tag != null) {
UUID mapUUID = tag.getUUID("mapDisplay");
if (mapUUID != null) {
item = trimExtraData(item);
item.setDurability(getMapId(new MapUUID(mapUUID, tileX, tileY)));
return item;
}
}
// Static map Id MUST be enforced
storeStaticMapId(item.getDurability());
return null;
}
use of com.bergerkiller.bukkit.common.map.util.MapUUID in project BKCommonLib by bergerhealer.
the class CommonMapController method onPacketReceive.
@Override
public synchronized void onPacketReceive(PacketReceiveEvent event) {
// Handle input coming from the player for the map
if (event.getType() == PacketType.IN_STEER_VEHICLE) {
Player p = event.getPlayer();
MapPlayerInput input = playerInputs.get(p);
if (input != null) {
CommonPacket packet = event.getPacket();
int dx = (int) -Math.signum(packet.read(PacketType.IN_STEER_VEHICLE.sideways));
int dy = (int) -Math.signum(packet.read(PacketType.IN_STEER_VEHICLE.forwards));
int dz = 0;
if (packet.read(PacketType.IN_STEER_VEHICLE.unmount)) {
dz -= 1;
}
if (packet.read(PacketType.IN_STEER_VEHICLE.jump)) {
dz += 1;
}
// Receive input. If it will be handled, it will cancel further handling of this packet
event.setCancelled(input.receiveInput(dx, dy, dz));
}
}
// We have to prevent that in here
if (event.getType() == PacketType.IN_SET_CREATIVE_SLOT) {
ItemStack item = event.getPacket().read(PacketType.IN_SET_CREATIVE_SLOT.item);
UUID mapUUID = CommonMapUUIDStore.getMapUUID(item);
if (mapUUID != null && CommonMapUUIDStore.getStaticMapId(mapUUID) == -1) {
// Dynamic Id map. Since we do not refresh NBT data over the network, this packet contains incorrect data
// Find the original item the player took (by UUID). If it exists, merge its NBT data with this item.
ItemStack originalMapItem = null;
for (ItemStack oldItem : event.getPlayer().getInventory()) {
if (mapUUID.equals(CommonMapUUIDStore.getMapUUID(oldItem))) {
originalMapItem = oldItem.clone();
break;
}
}
if (originalMapItem != null) {
// Original item was found. Restore all properties of that item.
event.getPacket().write(PacketType.IN_SET_CREATIVE_SLOT.item, originalMapItem);
} else {
// Dynamic Id. Force a durability value of 0 to prevent creation of new World Map instances
item = ItemUtil.cloneItem(item);
item.setDurability((short) 0);
event.getPacket().write(PacketType.IN_SET_CREATIVE_SLOT.item, item);
}
}
}
}
use of com.bergerkiller.bukkit.common.map.util.MapUUID 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.util.MapUUID 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();
}
}
Aggregations