UNIVERSITÀ DEGLI STUDI DI PARMA Dipartimento di … · giochi online. Non analizzerò, quindi, gli...

86

Transcript of UNIVERSITÀ DEGLI STUDI DI PARMA Dipartimento di … · giochi online. Non analizzerò, quindi, gli...

UNIVERSITÀ DEGLI STUDI DI PARMADipartimento di Matematica e Informatica

Corso di Laurea in Informatica

Progetto MaNGOS:

Un server open source per

videogiochi online

Candidato: Simone Boni

Relatore: Prof. Enea Zaanella

Anno Accademico 2013/2014

Ringrazio mia moglie Elena e tutta la mia famiglia che ha sempre creduto inme, mi ha sempre sostenuto, mi è stata vicina, mi ha sempre incitato a nonfermarmi mai ed è sempre stata pronta a festeggiare quando era momento.

Un ringraziamento ai colleghi di lavoro che hanno fatto di tutto perlasciarmi lo spazio e i tempi per concludere questa tappa della mia carriera

universitaria.

Dedicato al mio papà, che è sempre stato il migliore tra i maestri.

Introduzione

Fin dall'adolescenza ho avuto una particolare attrazione per il mondo deicomputer e dei videogiochi, tanto che la mia carriera scolastica si è poi in-centrata nell'approfondimento delle mie conoscenze sul mondo della program-mazione e costruzione dei software.

Sullo sfondo di quella che poi è diventata la mia attività lavorativa, hosempre avuto la curiosità di scoprire come viene realizzato un videogioco e,da qui, la mia spinta a prendere un caso reale da poter toccare con mano esu cui poter fare esperimenti.

Ciò su cui mi sono orientato è un videogioco online molto in voga e famosodi cui sono state create anche versioni open source e di libero accesso.

Lo scopo della tesi è di analizzare uno di questi emulatori per scoprirecome l'architettura client-server viene adattata e sfruttata per lo sviluppo deigiochi online. Non analizzerò, quindi, gli aspetti graci come i modelli 3D, lacostruzione degli ambienti di gioco, i problemi di rendering e gestione delletexture, ecc., ma focalizzerò il mio studio sulla costruzione dei componentiche consentono l'interazione tra utente e ambiente del gioco, tra più utentinello stesso ambiente e altre caratteristiche legate all'architettura di gestionedei vari oggetti che interagiscono nel videogioco.

Il videogioco che ho scelto per lo studio, e sul quale ho anche trascorso pa-recchie ore della mia vita, è il celebre, e anche discusso, World Of WarcrafTM

della software house Blizzard Entertainment.Questo gioco appartiene alla categoria dei MMORPG (Massive(ly) Mul-

tiplayer Online Role-Playing Game, ovvero gioco di ruolo in rete multi gioca-tore di massa), un gioco di ruolo che viene svolto tramite Internet contempo-raneamente da più persone che, dalla sua prima uscita nel 2004, ha raccoltopiù di dieci milioni di utenti con un picco massimo di dodici milioni di utentinel 20101.

La tesi si divide in 6 capitoli:

• Il primo capitolo fornisce alcuni preliminari sui giochi di ruolo online.Vengono illustrate brevemente le nozioni di base dei giochi di ruolo e

1 I dati sugli utenti sono stati tratti da Wikipedia

5

le caratteristiche di quello preso in analisi. Nel capitolo si illustreran-no anche le informazioni sull'emulatore usato e analizzato per ricrearel'ambiente di gioco.

• Il secondo capitolo illustra la struttura dell'emulatore, analizzando lasua installazione e i componenti che lo costituiscono.

• Il terzo capitolo mostra la struttura del database, illustrando le relazionitra gli oggetti e la loro costruzione.

• Il quarto capitolo spiega gli sviluppi eettuati e le analisi sui dati perraggiungere gli obiettivi di sviluppo.

• Il quinto capitolo presenta un esempio di server con emulatori per ilvideogioco in oggetto.

• Nel capitolo conclusivo verrà brevemente riassunto il lavoro fatto

Indice

Introduzione 4

1 World of WarcraftTM ed emulatore MaNGOS 81.1 I MMORPG . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81.2 World Of WarcraftTM . . . . . . . . . . . . . . . . . . . . . . 9

1.2.1 Struttura del gioco . . . . . . . . . . . . . . . . . . . . 91.2.2 Personaggi . . . . . . . . . . . . . . . . . . . . . . . . . 101.2.3 Espansioni . . . . . . . . . . . . . . . . . . . . . . . . . 101.2.4 Architettura software . . . . . . . . . . . . . . . . . . . 11

1.3 Progetto MaNGOS . . . . . . . . . . . . . . . . . . . . . . . . 111.3.1 Storia della sua evoluzione . . . . . . . . . . . . . . . . 121.3.2 Logica operativa della community . . . . . . . . . . . . 131.3.3 Limitazioni nello sviluppo derivanti da oggetti Close

Source . . . . . . . . . . . . . . . . . . . . . . . . . . . 16

2 Il database 172.1 Studio del Database . . . . . . . . . . . . . . . . . . . . . . . 17

2.1.1 Dierenze tra i cores . . . . . . . . . . . . . . . . . . . 182.1.2 Dierenze tra InnoDB e MyIsam . . . . . . . . . . . . 192.1.3 Relazioni fra macro-oggetti del database . . . . . . . . 20

2.2 Esempio di analisi . . . . . . . . . . . . . . . . . . . . . . . . . 26

3 Struttura dell'emulatore 293.1 Ambiente Server . . . . . . . . . . . . . . . . . . . . . . . . . 293.2 Repository GitHub . . . . . . . . . . . . . . . . . . . . . . . . 313.3 Download, compilazione, installazione e prima congurazione . 313.4 Le componenti del server . . . . . . . . . . . . . . . . . . . . . 33

3.4.1 Realmd . . . . . . . . . . . . . . . . . . . . . . . . . . 333.4.2 Mangosd . . . . . . . . . . . . . . . . . . . . . . . . . . 34

3.5 I le DBC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44

INDICE 7

4 Implementazioni 484.1 Tipologie di implementazione . . . . . . . . . . . . . . . . . . 484.2 Modalità di implementazione . . . . . . . . . . . . . . . . . . . 48

4.2.1 Database script . . . . . . . . . . . . . . . . . . . . . . 494.2.2 C++ in ScriptDev2 . . . . . . . . . . . . . . . . . . . . 494.2.3 Lua script . . . . . . . . . . . . . . . . . . . . . . . . . 50

4.3 Ricerca e risoluzione . . . . . . . . . . . . . . . . . . . . . . . 504.3.1 Errore di cambio fase . . . . . . . . . . . . . . . . . . . 524.3.2 Personaggio senza animazioni . . . . . . . . . . . . . . 57

4.4 Pull Request sul repository . . . . . . . . . . . . . . . . . . . . 74

5 Un esempio di community 775.1 Un esempio di Server Privato . . . . . . . . . . . . . . . . . . 77

5.1.1 Organizzazione . . . . . . . . . . . . . . . . . . . . . . 785.1.2 Bugtracker e changelog . . . . . . . . . . . . . . . . . . 785.1.3 il sistema delle donazioni . . . . . . . . . . . . . . . . . 79

6 Conclusioni 81

Bibliograa 83

Glossario 84

Capitolo 1

World of WarcraftTM ed

emulatore MaNGOS

In questa sezione si andranno a presentare i concetti dei giochi di ruolo on-line, si presenterà il gioco considerato e la community dell'emulatore analiz-zato. Per una breve descrizione dei principali termini utilizzati si rimanda alglossario.

1.1 I MMORPG

Un Massive(ly) Multiplayer Online Role-Playing Game (MMORPG), ovverogioco di ruolo in rete multi giocatore di massa, è un gioco di ruolo che vienesvolto tramite Internet contemporaneamente da più persone reali.

I MMORPG possono essere di vario tipo, sia che utilizzino sosticati soft-ware, sia che utilizzino un browser web, sia che usino un semplice emulatoredi terminale telnet (MUD, MUSH, MOO e simili).

Negli ultimi anni gli sviluppatori di videogiochi, hanno ampiamente arric-chito la panoramica dei MMORPG esistenti sul mercato, orendo ai giocatoriambientazioni grache curate nei minimi dettagli (città, strade, paesaggi im-mensi...), sfruttano le più moderne tecnologie in termini di texture e graca3D.

Molto comune in questo tipo di giochi è l'ambientazione fantasy: il mondoè popolato da diverse razze (el, orchi, nani, umani, ecc) o anche personaggisimili a noi che possono essere scelti dal giocatore e che possono essere sud-divise in fazioni nemiche. Esiste anche l'ambientazione reale: con personaggisimili a noi (uomini) dove in alcuni si può, ad esempio, andare a cavallo o inmacchina, sfruttando innovazioni della tecnologia 3D.

1.2 World Of WarcraftTM 9

L'eterna contrapposizione tra bene e male è rappresentata principalmentedalla lotta di giocatori contro mostri ma in ogni MMORPG, c'è sempre unobiettivo che va al di là della sda con i mostri e l'ambiente (in inglese Playerversus Monster (PvM) o Player versus Environment (PvE)): i mostri in ef-fetti rappresentano il mezzo per far crescere di livello il proprio personaggio,in modo che possa poi essere più forte per l'obiettivo nale, ad esempio con-quistare un castello e mantenerne il possesso contro gli attacchi degli altrigiocatori oppure combattere contro la fazione nemica e ottenere punteggi.Per questo particolare aspetto, questo tipo di giochi possono essere conside-rati come Never-Ending Games, perché soggetti a costanti aggiornamenti neltempo e perché non presentano una ne ben precisa.[10]

1.2 World Of WarcraftTM

World of WarcraftTM (letteralmente "il mondo di Warcraft", spesso abbre-viato in WoW) è un videogioco fantasy tridimensionale di tipo MMORPG,giocabile esclusivamente con l'utilizzo di Internet e con il pagamento di uncanone. Sviluppato dalla Blizzard EntertainmentTM , è stato pubblicato il 23novembre 2004.

1.2.1 Struttura del gioco

Le dinamiche di gioco di World of Warcraft riprendono quelle tradizionali deivideogiochi di ruolo online. Il giocatore agisce nel mondo virtuale per mezzodi un avatar ("personaggi" o "PG"), interagendo con personaggi controlla-ti dal computer (in inglese Non Playing Character (NPC)), svolgendo unaserie di missioni che gli vengono via via assegnate. Procedendo di missionein missione, progredisce nelle proprie capacità di combattimento e acquisiscenuovi oggetti che può utilizzare direttamente, commerciare con NPC o al-tri giocatori. Parallelamente, può acquisire capacità secondarie (per esempioimparare a creare pozioni magiche con le erbe, a forgiare armi e armature,a pescare, a cucinare e così via). Rispetto ai tradizionali MMORPG, in cuii giocatori sono costretti a molte ore di azioni ripetitive per progredire, inWorld of WarcraftTM il ritmo di gioco è molto più veloce, e le "perdite ditempo " tipiche di questo genere sono ridotte al minimo.

World of WarcraftTM utilizza diversi server chiamati "reami". I reamihanno caratteristiche diverse per far sì che il giocatore possa scegliere lo stiledi gioco che più gli si addice (Normale, Player versus Player, Roleplaying,Roleplaying Player versus Player).

1.2 World Of WarcraftTM 10

1.2.2 Personaggi

Il personaggio ottiene dei punti, denominati comunemente Experience Points(EXP), ad ogni avventura completata, con l'uccisione delle creature nemichenelle quali si imbatte o semplicemente esplorando territori sconosciuti. Sco-po del personaggio è aumentare il proprio livello e la qualità del proprioequipaggiamento, al ne di confrontarsi in sde sempre più dicili.

Ogni personaggio è caratterizzato da elementi tipici dei giochi di ruolo,come caratteristiche, abilità, talenti, magie o mosse speciali, una classe.

Ogni classe ha abilità dierenti, un diverso stile di gioco e la possibilitàdi utilizzare o meno alcuni tipi di equipaggiamento, come ad esempio cottedi maglia, stoa, cuoio, corazza a piastre o spade, mazze, bastoni, pugnali,armi da pugno, archi, fucili, ecc. [11]

1.2.3 Espansioni

Dopo la prima pubblicazione del gioco sono state realizzate delle espansioniovvero delle aggiunte di contenuti al gioco originale, principalmente per con-trastare la caratteristica di tutti i giochi di ruolo per cui arrivati al massimolivello raggiungibile e completate tutte le sde possibile il giocatore tende acercare nuove sde da arontare, magari cambiando videogioco. Le espansio-ni sono quindi mirate a non perdere i giocatori abbonati quando "niscono" ilgioco, ma a orono nuove sde per avere eettivamente l'eetto never-endinggame.

Attualmente sono state rilasciate cinque espansioni che hanno di volta involta aggiunto, modicato e ampliato le possibilità di gioco dei personaggi.

La popolarità del gioco e la sua costruzione articolata di una story linedi base che motivasse la costruzione del mondo di gioco, oltre a dare una ca-ratterizzazione speciali a vari personaggi che si possono incontrare nel gioco,ha fatto sì che si costruisse attorno al gioco un vero e proprio mondo fantasycon tanto di romanzi. Le espansioni, nel tempo, sono diventate la storia del-l'evoluzione del mondo di Warcraft nell'eterna lotta tra bene e male, temaclassico dei romanzi fantasy. L'ambiente di gioco non è quindi solo frutto diuna buona creatività da parte degli sviluppatori, ma frutto di un accuratostudio e lavoro costruttivo per rendere gli ambienti, i personaggi e gli oggettiparte di un mondo fantastico con una storia. Questo, a dierenza di altrigiochi MMORPG è stato sicuramente un punto di maggiore forza e motivodei tanto successo nel corso degli anni.

1.3 Progetto MaNGOS 11

1.2.4 Architettura software

Il videogioco è strutturato nel classico stile client-server. C'è quindi una con-tinua e indispensabile comunicazione tra il client installato sul computer delgiocatore e il server a cui è collegato. La velocità di comunicazione e la la-tenza della connessione di rete è una componente fondamentale per averesessioni di gioco uide e senza ritardi nell'esecuzione delle azioni.

Essendo sia il client che il server "close source" non è stato possibileanalizzare le logiche di scambio delle informazioni tanto più che, anche ef-fettuando analisi sul traco di rete, i pacchetti intercettati risultano esserecifrati o in formato non direttamente interpretabile.

Le uniche informazioni che si posso carpire provengono dal client sono idati di gioco contenuti nei le archivio che lo compongono. Il client, infatti, ècorredato di tutte le informazioni grache e sonore che vengono visualizzateal giocatore durante le sessioni di gioco. Questa logica di dislocazione deidati di gioco nel client consente di ridurre la mole di dati inviati dal serveral client, lasciando più spazio per le sole informazioni essenziali alle azionidi gioco. Esistono alcuni strumenti che consentono di visualizzare in modoabbastanza user-friendly i contenuti di questi archivi, permettendo l'analisidegli oggetti che sono poi usati nel videogioco e le loro informazioni basilariper il funzionamento nelle logiche del gioco stesso. Queste informazioni ri-sultano utili per interpretare gli eetti di azione (del client) e reazione (delserver) che si vericano durante le sessioni di gioco, e ricostruire le logiche difunzionamento.

1.3 Progetto MaNGOS

Il videogioco non nasce open source, ma la sua popolarità ha spinto alcuniprogrammatori a costruire degli emulatori open source che ricreano le funzio-nalità del gioco originale. Data la complessità che il videogioco ha raggiuntonel tempo, lo sviluppo di questi emulatori non ha mai raggiunto gli stessilivelli dei server originali ma le caratteristiche di base per poter funzionaresono state comunque realizzate.

Dovendo costruire questi emulatori senza poter visionare il codice sorgen-te originale dei server uciali della software house, è di grande aiuto aglisviluppatori il gran numero di informazioni sui contenuti del gioco e sulle suelogiche di funzionamento che i videogiocatori hanno organizzato in alcuniportali dedicati con libero accesso.

Un'altra motivazione che ha contribuito la creazione di questi emulatoriè l'abbonamento mensile a pagamento che la software house richiede per

1.3 Progetto MaNGOS 12

poter usare il videogioco in oggetto. Gli emulatori open source non prevedonoquesto abbonamento e quindi risultano essere anche gratuiti per i giocatori,i quali sono consapevoli però che il videogioco non è completo di tutte le sueparti ma solo di quelle che sono state ricostruite.

L'emulatore su cui ho focalizzato il mio studio è il progetto open sourceMassively Network Game Object Server (MaNGOS) scritto in C++ voltoa creare un applicativo server per MMORPG. Il progetto è sotto licenzaGPL e il codice sorgente delle nuove versioni viene costantemente rilasciatonel servizio git di GitHub. Attualmente il progetto supporta il protocollo direte del MMORPG World of WarcraftTM . MaNGOS non è considerato unemulatore server di uno specico MMORPG, bensì è un progetto educativoper la programmazione ad oggetti in C++, a cui tutti gli utenti possonoapportare il proprio contributo, aumentando così il patrimonio culturale ditutta la community di utenti/sviluppatori.

1.3.1 Storia della sua evoluzione

Dalla creazione di MaNGOS (intorno al 28 agosto 2005) no al dicembre2012 theLuda era il leader di MaNGOS. La sua idea originale di un progettoopen-source educativo continua ancora oggi.

Durante questo periodo si sono vericati diverse divisioni (come per tutti igrandi progetti), da cui sono nati i progetti Trinity, MangosR2 e CMaNGOS.

Dopo l'hacking del sito, forum, server e GitHub nel maggio 2013, theLudae gli altri sviluppatori di alto livello hanno deciso di abbandonare il progettoe alcuni hanno lasciato il gruppo per sempre. Durante questo periodo Antzchiese il permesso di mantenere il progetto in corso e con l'aiuto del MadMaxricostruirono il forum, il sito web e il repository GitHub.

La perdita di theLuda come il leader e alcuni degli sviluppatori di altolivello è stato un duro colpo per la squadra MaNGOS, ma questa situazionenon durò troppo a lungo. Nel luglio 2013 theLuda fu convinto a tornare comesviluppatore senior e consulente per il progetto MaNGOS.

Da allora hanno continuato a sviluppare i cores ed espandere la loro ba-se di conoscenze nonché incoraggiare e allenare la prossima generazione diesperti MaNGOS.

