Client to server comunication in MMO
Options
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
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
This should return somekind of data to the client, right?
Ok, now about the OperationRaiseGenericEvent
Server-side - OperationRaiseGenericEvent
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
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
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)
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)
0
Comments
-
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.0