Difference between revisions of "Hacker's Guide"

From OdaWiki
(Getting Started)
(Getting Started)
 
(11 intermediate revisions by 6 users not shown)
Line 1: Line 1:
 
== Getting Started ==
 
== Getting Started ==
  
You'll want to have a look at our [[svn]] and [[bug]] pages.
+
You'll want to have a look at our [[svn]] and [[bugs]] pages.  Also, having familiarity with Doom's usage of [[fixed-point]] numbers would be handy as well.
  
 
== Code structure ==
 
== Code structure ==
Line 20: Line 20:
 
* '''s_*''': sound related code
 
* '''s_*''': sound related code
 
* '''sv_*''': server only code
 
* '''sv_*''': server only code
* '''st_*''': ???
+
* '''st_*''': ??? (mostly hud render related code)
 
* '''v_*''': video related code
 
* '''v_*''': video related code
 
* '''wi_*''': intermission related code
 
* '''wi_*''': intermission related code
Line 31: Line 31:
 
== Style and guidelines ==
 
== Style and guidelines ==
  
* Avoid C style strings. Replace them with C++ types where it is safe to do so.
+
See the [[Coding_standard|coding standard]]
* Code defensively and securely
+
* Do not add globals
+
* Code for clarity
+
* Maintain traditional naming conventions
+
* Respect existing code
+
  
== Networking ==
+
== Subsystems, APIs, and Interfaces ==
 +
Odamex is a very large and deep program with around 13 years worth of hacks and additions added to it.  It can be very daunting to a new developer, so in this section we will try to document some of the interfaces provided by the source and some of the quirks that need to be accounted for.
  
Odamex uses UDP
+
=== Network ===
 +
Odamex uses the User Datagram Protocol (UDP) for its communcations, data may or may not be compressed (server dependant), data is always converted to little endian format.
 +
 
 +
==== Design practices ====
 +
Designing network code isn't an easy task, you must take into account bandwidth usage, server load requirements, security and many other things.
 +
 
 +
Our goal for networking in Odamex is to reduce as much bandwidth and server load usage as possible.. To put it into perspective, if it can be done (ie calculated, executed etc) on the clients machine, then that is the best solution most of the time.
 +
 
 +
We also want to provide good security against cheating, server attacks and such, so robust code must be written to prevent such things happening, the server (and even the master server) should be the most solid foundation, it should resist anything that is thrown at it (oversized buffers, forged packets etc)
 +
 
 +
==== Interface ====
 +
The network interface is rather simple and is composed of multiple Read/Write functions.  These functions wrap converting from host to network byte order, building packets, and sending data.  They are mainly composed of '''MSG_Read*''' and '''MSG_Write*'''  The wildcards can be
 +
replaced with anything from the following table.
 +
 
 +
{|border=1
 +
 
 +
|-
 +
! Function !!Description
 +
 
 +
|-
 +
| '''Functions that write data to a buffer'''
 +
 
 +
|-
 +
| void MSG_WriteMarker(buf_t *, svc_t)
 +
| Writes a data block identifier (from server messages to client)
 +
 
 +
|-
 +
| void MSG_WriteMarker(buf_t *, clc_t)
 +
| Writes a data block identifier (used for client messages to server)
 +
 
 +
|-
 +
| void MSG_WriteBool(buf_t *, bool)
 +
| Writes a boolean (true/false) value
 +
 
 +
|-
 +
| void MSG_WriteByte(buf_t *, int)
 +
| Writes an 8bit value
 +
 
 +
|-
 +
| void MSG_WriteShort(buf_t *, int)
 +
| Writes a 16bit value
 +
 
 +
|-
 +
| void MSG_WriteLong(buf_t *, int)
 +
| Writes a 32bit value
 +
 
 +
|-
 +
| void MSG_WriteFloat(buf_t *, float)
 +
| Writes a 32bit floating point value
 +
 
 +
|-
 +
| void MSG_WriteString(buf_t *, const char *)
 +
| Writes a null-terminated string
 +
 
 +
|-
 +
| void MSG_WriteChunk(buf_t *, const void *, unsigned l)
 +
| Writes a block of data, last parameter is the length
 +
 
 +
|-
 +
|
 +
|
 +
 
 +
|-
 +
| '''Functions that read data from a received buffer'''
 +
 
 +
|-
 +
| bool MSG_ReadBool(void)
 +
| Reads a boolean value
 +
 
 +
|-
 +
| int MSG_WriteByte(void)
 +
| Reads an 8bit value
 +
 
 +
|-
 +
| int MSG_ReadShort(void)
 +
| Reads a 16bit value
 +
 
 +
|-
 +
| int MSG_ReadLong(void)
 +
| Reads a 32bit value
 +
 
 +
|-
 +
| float MSG_ReadFloat(void)
 +
| Reads a 32bit floating point value
 +
 
 +
|-
 +
| const char *MSG_ReadString(void)
 +
| Reads a null-terminated string
 +
 
 +
|-
 +
| void *MSG_ReadChunk(size_t &)
 +
| Reads a block of data, the parameter is the size to read
 +
 
 +
|}
 +
 
 +
 
 +