In agosto 2013 il team MaNGOS raccolse le persone provenienti da altriprogetti di emulatori morti. In settembre 2013 uno dei fondatori di un pro-getto esterno (wowAdict) si è unito al team per lavorare al progetto parallelorinominato MangosVB. Gli obiettivi principali di questo progetto sono direalizzare un porting in VB.NET dei sorgenti C++ relativi ai vari cores diMaNGOS.[3]

1.3 Progetto MaNGOS 13

1.3.2 Logica operativa della community

La community si è primariamente suddivisa in cinque progetti (core), unoper ogni espansione (esclusa l'ultima) più la versione originale, denominati:MaNGOS Zero (versione originale chiamata anche Vanilla); MaNGOS One(prima espansione chiamata anche The Burning Crusade o TbC); MaNGOSTwo (seconda espansione chiamata Wrath of the Lich King o WotLK); MaN-GOS Three (terza espansione chiama Cataclysm o Cata); MaNGOS Four(quarta espansione chiamata Mist of Pandaria o MoP).

Le funzioni essenziali di ciascun progetto sono condivise e sviluppate par-tendo da MaNGOS Zero. Quando sono vericate essere stabili, vengono ri-portate anche sugli altri cores in modo da avere una distribuzione uniformedelle funzioni che stanno alla base di tutti i progetti. Questa strategia aiuta lacommunity ad avere una distribuzione uniforme del codice sorgente prodottoe migliora le attività manutentive e correttive tra i vari cores.

Le gure operative che lavorano sui vari progetti sono le seguenti: Com-munity Manager; Junior Developer; Developer; Senior Developer; Eluna De-veloper; Donator; VIP Donator; Utente registrato.

Il nodo attorno a cui tutto ruota è il forum della community, dove gliutenti esterni e i membri uciali del progetto MaNGOS possono confrontarsi,scrivere le note sulle evoluzioni, richiedere supporto nello sviluppo agli altrimembri e condividere anche le scoperte o le innovazioni introdotte. Il forumrisulta quindi lo strumento cardine per l'evoluzione del progetto.

I membri uciali che ricoprono le varie gure operative descritte prima adeccezione degli utenti registrati sono attivi giornalmente pur essendo poco piùdi una dozzina in tutto. Internamente si sono suddivisi i compiti principali,per evitare di fare lo stesso lavoro due volte. Gli utenti registrati che operanocome satelliti attorno al progetto sono invece molti di più, ma sono anchemolto meno costanti nelle attività. Tra questi ancora oggi sono attivi Antz eMadMax, già citati nella storia di MaNGOS.

Indubbiamente la parte più complessa del progetto non è tanto la co-struzione del codice ma la gestione di tutte le persone che direttamente oindirettamente operano su di esso. Evitare la scrittura delle stesse cose dapiù persone e assistere nelle richieste di supporto da parte degli utenti chesi approcciano per la prima volta alle tematiche di sviluppo sono i temi chepiù frequentemente devono essere arontati.

Navigando per qualche tempo nel forum e partecipando attivamente an-che alle evoluzioni, ho notato alcuni proli di utenti che si approcciano alprogetto. Le impressioni sono di una vasta gamma di approcci dierenti, co-me chi si presenta come un grande sviluppatore che ha fatto tante cose maquando gli si chiede di estendere i suoi sviluppi alla community sparisce nel

1.3 Progetto MaNGOS 14

nulla oppure chi fa richieste di assistenza nella compilazione del progetto perla sua esecuzione e poi non torna a dare feedback sui suoi tentativi. Questoda una idea, se pur parziale e approssimata, di quanto la programmazionee sviluppo di applicativi sia spesso approcciata senza vere basi e in modosuperciale.

Attualmente la community si sta concentrando principalmente sullo svi-luppo del server MaNGOS Zero con il focus principale all'ambiente Windows,creando quindi le librerie e l'ambiente di sviluppo su Visual Studio. Questadecisione probabilmente deriva anche dal fatto che spesso i potenziali svi-luppatori esterni alla community hanno maggiore familiarità con i tool disviluppo su Windows, che hanno un impatto graco molto più diretto deigli strumenti disponibili in ambiente Linux. Per un programmatore alle pri-me armi con la gestione degli oggetti, delle librerie e le relative dipendenze,un ambiente di sviluppo come Visual Studio di Microsoft risulta avere unapprendimento più semplice e intuitivo sfruttando molti tool integrati di as-sistenza allo sviluppo come, a esempio, la ricerca della denizione dei metodidi una classe all'interno di tutto i sorgenti del progetto aperto. Le stesse ope-razioni però si possono svolgere anche in ambiente Linux, ma richiedono unamaggiore conoscenza dei comandi shell.

Nonostante questa preferenza per l'ambiente graco, sono comunque te-nute aggiornate anche tutte le procedure Linux per la compilazione, che sfrut-tano CMake come motore per la gestione delle dipendenze e di costruzionedegli oggetti.

Lo strumento scelto dalla community per gestire ed organizzare i sorgentidei vari progetti è il repository GitHub. In passato veniva utilizzato il servizioSVN, ma è stato poi rimpiazzato con quello attuale per questioni di migliorgestione delle revisioni. Ogni espansione, sul repository, è suddivisa in treblocchi:

• Server: questo repository contiene tutte le classi C++ essenziali delserver e le librerie C++ che gestiscono tutte le funzionalità del gioco.

• Database: questo repository contiene tutti gli script SQL per popolareil database MySQL con gli oggetti di gioco.

• Scripts: Questo repository contiene una libreria C++ aggiuntiva di sup-porto per gli sviluppatori che si integra con il core del server per renderefunzionanti oggetti di gioco che necessitano di funzioni più avanzate ospeciche rispetto a quelle generiche presenti nel core.

Dato l'obiettivo del progetto MaNGOS, i sorgenti sono liberamente scarica-bili e usabili in vari modi, dalla banale copia in locale diretta al più articolato

1.3 Progetto MaNGOS 15

fork sul proprio account GitHub per poter gestire la propria copia del pro-getto e svilupparla parallelamente a quella originale. Con questo metodo poiè possibile eettuare dei "Pull Request", ovvero trasferire le modiche fat-te sulla copia nell'account personale di GitHub nel repository originale delprogetto e contribuire quindi personalmente allo sviluppo del medesimo.

I trasferimenti di modiche sul progetto originale non sono diretti, mapassano sotto la supervisione di alcuni moderatori che convalidano quantoproposto. In questo modo si evitano potenziali manomissioni o alterazionierrate del codice, lasciando comunque la possibilità a chiunque di contribuireallo sviluppo del progetto MaNGOS.

Ritengo che la libertà di partecipazione ad un progetto così complesso,ma anche più in generale a qualsiasi progetto di sviluppo, da parte di personequalsiasi che non sempre hanno un background o conoscenze sulla program-mazione e sulle logiche di sviluppo di un applicativo solide, possa innescare unprocesso di autodistruzione se non viene controllato e gestito con accuratez-za. La metafora del gigante con i piedi di argilla può essere molto calzante inquanto spesso un bug o un errore di programmazione in una funzione essen-ziale (causato da un programmatore inesperto) può inciare tutto il processodi funzionamento di un applicativo molto articolato.

Un altro obiettivo della community è la gestione della documentazionedel progetto. Essendo questo un progetto educativo la documentazione èfondamentale e di primaria importanza anché chi si approccia a MaNGOSpossa apprendere gli esperimenti e le evoluzioni apportate, possa impararee scoprire come realizzare un oggetto così complesso e articolato. Questocompito è tutt'altro che semplice, sia per l'eterogeneità delle persone checontribuiscono, sia per i continui cambiamenti evolutivi che il progetto stessosubisce.

Durante la vita del progetto MaNGOS sono nati alcuni progetti parallelida membri appartenenti alla community che hanno preferito intraprenderestrade diverse da quelle che la community stessa voleva percorrere. Questiprogetti sono il TrinityCore e il CMaNGOS.

Queste biforcazioni hanno mantenuto la losoa open source di MaN-GOS, ma hanno poi intrapreso percorsi di sviluppo dierenti dal progettooriginale. Ho condotto qualche breve ricerca su questi progetti gli e alla neho raggiunto la conclusione che pur percorrendo strade dierenti, il risultatoè abbastanza simile: uno sviluppo lento ma continuo, volto si a costruire unserver quanto più funzionante possibile ma al tempo stesso sono anche dellecontinue fonti di nuove conoscenze per chi partecipa alle community.

I membri uciali della community non percepiscono un salario sso emensile, ma svolgono le attività nel tempo libero e come hobby al di fuoridegli orari di lavoro. Sul forum è presente una funzione di donazione naliz-

1.3 Progetto MaNGOS 16

zata principalmente alla manutenzione dei server privati e del dominio delprogetto. Non ci sono quindi aspetti commerciali o nanziari che tengonoviva la community, ma la semplice voglia di ciascun membro nel contribuireliberamente all'evoluzione del progetto MaNGOS.

1.3.3 Limitazioni nello sviluppo derivanti da oggetti Clo-

se Source

Come accennato in precedenza, sia il server che il client sono close source. Deiserver uciali non esistono nemmeno i le binari per eventuali installazioni ditest. Questo ha reso complicata la creazione delle funzioni "core" dei progetti.

Una possibile apertura per ricostruire le funzionalità del gioco è data dalclient, che pur essendo close source, contiene tutti i dettagli degli oggetti digioco in le-database consultabili con opportuni strumenti.

Per analizzare i le del client ho usato gli strumenti:

• Mydbceditor: Questo tool consente di visualizzare e modicare i le-database che contengono i dati strutturati dei vari oggetti che nel giocovengono visualizzati ed usati.

• Ladik's MPQ Editor: Questo tool consente di visualizzare il contenutodei le MPQ contenenti oggetti graci e multimediali quali texture, clipvideo, clip audio e altri contenuti visualizzati durante il gioco.

Durante la fase di analisi degli oggetti di gioco ho potuto scoprirne le carat-teristiche grazie a questi strumenti.

Capitolo 2

Il database

In questa sezione si presenterà la base di dati che contiene tutte le informa-zioni degli elementi del gioco. Per una breve descrizione dei principali terminiutilizzati si rimanda al glossario.

2.1 Studio del Database

Gli script di costruzione e popolazione del database e anche le guide di in-stallazione sono costruiti per il database relazionale MySQL di Oracle. Al-l'interno dei vari les sono presenti però anche alcune bozze per costruire labase di dati anche per il database PostgreSQL, ma questi ultimi non sonostati oggetto di analisi.

La costruzione del server si suddivide in tre più uno schemi. I primitre sono caratteristici del reame2, contengono quindi informazioni specicherelative all'espansione di gioco del reame:

• mangos: contiene le informazioni sugli oggetti di gioco, le creature, gliNPC, ecc... ovvero le componenti con cui il giocatore può interagiredurante le sessioni di gioco.

• character: contiene le informazioni relative ai personaggi che il gioca-tore ha creato, con tutte le informazioni di corredo sul loro avanzamentonel gioco partendo dai dati caratteristici, l'equipaggiamento (ovvero glioggetti che il personaggio possiede), le quest che ha completato e tuttegli altri elementi che ha usato o incontrato durante le sessioni di gioco.

2Il concetto di reame sarà meglio esplicitato nel prossimo capitolo. Anticipando breve-mente il signicato, il reame è il processo che gestisce le interazioni tra giocatore e ambientedi gioco.

2.1 Studio del Database 18

• scriptdev2:contiene informazioni di supporto per gli script aggiuntividel server, ovvero gli script per il funzionamento specico di alcunieventi, oggetti o elementi che non sono gestiti gestiti con le normalifunzioni basilari, ma sono realizzati separatamente.

Il quarto schema, invece, contiene informazioni relative ai reami che il serverospita

• realmd: contiene le informazioni per le connessioni ai reami quali iriferimenti dei server, le credenziali di accesso (account e password) equanto serve per il processo di login, scelta del reame e del personaggiocon cui giocare.

Possiamo quindi trovare all'interno della stessa istanza del database lacoesistenza di più reami con nomi di schemi opportuni per distinguerli e unsingolo schema per le informazioni di connessioni ai reami. Nulla vieta peròdi gestire su istanze di database separate i singoli reami e il singolo schemacon le informazioni sui reami stessi. In questo modo è possibile costruire unastruttura scalabile e/o decentralizzata a seconda delle esigenze, dimensioni enumero dei reami disponibili per i giocatori.

2.1.1 Dierenze tra i cores

Come descritto in precedenza, il progetto MaNGOS è suddiviso in diversicores. Le dierenze nel database tra i cores sono essenzialmente di due tipi:

• strutturali: ogni espansione aggiunge nuove tipologie di oggetti, am-bienti e attività che il giocatore può usare, esplorare e svolgere. Questenuove funzionalità si riettono sulla struttura del database con l'ag-giunta di colonne a tabelle esistenti o nuove tabelle. La logica del-le colonne esistenti rimane immutata o al più viene dismessa quandouna nuova funzionalità sostituisce una vecchia. Questa modalità di co-struzione delle espansioni consente di preservare le strutture dei datioriginali e introdurre quindi i nuovi elementi senza dover ricostruiretutta la struttura da zero mano a mano che si aggiungono le espansionisuccessive.

• contenuti: ogni espansione aggiunge nuovi contenuti e può rende ob-soleti o non più usati alcuni contenuti precedenti. I dati quindi tendonosostanzialmente ad aumentare e mai ad essere rimossi. Anche in que-sto caso l'introduzione di nuove espansioni conserva i dati precedenti enon è quindi necessario reinserire tutti i dati precedenti per le nuovefunzionalità. Al più sarà necessario aggiungere i nuovi valori di default

2.1 Studio del Database 19

per le eventuali nuove colonne delle tabelle che contengono i dettaglidelle nuove funzionalità.

L'evoluzione tra un core e quello successivo, ovvero il passaggio da unaespansione a quella successiva, è abbastanza conservativo nei confronti deidati e della struttura del database, per cui non dovrà mai essere necessariala riscrittura completa di tutta la base dati per il passaggio ad una nuovaespansione.

2.1.2 Dierenze tra InnoDB e MyIsam

Il database relazionale MySQL utilizza due tipologie di motori per la ge-stione dei dati nelle tabelle: MyISAM e InnoDB. Gli script di costruzione eimportazione dei dati nel database specicano per ogni tabella quale motoreusare. Questa scelta costruttiva non è casuale ma ben studiata per orire ilmassimo delle prestazioni.

Il motore MyISAM ha la caratteristica di essere molto performante perle letture di dati a scapito dei controlli di integrità referenziale. Infatti letabelle con questo motore non possono avere chiavi esterne (o Foreign Key)utilizzate nel database relazionali per garantire la coerenza degli indici chiavetra tabelle. Sono tuttavia disponibili gli indici di tabella, per ottimizzare lericerche. Inoltre per questo motore non esiste il concetto di transazione mai lock dei dati avvengono per singola riga della tabella e non per blocco dioperazioni sulla tabella.[7]

Il motore InnoDB invece possiede tutte le caratteristiche richieste da unabase dati relazionale (quindi sono disponibili le Foreign Key e tutti i controllie peculiarità ad esse relative oltre alla gestione delle transazioni) ma la com-plessità delle operazioni per garantire le caratteristiche relazionali (Atomicità,Consistenza, Isolamento e Durabilità delle transazioni) richiedono maggioririsorse e, per tanto, queste tabelle possono risultare più lente sia in letturache in scrittura.[7]

La decisione sul motore con cui creare una tabella, quindi, dipende dallemodalità d'uso dei dati in essa contenuti. Se verranno fatte poche modichema tante letture potrebbe essere più indicato un motore MyISAM; se invecedovessero risultare maggiori le modiche e inserimenti di dati oltre ad esserenecessaria la presenza di riferimenti coerenti a chiavi esterne (quindi l'uso diforeign key) la scelta ricadrebbe ovviamente sul motore InnoDB.

Analizzando i le di script di costruzione e popolamento del databaseè possibile notare che gli schemi mangos e scriptdev2 contengono uni-camente tabelle con motore MyISAM, mentre gli schemi characters e

2.1 Studio del Database 20

realmd contengono tabelle con entrambi i motori, a seconda della presenzao meno di relazioni fra tabelle.

Questa costruzione lascia intendere che gli schemi mangos e scriptdev2contengano dati che cambiano poco o niente durante l'esecuzione del server,mentre gli altri schemi hanno dati che sono modicati più frequentementee sono in relazione tra loro. Nell'analisi dei componenti del server del pros-simo capitolo sarà dettagliata maggiormente il motivo di questa dierenzacostruttiva.

2.1.3 Relazioni fra macro-oggetti del database

Schema realmd

Questo schema contiene i dati relativi agli account dei giocatori e le informa-zioni relative ai reami disponibili.

Gli account sono memorizzati nella tabella accounts e i dati essenzialiin essa contenuti sono:

• id: contiene il numero identicativo dell'account, usato in tutte le ta-belle che contengono dati ad esso relativi (come ad esempio la tabellacharacters nello schema mangosd).

• username: contiene il nome dell'account scelto dal giocatore. Questonome deve essere univoco.

• gmlevel: contiene il valore che stabilisce il livello di autorizzazioni perl'account. Normalmente tutti gli account sono di tipo giocatore, esi-stono però altre due tipologie di autorizzazioni: Game Master e Admi-nistrator, che hanno più libertà di violare le meccaniche di gioco perscopi di gestione e assistenza ai giocatori.

• expansion: contiene il valore che indica l'espansione a cui il giocatoreè abilitato. Ovviamente questo valore abilita solo a espansioni uguali oprecedenti a quella del reame a cui si è collegati. Non sarà mai possibileavere un giocatore abilitato ad una espansione più recente di quellacongurata nel reame.

I reami sono memorizzati nella tabella realmlist e i dati essenziali inessa contenuti sono:

• nome: il nome del reame;

• IP: indirizzo IP del reame;

• porta: porta TCP del reame;

2.1 Studio del Database 21

Schema mangos

Pur non essendoci dei legami espliciti fra le tabelle dello schema mangos,analizzando i dati e le strutture è possibile ricostruire le relazioni tra le tabellee tra i contenuti delle tabelle stesse anche senza le foreign key. La vericadella relazione reale tra gli oggetti sarà lasciata al reame durante l'esecuzione.

