Salta ai contenuti

Passare da un altro telefono

Una città che ha già un telefono racchiude anni di storia al suo interno: numeri imparati a memoria, conversazioni, foto, @handle. Perdere tutto questo è il vero prezzo del cambiare telefono, ed è il motivo per cui la maggior parte dei server non lo fa mai. Questo strumento legge le tabelle del vecchio telefono e scrive nelle nostre.

È possibile migrare da quattro telefoni, e tutti e quattro vengono testati allo stesso modo: le loro tabelle vengono create dallo schema fornito dal loro installer, ci viene scritta dentro una piccola città, l’importazione viene eseguita per davvero e ogni singola riga dichiarata viene verificata subito dopo.

DaLe sue tabelleSu cosa indicizza tutto
lb-phonephone_*il numero di telefono, con phone_phones che lo associa a un proprietario
Quasar Smartphone Proqs_phone_*uno scope_id — un telefono, non una persona
NPWDnpwd_*l’identificatore del framework, e i suoi numeri sono già in users
qb-phoneplayer_contacts, phone_messages…citizenid, che è il proprietario del telefono su QBCore

Non tocca mai il vecchio telefono. Nemmeno un’istruzione scrive in una tabella che non sia la nostra. I dati di lb-phone restano esattamente com’erano prima, il che rende semplicissimo tornare indietro: basta eliminare le nostre righe.

La prova generale è reale. DryRun è attivo per impostazione predefinita. Legge tutto ciò che leggerebbe un’esecuzione reale, calcola ogni riga che scriverebbe, non ne scrive nessuna e stampa il conteggio. È lo stesso identico codice: una prova che prendesse scorciatoie non proverebbe proprio nulla.

Non può succedere due volte. Un’esecuzione reale lascia una ricevuta nel database. Al riavvio successivo il sistema la trova e si ferma, perché altrimenti una riga di configurazione dimenticata duplicherebbe ogni conversazione della città.

-- shared/config/import.lua
Config.Import = {
From = 'lb-phone', -- or false, which is where it starts
DryRun = true, -- read the count first
Numbers = 'keep', -- their old numbers move across
Crypto = 'cash', -- sell their coins at their own price
}

Riavvia una volta e leggi la console:

[mic_phone import] lb-phone — REHEARSAL, nothing was written
[mic_phone import] contacts 482
[mic_phone import] messages 19104
[mic_phone import] numbers 137
[mic_phone import] photos 2210
[mic_phone import] social 96
[mic_phone import] · a phone whose owner is not in `users` any more was skipped (×8)
[mic_phone import] · lb-phone does not say whether an alarm repeats, so its alarms arrive as one-off alarms

Poi imposta DryRun = false, riavvia ancora una volta e infine rimetti From = false.

Se le tabelle non sono presenti nel database, lo segnala e non fa nulla; quindi scrivere il nome del telefono sbagliato ti costa solo una riga in console.

Tutto ciò che segue riguarda lb-phone, che è il più completo dei quattro. Le differenze con gli altri tre sono spiegate più avanti.

Da lb-phoneDiventa
phone_phonesil numero in users, la batteria, le impostazioni del telefono
il suo settings.appsla schermata Home: lo stesso dock, le stesse app sulle stesse pagine
phone_phone_contactsi contatti, inclusi preferiti e immagini
phone_message_*le conversazioni, i gruppi e i contatori dei messaggi non letti
phone_phone_callsle chiamate recenti, una riga per parte, incluse le chiamate perse
phone_photosla libreria, foto e video
phone_mail_*le email, lette e non lette
phone_maps_locationsi luoghi salvati
phone_marketplace_posts, phone_yellow_pages_postsgli annunci
Instagram, Twitter, TikTok, TinderInstapic, Twixel, Klipz, Flinder — handle, nomi, foto, bio, post, follower e la spunta di verifica
phone_darkchat_*la darknet: la stanza, chi c’era dentro, cosa è stato detto
phone_notes, phone_clock_alarmsnote e sveglie — le sveglie di lb-phone non specificano se si ripetono, quindi arrivano come sveglie singole
phone_cryptovedi Criptovalute più sotto

Le immagini sono URL su entrambi i telefoni, quindi nulla viene scaricato o ricaricato. Le foto di un giocatore continuano a funzionare fin dal primo giorno perché non sono mai appartenute davvero a nessuno dei due telefoni.

Il resoconto dichiara esplicitamente ciascuno di questi punti, invece di lasciare che qualcuno se ne accorga da solo.

  • Sfondi e suonerie. I loro fanno riferimento ai loro file, i nostri ai nostri. Un’immagine rotta è peggio di quella predefinita.
  • Password dei social. Vedi sotto: gli account passano, le password non possono farlo.
  • Modalità aereo, di proposito. Importare un interruttore che qualcuno aveva lasciato acceso significa importare un telefono che non funziona per un giocatore che non capisce il perché.
  • Album fotografici. Ogni immagine si trova nella libreria, ma gli album non vengono ricostruiti.

Il meglio strutturato dei quattro, e la corrispondenza è esatta anziché approssimativa in tre punti:

  • I messaggi non letti vengono ricontati, non copiati. Quasar salva last_read_message_id; il nostro salva un numero. Quindi il numero viene ricalcolato — quanti messaggi in quella conversazione sono arrivati dopo l’ultimo letto — il che risulta corretto anche se il loro contatore si era disallineato.
  • Le chiamate recenti usano già incoming, outgoing e missed, che sono esattamente le nostre tre parole.
  • Una foto sa di essere un video, con la sua durata e la sua copertina, quindi arriva come video.

