- Код: Выделить всё
using System;
using System.Collections;
using System.Collections.Generic;
using ExitGames.Client.Photon;
public class Game : IPhotonPeerListener
{
#region Members
public string RoomName = "";
public bool useTcp = false;
public string ipPort = "77.122.221.253:5055";
public static readonly string LobbyName = "Bootcamp_lobby"; // also used in all other realtime demos
public static readonly string RoomNamePrefix = "Bootcamp Default";
public static readonly string AppName = "LiteLobby";
public int RoomNumber = Environment.TickCount % 2;
public LitePeer peer;
public Dictionary<int, Player> Players;
public Player LocalPlayer;
public PlayerLocal PlayerLocal;
public ChatScreen chatScreen;
public delegate void DebugOutputDelegate(string debug);
public DebugOutputDelegate DebugListeners;
private readonly usePhoton usePhoton;
#endregion
#region Constructor and Gameloop
public Game(DebugOutputDelegate debugDelegate, usePhoton photon)
{
this.usePhoton = photon;
this.DebugListeners = debugDelegate;
}
/// <summary>
/// Update must be called by a gameloop (a single thread), so it can handle
/// automatic movement and networking.
/// </summary>
public void Update()
{
this.Service();
}
#endregion
#region IPhotonPeerListener Members
// This is the callback for the Photon library's debug output
public void DebugReturn(DebugLevel level, string debug)
{
this.DebugListeners(debug); // This demo simply ignores the debug level
}
// Photon library callback for state changes (connect, disconnect, etc.)
// Processed within PhotonPeer.DispatchIncomingCommands()!
public void PeerStatusCallback(StatusCode returnCode)
{
this.DebugReturn("nPeerReturn():" + returnCode);
// handle returnCodes for connect, disconnect and errors (non-operations)
switch (returnCode)
{
case StatusCode.Connect:
this.DebugReturn("Connect(ed)");
//this.JoinRandomWithLobby();
break;
case StatusCode.Disconnect:
this.DebugReturn("Disconnect(ed) peer.state: " + this.peer.PeerState);
this.LocalPlayer.playerID = 0;
this.Players.Clear();
break;
case StatusCode.ExceptionOnConnect:
this.DebugReturn("Exception_Connect(ed) peer.state: " + this.peer.PeerState);
this.LocalPlayer.playerID = 0;
this.Players.Clear();
break;
case StatusCode.Exception:
this.DebugReturn("Exception peer.state: " + this.peer.PeerState);
this.Players.Clear();
this.LocalPlayer.playerID = 0;
break;
case StatusCode.SendError:
this.DebugReturn("SendError! peer.state: " + this.peer.PeerState);
this.Players.Clear();
this.LocalPlayer.playerID = 0;
break;
default:
this.DebugReturn("PeerStatusCallback: " + returnCode);
break;
}
}
// Photon library callback to get us operation results (if our operation was executed server-side)
// Only called for reliable commands! Anything sent unreliable will not produce a result.
// Processed within PhotonPeer.DispatchIncomingCommands()!
public void OperationResult(byte opCode, int returnCode, Hashtable returnValues, short invocID)
{
if (opCode != (byte)LiteOpCode.RaiseEvent)
{
this.DebugReturn("nPeerReturn() " + opCode + "/" + returnCode);
}
// handle operation returns (aside from "join", this demo does not watch for returns)
switch (opCode)
{
case (byte)LiteOpCode.Join:
{
// get the local player's numer from the returnvalues, get the player from the list and colorize it:
int actorNrReturnedForOpJoin = (int)returnValues[(byte)LiteOpKey.ActorNr];
this.LocalPlayer.playerID = actorNrReturnedForOpJoin;
foreach (Player oldPlayer in this.Players.Values)
{
if (oldPlayer.PlayerIsLocal == false)
{
usePhoton.RemoveRemotePlayer(oldPlayer);
}
}
this.Players.Clear();
this.LocalPlayer.PlayerIsLocal = true;
this.Players.Add(actorNrReturnedForOpJoin, this.LocalPlayer);
this.DebugReturn("[LocalPlayer] " + this.LocalPlayer.name);
foreach (DictionaryEntry actor in returnValues)
{
this.DebugReturn(actor.Key.ToString());
}
Hashtable actors = (Hashtable)returnValues[(byte)14];
if (actors == null) break;
foreach (DictionaryEntry actor in actors)
{
int i = (int)actor.Key;
if (i == actorNrReturnedForOpJoin) continue;
Player pl = new Player(i);
usePhoton.AddRemotePlayer(pl);
pl.playerRemote.SetProperties((Hashtable)actor.Value);
this.Players.Add(i, pl);
}
break;
}
}
}
// Called by Photon lib for each incoming event (player- and position-data in this demo, as well as joins and leaves).
// Processed within PhotonPeer.DispatchIncomingCommands()!
public void EventAction(byte eventCode, Hashtable photonEvent)
{
if (eventCode != Constants.EV_MOVE)
{
this.DebugReturn("EventAction() " + eventCode);
}
int actorNr = (int)photonEvent[(byte)LiteEventKey.ActorNr];
// get the player that raised this event
Player p;
this.Players.TryGetValue(actorNr, out p);
switch (eventCode)
{
case (byte)LiteEventCode.Join:
int actor =(int)photonEvent[(byte)LiteEventKey.ActorNr];
if (actor != this.LocalPlayer.playerID)
{
var remote = new Player(actor);
usePhoton.AddRemotePlayer(remote);
Hashtable properties = (Hashtable)photonEvent[(byte)14];
remote.playerRemote.SetProperties(properties);
this.Players.Add(actor, remote);
}
// get the list of current players and check it against local list - create any that's not yet there
this.PrintPlayers();
break;
case (byte)LiteEventCode.Leave:
this.Players.Remove(actorNr);
usePhoton.RemoveRemotePlayer(p);
break;
case (byte)LiteEventCode.SetProperties:
Hashtable properties = (Hashtable)photonEvent[(byte)LiteEventKey.Properties];
p.playerRemote.SetProperties(properties);
break;
case Constants.EV_HIT:
DebugReturn("actorNR " + actorNr + " _p.playerRemote.Name_ " + p.playerRemote.Name);
Hashtable data = (Hashtable)photonEvent[(byte)LiteEventKey.Data];
int target = (int)data["T"];
if (target == LocalPlayer.playerID)
{
switch ((byte)data["H"])
{
case 0:
PlayerLocal.DownLifeHitSoldier(p.playerRemote.Name);
break;
case 1:
PlayerLocal.DownLifeHitSoldierGranade(p.playerRemote.Name);
break;
}
}
break;
case Constants.EV_MOVE:
p.playerRemote.SetPosition((Hashtable)photonEvent[(byte)LiteEventKey.Data]);
break;
case Constants.EV_ANIM:
p.playerRemote.SetAnim((Hashtable)photonEvent[(byte)LiteEventKey.Data]);
break;
case Constants.EV_FRAG:
p.playerRemote.Dead = true;
p.playerRemote.SetSpawnPosition((Hashtable)photonEvent[(byte)LiteEventKey.Data]);
break;
case Constants.EV_FIRE:
p.playerRemote.SetFire((Hashtable)photonEvent[(byte)LiteEventKey.Data]);
break;
case Constants.EV_CHAT:
chatScreen.IncomingMessage((Hashtable)photonEvent[(byte)LiteEventKey.Data]);
break;
}
}
#endregion
#region Game Handling
// Here the connection to Photon is established (if not already connected).
public bool Connect()
{
if (this.peer == null)
{
this.peer = new LitePeer(this, this.useTcp);
}
else if (this.peer.PeerState != (byte)PeerStateValue.Disconnected)
{
this.DebugReturn("already connected! disconnect first.");
return false;
}
// The amount of debugging/logging from the Photon library can be set this way:
this.peer.DebugOut = DebugLevel.ERROR;
try
{
if (!this.peer.Connect(this.ipPort, AppName))
{
this.DebugReturn("not connected");
return false;
}
}
catch (System.Security.SecurityException ex)
{
// Unity 3.0 requires a policy file for webplayer-builds. Currently, the security
// exception that's thrown is not translated into a returnCode / callback for Connect().
this.DebugReturn("Security Exception (check policy file): " + ex);
}
this.Players = new Dictionary<int, Player>();
this.LocalPlayer = new Player(0);
return true;
}
// new for lobby sample: joins a room/game and attachs it to a lobby
public void JoinToLobby(string _roomName)
{
RoomName = _roomName;
// if this client is in a game already, it is now outdated: clean list of players and local actor number
foreach (Player oldPlayer in this.Players.Values)
{
if (oldPlayer.PlayerIsLocal == false)
{
usePhoton.RemoveRemotePlayer(oldPlayer);
}
}
this.Players.Clear();
this.LocalPlayer.playerID = 0;
// the LiteLobby application defines an (optional) parameter "lobby", which is given key (byte)5
Hashtable operationParameters = new Hashtable();
operationParameters.Add((byte)4, RoomName); // joins the random room
operationParameters.Add((byte)5, LobbyName); // sets a lobby for this game
if (!this.usePhoton.Player.gameObject.GetComponent<PlayerLocal>())
{
// create a player Transform instance
this.PlayerLocal = this.usePhoton.Player.gameObject.AddComponent<PlayerLocal>();
this.PlayerLocal.Initialize(this);
this.PlayerLocal.name += this.LocalPlayer.playerID;
this.chatScreen = this.usePhoton.chatScreen;
this.chatScreen.NameSender = this.LocalPlayer.name;
}
Hashtable properties = this.PlayerLocal.GetProperties();
operationParameters.Add((byte)14, properties);
operationParameters.Add((byte)13, true);
this.peer.OpCustom((byte)LiteOpCode.Join, operationParameters, true);
this.chatScreen.Initialize(this);
}
// Disconnect from the server.
internal void Disconnect()
{
if (this.peer != null)
{
this.peer.Disconnect(); //this will dump all prepared outgoing data and immediately send a "disconnect"
}
}
public void Service()
{
this.peer.Service();
}
// Simple "help" function to print current list of players.
// As this function uses the players list, make sure it's not called while
// peer.DispatchIncomingCommands() might modify the list!! (e.g. by lock(this))
public void PrintPlayers()
{
string players = "Players: ";
foreach (Player p in this.Players.Values)
{
players += p.ToString() + ", ";
}
this.DebugReturn(players);
}
// This is only used by the game / application, not by the Photon library
public void DebugReturn(string debug)
{
this.DebugListeners(debug);
}
#endregion
}