Salta ai contenuti

Eventi e timer

Questa pagina fa parte di Scrivere script Lua. Le funzioni sono elencate nella guida di riferimento: events e timer.

Salva questo listener come scripts/common/character_log.lua:

local character_log = {}
character_log.handle = events.on("character_created", function(e)
log.info("New character {Name}", e.name)
end)
return character_log

Aggiungi require("common.character_log") al scripts/init.lua esistente, conservando il resto del codice. Avvia il server oppure inserisci script reload init.lua nella console del server. Crea un nuovo personaggio dal client: il log della console deve mostrare New character seguito dal suo nome. Accedere con un personaggio esistente non genera character_created.

Conserva la tabella restituita dal modulo se vuoi annullare l’iscrizione in seguito. Per rimuovere deliberatamente il listener, esegui questo da codice che richiede lo stesso modulo:

local character_log = require("common.character_log")
events.off(character_log.handle) -- returns false when the handle is unknown

Il secondo blocco serve alla pulizia; non aggiungerlo alla prima prova, altrimenti il listener verrà rimosso prima che si possa creare un personaggio.

  • Ogni handler viene eseguito sul ciclo di gioco come coroutine, quindi può chiamare wait().
  • Gli handler di un evento vengono eseguiti nell’ordine di iscrizione. Iscriversi o annullare l’iscrizione dentro un handler ha effetto dall’evento successivo.
  • Ogni handler riceve una propria tabella; modificarla non influisce sugli altri handler.
  • Gli eventi sono notifiche: un handler non può annullare o modificare ciò che è accaduto. Un errore in un handler viene segnalato come qualsiasi errore di script, e gli altri handler vengono comunque eseguiti.
  • Le iscrizioni appartengono al file che le ha create. Ricaricare o invalidare il file le rimuove, come i suoi timer; arrestare il motore le rimuove tutte.
  • Un nome evento sconosciuto genera un errore in events.on. Il file generato definitions.lua elenca i nomi validi come alias EventName, così gli editor li completano.

Evento Campi
character_created serial, account_id, name, race e gender (numeri della razza e del genere; gli script non ricevono tabelle enum per essi), map, x, y, z. Generato dopo il salvataggio di un nuovo personaggio e dei suoi oggetti iniziali.
character_deletion_requested serial, account_id, name. Generato dopo che un giocatore chiede di eliminare un personaggio; resta ripristinabile fino alla rimozione.
character_entered_world serial, account_id, name, map, x, y, z. Generato dopo che un personaggio è entrato nel mondo e il login del client è stato completato.
player_say serial, name, text, type. Generato dopo che il personaggio di un giocatore ha detto qualcosa e i giocatori e NPC intorno lo hanno sentito; text è ciò che hanno sentito e type il modo in cui è stato detto, un numero come SpeechType.Yell. Un comando (testo che inizia con un punto) non genera nulla.
character_left_world serial, account_id, name, map, x, y, z. Generato dopo che un personaggio ha lasciato il mondo perché la sessione si è chiusa, una volta tentato il salvataggio.
player_region_changed serial, name, previous, current, map, x, y, z. Generato quando il personaggio di un giocatore cammina o viene teletrasportato da una regione a un’altra, o cambia mappa; previous e current sono i nomi delle regioni, nil fuori da ogni regione, e previous è anche nil quando il personaggio è appena entrato nel mondo
item_created serial, template (nil quando l’oggetto non ne ha uno). Generato quando un nuovo oggetto è entrato nel mondo: creato da uno script, da un venditore, da uno spawn o da un mestiere. Ciò che viene caricato all’avvio o a un login, il resto di una pila divisa, gli oggetti che .decorate posiziona e quelli che un allegato di libro sistema non generano nulla.
item_deleted serial, template. Generato quando un oggetto è stato eliminato: decadimento, unione in una pila, item.delete, l’equipaggiamento di un NPC rimosso. Il logout non genera nulla.
mobile_created serial, template. Generato quando un NPC è stato fatto comparire, anche un animale uscito da una stalla, un animale cavalcato che è stato fatto scendere o un animale legato risollevato dal suo cadavere: la creatura ha ogni volta un nuovo seriale. Gli NPC caricati all’avvio non generano nulla, e una statuetta eterea non crea alcuna creatura.
mobile_deleted serial, template. Generato quando un NPC ha lasciato il mondo: dopo la sua morte, .remove, un animale che è entrato in una stalla, o un animale che è stato montato ed è diventato l’oggetto cavalcatura che il suo cavaliere indossa. Un animale che torna ha un nuovo seriale.
mobile_died serial, killer, corpse (0 se non c’è). Generato quando un giocatore o un NPC è morto; un corpo umano lo genera quando la sua caduta è finita.
pet_tamed serial (l’animale), tamer. Generato quando una creatura è diventata di un giocatore, con pet.tame o .tame.
craft_succeeded actor, craft (l’id del mestiere), item (il seriale di ciò che è stato creato). Generato dallo script di creazione condiviso quando un tentativo è riuscito; un tentativo fallito non genera nulla.
corpse_carved serial (il cadavere), carver, items (quanti oggetti sono stati creati, dentro il cadavere o accanto a esso, con una pila che conta come uno). Generato quando un coltello ha tolto oggetti da un cadavere (carve.corpse); un’operazione che non ha trovato nulla non genera nulla.
party_invite party_id, leader, invitee. Generato quando un capo ha invitato un giocatore; party_id è il numero del gruppo, conservato finché il server è in esecuzione.
party_joined party_id, member. Generato quando un giocatore invitato ha accettato ed è entrato nel gruppo.
party_left party_id, member, reason (left, kicked o logout). Generato quando un membro non è più nel gruppo, anche quello la cui uscita lo scioglie.
party_disbanded party_id, reason (too_small quando restavano meno di due membri, emptied quando è terminato l’ultimo invito dell’unico membro). Generato quando un gruppo non esiste più.

