]> git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - cmd.c
PRVM: indicate which VM triggered some common string messages
[xonotic/darkplaces.git] / cmd.c
diff --git a/cmd.c b/cmd.c
index deb9a4a66b11706ae19ccf817a852d8f8c827db9..6230fa021854d31fd72fb6535b664e3ddd196446 100644 (file)
--- a/cmd.c
+++ b/cmd.c
@@ -74,11 +74,13 @@ Cmd_Defer_f
 Cause a command to be executed after a delay.
 ============
 */
-static cmd_input_t *Cbuf_NodeGet(cmd_buf_t *cbuf, cmd_input_t *existing);
+static void Cbuf_ParseText(cmd_state_t *cmd, llist_t *head, cmd_input_t *existing, const char *text, qbool allowpending);
+static void Cbuf_LinkString(cmd_state_t *cmd, llist_t *head, cmd_input_t *existing, const char *text, qbool leavepending, unsigned int cmdsize);
 static void Cmd_Defer_f (cmd_state_t *cmd)
 {
        cmd_input_t *current;
        cmd_buf_t *cbuf = cmd->cbuf;
+       unsigned int cmdsize;
 
        if(Cmd_Argc(cmd) == 1)
        {
@@ -93,25 +95,19 @@ static void Cmd_Defer_f (cmd_state_t *cmd)
        else if(Cmd_Argc(cmd) == 2 && !strcasecmp("clear", Cmd_Argv(cmd, 1)))
        {
                while(!List_Is_Empty(&cbuf->deferred))
+               {
+                       cbuf->size -= List_Entry(cbuf->deferred.next, cmd_input_t, list)->length;
                        List_Move_Tail(cbuf->deferred.next, &cbuf->free);
+               }
        }
-       else if(Cmd_Argc(cmd) == 3)
+       else if(Cmd_Argc(cmd) == 3 && (cmdsize = strlen(Cmd_Argv(cmd, 2))) )
        {
-               const char *text = Cmd_Argv(cmd, 2);
-               current = Cbuf_NodeGet(cbuf, NULL);
-               current->length = strlen(text);
-               current->source = cmd;
-               current->delay = atof(Cmd_Argv(cmd, 1));
-
-               if(current->size < current->length)
-               {
-                       current->text = (char *)Mem_Realloc(cbuf_mempool, current->text, current->length + 1);
-                       current->size = current->length;
-               }
+               Cbuf_Lock(cbuf);
 
-               strlcpy(current->text, text, current->length + 1);
+               Cbuf_LinkString(cmd, &cbuf->deferred, NULL, Cmd_Argv(cmd, 2), false, cmdsize);
+               List_Entry(cbuf->deferred.prev, cmd_input_t, list)->delay = atof(Cmd_Argv(cmd, 1));
 
-               List_Move_Tail(&current->list, &cbuf->deferred);
+               Cbuf_Unlock(cbuf);
        }
        else
        {
@@ -362,25 +358,25 @@ Cbuf_Execute_Deferred --blub
 */
 static void Cbuf_Execute_Deferred (cmd_buf_t *cbuf)
 {
-       cmd_input_t *current;
-       double eat;
+       cmd_input_t *current, *n;
+       vec_t eat;
 
        if (host.realtime - cbuf->deferred_oldtime < 0 || host.realtime - cbuf->deferred_oldtime > 1800)
                cbuf->deferred_oldtime = host.realtime;
        eat = host.realtime - cbuf->deferred_oldtime;
-       if (eat < (1.0 / 120.0))
+       if (eat < 1/128)
                return;
        cbuf->deferred_oldtime = host.realtime;
 
-       List_For_Each_Entry(current, &cbuf->deferred, cmd_input_t, list)
+       List_For_Each_Entry_Safe(current, n, &cbuf->deferred, cmd_input_t, list)
        {
                current->delay -= eat;
                if(current->delay <= 0)
                {
-                       cbuf->size += current->length;
-                       List_Move(&current->list, &cbuf->start);
-                       // We must return and come back next frame or the engine will freeze. Fragile... like glass :3
-                       return;
+                       Cbuf_AddText(current->source, current->text); // parse deferred string and append its cmdstring(s)
+                       List_Entry(cbuf->start.prev, cmd_input_t, list)->pending = false; // faster than div0-stable's Cbuf_AddText(";\n");
+                       List_Move_Tail(&current->list, &cbuf->free); // make deferred string memory available for reuse
+                       cbuf->size -= current->length;
                }
        }
 }
@@ -390,12 +386,14 @@ static void Cbuf_Execute_Deferred (cmd_buf_t *cbuf)
 Cbuf_Execute
 ============
 */
+extern qbool prvm_runawaycheck;
 static qbool Cmd_PreprocessString(cmd_state_t *cmd, const char *intext, char *outtext, unsigned maxoutlen, cmd_alias_t *alias );
 void Cbuf_Execute (cmd_buf_t *cbuf)
 {
        cmd_input_t *current;
        char preprocessed[MAX_INPUTLINE];
        char *firstchar;
+       unsigned int i = 0;
 
        // LadyHavoc: making sure the tokenizebuffer doesn't get filled up by repeated crashes
        cbuf->tokenizebufferpos = 0;
@@ -447,6 +445,16 @@ void Cbuf_Execute (cmd_buf_t *cbuf)
                        cbuf->wait = false;
                        break;
                }
+
+               if (++i == 1000000 && prvm_runawaycheck)
+               {
+                       Con_Printf(CON_WARN "Cbuf_Execute: runaway loop counter hit limit of %d commands, clearing command buffers!\n", i);
+                       while (!List_Is_Empty(&cbuf->start))
+                               List_Move_Tail(cbuf->start.next, &cbuf->free);
+                       while (!List_Is_Empty(&cbuf->deferred))
+                               List_Move_Tail(cbuf->deferred.next, &cbuf->free);
+                       cbuf->size = 0;
+               }
        }
 }
 
@@ -1698,7 +1706,7 @@ void Cmd_Shutdown(void)
 Cmd_Argc
 ============
 */
-int            Cmd_Argc (cmd_state_t *cmd)
+inline int Cmd_Argc (cmd_state_t *cmd)
 {
        return cmd->argc;
 }
@@ -1708,7 +1716,7 @@ int               Cmd_Argc (cmd_state_t *cmd)
 Cmd_Argv
 ============
 */
-const char *Cmd_Argv(cmd_state_t *cmd, int arg)
+inline const char *Cmd_Argv(cmd_state_t *cmd, int arg)
 {
        if (arg >= cmd->argc )
                return cmd->null_string;
@@ -1720,7 +1728,7 @@ const char *Cmd_Argv(cmd_state_t *cmd, int arg)
 Cmd_Args
 ============
 */
-const char *Cmd_Args (cmd_state_t *cmd)
+inline const char *Cmd_Args (cmd_state_t *cmd)
 {
        return cmd->args;
 }