Thread: Console commands

  1. #1
    Woof, woof! zacs7's Avatar
    Join Date
    Mar 2007
    Location
    Australia
    Posts
    3,459

    Console commands

    Hi,

    I'm creating a console for my game, I plan on having commands and I was wondering what's the best way to implement them? Such as, converting the text into functions, ie 'exit' quits, 'setres x y' sets the resolution.

    I was thinking of having some sort of table like:

    Code:
    struct consoleCommands_t {
        char * cmd;
        void * func;
        /* should I have some sort of list of the arguments the fn takes? */
    } commands[] = {    {"setres", &consoleSetRes, /* list of args it takes (ie 2 ints) */}};
    
    static void consoleSetRes(int x, int y)
    {
        /* changes the res */
        return;
    }
    And then a function that parses the command and relates it to the table, otherwise command not found. Or is there a cleaner / better way? Also what's the best way to list the args the function will take (and call it accordingly).

    Thanks in advance

  2. #2
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    The table idea is not bad, if all your commands are fairly simple in their syntax.

  3. #3
    Woof, woof! zacs7's Avatar
    Join Date
    Mar 2007
    Location
    Australia
    Posts
    3,459
    hmm k thanks, they will be simple (there's no optional parameters).
    Once I've parsed the command, how should I call consoleSetRes(x, y) with its args?
    ie, the user enteres 'setres 800 600', the parser looks up 'setres' in the table and calls consoleSetRes() but how do I pass 800 and 600 to consoleSetRes() without hardcoding it in? If that makes sense, ie just using a function pointer. Considering most of the functions will have different prototypes.

    Perhaps I could pass an array of structures?, ie:
    Code:
    union argData_t {
        char stringArg[16];
        int intArg;
        float floatArg;
    };
    
    struct arg_t {
        enum dType type          /* type of arg */
        union argData_t data;  /* the data */
    }
    Then the table contains what params it expects and their types? That way each function will have the same prototype, ie.

    Code:
    static void consoleSetRes(struct arg_t * args, int numArgs)
    {
        /* x is args[0].data.intArg */
        /* y is args[1].data.intArg */
        return;
    }
    Or am I over complicating this? cause it certainly feels like it
    Last edited by zacs7; 10-21-2007 at 11:24 PM.

  4. #4
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    Separate command identification from parameter parsing, so
    Code:
    struct consoleCommands_t {
        char * cmd;
        void (*func)(char*);
    } commands[] = {    {"setres", parseConsoleSetRes}    };
    
    static void parseConsoleSetRes( char *args )
    {
        /* extract x, y from the args string */
        consoleSetRes( x, y );
    }
    static void consoleSetRes(int x, int y)
    {
        /* changes the res */
        return;
    }
    > Perhaps I could pass an array of structures?
    Is also another approach, but the central parser is looking complicated.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  5. #5
    Woof, woof! zacs7's Avatar
    Join Date
    Mar 2007
    Location
    Australia
    Posts
    3,459
    Hmm that's a good idea Salem Thanks a lot brewbuck & Salem.

  6. #6
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    I've implemented similar things by using an "argc, argv[]" mechanism to the commands. If you are typing in commands, then you probably want a generic function to split up strings, because most of the time, that's going to be the same for all of the functions.

    In your case, that would be argc=3, argv[0]="setres", argv[1]="800", argv[2]="600".

    You may wan to incorporate a "minumum number of args" [and maximum?] in your list as well. That would allow you one single piece of code that checks that you have the right number of args, so you don't have to replicate that code 50 times over.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  7. #7
    Woof, woof! zacs7's Avatar
    Join Date
    Mar 2007
    Location
    Australia
    Posts
    3,459
    Hmm that seems like a better way to go, thanks matsp. I could always implement that and Salem's idea (but chuck it in one), ie 'x' would be atoi(argv[1]). I'm not sure I'd implement max/min args, probably just 'args' since there aren't really going to be any 'optional' parameters (as one command usually just does one thing).

    Thanks for the suggestions everyone

    Offtopic, I'm still deciding if I want to make my game open-source, since it is largely multiplayer. Would I not see a lot of 'hacks' and cheating if it was open-source? Could someone not recompile it with their own super player and join any old server? It's a shame since I really wanted to use sf.net
    Last edited by zacs7; 10-22-2007 at 03:07 AM.

  8. #8
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Quote Originally Posted by zacs7 View Post
    Hmm that seems like a better way to go, thanks matsp. I could always implement that and Salem's idea (but chuck it in one), ie 'x' would be atoi(argv[1]). I'm not sure I'd implement max/min args, probably just 'args' since there aren't really going to be any 'optional' parameters (as one command usually just does one thing).
    You think so right now. How about you change your "setres" to "setscreenmode" and then want to allow optional "32" or "16" for bits per pixel later on?

    Of course, it's only a small change in the basic framework, nothing to do inside all the different functions, so you can hold fire and implement it later.

    Offtopic, I'm still deciding if I want to make my game open-source, since it is largely multiplayer. Would I not see a lot of 'hacks' and cheating if it was open-source? Could someone not recompile it with their own super player and join any old server? It's a shame since I really wanted to use sf.net
    That's a good question - and one that is sort of familiar: The widespread (claims) of cheating in various of BOINC projects comes to mind.

    The other question is of course, how long will it be before someone figures out how to create a "super player" by hacking the binary? If that's not MUCH harder than compiling your own code, then it's not going to be much of a difference in other ways either.

    It's probably easier/better to implement some safe-guards against "super-players" in the server-side, perhaps?

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  9. #9
    Woof, woof! zacs7's Avatar
    Join Date
    Mar 2007
    Location
    Australia
    Posts
    3,459
    > It's probably easier/better to implement some safe-guards against "super-players" in the server-side, perhaps?

    Yeah I was thinking about that, something like what the Unreal engine does -- to prevent wallhacks player coords are only sent to the players that can see them. So it's really impossible for the client to cheat. I suppose I could always introduce some sort of hashing, and/or a closed source anti-hack tool.

    Anyway, thanks for the suggestions matsp, it is a good idea to implement it now -- even if it serves no real purpose, at least it can.

  10. #10
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    With open-source clients, the only way to really prevent cheating is to have all the logic server-side and give clients only the barest information they need. And even then you can't prevent things like bots. (auto-players)
    The problem is that whatever closed-source module you add, the interface to it is open, and thus it can be worked around.
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

  11. #11
    Registered Abuser
    Join Date
    Jun 2006
    Location
    Toronto
    Posts
    591
    I recently created parsing for a fixed (but extensible) set of commands in my program. I used a trie structure/algorithm and found it very effective as well as worked it out to be the most effecient parsing solution I examined thus far (I think I worked it out as linear time versus logarithmic for simple BST search). If you need generic code to set it up, I can give you some of mine.
    Last edited by @nthony; 10-22-2007 at 06:45 PM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Full Screen Console
    By St0rmTroop3er in forum C++ Programming
    Replies: 1
    Last Post: 09-26-2005, 09:59 PM
  2. Console Functions Help
    By Artist_of_dream in forum C++ Programming
    Replies: 9
    Last Post: 12-04-2004, 03:44 AM
  3. Getting Text from Console commands
    By Unregistered in forum Windows Programming
    Replies: 4
    Last Post: 04-14-2002, 08:14 AM
  4. Just one Question?
    By Irish-Slasher in forum C++ Programming
    Replies: 6
    Last Post: 02-12-2002, 10:19 AM
  5. console commands
    By face_master in forum C++ Programming
    Replies: 0
    Last Post: 09-16-2001, 03:10 AM