aboutsummaryrefslogtreecommitdiff
path: root/src/parsec_server/g_stgate_sv.cpp
diff options
context:
space:
mode:
authorFelix Morgner <felix.morgner@gmail.com>2026-08-24 11:16:07 +0200
committerFelix Morgner <felix.morgner@gmail.com>2026-08-24 11:16:07 +0200
commitc068f22329d5cc722622a2183bbb22eef2093df7 (patch)
tree12d56c1aede67988a55e241364606bfbb4dba933 /src/parsec_server/g_stgate_sv.cpp
downloadopenparsec-c068f22329d5cc722622a2183bbb22eef2093df7.tar.xz
openparsec-c068f22329d5cc722622a2183bbb22eef2093df7.zip
initial importHEADmain
Diffstat (limited to 'src/parsec_server/g_stgate_sv.cpp')
-rwxr-xr-xsrc/parsec_server/g_stgate_sv.cpp672
1 files changed, 672 insertions, 0 deletions
diff --git a/src/parsec_server/g_stgate_sv.cpp b/src/parsec_server/g_stgate_sv.cpp
new file mode 100755
index 0000000..afdc0db
--- /dev/null
+++ b/src/parsec_server/g_stgate_sv.cpp
@@ -0,0 +1,672 @@
+/*
+ * PARSEC - Stargate Model
+ *
+ * $Author: uberlinuxguy $ - $Date: 2004/09/26 03:43:47 $
+ *
+ * Orginally written by:
+ * Copyright (c) Clemens Beer <cbx@parsec.org> 1999-2002
+ * Copyright (c) Markus Hadwiger <msh@parsec.org> 1999-2000
+ * Copyright (c) Andreas Varga <sid@parsec.org> 2000
+ *
+ * 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 <stddef.h>
+#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"
+
+// subsystem headers
+#include "net_defs.h"
+#include "e_defs.h"
+#include "sys_defs.h"
+
+// subsystem linkage info
+#include "linkinfo.h"
+
+// UNP header
+#include "net_wrap.h"
+
+// mathematics header
+#include "utl_math.h"
+
+// model header
+//#include "utl_model.h"
+
+// local module header
+#include "g_stgate.h"
+
+// proprietary module headers
+#include "con_info_sv.h"
+#include "net_udpdriver.h"
+#include "net_util.h"
+#include "obj_clas.h"
+#include "obj_creg.h"
+#include "obj_cust.h"
+#include "e_simulator.h"
+
+// flags
+
+
+
+// generic string paste area --------------------------------------------------
+//
+#define PASTE_STR_LEN 255
+static char paste_str[ PASTE_STR_LEN + 1 ];
+
+
+// stargate limits and constants ----------------------------------------------
+//
+#define STARGATE_RADIUS 50.0f
+#define STARGATE_NUM_PLATES 12 // number of plates the stargate consists of
+#define STARGATE_NUM_FLARES STARGATE_NUM_PLATES // number of flares attached to the stargate
+#define STARGATE_INTERIOR_NUM_RINGS 15
+#define STARGATE_INTERIOR_VERTS_PER_RING ( STARGATE_NUM_PLATES * 2 )
+#define STARGATE_INTERIOR_NUM_VERTS ( ( STARGATE_INTERIOR_VERTS_PER_RING * STARGATE_INTERIOR_NUM_RINGS ) + 1 )
+#define STARGATE_INTERIOR_RADIUS ( STARGATE_RADIUS * 0.98f )
+
+#define STARGATE_RING_NUM_PARTS STARGATE_NUM_PLATES
+#define STARGATE_PART_RADIUS STARGATE_RADIUS
+#define STARGATE_RADIUS_EXPANSION 1.0f
+#define STARGATE_NUM_RINGS 20
+#define STARGATE_RING_PART_ZSPACING 10.0f
+#define STARGATE_PART_ZOFFSET INT_TO_GEOMV( -2 )
+
+#define STARGATE_INTERIOR_TEXTURE_NAME "sg_int.3df"
+#define STARGATE_FLARE_PDEF_NAME "sgateposlt"
+
+
+#if ( STARGATE_INTERIOR_NUM_RINGS > 32 )
+ #error "too many rings in stargate interior"
+#endif
+
+
+// module local functions -----------------------------------------------------
+//
+PRIVATE int StargateInstantiate_InitInteriorVertices( Stargate *stargate );
+
+PRIVATE int StargateModify_RealizeNode( GenObject* base );
+PRIVATE int StargateModify_ActiveChanged( GenObject* base );
+PRIVATE int StargateModify_AutoactivateChanged( GenObject* base );
+PRIVATE void StargateModify_CreateActiveParticles( CustomObject *base );
+
+
+// offset definitions into the Stargate ---------------------------------------
+//
+#define OFS_ROTSPEED offsetof( Stargate, rotspeed )
+#define OFS_RADIUS offsetof( Stargate, radius )
+#define OFS_DESTNAME offsetof( Stargate, destination_name )
+#define OFS_DESTIP offsetof( Stargate, destination_ip )
+#define OFS_DESTPORT offsetof( Stargate, destination_port )
+#define OFS_ACTDISTANCE offsetof( Stargate, actdistance )
+#define OFS_DORMANT offsetof( Stargate, dormant )
+#define OFS_ACTIVE offsetof( Stargate, active )
+#define OFS_AUTOACTIVATE offsetof( Stargate, autoactivate )
+#define OFS_NUMPARTACTIVE offsetof( Stargate, numpartactive )
+#define OFS_ACTCYLLEN offsetof( Stargate, actcyllen )
+#define OFS_PARTVEL offsetof( Stargate, partvel )
+#define OFS_MODULSPEED offsetof( Stargate, modulspeed )
+#define OFS_MODULRAD1 offsetof( Stargate, modulrad1 )
+#define OFS_MODULRAD2 offsetof( Stargate, modulrad2 )
+#define OFS_ACTTIME offsetof( Stargate, acttime )
+#define OFS_FLARE_NAME offsetof( Stargate, flare_name )
+#define OFS_INTERIOR_NAME offsetof( Stargate, interior_name )
+
+
+// list of console-accessible properties --------------------------------------
+//
+PRIVATE
+proplist_s Stargate_PropList[] = {
+
+ { "rotspeed", OFS_ROTSPEED, 0, 0xffff, PROPTYPE_INT, NULL },
+ { "radius", OFS_RADIUS, 0x10000, 0x4000000, PROPTYPE_FLOAT, NULL },
+ //{ "destname", OFS_DESTNAME, 0, MAX_SERVER_NAME, PROPTYPE_STRING, NULL },
+ //{ "destip", OFS_DESTIP, 0, STARGATE_MAX_DEST_IP, PROPTYPE_STRING, StargateModify_RealizeNode },
+ //{ "destport", OFS_DESTPORT, 1024, 65535, PROPTYPE_INT, StargateModify_RealizeNode },
+ { "actdistance", OFS_ACTDISTANCE, 0x10000, 0x4000000, PROPTYPE_FLOAT, NULL },
+ { "dormant", OFS_DORMANT, 0x0, 0x1, PROPTYPE_INT, NULL },
+ { "active", OFS_ACTIVE, 0x0, 0x1, PROPTYPE_INT, StargateModify_ActiveChanged },
+ { "autoactivate", OFS_AUTOACTIVATE, 0x0, 0x1, PROPTYPE_INT, StargateModify_AutoactivateChanged },
+ { "numpartactive", OFS_NUMPARTACTIVE, 1, 2048, PROPTYPE_INT, NULL },
+ { "actcyllen", OFS_ACTCYLLEN, 0, 2048, PROPTYPE_INT, NULL },
+ { "partvel", OFS_PARTVEL, 0x10000, 0x4000000, PROPTYPE_FLOAT, NULL },
+ { "modulspeed", OFS_MODULSPEED, 0, 0xffff, PROPTYPE_INT, NULL },
+ { "modulrad1", OFS_MODULRAD1, 0x10000, 0x4000000, PROPTYPE_FLOAT, NULL },
+ { "modulrad2", OFS_MODULRAD2, 0x10000, 0x4000000, PROPTYPE_FLOAT, NULL },
+ { "acttime", OFS_ACTTIME, 0, FRAME_MEASURE_TIMEBASE*10, PROPTYPE_INT, NULL },
+ { "flare_name", OFS_FLARE_NAME, 0, MAX_TEXNAME, PROPTYPE_STRING, NULL },
+ { "interior_name", OFS_INTERIOR_NAME, 0, MAX_TEXNAME, PROPTYPE_STRING, NULL },
+
+ { NULL, 0, 0, 0, 0, NULL },
+};
+
+
+// type fields init function for stargate -------------------------------------
+//
+PRIVATE
+void StargateInitType( CustomObject *base )
+{
+ ASSERT( base != NULL );
+
+ Stargate *stargate = (Stargate *) base;
+
+ stargate->rotspeed = 0x0004;
+ stargate->radius = STARGATE_PART_RADIUS;
+ stargate->actdistance = 300;
+ stargate->dormant = FALSE;
+ stargate->active = FALSE;
+ stargate->autoactivate = TRUE;
+ stargate->numpartactive = 600;
+ stargate->actcyllen = 300;
+ stargate->partvel = 150;
+ stargate->modulspeed = DEG_TO_BAMS( 1.0f );
+ stargate->modulate_bams = BAMS_DEG0;
+ stargate->modulrad1 = 5.0f;
+ stargate->modulrad2 = 2.0f;
+ stargate->modulfade = 2.0f;
+ stargate->acttime = FRAME_MEASURE_TIMEBASE;
+
+ stargate->activating = FALSE;
+ stargate->curactcyllen = 0;
+ stargate->manually_activated = FALSE;
+ stargate->actring = 0.0f;
+
+ strcpy( stargate->flare_name, STARGATE_FLARE_PDEF_NAME );
+ strcpy( stargate->interior_name, STARGATE_INTERIOR_TEXTURE_NAME );
+
+ stargate->pcluster = NULL;
+ stargate->interior_vtxlist = NULL;
+ stargate->interior_viewvtxs = NULL;
+ stargate->interior_u = NULL;
+ stargate->interior_v = NULL;
+ stargate->interior_texmap = NULL;
+
+ stargate->ping = -1;
+ stargate->lastpinged = 0;
+}
+
+
+/*// notification callback when eihter IP or port is changed --------------------
+//
+PRIVATE
+int StargateModify_RealizeNode( GenObject* base )
+{
+ ASSERT( base != NULL );
+ Stargate* stargate = (Stargate *) base;
+
+ // try to resolve DNS name to IP address (still as string)
+ char resolved_name[ MAX_IPADDR_LEN + 1 ];
+ if ( TheUDPDriver->ResolveHostName( stargate->destination_ip, NULL ) ) {
+
+ // save server address for later use by NET_GMSV.C
+ inet_aton( resolved_name, &stargate->destination_node );
+ NODE_StorePort( &stargate->destination_node, stargate->destination_port );
+
+ MSGOUT( "stargate->destinaiton %s resolved to %s", stargate->destination_ip, NODE_Print( &stargate->destination_node ) );
+ } else {
+ // DNS lookup failed
+ return FALSE;
+ }
+
+ return TRUE;
+}*/
+
+
+// notification callback when "active" changed --------------------------------
+//
+PRIVATE
+int StargateModify_ActiveChanged( GenObject* base )
+{
+ ASSERT( base != NULL );
+ Stargate *stargate = (Stargate *) base;
+
+ // manual activation/deactivation only if autoactivate off
+ if ( stargate->autoactivate ) {
+ return TRUE;
+ }
+
+ // prevent manual activation when stargate dormant
+ if ( stargate->dormant ) {
+ stargate->active = FALSE;
+ }
+
+ if ( ( stargate->active ) && ( !stargate->manually_activated ) ) {
+ stargate->manually_activated = TRUE;
+ } else {
+ stargate->manually_activated = FALSE;
+ }
+
+ return TRUE;
+}
+
+
+// notification callback when "autoactivate" changed --------------------------
+//
+PRIVATE
+int StargateModify_AutoactivateChanged( GenObject* base )
+{
+ ASSERT( base != NULL );
+ Stargate *stargate = (Stargate *) base;
+
+ // deactivate the stargate when it's active due to a manual activation
+ if ( stargate->autoactivate && stargate->manually_activated ) {
+ stargate->active = FALSE;
+ stargate->manually_activated = FALSE;
+ }
+
+ return TRUE;
+}
+
+// stargate constructor (class instantiation) ---------------------------------
+//
+PRIVATE
+void StargateInstantiate( CustomObject *base )
+{
+ ASSERT( base != NULL );
+ Stargate *stargate = (Stargate *) base;
+}
+
+/*
+
+// ----------------------------------------------------------------------------
+//
+#define PING_WAIT_MAX (5 * 600)
+
+static refframe_t stargate_ping_wait = 0;
+
+
+// determine whether stargate is dormant or not -------------------------------
+//
+PRIVATE
+void DetermineStargateDormantState( Stargate *stargate )
+{
+ ASSERT( stargate != NULL );
+
+#ifdef LINKED_PROTOCOL_GAMESERVER
+
+ // only while connected
+ if ( !NET_ConnectedGMSV() ) {
+ return;
+ }
+
+ // re-issue a server ping, once every 5 seconds
+ if ( ( stargate_ping_wait += CurScreenRefFrames ) > PING_WAIT_MAX ) {
+
+ stargate_ping_wait = 0;
+
+ int ping = -1;
+ if ( stargate->destination_node.address[ 0 ] != 0 ) {
+
+ NET_ServerPing( &stargate->destination_node, TRUE, FALSE );
+ }
+
+ //NOTE:
+ // ping result is not valid here, since we didn't wait
+ // for the arrival of the ping packet. The ping time will
+ // be available once the NET_ProcessPingPacket() function
+ // has processed the returned packet.
+
+ //NOTE:
+ // when a ping packet arrives, NET_ProcessPingPacket()
+ // sets Stargate::dormant, Stargate::ping, Stargate::lastpinged.
+
+ refframe_t curtime = SYSs_GetRefFrameCount();
+
+ // if we didn't get a pingreply for quite some time, we assume the
+ // server went down or was quit, so we switch the stargate to dormant state
+ if ( ( curtime - stargate->lastpinged ) > ( PING_WAIT_MAX * 2 ) ) {
+
+ stargate->dormant = TRUE;
+ stargate->ping = -1;
+ stargate->active = FALSE;
+ }
+ }
+
+#endif // LINKED_PROTOCOL_GAMESERVER
+
+}
+*/
+
+// stargate animation callback ------------------------------------------------
+//
+PRIVATE
+int StargateAnimate( CustomObject *base )
+{
+ ASSERT( base != NULL );
+ Stargate *stargate = (Stargate *) base;
+
+ // simply rotate around Z
+ ObjRotZ( stargate->ObjPosition, stargate->rotspeed * TheSimulator->GetThisFrameRefFrames() );
+
+ // determine whether stargate is dormant or not
+ //DetermineStargateDormantState( stargate );
+
+ return TRUE;
+}
+
+
+// stargate destructor (instance destruction) ---------------------------------
+//
+PRIVATE
+void StargateDestroy( CustomObject *base )
+{
+ ASSERT( base != NULL );
+ Stargate *stargate = (Stargate *) base;
+}
+
+
+// check whether a ship is in range of a stargate -----------------------------
+//
+PRIVATE
+int ShipInStargateRange( Stargate *stargate, ShipObject *ship, geomv_t range )
+{
+ ASSERT( stargate != NULL );
+ ASSERT( ship != NULL );
+
+ //NOTE:
+ // the ship is treated as a sphere for activation
+ // range detection.
+
+ Vector3 gatenormal;
+ FetchZVector( stargate->ObjPosition, &gatenormal );
+
+ Vertex3 gatepos;
+ FetchTVector( stargate->ObjPosition, &gatepos );
+
+ Vertex3 shippos;
+ FetchTVector( ship->ObjPosition, &shippos );
+
+ geomv_t shipdot = -DOT_PRODUCT( &gatenormal, &shippos );
+ geomv_t gatedot = -DOT_PRODUCT( &gatenormal, &gatepos );
+ geomv_t distance = shipdot - gatedot;
+
+ // bounding sphere touching in negative halfspace is still ok
+ distance += ship->BoundingSphere;
+
+ // not in range if ship in wrong halfspace
+ if ( GEOMV_NEGATIVE( distance ) ) {
+ return FALSE;
+ }
+
+ // in range if ship bounding sphere intersects gate range hemisphere
+ range += ship->BoundingSphere * 2;
+ return ( distance < range );
+}
+
+
+// check whether a ship is in jump range of a stargate ------------------------
+//
+PRIVATE
+int ShipInStargateJumpRange( Stargate *stargate, ShipObject *ship, geomv_t range )
+{
+ ASSERT( stargate != NULL );
+ ASSERT( ship != NULL );
+
+ //NOTE:
+ // the ship is treated as a point for jump
+ // range detection.
+
+ Vector3 gatenormal;
+ FetchZVector( stargate->ObjPosition, &gatenormal );
+
+ Vertex3 gatepos;
+ FetchTVector( stargate->ObjPosition, &gatepos );
+
+ Vertex3 shippos;
+ FetchTVector( ship->ObjPosition, &shippos );
+
+ geomv_t shipdot = -DOT_PRODUCT( &gatenormal, &shippos );
+ geomv_t gatedot = -DOT_PRODUCT( &gatenormal, &gatepos );
+ geomv_t distance = shipdot - gatedot;
+
+ // not in range if ship in wrong halfspace
+ if ( GEOMV_NEGATIVE( distance ) ) {
+ return FALSE;
+ }
+
+ // check whether inside of boundingsphere around stargate
+ Vector3 stargate_ship;
+ VECSUB( &stargate_ship, &shippos, &gatepos );
+
+ geomv_t stargate_ship_len = VctLenX( &stargate_ship );
+ if ( stargate_ship_len > stargate->BoundingSphere ) {
+ return FALSE;
+ }
+
+ // inside the activation distance/range ?
+ if ( distance < range ) {
+
+ Vector3 shipnormal;
+ FetchZVector( ship->ObjPosition, &shipnormal );
+
+ // ship must be flying approximately head-on into the gate
+ //FIXME: cone_angle like for teleporter
+ geomv_t dirdot = DOT_PRODUCT( &gatenormal, &shipnormal );
+ return ( dirdot > FLOAT_TO_GEOMV( 0.7f ) );
+ }
+
+ return FALSE;
+}
+
+
+// stargate collision callback ------------------------------------------------
+//
+PRIVATE
+int StargateCollide( CustomObject *base )
+{
+ ASSERT( base != NULL );
+
+ Stargate *stargate = (Stargate *) base;
+
+ // dormant stargate is simply graphics
+ if ( stargate->dormant ) {
+ return TRUE;
+ }
+
+/* int inrange = 0x00;
+
+ // check local ship
+ if ( ShipInStargateRange( stargate, MyShip, stargate->actdistance ) ) {
+ inrange |= 0x01;
+ }
+
+ // check all other ships
+ if ( inrange == 0x00 ) {
+
+ ShipObject *walkships = FetchFirstShip();
+ for ( ; walkships; walkships = (ShipObject *) walkships->NextObj ) {
+
+ if ( ShipInStargateRange( stargate, walkships, stargate->actdistance ) ) {
+ inrange |= 0x02;
+ break;
+ }
+ }
+ }
+
+ // only toggle active when autoactivation is set
+ if ( stargate->autoactivate ) {
+
+ if ( inrange != 0x00 ) {
+
+ if ( !stargate->active ) {
+
+ // create the active stargate particles
+ StargateModify_CreateActiveParticles( stargate );
+
+ // activate stargate
+ stargate->active = TRUE;
+ }
+
+ } else {
+
+ // deactivate stargate
+ stargate->active = FALSE;
+
+ // and clear the activating sequence to stop adding particles
+ stargate->activating = FALSE;
+ }
+ }
+
+ if ( !stargate->active ) {
+ return TRUE;
+ }
+
+ if ( inrange == 0x00 ) {
+ return TRUE;
+ }
+
+#ifdef LINKED_PROTOCOL_GAMESERVER
+
+ // check for fly-through sequence if connected to game server
+ if ( !NET_ConnectedGMSV() ) {
+ return TRUE;
+ }
+
+ // radius of hemisphere used for jump range detection
+ geomv_t jumpdistance = FLOAT_TO_GEOMV( stargate->radius * 0.25f );
+
+ // check local ship for jump
+ if ( ( inrange == 0x01 ) && ShipInStargateJumpRange( stargate, MyShip, jumpdistance ) ) {
+
+ // schedule server jump if not already done
+ if ( CurJumpServer == NULL ) {
+
+ CurJumpServer = (char *) ALLOCMEM( strlen( stargate->destination_ip ) + 1 );
+ if ( CurJumpServer == NULL )
+ OUTOFMEM( 0 );
+ strcpy( CurJumpServer, stargate->destination_ip );
+
+ //TODO:
+ // initiate animation and sfx
+ ShowMessage( "prepare to jump!!!" );
+ }
+
+ } else {
+
+ // check all other ships
+ ShipObject *walkships = FetchFirstShip();
+ for ( ; walkships; walkships = (ShipObject *) walkships->NextObj ) {
+
+ if ( ShipInStargateJumpRange( stargate, walkships, jumpdistance ) ) {
+
+ stargate->modulfade = 120.0f;
+ break;
+ }
+ }
+ }
+
+#endif // LINKED_PROTOCOL_GAMESERVER
+*/
+ return TRUE;
+}
+
+// handle persistency ---------------------------------------------------------
+//
+int StargatePersistToStream( CustomObject* base, int tostream, void* rl )
+{
+ ASSERT( base != NULL );
+ ASSERT( tostream == TRUE );
+ Stargate* stargate = (Stargate*) base;
+
+ // determine size in packet
+ size_t size = E_REList::RmEvGetSizeFromType( RE_STARGATE );
+
+ // write to RE list
+ if ( rl != NULL ) {
+
+ E_REList* pREList = (E_REList*)rl;
+
+ RE_Stargate* re_stg = (RE_Stargate*)pREList->NET_Allocate( RE_STARGATE );
+ ASSERT( re_stg != NULL );
+
+ re_stg->serverid = stargate->serverid;
+
+ re_stg->pos[ 0 ] = stargate->ObjPosition[ 0 ][ 3 ];
+ re_stg->pos[ 1 ] = stargate->ObjPosition[ 1 ][ 3 ];
+ re_stg->pos[ 2 ] = stargate->ObjPosition[ 2 ][ 3 ];
+
+ re_stg->dir[ 0 ] = stargate->ObjPosition[ 0 ][ 2 ];
+ re_stg->dir[ 1 ] = stargate->ObjPosition[ 1 ][ 2 ];
+ re_stg->dir[ 2 ] = stargate->ObjPosition[ 2 ][ 2 ];
+
+ re_stg->dormant = stargate->dormant;
+ re_stg->active = stargate->active;
+ re_stg->rotspeed = stargate->rotspeed;
+ re_stg->radius = stargate->radius;
+ re_stg->actdistance = stargate->actdistance;
+ re_stg->numpartactive = stargate->numpartactive;
+ re_stg->actcyllen = stargate->actcyllen;
+ re_stg->partvel = stargate->partvel;
+ re_stg->modulspeed = stargate->modulspeed;
+ re_stg->modulrad1 = stargate->modulrad1;
+ re_stg->modulrad2 = stargate->modulrad2;
+ re_stg->acttime = stargate->acttime;
+ re_stg->autoactivate= stargate->autoactivate;
+
+ strncpy( re_stg->flare_name, stargate->flare_name, MAX_TEXNAME );
+ re_stg->flare_name[ MAX_TEXNAME ] = 0;
+
+ strncpy( re_stg->interior_name, stargate->interior_name, MAX_TEXNAME );
+ re_stg->interior_name[ MAX_TEXNAME ] = 0;
+ }
+
+ return size;
+}
+
+
+// register object type for stargate ------------------------------------------
+//
+PRIVATE
+void StargateRegisterCustomType()
+{
+ custom_type_info_s info;
+ memset( &info, 0, sizeof( info ) );
+
+ info.type_name = "stargate";
+ info.type_id = 0x00000000;
+ info.type_size = sizeof( Stargate );
+ info.type_template = NULL;
+ info.type_flags = CUSTOM_TYPE_DEFAULT;
+ info.callback_init = StargateInitType;
+ info.callback_instant = StargateInstantiate;
+ info.callback_destroy = StargateDestroy;
+ info.callback_animate = StargateAnimate;
+ info.callback_collide = StargateCollide;
+ info.callback_persist = StargatePersistToStream;
+
+ OBJ_RegisterCustomType( &info );
+ CON_RegisterCustomType( info.type_id, Stargate_PropList );
+}
+
+
+// module registration function -----------------------------------------------
+//
+REGISTER_MODULE( G_STGATE_SV )
+{
+ // register type
+ StargateRegisterCustomType();
+}