Per l'analisi della struttura del database non sono disponibili online molteinformazioni, ma la community ha realizzato un manuale PDF scaricabile3[4]abbastanza esaustivo con le informazioni sulla struttura del database e di ognisingola tabella. Con questo manuale e portali internet dedicati è possibilericostruire le relazioni logiche tra gli elementi codicati nel database.

A titolo esemplicativo dalla mia analisi dei dati e delle relazioni logichetra le tabelle dello schema mangos ne riporto una porzione partendo daquella che risulta essere la struttura portante del gioco: le quest (o missioni).Tutto parte dalla tabella quest_template4 la cui struttura contiene i datiper lo svolgimento e il completamento della quest. Delle 168 colonne di cui latabella è composta, ne analizziamo solo le principali per il nostro obiettivo:scoprire come funziona la relazione tra una quest e gli oggetti in essa coinvolti.

I campi di nostro interesse sono i seguenti:

• entry: contiene il codice numerico identicativo della quest. Questoidenticativo è usato in tutte le altre tabelle che hanno dei riferimentia questa.

• requiredClasses: contiene un bitmask che identica la classe del per-sonaggio che può accettare la quest (non tutte le quest sono libere, maesistono quest che sono speciche di alcune classi di personaggio, ed ècorretto che solo quelle classi di personaggio possano accettare le questa loro dedicate). I valori possibili della bitmask sono deniti nel leChrClasses.dbc.

• requiredRaces contiene un bitmask che identica la razza del perso-naggio che può accettare la quest (non tutte le quest sono libere, maesistono quest che sono speciche di alcune razze di personaggio, ed ècorretto che solo quelle razze di personaggio possano accettare le questa loro dedicate). I valori possibili della bitmask sono deniti nel leChrRaces.dbc.

3Il documento è consultabile a MaNGOS-Zero docshttps://media.readthedocs.org/pdf/mangoszero-docs/latest/mangoszero-docs.pdf

4le informazioni sono state identicate nel documento MaNGOS-Zero docs in data10/11/2014

2.1 Studio del Database 22

• prevQuestId: contiene il codice numerico della quest che precede quel-la corrente e che deve essere completa prima di poter accettare quellaattuale.

• nextQuestId: contiene il codice numerico della quest successiva aquella corrente.

• reqItemId1: contiene il codice numerico della colonna entry nellatabella item_template richiesto da questa quest.

• reqItemCount1: contiene il numero di oggetti identicati dalla colon-na reqItemId1 necessari per poter terminare la quest.

• ReqCreatureOrGOId1: contiene il codice numerico della colonna en-try nella tabella creature_template oppure nella tabella game-object_template richiesto da questa quest. Queste due tabelle fan-no riferimento ad una unica colonna in quanto sono mutamente esclu-sive.

• ReqCreatureOrGOCount1: contiene il numero di creature o oggettiidenticati dalla colonna ReqCreatureOrGOId1 con cui è necessariointeragire per poter terminare la quest.

Da questo estratto della struttura relativa alla tabella delle quest è quindipossibile notare che non tutti i dati sono codicati all'interno del database,ma alcuni sono presenti nei le-database DBC estratti dal client e conservatinell'apposita cartella del percorso di esecuzione del reame di cui parlere-mo nel prossimo capitolo. Altre colonne, invece, possono contenere i codiciidenticativi degli altri oggetti (codicati nel database) che sono coinvolti erecuperare quindi le loro caratteristiche.

Un altro esempio di come sono costruiti gli elementi del gioco all'internodel database è dato dall'analisi degli elementi nella tabella creature_-template. Questa tabella contiene tutti gli elementi di tipo creatura (mostrida combattere, NPC e altre creature speciali). Per questi elementi esisto varietabelle di supporto in quanto le azioni e le relazioni con gli altri elementi delgioco sono tante e complesse. La tabella che contiene la denizione di unacreatura è quindi la tabella creature_template dove la colonna entryè chiave e consente di identicare in modo univoco una creatura. Questocodice sarà poi utilizzato in tutte le altre tabelle per le varie relazioni, comegià abbiamo visto nella tabella delle quest. Oltre a questa tabella dove sonodenite le informazioni di base e più generiche della creatura ce ne sono altredi supporto di cui, le principali e più rilevanti, sono:

2.1 Studio del Database 23

• creature_questrelation: denisce quale creatura inizia una quest,ovvero da quale NPC il giocatore deve recarsi per iniziare una specicaquest.

• creature_involvedrelation: denisce quale creatura termina la que-st, ovvero da quale NPC il giocatore deve recarsi quando ha completatogli obiettivi della quest per terminarla e ricevere la ricompensa.

• creature_movement_template:denisce il percorso che una crea-tura percorre in modo autonomo.

• creature_loot_template: identica quali oggetti la creatura puòorire al giocatore quando viene uccisa.

• creature_ai_scripts: contiene le informazioni per consentire alla crea-tura di eseguire azioni al vericarsi di determinati eventi. Questa tabellaviene usata per il Database Scripting descritto nel quarto capitolo.

• creature: contiene le informazioni su dove la creatura si trova nell'am-biente di gioco e il suo comportamento. All'interno di questa tabellaè possibile trovare più volte il codice identicativo del template dellacreatura in quanto alcune di esse si possono trovare in zone dierentidel gioco. L'uso di una tabella template per la denizione delle carat-teristiche di una creatura facilita la gestione delle sue caratteristichequando viene replicata più volte.

Da questa macro analisi è possibile costruire il seguente schema:

Figura 2.1: Schema logico relazionale della tabella quest_template e suedipendenze

2.1 Studio del Database 24

Come per le creature, anche altri elementi presenti nel database sfruttanouna organizzazione simile dei dati, in modo da ottimizzare al massimo lagestione delle caratteristiche di ogni elemento cercando di rispettare quantopiù possibile il paradigma della normalizzazione delle tabelle di un database.

Schema characters

In questo schema sono presenti le tabelle che contengono tutti i riferimentie i dati dei personaggi che ogni giocatore ha creato. Queste tabelle sonocostantemente lette e aggiornate dal reame e risultano quindi le più criticheper le performance.

La tabella cuore di tutto il sistema di riferimenti è characters checontiene i dati di base di tutti i personaggi. A questa tabella sono poi col-legate tutte le altre, che contengono dati aggiuntivi relativi ad ogni singolopersonaggio. I dati basilari e più importanti contenuti in questa tabella sono:

• guid: contiene l'identicativo univoco del personaggio. Questo iden-ticativo sarà usato in tutte le tabelle di relazione per identicareunivocamente il personaggio a cui appartengono gli attributi aggiuntivi.

• account: contiene l'identicatore dell'account. Questo identicatore èmemorizzato nella tabella realmd.accounts.

• name: contiene il nome del personaggio assegnato dal giocatore. Questonome deve essere univoco.

• race: contiene la razza del personaggio.

• class: contiene la classe del personaggio.

• gender: contiene il sesso del personaggio.

• level: contiene il livello del personaggio.

• xp: contiene il valore dell'esperienza correntemente raggiunta dal per-sonaggio.

• money: contiene il valore dei soldi che il personaggio possiede.

Oltre a questo insieme basilari, sono presenti anche altre colonne che svolgonofunzioni statistiche e organizzative per il personaggio.

Altre tabelle che si collegano a questa appena descritta per conservareinformazioni aggiuntive sono:

2.1 Studio del Database 25

• character_queststatus: contiene tutte le informazioni di relazionetra ogni personaggio e le quest che ha accettato, completato o abban-donato nel corso delle sessioni di gioco.

• character_talent: contiene le informazioni sui talenti che ogni perso-naggio apprende nel progredire della sua esperienza di gioco.

• character_inventory: contiene l'elenco di tutti gli oggetti che ognipersonaggio ha nel proprio inventario.

• character_ticket: contiene tutte le richieste di assistenza che i per-sonaggi hanno fatto.

Oltre ai dati dei personaggi, in questo schema sono presenti altre infor-mazioni:

• gilde 5: In queste tabelle sono raccolte le informazioni di base sulla gildapiù tutti i vantaggi di cui i personaggi possono usufruire se appartengo-no alla gilda. Le informazioni sono contenute in: guild, guild_member,guild_rank, guild_bank_item e guild_bank_right.

• posta: In queste tabelle sono gestite le comunicazioni postali tra igiocatori. Le informazioni sono contenute in: mail e mail_items

• arena6: In queste tabelle sono gestite le squadre di giocatori che si scon-trano nelle arene oltre ai punteggi di ogni squadra. Le informazioni sonocontenute in: arena_team, arena_team_member e arena_team_stats

Per dare un'idea della quantità di informazioni che vengono archiviate egestite per ogni singolo personaggio di un account riporto un esempio. Latabella characters si può considerare la radice di tutte le informazioni suipersonaggi. Essa contiene, per ogni personaggio7, una riga composta da ses-santadue colonne. Questa tabella è associata a circa cinquanta altre tabellecontenute nello stesso schema, ognuna delle quali ha un numero di colon-ne compreso tra due a venti. Non tutte queste relazioni sono di tipo uno

5Le gilde sono tipicamente delle associazioni di giocatori. Vengono formate per coordi-nare e organizzare in modo più funzionale la partecipazione agli eventi di gioco in gruppo,oltre a migliorare la collaborazione tra giocatori nella progressione di gioco, dove i piùesperti aiutano i neo arrivati.

6Le arene sono aree di gioco in cui le squadre di giocatori possono competere uno control'altro in combattimenti di sopravvivenza. La vittoria viene aggiudicata alla squadra cheriesce ad sconggere tutti i giocatori avversari senza limiti di tempo.

7Supponendo che giocatore possieda un solo account può avere un numero massimodi dieci personaggi, corrispondente al limite di personaggi per account.

2.2 Esempio di analisi 26

a molti, ma alcune lo sono e associano, ad ogni personaggio, un numero dirighe che aumenta mano a mano che il personaggio progredisce nel gioco,raggiungendo anche qualche migliaia di record nel caso della tabella charac-ter_queststatus8. Quando un personaggio è vicino al completamento ditutte le sde che il gioco può proporre, il numero di ennuple ad esso relativepuò essere decisamente molto maggiore di una decina di migliaia (di cui lamaggior parte saranno, come visto, relative alle quest).

Schema scriptdev2

Questo schema contiene poche tabelle, in quanto il suo scopo è solo di fornireun supporto molto mirato e specico per le implementazioni che non trovanorisoluzione nella struttura di base del reame. Per questo motivo ci sono solotre tabelle:

• gossip_text: In questa tabella sono memorizzati i testi dei dialoghiche i NPC possono avere quando interagiscono con un personaggio, evengono impostati dagli script C++ del progetto ScriptDev2.

• script_text: In questa tabella sono memorizzati i testi aggiuntivi che iNPC possono dire, e vengono richiamati dagli script C++ del progettoScriptDev2.

• script_waypoint: In questa tabella sono memorizzati i percorsi deiNPC che sono richiamati dagli script C++ del progetto ScriptDev2.

2.2 Esempio di analisi

Per fare un esempio di analisi del contenuto del database prendiamo l'e-sempio della quest "All Hell Breaks Loose" che un giocatore può arontare.Innanzitutto per scoprire i dettagli della quest è possibile consultare le suecaratteristiche e scoprire il suo codice identicativo in uno dei vari portalionline che raccolgono tutti i dati degli elementi del gioco. Nel nostro casouseremo il portale WoWHead9. Dal portale possiamo risalire all'identicati-vo della quest 14093 che dovremo cercare nella tabella quest_template.

8Nell'espansione di gioco considerata ci sono circa 10565 quest disponibili perentrambe le fazioni. Un personaggio di una fazione avrà quindi a disposizione cir-ca più di 5000 quest da poter svolgere. La fonte di questi dati è stato il collega-mento http://www.wowhead.com/quests?lter=minrl=1;maxrl=85 del portale dedicatoWoWHead visitato in data 14/03/2015

9Informazioni disponibili nel collegamento http://www.wowhead.com/quest=14093/all-hell-breaks-loose in data 13/03/2015

2.2 Esempio di analisi 27

Possiamo quindi costruire una query per cercare nella tabella delle quest ilcodice trovato:

1 SELECT entry, requiredClasses, requiredRaces,2 prevQuestId, nextQuestId, reqItemId1,3 reqItemCount1, ReqCreatureOrGOId1, ReqCreatureOrGOCount14 FROM quest_template WHERE entry = 14093;

Il risultato sarà il seguente:Colonna Valoreentry 14093requiredClasses 0requiredRaces 2097152prevQuestId 14091nextQuestId 14099reqItemId1 0reqItemCount1 0ReqCreatureOrGOId1 34884ReqCreatureOrGOCount1 6

Come possiamo notare dai dati estratti, la colonna reqItemId1 è va-lorizzata a 0, quindi per questa quest non ci sono oggetti in relazione dacercare. Diversamente la colonna ReqCreatureOrGOId1 ha un valore. Équindi questo il numero identicativo che dovremo vericare essere coerentecon quanto riportato sul portale WoWHead.

Per procedere con l'analisi si possono intraprendere due dierenti stradeche portano al medesimo risultato:

1. Verichiamo sul portale WoWHead il codice trovato a quale creaturacorrisponde, oppure nel dettaglio della quest sempre sul portale Wo-WHead verichiamo che la creatura associata abbia il codice trovatonella nostra tabella.

2. Verichiamo nel database il codice che abbiamo ottenuto a quale crea-tura o gameObject appartiene, e successivamente confrontiamo il risul-tato con quanto riportato sul portale WoWHead per la quest in oggettodi analisi.

Se intraprendiamo la prima strada verichiamo velocemente che il valoredella colonna corrisponde con il codice della creatura indicata sul portaleWoWHead.

2.2 Esempio di analisi 28

Provando a percorrere anche la seconda strada dovremo cercare nella co-lonna entry della tabella creature_template oppure della tabella game-object_template il valore 34884.

1 SELECT entry, name2 FROM gameobject_template WHERE entry = 34884;

Il risultato sarà il seguente:Colonna Valoreentry NULLname NULL

1 SELECT entry, name2 FROM creature_template WHERE entry = 34884;

Il risultato sarà il seguente:Colonna Valoreentry 34884name Rampaging Worgen

Dai risultati ottenuti abbiamo scoperto che il valore della colonna Req-CreatureOrGOId1 fa riferimento ad una creatura. Vericando ora il nomedella creatura e il suo codice sul portale WoWHead relativamente alla questin analisi avremo la conferma della correttezza dei dati.

Oltre a vericare il valore della colonna ReqCreatureOrGOId1 pos-siamo constatare che anche la colonna ReqCreatureOrGOCount1 è valo-rizzata correttamente con il valore 6 come richiesto dalla quest presente sulportale WoWHead. Con questi controlli abbiamo appurato che la quest "AllHell Breaks Loose"10 è correttamente codicata nel database. I dati presentinei portali si suppone siano corretti, in quanto inseriti e vericati da milionidi utenti che li consultano per progredire nella loro esperienza di gioco.

10Informazioni disponibili nel collegamento http://www.wowhead.com/quest=14093/all-hell-breaks-loose in data 13/03/2015

Capitolo 3

Struttura dell'emulatore

In questa sezione si andranno a presentare l'ambiente dove l'emulatore è statoinstallato e i componenti principali del progetto. Per una breve descrizionedei principali termini utilizzati si rimanda al glossario.

3.1 Ambiente Server

L'emulatore è sviluppato interamente in linguaggio C++ e, per sua natu-ra, può essere compilato ed eseguito su qualsiasi piattaforma per cui esistaun compilatore. Gli sviluppatori però si sono focalizzati su due principaliambienti: Microsoft Windows e distribuzioni Linux quali Debian e Ubuntu.

Le principali dierenze nei progetti tra le due piattaforme risiedono nellelibrerie usate per la gestione della memoria, dei thread e di altre risorserelative per lo più al sistema operativo.

Per entrambe le piattaforme sono stati predisposti e pre-congurati i re-lativi ambienti di compilazione: Microsoft Visual Studio dalla versione 2010alla 2013 per l'ambiente Microsoft Windows, e CMake per gli ambienti Linux.

Nella mia sperimentazione ho provato la compilazione e l'esecuzione delprogetto in entrambi gli ambienti, senza riscontrare dierenze nel prodottocompilato e pronto per l'esecuzione. La compilazione in ambiente Windowspuò risultare più intuitiva grazie all'integrazione con un IDE come VisualStudio. Probabilmente però un ambiente di sviluppo così integrato può por-tare a limitazioni nelle congurazioni e personalizzazioni dei parametri dicompilazione che il compilatore CMake invece può avere.

Nelle fasi di implementazione di alcune funzionalità mancanti del giocomi sono orientato su una distribuzione Debian virtualizzata. I vantaggi dellavirtualizzazione si sono rivelati estremamente utili per un progetto di speri-mentazione dove, a volte, si commettono errori o si modicano dati per cui

3.1 Ambiente Server 30

un ripristino della macchina virtuale è più semplice di una re-installazione econgurazione di tutto il sistema.

Sul sito uciale del progetto MaNGOS esistono alcune guide che spieganole operazioni necessarie per il download dei sorgenti e di tutti i componenti,la compilazione, la congurazione di base e il primo avvio del server di gioco.Questa documentazione però non sempre risulta essere adabile per averetutto funzionante al primo tentativo. Esistono infatti alcune situazioni dipen-denti dal sistema operativo e dagli strumenti usati che richiedono interventicorrettivi manuali per arrivare alla soluzione funzionante. Queste correzionispesso sono anche dovute al continuo sviluppo del progetto, e di fronte allacostruzione di nuove strutture e nuovi oggetti la documentazione non sempreviene aggiornata di pari passo.

La postazione ospitante la macchina virtuale è stata un computer con leseguenti caratteristiche:

Figura 3.1: Dettagli del computer host per la macchina virtuale

Per il sistema di virtualizzazione è stato usato il software Hyper-V[9]

3.2 Repository GitHub 31

preinstallato in Windows 8.1 Professional. La preferenza di questo prodottoad altri di uguali caratteristiche è stata fatta per massimizzare le prestazioni.

La distribuzione Linux usata per il server virtualizzato è stata la Debian7.5. La scelta è stata fatta per i seguenti motivi: guide di installazione Linuxmaggiormente orientate a questa distribuzione; Debian è una distribuzioneche ore un giusto compromesso tra libertà di uso degli strumenti shell eun ambiente graco minimale che lascia risorse libere per gli applicativi inesecuzione.

3.2 Repository GitHub

