package robombs.game.view; import java.util.*; import robombs.game.model.*; import robombs.game.*; import com.threed.jpct.*; import com.threed.jpct.util.*; /** * A manager class for handling client objects. This manager holds references to * all client objects that this client knows of (even remote ones). */ public class ClientObjectManager { static final private long serialVersionUID = 1L; private Map<LocalObject, ClientObject> objects = null; private ClientObjectFactory cFac = ClientObjectFactory.getInstance(); private ShadowHelper sh = null; private boolean forBotClient = false; /** * Creates a new manager. */ public ClientObjectManager(ShadowHelper sh, boolean forBotClient) { objects = new HashMap<LocalObject, ClientObject>(); this.sh = sh; this.forBotClient = forBotClient; Colorizer.getInstance().init(); } /** * Returns all client objects that this manager knows of. * * @return Collection the client objects */ public Collection<ClientObject> getClientObjects() { return objects.values(); } /** * Returns the underlying data model of a view object. * * @param co * the view object * @return LocalObject the underlying local object that the view object * represents */ public LocalObject getLocalObjectToView(ClientObject co) { for (Iterator<Map.Entry<LocalObject, ClientObject>> itty = objects.entrySet().iterator(); itty.hasNext();) { Map.Entry<LocalObject, ClientObject> entry = itty.next(); if (co.equals(entry.getValue())) { return (LocalObject) entry.getKey(); } } return null; } /** * Gets a client object that has been created on a remote client with a * given id. If no such object exists, it returns null. * * @param objID * the id of the object * @param clientID * the id of the client * @return ClientObject the object or null */ public ClientObject getClientObject(int objID, int clientID) { LocalObject dummy = new LocalObject(clientID); dummy.setObjectID(objID); if (objects.containsKey(dummy)) { return (ClientObject) objects.get(dummy); } return null; } public void setShadowHelper(ShadowHelper sh) { this.sh = sh; } public List<SimpleVector> getPlayerPositions(boolean livingOnly, ClientObject self) { int myTeam = TeamAssigner.getTeam(self.getClientID(), self.getObjectID()); if (myTeam == 0) { return getPlayerPositions(livingOnly); } List<SimpleVector> res = new ArrayList<SimpleVector>(); for (ClientObject co : objects.values()) { if (co instanceof EnemyView && (!livingOnly || co.getBackAnimation() != Animations.DEAD) && TeamAssigner.getTeam(co.getClientID(), co.getObjectID()) != myTeam) { // Include both, just to be sure... res.add(co.getBackPosition()); res.add(co.getTranslation()); } } return res; } public List<SimpleVector> getPlayerPositions(boolean livingOnly) { List<SimpleVector> res = new ArrayList<SimpleVector>(); for (ClientObject co : objects.values()) { if (co instanceof EnemyView && (!livingOnly || co.getBackAnimation() != Animations.DEAD)) { // Include both, just to be sure... res.add(co.getBackPosition()); res.add(co.getTranslation()); } } return res; } public int getPlayerCount() { int cnt = 0; for (ClientObject co : objects.values()) { // A player with a very low y-position is actually there, but not // placed on the floor. // Such a player should be considered as absent. if (co instanceof EnemyView && co.getTranslation().y > Globals.skyLimit && co.getBackPosition().y > Globals.skyLimit) { cnt++; } } return cnt; } public void enterCollisionMode() { for (ClientObject co : objects.values()) { co.enterCollisionMode(); } } public void leaveCollisionMode() { for (ClientObject co : objects.values()) { co.leaveCollisionMode(); } } /** * Returns the view object for a given local object. If the manager already * knows of this object, it returns that one. If it doesn't, it creates a * new one and returns that. * * @param lo * the local object on which the view is based * @param world * the current world (needed, because the manager has to add the * new view object to it) * @param bulMan * the manager for the local bullets (because collisions of local * bullets with this object has be determined) * @return ClientObject the object */ public ClientObject getOrCreateClientObject(LocalObject lo, World world, ClientEventQueue eventQueue) { ClientObject co = objects.get(lo); if (co != null) { co.touch(); co.setToLocalObject(lo); co.setRemoteFlag(true); co.setTransfered(true); } else { co = cFac.create(lo.getType()); co.setEventQueue(eventQueue); // System.out.println(lo.getType()+"/"+lo.getPosition()); co.addCollisionListener(new ClientObjectCollisionListener(lo, false)); co.touch(); co.setToLocalObject(lo); co.setRemoteFlag(true); co.setTransfered(true); co.initTransformation(); co.addToWorld(world); objects.put(lo, co); if (!forBotClient) { if (lo.getType() == Types.PLAYER) { Colorizer.getInstance().colorize(co, lo); } } if (sh != null) { sh.addCaster(co); } } return co; } public static ClientObject createLocalPlayerObject(LocalObject lo, World world, ClientEventQueue eventQueue) { // Der Player muss nicht vom Manager verwaltet werden. Er wird hier nur // erzeugt. ClientObject co = ClientObjectFactory.getInstance().create(Types.LOCAL_PLAYER); co.setEventQueue(eventQueue); co.addToWorld(world); co.setRemoteFlag(false); co.setAsLocalOnly(); co.setVisibility(true); return co; } /** * Removes all objects from the manager and the world. * * @param world * the current world */ public void removeAll(World world) { List<ClientObject> tmp = new ArrayList<ClientObject>(objects.values()); for (Iterator<ClientObject> itty = tmp.iterator(); itty.hasNext();) { ClientObject co = itty.next(); if (!co.isLocalOnly()) { remove(co, world); if (sh != null) { sh.removeCaster(co); } } } } public void process(long ticks, Level level, World world, boolean received, boolean botUsage) { List<ClientObject> toKick = new ArrayList<ClientObject>(); for (ClientObject obj : getClientObjects()) { if (obj.isTransfered() || !received) { if (!botUsage) { obj.process(ticks, level); } else { obj.processForBotClient(ticks, level); } } else { if (received && !obj.isLocalOnly()) { toKick.add(obj); } } } for (ClientObject co : toKick) { remove(co, world); if (sh != null) { sh.removeCaster(co); } } } /** * Removes a single object from the manager and the world. * * @param co * the object to remove * @param world * the world */ public void remove(ClientObject co, World world) { co.removeFromWorld(world); Set<Map.Entry<LocalObject, ClientObject>> entries = objects.entrySet(); for (Iterator<Map.Entry<LocalObject, ClientObject>> itty = entries.iterator(); itty.hasNext();) { Map.Entry<LocalObject, ClientObject> es = itty.next(); if (es.getValue().equals(co)) { itty.remove(); if (sh != null) { sh.removeCaster(co); } } } } public String toString() { StringBuilder sb = new StringBuilder(); for (ClientObject obj : getClientObjects()) { sb.append(obj.getClass().getName() + " - " + obj.getBackPosition() + " - " + obj.getID()); } return sb.toString(); } }