private void HandleErrorHttpRespone(PeerBase peer, byte operationCode, HttpRequestQueueResultCode result, AsyncHttpRequest request, string requestUri) { string msg; if (request != null) { msg = string.Format( "webRpc request to address '{0}' failed. HttpQueueResult:{3}, WebStatus:{1}, Exception :{2}", requestUri, request.WebStatus, request.Exception == null ? "(null)" : request.Exception.ToString(), result); } else { msg = string.Format("webRpc request to address '{0}' failed. HttpQueueResult:{1}", requestUri, result); } this.SendErrorResponse(peer, operationCode, new SendParameters(), msg: msg); if (result == HttpRequestQueueResultCode.QueueFull) { Log.Debug(msg); } else { Log.Error(msg); } }
public bool HandleCall(PeerBase peer, string userId, OperationRequest request, object authResultsSecure, SendParameters sp) { var rpcRequest = new WebRpcRequest(peer.Protocol, request); if (!rpcRequest.IsValid) { var msg = string.Format("Invalid RPC request format: {0}", rpcRequest.GetErrorMessage()); Log.Error(msg); this.SendErrorResponse(peer, request.OperationCode, sp, (short)ErrorCode.OperationInvalid, msg); return(false); } try { var data = this.SerializeRequest(rpcRequest, userId, authResultsSecure); var uri = this.MakeRequestUri(rpcRequest); return(this.SendHttpRequest(peer, uri, data, rpcRequest)); } catch (Exception e) { var msg = string.Format("Exception during RPC request handling {0}", e); Log.Error(msg); this.SendErrorResponse(peer, request.OperationCode, sp, msg: msg); } return(true); }
private bool SendHttpRequest(PeerBase peer, string uri, string data, WebRpcRequest rpcRequest) { var binData = Encoding.UTF8.GetBytes(data); HttpRequestQueueCallback callback = (result, request, state) => this.HandleHttpResponse(peer, rpcRequest.OperationRequest.OperationCode, result, rpcRequest, request, uri); var webRequest = (HttpWebRequest)WebRequest.Create(uri); webRequest.Proxy = null; webRequest.Method = "POST"; webRequest.ContentType = "application/json"; webRequest.Accept = "application/json"; webRequest.Timeout = this.httpRequestTimeout; if (Log.IsDebugEnabled) { Log.DebugFormat("WebRpc request {0}:{1}", uri, data); } this.httpRequestQueue.Enqueue(webRequest, binData, callback, null); return(true); }
public void OnDisconnectByOtherPeer(PeerBase peer) { this.ExitWorld(); peer.RequestFiber.Enqueue(() => peer.RequestFiber.Enqueue(peer.Disconnect)); CL.Out(LogFilter.PLAYER, "Player {0} disconnected by other peer".f(name)); }
/// <summary> /// Initializes a new instance of the <see cref = "ClientInterestArea" /> class. /// </summary> /// <param name = "peer"> /// The peer. /// </param> /// <param name = "id"> /// The id for this interest area. /// Unique per <see cref = "Actor" />. /// </param> /// <param name = "world"> /// The <see cref = "IWorld" /> this interest area is watching. /// </param> /// <param name = "fiber"> /// The fiber this intereast receives events on. /// </param> public ClientInterestArea(PeerBase peer, byte id, IWorld world, IFiber fiber) : base(id, world) { this.peer = peer; this.eventChannelSubscriptions = new Dictionary <Item, IDisposable>(); this.fiber = fiber; }
protected MmoActor(PeerBase peer, World world) { this.peer = peer; this.world = world; this.interestAreas = new Dictionary <byte, InterestArea>(); this.interestItems = new InterestItems(peer); }
/// <summary> /// Initializes a new instance of the <see cref = "ClientInterestArea" /> class. /// </summary> /// <param name = "peer"> /// The peer. /// </param> /// <param name = "id"> /// The id for this interest area. /// Unique per <see cref = "Actor" />. /// </param> /// <param name = "world"> /// The <see cref = "IWorld" /> this interest area is watching. /// </param> /// <param name = "fiber"> /// The fiber this intereast receives events on. /// </param> public ClientInterestArea(PeerBase peer, byte id, IWorld world, IFiber fiber) : base(id, world) { this.peer = peer; this.eventChannelSubscriptions = new Dictionary<Item, IDisposable>(); this.fiber = fiber; }
/// <summary> /// Initializes a new instance of the <see cref="RoomReference"/> class. /// </summary> /// <param name="roomCache"> /// The room cache. /// </param> /// <param name="room"> /// The room. /// </param> public RoomReference(RoomCacheBase roomCache, Room room, PeerBase ownerPeer) { this.roomCache = roomCache; this.id = Guid.NewGuid(); this.Room = room; this.ownerPeer = ownerPeer; }
/// <summary> /// Initializes a new instance of the <see cref = "Actor" /> class. /// </summary> /// <param name = "peer"> /// The owner peer. /// </param> /// <param name = "world"> /// The world. /// </param> protected Actor(PeerBase peer, IWorld world) { this.peer = peer; this.world = world; this.ownedItems = new Dictionary<byte, Dictionary<string, Item>>(); this.interestAreas = new Dictionary<byte, InterestArea>(); }
/// <summary> /// Handles operation SetViewDistance: Changes the subscribe and unsubscribe radius for an InterestArea. /// </summary> public OperationResponse OperationSetViewDistance(PeerBase peer, OperationRequest request) { var operation = new SetViewDistance(peer.Protocol, request); if (!operation.IsValid) { return(new OperationResponse(request.OperationCode) { ReturnCode = (int)ReturnCode.InvalidOperationParameter, DebugMessage = operation.GetErrorMessage() }); } operation.OnStart(); InterestArea interestArea; if (this.TryGetInterestArea(operation.InterestAreaId, out interestArea) == false) { return(operation.GetOperationResponse((int)ReturnCode.InterestAreaNotFound, "InterestAreaNotFound")); } lock (interestArea.SyncRoot) { interestArea.ViewDistanceEnter = operation.ViewDistanceEnter; interestArea.ViewDistanceExit = operation.ViewDistanceExit; interestArea.UpdateInterestManagement(); } // don't send response return(null); }
/// <summary> /// Handles operation SetProperties: Sets the Item.Properties of an Item and ultimately sends event ItemPropertiesSet to other clients. /// </summary> public OperationResponse OperationSetProperties(PeerBase peer, OperationRequest request, SendParameters sendParameters) { var operation = new SetProperties(peer.Protocol, request); if (!operation.IsValid) { return(new OperationResponse(request.OperationCode) { ReturnCode = (int)ReturnCode.InvalidOperationParameter, DebugMessage = operation.GetErrorMessage() }); } operation.OnStart(); Item item; if (string.IsNullOrEmpty(operation.ItemId)) { item = this.Avatar; // set return values operation.ItemId = item.Id; } else if (this.TryGetItem(operation.ItemId, out item) == false) { return(operation.GetOperationResponse((int)ReturnCode.ItemNotFound, "ItemNotFound")); } return(this.ItemOperationSetProperties(item, operation, sendParameters)); }
protected override OperationResponse OnOperationRequest(PeerBase peer, OperationRequest operationRequest, SendParameters sendParameters) { Dictionary <byte, object> dict = operationRequest.Parameters; foreach (object value in dict.Values) { MasterApplication.log.Info("============OperationHandlerInitial==========:" + value.ToString()); } switch (operationRequest.OperationCode) { default: return(HandleUnknownOperationCode(operationRequest, log)); case (byte)OperationCode.Authenticate: return(((MasterClientPeer)peer).HandleAuthenticate(operationRequest, sendParameters)); case (byte)OperationCode.CreateGame: case (byte)OperationCode.JoinGame: case (byte)OperationCode.JoinLobby: case (byte)OperationCode.JoinRandomGame: case (byte)OperationCode.FindFriends: case (byte)OperationCode.LobbyStats: case (byte)OperationCode.LeaveLobby: case (byte)OperationCode.DebugGame: case (byte)OperationCode.Rpc: case (byte)OperationCode.Settings: case (byte)OperationCode.GetGameList: return(new OperationResponse(operationRequest.OperationCode) { ReturnCode = (int)Photon.Common.ErrorCode.OperationDenied, DebugMessage = LBErrorMessages.NotAuthorized }); } }
public void Dispose() { CloseConnection(); Peer = null; ServerTransport = null; ConnectionId = ""; }
public Subscription AddSubscription(PeerBase peer, int gameCount) { if (log.IsDebugEnabled) { log.DebugFormat("New Subscription: pid={0}, gc={1}, props={2}", peer.ConnectionId, gameCount, this.propertyString); } if (gameCount < 0) { gameCount = 0; } var subscription = new Subscription(this, peer, gameCount); HashSet<PeerBase> hashSet; if (this.subscriptions.TryGetValue(gameCount, out hashSet) == false) { if (log.IsDebugEnabled) { log.DebugFormat("Creating new hashset for game count = {0}", gameCount); } hashSet = new HashSet<PeerBase>(); this.subscriptions.Add(gameCount, hashSet); } hashSet.Add(peer); return subscription; }
protected MmoActor(PeerBase peer, World world) { this.peer = peer; this.world = world; this.interestAreas = new Dictionary<byte, InterestArea>(); this.interestItems = new InterestItems(peer); }
public void PeerDisconnected(PeerBase peer) { lock (Connections) { Connections.Remove(peer); } }
public void PeerConnected(PeerBase peer) { lock(Connections) { Connections.Add(peer); } }
/// <summary> /// Handles operation SpawnItem: Creates a new Item and optionally subscribes an InterestArea to it. /// </summary> public OperationResponse OperationSpawnItem(PeerBase peer, OperationRequest request) { log.InfoFormat("Spawn item operation started for peer: {0}", this.Peer.ToString()); var operation = new SpawnItem(peer.Protocol, request); if (!operation.IsValid) { log.InfoFormat("Spawn item operation invalid"); return(new OperationResponse(request.OperationCode) { ReturnCode = (int)ReturnCode.InvalidOperationParameter, DebugMessage = operation.GetErrorMessage() }); } operation.OnStart(); var item = new Item(operation.Position, operation.Rotation, operation.Properties, this, operation.ItemId, operation.ItemType, this.World); if (this.World.ItemCache.AddItem(item)) { log.InfoFormat("adding item"); this.AddItem(item); return(this.ItemOperationSpawn(item, operation)); } log.InfoFormat("Spawn item operation for peer: {0}", this.Peer.ToString()); item.Dispose(); return(operation.GetOperationResponse((int)ReturnCode.ItemAlreadyExists, "ItemAlreadyExists")); }
public void removeClientPeer(PeerBase peer) { aclient_peer.Remove(peer); // remove from game's player list? agame_scene[cur_game].removeClient((STServerPeer)peer); }
/// <summary> /// Initializes a new instance of the <see cref="RoomReference"/> class. /// </summary> /// <param name="roomCache"> /// The room cache. /// </param> /// <param name="room"> /// The room. /// </param> /// <param name="ownerPeer"> /// An <see cref="PeerBase"/> instance which obtained the room reference. /// </param> public RoomReference(RoomCacheBase roomCache, Room room, PeerBase ownerPeer) { this.roomCache = roomCache; this.id = Guid.NewGuid(); this.Room = room; this.ownerPeer = ownerPeer; }
public RoomReference(RoomCacheBase roomCache, Room room, PeerBase ownerPeer) { _roomCache = roomCache; Id = Guid.NewGuid(); Room = room; OwnerPeer = ownerPeer; }
public void PeerConnected(PeerBase peer) { lock ( Connections ) { Connections.Add(peer); } }
/// <summary> /// Initializes a new instance of the <see cref = "Actor" /> class. /// </summary> /// <param name = "peer"> /// The owner peer. /// </param> /// <param name = "world"> /// The world. /// </param> protected Actor(PeerBase peer, IWorld world) { this.peer = peer; this.world = world; this.ownedItems = new Dictionary <byte, Dictionary <string, Item> >(); this.interestAreas = new Dictionary <byte, InterestArea>(); }
public OperationResponse OnOperationRequest(PeerBase peer, OperationRequest operationRequest, SendParameters sendParameters) { switch ((OperationCode)operationRequest.OperationCode) { case OperationCode.EnterWorld: return(DefaultResponses.CreateNegativeResponse(operationRequest, ReturnCode.OperationNotAllowed)); case OperationCode.Move: return(OperationMove(peer, operationRequest)); case OperationCode.CharacterAction: return(OperationCharacterAction(peer, operationRequest)); case OperationCode.StartAiLoop: AILooper.Instance.Start(); return(null); case OperationCode.ToggleAiLoop: AILooper.Instance.ToggleLoop(); return(null); default: return(DefaultResponses.CreateNegativeResponse(operationRequest, ReturnCode.OperationNotSupported)); } }
public void RemoveSubscriber(PeerBase subscriber) { using (Lock.TryEnter(this.Subscribers, 10000)) { this.Subscribers.Remove(subscriber); } }
public override OperationResponse OnOperationRequest(PeerBase peer, OperationRequest operationRequest, SendParameters sendParameters) { switch (operationRequest.OperationCode) { default: return(HandleUnknownOperationCode(operationRequest, log)); case (byte)OperationCode.Authenticate: return(new OperationResponse(operationRequest.OperationCode) { ReturnCode = (short)ErrorCode.OperationDenied, DebugMessage = LBErrorMessages.Authenticating }); case (byte)OperationCode.CreateGame: case (byte)OperationCode.JoinGame: case (byte)OperationCode.JoinLobby: case (byte)OperationCode.JoinRandomGame: case (byte)OperationCode.LeaveLobby: case (byte)OperationCode.DebugGame: case (byte)OperationCode.FindFriends: case (byte)OperationCode.LobbyStats: return(new OperationResponse(operationRequest.OperationCode) { ReturnCode = (short)ErrorCode.OperationDenied, DebugMessage = LBErrorMessages.NotAuthorized, }); } }
public void AddSubscriber(PeerBase subscriber) { using (Lock.TryEnter(this.Subscribers, 10000)) { this.Subscribers.Add(subscriber); } }
public virtual IGameListSubscription AddSubscription(PeerBase peer, Hashtable gamePropertyFilter, int maxGameCount) { var subscribtion = new Subscribtion(this, maxGameCount); this.peers.Add(peer); return(subscribtion); }
public void PeerDisconnected(PeerBase peer) { lock ( Connections ) { Connections.Remove(peer); } }
/// <summary> /// Adds a reference to the room instance. /// </summary> /// <param name="ownerPeer"> /// The peer that holds this reference. /// </param> /// <returns> /// a new <see cref="RoomReference"/> /// </returns> public RoomReference AddReference(PeerBase ownerPeer) { var reference = new RoomReference(this.roomFactory, this.Room, ownerPeer); this.references.Add(reference.Id, reference); if (log.IsDebugEnabled) { log.DebugFormat( "Created room instance reference: roomName={0}, referenceCount={1}", this.Room.Name, this.ReferenceCount); } if (this.logQueue.Log.IsDebugEnabled) { this.logQueue.Add( new LogEntry( "AddReference", string.Format( "RoomName={0}, ReferenceCount={1}, OwnerPeer={2}", this.Room.Name, this.ReferenceCount, ownerPeer))); } return(reference); }
/// <summary> /// Handles operation RemoveInterestArea: Removes one of the actor's InterestAreas. /// </summary> public OperationResponse OperationRemoveInterestArea(PeerBase peer, OperationRequest request) { var operation = new RemoveInterestArea(peer.Protocol, request); if (!operation.IsValid) { return(new OperationResponse(request.OperationCode) { ReturnCode = (int)ReturnCode.InvalidOperationParameter, DebugMessage = operation.GetErrorMessage() }); } operation.OnStart(); InterestArea interestArea; if (this.TryGetInterestArea(operation.InterestAreaId, out interestArea)) { lock (interestArea.SyncRoot) { interestArea.Detach(); interestArea.Dispose(); } this.RemoveInterestArea(operation.InterestAreaId); return(operation.GetOperationResponse(MethodReturnValue.Ok)); } return(operation.GetOperationResponse((int)ReturnCode.InterestAreaNotFound, "InterestAreaNotFound")); }
public Subscription AddSubscription(PeerBase peer, int gameCount) { if (log.IsDebugEnabled) { log.DebugFormat("New Subscription: pid={0}, gc={1}, props={2}", peer.ConnectionId, gameCount, this.propertyString); } if (gameCount < 0) { gameCount = 0; } var subscription = new Subscription(this, peer, gameCount); HashSet <PeerBase> hashSet; if (this.subscriptions.TryGetValue(gameCount, out hashSet) == false) { if (log.IsDebugEnabled) { log.DebugFormat("Creating new hashset for game count = {0}", gameCount); } hashSet = new HashSet <PeerBase>(); this.subscriptions.Add(gameCount, hashSet); } hashSet.Add(peer); return(subscription); }
public OperationResponse OnOperationRequest(PeerBase peer, OperationRequest operationRequest, SendParameters sendParameters) { switch ((OperationCode)operationRequest.OperationCode) { case OperationCode.CreateWorld: { return(this.OperationCreateWorld(peer, operationRequest)); } case OperationCode.EnterWorld: { return(this.OperationEnterWorld(peer, operationRequest, sendParameters)); } case OperationCode.SubscribeCounter: { return(CounterOperations.SubscribeCounter(peer, operationRequest)); } case OperationCode.UnsubscribeCounter: { return(CounterOperations.UnsubscribeCounter(peer, operationRequest)); } case OperationCode.ExecAction: { return(this.ExecAction(peer, operationRequest, sendParameters)); } default: { return(InvalidOperation(operationRequest)); } } }
public void OnDisconnect(PeerBase peer) { if (m_Peer.Name != null) { World.Instance.RemoveEntity(m_Peer.Name); } peer.Dispose(); }
private void PublishStatisticEvent(PeerBase peer) { var lobbyList = this.lobbyFactory.GetLobbies(this.maxLobbyStatsCount); var lobbyStats = LobbyListToLobbyStatsData(lobbyList); var eventData = new EventData((byte)EventCode.LobbyStats, lobbyStats); peer.SendEvent(eventData, new SendParameters()); }
public bool TransitDisposeConnected(PeerBase peer) { if (peer.TransitConnectionState(DisposeDisconnecting.Instance, this)) { return(false); } return(peer.ConnectionStateImpl.TransitDisposeConnected(peer)); }
/// <summary> /// Handles operation AttachInterestArea: Attaches an existing InterestArea to an existing Item. /// </summary> public OperationResponse OperationAttachInterestArea(PeerBase peer, OperationRequest request, SendParameters sendParameters) { var operation = new AttachInterestArea(peer.Protocol, request); if (!operation.IsValid) { return(new OperationResponse(request.OperationCode) { ReturnCode = (int)ReturnCode.InvalidOperationParameter, DebugMessage = operation.GetErrorMessage() }); } operation.OnStart(); InterestArea interestArea; if (this.TryGetInterestArea(operation.InterestAreaId, out interestArea) == false) { return(operation.GetOperationResponse((int)ReturnCode.InterestAreaNotFound, "InterestAreaNotFound")); } Item item; bool actorItem; if (string.IsNullOrEmpty(operation.ItemId)) { item = this.Avatar; actorItem = true; // set return vaues operation.ItemId = item.Id; } else { actorItem = this.TryGetItem(operation.ItemId, out item); } if (actorItem) { // we are already in the item thread, invoke directly return(this.ItemOperationAttachInterestArea(item, operation, interestArea, sendParameters)); } else { // search world cache just to see if item exists at all if (this.World.ItemCache.TryGetItem(operation.ItemId, out item) == false) { return(operation.GetOperationResponse((int)ReturnCode.ItemNotFound, "ItemNotFound")); } else { // second parameter (peer) allows us to send an error event to the client (in case of an error) item.Fiber.Enqueue(() => this.ExecItemOperation(() => this.ItemOperationAttachInterestArea(item, operation, interestArea, sendParameters), sendParameters)); // response is sent later return(null); } } }
/// <summary> /// Kicks the actor from the world (event WorldExited is sent to the client) and then disconnects the client. /// </summary> /// <remarks> /// Called by DisconnectByOtherPeer after being enqueued to the PeerBase.RequestFiber. /// It kicks the actor from the world (event WorldExited) and then continues the original request by calling the original peer's OnOperationRequest method. /// </remarks> public void OnDisconnectByOtherPeer(PeerBase otherPeer, OperationRequest otherRequest, SendParameters sendParameters) { this.ExitWorld(); // disconnect peer after the exit world event is sent this.Peer.RequestFiber.Enqueue(() => this.Peer.RequestFiber.Enqueue(this.Peer.Disconnect)); // continue execution of other request PeerHelper.InvokeOnOperationRequest(otherPeer, otherRequest, sendParameters); }
public SocketUdpNativeDllImport(PeerBase npeer) : base(npeer) { if (this.ReportDebugOfLevel(DebugLevel.ALL)) { this.Listener.DebugReturn(DebugLevel.ALL, "SocketWrapper: UDP, Unity Android Native."); } this.Protocol = ConnectionProtocol.Udp; this.PollReceive = false; }
public SocketUdp(PeerBase npeer) : base(npeer) { if (this.ReportDebugOfLevel(DebugLevel.ALL)) { this.Listener.DebugReturn(DebugLevel.ALL, "CSharpSocket: UDP, Unity3d."); } this.Protocol = ConnectionProtocol.Udp; this.PollReceive = false; }
public SocketWebTcp(PeerBase npeer) : base(npeer) { ServerAddress = npeer.ServerAddress; if (this.ReportDebugOfLevel(DebugLevel.INFO)) { Listener.DebugReturn(DebugLevel.INFO, "new SocketWebTcp() " + ServerAddress); } Protocol = ConnectionProtocol.Tcp; PollReceive = false; }
/// <summary> /// The client stops receiving counter updates from the PhotonApplication.CounterPublisher. /// </summary> public static OperationResponse UnsubscribeCounter(PeerBase peer, OperationRequest request) { var mmoPeer = (MmoPeer)peer; if (mmoPeer.CounterSubscription == null) { return new OperationResponse(request.OperationCode) { ReturnCode = (int)ReturnCode.InvalidOperation, DebugMessage = "not subscribed" }; } mmoPeer.CounterSubscription.Dispose(); mmoPeer.CounterSubscription = null; return new OperationResponse(request.OperationCode); }
public OperationResponse OperationEnterWorld(PeerBase peer, OperationRequest request, SendParameters sendParameters) { var operation = new EnterWorld(peer.Protocol, request); if (!operation.IsValid) { return new OperationResponse(request.OperationCode) { ReturnCode = (int)ErrorCode.InvalidOperationParameter, DebugMessage = operation.GetErrorMessage() }; } MmoWorld world = MmoWorld.Instance; var actor = new MmoActor(peer, world, interestArea); var avatar = new MmoItem(world, operation.Position, operation.Rotation, operation.Properties, actor, operation.Username, (byte)ItemType.Avatar); while (world.ItemCache.AddItem(avatar) == false) { Item otherAvatarItem; if (world.ItemCache.TryGetItem(avatar.Type, avatar.Id, out otherAvatarItem)) { avatar.Dispose(); actor.Dispose(); interestArea.Dispose(); ((Peer)((MmoItem)otherAvatarItem).Owner.Peer).DisconnectByOtherPeer(this, request, sendParameters); // request continued later, no response here return null; } } // init avatar actor.AddItem(avatar); actor.Avatar = avatar; ((Peer)peer).SetCurrentOperationHandler(actor); // set return values var responseObject = new EnterWorldResponse { }; // send response; use item channel to ensure that this event arrives before any move or subscribe events var response = new OperationResponse(request.OperationCode, responseObject); sendParameters.ChannelId = Settings.ItemEventChannel; peer.SendOperationResponse(response, sendParameters); avatar.Spawn(operation.Position); // response already sent return null; }
public override IGameListSubscription AddSubscription(PeerBase peer, Hashtable gamePropertyFilter, int maxGameCount) { if (gamePropertyFilter == null) { gamePropertyFilter = new Hashtable(0); } GameChannel gameChannel; var key = new GameChannelKey(gamePropertyFilter); if (!this.GameChannels.TryGetValue(key, out gameChannel)) { gameChannel = new GameChannel(this, key); this.GameChannels.Add(key, gameChannel); } return gameChannel.AddSubscription(peer, maxGameCount); }
public OperationResponse OnOperationRequest(PeerBase peer, OperationRequest operationRequest, SendParameters sendParameters) { switch ((OperationCode)operationRequest.OperationCode) { case OperationCode.EnterWorld: return this.OperationEnterWorld(peer, operationRequest, sendParameters); case OperationCode.ExitWorld: case OperationCode.Move: return InvalidOperation(operationRequest); } return new OperationResponse(operationRequest.OperationCode) { ReturnCode = (int)ErrorCode.OperationNotSupported, DebugMessage = "OperationNotSupported: " + operationRequest.OperationCode }; }
private static void PublishCounterData(PeerBase peer, ICollection<CounterSampleMessage> counterSamples) { IEnumerable<CounterAggregation> aggregations = CounterAggregation.Create(counterSamples); foreach (CounterAggregation aggregation in aggregations) { var @event = new CounterDataEvent { Name = aggregation.CounterName, TimeStamps = aggregation.Timestamps.ToArray(), Values = aggregation.Values.ToArray() }; var eventData = new EventData((byte)EventCode.CounterData, @event); // already in right fiber, we would use peer.SendEvent otherwise peer.SendEvent(eventData, new SendParameters { ChannelId = Settings.DiagnosticsEventChannel }); } }
// The client receives counter updates from the PhotonApplication.CounterPublisher. public static OperationResponse SubscribeCounter(PeerBase peer, OperationRequest request) { var operation = new SubscribeCounter(peer.Protocol, request); if (!operation.IsValid) { return new OperationResponse(request.OperationCode) { ReturnCode = (int)ReturnCode.InvalidOperationParameter, DebugMessage = operation.GetErrorMessage() }; } var mmoPeer = (MmoPeer)peer; if (mmoPeer.CounterSubscription == null) { mmoPeer.CounterSubscription = PhotonApplication.CounterPublisher.Channel.SubscribeToBatch( peer.RequestFiber, m => PublishCounterData(peer, m), operation.ReceiveInterval); return operation.GetOperationResponse(MethodReturnValue.Ok); } return operation.GetOperationResponse((int)ReturnCode.InvalidOperation, "already subscribed"); }
/// <summary> /// Gets a room reference for a room with a specified id. /// If the room with the specified id does not exists, a new room will be created. /// </summary> /// <param name="roomName"> /// The room id. /// </param> /// <param name="ownerPeer"> /// The peer that holds this reference. /// </param> /// <param name="args"> /// Optionally arguments used for room creation. /// </param> /// <returns> /// a <see cref="RoomReference"/> /// </returns> public RoomReference GetRoomReference(string roomName, PeerBase ownerPeer, params object[] args) { lock (this.SyncRoot) { RoomInstance roomInstance; if (!this.RoomInstances.TryGetValue(roomName, out roomInstance)) { if (log.IsDebugEnabled) { log.DebugFormat("Creating room instance: roomName={0}", roomName); } Room room = this.CreateRoom(roomName, args); roomInstance = new RoomInstance(this, room); this.RoomInstances.Add(roomName, roomInstance); } return roomInstance.AddReference(ownerPeer); } }
/// <summary> /// Expects operation RadarSubscribe and subscribes the peer to the Radar. /// Publishes an OperationResponse with error code ReturnCode.Ok if successful. /// </summary> public static OperationResponse OperationRadarSubscribe(PeerBase peer, OperationRequest request, SendParameters sendParameters) { var mmoPeer = (MmoPeer)peer; var operation = new RadarSubscribe(peer.Protocol, request); if (!operation.IsValid) { return new OperationResponse(request.OperationCode) { ReturnCode = (int)ReturnCode.InvalidOperationParameter, DebugMessage = operation.GetErrorMessage() }; } if (mmoPeer.RadarSubscription != null) { mmoPeer.RadarSubscription.Dispose(); mmoPeer.RadarSubscription = null; } World world; if (WorldCache.Instance.TryGet(operation.WorldName, out world) == false) { return operation.GetOperationResponse((int)ReturnCode.WorldNotFound, "WorldNotFound"); } mmoPeer.RadarSubscription = world.Radar.Channel.Subscribe(mmoPeer.RequestFiber, m => RadarChannel_OnItemEventMessage(peer, m)); // set return values var responseObject = new RadarSubscribeResponse { BoundingBox = world.Area, TileDimensions = world.TileDimensions, WorldName = world.Name }; // send response before sending radar content var response = new OperationResponse(request.OperationCode, responseObject); peer.SendOperationResponse(response, sendParameters); // send complete radar content to client world.Radar.SendContentToPeer(mmoPeer); // response already sent return null; }
private void HandleFiendFriends(PeerBase peer, FindFriendsRequest request, SendParameters sendParameters) { try { var onlineList = new bool[request.UserList.Length]; var gameIds = new string[request.UserList.Length]; for (int i = 0; i < request.UserList.Length; i++) { PlayerState playerState; if (this.playerDict.TryGetValue(request.UserList[i], out playerState)) { onlineList[i] = true; if (playerState.ActiveGame != null) { gameIds[i] = playerState.ActiveGame.Id; } else { gameIds[i] = string.Empty; } } else { gameIds[i] = string.Empty; } } var response = new FindFriendsResponse { IsOnline = onlineList, UserStates = gameIds }; var opResponse = new OperationResponse((byte)OperationCode.FindFriends, response); peer.SendOperationResponse(opResponse, sendParameters); } catch (Exception ex) { log.Error(ex); } }
/// <summary> /// Initializes a new instance of the <see cref="MmoClientInterestArea"/> class. /// </summary> /// <param name="peer"> /// The peer state. /// </param> /// <param name="id"> /// The interesta area id. /// </param> /// <param name="world"> /// The world. /// </param> public MmoClientInterestArea(PeerBase peer, byte id, IWorld world) : base(peer, id, world, peer.RequestFiber) { }
/// <summary> /// Expects operation EnterWorld and creates a new MmoActor with a new Item as avatar and a new MmoClientInterestArea. /// </summary> /// <remarks> /// The MmoActor becomes the new Peer.CurrentOperationHandler. /// If another MmoActor with the same name exists he is disconnected. /// An OperationResponse with error code ReturnCode.Ok is published on success. /// </remarks> public OperationResponse OperationEnterWorld(PeerBase peer, OperationRequest request, SendParameters sendParameters) { var operation = new EnterWorld(peer.Protocol, request); if (!operation.IsValid) { return new OperationResponse(request.OperationCode) { ReturnCode = (int)ReturnCode.InvalidOperationParameter, DebugMessage = operation.GetErrorMessage() }; } World world; if (WorldCache.Instance.TryGet(operation.WorldName, out world) == false) { return operation.GetOperationResponse((int)ReturnCode.WorldNotFound, "WorldNotFound"); } var interestArea = new ClientInterestArea(peer, operation.InterestAreaId, world) { ViewDistanceEnter = operation.ViewDistanceEnter, ViewDistanceExit = operation.ViewDistanceExit }; var actor = new MmoActorOperationHandler(peer, world, interestArea); var avatar = new Item(operation.Position, operation.Rotation, operation.Properties, actor, operation.Username, (byte)ItemType.Avatar, world); while (world.ItemCache.AddItem(avatar) == false) { Item otherAvatarItem; if (world.ItemCache.TryGetItem(avatar.Id, out otherAvatarItem)) { avatar.Dispose(); actor.Dispose(); interestArea.Dispose(); (((Item)otherAvatarItem).Owner).DisconnectByOtherPeer(this.peer, request, sendParameters); // request continued later, no response here return null; } } // init avatar actor.AddItem(avatar); actor.Avatar = avatar; ((Peer)peer).SetCurrentOperationHandler(actor); // set return values var responseObject = new EnterWorldResponse { BoundingBox = world.Area, TileDimensions = world.TileDimensions, WorldName = world.Name }; // send response; use item channel to ensure that this event arrives before any move or subscribe events var response = new OperationResponse(request.OperationCode, responseObject); sendParameters.ChannelId = Settings.ItemEventChannel; peer.SendOperationResponse(response, sendParameters); lock (interestArea.SyncRoot) { interestArea.AttachToItem(avatar); interestArea.UpdateInterestManagement(); } avatar.Spawn(operation.Position); world.Radar.AddItem(avatar, operation.Position); // response already sent return null; }
private static void RadarChannel_OnItemEventMessage(PeerBase peer, ItemEventMessage message) { // already in right fiber, we would use peer.SendEvent otherwise peer.SendEvent(message.EventData, message.SendParameters); }
/// <summary> /// IOperationHandler implementation. /// </summary> public OperationResponse OnOperationRequest(PeerBase peer, OperationRequest operationRequest, SendParameters sendParameters) { switch ((OperationCode)operationRequest.OperationCode) { case OperationCode.CreateWorld: { return this.OperationCreateWorld(peer, operationRequest); } case OperationCode.EnterWorld: { return this.OperationEnterWorld(peer, operationRequest, sendParameters); } case OperationCode.RadarSubscribe: { return OperationRadarSubscribe(peer, operationRequest, sendParameters); } case OperationCode.SubscribeCounter: { return CounterOperations.SubscribeCounter(peer, operationRequest); } case OperationCode.UnsubscribeCounter: { return CounterOperations.UnsubscribeCounter(peer, operationRequest); } case OperationCode.AddInterestArea: case OperationCode.AttachInterestArea: case OperationCode.DestroyItem: case OperationCode.DetachInterestArea: case OperationCode.ExitWorld: case OperationCode.GetProperties: case OperationCode.Move: case OperationCode.MoveInterestArea: case OperationCode.RemoveInterestArea: case OperationCode.SetProperties: case OperationCode.SetViewDistance: case OperationCode.SpawnItem: case OperationCode.SubscribeItem: case OperationCode.UnsubscribeItem: { return InvalidOperation(operationRequest); } } return new OperationResponse(operationRequest.OperationCode) { ReturnCode = (int)ReturnCode.OperationNotSupported, DebugMessage = "OperationNotSupported: " + operationRequest.OperationCode }; }
/// <summary> /// Expects operation CreateWorld and adds a new World to the WorldCache. /// </summary> public OperationResponse OperationCreateWorld(PeerBase peer, OperationRequest request) { var operation = new CreateWorld(peer.Protocol, request); if (!operation.IsValid) { return new OperationResponse(request.OperationCode) { ReturnCode = (int)ReturnCode.InvalidOperationParameter, DebugMessage = operation.GetErrorMessage() }; } World world; MethodReturnValue result = WorldCache.Instance.TryCreate( operation.WorldName, operation.BoundingBox, operation.TileDimensions, out world) ? MethodReturnValue.Ok : MethodReturnValue.New((int)ReturnCode.WorldAlreadyExists, "WorldAlreadyExists"); return operation.GetOperationResponse(result); }
/// <summary> /// IOperationHandler implementation. /// Disconnects the peer. /// </summary> public void OnDisconnectByOtherPeer(PeerBase peer) { // disconnect after any queued events are sent peer.RequestFiber.Enqueue(() => peer.RequestFiber.Enqueue(peer.Disconnect)); }
/// <summary> /// IOperationHandler implementation. /// Stops any further operation handling and disposes the peer's resources. /// </summary> public void OnDisconnect(PeerBase peer) { this.peer.SetCurrentOperationHandler(null); this.peer.Dispose(); }
/// <summary> /// Handles operation SpawnItem: Creates a new Item and optionally subscribes an InterestArea to it. /// </summary> public OperationResponse OperationSpawnItem(PeerBase peer, OperationRequest request) { var operation = new SpawnItem(peer.Protocol, request); if (!operation.IsValid) { return new OperationResponse(request.OperationCode) { ReturnCode = (int)ReturnCode.InvalidOperationParameter, DebugMessage = operation.GetErrorMessage() }; } operation.OnStart(); var item = new Item(operation.Position, operation.Rotation, operation.Properties, this, operation.ItemId, operation.ItemType, this.World); if (this.World.ItemCache.AddItem(item)) { this.AddItem(item); return this.ItemOperationSpawn(item, operation); } item.Dispose(); return operation.GetOperationResponse((int)ReturnCode.ItemAlreadyExists, "ItemAlreadyExists"); }
/// <summary> /// Handles operation UnsubscribeItem: manually unsubscribes an existing InterestArea from an existing Item. /// The client receives event ItemUnsubscribed on success. /// </summary> public OperationResponse OperationUnsubscribeItem(PeerBase peer, OperationRequest request, SendParameters sendParameters) { var operation = new UnsubscribeItem(peer.Protocol, request); if (!operation.IsValid) { return new OperationResponse(request.OperationCode) { ReturnCode = (int)ReturnCode.InvalidOperationParameter, DebugMessage = operation.GetErrorMessage() }; } operation.OnStart(); Item item; bool actorItem = this.TryGetItem(operation.ItemId, out item); if (actorItem == false) { if (this.World.ItemCache.TryGetItem(operation.ItemId, out item) == false) { return operation.GetOperationResponse((int)ReturnCode.ItemNotFound, "ItemNotFound"); } } this.interestItems.UnsubscribeItem(item); if (actorItem) { // we are already in the item thread, invoke directly return this.ItemOperationUnsubscribeItem(item, operation); } else { // second parameter (peer) allows us to send an error event to the client (in case of an error) item.Fiber.Enqueue(() => this.ExecItemOperation(() => this.ItemOperationUnsubscribeItem(item, operation), sendParameters)); // operation continues later return null; } }
public OperationResponse OnOperationRequest(PeerBase peer, OperationRequest operationRequest, SendParameters sendParameters) { switch ((OperationCode)operationRequest.OperationCode) { case OperationCode.AddInterestArea: return this.OperationAddInterestArea(peer, operationRequest, sendParameters); case OperationCode.AttachInterestArea: return this.OperationAttachInterestArea(peer, operationRequest, sendParameters); case OperationCode.DestroyItem: return this.OperationDestroyItem(peer, operationRequest, sendParameters); case OperationCode.DetachInterestArea: return this.OperationDetachInterestArea(peer, operationRequest); case OperationCode.ExitWorld: return this.OperationExitWorld(peer, operationRequest); case OperationCode.GetProperties: return this.OperationGetProperties(peer, operationRequest, sendParameters); case OperationCode.Move: return this.OperationMove(peer, operationRequest, sendParameters); case OperationCode.MoveInterestArea: return this.OperationMoveInterestArea(peer, operationRequest); case OperationCode.RemoveInterestArea: return this.OperationRemoveInterestArea(peer, operationRequest); case OperationCode.SetProperties: return this.OperationSetProperties(peer, operationRequest, sendParameters); case OperationCode.SetViewDistance: return this.OperationSetViewDistance(peer, operationRequest); case OperationCode.SpawnItem: return this.OperationSpawnItem(peer, operationRequest); case OperationCode.SubscribeItem: return this.OperationSubscribeItem(peer, operationRequest, sendParameters); case OperationCode.UnsubscribeItem: return this.OperationUnsubscribeItem(peer, operationRequest, sendParameters); case OperationCode.RadarSubscribe: return MmoInitialOperationHandler.OperationRadarSubscribe(peer, operationRequest, sendParameters); case OperationCode.SubscribeCounter: return CounterOperations.SubscribeCounter(peer, operationRequest); case OperationCode.UnsubscribeCounter: return CounterOperations.SubscribeCounter(peer, operationRequest); case OperationCode.RaiseGenericEvent: return this.OperationRaiseGenericEvent(peer, operationRequest, sendParameters); case OperationCode.CreateWorld: case OperationCode.EnterWorld: return InvalidOperation(operationRequest); } return new OperationResponse(operationRequest.OperationCode) { ReturnCode = (int)ReturnCode.OperationNotSupported, DebugMessage = "OperationNotSupported: " + operationRequest.OperationCode }; }