Il servizio GitHub è un repository online dove gli utenti possono deposita-re i propri progetti e usare le potenzialità del sistema Git per gestirli incollaborazione con altre persone.[5]

Il progetto MaNGOS si avvale di questo repository per gestire l'evoluzionee l'implementazione dei suoi cores, oltre a rendere disponibili per gli utentii sorgenti. I contributori al progetto sono di due principali categorie, condierenti privilegi:

• membri sviluppatori: sono utenti che sono stati autorizzati dai gesto-ri della community a sviluppare determinate parti dei cores ed eseguonoliberamente le operazioni di push11.

• utenti sviluppatori: sono utenti generici (anche membri della commu-nity) che non hanno il permesso di eseguire operazioni di push. Possonougualmente contribuire al progetto con le operazioni pull request12.

Nella mia esperienza, non essendo un membro sviluppatore, per le mo-diche che ho apportato al progetto MaNGOS Three ho sempre eettuatodelle operazioni di pull request, sempre accettate.

3.3 Download, compilazione, installazione e pri-

ma congurazione

Per l'analisi e lo sviluppo di alcune parti del server ho usato il progettoMaNGOS Three. Questa scelta è stata fatta per alcuni semplici motivi: ero

11L'operazione di push in un repository corrisponde alla possibilità di upload dei lesorgenti modicati nel repository.

12L'operazione pull request in un repository consiste nel richiedere ai gestori la vericadei le sorgenti modicati e l'importazione nel repository se considerati validi.

3.3 Download, compilazione, installazione e prima congurazione32

già in possesso del client di gioco, da cui devono essere estratti alcuni dati perl'esecuzione del server; per l'ambiente Linux Debian le guide di installazionemenzionavano questo progetto. Tutte le mie analisi, ricerche ed elaborazioniriguarderanno ora il progetto MaNGOS Three (chiamato anche Cataclysm oabbreviato in Cata, nome uciale della terza espansione del gioco).

Dopo aver congurato l'ambiente Debian con tutti i tool necessari perla compilazione e il funzionamento del server MaNGOS (gcc, g++, CMake,MySQL e altri), la prima cosa da fare è stato il download dei sorgenti dalrepository GitHub personale su cui avevo precedentemente eseguito una forkdel progetto MaNGOS Three originale.

Le parti copiate localmente dal repository sono i tre oggetti che compon-gono il server MaNGOS Three: database, server e scripts. Gli oggetti sonostati organizzati in due cartelle: server e database, mentre il progettodegli scripts è una parte aggiuntiva del server, per tanto è stato posizionatoall'interno delle cartelle del server.

Il server sarebbe già pronto per essere compilato. Quindi ho creato unacartella (denominata build) per le istruzioni di compilazione e una cartella(denominata run) in cui sono stati messi i le binari prodotti dalla com-pilazione. Creata la struttura di compilazione con il comando cmake nellacartella build ho eseguito il comando make install per avviare la primacompilazione, dove sono state vericate tutte le dipendenze degli oggetti dacostruire e compilati i sorgenti. Il risultato della compilazione ha prodottonella cartella run le sottocartelle classiche si un applicativo: bin (contenentei le binari o eseguibili), etc (contenente i le di congurazione), include(contenete gli header della libreria ACE) e la cartella lib (contenente lelibrerie compilate di supporto ai le binari).

Prima di poter eseguire il server compilato è necessario aggiungere lacartella data che contiene gli oggetti estratti dal client di gioco. Questioggetti sono:

• Dbc: le che contengono i dati strutturati degli oggetti presenti nelgioco.

• Map: le che contengono le informazioni sulle mappe di gioco.

• Vmap: le che contengono i modelli graci degli oggetti di gioco.

Per estrarre queste informazioni dai le del client ho usato i tool già compilatiper windows in quanto il client è unicamente per questi sistemi operativi(esistono però porting anche per Linux e Mac).

Terminata l'estrazione dei dati e il loro posizionamento nella cartelladeputata ho eseguito lo script di popolamento del database nell'appositacartella.

3.4 Le componenti del server 33

A questo punto, il sistema è pronto per entrare in esecuzione. Il suo funzio-namento si basa su due processi demoni: il reame (mangosd) e l'interfaccia diconnessione (realmd) presenti nella cartella bin. Dopo averli avviati entrambiil server è pronto per ricevere la prima connessione.

3.4 Le componenti del server

Dopo aver analizzato la procedura di download dei sorgenti e compilazione,nella cartella bin si trovano i due eseguibili che compongono il server. Il pri-mo è realmd e il secondo è mangosd. Saranno ora analizzati separatamenteper mostrare il loro funzionamento.

3.4.1 Realmd

Il demone realmd gestisce la fase iniziale di connessione al reame. Questoprocesso che si interpone tra il client e il reame ha la funzione di gestire ireami e le connessioni ad essi.

Un reame è una istanza di un server con caratteristiche ben denite quali:l'espansione di gioco, il rate (o moltiplicatore) per i punti esperienza e per lelogiche probabilistiche del gioco, più le informazioni relative all'indirizzo IPe la porta TCP a cui il reame risponde. Su un server possono coesistere piùreami, ciascuno con le proprie congurazioni, a cui il giocatore può accedere.È quindi compito del processo realmd mostrare all'utente l'elenco dei reamidisponibili fra cui scegliere dopo l'autenticazione.

Questo demone gestisce le credenziali di accesso (account e password) e neverica la correttezza. Se l'autenticazione avviene con successo nel client verràmostrato l'elenco dei reami disponibili fra cui scegliere come, ad esempio,nella gura 3.2 in cui sono disponibili per la scelta due reami.

Un'altra funzionalità di questo processo è quella di vericare che la ver-sione del client sia compatibile con il reame a cui ci si collega. Questo èun prerequisito fondamentale per evitare incongruenze ed errori durante lesessioni di gioco, causate dalle peculiarità speciche di ogni espansione.

Per stabilire i parametri di congurazione di questo demone bisogna veri-care il le realmd.conf nella cartella etc. I parametri fondamentali peril corretto funzionamento sono:

• LoginDatabaseInfo: contiene i riferimenti al database e all'utente dausare per la connessione al database separati da ; nel seguente ordi-ne: IP;porta;username;password;schema. Di default ha questo valore:"127.0.0.1;3306;mangos;mangos;realmd".

3.4 Le componenti del server 34

Figura 3.2: Visualizzazione elenco di selezione del reame

• RealmServerPort: contiene il riferimento alla porta TCP su cui ilprocesso sarà in ascolto di connessioni. Di default il valore è impostatoa 3724.

• BindIP: contiene il riferimento all'indirizzo IP su cui il processo potràricevere le connessioni. Di default il valore è 0.0.0.0 in modo da poterricevere connessioni da qualsiasi fonte interna o esterna al server.

• LogFile: contiene il riferimento al le di log che il processo produce. Didefault il valore è Realmd.log ma, se lasciato vuoto, vengono disattivatii log su le.

I log prodotti da questo demone non contengono dati rilevanti, se non incaso di eccezioni o errori.

3.4.2 Mangosd

Il demone mangosd gestisce tutte le connessioni con il client. È il cuore ditutte le meccaniche di gioco, delle interazioni tra gli elementi del gioco etra i giocatori stessi. Questo processo è quindi il reame a cui i giocatori si

3.4 Le componenti del server 35

collegano per le loro sessioni di gioco dopo essere passati dall'interfaccia digestione dei reami.

Per rendere tutto questo funzionante nel modo più eciente possibile ilprocesso, all'avvio, esegue una lettura dei dati statici dal database (legge tut-te le informazioni presenti nello schema mangosd del database) e conservain memoria tutti i dati. Risulta quindi importante che il sistema operati-vo disponga di un suciente quantitativo di memoria RAM disponibile perquesto applicativo. Questa strategia di gestione dei dati statici è molto vin-cente per garantire la risposta del reame alle richieste del client in temporeale. L'utilizzo costante di connessioni al database per leggere gli elementidi gioco statici per ogni personaggio connesso incerebbe notevolmente leprestazioni all'aumentare delle connessioni. L'utilizzo dei dati memorizzatiall'interno della memoria del processo favorisce la velocità di risposta ancheal crescere del numero di connessioni. Indicativamente, dai dettagli del ledi congurazione, il limite di default di connessioni che il reame può ricevereè 1024, che risulta essere un numero piuttosto elevato. Durante l'analisi delreame non è stato possibile ricreare un numero di connessioni elevato e, pertanto, non è stato possibile vericare la variazione di prestazioni con datisignicativi.

Per rendere una idea maggiore di cosa comporti l'avvio del reame sono ri-portate nelle gure 3.3 e 3.4 le informazioni sulle risorse occupate nel sistemaoperativo.

Terminato quindi il caricamento di tutti gli oggetti il reame è prontoper ricevere le connessioni che il processo realmd gli passerà quando ungiocatore si collega.

Durante il caricamento, la console di esecuzione e anche il le di logvengono popolati con tutti gli stati di avanzamento e gli eventuali erroridi controllo dei dati letti che si possono presentare. Ai dati che sono lettidal database vengono applicate delle logiche di controllo per vericarne laconsistenza e coerenza, in modo da non caricare informazioni che potrebberodestabilizzare il funzionamento del reame. Tutte le anomalie sono quindisegnalate e riportate nel le di log anché possano essere valutate e corrette.

Terminato il caricamento, prima di ricevere una qualsiasi connessione, ilreame è un processo apparentemente fermo. Il suo output in console non ri-porta nulla di rilevante come anche il log. Non appena riceve una connessione,invece, si attivano tutte le chiamate al database per recuperare le informa-zioni sul giocatore e sul personaggio in uso, per poi attivare i meccanismi dipopolamento della mappa di gioco in cui il personaggio si trova.

Per rendere scalabile e performante il reame la mappa di gioco di tutto ilmondo è suddivisa in tre livelli. La mappa, la zona e l'area.

3.4 Le componenti del server 36

Figura 3.3: Graco uso risorse in fase di avvio

Figura 3.4: Elenco dei processi attivi e utilizzo memoria

3.4 Le componenti del server 37

