package net.scapeemulator.game.model.object; 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.object.GroundObjectList.GroundObject; import net.scapeemulator.game.model.player.Player; import net.scapeemulator.game.msg.impl.PlacementCoordsMessage; import net.scapeemulator.game.msg.impl.object.GroundObjectAnimateMessage; import net.scapeemulator.game.msg.impl.object.GroundObjectRemoveMessage; import net.scapeemulator.game.msg.impl.object.GroundObjectUpdateMessage; /** * @author Hadyn Richard */ public final class GroundObjectSynchronizer extends GroundObjectListenerAdapter { /** * The player to synchronize the object list for. */ private final Player player; /** * The set of unique ids for objects that are within the players scene. */ private final Set<Integer> uids = new HashSet<>(); /** * The list of ground objects to remove once the player reaches a certain * height. */ private final List<GroundObject> toRemove = new LinkedList<>(); public GroundObjectSynchronizer(Player player) { this.player = player; } @Override public void groundObjectAdded(GroundObject object) { Position position = object.getPosition(); boolean withinScene = player.getLastKnownRegion().isWithinScene(position); boolean sameHeight = player.getPosition().getHeight() == position.getHeight(); if (withinScene && sameHeight && !uids.contains(object.getUid())) { uids.add(object.getUid()); sendPlacementCoords(position); player.send(new GroundObjectUpdateMessage(object.getPosition(), object.getId(), object.getType().getId(), object.getRotation())); return; } if (!withinScene && uids.contains(object.getUid())) { uids.remove(object.getUid()); } } @Override public void groundObjectIdUpdated(GroundObject object, int oldId) { Position position = object.getPosition(); boolean sameHeight = player.getPosition().getHeight() == position.getHeight(); if (sameHeight && player.getLastKnownRegion().isWithinScene(position)) { uids.add(object.getUid()); sendPlacementCoords(position); player.send(new GroundObjectUpdateMessage(object.getPosition(), object.getId(), object.getType().getId(), object.getRotation())); } } @Override public void groundObjectRotationUpdated(GroundObject object, int oldRotation) { Position position = object.getPosition(); boolean sameHeight = player.getPosition().getHeight() == position.getHeight(); if (sameHeight && player.getLastKnownRegion().isWithinScene(position)) { uids.add(object.getUid()); sendPlacementCoords(position); player.send(new GroundObjectUpdateMessage(object.getPosition(), object.getId(), object.getType().getId(), object.getRotation())); } } @Override public void groundObjectAnimated(GroundObject object) { Position position = object.getPosition(); boolean sameHeight = player.getPosition().getHeight() == position.getHeight(); if (sameHeight && player.getLastKnownRegion().isWithinScene(position)) { sendPlacementCoords(position); player.send(new GroundObjectAnimateMessage(position, object.getAnimationId(), object.getType().getId(), object.getRotation())); } } @Override public void groundObjectRemoved(GroundObject object) { Position position = object.getPosition(); uids.remove(object.getUid()); if (player.getPosition().isWithinScene(position)) { if (player.getPosition().getHeight() == position.getHeight()) { sendPlacementCoords(position); player.send(new GroundObjectRemoveMessage(position, object.getType().getId(), object.getRotation())); } else { toRemove.add(object); } } } /** * Purges the to remove list. */ public void purge() { if (!toRemove.isEmpty()) { for (GroundObject 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 GroundObjectRemoveMessage(position, object.getType().getId(), object.getRotation())); } } toRemove.clear(); } } /** * Sends a set of placement coords. */ private void sendPlacementCoords(Position position) { int localX = position.getLocalX(player.getLastKnownRegion().getRegionX()) & 0xf8; int localY = position.getLocalY(player.getLastKnownRegion().getRegionY()) & 0xf8; player.send(new PlacementCoordsMessage(localX, localY)); } }