Gli ultimi dodici sono notifiche del mondo, non di un personaggio: il server pubblica ciascuno solo mentre uno script lo ascolta, quindi un evento a cui nessuno è iscritto costa una ricerca. Gli hook degli script li elencano accanto agli hook e dicono cosa non è stato costruito.

Ogni consegna è un elemento di lavoro del ciclo di gioco. Un riempimento di massa con un ascoltatore su item_created, come uno spawn o uno script che crea migliaia di oggetti, accoda un elemento di lavoro per ogni oggetto; quando la coda del ciclo è piena gli eventi vengono scartati, con un avviso nel log.

Host e plugin pubblicano un evento del bus verso Lua con una registrazione esplicita, prima che il motore si avvii:

container.AddScriptEvent<MyEvent>(
"my_event",
e => new Dictionary<string, object?> { ["name"] = e.Name, ["amount"] = e.Amount });

Il nome deve essere snake_case e univoco, e ogni tipo di evento viene pubblicato una volta. La mappatura viene eseguita sul thread di pubblicazione e deve solo leggere l’evento. Può restituire stringhe, booleani, numeri, enum (inviati come numeri) o null. Una mappatura che fallisce viene registrata nel log, e l’evento viene saltato solo per Lua. Gli eventi pubblicati quando nessuno script è iscritto costano una ricerca e non vengono accodati.

Tutti i ritardi dei timer e gli argomenti di wait sono in secondi.

timer.after esegue una funzione una volta, timer.every la ripete e timer.cancel arresta entrambi; wait sospende la coroutine che lo chiama.

Chiama wait da una coroutine pianificata, come una callback di timer, non al livello principale di init.lua o di un modulo richiesto. Serve un ritardo positivo e finito che rientri nell’intervallo del timer. Cede la coroutine invece di bloccare il thread. Ogni occorrenza di un timer ripetuto avvia una coroutine: se una chiama wait per un tempo superiore all’intervallo di ripetizione, più invocazioni sospese possono coesistere. Annullare il timer impedisce avvii successivi; non annulla una coroutine già avviata. Per sequenze che non devono sovrapporsi, usa una callback singola che pianifica la propria esecuzione successiva solo dopo aver terminato il lavoro.

Creato con ❤️ da Tom

Offrimi un caffè