summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source/mvd_game.c117
-rw-r--r--source/mvd_local.h6
-rw-r--r--source/sv_local.h3
-rw-r--r--source/sv_user.c6
4 files changed, 102 insertions, 30 deletions
diff --git a/source/mvd_game.c b/source/mvd_game.c
index 26ce906..4fc07a3 100644
--- a/source/mvd_game.c
+++ b/source/mvd_game.c
@@ -222,6 +222,7 @@ static void MVD_FollowStop( udpClient_t *client ) {
}
client->clientNum = mvd->clientNum;
+ client->oldtarget = client->target;
client->target = NULL;
if( client->layout_type == LAYOUT_FOLLOW ) {
@@ -380,18 +381,46 @@ SPECTATOR COMMANDS
==============================================================================
*/
+static void MVD_BroadcastPrintf( mvd_t *mvd, int level, const char *fmt, ... ) {
+ va_list argptr;
+ char text[MAXPRINTMSG];
+ int len;
+ udpClient_t *other;
+ client_t *cl;
+
+ va_start( argptr, fmt );
+ len = Q_vsnprintf( text, sizeof( text ), fmt, argptr );
+ va_end( argptr );
+
+ MSG_WriteByte( svc_print );
+ MSG_WriteByte( level );
+ MSG_WriteData( text, len + 1 );
+
+ LIST_FOR_EACH( udpClient_t, other, &mvd->udpClients, entry ) {
+ cl = other->cl;
+ if( cl->state < cs_spawned ) {
+ continue;
+ }
+ if( level < cl->messagelevel ) {
+ continue;
+ }
+ if( level == PRINT_CHAT && ( other->uf & UF_NOMVDCHAT ) ) {
+ continue;
+ }
+ SV_ClientAddMessage( cl, MSG_RELIABLE );
+ }
+
+ SZ_Clear( &msg_write );
+}
+
void MVD_SwitchChannel( udpClient_t *client, mvd_t *mvd ) {
client_t *cl = client->cl;
- if( mvd == client->mvd ) {
- SV_ClientPrintf( client->cl, PRINT_HIGH,
- "[MVD] You are already on this channel.\n" );
- return; // nothing to do
- }
-
List_Remove( &client->entry );
List_Append( &mvd->udpClients, &client->entry );
client->mvd = mvd;
+ client->begin_time = 0;
+ client->target = client->oldtarget = NULL;
cl->gamedir = mvd->gamedir;
cl->mapname = mvd->configstrings[CS_NAME];
@@ -407,6 +436,28 @@ void MVD_SwitchChannel( udpClient_t *client, mvd_t *mvd ) {
SV_ClientAddMessage( client->cl, MSG_RELIABLE|MSG_CLEAR );
}
+void MVD_TrySwitchChannel( udpClient_t *client, mvd_t *mvd ) {
+ if( mvd == client->mvd ) {
+ SV_ClientPrintf( client->cl, PRINT_HIGH,
+ "[MVD] You are already on this channel.\n" );
+ return; // nothing to do
+ }
+ if( client->begin_time ) {
+ if( client->begin_time > svs.realtime ) {
+ client->begin_time = svs.realtime;
+ }
+ if( svs.realtime - client->begin_time < 3000 ) {
+ SV_ClientPrintf( client->cl, PRINT_HIGH,
+ "[MVD] You may not switch channels too soon.\n" );
+ return;
+ }
+ MVD_BroadcastPrintf( client->mvd, PRINT_MEDIUM,
+ "[MVD] %s left the channel.\n", client->cl->name );
+ }
+
+ MVD_SwitchChannel( client, mvd );
+}
+
static void MVD_Admin_f( udpClient_t *client ) {
char *s = mvd_admin_password->string;
@@ -436,7 +487,7 @@ static void MVD_Say_f( udpClient_t *client ) {
udpClient_t *other;
client_t *cl;
char buffer[128];
- int i, length;
+ int i, len;
if( mvd_flood_mute->integer && !client->admin ) {
SV_ClientPrintf( client->cl, PRINT_HIGH,
@@ -470,12 +521,12 @@ static void MVD_Say_f( udpClient_t *client ) {
client->floodSamples[client->floodHead & FLOOD_MASK] = sv.time;
client->floodHead++;
- length = Com_sprintf( buffer, sizeof( buffer ), "{%s}: %s\n",
+ len = Com_sprintf( buffer, sizeof( buffer ), "{%s}: %s\n",
client->cl->name, Cmd_Args() );
MSG_WriteByte( svc_print );
MSG_WriteByte( PRINT_CHAT );
- MSG_WriteData( buffer, length + 1 );
+ MSG_WriteData( buffer, len + 1 );
LIST_FOR_EACH( udpClient_t, other, &mvd->udpClients, entry ) {
cl = other->cl;
@@ -497,6 +548,8 @@ static void MVD_Say_f( udpClient_t *client ) {
static void MVD_Observe_f( udpClient_t *client ) {
if( client->target ) {
MVD_FollowStop( client );
+ } else if( client->oldtarget && client->oldtarget->inuse ) {
+ MVD_FollowStart( client, client->oldtarget );
} else {
MVD_FollowFirst( client );
}
@@ -542,13 +595,27 @@ static void MVD_Invuse_f( udpClient_t *client ) {
continue;
}
if( cursor == client->cursor ) {
- MVD_SwitchChannel( client, mvd );
+ MVD_TrySwitchChannel( client, mvd );
return;
}
cursor++;
}
}
+static void MVD_Join_f( udpClient_t *client ) {
+ mvd_t *mvd;
+
+ SV_BeginRedirect( RD_CLIENT );
+ mvd = MVD_SetChannel( 1 );
+ Com_EndRedirect();
+
+ if( !mvd ) {
+ return;
+ }
+
+ MVD_TrySwitchChannel( client, mvd );
+}
+
static void MVD_GameClientCommand( edict_t *ent ) {
udpClient_t *client = EDICT_MVDCL( ent );
char *cmd;
@@ -620,8 +687,12 @@ static void MVD_GameClientCommand( edict_t *ent ) {
MVD_LayoutChannels( client );
return;
}
+ if( !strcmp( cmd, "join" ) ) {
+ MVD_Join_f( client );
+ return;
+ }
- SV_ClientPrintf( client->cl, PRINT_LOW, "[MVD] Unknown command: %s\n", cmd );
+ SV_ClientPrintf( client->cl, PRINT_HIGH, "[MVD] Unknown command: %s\n", cmd );
}
/*
@@ -783,13 +854,13 @@ static void MVD_GameClientBegin( edict_t *ent ) {
memset( &client->lastcmd, 0, sizeof( client->lastcmd ) );
memset( &client->ps, 0, sizeof( client->ps ) );
- if( !client->connected ) {
- SV_BroadcastPrintf( PRINT_MEDIUM, "[MVD] %s entered the server\n",
- client->cl->name );
- client->connected = qtrue;
+ if( !client->begin_time ) {
+ MVD_BroadcastPrintf( mvd, PRINT_MEDIUM,
+ "[MVD] %s entered the channel\n", client->cl->name );
}
+ client->begin_time = svs.realtime;
- // spawn the spectator
+ // spawn the spectator
VectorScale( mvd->spawnOrigin, 8, client->ps.pmove.origin );
VectorCopy( mvd->spawnAngles, client->ps.viewangles );
@@ -822,10 +893,10 @@ static void MVD_GameClientDisconnect( edict_t *ent ) {
udpClient_t *client = EDICT_MVDCL( ent );
client_t *cl = client->cl;
- if( client->connected ) {
- SV_BroadcastPrintf( PRINT_MEDIUM,
- "[MVD] %s left the server\n", cl->name );
- client->connected = qfalse;
+ if( client->begin_time ) {
+ MVD_BroadcastPrintf( client->mvd, PRINT_MEDIUM,
+ "[MVD] %s disconnected\n", cl->name );
+ client->begin_time = 0;
}
}
@@ -850,11 +921,7 @@ static void MVD_GameClientThink( edict_t *ent, usercmd_t *cmd ) {
pmove_t pm;
if( !( old->buttons & BUTTON_ATTACK ) && ( cmd->buttons & BUTTON_ATTACK ) ) {
- if( client->target ) {
- MVD_FollowStop( client );
- } else {
- MVD_FollowFirst( client );
- }
+ MVD_Observe_f( client );
}
if( client->target ) {
diff --git a/source/mvd_local.h b/source/mvd_local.h
index 8f8cbf8..e75fdb1 100644
--- a/source/mvd_local.h
+++ b/source/mvd_local.h
@@ -78,9 +78,9 @@ typedef struct {
client_t *cl;
qboolean admin;
- qboolean connected;
+ unsigned begin_time;
int lastframe;
- mvd_player_t *target;
+ mvd_player_t *target, *oldtarget;
float fov;
int uf;
int cursor;
@@ -182,6 +182,8 @@ void MVD_GetStatus( void );
void MVD_Free( mvd_t *mvd );
void MVD_Shutdown( void );
+mvd_t *MVD_SetChannel( int arg );
+
const char *MVD_Play_g( const char *partial, int state );
void MVD_Connect_f( void );
diff --git a/source/sv_local.h b/source/sv_local.h
index f86d692..0994397 100644
--- a/source/sv_local.h
+++ b/source/sv_local.h
@@ -432,6 +432,9 @@ void SV_ClientReset( client_t *client );
typedef enum {RD_NONE, RD_CLIENT, RD_PACKET} redirect_t;
#define SV_OUTPUTBUF_LENGTH (MAX_PACKETLEN_DEFAULT - 16)
+#define SV_BeginRedirect( target ) \
+ Com_BeginRedirect( target, sv_outputbuf, SV_OUTPUTBUF_LENGTH, SV_FlushRedirect )
+
extern char sv_outputbuf[SV_OUTPUTBUF_LENGTH];
void SV_FlushRedirect( int redirected, char *outputbuf, int length );
diff --git a/source/sv_user.c b/source/sv_user.c
index 11910bc..ebd5acb 100644
--- a/source/sv_user.c
+++ b/source/sv_user.c
@@ -695,7 +695,7 @@ static void SV_ShowServerinfo_f( void ) {
Cvar_BitInfo( serverinfo, CVAR_SERVERINFO );
- Com_BeginRedirect( RD_CLIENT, sv_outputbuf, SV_OUTPUTBUF_LENGTH, SV_FlushRedirect );
+ SV_BeginRedirect( RD_CLIENT );
Info_Print( serverinfo );
Com_EndRedirect();
}
@@ -784,13 +784,13 @@ static void SV_CvarResult_f( void ) {
#if USE_ANTICHEAT & 2
static void SV_AC_List_f( void ) {
- Com_BeginRedirect( RD_CLIENT, sv_outputbuf, SV_OUTPUTBUF_LENGTH, SV_FlushRedirect );
+ SV_BeginRedirect( RD_CLIENT );
AC_List_f();
Com_EndRedirect();
}
static void SV_AC_Info_f( void ) {
- Com_BeginRedirect( RD_CLIENT, sv_outputbuf, SV_OUTPUTBUF_LENGTH, SV_FlushRedirect );
+ SV_BeginRedirect( RD_CLIENT );
AC_Info_f();
Com_EndRedirect();
}