Evan's Console Project (Cancelled)

Status
Not open for further replies.

Evanski

Raccoon Lord
Forum Staff
Moderator
This is an on-going project to make a command prompt type system in GMS.

I started with GMWolf's user input video (check it out its awesome and helpful)
It finds what character the user has typed and compares that to an allowed keys list. (more in GMwolfs video)
I then edited it using UTF-8 character codes to replace what the player has typed to that character in a string,
using this we can now allow for more advanced things to be done.
When the user presses inter it saves what they typed in a variable which holds the input string.
As of now it runs a chain of scripts to filter what commands have been typed and matches those words to a ds_grid holding the commands we want, then sets the value of the command to true in a different grid.
Once we have done that we read the grid and check how many are true, if more then one we give an error, if none we give an error, if one we then move on to running the command. We pull the command name from the grid and then add "scr_cmd_" to it, (so we can execute the script through code and so we dont have one worded named scripts).

The command scripts are where it gets fun.
We get the fill string of what the user typed and delete the part where the command name is, depending on the script we look for brackets "[ ]" (as of right now I dont know how to make it look for " with out breaking the strings), we then delete the brackets and save everything after the last ] for later (depending on the script) we are now left with what was inside the brackets being our argument for the command, and with that we configure the script to do what it does with the arguments in mind.

Commands implemented so far
Print: prints text given in [], usage: print [string to print]
Color: Changes the color of the displayed text, useage: color ID, 'Color list' for color options.
Help: Displays info about given command, usage: Help [Command to get help]
Quit: Quits the game.


color.gif
help.gif
print.gif


Code:
//UTF-8 FTW!! <3
special_key = ""; // making an empty var that were going to put our key into
#region //set keys ---------------------------
/*  list:
    (220 = \)
    (219 = [ {)
    (221 = ] })
    (190 = .)
    (191 = / ?)
    (187 = = +)
    (189 = - _)
    (188 = ,)
    (192 = ` ~) if using this as a debug system I should add an if enabled feature to this for bringing the console up or down
    (96  = numpad_0)
    (97  = numpad_1)
    (98  = numpad_2)
    (99  = numpad_3)
    (100 = numpad_4)
    (101 = numpad_5)
    (102 = numpad_6)
    (103 = numpad_7)
    (104 = numpad_8)
    (105 = numpad_9)
    (106 = numpad_*)
    (107 = numpad_+)
    (109 = numpad_-)
    (110 = numpad_.)
    (111 = numpad_/)
    (13  = numpad_enter)
    (33  = pg_up)
    (34  = pg_down)
    (222 = " ')
*/
#endregion

#region //key id list
enum k_id{
    backslash = 220,
    bracksL   = 219,
    bracksR   = 221,
    ddot      = 190,
    foreslash = 191,
    eqplus      = 187,
    minline      = 189,
    comma      = 188,
    tilda     = 192,
    np_0      =  96,
    np_1      =  97,
    np_2      =  98,
    np_3      =  99,
    np_4      = 100,
    np_5      = 101,
    np_6      = 102,
    np_7      = 103,
    np_8      = 104,
    np_9      = 105,
    np_star      = 106,
    np_plus   = 107,
    np_min    = 109,
    np_ddot   = 110,
    np_fslash = 111,
    np_enter  =  13,
    pg_up     =  33,
    pg_down   =  34,
    printhes   =  222,

}
#endregion

#region //If key press do this
switch(pressed_key)
{
    case (k_id.backslash)       : special_key = "\\";       break;
    case (k_id.bracksL)           : special_key = (lc_key);   break;
    case (k_id.bracksR)           : special_key = (lc_key);   break;
    case (k_id.ddot)           : special_key = ".";           break;
    case (k_id.foreslash)       : special_key = (lc_key);   break;
    case (k_id.eqplus)           : special_key = (lc_key);   break;
    case (k_id.minline)           : special_key = (lc_key);   break;
    case (k_id.comma)           : special_key = ",";           break;
  //case (k_id.tilda)           : if enabled                   break;
    case (k_id.np_0)           : special_key = "0";           break;
    case (k_id.np_1)           : special_key = "1";           break;
    case (k_id.np_2)           : special_key = "2";           break;
    case (k_id.np_3)           : special_key = "3";           break;
    case (k_id.np_4)           : special_key = "4";           break;
    case (k_id.np_5)           : special_key = "5";           break;
    case (k_id.np_6)           : special_key = "6";           break;
    case (k_id.np_7)           : special_key = "7";           break;
    case (k_id.np_8)           : special_key = "8";           break;
    case (k_id.np_9)           : special_key = "9";           break;
    case (k_id.np_star)           : special_key = "*";           break;
    case (k_id.np_plus)           : special_key = "+";           break;
    case (k_id.np_min)           : special_key = "-";           break;
    case (k_id.np_ddot)           : special_key = ".";           break;
    case (k_id.np_fslash)       : special_key = "/";           break;
    case (k_id.np_enter)       : special_key = ""; script_execute(global.consolescript);           break;
    case (k_id.pg_up)           :            break;
    case (k_id.pg_down)           :            break;
    case (k_id.printhes)       : special_key = (lc_key);   break;

    default: special_key = "";
}
#endregion

return(special_key)
Code:
//SET UP----------------------------------------------------------------------------------------
#region//GET ARGUMENTS--------------------------------------------------------------------------

    //find our arguments
    #region //if just entered the word print no space
        if ((global.input_string) == "print") ^^ ((global.input_string) == "PRINT") ^^ ((global.input_string) == "Print")
        {
            var error = string("Not enough arguments, usage: print [string to print]");
            //show_message(error)
            global.last_input = global.input_string;
            global.input_string = error;
            with(obj_input)
            {
                //destroy grid
                ds_grid_destroy(cmd_list);
                global.con_input = true;
            }
            var my_arguments = "";
            exit;
        }
    #endregion

    var count = string_length(value);
    var instring = global.input_string;
    instring = string_delete(instring,1,count+1);
    var arguments = instring;
    var my_arguments = string(arguments);


    //find end ]
    print_string_error = 0;
    print_string = my_arguments;
    var startbracket = 1;
    var endbracket = 2;

    end_pos = string_pos("]", my_arguments);
    if (end_pos != 0) //if ] exists
    {
        //delete everything after ]
        print_string = string_delete(my_arguments,(end_pos),( (string_length(my_arguments)) ));
    } else {
        print_string_error += endbracket;
    }

    start_pos = string_pos("[", my_arguments);
    if (start_pos != 0) //if [ exists
    {
        //delete the [
        print_string = string_delete(print_string,1,1);
    } else {
        print_string_error += startbracket;
    }
#endregion
#region//SCRIPT MAIN----------------------------------------------------------------------------
var script_error = false;

//Get my arguments if there are not print the error saying so
if (my_arguments == ("")) ^^ (print_string_error == 3)
{
    var error = string("Not enough arguments, usage: print [string to print]");
    //show_message(error)
    global.last_input = global.input_string;
    global.input_string = error;
    script_error = true;
}

//start backet error check
if (print_string_error == 1) && (my_arguments != (""))
{
    var error = string("No starting bracket '[', usage: print [string to print]");
    //show_message(error)
    global.last_input = global.input_string;
    global.input_string = error;
    script_error = true;
}

//end backet error check
if (print_string_error == 2) && (my_arguments != (""))
{
    var error = string("No ending bracket ']', usage: print [string to print]");
    //show_message(error)
    global.last_input = global.input_string;
    global.input_string = error;
    script_error = true;
}

if (script_error = false)
{
    //other wise print the string
    //show_message(print_string);
    global.input_string = print_string;
}
#endregion
#region//CLEAN UP-------------------------------------------------------------------------------
    with(obj_input)
    {
        //destroy grid
        ds_grid_destroy(cmd_list);
        global.con_input = true;
    }
    global.arguments_string = "";
#endregion
//FINISH----------------------------------------------------------------------------------------
exit;

I dont plan on releasing this as of right now because theres not really any fun thing to do with it.
However I have made it so you can just write your own command keyword and script for it
that being said there is a buggy earlier version I posted HERE that you can toy with if you wish.

TO DO

  • Change all the chained scripts to be a single script
  • implement more command ideas
  • able to write and run custom system files like how .bat files work
  • make ascii game from above todo
  • tidy up the code and dust some debug cobwebs
If anyone has and Ideas, questions, code improvements, grammatical/speiling mistakes PLEASE comment them down below, thanks.
 
Last edited:
J

jashe369

Guest
I actually am working on a old school computer console game... Well it is a game that pretends to be an old school console.

For text input I used keyboard_string

It works great because it accepts backspace build in and you can do all the special keys blah blah blah...

here is an example of how I do what I want to do for the text input .

I do this all in one object here is what the draw code looks like
In this code I have it set to a flashing cursor at the end.
I also use globals because of scripts that need to update lines and they will be used an other ways too.

DRAW EVENT:
Code:
//Current active line
if global.cursor = 0
{
    // The global.promptlocal is the command prompt text IE C:\>
    draw_text_color(global.currenttxtX,global.currenttxtY,(global.promptlocal + keyboard_string + "_"),c_lime,c_lime,c_lime,c_lime,1)
    if global.countt11 < 11
    {
        global.countt11 += 1
    }
    else
    {
        global.countt11 = 0
        global.cursor =  1
    }
}
else
{
    draw_text_color(global.currenttxtX,global.currenttxtY,(global.promptlocal + keyboard_string),c_lime,c_lime,c_lime,c_lime,1)
        if global.countt11 < 11
    {
        global.countt11 += 1
    }
    else
    {
        global.countt11 = 0
        global.cursor =  0
    }
}
That is it ... No need for anything special unless you want to keep it to a certain amount of char say 80 like I do for my program. then you do something like this in the step event.
Code:
// Makes sure you can only input keyboard strings of 80 char long.
if string_length(keyboard_string) > 80
{
    keyboard_string = string_copy(keyboard_string, 1, 80);
}
Here is an example of the console. I used the command load s to load the s drive and then does stuff.
examplescreenshot.png


To get commands to work I use scripts for each command personal preference. I use a enter button release to do scripts with a case statement that gets a parsed version of the keyboard_string.

again keyboard_string live updates in the game and can store up to 1000 characters I think and when you hit backspace it removes the last key hit. The cool part is it when you hit \ it is already in the string correctly it doesn't need any special code to be stored right. It also is much faster since you don't need a whole large code block on every step to do this . I have been using this for a few weeks now and haven't found any downsides. You can also dump strings into keyboard_string, but that is temperamental at best.
 

Evanski

Raccoon Lord
Forum Staff
Moderator
I actually am working on a old school computer console game... Well it is a game that pretends to be an old school console.

For text input I used keyboard_string

It works great because it accepts backspace build in and you can do all the special keys blah blah blah...

here is an example of how I do what I want to do for the text input .

I do this all in one object here is what the draw code looks like
In this code I have it set to a flashing cursor at the end.
I also use globals because of scripts that need to update lines and they will be used an other ways too.

DRAW EVENT:
Code:
//Current active line
if global.cursor = 0
{
    // The global.promptlocal is the command prompt text IE C:\>
    draw_text_color(global.currenttxtX,global.currenttxtY,(global.promptlocal + keyboard_string + "_"),c_lime,c_lime,c_lime,c_lime,1)
    if global.countt11 < 11
    {
        global.countt11 += 1
    }
    else
    {
        global.countt11 = 0
        global.cursor =  1
    }
}
else
{
    draw_text_color(global.currenttxtX,global.currenttxtY,(global.promptlocal + keyboard_string),c_lime,c_lime,c_lime,c_lime,1)
        if global.countt11 < 11
    {
        global.countt11 += 1
    }
    else
    {
        global.countt11 = 0
        global.cursor =  0
    }
}
That is it ... No need for anything special unless you want to keep it to a certain amount of char say 80 like I do for my program. then you do something like this in the step event.
Code:
// Makes sure you can only input keyboard strings of 80 char long.
if string_length(keyboard_string) > 80
{
    keyboard_string = string_copy(keyboard_string, 1, 80);
}
Here is an example of the console. I used the command load s to load the s drive and then does stuff.
View attachment 26235


To get commands to work I use scripts for each command personal preference. I use a enter button release to do scripts with a case statement that gets a parsed version of the keyboard_string.

again keyboard_string live updates in the game and can store up to 1000 characters I think and when you hit backspace it removes the last key hit. The cool part is it when you hit \ it is already in the string correctly it doesn't need any special code to be stored right. It also is much faster since you don't need a whole large code block on every step to do this . I have been using this for a few weeks now and haven't found any downsides. You can also dump strings into keyboard_string, but that is temperamental at best.
My system is set up so if i want to disable/enable or add certain keys, I can
Using UTF-8 I can have a key for any keyboard of any type in any part of the world
I dont need to worry about special charecters such as " \ /n # Thats all handled for me
Check out a video on Tom Scotts emoji keyboard
technically my system could use those keys but thats up to if game maker can read them and only yoyo can manage that part

My major goal with this is to make it almost future proof, while also being mod/adjustable
 
Last edited:

Evanski

Raccoon Lord
Forum Staff
Moderator
technically my system could use those keys but thats up to if game maker can read them and only yoyo can manage that part
This statement is false, emojis use UT-1F where im using basic UTF-8, technically i could add on to my key list to accept emoji but I see no reason to

emojis use full Unicode code, so
U+1F600 is the grin face

I use UTF-8, so
A is 65
b is 66

so its well yes but actually no
 
Last edited:
J

jashe369

Guest
My major goal with this is to make it almost future proof
because keyboard_string a build in value that is required by game maker and takes less resources is not future proof ...

also being mod/adjustable
Technicality that is true, but your system costs loads of resources to do that and what is the beneficent ? from what I can see even with your system it is still going to be region locked to English characters, as for customization that is great, but it looks like you still need to have error reporting for bad or incorrect input. These are the two main reasons I would see having it customized would be great. The only other reason would be to lock it down to the point of using very simple input IE WASD in that case it would be easier to implement a switch to that logic mechanic.

Just because it can be modded or customized doesn't mean it is a better implementation. For your use it doesn't seem to be a better system at all.

so lastly

My system is set up so if i want to disable/enable or add certain keys, I can
Using UTF-8 I can have a key for any keyboard of any type in any part of the world
Well keyboard_string simply gets input from a keyboard. That is all and I mean that literally. you type it, it gets it! So the region issue comes down to a implementation of your code to accept other languages.
So either way you would need to code it so that your system can understand other language and spits stuff out in said other language.
take a look here https://docs.yoyogames.com/source/dadiospice/002_reference/mouse, keyboard and other controls/keyboard input/keyboard_string.html

I was simply trying to show you there is an easier way. I am sorry that you seemed to take it as personal attack to your code, and felt a need to defend what you were doing.

Sadly I think your system just takes up more resources and doesn't provide any benefits over the default system. As parsing and error checking on code that runs each command you have is going to be far more efficient and far less complicated. also i am kind of wondering why you need to use a ds_grid for your code.
Code:
ds_grid_destroy(cmd_list);
Either way I wish you the best of luck sorry I tried to offer you a more efficient system, that end up upsetting you.

Again best of luck man.
 

Evanski

Raccoon Lord
Forum Staff
Moderator
I am sorry that you seemed to take it as personal attack to your code, and felt a need to defend what you were doing.
I didnt, if it came off that way I didnt mean to my apologies, I was simply stating how/ why I choose the code I did

Well keyboard_string simply gets input from a keyboard. That is all and I mean that literally. you type it, it gets it!
Yes, thats why im using UTF-8 codes, UTF-8 is international for key presses, so if a russian person typed a russian charecter it would type that charecter (as far as I know, any errors would be in my implementation but every charecter no matter what language has typed fine), also my project uses commands, its mostly technical, think of my project like Dos running on a computer, you type apple its going to yell at you, if you type color 0a, i will change the screen to green, as far as i know there is no coding language that is in a different language other then English, and my commands are single common function words, like "If" "false" "true", leading from that

also i am kind of wondering why you need to use a ds_grid for your code.
this is to hold my custom commands, so I can pull them from text, my "command prompt" is a vary basic code interpreter if you look at it that way, it compares the string you typed to the grid to check syntax's

again I didnt mean to sound like I was being attacked and started fighting back, I appreciate your input and helpful suggestions, and good luck on your project also.
 
J

jashe369

Guest
I am glad to hear that, I was worried I upset you when all I was trying to do was explain that keyboard_string is more efficient.

Also I mean program for another language not program in another language. Sorry for not clarifying.

like color is that in English but in Russian that is цвет (tsvet)

sorry was telling you that the commands themselves would need to be set to accept another language and on screen text would need to be written in said other language... not the code itself. I hope the extra clarification helps

I am currently working on a very similar project.

My project will be an,"Emulated" old computer. It really is just a pretend computer system that the player will poke through and get at files to uncover a mystery. Think Hacknet but with video/audio/image/text files. Then there will be a gui too. So the user starts on one system and connects to other systems. each system will have their own OS some will be similar others will not.

The , "Emulated" OS systems will be copycats of DOS, UNIX(Linux), Windows, Workbench, C64 prompt, etc... I even want to touch on BeOS and maybe even Arc firstclass client and System 7.

The start of all that is an, "Emulator" program that will have some setting such as screen color and text color and ram amount and an already included drive and floppy image file. To add a suspension of disbelief I will be using, IPv5 to connect to address on the pretend internet.

I have even written a Basic interpreter and text editor in my console game so far. You can even add and remove files and folders. The files are handled with a database package I got from the marketplace and it works well.

I certainly hope your game turns out just as exciting as I am hoping mine will.
 

Evanski

Raccoon Lord
Forum Staff
Moderator
I've almost implemented a SET command
the command will let you set and unset values to variables and save them to a text file

usage Set [Variable] [Value] optional( OPERATOR [Value2])

so if we type SET [score] [6] + [5]
it will set Score to be 11
you can also type

SET [score] [Unset]
and it will unset the variable (like as if it was deleted)

Im waiting on GMLs 2019 update that changes scripts
as this whole project relies heavily on scripts

When I get the basic commands implemented so its not just "do it your self typing"
I'll release a demo
im excited to see what people manage to do with this
 

Evanski

Raccoon Lord
Forum Staff
Moderator
This looks like a fantastic project. I think all games should have a command console or something like that. I look forward to seeing your progress.
It is able to be ripped out of a project and thrown into another, basically you import the main script and then write your command scripts that fit your debugging/cheat wants for your game
 
Status
Not open for further replies.
Top