Skip to content

Add custom built in script, command precalls, array and dictionary support#9

Open
ZRavyyy wants to merge 20 commits intolimbonaut:masterfrom
ZRavyyy:master
Open

Add custom built in script, command precalls, array and dictionary support#9
ZRavyyy wants to merge 20 commits intolimbonaut:masterfrom
ZRavyyy:master

Conversation

@ZRavyyy
Copy link

@ZRavyyy ZRavyyy commented Feb 7, 2025

Explanation of added features:

Custom built-in script

It is the link between the game (or any project), and the console itself. It is very convenient to add commands in it, without cluttering the scripts of your game.

Initialized before autoexec script is called, so not only built-in commands can be used in autoexec script.

Example:

extends Node
## Custom builtin script

func _init() -> void:
    Console.unregister_command("eval")

    Console.register_command(cmd_test)
    Console.register_command_precall(_precall, cmd_test)

func _precall(p_func: Callable, p_args: Array):
    if not World.is_in_world:
        Console.error("Console works only in world")
        return FAILED
    else:
        return p_func.callv(p_args)

func cmd_test(text: String, vec2: Vector2, arr: Array, dict: Dictionary) -> void:
	Console.info("text: %s\nvec2: %s\narr: %s\ndict: %s" % [text, vec2, arr, dict])

Command precall

Called before the function call. Can be used for its own checks before calling a function.

Personally, I need this function to check players for rights, let's say access to the command kick, spawn, set_time should get only privileged players, and only if the player is in the world, and to check in each function whether the player has rights clutters the real function with a lot of checks. That's why I consider precall a necessary function, at least in multiplayer.

Array and Dictionary

Well, this needs no explanation. You can now enter arrays, dictionaries, sub-arrays, sub-subarrays, etc. into the console.

Unsafe

Now you can enable unsafe conversion (of arrays, vectors and dictionaries) in the console config file.

Enabling unsafe conversion may increase the speed of console commands, but hits security significantly due to unchecked initialization of vectors, arrays, and dictionaries, which could potentially include auto-initializing script (theoretically).

This may not be very useful in normal cases, but in situations where you need to process a huge array or dictionary, it will significantly speed up the processing of the command

@limbonaut
Copy link
Owner

That's a lot of stuff. Thanks for submitting! I'll need some time to review it.

Copy link
Owner

@limbonaut limbonaut left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for submitting your contribution. There are a few things that need some work before I can give it the green light.

## but it can also improve the speed of the console.
## Enable parameters in this category only if you are not going to use the console online.
@export_category("unsafe")
@export var unsafe_conversion: bool = false
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd rather cut the unsafe flag - it's not necessary. If something doesn't fit into performance expectations, we better optimize it instead.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My idea is that this should be used for huge commands that need to be processed without checking, otherwise checking the whole command could take a long time, but I'm not sure if it's really that useful.

limbo_console.gd Outdated
const THEME_DEFAULT := "res://addons/limbo_console/res/default_theme.tres"
const HISTORY_FILE := "user://limbo_console_history.log"
# Custom builtin script support
const CUSTOM_BUILTIN_SCRIPT := "res://addons/limbo_console.gd"
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Built-in means something is included with the addon as a default feature. But this is a custom init script that users can add themselves. It should be in the options, and the default name shouldn’t be the same as the file we already have. I think we should move this to the options as init_script setting and not set any default value. That way, users can choose their own location if they need this.

limbo_console.gd Outdated


# Custom builtin script support
func _init_custom_builtin_script() -> void:
Copy link
Owner

@limbonaut limbonaut Mar 15, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Something is either custom-made or built-in, not both.

I don’t think this functionality is absolutely necessary - we can use Autoloads to achieve the same thing. This basically gives us a special way to do what autoloads can already do. Perhaps, for autoexecs, is this something you need?

limbo_console.gd Outdated
elif char == '(' or char == '{' or char == '[':
brackets += char
elif char == ')' or char == '}' or char == ']':
if char == ')' and '(' in brackets:
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it would be better to check if the opening bracket ( is the last character in the brackets string. This way, we can catch any issues with bracket ordering much earlier.

limbo_console.gd Outdated
elif char == ')' or char == '}' or char == ']':
if char == ')' and '(' in brackets:
brackets = brackets.erase(brackets.rfind('('))
elif char == '}' and '{' in brackets:
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And same here.

limbo_console.gd Outdated
for arg in method_info.args:
if not arg.type in [TYPE_NIL, TYPE_BOOL, TYPE_INT, TYPE_FLOAT, TYPE_STRING, TYPE_VECTOR2, TYPE_VECTOR2I, TYPE_VECTOR3, TYPE_VECTOR3I, TYPE_VECTOR4, TYPE_VECTOR4I]:
if not arg.type in [TYPE_NIL, TYPE_BOOL, TYPE_INT, TYPE_FLOAT, TYPE_STRING, TYPE_VECTOR2, TYPE_VECTOR2I, TYPE_VECTOR3, TYPE_VECTOR3I, TYPE_VECTOR4, TYPE_VECTOR4I,\
# Dictionary support and Array support
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
# Dictionary support and Array support

limbo_console.gd Outdated
_hist_idx = wrapi(_hist_idx, -1, _history.size())
# Now scrolling stops when reaching the end or beginning of the history
_hist_idx = clampi(_hist_idx, -1, _history.size() - 1)
#_hist_idx = wrapi(_hist_idx, -1, _history.size())
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
#_hist_idx = wrapi(_hist_idx, -1, _history.size())

limbo_console.gd Outdated
var comp: Dictionary
var key = ""
var brackets: String
var token = ""
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
var token = ""
var token: Variant = ""

limbo_console.gd Outdated
if valid:
var err = cmd.callv(command_args)
# Command precalls support
var err
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For clarity:

Suggested change
var err
var err: Variant

limbo_console.gd Outdated

# Dictionary support
func _parse_dictionary_arg(p_text: String):
assert(p_text.begins_with('{') and p_text.ends_with('}'), "Dictionary string presentation must begin and end with curly brackets")
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Asserts are annoying - they interrupt execution and throw you into the code editor. Something I'd like to avoid.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, I saw that you use asserts in vectors, so I figured it was normal for you.

@limbonaut
Copy link
Owner

I find it hard to come back to reviewing this PR because theres just too much mixed into it. I'd prefer changes to be split into atomic PRs, each dealing with one logical change or feature with corresponding README updates. Some things are naturally connected (like array and dictionary support share parsing logic), but this PR also mixes in the init script system, command precalls, and various unrelated tweaks. That's just too much scope for a single PR.

To be transparent about where each stands:

  • Array and dictionary: Most likely to land. I'd welcome a focused PR for just this.
  • Command precalls: I'm not convinced on the approach, and would want to discuss alternatives first.
  • Init script: I’m okay with it in principle (though it needs some adjustments), but it may eventually be replaced by a plugin system.

Thanks for the contribution, and sorry for the late response.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants