View Full Version: Continuità.

DimensioneX Forum > DimensioneX Generale > Continuità.



Title: Continuità.


Ferion - August 30, 2005 04:38 PM (GMT)
Ciao cris..
Molti giocatori sul mio forum mi continuano a ripetere che il problema della continuità del gioco(i riavvi e lo spostamento degli oggetti ecc.ecc.) è una cosa estenuante.
Volevo chiederti se è stata trovata una soluzione a tale problema.

Cris - August 30, 2005 05:42 PM (GMT)
La persistenza dei mondi era a piano per il settembre dell'anno scorso, poi la cosa è slittata per lavorare su altre cose che sembravano più urgenti.

Con la nuova versione di DimensioneX che uscirà (la 5.7) avrò sistemato alcune cose fondamentali come la gestione degli ARRAY per realizzare giochi a turno - tipo dama e scacchi e a quel punto ritornerò sul punto della persistenza (o continuità, come la vuoi chiamare).

Mentre sicuramente la situazione migliorerà molto (e su questo ho la certezza) secondo me però alcune lamentele rimarranno insoddisfatte perchè oggettivamente in un modo multiplayer in cui vengono fatti dei cambiamenti è totalmente impossibile che tutto prosegua nonostante le modifiche in modo liscio liscio.

Mi spiego.

Intanto c'è da dire che molta gente non capisce che se metti per terra un oggetto è virtualmente impossibile che quando torni resti lì, esattamente come nella vita normale se appoggi il cellulare in strada non lo ritroverai di sicuro il giorno dopo (anche se può succedere!).
Da qui nascono i vari meccanismi (stanza di salvataggio dove restano gli oggetti. ecc. ecc.) che sono degli ottimi compromessi per risolvere la cosa.

Però ovviamente non sempre riesci a risolvere le cose. Facciamo alcuni casi, da cui capirai che nessuno al mondo è in grado di risolverli (o almeno non mi immagino come)

caso 1) dei giocatori hanno conquistato un oggetto creato dinamicamente (es. la corona) a cui sono legati degli eventi. Per motivi vari devo fare delle modifiche a quegli eventi per cui dopo il riavvio il codice relativo agli eventi di quell'oggetto non esiste più o ha cambiato nome. Non ho scelta: non posso ripristinare l'oggetto e devo far ripartire da zero. E la gente si lamenterà...

caso 2) per effetto di un errore mio diversi giocatori riescono a conquistare un oggetto che non avrebbero potuto possedere se non dopo molto tempo. correggo e riavvio. Ovviamente ho due scelte: se ripristino la situazione si crea un caso sbilanciato, perchè ho giocatori diventati potenti perché hanno potuto "barare" grazie ad un errore del gioco. Se non ripristino la situazione e parto da zero tutto è più corretto, ma poi la gente si lamenterà...

Per entrambi i casi, quando metto su la versione nuova del gioco, diventa un vero inferno esaminare caso per caso tutti i giocatori i mostri e gli oggetti per capire chi ripristinare e chi no, eccetera. Faccio molto prima a far ripartire tutto con una situazione pulita.

Quindi la mia proposta di come risolvere la cosa è:

- In caso di riavvio del server SENZA modifiche al gioco il server durante lo shutdown salva la situazione e quando si risveglia ricarica tutto come era. e OK.

- In caso di messa online di una nuova versione, durante lo shutdown viene comunque fatto un SAVE di tutto. Quando il server si risveglia capisce che il mondo è stato aggiornato. A quel punto deve per forza azzerare tutto. Vedremo poi di fornire qualche mezzo per dire al motore se e cosa ripristinare selettivamente leggendo da quanto salvato: lo stato interno del "mondo", le creature che erano vive e gli oggetti che c'erano (posto però che le stanze dove stavano esistano ancora e che gli eventi collegati non siano stati cambiati, sennò lui poi che cosa esegue? codice vecchio sulla versione nuova?)
Tipicamente, se non hai cambiato le funzioni principali potresti ripristinare lo stato del mondo, il denaro, le armi create, i mostri. ma ripeto anche qui ci potrebbe essere qualcuno che si lamenta. E comunque, il rischio che si verifichino errori imprevisti a causa di una situazione "ibrida" o "sporca" è altissimo.

