[crossfire] 2.0 object-type refactoring

Mark Wedel mwedel at sonic.net
Sun Oct 29 23:35:12 CST 2006


  Few questions:
Use form of server/types/foo.c or server/types/foo/bar.c depending on if the 
object type requires multiple C files to be clean.

  With the fact that the SVN repository is called server, it is unclear exactly 
what server refers to.

If we include the repository name, is it:
server/server/types
server/common (example of existing directory)

Or

server/types
common/ (being the exististing directory)

  IMO, I'd prefer the second form - put the types directory at the top level, 
relative to the server directory.  This is how the socket code is, doesn't have 
any real disadvantage, but could have some advantages (better for unit tests? 
Better for stand alone program that does simulations, etc?)

Function pointers:
It's not specifically mentioned on how the callbacks are registed.  I see one of 
two ways:

  register_apply_callback(type, funcpointer);

  or

  register_callback(type, funcpointer, callback_type)

  Both have pros and cons.  The first case has the advantage that the compiler 
can do actual type checking on funcpointer.  The second has the advantage you 
don't need as many callback functions, and it makes it easier to add new 
callbacks (add the new callback_type #define, update the number of callback 
types, and recompile.  One could even do things like:

callbacks[ob->type][CALLBACK_TYPE](....)

  It's also not really mentioned on how the callbacks themselves are registered 
(that code has to be someplace).  And rather than having a single function that 
registers all the callbacks for all the object types, I'd suggest that each type 
file has something like init_callbacks_weapons (or something).  Then in some 
other place, you have that function that calls all the init_callbacks - having a 
function of MAX_TYPES lines longer is much better than one of MAX_TYPES * 
MAX_CALLBACK_METHODS lines long.

  The other advantage of this is that the individual types files themselves can 
then declare all the functions except the init function static, so that it can't 
be called by other functions.

  I suppose that one could use various system function calls to try and look up 
the function names and call them (presuming a standard naming scheme, like 
init_callbacks_46, where 46 is the type number for that object), but that may be 
overly complicating things.

  Other thoughts:
It may be better working on getting all of this infrastructure/callback methods 
in place, and implementing one type of object using them instead of focusing on 
the specific callback method (the web page mentioned doing all the apply stuff). 
  Why?  That way, if someone does write code for a new object type, all the 
pieces are in place so they can use the new method.  If only the apply callback 
is implemented, they can use that logic, but are left using old coding method 
for the other areas, that then needs to be converted down the road.

  Also, by doing all the different callback methods, it provides better coverage 
of the callback logic, eg, if there are issues with any of the methods, they 
will be found sooner vs later.

Second, if we're going to be writing all new functions, we should use some other 
'best practices'.  In particular, for anything that would return a string value, 
they should be modified so that a string pointer (and length of that pointer) is 
passed in, instead of using static return buffers.  This will assist if we ever 
thread the server, but it will also help prevent a few bugs (related to this, 
sprintf, strcat, and strcpy should never be used, but rather snprintf, strncat, 
and strncpy instead)







More information about the crossfire mailing list