Search in sources :

Example 1 with MapUUID

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);
            }
        }
    }
}
Also used : Entity(org.bukkit.entity.Entity) ItemFrame(org.bukkit.entity.ItemFrame) MapUUID(com.bergerkiller.bukkit.common.map.util.MapUUID) DataWatcher(com.bergerkiller.bukkit.common.wrappers.DataWatcher) ItemStack(org.bukkit.inventory.ItemStack)

Example 2 with MapUUID

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;
}
Also used : CommonTagCompound(com.bergerkiller.bukkit.common.nbt.CommonTagCompound) MapUUID(com.bergerkiller.bukkit.common.map.util.MapUUID) UUID(java.util.UUID) MapUUID(com.bergerkiller.bukkit.common.map.util.MapUUID)

Example 3 with MapUUID

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);
            }
        }
    }
}
Also used : Player(org.bukkit.entity.Player) MapPlayerInput(com.bergerkiller.bukkit.common.map.MapPlayerInput) CommonPacket(com.bergerkiller.bukkit.common.protocol.CommonPacket) ItemStack(org.bukkit.inventory.ItemStack) MapUUID(com.bergerkiller.bukkit.common.map.util.MapUUID) UUID(java.util.UUID)

Example 4 with MapUUID

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);
            }
        }
    }
}
Also used : MapDisplayInfo(com.bergerkiller.bukkit.common.map.binding.MapDisplayInfo) ArrayList(java.util.ArrayList) MapSession(com.bergerkiller.bukkit.common.map.MapSession) Map(java.util.Map) IdentityHashMap(java.util.IdentityHashMap) IntHashMap(com.bergerkiller.bukkit.common.wrappers.IntHashMap) HashMap(java.util.HashMap) OutputTypeMap(com.bergerkiller.mountiplex.reflection.util.OutputTypeMap) ItemFrameInfo(com.bergerkiller.bukkit.common.map.binding.ItemFrameInfo) MapUUID(com.bergerkiller.bukkit.common.map.util.MapUUID)

Example 5 with MapUUID

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();
    }
}
Also used : Player(org.bukkit.entity.Player) PlayerInventory(org.bukkit.inventory.PlayerInventory) MapSession(com.bergerkiller.bukkit.common.map.MapSession) ItemFrameInfo(com.bergerkiller.bukkit.common.map.binding.ItemFrameInfo) MapUUID(com.bergerkiller.bukkit.common.map.util.MapUUID) EntityItemFrameHandle(com.bergerkiller.generated.net.minecraft.world.entity.decoration.EntityItemFrameHandle) ItemStack(org.bukkit.inventory.ItemStack) MapUUID(com.bergerkiller.bukkit.common.map.util.MapUUID) UUID(java.util.UUID) HashSet(java.util.HashSet) MapDisplayTile(com.bergerkiller.bukkit.common.map.MapDisplayTile)

Aggregations

MapUUID (com.bergerkiller.bukkit.common.map.util.MapUUID)18 UUID (java.util.UUID)10 ItemStack (org.bukkit.inventory.ItemStack)6 MapSession (com.bergerkiller.bukkit.common.map.MapSession)5 Player (org.bukkit.entity.Player)5 ItemFrameInfo (com.bergerkiller.bukkit.common.map.binding.ItemFrameInfo)3 MapDisplayInfo (com.bergerkiller.bukkit.common.map.binding.MapDisplayInfo)3 DataWatcher (com.bergerkiller.bukkit.common.wrappers.DataWatcher)3 HashSet (java.util.HashSet)3 PlayerInventory (org.bukkit.inventory.PlayerInventory)3 MapDisplayTile (com.bergerkiller.bukkit.common.map.MapDisplayTile)2 MapPlayerInput (com.bergerkiller.bukkit.common.map.MapPlayerInput)2 CommonTagCompound (com.bergerkiller.bukkit.common.nbt.CommonTagCompound)2 IntVector3 (com.bergerkiller.bukkit.common.bases.IntVector3)1 ItemFrameInfo (com.bergerkiller.bukkit.common.internal.CommonMapController.ItemFrameInfo)1 CommonPacket (com.bergerkiller.bukkit.common.protocol.CommonPacket)1 IntHashMap (com.bergerkiller.bukkit.common.wrappers.IntHashMap)1 LongHashSet (com.bergerkiller.bukkit.common.wrappers.LongHashSet)1 PacketPlayInSteerVehicleHandle (com.bergerkiller.generated.net.minecraft.network.protocol.game.PacketPlayInSteerVehicleHandle)1 EntityItemFrameHandle (com.bergerkiller.generated.net.minecraft.world.entity.decoration.EntityItemFrameHandle)1