Skip to content

Commit

Permalink
Add a SpectatorClassComponent that copies the playerstate of the spec…
Browse files Browse the repository at this point in the history
…tated plaer.

This also fixes the issue of players being booted from a server during intermission.
  • Loading branch information
DolceTriade committed Dec 19, 2015
1 parent 5e72438 commit d378fdc
Show file tree
Hide file tree
Showing 7 changed files with 92 additions and 43 deletions.
1 change: 1 addition & 0 deletions src.cmake
Expand Up @@ -179,6 +179,7 @@ set(SGAMELIST
${GAMELOGIC_DIR}/sgame/components/ThinkingComponent.cpp ${GAMELOGIC_DIR}/sgame/components/ThinkingComponent.cpp
${GAMELOGIC_DIR}/sgame/components/TrapperComponent.cpp ${GAMELOGIC_DIR}/sgame/components/TrapperComponent.cpp
${GAMELOGIC_DIR}/sgame/components/TurretComponent.cpp ${GAMELOGIC_DIR}/sgame/components/TurretComponent.cpp
${GAMELOGIC_DIR}/sgame/components/SpectatorComponent.cpp


${ENGINE_DIR}/server/sg_api.h ${ENGINE_DIR}/server/sg_api.h
${ENGINE_DIR}/server/sg_msgdef.h ${ENGINE_DIR}/server/sg_msgdef.h
Expand Down
31 changes: 31 additions & 0 deletions src/sgame/components/SpectatorComponent.cpp
@@ -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;
}
33 changes: 33 additions & 0 deletions src/sgame/components/SpectatorComponent.h
@@ -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_
13 changes: 13 additions & 0 deletions src/sgame/entities.yaml
Expand Up @@ -113,6 +113,12 @@ components:
messages: messages:
- Damage - Damage


Spectator:
messages:
- PrepareNetCode
requires:
- Client

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


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

#---------------+ #---------------+
# Alien Classes | # Alien Classes |
#---------------+ #---------------+
Expand Down
42 changes: 0 additions & 42 deletions src/sgame/sg_active.cpp
Expand Up @@ -2272,47 +2272,6 @@ void G_RunClient( gentity_t *ent )
ClientThink_real( 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 ClientEndFrame
Expand All @@ -2326,7 +2285,6 @@ void ClientEndFrame( gentity_t *ent )
{ {
if ( ent->client->sess.spectatorState != SPECTATOR_NOT ) if ( ent->client->sess.spectatorState != SPECTATOR_NOT )
{ {
SpectatorClientEndFrame( ent );
return; return;
} }


Expand Down
5 changes: 4 additions & 1 deletion src/sgame/sg_client.cpp
Expand Up @@ -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. // - Call assignment operators on the new components to transfer state from old entity.


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


case PCL_ALIEN_BUILDER0: { case PCL_ALIEN_BUILDER0: {
Expand Down
10 changes: 10 additions & 0 deletions src/sgame/sg_main.cpp
Expand Up @@ -23,6 +23,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA


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


#define INTERMISSION_DELAY_TIME 1000 #define INTERMISSION_DELAY_TIME 1000


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