• La mappa è banalmente associabile al concetto di continente. Il mon-do è suddiviso in continenti (che variano di numero a seconda dell'e-spansione di gioco del reame) e ciascun continente è una mappa digioco.

• La zona è una regione di un continente.

• L'area è una porzione ristretta della zona.

Con questi tre livelli tutto l'ambiente di gioco è suddiviso in piccole areee, quando un giocatore si collega, il personaggio sarà all'interno di una diqueste aree. Il reame attiva gli eventi relativi agli elementi di gioco (NPC,mostri, oggetti) che sono all'interno dell'area in cui il personaggio si trova,e trasmette queste informazioni al client che visualizza gli elementi animati(dal reame) nel gioco. Questa operazione di animazione degli elementi digioco appartenenti ad una specica area viene fatta per ciascun giocatoreconnesso. Quando un giocatore si sposta da un'area ad un'altra vengonoterminate le azioni degli elementi dell'area abbandonata e contestualmenteavviati gli eventi della nuova area di gioco. Essendo tutto nella memoria delprocesso del reame, quando due giocatori si trovano nella medesima areagli elementi animati sono condivisi, permettendo un risparmio di risorse, econsentendo anche l'interazione tra i giocatori.

Oltre a questi livelli di suddivisione, ogni area possiede delle coordinategeograche (coordinate in ascisse e ordinate di un piano cartesiano) con cuiidenticare con esattezza la posizione di ogni elemento e i movimenti deipersonaggi. Queste coordinate geograche sono anche presenti nelle tabelledel database che contengono i riferimenti alle posizioni degli elementi di gioco.In questo modo il reame sa dove devono essere visualizzati gli elementi digioco nel client.

Nelle gure 3.5, 3.6, 3.7 e 3.8 sono riportate alcune immagini che esempli-cano i tre livelli di suddivisione del mondo di gioco e il sistema di coordinatenell'area dove si trova il personaggio.

Analizzando i log del server sono riportati i riferimenti ai cambi di area.

1 32 GameObjects, 78 Creatures, and 0 Corpses/Bones loaded forgrid 1481 on map 530

2 Grid[23,8] on map 530 moved to IDLE state3 Grid[23,9] on map 530 moved to IDLE state4 WORLD: Received opcode CMSG_ZONEUPDATE: newzone is 3524

Come è possibile notare nel log e nell'immagine, oltre ai concetti dimappa, area e zona sono presenti anche altri sottolivelli usati dal sistemae trasparenti per l'utente:

3.4 Le componenti del server 38

Figura 3.5: Immagine del mondo

Figura 3.6: Immagine di un continente

3.4 Le componenti del server 39

Figura 3.7: Immagine di una regione

Figura 3.8: Immagine dei dati dettagliati sulla posizione del giocatore

• griglia: è una ulteriore suddivisione della zona.

• cella: è l'ultima suddivisione in cui una griglia è ripartita.

Questa suddivisione in parti molto piccole del mondo di gioco risulta

3.4 Le componenti del server 40

molto eciente in quanto i movimenti dei giocatori avvengono a velocitàcostanti. Inoltre, il caricamento degli oggetti di gioco, avviene solo in funzionedi un cambio di griglia. Essendo le griglie piccole, gli oggetti di gioco dacaricare sono limitati,mantenendo un buon rapporto tra funzionalità del giocoe performance (ovvero, tempi di risposta).

La comunicazione tramite OPCODE

La comunicazione tra client e reame avviene tramite pacchetti di rete co-struiti con determinati codici identicativi dell'operazione richiesta chiamatiOPCODE. Questi pacchetti di rete contengono le informazioni che il reameo il client richiedono di volta in volta e dipendono delle azioni che il perso-naggio compie nell'ambiente di gioco. Esistono diverse decine di OPCODEcodicati e la classe C++ in cui sono censiti e gestiti è Opcodes.cpp si-tuata nella cartella src/game della directory che contenente i sorgenti delprogetto server.

Guardando nel le di log è possibile trovare vari OPCODE che server eclient si sono scambiati durante una sessione di gioco:

1 WORLD: CMSG_CREATURE_QUERY ’Alliance Axeman’ - Entry: 17244.2 WORLD: Sent SMSG_CREATURE_QUERY_RESPONSE3 WORLD: CMSG_CREATURE_QUERY ’Alliance Logger’ - Entry: 17247.4 WORLD: Sent SMSG_CREATURE_QUERY_RESPONSE5 WORLD: CMSG_CREATURE_QUERY ’Rat’ - Entry: 4075.6 WORLD: Sent SMSG_CREATURE_QUERY_RESPONSE7 WORLD: CMSG_CREATURE_QUERY ’Chicken’ - Entry: 620.8 WORLD: Sent SMSG_CREATURE_QUERY_RESPONSE9 WORLD: CMSG_CREATURE_QUERY ’Stormwind Marine’ - Entry: 20556.10 WORLD: Sent SMSG_CREATURE_QUERY_RESPONSE11 PLAYER: Player 1 discovered a new area: 357312 WORLD: CMSG_CREATURE_QUERY ’Admiral Odesyus’ - Entry: 17240.13 WORLD: Sent SMSG_CREATURE_QUERY_RESPONSE14 WORLD: CMSG_CREATURE_QUERY ’Archaeologist Adamant Ironheart’

- Entry: 17242.15 WORLD: Sent SMSG_CREATURE_QUERY_RESPONSE16 WORLD: CMSG_CREATURE_QUERY ’Priestess Kyleen Il’dinare’-

Entry: 17241.17 WORLD: Sent SMSG_CREATURE_QUERY_RESPONSE18 WORLD: CMSG_CREATURE_QUERY ’Pack Mule’ - Entry: 16225.19 WORLD: Sent SMSG_CREATURE_QUERY_RESPONSE20 WORLD: CMSG_GAMEOBJECT_QUERY ’Campfire’ - Entry: 181712.21 WORLD: Sent SMSG_GAMEOBJECT_QUERY_RESPONSE22 WORLD: CMSG_GAMEOBJECT_QUERY ’Campfire’ - Entry: 1870.23 WORLD: Sent SMSG_GAMEOBJECT_QUERY_RESPONSE

3.4 Le componenti del server 41

24 WORLD: Received opcode CMSG_QUESTGIVER_STATUS_QUERY - forPlayer Corsol (Guid: 1) to Creature (Entry: 17240 Guid:68995)

25 WORLD: Sent SMSG_QUESTGIVER_STATUS for Creature (Entry: 17240Guid: 68995)

26 WORLD: Received opcode CMSG_QUESTGIVER_STATUS_QUERY - forPlayer Corsol (Guid: 1) to Creature (Entry: 17242 Guid:68994)

27 WORLD: Sent SMSG_QUESTGIVER_STATUS for Creature (Entry: 17242Guid: 68994)

28 WORLD: Received opcode CMSG_QUESTGIVER_STATUS_QUERY - forPlayer Corsol (Guid: 1) to Creature (Entry: 17241 Guid:67018)

29 WORLD: Sent SMSG_QUESTGIVER_STATUS for Creature (Entry: 17241Guid: 67018)

30 WORLD: Received opcode CMSG_ZONEUPDATE: newzone is 352431 STORAGE: DestroyZoneLimitedItem in map 530 and area 3524

Nella porzione di log riportato è visibile lo scambio di informazioni traclient e server tramite OPCODE per popolare l'area visualizzata dal perso-naggio con gli elementi di gioco in essa contenuti. Nello scambio di OPCODEè anche visibile l'uso dei codici identicativi degli elementi di gioco (entry) egli identicativi univoci dei singoli oggetti (guid).

Nelle gure 3.9 e 3.10 sono ragurati il usso dei pacchetti di rete scam-biati tra client e reame (in azzurro ciò che il client ha mandato al reame e inrosso ciò che il reame ha mandato al client) ed i dettagli del protocollo TC-P/IP di un pacchetto di rete. Come si può notare il contenuto dei pacchettiè in formato binario e quindi non è interpretabile direttamente.

Per capire meglio come vengono costruiti dal server i pacchetti di dativediamo una porzione di codice in cui il client ha richiesto al reame il tempo digioco del personaggio, e il reame risponde componendo l'apposito pacchettobinario e lo rimanda in risposta.

1 void WorldSession::HandlePlayedTime(WorldPacket& recv_data)2 3 uint8 unk1;4 recv_data >> unk1;56 WorldPacket data(SMSG_PLAYED_TIME, 4 + 4 + 1);7 data << uint32(_player->GetTotalPlayedTime());8 data << uint32(_player->GetLevelPlayedTime());9 data << uint8(unk1);10 SendPacket(&data);11

3.4 Le componenti del server 42

Figura 3.9: Ricostruzione parziale del usso dei pacchetti di rete

Figura 3.10: Dettagli TCP e IP di un pacchetto di rete

3.4 Le componenti del server 43

Per mantenere la connessione tra reame e client sempre attiva e stabilireanche i parametri di velocità della connessione stessa esiste un OPCODE cheil client invia costantemente al reame per vericare la sua attività e la latenzadella connessione.

1 WORLD: Received opcode CMSG_TIME_SYNC_RESP: counter 3,clientticks 248165080, time since last sync 10062

2 WORLD: Opcode CMSG_TIME_SYNC_RESP -- Our ticks: 248165132,diff 52, latency 131

3 WORLD: Received opcode CMSG_TIME_SYNC_RESP: counter 4, clientticks 248175169, time since last sync 10089

4 WORLD: Opcode CMSG_TIME_SYNC_RESP -- Our ticks: 248175221,diff 52, latency 131

5 WORLD: Received opcode CMSG_TIME_SYNC_RESP: counter 5, clientticks 248185169, time since last sync 10000

6 WORLD: Opcode CMSG_TIME_SYNC_RESP -- Our ticks: 248185222,diff 53, latency 131

Come riportato dalla sequenza estratta dal le di log si può notare ilcostante invio da parte del client ogni 10 secondi di un OPCODE di sincro-nizzazione e verica della latenza.

Oltre alle funzioni di gestione delle connessioni ai client la shell doveviene eseguito l'oggetto realmd può svolgere funzioni di console per il reame.Questa interfaccia ha dei suoi comandi costruiti per gestire i personaggi deigiocatori e altre funzioni di manutenzione del reame. Alcuni comandi, peresempio, sono:

• account create: con l'aggiunta dei parametri username e password,consente la creazione di un nuovo account per il reame corrente.

• reload all_item: consente il caricamento di tutti gli oggetti di gioco.Può servire nel caso di aggiornamento sui dati nel database ed evitare didover riavviare il reame per rendere disponibili ai giocatori le modicheapportate.

• server info: visualizza le informazioni sulla versione del server e sulnumero di giocatori connessi.

• server restart: serve per riavviare il reame dopo un intervallo di tempo(in secondi) impostato. Questi comandi sono anche invocabili nel clientdurante una sessione di gioco per quei giocatori che sono autorizzati.

Per stabilire i parametri di congurazione di questo eseguibile bisognavericare il le mangosd.conf nella cartella etc. I parametri fondamentaliper il corretto funzionamento sono:

3.5 I le DBC 44

• RealmID: stabilisce a qual'è l'id codicato nel database di questoreame.

• DataDir: contiene il percorso assoluto della cartella in cui sono con-tenuti i le .dbc, .map e .vmap con i dati estratti dal client che ilreame consulterà durante la sua esecuzione.

• LoginDatabaseInfo: stabilisce le informazioni di connessione al da-tabase per lo schema relativo alle informazioni di login dell'account. Ilvalore di default è 127.0.0.1;3306;mangos;mangos;realmd

• WorldDatabaseInfo: stabilisce le informazioni di connessione al da-tabase per lo schema relativo alle informazioni degli elementi statici digioco. Il valore di default è 127.0.0.1;3306;mangos;mangos;mangos

• CharacterDatabaseInfo: stabilisce le informazioni di connessione aldatabase per lo schema relativo alle informazioni dei personaggi di ogniaccount. Il valore di default è 127.0.0.1;3306;mangos;mangos;characters

• WorldServerPort: contiene il riferimento alla porta TCP su cui ilprocesso resterà in ascolto delle connessioni dei client. Di default ilvalore è 8085, ma è fondamentale modicarlo quando sul medesimoserver vengono eseguite più istanze di reami.

• BindIP: contiene il riferimento all'indirizzo IP su cui il processo potràricevere le connessioni. Di default il valore è 0.0.0.0 in modo da poterricevere connessioni da qualsiasi fonte interna o esterna al server.

Oltre a queste impostazioni, questo le contiene anche tutti i parametri perpersonalizzare il comportamento del reame nella gestione di vari aspetti digioco. Il le contiene anche le descrizioni dei singoli parametri con i relativivalori di default (o congurati) per personalizzare il reame a proprio uso econsumo.

3.5 I le DBC

I le DBC sono le binari estratti dal client del gioco che contengono informa-zioni strutturate riguardanti alcuni elementi del gioco stesso. Essendo questeinformazioni statiche e già presenti nel client, non vengono riportate anchenel database del server, ma i le devono essere posizionati in una cartellaspecica in cui il reame possa andare a recuperare queste informazioni.

3.5 I le DBC 45

L'uso di questi le archivio risulta fondamentale per minimizzare le infor-mazioni da veicolare nella comunicazione tra client e server come accennatonel capitolo 1.2.4. La caratteristica fondamentale di questi le archivio è lastaticità dei dati: essendo estratti direttamente dal client e non essendo ilclient soggetto a modiche (se non cambiando espansione di gioco, per cuiè necessario cambiare anche il reame), questa peculiarità è garantita. Anchequeste informazioni sono caricate dal reame in fase di avvio. Quando un og-getto di gioco, le cui informazioni provengono da un le DBC, viene attivato,il reame invia al client unicamente il codice identicativo (presente nel learchivio) dell'oggetto di gioco, lasciando al client la lettura di tutte le altrecaratteristiche dai suoi dati locali.

Come accennato nel primo capitolo con il tool MyDBCExplorer è possi-bile visualizzare il contenuto di questi le-archivio. Uno fra i più importantidi questi le è Spell.dbc.

Figura 3.11: Visualizzazione contenuto le Spell.dbc

Come è possibile vedere dalla gura 3.11, il le contiene i dati con valorinumerici (sono pochi i valori testuali). Per poter sapere il signicato deivalori nelle colonne è possibile sfruttare le informazioni presenti nel le .cpp

3.5 I le DBC 46

che svolge le funzioni di interfaccia di lettura dei dati per il reame, dovesono commentati e spiegate in parte le colonne. Ecco quindi l'estratto dal leDBCStructure.h:

1 // Spell.dbc2 struct MANGOS_DLL_SPEC SpellEntry3 4 uint32 Id; // 0 m_ID5 uint32 Attributes; // 1 m_attribute6 uint32 AttributesEx; // 2 m_attributesEx7 uint32 AttributesEx2;// 3 m_attributesExB8 uint32 AttributesEx3;// 4 m_attributesExC9 uint32 AttributesEx4;// 5 m_attributesExD10 uint32 AttributesEx5;// 6 m_attributesExE11 uint32 AttributesEx6;// 7 m_attributesExF12 uint32 AttributesEx7;// 8 m_attributesExG13 uint32 AttributesEx8;// 9 m_attributesExH14 uint32 AttributesEx9;// 10 m_attributesExI15 uint32 AttributesEx10;// 11 m_attributesExJ16 uint32 CastingTimeIndex;// 12 m_castingTimeIndex17 uint32 DurationIndex;// 13 m_durationIndex18 uint32 powerType; // 14 m_powerType19 uint32 rangeIndex; // 15 m_rangeIndex20 float speed; // 16 m_speed21 uint32 SpellVisual[2];// 17-18 m_spellVisualID22 uint32 SpellIconID; // 19 m_spellIconID23 uint32 activeIconID; // 20 m_activeIconID24 DBCString SpellName; // 21 m_name_lang25 DBCString Rank; // 22 m_nameSubtext_lang26 //DBCString Description;// 23 m_description_lang not

used27 //DBCString ToolTip;28 // 24 m_auraDescription_lang not used29 uint32 SchoolMask; // 25 m_schoolMask30 uint32 runeCostID; // 26 m_runeCostID31 //uint32 spellMissileID;// 27 m_spellMissileID not

used32 //uint32 spellDescriptionVariableID;33 // 28 m_spellDescriptionVariableID, 3.2.034 uint32 SpellDifficultyId; // 29 m_spellDifficultyID35 - id from SpellDifficulty.dbc36 //float unk_f1; // 3037 uint32 SpellScalingId; // 31 SpellScaling.dbc38 uint32 SpellAuraOptionsId;39 // 32 SpellAuraOptions.dbc40 uint32 SpellAuraRestrictionsId;41 // 33 SpellAuraRestrictions.dbc42 uint32 SpellCastingRequirementsId;43 // 34 SpellCastingRequirements.dbc

3.5 I le DBC 47

44 uint32 SpellCategoriesId; // 35 SpellCategories.dbc45 uint32 SpellClassOptionsId; // 36 SpellClassOptions.dbc46 uint32 SpellCooldownsId; // 37 SpellCooldowns.dbc47 //uint32 unkIndex7; // 38 all zeros...48 uint32 SpellEquippedItemsId; // 39 SpellEquippedItems.dbc49 uint32 SpellInterruptsId; // 40 SpellInterrupts.dbc50 uint32 SpellLevelsId; // 41 SpellLevels.dbc51 uint32 SpellPowerId; // 42 SpellPower.dbc52 uint32 SpellReagentsId; // 43 SpellReagents.dbc53 uint32 SpellShapeshiftId; // 44 SpellShapeshift.dbc54 uint32 SpellTargetRestrictionsId;55 // 45 SpellTargetRestrictions.dbc56 uint32 SpellTotemsId; // 46 SpellTotems.dbc57 //uint32 ResearchProject; // 47 ResearchProject.dbc

Come è possibile notare nel le .cpp alcune colonne descrittive del le-archivio DBC sono commentate. Questo indica che queste colonne apparten-gono a precedenti espansioni e nella corrente non sono più in uso o sono staterimpiazzate da nuove informazioni più esaustive.

Capitolo 4

Implementazioni

In questo capitolo saranno mostrati i processi di verica dei bug di gioco con lerelative analisi e ricerche per costruire il codice o i dati nel database anché ilproblema sia risolto. Per una breve descrizione dei principali termini utilizzatisi rimanda al glossario.

4.1 Tipologie di implementazione

Il lavoro svolto si è concentrato sulla corretta implementazione delle inte-razioni tra i vari oggetti di gioco. Non si sono invece considerate modichestrutturali dell'architettura del videogioco, o sui servizi di base quali la gra-ca ed la simulazione 3D, in quanto queste sono di fatto attribuite in esclusivaad alcuni specici membri della community, in possesso non solo delle ade-guate conoscenze tecniche, ma soprattutto della reputazione necessaria perfare accettare le modiche proposte dalla community stessa.

4.2 Modalità di implementazione

L'implementazione (o anche in gergo scripting) degli elementi di gioco di unreame (le funzioni basilari del reame che sono implementate esclusivamentein linguaggio C++) può essere fatto in tre modi distinti. Queste tre tipologiedi scripting, oltre ad essere complementari, possono anche essere usate inmodo ibrido, ovvero ottenere le funzionalità volute per un elemento di giocomescolando parti di Database script con le C++ di ScriptDev2, in base allacomplessità delle funzionalità da implementare.

4.2 Modalità di implementazione 49

4.2.1 Database script

Questa tipologia di scripting si basa unicamente su alcune tabelle presen-ti nello schema mangos che consentono di codicare azioni aggiuntive pergli elementi del gioco. Queste azioni verranno poi eseguite direttamente dalreame che è già in grado di interpretare (ovvero decodicare ed esegui-re) questi script aggiuntivi. Alcune delle tabelle coinvolte in questa tipo-logia di scripting sono: creature_ai_scripts, creature_ai_texts,dbscripts_on_go_template_use, dbscripts_on_spell. Per que-sta tipologia di scripting è suciente conoscere le strutture dati del databasee la logica di funzionamento e interazione degli elementi del gioco. Dopo averinserito le informazioni nel database sarà suciente riavviare il reame perrenderle operative.

4.2.2 C++ in ScriptDev2

In questo secondo caso, per implementare una modica occorre scrivere por-zioni di codice C++ da integrare con il codice esistente, che poi dovrà esserericompilato: è quindi chiaro che siamo in presenza di un "abuso" del termi-ne scripting. All'interno della community si parla comunque di scripting inquanto il codice C++ che viene aggiunto usa pesantemente i servizi forni-ti dalla libreria ScriptDev2 ; in pratica, è come se le funzioni fornite dallalibreria denissero un linguaggio di livello più alto rispetto al C++.[2]

Come appena descritto, questa tipologia di scripting prevede la scritturadi codice in C++ nel progetto ScriptDev2 in abbinamento ad alcune informa-zioni salvate nell'omonimo schema del database. Anché questa metodologiadi scripting sia usata dal reame, sarà necessario compilare il progetto e il rea-me per avere l'integrazione nel sistema di gioco. Per poter costruire gli scriptC++ è necessaria la conoscenza delle basi di programmazione C++ ad ogget-ti più un minimo di logica di funzionamento e interazione degli elementi delgioco ottenibile, quest'ultima, dall'analisi del database e tramite l'esperienzadiretta di gioco.[8]

Anché lo script realizzato nella libreria venga interpretato dal reame ènecessario specicare nella colonna ScriptName presente in tutte le tabelle"template" dei principali elementi del gioco (es: creature_template, gameob-ject_template, ecc...) il nome usato nella denizione della classe C++ imple-mentante le funzionalità nel progetto ScriptDev2 13. Con questa associazionelogica l'oggetto di gioco implementato userà le direttive costruite in C++per eseguire quanto programmato.

13Nel capitolo 4.3.2 sarà presentato un esempio di implementazione che chiariràmaggiormente il legame tra elementi di gioco nel database e gli script in ScriptDev2

4.3 Ricerca e risoluzione 50

Non è stato possibile trovare ulteriori informazioni su questo progetto inquanto il portale http://www.scriptdev2.com/ con tutte i dati di sviluppo èrisultato essere chiuso, per tutto il periodo di analisi, in seguito ad un attaccohacker che ne ha violato i contenuti. Per garantire comunque la continuitàdel progetto e la disponibilità dei sorgenti, le informazioni sul repositoryGitHub14 sono state mantenute attive, ma prive di documentazione rilevante.

4.2.3 Lua script

Questa tipologia di scripting è di recente introduzione nel progetto MaNGOSe per ora è applicabile unicamente alla versione base del gioco (MaNGOS Ze-ro). Questo metodo prevede un motore (chiamato ELUNA) integrato nellefunzionalità di base del reame che interpreta degli script esterni scritti in lin-guaggio Lua. Diversamente rispetto al caso precedente questi script possonoessere aggiunti anche "a caldo" ovvero durante l'esecuzione del reame e nonrichiedono nessun intervento di compilazione come i veri linguaggi di scrip-ting. Il motore ELUNA legge, interpreta ed esegue gli script ogni volta cheun oggetto di gioco per cui sono stati progettati viene animato dal reame.

Il videogioco World of WarcraftTM ha molte delle sue funzionalità costrui-te con LUA script, non è quindi un caso che anche questo emulatore abbiaintegrato un motore per questo linguaggio di programmazione. Questo moto-re rende disponibili alcune oggetti di base che lo sviluppatore può usare perfar interagire il proprio script con il reame e ottenere le animazioni volute.

Il linguaggio LUA è un linguaggio che combina la semplicità della sintassiprocedurale con costrutti basi di tipo array associativi. La tipizzazione dellevariabili e degli oggetti è dinamica e il codice sorgente è processato da un in-terprete in una macchina virtuale (in parte similare a JavaTM). I suo punti diforza sono la velocità di esecuzione, la portabilità e la facilità di integrazionecon ambienti sviluppati in altri linguaggi.[1]

4.3 Ricerca e risoluzione

Nell'analisi del reame ho potuto vericare che esistono due categorie princi-pali di errori:

• errori nelle funzioni basilari: le funzioni basilari del reame possonopresentare, a loro volta, due tipologie di errori:

logici: questi errori derivano da interpretazioni non corrette dellalogica di funzionamento delle funzionalità di base da parte degli

14Informazioni disponibili all'indirizzo https://github.com/scriptdev2

4.3 Ricerca e risoluzione 51

sviluppatori che si traducono in un comportamento del reame di-verso da quanto aspettato da parte dei giocatori durante le sessionidi gioco (ad esempio un incantesimo che non ha eetti sul bersa-glio, oppure una abilità di un personaggio che ha eetti diversi daquelli attesi, ecc...).

implementativi: questi errori sono caratterizzati dall'assenza diimplementazioni per la logica di gioco. Il giocatore ne ha eviden-za quando una funzione del gioco risulta non attiva. Nel reamequesti bug sono spesso individuabili nei log quando è presente unOPCODE (descritto nel capitolo precedente) segnalato come sco-nosciuto oppure le funzioni sono solo denite nel codice C++ manon implementate (ad esempio l'incapacità di un personaggio dieseguire una metamorfosi, oppure l'impossibilità di volare nellearee di gioco dove consentito, ecc...).

• errori negli elementi di gioco: derivano da informazioni assenti neldatabase e non codicate nelle librerie esterne (ScriptDev2 o ELUNA).L'interazione con essi risulta quindi limitata o impossibile (ad esempioun NPC senza azioni, un oggetto non usabile, ecc...).

L'obiettivo primario di ogni reame è quello di evitare un crash del sistema,con conseguente disconnessione degli utenti e la necessità di un riavvio ma-nuale del reame. Per questo motivo si preferisce avere bug silenti, che limitinol'esperienza di gioco unicamente al loro scopo d'uso e non abbiano eetto sututto il resto del reame. In questo modo il giocatore potrà proseguire la suasessione di gioco con altre attività che non prevedano l'uso della funzionalitàmancante o errata.

Questa strategia ha il vantaggio di rendere più stabile l'esecuzione delreame, ma lo svantaggio di complicare l'identicazione degli errori, special-mente quelli relativi alle funzionalità basilari. Se per gli elementi di gioco leinformazioni sulle loro caratteristiche abbondano nei portali dedicati, per lefunzionalità di base invece le informazioni sono più carenti e necessitano dimaggior interpretazione e verica. Il metodo migliore per poter identica-re i bug e vericare la correttezza delle implementazioni resta soltanto uno:giocare.

Il modo migliore per farlo sarebbe tramite il confronto delle dierenze trauna sessione di gioco su un server uciale e quella sul reame in costruzione,per vericare che le implementazioni realizzate rispecchino il più possibileil comportamento del gioco uciale. Per percorrere questa metodologia diverica è però necessario abbonarsi al servizio a pagamento mensile dellasoftware house che gestisce e sviluppa il gioco. In alternativa è possibile fare

4.3 Ricerca e risoluzione 52

confronti con le altre realtà non uciali presenti in rete che orono un accessogratuito al gioco, tenendo in considerazione che anche queste realtà usanoreami in via di sviluppo e quindi non pienamente funzionanti o con libereinterpretazioni delle logiche di gioco dierenti da quelle uciali.

Date le limitate disponibilità di documentazione ho limitato la mia ri-cerca e correzione degli errori agli elementi di gioco, trascurando le funzionibasilari del reame. Di seguito saranno illustrate alcune delle fasi di ricerca erisoluzione di bug, con approcci sia di Database Scripting che con soluzioniin ScriptDev2.

Per la ricerca ho scelto appositamente un'area di gioco che sapevo aves-se evidenti problemi e nei paragra seguenti saranno presentate alcune dellemodalità di controllo degli errori, la verica del comportamento atteso tra-mite i portali dedicati, la ricerca delle informazioni mancanti nel database ela correzione apportata per ottenere il risultato corretto.

4.3.1 Errore di cambio fase

Durante una delle prime sessioni di gioco volte ad identicare i problemi, hosubito riscontrato un errore di cambio di fase.

Cambio di fase

Il cambio di fase è una tecnica comunemente usata nei MMORPG che con-sente di visualizzare un zona di gioco in modo dierente ai personaggi chela attraversano. Il suo funzionamento è legato alle informazioni che il reamemanda al client sugli elementi di gioco da visualizzare. Ogni elemento di gio-co appartiene ad una o più fasi e, in base a questa appartenenza, il reameveicola gli elementi di gioco da visualizzare al client.

Ad esempio è possibile accettare una quest da un NPC che è presentein una fase iniziale ma non nella fase successiva. Se la quest prevede che ilpersonaggio subisca un cambio di fase e quindi passi nella fase successiva,l'NPC da cui ha preso la quest non sarà più visibile in quanto il server avràinviato al client le informazioni di reset degli elementi di gioco visualizzati e inuovi elementi di gioco da mostrare in cui l'NPC in questione non è presente.

Pur rimanendo nella stessa area di gioco è quindi possibile visualizzareelementi di gioco e scenari (terreni, strutture, ecc...) dierenti sfruttando lefasi.[12] Inoltre, per avere una conferma anche visiva del risultato atteso, èstato controllato il comportamento delle fasi eettuando una sessione di giocosu un server privato, presentato nel prossimo capitolo.

4.3 Ricerca e risoluzione 53

Individuazione dell'errore

Un errore di cambio fase è stato riscontrato con una la quest "Something'sAmiss". Durante il gioco l'accettazione della quest non attivava il cambio difase e non era quindi possibile trovare l'NPC da cui andare per il completa-mento della quest. Per identicare l'errore, già evidente durante il gioco perla mancanza del NPC nella sua posizione come mostrato dalla gura 4.1, hovericato sul portale WoWHead il funzionamento della quest.

Figura 4.1: Area senza il cambio di fase

Correzione dell'errore

Una possibile modalità di risoluzione del problema del cambio di fase è statarealizzata tramite un intervento di codica degli eventi che attivano le fun-zionalità del reame anché avvenga il cambio di fase all'accettazione dellaquest e rimanga attiva (la nuova fase) quando la quest è stata completata.

Per apportare questa correzione ho eettuato un intervento sul data-base, usando quindi la modalità di Database scripting. La soluzione pote-

4.3 Ricerca e risoluzione 54

va essere codicata anche in C++ usando le funzionalità ScriptDev2, maavrebbe richiesto un sforzo maggiore di programmazione, oltre a risultareprobabilmente meno eciente.

Per risolvere questo problema non ho trovato documentazione specica equindi ho analizzato il database per cercare di scoprire dove fossero le infor-mazioni per gestire il cambio di fase, scoprendo la tabella mangos.phase_-definitions. Trovata la tabella ho cercato nuovamente documentazionesu come valorizzare i dati, senza successo. L'assenza di documentazione inmerito può essere imputata al fatto che questa versione del gioco è sviluppa-ta parallelamente al progetto MaNGOS Zero come già spiegato nei capitoliprecedenti e quindi la documentazione disponibile fa principalmente riferi-mento a progetto Zero dove non esistono le fasi. Le novità introdotte dalleespansioni successive non sono ancora state documentate completamente e,per trovare le risposte, ho alterato le funzionalità basilari del reame relativeal cambio di fase aggiungendo output per la console di gioco e il le di lognel le phaseMgr.cpp che, unite a tante prove, mi hanno consentito di capirela logica di funzionamento delle colonne della tabella:

• zoneID: contiene il codice dell'area di gioco in cui si deve eettuareil cambio di fase. Come abbiamo visto nell'analisi delle zone di gio-co, esiste il comando .gps da eseguire durante una sessione di giocoche ci consente di scoprire il codice della zona per la nostra quest dacorreggere.

• entry: contiene un numero progressivo per la gestione di più cambi difase per la stessa zona se necessario.

• phasemask: contiene il codice della fase di destinazione dopo il cambio.Se si valorizza con il valore della fase corrente non verrà cambiata lafase, diversamente verranno avviate le procedure, dal reame, di cambiofase per mostrare gli oggetti della fase indicata in questa colonna nelclient.

• phaseId: contene un valore che indica al reame di inviare le informa-zioni di cambio fase al client.

• terrainswap: contene un valore che indica al reame di inviare le infor-mazioni di cambio fase al client se non valorizzata la colonna phaseId.

• ags: contiene una combinazione di ag fra i seguenti:

PHASE_FLAG_OVERWRITE_EXISTING: con valore 0x01,indica gli elementi di gioco della nuova fase sostituiranno quellidella fase precedente.

4.3 Ricerca e risoluzione 55

PHASE_FLAG_NO_MORE_PHASES: con valore 0x02,indica che non ci saranno fasi successive a quella corrente.

PHASE_FLAG_NEGATE_PHASE: con valore 0x04, indi-ca che il cambio di fase non potrà avvenire se non aggiungendo ilvalore nella colonna phasemask, consentendo di vedere più fasi incontemporanea.

• condition_id: contiene il codice identicativo della condizione cheattiva il cambio di fase.

• comment: contiene un commento o una descrizione su questo cambiodi fase, utile per la verica o ricerca delle informazioni.

Analizzando le colonne della tabella è possibile notare che la penultimarichiede il riferimento ad una condizione.

Per le condizioni esiste una tabella dedicata conditions documentatanel manuale mangozeros-docs.pdf 15[4] già menzionato nel capitolo di analisidel database. Le condizioni sono delle regole che si attivano al vericarsi dideterminati eventi relativi agli elementi di gioco ad esse associati. Leggendo lespeciche di questa tabella sono state trovate due condizioni che possono sca-tenare il cambio di fase per la quest in oggetto di correzione, in particolare lecondizioni: CONDITION_QUESTTAKEN e CONDITION_QUESTREWARDED.Con la prima è possibile innescare il cambio di fase, mentre con la seconda èpossibile mantenere la nuova fase successivamente.

Le informazioni necessarie in questa tabella sono quindi due: la condizionee l'oggetto scatenante la condizione. La prima informazione la abbiamo appe-na trovata, resta qui da trovare la seconda. Sfruttando il portale WoWHead,come visto nel capitolo dell'analisi del database, è possibile identicare ilcodice entry di una quest che è ciò che ci serve.

Trovate le informazioni necessarie ovvero: quest entry = 14091, CON-DITION_QUESTTAKEN= 9,CONDITION_QUESTREWARDED= 8, id zona = 4755, fase iniziale = 1 e fase successiva = 2, sono stateinserite nel database le due condizioni, una per il cambio fase e una per ilmantenimento della nuova fase e, successivamente, sono stati inseriti i datiper il cambio di fase.

Di seguito il codice SQL per l'aggiunta delle informazioni:

1 INSERT INTO conditions (type, value1, value2) VALUES2 (9, 14091, 2),

15Il documento è consultabile a MaNGOS-Zero docshttps://media.readthedocs.org/pdf/mangoszero-docs/latest/mangoszero-docs.pdfvisionato in data 12/11/2014

4.3 Ricerca e risoluzione 56

3 (8, 14091, 0);45 INSERT INTO phase_definitions (zoneId, entry, phasemask,

phaseId, terrainswapmap, flags, condition_id, comment)VALUES

6 (4755, 1, 2, 1, 0, 1, (7 SELECT condition_entry FROM conditions8 WHERE type = 9 AND value1 = 140919 AND value2 = 0),10 ’Gilneas city entering in second phase’),11 (4755, 2, 2, 1, 0, 2, (12 SELECT condition_entry FROM conditions13 WHERE type = 8 AND value1 = 1409114 AND value2 = 0),15 ’Gilneas city stay in second phase’);

Dopo il riavvio del reame, la prova sul campo ha confermato la correttezzadelle informazioni, come mostrato nella Figura 4.2.

Figura 4.2: Area dopo il corretto cambio di fase

4.3 Ricerca e risoluzione 57

Per contribuire alla documentazione sulla gestione delle fasi, ho pubblica-to nel forum del progetto MaNGOS una mini guida con le spiegazioni sullatabella phase_denitions e come valorizzare i campi usando questa correzionedella quest come esempio. La documentazione pubblicata in data 14 Novem-bre 2014 è raggiungibile al url https://www.getmangos.eu/database/10176-gilneas-starting-zone-phase-change-post73574.html (consultabile soltanto pergli utenti registrati al forum del progetto MaNGOS).

4.3.2 Personaggio senza animazioni

Un altro problema riscontrato durante una sessioni di gioco per identicaregli errori, è stato la mancanza di animazioni e azioni per un NPC.

Azioni e animazioni

Ogni personaggio non giocante NPC ha delle azioni e animazioni che ripeteanche in funzione dell'ambiente che lo circonda. Le azioni e animazioni cheun NPC può compiere sono svariate, le più comuni sono: partecipare a dialo-ghi (in formato testuale o anche audio se codicato), spostarsi seguendo unpercorso prestabilito, attaccare nemici entro un raggio di minaccia (chiamatoanche Aggro) e utilizzare incantesimi (chiamati anche Spell). Queste azionisolitamente sono codicate nel database ma, per alcuni casi, sono necessa-ri gli script esterni del progetto ScriptDev2 per realizzare tutte le azioni eanimazioni.

Individuazione dell'errore

Un personaggio per cui le azioni e animazioni non erano codicate era il NPC"Prince Liam Greymane", (presente nei dettagli della quest relativa alla riso-luzione dell'errore precedente). Dopo il cambio di fase, di cui abbiamo vistola correzione nel paragrafo precedente, l'NPC in oggetto di analisi dovrebbepronunciare delle frasi di incitazione e combattere contro i Worgen16 presentinell'area. Ma ciò non avviene come mostrato in gura 4.3.

Correzione dell'errore

Un esempio di risoluzione problema dell'assenza di azioni e animazioni è statorealizzato modicando il le gilneas_city.cpp del progetto ScriptDev2.

Per implementare un elemento di gioco con uno script in C++ nel pro-getto ScriptDev2 è necessario costruire due strutture dati principali:

16I Worgen sono una razza di creature del gioco molto similari a lupi mannari.

4.3 Ricerca e risoluzione 58

Figura 4.3: NPC "Prince Liam Greymane" senza animazioni e azioni

• Enum: Questa struttura dati è stata usata per organizzare i riferimentidi codici identicanti testi, azioni o altri valori statici.

• Struct: Questa struttura dati contiene gli attributi e i metodi peranimare l'NPC.

Oltre a queste strutture dati, è necessario codicare i testi con gli even-tuali audio nella tabella script_texts del database scriptdev2. Questeinformazioni saranno richiamate tramite i codici identicativi memorizzati inapposite variabili nella struttura dati enum del le cpp.

Per stabilire il corretto comportamento del NPC sono state vericate lesui caratteristiche sul portale WoWWiki (per trovare i testi da visualizzare)e sul portale WoWHead (per trovare gli audio vocali). Inoltre, per avere unaconferma anche visiva del risultato atteso, è stato controllato il comporta-mento del NPC in oggetto di analisi eettuando una sessione di gioco su unserver privato, presentato nel prossimo capitolo.

4.3 Ricerca e risoluzione 59

Trovati i testi che l'NPC deve pronunciare, bisogna codicarli nella tabelladel database con la seguente struttura (documentata sempre nel documentomangoszero-doc.pdf già nominato):

• entry: contiene il codice identicativo del testo. Questo identicativo ècostruito secondo un precisa struttura: -1<codice mappa><contatorea tre cifre decimali>

• content_default: contiene il testo da far pronunciare all'NPC.

• sound: contiene il codice di riferimento per l'audio da riprodurre. Que-sto codice è un riferimento al contenuto del le SoundEntries.dbc.

• type: contiene il codice che stabilisce come il testo verrà mostrato algiocatore. Questo valore è un riferimento al contenuto del le Langua-ges.dbc.

• language: contiene il codice che stabilisce la lingua di gioco con cuiil testo sarà scritto (le lingue di gioco variano in base alle razze deipersonaggi). L'elenco dei possibile valori codicati per questa colonnaè specicato nel documento mangoszero-doc.pdf 17.

• emote: contiene il codice che stabilisce quale animazione l'NPC dovràcompiere quando pronuncia il testo. Questo valore è un riferimento alcontenuto del le Emotes.dbc.

• comment: contiene un commento al testo, spesso utile per sapere inquale script C++ il testo è utilizzato.

Oltre al testo da inserire sono necessarie anche altre informazioni non tut-te di facile deduzione. Le codiche presenti nei le DBC da usare sono tutteabbastanza intuitive ad eccezione dell'audio. Per identicare quest'ultimo èstato usato, oltre al visualizzatore di le DBC già visto, anche lo strumentodi analisi dei l MPQ presentato nel paragrafo 1.3.4 del primo capitolo.

Con lo strumento Ladik’s MPQ Editor è stato aperto il le del client(le archivio .MPQ) contenente gli audio degli NPC e sono state ricercatele voci relative all'NPC "Prince Liam Greymane" trovandone un cospicuoelenco come mostrato in gura 4.4. Fortunatamente i nomi dei le contengonoindizi che consentono di limitarne l'ascolto a poche unità per trovare i testicorretti da associare. Trovati i nomi dei le audio, li ho ricercati all'internodel le SoundEntries.dbc con il programma MyDbcEditor, ricavando ilcodice da usare nella tabella come mostrato in gura 4.5.

4.3 Ricerca e risoluzione 60

Figura 4.4: Ricerca audio per l'NPC "Prince Liam Greymane" nei le MPQdel client

Figura 4.5: Ricerca del codice relativo ai le audio del NPC "Prince LiamGreymane" del le DBC

4.3 Ricerca e risoluzione 61

Ottenute le informazioni necessarie ho potuto popolare la tabella.

1 INSERT INTO script_texts (entry, content_default, sound, type, language, emote, comment) VALUES

2 (-1654004, ’Stand your ground men!’, 19617, 1, 7, 424, ’npc_prince_liam_greymane_phase2’),

3 (-1654005, ’Defeat these foul beasts!’, 19618, 1, 7, 424, ’npc_prince_liam_greymane_phase2’),

4 (-1654006, ’Protect the Civilians!’, 19619, 1, 7, 424, ’npc_prince_liam_greymane_phase2’),

5 (-1654007, ’Push them back!’, 19620, 1, 7, 424, ’npc_prince_liam_greymane_phase2’),

6 (-1654008, ’Take heart men, we must protect our city!’,19621, 1, 7, 424, ’npc_prince_liam_greymane_phase2’);

La costruzione dello script che consente l'animazione del personaggio inquestione si basa sull'estensione della classe ScriptedAI dichiarata nel lesc_creature.h del progetto ScriptDev2 e parzialmente implementata nel lesc_creature.cpp. I principali metodi che questa struttura ore sono:

1 struct MANGOS_DLL_DECL ScriptedAI : public CreatureAI2 3 public:4 explicit ScriptedAI(Creature* pCreature);5 ~ScriptedAI() 67 // *************8 // CreatureAI Functions9 // *************1011 // == Information about AI ========================12 // Get information about the AI13 void GetAIInformation(ChatHandler& reader) override;1415 // == Reactions At =================================1617 // Called if IsVisible(Unit* pWho) is true at each

relative pWho move18 void MoveInLineOfSight(Unit* pWho) override;1920 // Called for reaction at enter to combat if not in

combat yet (enemy can be NULL)21 void EnterCombat(Unit* pEnemy) override;2223 // Called at any Heal received

17Il documento è consultabile a MaNGOS-Zero docshttps://media.readthedocs.org/pdf/mangoszero-docs/latest/mangoszero-docs.pdfvisionato in data 15/12/2014

4.3 Ricerca e risoluzione 62

24 void HealedBy(Unit* /*pHealer*/, uint32& /*uiHealedAmount

*/) override 2526 // Called at any Damage to any victim (before damage

apply)27 void DamageDeal(Unit* /*pDoneTo*/, uint32& /*uiDamage*/)

override 2829 // Called at any Damage from any attacker (before damage

apply)30 void DamageTaken(Unit* /*pDealer*/, uint32& /*uiDamage*/)