Fammi sapere che ne pensi, prima di iniziare è meglio capire come risolvere le questioni dubbie come quelle che ho elencato.

Ferion - August 31, 2005 08:53 AM (GMT)
Beh,prima di tutto ,rileggendo il mio messaggio,mi sembrava di essere stato forse un po ...pressoso....assolutamente però non volevo farti pressione sulla cosa.
Quello che dici è praticamente vero....
Vorrei discuterne un po,anche in senso di dialogo,che è un discorso che continuiamo da tanto tempo^__^.
allora:
Sinceramente io gli array non so nemmeno cosa siano^___^....sai le ultime novità non le ho seguite molto,infatti sto tentando di usare solo ora le page....
Comunque
Il tuo discorso non fa una grinza.
pensando ora sembra quasi uno svantaggio produrre una sorta di persistenza.....creerebbe soltanto una serie di casini,e vista la complessità di nostri gfiochi veramente si rischia ancheche si accavalli la vecchia versione con la nuova,e poi con le aree distaccate come funzionerebbe se si aggiorna solo un'area?
Quindi ritiro tutto cioc he ti ho chiesto , capendobene che rivoluzionerebbe un casino il tutto.

Ora però vorrei proporti una cosa,
Il problemA della persistenza nel mio gioco consisteva solo nel fatto che la gente non ritrova piu gli oggetti che lascia nella stanza per il salvataggio(quella dove non si possono raccogliere oggetti).Di conseguenza tipo il denaro e le armi ,anche se uno salva la,nel giro dei 3 o 4 giorni non li trova piu comunque.
Per di piu sarebbe un casino per il fatto delle chiavi.Uno salva con una chiave importante per continuare il gioco nella stanza per il salvataggio e tutti quanti sono fregati!!!!!

Vorrei proporti di modificare i piani per modificare dimx,se posso permettermi di lanciarti quest'idea.
E' possibile fare una sorta di salvataggio delle posizioni di tutti gli oggetti(e solo di quello) tipo ogni 10 Ontick tramite uno script nel file dwx,senza modificare il motore del gioco,in modo da non influenzare anche gli altri giochi,e non rischiare grandissimi casini di BUG?
Cioè,secondo te,se si fa una sorta di
For each item in $WORLD (sempre che si scriva così il comando(la maggior parte delle volte i comandi li copio da alcuni miei sscript vecchI))

