Skip to content

Commit

Permalink
fix: implement varargs for ESC commands. 'custom' makes use of this #592
Browse files Browse the repository at this point in the history
  • Loading branch information
BHSDuncan authored May 2, 2022
1 parent ba5be04 commit 738ce0d
Show file tree
Hide file tree
Showing 5 changed files with 53 additions and 27 deletions.
13 changes: 8 additions & 5 deletions addons/escoria-core/game/core-scripts/esc/commands/custom.gd
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
# `custom object node func_name [params]`
# `custom object node func_name [params...]`
#
#
# Executes the specified Godot function. This function must be in a script
# attached to a child node of a registered `ESCitem`.
# attached to a child node of a registered `ESCItem`.
#
# **Parameters**
#
# - *object*: Global ID of the target `ESCItem`
# - *node*: Name of the child node of the target `ESCItem`
# - *func_name*: Name of the function to be called
# - params: Any arguments to be passed to the function (array and object parameters are not supported). Multiple
# parameters can be passed by using comma-separated values inside a string
# - params: Any arguments to be passed to the function (array and object parameters are not supported).
# Multiple parameters can be passed by simply passing them in as additional arguments separated by
# spaces, e.g. `custom the_object the_node the_function arg1 arg2 arg3`
#
# @ESC
extends ESCBaseCommand
Expand All @@ -22,7 +23,9 @@ func configure() -> ESCCommandArgumentDescriptor:
return ESCCommandArgumentDescriptor.new(
3,
[TYPE_STRING, TYPE_STRING, TYPE_STRING, TYPE_ARRAY],
[null, null, null, []]
[null, null, null, []],
[true],
true
)


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,14 +42,14 @@ func _init(command_string):
).strip_edges()
)
for parameter in parsed_parameters.split(" "):
if parameter.begins_with('"') and parameter.ends_with('"'):
if len(parameter) > 1 and parameter.begins_with('"') and parameter.ends_with('"'):
parameters.append(
parameter
)
elif ":" in parameter and '"' in parameter:
quote_open = true
parameter_values.append(parameter)
elif parameter.begins_with('"'):
elif not quote_open and parameter.begins_with('"'):
quote_open = true
parameter_values.append(parameter)
elif parameter.ends_with('"'):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,47 +30,63 @@ var defaults: Array = []
# Whether to strip quotes on specific arguments
var strip_quotes: Array = []

# Whether the final argument is a series of varargs
var has_varargs: bool = false


# Initialize the descriptor
func _init(
p_min_args: int = 0,
p_types: Array = [],
p_defaults: Array = [],
p_strip_quotes: Array = [true]
p_strip_quotes: Array = [true],
p_has_varargs: bool = false
):
max_args = p_types.size()
min_args = p_min_args
types = p_types
defaults = p_defaults
strip_quotes = p_strip_quotes
has_varargs = p_has_varargs


# Combine the default argument values with the given arguments
func prepare_arguments(arguments: Array) -> Array:
var complete_arguments = defaults
var varargs = []

for index in range(arguments.size()):
# If we have too many arguments passed in, complete_arguments won't
# be able to match 1:1. This condition will be validated later but so
# to avoid duplicating validation code, just grow complete_arguments
# since the arguments won't be used anyway.
if index >= complete_arguments.size():
complete_arguments.append(arguments[index])
continue

complete_arguments[index] = escoria.utils.get_typed_value(
arguments[index],
types[index]
)
var strip = strip_quotes[0]
if strip_quotes.size() == complete_arguments.size():
strip = strip_quotes[index]

if strip and typeof(complete_arguments[index]) == TYPE_STRING:
complete_arguments[index] = complete_arguments[index].replace(
'"',
''
if has_varargs:
varargs.append(arguments[index])
else:
complete_arguments.append(arguments[index])
elif index == complete_arguments.size() - 1 and has_varargs:
# Varargs are a special case and need to be gathered and added at
# the end as an array, untyped and unchecked. They should also only
# appear at the very end of a command's argument list.
varargs.append(arguments[index])
else:
complete_arguments[index] = escoria.utils.get_typed_value(
arguments[index],
types[index]
)
var strip = strip_quotes[0]
if strip_quotes.size() == complete_arguments.size():
strip = strip_quotes[index]

if strip and typeof(complete_arguments[index]) == TYPE_STRING:
complete_arguments[index] = complete_arguments[index].replace(
'"',
''
)

if has_varargs:
complete_arguments[complete_arguments.size() - 1] = varargs

return complete_arguments

Expand All @@ -91,7 +107,7 @@ func validate(command: String, arguments: Array) -> bool:
]
)

if arguments.size() > self.max_args:
if arguments.size() > self.max_args and not has_varargs:
escoria.logger.report_errors(
"ESCCommandArgumentDescriptor:validate()",
[
Expand All @@ -104,6 +120,11 @@ func validate(command: String, arguments: Array) -> bool:
if arguments[index] == null:
# No type checking for null values
continue

if has_varargs and index == arguments.size() - 1:
# If we have varargs at the end, do not validate them.
continue

var correct = false
var types_index = index
if types_index > types.size():
Expand Down
3 changes: 2 additions & 1 deletion addons/escoria-core/game/main.gd
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,8 @@ func set_scene(p_scene: Node) -> void:
#
# - p_scene: The scene currently being initialized by set_scene.
func finish_current_scene_init(p_scene: Node) -> void:
move_child(p_scene, 0)
if is_a_parent_of(p_scene):
move_child(p_scene, 0)

current_scene = p_scene

Expand Down
5 changes: 3 additions & 2 deletions game/rooms/room03/esc/room03_bridge.esc
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@


:setup
custom r3_r_exit door_enabler enable_door a b c 1 2 345

# If the room hasn't been visited previously, open the bridge and break the button
> [!room3_visited]
Expand All @@ -21,7 +22,7 @@
# We use a custom function to enable the collision polygon on the door
# to enable it to work as a door once the bridge is closed.
# You'll find the script in room3/Hotspots/r_door/door_enabler
custom r3_r_exit door_enabler enable_door
custom r3_r_exit door_enabler enable_door

> [eq ESC_LAST_SCENE room2]
teleport player r3_l_exit
Expand Down Expand Up @@ -67,4 +68,4 @@
# This is for when you close the bridge then go back to room 2
# Set the bridge closed

set_global r3_bridge_closed true
set_global r3_bridge_closed true

0 comments on commit 738ce0d

Please sign in to comment.