You can read
protocolgame.cpp and
protocolgamebase.cpp (only exists on otx) to see how the server handles that the packets client sends.
I think the encryption changed on the 11.75 version (not sure) so you have not only the new features but also changes to encryption methods.
I'll try to pass you trough what I've learned trying to implement the new Daily Reward System
(keep in mind the 11.75 protocol has a lot more this is just me trying to get you started):
When you click the Reward Wall Button on your 11.4 client:
1) The client sends a packet with a
0xD8 header. (You can find this by printing it on the engine on
ProtocolGame:: ParsePacket(NetworkMessage& msg) there is a line printing the packet header, so now you know what packet the client is sending.)
2) You catch that packet on
protocolgame.cpp, there is a switch statement there (
ProtocolGame:: ParsePacket(NetworkMessage& msg)) and call the method that will parse that request.
For example:
case 0xD8: parseOpeningRewardWall(); break;
3) Now, you have to get to know more about the client, and this is the tough part. You need to know what the client is expecting you to send, this is where Reverse Engineering comes in.
I'll not go into this subject because I have no knowledge on how to reverse engineer the client, I'm implementing the reward wall reading the
decompiled flash client code.
4) After reading the flash client source for a while (where I found that the client would do the same as tfs, a switch for all the possible packets the server is going to send, I searched for "reward" and easily found this:
JavaScript:
protected static const SOPENREWARDWALL:int = 226;
....
case SOPENREWARDWALL:
this.readSOPENREWARDWALL(CommunicationData);
a_MessageReader.finishMessage();
break;
(the
s in
sopenrewardwall means a server request to open the reward wall)
So now, I know that if the server is sending a
0xE2 (226 in hex) packet header this function will be called in the client:
JavaScript:
protected function readSOPENREWARDWALL(param1:ByteArray) : void
{
var _loc5_:int = 0;
var _loc9_:String = null;
var _loc2_:Boolean = param1.readBoolean(); --
var _loc3_:int = param1.readUnsignedInt(); --
var _loc4_:int = param1.readUnsignedByte(); --
_loc5_ = param1.readUnsignedByte(); --
if(_loc5_ != 0)
{
_loc9_ = StringHelper.s_ReadLongStringFromByteArray(param1);
}
var _loc6_:int = param1.readUnsignedInt();
var _loc7_:int = param1.readUnsignedShort();
var _loc8_:int = param1.readUnsignedShort();
}
Now, all I have to do it make the server (otx or tfs) send a
0xE2 packet header with te structure above when it receives a
0xD8 packet header:
On step 2 I show an example:
case 0xD8: parseOpeningRewardWall(); break;
But how does that method work? Let me show you:
C++:
NetworkMessage msg;
msg.addByte(0xE2); // this is the packet header that will make the client read this as an "opening reward wall" request.
msg.addByte(0x01);
msg.add<uint32_t>(21);
msg.addByte(0x00);
msg.addByte(0x00);
//msg.addString(player->getName()); // if the last byte is 1 a string needs to be sent after it
msg.add<uint32_t>(300);
msg.add<uint16_t>(1);
msg.add<uint16_t>(1);
writeToOutputBuffer(msg);
sendDailyRewards();
Keep in mind that theese bytes i'm adding to the msg are completely fake and only for test purposes and each byte means something on the client side. (I still don't know what some of them mean)
For example: I came to find that the first byte I send is 0x00 or 0x01, 0 means the player is opening the reward wall through the client button (he needs to pay to get instance reward access), 1 means its from a reward shrine so it's free.
I call this "bytes structure" idk if thats right, but its simply the structure or sequence of the bytes you send to the client.
The last method I call is to send the rewards so the window has something for the player to redeem, but thats a story for another time.
Edit:
remainder: when you send something wrong to the client (a string instead of a int or something like that) the client will crash with a debug msg.
I'm not sure and this can easily be untrue, but I think you can't log in to the server because the encryption on that version changed, also the character list is handled by the webservice you have running on your gesior/znote, not by the engine.
I hope this can get you started and if you need anything you can PM me and I'll be glad to help you if possible.