package net.scapeemulator.game.model.grounditem; import java.util.HashSet; import java.util.LinkedList; import java.util.List; import java.util.Set; import net.scapeemulator.game.model.Position; import net.scapeemulator.game.model.grounditem.GroundItemList.GroundItem; import net.scapeemulator.game.model.player.Player; import net.scapeemulator.game.msg.impl.PlacementCoordsMessage; import net.scapeemulator.game.msg.impl.grounditem.GroundItemCreateMessage; import net.scapeemulator.game.msg.impl.grounditem.GroundItemRemoveMessage; import net.scapeemulator.game.msg.impl.grounditem.GroundItemUpdateMessage; /** * @author Hadyn Richard * @author David Insley */ public final class GroundItemSynchronizer extends GroundItemListener { /** * The player to synchronize the ground items for. */ private final Player player; /** * The ids of all the ground items that the synchronizer has handled. */ private final Set<Integer> uids = new HashSet<>(); /** * The list of ground objects to remove once the player reaches a certain height. */ private final List<GroundItem> toRemove = new LinkedList<>(); /** * Constructs a new synchronizer for a player. * * @param player player to synchronize the ground items for */ public GroundItemSynchronizer(Player player) { this.player = player; } @Override public boolean shouldFireEvents(GroundItem groundItem) { int owner = groundItem.getOwner(); return (owner == -1) || (owner == player.getDatabaseId()); } @Override public void groundItemCreated(GroundItem groundItem) { Position position = groundItem.getPosition(); boolean withinScene = player.getLastKnownRegion().isWithinScene(position); boolean sameHeight = player.getPosition().getHeight() == position.getHeight(); if (withinScene && sameHeight && !uids.contains(groundItem.getUid())) { uids.add(groundItem.getUid()); sendPlacementCoords(position); player.send(new GroundItemCreateMessage(groundItem.getItemId(), groundItem.getAmount(), position)); return; } /* Remove the ground item from the added list if its not longer in the scene */ if (!withinScene && uids.contains(groundItem.getUid())) { uids.remove(groundItem.getUid()); } } @Override public void groundItemUpdated(GroundItem groundItem, int previousAmount) { Position position = groundItem.getPosition(); if (uids.contains(groundItem.getUid()) && player.getPosition().isWithinScene(position)) { sendPlacementCoords(position); player.send(new GroundItemUpdateMessage(groundItem.getItemId(), groundItem.getAmount(), groundItem.getPosition(), previousAmount)); } } @Override public void groundItemRemoved(GroundItem groundItem) { Position position = groundItem.getPosition(); boolean sameHeight = player.getPosition().getHeight() == position.getHeight(); uids.remove(groundItem.getUid()); if (sameHeight && player.getPosition().isWithinScene(position)) { sendPlacementCoords(position); player.send(new GroundItemRemoveMessage(groundItem.getItemId(), groundItem.getPosition())); } if (!sameHeight && player.getPosition().isWithinScene(position)) { toRemove.add(groundItem); } } /** * Purges the to remove list. */ public void purge() { if (!toRemove.isEmpty()) { for (GroundItem object : toRemove) { boolean sameHeight = object.getPosition().getHeight() == player.getPosition().getHeight(); Position position = object.getPosition(); if (sameHeight && player.getPosition().isWithinScene(position)) { sendPlacementCoords(position); player.send(new GroundItemRemoveMessage(object.getItemId(), position)); } } toRemove.clear(); } } private void sendPlacementCoords(Position position) { int localX = position.getLocalX(player.getLastKnownRegion().getRegionX()) & 0xfff8; int localY = position.getLocalY(player.getLastKnownRegion().getRegionY()) & 0xfff8; player.send(new PlacementCoordsMessage(localX, localY)); } }