aboutsummaryrefslogtreecommitdiff
path: root/src/parsec_server/e_simplayerinfo.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/e_simplayerinfo.cpp
downloadopenparsec-main.tar.xz
openparsec-main.zip
initial importHEADmain
Diffstat (limited to 'src/parsec_server/e_simplayerinfo.cpp')
-rwxr-xr-xsrc/parsec_server/e_simplayerinfo.cpp315
1 files changed, 315 insertions, 0 deletions
diff --git a/src/parsec_server/e_simplayerinfo.cpp b/src/parsec_server/e_simplayerinfo.cpp
new file mode 100755
index 0000000..162f888
--- /dev/null
+++ b/src/parsec_server/e_simplayerinfo.cpp
@@ -0,0 +1,315 @@
+/*
+ * PARSEC - Player Information (Simulation)
+ *
+ * $Author: uberlinuxguy $ - $Date: 2004/09/26 03:43:46 $
+ *
+ * Orginally written by:
+ * Copyright (c) Clemens Beer <cbx@parsec.org> 2001-2002
+ *
+ * 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 <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <math.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"
+
+// local module header
+#include "e_simplayerinfo.h"
+
+// proprietary module headers
+#include "con_aux_sv.h"
+//#include "g_colldet.h"
+//#include "g_extra.h"
+////#include "net_csdf.h"
+//#include "net_packetdriver.h"
+#include "net_game_sv.h"
+//#include "net_stream.h"
+#include "obj_creg.h" // for ShipClasses
+////#include "e_stats.h"
+#include "g_main_sv.h"
+#include "e_connmanager.h"
+#include "e_gameserver.h"
+#include "e_simulator.h"
+//#include "e_packethandler.h"
+//#include "e_relist.h"
+//#include "sys_refframe_sv.h"
+
+// reset all player fields to defaults ( not connected ) ----------------------
+//
+void E_SimPlayerInfo::Reset()
+{
+ m_Status = PLAYER_INACTIVE;
+ m_objclass = -1;
+
+ m_pShip = NULL;
+ m_nShipID = SHIPID_NOSHIP;
+
+ m_nClientID = -1;
+ m_IgnoreJoinUntilUnjoinFromClient = FALSE;
+}
+
+// set the desired player status ( inactive/joined/unjoined ) -----------------
+//
+void E_SimPlayerInfo::SetDesiredPlayerStatus( RE_PlayerStatus* playerstatus )
+{
+ ASSERT( playerstatus != NULL );
+
+ // identify sender
+ int nClientID = playerstatus->senderid;
+ ASSERT( ( nClientID >= 0 ) && ( nClientID < MAX_NUM_CLIENTS ) );
+
+ switch( playerstatus->player_status ) {
+ // desired player status is INACTIVE (disconnect)
+ case PLAYER_INACTIVE:
+ {
+ ASSERT( FALSE );
+ }
+ break;
+ // desired player_status is JOINED ( join/ensure joined )
+ case PLAYER_JOINED:
+ {
+ // player must not be joined already in order to join
+ if ( m_Status == PLAYER_JOINED ) {
+ return;
+ }
+
+ // player must be connected in order to join
+ if ( m_Status == PLAYER_INACTIVE ) {
+ DBGTXT( MSGOUT( "SetDesiredPlayerStatus(): filtering join for inactive player: %d.", nClientID ); );
+ return;
+ }
+
+ // check whether to ignore the JOIN
+ if ( m_IgnoreJoinUntilUnjoinFromClient ) {
+ DBGTXT( MSGOUT( "SetDesiredPlayerStatus(): filtering join until unjoin is ACK: %d.", nClientID ); );
+ return;
+ }
+
+ // player status must be CONNECTED
+ ASSERT( m_Status == PLAYER_CONNECTED );
+
+ // only allow join of players when game is running
+ if ( TheGame->IsGameRunning() ) {
+
+ // update tables and create ship
+ PerformJoin( playerstatus );
+
+ // player status must now be JOINED
+ ASSERT( m_Status == PLAYER_JOINED );
+
+ DBGTXT( MSGOUT( "SetDesiredPlayerStatus(): joined player %d.", nClientID ); );
+ }
+ }
+ break;
+ // desired player_status is CONNECTED ( unjoin/ensure unjoined )
+ case PLAYER_CONNECTED:
+ {
+ // check whether this is an ACK package from the client that he received the unjoin packet from the server
+ if ( m_IgnoreJoinUntilUnjoinFromClient && ( m_Status == PLAYER_CONNECTED ) ) {
+
+ // reset flag ( we now again accept all states from the client )
+ m_IgnoreJoinUntilUnjoinFromClient = FALSE;
+
+ // reset last unjoin flag to USER_EXIT
+ TheGame->ResetDeathInfo( nClientID );
+ } else {
+
+ // player must be joined in order to unjoin
+ if ( m_Status == PLAYER_CONNECTED ) {
+ return;
+ }
+
+ // player must be connected in order to unjoin
+ if ( m_Status == PLAYER_INACTIVE ) {
+ DBGTXT( MSGOUT( "SetDesiredPlayerStatus(): filtering unjoin for inactive player: %d.", nClientID ); );
+ return;
+ }
+
+ // player status must be JOINED
+ ASSERT( m_Status == PLAYER_JOINED );
+
+ // update tables and delete ship
+ PerformUnjoin( playerstatus );
+
+ // reset the flag
+ m_IgnoreJoinUntilUnjoinFromClient = FALSE;
+
+ // player status must now be CONNECTED
+ ASSERT( m_Status == PLAYER_CONNECTED );
+
+ DBGTXT( MSGOUT( "SetDesiredPlayerStatus(): unjoined player %d.", nClientID ); );
+ }
+ }
+ break;
+ default:
+ ASSERT( FALSE );
+ break;
+ }
+}
+
+// update tables and create ship for newly joined player ----------------------
+//
+void E_SimPlayerInfo::PerformJoin( RE_PlayerStatus* playerstatus )
+{
+ //NOTE: nearly identical to NET_GAME::PerformJoin
+
+ ASSERT( playerstatus != NULL );
+ ASSERT( playerstatus->player_status == PLAYER_JOINED );
+ ASSERT( m_Status == PLAYER_CONNECTED );
+
+ // update player status
+ m_Status = PLAYER_JOINED;
+
+ // there must not be a ship for this player
+ ASSERT( m_nShipID == SHIPID_NOSHIP );
+ ASSERT( m_pShip == NULL );
+
+ // get the objectclass
+ m_objclass = ShipClasses[ playerstatus->objectindex ];
+
+ ASSERT( (dword)m_objclass != CLASS_ID_INVALID );
+
+ // fetch the latest state
+ E_SimClientState* pSimClientState = TheSimulator->GetSimClientState( m_nClientID );
+
+ // init the join position for the new player
+ E_SimShipState _SimShipState;
+ GAMECODE2( TheGame->JoinPlayer( m_nClientID, &_SimShipState ); );
+
+ // reset the sim-state of the client
+ pSimClientState->ForceNewState( &_SimShipState );
+
+ // force a client resync
+ pSimClientState->SetClientResync();
+
+ // create ship object for new player
+ GenObject* objectpo = TheWorld->CreateObject( m_objclass, _SimShipState.GetObjPosition(), playerstatus->senderid );
+ ASSERT( objectpo != NULL );
+
+ // set correct global objectid for player-ship
+ objectpo->HostObjNumber = ShipHostObjId( playerstatus->senderid );
+ m_pShip = (ShipObject*)objectpo;
+ m_nShipID = objectpo->ObjectNumber;
+
+ // display object id of remote player's ship
+ //FIXME: this could go into UI_PlayerJoinedFeedback
+ DBGTXT( MSGOUT( "player %s joined and got object id %d.", TheConnManager->GetClientName( m_nClientID ), m_nShipID ); );
+
+ MSGOUT( "joined client %d", m_nClientID );
+
+ // give UI feedback when player has joined
+ GAMECODE ( UI_PlayerJoinedFeedback( playerstatus ) );
+}
+
+
+// update tables and delete ship of player who unjoined -----------------------
+//
+void E_SimPlayerInfo::PerformUnjoin( RE_PlayerStatus* playerstatus )
+{
+ ASSERT( playerstatus != NULL );
+ ASSERT( playerstatus->player_status == PLAYER_CONNECTED );
+ if(m_Status != PLAYER_JOINED)
+ return;
+ ASSERT( m_pShip != NULL );
+ ASSERT( m_nShipID != SHIPID_NOSHIP );
+
+ //FIXME: check whether this should be handled here
+
+ // downing of ship starts explosion
+ if ( playerstatus->params[ 0 ] == SHIP_DOWNED ) {
+
+ // exec gamecode when player ship is downed
+ GAMECODE ( GC_UnjoinPlayer_ShipDowned( playerstatus ) );
+
+ //FIXME: we must not yet kill the ShipObject as the E_Distributable might need it
+ //FIXME: really ??????????????
+ // kill ship object
+ TheWorld->KillSpecificShipObject( m_nShipID );
+
+ // user exit opens stargate and deletes ship
+ } else if ( playerstatus->params[ 0 ] == USER_EXIT ) {
+
+ // exec gamecode when player exits to menu
+ GAMECODE ( GC_UnjoinPlayer_UserExit( playerstatus ) );
+
+ // kill ship object
+ TheWorld->KillSpecificShipObject( m_nShipID );
+ }
+
+ // unjoin the player in G_Main
+ TheGame->UnjoinPlayer( m_nClientID );
+
+ // signify that player is only connected, but not joined.
+ m_Status = PLAYER_CONNECTED;
+ m_pShip = NULL;
+ m_nShipID = SHIPID_NOSHIP;
+ m_objclass = -1;
+
+ MSGOUT( "unjoined client %d", m_nClientID );
+
+ // give UI feedback when player has unjoined
+ GAMECODE ( UI_PlayerUnjoinedFeedback( playerstatus ) );
+}
+
+// set the player status to connected -----------------------------------------
+//
+void E_SimPlayerInfo::Connect( int nClientID )
+{
+ ASSERT( ( nClientID >= 0 ) && ( nClientID < MAX_NUM_CLIENTS ) );
+ ASSERT( m_Status == PLAYER_INACTIVE );
+
+ m_nClientID = nClientID;
+ m_Status = PLAYER_CONNECTED;
+}
+
+// set the player status to disconnected --------------------------------------
+//
+void E_SimPlayerInfo::Disconnect()
+{
+ ASSERT( ( m_Status == PLAYER_CONNECTED ) || ( m_Status == PLAYER_JOINED ) );
+
+ if ( m_Status == PLAYER_JOINED ) {
+
+ DBGTXT( MSGOUT( "E_SimPlayerInfo::Disconnect() unjoining still joined player before disconnecting" ); );
+
+ // fill rudimentary RE
+ RE_PlayerStatus ps;
+ ps.player_status = PLAYER_CONNECTED;
+ ps.params[ 0 ] = USER_EXIT;
+ ps.senderid = m_nClientID;
+
+ // set the state of the player
+ SetDesiredPlayerStatus( &ps );
+ }
+
+ Reset();
+}
+