MSG_WriteByte (&client->netconnection->message, svc_signonnum);
MSG_WriteByte (&client->netconnection->message, 1);
- client->sendsignon = true;
client->spawned = false; // need prespawn, spawn, etc
}
PRVM_ExecuteProgram (prog->globals.server->SetNewParms, "QC function SetNewParms is missing");
for (i=0 ; i<NUM_SPAWN_PARMS ; i++)
client->spawn_parms[i] = (&prog->globals.server->parm1)[i];
- }
- // set up the entity for this client (including .colormap, .team, etc)
- PRVM_ED_ClearEdict(client->edict);
+ // set up the entity for this client (including .colormap, .team, etc)
+ PRVM_ED_ClearEdict(client->edict);
+ }
// don't call SendServerinfo for a fresh botclient because its fields have
// not been set up by the qc yet
=======================
*/
static unsigned char sv_sendclientdatagram_buf[NET_MAXMESSAGE]; // FIXME?
-qboolean SV_SendClientDatagram (client_t *client)
+void SV_SendClientDatagram (client_t *client)
{
int rate, maxrate, maxsize, maxsize2;
sizebuf_t msg;
msg.maxsize = maxsize;
msg.cursize = 0;
- MSG_WriteByte (&msg, svc_time);
- MSG_WriteFloat (&msg, sv.time);
-
- // add the client specific data to the datagram
- SV_WriteClientdataToMessage (client, client->edict, &msg, stats);
- VM_SV_WriteAutoSentStats (client, client->edict, &msg, stats);
- SV_WriteEntitiesToClient (client, client->edict, &msg, stats);
-
- // expand packet size to allow effects to go over the rate limit
- // (dropping them is FAR too ugly)
- msg.maxsize = maxsize2;
-
- // copy the server datagram if there is space
- // FIXME: put in delayed queue of effects to send
- if (sv.datagram.cursize > 0 && msg.cursize + sv.datagram.cursize <= msg.maxsize)
- SZ_Write (&msg, sv.datagram.data, sv.datagram.cursize);
-
-// send the datagram
- if (NetConn_SendUnreliableMessage (client->netconnection, &msg) == -1)
+ if (host_client->spawned)
+ {
+ MSG_WriteByte (&msg, svc_time);
+ MSG_WriteFloat (&msg, sv.time);
+
+ // add the client specific data to the datagram
+ SV_WriteClientdataToMessage (client, client->edict, &msg, stats);
+ VM_SV_WriteAutoSentStats (client, client->edict, &msg, stats);
+ SV_WriteEntitiesToClient (client, client->edict, &msg, stats);
+
+ // expand packet size to allow effects to go over the rate limit
+ // (dropping them is FAR too ugly)
+ msg.maxsize = maxsize2;
+
+ // copy the server datagram if there is space
+ // FIXME: put in delayed queue of effects to send
+ if (sv.datagram.cursize > 0 && msg.cursize + sv.datagram.cursize <= msg.maxsize)
+ SZ_Write (&msg, sv.datagram.data, sv.datagram.cursize);
+ }
+ else if (realtime > client->keepalivetime)
{
- SV_DropClient (true);// if the message couldn't send, kick off
- return false;
+ // the player isn't totally in the game yet
+ // send small keepalive messages if too much time has passed
+ client->keepalivetime = realtime + 5;
+ MSG_WriteChar (&msg, svc_nop);
}
- return true;
+// send the datagram
+ NetConn_SendUnreliableMessage (client->netconnection, &msg, sv.protocol);
}
/*
}
-/*
-=======================
-SV_SendNop
-
-Send a nop message without trashing or sending the accumulated client
-message buffer
-=======================
-*/
-void SV_SendNop (client_t *client)
-{
- sizebuf_t msg;
- unsigned char buf[4];
-
- msg.data = buf;
- msg.maxsize = sizeof(buf);
- msg.cursize = 0;
-
- MSG_WriteChar (&msg, svc_nop);
-
- if (NetConn_SendUnreliableMessage (client->netconnection, &msg) == -1)
- SV_DropClient (true); // if the message couldn't send, kick off
- client->last_message = realtime;
-}
-
/*
=======================
SV_SendClientMessages
{
int i, prepared = false;
+ if (sv.protocol == PROTOCOL_QUAKEWORLD)
+ Sys_Error("SV_SendClientMessages: no quakeworld support\n");
+
// update frags, names, etc
SV_UpdateToReliableMessages();
continue;
}
- if (host_client->spawned)
- {
- if (!prepared)
- {
- prepared = true;
- // only prepare entities once per frame
- SV_PrepareEntitiesForSending();
- }
- if (!SV_SendClientDatagram (host_client))
- continue;
- }
- else
+ if (!prepared)
{
- // the player isn't totally in the game yet
- // send small keepalive messages if too much time has passed
- // send a full message when the next signon stage has been requested
- // some other message data (name changes, etc) may accumulate
- // between signon stages
- if (!host_client->sendsignon)
- {
- if (realtime - host_client->last_message > 5)
- SV_SendNop (host_client);
- continue; // don't send out non-signon messages
- }
- }
-
- if (host_client->netconnection->message.cursize)
- {
- if (!NetConn_CanSendMessage (host_client->netconnection))
- continue;
-
- if (NetConn_SendReliableMessage (host_client->netconnection, &host_client->netconnection->message) == -1)
- SV_DropClient (true); // if the message couldn't send, kick off
- SZ_Clear (&host_client->netconnection->message);
- host_client->last_message = realtime;
- host_client->sendsignon = false;
+ prepared = true;
+ // only prepare entities once per frame
+ SV_PrepareEntitiesForSending();
}
+ SV_SendClientDatagram (host_client);
}
// clear muzzle flashes
//
if (sv.active)
{
- // Tell all the clients that the server is changing levels
- SV_VM_Begin();
- MSG_WriteByte(&sv.reliable_datagram, svc_stufftext);
- MSG_WriteString(&sv.reliable_datagram, "reconnect\n");
- SV_VM_End();
+ client_t *client;
+ for (i = 0, client = svs.clients;i < svs.maxclients;i++, client++)
+ {
+ if (client->netconnection)
+ {
+ MSG_WriteByte(&client->netconnection->message, svc_stufftext);
+ MSG_WriteString(&client->netconnection->message, "reconnect\n");
+ }
+ }
}
else
{
//
// set up the new server
//
- Host_ClearMemory ();
-
memset (&sv, 0, sizeof(sv));
+ // if running a local client, make sure it doesn't try to access the last
+ // level's data which is no longer valiud
+ cls.signon = 0;
SV_VM_Setup();
}
// load replacement entity file if found
- entities = NULL;
- if (sv_entpatch.integer)
- entities = (char *)FS_LoadFile(va("maps/%s.ent", sv.name), tempmempool, true, NULL);
- if (entities)
+ if (sv_entpatch.integer && (entities = (char *)FS_LoadFile(va("maps/%s.ent", sv.name), tempmempool, true, NULL)))
{
Con_Printf("Loaded maps/%s.ent\n", sv.name);
PRVM_ED_LoadFromFile (entities);
// LordHavoc: for consistency set these here
int num = PRVM_NUM_FOR_EDICT(e) - 1;
+ e->priv.server->move = false; // don't move on first frame
+
if (num >= 0 && num < svs.maxclients)
{
prvm_eval_t *val;
int eval_SendEntity;
int eval_Version;
int eval_customizeentityforclient;
+int eval_dphitcontentsmask;
+
+int gval_trace_dpstartcontents;
+int gval_trace_dphitcontents;
+int gval_trace_dphitq3surfaceflags;
+int gval_trace_dphittexturename;
mfunction_t *SV_PlayerPhysicsQC;
mfunction_t *EndFrameQC;
eval_SendEntity = PRVM_ED_FindFieldOffset("SendEntity");
eval_Version = PRVM_ED_FindFieldOffset("Version");
eval_customizeentityforclient = PRVM_ED_FindFieldOffset("customizeentityforclient");
+ eval_dphitcontentsmask = PRVM_ED_FindFieldOffset("dphitcontentsmask");
// LordHavoc: allowing QuakeC to override the player movement code
SV_PlayerPhysicsQC = PRVM_ED_FindFunction ("SV_PlayerPhysics");
SV_InitCmd = PRVM_G_STRING(PRVM_ED_FindGlobal("SV_InitCmd")->ofs);
else
SV_InitCmd = NULL;
+
+ gval_trace_dpstartcontents = PRVM_ED_FindGlobalOffset("trace_dpstartcontents");
+ gval_trace_dphitcontents = PRVM_ED_FindGlobalOffset("trace_dphitcontents");
+ gval_trace_dphitq3surfaceflags = PRVM_ED_FindGlobalOffset("trace_dphitq3surfaceflags");
+ gval_trace_dphittexturename = PRVM_ED_FindGlobalOffset("trace_dphittexturename");
}
#define REQFIELDS (sizeof(reqfields) / sizeof(prvm_required_field_t))