#include "sv_demo.h"
#include "image.h"
+#include "utf8lib.h"
+
// for secure rcon authentication
#include "hmac.h"
#include "mdfour.h"
for (j = 0;j < NETGRAPH_PACKETS;j++)
if (client->netconnection->incoming_netgraph[j].unreliablebytes == NETGRAPH_LOSTPACKET)
packetloss++;
- packetloss = packetloss * 100 / NETGRAPH_PACKETS;
+ packetloss = (packetloss * 100 + NETGRAPH_PACKETS - 1) / NETGRAPH_PACKETS;
ping = bound(0, (int)floor(client->ping*1000+0.5), 9999);
}
void Host_Savegame_to (const char *name)
{
qfile_t *f;
- int i, lightstyles = 64;
+ int i, k, l, lightstyles = 64;
char comment[SAVEGAME_COMMENT_LENGTH+1];
+ char line[MAX_INPUTLINE];
qboolean isserver;
+ char *s;
// first we have to figure out if this can be saved in 64 lightstyles
// (for Quake compatibility)
for (i=1 ; i<MAX_SOUNDS ; i++)
if (sv.sound_precache[i][0])
FS_Printf(f,"sv.sound_precache %i %s\n", i, sv.sound_precache[i]);
+
+ // darkplaces extension - save buffers
+ for (i = 0; i < (int)Mem_ExpandableArray_IndexRange(&prog->stringbuffersarray); i++)
+ {
+ prvm_stringbuffer_t *stringbuffer = (prvm_stringbuffer_t*) Mem_ExpandableArray_RecordAtIndex(&prog->stringbuffersarray, i);
+ if(stringbuffer && (stringbuffer->flags & STRINGBUFFER_SAVED))
+ {
+ for(k = 0; k < stringbuffer->num_strings; k++)
+ {
+ if (!stringbuffer->strings[k])
+ continue;
+ // Parse the string a bit to turn special characters
+ // (like newline, specifically) into escape codes
+ s = stringbuffer->strings[k];
+ for (l = 0;l < (int)sizeof(line) - 2 && *s;)
+ {
+ if (*s == '\n')
+ {
+ line[l++] = '\\';
+ line[l++] = 'n';
+ }
+ else if (*s == '\r')
+ {
+ line[l++] = '\\';
+ line[l++] = 'r';
+ }
+ else if (*s == '\\')
+ {
+ line[l++] = '\\';
+ line[l++] = '\\';
+ }
+ else if (*s == '"')
+ {
+ line[l++] = '\\';
+ line[l++] = '"';
+ }
+ else
+ line[l++] = *s;
+ s++;
+ }
+ line[l] = '\0';
+ FS_Printf(f,"sv.bufstr %i %i \"%s\"\n", i, k, line);
+ }
+ }
+ }
FS_Printf(f,"*/\n");
#endif
Host_Loadgame_f
===============
*/
+
void Host_Loadgame_f (void)
{
char filename[MAX_QPATH];
const char *t;
char *text;
prvm_edict_t *ent;
- int i;
+ int i, k;
int entnum;
int version;
float spawn_parms[NUM_SPAWN_PARMS];
+ prvm_stringbuffer_t *stringbuffer;
+ size_t alloclen;
if (Cmd_Argc() != 2)
{
}
}
+ // unlink all entities
+ World_UnlinkAll(&sv.world);
+
// load the edicts out of the savegame file
end = t;
for (;;)
else
Con_Printf("unsupported sound %i \"%s\"\n", i, com_token);
}
+ else if (!strcmp(com_token, "sv.bufstr"))
+ {
+ COM_ParseToken_Simple(&t, false, false);
+ i = atoi(com_token);
+ COM_ParseToken_Simple(&t, false, false);
+ k = atoi(com_token);
+ COM_ParseToken_Simple(&t, false, false);
+ stringbuffer = (prvm_stringbuffer_t*) Mem_ExpandableArray_RecordAtIndex(&prog->stringbuffersarray, i);
+ // VorteX: nasty code, cleanup required
+ // create buffer at this index
+ if(!stringbuffer)
+ stringbuffer = (prvm_stringbuffer_t *) Mem_ExpandableArray_AllocRecordAtIndex(&prog->stringbuffersarray, i);
+ if (!stringbuffer)
+ Con_Printf("cant write string %i into buffer %i\n", k, i);
+ else
+ {
+ // code copied from VM_bufstr_set
+ // expand buffer
+ if (stringbuffer->max_strings <= i)
+ {
+ char **oldstrings = stringbuffer->strings;
+ stringbuffer->max_strings = max(stringbuffer->max_strings * 2, 128);
+ while (stringbuffer->max_strings <= i)
+ stringbuffer->max_strings *= 2;
+ stringbuffer->strings = (char **) Mem_Alloc(prog->progs_mempool, stringbuffer->max_strings * sizeof(stringbuffer->strings[0]));
+ if (stringbuffer->num_strings > 0)
+ memcpy(stringbuffer->strings, oldstrings, stringbuffer->num_strings * sizeof(stringbuffer->strings[0]));
+ if (oldstrings)
+ Mem_Free(oldstrings);
+ }
+ // allocate string
+ stringbuffer->num_strings = max(stringbuffer->num_strings, k + 1);
+ if(stringbuffer->strings[k])
+ Mem_Free(stringbuffer->strings[k]);
+ stringbuffer->strings[k] = NULL;
+ alloclen = strlen(com_token) + 1;
+ stringbuffer->strings[k] = (char *)Mem_Alloc(prog->progs_mempool, alloclen);
+ memcpy(stringbuffer->strings[k], com_token, alloclen);
+ }
+ }
// skip any trailing text or unrecognized commands
while (COM_ParseToken_Simple(&t, true, false) && strcmp(com_token, "\n"))
;
host_client->name[1] = '0' + STRING_COLOR_DEFAULT;
}
- COM_StringLengthNoColors(host_client->name, 0, &valid_colors);
+ u8_COM_StringLengthNoColors(host_client->name, 0, &valid_colors);
if(!valid_colors) // NOTE: this also proves the string is not empty, as "" is a valid colored string
{
size_t l;
*/
void Host_Pings_f (void)
{
- int i, j, ping, packetloss;
+ int i, j, ping, packetloss, movementloss;
char temp[128];
if (!host_client->netconnection)
for (i = 0;i < svs.maxclients;i++)
{
packetloss = 0;
+ movementloss = 0;
if (svs.clients[i].netconnection)
+ {
for (j = 0;j < NETGRAPH_PACKETS;j++)
if (svs.clients[i].netconnection->incoming_netgraph[j].unreliablebytes == NETGRAPH_LOSTPACKET)
packetloss++;
- packetloss = packetloss * 100 / NETGRAPH_PACKETS;
+ for (j = 0;j < NETGRAPH_PACKETS;j++)
+ if (svs.clients[i].movement_count[j] < 0)
+ movementloss++;
+ }
+ packetloss = (packetloss * 100 + NETGRAPH_PACKETS - 1) / NETGRAPH_PACKETS;
+ movementloss = (movementloss * 100 + NETGRAPH_PACKETS - 1) / NETGRAPH_PACKETS;
ping = (int)floor(svs.clients[i].ping*1000+0.5);
ping = bound(0, ping, 9999);
if (sv.protocol == PROTOCOL_QUAKEWORLD)
else
{
// write the string into the packet as multiple unterminated strings to avoid needing a local buffer
- dpsnprintf(temp, sizeof(temp), " %d %d", ping, packetloss);
+ if(movementloss)
+ dpsnprintf(temp, sizeof(temp), " %d %d,%d", ping, packetloss, movementloss);
+ else
+ dpsnprintf(temp, sizeof(temp), " %d %d", ping, packetloss);
MSG_WriteUnterminatedString(&host_client->netconnection->message, temp);
}
}
void Host_PingPLReport_f(void)
{
+ char *errbyte;
int i;
int l = Cmd_Argc();
if (l > cl.maxclients)
for (i = 0;i < l;i++)
{
cl.scores[i].qw_ping = atoi(Cmd_Argv(1+i*2));
- cl.scores[i].qw_packetloss = atoi(Cmd_Argv(1+i*2+1));
+ cl.scores[i].qw_packetloss = strtol(Cmd_Argv(1+i*2+1), &errbyte, 0);
+ if(errbyte && *errbyte == ',')
+ cl.scores[i].qw_movementloss = atoi(errbyte + 1);
+ else
+ cl.scores[i].qw_movementloss = 0;
}
}