Latest MultiPlayer updates
This commit is contained in:
parent
a4ea7c7561
commit
9914cfa93c
5 changed files with 88 additions and 44 deletions
|
@ -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
|
||||
#define MPMESSAGES_H
|
||||
|
||||
|
|
|
@ -45,6 +45,7 @@
|
|||
# include <arpa/inet.h>
|
||||
#endif
|
||||
#include <plib/netSocket.h>
|
||||
#include <plib/sg.h>
|
||||
|
||||
#include <Main/globals.hxx>
|
||||
#include <Model/loader.hxx>
|
||||
|
@ -66,6 +67,7 @@ MPPlayer::MPPlayer() {
|
|||
m_bInitialised = false;
|
||||
m_LastUpdate = 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) {
|
||||
|
||||
|
||||
// Remove the model from the game
|
||||
if (!m_bLocalPlayer) {
|
||||
globals->get_scenery()->get_scene_graph()->removeKid(m_ModelSel);
|
||||
if (m_bInitialised && !m_bLocalPlayer) {
|
||||
|
||||
// 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_bUpdated = false;
|
||||
m_LastUpdate = 0;
|
||||
m_sCallsign = "none";
|
||||
|
||||
}
|
||||
|
||||
|
@ -147,7 +160,7 @@ void MPPlayer::SetPosition(const sgMat4 PlayerPosMat4) {
|
|||
|
||||
// Save the position matrix and update time
|
||||
if (m_bInitialised) {
|
||||
memcpy(m_ModelPos, PlayerPosMat4, sizeof(sgMat4));
|
||||
sgCopyMat4(m_ModelPos, PlayerPosMat4);
|
||||
time(&m_LastUpdate);
|
||||
m_bUpdated = true;
|
||||
}
|
||||
|
@ -159,26 +172,24 @@ void MPPlayer::SetPosition(const sgMat4 PlayerPosMat4) {
|
|||
/******************************************************************
|
||||
* Name: Draw
|
||||
* Description: Updates the position for the player's model
|
||||
* The state of the player (old, initialised etc)
|
||||
* is returned.
|
||||
* The state of the player's data 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;
|
||||
|
||||
if (m_bInitialised) {
|
||||
if (m_bInitialised && !m_bLocalPlayer) {
|
||||
if ((time(NULL) - m_LastUpdate < TIME_TO_LIVE)) {
|
||||
// Peform an update if it has changed since the last update
|
||||
if (m_bUpdated) {
|
||||
|
||||
// Transform and update player model
|
||||
m_ModelSel->select(1);
|
||||
sgSetCoord( &sgPlayerCoord, m_ModelPos);
|
||||
m_ModelTrans->setTransform( &sgPlayerCoord );
|
||||
|
||||
iResult = PLAYER_DATA_AVAILABLE;
|
||||
eResult = PLAYER_DATA_AVAILABLE;
|
||||
|
||||
// Clear the updated flag so that the position data
|
||||
// is only available if it has changed
|
||||
|
@ -187,12 +198,12 @@ int MPPlayer::Draw(void) {
|
|||
|
||||
// Data has not been updated for some time.
|
||||
} 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) {
|
||||
|
||||
|
||||
m_ModelSel = new ssgSelector;
|
||||
m_ModelTrans = new ssgTransform;
|
||||
m_ModelTrans = new ssgTransform;
|
||||
|
||||
ssgEntity *Model = globals->get_model_loader()->load_model(m_sModelName);
|
||||
Model->clrTraversalMaskBits( SSGTRAV_HOT );
|
||||
m_ModelTrans->addKid( Model );
|
||||
m_ModelSel->addKid( m_ModelTrans );
|
||||
ssgFlatten( Model );
|
||||
ssgStripify( m_ModelSel );
|
||||
// Load the model
|
||||
m_Model = globals->get_model_loader()->load_model(m_sModelName);
|
||||
m_Model->clrTraversalMaskBits( SSGTRAV_HOT );
|
||||
|
||||
globals->get_scenery()->get_scene_graph()->addKid( m_ModelSel );
|
||||
globals->get_scenery()->get_scene_graph()->addKid( Model );
|
||||
// Add model to transform
|
||||
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);
|
||||
PosMsg->sModel[MAX_MODEL_NAME_LEN - 1] = '\0';
|
||||
|
||||
memcpy(PosMsg->PlayerPos, m_ModelPos, sizeof(sgMat4));
|
||||
sgCopyMat4(PosMsg->PlayerPos, m_ModelPos);
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -29,7 +29,13 @@
|
|||
/****************************************************************
|
||||
* @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
|
||||
#define TIME_TO_LIVE 10
|
||||
|
||||
#define PLAYER_DATA_NOT_AVAILABLE 0
|
||||
#define PLAYER_DATA_AVAILABLE 1
|
||||
#define PLAYER_DATA_EXPIRED 2
|
||||
|
||||
class MPPlayer {
|
||||
public:
|
||||
|
@ -60,6 +63,12 @@ public:
|
|||
/** Destructor. */
|
||||
~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.
|
||||
* @param sIP IP address or host name 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,
|
||||
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 */
|
||||
void Close(void);
|
||||
|
||||
|
@ -84,7 +90,7 @@ public:
|
|||
|
||||
/** Transform and place model for player
|
||||
*/
|
||||
int Draw(void);
|
||||
TPlayerDataState Draw(void);
|
||||
|
||||
/** Returns the callsign for the player
|
||||
* @return Aircraft's callsign
|
||||
|
@ -97,9 +103,6 @@ public:
|
|||
*/
|
||||
bool CompareCallsign(const char *sCallsign) const;
|
||||
|
||||
/** Loads the model of the aircraft */
|
||||
void LoadModel(void);
|
||||
|
||||
/** Populates a position message for the player
|
||||
* @param MsgHdr Header to be populated
|
||||
* @param PosMsg Position message to be populated
|
||||
|
@ -115,6 +118,9 @@ public:
|
|||
|
||||
private:
|
||||
|
||||
/** Loads the model of the aircraft */
|
||||
void LoadModel(void);
|
||||
|
||||
/** True if object is initialised */
|
||||
bool m_bInitialised;
|
||||
|
||||
|
@ -130,13 +136,13 @@ private:
|
|||
/** Player's callsign */
|
||||
string m_sCallsign;
|
||||
|
||||
/** Aircraft model for player */
|
||||
/** Aircraft model name for player */
|
||||
string m_sModelName;
|
||||
|
||||
/** Simgear model selection */
|
||||
ssgSelector *m_ModelSel;
|
||||
/** The player's loaded model */
|
||||
ssgEntity *m_Model;
|
||||
|
||||
/** Simgear model transform */
|
||||
/** Model transform */
|
||||
ssgTransform *m_ModelTrans;
|
||||
|
||||
/** True if this player is the local player */
|
||||
|
|
|
@ -332,16 +332,18 @@ void FGMultiplayRxMgr::ProcessData(void) {
|
|||
******************************************************************/
|
||||
void FGMultiplayRxMgr::Update(void) {
|
||||
|
||||
int iPlayerDataState;
|
||||
MPPlayer::TPlayerDataState ePlayerDataState;
|
||||
int iPlayerId;
|
||||
|
||||
for (iPlayerId = 0; iPlayerId < MAX_PLAYERS; iPlayerId++) {
|
||||
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
|
||||
// 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];
|
||||
m_Player[iPlayerId] = NULL;
|
||||
}
|
||||
|
|
|
@ -123,7 +123,7 @@ bool FGMultiplayTxMgr::init(void) {
|
|||
// Create a player object for the local player
|
||||
if (bSuccess) {
|
||||
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)) {
|
||||
cerr << "FGMultiplayTxMgr::init - Failed to create player object for local player" << endl;
|
||||
bSuccess = false;
|
||||
|
|
Loading…
Add table
Reference in a new issue