Client to server comunication in MMO

Scoppio
edited April 2011 in Photon Server
Iactually what I'm doing is trying to use the Operation.RaiseGenericEven() on the clientside to extend the MMO server, but I feel I'm hitting my forehead against the wall.

I've tried the other tutorials (blanl server 1 and 2, hello world 1 and 2, extending lite) but I fell lame, maybe my inexperience with dotnet is taking its toll on me.

What I was able to absorb from the MMO demo and understand

SendOperation is the funciton used to transfer data "client->server".

The "returnMethod" should return an error and a debug message, but I don't see how to transfer "substantial data".

"RaiseGenericEvent" should be the place to extend the function to a few extras, ok, fine, but I don't get to see how its done, the operation seens to take every piece of substantial information and then it has its own code to deal with it.

Client-side
        public static void RaiseGenericEvent(
            Game game, string itemId, byte? itemType, byte customEventCode, object eventData, byte eventReliability, EventReceiver eventReceiver)
        {
            var data = new Hashtable
                {
                    { (byte)ParameterCode.CustomEventCode, customEventCode }, 
                    { (byte)ParameterCode.EventReliability, eventReliability }, 
                    { (byte)ParameterCode.EventReceiver, (byte)eventReceiver }
                };

            if (eventData != null)
            {
                data.Add((byte)ParameterCode.EventData, eventData);
            }

            if (itemId != null)
            {
                data.Add((byte)ParameterCode.ItemId, itemId);
            }

            if (itemType.HasValue)
            {
                data.Add((byte)ParameterCode.ItemType, itemType.Value);
            }

            game.SendOperation(OperationCode.RaiseGenericEvent, data, true, Settings.ItemChannel);
        }

Thats pretty much straight forward: - You send the data to me, I send it to the server.

There are however two things that I can't deal effectivelly

Server-side - ExtensionMethods
public static OperationResponse GetOperationResponse(this Operation operation, MethodReturnValue returnValue)
        {
            return operation.GetOperationResponse(returnValue.Error, returnValue.Debug);
        }

This should return somekind of data to the client, right?


Ok, now about the OperationRaiseGenericEvent

Server-side - OperationRaiseGenericEvent
        [Operation(OperationCode = (byte)OperationCode.RaiseGenericEvent)]
        public OperationResponse OperationRaiseGenericEvent(Peer peer, OperationRequest request)
        {
            var operation = new RaiseGenericEvent(request);
            if (!operation.IsValid)
            {
                return new OperationResponse(request, (int)ErrorCode.InvalidOperationParameter, operation.GetErrorMessage());
            }

            Item item;
            bool actorItem = true;
            if (false == operation.ItemType.HasValue || string.IsNullOrEmpty(operation.ItemId))
            {
                item = this.Avatar;

                // set return values
                operation.ItemType = item.Type;
                operation.ItemId = item.Id;
            }
            else if (this.TryGetItem(operation.ItemType.Value, operation.ItemId, out item) == false)
            {
                if (this.World.ItemCache.TryGetItem(operation.ItemType.Value, operation.ItemId, out item) == false)
                {
                    return operation.GetOperationResponse((int)ErrorCode.ItemNotFound, "ItemNotFound");
                }

                actorItem = false;
            }

            if (actorItem)
            {
                // we are already in the item thread, invoke directly
                return ItemOperationRaiseGenericEvent(item, operation);
            }

            // second parameter (peer) allows us to send an error event to the client (in case of an error)
            item.OperationQueue.EnqueueOperation(() => ItemOperationRaiseGenericEvent(item, operation), this.Peer, request);

            // operation continued later
            return null;
        }

Well, this should be the function to be extended, or isn't it? There is the "ItemOperationRaiseGenericEvent" and it seens to be the one that actually do something
        private static OperationResponse ItemOperationRaiseGenericEvent(Item item, RaiseGenericEvent operation)
        {
            if (item.Disposed)
            {
                return operation.GetOperationResponse((int)ErrorCode.ItemNotFound, "ItemNotFound");
            }

            var eventInstance = new ItemGeneric
                {
                    ItemId = item.Id,
                    ItemType = item.Type,
                    CustomEventCode = operation.CustomEventCode,
                    EventData = operation.EventData
                };
            
            EventData eventData = eventInstance.GetEventData((byte)EventCode.ItemGeneric, (Reliability)operation.EventReliability, Settings.ItemEventChannel);

            switch (operation.EventReceiver)
            {
                case (byte)EventReceiver.ItemOwner:
                    {
                        if (((IMmoItem)item).ReceiveEvent(eventData) == false)
                        {
                            string debugMessage = string.Format("Target item {0}/{1} could not receive event", item.Type, item.Id);
                            return operation.GetOperationResponse((int)ErrorCode.InvalidOperation, debugMessage);
                        }

                        break;
                    }

                case (byte)EventReceiver.ItemSubscriber:
                    {
                        var message = new ItemEventMessage(item, eventData);
                        item.EventChannel.Publish(message);
                        break;

                    }

                default:
                    {
                        return operation.GetOperationResponse((int)ErrorCode.ParameterOutOfRange, "Invalid EventReceiver " + operation.EventReceiver);
                    }
            }

            // no response
            operation.OperationRequest.OnCompleted();
            return null;
        }

My guess is, the data is sent from client to the server and it arrives on "OperationRaiseGenericEvent" which then verifies if it was sent from a legal source and what source sent it, then it passes to "ItemOperationRaiseGenericEvent" and this new function does the real job. But since there is nothing to different to do then it simply have a switch that says "hey, was it the subscriber who sent me this request or was it the owner of the item?" and then he says "well, theres nothing I can do, you should be sorry for wasting my time" and then simply drops everything to the ground without even checking what is the operation.CustomEventCode because there is no need after all.

But if I want to give it some use, should then I add something to it? I mean... should I add one switch inside the
        private static OperationResponse ItemOperationRaiseGenericEvent(Item item, RaiseGenericEvent operation)
        {
         ...
              case (byte)EventReceiver.ItemSubscriber:
                    {
                        //var message = new ItemEventMessage(item, eventData); //should be removed
                        //item.EventChannel.Publish(message); //should be removed
//adding a switch
                        switch(eventInstance.CustomEventCode){
                        case (byte)EventCode.CODESAMPLE1:
                        //add substantial data
                        break;
                        case (byte)EventCode.CODESAMPLE2:
                        //add substantial data
                        break;
                        case (byte)EventCode.CODESAMPLE2:
                        //add substantial data
                        break;

                        }
//return to the old "case"
                        break;

                    }
       ...

What I wanted was somekind of "switch case" operation inside this specific operation so I could add things like "sql requests", "item spawn", "attack", etc... But yet the lack of "how to return data to the client" hooks me, I thought that the "publish" would do the trick, but I didn't understand it well enough to be confortable using it.


PS.: Sincerely, due to the numbers of barriers on coding the server/client communication/behaviour I'm thinking of putting this project in the stack/frezzer while I keep pace in University and gather a better number of programers to help me in this project (its actually only me as a C# programmer and a guy that helps me sometimes, the other guys are all designers, sound technicians, illustrators and 3d modelers)

Comments

  • Boris
    Boris ✭✭
    raise event is just a method to forward messages (events) to other clients (RPC calls on remote clients), not really a way to add functions to the server.
    If you want to do something special on the server add new operations.