Minecraft Modding 1.12.2
Le développement de mod de Minecraft continue d'être difficile à comprendre en raison de petites différences non seulement dans la grande version mais aussi dans la petite version. Donc je ne sais pas si cela aidera les utilisateurs qui sont arrivés à cet article, mais j'espère que ce sera un indice.
Si vous voulez vérifier le code source directement, veuillez vous référer à Github.
Je prévois de créer les contenus suivants à tout moment.
J'étudie moi-même encore, donc si vous trouvez des erreurs dans l'explication, veuillez commenter.
Veuillez créer l'environnement de développement en vous référant à ici.
Créez un répertoire jp / artan / tm
dans le répertoire src / main / java
, et créez un `TutorialMod.java 'dans ce répertoire.
src/main/java/jp/artan/tm/TutorialMod.java
package jp.artan.tm;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.common.event.FMLConstructionEvent;
import net.minecraftforge.fml.common.event.FMLInitializationEvent;
import net.minecraftforge.fml.common.event.FMLPostInitializationEvent;
import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;
import org.apache.logging.log4j.Logger;
@Mod(modid = TutorialMod.MODID, name = TutorialMod.NAME, version = TutorialMod.VERSION)
public class TutorialMod
{
public static final String MODID = "tm";
public static final String NAME = "Tutorial Mod";
public static final String VERSION = "1.0";
public static Logger logger;
@Mod.EventHandler
public void construct(FMLConstructionEvent event) {
}
@Mod.EventHandler
public void preInit(FMLPreInitializationEvent event) {
logger = event.getModLog();
logger.info("TutorialMod.preInit");
}
@Mod.EventHandler
public void init(FMLInitializationEvent event) {
logger.info("TutorialMod.init");
}
@Mod.EventHandler
public void postInit(FMLPostInitializationEvent event) {
logger.info("TutorialMod.postInit");
}
}
Tous les fichiers java à créer à partir de maintenant seront expliqués en fonction de src / main / java / jp / artan / tm
.
De plus, les données png telles que les textures et les données json seront expliquées en fonction de src / main / assets / tm
.
Le proxy est un mécanisme pour déterminer si c'est le client / serveur qui a appelé le Mod et qui appelle automatiquement l'événement approprié. La raison pour laquelle ce mécanisme est nécessaire est que les informations de modèle requises pour les éléments expliqués ci-dessous ne doivent pas être exécutées sur le serveur.
Maintenant, créez le fichier suivant.
proxy/CommonProxy.java
package jp.artan.tm.proxy;
import jp.artan.tm.TutorialMod;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.common.event.FMLInitializationEvent;
import net.minecraftforge.fml.common.event.FMLPostInitializationEvent;
import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;
@Mod.EventBusSubscriber(modid = TutorialMod.MODID)
public abstract class CommonProxy {
public void preInit(FMLPreInitializationEvent event) {
TutorialMod.logger.info("CommonProxy.preInit");
}
public void init(FMLInitializationEvent event) {
TutorialMod.logger.info("CommonProxy.init");
}
public void postInit(FMLPostInitializationEvent event) {
TutorialMod.logger.info("CommonProxy.postInit");
}
}
proxy/ClientProxy.java
package jp.artan.tm.proxy;
import jp.artan.tm.TutorialMod;
import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;
public class ClientProxy extends CommonProxy {
@Override
public void preInit(FMLPreInitializationEvent event) {
super.preInit(event);
TutorialMod.logger.info("ClientProxy.preInit");
}
}
proxy/ServerProxy.java
package jp.artan.tm.proxy;
public class ServerProxy extends CommonProxy {
//Je n'expliquerai pas le serveur cette fois, donc je ne décrirai rien
//Créez et utilisez preinit etc. selon vos besoins.
}
Décrivez le traitement courant pour le client / serveur dans CommonProxy
, et décrivez le traitement à effectuer uniquement par chacun dans ClientProxy
et ServerProxy
.
Ensuite, «ClientProxy» et «ServerProxy» sont automatiquement sélectionnés et le processus pour les appeler est décrit dans «TutorialMod.java». L'endroit où il est écrit comme note supplémentaire dans le commentaire est celui ajouté cette fois.
TutorialMod.java
package jp.artan.tm;
import jp.artan.tm.proxy.CommonProxy;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.common.SidedProxy;
import net.minecraftforge.fml.common.event.FMLConstructionEvent;
import net.minecraftforge.fml.common.event.FMLInitializationEvent;
import net.minecraftforge.fml.common.event.FMLPostInitializationEvent;
import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;
import org.apache.logging.log4j.Logger;
@Mod(modid = TutorialMod.MODID, name = TutorialMod.NAME, version = TutorialMod.VERSION)
public class TutorialMod
{
public static final String MODID = "tm";
public static final String NAME = "Tutorial Mod";
public static final String VERSION = "1.0";
public static Logger logger;
public static final String CLIENT_PROXY = "jp.artan." + MODID + ".proxy.ClientProxy"; //Postscript
public static final String SERVER_PROXY = "jp.artan." + MODID + ".proxy.ServerProxy"; //Postscript
@SidedProxy(clientSide = CLIENT_PROXY, serverSide = SERVER_PROXY) //Postscript
public static CommonProxy proxy; //Postscript
@Mod.EventHandler
public void construct(FMLConstructionEvent event) {
MinecraftForge.EVENT_BUS.register(proxy); //Postscript
}
@Mod.EventHandler
public void preInit(FMLPreInitializationEvent event) {
logger = event.getModLog();
logger.info("TutorialMod.preInit");
proxy.preInit(event); //Postscript
}
@Mod.EventHandler
public void init(FMLInitializationEvent event) {
logger.info("TutorialMod.init");
proxy.init(event); //Postscript
}
@Mod.EventHandler
public void postInit(FMLPostInitializationEvent event) {
logger.info("TutorialMod.postInit");
proxy.postInit(event); //Postscript
}
}
J'expliquerai en extrayant une partie.
.java
public static final String CLIENT_PROXY = "jp.artan." + MODID + ".proxy.ClientProxy";
public static final String SERVER_PROXY = "jp.artan." + MODID + ".proxy.ServerProxy";
@SidedProxy(clientSide = CLIENT_PROXY, serverSide = SERVER_PROXY)
public static CommonProxy proxy;
L'annotation «SidedProxy» attachée à la variable «proxy» est importante.
En spécifiant cette annotation, une instance est automatiquement générée en fonction des informations de répertoire de fichiers spécifiées de clientSide
et serverSide
et stockée dans une variable.
** * Le chemin spécifié à ce moment sera le chemin basé sur src / main / java
**
Si vous démarrez le client et le serveur à ce stade, vous pouvez voir que chaque instance est préparée automatiquement.
runClient.log
[17:25:39] [Client thread/INFO] [tm]: TutorialMod.preInit
[17:25:39] [Client thread/INFO] [tm]: CommonProxy.preInit
[17:25:39] [Client thread/INFO] [tm]: ClientProxy.preInit
[17:25:44] [Client thread/INFO] [tm]: TutorialMod.init
[17:25:44] [Client thread/INFO] [tm]: CommonProxy.init
[17:25:44] [Client thread/INFO] [tm]: TutorialMod.postInit
[17:25:44] [Client thread/INFO] [tm]: CommonProxy.postInit
runServer.log
[17:33:43] [Server thread/INFO] [tm]: TutorialMod.preInit
[17:33:43] [Server thread/INFO] [tm]: CommonProxy.preInit
[17:33:43] [Server thread/INFO] [tm]: TutorialMod.init
[17:33:43] [Server thread/INFO] [tm]: CommonProxy.init
[17:33:44] [Server thread/INFO] [tm]: TutorialMod.postInit
[17:33:44] [Server thread/INFO] [tm]: CommonProxy.postInit
Ensuite, je voudrais implémenter un élément qui n'a pas de fonction. Avant cela, nous allons créer un mécanisme pour enregistrer les éléments dans le registre gemé et le Model Loder à la fois.
event/IItemRegisterEvent.java
package jp.artan.tm.event;
import net.minecraft.item.Item;
import net.minecraftforge.client.event.ModelRegistryEvent;
import net.minecraftforge.event.RegistryEvent;
public interface IItemRegisterEvent {
/**
* Register Item
*
* @param event
*/
void registerItem(RegistryEvent.Register<Item> event);
/**
* Register Model
*
* @param event
*/
void registerModel(ModelRegistryEvent event);
}
init/ItemInit.java
package jp.artan.tm.init;
import jp.artan.tm.event.IItemRegisterEvent;
import java.util.ArrayList;
import java.util.List;
public class ItemInit {
public static final List<IItemRegisterEvent> ITEMS = new ArrayList<IItemRegisterEvent>();
}
proxy/CommonProxy.java
package jp.artan.tm.proxy;
import jp.artan.tm.TutorialMod;
import jp.artan.tm.init.ItemInit;
import net.minecraft.item.Item;
import net.minecraftforge.event.RegistryEvent;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.common.event.FMLInitializationEvent;
import net.minecraftforge.fml.common.event.FMLPostInitializationEvent;
import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
@Mod.EventBusSubscriber(modid = TutorialMod.MODID)
public abstract class CommonProxy {
public void preInit(FMLPreInitializationEvent event) {
TutorialMod.logger.info("CommonProxy.preInit");
}
public void init(FMLInitializationEvent event) {
TutorialMod.logger.info("CommonProxy.init");
}
public void postInit(FMLPostInitializationEvent event) {
TutorialMod.logger.info("CommonProxy.postInit");
}
//Ajouté ci-dessous
@SubscribeEvent
public void registerItems(RegistryEvent.Register<Item> event) {
TutorialMod.logger.info("CommonProxy.registerItems");
ItemInit.ITEMS.forEach(f -> f.registerItem(event));
}
//Ajouté ci-dessus
}
proxy/ClientProxy.java
package jp.artan.tm.proxy;
import jp.artan.tm.TutorialMod;
import jp.artan.tm.init.ItemInit;
import net.minecraftforge.client.event.ModelRegistryEvent;
import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
public class ClientProxy extends CommonProxy {
@Override
public void preInit(FMLPreInitializationEvent event) {
super.preInit(event);
TutorialMod.logger.info("ClientProxy.preInit");
}
//Ajouté ci-dessous
@SubscribeEvent
public void registerModels(ModelRegistryEvent event) {
TutorialMod.logger.info("ClientProxy.registerModels");
ItemInit.ITEMS.forEach(f -> f.registerModel(event));
}
//Ajouté ci-dessus
}
Les objets qui héritent de IItemRegisterEvent sont gérés collectivement par ITEMS et enregistrés un par un dans geméRegistry et ModelLoder. ** * L'événement registerModels ne doit être exécuté que sur le client. ** **
Maintenant, je voudrais enregistrer l'élément pour le sujet principal.
item/TutorialItem.java
package jp.artan.tm.item;
import jp.artan.tm.TutorialMod;
import jp.artan.tm.event.IItemRegisterEvent;
import jp.artan.tm.init.ItemInit;
import net.minecraft.client.renderer.block.model.ModelResourceLocation;
import net.minecraft.creativetab.CreativeTabs;
import net.minecraft.item.Item;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.client.event.ModelRegistryEvent;
import net.minecraftforge.client.model.ModelLoader;
import net.minecraftforge.event.RegistryEvent;
public class TutorialItem extends Item implements IItemRegisterEvent {
private final String name;
public TutorialItem(String name) {
super();
this.name = name;
this.setUnlocalizedName(this.name);
this.setRegistryName(TutorialMod.MODID, this.name);
this.setCreativeTab(CreativeTabs.MISC);
ItemInit.ITEMS.add(this);
}
@Override
public void registerItem(RegistryEvent.Register<Item> event) {
event.getRegistry().register(this);
}
public void registerModel(ModelRegistryEvent event) {
ModelLoader.setCustomModelResourceLocation(this, 0,
new ModelResourceLocation(new ResourceLocation(TutorialMod.MODID, this.name), "inventory"));
}
}
Après avoir créé TutorialItem, créez une instance avec ItemInit.
init/ItemInit.java
package jp.artan.tm.init;
import jp.artan.tm.event.IItemRegisterEvent;
import jp.artan.tm.item.TutorialItem;
import net.minecraft.item.Item;
import java.util.ArrayList;
import java.util.List;
public class ItemInit {
public static final List<IItemRegisterEvent> ITEMS = new ArrayList<IItemRegisterEvent>();
public static final Item TUTORIAL_ITEM = new TutorialItem("tutorial_item"); //Postscript
}
Si vous l'exécutez avec ceci, les éléments seront enregistrés dans l'onglet «Autre» comme indiqué ci-dessous.
En l'état, il est difficile à lire et la texture n'est pas définie, on ne peut donc pas dire qu'elle soit très utilisable. Alors, définissons la texture et la langue.
Cette fois, nous créons une instance comme new TutorialItem (" tutorial_item ")
, donc le nom de l'élément est tutorial_item
.
models/item/tutorial_item.json
{
"parent": "item/generated",
"textures": {
"layer0": "tm:items/tutorial_item"
}
}
textures/items/tutorial_item.png [] ** * Veuillez noter que l'image ne sera pas lue correctement à moins qu'elle ne mesure 16 pixels x 16 pixels. ** **
lang/en_us.lang
# English Language File
# Items
item.tutorial_item.name=Tutorial Item
lang/ja_jp.lang
#Fichier de langue japonaise
# Items
item.tutorial_item.name=Élément du didacticiel
** * Selon la version de Forge, ʻen_us.lang,
ja_jp.lang doit être spécifié comme ʻen_US.lang
, ja_JP.lang
. ** **
Il n'y a pas de problème s'il y a des données comme indiqué dans l'image suivante.
Les éléments et les blocs créés par moi-même constituent un certain groupe et je souhaite les enregistrer dans l'onglet Création. Cette fois, je voudrais créer un onglet tutoriel.
Je souhaite définir l'élément créé ci-dessus pour l'icône de l'onglet Création.
tab/TutorialTab.java
package jp.artan.tm.tab;
import jp.artan.tm.init.ItemInit;
import net.minecraft.creativetab.CreativeTabs;
import net.minecraft.item.ItemStack;
public class TutorialTab extends CreativeTabs {
public TutorialTab() {
super("tutorial_tab");
}
@Override
public ItemStack getTabIconItem() {
return new ItemStack(ItemInit.TUTORIAL_ITEM);
}
}
Assurez-vous de transmettre la chaîne transmise au constructeur CreativeTabs en minuscules. De plus, le nom spécifié ici sera la chaîne de caractères utilisée dans le paramètre de langue d'écriture.
lang/en_us.lang
# English Language File
# Tabs
itemGroup.tutorial_tab=Tutorial Tab
# Items
item.tutorial_item.name=Tutorial Item
lang/ja_jp.lang
#Fichier de langue japonaise
# Tabs
itemGroup.tutorial_tab=Onglet Tutoriel
# Items
item.tutorial_item.name=Élément du didacticiel
TutorialMod.java
package jp.artan.tm;
import jp.artan.tm.proxy.CommonProxy;
import jp.artan.tm.tab.TutorialTab;
import net.minecraft.creativetab.CreativeTabs;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.common.SidedProxy;
import net.minecraftforge.fml.common.event.FMLConstructionEvent;
import net.minecraftforge.fml.common.event.FMLInitializationEvent;
import net.minecraftforge.fml.common.event.FMLPostInitializationEvent;
import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;
import org.apache.logging.log4j.Logger;
@Mod(modid = TutorialMod.MODID, name = TutorialMod.NAME, version = TutorialMod.VERSION)
public class TutorialMod
{
public static final String MODID = "tm";
public static final String NAME = "Tutorial Mod";
public static final String VERSION = "1.0";
public static Logger logger;
public static final String CLIENT_PROXY = "jp.artan." + MODID + ".proxy.ClientProxy";
public static final String SERVER_PROXY = "jp.artan." + MODID + ".proxy.ServerProxy";
@SidedProxy(clientSide = CLIENT_PROXY, serverSide = SERVER_PROXY)
public static CommonProxy proxy;
public static CreativeTabs creativeTabs = new TutorialTab(); //Postscript
@Mod.EventHandler
public void construct(FMLConstructionEvent event) {
MinecraftForge.EVENT_BUS.register(proxy);
}
@Mod.EventHandler
public void preInit(FMLPreInitializationEvent event) {
logger = event.getModLog();
logger.info("TutorialMod.preInit");
proxy.preInit(event);
}
@Mod.EventHandler
public void init(FMLInitializationEvent event) {
logger.info("TutorialMod.init");
proxy.init(event);
}
@Mod.EventHandler
public void postInit(FMLPostInitializationEvent event) {
logger.info("TutorialMod.postInit");
proxy.postInit(event);
}
}
Maintenant que vous avez créé l'onglet de création, remplacez la destination d'enregistrement de l'élément créé ci-dessus par l'onglet créé à partir de l'onglet «Autre».
item/TutorialItem.java
package jp.artan.tm.item;
import jp.artan.tm.TutorialMod;
import jp.artan.tm.event.IItemRegisterEvent;
import jp.artan.tm.init.ItemInit;
import net.minecraft.client.renderer.block.model.ModelResourceLocation;
import net.minecraft.creativetab.CreativeTabs;
import net.minecraft.item.Item;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.client.event.ModelRegistryEvent;
import net.minecraftforge.client.model.ModelLoader;
import net.minecraftforge.event.RegistryEvent;
public class TutorialItem extends Item implements IItemRegisterEvent {
private final String name;
public TutorialItem(String name) {
super();
this.name = name;
this.setUnlocalizedName(this.name);
this.setRegistryName(TutorialMod.MODID, this.name);
this.setCreativeTab(TutorialMod.creativeTabs); //Changement
ItemInit.ITEMS.add(this);
}
@Override
public void registerItem(RegistryEvent.Register<Item> event) {
event.getRegistry().register(this);
}
public void registerModel(ModelRegistryEvent event) {
ModelLoader.setCustomModelResourceLocation(this, 0,
new ModelResourceLocation(new ResourceLocation(TutorialMod.MODID, this.name), "inventory"));
}
}
Si cela ressemble à l'image ci-dessous, c'est réussi.
J'avais l'habitude d'avoir une icône de banane, mais je ne pouvais pas la manger car celle que j'avais fabriquée plus tôt était un article non fonctionnel. Ensuite, je voudrais ajouter des articles comestibles. Aussi, pour la texture de cet article, j'utiliserai la texture de la pomme vanille.
imte/TutorialFood.java
package jp.artan.tm.item;
import jp.artan.tm.TutorialMod;
import jp.artan.tm.event.IItemRegisterEvent;
import jp.artan.tm.init.ItemInit;
import net.minecraft.client.renderer.block.model.ModelResourceLocation;
import net.minecraft.item.Item;
import net.minecraft.item.ItemFood;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.client.event.ModelRegistryEvent;
import net.minecraftforge.client.model.ModelLoader;
import net.minecraftforge.event.RegistryEvent;
public class TutorialFood extends ItemFood implements IItemRegisterEvent {
private final String name;
public TutorialFood(String name, int amount, float saturation) {
super(amount, saturation, false);
this.name = name;
this.setUnlocalizedName(this.name);
this.setRegistryName(TutorialMod.MODID, this.name);
this.setCreativeTab(TutorialMod.creativeTabs);
ItemInit.ITEMS.add(this);
}
@Override
public void registerItem(RegistryEvent.Register<Item> event) {
event.getRegistry().register(this);
}
@Override
public void registerModel(ModelRegistryEvent event) {
ModelLoader.setCustomModelResourceLocation(this, 0,
new ModelResourceLocation(new ResourceLocation(TutorialMod.MODID, this.name), "inventory"));
}
}
Les arguments du constructeur ItemFood sont les suivants. 1er argument montant Le montant de la récupération en mangeant 2ème argument saturation La quantité de récupération de satiété cachée en mangeant Le troisième argument estWolfFood: faire de la nourriture pour loup
init/ItemInit.java
package jp.artan.tm.init;
import jp.artan.tm.event.IItemRegisterEvent;
import jp.artan.tm.item.TutorialFood;
import jp.artan.tm.item.TutorialItem;
import net.minecraft.item.Item;
import java.util.ArrayList;
import java.util.List;
public class ItemInit {
public static final List<IItemRegisterEvent> ITEMS = new ArrayList<IItemRegisterEvent>();
public static final Item TUTORIAL_ITEM = new TutorialItem("tutorial_item");
public static final Item TUTORIAL_FOOD = new TutorialFood("tutorial_food", 1, 1.0F); //Postscript
}
lang/en_us.lang
# English Language File
# Tabs
itemGroup.tutorial_tab=Tutorial Tab
# Items
item.tutorial_item.name=Tutorial Item
item.tutorial_food.name=Tutorial Food
lang/ja_jp.lang
#Fichier de langue japonaise
# Tabs
itemGroup.tutorial_tab=Onglet Tutoriel
# Items
item.tutorial_item.name=Élément du didacticiel
item.tutorial_food.name=Tutoriel alimentaire
models/item/tutorial_food.json
{
"parent": "item/generated",
"textures": {
"layer0": "minecraft:items/apple"
}
}
Si vous l'exécutez avec ceci, ce sera comme suit.
Ensuite, je voudrais ajouter des cultures sur le terrain. Vous aurez besoin de trois éléments, un élément de départ, un élément de recadrage et un bloc de recadrage, pour créer un recadrage.
Commencez par configurer pour que les blocs puissent être enregistrés dans un lot de la même manière que le processus d'enregistrement du lot d'articles.
event/IBlockRegisterEvent.java
package jp.artan.tm.event;
import net.minecraft.block.Block;
import net.minecraftforge.client.event.ModelRegistryEvent;
import net.minecraftforge.event.RegistryEvent;
public interface IBlockRegisterEvent {
/**
* Register Block
*
* @param event
*/
void registerBlock(RegistryEvent.Register<Block> event);
/**
* Register Model
*
* @param event
*/
void registerModel(ModelRegistryEvent event);
}
init/BlockInit.java
package jp.artan.tm.init;
import jp.artan.tm.block.TutorialPlant;
import jp.artan.tm.event.IBlockRegisterEvent;
import net.minecraft.block.BlockCrops;
import java.util.ArrayList;
import java.util.List;
public class BlockInit {
public static final List<IBlockRegisterEvent> BLOCKS = new ArrayList<IBlockRegisterEvent>();
}
proxy/CommonProxy.java
package jp.artan.tm.proxy;
import jp.artan.tm.TutorialMod;
import jp.artan.tm.init.BlockInit;
import jp.artan.tm.init.ItemInit;
import net.minecraft.block.Block;
import net.minecraft.item.Item;
import net.minecraftforge.event.RegistryEvent;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.common.event.FMLInitializationEvent;
import net.minecraftforge.fml.common.event.FMLPostInitializationEvent;
import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
@Mod.EventBusSubscriber(modid = TutorialMod.MODID)
public abstract class CommonProxy {
public void preInit(FMLPreInitializationEvent event) {
TutorialMod.logger.info("CommonProxy.preInit");
}
public void init(FMLInitializationEvent event) {
TutorialMod.logger.info("CommonProxy.init");
}
public void postInit(FMLPostInitializationEvent event) {
TutorialMod.logger.info("CommonProxy.postInit");
}
@SubscribeEvent
public void registerItems(RegistryEvent.Register<Item> event) {
TutorialMod.logger.info("CommonProxy.registerItems");
ItemInit.ITEMS.forEach(f -> f.registerItem(event));
}
@SubscribeEvent
public void registerBlocks(RegistryEvent.Register<Block> event) { //Postscript
TutorialMod.logger.info("CommonProxy.registerBlocks");
BlockInit.BLOCKS.forEach(f -> f.registerBlock(event));
}
}
proxy/ClientProxy.java
package jp.artan.tm.proxy;
import jp.artan.tm.TutorialMod;
import jp.artan.tm.init.BlockInit;
import jp.artan.tm.init.ItemInit;
import net.minecraftforge.client.event.ModelRegistryEvent;
import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
public class ClientProxy extends CommonProxy {
@Override
public void preInit(FMLPreInitializationEvent event) {
super.preInit(event);
TutorialMod.logger.info("ClientProxy.preInit");
}
@SubscribeEvent
public void registerModels(ModelRegistryEvent event) {
TutorialMod.logger.info("ClientProxy.registerModels");
ItemInit.ITEMS.forEach(f -> f.registerModel(event));
BlockInit.BLOCKS.forEach(f -> f.registerModel(event)); //Postscript
}
}
Chaque bloc de culture et élément d'amorçage se trouve dans une instance et l'autre instance est utilisée. De plus, vous avez besoin d'une instance du bloc de recadrage lorsque vous instanciez un élément d'amorçage.
Tout d'abord, placez chaque instance dans BlockInit et ItemInit. Les noms de classe sont respectivement TutorialPlant et TutorialSeed.
init/BlockInit.java
package jp.artan.tm.init;
import jp.artan.tm.block.TutorialPlant;
import jp.artan.tm.event.IBlockRegisterEvent;
import net.minecraft.block.BlockCrops;
import java.util.ArrayList;
import java.util.List;
public class BlockInit {
public static final List<IBlockRegisterEvent> BLOCKS = new ArrayList<IBlockRegisterEvent>();
public static final BlockCrops TUTORIAL_PLANT = new TutorialPlant("tutorial_plant");
}
init/ItemInit.java
package jp.artan.tm.init;
import jp.artan.tm.event.IItemRegisterEvent;
import jp.artan.tm.item.TutorialFood;
import jp.artan.tm.item.TutorialItem;
import jp.artan.tm.item.TutorialSeed;
import net.minecraft.item.Item;
import net.minecraft.item.ItemFood;
import net.minecraft.item.ItemSeeds;
import java.util.ArrayList;
import java.util.List;
public class ItemInit {
public static final List<IItemRegisterEvent> ITEMS = new ArrayList<IItemRegisterEvent>();
public static final Item TUTORIAL_ITEM = new TutorialItem("tutorial_item");
public static final ItemFood TUTORIAL_FOOD = new TutorialFood("tutorial_food", 1, 1.0F);
public static final ItemSeeds TUTORIAL_SEED = new TutorialSeed("tutorial_seed");
}
Maintenant que nous avons placé chaque instance, nous allons créer un TutorialPlant et un TutorialSeed.
block/TutorialPlant.java
package jp.artan.tm.block;
import jp.artan.tm.TutorialMod;
import jp.artan.tm.event.IBlockRegisterEvent;
import jp.artan.tm.init.BlockInit;
import jp.artan.tm.init.ItemInit;
import net.minecraft.block.Block;
import net.minecraft.block.BlockCrops;
import net.minecraft.client.renderer.block.model.ModelResourceLocation;
import net.minecraft.item.Item;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.client.event.ModelRegistryEvent;
import net.minecraftforge.client.model.ModelLoader;
import net.minecraftforge.event.RegistryEvent;
public class TutorialPlant extends BlockCrops implements IBlockRegisterEvent {
protected final String Name;
public TutorialPlant(String name) {
super();
this.Name = name;
this.setUnlocalizedName(this.Name);
this.setRegistryName(TutorialMod.MODID, this.Name);
BlockInit.BLOCKS.add(this);
}
@Override
public Item getSeed() {
return ItemInit.TUTORIAL_SEED;
}
@Override
public Item getCrop() {
return ItemInit.TUTORIAL_FOOD;
}
@Override
public void registerBlock(RegistryEvent.Register<Block> event) {
event.getRegistry().register(this);
}
@Override
public void registerModel(ModelRegistryEvent event) {
ModelLoader.setCustomModelResourceLocation(Item.getItemFromBlock(this), 0,
new ModelResourceLocation(new ResourceLocation(TutorialMod.MODID, this.Name), "inventory"));
}
}
Spécifiez l'élément de départ à déposer lors de la destruction d'un bloc de culture avec getSeed
Spécifiez l'élément de recadrage à déposer lors de la destruction d'un bloc de recadrage avec getCrop
item/TutorialSeed.java
package jp.artan.tm.item;
import jp.artan.tm.TutorialMod;
import jp.artan.tm.event.IItemRegisterEvent;
import jp.artan.tm.init.BlockInit;
import jp.artan.tm.init.ItemInit;
import net.minecraft.block.state.IBlockState;
import net.minecraft.client.renderer.block.model.ModelResourceLocation;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.init.Blocks;
import net.minecraft.item.Item;
import net.minecraft.item.ItemSeeds;
import net.minecraft.item.ItemStack;
import net.minecraft.util.EnumActionResult;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.EnumHand;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.IBlockAccess;
import net.minecraft.world.World;
import net.minecraftforge.client.event.ModelRegistryEvent;
import net.minecraftforge.client.model.ModelLoader;
import net.minecraftforge.common.EnumPlantType;
import net.minecraftforge.event.RegistryEvent;
public class TutorialSeed extends ItemSeeds implements IItemRegisterEvent {
private final String name;
public TutorialSeed(String name) {
super(BlockInit.TUTORIAL_PLANT, Blocks.FARMLAND);
this.name = name;
this.setUnlocalizedName(this.name);
this.setRegistryName(TutorialMod.MODID, this.name);
this.setCreativeTab(TutorialMod.creativeTabs);
ItemInit.ITEMS.add(this);
}
@Override
public EnumActionResult onItemUse(EntityPlayer player, World worldIn, BlockPos pos, EnumHand hand,
EnumFacing facing, float hitX, float hitY, float hitZ) {
ItemStack stack = player.getHeldItem(hand);
IBlockState state = worldIn.getBlockState(pos);
if (facing == EnumFacing.UP && player.canPlayerEdit(pos.offset(facing), facing, stack)
&& state.getBlock().canSustainPlant(state, worldIn, pos, EnumFacing.UP, this)
&& worldIn.isAirBlock(pos.up())) {
worldIn.setBlockState(pos.up(), BlockInit.TUTORIAL_PLANT.getDefaultState());
if (player.capabilities.isCreativeMode || !worldIn.isRemote) {
stack.shrink(1);
}
return EnumActionResult.SUCCESS;
}
return EnumActionResult.FAIL;
}
@Override
public EnumPlantType getPlantType(IBlockAccess world, BlockPos pos) {
return EnumPlantType.Crop;
}
@Override
public IBlockState getPlant(IBlockAccess world, BlockPos pos) {
return BlockInit.TUTORIAL_PLANT.getDefaultState();
}
@Override
public void registerItem(RegistryEvent.Register<Item> event) {
event.getRegistry().register(this);
}
@Override
public void registerModel(ModelRegistryEvent event) {
ModelLoader.setCustomModelResourceLocation(this, 0,
new ModelResourceLocation(new ResourceLocation(TutorialMod.MODID, this.name), "inventory"));
}
}
Ensuite, définissez la langue et la texture.
lang/en_us.lang
# English Language File
# Tabs
itemGroup.tutorial_tab=Tutorial Tab
# Items
item.tutorial_item.name=Tutorial Item
item.tutorial_food.name=Tutorial Food
item.tutorial_seed.name=Tutorial Seed
lang/ja_jp.lang
#Fichier de langue japonaise
# Tabs
itemGroup.tutorial_tab=Onglet Tutoriel
# Items
item.tutorial_item.name=Élément du didacticiel
item.tutorial_food.name=Tutoriel alimentaire
item.tutorial_seed.name=Tutoriel espèces
models/item/tutorial_seed.json
{
"parent": "item/generated",
"textures": {
"layer0": "tm:items/tutorial_seed"
}
}
models/item/tutorial_plant.json
{
"parent": "block/cube_all",
"textures": {
"all": "tm:blocks/tutorial_plant"
}
}
blockstates/tutorial_plant.json
{
"variants": {
"age=0": {
"model": "tm:tutorial_plant0"
},
"age=1": {
"model": "tm:tutorial_plant1"
},
"age=2": {
"model": "tm:tutorial_plant2"
},
"age=3": {
"model": "tm:tutorial_plant3"
},
"age=4": {
"model": "tm:tutorial_plant4"
},
"age=5": {
"model": "tm:tutorial_plant5"
},
"age=6": {
"model": "tm:tutorial_plant6"
},
"age=7": {
"model": "tm:tutorial_plant7"
}
}
}
Dans le fichier ci-dessus, vous pouvez spécifier le fichier json qui stocke les informations de texture correspondant aux 7 étapes de croissance des cultures. Puisque seules les données de l'état initial qui n'ont pas augmenté sont décrites ci-dessous, créez 8 données json de 0 à 7.
models/block/tutorial_plant0.json
{
"parent": "block/crop",
"textures": {
"crop": "tm:blocks/tutorial_plant0"
}
}
Les éléments de culture et les éléments de semence spécifiés dans l'installation du didacticiel doivent être abandonnés lorsqu'ils sont détruits après une croissance maximale.
À partir de la gauche, c'est un bloc lorsque la croissance est la 0ème étape, la croissance est la 3ème étape et la croissance est la 6ème étape.