override 3132 // Called at creature killing another unit33 void KilledUnit(Unit* /*pVictim*/) override 3435 // Called when hit by a spell36 void SpellHit(Unit* /*pCaster*/, const SpellEntry*

/*pSpell*/) override 3738 // Called when spell hits creature’s target39 void SpellHitTarget(Unit* /*pTarget*/, const SpellEntry*

/*pSpell*/) override 4041 // Called when the creature is target of hostile action:

swing, hostile spell landed, fear/etc)42 /// This will by default result in reattacking, if the

creature has no victim43 void AttackedBy(Unit* pAttacker) override CreatureAI::

AttackedBy(pAttacker); 4445 // Called at text emote receive from player46 void ReceiveEmote(Player* /*pPlayer*/, uint32 /*uiEmote

*/) override 4748 // Called at each attack of m_creature by any victim49 void AttackStart(Unit* pWho) override;5051 // Called at World update tick52 void UpdateAI(const uint32) override;5354 // == State checks =================================5556 // Check if unit is visible for MoveInLineOfSight57 bool IsVisible(Unit* pWho) const override;5859 // Called when victim entered water and creature can not

enter water60 bool canReachByRangeAttack(Unit* pWho) override

4.3 Ricerca e risoluzione 63

return CreatureAI::canReachByRangeAttack(pWho);

