Questa guida e' molto semplice e sicuramente incompleta,
e' soltanto per iniziare. Sara' naturalmente integrata, modificata,
aggiornata ed anche riscritta da capo se sara' necessario in base
ai vostri commenti, alle vostre domande, ed agli sviluppi futuri del
client. A fondo pagina trovate le versioni scaricabili dei sorgenti
dei due plug-ins che ho scritto io, spero vi siano utili per farvi
un'idea del funzionamento.
(le specifiche qui descritte sono valide per GosClient 1.6.0 versione
finale)
Introduzione
I plug-ins di GosClient sono praticamente dll standard di windows
e comunicano con il client attraverso due metodi:
- il primo consiste nell'esportazione di alcune funzioni da parte
della dll, questo metodo permette l'inizializzazione e il passaggio
delle prime informazioni al client
- eseguita l'inizializzazione entra in gioco il secondo metodo, basato
sulla comunicazione tramite socket utilizzando il protocollo tcp-ip,
come in una applicazione client-server
Esiste un preciso protocollo che viene utilizzato durante le comunicazioni
tramite tcp-ip, che illustrero' piu' avanti. Tramite questo protocollo
il plug-in potra' ricevere (e se lo desidera bloccare) l'output che
il client riceve dal MUD, cosi' come ricevera' l'input proveniente
dall'utente, potra' quindi a sua volta inviare un output sostitutivo
a quello bloccato, inviare messaggi di stato e di errore ed inviare
comandi da eseguire nel MUD. Oltre a questi canali di comunicazione
basilari esistono alcune notifiche (quando viene cambiata la configurazione,
o si cambia profilo, per esempio) ed altre informazioni (nome del
mud, nome del profilo, cartella del mud e del profilo, cartella del
client ecc...).
Funzionamento interno del client
All'interno del client esistono diversi "canali" che vengono
ricevuti da ogni singola sua parte (quindi anche dai plug-ins).
Quando arrivano dei dati dal MUD, questi vengono trasformati in stringa
e inviati una prima volta a tutti i componenti per essere elaborati
(e' questa la stringa che sara' possibile bloccare e sostituire),
dopo il primo invio la stringa viene suddivisa in singole righe e
"ripulita" dalle sequenze ANSI, in modo che ogni riga sia
cosi' costituita di testo semplice. Questo output "pulito"
viene quindi passato ai componenti ed e' molto utile per alcune elaborazioni
(come ad esempio l'estrapolazione di titolo e descrizione di una stanza
per il mapper). Questi (normale e pulito) sono i due principali tipi
di output, oltre a questi ce ne sono altri che permettono di inviare
output alla finestra di stato e di inviare errori, mostrati in rosso
nella finestra di stato.
Come l'output del mud, anche l'input dell'utente "passa"
attraverso tutti i componenti prima di essere inviato, in modo da
permettere eventuali elaborazioni (come ad esempio lo spostamento
della posizione corrente nel mapper all'invio di un movimento). Esistono
due modi per inviare l'input: il primo e' l'invio diretto, adatto
per stringhe abbastanza corte; il secondo consiste nell'accodamento
alla coda di invio, utile nel caso in cui si debbano inviare molti
comandi insieme (saparati da CRLF) per non che i vari metodi anti-flood
dei mud entrino in azione per un invio troppo precipitoso.
Oltre ai sistemi di input e output esiste un sistema di notifica (come
gia' accennato in precedenza) che permette di sapere lo stato del
sistema attraverso ogni suo cambiamento. Vengono notificati gli eventi
piu' importanti, come il cambio di profilo, la disconnessione, il
cambio di layout, il cambio di colori eccetera...
Funzioni di inizializzazione
Come accennato in precedenza la dll del plug-in deve esportare alcune
funzioni per permettere le inizializzazioni e lo scambio di alcune
informazioni. Si tratta in tutto di quattro funzioni, due delle quali
facoltative:
gosInit
Questa funzione permette l'inizializzazione del plug-in, prima
di ritornare da questa funzione bisogna aver attivato la connessione
tramite tcp-ip al client sulla porta indicata nei parametri,
il client attendera' per cinque secondi la connessione del
plug-in dopodiche', sequesta non sara' andata a buon fine,
andra' in errore di timeout e terminera' l'esecuzione dello
stesso. Quando si riceve una chiamata a questa funzione bisogna
eseguire le inizializzazioni, ma non mostrare finestre, per
quello bisogna attendere il segnale 001 (vedi Protocollo)
dichiarazione:
long __stdcall gosInit(HWND hWnd,
long s, long
lPort, long* lpCanStop)
parametri:
hWnd |
Contiene un handle alla finestra principale del client,
tutte le finestre dei plug-in dovrebbero appartenere
a questa finestra. Per stabilire questo legame bisogna
creare la finestra inserendo questo valore nel parametro
hWndParent delle funzioni CreateWindow o CreateWindowEx. |
s |
non utilizzato |
lPort |
Porta a cui connettersi per attivare la comunicazione
tcp-ip gra client e plug-in. |
lpCanStop |
indica se il plug-in e' abilitato a bloccare l'output
del MUD o meno. Inizialmente il valore puntato da questa
variabile e' 0, variarlo in 1 se si vuole che il plug-in
possa modificare l'output del MUD verso il resto del
client (vedi Sistema di sostituzione dell'output). |
valori di ritorno:
la funzione deve ritornare un valore diverso da0 se l'inizializzazione
e' stata completata, altrimenti 0.
|
gosInfo
Questa funzione permette di passare alcune piccole informazioni
generali sul plug-in al client.
dichiarazione:
long __stdcall gosInfo(long
a, long
b, long c, gosPluginInfo* pGPI)
parametri:
a,b,c |
non utilizzati |
pGPI |
punta ad una struttura gosPluginInfo, dichiarata
come segue:
typedef struct gosPluginInfo
{
const
char lpTitle[128];
int
nMajor;
int
nMinor;
int
nRevision;
} gosPluginInfo;
lpTitle dovra' contenere il titolo del plug-in (per
un massimo di 128 caratteri)
nMajor, nMinor e nRevision sono invece tre valori
di versione, a partire dal piu' importante fino al
meno importante.
|
valori di ritorno:
la funzione deve ritornare un valore diverso da 0 se e'
andata a buon fine, altrimenti 0.
|
gosConf (facoltativa)
Questa funzione indica al plug-in che e' stato richiesto dall'utente
di mostrare la finestra di configurazione. Se il plug-in non
ha una finestra di configurazione questa funzione puo' anche
non figurare, oppure esistere e non eseguire niente, ritornando
0.
dichiarazione:
long __stdcall gosConf(HWND hParent,
long b, long
c, gosPaths* pGP)
parametri:
hParent |
Handle alla finestra principale del client, a cui
la finestra di configurazione deve appartenere (secondo
le stesse modalita' definite per gosInit) |
b,c |
non utilizzati |
pGP |
punta ad una struttura gosPaths contenente informazioni
sulle varie directory del client (in cui il plug-in
puo' scrivere le sue configurazioni sotto forma di
files), dichiarata come segue:
typedef struct gosPathsStruct
{
LPCTSTR lpClientPath;
LPCTSTR lpMudPath;
LPCTSTR lpProfilePath;
} gosPaths;
tutti i parametri contengono le stringhe dei percorsi
assoluti riguardo rispettivamente al client, al mud
selezionato ed al profilo selezionato.
|
valori di ritorno:
la funzione deve ritornare un valore diverso da 0 se il
plug-in possiede una finestra di configurazione, altrimenti
0.
|
gosCred (facoltativa)
Questa funzione informa il plug-in che e' stato richiesto
dall'utente di vedere la finestra di informazioni del plug-in.
dichiarazione:
long __stdcall gosCred(long
a, long
b, long c, long
d)
parametri:
valori di ritorno:
la funzione deve ritornare un valore diverso da 0 se il
plug-in possiede una finestra di informazioni, altrimenti
0.
|
Protocollo
Ogni stringa inviata e ricevuta deve essere preceduta da un carattere
iniziale (ASCII 140) e da un codice di 3 cifre che identifica il tipo
di dati successivo (i messaggi marcati in blu vengono ricevuti e possono
essere inviati solo da un plug-in abilitato a modificare l'output
del MUD):
001
|
partenza |
|
indica che le inizializzazioni per il
plug-in sono state completate, quando si riceve questo messaggio
bisogna rendere operativo a tutti gli effetti il plug-in, mostrando
la finestra del plug-inad esempio. |
002
|
output preliminare |
|
e' il codice per la ricezione dell'output preliminare. Dopo
il codice c'e' uno spazio e quindi la stringa di output. Questo
messaggio viene inviato come prima cosa appena viene ricevuto
dal mud, e' in questa sede che il programma e' in grado di
bloccare e sostituire l'output (vedi Sistema di sostituzione
dell'output) se ne e' stato abilitato in gosInit.
Es.
"002 [1;32mstringa [1;35mdi [1;33moutput"
|
003
|
output normale |
|
e' il codice per la ricezione dell'output in forma normale.
Dopo il codice deve esserci uno spazio e quindi la stringa
di output.
Es.
"003 [1;32mstringa [1;35mdi [1;33moutput"
|
004
|
output pulito |
|
codice per la ricezione dell'output pulito, la stringa di
output vero e proprio si trova accodata al codice, dopo uno
spazio.
Es.
"004 stringa di output"
|
005
|
input normale |
|
invio e ricezione dell'input, come al solito la stringa di
input e' accodata al codice, dopo uno spazio.
Es.
"005 stringa di input"
|
006
|
input da accodare |
|
codice per l'invio di stringhe da accodare per l'invio ritardato.
Ogni riga estratta dalla stringa inviata in questo modo viene
suddivisa ed iviata a brevi intervalli di tempo.
Es.
"006 stringa di input, prima riga \n seconda riga \n
terza riga \n ecc..."
|
007
|
messaggi di errore |
|
tramite questo codice si possono inviare messaggi di errore,
che verranno mostrati in rosso sulla scheda "status"
sul client.
|
008
|
messaggi di stato |
|
tramite questo codice si possono inviare
messaggi di stato, che verranno mostrati sulla scheda "status"
sul client. |
010
|
notifica |
|
questo codice permette di ricevere notifiche
dal client. Ogni notifica e' identificata da un numero,
che verra' accodato al codice dopo uno spazio. Le possibili
notifiche sono:
1 |
Chiusura della connessione |
3 |
Cambio dei colori |
4 |
Cambio del profilo |
5 |
Cambio nella configurazione |
10 |
Cambio nel layout |
Es.
"010 5" //notifica del cambio nella configurazione
|
011
|
conferma output |
|
questo messaggio deve essere inviato dal plug-in in risposta
ad un messaggio 002 nel caso in cui voglia lasciare l'output
del mud invariato.
Es.
"011"
|
012
|
sostituisci output |
|
questo messaggio deve essere inviato dal plug-in in risposta
ad un messaggio 002 nel caso in cui si voglia variare l'output
del mud, la nuova stringa di output dovra' essere accodata
al codice stesso (sempre preceduta da uno spazio vuoto).
Es.
"012 [1;32mStRiNgA [1;35mdI [1;33moUtPuT mOdIfIcAtA"
|
050
|
nome del MUD |
|
questo messaggio viene inviato una sola volta prima di quello
di partenza (partenza, 001), comunica al plug-in il nome del
MUD corrente.
Es.
"050 Silmaril"
|
051
|
nome del profilo |
|
questo messaggio viene inviato la prima volta prima dello
001 e poi ogni volta che si verifica un cambio di profilo,
comunica al plug-in il nome del profilo selezionato.
Es.
"051 Seph"
|
052
|
cartella del client |
|
viene inviato una sola volta prima dello 001, comunica la
cartella assoluta del client (sicuramente esistente, termina
sempre con \).
Es.
"052 C:\Programmi\GoS\"
|
053
|
cartella del MUD |
|
viene inviato una sola volta prima dello 001, comunica la
cartella assoluta del MUD selezionato (sicuramente esistente,
termina sempre con \).
Es.
"052 C:\Programmi\GoS\silmaril\"
|
054
|
cartella del profilo |
|
viene inviato inizialmente prima dello 001 ed ogni volta
che si cambia profilo, comunica la cartella assoluta del profilo
selezionato (sicuramente esistente, termina sempre con \).
Es.
"052 C:\Programmi\GoS\silmaril\p_seph\"
|
|
|
Esempio di sessione
Riporto qui sotto un esempio di sessione per dare un'idea della sequenza
di comunicazione che intercorre fra client e plug-ins.
Le scritte fra parentesi quadre indica delle azioni, quelle fra virgolette
delle frasi inviate tramite il collegamento tcp-ip.
<client> [chiama gosInfo del plug-in]
<plugin> [in gosInfo: riempie la struttura gosPluginInfo e ritorna
1]
<client> [chiama gosInit del plug-in]
<plugin> [in gosInit: attiva il collegamento con il client]
<client> [riceve la richiesta e conferma il collegamento]
<plugin> [in gosInit: ritorna 1]
<client> [conferma inizializzazione avvenuta]
<client> "050 Silmaril"
<client> "051 Seph"
<client> "052 C:\Programmi\GoS\"
<client> "053 C:\Programmi\GoS\silmaril\"
<client> "054 C.\Programmi\GoS\silmaril\p_seph\"
<client> "001 start"
<plugin> [mostra una finestra]
.. (varie comunicazioni di input e output)
..
<client> [interrompe il collegamento]
<plugin> [distrugge le finestra e chiudi il collegamento a sua
volta]
<client> [termina il plugin]
Sistema di sostituzione dell'output
Il sistema di sostituzione dell'output e' molto utile quando il plug-in
in questione non solo deve eseguire un'azione in base alle informazioni
che riceve, ma deve modificarle per nascondere qualcosa di inutile
all'utente oppure mostrare altre informazioni (come nel caso del plug-in
per il Mud Sound Protocol, che utilizza questa tecnica per nascondere
le sequenze del MSP). Il metodo funziona praticamente cosi':
il client invia ad ogni plug-in abilitato un messaggio 002 ogni volta
che riceve una stringa dal mud. Il plug-in deve analizzare quella
stringa e decidere se vuole modificarla o meno, se non vuole modificarla
deve inviare un messaggio di risposta 011; se, al contrario, vuole
modificarla dovra' apportare le modifiche e rispondere con un messaggio
012 accodando la nuova stringa di output (vedi Protocollo per
le definizioni dei messaggi). Un client abilitato a bloccare l'output
deve _sempre_ rispondere ad un messaggio 002 o con uno 011 o con uno
012, poiche' il client resta in attesa della risposta per 5 secondi
prima di ignorarla e dare per scontato che il plug-in non voglia modificare
l'output.
Plug-ins di esempio
Per ora un vero e proprio plug-in di esempio non e' disponibile,
metto a disposizione di tutti pero' i sorgenti di quelli che sono
gli unici due plug-ins che ho scritto. In futuro rendero' disponibile
un plug-in di esempio completamente commentato ed un programma che
emuli il GosClient per eseguire il debug piu' agevolmente. Il codice
e' liberamente riutilizzabile (compresa la classe CAlexfMixer che
non ho scritto io).
|
Pacchetto
|
Dimensione
|
Contenuto |
Linguaggio
|
|
|
|
|
|
|
|
22 Kb
|
Sorgenti del Mud Sound Protocol Plug-In versione
1.1
Progetto per Visual C++ 6. |
C++/MFC |
|
|
|
|
|
|
|
19 Kb
|
Sorgenti del plug-in per il tastierino numerico
versione 1.0
Progetto per Visual C++ 6. |
C++/MFC |
|
|
|
|
|
Conclusione
Sono a disposizione per qualsiasi chiarimento su questa piccola guida
e sui miei sorgenti, scrivete ogni dubbio a questo
indirizzo email, vi rispondero' appena possibile.
Vi prego anche di informarmi qualora abbiate in progetto di sviluppare
un plug-in per il mio client, grazie :).
|