static void CL_FinishTimeDemo (void);
+// from ProQuake: space to fill out the demo header for record at any tim
+static unsigned char *demo_head;
+static int *demo_head_sizes;
+
/*
==============================================================================
if (cls.demopaused) // LadyHavoc: pausedemo
return;
+ if (cls.signon < 2)
+ {
+ Vec_Append ((void**)&demo_head, 1, message->data, message->cursize);
+ VEC_PUSH (demo_head_sizes, message->cursize);
+ }
len = LittleLong (message->cursize);
FS_Write (cls.demofile, &len, 4);
for (i=0 ; i<3 ; i++)
if (c == 2 && cls.state == ca_connected)
{
+#if 0
Con_Print("Can not record - already connected to server\nClient demo recording must be started before connecting\n");
return;
+#endif
}
+#if 0
if (cls.state == ca_connected)
CL_Disconnect();
+#endif
// write the forced cd track number, or -1
if (c == 4)
cls.demorecording = true;
cls.demo_lastcsprogssize = -1;
cls.demo_lastcsprogscrc = -1;
+
+ // from ProQuake: initialize the demo file if we're already connected
+ if (c == 2 && cls.state == ca_connected)
+ {
+ sizebuf_t buf;
+ unsigned char tmpbuf[NET_MAXMESSAGE];
+ int cursize = buf.cursize;
+ int maxsize = buf.maxsize;
+ int i, count;
+
+ buf.data = demo_head;
+ for (i = 0, count = VEC_SIZE (demo_head_sizes); i < count; i++)
+ {
+ buf.cursize = demo_head_sizes[i];
+ CL_WriteDemoMessage(&buf);
+ buf.data += buf.cursize;
+ }
+
+ buf.data = tmpbuf;
+ buf.maxsize = sizeof (tmpbuf);
+ SZ_Clear (&buf);
+
+ // current names, colors, and frag counts
+ for (i = 0; i < cl.maxclients; i++)
+ {
+ MSG_WriteByte (&buf, svc_updatename);
+ MSG_WriteByte (&buf, i);
+ MSG_WriteString (&buf, cl.scores[i].name);
+ MSG_WriteByte (&buf, svc_updatefrags);
+ MSG_WriteByte (&buf, i);
+ MSG_WriteShort (&buf, cl.scores[i].frags);
+ MSG_WriteByte (&buf, svc_updatecolors);
+ MSG_WriteByte (&buf, i);
+ MSG_WriteByte (&buf, cl.scores[i].colors);
+ }
+
+ // send all current light styles
+ for (i = 0; i < MAX_LIGHTSTYLES; i++)
+ {
+ MSG_WriteByte (&buf, svc_lightstyle);
+ MSG_WriteByte (&buf, i);
+ MSG_WriteString (&buf, cl.lightstyle[i].map);
+ }
+
+ // what about the CD track or SVC fog... future consideration.
+ MSG_WriteByte (&buf, svc_updatestat);
+ MSG_WriteByte (&buf, STAT_TOTALSECRETS);
+ MSG_WriteLong (&buf, cl.stats[STAT_TOTALSECRETS]);
+
+ MSG_WriteByte (&buf, svc_updatestat);
+ MSG_WriteByte (&buf, STAT_TOTALMONSTERS);
+ MSG_WriteLong (&buf, cl.stats[STAT_TOTALMONSTERS]);
+
+ MSG_WriteByte (&buf, svc_updatestat);
+ MSG_WriteByte (&buf, STAT_SECRETS);
+ MSG_WriteLong (&buf, cl.stats[STAT_SECRETS]);
+
+ MSG_WriteByte (&buf, svc_updatestat);
+ MSG_WriteByte (&buf, STAT_MONSTERS);
+ MSG_WriteLong (&buf, cl.stats[STAT_MONSTERS]);
+
+ // view entity
+ MSG_WriteByte (&buf, svc_setview);
+ MSG_WriteShort (&buf, cl.viewentity);
+
+ // signon
+ MSG_WriteByte (&buf, svc_signonnum);
+ MSG_WriteByte (&buf, 3);
+
+ CL_WriteDemoMessage(&buf);
+
+ }
}
void CL_PlayDemo(const char *demo)
}
return blocks * 4;
}
+
+
+/*
+============================================================================
+
+ DYNAMIC VECTORS
+
+============================================================================
+*/
+
+void Vec_Grow (void **pvec, size_t element_size, size_t count)
+{
+ vec_header_t header;
+ if (*pvec)
+ header = VEC_HEADER(*pvec);
+ else
+ header.size = header.capacity = 0;
+
+ if (header.size + count > header.capacity)
+ {
+ void *new_buffer;
+ size_t total_size;
+
+ header.capacity = header.size + count;
+ header.capacity += header.capacity >> 1;
+ if (header.capacity < 16)
+ header.capacity = 16;
+ total_size = sizeof(vec_header_t) + header.capacity * element_size;
+
+ if (*pvec)
+ new_buffer = realloc (((vec_header_t*)*pvec) - 1, total_size);
+ else
+ new_buffer = malloc (total_size);
+ if (!new_buffer)
+ Sys_Error ("Vec_Grow: failed to allocate %lu bytes\n", (unsigned long)total_size);
+
+ *pvec = 1 + (vec_header_t*)new_buffer;
+ VEC_HEADER(*pvec) = header;
+ }
+}
+
+void Vec_Append (void **pvec, size_t element_size, const void *data, size_t count)
+{
+ if (!count)
+ return;
+ Vec_Grow (pvec, element_size, count);
+ memcpy ((unsigned char *)*pvec + VEC_HEADER(*pvec).size, data, count * element_size);
+ VEC_HEADER(*pvec).size += count;
+}
+
+void Vec_Clear (void **pvec)
+{
+ if (*pvec)
+ VEC_HEADER(*pvec).size = 0;
+}
+
+void Vec_Free (void **pvec)
+{
+ if (*pvec)
+ {
+ free(&VEC_HEADER(*pvec));
+ *pvec = NULL;
+ }
+}
void COM_Init_Commands(void);
+//============================================================================
+// void* Vector
+//============================================================================
+typedef struct vec_header_t {
+ size_t capacity;
+ size_t size;
+} vec_header_t;
+
+#define VEC_HEADER(v) (((vec_header_t*)(v))[-1])
+
+#define VEC_PUSH(v,n) do { Vec_Grow((void**)&(v), sizeof((v)[0]), 1); (v)[VEC_HEADER(v).size++] = (n); } while (0)
+#define VEC_SIZE(v) ((v) ? VEC_HEADER(v).size : 0)
+#define VEC_FREE(v) Vec_Free((void**)&(v))
+#define VEC_CLEAR(v) Vec_Clear((void**)&(v))
+
+void Vec_Grow (void **pvec, size_t element_size, size_t count);
+void Vec_Append (void **pvec, size_t element_size, const void *data, size_t count);
+void Vec_Clear (void **pvec);
+void Vec_Free (void **pvec);
+
//============================================================================
// Endianess handling
//============================================================================