| Register | Members | Blogs | Chat |
| FlyFF Releases Discuss, Guide on how to Build an Emulator. [ Added FlyFF Emulator Forums ] at Flyff forum; Full C++ video guide I will try to Define the Steps to making an emulator to the best of my ... |
|
![]() |
| Thread Tools |
|
cout << "Hello World \n";
Rank: Member
|
Full C++ video guide
I will try to Define the Steps to making an emulator to the best of my ability If you have any questions feel free to add my msn elitefrost@live.com This is not a discussion For Caali's unfixible files chat room for developers http://xat.com/flyffdevs Kiki's source files http://rapidshare.com/files/15249115...files.rar.html 100% Credits to kiki and not me! Forums for Emulator Devlopment: http://z10.invisionfree.com/FlyFF_De...ex.php?act=idx Any sort of discussion about Caali's files will be banned. I once was stuck on how to start an emulator and this is a post that helped me alot First, you choose a coding language you want to use to create the emulator.
Then, you learn it, if you haven't done so until now. Now that you know the basics of the language, you start learning how to use sockets with it. First, you create a socket, bind it to port 23000, tell it to listen for connections, set it to read and parse data, then send some other data back to the client. You should use a packet sniffer to know what data to send. Your emulator should have classes (in my opinion) to work well. Mine has a class for almost everything: MySQL, sockets, packets, inter-server packets, server-related variables, packet parsing, packet handling, logging, client class, configuration files parser, error handling.. that's about all of them. Good luck. As far as I know, most of the developers don't use C++ to develop the emulator. Some use Java, but most use C#. you will to know alot of basics to make a flyff server this includes sockets, and packet structure and of course the language it self. You should learn the language and use the flyff server you are trying to build as a lesson for yourself it won't be the best but it will help you build it. You could also use a source from like ms or rose to get you going in the right direction. Just edit the source to fit around the flyff stuff ( like you wouldn't use maple encryption for flyff ).
addishen Part I WireShark First off. Pick your packet Sniffer. I would suggest using Wireshark since it's free and easy to use. The download can be found here. http://www.wireshark.org/download.html Got wireshark ? Good we'll start collecting packets from the official Flyff. First off you open The wireshark program ![]() Go Captures> Interfaces and select your Ethernet card. Now you need to filter out all other Ip's except the official flyff one ![]() Put First Capture Filter into the Filter Name box. I want you to enter host followed by your ip address into the Filter String box. If you ip address is 192.168.1.2, the Filter String box would contain the following. host 192.168.1.2 We are telling Wireshark to capture everything coming from and going to your ip address. So we will get a log of all the traffic that is coming from or going to your computer. When you have finished those two changes click the Ok button at the bottom of this page. ![]() You should now be back at the Capture Options window. Then click the Start button at the bottom of the screen. ![]() You are now see packets as they are being sent to and from your computer. You might see a lot of traffic or just a little traffic depending upon how much is going on on your network. If you do not see any packets, try opening up a web page. If you still do not see captured data, then you probably have the wrong Interface selected on the Capture options window. When you have a couple packets, click the Capture option at the top of the screen and then Stop option in the menu that drops down. Wireshark has captured some data as you can see on your screen. There are three frames here. I have labeled them as Frame 1, Frame 2, and Frame 3 in the picture above. Frame 1 shows you an overview of what packets came in and when out of your network. Frame 2 shows more detailed information about a selected packet. Frame 3 shows the hex data of the packet. We only really care about frame 1. The source column tells us where the data was coming from and the destination column tells us where the data was going to. Both of these columns will always have ip addresses in them. The protocol column tells us what protocol that packet was sent with. Which is useful when trying to figure out what ports/procotols a program uses. The info box contains the information that we really need. The info box lists specific requests made over the network. It also lists what ports the data traveled on. Notice that every time a port is listed it is listed as a pair of ports. Data always travels on ports. It is send out of the source ip address on a port, and then received on the destination ip address on a port. These ports are rarely the same. Keeping that in mind, it is easy to see why there are two ports listed in the info box. The first port is the source port. Notice the > which you can think of as the word to. From the first port > to the second port. I hope that I have explained enough to give you a general feel for the program. Check out the help section of the program for more capture filter options. Notice that there is also a filter box above the data you have captured. This is the dISPlay filter. It works like the capture filter, but allows you to filter data that has already been captured. Click the help button in the dISPlay filter window for examples of how to use it. Wire Shark Tutorial Credit: http://portforward.com/networking/ethereal.htm Part II Capturing Packets and Understanding the structure Now that you have Wireshark set on the Flyff Ip it's now time to start capturing packets. Start up Flyff and camp the Server screen or ingame ![]() You should start to be recieving packets sent from the server After careful hours of looking through various packets, I was able to determine what I think is the correct structure of the shop window for npcs.
Keep in mind that this is a work in progress but I believe this will help in the construction of new and possibly remixed npc shops. So here we go. This is a rough breakdown for Boboku's Weapon Shop. For those of you who do not know what I am going to show. Please consult packet structures in the release section. Code:
[5e] [INT-Length] [00 FF FF FF] [01 00] [03 00 00 00] --> NPC Spawn ID (I think it tells what shop to open) [14 00] ---> Call Shop window Command [00 00 00 00] [01 -> 63 00 00 00] ------> 01 00 00 00 to 63 00 00 00 changing the first byte consecutively in hex [NUMBER OF SLOTS SHORT-INT] -----> Determins how many slots for items on the page [00 00 00 00] --> Unknown possibly slot number? [INT-ITEM ID] --> ID of the item (1D = Petal Sword) [00] x 8 [INT-Quantity] --> I believe this is how many items are in the slot [NOTE #1] --> This two byte int is an ID for the item type. in this case DD 6D represents Mercenary Sword (I think) [00] x 40 [01] ---> Next slot When all the pages are done, it repeats that long 01 - 63 int loop again but 3 times. There you have it. This was captured on Caalis server. It is possible to assume that some of the information is current, but my server might be slightly different than this. I will keep you posted. Code:
Flyff Packet Structure
short: 2byte
int: 4byte
float: 4byte
pstr: [(int)length][string]
Client's packet structure
These are packets sent by the client to the server
[(byte)0x5e][(int)unknown][(int)length][data][(int)s]
0x5e: starts every packet
unknown: the next 4 bytes should be skipped
length: length of the data field in bytes
data: commands/requests to the server
s: this field has to be saved in the charserver
For recieving the clients packets, you need to read the first 9 bytes(3 fields) of the packet, than determine the remaining bytes by the length field, and read them (its length+4 because length doesnt include the s field).
The data field's structure:
[(int)unknown][(int)0xffffffff][(int)command_id][command_data]
unknown: yet again. 4 bytes to be skipped
0xffffffff: this value is constant. allways -1
command_id: this integer determines what to do with the upcomeing data (if any)
command_data: this field's size is determined by the command_id (but it doesnt exceed the packet's length+4!).
Its usually uses the s field for data storage as well.
The client allways sends only 1 command per packet.
Server's packet structure
These are packets sent by the server to the client
[(byte)0x5e][(int)length][data]
0x5e: starts every packet
length: length of the data field in bytes
data: commands/answers to the client
This is basically the same as the clients structure above, without the unknown fields, and without the s field.
The data field's structure:
Loginserver and characterserver:
These servers only send 1 command per packet.
[(int)command_id][command_data]
command_id: determines what to do with the upcomeing data
command_data: size is determined by the command_id, same as above just note there is no s field.
Worldserver:
This server may send multiple commands per packet.
[(int)a][(int)character_id][(short)ncommands][commandfield]
a: this is usually 0xffffff00, except at the first packet sent by the worldserver, where its 0x0000ff00
character_id: the character's id wich is logged in on the client wich this packet is sent to.
ncommands: number of commands in the comand field
The command field's structure:
The command field is consist of ncommands number of commands with the following structure:
[(int)character_id][(short)command_id][command_data]
character_id: the character's id wich is the subject to the command (ex.: if the command_id is death, the character with id
character_id will die in each client wich are recieved the packet)
command_id: this determines what will happen to the character with character_id, also it determines the command_data field's
size (migth be 0) (ex.: the command death doesnt require any additional info)
command_data: any info needed by the client to complete the command command_id
A good way to determine where a command starts is checking your character_id at the beginning of the packet (since that id is your char's id if you recorded your gameplay). Than just search for other appearances of this id.
Packets sent by the loginserver to the client:
command_id desc command_data
0 greet [(int)magic]
0xfd server list
0xfe login refuse [(int)error_type] some error types: 0x79: wrong id, 0x78: wrong password, 0x6d: service unavaliable
Packets sent by the client to the loginserver:
command_id desc command_data
0x18 unknown none
0xfc server list request [(pstr)client compile date][(pstr)unknown][(pstr)username][(pstr)password]
packets sent by the characterserver to the client:
command_id desc command_data
0 greet [(int)magic]
0x0b [(int)s][(int)magic][(int)magic]
0x11 first packet after login [(int)magic][(int)magic][(int)magic][(int)magic]
0x14 this should only be sent after [(int)s] (sends back the last saved s field)
the client authenticated itself
the client will keep calling this while it runs, and the characterserver should allways repply, else the player gets dc.
0xf2 only sent after authentication [(pstr)serverip]
0xf3 character informations [(int)s][(int)n_chars][character_data][(int)n_chars][additional_data]
nchars=number of characters
character data sent n_chars times, with the data of the nth char.
additional_data sent n_chars times, structure:
[(byte)0][(int)0][(int)0][(int)0]
packets sent by the client to the character server:
0x0b unknown none
0x11 should answer with 0x14 if none
the client isnt authenticated
itself yet, nothing otherwise
0x14 answers with 0x0b without the character list shown, 0x14 after
0xf4 character create [(pstr)username][(pstr)password][(byte)slotid][(pstr)character_name]
slotid: 0=left, 1=middle, 2=rigth
0xf5 character delete [(pstr)username][(pstr)password][(pstr)unknown][(int)character_id]
0xf6 character list [(pstr)unknown_date][(pstr)username][(pstr)password]
0xff05 last packet before worldserver [(pstr)user][(int)unknown][(pstr)character_name]
The characterserver has a pretty nice "dance" here, if you make one step wrong, the client migth freeze.
The authentication is complete when the client send your username and password the first time (the characterserver will repply to this packet with the character list)
The dance is like this:
if Client sends 0x0b, server repplies with 0x11
if the client sends 0x11, the server repplies 0x14 ONLY if the client hasnt autheticated yet
if the client sends 0x14, the server repplies 0x0b if not authenticated, 0x14 if authenticated
if the client sends 0xf6, itll get authenticated, and the server should send 0xf2 (ip), than 0xf6(charlist) rigth after
from hereon the charserver shouldnt do anything, (itll just keep repplying to the clients 0x14's with 0x14's, (else the client will get dc))
after you choosen your character, the client will send a 0xff05, and connect to the worldserver after it recieved the answer from 0xff05
Worldserver:
I begin with some text here.
For the first packet, you recieve a damn long and big and important and whatnot packet.
Its a spawning packet, basically spawns your character into the world. And its contains nearly every damn information to do it.
command_id desc structure
0xf0 spawn, damn lot of variations of this packet
0xf1 desapwn(remove) none
0xf2 mapchange [(int)mapid][(float)x][(float)y][(float)z]
0x98 special motions [(int)motion id] (ex.: 4=sitdown/standup)
0xc1 movetoxyz [(float)x][(float)y][(float)z][(byte)1]
0xc2 movetochar [(int)character_id][(int)0]
0xc7 death [(int)killer_character_id][(int)0x29]
0xc8 teleport [(float)x][(float)y][(float)z][(int)0][(int)0][(int)0][(int)0][(int)1][(int)0][(int)0][(int)-1][(int)4][(int)0][(int)0][(int)0]
0xcb motionok [(float)x][(float)y][(float)z]...etc...
0xcc flying [(float)x][(float)y][(float)z]...etc...
0xe0 attackmotion [(int)motion_id][(int)target_character_id][(int)0][(int)0x10000]
0x13 damage (numbers) [(int)attacker_id][(int)damage][(int)flags]
0x0f effect(like success/failure) [(int)effect id][(float)x=0][(float)y=0][(float)z=0][(int)0] (if x,y,z=0 here, the client will
use the characters x,y,z who got the command)
0x19 skilleffect [(int)skill_id][(int)skill level][(int)target_character_id][(int)0][(int)3]
0xa0 green text [(byte)1][(pstr)text]
0xd0 shout [(int)shouter_character's id (migth not visible in client)][(pstr)shouter_char_name][(pstr)text]
0x01 chat [(pstr)text]
Well, Although I dont want a source to be released, I also dont want to limit other developers - who like me may have trouble figuring out the packets... Took me a while to understand them too.
So I'll list here packet information as I figure it out, that way someone with enough coding knowledge can create a private server, and we still keep the private server numbers rather low. I'm starting to day with the Login server, I'll post the Character server, and known packets of the world server tomorrow as I'm lazy... LOL Key 4 Bytes - Integer, Hash 2 Bytes - Short 8 Bytes - Long * - When I have a * before INT, it means the integer is little edianed. (http://en.wikipedia.org/wiki/Endianness#Little-endian), this is on server packets and client packets, if I use the * on a server packet, it means you need to make it little edian, if I use it on a client packet, it means its already little edian, so you gotta change it back to normal. Not sure if ALL intergers are like this, I dont think I've come across one that isnt yet, but I'll let you know in the future. When I use "INT-Length" it means the length of the data following those 4 bytes (As an Integer). When I use "##-Command" it means the as 4 bytes, ## being the command. Comments made by me for extra info (like the one about capacitys on eFlyff) are bold, followed by italics. Common Packets First thing the server does after receiving a connection is it sends a session key. Length: 13 Structure Code:
[5E] [INT-Length] [00] [00] [00] [00] [00] [00] [00] [00] Login Server Remember, after receiving a connection, the server sends the session key. Login packet (Client -> Server) Structure Code:
[5E] [HASH-Length] [INT-Length] [HASH-Data] [INT-Data] [FC-Command] [INT-Length] [Date-Reversed] [*INT-Length] [Data-Note#1] [*INT-Length] [Username] [*INT-Length] [Password] Incorrect Login (Server -> Client) Length: 13 Structure Code:
[5E] [INT-Length] [FE] [00] [00] [00] [Data-Note#2] [00] [00] [00] Types Code:
[27] - Opps try again. [77] - This ID has been blocked [78] - Wrong password [79] - Wrong ID [80] - Your time is up [81] - Other DB Error [83] - You cannot connect after 22:00 [84] - You cannot connect from outside the service for Flyff. [85] - Your character is being checked at the moment. Please login after a while. [86] - Wrong password, cannot log into account for 15 seconds. [87] - Wrong password three times, cannot log into account for 15 minutes. [88] - Server verification error. [89] - Session is over. please try again. [6D] - Service is currently unavailable, please check Flyff site for details. [FF] - Connecting please wait... [67] - This account is already connected. (Yes/No) Ok so they logged in correctly, YAY lets send the server list. Structure Code:
[5E] [INT-Length] [FD-Command] [Note#3] [INT-Length] [Username] [0B] [00] [00] [00] [FF] [FF] [FF] [FF] [*INT-Server ID] [*INT-Length] [Server Name] [*INT-Length] [Server IP] [00] [00] [00] [00] [00] [00] [00] [00] [01] [00] [00] [00] [00] [00] [00] [00] [*INT-Cluster ID] [*INT-Channel ID] [*INT-Length] [Channel Name] [00] [00] [00] [00] [00] [00] [00] [00] [*INT-Online Players] [01] [00] [00] [00] [*INT- Channel Capacity] Note #3: I dont know what these 5 bytes are, never really looked into it, chances are its a hash of some sort of the following data, anyway eFlyff uses [FE] [CE] [84] [B0] [01] (and so do I, and it works :P) Handy Info Flyff channels can store 1100 players each (Maybe they're done that to optimize lag? Presuming they have the money for the best servers... they've limited it to that for a reason, where FlyForFame (havent checked exactly) have gone waaaay over 1100 (GM Notices boasting about 2k+) and its VERY laggy... Also thought I'd mention, if you sit on the server selection screen doing nothing, client sends (roughly every minute) this packet: Code:
[5E] [94] [A7] [D8] [58] [04] [00] [00] [00] [0B] [F0] [C1] [08] [14] [00] [00] [00] Its totally up to you xD Database At this point, I (think) my database was structured like this (may be wrong cause I cant exactly go back in time :(. Accounts - ID - Username - Password - Banned - Last_IP Clusters - ID - Name - IP Channels - ID - Cluster - Name - Capacity ---------------------------------------------------------------------------------------------------------------------------- Righteo, and to start the Character server, I'll see how far I get before I get bored of typing, also I'm not sure on the order of these packets, but then you shouldn't be coding your server to run in order anyway. First things first, dont forget on connection to send the session key. Authentication I'm not going to explain Authentication, its alot of information and I'm to lazy to post it, check the other thread here about the Flyff Packet structure, it explains Authentication. Server Select (Client -> Server) After selecting a server, it then connects to the Character server, and authenticates. Character server packets are identified by the 17th byte. Packet command: [F6] This packet contains date, verification hash, username & password. Your server should check this information is correct, and then send back the characters that belong to this person. Character Display (Server -> Client) Structure Code:
[5E] [INT-Size] [F3] [00] [00] [00] [Data - Note #4] [00] [00] [00] [00] [*INT-Slot] [INT-Length] [INT-Map ID] [0B] [00] [00] [00] [*INT-Length] [Char-Name] [Float-X] [Float-Y] [Float-Z] [*Char-ID] [00] <- x 16 [*INT-HairStyle] [INT-HairColor] [*INT-Face] [INT-Gender (0/1)] [*INT-Job] [*INT-Level] [00] [00] [00] [00] [*INT-STR] [*INT-STA] [*INT-DEX] [*INT-INT] [00] [00] [00] [00] [INT-Note#5] [INT-Note#6] ..... Once you've added all your chars... Code:
[*INT-LastCharSlot] [*INT-Note#7] Note #5: This is an INT, of how many items the person has equiped (Only counting... helmet, suit, gaunlets, boots, cs helmet, cs boots, cs gaunlets, cs suit, cloak, weapon & shield/weapon 2. Note #6: This is the ID's of each item, 1 after the other. Note #7: Depending on how many chars there were you add this times char amount. Code:
[*INT-Char #] [00] [00] [00] [00] [00] ... Hope thats helpful to someone, and that it makes some sense x_X I dont think I'll be posting anymore as its rather hard to change my code back into packets xD... but if I do I'll take you guys right up to the World spawn, cause that packet is insanely large and I dont want to explain it... Good Luck ^_^ ------------------------------------------------------------ Note If you want to learn how to code a server, heres some stuff packages to look up in java: (These are the imports im currently using). java.net.ServerSocket java.net.Socket java.util.Vector java.util.Enumeration java.io.* - ByteArrayOutputStream - OutputStream - IOException java.sql.* java.util.zip.CRC32 Enjoy, and have fun coding ;) P.S Sorry about my spelling & grammer, I know its not the greatest, but hopefully its readable :| Edit: Attached is the document I used to figure out the structure of the Clusters list, got to the second cluster before I saw the pattern, someone might find it handy... maybe? Also - someone needs to add ".docx" to the valid uploads list x_X *** UPDATED *** Credits for packet breakdowns DeadlyData GlaphanKing GZP ανєяηιкαѕ Part III Learning a Coding language and Starting your source! The two most famous Flyff emulator coding language is c++ and c# You can either 1. Learn it in college 2. Use Online tutorials. Some great tutorial sites for learning c++ is www.cplusplus.com/doc/tutorial/ www.cprogramming.com/tutorial.html And some great sites for learning c# is www.functionx.com/csharp/index.htm http://www.softsteel.co.uk/tutorials.../contents.html www.java2s.com/Tutorial/CSharp/CatalogCSharp.htm Once you've started to capture packets you now Hide them, then seek them and add them to the source. a source could be a .cpp or .h File. It would be Ideal to .have . cpp or c# files that have actually coding in it [Both of these will be explained don't worry] .cpp also known as C++ Source Code Files Cpp is a Program source code written in the C++ programming language; may be a standalone program or one of many files referenced within a programming project; can be viewed with a text editor, but most software development programs will display the text with helpful syntax highlighting. More Stuff will be added! Break Down of a Cpp file Code:
Breakdown of a source code (.cpp) file
A file comment description codeblock.
It is formatted the same as the header file.
//----------------------------------------------------------------------------------------
/*!
\file bookmark_dialog.cpp
\modified
\copyright (c) Robert O'Connor ( rob@medicalmnemonics.com )
\licence GPL
\brief Describes bookmark_dialog class
\author Robert O'Connor
\date 2002/01/03
*/
// RCS-ID: $Id: included_breakdown_cpp.html,v 1.1 2002/09/02 02:27:13 robertoconnor Exp $
//----------------------------------------------------------------------------------------
GCC implementation codeblock.
This is the second part of the GCC #pragma interface/implementation combo. It goes as the first line. This #pragma tells the compiler that is the one and only .cpp file that should hold the debug info for the class. It should be the header of this class. Turned off for APPLE, since OSX Jaguar doesn't like it (or need it).
//----------------------------------------------------------------------------------------
// GCC implementation
//----------------------------------------------------------------------------------------
#if defined(__GNUG__) && ! defined(__APPLE__)
#pragma implementation "bookmark_dialog.h"
#endif
Application setup.h codeblock:
Include the application's setup.h file, so that we can remove everything in the next part, if the feature is one that we want to compile out.
//----------------------------------------------------------------------------------------
// Setup information
//----------------------------------------------------------------------------------------
#include "setup.h"
Start feature removal codeblock:
Same idea as header had.
//----------------------------------------------------------------------------------------
// Begin feature removal condition
//----------------------------------------------------------------------------------------
#if ( setupUSE_INTEGRATED_HTML_EDITOR )
Standard wxWindows headers codeblock:
A block that will be the same unchanged in every single .cpp file of the project. (You can skip reading through the details of it if you what if you don't care about what is going on).
//----------------------------------------------------------------------------------------
// Standard wxWindows headers
//----------------------------------------------------------------------------------------
This includes the headers for the compilers that support precompiled headers to increase compile speed of the application.
// For compilers that support precompilation, includes "wx/wx.h".
#include "wx/wxprec.h"
The #pragma hdrstop for BCC tells the compiler that all the headers above that pragma are the same same (which they are, since BCC compiler won't see the #pragma interface of GCC). BCC has precompiled headers which will greatly speed up compile time, but for it to work, everything above #pragma hdrstop has to be the same for all the .cpp files. Therefore put the headers that are unique to this file after this #pragma hdrstop.
#ifdef __BORLANDC__
#pragma hdrstop
#endif
If it isn't a compiler that can support precompiled headers, then just include a long list of the most commonly used headers in the wxWindows library, like windows, strings, etc.
// For all others, include the necessary headers (this file is usually all you
// need because it includes almost all "standard" wxWindows headers)
#ifndef WX_PRECOMP
#include "wx/wx.h"
#endif
Header of this .cpp file codeblock
//----------------------------------------------------------------------------------------
// Header of this .cpp file
//----------------------------------------------------------------------------------------
#include "bookmark_dialog.h"
Remaining headers codeblock:
These are the unique headers needed by this class. For better sourcecode organization, they are always arranged in the order of first the wxWindows library headers required by the class, then any wxWindows/contrib headers required (often just the XRC resources header), then finally any headers of the application.
//----------------------------------------------------------------------------------------
// Remaining headers: Needed wx headers, then wx/contrib headers, then application headers
//----------------------------------------------------------------------------------------
#include "wx/xrc/xmlres.h" // XRC XML resouces
//----------------------------------------------------------------------------------------
#include "utils_controls.h"
#include "help_controller.h"
Internal constants codeblock (some classes)
Some classes may use some internal constants, such as id numbers for a popup menu, list columns, etc. If so, these internal constants should go into this block.
//----------------------------------------------------------------------------------------
// Internal constants
//----------------------------------------------------------------------------------------
// Popup menu (PU) item IDs
enum {
PU_ADD_CHANNEL = wxID_HIGHEST + 2,
PU_ADD_CHANNEL_WIZARD,
PU_CONFIGURE_CHANNEL
};
DECLARE_DYNAMIC/ABSTRACT_CLASS codeblock:
If the header had a DECLARE_DYNAMIC_CLASS(), then a IMPLEMENT_DYNAMIC_CLASS() now needs to go here. If it was DECLARE_ABSTRACT_CLASS() in the header it wold be a IMPLEMENT_ABSTRACT_CLASS() here instead.
//----------------------------------------------------------------------------------------
// wxWindows macro: implement dynamic class
//----------------------------------------------------------------------------------------
IMPLEMENT_DYNAMIC_CLASS( bookmark_dialog, wxDialog )
Event table codeblock (classes that want to handle events):
This is the event table for the class. This is used for you to connect a certain event to a certain custom function.
//----------------------------------------------------------------------------------------
// Event table: connect the events to the handler functions to process them
//----------------------------------------------------------------------------------------
BEGIN_EVENT_TABLE( bookmark_dialog, wxDialog )
Entries for children of the class have 3 parts:
-EVT_BUTTON: What type of event it is that should be connected to the custom function (a button click event)
-wxID_HELP_CONTEXT: Only events raised by buttons by that ID will be sent to the custom function. wxID_HELP_CONTEXT is a special ID nubmer define for the help button. The ID number of -1 would specify events raised by all buttons.
-bookmark_dialog::on_help_button: This is the custom function that should be fired by button events raised by the buttons with an ID of wxID_HELP_CONTEXT.
EVT_BUTTON( wxID_HELP_CONTEXT, bookmark_dialog::on_help_button )
EVT_BUTTON( wxID_OK, bookmark_dialog::OnOK )
If the event is raised by a some child control in the XML resources, then just specify the control with a XRCID() macro. In this hypothetical example, only button click events named "bookmark_dialog_preferences_button" in the XRC file will trigger the on_preferences_button() function.
EVT_BUTTON( XRCID( "bookmark_dialog_preferences_button" ), bookmark_dialog::on_preferences_button )
An event raised by the class itself for example the event of this dialog closing obviously doen't need an identifier, so just 2 parts here:
-EVT_CLOSE: Only close events will be sent to the custom function.
-on_close(): The custom function that should be fired.
EVT_CLOSE( main_frame::on_close )
END_EVENT_TABLE()
Public members codeblock:
A block of what the public members of the class should do. The first member is the constructor, then the destructor, then the rest.
//----------------------------------------------------------------------------------------
// Public members
//----------------------------------------------------------------------------------------
bookmark_dialog::bookmark_dialog( wxWindow* parent )
{
wxXmlResource::Get()->LoadDialog( this, parent, "bookmark_dialog" );
}
bookmark_dialog::~bookmark_dialog()
{
}
void bookmark_dialog::transfer_to( wxString& starting_text, wxString& ending_text )
{
starting_text = m_starting_text;
ending_text = m_ending_text;
}
Protected members codeblock:
A block of what the protected members of the class should do, if there is any.
//----------------------------------------------------------------------------------------
// Protected members
//----------------------------------------------------------------------------------------
Private members codeblock:
A block of what the private members of the class should do.
//----------------------------------------------------------------------------------------
// Private members
//----------------------------------------------------------------------------------------
void bookmark_dialog::OnOK( wxCommandEvent& event )
{
wxString output_string;
wxString buf;
output_string = "<a";
wxString name_string = XRCCTRL( *this, "bookmark_dialog_name_textctrl", wxTextCtrl )->GetValue();
output_string += " name=\"" + name_string + "\">";
wxString description_string = XRCCTRL( *this, "bookmark_dialog_description_textctrl", wxTextCtrl )->GetValue();
output_string += description_string;
output_string += "</a>";
// Store the starting and ending strings as class members, ready to be transferred
// by transfer_to(...) method.
m_starting_text = output_string;
m_ending_text = "";
// Get rid of the modal dialog. Not transferring any info from this modal's control
// to a parent dialog, so don't have to bother with wxWindow::Validate or
// wxWindow::TransferDataFromWindow.
EndModal( wxID_OK );
}
void bookmark_dialog::on_help_button( wxCommandEvent &event )
{
#if ( setupUSE_ONLINE_HELP )
help_controller::get()->show_help_topic( plkrHELP_ID_BOOKMARK_DIALOG );
#endif
}
Module definition block (only a few global classes):
Not in bookmark_dialog, but in a few classes such as plucker_controller, help_controller, and commandline_parser, you will see they are set up with wxModules. These wxModules remove the requirement and headaches of creating and cleaning up globals. To use a wxModule instead of a global, there is a derived class wxModule definition down at the bottom of the class's .cpp file (the module doesn't need to be mentioned in any header anywhere).
Before the program 'starts' any execution, it gets a list of all the modules in the application and runs all of their OnInit() functions (which will do nothing in this application; they just return TRUE). After the program 'ends', then all of the wxModule's OnExit() functions are called, which will clean up the classes managed by the wxModule.
Each of the classes managed by wxModule have a get() and set() method which gets or sets the single instance. By calling some_class::get() you can create an instance on demand if there isn't one yet, but retrieve the existing instance if there is one already made. For example, see the call to help_controller::get()->show_help_topic(plkrHELP_ID_BOOKMARK_DIALOG) in the bookmark_dialog::on_help_button() above: it will get the single help_controller and call its show_help_topic() method if it exists already, or else create one on demand and then do its show_help_topic() method.
//----------------------------------------------------------------------------------------
// Module definition
//----------------------------------------------------------------------------------------
class module_body_dialog : public wxModule
{
DECLARE_DYNAMIC_CLASS( module_body_dialog )
public:
module_body_dialog() {}
bool OnInit()
{
return TRUE;
}
void OnExit()
{
wxLogDebug( "Entered module_body_dialog::OnExit()" );
// We set it to null, and a pointer returns to the previous one, which we delete.
delete body_dialog::set( NULL );
wxLogDebug( "Completed module_body_dialog::OnExit()" );
}
};
IMPLEMENT_DYNAMIC_CLASS( module_body_dialog, wxModule )
Break Down of a c# Source File Code:
any programming languages have well defined standards for documenting source code. These standards are useful in that they allow developers to add comments to code in a uniform format. Furthermore, it is possible to use tools to extract the documentation from an entire application's source code and use it to automatically produce project technical documentation in a fraction of the time it would take to manually produce the documentation.
Programming languages such as Java have had code documentation standards for many years. The Java system is called JavaDoc, and allows developers to easily create HTML format documentation from project source code.
Since classic Active Server Pages (ASP) has no defined standards of source code documentation, ASP web application documentation of source code can vary enormously from project to project. While applications such as our ASP Documentation Tool can create technical documentation from ASP source code, lack of a defined documentation standard is a major limitation of ASP. Visual Basic 6.0 is similarly affected by a lack of documentation standards (although our VB Documentation Tool resolves this).
Thankfully with the introduction of the .NET Framework and the new C# programming language, Microsoft included some form of code documentation standards - XML Comments. These were further enhanced with the 2.0 release of the .NET Framework (which also allowed XML comments to be used with VB.NET.
Commenting C# source code
XML comments are added to source code by prefixing the XML comment lines with three forward slashes. Visual Studio will automatically insert a documentation template whenever three forward slashes are typed within a C# source code file. Visual Studio's intellisense system also works within XML comments, using the comments to enhance the information presented about a class, constructor or other member.
Although these comments can potentially be added to the source code at any point, it is usual to ensure that documentation is inserted immediately before the definition of classes, functions, subroutines and properties, thereby allowing these members to be documented. An example of a function documented with XML comments is shown below:
/// <summary>
///<para>Non-HTML files like Adobe Acrobat PDF files and Word
///documents are stored with their original URLs partially
///encoded in their filenames. This function will return the
///original URL of the file.</para>
///<para>The encoding done by the Index Server Companion removes
///characters that cannot be present in Windows filenames
///(these are: \/:*?"<>|). The decoding performed is:</para>
/// <list type="table">
/// <listheader><term>Find</term><description>Replace</description></listheader>
/// <item><term>^f</term><description>\</description></item>
/// <item><term>^b</term><description>/</description></item>
/// <item><term>^c</term><description>:</description></item>
/// <item><term>^s</term><description>*</description></item>
/// <item><term>^q</term><description>?</description></item>
/// <item><term>^d</term><description>\</description></item>
/// <item><term>^l</term><description><</description></item>
/// <item><term>^g</term><description>></description></item>
/// <item><term>^p</term><description>|</description></item>
/// </list>
/// </summary>
/// <param name="FileName">The document's original filename.</param>
/// <returns>Decoded filename</returns>
/// <exception cref="System.Exception">Throws an exception when something goes wrong.</exception>
private string CreateURLFromFileName(string FileName)
{
try
{
//Remove o_ prefix from URL
FileName = FileName.Substring(2, FileName.Length - 2);
//Remove other encoded characters
FileName = FileName.Replace("^f", "\\");
FileName = FileName.Replace("^b", "/");
FileName = FileName.Replace("^c", ":");
FileName = FileName.Replace("^s", "*");
FileName = FileName.Replace("^q", "?");
FileName = FileName.Replace("^d", "\"");
FileName = FileName.Replace("^l", "<");
FileName = FileName.Replace("^g", ">");
FileName = FileName.Replace("^p", "|");
FileName = FileName.Replace("^f", "\\");
FileName = FileName.Replace("^f", "\\");
FileName = FileName.Replace("^f", "\\");
FileName = FileName.Replace("^f", "\\");
}
catch
{
}
return FileName;
}
This example shows that as well as a general description of the function's purpose, the function's arguments and return values can also be documented using standard syntax. There are also clearly defined standards for cross-referencing the documentation, adding hyperlinks, lists, tables and code samples. The MSDN documentation for the .NET Framework describes all of the XML comment standard markup supported by the .NET Framework. It is also possible to use your own XML tags within the comments.
The "official" XML comment tags
The following XML comment tags are officially supported in C#: c,code, example, exception, include, list, para, param, paramref, permission, remarks, returns, see, seealso, summary and typeparam.
c: This tag is used to denote code, so it can be used to identify sample code associated with a particular entity within the source code. Note that the tag can only be used to represent a single line of code or to denote that some of the text on a line should be marked up as code. Example: <c>double SalesTotal = 12</c>
code: This tag is used to denote more than one line of code, so it can be used to identify longer areas of sample code.
example: This tag may be used to describe an example of using a particular method or class. It is possible to include code samples within the example tag by making use of either the c or code tags.
exception: The exception tag allows a method's exception handling to be documented. The cref attribute allows the namespace of the exception handler to be included. Example: <exception cref="System.Exception" >Throws an exception if the customer is not found.</exception>
include: This tag allows documentation to be imported from an external XML file rather than being stored within the source code itself. As such it may be useful if the documentation is written by people other than the software developers (e.g. technical writers).
list: This tag allows bulleted or numbered lists or tables to be added to XML comments.
para: This tag indicates that the text within the tags should be formatted within a paragraph. As such it can be used to format text within other tags such as summary or returns. Example: <para>This is a paragraph</para>
param: The param tag is used to document a method's arguments. The tag's name attribute specifies the name of the argument to which the tag refers. The tag is also used by Visual Studio's Intellisense system to show a description of a method's arguments. It is also used by the Visual Studio Object Browser. Example: <param name="FileName" >The filename of the file to be loaded.</param>
paramref: This tag can be used to refer to a method's argument elsewhere within the method's XML comments. The tag's name attribute specifies the name of the argument to which the tag refers. Note that the param tag is actually used to describe the parameter. Example: Use the <paramref name="FileName"/> argument to specify which filename is loaded.
permission: The permission tag can be used to describe any special permissions a specific object needs. The object to which the permission refers is included as the cref attribute. Example: Class needs to write to the file system, ensure user has appropriate access.
summary: The summary tag describes a method or class, so it is the most important tag. As well as being used in a project's documentation, the tag is also used by Visual Studio's Intellisense system to show a description of the method or class being referenced. It is also used by the Visual Studio Object Browser.
remarks: The remarks tag can be used to supply additional information about a method or class, supplementing the details given in the summary tag. As with the summary tag, this tag is also used by Visual Studio's Intellisense system and the Visual Studio Object Browser.
returns: Describes the return value of a method. Example: <returns>True if user has permission to access the resource, otherwise False.</returns>
see: The see tag is used to reference other entities (such as classes) in the project. The see tag is intended for use within other tags such as the summary tag. Example: <seealso cref="System.Configuration"/>
seealso: The seealso tag resembles the see tag and has identical syntax, except that the text is intended to be used to create a separate seealso section for the entity's documentation.
typeparam: Typeparam is used in an identical way to param, except that it is used to document a type associated with a generic class or function.
value: Value is only used when documenting a property, and is used to describe the value assigned to that. The comment is not required for properties that are marked as read only. Example: <value>Sets the employee's salary</value>
What to do with the documented code
Once the XML comments have been added to the code, it is useful to be able to do something with them. Although code documented in a standard format is an obvious benefit, XML comments allow much more to be done with the source code.
Visual Studio allows the comments to be compiled to an XML file. Although this is a useful feature, the XML file should be considered an intermediate documentation format rather than finished project documentation. Simple documentation can be created by applying an XSL stylesheet to the XML file in order to produce a more easily readable HTML version of the documentation. Here is a simple example of how to implement a suitable XSL stylesheet: Simple XSLT stylesheet for Visual Studio .NET XML documentation.
If you want more comprehensive documentation, our .NET Documentation Tool product creates documentation from C# source code (VB.NET is also supported).
Summary & Conclusions
Hopefully this article will encourage you to add XML comments to your C# source code. Whether you are working for a company or for yourself, well commented code always looks professional, and can help give you the competitive edge over other developers and businesses.
http://desktop.plkr.org/docs/develop...kdown_cpp.html More will be added
__________________
Last edited by FrostElite; 10-13-2008 at 02:22 AM. |
|
||
| permalink | ||||
| FrostElite |
| View Public Profile |
| Find More Posts by FrostElite |
RaGEZONE is proudly sponsored by
|
|
|
|
FlyForFame
Rank: Subscriber
|
Mmmmm sexy add more!
__________________
FlyForFame FaceBookGroup |
|
||
| permalink | ||||
|
Alpha
Rank: New Blood
|
Maaan, thats sexy... Cheers.. I am into learning languages now.. RageZone pushed me...
Thanks alot man... By the way.. do you know what should i start from... on some other forums i asked, people said first learn QBasic, then VisualBasic, and then C# and C++ . What you think Elite ? |
|
||
| permalink | ||||
|
cout << "Hello World \n";
Rank: Member
|
Maaan, thats sexy... Cheers.. I am into learning languages now.. RageZone pushed me...
Thanks alot man... By the way.. do you know what should i start from... on some other forums i asked, people said first learn QBasic, then VisualBasic, and then C# and C++ . What you think Elite ?
__________________
|
|
||
| permalink | ||||
| FrostElite |
| View Public Profile |
| Find More Posts by FrostElite |
|
为您服务
Rank: Member
|
w0w... this is cool dude, ill start to dev my own also...xD
|
|
||
| permalink | ||||
|
The Omega
Rank: New Blood
|
WoW nice guide, it work? :D
|
|
||
| permalink | ||||
|
cout << "Hello World \n";
Rank: Member
|
Alright good luck with that ;] if you have any questions just ask
__________________
|
|
||
| permalink | ||||
| FrostElite |
| View Public Profile |
| Find More Posts by FrostElite |
|
Alpha
Rank: New Blood
|
Wow Thanks a lot i'll try it but its much work...
|
|
||
| permalink | ||||
| Blackclown |
| View Public Profile |
| Find More Posts by Blackclown |
|
cout << "Hello World \n";
Rank: Member
|
Yea, it' alot we're still at the beginning ;P
__________________
|
|
||
| permalink | ||||
| FrostElite |
| View Public Profile |
| Find More Posts by FrostElite |
|
cout << "Hello World \n";
Rank: Member
|
__________________
|
|
||
| permalink | ||||
| FrostElite |
| View Public Profile |
| Find More Posts by FrostElite |
|
Crazy flyff doctor
Rank: Member
|
Nice thanks for us, but more job for understand and do the tuto.
|
|
||
| permalink | ||||
| ayboangelus |
| View Public Profile |
| Find More Posts by ayboangelus |




