aboutsummaryrefslogtreecommitdiff
path: root/src/libparsec/obj_cust.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/libparsec/obj_cust.cpp')
-rw-r--r--src/libparsec/obj_cust.cpp361
1 files changed, 361 insertions, 0 deletions
diff --git a/src/libparsec/obj_cust.cpp b/src/libparsec/obj_cust.cpp
new file mode 100644
index 0000000..fcd997c
--- /dev/null
+++ b/src/libparsec/obj_cust.cpp
@@ -0,0 +1,361 @@
+/*
+ * PARSEC - Custom Object Types
+ *
+ * $Author: uberlinuxguy $ - $Date: 2004/09/26 03:43:44 $
+ *
+ * Orginally written by:
+ * Copyright (c) Clemens Beer <cbx@parsec.org> 2001
+ * Copyright (c) Markus Hadwiger <msh@parsec.org> 1999
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+// C library
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+// compilation flags/debug support
+#include "config.h"
+#include "debug.h"
+
+// general definitions
+#include "general.h"
+#include "objstruc.h"
+
+// global externals
+#include "globals.h"
+#ifdef PARSEC_SERVER
+ #include "e_world_trans.h"
+#endif // PARSEC_SERVER
+
+// local module header
+#include "obj_cust.h"
+
+// proprietary module headers
+//#include "obj_ctrl.h"
+
+
+
+// string constants -----------------------------------------------------------
+//
+static char custom_type_invalid[] = "invalid custom object type.";
+
+
+// custom type table ----------------------------------------------------------
+//
+int num_custom_types = 0;
+custom_type_info_s custom_type_info[ MAX_NUM_CUSTOM_TYPES ];
+
+
+// look up custom type via name -----------------------------------------------
+//
+dword OBJ_FetchCustomTypeId( const char *name )
+{
+ ASSERT( name != NULL );
+
+ // search for type name in table
+ for ( int tid = 0; tid < num_custom_types; tid++ )
+ if ( strcmp( custom_type_info[ tid ].type_name, name ) == 0 )
+ return custom_type_info[ tid ].type_id;
+
+ return TYPE_ID_INVALID;
+}
+
+
+// determine type name of custom type -----------------------------------------
+//
+const char *OBJ_FetchCustomTypeName( dword objtypeid )
+{
+ if ( !TYPEID_TYPE_CUSTOM( objtypeid ) )
+ return NULL;
+
+ int tindx = ( objtypeid & TYPENUMBERMASK ) - NUM_DISTINCT_OBJTYPES;
+
+ ASSERT( tindx >= 0 );
+ ASSERT( tindx < num_custom_types );
+
+ if ( custom_type_info[ tindx ].type_id != objtypeid )
+ return NULL;
+
+ // fetch name from table
+ return custom_type_info[ tindx ].type_name;
+}
+
+
+// get the flags for a custom type --------------------------------------------
+//
+int OBJ_GetCustomTypeFlags( dword objtypeid )
+{
+ if ( !TYPEID_TYPE_CUSTOM( objtypeid ) )
+ return 0;
+
+ int tindx = ( objtypeid & TYPENUMBERMASK ) - NUM_DISTINCT_OBJTYPES;
+
+ ASSERT( tindx >= 0 );
+ ASSERT( tindx < num_custom_types );
+
+ if ( custom_type_info[ tindx ].type_id != objtypeid )
+ return 0;
+
+ // fetch flags from table
+ return custom_type_info[ tindx ].type_flags;
+}
+
+// determine instance size of custom type -------------------------------------
+//
+size_t OBJ_FetchCustomTypeSize( dword objtypeid )
+{
+ ASSERT( TYPEID_TYPE_CUSTOM( objtypeid ) );
+ int tindx = ( objtypeid & TYPENUMBERMASK ) - NUM_DISTINCT_OBJTYPES;
+
+ ASSERT( tindx >= 0 );
+ ASSERT( tindx < num_custom_types );
+ ASSERT( custom_type_info[ tindx ].type_id == objtypeid );
+
+ if ( custom_type_info[ tindx ].type_id != objtypeid ) {
+
+ // point of no return
+ PANIC( custom_type_invalid );
+ }
+
+ // fetch size from table
+ return custom_type_info[ tindx ].type_size;
+}
+
+
+// fetch template (object with default/user-altered values) for custom type ---
+//
+CustomObject *OBJ_FetchCustomTypeTemplate( dword objtypeid )
+{
+ ASSERT( TYPEID_TYPE_CUSTOM( objtypeid ) );
+ int tindx = ( objtypeid & TYPENUMBERMASK ) - NUM_DISTINCT_OBJTYPES;
+
+ ASSERT( tindx >= 0 );
+ ASSERT( tindx < num_custom_types );
+ ASSERT( custom_type_info[ tindx ].type_id == objtypeid );
+
+ if ( custom_type_info[ tindx ].type_id != objtypeid )
+ return NULL;
+
+ // fetch template from table
+ return custom_type_info[ tindx ].type_template;
+}
+
+
+// init custom object from supplied custom type template ----------------------
+//
+int OBJ_InitFromCustomTypeTemplate( CustomObject *obj, CustomObject *templ )
+{
+ ASSERT( obj != NULL );
+
+ // copy over template if available
+ if ( templ != NULL ) {
+
+ ASSERT( obj->InstanceSize >= sizeof( CustomObject ) );
+
+ // base part must be left untouched
+ size_t userareasize = obj->InstanceSize - sizeof( CustomObject );
+ if ( userareasize > 0 ) {
+ memcpy( (char*)obj + sizeof( CustomObject ),
+ (char*)templ + sizeof( CustomObject ),
+ userareasize );
+ }
+
+ return TRUE;
+ }
+
+ // no template, default init should be done
+ return FALSE;
+}
+
+
+// init instance (class) of custom object type --------------------------------
+//
+void OBJ_InitCustomType( GenObject *classpo )
+{
+ ASSERT( classpo != NULL );
+ ASSERT( OBJECT_TYPE_CUSTOM( classpo ) );
+
+ CustomObject *obj = (CustomObject *) classpo;
+
+ int customid = ( classpo->ObjectType & TYPENUMBERMASK ) - NUM_DISTINCT_OBJTYPES;
+ if ( ( customid < 0 ) || ( customid >= num_custom_types ) ) {
+ ASSERT( 0 );
+ return;
+ }
+
+ if ( custom_type_info[ customid ].type_id != classpo->ObjectType ) {
+ ASSERT( 0 );
+ return;
+ }
+
+ // init fields of struct CustomObject
+ obj->callback_instant = custom_type_info[ customid ].callback_instant;
+ obj->callback_destroy = custom_type_info[ customid ].callback_destroy;
+ obj->callback_animate = custom_type_info[ customid ].callback_animate;
+ obj->callback_collide = custom_type_info[ customid ].callback_collide;
+ obj->callback_notify = custom_type_info[ customid ].callback_notify;
+ obj->callback_persist = custom_type_info[ customid ].callback_persist;
+
+ // invoke class init callback if available
+ if ( custom_type_info[ customid ].callback_init != NULL ) {
+ (*custom_type_info[ customid ].callback_init)( obj );
+ }
+}
+
+
+// register new custom type, assign next available id -------------------------
+//
+dword OBJ_RegisterCustomType( custom_type_info_s *info )
+{
+ ASSERT( info != NULL );
+
+ // guard against maximum number of custom types
+ if ( num_custom_types >= MAX_NUM_CUSTOM_TYPES ) {
+ ASSERT( 0 );
+ info->type_id = TYPE_ID_INVALID;
+ return TYPE_ID_INVALID;
+ }
+
+ // guard against maximum number of type ids
+ if ( num_custom_types + NUM_DISTINCT_OBJTYPES > TYPENUMBERMASK ) {
+ ASSERT( 0 );
+ info->type_id = TYPE_ID_INVALID;
+ return TYPE_ID_INVALID;
+ }
+
+ // assign next sequential id
+ dword tindx = num_custom_types;
+ info->type_id = ( NUM_DISTINCT_OBJTYPES + tindx ) | CUSTM_LIST_NO |
+ ( info->type_id & ~( TYPENUMBERMASK | TYPELISTMASK ) );
+
+ // init table entry
+ custom_type_info[ tindx ].type_name = info->type_name;
+ custom_type_info[ tindx ].type_id = info->type_id;
+ custom_type_info[ tindx ].type_size = info->type_size;
+ custom_type_info[ tindx ].type_template = info->type_template;
+ custom_type_info[ tindx ].type_flags = info->type_flags;
+ custom_type_info[ tindx ].callback_init = info->callback_init;
+ custom_type_info[ tindx ].callback_instant = info->callback_instant;
+ custom_type_info[ tindx ].callback_destroy = info->callback_destroy;
+ custom_type_info[ tindx ].callback_animate = info->callback_animate;
+ custom_type_info[ tindx ].callback_collide = info->callback_collide;
+ custom_type_info[ tindx ].callback_notify = info->callback_notify;
+ custom_type_info[ tindx ].callback_persist = info->callback_persist;
+
+ // one more custom type
+ num_custom_types++;
+
+ // return id (caller field type_id is now valid)
+ return info->type_id;
+}
+
+
+// register custom object with genobject (insert at head of list) -------------
+//
+void OBJ_RegisterNotifyCustomObject( GenObject *genobj, CustomObject *customobj )
+{
+ ASSERT( genobj != NULL );
+ ASSERT( customobj != NULL );
+
+ //NOTE:
+ // if the custom object needs a pointer to the GenObject it has
+ // been registered with, it must store this pointer in its own
+ // mem area, i.e., in the struct derived from CustomObject.
+
+ // every custom object can only be part of a single list
+ ASSERT( customobj->NotifyCustmObjects == NULL );
+
+ // insert at head of list
+ customobj->NotifyCustmObjects = genobj->NotifyCustmObjects;
+ genobj->NotifyCustmObjects = customobj;
+}
+
+
+// unregister custom object from genobject (delete from list if contained) ----
+//
+int OBJ_UnregisterNotifyCustomObject( GenObject *genobj, CustomObject *customobj )
+{
+ ASSERT( genobj != NULL );
+ ASSERT( customobj != NULL );
+
+ // scan list for specified custom object
+ GenObject *prev = genobj;
+ CustomObject *scan = genobj->NotifyCustmObjects;
+ for ( ; scan != NULL; scan = scan->NotifyCustmObjects ) {
+
+ // remove from list when found
+ if ( scan == customobj ) {
+ prev->NotifyCustmObjects = scan->NotifyCustmObjects;
+ scan->NotifyCustmObjects = NULL;
+ return TRUE;
+ }
+ prev = scan;
+ }
+
+ // custom object was not registered
+ return FALSE;
+}
+
+
+// notify custom objects registered with genobject ----------------------------
+//
+void OBJ_NotifyCustomObjectsList( GenObject *genobj, int event )
+{
+ ASSERT( genobj != NULL );
+
+ // if the event is delete, the list must be unlinked
+ int unlinklist = ( event == CUSTOM_NOTIFY_GENOBJECT_DELETE );
+
+ // walk list of registered custom objects
+ GenObject *prev = genobj;
+ CustomObject *customobj = genobj->NotifyCustmObjects;
+ for ( ; customobj != NULL; customobj = customobj->NotifyCustmObjects ) {
+
+ // call notify callback if it is valid
+ if ( customobj->callback_notify != NULL ) {
+ (*customobj->callback_notify)( customobj, genobj, event );
+ }
+
+ // step to next element, unlink list if desired
+ if ( unlinklist ) {
+ prev->NotifyCustmObjects = NULL;
+ prev = customobj;
+ }
+ }
+}
+
+
+// module registration function -----------------------------------------------
+//
+REGISTER_MODULE( OBJ_CUST )
+{
+ //NOTE:
+ // register a type that consists only of
+ // geometry. this can be used to view
+ // objects using the summon command.
+
+ custom_type_info_s info;
+ memset( &info, 0, sizeof( info ) );
+
+ info.type_name = "geometry";
+ info.type_size = sizeof( CustomObject );
+
+ OBJ_RegisterCustomType( &info );
+}
+
+
+