Permalink
Browse files

Add a SpectatorClassComponent that copies the playerstate of the spec…

…tated plaer.

This also fixes the issue of players being booted from a server during intermission.
  • Loading branch information...
DolceTriade committed Dec 14, 2015
1 parent 5e72438 commit d378fdc9776bb815a47b3b9b9d326a37f72cc6e1
@@ -179,6 +179,7 @@ set(SGAMELIST
${GAMELOGIC_DIR}/sgame/components/ThinkingComponent.cpp
${GAMELOGIC_DIR}/sgame/components/TrapperComponent.cpp
${GAMELOGIC_DIR}/sgame/components/TurretComponent.cpp
${GAMELOGIC_DIR}/sgame/components/SpectatorComponent.cpp

${ENGINE_DIR}/server/sg_api.h
${ENGINE_DIR}/server/sg_msgdef.h
@@ -0,0 +1,31 @@
#include "SpectatorComponent.h"

SpectatorComponent::SpectatorComponent(Entity& entity, ClientComponent& r_ClientComponent)
: SpectatorComponentBase(entity, r_ClientComponent)
{}

void SpectatorComponent::HandlePrepareNetCode() {
gclient_t* cl = entity.oldEnt->client;

if (!cl
|| cl->sess.spectatorState != SPECTATOR_FOLLOW
|| cl->sess.spectatorClient < 0
|| cl->sess.spectatorClient >= level.maxclients
|| level.clients[cl->sess.spectatorClient].pers.connected != CON_CONNECTED) {
return;
}

// Save
int score = cl->ps.persistant[PERS_SCORE];
int ping = cl->ps.ping;

// Copy
cl->ps = level.clients[cl->sess.spectatorClient].ps;

// Restore
cl->ps.persistant[PERS_SCORE] = score;
cl->ps.ping = ping;

cl->ps.pm_flags |= PMF_FOLLOW;
cl->ps.pm_flags &= ~PMF_QUEUED;
}
@@ -0,0 +1,33 @@
#ifndef SPECTATOR_COMPONENT_H_
#define SPECTATOR_COMPONENT_H_

#include "../backend/CBSEBackend.h"
#include "../backend/CBSEComponents.h"

class SpectatorComponent: public SpectatorComponentBase {
public:
// ///////////////////// //
// Autogenerated Members //
// ///////////////////// //

/**
* @brief Default constructor of the SpectatorComponent.
* @param entity The entity that owns the component instance.
* @param r_ClientComponent A ClientComponent instance that this component depends on.
* @note This method is an interface for autogenerated code, do not modify its signature.
*/
SpectatorComponent(Entity& entity, ClientComponent& r_ClientComponent);

/**
* @brief Handle the PrepareNetCode message.
* @note This method is an interface for autogenerated code, do not modify its signature.
*/
void HandlePrepareNetCode();

// ///////////////////// //

private:

};

#endif // SPECTATOR_COMPONENT_H_
@@ -113,6 +113,12 @@ components:
messages:
- Damage

Spectator:
messages:
- PrepareNetCode
requires:
- Client

AlienClass:
requires:
- Client
@@ -302,6 +308,13 @@ entities:
# Player Classes #
##################

#-----------------+
# Spectator Class |
#-----------------+
Spectator:
components:
Spectator:

#---------------+
# Alien Classes |
#---------------+
@@ -2272,47 +2272,6 @@ void G_RunClient( gentity_t *ent )
ClientThink_real( ent );
}

/*
==================
SpectatorClientEndFrame
==================
*/
void SpectatorClientEndFrame( gentity_t *ent )
{
gclient_t *cl;
int clientNum;
int score, ping;

// if we are doing a chase cam or a remote view, grab the latest info
if ( ent->client->sess.spectatorState == SPECTATOR_FOLLOW )
{
clientNum = ent->client->sess.spectatorClient;

if ( clientNum >= 0 && clientNum < level.maxclients )
{
cl = &level.clients[ clientNum ];

if ( cl->pers.connected == CON_CONNECTED )
{
// Save
score = ent->client->ps.persistant[ PERS_SCORE ];
ping = ent->client->ps.ping;

// Copy
ent->client->ps = cl->ps;

// Restore
ent->client->ps.persistant[ PERS_SCORE ] = score;
ent->client->ps.ping = ping;

ent->client->ps.pm_flags |= PMF_FOLLOW;
ent->client->ps.pm_flags &= ~PMF_QUEUED;
}
}
}
}

/*
==============
ClientEndFrame
@@ -2326,7 +2285,6 @@ void ClientEndFrame( gentity_t *ent )
{
if ( ent->client->sess.spectatorState != SPECTATOR_NOT )
{
SpectatorClientEndFrame( ent );
return;
}

@@ -1501,7 +1501,10 @@ static void ClientSpawnCBSE(gentity_t *ent, bool evolving) {
// - Call assignment operators on the new components to transfer state from old entity.

case PCL_NONE:
// TODO: Add SpectatorEntity.
SpectatorEntity::Params params;
params.oldEnt = ent;
params.Client_clientData = client;
ent->entity = new SpectatorEntity(params);
return;

case PCL_ALIEN_BUILDER0: {
@@ -23,6 +23,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA

#include "sg_local.h"
#include "CBSE.h"
#include "backend/CBSEBackend.h"

#define INTERMISSION_DELAY_TIME 1000

@@ -2991,9 +2992,18 @@ void G_RunFrame( int levelTime )
void G_PrepareEntityNetCode() {
// TODO: Allow ForEntities with empty template arguments.
gentity_t *oldEnt = &g_entities[0];
// Prepare netcode for all non-specs first.
for (int i = 0; i < level.num_entities; i++, oldEnt++) {
if (oldEnt->entity) {
if (oldEnt->entity->Get<SpectatorComponent>()) {
continue;
}
oldEnt->entity->PrepareNetCode();
}
}

// Prepare netcode for specs
ForEntities<SpectatorComponent>([&](Entity& entity, SpectatorComponent& spectatorComponent){
entity.PrepareNetCode();
});
}

0 comments on commit d378fdc

Please sign in to comment.