1
0
Fork 0

Latest MultiPlayer updates

This commit is contained in:
ehofman 2003-03-26 14:06:51 +00:00
parent a4ea7c7561
commit 9914cfa93c
5 changed files with 88 additions and 44 deletions

View file

@ -1,3 +1,26 @@
// mpmessages.hxx -- Message definitions for multiplayer communications
// within a multiplayer Flightgear
//
// Written by Duncan McCreanor, started February 2003.
// duncan.mccreanor@airservicesaustralia.com
//
// Copyright (C) 2003 Airservices Australia
//
// 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., 675 Mass Ave, Cambridge, MA 02139, USA.
//
#ifndef MPMESSAGES_H #ifndef MPMESSAGES_H
#define MPMESSAGES_H #define MPMESSAGES_H

View file

@ -45,6 +45,7 @@
# include <arpa/inet.h> # include <arpa/inet.h>
#endif #endif
#include <plib/netSocket.h> #include <plib/netSocket.h>
#include <plib/sg.h>
#include <Main/globals.hxx> #include <Main/globals.hxx>
#include <Model/loader.hxx> #include <Model/loader.hxx>
@ -66,6 +67,7 @@ MPPlayer::MPPlayer() {
m_bInitialised = false; m_bInitialised = false;
m_LastUpdate = 0; m_LastUpdate = 0;
m_PlayerAddress.set("localhost", 0); m_PlayerAddress.set("localhost", 0);
m_sCallsign = "none";
} }
@ -124,15 +126,26 @@ bool MPPlayer::Open(const string &sAddress, const int &iPort, const string &sCal
******************************************************************/ ******************************************************************/
void MPPlayer::Close(void) { void MPPlayer::Close(void) {
// Remove the model from the game // Remove the model from the game
if (!m_bLocalPlayer) { if (m_bInitialised && !m_bLocalPlayer) {
globals->get_scenery()->get_scene_graph()->removeKid(m_ModelSel);
// Disconnect the model from the transform, then the transform from the scene.
m_ModelTrans->removeKid(m_Model);
globals->get_scenery()->get_aircraft_branch()->removeKid( m_ModelTrans);
// Flush the model loader so that it erases the model from its list of
// models.
globals->get_model_loader()->flush();
// Assume that plib/ssg deletes the model and transform as their
// refcounts should be zero.
} }
m_bInitialised = false; m_bInitialised = false;
m_bUpdated = false; m_bUpdated = false;
m_LastUpdate = 0; m_LastUpdate = 0;
m_sCallsign = "none";
} }
@ -147,7 +160,7 @@ void MPPlayer::SetPosition(const sgMat4 PlayerPosMat4) {
// Save the position matrix and update time // Save the position matrix and update time
if (m_bInitialised) { if (m_bInitialised) {
memcpy(m_ModelPos, PlayerPosMat4, sizeof(sgMat4)); sgCopyMat4(m_ModelPos, PlayerPosMat4);
time(&m_LastUpdate); time(&m_LastUpdate);
m_bUpdated = true; m_bUpdated = true;
} }
@ -159,26 +172,24 @@ void MPPlayer::SetPosition(const sgMat4 PlayerPosMat4) {
/****************************************************************** /******************************************************************
* Name: Draw * Name: Draw
* Description: Updates the position for the player's model * Description: Updates the position for the player's model
* The state of the player (old, initialised etc) * The state of the player's data is returned.
* is returned.
******************************************************************/ ******************************************************************/
int MPPlayer::Draw(void) { MPPlayer::TPlayerDataState MPPlayer::Draw(void) {
int iResult = PLAYER_DATA_NOT_AVAILABLE; MPPlayer::TPlayerDataState eResult = PLAYER_DATA_NOT_AVAILABLE;
sgCoord sgPlayerCoord; sgCoord sgPlayerCoord;
if (m_bInitialised) { if (m_bInitialised && !m_bLocalPlayer) {
if ((time(NULL) - m_LastUpdate < TIME_TO_LIVE)) { if ((time(NULL) - m_LastUpdate < TIME_TO_LIVE)) {
// Peform an update if it has changed since the last update // Peform an update if it has changed since the last update
if (m_bUpdated) { if (m_bUpdated) {
// Transform and update player model // Transform and update player model
m_ModelSel->select(1);
sgSetCoord( &sgPlayerCoord, m_ModelPos); sgSetCoord( &sgPlayerCoord, m_ModelPos);
m_ModelTrans->setTransform( &sgPlayerCoord ); m_ModelTrans->setTransform( &sgPlayerCoord );
iResult = PLAYER_DATA_AVAILABLE; eResult = PLAYER_DATA_AVAILABLE;
// Clear the updated flag so that the position data // Clear the updated flag so that the position data
// is only available if it has changed // is only available if it has changed
@ -187,12 +198,12 @@ int MPPlayer::Draw(void) {
// Data has not been updated for some time. // Data has not been updated for some time.
} else { } else {
iResult = PLAYER_DATA_EXPIRED; eResult = PLAYER_DATA_EXPIRED;
} }
} }
return iResult; return eResult;
} }
@ -227,18 +238,21 @@ bool MPPlayer::CompareCallsign(const char *sCallsign) const {
void MPPlayer::LoadModel(void) { void MPPlayer::LoadModel(void) {
m_ModelSel = new ssgSelector; m_ModelTrans = new ssgTransform;
m_ModelTrans = new ssgTransform;
ssgEntity *Model = globals->get_model_loader()->load_model(m_sModelName); // Load the model
Model->clrTraversalMaskBits( SSGTRAV_HOT ); m_Model = globals->get_model_loader()->load_model(m_sModelName);
m_ModelTrans->addKid( Model ); m_Model->clrTraversalMaskBits( SSGTRAV_HOT );
m_ModelSel->addKid( m_ModelTrans );
ssgFlatten( Model );
ssgStripify( m_ModelSel );
globals->get_scenery()->get_scene_graph()->addKid( m_ModelSel ); // Add model to transform
globals->get_scenery()->get_scene_graph()->addKid( Model ); m_ModelTrans->addKid( m_Model );
// Optimise model and transform
ssgFlatten( m_Model );
ssgStripify( m_ModelTrans );
// Place on scene under aircraft branch
globals->get_scenery()->get_aircraft_branch()->addKid( m_ModelTrans );
} }
@ -254,8 +268,7 @@ void MPPlayer::FillPosMsg(T_MsgHdr *MsgHdr, T_PositionMsg *PosMsg) {
strncpy(PosMsg->sModel, m_sModelName.c_str(), MAX_MODEL_NAME_LEN); strncpy(PosMsg->sModel, m_sModelName.c_str(), MAX_MODEL_NAME_LEN);
PosMsg->sModel[MAX_MODEL_NAME_LEN - 1] = '\0'; PosMsg->sModel[MAX_MODEL_NAME_LEN - 1] = '\0';
sgCopyMat4(PosMsg->PlayerPos, m_ModelPos);
memcpy(PosMsg->PlayerPos, m_ModelPos, sizeof(sgMat4));
} }

View file

@ -29,7 +29,13 @@
/**************************************************************** /****************************************************************
* @version $Id$ * @version $Id$
* *
* Description: * Description: This class holds information about a player in a
* multiplayer game. The model for a remote player is loaded and
* added onto the aircraft branch of the scene on calling Open.
* The model is unloaded from the scene when Close is called
* or the object is deleted. The model's positioning transform is
* updated by calling SetPosition. The updated position transform
* is applied to the model on the scene by calling Draw.
* *
******************************************************************/ ******************************************************************/
@ -47,9 +53,6 @@ SG_USING_STD(string);
// Number of seconds before a player is consider to be lost // Number of seconds before a player is consider to be lost
#define TIME_TO_LIVE 10 #define TIME_TO_LIVE 10
#define PLAYER_DATA_NOT_AVAILABLE 0
#define PLAYER_DATA_AVAILABLE 1
#define PLAYER_DATA_EXPIRED 2
class MPPlayer { class MPPlayer {
public: public:
@ -60,6 +63,12 @@ public:
/** Destructor. */ /** Destructor. */
~MPPlayer(); ~MPPlayer();
/** Enumeration of the states for the player's data */
enum PlayerDataState {PLAYER_DATA_NOT_AVAILABLE = 0, PLAYER_DATA_AVAILABLE, PLAYER_DATA_EXPIRED};
/** Player data state */
typedef enum PlayerDataState TPlayerDataState;
/** Initialises the class. /** Initialises the class.
* @param sIP IP address or host name for sending data to the player * @param sIP IP address or host name for sending data to the player
* @param sPort Port number for sending data to the player * @param sPort Port number for sending data to the player
@ -71,9 +80,6 @@ public:
bool Open(const string &sIP, const int &iPort, const string &sCallsign, bool Open(const string &sIP, const int &iPort, const string &sCallsign,
const string &sModelName, const bool bLocalPlayer); const string &sModelName, const bool bLocalPlayer);
/** Initialises the player count for all instances of this object to zero. */
static void ResetPlayerCnt(void);
/** Closes the player connection */ /** Closes the player connection */
void Close(void); void Close(void);
@ -84,7 +90,7 @@ public:
/** Transform and place model for player /** Transform and place model for player
*/ */
int Draw(void); TPlayerDataState Draw(void);
/** Returns the callsign for the player /** Returns the callsign for the player
* @return Aircraft's callsign * @return Aircraft's callsign
@ -97,9 +103,6 @@ public:
*/ */
bool CompareCallsign(const char *sCallsign) const; bool CompareCallsign(const char *sCallsign) const;
/** Loads the model of the aircraft */
void LoadModel(void);
/** Populates a position message for the player /** Populates a position message for the player
* @param MsgHdr Header to be populated * @param MsgHdr Header to be populated
* @param PosMsg Position message to be populated * @param PosMsg Position message to be populated
@ -115,6 +118,9 @@ public:
private: private:
/** Loads the model of the aircraft */
void LoadModel(void);
/** True if object is initialised */ /** True if object is initialised */
bool m_bInitialised; bool m_bInitialised;
@ -130,13 +136,13 @@ private:
/** Player's callsign */ /** Player's callsign */
string m_sCallsign; string m_sCallsign;
/** Aircraft model for player */ /** Aircraft model name for player */
string m_sModelName; string m_sModelName;
/** Simgear model selection */ /** The player's loaded model */
ssgSelector *m_ModelSel; ssgEntity *m_Model;
/** Simgear model transform */ /** Model transform */
ssgTransform *m_ModelTrans; ssgTransform *m_ModelTrans;
/** True if this player is the local player */ /** True if this player is the local player */

View file

@ -332,16 +332,18 @@ void FGMultiplayRxMgr::ProcessData(void) {
******************************************************************/ ******************************************************************/
void FGMultiplayRxMgr::Update(void) { void FGMultiplayRxMgr::Update(void) {
int iPlayerDataState; MPPlayer::TPlayerDataState ePlayerDataState;
int iPlayerId; int iPlayerId;
for (iPlayerId = 0; iPlayerId < MAX_PLAYERS; iPlayerId++) { for (iPlayerId = 0; iPlayerId < MAX_PLAYERS; iPlayerId++) {
if (m_Player[iPlayerId] != NULL) { if (m_Player[iPlayerId] != NULL) {
iPlayerDataState = m_Player[iPlayerId]->Draw(); ePlayerDataState = m_Player[iPlayerId]->Draw();
// If the player has not received an update for some // If the player has not received an update for some
// time then assume that the player has quit. // time then assume that the player has quit.
if (iPlayerDataState == PLAYER_DATA_EXPIRED) { if (ePlayerDataState == MPPlayer::PLAYER_DATA_EXPIRED) {
SG_LOG( SG_NETWORK, SG_BULK, "FGMultiplayRxMgr::Update - Deleting player from game. Callsign: "
<< m_Player[iPlayerId]->Callsign() );
delete m_Player[iPlayerId]; delete m_Player[iPlayerId];
m_Player[iPlayerId] = NULL; m_Player[iPlayerId] = NULL;
} }

View file

@ -123,7 +123,7 @@ bool FGMultiplayTxMgr::init(void) {
// Create a player object for the local player // Create a player object for the local player
if (bSuccess) { if (bSuccess) {
mLocalPlayer = new MPPlayer(); mLocalPlayer = new MPPlayer();
if (!mLocalPlayer->Open(fgGetString("/sim/multiplay/rxaddress"), fgGetInt("/sim/multiplay/rxport"), if (!mLocalPlayer->Open(fgGetString("/sim/multiplay/rxhost"), fgGetInt("/sim/multiplay/rxport"),
fgGetString("/sim/multiplay/callsign"), fgGetString("/sim/model/path"), true)) { fgGetString("/sim/multiplay/callsign"), fgGetString("/sim/model/path"), true)) {
cerr << "FGMultiplayTxMgr::init - Failed to create player object for local player" << endl; cerr << "FGMultiplayTxMgr::init - Failed to create player object for local player" << endl;
bSuccess = false; bSuccess = false;