Dentro de un juego que estoy desarrollando actualmente, mantengo todos los datos guardados/del juego en un gran objeto JS.
por ejemplo:
const save = { inventory: { equips: { weapon: {...}, chestplate: {...} }, money: 50123 }, gameBooleans: { isThisUnlocked: false, isThatUnlocked: false }, settings: { version: '1.3.4' } } Cada vez que publico una nueva actualización, verifico si save.settings.version es igual a la versión más reciente. Si no es así, actualizo los datos guardados antiguos para incluir los nuevos valores.
Mi problema en este momento es que a medida que desarrollo el juego, agrego nuevos campos a los datos guardados. P.ej. save.gameBooleans.isThisNewThingUnlocked: false .
Anteriormente, lo que he estado haciendo es agregar manualmente cada campo nuevo al objeto cuando el juego detecta un guardado anterior:
const currentVersion = '1.3.3' if (save.settings.version === '1.3.2') { save.gameBooleans.isThisNewThingUnlocked = false save.gameBooleans.isThisOtherNewThingUnlocked = false ...etc save.settings.version = currentVersion }Esto se está volviendo bastante tedioso y, a veces, pierdo un campo que rompe el juego y molesta a mis miles de jugadores jaja. Me preguntaba si había un mejor enfoque.
Intenté usar lodash deepmerge pero si lo uso así: _.mergeDeep(upToDateState, oldSave) , no agrega la nueva clave/campos. Y cuando se usa de otra manera: _.mergeDeep(oldSave, upToDateState) , esto agrega los nuevos valores pero sobrescribe algunos valores existentes.
No quiero escribir mi propia función para manejar esto, pero parece que tengo que hacerlo. ¿Alguien tiene alguna idea?
Puede usar la función Object.keys() para iterar a través de cada clave del nuevo objeto y hacer una copia completa en el objeto save , incluidas las nuevas claves, sin hacerlo manualmente. La función debería ser así.
function deepCopy(old_, new_) { // Iterate through each key of the new object Object.keys(new_).forEach(key => { //If there is a nested object, recall the function if (typeof new_[key] === 'object' && ! Array.isArray(new_[key]) && new_[key] !== null) deepCopy(old_[key], new_[key]) // If there is a non-object value, just copy the value else old_[key] = new_[key]; }); } Tenga en cuenta que esta función haría una copia de referencia de los valores de la matriz (lo que puede no ser deseable). Sin embargo, puede hacer un nuevo condicional para manejar matrices y hacer una copia de valor usando el operador de propagación newArray = ...oldArray .
Creé un nuevo objeto llamado update que tiene 2 claves nuevas en el valor de gameBooleans :
const save = { gameBooleans: { isThisUnlocked: false, isThatUnlocked: false }, settings: { version: '1.3.4' } } const update = { gameBooleans: { isThisUnlocked: true, isThatUnlocked: true, foo: true, bar: true, }, settings: { version: '1.3.4' } } function deepCopy(old_, new_) { Object.keys(new_).forEach(key => { if (typeof new_[key] === 'object' && ! Array.isArray(new_[key]) && new_[key] !== null) deepCopy(old_[key], new_[key]) else old_[key] = new_[key]; }); } deepCopy(save, update) console.log(save)¿Es esto suficiente para lo que estás tratando de lograr?
const currentVersion = '1.3.3' if (save.settings.version === '1.3.2') { save = { ...save, gameBooleans: { ...save.gameBooleans, isThisNewThingUnlocked: false, isThisOtherNewThingUnlocked: false }, settings: { ...save.settings, version: currentVersion } } }De esta manera, mantiene todas las propiedades que tenía en el objeto anterior, agregando otras nuevas o anulando si la propiedad ya existe.