Posted May 5, 20196 yr Hey all, I'm pretty new to modding and am having trouble learning all the basics. I've figured out how to register and create my own blocks/items as well as how to give them custom properties and such. However, I'm having trouble figuring out how to get started with creating and registering entities. Does anyone have any examples they can post on how to register and create custom entities in 1.13.2? Thank you! Edited May 5, 20196 yr by iLaysChipz
May 5, 20196 yr You would subscribe to a registry event that fires for the EntityType registry, then register your EntityType into said registry. That's it. Nothing else changed from 1.12 or earlier.
May 7, 20196 yr On 5/6/2019 at 2:14 AM, V0idWa1k3r said: You would subscribe to a registry event that fires for the EntityType registry This is now on the mod event bus About Me Spoiler My Discord - Cadiboo#8887 My Website - Cadiboo.github.io My Mods - Cadiboo.github.io/projects My Tutorials - Cadiboo.github.io/tutorials Versions below 1.14.4 are no longer supported on this forum. Use the latest version to receive support. When asking support remember to include all relevant log files (logs are found in .minecraft/logs/), code if applicable and screenshots if possible. Only download mods from trusted sites like CurseForge (minecraft.curseforge.com). A list of bad sites can be found here, with more information available at stopmodreposts.org Edit your own signature at www.minecraftforge.net/forum/settings/signature/ (Make sure to check its compatibility with the Dark Theme)
May 9, 20196 yr Author Can I get an example for what the register event should look like? Right now I have something that looks like Register Event @Mod.EventBusSubscriber(bus=Mod.EventBusSubscriber.Bus.MOD) public static class RegistryEvents { @SubscribeEvent public static void registerEntities(final RegistryEvent.Register<EntityType<?>> event) { event.getRegistry().registerAll ( EntityList.test = EntityType.Builder.create(EntityTest.class, i_have_no_idea_what_goes_here); ); } } Entity Class public class EntityTest extends EntityLiving implements IMob { protected EntityTest(EntityType<?> type, World world) { super(type, world); } @Override protected void registerAttributes() { super.registerAttributes(); this.getAttribute(SharedMonsterAttributes.FOLLOW_RANGE).setBaseValue(0.0D); this.getAttribute(SharedMonsterAttributes.MOVEMENT_SPEED).setBaseValue(0.0D); this.getAttribute(SharedMonsterAttributes.ATTACK_DAMAGE).setBaseValue(0.0D); this.getAttribute(SharedMonsterAttributes.ARMOR).setBaseValue(1.0D); this.getAttribute(SharedMonsterAttributes.MAX_HEALTH).setBaseValue(30.0D); } @Override public boolean isAIDisabled() { return true; } @Override public boolean canBeCollidedWith() { return true; } } Model Class @OnlyIn(Dist.CLIENT) public class ModelTest extends ModelBase { protected ModelRenderer test_cube; public ModelTest(float scale) { test_cube = new ModelRenderer(this); test_cube.addBox(-4.0F, 16.0F, -4.0F, 8, 8, 8); test_cube.setRotationPoint(0f, 8f, 0f); } @Override public void render(Entity entity, float f1, float f2, float f3, float f4, float f5, float scale) { this.setRotationAngles(f1, f2, f3, f4, f5, scale, entity); test_cube.render(scale); } } Render Class @OnlyIn(Dist.CLIENT) public class RenderTest extends RenderLiving<EntityTest> { private static final ResourceLocation TEST_TEXTURES = new ResourceLocation("textures/entity/slime/slime.png"); public RenderTest(RenderManager renderer) { super(renderer, new ModelTest(16), 0.25f); } protected ResourceLocation getEntityTexture(EntityTest entity) { return TEST_TEXTURES; } } Class holding entity declaration public class EntityList { public static EntityType<EntitySilkNest> silk_nest; } Also, I'm a little lost on how to connect the renderer, model, and entity together Edited May 9, 20196 yr by iLaysChipz
May 9, 20196 yr Author I edited the last post with all the relevant code. All I'm trying to create for now is a cube that can be attacked and defeated like any other mob. If I can get to that point I think I can handle everything else I need from there. Any resources on where I can find this information on my own would be really helpful. I'm sorry for all the trouble as I know this is a lot to ask. Thank you all for your input so far. I do appreciate it. Edited May 9, 20196 yr by iLaysChipz
May 9, 20196 yr Entity registration code (1.12.2, but nothing changed except that the event is now fired on the mod event bus) (you’ll need to scroll down a bit) https://gist.github.com/Cadiboo/b825d62fb46538e7b7b262c5612d62aa About Me Spoiler My Discord - Cadiboo#8887 My Website - Cadiboo.github.io My Mods - Cadiboo.github.io/projects My Tutorials - Cadiboo.github.io/tutorials Versions below 1.14.4 are no longer supported on this forum. Use the latest version to receive support. When asking support remember to include all relevant log files (logs are found in .minecraft/logs/), code if applicable and screenshots if possible. Only download mods from trusted sites like CurseForge (minecraft.curseforge.com). A list of bad sites can be found here, with more information available at stopmodreposts.org Edit your own signature at www.minecraftforge.net/forum/settings/signature/ (Make sure to check its compatibility with the Dark Theme)
May 9, 20196 yr Author Hey Cadiboo, thank you so much for replying! I couldn't find EntityEntry, but based on the post here, I think it's been updated to EntityType<T>. It seems the create method needs a class (Class<? extends T> entityClassIn) and world (Function<? super World, ? extends T> factoryIn). So far I've been able to get this to run: @SubscribeEvent public static void registerEntities(final RegistryEvent.Register<EntityType<?>> event) { event.getRegistry().registerAll ( EntityList.test = EntityType.Builder.create(EntityTest.class, null).build("test").setRegistryName(MODID,"test") ); } However, I can't summon the mob, and I can't find how to make a new spawn egg. Could you point me in the right direction on where to look? Again, thank you so much for taking the time to help me out
May 9, 20196 yr 2 hours ago, iLaysChipz said: EntityType.Builder.create(EntityTest.class, null) You set your factory (the function that makes instances of your entity) to null. Example: EntityType.Builder.create(EntityButterfly.class, EntityButterfly::new).tracker(200, 1, true).build("common_butterfly1").setRegistryName(MOD_ID, "common_butterfly1") About Me Spoiler My Discord - Cadiboo#8887 My Website - Cadiboo.github.io My Mods - Cadiboo.github.io/projects My Tutorials - Cadiboo.github.io/tutorials Versions below 1.14.4 are no longer supported on this forum. Use the latest version to receive support. When asking support remember to include all relevant log files (logs are found in .minecraft/logs/), code if applicable and screenshots if possible. Only download mods from trusted sites like CurseForge (minecraft.curseforge.com). A list of bad sites can be found here, with more information available at stopmodreposts.org Edit your own signature at www.minecraftforge.net/forum/settings/signature/ (Make sure to check its compatibility with the Dark Theme)
May 9, 20196 yr Author I thought so, but I'm getting an error I'm not sure how to resolve. It says The type EntityTest does not define EntityTest(World) that is applicable here. If I look to EntitySlime, I see it's constructors defined as: protected EntitySlime(EntityType<?> p_i48552_1_, World p_i48552_2_) { super(p_i48552_1_, p_i48552_2_); this.moveHelper = new EntitySlime.SlimeMoveHelper(this); } public EntitySlime(World worldIn) { this(EntityType.SLIME, worldIn); } where SLIME is defined in EntityType as a constant as: public static final EntityType<EntityTest> TEST = EntityType.register("test", EntityType.Builder.create(EntityTest.class, EntityTest::new)); So now I have my code looking like: public class EntityList { public static final EntityType<EntityTest> TEST = EntityType.register("test", EntityType.Builder.create(EntityTest.class, EntityTest::new)); } // ============================================================================================================================================= //... protected EntityTest(World world) { this(EntityList.TEST,world); } protected EntityTest(EntityType<?> type, World world) { super(type, world); this.moveHelper = new EntityMoveHelper(this); } //... I'm sorry if these are dumb questions, I've always learned best by example, and I'm having a lot of trouble trying to extrapolate the in-between bits on my own. Am I supposed to be casting the function as a factory somehow? Or is there extra parts needed in the constructor? Edited May 9, 20196 yr by iLaysChipz
May 9, 20196 yr 21 minutes ago, iLaysChipz said: public static final EntityType<EntityTest> TEST = EntityType.register("test", EntityType.Builder.create(EntityTest.class, EntityTest::new)); No. Don't ever do that. Don't use static initializers for registry entries, this can and WILL break stuff. There are many ways to get the reference to your EntityType, like the ObjectHolder annotation or simply a field.
May 9, 20196 yr Author Gotcha, thank you for letting me know! I honestly had no idea. I think I'm going to try and create a universal setup method like I saw in Cadiboo's example. I'm still getting an error with this second argument for the method EntityType.Builder.create(entityClassIn, factoryIn). I think the problem is because I'm not sure what to pass for the first argument of the constructor, which is asking for an EntityType. All the vanilla mobs pass in final static instances of themselves which is hella confusing to me. Does anyone know what the first argument for EntityLivingBase should be for a custom entity that extends it? Edited May 9, 20196 yr by iLaysChipz
May 9, 20196 yr 28 minutes ago, iLaysChipz said: I think the problem is because I'm not sure what to pass for the first argument of the constructor, which is asking for an EntityType. All the vanilla mobs pass in final static instances of themselves which is hella confusing to me. Pass your EntityType, obviously, that's what it is asking of you. Don't use a static initializer for it. Use the ObjectHolder annotation to get the reference to your EntityType, or store it in a field and pass said field.
June 7, 20196 yr I too am having problems adding a custom entity (that I had previously working under 12.2) I have an entity (extended from EntityChicken + some code borrowed from vanilla horse class) with a custom renderer and model. It looks like the entity gets registered as it I can do a "/summon chicken_mod:protochicken" in-game, but what I get is a normal vanilla chicken (as identified when targeted in debug screen), albeit with some of the behaviors I'm trying to add (for instance riding like a saddled horse) My code in its entirety can be found here: https://github.com/pchonacky/randombits.git, but I will include the important bits below for brevity. Any help is appreciated. /Philip Rendering Registration: private void setup(final FMLCommonSetupEvent event) { DistExecutor.runWhenOn( Dist.CLIENT, () -> () -> RenderingRegistry.registerEntityRenderingHandler(EntityProtoChicken.class,RenderProtoChicken :: new) ); } Entity Registration (edited sightly for brevity): @Mod.EventBusSubscriber(modid=ChickenMod.MODID, bus=Mod.EventBusSubscriber.Bus.MOD) @ObjectHolder(ChickenMod.MODID) public static class RegistryEvents { //Register Entities @SubscribeEvent public static void onEntitiesRegistry(final RegistryEvent.Register<EntityType<?>> entityRegistryEvent) { entityRegistryEvent.getRegistry().registerAll( EntityType.Builder.create(EntityProtoChicken.class, EntityProtoChicken::new) .tracker(60, 24, true).disableSerialization().build("protochicken").setRegistryName(MODID, "protochicken") ); } } //RegistryEvents class Custom Entity: package net.chonacky.minecraft.mod.chicken_mod; import javax.annotation.Nullable; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.SharedMonsterAttributes; import net.minecraft.entity.passive.EntityChicken; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.util.EnumHand; import net.minecraft.util.math.MathHelper; import net.minecraft.world.World; public class EntityProtoChicken extends EntityChicken { public EntityProtoChicken(World worldIn) { super(worldIn); this.setSize(2.5F, 5.0F); this.setBoundingBox(this.getBoundingBox().offset(0, 0, 25)); this.stepHeight = 2.1F; // this.jumpPower = 0.0F; // this.isJumping = false; } @Override public float getEyeHeight() { return super.getEyeHeight()-0.5F; } @Override public void livingTick() { super.livingTick(); if (this.world.isRemote && this.dataManager.isDirty()) { this.dataManager.setClean(); } } @Override public boolean processInteract(EntityPlayer player, EnumHand hand) { this.mountTo(player); super.processInteract(player, hand); return true; } protected void mountTo(EntityPlayer player) { player.rotationYaw = this.rotationYaw; player.rotationPitch = this.rotationPitch; if (!this.world.isRemote) player.startRiding(this); } @Override public void updatePassenger(Entity passenger) { super.updatePassenger(passenger); float f = MathHelper.sin(this.renderYawOffset * 0.017453292F); float f1 = MathHelper.cos(this.renderYawOffset * 0.017453292F); //unused float f2 = 0.1F; //unused float f3 = 0.0F; passenger.setPosition( this.posX + (double)(0.1F * f), this.posY + (double)(this.height * 0.35F) + passenger.getYOffset() + 0.0D, this.posZ - (double)(0.1F * f1) ); if (passenger instanceof EntityLivingBase) ((EntityLivingBase)passenger).renderYawOffset = this.renderYawOffset; } @Override public void travel(float strafe, float vertical, float forward) { if (this.isBeingRidden() && this.canBeSteered() ) { //&& this.isHorseSaddled() EntityLivingBase controllingPassenger = (EntityLivingBase)this.getControllingPassenger(); this.rotationYaw = controllingPassenger.rotationYaw; this.prevRotationYaw = this.rotationYaw; this.rotationPitch = controllingPassenger.rotationPitch * 0.5F; this.setRotation(this.rotationYaw, this.rotationPitch); this.renderYawOffset = this.rotationYaw; this.rotationYawHead = this.renderYawOffset; strafe = controllingPassenger.moveStrafing * 0.5F; forward = controllingPassenger.moveForward; if (forward <= 0.0F) forward *= 0.25F; this.jumpMovementFactor = this.getAIMoveSpeed() * 0.1F; if (this.canPassengerSteer()) { this.setAIMoveSpeed((float)this.getAttribute(SharedMonsterAttributes.MOVEMENT_SPEED).getValue()); super.travel(strafe, vertical, forward); } else if (controllingPassenger instanceof EntityPlayer) { this.motionX = 0.0D; this.motionY = 0.0D; this.motionZ = 0.0D; } if (this.onGround) this.isJumping = false; } else { this.jumpMovementFactor = 0.02F; super.travel(strafe, vertical, forward); } } @Override public boolean canBeSteered() { return this.getControllingPassenger() instanceof EntityLivingBase; } @Override @Nullable public Entity getControllingPassenger() { return this.getPassengers().isEmpty() ? null : (Entity)this.getPassengers().get(0); } } Custom Model: package net.chonacky.minecraft.mod.chicken_mod; import net.minecraft.client.renderer.entity.model.ModelBase; import net.minecraft.client.renderer.entity.model.ModelRenderer; import net.minecraft.entity.Entity; import net.minecraft.util.math.MathHelper; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; @OnlyIn(Dist.CLIENT) public class ModelProtoChicken extends ModelBase { public ModelRenderer head; public ModelRenderer body; public ModelRenderer rightLeg; public ModelRenderer leftLeg; public ModelRenderer rightShin; public ModelRenderer leftShin; public ModelRenderer leftFoot; public ModelRenderer rightFoot; public ModelProtoChicken() { this.textureWidth = 132; this.textureHeight = 64; this.head = new ModelRenderer(this, 0, 16); this.head.addBox(-8.0F, -8.0F, -8.0F, 16, 8, 16, 5.0F); this.head.setRotationPoint(0.0F, -42.0F, 0.0F); this.body = new ModelRenderer(this, 0, 0); this.body.addBox(-16.0F, -16.0F, -16.0F, 32, 32, 32, 5.0F); this.body.setRotationPoint(0.0F, -23.0F, 0.0F); this.leftLeg = new ModelRenderer(this, 128,32); this.leftLeg.addBox(0.0F, 0.5F, 0.0F, 1, 13, 1 , 3.0F); this.leftLeg.setRotationPoint(20.0F, 0.0F, -24.0F); this.body.addChild(this.leftLeg); this.leftShin = new ModelRenderer(this, 128,32); this.leftShin.addBox(0.0F, -0.5F, 0.0F, 1, 13, 1, 3.0F); this.leftShin.setRotationPoint(0.0F, 12.0F, 0.0F); this.leftLeg.addChild(this.leftShin); this.leftFoot = new ModelRenderer(this,128,32); this.leftFoot.addBox(0.0F, 1.0F, -0.0F, 1, 4, 1, 3.0F); this.leftFoot.setRotationPoint(0.0F, 14.0F, 0.0F); this.leftShin.addChild(this.leftFoot); this.rightLeg = new ModelRenderer(this, 128,32); this.rightLeg.addBox(0.0F, 0.5F, 0.0F, 1, 13, 1 , 3.0F); this.rightLeg.setRotationPoint(-20.0F, 0.0F, -24.0F); this.body.addChild(this.rightLeg); this.rightShin = new ModelRenderer(this, 128,32); this.rightShin.addBox(0.0F, -0.5F, 0.0F, 1, 13, 1, 3.0F); this.rightShin.setRotationPoint(0.0F, 12.0F, 0.0F); this.rightLeg.addChild(this.rightShin); this.rightFoot = new ModelRenderer(this,128,32); this.rightFoot.addBox(0.0F, 1.0F, -0.0F, 1, 4, 1, 3.0F); this.rightFoot.setRotationPoint(0.0F, 14.0F, 0.0F); this.rightShin.addChild(this.rightFoot); // } /** * Sets the models various rotation angles then renders the model. */ @Override public void render(Entity entityIn, float limbSwing, float limbSwingAmount, float ageInTicks, float netHeadYaw, float headPitch, float scale) { this.setRotationAngles(limbSwing, limbSwingAmount, ageInTicks, netHeadYaw, headPitch, scale, entityIn); this.head.render(scale); this.body.render(scale); } /** * Sets the model's various rotation angles. For bipeds, par1 and par2 are used for animating the movement of arms * and legs, where par1 represents the time(so that arms and legs swing back and forth) and par2 represents how * "far" arms and legs can swing at most. */ @Override public void setRotationAngles(float limbSwing, float limbSwingAmount, float ageInTicks, float netHeadYaw, float headPitch, float scaleFactor, Entity entityIn) { this.head.rotateAngleX = headPitch * 0.017453292F; this.head.rotateAngleY = netHeadYaw * 0.017453292F; this.body.rotateAngleX = ((float)Math.PI / 2F); this.leftLeg.rotateAngleX = (MathHelper.cos(limbSwing * 0.6662F + (float)Math.PI) * 1.4F * limbSwingAmount) -((float)Math.PI/4); this.leftShin.rotateAngleX = -(MathHelper.cos(limbSwing * 0.6662F + (float)Math.PI) * 1.4F * limbSwingAmount) -((float)Math.PI/2); this.leftFoot.rotateAngleX = -((float)Math.PI/4) ; this.rightLeg.rotateAngleX = -(MathHelper.cos(limbSwing * 0.6662F + (float)Math.PI) * 1.4F * limbSwingAmount) -((float)Math.PI/4); this.rightShin.rotateAngleX = +(MathHelper.cos(limbSwing * 0.6662F + (float)Math.PI) * 1.4F * limbSwingAmount) -((float)Math.PI/2); this.rightFoot.rotateAngleX = -((float)Math.PI/4) ; // this.rightWing.rotateAngleZ = ageInTicks; // this.leftWing.rotateAngleZ = -ageInTicks; } } Custom Renderer: package net.chonacky.minecraft.mod.chicken_mod; import net.minecraft.client.renderer.entity.RenderLiving; import net.minecraft.client.renderer.entity.RenderManager; import net.minecraft.util.ResourceLocation; import net.minecraft.util.math.MathHelper; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; @OnlyIn(Dist.CLIENT) public class RenderProtoChicken extends RenderLiving<EntityProtoChicken> { private static final ResourceLocation PROTOCHICKEN_TEXTURES = new ResourceLocation(ChickenMod.MODID+":textures/entity/byhut.png"); //"chicken:textures/entity/checker.png" // public RenderLiving(RenderManager rendermanagerIn, ModelBase modelbaseIn, float shadowsizeIn) public RenderProtoChicken(RenderManager manager) { super(manager, new ModelProtoChicken(), 1.75F); } @Override protected ResourceLocation getEntityTexture(EntityProtoChicken entity) { return PROTOCHICKEN_TEXTURES; } /** * Defines what float the third param in setRotationAngles of ModelBase is */ @Override protected float handleRotationFloat(EntityProtoChicken livingBase, float partialTicks) { float f = livingBase.oFlap + (livingBase.wingRotation - livingBase.oFlap) * partialTicks; float f1 = livingBase.oFlapSpeed + (livingBase.destPos - livingBase.oFlapSpeed) * partialTicks; return (MathHelper.sin(f) + 1.0F) * f1; } @Override public void doRender(EntityProtoChicken entity, double x, double y, double z, float entityYaw, float partialTicks) { if (entity.isInWater()) { super.doRender(entity, x, (y-1.0D), z, entityYaw, partialTicks); } else { super.doRender(entity, x, y, z, entityYaw, partialTicks); } if (!this.renderOutlines) { this.renderLeash(entity, x, y, z, entityYaw, partialTicks); } } }
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.