6162 // *************63 // Variables64 // *************6566 // *************67 // Pure virtual functions68 // *************6970 /**71 * This is a SD2 internal function, that every AI must

implement72 * Usally used to reset combat variables73 * Called by default on creature evade and respawn74 * In most scripts also called in the constructor of the

AI75 */76 virtual void Reset() = 0;7778 /// Called at creature EnterCombat with an enemy79 /**80 * This is a SD2 internal function81 * Called by default on creature EnterCombat with an

enemy82 */83 virtual void Aggro(Unit* /*pWho*/) 8485 // *************86 // AI Helper Functions87 // *************8889 // Start movement toward victim90 void DoStartMovement(Unit* pVictim, float fDistance = 0,

float fAngle = 0);9192 // Start no movement on victim93 void DoStartNoMovement(Unit* pVictim);9495 // Stop attack of current victim96 void DoStopAttack();9798 // Cast spell by Id99 void DoCast(Unit* pTarget, uint32 uiSpellId, bool

bTriggered = false);100101 // Cast spell by spell info102 void DoCastSpell(Unit* pTarget, SpellEntry const*

4.3 Ricerca e risoluzione 64

pSpellInfo, bool bTriggered = false);103104 // Returns spells that meet the specified criteria from

the creatures spell list105 SpellEntry const* SelectSpell(Unit* pTarget, int32

uiSchool, int32 iMechanic, SelectTarget selectTargets,uint32 uiPowerCostMin, uint32 uiPowerCostMax, float

fRangeMin, float fRangeMax, SelectEffect selectEffect);

106107 // Checks if you can cast the specified spell108 bool CanCast(Unit* pTarget, SpellEntry const* pSpell,

bool bTriggered = false);109110 void SetEquipmentSlots(bool bLoadDefault, int32 iMainHand

= EQUIP_NO_CHANGE, int32 iOffHand = EQUIP_NO_CHANGE,int32 iRanged = EQUIP_NO_CHANGE);

111112 ;

Vista la numerosità dei metodi disponibili vediamo ora lo scopo di quelliche saranno coinvolti nella realizzazione della soluzione al bug in oggetto dianalisi:

• virtual void Reset() = 0;: viene utilizzato per reimpostare le strut-ture dati e le azioni della creatura allo stato originale (prima della suaattivazione).

• virtual void Aggro(Unit* /*pWho*/) : viene richiamato ognivolta che la creatura può entrare in combattimento con altre creatu-re. L'invocazione di questo metodo avviene direttamente dalla libreriaScriptDev2 durante l'esecuzione del reame.

• void AttackedBy(Unit* pAttacker) override CreatureAI::-AttackedBy(pAttacker); : viene invocato dalla libreria quando lacreatura viene attaccata da un'altra creatura. Le funzioni sono eredi-tate da un'altra classe CreatureAI dichiarata nelle funzioni basilari delreame. Le creature della libreria ScriptDev2 ereditano tutti i metodidelle creature denite nel reame per garantire la consistenza e coerenzadegli oggetti.

• void AttackStart(Unit* pWho) override;: viene invocato quandola creatura rappresentata da questa classe deve compiere una azione diattacco.

4.3 Ricerca e risoluzione 65

• void UpdateAI(const uint32) override;: viene invocato dal reameciclicamente per consentire l'esecuzione continua delle abilità imple-mentate. Anche quanto l'NPC viene ucciso e nel periodo per cui il suocorpo rimane nell'area di gioco questo metodo viene sempre invocato.

Per meglio utilizzare e organizzare gli identicativi numerici relativi alleinformazioni archiviate nel database e agli elementi di gioco è stata realizzatauna struttura di tipo Enum, adatta a questo scopo, così popolata:

1 enum 2 SAY_STORYLINE4 = -1654004,3 SAY_STORYLINE5 = -1654005,4 SAY_STORYLINE6 = -1654006,5 SAY_STORYLINE7 = -1654007,6 SAY_STORYLINE8 = -1654008,78 SAY_STORY_DELAY = 30000,910 SPELL_SHOOT = 5009211 ;

I dati membri di questa classe, usati per gestire le azioni del NPC in oggettodi analisi saranno:

1 uint32 m_uiSayStoryTimer;2 int m_uiSayStoryLast;34 Unit* lastVictim;56 bool m_bCanSayStory;7 bool IsSelfRooted;

Vediamo quindi lo scopo di ciascun dato membro:

• m_uiSayStoryTimer: serve per temporizzare la successione dei testida pronunciare.

• lastVictim: conterrà la classe relativa all'ultima creatura bersaglio delnostro NPC .

• m_uiSayStoryLast: serve per tenere la traccia dell'ultimo testo pro-nunciato e proseguire in sequenza con i testi successivi, no a ricomin-ciare dal primo dopo che l'ultimo è stato pronunciato.

• m_bCanSayStory: serve come "semaforo" per stabilire quando è ilmomento corretto per pronunciare il testo. Viene usato in combinazionecon m_uiSayStoryTimer.

4.3 Ricerca e risoluzione 66

• IsSelfRooted: serve per vericare se il nostro NPC ha il come bersagliose stesso o una creatura diversa.

Oltre a questi dati membri da me creati esiste l'oggetto m_creatureche appartiene alla classe madre CreatureAI, ereditato automaticamente, cosìdenito:

1 Creature* const m_creature;

I dati membri sono inizializzati (e reimpostati ogni volta) con i seguentivalori:

1 void Reset() override2 3 m_uiSayStoryTimer = SAY_STORY_DELAY;4 m_uiSayStoryLast = 0;5 lastVictim = NULL;6 m_bCanSayStory = true;7 IsSelfRooted = false;8

Il metodo Aggro(), di cui è stata mostrata la denizione in precedenza, saràcosì denito:

1 void Aggro(Unit* who) override2 3 if (!m_creature->CanReachWithMeleeAttack(who) && !

m_creature->CanUseEquippedWeapon(RANGED_ATTACK))4 5 IsSelfRooted = true;6 7

Questo metodo viene usato per stabilire se il nostro NPC può attaccareuna creatura che ha vicino o entro il suo raggio di azione delle sue armi adistanza. Il metodo CanReachWithMeleeAttack(who) consente di stabilire sela creatura contenuta nell'oggetto who può essere attaccata dal nostro NPCcon un'arma da combattimento di mischia, mentre il metodo CanUseEquip-pedWeapon(RANGED_ATTACK) consente di stabilire se il nostro NPC hala possibilità di usare un'arma da distanza presente nel suo equipaggiamen-to (RANGED_ATTACK è una costante denita globalmente nel progettoScriptDev2 per identicare gli attacchi con armi da distanza, ad esempio:archi, balestre, fucili, ecc.). Se entrambe le condizioni non sono soddisfatte,viene impostata la condizione di bersaglio sul NPC stesso per impedirgli dicompiere azioni di attacco.

4.3 Ricerca e risoluzione 67

Il metodo AttackedBy, di cui è stata mostrata la denizione in prece-denza, sarà così denito:

1 void AttackedBy(Unit* pAttacker) override2 // Check if Liam is attacking who attack he and don’t jump

on multiple attackers3 if (m_creature->getVictim() && (m_creature->getVictim() ==

pAttacker || lastVictim == pAttacker))4 return;56 if (m_creature->IsFriendlyTo(pAttacker))7 return;89 lastVictim = pAttacker;10 AttackStart(pAttacker);11

Questo metodo viene usato per mantenere il bersaglio sso su una so-la creatura quando più creature attaccano il nostro NPC. Con l'opportunacombinazione delle condizioni di controllo sul metodo getVictim() che iden-tica l'attuale bersaglio, sull'oggetto pAttacker che identica la creatura cheattacca il nostro NPC e lastVictim che, come visto nella denizione dei datimembro, contiene la classe dell'ultimo bersaglio del nostro NPC, il bersagliodegli attacchi viene mantenuto sso su una singola creatura no alla sua uc-cisione. Infatti il metodo AttackStart(pAttacker) verrà invocato unicamentequando il bersaglio corrente è uguale a quello precedente (se era stato giàidenticato) e il bersaglio corrente è diverso dal NPC stesso. Questo metodoconsente di eseguire una azione di attacco.

Il metodo UpdateAI(), di cui è stata mostrata la denizione in prece-denza, è il punto nevralgico in cui gestire le attività del NPC e sarà cosìdenito:

1 void UpdateAI(const uint32 uiDiff) override2 3 // Ready to say emote4 if (m_bCanSayStory)5 6 m_uiSayStoryTimer = SAY_STORY_DELAY;78 // Sequence switch between 3 texts9 switch (m_uiSayStoryLast)10 11 case 0: DoScriptText(SAY_STORYLINE4, m_creature);

m_uiSayStoryLast++; break;12 case 1: DoScriptText(SAY_STORYLINE5, m_creature);

m_uiSayStoryLast++; break;

4.3 Ricerca e risoluzione 68

13 case 2: DoScriptText(SAY_STORYLINE6, m_creature);m_uiSayStoryLast++; break;

14 case 3: DoScriptText(SAY_STORYLINE7, m_creature);m_uiSayStoryLast++; break;

15 case 4: DoScriptText(SAY_STORYLINE8, m_creature);m_uiSayStoryLast = 0; break;

16 1718 m_bCanSayStory = false;19 2021 if (m_uiSayStoryTimer < uiDiff)22 23 m_bCanSayStory = true;24 m_uiSayStoryTimer = SAY_STORY_DELAY;25 26 else27 m_uiSayStoryTimer -= uiDiff;2829 // Return since we have no target30 if (!m_creature->SelectHostileTarget()

|| !m_creature->getVictim())31 return;3233 // Equipped ranged weapon usable and not close to victim34 if (m_creature->GetCombatDistance(m_creature->getVictim(),

false) > 0 && m_creature->CanUseEquippedWeapon(RANGED_ATTACK) )

35 36 // Make sure our attack is ready37 if (m_creature->isAttackReady(RANGED_ATTACK))38 39 // Use spell instead of normal ranged attack that seem

not working. TODO: check ranged attack!40 DoCastSpellIfCan(m_creature->getVictim(), SPELL_SHOOT);41 m_creature->resetAttackTimer(RANGED_ATTACK);42 4344 45 else if (m_creature->CanReachWithMeleeAttack(m_creature->

getVictim()))46 47 // If we are within range melee the target48 // Make sure our attack is ready49 if (m_creature->isAttackReady())50 51 m_creature->AttackerStateUpdate(m_creature->getVictim()

);52 m_creature->resetAttackTimer();

4.3 Ricerca e risoluzione 69

53 54 55 else if (IsSelfRooted)56 57 // Cancel our current spell and then allow movement again58 m_creature->InterruptNonMeleeSpells(false);59 IsSelfRooted = false;60 61

In questo metodo vengono gestite le azioni di combattimento e la pronun-cia dei testi con le strutture dati dichiarate nella parte iniziale della classe.Il controllo sulla struttura dati m_bCanSayStory viene fatto per vericarese la condizione di possibilità di pronuncia dei testi è soddisfatta. A quelpunto vengono reimpostati i timer e viene richiamata la funzione della libre-ria ScriptDev2 DoScriptText che attiva l'animazione di dialogo, seguendo lasequenza di testi preimpostata.

Il controllo sulla struttura dati m_uiSayStoryTimer serve per stabilirequando sarà nuovamente possibile pronunciare testi sfruttando la variabileuiDi che contiene la dierenza tra una chiamata al metodo in oggetto el'altra. Questa dierenza è ssa al valore di 1000 millisecondi (ovvero il me-todo UpdateAI() viene invocato dalla libreria ScriptDev2 ogni secondo). Sela struttura dati contatore ha un valore inferiore vengono attivate le condi-zioni per la riproduzione dei dialoghi alla prossima invocazione del metodo,altrimenti viene decrementata.

Il controllo sulle condizioni SelectHostileTarget() e getVictim() servonoper stabilire se la creatura in oggetto di scripting non ha un bersaglio dapoter attaccare o non è in combattimento con un'altra creatura. Se almenouna di queste due condizioni è soddisfatta l'esecuzione del metodo vieneinterrotta in quanto le azioni successive non sono da eseguire.

La sequenza delle ultime condizioni da vericare serve per stabilire se lacreatura può attaccare con un'arma a distanza, deve attaccare in corpo acorpo oppure, da ultimo, se non deve fare azioni di attacco in quanto il suobersaglio è se stessa.

Con il metodo GetCombatDistance(m_creature->getVictim(), false) vie-ne vericata la condizione per cui la nostra creatura possa compiere un attac-co in distanza con il suo attuale bersaglio identicato dall'oggetto ritornatodal metodo getVictim() (il parametro false serve per indicare che la valuta-zione della distanza deve essere fatta per le armi da distanza e non da corpo acorpo, valutabile con lo stesso metodo e questo secondo parametro imposta-to a true). Il secondo metodo per la verica della condizione CanUseEquip-pedWeapon(RANGED_ATTACK) serve per vericare che la nostra creatura

4.3 Ricerca e risoluzione 70

abbia a disposizione un'arma per combattere dalla distanza, specicata dallastruttura dati globale al progetto ScriptDev2 RANGED_ATTACK. Confer-mate le valutazioni appena descritte resta un ultimo controllo prima di poterfar eseguire l'attacco: la verica che l'arma sia pronta per l'uso con il meto-do isAttackReady(RANGED_ATTACK)18. Se tutte queste condizioni sonosoddisfatte viene invocato il metodo DoCastSpellIfCan(...), che farà eseguirel'azione di attacco alla nostra creatura, e il metodo per attivare il tempo diricarica dell'arma. Se invece l'attacco dalla distanza non fosse possibile vienevericata la possibilità di eseguire un attacco in corpo a corpo con il me-todo CanReachWithMeleeAttack(...). Dopo aver vericato che l'arma per ilcombattimento sia pronta viene invocato il metodo AttackerStateUpdate(...)per questa tipologia di combattimenti e attivato il tempo di ricarica dell'ar-ma. L'ultimo controllo della sequenza è la verica di avere come obiettivo sestessi e quindi interrompere qualsiasi attività di combattimento e rimuoverel'obiettivo.

La classe completa di tutte le sue parti sarà quindi così costruita:

1 struct MANGOS_DLL_DECL npc_prince_liam_greymane_phase2AI :public ScriptedAI

2 3 npc_prince_liam_greymane_phase2AI(Creature* pCreature) :

ScriptedAI(pCreature)4 5 Reset();6 78 uint32 m_uiSayStoryTimer;9 int m_uiSayStoryLast;1011 Unit* lastVictim;1213 bool m_bCanSayStory;14 bool IsSelfRooted;1516 void Reset() override17

18L'uso delle armi non avviene tramite click del mouse o tasti speciali, ma è gestito inautomatico dalle logiche del sistema di gioco. In particolare ogni arma, ma anche gli incan-tesimi e tutti gli oggetti di gioco, hanno un tempo di ricarica prima di poter essere usati e,successivamente al tempo di ricarica, l'azione dell'oggetto avviene in automatico. Quandouna creatura inizia una azione di combattimento l'uso dell'arma avviene in automaticoin base al suo tempo di ricarica, sia per le creature che per i giocatori. Questo sistemaconsente l'equità e l'ordine nel numero di attacchi consecutivi in un combattimento tracreature e tra giocatori

4.3 Ricerca e risoluzione 71

18 m_uiSayStoryTimer = SAY_STORY_DELAY;19 m_uiSayStoryLast = 0;20 lastVictim = NULL;21 m_bCanSayStory = true;22 IsSelfRooted = false;23 2425 void Aggro(Unit* who) override26 27 if (!m_creature->CanReachWithMeleeAttack(who) &&

!m_creature->CanUseEquippedWeapon(RANGED_ATTACK))

28 29 IsSelfRooted = true;30 31 3233 void AttackedBy(Unit* pAttacker) override34 35 // Check if Liam is attacking who attack he and don’t

jump on multiple attackers36 if (m_creature->getVictim() && (m_creature->getVictim()

== pAttacker || lastVictim == pAttacker))37 return;3839 if (m_creature->IsFriendlyTo(pAttacker))40 return;4142 lastVictim = pAttacker;43 AttackStart(pAttacker);44 4546 void UpdateAI(const uint32 uiDiff) override47 48 // Ready to say emote49 if (m_bCanSayStory)50 51 m_uiSayStoryTimer = SAY_STORY_DELAY;5253 // Sequence switch between 3 texts54 switch (m_uiSayStoryLast)55 56 case 0: DoScriptText(SAY_STORYLINE4, m_creature);

m_uiSayStoryLast++; break;57 case 1: DoScriptText(SAY_STORYLINE5, m_creature);

m_uiSayStoryLast++; break;58 case 2: DoScriptText(SAY_STORYLINE6, m_creature);

m_uiSayStoryLast++; break;59 case 3: DoScriptText(SAY_STORYLINE7, m_creature);

4.3 Ricerca e risoluzione 72

m_uiSayStoryLast++; break;60 case 4: DoScriptText(SAY_STORYLINE8, m_creature);

m_uiSayStoryLast = 0; break;61 //case 3: DoScriptText(SAY_HELP4, m_creature); break;62 6364 m_bCanSayStory = false;65 6667 if (m_uiSayStoryTimer < uiDiff)68 69 m_bCanSayStory = true;70 m_uiSayStoryTimer = SAY_STORY_DELAY;71 72 else m_uiSayStoryTimer -= uiDiff;737475 // Return since we have no target76 if (!m_creature->SelectHostileTarget()

|| !m_creature->getVictim())77 return;7879 // Equipped ranged weapon usable and not close to victim80 if (m_creature->GetCombatDistance(m_creature->getVictim()

, false) > 0 && m_creature->CanUseEquippedWeapon(RANGED_ATTACK) )

81 82 // Make sure our attack is ready83 if (m_creature->isAttackReady(RANGED_ATTACK))84 85 // Use spell instead of normal ranged attack that

seem not working. TODO: check ranged attack!86 DoCastSpellIfCan(m_creature->getVictim(), SPELL_SHOOT

);87 //m_creature->AttackerStateUpdate(m_creature->

