Créer une structure multiblocks
-
Sommaire
Introduction
Nous allons voir comment créer une structure multi-block.
Tout d’abord qu’est ce qu’une structure multi-block ? C’est un ensemble de bloc qui une fois disposés
correctement, forment un ensemble.Pré-requis
Code
La classe principale :
Déclarez votre bloc dans votre classe principale, pour ce tutoriel il s’appellera multiBlockTuto
public static Block multiBlockTuto;
Puis instanciez-le et enregistrez-le dans la fonction preInit
multiBlockTuto = new BlockMultiBlockTuto(); GameRegistry.registerBlock(multiBlockTuto, "multiblocktuto");
Créez la classe BlockMultiBlockTuto.
La classe du bloc :
La classe du bloc devrait être extends Block, si ce n’est pas le cas, faites-le.
Implémentez ensuite l’interface ITileEntityProviderpublic class BlockMultiBlockTuto extends Block implements ITileEntityProvider
Définissez le constructeur comme pour un bloc normal.
On ajoute maintenant la fonction permettant de créer le TileEntity
@Override public TileEntity createNewTileEntity(World worldIn, int meta) { return new TileEntityMultiBlockTuto(); }
Créez la classe TileEntityMultiBlockTuto.
La classe du TileEntity
La structure que nous allons créer est une structure de 1 de hauteur, 3 de largeur, 3 de longueur,
ce qui nous fait une structure composée de 331 = 9 blocs.Le concept sera le suivant, dans toute la structure il y aura un bloc qui sera,
dit ‘master’ et les autres ne feront que vérifier que ce block existe. C’est dans ce master
que toute les informations que vous voudrez enregistrer dans la structure devront se trouver.Chaque bloc, quelqu’il soit, aura 5 variables qui définira sont état :
- Est-t-il oui ou non master (1 variable)
- As-t-il oui ou non un master (1 variable)
- Quels sont les coordonnées du master (3 variables x, y, z)
Ainsi on déclare chaque variable et on les enregistres dans les NBT
private boolean hasMaster = false; private boolean isMaster = false; private int masterX = 0; private int masterY = 0; private int masterZ = 0; @Override public void readFromNBT(NBTTagCompound compound) { super.readFromNBT(compound); this.hasMaster = compound.getBoolean("HasMaster"); this.isMaster = compound.getBoolean("IsMaster"); this.masterX = compound.getInteger("MasterX"); this.masterY = compound.getInteger("MasterY"); this.masterZ = compound.getInteger("MasterZ"); } @Override public void writeToNBT(NBTTagCompound compound) { super.writeToNBT(compound); compound.setBoolean("HasMaster", hasMaster); compound.setBoolean("IsMaster", isMaster); compound.setInteger("MasterX", masterX); compound.setInteger("MasterY", masterY); compound.setInteger("MasterZ", masterZ); }
Suite à ça ajoutons directement les getter et setter
public boolean hasMaster() { return this.hasMaster; } public boolean isMaster() { return this.isMaster; } public int getMasterX() { return this.masterX; } public int getMasterY() { return this.masterY; } public int getMasterZ() { return this.masterZ; } public void setMaster(int x, int y, int z) { this.hasMaster = true; this.masterX = x; this.masterY = y; this.masterZ = z; }
Nous allons maintenant créer une fonction afin de vérifier la présense
d’une structure, chaque bloc va essayer de créer une structure dans il est
master tant qu’il ne sera ou n’aura pas de master.
Pour vérifier la structure on va se baser sur le bloc du milieux de notre
carré de 3 par 3.private boolean checkStructure() { int n = 0; for(int x = this.pos.getX() - 1; x < this.pos.getX() + 2; x++) { for(int z = this.pos.getZ() - 1; z < this.pos.getZ() + 2; z++) { BlockPos position = new BlockPos(x, this.pos.getY(), z); TileEntity tile = worldObj.getTileEntity(position); if(tile != null && tile instanceof TileEntityMultiBlockTuto) { TileEntityMultiBlockTuto t = (TileEntityMultiBlockTuto)tile; if(t.hasMaster) { if(this.pos.getX() == t.getMasterX() && this.pos.getY() == t.getMasterY() && this.pos.getZ() == t.getMasterZ()) { n++; } } else { n++; } } } } if(n == 9) { return true; } return false; }
On compte le nombre de bloc qui n’ont pas de master ou qui ont pour master le bloc qui check.
Si il est égal à 9, le nombre de bloc dans la structure alors c’est bon, dans ce cas on met
en place la structure en indiquant à chaque bloc la place du master et le fait qu’il ai un master.private void setupStructure() { for(int x = this.pos.getX() - 1; x < this.pos.getX() + 2; x++) { for(int z = this.pos.getZ() - 1; z < this.pos.getZ() + 2; z++) { BlockPos position = new BlockPos(x, this.pos.getY(), z); TileEntity tile = worldObj.getTileEntity(position); if(tile != null && tile instanceof TileEntityMultiBlockTuto) { TileEntityMultiBlockTuto t = (TileEntityMultiBlockTuto)tile; t.setMaster(this.pos.getX(), this.pos.getY(), this.pos.getZ()); this.isMaster = true; } } } }
Vous verrez que une fois la structure faite nous allons re-vérifier son intégrité, dans le cas
où elle n’est plus correcte, il va falloir indiquer à chaque bloc que c’est fini, il n’y a plus
de structure.
Il faut donc une fonction qui reset la structure, qui sera exécutée par le master et une qui reset
juste le bloc qui sera appelée dans la boucle pour reset la structure.private void resetStructure() { for(int x = this.pos.getX() - 1; x < this.pos.getX() + 2; x++) { for(int z = this.pos.getZ() - 1; z < this.pos.getZ() + 2; z++) { BlockPos position = new BlockPos(x, this.pos.getY(), z); TileEntity tile = worldObj.getTileEntity(position); if(tile != null && tile instanceof TileEntityMultiBlockTuto) { TileEntityMultiBlockTuto t = (TileEntityMultiBlockTuto)tile; t.reset(); } } } } public void reset() { this.isMaster = false; this.hasMaster = false; this.masterX = 0; this.masterY = 0; this.masterZ = 0; }
Dans le cas où le master est détruit, il ne pourra pas reset la structure, il faut alors que chaque
bloc vérifie si le master existe encoreprivate boolean checkForMaster() { BlockPos position = new BlockPos(masterX, masterY, masterZ); TileEntity tile = worldObj.getTileEntity(position); if(tile != null && tile instanceof TileEntityMultiBlockTuto) { TileEntityMultiBlockTuto t = (TileEntityMultiBlockTuto)tile; if(t.isMaster()) { return true; } } return false; }
Les deux fonctions concernant les packets
@Override public Packet getDescriptionPacket() { NBTTagCompound nbttagcompound = new NBTTagCompound(); this.writeToNBT(nbttagcompound); return new S35PacketUpdateTileEntity(this.getPos(), this.getBlockMetadata(), nbttagcompound); } @Override public void onDataPacket(NetworkManager net, S35PacketUpdateTileEntity pkt) { this.readFromNBT(pkt.getNbtCompound()); this.worldObj.markBlockRangeForRenderUpdate(this.pos, this.pos); }
Implémentez la classe de l’interface IUpdatePlayerListBox
La fonction update est appellée à chaque update du bloc, on y appeler nos fonctions,
mais réfléchissons à la façon dont nous allons nous y prendre.public void update() {}
Tout d’abord si le bloc est un master il va devoir vérifier la structure,
si elle n’est plus correcte alors on la resetif(this.isMaster) { if(!this.checkStructure()) { this.resetStructure(); } }
Sinon si il a un master, on doit vérifier si sont master est encore là,
sinon on reset le blocelse if(this.hasMaster) { if(!checkForMaster()) { this.reset(); } }
Sinon si il n’a pas de master alors il doit il va essayer de créer une structure
else if(!this.hasMaster) { if(this.checkStructure()) { this.setupStructure(); } }
La situation de notre bloc a changé, on le signal.
this.markDirty();
Voilà, tout fonctionne, les autres variables que vous voudriez enregistrer doivent êtres enregistrer dans le master
seulement, mettez donc une condition dans les fonctions read et write et n’oubliez pas de reset les variables
dans la fonction reset.Bonus
Une idée ?
Résultat
Pour une plus grande clartée j’ai ajouté des blocstates, chaque situation
à sa propre couleur, rouge si le bloc ne fait pas partie d’une structure,
rose si il fait partie d’une structure mais qu’il n’est pas master, et
jaune si il est master. -
Tutoriel intéressant mais quelques problèmes dans le code : dans ta fonction checkStructure et setupStructure, d’où sort le “pos” ? Si c’est une variable de la TileEntity, mets un this.pos sinon on peut difficilement comprendre.
De plus, à quoi sert le “else if (!t.hasMaster)” ? Un simple else suffit :
if(t.hasMaster) { if(pos.getX() == t.getMasterX() && pos.getY() == t.getMasterY() && pos.getZ() == t.getMasterZ()) { n++; } } else if(!t.hasMaster) { n++; }
-
Efectivement pos est une variable de la classe TileEntity, je mettrai le this (le week-end prochain) et pour le else if pareil, c’est vrai qu’il ne sert à rien
EDIT : mis à jour
-
Salut les gens, juste pour savoir, ce tuto marche-t-il aussi en 1.7.10?
Des fonctions que j’ai pu voir logiquement oui, mais je ne suis pas certain. -
Il faut adapter les blocs pos par x, y z et les block state par les metadata et normalement c’est bon.
-
pour l’ider tu pourrai four une structure mais avec un gui et fait une machine ?
-
comment on fait pour faire une condition ex jene veux que mon block de base ne fasse rien et que mon multiblock,si il y a dde l’orage imprimer dans le chat il u a l’orage(je sais il faut un
System.out.println("c'est orageux")
)mais quand meme