From 99a97622a6f957efc9395fc3693713987c4a7cb5 Mon Sep 17 00:00:00 2001 From: Ray Greenwell Date: Tue, 23 May 2006 21:44:05 +0000 Subject: [PATCH] Refactored things so that the whirled.spot Location class is merely an interface and specific games can define their own concept of a location. Portal and SceneLocation now both have a Location instance within them. All the whirled stuff is happy not knowing the details of the Location even though it manages portals and other such goodies. The 'stage' stuff does need to know, and yohoho uses the new StageLocation class that is essentially identical to the old 'Location'. SceneLocation previously extended Location, and there were a lot of places where they were used somewhat interchangeably, or a SceneLocation and a regular Location were compared. This shouldn't be done anymore and I've left in code that should dump stack if it occurs, so that we can spot these logic errors at runtime. git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@4140 542714f4-19e9-0310-aa3c-eee0fc999fb1 --- .../stage/client/StageSceneController.java | 23 ++++ .../stage/client/StageScenePanel.java | 28 ++--- .../stage/server/StageSceneManager.java | 78 ++++++------ .../stage/tools/editor/EditorScenePanel.java | 6 +- .../stage/tools/editor/PortalTool.java | 12 +- .../stage/tools/viewer/ViewerScenePanel.java | 7 +- .../stage/tools/xml/StageSceneParser.java | 9 +- .../threerings/stage/util/StageSceneUtil.java | 54 +++++---- .../whirled/spot/data/Location.java | 112 +++--------------- .../threerings/whirled/spot/data/Portal.java | 18 +-- .../whirled/spot/data/SceneLocation.java | 36 ++++-- .../spot/tools/xml/SpotSceneRuleSet.java | 9 +- 12 files changed, 188 insertions(+), 204 deletions(-) diff --git a/src/java/com/threerings/stage/client/StageSceneController.java b/src/java/com/threerings/stage/client/StageSceneController.java index 4e405b378..227be9154 100644 --- a/src/java/com/threerings/stage/client/StageSceneController.java +++ b/src/java/com/threerings/stage/client/StageSceneController.java @@ -3,12 +3,16 @@ package com.threerings.stage.client; +import com.samskivert.util.Tuple; + import com.threerings.crowd.client.PlaceView; import com.threerings.crowd.util.CrowdContext; import com.threerings.whirled.data.SceneUpdate; import com.threerings.whirled.spot.client.SpotSceneController; +import com.threerings.stage.Log; +import com.threerings.stage.data.StageLocation; import com.threerings.stage.util.StageContext; /** @@ -17,6 +21,25 @@ import com.threerings.stage.util.StageContext; */ public class StageSceneController extends SpotSceneController { + /** + * Called when the user clicks on a location within the scene. + */ + public void handleLocationClicked (Object source, StageLocation loc) + { + Log.warning("handleLocationClicked(" + source + ", " + loc + ")"); + } + + /** + * Handles a cluster clicked event. + * + * @param tuple a Tuple containing (Cluster, Point) with the Cluster + * that was clicked and the Point being the screen coords of the click. + */ + public void handleClusterClicked (Object source, Tuple tuple) + { + Log.warning("handleClusterClicked(" + source + ", " + tuple + ")"); + } + // documentation inherited protected PlaceView createPlaceView (CrowdContext ctx) { diff --git a/src/java/com/threerings/stage/client/StageScenePanel.java b/src/java/com/threerings/stage/client/StageScenePanel.java index f3347f675..3f4b1d4e4 100644 --- a/src/java/com/threerings/stage/client/StageScenePanel.java +++ b/src/java/com/threerings/stage/client/StageScenePanel.java @@ -46,11 +46,14 @@ import com.threerings.crowd.client.PlaceView; import com.threerings.crowd.data.PlaceObject; import com.threerings.whirled.data.SceneUpdate; + import com.threerings.whirled.spot.data.Cluster; import com.threerings.whirled.spot.data.Location; import com.threerings.whirled.spot.data.Portal; +import com.threerings.whirled.spot.data.SceneLocation; import com.threerings.stage.Log; +import com.threerings.stage.data.StageLocation; import com.threerings.stage.data.StageMisoSceneModel; import com.threerings.stage.data.StageScene; import com.threerings.stage.data.StageSceneModel; @@ -68,10 +71,6 @@ public class StageScenePanel extends MisoScenePanel * within the scene. */ public static final String LOCATION_CLICKED = "LocationClicked"; - /** An action command generated when something besides the user wants - * us to move to a location. */ - public static final String LOCATION_REQUESTED = "LocationRequested"; - /** An action command generated when a cluster is clicked. */ public static final String CLUSTER_CLICKED = "ClusterClicked"; @@ -163,9 +162,10 @@ public class StageScenePanel extends MisoScenePanel _portobjs.clear(); for (Iterator iter = _scene.getPortals(); iter.hasNext(); ) { Portal portal = (Portal) iter.next(); - Point p = getScreenCoords(portal.loc.x, portal.loc.y); - int tx = MisoUtil.fullToTile(portal.loc.x); - int ty = MisoUtil.fullToTile(portal.loc.y); + StageLocation loc = (StageLocation) portal.loc; + Point p = getScreenCoords(loc.x, loc.y); + int tx = MisoUtil.fullToTile(loc.x); + int ty = MisoUtil.fullToTile(loc.y); Point ts = MisoUtil.tileToScreen(_metrics, tx, ty, new Point()); // Log.info("Added portal " + portal + @@ -180,7 +180,7 @@ public class StageScenePanel extends MisoScenePanel ObjectTile tile = new PortalObjectTile( ts.x + _metrics.tilehwid - p.x + (PORTAL_ICON_WIDTH / 2), ts.y + _metrics.tilehei - p.y + (PORTAL_ICON_HEIGHT / 2)); - tile.setImage(ots.getTileMirage(portal.loc.orient)); + tile.setImage(ots.getTileMirage(loc.orient)); _portobjs.add(new SceneObject(this, info, tile) { public boolean setHovered (boolean hovered) { @@ -266,15 +266,14 @@ public class StageScenePanel extends MisoScenePanel // if the hover object is a cluster, we clicked it! if (event.getButton() == MouseEvent.BUTTON1) { if (hobject instanceof Cluster) { - int mx = event.getX(), my = event.getY(); - Object actarg = new Tuple(hobject, new Point(mx, my)); + Object actarg = new Tuple(hobject, event.getPoint()); Controller.postAction(this, CLUSTER_CLICKED, actarg); } else { // post an action indicating that we've clicked on a location Point lc = MisoUtil.screenToFull( _metrics, event.getX(), event.getY(), new Point()); Controller.postAction(this, LOCATION_CLICKED, - new Location(lc.x, lc.y, (byte)0)); + new StageLocation(lc.x, lc.y, (byte)0)); } return true; } @@ -304,10 +303,10 @@ public class StageScenePanel extends MisoScenePanel { // compute a screen rectangle that contains all possible "spots" // in this cluster - ArrayList spots = StageSceneUtil.getClusterLocs(cluster); + ArrayList spots = StageSceneUtil.getClusterLocs(cluster); Rectangle cbounds = null; for (int ii = 0, ll = spots.size(); ii < ll; ii++) { - Location loc = (Location)spots.get(ii); + StageLocation loc = ((StageLocation) spots.get(ii).loc); Point sp = getScreenCoords(loc.x, loc.y); if (cbounds == null) { cbounds = new Rectangle(sp.x, sp.y, 0, 0); @@ -482,7 +481,8 @@ public class StageScenePanel extends MisoScenePanel Iterator iter = _scene.getPortals(); while (iter.hasNext()) { Portal portal = (Portal)iter.next(); - if (portal.loc.x == fullX && portal.loc.y == fullY) { + StageLocation loc = (StageLocation) portal.loc; + if (loc.x == fullX && loc.y == fullY) { return portal; } } diff --git a/src/java/com/threerings/stage/server/StageSceneManager.java b/src/java/com/threerings/stage/server/StageSceneManager.java index 3512a06f0..c646c0c2e 100644 --- a/src/java/com/threerings/stage/server/StageSceneManager.java +++ b/src/java/com/threerings/stage/server/StageSceneManager.java @@ -37,6 +37,7 @@ import com.threerings.stage.client.StageSceneService; import com.threerings.stage.data.DefaultColorUpdate; import com.threerings.stage.data.ModifyObjectsUpdate; import com.threerings.stage.data.StageCodes; +import com.threerings.stage.data.StageLocation; import com.threerings.stage.data.StageMisoSceneModel; import com.threerings.stage.data.StageOccupantInfo; import com.threerings.stage.data.StageScene; @@ -67,7 +68,7 @@ public class StageSceneManager extends SpotSceneManager _tloc.y = MisoUtil.toFull(y, 2); return mayStandAtLocation((BodyObject)traverser, _tloc); } - protected Location _tloc = new Location(); + protected StageLocation _tloc = new StageLocation(); }; } @@ -150,7 +151,7 @@ public class StageSceneManager extends SpotSceneManager * Called by NPPs to determine whether or not they can stand at the * specified location. */ - public boolean mayStandAtLocation (BodyObject source, Location loc) + public boolean mayStandAtLocation (BodyObject source, StageLocation loc) { return validateLocation(source, loc, false); } @@ -279,7 +280,8 @@ public class StageSceneManager extends SpotSceneManager super.updateLocation(source, loc); // keep a rectangle around for each un-clustered occupant - int tx = MisoUtil.fullToTile(loc.x), ty = MisoUtil.fullToTile(loc.y); + StageLocation sloc = (StageLocation) loc; + int tx = MisoUtil.fullToTile(sloc.x), ty = MisoUtil.fullToTile(sloc.y); _loners.put(source.getOid(), new Rectangle(tx, ty, 1, 1)); } @@ -307,8 +309,9 @@ public class StageSceneManager extends SpotSceneManager _plocs.clear(); for (Iterator iter = _sscene.getPortals(); iter.hasNext(); ) { Portal port = (Portal)iter.next(); - _plocs.add(new Point(MisoUtil.fullToTile(port.loc.x), - MisoUtil.fullToTile(port.loc.y))); + StageLocation loc = (StageLocation) port.loc; + _plocs.add(new Point(MisoUtil.fullToTile(loc.x), + MisoUtil.fullToTile(loc.y))); } } @@ -316,7 +319,7 @@ public class StageSceneManager extends SpotSceneManager * Helper function for {@link #mayStandAtLocation} and {@link * #validateLocation(BodyObject,Location)}. */ - protected boolean validateLocation (BodyObject source, Location loc, + protected boolean validateLocation (BodyObject source, StageLocation loc, boolean allowPortals) { int tx = MisoUtil.fullToTile(loc.x), ty = MisoUtil.fullToTile(loc.y); @@ -335,14 +338,16 @@ public class StageSceneManager extends SpotSceneManager } // if they are already standing on this tile, allow it - Location cloc = (Location) + SceneLocation cloc = (SceneLocation) _ssobj.occupantLocs.get(new Integer(source.getOid())); - if (cloc != null && - MisoUtil.fullToTile(cloc.x) == tx && - MisoUtil.fullToTile(cloc.y) == ty) { -// Log.info("Allowing adjust [who=" + source.who () + -// ", cloc=" + cloc + ", nloc=" + loc + "]."); - return true; + if (cloc != null) { + StageLocation sloc = (StageLocation) cloc.loc; + if (MisoUtil.fullToTile(sloc.x) == tx && + MisoUtil.fullToTile(sloc.y) == ty) { +// Log.info("Allowing adjust [who=" + source.who () + +// ", cloc=" + cloc + ", nloc=" + loc + "]."); + return true; + } } // make sure they're not standing in a cluster footprint, an @@ -393,9 +398,10 @@ public class StageSceneManager extends SpotSceneManager MisoSceneMetrics metrics = StageSceneUtil.getMetrics(); SceneLocation loc = new SceneLocation( entry.getOppLocation(), body.getOid()); - int tx = MisoUtil.fullToTile(loc.x), - ty = MisoUtil.fullToTile(loc.y); - int oidx = loc.orient/2; + StageLocation sloc = (StageLocation) loc.loc; + int tx = MisoUtil.fullToTile(sloc.x), + ty = MisoUtil.fullToTile(sloc.y); + int oidx = sloc.orient/2; int lidx = (oidx+3)%4; // rotate to the left int ridx = (oidx+1)%4; // rotate to the right @@ -409,7 +415,7 @@ public class StageSceneManager extends SpotSceneManager ty += PORTAL_DY[oidx]; // look in the center column - if (checkEntry(metrics, body, tx, ty, loc)) { + if (checkEntry(metrics, body, tx, ty, sloc)) { break LOC_SEARCH; } @@ -417,7 +423,7 @@ public class StageSceneManager extends SpotSceneManager for (int lx = tx, ly = ty, ff = 0; ff < fan; ff++) { lx += PORTAL_DX[lidx]; ly += PORTAL_DY[lidx]; - if (checkEntry(metrics, body, lx, ly, loc)) { + if (checkEntry(metrics, body, lx, ly, sloc)) { break LOC_SEARCH; } } @@ -426,7 +432,7 @@ public class StageSceneManager extends SpotSceneManager for (int rx = tx, ry = ty, ff = 0; ff < fan; ff++) { rx += PORTAL_DX[ridx]; ry += PORTAL_DY[ridx]; - if (checkEntry(metrics, body, rx, ry, loc)) { + if (checkEntry(metrics, body, rx, ry, sloc)) { break LOC_SEARCH; } } @@ -434,24 +440,25 @@ public class StageSceneManager extends SpotSceneManager // if this is our last pass and we didn't find anything, // revert back to the portal location if (fan == MAX_FAN-1) { - loc = new SceneLocation( - entry.getOppLocation(), body.getOid()); + sloc = (StageLocation) entry.getOppLocation(); } } - tx = MisoUtil.fullToTile(loc.x); - ty = MisoUtil.fullToTile(loc.y); + tx = MisoUtil.fullToTile(sloc.x); + ty = MisoUtil.fullToTile(sloc.y); _loners.put(body.getOid(), new Rectangle(tx, ty, 1, 1)); + + loc.loc = sloc; return loc; } /** Helper function for {@link #computeEnteringLocation}. */ protected boolean checkEntry (MisoSceneMetrics metrics, BodyObject body, - int tx, int ty, SceneLocation sloc) + int tx, int ty, StageLocation loc) { - sloc.x = MisoUtil.toFull(tx, metrics.finegran/2); - sloc.y = MisoUtil.toFull(ty, metrics.finegran/2); - return validateLocation(body, sloc, false); + loc.x = MisoUtil.toFull(tx, metrics.finegran/2); + loc.y = MisoUtil.toFull(ty, metrics.finegran/2); + return validateLocation(body, loc, false); } // documentation inherited @@ -459,7 +466,7 @@ public class StageSceneManager extends SpotSceneManager { // TODO: make sure the user isn't warping to hell and gone (and if // they are, make sure they're an admin) - return validateLocation(source, loc, true); + return validateLocation(source, (StageLocation)loc, true); } // documentation inherited @@ -653,14 +660,15 @@ public class StageSceneManager extends SpotSceneManager // if we're adding our first player, assign initial dimensions // to the cluster cl.width = 1; cl.height = 1; - Location loc = locationForBody(bodyOid); + SceneLocation loc = locationForBody(bodyOid); if (loc == null) { Log.warning("Foreign body added to cluster [clrec=" + clrec + ", body=" + body.who() + "]."); cl.x = 10; cl.y = 10; } else { - cl.x = MisoUtil.fullToTile(loc.x); - cl.y = MisoUtil.fullToTile(loc.y); + StageLocation sloc = (StageLocation) loc.loc; + cl.x = MisoUtil.fullToTile(sloc.x); + cl.y = MisoUtil.fullToTile(sloc.y); } // we'll do everything else when occupant two shows up return; @@ -703,7 +711,7 @@ public class StageSceneManager extends SpotSceneManager // Log.info("Maybe moving " + bodyOid + " from " + sloc + // " to " + cloc + // " (avail=" + StringUtil.toString(locs) + ")."); - if (cloc != null && !cloc.equivalent(sloc)) { + if (cloc != null && !cloc.loc.equivalent(sloc.loc)) { cloc.bodyOid = bodyOid; // Log.info("Moving " + bodyOid + " to " + cloc + // " for " + cl + "."); @@ -771,14 +779,16 @@ public class StageSceneManager extends SpotSceneManager * supplied location. */ protected static SceneLocation getClosestLoc ( - ArrayList locs, SceneLocation loc) + ArrayList locs, SceneLocation optimalLocation) { + StageLocation loc = (StageLocation) optimalLocation.loc; SceneLocation cloc = null; float cdist = Integer.MAX_VALUE; int cidx = -1; for (int ii = 0, ll = locs.size(); ii < ll; ii++) { SceneLocation tloc = (SceneLocation)locs.get(ii); - float tdist = MathUtil.distance(loc.x, loc.y, tloc.x, tloc.y); + StageLocation sl = (StageLocation) tloc.loc; + float tdist = MathUtil.distance(loc.x, loc.y, sl.x, sl.y); if (tdist < cdist) { cloc = tloc; cdist = tdist; diff --git a/src/java/com/threerings/stage/tools/editor/EditorScenePanel.java b/src/java/com/threerings/stage/tools/editor/EditorScenePanel.java index 6d7c0e57e..969d727bb 100644 --- a/src/java/com/threerings/stage/tools/editor/EditorScenePanel.java +++ b/src/java/com/threerings/stage/tools/editor/EditorScenePanel.java @@ -51,6 +51,7 @@ import com.threerings.miso.data.ObjectInfo; import com.threerings.miso.util.MisoUtil; import com.threerings.stage.client.StageScenePanel; +import com.threerings.stage.data.StageLocation; import com.threerings.stage.data.StageMisoSceneModel; import com.threerings.stage.data.StageScene; @@ -888,15 +889,16 @@ public class EditorScenePanel extends StageScenePanel protected void paintPortal (Graphics2D gfx, EditablePortal port) { // get the portal's center coordinate + StageLocation loc = (StageLocation) port.loc; Point spos = new Point(); - MisoUtil.fullToScreen(_metrics, port.loc.x, port.loc.y, spos); + MisoUtil.fullToScreen(_metrics, loc.x, loc.y, spos); int cx = spos.x, cy = spos.y; // translate the origin to center on the portal gfx.translate(cx, cy); // rotate to reflect the portal orientation - double rot = (Math.PI / 4.0f) * port.loc.orient; + double rot = (Math.PI / 4.0f) * loc.orient; gfx.rotate(rot); // draw the triangle diff --git a/src/java/com/threerings/stage/tools/editor/PortalTool.java b/src/java/com/threerings/stage/tools/editor/PortalTool.java index f13ee6306..ce87e623e 100644 --- a/src/java/com/threerings/stage/tools/editor/PortalTool.java +++ b/src/java/com/threerings/stage/tools/editor/PortalTool.java @@ -17,6 +17,7 @@ import com.threerings.util.DirectionUtil; import com.threerings.whirled.spot.data.Location; import com.threerings.whirled.spot.tools.EditablePortal; +import com.threerings.stage.data.StageLocation; import com.threerings.stage.data.StageScene; import com.threerings.stage.tools.editor.util.ExtrasPainter; @@ -37,7 +38,7 @@ public class PortalTool extends MouseInputAdapter // configure the portal with these full coordinates _portal = new EditablePortal(); - _portal.loc = new Location(p.x, p.y, (byte)DirectionCodes.NORTH); + _portal.loc = new StageLocation(p.x, p.y, (byte)DirectionCodes.NORTH); // we want to listen to drags and clicks _panel.addMouseListener(this); @@ -99,8 +100,9 @@ public class PortalTool extends MouseInputAdapter } // if our orientation changed, repaint - if (norient != _portal.loc.orient) { - _portal.loc.orient = (byte)norient; + StageLocation loc = (StageLocation) _portal.loc; + if (norient != loc.orient) { + loc.orient = (byte)norient; _panel.repaint(); } } @@ -111,8 +113,8 @@ public class PortalTool extends MouseInputAdapter protected void savePortal () { // try to come up with a reasonable name - String dirname = - DirectionUtil.toString(_portal.loc.orient).toLowerCase(); + byte orient = ((StageLocation) _portal.loc).orient; + String dirname = DirectionUtil.toString(orient).toLowerCase(); String name = dirname; for (int ii=1; portalNameExists(name); ii++) { name = dirname + ii; diff --git a/src/java/com/threerings/stage/tools/viewer/ViewerScenePanel.java b/src/java/com/threerings/stage/tools/viewer/ViewerScenePanel.java index 97a36879c..eb0283ebd 100644 --- a/src/java/com/threerings/stage/tools/viewer/ViewerScenePanel.java +++ b/src/java/com/threerings/stage/tools/viewer/ViewerScenePanel.java @@ -31,6 +31,7 @@ import com.threerings.stage.client.StageScenePanel; import com.threerings.whirled.spot.data.Location; import com.threerings.stage.Log; +import com.threerings.stage.data.StageLocation; import com.threerings.stage.data.StageScene; import com.threerings.stage.util.StageContext; @@ -66,8 +67,8 @@ public class ViewerScenePanel extends StageScenePanel setScene(scene); // move all of our sprites to the default entrance - _defloc = defloc; - Point defpos = getScreenCoords(defloc.x, defloc.y); + _defloc = (StageLocation) defloc; + Point defpos = getScreenCoords(_defloc.x, _defloc.y); _sprite.setLocation(defpos.x, defpos.y); if (_decoys != null) { @@ -220,7 +221,7 @@ public class ViewerScenePanel extends StageScenePanel protected static final int DEFAULT_NUM_DECOYS = 10; /** The current scene's default entrance. */ - protected Location _defloc; + protected StageLocation _defloc; /** Provides character sprite data. */ protected CharacterManager _charmgr; diff --git a/src/java/com/threerings/stage/tools/xml/StageSceneParser.java b/src/java/com/threerings/stage/tools/xml/StageSceneParser.java index 7a3936286..54fed8262 100644 --- a/src/java/com/threerings/stage/tools/xml/StageSceneParser.java +++ b/src/java/com/threerings/stage/tools/xml/StageSceneParser.java @@ -11,6 +11,9 @@ import com.threerings.whirled.spot.tools.xml.SpotSceneRuleSet; import com.threerings.whirled.tools.xml.SceneParser; import com.threerings.whirled.tools.xml.SceneRuleSet; +import com.threerings.whirled.spot.data.Location; + +import com.threerings.stage.data.StageLocation; import com.threerings.stage.data.StageSceneModel; /** @@ -37,7 +40,11 @@ public class StageSceneParser extends SceneParser }); // add rule sets for our aux scene models - registerAuxRuleSet(new SpotSceneRuleSet()); + registerAuxRuleSet(new SpotSceneRuleSet() { + protected Location createLocation () { + return new StageLocation(); + } + }); registerAuxRuleSet(new StageMisoSceneRuleSet()); } diff --git a/src/java/com/threerings/stage/util/StageSceneUtil.java b/src/java/com/threerings/stage/util/StageSceneUtil.java index 3b4db7e28..79ef83e02 100644 --- a/src/java/com/threerings/stage/util/StageSceneUtil.java +++ b/src/java/com/threerings/stage/util/StageSceneUtil.java @@ -31,6 +31,7 @@ import com.threerings.whirled.spot.data.Location; import com.threerings.whirled.spot.data.SceneLocation; import com.threerings.stage.Log; +import com.threerings.stage.data.StageLocation; import com.threerings.stage.data.StageMisoSceneModel; import com.threerings.stage.data.StageSceneModel; @@ -51,7 +52,7 @@ public class StageSceneUtil * Does the necessary jiggery pokery to figure out where the specified * object's associated location is. */ - public static Location locationForObject ( + public static StageLocation locationForObject ( TileManager tilemgr, ObjectInfo info) { return locationForObject(tilemgr, info.tileId, info.x, info.y); @@ -67,7 +68,7 @@ public class StageSceneUtil * @param tx the object's x tile coordinate. * @param ty the object's y tile coordinate. */ - public static Location locationForObject ( + public static StageLocation locationForObject ( TileManager tilemgr, int tileId, int tx, int ty) { try { @@ -89,7 +90,8 @@ public class StageSceneUtil // ", sy=" + tset.getYSpot(tidx) + // ", lx=" + opos.x + ", ly=" + opos.y + // ", fg=" + _metrics.finegran + "]."); - return new Location(opos.x, opos.y, (byte)tset.getSpotOrient(tidx)); + return new StageLocation(opos.x, opos.y, + (byte)tset.getSpotOrient(tidx)); } catch (Exception e) { Log.warning("Unable to look up object tile for scene object " + @@ -189,9 +191,9 @@ public class StageSceneUtil /** * Computes a list of the valid locations in this cluster. */ - public static ArrayList getClusterLocs (Cluster cluster) + public static ArrayList getClusterLocs (Cluster cluster) { - ArrayList list = new ArrayList(); + ArrayList list = new ArrayList(); // convert our tile coordinates into a cartesian coordinate system // with units equal to one fine coordinate in size @@ -204,9 +206,10 @@ public class StageSceneUtil // if it's a 1x1 cluster, return one location in the center of the // cluster if (cluster.width == 1) { - list.add(new SceneLocation(MisoUtil.toFull(cluster.x, 2), - MisoUtil.toFull(cluster.y, 2), - (byte)DirectionCodes.SOUTHWEST, 0)); + StageLocation loc = new StageLocation( + MisoUtil.toFull(cluster.x, 2), MisoUtil.toFull(cluster.y, 2), + (byte)DirectionCodes.SOUTHWEST); + list.add(new SceneLocation(loc, 0)); return list; } @@ -233,7 +236,8 @@ public class StageSceneUtil sx = MisoUtil.toFull(tx, sx-(tx*_metrics.finegran)); int ty = MathUtil.floorDiv(sy, _metrics.finegran); sy = MisoUtil.toFull(ty, sy-(ty*_metrics.finegran)); - list.add(new SceneLocation(sx, sy, (byte)orient, 0)); + StageLocation loc = new StageLocation(sx, sy, (byte) orient); + list.add(new SceneLocation(loc, 0)); } return list; @@ -279,7 +283,7 @@ public class StageSceneUtil * * @return the closest spot to the */ - public static Location findStandingSpot ( + public static StageLocation findStandingSpot ( Rectangle foot, int dist, AStarPathUtil.TraversalPred pred, Object traverser, final Point nearto, int orient) { @@ -292,28 +296,36 @@ public class StageSceneUtil int xx1 = foot.x-dd, xx2 = foot.x+foot.width+dd-1; // get the corners - spots.add(new Location(xx1, yy1, (byte)DirectionCodes.SOUTHWEST)); - spots.add(new Location(xx1, yy2, (byte)DirectionCodes.SOUTHEAST)); - spots.add(new Location(xx2, yy1, (byte)DirectionCodes.NORTHWEST)); - spots.add(new Location(xx2, yy2, (byte)DirectionCodes.NORTHEAST)); + spots.add( + new StageLocation(xx1, yy1, (byte)DirectionCodes.SOUTHWEST)); + spots.add( + new StageLocation(xx1, yy2, (byte)DirectionCodes.SOUTHEAST)); + spots.add( + new StageLocation(xx2, yy1, (byte)DirectionCodes.NORTHWEST)); + spots.add( + new StageLocation(xx2, yy2, (byte)DirectionCodes.NORTHEAST)); // then the sides for (int xx = xx1+1; xx < xx2; xx++) { - spots.add(new Location(xx, yy1, (byte)DirectionCodes.WEST)); - spots.add(new Location(xx, yy2, (byte)DirectionCodes.EAST)); + spots.add( + new StageLocation(xx, yy1, (byte)DirectionCodes.WEST)); + spots.add( + new StageLocation(xx, yy2, (byte)DirectionCodes.EAST)); } for (int yy = yy1+1; yy < yy2; yy++) { - spots.add(new Location(xx1, yy, (byte)DirectionCodes.SOUTH)); - spots.add(new Location(xx2, yy, (byte)DirectionCodes.NORTH)); + spots.add( + new StageLocation(xx1, yy, (byte)DirectionCodes.SOUTH)); + spots.add( + new StageLocation(xx2, yy, (byte)DirectionCodes.NORTH)); } // sort them in order of closeness to the players current // coordinate spots.sort(new Comparator() { public int compare (Object o1, Object o2) { - return dist((Location)o1) - dist((Location)o2); + return dist((StageLocation)o1) - dist((StageLocation)o2); } - private final int dist (Location l) { + private final int dist (StageLocation l) { return Math.round(100*MathUtil.distance( l.x, l.y, nearto.x, nearto.y)); } @@ -322,7 +334,7 @@ public class StageSceneUtil // return the first spot that can be "traversed" which we're // taking to mean "stood upon" for (int ii = 0, ll = spots.size(); ii < ll; ii++) { - Location loc = (Location)spots.get(ii); + StageLocation loc = (StageLocation)spots.get(ii); if (pred.canTraverse(traverser, loc.x, loc.y)) { // convert to full coordinates loc.x = MisoUtil.toFull(loc.x, 2); diff --git a/src/java/com/threerings/whirled/spot/data/Location.java b/src/java/com/threerings/whirled/spot/data/Location.java index 29da53679..6804bd1fc 100644 --- a/src/java/com/threerings/whirled/spot/data/Location.java +++ b/src/java/com/threerings/whirled/spot/data/Location.java @@ -1,112 +1,34 @@ -// -// $Id$ -// -// Narya library - tools for developing networked games -// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved -// http://www.threerings.net/code/narya/ -// -// This library is free software; you can redistribute it and/or modify it -// under the terms of the GNU Lesser General Public License as published -// by the Free Software Foundation; either version 2.1 of the License, or -// (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - package com.threerings.whirled.spot.data; -import com.threerings.io.SimpleStreamableObject; -import com.threerings.util.DirectionCodes; -import com.threerings.util.DirectionUtil; +import com.threerings.io.Streamable; -/** - * Contains information on a scene occupant's position and orientation. - */ -public class Location extends SimpleStreamableObject - implements Cloneable +public interface Location extends Streamable, Cloneable { - /** The user's x position (interpreted by the display system). */ - public int x; - - /** The user's y position (interpreted by the display system). */ - public int y; - - /** The user's orientation (defined by {@link DirectionCodes}). */ - public byte orient; - - /** {@link #toString} helper function. */ - public String orientToString () - { - return DirectionUtil.toShortString(orient); - } + /** + * Get a new Location instance that is equals() to this one but that + * has an orientation facing the opposite direction. + */ + public Location getOpposite (); /** - * A zero-argument constructor used when unserializing instances. + * Two locations are equivalent if they specify the same location + * and orientation. */ - public Location () - { - } + public boolean equivalent (Location other); /** - * Constructs a location with the specified coordinates and - * orientation. + * Two locations are equals if they specify the same coordinates, but + * the orientation may be different. */ - public Location (int x, int y, byte orient) - { - this.x = x; - this.y = y; - this.orient = orient; - - if (orient == -1) { - Thread.dumpStack(); - } - } + public boolean equals (Object other); /** - * Creates a clone of this instance. + * The hashcode of a Location should be based only on its coordinates. */ - public Object clone () - { - try { - return (Location)super.clone(); - } catch (CloneNotSupportedException cnse) { - throw new RuntimeException("Location.clone() failed " + cnse); - } - } + public int hashCode (); /** - * Location equality is determined by coordinates. + * Locations are cloneable. */ - public boolean equals (Object other) - { - if (other instanceof Location) { - Location oloc = (Location)other; - return (x == oloc.x) && (y == oloc.y); - } else { - return false; - } - } - - /** - * Location equivalence means that the coordinates and orientation are - * the same. - */ - public boolean equivalent (Location oloc) - { - return equals(oloc) && (orient == oloc.orient); - } - - /** - * Computes a reasonable hashcode for location instances. - */ - public int hashCode () - { - return x ^ y; - } + public Object clone (); } diff --git a/src/java/com/threerings/whirled/spot/data/Portal.java b/src/java/com/threerings/whirled/spot/data/Portal.java index 45b2bc33c..44b9ac860 100644 --- a/src/java/com/threerings/whirled/spot/data/Portal.java +++ b/src/java/com/threerings/whirled/spot/data/Portal.java @@ -22,7 +22,6 @@ package com.threerings.whirled.spot.data; import com.threerings.io.SimpleStreamableObject; -import com.threerings.util.DirectionUtil; /** * Represents an exit to another scene. A body sprite would walk over to a @@ -39,9 +38,8 @@ public class Portal extends SimpleStreamableObject /** This portal's unique identifier. */ public short portalId; - /** The location of the portal. Typically this is a base Location (2d) - * class, but different games could use a different subclass of - * Location. */ + /** The location of the portal. + * This field is present on client and server, it is streamed specially. */ public Location loc; /** The scene identifier of the scene to which a body will exit when @@ -70,9 +68,7 @@ public class Portal extends SimpleStreamableObject */ public Location getOppLocation () { - Location oppLoc = getLocation(); - oppLoc.orient = (byte) DirectionUtil.getOpposite(oppLoc.orient); - return oppLoc; + return loc.getOpposite(); } /** @@ -102,12 +98,8 @@ public class Portal extends SimpleStreamableObject */ public boolean equals (Object other) { - if (other instanceof Portal) { - Portal oport = (Portal)other; - return portalId == oport.portalId; - } else { - return false; - } + return (other instanceof Portal) && + ((Portal) other).portalId == portalId; } /** diff --git a/src/java/com/threerings/whirled/spot/data/SceneLocation.java b/src/java/com/threerings/whirled/spot/data/SceneLocation.java index e3d39c007..47aa3afec 100644 --- a/src/java/com/threerings/whirled/spot/data/SceneLocation.java +++ b/src/java/com/threerings/whirled/spot/data/SceneLocation.java @@ -21,33 +21,29 @@ package com.threerings.whirled.spot.data; +import com.threerings.io.SimpleStreamableObject; + import com.threerings.presents.dobj.DSet; /** * Extends {@link Location} with the data and functionality needed to * represent a particular user's location in a scene. */ -public class SceneLocation extends Location +public class SceneLocation extends SimpleStreamableObject implements DSet.Entry { /** The oid of the body that occupies this location. */ public int bodyOid; - /** - * Creates a scene location with the specified information. - */ - public SceneLocation (int x, int y, byte orient, int bodyOid) - { - super(x, y, orient); - this.bodyOid = bodyOid; - } + /** The actual location, which is interpreted by the display system. */ + public Location loc; /** * Creates a scene location with the specified information. */ public SceneLocation (Location loc, int bodyOid) { - super(loc.x, loc.y, loc.orient); + this.loc = loc; this.bodyOid = bodyOid; } @@ -67,6 +63,26 @@ public class SceneLocation extends Location return _key; } + // documentation inherited + public boolean equals (Object other) + { + // TEMP + if (other instanceof Location) { + Thread.dumpStack(); // this will help us find logic errors, + // as a SceneLocation and a Location shouldn't be compared + } + // END: temp + + return (other instanceof SceneLocation) && + this.loc.equals(((SceneLocation) other).loc); + } + + // documentation inherited + public int hashCode () + { + return loc.hashCode(); + } + /** Used for {@link #getKey}. */ protected transient Integer _key; } diff --git a/src/java/com/threerings/whirled/spot/tools/xml/SpotSceneRuleSet.java b/src/java/com/threerings/whirled/spot/tools/xml/SpotSceneRuleSet.java index ed4a7846b..eaa59811d 100644 --- a/src/java/com/threerings/whirled/spot/tools/xml/SpotSceneRuleSet.java +++ b/src/java/com/threerings/whirled/spot/tools/xml/SpotSceneRuleSet.java @@ -43,7 +43,7 @@ import com.threerings.whirled.spot.tools.EditablePortal; /** * Used to parse a {@link SpotSceneModel} from XML. */ -public class SpotSceneRuleSet implements NestableRuleSet +public abstract class SpotSceneRuleSet implements NestableRuleSet { // documentation inherited from interface public String getOuterElement () @@ -70,10 +70,7 @@ public class SpotSceneRuleSet implements NestableRuleSet * Create a new instance of the Location class that should be used * with Portals. */ - protected Location createNewLocation () - { - return new Location(); - } + protected abstract Location createLocation (); /** * A rule used to create the portal but also initialize the Location @@ -95,7 +92,7 @@ public class SpotSceneRuleSet implements NestableRuleSet // create the empty Location in the Portal Portal p = (Portal) digester.peek(); - p.loc = _ruleset.createNewLocation(); + p.loc = _ruleset.createLocation(); } protected SpotSceneRuleSet _ruleset;