getVictim(),RANGED_ATTACK);88 m_creature->resetAttackTimer(RANGED_ATTACK);89 9091 92 else if (m_creature->CanReachWithMeleeAttack(m_creature->

getVictim()))93 94 // If we are within range melee the target95 // Make sure our attack is ready96 if (m_creature->isAttackReady())97 98 m_creature->AttackerStateUpdate(m_creature->

getVictim());

4.3 Ricerca e risoluzione 73

99 m_creature->resetAttackTimer();100 101102 103 else if (IsSelfRooted)104 105 // Cancel our current spell and then allow movement

again106 m_creature->InterruptNonMeleeSpells(false);107 IsSelfRooted = false;108 109110 111 ;

Per terminare le operazioni di implementazione è necessario aggiungere laclasse relativa al NPC in oggetto di script nel metodo che istanzia tutti glioggetti presenti nel le di script C++ invocato dalla libreria ScriptDev2quando un personaggio si trova nell'area di gioco:

1 void AddSC_gilneas_city()2 3 Script* pNewScript;45 pNewScript->Name = "npc_prince_liam_greymane_phase2";6 pNewScript->GetAI = &

GetAI_npc_prince_liam_greymane_phase2;7 pNewScript->RegisterSelf();8

Ora l'NPC è pronto per eseguire le azioni e le animazioni corrette. Per con-sentire al reame di attivare le procedure della libreria ScriptDev2 relative alloscript realizzato, è necessario inserire nella tabella creature_template,già vista nel terzo capitolo durante l'analisi del database, il nome delloscript creato, ovvero npc_prince_liam_greymane_phase2 nella colon-na ScriptName. Inoltre bisogna valorizzare la colonna flags_extra a 0,per rendere l'NPC attivo (il signicato dei valori associati a questa colonna èspiegato sempre nel documento mangoszero-doc.pdf 19). Da ultimo è necessa-rio cambiare anche il valore della colonna unit_flags con il nuovo valore33024. Questa codica non è documentata, ma sono arrivato a ritenere cor-retto questo valore sulla base di altri NPC che hanno comportamenti similiper cui sono state apportate le implementazioni.

19Il documento è consultabile a MaNGOS-Zero docshttps://media.readthedocs.org/pdf/mangoszero-docs/latest/mangoszero-docs.pdfvisionato in data 15/12/2014

4.4 Pull Request sul repository 74

1 UPDATE creature_template SET ScriptName = ’npc_prince_liam_greymane_phase2’, flags_extra = ’0’,unit_flags = ’33024’ WHERE entry = 34913 ;

Dopo aver ricompilato il reame, con il progetto ScriptDev2 contenente ilnuovo script come mostrato in gura 4.6, l'NPC avrà le azioni e animazionicorrette come mostrato in gura 4.7.

Figura 4.6: Compilazione del reame con le modiche apportate

Per contribuire alla documentazione sullo scripting degli NPC, ho pub-blicato nel forum del progetto MaNGOS una mini guida per associare untesto ad un NPC. La documentazione pubblicata in data 17 dicembre 2014è raggiungibile all'url https://www.getmangos.eu/mangos-university/10209-scripting-howto-add-emote-text-creature.html (consultabile soltanto per gliutenti registrati al forum del progetto MaNGOS).

4.4 Pull Request sul repository

Tutte le correzioni, sia con Database Scripts che in ScriptDev2, apportate etestate essere funzionanti, sono state proposte al repository principale dovei responsabili e moderatori le hanno accettate e integrate nel progetto. Di

4.4 Pull Request sul repository 75

Figura 4.7: NPC "Prince Liam Greymane" con animazioni e azioni

seguito è riportato un breve elenco delle correzioni che sono state eettuateall'inizio del periodo di analisi:

• NPC Prince Liam Greymane in fase 1: Assegnati testi e voce.

• Cambio di fase: Corretto cambio di fase dopo accettazione e completa-mento della quest Something’s Amiss.

• NPC Prince Liam Greymane in fase 2: Assegnati testi, voce eazioni.

• Creatura Rampaging Worgen: associata abilità Enrage.

• Corretta quest Evacuate the Merchant Square: aggiunta abili-tà Knoking per tutti i giocatori, aggiunta la comparsa delle creatureFrightened Citizen e Rampaging Worgen con relative azioniall'apertura della porta e associata la progressione della quest quandovengono aperte le porte indicate.

Successivamente non ho più eettuato proposte di correzioni al repositoryin quanto sto cercando di raggrupparle in porzioni di codice più corpose edomogenee ed omogenei.

4.4 Pull Request sul repository 76

Sebbene alla pull request corrisponda una fase di peer review, non esisteun vero e proprio meccanismo di validazione automatica delle correzioni: laloro bontà viene vericata empiricamente provando le varie sessioni di gioco.

Figura 4.8: Pull Request accettate con le modiche fatte su GitHub

Capitolo 5

Un esempio di community

In questo capitolo sarà presentato brevemente un modello reale di server peril gioco World Of WarcraftTM basato su un motore open source.20 Per unabreve descrizione dei principali termini utilizzati si rimanda al glossario.

5.1 Un esempio di Server Privato

La community www.molten-wow.com, ribattezzata di recente in www.Warmane.com,è un esempio di realtà costruita attorno allo sviluppo di un server per il giocoWorld Of WarcraftTM basato sul progetto open source TrinityCore, glio diMaNGOS. Questa community, fondata nel 2009 è cresciuta molto nel corsodegli anni arrivando ad avere più di 20.000 utenti attivi nei momenti di piccodelle connessioni.

Dall'agosto del 2010 sono iscritto a questa community e con altalenantiperiodi di assidua frequenza ho assistito in prima persona alla sua storia.Ci sono stati periodi in cui la community era più attiva e periodi di minorattività non solo da parte dei giocatori, ma anche da parte dello sta checurava lo sviluppo dei reami e la gestione degli utenti. Da ultimo, con l'iniziodell'anno 2015, si sono vericati due eventi cruciali:

• Verso la ne di gennaio 2015 la community ha subito un abbandonoda parte di alcuni membri dello sta che hanno causato un blackoutgenerale di tutti i servizi oerti per alcuni giorni, oltre alla perdita deidati di gioco di tutti i giocatori. La motivazione di questo boicottaggiosembra essere stata di carattere economico, ovvero di pagamenti nonricevuti per il lavoro svolto da alcuni sviluppatori.

20Tutte le informazioni riportate in questo capitolo sono frutto di una rielaborazionedella informazioni frammentate in più parti del forum della community.

5.1 Un esempio di Server Privato 78

• Dalla ne di febbraio 2015 la community di molten-wow ha avviato unprocesso di fusione con un'altra community per arrivare alla creazionedi quella attuale warmane.

5.1.1 Organizzazione

Ad oggi, la community, ospita sette reami con tre espansioni di gioco die-renti:

• Tre reami Wrath of the Lich King, la seconda espansione del gioco.

• Due reami Cataclysm, la terza espansione del gioco.

• Due reami Mist of Pandaria, la quarta espansione del gioco.

Recentemente è stato anche annunciato un reame PTR (Public Test Realm,ovvero un reame in versione pre release con lo scopo di vericare le funzio-nalità di base del gioco) Warlords of Draenor, la quinta e ultima (per ora)espansione del gioco.

Questi reami non sono totalmente funzionanti, anzi, hanno tutti dellefunzionalità mancanti o errate in particolare nel caso di espansioni recentiquanto l'espansione del gioco è più recente. Per correggere le funzionalitàmancanti, lo sta è composto da una cospicua squadra di sviluppatori chelavorano a tempo pieno alle evoluzioni.

Oltre ai reami, la community è incentrata su un portale/forum dove av-vengono le comunicazioni fra sta e giocatori. Inoltre il portale è una piccolaestensione del gioco in quanto per ogni account registrato sono disponibiliun insieme di strumenti dedicati alla gestione dei personaggi, degli oggetti digioco acquistabili e altre funzionalità di supporto.

Per rendere maggiormente l'idea delle dimensioni di questa communityriporto alcune informazioni statistiche sul forum:

• Numero di utenti registrati: 2.119.170.

• Numero di articoli del forum: 37.852.

• Numero di risposte negli articoli del forum: 533.651.

5.1.2 Bugtracker e changelog

Per gestire al meglio lo sviluppo dei reami nella correzione dei bug, i gioca-tori della community possono segnalare le funzionalità mancanti dei reami

5.1 Un esempio di Server Privato 79

in un apposito portale dedicato alla raccolta delle segnalazioni, chiamatoBugTracker.

In questo portale le segnalazioni vengono suddivise primariamente perespansione di gioco, poi per ogni espansione sono presenti sezioni che identi-cano puntualmente la tipologia di oggetto che riscontra il problema (quest,spell, abilità, oggetto, ecc.). In questo portale vengono riportati tutti i det-tagli sugli errori riscontrati e lo sta, che prende in carico la segnalazione,può tracciare lo stato di avanzamento dei lavori di correzione, suddividersi lecorrezioni e pianicare gli aggiornamenti. Questi ultimi avvengono tramiteannunci sul portale della community, che avvisano i giocatori quando il rea-me coinvolto verrà spento per applicare gli aggiornamenti delle funzionalitàmancanti o errate.

Per informare i giocatori sui progressi delle correzioni, dopo ogni aggior-namento di una espansione, viene pubblicato un changelog21 con i dettaglisulle funzionalità corrette.

5.1.3 il sistema delle donazioni

I gestori della community hanno avviato con successo, come anche in altriserver privati per questo videogioco, una politica di mantenimento dei costi dihosting e sviluppo tramite un sistema di scambio della valuta corrente in get-toni della community. Questi gettoni possono essere usati da ogni giocatoreper comprare oggetti di gioco o benet per i personaggi.

Per incentivare l'uso dei gettoni gli oggetti di gioco e i benet acquistabilisono esclusivi di queste transazioni e non possono essere ottenuti durante lesessioni di gioco.

Il costante ricambio di giocatori in combinazione con questa "strategia dimercato aggressiva" uniti ai nuovi contenuti che ogni nuova espansione porta,favoriscono degli introiti abbastanza costanti che consentono il mantenimentodi un organico salariato dedicato agli sviluppi e alle migliorie dei reami e ditutte le altre infrastrutture della community.

Lo sta raccoglie le candidature che i giocatori fanno tramite presenta-zione del proprio Curriculum Vitae. Se ritenuti sucientemente abili per leattività di sviluppo, i giocatori possono entrare nell'organico dello sta apagamento.

A titolo esemplicativo riporto i dettagli dei requisiti richiesti per ricoprirealcune posizioni di sviluppatore:[6]

21Il changelog (tradotto in italiano diario dei cambiamenti) è solitamente un documentoche riepiloga le modiche apportate nell'ultima versione di un software.

5.1 Un esempio di Server Privato 80

• Senior Reverse Engineer con una vasta esperienza in reverse engi-neering e conoscenza della programmazione C++. Stipendio mensilecirca $5.000. Requisiti:

Vasta conoscenza di Assembly (x86-64,mips) C, C++, Java, C#,Lua, Pascal, Verilog, VHDL.

Esperienza di lavoro con Ida PRO, WinDbg, WinICE, VisualStudio ecc.

Abilità nell'uso dei sistemi UNIX

Abilità di lavoro con sistemi di gestione dei sorgenti come GIT eSVN

• Senior C++ Programmer con vasta esperienza nello sviluppo diinfrastrutture. Stipendio mensile circa $4.000. Requisiti:

Vasta esperienza nella programmazione C++.

Buona conoscenza del linguaggio SQL.

Buona capacità di comprensione del codice

Abilità di scrivere e sviluppare codice eciente e ottimizzato persistemi multiutente.

Abilità nell'uso dei sistemi UNIX

Abilità di lavoro con sistemi di gestione dei sorgenti come GIT eSVN

• Senior Database Developer con vasta esperienza e conoscenza diMySQL, DB Scripting (Quests, NPCs, General). Stipendio mensilecirca $3.000. Requisiti:

Obbligatoria la conoscenza del sistema TrinityCore SmartAI.

Abilità di lavoro con sistemi di gestione dei sorgenti come GIT eSVN

La conoscenza della struttura del database TrinityCore sarà con-siderata come bonus

Osservando le proposte di salario mensile per questi ruoli è possibile in-tuire che una community abbastanza grande come quella in oggetto di ana-lisi comporti anche introiti sucienti a mantenere uno sta motivato nellosviluppo non solo spinto da spirito di volontariato personale.

Capitolo 6

Conclusioni

L'obiettivo di questo lavoro era di analizzare un emulatore open source per ungioco online molto popolare e famoso, al ne di capire quali siano le logichedi costruzione e sviluppo incrementale di un videogioco.

Come riportato nell'introduzione ai concetti del videogioco in analisi, nonesistono dei sorgenti con libero accesso sia per la componente client che perla componente server e, per tanto, tutte le funzionalità dell'emulatore sonostate costruite sulla base di esperienze di gioco, analisi dei dati presenti neiportali dedicati ed esperimenti pratici.

La costruzione di un emulatore è quindi un processo lento, che richiedemolte risorse (non solo economiche) e che dicilmente eguaglierà le fun-zionalità del gioco originale. Ciò nonostante esistono realtà che riescono afar progredire l'evoluzione di questi emulatori per fornire un servizio (quasi)gratuito ai giocatori.

La mia trattazione è stata volutamente un percorso a tappe partito dalconcetto generico di videogioco online, passando ad un esempio concretodi sua realizzazione (l'emulatore), addentrandosi nell'ambiente in cui questoemulatore vive, guardando come questo emulatore funziona e consente l'in-terazione con il giocatore, per arrivare a realizzare una porzione di gioco ecapire i legami tra gli oggetti che all'apparenza possono sembrare banali oscontati (per chi li usa frequentemente) ma che in realtà nascondono tuttauna serie di logiche e schemi che rendono possibile la magia del gioco.

Guardando il lavoro svolto nel suo complesso, oltre a poter identicareaspetti dell'emulatore che possono ricevere una maggiore attenzione, si puòavere l'impressione che mi sia dedicato a questa analisi per un banale scopoludico. La realtà dei fatti invece è molto dierente. Sicuramente una compo-

82

nente ludica nella scelta dell'oggetto di studio è stata presa in considerazionema, in modo molto maggiore, la scelta è derivata dalla connessione strettache lega il gioco con l'apprendimento e, ancora maggiormente, il legame tragioco e creatività. Il lavoro svolto da chi analizza e sviluppa software ritengoche sia fondamentalmente un esercizio di creatività. Senza la creatività nonsi possono costruire software innovativi, senza la creatività non si possonorisolvere problemi apparentemente irrisolvibili, senza la creatività non si puòmigliorare il mondo. Per questo motivo l'analisi condotta è stata in primisuno stimolo di ricerca della creatività in un gioco, piuttosto che un meroesercizio pratico di analisi applicata ad un software.

Bibliograa

[1] LUA about. LUA. Visionato in data: 24 Marzo 2015. url: http://www.lua.org/about.html.

[2] CPP. C++ Standards. Visionato in data: 3 Aprile 2015. url: https://isocpp.org/std/status.

[3] getMaNGOS. getMaNGOS History. Visionato in data: 2 Marzo 2015.url: https://www.getmangos.eu/history.php.

[4] getMaNGOS. MaNGOS Zero docs. Visionato in data: da Ottobre 2014a Aprile 2015. url: https://media.readthedocs.org/pdf/mangoszero-docs/latest/mangoszero-docs.pdf.

[5] gitHub. The GitHub. Visionato in data: 26 Marzo 2015. url: https://github.com/about.

[6] Molten-WoW. Molten Team Is Hiring! Visionato in data: 25 Marzo2015. url: http://forum.warmane.com/showthread.php?t=282774.

[7] MySQL. MySQL Sorage Engine. Visionato in data: 10 Marzo 2015.url: https : / / dev . mysql . com / doc / refman / 5 . 6 / en /storage-engines.html.

[8] ScriptDev2 Team. ScriptDev2 Home. Visionato in data: da Ottobre2014 a Aprile 2015. url: http://www.scriptdev2.com/.

[9] Microsoft TechNet. Installare il ruolo Hyper-V e congurare una mac-china virtuale. Visionato in data: 3 Ottobre 2014. url: https://technet.microsoft.com/it-it/library/hh846766.aspx.

[10] Wikipedia.MMORPG. Visionato in data: 24 Febbraio 2015. url: https://it.wikipedia.org/wiki/MMORPG.

[11] Wikipedia. World Of Warcraft. Visionato in data: 25 Febbraio 2015.url: https://it.wikipedia.org/wiki/World_of_Warcraft.

[12] WoWPedia. Phasing. Visionato in data: 20 Marzo 2015. url: http://wow.gamepedia.com/Phasing.

Glossario

bitmask Un bitmask è una tipologia di dato binario posizionale su cui ven-gono eettuati confronti bit a bit tramite gli operatori logici (AND, OR eNOT).

CMake è un tool per automatizzare la fase di costruzione (compilazione,collegamento, test, distribuzione, ecc.) di un sistema software; in particolare,consente di generare i Makele (da usare se si lavora in ambiente Linux).

EXP Experience Points.

GitHub è un portale web con lo scopo di fornire servizi come repository econtrollo delle versioni.

MaNGOS Massively Network Game Object Server.MMORPG Massive(ly) Multiplayer Online Role-Playing Game.MySQL è un Relational Database Management System (RDBMS) opensource.

NPC Non Playing Character.

PostgreSQL è un Relational Database Management System (RDBMS) opensource.PvE Player versus Environment.PvM Player versus Monster.

quest Una quest (o missione) consiste in un insieme di sde che il giocatoredeve superare per ottenere una ricompensa.

repository Un repository è un ambiente di un sistema informativo (ad es.di tipo ERP), in cui vengono gestiti i metadati, attraverso tabelle relazionali.

scripting Il termine scripting indica la costruzione di codice sorgente usandoun metalinguaggio che sarà interpretato da un interprete costruito ad-hocprima di essere eseguito.

Glossario 85

shell La shell è una interfaccia del sistema operativo testuale, in cui i comandivengono inseriti testualmente.SVN , abbreviazione di Subversion, è un sistema di controllo di versione perle sorgenti.

Visual Studio è un ambiente IDE per lo sviluppo software.

WoWHead è un portale web dedicato alla visualizzazione dei dettagli suglielementi di gioco per World Of WarcraftTM .WoWWiki è un portale web dedicato alla visualizzazione dei dettagli suglielementi di gioco per World Of WarcraftTM .