Posted January 14, 20178 yr EDIT 2 (solved, 01.14.17 6:38pm): I forgot the "two hands" new mechanic and it seems that the EntityInteract is now fired for each hand ! I just added a check of the hand using event.getHand() and this would return whether the main hand or the off hand. It now works well. EDIT (01.14.17 6:24 pm): Okay so it seems that it only spawns only one entity (I tested on a flat map, and when I summon an entity with its egg, it only shows +1 entity with F3 enabled, sorry I should have done this before) and that the graphic glitch is another topic. But then, why would my function setEntityTextureID be called twice on the same side ? Good evening, I made a custom entity (a dialog NPC) and when I summon this entity with its egg, it seems that there are two entities. Am I missing something obvious ? (like client/server checks) CraftAndConquerEntities (my register class): package net.theviolentsquirrels.craftandconquer.entity; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityList; import net.minecraftforge.fml.common.registry.EntityRegistry; import net.theviolentsquirrels.craftandconquer.CraftAndConquer; import java.util.BitSet; /** * Created by Mathieu on 12/01/2017. */ public class CraftAndConquerEntities { private static final CraftAndConquerEntities INSTANCE = new CraftAndConquerEntities(); private BitSet availableIndices; private CraftAndConquerEntities() { this.availableIndices = new BitSet(256); this.availableIndices.set(0, 255); for (Object id : EntityList.ID_TO_CLASS.keySet()) { this.availableIndices.clear((Integer) id); } } public static CraftAndConquerEntities instance() { return (INSTANCE); } public static void registerEntities() { CraftAndConquerEntities.createEntity(EntityNPCDialog.class, "EntityNPCDialog", 0xC0392B, 0xE67E22); } public static int findGlobalUniqueId() { int result = CraftAndConquerEntities.instance().availableIndices.nextSetBit(0); if (result < 0) { throw (new RuntimeException("No more entity ID left !")); } return (result); } public static void createEntity(Class<? extends Entity> entityClass, String entityName, int solidColor, int spotColor) { int randomID = CraftAndConquerEntities.findGlobalUniqueId(); EntityRegistry.registerModEntity(entityClass, entityName, randomID, CraftAndConquer.instance, 64, 1, true, solidColor, spotColor); } } EntityNPCDialog (my custom entity): package net.theviolentsquirrels.craftandconquer.entity; import net.minecraft.entity.EntityLiving; import net.minecraft.util.SoundEvent; import net.minecraft.world.World; import net.theviolentsquirrels.craftandconquer.client.audio.CraftAndConquerSounds; import javax.annotation.Nullable; /** * Created by Mathieu on 12/01/2017. */ public class EntityNPCDialog extends EntityLiving { public EntityNPCDialog(World worldIn) { super(worldIn); } @Nullable @Override protected SoundEvent getAmbientSound() { return (CraftAndConquerSounds.NPCDialogSoundEvent); } @Nullable @Override protected SoundEvent getHurtSound() { return (CraftAndConquerSounds.NPCDialogSoundEvent); } @Nullable @Override protected SoundEvent getDeathSound() { return (CraftAndConquerSounds.NPCDialogSoundEvent); } @Override protected SoundEvent getFallSound(int heightIn) { return (CraftAndConquerSounds.NPCDialogSoundEvent); } @Override protected SoundEvent getSwimSound() { return (CraftAndConquerSounds.NPCDialogSoundEvent); } @Override protected SoundEvent getSplashSound() { return (CraftAndConquerSounds.NPCDialogSoundEvent); } } ClientProxy (where I register my entities and their renderers): package net.theviolentsquirrels.craftandconquer.proxy; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.block.model.ModelResourceLocation; import net.minecraft.client.renderer.entity.RenderManager; import net.minecraft.item.Item; import net.minecraftforge.client.model.ModelLoader; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.fml.client.registry.RenderingRegistry; import net.minecraftforge.fml.common.FMLCommonHandler; import net.minecraftforge.fml.common.network.NetworkRegistry; import net.theviolentsquirrels.craftandconquer.CraftAndConquer; import net.theviolentsquirrels.craftandconquer.GuiHandler; import net.theviolentsquirrels.craftandconquer.block.CraftAndConquerBlocks; import net.theviolentsquirrels.craftandconquer.client.audio.CraftAndConquerSounds; import net.theviolentsquirrels.craftandconquer.client.model.ModelEntityNPCDialog; import net.theviolentsquirrels.craftandconquer.client.renderer.entity.RenderNPCDialog; import net.theviolentsquirrels.craftandconquer.entity.CraftAndConquerEntities; import net.theviolentsquirrels.craftandconquer.entity.EntityNPCDialog; import net.theviolentsquirrels.craftandconquer.event.NPCInteractEvent; import net.theviolentsquirrels.craftandconquer.item.CraftAndConquerItems; import net.theviolentsquirrels.craftandconquer.recipe.CraftAndConquerRecipes; /** * Created by Mathieu on 31/12/2016. */ public class ClientProxy extends CommonProxy { @Override public void preInit() { super.preInit(); CraftAndConquerBlocks.init(); CraftAndConquerItems.init(); CraftAndConquerSounds.registerSounds(); CraftAndConquerEntities.registerEntities(); } @Override public void init() { super.init(); CraftAndConquerRecipes.init(); NetworkRegistry.INSTANCE.registerGuiHandler(CraftAndConquer.instance, new GuiHandler()); CraftAndConquer.proxy.registerEntityRenderers(); } @Override public void postInit() { super.postInit(); } @Override public void registerItemRenderer(Item item, int meta, String id) { ModelLoader.setCustomModelResourceLocation(item, meta, new ModelResourceLocation(CraftAndConquer.MODID + ":" + id, "inventory")); } @Override public void registerEntityRenderers() { RenderManager renderManager = Minecraft.getMinecraft().getRenderManager(); RenderingRegistry.registerEntityRenderingHandler(EntityNPCDialog.class, new RenderNPCDialog(renderManager, new ModelEntityNPCDialog(), 0)); } } RenderNPCDialog (the renderer of my entity): package net.theviolentsquirrels.craftandconquer.client.renderer.entity; import net.minecraft.client.model.ModelBiped; import net.minecraft.client.renderer.entity.RenderBiped; import net.minecraft.client.renderer.entity.RenderManager; import net.minecraft.util.ResourceLocation; import net.theviolentsquirrels.craftandconquer.CraftAndConquer; import net.theviolentsquirrels.craftandconquer.entity.EntityNPCDialog; import org.apache.logging.log4j.Level; /** * Created by Mathieu on 12/01/2017. */ public class RenderNPCDialog extends RenderBiped<EntityNPCDialog> { private static final ResourceLocation[] NPC_DIALOG_TEXTURES = new ResourceLocation[] { new ResourceLocation(CraftAndConquer.MODID, "textures/entities/npc/npc_dialog.png"), new ResourceLocation(CraftAndConquer.MODID, "textures/entities/npc/npc_dialog_2.png"), }; private static int textureID = 0; public RenderNPCDialog(RenderManager renderManagerIn, ModelBiped modelBipedIn, float shadowSizeIn) { super(renderManagerIn, modelBipedIn, shadowSizeIn); } @Override protected ResourceLocation getEntityTexture(EntityNPCDialog entity) { return (RenderNPCDialog.NPC_DIALOG_TEXTURES[textureID]); } public static void setEntityTextureID() { CraftAndConquer.logger.log(Level.INFO, "textureID before:\t" + textureID); textureID = (textureID + 1 < NPC_DIALOG_TEXTURES.length) ? textureID + 1 : 0; CraftAndConquer.logger.log(Level.INFO, "textureID after:\t" + textureID); } } Also, in the console, I can observe this when I interact with my entity once (EntityInteract event): [17:22:11] [Client thread/INFO] [craftandconquer]: textureID before: 0 [17:22:11] [Client thread/INFO] [craftandconquer]: textureID after: 1 [17:22:11] [Client thread/INFO] [craftandconquer]: textureID before: 1 [17:22:11] [Client thread/INFO] [craftandconquer]: textureID after: 0 [17:22:12] [server thread/INFO] [craftandconquer]: textureID before: 0 [17:22:12] [server thread/INFO] [craftandconquer]: textureID after: 1 [17:22:12] [server thread/INFO] [craftandconquer]: textureID before: 1 [17:22:12] [server thread/INFO] [craftandconquer]: textureID after: 0 I think in the event I would need to check isRemote, but even with this check, it would trigger twice so I was thinking about a "double spawn" ? Thank you for your answers. Squirrel ! Squirrel ! Squirrel !
January 14, 20178 yr Author Your entity registration is very broken! You must only use EntityRegistry.registerModEntity. Do nothing else to register your entity! Do not use global IDs! Why are you registering your entities in your client proxy? This means they will not work on a server. I do need to specify an id for the method below: public static void registerModEntity(Class<? extends Entity> entityClass, String entityName, int id, Object mod, int trackingRange, int updateFrequency, boolean sendsVelocityUpdates, int eggPrimary, int eggSecondary) I don't quite understand why would you mean by "do not use global IDs" then. About the entities registration, I noticed my error once the topic has been created, the method call has been moved to the preInit() in the CommonProxy since. Squirrel ! Squirrel ! Squirrel !
January 14, 20178 yr Author Those IDs are just internal to your mod. Start at 0 and go up from there. By "do not use global IDs" I mean to not manually hack into vanilla's EntityList and search through there for free global IDs. I don't know where you got that from or if you decided yourself that you needed something like that, fact is, it is broken and causes a lot of problems. To be honest, I followed tutorial haha. I thought that ID's for this method were directly linked with the vanilla registry. My bad. Squirrel ! Squirrel ! Squirrel !
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.