Jump to content

Learn Mangos and become a dev


Guest rhaziel
 Share

Recommended Posts

Hi guys,

Now im kind of new to C++ (or atleast such extensive enterprises as Mangos).

I've done some programming in the days and i do know C++ and Delphi (T Pascal) and some ASM.

What i want is to find a simple almost the first ever made mangos core (or any other emu with a simple structure).

I want to have the source - so that i can dissasmeble it and break to pieces.

Once i do that i will put it all back together with some of my personal modifications.

And then i will write it from scratch. And once im done - i should be able to contribute atleast in some extent.

Please direct me to some good source so that i can start learning.

Link to comment
Share on other sites

Hi rhaziel,

while MaNGOS looks big and scary, it actually all boils down to a couple of files. I suggest you start at understanding WHAT MaNGOS is trying to emulate - in order of appearance:

While this list is probably very incomplete, it should be enough to jumpstart your MaNGOS adventure. In parallel, it may help you to look at PseuWoW (http://mangosclient.org)(yes, shameless self-promo), which attempts to emulate the client part.

If you have any specific questions, you should ask them in the appropriate boards, and they may be answered... at some point ;)

Link to comment
Share on other sites

I've actually seem PseuWoW before i even started this thread. tho the web page seemed kinda abandoned.

Nonetheless i will dive into this for sure - not sure if server or client side but for sure will contribute.

But btw guys, can u tell me - what exactly is the point of pseuwow since the official client works just fine?

Link to comment
Share on other sites

@ensiferum: this is off topic - go over to the proper forums.

@rhaziel: Try a specific question. For general ideas on the structure on the system check my post above.

Let me walk you through how I would go about figuring out how this system works. This may or may not work for you.

1) Compile MaNGOS

2) Compile PseuWoW

3) Configure PseuWoW for the maximum debug output possible

Specifically this means in PseuWoW.conf:

debug=3 // Output every single piece of debug crap ever deposited in the source

showopcodes=3 // Show every single opcode that goes over the wire

hidefrequentopcodes=0 // REALLY every single opcode

HideDisabledOpcodes=0 // ...

showmyopcodes=1 // Also show what I am sending to the server

enablegui=0 // GUI adds unnecessary complexity, so no need for that

4) Now start up PseuWow and see what happens... OMG! It's full of crap!!! ...No, seriously:

2011-10-07 11:00:19 +----------------------------------+

2011-10-07 11:00:19 | © 2006-2010 Snowstorm Software |

2011-10-07 11:00:19 | http://www.mangosclient.org |

2011-10-07 11:00:19 +----------------------------------+

2011-10-07 11:00:19 Platform: Unix

2011-10-07 11:00:19 Compiler: GCC (40502)

2011-10-07 11:00:19 Compiled: Sep 22 2011 16:39:00

2011-10-07 11:00:19

2011-10-07 11:00:19 --- Initializing Instance ---

2011-10-07 11:00:19 *** DefScript StartUp [A13.51]...

2011-10-07 11:00:19 *** Loading 14 script files.

2011-10-07 11:00:19 * Loading script file [./scripts/__core_chat.def]

2011-10-07 11:00:19 * Loading script file [./scripts/__core_chatAI.def]

2011-10-07 11:00:19 * Loading script file [./scripts/__core_eventstubs.def]

2011-10-07 11:00:19 * Loading script file [./scripts/__core_func.def]

2011-10-07 11:00:19 * Loading core scripts...

2011-10-07 11:00:19 * Loading script file [./scripts/__core_funstuff.def]

2011-10-07 11:00:19 * Loading script file [./scripts/__core_hookHelper.def]

2011-10-07 11:00:19 * Loading script file [./scripts/__core_internal.def]

2011-10-07 11:00:19 * Loading core scripts (internal config)...

2011-10-07 11:00:19 ** Configuring PseuWoW...

2011-10-07 11:00:19 * Loading 1 conf files.

2011-10-07 11:00:19 * Loading conf file [ PseuWoW.conf ]

2011-10-07 11:00:19 MemoryDataHolder: Single-threaded mode.

2011-10-07 11:00:19 * Configuration applied.

2011-10-07 11:00:19 * Cleaning up variables...

2011-10-07 11:00:19 * Dangerous variables removed.

2011-10-07 11:00:19 * Assigning permissions for internal functions...

2011-10-07 11:00:19 ** All Config done.

