// ----------------------------------------------------------------------------
//
// Loadbalancing Framework for Photon - Copyright (C) 2011 Exit Games GmbH
//
//
// This class resembles info about available rooms, as sent by the Master
// server's lobby. Consider all values as readonly.
//
// developer@photonengine.com
// ----------------------------------------------------------------------------
#if UNITY_4_7_OR_NEWER
#define UNITY
#endif
namespace ExitGames.Client.Photon.LoadBalancing
{
using System.Collections;
#if UNITY || NETFX_CORE
using Hashtable = ExitGames.Client.Photon.Hashtable;
using SupportClass = ExitGames.Client.Photon.SupportClass;
#endif
///
/// A simplified room with just the info required to list and join, used for the room listing in the lobby.
/// The properties are not settable (IsOpen, MaxPlayers, etc).
///
///
/// This class resembles info about available rooms, as sent by the Master server's lobby.
/// Consider all values as readonly. None are synced (only updated by events by server).
///
public class RoomInfo
{
/// Used internally in lobby, to mark rooms that are no longer listed (for being full, closed or hidden).
protected internal bool removedFromList;
/// Backing field for property.
private Hashtable customProperties = new Hashtable();
/// Backing field for property.
protected byte maxPlayers = 0;
/// Backing field for property.
protected string[] expectedUsers;
/// Backing field for property.
protected bool isOpen = true;
/// Backing field for property.
protected bool isVisible = true;
/// Backing field for property. False unless the GameProperty is set to true (else it's not sent).
protected bool autoCleanUp = true;
/// Backing field for property.
protected string name;
/// Backing field for master client id (actorNumber). defined by server in room props and ev leave.
protected internal int masterClientId;
/// Backing field for property.
protected string[] propertiesListedInLobby;
/// Read-only "cache" of custom properties of a room. Set via Room.SetCustomProperties (not available for RoomInfo class!).
/// All keys are string-typed and the values depend on the game/application.
///
public Hashtable CustomProperties
{
get
{
return this.customProperties;
}
}
/// The name of a room. Unique identifier for a room/match (per AppId + game-Version).
public string Name
{
get
{
return this.name;
}
}
///
/// Count of players currently in room. This property is overwritten by the Room class (used when you're in a Room).
///
public int PlayerCount { get; private set; }
///
/// State if the local client is already in the game or still going to join it on gameserver (in lobby: false).
///
public bool IsLocalClientInside { get; set; }
///
/// The limit of players for this room. This property is shown in lobby, too.
/// If the room is full (players count == maxplayers), joining this room will fail.
///
///
/// As part of RoomInfo this can't be set.
/// As part of a Room (which the player joined), the setter will update the server and all clients.
///
public byte MaxPlayers
{
get
{
return this.maxPlayers;
}
}
///
/// Defines if the room can be joined.
/// This does not affect listing in a lobby but joining the room will fail if not open.
/// If not open, the room is excluded from random matchmaking.
/// Due to racing conditions, found matches might become closed even while you join them.
/// Simply re-connect to master and find another.
/// Use property "IsVisible" to not list the room.
///
///
/// As part of RoomInfo this can't be set.
/// As part of a Room (which the player joined), the setter will update the server and all clients.
///
public bool IsOpen
{
get
{
return this.isOpen;
}
}
///
/// Defines if the room is listed in its lobby.
/// Rooms can be created invisible, or changed to invisible.
/// To change if a room can be joined, use property: open.
///
///
/// As part of RoomInfo this can't be set.
/// As part of a Room (which the player joined), the setter will update the server and all clients.
///
public bool IsVisible
{
get
{
return this.isVisible;
}
}
///
/// Constructs a RoomInfo to be used in room listings in lobby.
///
/// Name of the room and unique ID at the same time.
/// Properties for this room.
protected internal RoomInfo(string roomName, Hashtable roomProperties)
{
this.InternalCacheProperties(roomProperties);
this.name = roomName;
}
///
/// Makes RoomInfo comparable (by name).
///
public override bool Equals(object other)
{
RoomInfo otherRoomInfo = other as RoomInfo;
return (otherRoomInfo != null && this.Name.Equals(otherRoomInfo.name));
}
///
/// Accompanies Equals, using the name's HashCode as return.
///
///
public override int GetHashCode()
{
return this.name.GetHashCode();
}
/// Returns most interesting room values as string.
/// Summary of this RoomInfo instance.
public override string ToString()
{
return string.Format("Room: '{0}' {1},{2} {4}/{3} players.", this.name, this.isVisible ? "visible" : "hidden", this.isOpen ? "open" : "closed", this.maxPlayers, this.PlayerCount);
}
/// Returns most interesting room values as string, including custom properties.
/// Summary of this RoomInfo instance.
public string ToStringFull()
{
return string.Format("Room: '{0}' {1},{2} {4}/{3} players.\ncustomProps: {5}", this.name, this.isVisible ? "visible" : "hidden", this.isOpen ? "open" : "closed", this.maxPlayers, this.PlayerCount, this.customProperties.ToStringFull());
}
/// Copies "well known" properties to fields (IsVisible, etc) and caches the custom properties (string-keys only) in a local hashtable.
/// New or updated properties to store in this RoomInfo.
protected internal virtual void InternalCacheProperties(Hashtable propertiesToCache)
{
if (propertiesToCache == null || propertiesToCache.Count == 0 || this.customProperties.Equals(propertiesToCache))
{
return;
}
// check of this game was removed from the list. in that case, we don't
// need to read any further properties
// list updates will remove this game from the game listing
if (propertiesToCache.ContainsKey(GamePropertyKey.Removed))
{
this.removedFromList = (bool)propertiesToCache[GamePropertyKey.Removed];
if (this.removedFromList)
{
return;
}
}
// fetch the "well known" properties of the room, if available
if (propertiesToCache.ContainsKey(GamePropertyKey.MaxPlayers))
{
this.maxPlayers = (byte)propertiesToCache[GamePropertyKey.MaxPlayers];
}
if (propertiesToCache.ContainsKey(GamePropertyKey.IsOpen))
{
this.isOpen = (bool)propertiesToCache[GamePropertyKey.IsOpen];
}
if (propertiesToCache.ContainsKey(GamePropertyKey.IsVisible))
{
this.isVisible = (bool)propertiesToCache[GamePropertyKey.IsVisible];
}
if (propertiesToCache.ContainsKey(GamePropertyKey.PlayerCount))
{
this.PlayerCount = (int)((byte)propertiesToCache[GamePropertyKey.PlayerCount]);
}
if (propertiesToCache.ContainsKey(GamePropertyKey.CleanupCacheOnLeave))
{
this.autoCleanUp = (bool)propertiesToCache[GamePropertyKey.CleanupCacheOnLeave];
}
if (propertiesToCache.ContainsKey(GamePropertyKey.MasterClientId))
{
this.masterClientId = (int)propertiesToCache[GamePropertyKey.MasterClientId];
}
if (propertiesToCache.ContainsKey(GamePropertyKey.PropsListedInLobby))
{
this.propertiesListedInLobby = propertiesToCache[GamePropertyKey.PropsListedInLobby] as string[];
}
if (propertiesToCache.ContainsKey((byte)GamePropertyKey.ExpectedUsers))
{
this.expectedUsers = (string[])propertiesToCache[GamePropertyKey.ExpectedUsers];
}
// merge the custom properties (from your application) to the cache (only string-typed keys will be kept)
this.customProperties.MergeStringKeys(propertiesToCache);
this.customProperties.StripKeysWithNullValues();
}
}
}