Major Squirrel Posted January 14, 2017 Share Posted January 14, 2017 Good evening, Following my topic today, I would like to change the skin of a custom entity (a NPC) by right-clicking on it with a specific item. As a naive approach, I tried to change the index of the texture array to redirect the correct texture in my getEntityTexture method. So far, this works on a client, the texture of the entity changes when I correctly right-click on the entity, but this does not work on a server. I have a NoClassDefFoundError that pops on the server console when processing the texture change (the client, however, does not crash). RenderNPCDialog (the renderer): public class RenderNPCDialog extends RenderLiving<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, ModelBase modelBaseIn, float shadowSizeIn) { super(renderManagerIn, modelBaseIn, shadowSizeIn); } @Override protected ResourceLocation getEntityTexture(EntityNPCDialog entity) { return (RenderNPCDialog.NPC_DIALOG_TEXTURES[textureID]); } public static void setEntityTextureID() { textureID = (textureID + 1 < NPC_DIALOG_TEXTURES.length) ? textureID + 1 : 0; } } NPCInteractEvent (the event that processes the texture change): public class NPCInteractEvent { @SubscribeEvent public void onEntityNPCInteract(PlayerInteractEvent.EntityInteract event) { ItemStack heldItem = event.getEntityPlayer().getHeldItem(EnumHand.MAIN_HAND); ItemBase npcManager = CraftAndConquerItems.npcManager; if (event.getTarget() instanceof EntityNPCDialog && event.getHand().equals(EnumHand.MAIN_HAND) && heldItem.getItem().equals(npcManager)) { if (!event.getWorld().isRemote) RenderNPCDialog.setEntityTextureID(); } } } ClientProxy: public class ClientProxy extends CommonProxy { @Override public void preInit() { super.preInit(); } @Override public void init() { super.init(); } @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.5f)); } } CommonProxy: public class CommonProxy { public void preInit() { CraftAndConquerBlocks.init(); CraftAndConquerItems.init(); CraftAndConquerSounds.registerSounds(); CraftAndConquerEntities.registerEntities(); NetworkRegistry.INSTANCE.registerGuiHandler(CraftAndConquer.instance, new GuiHandler()); } public void init() { CraftAndConquerRecipes.init(); CraftAndConquer.proxy.registerEntityRenderers(); MinecraftForge.EVENT_BUS.register(new NPCInteractEvent()); } public void postInit() { } public void registerItemRenderer(Item item, int meta, String id) { } public void registerEntityRenderers() { } } Logs from the server console: [00:16:38] [server thread/ERROR] [FML]: Exception caught during firing event net.minecraftforge.event.entity.player.PlayerInteractEvent$EntityInteract@5a71b038: java.lang.NoClassDefFoundError: net/theviolentsquirrels/craftandconquer/client/renderer/entity/RenderNPCDialog at net.theviolentsquirrels.craftandconquer.event.NPCInteractEvent.onEntityNPCInteract(NPCInteractEvent.java:27) ~[NPCInteractEvent.class:?] at net.minecraftforge.fml.common.eventhandler.ASMEventHandler_6_NPCInteractEvent_onEntityNPCInteract_EntityInteract.invoke(.dynamic) ~[?:?] at net.minecraftforge.fml.common.eventhandler.ASMEventHandler.invoke(ASMEventHandler.java:90) ~[ASMEventHandler.class:?] at net.minecraftforge.fml.common.eventhandler.EventBus.post(EventBus.java:185) [EventBus.class:?] at net.minecraftforge.common.ForgeHooks.onInteractEntity(ForgeHooks.java:1008) [ForgeHooks.class:?] at net.minecraft.entity.player.EntityPlayer.interact(EntityPlayer.java:1246) [EntityPlayer.class:?] at net.minecraft.network.NetHandlerPlayServer.processUseEntity(NetHandlerPlayServer.java:1072) [NetHandlerPlayServer.class:?] at net.minecraft.network.play.client.CPacketUseEntity.processPacket(CPacketUseEntity.java:93) [CPacketUseEntity.class:?] at net.minecraft.network.play.client.CPacketUseEntity.processPacket(CPacketUseEntity.java:14) [CPacketUseEntity.class:?] at net.minecraft.network.PacketThreadUtil$1.run(PacketThreadUtil.java:15) [PacketThreadUtil$1.class:?] at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) [?:1.8.0_111] at java.util.concurrent.FutureTask.run(FutureTask.java:266) [?:1.8.0_111] at net.minecraft.util.Util.runTask(Util.java:25) [util.class:?] at net.minecraft.server.MinecraftServer.updateTimeLightAndEntities(MinecraftServer.java:742) [MinecraftServer.class:?] at net.minecraft.server.dedicated.DedicatedServer.updateTimeLightAndEntities(DedicatedServer.java:408) [DedicatedServer.class:?] at net.minecraft.server.MinecraftServer.tick(MinecraftServer.java:687) [MinecraftServer.class:?] at net.minecraft.server.MinecraftServer.run(MinecraftServer.java:536) [MinecraftServer.class:?] at java.lang.Thread.run(Thread.java:745) [?:1.8.0_111] Caused by: java.lang.ClassNotFoundException: net.theviolentsquirrels.craftandconquer.client.renderer.entity.RenderNPCDialog at net.minecraft.launchwrapper.LaunchClassLoader.findClass(LaunchClassLoader.java:191) ~[launchwrapper-1.12.jar:?] at java.lang.ClassLoader.loadClass(ClassLoader.java:424) ~[?:1.8.0_111] at java.lang.ClassLoader.loadClass(ClassLoader.java:357) ~[?:1.8.0_111] ... 18 more Caused by: java.lang.NoClassDefFoundError: net/minecraft/client/renderer/entity/RenderLiving at java.lang.ClassLoader.defineClass1(Native Method) ~[?:1.8.0_111] at java.lang.ClassLoader.defineClass(ClassLoader.java:763) ~[?:1.8.0_111] at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142) ~[?:1.8.0_111] at net.minecraft.launchwrapper.LaunchClassLoader.findClass(LaunchClassLoader.java:182) ~[launchwrapper-1.12.jar:?] at java.lang.ClassLoader.loadClass(ClassLoader.java:424) ~[?:1.8.0_111] at java.lang.ClassLoader.loadClass(ClassLoader.java:357) ~[?:1.8.0_111] ... 18 more Caused by: java.lang.ClassNotFoundException: net.minecraft.client.renderer.entity.RenderLiving at net.minecraft.launchwrapper.LaunchClassLoader.findClass(LaunchClassLoader.java:101) ~[launchwrapper-1.12.jar:?] at java.lang.ClassLoader.loadClass(ClassLoader.java:424) ~[?:1.8.0_111] at java.lang.ClassLoader.loadClass(ClassLoader.java:357) ~[?:1.8.0_111] at java.lang.ClassLoader.defineClass1(Native Method) ~[?:1.8.0_111] at java.lang.ClassLoader.defineClass(ClassLoader.java:763) ~[?:1.8.0_111] at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142) ~[?:1.8.0_111] at net.minecraft.launchwrapper.LaunchClassLoader.findClass(LaunchClassLoader.java:182) ~[launchwrapper-1.12.jar:?] at java.lang.ClassLoader.loadClass(ClassLoader.java:424) ~[?:1.8.0_111] at java.lang.ClassLoader.loadClass(ClassLoader.java:357) ~[?:1.8.0_111] ... 18 more [00:16:38] [server thread/ERROR] [FML]: Index: 1 Listeners: [00:16:38] [server thread/ERROR] [FML]: 0: NORMAL [00:16:38] [server thread/ERROR] [FML]: 1: ASM: net.theviolentsquirrels.craftandconquer.event.NPCInteractEvent@4d7d80dd onEntityNPCInteract(Lnet/minecraftforge/event/entity/player/PlayerInteractEvent$EntityInteract;)V [00:16:38] [server thread/FATAL] [net.minecraft.server.MinecraftServer]: Error executing task java.util.concurrent.ExecutionException: java.lang.NoClassDefFoundError: net/theviolentsquirrels/craftandconquer/client/renderer/entity/RenderNPCDialog at java.util.concurrent.FutureTask.report(FutureTask.java:122) ~[?:1.8.0_111] at java.util.concurrent.FutureTask.get(FutureTask.java:192) ~[?:1.8.0_111] at net.minecraft.util.Util.runTask(Util.java:26) [util.class:?] at net.minecraft.server.MinecraftServer.updateTimeLightAndEntities(MinecraftServer.java:742) [MinecraftServer.class:?] at net.minecraft.server.dedicated.DedicatedServer.updateTimeLightAndEntities(DedicatedServer.java:408) [DedicatedServer.class:?] at net.minecraft.server.MinecraftServer.tick(MinecraftServer.java:687) [MinecraftServer.class:?] at net.minecraft.server.MinecraftServer.run(MinecraftServer.java:536) [MinecraftServer.class:?] at java.lang.Thread.run(Thread.java:745) [?:1.8.0_111] Caused by: java.lang.NoClassDefFoundError: net/theviolentsquirrels/craftandconquer/client/renderer/entity/RenderNPCDialog at net.theviolentsquirrels.craftandconquer.event.NPCInteractEvent.onEntityNPCInteract(NPCInteractEvent.java:27) ~[NPCInteractEvent.class:?] at net.minecraftforge.fml.common.eventhandler.ASMEventHandler_6_NPCInteractEvent_onEntityNPCInteract_EntityInteract.invoke(.dynamic) ~[?:?] at net.minecraftforge.fml.common.eventhandler.ASMEventHandler.invoke(ASMEventHandler.java:90) ~[ASMEventHandler.class:?] at net.minecraftforge.fml.common.eventhandler.EventBus.post(EventBus.java:185) ~[EventBus.class:?] at net.minecraftforge.common.ForgeHooks.onInteractEntity(ForgeHooks.java:1008) ~[ForgeHooks.class:?] at net.minecraft.entity.player.EntityPlayer.interact(EntityPlayer.java:1246) ~[EntityPlayer.class:?] at net.minecraft.network.NetHandlerPlayServer.processUseEntity(NetHandlerPlayServer.java:1072) ~[NetHandlerPlayServer.class:?] at net.minecraft.network.play.client.CPacketUseEntity.processPacket(CPacketUseEntity.java:93) ~[CPacketUseEntity.class:?] at net.minecraft.network.play.client.CPacketUseEntity.processPacket(CPacketUseEntity.java:14) ~[CPacketUseEntity.class:?] at net.minecraft.network.PacketThreadUtil$1.run(PacketThreadUtil.java:15) ~[PacketThreadUtil$1.class:?] at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) ~[?:1.8.0_111] at java.util.concurrent.FutureTask.run(FutureTask.java:266) ~[?:1.8.0_111] at net.minecraft.util.Util.runTask(Util.java:25) ~[util.class:?] ... 5 more Caused by: java.lang.ClassNotFoundException: net.theviolentsquirrels.craftandconquer.client.renderer.entity.RenderNPCDialog at net.minecraft.launchwrapper.LaunchClassLoader.findClass(LaunchClassLoader.java:191) ~[launchwrapper-1.12.jar:?] at java.lang.ClassLoader.loadClass(ClassLoader.java:424) ~[?:1.8.0_111] at java.lang.ClassLoader.loadClass(ClassLoader.java:357) ~[?:1.8.0_111] at net.theviolentsquirrels.craftandconquer.event.NPCInteractEvent.onEntityNPCInteract(NPCInteractEvent.java:27) ~[NPCInteractEvent.class:?] at net.minecraftforge.fml.common.eventhandler.ASMEventHandler_6_NPCInteractEvent_onEntityNPCInteract_EntityInteract.invoke(.dynamic) ~[?:?] at net.minecraftforge.fml.common.eventhandler.ASMEventHandler.invoke(ASMEventHandler.java:90) ~[ASMEventHandler.class:?] at net.minecraftforge.fml.common.eventhandler.EventBus.post(EventBus.java:185) ~[EventBus.class:?] at net.minecraftforge.common.ForgeHooks.onInteractEntity(ForgeHooks.java:1008) ~[ForgeHooks.class:?] at net.minecraft.entity.player.EntityPlayer.interact(EntityPlayer.java:1246) ~[EntityPlayer.class:?] at net.minecraft.network.NetHandlerPlayServer.processUseEntity(NetHandlerPlayServer.java:1072) ~[NetHandlerPlayServer.class:?] at net.minecraft.network.play.client.CPacketUseEntity.processPacket(CPacketUseEntity.java:93) ~[CPacketUseEntity.class:?] at net.minecraft.network.play.client.CPacketUseEntity.processPacket(CPacketUseEntity.java:14) ~[CPacketUseEntity.class:?] at net.minecraft.network.PacketThreadUtil$1.run(PacketThreadUtil.java:15) ~[PacketThreadUtil$1.class:?] at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) ~[?:1.8.0_111] at java.util.concurrent.FutureTask.run(FutureTask.java:266) ~[?:1.8.0_111] at net.minecraft.util.Util.runTask(Util.java:25) ~[util.class:?] ... 5 more Caused by: java.lang.NoClassDefFoundError: net/minecraft/client/renderer/entity/RenderLiving at java.lang.ClassLoader.defineClass1(Native Method) ~[?:1.8.0_111] at java.lang.ClassLoader.defineClass(ClassLoader.java:763) ~[?:1.8.0_111] at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142) ~[?:1.8.0_111] at net.minecraft.launchwrapper.LaunchClassLoader.findClass(LaunchClassLoader.java:182) ~[launchwrapper-1.12.jar:?] at java.lang.ClassLoader.loadClass(ClassLoader.java:424) ~[?:1.8.0_111] at java.lang.ClassLoader.loadClass(ClassLoader.java:357) ~[?:1.8.0_111] at net.theviolentsquirrels.craftandconquer.event.NPCInteractEvent.onEntityNPCInteract(NPCInteractEvent.java:27) ~[NPCInteractEvent.class:?] at net.minecraftforge.fml.common.eventhandler.ASMEventHandler_6_NPCInteractEvent_onEntityNPCInteract_EntityInteract.invoke(.dynamic) ~[?:?] at net.minecraftforge.fml.common.eventhandler.ASMEventHandler.invoke(ASMEventHandler.java:90) ~[ASMEventHandler.class:?] at net.minecraftforge.fml.common.eventhandler.EventBus.post(EventBus.java:185) ~[EventBus.class:?] at net.minecraftforge.common.ForgeHooks.onInteractEntity(ForgeHooks.java:1008) ~[ForgeHooks.class:?] at net.minecraft.entity.player.EntityPlayer.interact(EntityPlayer.java:1246) ~[EntityPlayer.class:?] at net.minecraft.network.NetHandlerPlayServer.processUseEntity(NetHandlerPlayServer.java:1072) ~[NetHandlerPlayServer.class:?] at net.minecraft.network.play.client.CPacketUseEntity.processPacket(CPacketUseEntity.java:93) ~[CPacketUseEntity.class:?] at net.minecraft.network.play.client.CPacketUseEntity.processPacket(CPacketUseEntity.java:14) ~[CPacketUseEntity.class:?] at net.minecraft.network.PacketThreadUtil$1.run(PacketThreadUtil.java:15) ~[PacketThreadUtil$1.class:?] at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) ~[?:1.8.0_111] at java.util.concurrent.FutureTask.run(FutureTask.java:266) ~[?:1.8.0_111] at net.minecraft.util.Util.runTask(Util.java:25) ~[util.class:?] ... 5 more Caused by: java.lang.ClassNotFoundException: net.minecraft.client.renderer.entity.RenderLiving at net.minecraft.launchwrapper.LaunchClassLoader.findClass(LaunchClassLoader.java:101) ~[launchwrapper-1.12.jar:?] at java.lang.ClassLoader.loadClass(ClassLoader.java:424) ~[?:1.8.0_111] at java.lang.ClassLoader.loadClass(ClassLoader.java:357) ~[?:1.8.0_111] at java.lang.ClassLoader.defineClass1(Native Method) ~[?:1.8.0_111] at java.lang.ClassLoader.defineClass(ClassLoader.java:763) ~[?:1.8.0_111] at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142) ~[?:1.8.0_111] at net.minecraft.launchwrapper.LaunchClassLoader.findClass(LaunchClassLoader.java:182) ~[launchwrapper-1.12.jar:?] at java.lang.ClassLoader.loadClass(ClassLoader.java:424) ~[?:1.8.0_111] at java.lang.ClassLoader.loadClass(ClassLoader.java:357) ~[?:1.8.0_111] at net.theviolentsquirrels.craftandconquer.event.NPCInteractEvent.onEntityNPCInteract(NPCInteractEvent.java:27) ~[NPCInteractEvent.class:?] at net.minecraftforge.fml.common.eventhandler.ASMEventHandler_6_NPCInteractEvent_onEntityNPCInteract_EntityInteract.invoke(.dynamic) ~[?:?] at net.minecraftforge.fml.common.eventhandler.ASMEventHandler.invoke(ASMEventHandler.java:90) ~[ASMEventHandler.class:?] at net.minecraftforge.fml.common.eventhandler.EventBus.post(EventBus.java:185) ~[EventBus.class:?] at net.minecraftforge.common.ForgeHooks.onInteractEntity(ForgeHooks.java:1008) ~[ForgeHooks.class:?] at net.minecraft.entity.player.EntityPlayer.interact(EntityPlayer.java:1246) ~[EntityPlayer.class:?] at net.minecraft.network.NetHandlerPlayServer.processUseEntity(NetHandlerPlayServer.java:1072) ~[NetHandlerPlayServer.class:?] at net.minecraft.network.play.client.CPacketUseEntity.processPacket(CPacketUseEntity.java:93) ~[CPacketUseEntity.class:?] at net.minecraft.network.play.client.CPacketUseEntity.processPacket(CPacketUseEntity.java:14) ~[CPacketUseEntity.class:?] at net.minecraft.network.PacketThreadUtil$1.run(PacketThreadUtil.java:15) ~[PacketThreadUtil$1.class:?] at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) ~[?:1.8.0_111] at java.util.concurrent.FutureTask.run(FutureTask.java:266) ~[?:1.8.0_111] at net.minecraft.util.Util.runTask(Util.java:25) ~[util.class:?] ... 5 more I have explored the code of the Custom NPC mod to get some hints, but it seems that I am unable to find what I would like to do. I have checked the content of my .jar file and the class RenderNPCDialog does exist, so I don't quite understand what is going on. Thank you for your help ! Quote Squirrel ! Squirrel ! Squirrel ! Link to comment Share on other sites More sharing options...
Animefan8888 Posted January 14, 2017 Share Posted January 14, 2017 You will need to create a packet that sends this to the client(s). Quote VANILLA MINECRAFT CLASSES ARE THE BEST RESOURCES WHEN MODDING I will be posting 1.15.2 modding tutorials on this channel. If you want to be notified of it do the normal YouTube stuff like subscribing, ect. Forge and vanilla BlockState generator. Link to comment Share on other sites More sharing options...
Major Squirrel Posted January 14, 2017 Author Share Posted January 14, 2017 You will need to create a packet that sends this to the client(s). Okay so I just checked Vanilla and it seems that EntityWolf has the same thing as me: three different textures regarding the wolf behavior (tamed, not tamed and angry) and the getEntityTexture returns the correct one according to the correct behavior. But it does not seem to send any packet to the client. I don't understand why would I need to send any packet here since there is a NoClassDefFoundError. Would you mean to send a packet to the client so that - on the client - it calls the function from RenderNPCDialog ? If yes, is it the correct thing to do in general in Minecraft to notify players of a texture change ? Quote Squirrel ! Squirrel ! Squirrel ! Link to comment Share on other sites More sharing options...
Major Squirrel Posted January 15, 2017 Author Share Posted January 15, 2017 First of all, you cannot have this as a static field in your renderer. It would mean that the texture for all of your entities always change at once. You need to store the texture in the entity. Yup, thank you. I will change that so that the texture index has to be stored directly in this entity. Maybe I can do it with DataWatchers ? The wolf synchronizes the necessary state (tamed, angry) to the client via the DataWatcher mechanic, you should be able to find a tutorial if you don't know how to use it. There was an old tutorial on the wiki, but the link isn't available anymore... I'm gonna try to read through the source code tho. Quote Squirrel ! Squirrel ! Squirrel ! Link to comment Share on other sites More sharing options...
Major Squirrel Posted January 15, 2017 Author Share Posted January 15, 2017 Good evening, I managed to use DataWatchers - not really DataWatchers, more DataParameter and EntityDataManager - to store the texture index in the entity and thus being able to make it work. EntityNPCDialog: public class EntityNPCDialog extends EntityLiving { private static final DataParameter<Integer> TEXTURE_INDEX = EntityDataManager.<Integer>createKey(EntityNPCDialog.class, DataSerializers.VARINT); public EntityNPCDialog(World worldIn) { super(worldIn); } @Override protected void entityInit() { super.entityInit(); this.dataManager.register(TEXTURE_INDEX, 0); } @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); } public void setTextureIndex() { int textureID = this.dataManager.get(TEXTURE_INDEX); this.dataManager.set(TEXTURE_INDEX, (textureID + 1 < 2) ? textureID + 1 : 0); } public int getTextureIndex() { return (this.dataManager.get(TEXTURE_INDEX)); } } NPCInteractEvent: public class NPCInteractEvent { @SubscribeEvent public void onEntityNPCInteract(PlayerInteractEvent.EntityInteract event) { ItemStack heldItem = event.getEntityPlayer().getHeldItem(EnumHand.MAIN_HAND); ItemBase npcManager = CraftAndConquerItems.npcManager; if (event.getTarget() instanceof EntityNPCDialog && event.getHand().equals(EnumHand.MAIN_HAND) && heldItem.getItem().equals(npcManager)) { if (!event.getWorld().isRemote) ((EntityNPCDialog) event.getTarget()).setTextureIndex(); } } } NPCInteractEvent @SideOnly(Side.CLIENT) public class RenderNPCDialog extends RenderLiving<EntityNPCDialog> { public 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"), }; public RenderNPCDialog(RenderManager renderManagerIn, ModelBase modelBaseIn, float shadowSizeIn) { super(renderManagerIn, modelBaseIn, shadowSizeIn); } @Override protected ResourceLocation getEntityTexture(EntityNPCDialog entity) { return (RenderNPCDialog.NPC_DIALOG_TEXTURES[entity.getTextureIndex()]); } } Here is what I did : I took a look at the EntityWolf and RenderWolf vanilla classes which cover the purpose of my question. The Wolf has three skins according to its state (tamed, not tamed and angry as written above). The getEntityTexture method in RenderWolf returns the correct texture according to different checks (isTamed and isAngry). Actually, those booleans are updated at the same time the EntityWolf's DataParameters are. (You can see a DataParameter named TAMED in EntityTameable which is the extend of the EntityWolf class.) All I had to do was to create a custom DataParameter for my entity (TEXTURE_INDEX), override the entityInit method to register my DataParameter into the EntityDataManager of my custom entity, and correctly get and set the value in my TEXTURE_INDEX parameter. The NoClassDefFoundError was there because I was trying to access my Render class from my Entity class, now there is no access anymore. The last thing I have to do is to store the index in NBT tags in order to retrieve the correct texture when the server restarts. I have one question though: what if I don't want to get the texture from an existing array, but loading it from a folder ? Right now, all the clients are aware of the different textures of the entity because they are stored in the class. Would it be possible to load the texture from a folder from the server, applying it to the entity and notify all the clients that the texture has changed ? Right now, I would see a problem because the clients would not be aware of this specific texture applied on the entity (you know, same when a player changes his skin from minecraft.net, there has to be a reconnect on the server in order to update the thing). Quote Squirrel ! Squirrel ! Squirrel ! Link to comment Share on other sites More sharing options...
Major Squirrel Posted January 15, 2017 Author Share Posted January 15, 2017 You would either have to transfer the texture to the client through normal packets and then manually inject it into the texture system, or use the same mechanic skins use and host them on a server somewhere. I didn't really know where to start, so I took a look at vanilla classes and I noticed the getDownloadImageSkin method in AbstractClientPlayer. I naively and simply copy-pasted the method into my custom entity class and changed the method's content so that it downloads a specific texture (hard-coded, I will change this later once it works) from imgur and then put this texture instead of the NPC default one. Moreover, I created a DefaultNPCSkin class (similar to the existing DefaultPlayerSkin vanilla class) which holds the default texture for NPCs and is accessible from my Renderer and the NPCInteractEvent class. I don't know why, but I'm getting a cast error between ThreadDownloadImageData and SimpleTexture in my own getDownloadImageSkin method. The thing is, I just copy-pasted the existing one from vanilla and it seems to work well, so I don't quite understand what is going on: yet, ThreadDownloadImageData extends from multiple classes (SimpleTexture, which itself extends from AbstractTexture), especially AbstractTexture which implements the ITextureObject. Could you help me on this one ? EntityNPCDialog: public class EntityNPCDialog extends EntityLiving { // private static final DataParameter<Integer> TEXTURE_INDEX = EntityDataManager.<Integer>createKey(EntityNPCDialog.class, DataSerializers.VARINT); public EntityNPCDialog(World worldIn) { super(worldIn); } // @Override // protected void entityInit() { // super.entityInit(); // // this.dataManager.register(TEXTURE_INDEX, 0); // } @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); } // public void setTextureIndex() { // int textureID = this.dataManager.get(TEXTURE_INDEX); // // this.dataManager.set(TEXTURE_INDEX, (textureID + 1 < 2) ? textureID + 1 : 0); // } // // public int getTextureIndex() { // return (this.dataManager.get(TEXTURE_INDEX)); // } public static ThreadDownloadImageData getDownloadImageSkin(ResourceLocation resourceLocationIn) { TextureManager texturemanager = Minecraft.getMinecraft().getTextureManager(); ITextureObject itextureobject = texturemanager.getTexture(resourceLocationIn); if (itextureobject == null) { itextureobject = new ThreadDownloadImageData((File) null, "http://imgur.com/Z0pbA3P.png", DefaultNPCSkin.getDefaultSkin(), new ImageBufferDownload()); texturemanager.loadTexture(resourceLocationIn, itextureobject); } return ((ThreadDownloadImageData) itextureobject); } } NPCInteractEvent public class NPCInteractEvent { @SubscribeEvent public void onEntityNPCInteract(PlayerInteractEvent.EntityInteract event) { ItemStack heldItem = event.getEntityPlayer().getHeldItem(EnumHand.MAIN_HAND); ItemBase npcManager = CraftAndConquerItems.npcManager; if (event.getTarget() instanceof EntityNPCDialog && event.getHand().equals(EnumHand.MAIN_HAND) && heldItem.getItem().equals(npcManager)) { if (!event.getWorld().isRemote) EntityNPCDialog.getDownloadImageSkin(DefaultNPCSkin.getDefaultSkin()); } } } DefaultNPCSkin: public class DefaultNPCSkin { private static final ResourceLocation NPC_DIALOG_DEFAULT_TEXTURE = new ResourceLocation(CraftAndConquer.MODID, "textures/entities/npc/npc_dialog.png"); public static ResourceLocation getDefaultSkin() { return (NPC_DIALOG_DEFAULT_TEXTURE); } } RenderNPCDialog: public class RenderNPCDialog extends RenderLiving<EntityNPCDialog> { // public 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"), // }; public RenderNPCDialog(RenderManager renderManagerIn, ModelBase modelBaseIn, float shadowSizeIn) { super(renderManagerIn, modelBaseIn, shadowSizeIn); } @Override protected ResourceLocation getEntityTexture(EntityNPCDialog entity) { return (DefaultNPCSkin.getDefaultSkin()); } } Logs from the console (I tested on singleplayer first, before going further with dedicated server): [18:10:29] [server thread/ERROR] [FML]: Exception caught during firing event net.minecraftforge.event.entity.player.PlayerInteractEvent$EntityInteract@32971884: java.lang.ClassCastException: net.minecraft.client.renderer.texture.SimpleTexture cannot be cast to net.minecraft.client.renderer.ThreadDownloadImageData at net.theviolentsquirrels.craftandconquer.entity.EntityNPCDialog.getDownloadImageSkin(EntityNPCDialog.java:92) ~[EntityNPCDialog.class:?] at net.theviolentsquirrels.craftandconquer.event.NPCInteractEvent.onEntityNPCInteract(NPCInteractEvent.java:27) ~[NPCInteractEvent.class:?] at net.minecraftforge.fml.common.eventhandler.ASMEventHandler_6_NPCInteractEvent_onEntityNPCInteract_EntityInteract.invoke(.dynamic) ~[?:?] at net.minecraftforge.fml.common.eventhandler.ASMEventHandler.invoke(ASMEventHandler.java:90) ~[ASMEventHandler.class:?] at net.minecraftforge.fml.common.eventhandler.EventBus.post(EventBus.java:185) [EventBus.class:?] at net.minecraftforge.common.ForgeHooks.onInteractEntity(ForgeHooks.java:1008) [ForgeHooks.class:?] at net.minecraft.entity.player.EntityPlayer.interact(EntityPlayer.java:1246) [EntityPlayer.class:?] at net.minecraft.network.NetHandlerPlayServer.processUseEntity(NetHandlerPlayServer.java:1072) [NetHandlerPlayServer.class:?] at net.minecraft.network.play.client.CPacketUseEntity.processPacket(CPacketUseEntity.java:93) [CPacketUseEntity.class:?] at net.minecraft.network.play.client.CPacketUseEntity.processPacket(CPacketUseEntity.java:14) [CPacketUseEntity.class:?] at net.minecraft.network.PacketThreadUtil$1.run(PacketThreadUtil.java:15) [PacketThreadUtil$1.class:?] at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) [?:1.8.0_111] at java.util.concurrent.FutureTask.run(FutureTask.java:266) [?:1.8.0_111] at net.minecraft.util.Util.runTask(Util.java:25) [util.class:?] at net.minecraft.server.MinecraftServer.updateTimeLightAndEntities(MinecraftServer.java:742) [MinecraftServer.class:?] at net.minecraft.server.MinecraftServer.tick(MinecraftServer.java:687) [MinecraftServer.class:?] at net.minecraft.server.integrated.IntegratedServer.tick(IntegratedServer.java:156) [integratedServer.class:?] at net.minecraft.server.MinecraftServer.run(MinecraftServer.java:536) [MinecraftServer.class:?] at java.lang.Thread.run(Thread.java:745) [?:1.8.0_111] [18:10:29] [server thread/ERROR] [FML]: Index: 1 Listeners: [18:10:29] [server thread/ERROR] [FML]: 0: NORMAL [18:10:29] [server thread/ERROR] [FML]: 1: ASM: net.theviolentsquirrels.craftandconquer.event.NPCInteractEvent@664a3770 onEntityNPCInteract(Lnet/minecraftforge/event/entity/player/PlayerInteractEvent$EntityInteract;)V [18:10:29] [server thread/FATAL]: Error executing task java.util.concurrent.ExecutionException: java.lang.ClassCastException: net.minecraft.client.renderer.texture.SimpleTexture cannot be cast to net.minecraft.client.renderer.ThreadDownloadImageData at java.util.concurrent.FutureTask.report(FutureTask.java:122) ~[?:1.8.0_111] at java.util.concurrent.FutureTask.get(FutureTask.java:192) ~[?:1.8.0_111] at net.minecraft.util.Util.runTask(Util.java:26) [util.class:?] at net.minecraft.server.MinecraftServer.updateTimeLightAndEntities(MinecraftServer.java:742) [MinecraftServer.class:?] at net.minecraft.server.MinecraftServer.tick(MinecraftServer.java:687) [MinecraftServer.class:?] at net.minecraft.server.integrated.IntegratedServer.tick(IntegratedServer.java:156) [integratedServer.class:?] at net.minecraft.server.MinecraftServer.run(MinecraftServer.java:536) [MinecraftServer.class:?] at java.lang.Thread.run(Thread.java:745) [?:1.8.0_111] Caused by: java.lang.ClassCastException: net.minecraft.client.renderer.texture.SimpleTexture cannot be cast to net.minecraft.client.renderer.ThreadDownloadImageData at net.theviolentsquirrels.craftandconquer.entity.EntityNPCDialog.getDownloadImageSkin(EntityNPCDialog.java:92) ~[EntityNPCDialog.class:?] at net.theviolentsquirrels.craftandconquer.event.NPCInteractEvent.onEntityNPCInteract(NPCInteractEvent.java:27) ~[NPCInteractEvent.class:?] at net.minecraftforge.fml.common.eventhandler.ASMEventHandler_6_NPCInteractEvent_onEntityNPCInteract_EntityInteract.invoke(.dynamic) ~[?:?] at net.minecraftforge.fml.common.eventhandler.ASMEventHandler.invoke(ASMEventHandler.java:90) ~[ASMEventHandler.class:?] at net.minecraftforge.fml.common.eventhandler.EventBus.post(EventBus.java:185) ~[EventBus.class:?] at net.minecraftforge.common.ForgeHooks.onInteractEntity(ForgeHooks.java:1008) ~[ForgeHooks.class:?] at net.minecraft.entity.player.EntityPlayer.interact(EntityPlayer.java:1246) ~[EntityPlayer.class:?] at net.minecraft.network.NetHandlerPlayServer.processUseEntity(NetHandlerPlayServer.java:1072) ~[NetHandlerPlayServer.class:?] at net.minecraft.network.play.client.CPacketUseEntity.processPacket(CPacketUseEntity.java:93) ~[CPacketUseEntity.class:?] at net.minecraft.network.play.client.CPacketUseEntity.processPacket(CPacketUseEntity.java:14) ~[CPacketUseEntity.class:?] at net.minecraft.network.PacketThreadUtil$1.run(PacketThreadUtil.java:15) ~[PacketThreadUtil$1.class:?] at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) ~[?:1.8.0_111] at java.util.concurrent.FutureTask.run(FutureTask.java:266) ~[?:1.8.0_111] at net.minecraft.util.Util.runTask(Util.java:25) ~[util.class:?] ... 5 more Quote Squirrel ! Squirrel ! Squirrel ! Link to comment Share on other sites More sharing options...
Recommended Posts
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.