e qui si fa un (com'era quel comando che salva la variabile del mondo???)
Savestate?ehm...
ah ecco,
savesetting item.name=item.container



Certo però sorgerebbe il problema degli oggetti creati dinamicamente.....darebbe un errore perchè al riavvio non esisterebbero piu......hmmmmmm...........Però si potrebbe fare per gli oggetti non dinamici(dato che nel mio gicoo di dinamico c'è solo il denaro),e assiscurare il salvataggio dello stato ogni ...che ne so ...30 minuti


ma ho paura che l'operazione sia lunghissima!!!!!o sbaglio?cioè,eseguire questo comando dimx quanto ci mette????
E secondo te funzionerebbe?

poi all'on start si mette
una lista di getstate per ogni oggetto non statico che 'è ne l gioco.....penso che così si ossa fare,però ovviamente vorrei sentire la tua opinione.


Cris - August 31, 2005 12:36 PM (GMT)
e infatti quello che hai proposto è esattamente l'operazione che pensavo di far fare a DimensioneX in modo autonomo. Come hai capito ci possono essere dei casi in cui si crea un pò di confusione. Uno come ti dicevo è il caso del codice eventi collegati cambiato. In quel caso l'operazione non può essere svolta "in automatico" ma sarebbe necessario un pannello apposito da superuser per fare queste operazioni mentre il gioco è attivo.

Già da adesso comunque puoi intervenire per sanare alcune situazioni, tramite script con gli strumenti disponibili. Il denaro, per esempio: quando salvi (onSave) potresti convertire il denaro un una variabile numerica (tipo: soldi=100) e poi all'ingresso creai il mucchietto da 100 monete e poni (soldi=null).

Guarda un esempio in cui son riuscito a consentire la permanenza del denaro.

Io in Underworld ho messo un personaggio, Garumir (lo trovi alla torre sud-est), che funziona come una banca. Tu arrivi, gli dai denaro, e lui lo converte in una variabile numerica "Crediti" agganciata a te e che vien salvata quando poi salvi (devi ovviamente ricordarti di salvare!). Quando rientri, anche giorni dopo quando tutto è riavviato, ti ripresenti e lui legge quanto hai di "Crediti" e riconverte il numero in denaro, azzerando i Crediti.

Punto interessante: chi mi dice che una volta incassato io non metta i soldi per terra, esca senza salvare, poi rientri ripristinando il profilo e mi ripresenti con i Crediti=100 facendo finta di non aver incassato nulla?

bene, per evitare che la gente faccia "furbate", Garumir al momento del deposito in banca ti genera una sorta di codice elettronico che corrisponde ai tuoi crediti e viene gestito di nascosto. Se tu ritiri il denaro, lui si fa una copia in un suo SET il codice del credito che ti ha appena pagato. Se tenti di fare il furbo e ti ripresenti, lui prima guarda nella sua collezione. Se vede che sei tornato con lo stesso codice che ha anche lui, significa che hai tentato di fare il furbo, quindi si rifiuta di darti il denaro.

Unico neo: il SET dei biglietti elettronici non vien salvato quindi in teoria, se il gioco vien riavviato, Garumir dimentica tutto e quindi - se non avevi salvato la situazione con Crediti=0 - puoi rifare il prelievo pur avendolo già incassato durante la partita precedente. Ma anche questa si risolverebbe salvando il set dei codici usati con la setSetting.

insomma, come vedi non appena credi di aver incontrato un limite si trova poi un modo per superarlo.

Ciò non toglie che la persistenza vada fatta, anche perché nel caso di riavvio del server (specie nel caso non siano state fatte modifiche al gioco) è indubbiamente utile.

Occhio infine con le setSetting perchè rallentano molto il tuo gioco. Ti conviene identificare bene le cose che ti serve veramente di salvare e trovare il modo di concentrare i salvataggi solo quando necessario (es. , invece di salvare tutte le armi di tutti ogni 10 secondi, conviene creare un personaggio che solo a richiesta mette "al sicuro" le tue armi, come fa garumir)

Mi rimane una domanda da fare: come è possibile che dopo 3/4 giorni le armi spariscano? In quella stanza nessuno può prendere oggetti....
è forse perchè il server viene riavviato? (non ci guardo mai granché)


Ferion - August 31, 2005 06:06 PM (GMT)
Esattamente questo...io non ho mai visto il mio gioco con piu di 4 giorni di funzionalità ,e quindi senza essere riavviato,tranne in veramente sporadici casi.
Il server viene a volte riavviato anche giornalieramente e questo ha seminato scompiglio e incazzamento tra i membri delle gilde.....pensa te,oltre alla stanza dei salvataggi,esistono delle gilde in cui molti giocatori appartenenti a essa depositano oggetti e denaro da condividere con gli altri membri della gilda in un loro magazzino privatol.hanno perso tutti i loro soldi e tesori che avevano accumulato nei loro magazzini dopo un sacco di avventure.
Per questo ho pensato a quello script del salvataggio.
Però se mi dici che è troppo pesante non è fattibile.
Quindi questo è un vero impiccio che devo tentare di risolvere.
No n è possibile salvare TUTTE le posizioni degli oggetti in un UNICA STRINGA tramite script nel dwx?
che ne so io setto il salvataggio di questi 4 oggetti in sequenza:
spada,tunica,water,crafen
come
positionworld=casa1,casa4,fattoria,cantina
ogni oggetto diviso con una virgola.
Così potrei dirgli(ma è questo che non so se è fattibile) di leggere la prima vocedella variabile positionworld e la metto in una variabile che poi dirò spada.conteiner=<<variabile>>
,per la tunica la seconda ecc.ecc.

Cris - September 1, 2005 08:50 AM (GMT)
L'idea che hai abbozzato è corretta.
Io però ti consiglio di fare una cosa ben strutturata procedendo per gradi successivi, perchè ogni soluzione è sempre meno facile a farsi che a dirsi.

Salvo aspettare che io implementi la persistenza (ma ci vorrà qualche mese, diciamo che ci sarà la primavera prossima) puoi inziare a sistemare le cose più importanti nel modo che ti indico qui sotto.

Inizia a salvare il denaro, poi risolvi per le armi e le armature.

Supponiamo che hai 5 stanze salvataggio: stanza1 stanza2 ecc. definite in un SET

A ogni tick, per ognuna delle stanze (ciclo For Each) chiami una funzioncina salvaStanza(stanza) che data una stanza salva con la setSetting il denaro contenuto in essa.
Il salvataggio potrebbe salvare in una variabile numerica che indica solo QUANTO denaro c'è, non la suddivisione dei vari mucchetti questo per semplificare). Esempio:

soldi_stanza1=100
soldi_stanza2=350
...

che significa ("nella stanza1 c'era un totale di 100 monete"... ecc)

Al risveglio (quindi alla onStart) chiami una funzioncina ripristinaStanza(stanza) nella quale data una stanza vai a vedere con la getSetting quanto denaro c'era in quella. Questo succede per tutte stanza1 stanza2 ecc. e così ricrei i 5 mucchiettoni.

et voilà il problema soldi è risolto.


Per le armi la cosa è simile, quello lo puoi fare subito dopo come per il denaro. La cosa è un pochino + complicata perchè devi memorizzare non solo quante sono le armi in totale nella stanza ma, per ogni arma anche di che tipo era. Un esempio:

armi_stanza1=3
arma1_stanza1=spadaferro
arma2_stanza1=armaturarame

al risveglio le ricrei dinamicamente (basta avere una funzioncina creaDinamicamente(tipoggetto,stanza) che dal codice tipoggetto es. "spadaferro" ricrea l'arma giusta nella stanza giusta).


Questo ora dovrebbe essere chiaro e parliamo di un caso con un certo numero di stanze di salvataggio, come ho detto tutte definite in un SET.
Ovviamente se vuoi estendere la cosa a tutto il gioco metterai tutte le stanze del gioco nel SET come se fossero tutte di salvataggio, però come ho detto la cosa appesantisce un bel pò, secondo me non ce n'è la necessità.

E' tutto, spero che sia d'aiuto. Fammi sapere come va OK?


Attenzione infine:

QUOTE

spada.conteiner=<<variabile>>


non si può fare, container è read-only. Devi usare la istruzione Move.

Ferion - September 6, 2005 04:51 PM (GMT)
il problema è che nella mia stanza salvataggio i giocatori nel pannello non hanno i comandi prendi e lascia.Tutto dovrebbe tornare automaticamente nello zaino.

Cris - September 7, 2005 08:28 AM (GMT)
non vedo grossi problemi. memorizza in una proprietà degli oggetti stessi (tipo: oggetto.proprietario) un riferimento al proprietario, così che poi puoi muoverli dove devono essere.

Ferion - September 10, 2005 05:54 PM (GMT)
si ma se memorizzo oggetto.proprietario,io riavvio e il parametro scompare.

Cris - September 12, 2005 08:29 AM (GMT)
QUOTE (Ferion @ Sep 10 2005, 06:54 PM)
si ma se memorizzo oggetto.proprietario, io riavvio e il parametro scompare.

Hai ragione, adesso capisco.

Allora, ovviamente se non ti basta ripristinare gli oggetti ma vuoi anche che questi "ricordino" il loro proprietario e ritornino a lui in mano quando lui rientra la cosa si complica.

Si complica perchè l'intero processo è gestito dal proprietario. Mi spiego.

Quando esci nel tuo profilo vengono salvati gli ID degli oggetti che avevi. Nota, gli ID, non il tipo di oggetti. Questo significa che se gli oggetti erano dinamici (tipo il denaro) gli ID possono cambiare e quindi è facile che al rientro non te li ritrovi.

Questo ti spiega perchè, quando rientri, il denaro quasi mai ti ritorna in mano.

Ora, se vuoi risolvere la cosa occorre che ribalti completamente la cosa.

Dovresti quindi fare queste due cose

1) Negl oggetti ci scrivi, come hai chiesto prima, il proprietario.
Il mio suggerimento di prima si potrebbe modificare così: Io salvo una cosa del genere con la saveSetting:

- per ogni stanza il numero di oggetti
- per ogni oggetto, il tipo di oggetto (object.type) e il proprietario (object.proprietario) che tu devi aver impostato a suo tempo. Ecco cosa finirà quindi nel DB

QUOTE
armi_stanza1=3
arma1_stanza1=spadaferro/tizio
arma2_stanza1=armaturarame/tizio
arma3_stanza1=armaturarame/caio

Nota la sbarra "/" che separa il tipo oggetto dal proprietario.

Quando rientri ricostruisci gli oggetti dinamici, così (l'esempio vale per le armi):

' Chiamare questa funzione per ogni stanza salvataggio
' ogni volta che si riavvia (es. alla onStart)
Function ripristinaArmi(idstanza)
Dim quante = getSetting("armi_" + idstanza)
Dim i
Dim setting, attributi, tipo, proprietario
For i = 1 To quante
setting = getSetting("arma" + i + "_" + idstanza)
  attributi = Split(setting,"/") ' splitta la stringa in due attributi tipo e proprietario
  ' OK adesso rircreiamo l'oggetto
  tipo = attributi(1)
  proprietario = attributi(2) ' Visto? ecco a cosa servono gli ARRAY!
  Call creaOggettoDinamico(tipo,idstanza,proprietario) ' Questa dovresti saperla fare anche tu
Next
End_Function

Sub creaOggettoDinamico(tipo,dove,proprietario)
Dim x
Dim attrs ' attributi
if tipo = "spadaferro"
attrs = "type=spadaferro,proprietario=" + proprietario
x = NewItem(... crea la spada di ferro dentro la stanza "dove" ...,attrs)
End_If
if tipo = "armaturarame"
' idem per la armatura
End_If
End_Sub


e così hai ricreato gli oggetti dinamici (in realtà solo armi e armature) al riavvio. Nota che le informazioni sui proprietari degli oggetti sono ripristinate

2) Ora però non hai ancora risolto nulla. Sì, perchè come dicevo prima il ripristino degli oggetti è gestito dal sistema a partire dal proprietario e si basa unicamente sugli ID
fino a che non lo cambiamo il ripristino fallirà perchè gli ID sono cambiati e il sistema non controlla se negli oggetti che hai nella stanza salvataggio c'è l'informazione sul proprietario.
Questa però puoi facilmente usarla tu.

Supponiamo allora che sfrutti la onReceive di ogni stanza salvataggio. Quando il proprietario ci rientra tu fai una verifica e se ci sono oggetti suoi glieli ridai. ecco:

QUOTE
EVENT stanzasalvataggio.onReceive()
Dim item
For Each item in getItemsIn($OWNER)
If item.proprietario = $AGENT
  'Questo oggetto è della persona appena entrata. Glielo ridò
  Move item,$AGENT
End_If
Next
END_EVENT




Fatto!

Cris - September 13, 2005 12:04 PM (GMT)
Ferion non mi hai detto nulla di questa ultima mia pensata. hai provato? ti piace?




Hosted for free by InvisionFree