cmds

Nick Trout nicktrout at shaw.ca
Sun Dec 21 17:31:35 EST 2003


I have client side working with Lua syntax functions instead of commands.
It's current a hybrid system which is emulating the argc/argv argument
system that was there previously. I create a Lua closure which redirects
function calls to a cmd.dispatch function which takes the variable args
table and pokes it back into the argument system and calls the unchanged
(*_f) function:

function cmd.add(name, fn)
    -- check not a variable
    if cvar.values[name] then
        com.print(string.format("cmd.add: %s already defined as a var\n",
name))
        return
    end
    -- check not exists already
    if _G[name] then
        com.print(string.format("cmd.add: %s already defined\n", name))
        return
    end

    _G[name] = function (...)
            cmd.dispatch(name,fn,arg)
        end
end

As you can see I've created a few namespaces, "com", "cmd" and "cvar", which
contain the Com_* counterparts etc. from the game.

I changed all of the key up/down +/-, config set and binding stuff over to
Lua calls and this all seems to work fine. So every time you hit an action
key to move or fire a Lua string is being compiled and executed! Its a
pretty fast compiler, there won't be any problems until a significant amount
of traffic is generated like this. If this does become an issue the bindings
etc can be precompiled in wrapper functions and the functions called
directly without compilation every time. This will also generate less/no
garbage.

Basically you can play the game and run around but game and server commands
are a little confused at the moment as that side is still using the arg
system, not Lua. It seems that the game avoids using the cmd registration in
favour of "if then else" checking of commands (I.e. Cmd_AddCommand() is not
used). I assume this is to stop the cmd space being polluted with game
commands and/or because they have a different calling mechanism (with ents).

So the problem I have now is how to go about the game/server side. I think
this should probably have its own Lua state to be separated from the
client(s). The cvar system doesn't seem to be separated, they all seem to
use the same cvars (when run on same machine). I assume these values must be
broadcast between the server and clients, and when we have a single player
machine they all just use the same cvar space. So, since I don't fully
understand how this works, this may well break when tested on multiple
machines.

I started off with the Lua stuff in qutil but moved it to qcommon, but it's
not all common. The Lua initialisation (state creation), error handing and
general Lua utilities should probably go (back) in qutil. Any client
specific functionality (e.g. creation of client Lua state and registration
of client  functions) should probably live in the client code (in a CL_
file). I'm a bit confused where this is, as there is a clgame, which seems
to be effects, and the rest seems to be in q2x. So I guess the client Lua
stuff should go in q2x. The server specific stuff will probably get
initialised here too (in a separate state, SV_ file). If I divide the two
states like this, this means the cvars will have to get communicated between
the states (which might happen already).

So, does this sound right:

 * The client side has its own Lua state.
 * Game and server share a Lua state.
 * Necessary cvars are communicated between the two states (using existing
system?)
 * Game/server side contains all the game logic and client side is much
simpler.

Brian: I'm back off to the UK for 3 weeks tomorrow so I very much doubt that
I'll have time to do the server side before I go. I might have a poke around
in the code while I'm done. Let me know if you want a copy of the changes
I've made. I'll say this is code in transition: a lot more work needs to be
done make the whole code base Lua compatible. You might even leave the arg
stuff in as an interface so that other languages could be used (but I think
this could get very messy unless a significant amount of abstraction work is
done). My idea was to get the config, bindings and command line stuff
working with Lua "externally" (which it is) and then go back and convert the
internals to Lua (which is mostly donkey work changing getarg(N) over to
lua_tostring(L, -N)).

Nick





More information about the q2x mailing list