// // $Id: Table.java,v 1.16 2003/03/27 23:45:04 mdb Exp $ package com.threerings.parlor.data; import com.samskivert.util.StringUtil; import com.threerings.presents.dobj.DSet; import com.threerings.parlor.data.ParlorCodes; import com.threerings.parlor.game.GameConfig; /** * This class represents a table that is being used to matchmake a game by * the Parlor services. */ public class Table implements DSet.Entry, ParlorCodes { /** The unique identifier for this table. */ public Integer tableId; /** The object id of the lobby object with which this table is * associated. */ public int lobbyOid; /** The oid of the game that was created from this table or -1 if the * table is still in matchmaking mode. */ public int gameOid = -1; /** An array of the usernames of the occupants of this table (some * slots may not be filled). */ public String[] occupants; /** The body oids of the occupants of this table. (This is not * propagated to remote instances.) */ public transient int[] bodyOids; /** The game config for the game that is being matchmade. This config * instance will also implement {@link TableConfig}. */ public GameConfig config; /** * Creates a new table instance, and assigns it the next monotonically * increasing table id. The supplied config instance must implement * {@link TableConfig} or a ClassCastException will be * thrown. * * @param lobbyOid the object id of the lobby in which this table is * to live. * @param config the configuration of the game being matchmade by this * table. */ public Table (int lobbyOid, GameConfig config) { // assign a unique table id tableId = new Integer(++_tableIdCounter); // keep track of our lobby oid this.lobbyOid = lobbyOid; // keep a casted reference around _tconfig = (TableConfig)config; this.config = config; // make room for the maximum number of players occupants = new String[_tconfig.getMaximumPlayers()]; bodyOids = new int[occupants.length]; } /** * Constructs a blank table instance, suitable for unserialization. */ public Table () { } /** * A convenience function for accessing the table id as an int. */ public int getTableId () { return tableId.intValue(); } /** * Once a table is ready to play (see {@link #mayBeStarted} and {@link * #shouldBeStarted}), the players array can be fetched using this * method. It will return an array containing the usernames of all of * the players in the game, sized properly and with each player in the * appropriate position. */ public String[] getPlayers () { // count up the players int pcount = 0; for (int i = 0; i < occupants.length; i++) { if (!StringUtil.blank(occupants[i])) { pcount++; } } // create and populate the players array String[] players = new String[pcount]; pcount = 0; for (int i = 0; i < occupants.length; i++) { if (!StringUtil.blank(occupants[i])) { players[pcount++] = occupants[i]; } } return players; } /** * Requests to seat the specified user at the specified position in * this table. * * @param position the position in which to seat the user. * @param username the username of the user to be set. * @param bodyOid the body object id of the user to be set. * * @return null if the user was successfully seated, a string error * code explaining the failure if the user was not able to be seated * at that position. */ public String setOccupant (int position, String username, int bodyOid) { // find out how many positions we have for occupation int maxpos = _tconfig.getDesiredPlayers(); // if there is no desired number of players, use the max if (maxpos == -1) { maxpos = _tconfig.getMaximumPlayers(); } // make sure the requested position is a valid one if (position >= maxpos) { return INVALID_TABLE_POSITION; } // make sure the requested position is not already occupied if (!StringUtil.blank(occupants[position])) { return TABLE_POSITION_OCCUPIED; } // otherwise all is well, stick 'em in occupants[position] = username; bodyOids[position] = bodyOid; return null; } /** * Requests that the specified user be removed from their seat at this * table. * * @return true if the user was seated at the table and has now been * removed, false if the user was never seated at the table in the * first place. */ public boolean clearOccupant (String username) { for (int i = 0; i < occupants.length; i++) { if (username.equals(occupants[i])) { occupants[i] = ""; bodyOids[i] = 0; return true; } } return false; } /** * Requests that the user identified by the specified body object id * be removed from their seat at this table. * * @return true if the user was seated at the table and has now been * removed, false if the user was never seated at the table in the * first place. */ public boolean clearOccupant (int bodyOid) { for (int i = 0; i < bodyOids.length; i++) { if (bodyOid == bodyOids[i]) { occupants[i] = ""; bodyOids[i] = 0; return true; } } return false; } /** * Returns true if this table has a sufficient number of occupants * that the game can be started. */ public boolean mayBeStarted () { // make sure at least the minimum number of players are here int want = _tconfig.getMinimumPlayers(), have = 0; for (int i = 0; i < occupants.length; i++) { if (!StringUtil.blank(occupants[i])) { if (++have == want) { return true; } } } return false; } /** * Returns true if sufficient seats are occupied that the game should * be automatically started. */ public boolean shouldBeStarted () { int need = _tconfig.getDesiredPlayers(); if (need == -1) { need = _tconfig.getMaximumPlayers(); } for (int i = 0; i < occupants.length; i++) { if (StringUtil.blank(occupants[i])) { if (--need == 0) { return true; } } } return false; } /** * Returns true if there is no one sitting at this table. */ public boolean isEmpty () { for (int i = 0; i < occupants.length; i++) { if (!StringUtil.blank(occupants[i])) { return false; } } return true; } /** * Returns true if this table is in play, false if it is still being * matchmade. */ public boolean inPlay () { return gameOid != -1; } // documentation inherited public Comparable getKey () { return tableId; } /** * Returns true if this table is equal to the supplied object (which * must be a table with the same table id). */ public boolean equals (Object other) { if (other != null && other instanceof Table) { return ((Table)other).tableId.equals(tableId); } else { return false; } } /** * Generates a string representation of this table instance. */ public String toString () { return "[tableId=" + tableId + ", lobbyOid=" + lobbyOid + ", gameOid=" + gameOid + ", occupants=" + StringUtil.toString(occupants) + ", bodyOids=" + StringUtil.toString(bodyOids) + ", config=" + config + "]"; } /** A casted reference of our game config object. */ protected transient TableConfig _tconfig; /** A counter for assigning table ids. */ protected static int _tableIdCounter = 0; }