Store information on individual instances

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By Dr. Numerus

So basically i want to create a lot of instances for certain object (lets just say chests).
Now i want to be able to put stuff into these individual chests, which is my first problem. How do i send a signal to a very specific chest among all other “copies” (instances)?

Furthermore, i want to read what items / how many are in the chest. That’s basically the same problem as above, i need to read different information from different chests.

Finally, what is a good way to store this information? Is it appropriate in this case to just use an array or something similar in one general script? Or is it better to store the information in each individual chest somehow?

Thanks a lot!

You could define some global singleton (see docs for globals example) which also contains a dictionary. Each chest instance probably has a unique node name. Use that name to put an entry in that dictionary which contains another dictionary with the chests contents. When chests want to know what is in them then they just look it up in the global dictionary with their node name.

var chest_contents = { 
     "chest1" : {"iron":10,"sword":{"material":steel,"value":10},"gems":10},
     "chest2" : {"gems":2,"jack":1}
    }

Such dictionaries can be saved in text files. Serialized to the JSON format. On the next run you just read the text file again and parse the JSON contents into the dictionary. (As is often done with other game settings)

wombatstampede | 2019-04-22 15:35

Ok, thank you, this was indeed very helpful. But why do i need to transform this dictionary to a text file in the first place? I often read that it is not recommended to save information in the script itself, but why? Can’t i just make a long 2d-array with all chest items or something?

Dr. Numerus | 2019-04-23 13:17

Sure, you can put a declaration of a dictionary or array in the code. If it is very big then it may be a bit tedious to edit.

But that is static. It’ll be the same every time you start the game. So if you want to change the contents of the chests and restore those contents the next game the game is run then you need to save that dictionary to a file.

Storing/Loading a dictionary is quite simple. The following code is written from memory. So it may contain errors.

const CHESTS_SAVE_FILE = "user://chests.txt"

var default_chests = {"chest1": {"iron":1}, "chest2": {"gold":1}}
var chest = null

func load_chests():
	var file = File.new()
	chests = null
	if file.file_exists(CHESTS_SAVE_FILE):
		var err = file.open(CHESTS_SAVE_FILE, file.READ)
		if err==OK:
			data = file.get_as_text()
			file.close()
			chests = parse_json(data)
		else:
			print("Error opening "+CHESTS_SAVE_FILE+" for read: "+str(err))
	if chests == null: #init chests with default values
		chests=default_chests.duplicate()

func save_chests():
	var file = File.new()
	var err = file.open(CHESTS_SAVE_FILE, file.WRITE)
	if err==OK:
		file.store_string(to_json(chests))
		file.close()
	else:
		print("Error opening "+CHESTS_SAVE_FILE+" for write: "+str(err))

wombatstampede | 2019-04-23 14:03

Great! Thank you so much!

Dr. Numerus | 2019-04-23 19:11

:bust_in_silhouette: Reply From: Dr. Numerus

So, thanks to the help of @wombatstampede i found the answer:

The solution was a dictionary, which can be accessed by a script of every individual chest, via a singleton. Each chest then just needs to check this global singleton dictionary. The distinction happens through the names or “IDs” from each chest, which is different every time a chest-scene is being instanced. This can be done just by calling the global method from a chest with the keyword “self”:

Global.checkDictionary(self)

Then, the chest “knows” the items, which belongs in itself. Adding or removing items is just the manipulation of that dictionary.

Problem solved!