Export a folder for the user to modify data

Godot Version

4.2.2

Question

Hi! I want to support a datapack-like system where users can add content to the game. I created this example where files in the strings folder will be parsed for text and then labels will be created. However, I have no idea how to export it in such a way that retains this functionality. Currently, I’m only able to export an .exe which simply contains the last labels before I exported it.

Root node “Game”

extends Node2D

func _ready():
	const PATH_TO_JSON = "res://strings/"

	var dir = DirAccess.open(PATH_TO_JSON)
	var strings = []

	if dir:
		var json_files = dir.get_files()
		for file in json_files:
			if file.ends_with(".json"):
				var contents = FileAccess.open(PATH_TO_JSON + file, FileAccess.READ)

				var json = JSON.new()
				var json_string = contents.get_as_text()

				var error = json.parse(json_string)
				if error == OK:
					var data_received = json.data
					strings.push_back(data_received.text)
				else:
					print("JSON Parse Error: ", json.get_error_message(), " in ", json_string, " at line ", json.get_error_line())
	else:
		print("Error: Could not open " + PATH_TO_JSON)
	create_labels(strings)


func create_labels(labels):
	var vertical_spacing = 20
	var start_position = Vector2(10, 10)
	
	for i in range(len(labels)):
		var label = Label.new()
		label.text = labels[i]
		label.position = start_position + Vector2(0, i * vertical_spacing)
		
		add_child(label)

“res://” maps the to packed file in exports, “user://” maps to a folder in app data

To make things simple for modifyable json you could get the folder the game executable is in (only works on exports) and scan files near the install game point

if OS.has_feature("standalone"): # not editor
    var folder := OS.get_executable_path().get_base_dir()
    # from folder you could ask for or create a mods folder
    var mods := folder.path_join("mods") # use path_join instead of +
    if DirAccess.dir_exists_absolute(mods):
        var dir := DirAccess.open(mods)
        dir.list_dir_begin() # etc ...

How would I debug this in development? Would I simply use the “res://” path in development and “user://” in production? Would I use OS.is_debug_build() to implement this? Please let me know if this is common practice.

For the “user://” path you don’t need to change anything for debug/release, it always maps to the same spot. For exporting to the executable folder you will have to test in an exported build, and ignore the option in editor, that’s what OS.has_feature("standalone") is for