2011-10-07 11:00:19 * Loading script file [./scripts/__core_list_extensions.def]

2011-10-07 11:00:19 * Loading script file [./scripts/__core_misc.def]

2011-10-07 11:00:19 * Loading script file [./scripts/__core_wrappers.def]

2011-10-07 11:00:19 * Loading script file [./scripts/autobroadcast.def]

2011-10-07 11:00:19 ** AutoBroadcast: skipped loading.

2011-10-07 11:00:19 * Loading script file [./scripts/database_loader.def]

2011-10-07 11:00:19 * Loading script file [./scripts/help.def]

2011-10-07 11:00:19 * Loading script file [./scripts/uptime.def]

2011-10-07 11:00:19 *** All files loaded without errors.

2011-10-07 11:00:19 *** StartUp complete!

2011-10-07 11:00:19 ** Loading / dyncompiling databases...

2011-10-07 11:00:19 Loading database 'race'

2011-10-07 11:00:19 File './data/scp/race.scp' matching database 'race', loading

2011-10-07 11:00:19 21 sections loaded

2011-10-07 11:00:19 Compacting database 'race' into file './cache/race.ccp'

2011-10-07 11:00:19 Database 'race' loaded from source and compacted with compression 6

--snip--

2011-10-07 11:00:19 Loading database 'emote'

2011-10-07 11:00:19 SCP: No files found that contain database [emote]

--snip--

2011-10-07 11:00:19 ** Databases loaded.

2011-10-07 11:00:19 RemoteController: listening on port 8101

2011-10-07 11:00:19 Starting CLI...

2011-10-07 11:00:19 Init complete.

2011-10-07 11:00:19 PseuInstance: Initialized and running!

2011-10-07 11:00:19 GUI not active or Login data pre-entered, skipping Login GUI

2011-10-07 11:00:19 RealmSocket connected!

2011-10-07 11:00:19 Packet Sent

2011-10-07 11:00:19 RealmSocket::OnRead() 119 bytes

2011-10-07 11:00:19 RealmSocket: Got AUTH_LOGON_CHALLENGE [119 of 118 bytes]

2011-10-07 11:00:19 Login successful, now calculating proof packet...

2011-10-07 11:00:19 == Server Bignums ==

2011-10-07 11:00:19 --> B=2CEC5E45B34CB20CABC099088CCF3D6B315F12DCBE070CC2F563D5447884D917

2011-10-07 11:00:19 --> g=07

2011-10-07 11:00:19 --> N=894B645E89E1535BBDAD5B8B290650530801B18EBFBF5E8FAB3C82872A3E9BB7

2011-10-07 11:00:19 --> salt=B1CDCBFEE4C62F33D47D3A41DEE66E1667D487764058304BF1A70BB6C3557361

2011-10-07 11:00:19 --> unk=96C6A6BE2A589806B0B0070D852BBAC7

2011-10-07 11:00:19 == My Bignums ==

2011-10-07 11:00:19 --> a=A4722A2E0E9F1B9764E615034870B981569409

2011-10-07 11:00:19 --> x=36A15107ECF19C70E49EF4E5B42D36C7E3990B47

2011-10-07 11:00:19 --> v=77F37E45F8A88CDE9943038D4AE6C3292F407ED62D9B3DCC93E701E56E4D5228

2011-10-07 11:00:19 --> A=7BADE689AA63658C8DA684A78660BF1C62114269930D4141B9B30F75EDE466BB

2011-10-07 11:00:19 --> u=DBC0E8AE033ACA9A9066E583DC160CB741A39737

2011-10-07 11:00:19 --> S=1F9CC8F4E9F82C234427CAD5FBA670BB3F13E45369A9785278F248A7ED4A6A4D

2011-10-07 11:00:19 --> SessionKey=B950BE26E5472829B32D9BFCDD442A3C4D7D70A4DA6290E5C4F2ACC78D823BFB39F3B5E21342083A

2011-10-07 11:00:19 == Common Hashes ==

2011-10-07 11:00:19 --> M1=9BB22EF3A2E65D59F59A69AC526A0DE5D6EE0EE4

2011-10-07 11:00:19 --> M2=B128DC34B9061495325AECA7059D269386B4D46F

2011-10-07 11:00:19 --> CRC=0000000000000000000000000000000000000000

2011-10-07 11:00:19 Data left on RealmSocket, Hexdump:

2011-10-07 11:00:19 00

-- CUT --