Passano anche note (quelle fissate restano fissate), sveglie, eventi del calendario e promemoria: un promemoria aperto con una scadenza diventa un evento a calendario, uno senza data mantiene il testo come nota e uno completato viene tralasciato. Quasar permette di ripetere una sveglia solo nei fine settimana, cosa che questo telefono non prevede, quindi quelle arrivano come sveglie singole.

Le conversazioni fissate e silenziate mantengono entrambi gli stati. Le email arrivano con la cartella in cui si trovavano — bozze e cestino vengono lasciati indietro, perché una bozza mai inviata non merita il trasloco. Cosa non passa: le impostazioni e la schermata Home, che vivono in un blocco JSON con la struttura proprietaria di Quasar, e i loro ID dell’App Store, che non corrispondono ai nostri.

Una cosa da sapere: Quasar permette a un personaggio di possedere più di un telefono, mentre questo mantiene un numero per personaggio. Il primo numero trovato diventa il suo; gli eventuali altri vengono segnalati nel resoconto e nulla viene sovrascritto.

Il più semplice, per una ragione che vale la pena dire chiaramente: NPWD salva già il numero in users.phone_number, che è la stessa identica colonna letta da questo telefono. Su un server NPWD standard non c’è alcun numero da spostare, e il resoconto lo dice chiaramente invece di fingere di aver lavorato.

Le sue conversazioni sono identificate da una stringa contenente i numeri dei partecipanti anziché da un ID, quindi l’associazione avviene su quella stringa. Il nome del profilo Twitter diventa l’@handle; Match non ha alcun nome utente, quindi l’account Flinder viene associato al numero del personaggio. Le foto non hanno una data propria, perciò la libreria viene datata secondo l’ordine di scatto. Le note passano allo stesso modo, datate secondo l’ordine di scrittura. Gli annunci non hanno prezzo e arrivano gratuiti.

Il più vecchio e il meno simile al nostro — ma l’identità è immediata, perché su QBCore questo telefono usa già il citizenid con cui qb-phone indicizza ogni cosa.

Il vero lavoro sono le conversazioni. qb-phone non ha il concetto di conversazione: phone_messages contiene una riga per persona e per numero con l’intero scambio salvato come array JSON, scritto separatamente da ciascun lato. Di conseguenza la stessa conversazione esiste due volte e le due copie non sempre coincidono. Ogni coppia di numeri viene quindi ricostruita una sola volta, prendendo il lato che contiene più messaggi: fonderli inventerebbe un ordine arbitrario, mentre importarli entrambi darebbe a tutti ogni messaggio doppio. Una conversazione priva di timestamp mantiene il proprio ordine e i messaggi vengono distanziati di un minuto l’uno dall’altro.

I numeri risiedono in players.charinfo in formato JSON anziché in una colonna dedicata, quindi vengono letti da lì e scritti dove li conserva questo telefono. I suoi tweet riportano un nome invece di un account, perciò viene creato un account Twixel per personaggio a partire dal suo nome.

Numbers = 'keep' è il senso dell’intera operazione: il numero stampato sul biglietto da visita di qualcuno, e salvato nella rubrica di tutti gli altri, continua a farlo squillare.

Un numero viene scritto esclusivamente in una colonna vuota. Se un personaggio ne ha già uno qui ed è diverso, si tratta di un conflitto: viene contato, elencato nel resoconto e nulla viene sovrascritto. I vecchi numeri mantengono anche il loro vecchio formato — 1234567890 invece di 555-###-#### — un dettaglio puramente estetico che riguarda solo i nuovi numeri assegnati da quel momento in poi.

Numbers = 'ours' li ignora e lascia che questo telefono assegni i propri. I vecchi contatti in rubrica non punteranno più a nessuno, quindi ha senso solo per una città che riparte da zero.

Le loro password sono salvate in chiaro in una colonna. Le nostre sono hash PBKDF2 calcolati nel browser del giocatore, ed è impossibile ricavare l’uno dall’altra — quindi la password è l’unica cosa che non passa, e non viene salvata da nessuna parte durante il tragitto.

L’account arriva contrassegnato come importato. La prima volta che il proprietario apre l’app, il telefono dice Questo account proviene dal tuo vecchio telefono. Scegli una password, e quella diventa la nuova password.

Questo meccanismo è sicuro per un motivo migliore di qualsiasi password: la riga nel database indica già il proprietario, e il server sa chi sta facendo la richiesta senza che glielo si debba dire. Non c’è nulla da dimostrare tramite una password che non è mai stata nostra.

Non esiste un tasso di cambio onesto tra due mercati inventati, quindi scegli tu cosa fare invece di lasciarlo tirare a indovinare:

  • 'cash' — vende le monete al prezzo del vecchio telefono e accredita l’importo nel portafoglio come movimento. Nessuno ci guadagna, nessuno ci perde e non c’è nulla su cui mettersi d’accordo.
  • 'skip' — tralascia. I saldi restano nelle vecchie tabelle e possono essere gestiti manualmente.
  • una tabella — la tua mappatura personalizzata, se vuoi che i saldi sopravvivano sotto forma di monete:
Crypto = { qbit = 'santo', lifeinvader = 'vine' },

Nulla del vecchio telefono è stato toccato, quindi:

  1. Elimina le nostre righe relative al passaggio che non è andato come volevi (il resoconto ne indica i nomi).
  2. Elimina la ricevuta: DELETE FROM mic_phone_json WHERE owner = '@import'.
  3. Imposta Config.Import.Again = true e riprova.

Skip permette di escludere singoli passaggi usando i nomi stampati nel resoconto:

Skip = { 'photos', 'crypto' },