Jump to content
Search In
  • More options...
Find results that contain...
Find results in...

Common issues and recommendations


Recommended Posts

What is this?

This is a collection of common issues and recommendations for the Modder Support subforum. Instead of repeating these things over and over again, a link to this thread can be used instead.

This post will be updated as needed.

Suggestions either via PM to me or in a separate thread to keep this topic clean.

Edited by diesieben07
  • Like 12
  • Thanks 4
  • Haha 2
Link to post
Share on other sites

Problematic Code

  1. Please use the registry events to register your blocks, items and other registry entries.
  2. Use ModelLoader.setCustomModelResourceLocation in ModelRegistryEvent to register your item models. Do not use the ItemModelMesher.

  3. Do not use methods that are deprecated in Forge or vanilla Minecraft. Usually there will be an explanatory method next to the method explaining what to use instead.
    There is an exception for methods in the Block class, these may be overridden. Instead of calling them, use the one in IBlockState resp. it's supertypes. 

  4. Do not use ITileEntityProvider or BlockContainer. These classes are legacy vanilla code. To add a TileEntity to your Block, override hasTileEntity and createTileEntity in your Block class. 

  5. Do not use IInventory. Use the capability API with IItemHandler.

  6. Do not reach across logical sides. This will cause subtle and not-so-subtle issues that may occur randomly and very rarely. Read and understand the documentation about sides to understand why this is a bad idea.
  7. Do not use the unlocalized names for things other than displaying the name of a block/item. If you want to access the registry name for a registry entry, use IForgeRegistryEntry::getRegistryName.
  8. Do not use numerical IDs for registry entries. They can and will change. Use the static references in e.g. the Items class or use textual IDs (e.g. minecraft:stone) if you need dynamic references.
  9. Any IForgeRegistryEntry (commonly items and blocks) is singleton-like. That means that there is only once instance of your block class. There is not a new Block instance for every position in the world and there is not a new Item instance for every ItemStack. This means that you cannot store position-related things as instance fields in your block class, etc. You must use a TileEntity resp. the NBT data on ItemStack.
  10. Unlocalized names, TileEntity registration names and enum entries added using EnumHelper should contain your ModID to avoid collisions between mods. Note: This also applies to the unlocalized name for entities (set by EntityEntryBuilder::name resp. the entityName parameter of EntityRegistry.registerModEntity).
  11. A TileEntity class must have a no-argument constructor. As a general recommendation a TileEntity should not have more than this one constructor, to avoid confusion.
  12. An ItemStack variable should never be null and all of vanilla and Forge code expects this to be the case. Use ItemStack.EMPTY instead of null and ItemStack::isEmpty to check for empty stacks. Do not compare against ItemStack.EMPTY.
  13. Registry names and asset file names must be completely lowercase.
  14. Do not create registry entries (anything implementing IForgeRegistryEntry, like blocks and items) in a static initializer. Use the proper events.
  15. Do not access client-only code from common code, use the @SidedProxy system. See the documentation about sides (in particular the section about @SidedProxy) for more information.
  16. Do not implement IMessage and IMessageHandler on the same class. It does not make logical sense and leads to confusion and hard to trace bugs.
  17. Handle exceptions properly. Do not avoid a game crash at all costs, sometimes it is okay to crash the game. Read this article for more information.
Edited by diesieben07
  • Like 5
  • Thanks 4
Link to post
Share on other sites

Code-Style

  1. The concept of a "common proxy" does not make sense. The whole point of @SidedProxy is to abstract over client specific and server specific behavior, the opposite of "common". Common code should go in your main mod class.
  2. Use @Override when you intend to override methods. This helps tremendously when updating your code for new versions of Minecraft, but in general is good practice. Read this Stack Overflow answer for an explanation.
  3. Using an interface (usually called IHasModel) on your Item and/or Block classes to denote that they are capable of registering a model is an anti-pattern and not necessary. All items require a model to be registered for them and usually no type-specific information from the item is needed, only the registry name, which is accessible for all items by default.
  4. Do not abuse inheritance for code-reuse. This often manifests in classes like ItemBase, BaseItem or ItemExampleMod. Using this pattern prevents you from extending other essential classes, such as ItemFood and in that case requires code duplication. Prefer composition or utility methods instead to reuse code.
Edited by diesieben07
  • Like 7
  • Thanks 1
Link to post
Share on other sites

General issues

  1. Do not use the "export" or "create jar file" functionalities of your IDE or other means to create your final mod file. You must use the Gradle build task. See the documentation for more info.
  2. When creating a Git repository for your mod, the repository root should be where your build.gradle file is. The MDK ships with a default .gitignore file so that only the necessary files will be added to version control.
