Networking 26.1.2
Una guida generale sul networking con l'API di Fabric.
Il networking in Minecraft si usa affinché client e server possano comunicare tra loro. Il networking è un argomento ampio, per cui questa pagina è suddivisa in diverse categorie.
Qual È l'Importanza del Networking?
I pacchetti sono il concetto fondamentale del networking in Minecraft. I pacchetti sono costituiti da dati arbitrari che possono essere inviati dal server al client o dal client al server. Dai un'occhiata al diagramma qui sotto, che fornisce una rappresentazione visiva dell'architettura di rete in Fabric:

Nota come i pacchetti fungano da ponte tra il server e il client; questo perché quasi tutto ciò che fai nel gioco coinvolge il networking in qualche modo, che tu lo sappia o meno. Ad esempio, quando invii un messaggio in chat, un pacchetto viene inviato al server con il contenuto. Il server quindi invia un altro pacchetto a tutti gli altri client con il tuo messaggio.
Una cosa importante da tenere a mente è che c'è sempre un server in esecuzione, anche in singleplayer o LAN. I pacchetti vengono ancora utilizzati per la comunicazione tra client e server, anche quando nessun altro sta giocando con te. Quando si parla di lati nel networking, si utilizzano i termini "client logico" e "server logico". Il server integrato per singleplayer/LAN e il server dedicato sono entrambi server logici, ma solo il server dedicato può essere considerato un server fisico.
Quando lo stato non è sincronizzato tra client e server, possono verificarsi problemi in cui il server o altri client non concordano su ciò che un altro client sta facendo. Questo fenomeno è spesso noto come "desync". Quando scrivi la tua mod, potresti dover inviare un pacchetto di dati per mantenere sincronizzato lo stato del server e di tutti i client.
Introduzione al Networking
Definire un Payload
INFO
Un payload sono i dati che vengono inviati in un pacchetto.
Questo può essere fatto creando un Record Java con un parametro BlockPos che implementi CustomPacketPayload.
java
No lines matched.1
Allo stesso tempo, abbiamo definito:
- Un
Identifierutilizzato per identificare il payload del nostro pacchetto. Per questo esempio, il nostro identificatore saràexample-mod:summon_lightning.
java
// #region identifier1
- Un'istanza pubblica statica di
CustomPayload.Typeper identificare in modo univoco questo payload personalizzato. Faremo riferimento a questo ID sia nel codice comune che in quello client.
java
public static final Identifier SUMMON_LIGHTNING_PAYLOAD_ID = Identifier.fromNamespaceAndPath(ExampleMod.MOD_ID, "summon_lightning");1
- Un'istanza pubblica statica di
StreamCodecaffinché il gioco sappia come serializzare/deserializzare i contenuti del pacchetto.
java
// #endregion identifier1
Abbiamo anche fatto override di type per restituire l'ID del nostro payload.
java
// #region payload_type
public static final CustomPacketPayload.Type<ClientboundSummonLightningPayload> TYPE = new CustomPacketPayload.Type<>(SUMMON_LIGHTNING_PAYLOAD_ID);
// #endregion payload_type1
2
3
4
2
3
4
Registrare un Payload
Prima di inviare un pacchetto con il nostro payload personalizzato, dobbiamo registrarlo su entrambi i lati fisici.
Questo si può fare nel nostro initializer comune usando PayloadTypeRegistry.clientboundPlay().register che accetta un CustomPayload.Type e un StreamCodec.
java
// #region clientbound1
Esiste un metodo simile per registrare i payload da client a server: PayloadTypeRegistry.serverboundPlay().register.
Inviare un Pacchetto al Client
Per inviare un pacchetto con il nostro payload personalizzato, possiamo usare ServerPlayNetworking.send che accetta un ServerPlayer e un CustomPayload.
Iniziamo creando il nostro oggetto Lightning Tater. Puoi fare override di use per attivare un'azione quando l'oggetto viene utilizzato. In questo caso, inviamo pacchetti ai giocatori nel livello del server.
java
No lines matched.1
Esaminiamo il codice sopra.
Inviamo pacchetti solo quando l'azione viene avviata sul server, uscendo anticipatamente con un controllo isClientSide():
java
// #region client_check
if (level.isClientSide()) {
return InteractionResult.PASS;1
2
3
2
3
Creiamo un'istanza del payload con la posizione dell'utente:
java
// #endregion client_check1
Infine, otteniamo i giocatori nel livello del server tramite PlayerLookup e inviamo un pacchetto a ciascun giocatore.
java
// #region payload_instance
ClientboundSummonLightningPayload payload = new ClientboundSummonLightningPayload(user.blockPosition());
// #endregion payload_instance1
2
3
2
3
INFO
L'API di Fabric fornisce PlayerLookup, una serie di funzioni ausiliarie che andranno a cercare i giocatori in un server.
Un termine usato di frequente per descrivere la funzionalità di questi metodi è "tracking" (tracciamento). Ciò significa che un'entità o un chunk sul server sono noti al client di un giocatore (all'interno della sua distanza di visualizzazione), e che l'entità o l'entità-blocco dovrebbe notificare i client che la stanno tracciando di eventuali cambiamenti.
Il tracciamento è un concetto importante per un networking efficiente, così che solo i giocatori necessari vengano notificati dei cambiamenti tramite l'invio di pacchetti.
Ricevere un Pacchetto sul Client
Per ricevere un pacchetto inviato da un server sul client, devi specificare come gestirai il pacchetto in arrivo.
Questo si può fare nell'initializer del client, chiamando ClientPlayNetworking.registerGlobalReceiver e passando un CustomPayload.Type e un PlayPayloadHandler, che è un'interfaccia funzionale.
In questo caso, definiremo l'azione da attivare all'interno dell'implementazione di PlayPayloadHandler (come espressione lambda).
java
No lines matched.1
Esaminiamo il codice sopra.
Possiamo accedere ai dati dal nostro payload chiamando i metodi getter del Record. In questo caso payload.pos(). Che può poi essere usato per ottenere le coordinate x, y e z.
java
// #region payload_pos1
Infine, creiamo una LightningBolt e aggiungiamola al livello.
java
BlockPos lightningPos = payload.pos();
// #endregion payload_pos
// #region lightning_bolt
LightningBolt entity = EntityType.LIGHTNING_BOLT.create(level, EntitySpawnReason.TRIGGERED);1
2
3
4
5
6
2
3
4
5
6
Ora, aggiungendo questa mod a un server, e quando un giocatore usa il nostro oggetto Lightning Tater, ogni giocatore vedrà un fulmine colpire la posizione dell'utente.
Inviare un Pacchetto al Server
Come per l'invio di un pacchetto al client, iniziamo creando un payload personalizzato. Questa volta, quando un giocatore usa una Patata Velenosa su un'entità vivente, chiediamo al server di applicare l'effetto Luminescenza su di essa.
java
No lines matched.1
Passiamo il codec appropriato insieme a un riferimento al metodo per ottenere il valore dal Record per costruire questo codec.
Poi registriamo il nostro payload nel nostro initializer comune. Ma, questa volta, come payload Client-to-Server, utilizzando PayloadTypeRegistry.serverboundPlay().register.
java
PayloadTypeRegistry.clientboundPlay().register(ClientboundSummonLightningPayload.TYPE, ClientboundSummonLightningPayload.CODEC);1
Per inviare un pacchetto, aggiungiamo un'azione per quando il giocatore usa una Patata Velenosa. Utilizzeremo l'evento UseEntityCallback per mantenere il codice conciso.
Registriamo l'evento nel nostro initializer del client, e usiamo isClientSide() per assicurarci che l'azione venga attivata solo sul client logico.
java
No lines matched.1
Creiamo un'istanza del nostro GiveGlowingEffectServerboundPayload con gli argomenti necessari. In questo caso, l'ID di rete dell'entità bersaglio.
java
}1
Infine, inviamo un pacchetto al server chiamando ClientPlayNetworking.send con l'istanza del nostro GiveGlowingEffectServerboundPayload.
java
1
Ricevere un Pacchetto sul Server
Questo può essere fatto nell'initializer comune, chiamando ServerPlayNetworking.registerGlobalReceiver e passando un CustomPayload.Type e un PlayPayloadHandler.
java
No lines matched.1
INFO
È importante che convalidare il contenuto del pacchetto lato server.
In questo caso, verifichiamo se l'entità esiste in base al suo ID di rete.
java
// #endregion serverbound1
Inoltre, l'entità-bersaglio deve essere un'entità vivente, e limitiamo la distanza tra il giocatore e l'entità-bersaglio a 5.
java
ServerPlayNetworking.registerGlobalReceiver(GiveGlowingEffectServerboundPayload.TYPE, (payload, context) -> {1
Ora, quando un giocatore cerca di usare una Patata Velenosa su un'entità vivente, l'effetto Luminescenza verrà applicato.

