Miscellaneous network functions and their descriptions are included in the table below.
 +
 
 +
{|border=1
 +
 
 +
|-
 +
! Function !!Description
 +
 
 +
|-
 +
| MSG_BytesLeft(void)
 +
| Returns the number of bytes left in the received buffer
 +
 
 +
|-
 +
| MSG_NextByte(void)
 +
| Returns the next byte (similar to MSG_ReadByte, only it peeks)
 +
 
 +
|-
 +
| SZ_Clear(buf_t *)
 +
| Clears the data from a buffer
 +
 
 +
|}
 +
 
 +
=== Players ===
 +
 
 +
=== Map Objects ===
 +
==== szp pointers ====
 +
 
 +
== Debugging the client on Linux ==
 +
 
 +
There's a problem with breakpoints and SDL under Linux. When a breakpoint pauses execution, the client keeps a lock on the mouse and keyboard (you can no longer do anything). If you kill the client process, you lose the breakpoint info. The current workaround is to use the [[nomouse|-nomouse]] commandline parameter.

Latest revision as of 16:33, 11 August 2012

Getting Started

You'll want to have a look at our svn and bugs pages. Also, having familiarity with Doom's usage of fixed-point numbers would be handy as well.

Code structure

Conventional file prefix

  • am_*: automap related code
  • c_*: console related code
  • cl_*: client only code
  • d_*: game/net code
  • f_*: finale related code
  • g_*: game related code
  • hu_*: hud related code
  • i_*: system/hardware dependant code
  • m_*: ???
  • p_*: game/object related code
  • r_*: render related code
  • s_*: sound related code
  • sv_*: server only code
  • st_*: ??? (mostly hud render related code)
  • v_*: video related code
  • wi_*: intermission related code
  • z_*: memory allocation related code

Files of interest

  • i_main.cpp: application entry point

Style and guidelines

See the coding standard

Subsystems, APIs, and Interfaces

Odamex is a very large and deep program with around 13 years worth of hacks and additions added to it. It can be very daunting to a new developer, so in this section we will try to document some of the interfaces provided by the source and some of the quirks that need to be accounted for.

Network

Odamex uses the User Datagram Protocol (UDP) for its communcations, data may or may not be compressed (server dependant), data is always converted to little endian format.

Design practices

Designing network code isn't an easy task, you must take into account bandwidth usage, server load requirements, security and many other things.

Our goal for networking in Odamex is to reduce as much bandwidth and server load usage as possible.. To put it into perspective, if it can be done (ie calculated, executed etc) on the clients machine, then that is the best solution most of the time.

We also want to provide good security against cheating, server attacks and such, so robust code must be written to prevent such things happening, the server (and even the master server) should be the most solid foundation, it should resist anything that is thrown at it (oversized buffers, forged packets etc)

Interface

The network interface is rather simple and is composed of multiple Read/Write functions. These functions wrap converting from host to network byte order, building packets, and sending data. They are mainly composed of MSG_Read* and MSG_Write* The wildcards can be replaced with anything from the following table.

Function Description
Functions that write data to a buffer
void MSG_WriteMarker(buf_t *, svc_t) Writes a data block identifier (from server messages to client)
void MSG_WriteMarker(buf_t *, clc_t) Writes a data block identifier (used for client messages to server)
void MSG_WriteBool(buf_t *, bool) Writes a boolean (true/false) value
void MSG_WriteByte(buf_t *, int) Writes an 8bit value
void MSG_WriteShort(buf_t *, int) Writes a 16bit value
void MSG_WriteLong(buf_t *, int) Writes a 32bit value
void MSG_WriteFloat(buf_t *, float) Writes a 32bit floating point value
void MSG_WriteString(buf_t *, const char *) Writes a null-terminated string
void MSG_WriteChunk(buf_t *, const void *, unsigned l) Writes a block of data, last parameter is the length
Functions that read data from a received buffer
bool MSG_ReadBool(void) Reads a boolean value
int MSG_WriteByte(void) Reads an 8bit value
int MSG_ReadShort(void) Reads a 16bit value
int MSG_ReadLong(void) Reads a 32bit value
float MSG_ReadFloat(void) Reads a 32bit floating point value
const char *MSG_ReadString(void) Reads a null-terminated string
void *MSG_ReadChunk(size_t &) Reads a block of data, the parameter is the size to read


Miscellaneous network functions and their descriptions are included in the table below.

Function Description
MSG_BytesLeft(void) Returns the number of bytes left in the received buffer
MSG_NextByte(void) Returns the next byte (similar to MSG_ReadByte, only it peeks)
SZ_Clear(buf_t *) Clears the data from a buffer

Players

Map Objects

szp pointers

Debugging the client on Linux

There's a problem with breakpoints and SDL under Linux. When a breakpoint pauses execution, the client keeps a lock on the mouse and keyboard (you can no longer do anything). If you kill the client process, you lose the breakpoint info. The current workaround is to use the -nomouse commandline parameter.