Open AlexLouder opened 3 months ago
Я могу сказать, почему это происходит, все из-за того, что в SDK подается годотовский массив или словарь а не JS массив или Object. Тоже самое у меня было когда подавался не правильный int (годотовский int превращается в какой-то не правильный int в js, который не обрабатывает яндекс). Это можно обойти, примерно как это я делаю тут
func save_data(data: Dictionary, flush: bool = false) -> void:
if not OS.has_feature("yandex"):
return
if not is_player_initialized:
init_player()
await player_initialized
var saves = JavaScriptBridge.create_object("Object")
for i in data.keys():
if data[i] is int:
saves[i] = float(data[i])
else:
saves[i] = data[i]
window.SaveData(saves, flush)
превращая исходный словарь в Object с заменой интов (надо проверять на словари/массивы также как и на инты и преобразовывать их тоже, а лучше, вообще, рекусрсивно заменять все массивы и словари). Справишься, сделай пул реквест, было бы замечательно. Не справишься, проблему локализовали, позже исправлю
Спасибо, забавно, но с интами у меня проблем не было. Я поковырялся и создал 2 вспомогательные рекурсивные функции для массива и словаря и 1 функция, которая превращает обычный словарь в словарь с javascriptobjects. Эти функции работают и если перед сохранением через них прогонять, то сохраняется все как надо, в консоли все ок.
func recursive_array_to_jsarray(array: Array) -> JavaScriptObject:
var jsArray:JavaScriptObject = JavaScript.create_object("Array")
for item in array:
if item is Array:
jsArray.push(recursive_array_to_jsarray(item))
continue
if item is Dictionary:
jsArray.push(recursive_dict_to_jsmap(item))
continue
jsArray.push(item)
return jsArray
func recursive_dict_to_jsmap(dict: Dictionary) -> JavaScriptObject:
var jsMap:JavaScriptObject = JavaScript.create_object('Map')
for key in dict:
if dict[key] is Array:
jsMap.set(key, recursive_array_to_jsarray(dict[key]))
#jsMap[key] = recursive_array_to_jsarray(dict[key])
continue
if dict[key] is Dictionary:
jsMap.set(key, recursive_dict_to_jsmap(dict[key]))
continue
jsMap.set(key, dict[key])
return jsMap
func dict_make_jsobjects(dict: Dictionary) -> Dictionary:
var out_dict = {}
for key in dict:
if dict[key] is Array:
out_dict[key] = recursive_array_to_jsarray(dict[key])
continue
if dict[key] is Dictionary:
out_dict[key] = recursive_dict_to_jsmap(dict[key])
continue
out_dict[key] = dict[key]
print('dict_make_jsobjects', out_dict)
return out_dict
Но столкнулся я с другой проблемой =) Проблема считать в godot сохраненные данные из этих JavaScriptObjects. По логике нужны функции recursive_jsarray_to_array() и recursive_jsmap_to_dict(), но я столкнулся со сложностями:
Error calling method _iter_init on: Array(4)0: "тест1"1: "iasd"2: "wobble"3: (4) [1, 2, 3, 4]length: 4[[Prototype]]: Array(0) error: TypeError: obj[method] is not a function at _godot_js_wrapper_object_call (index.js:9:275121)
Т.е. по сути массив уже виден, но как из него что-то вытащить - не понятно.
С JavaScriptObject можно использовать функции из JS. Надо просто погуглить как в JS понять массив это или словарь. И как в JS получить размер массива и тогда уже цикл по размеру массива сделать. (П.С. проблемы с интами только в 4 годо)
Я обошёл это более костыльным методом, который показался мне более удобным
func save_data(data: Dictionary, flush: bool = false) -> void:
if not OS.has_feature("yandex"):
return
if not is_player_initialized:
init_player()
await player_initialized
var saves = JavaScriptBridge.create_object("Object")
for i in data.keys():
if data[i] is int:
saves[i] = float(data[i])
else:
saves[i] = data[i]
#Добавил ещё ветку if с преобразованием массива в строчку
if data[i] is Array:
saves[i] = JSON.stringify(data[i])
window.SaveData(saves, flush)
После чего использую JSON.parse_string(). Это позволяет обрабатывать
#своя функция в коде, вызываемая с сигналом data_loaded в SDK
func _on_data_loaded(data):
saves = {}
for i in data.keys():
saves[i] = JSON.parse_string(data[i])
В документации яндекса https://yandex.ru/dev/games/doc/ru/sdk/sdk-player В описании метода player.setData приводят пример со списком:
{ achievements: ['trophy1', 'trophy2', 'trophy3'], }
У меня есть списки и словари, которые я хотел бы сохранить.
При сохранении и загрузки из json все в порядке. Но если сохранять в Godot через YandexSDK.save_data(data, true), то в Яндексе в консоли отобразится:
Я посмотрел код синглтона yandex_sdk (gd и js) и не понимаю, почему не работает. Пока приходится костылить, превращая списки в строку при сохранении и сплитить строку в список при загрузке.