An average PseuWoW login produces about 400 lines of logfile.

Obviously in the beginning you have some startup messages which say that some script files are loaded, some config is read, some databases are loaded, etc. If you would like to know specifics on how this is done, do a search over all files using some of the log output. For example if you would like to know how the databases are loaded, run "Loading databases" in your search, and you will find out that databases are loaded somewhere in src/Client/DefScriptInterface.cpp.

Then it says "Init complete. PseuInstance: Initialized and running" - The fun starts. PseuWoW connects to the server...

I have to admit, that the realm socket code does not produce very nice output. But still. Every single line of log output can be found in the source, so you can follow the code execution. I will go through the next 5 lines:

11:00:19 RealmSocket connected!

This line is logged in src/Client/Realm/RealmSocket.cpp RealmSocket::OnConnect(). When does this function get called? After some more searching we find out that RealmSocket is derived from TcpSocket (see src/Client/Realm/RealmSocket.h) and TcpSocket calls OnConnect() when a connection is made (see src/shared/Network/TcpSocket.cpp). Nice one!

11:00:19 Packet Sent

This line comes from src/Client/Realm/RealmSession.cpp RealmSession::SendLogonChallenge() which gets called from src/Client/PseuWoW.cpp PseuInstance::ConnectToRealm() which is called from PseuInstance::Update() which in turn gets called from PseuInstance::Run(). As you will also find out, Run() contains the main program loop. So after reading through some or all of these functions, you will see that SendLogonChallenge() puts together a data packet containing all kinds of logon data (I believe some of that is a bit hacky, now that I look at it...) (Client Version, account name, etc) and sends it off to the server.

This is the first contact. So what does the server do with it? (At this point you should take a look at server startup logs using the same strategy as before) The server (in this case realmd) gets this AUTH_LOGON_CHALLENGE packet. Searching mangos source for that string reveals that src/realmd/AuthSocket.cpp handles it in AuthSocket::_HandleLogonChallenge. Reading through the code (and ignoring or looking up bits you don't understand right away) you will see that realmd checks if the packet is okay, if the account exists, is not banned, suspended, or any other bad thing and if it is not, it calculates some lovely bignumbers which are then used as logon challenge to the client. By following the pkt object throughout the function you can see the structure and order of data in the packet, just as before in PseuWoW. In the end, the packet is sent back to the client, which then says:

11:00:19 RealmSocket::OnRead() 119 bytes

By now you will not have any difficulties to find out that this is called from src/Client/Realm/RealmSocket.cpp RealmSocket::OnRead(). It receives all data on the socket, and adds it to a packet queue for processing.

11:00:19 RealmSocket: Got AUTH_LOGON_CHALLENGE [119 of 118 bytes]

This message is reported from src/Client/Realm/RealmSession.cpp RealmSession::_HandleLogonChallenge(). How the hell did we get from the packet queue to this function? Let's see. RealmSession::_GetAuthHandlerTable() has a mention of _HandleLogonChallenge() in a table of some sorts. _GetAuthHandlerTable() gets called from RealmSession::Update() and returns a pointer to the table. A bit into the Update() function (which presumably gets called from the main loop, I leave it to you to verify this) you will find that a for loop goes through the table and checks if the Opcode of the packet matches the one in the table. If it does, a magic called "function pointers" is used to call the associated handler function, which we already know is _HandleLogonChallenge().

11:00:19 Login successful, now calculating proof packet...

This line is also from _HandleLogonChallenge(), a bit further down. As you will have found out at this point, PseuWoW has checked if there were any errors, and found none. So now it will extract the data from the packet, calculate login proof data and send it off again, while outputting copious amounts of debug information.

I hope this starts your learning process. What you will see all the time it this ping-pong game between the server and the client throwing packets at each other in response to something happening on either side (movement, attacks, cooldowns, etc) and replying to those packets.

I am not sure what you mean by "pinning this thing down", but I am very certain that only a handful of people on this planet have a complete in-depth understanding of every bit of code in the MaNGOS repository. It is also not necessary to understand the underlying network code to fix something in the spell handling (just as an example). So I would recommend you not to get lost in implementation details before you have the big picture. And by "big picture" I refer to the three classic things every program needs to do:

main()
{

Initialize();

while(running)
   DoStuff();

CleanUp();

}

Hope it helps, apologies for the rather lengthy post...

Shlainn

Link to comment
Share on other sites

 Share

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue. Privacy Policy Terms of Use