Edited by diesieben07
  • Like 5
  • Thanks 2
Link to post
Share on other sites
Guest
This topic is now closed to further replies.


  • Recently Browsing

  • Posts

    • Maybe recheck the code a couple of times? Im just a random guy who found this post  
    • world stops loading at 53%2021-04-18-1.log.gz
    • Try to swich versions of the game, if that dest work try to install the game again.
    • Hello There! Yes I know it's been a while and there are reasons that I explain in this video! But in this video talk about some pretty cool updates and announcements to the channel that I am super excited to share with you guys! Also yes this was filmed on the Hive about a day before it shut down! I hope you all enjoy this video and if you did don't forget to like and sub for more!  
    • Hi, I'm trying to create an entity based of a minecart but the entity appears to be invisible and unable to be interacted with. I'm not seeing any errors in the debug log. I have included my entity and renderer. I have not added any attributes to this entity as I don't think there is any way to add them to minecarts. I added a message during ticks that appears when its alive but the minecart itself does not. public class TrainEntity extends AbstractMinecartEntity { public TrainEntity(EntityType<?> p_i50126_1_, World p_i50126_2_) { super(p_i50126_1_, p_i50126_2_); } public TrainEntity(World p_i1723_1_, double p_i1723_2_, double p_i1723_4_, double p_i1723_6_) { super(EntityRegister.TRAINENTITY.get(), p_i1723_1_, p_i1723_2_, p_i1723_4_, p_i1723_6_); } public static final String REG = "train_entity"; @Override public Type getMinecartType() { return AbstractMinecartEntity.Type.RIDEABLE; } public ActionResultType interact(PlayerEntity p_184230_1_, Hand p_184230_2_) { ActionResultType ret = super.interact(p_184230_1_, p_184230_2_); if (ret.consumesAction()) return ret; if (p_184230_1_.isSecondaryUseActive()) { return ActionResultType.PASS; } else if (this.isVehicle()) { return ActionResultType.PASS; } else if (!this.level.isClientSide) { return p_184230_1_.startRiding(this) ? ActionResultType.CONSUME : ActionResultType.PASS; } else { return ActionResultType.SUCCESS; } } @Override public void tick() { super.tick(); STAR.LOGGER.debug("STAR - Training Hard"); } public class TrainEntityRender<T extends TrainEntity> extends EntityRenderer<T> { protected final EntityModel<T> model = new CreeperModel<>(); public TrainEntityRender(EntityRendererManager p_i46155_1_) { super(p_i46155_1_); this.shadowRadius = 0.7F; } @Override public ResourceLocation getTextureLocation(TrainEntity p_110775_1_) { return new ResourceLocation(STAR.MODID, "textures/entity/purple_thing.png"); } @Override public void render(T p_225623_1_, float p_225623_2_, float p_225623_3_, MatrixStack p_225623_4_, IRenderTypeBuffer p_225623_5_, int p_225623_6_) { super.render(p_225623_1_, p_225623_2_, p_225623_3_, p_225623_4_, p_225623_5_, p_225623_6_); //Bunch of other stuff copied from the MinecartRenderer p_225623_4_.scale(-1.0F, -1.0F, 1.0F); this.model.setupAnim(p_225623_1_, 0.0F, 0.0F, -0.1F, 0.0F, 0.0F); IVertexBuilder ivertexbuilder = p_225623_5_.getBuffer(this.model.renderType(this.getTextureLocation(p_225623_1_))); this.model.renderToBuffer(p_225623_4_, ivertexbuilder, p_225623_6_, OverlayTexture.NO_OVERLAY, 1.0F, 1.0F, 1.0F, 1.0F); p_225623_4_.popPose(); STAR.LOGGER.debug("STAR - RENDER"); } protected void renderMinecartContents(T p_225630_1_, float p_225630_2_, BlockState p_225630_3_, MatrixStack p_225630_4_, IRenderTypeBuffer p_225630_5_, int p_225630_6_) { Minecraft.getInstance().getBlockRenderer().renderSingleBlock(p_225630_3_, p_225630_4_, p_225630_5_, p_225630_6_, OverlayTexture.NO_OVERLAY); } } Event Register: @SubscribeEvent public static void onClientSetupEvent(FMLClientSetupEvent event) { LOGGER.info("STAR - Client Setup"); //Other renderers RenderingRegistry.registerEntityRenderingHandler(EntityRegister.TRAINENTITY.get(), TrainEntityRender::new); } Any help would be greatly appreciated. 
  • Topics

  • Who's Online (See full list)

×
×
  • Create New...

Important Information

By using this site, you agree to our Privacy Policy.