A lot of people have been experiencing problems with making new mobs or new Entities of any kind. While looking on these forums I saw a lot of error reports like this
Skipping Entity with id -72
java.lang.NullPointerException
at net.minecraft.src.NetClientHandler.handleMobSpawn(NetClientHandler.java:726)
at net.minecraft.src.Packet24MobSpawn.processPacket(Packet24MobSpawn.java:131)
at net.minecraft.src.MemoryConnection.processReadPackets(MemoryConnection.java:65)
at net.minecraft.src.NetClientHandler.processReadPackets(NetClientHandler.java:91)
at net.minecraft.src.WorldClient.tick(WorldClient.java:64)
at net.minecraft.client.Minecraft.runTick(Minecraft.java:1614)
at net.minecraft.client.Minecraft.runGameLoop(Minecraft.java:775)
at net.minecraft.client.Minecraft.run(Minecraft.java:723)
at java.lang.Thread.run(Unknown Source)
I went to that line of code and it's calling the method handleMobSpawn which in there it retrieves the Entity based on the EntityId. That error report above happens when that Entity that's being retrieved is null. So I double checked my code and made sure I added my Mob to the EntityList using ModLoader method,
The Entity is registered but I kept on getting the error report. But If you look at the first line of the error report,
Skipping Entity with id -72
you can see the Entity Id doesn't look right. In Modloader the method ModLoader.getUniqueEntityId() returns an EntityId which starts at 3000. So every time you call that method it will increment which gives an unique Id for each Entity. My Entity Id should be 3000 but why is Minecraft saying it's -72?
Apparently the problem is in the class Packet24MobSpawn. It's a packet class so it sends data to the Clients; correct me if I'm wrong. Looking at the constructor I noticed this line of code
this.type is an integer which is the type of mob and EntityList.getEntityID(par1EntityLiving) retrieves the Id from the Entity object(par1EntityLiving). Simple right? So if my Entity Id is 3000 then this.type should be 3000 too, but it's not. It's actually -72. Reason is because java is casting it to a byte. In Java, bytes range from -128 to 127 therefor 3000 isn't going to cast right. It's -72 because of Narrowing Primitive Conversion,
That being said, any value over 127 isn't going to work. If you look at EntityList.class and inside the static block you can see all the Entities' with their Ids. Every single one of them is below 127 except EntityEnderCrystal. EntityEnderCrystal uses Packet23VehicleSpawn which doesn't cast the Entity value, so no problem with that.
/** The entity ID. */
public int entityId;
/** The type of mob. */
public int type;
....
public Packet24MobSpawn(EntityLiving par1EntityLiving) {
this.entityId = par1EntityLiving.entityId;
this.type = (byte) EntityList.getEntityID(par1EntityLiving);
......
}
Above is a segment of Packet24MobSpawn. What I don't get is why they(Mojang) are casting the type field. type isn't a byte. My guess is since this packet is being sent to each client they want the values to have less data, or is this a bug? For now I'm just removing the cast statement so custom mobs can work. http://www.minecraft.../#entry17289084
You're a smart guy(or girl?). Either way, thanks for taking some time to explain it!
Thanks and guy btw. I tried my best at explaining it but most people will understand it. I just hope more people will see this. So far there are two ways around this. You can set your Entitiy Id to an Id that isn't in use or just take of the cast operation.
First solution
Use an Id that is between -128 to 127 which isn't in use. See below for Ids. Yes you can use this method minecraft probably reserved these Ids for future Entities.
Second solution
Remove the cast operation in Packet24MobSpawn class itself. Then just use any Id.
Thanks and guy btw. I tried my best at explaining it but most people will understand it. I just hope more people will see this. So far there are two ways around this. You can set your Entitiy Id to an Id that isn't in use or just take of the cast operation.
First solution
Use an Id that is between -128 to 127 which isn't in use. See below for Ids. Yes you can use this method minecraft probably reserved these Ids for future Entities.
Second solution
Remove the cast operation in Packet24MobSpawn class itself. Then just use any Id.
MrShawman is right. In the end you can only use 0-255. Even if you take off the byte cast you're still using 0-255. Yes all bytes in java are unsigned but doing the operation (byte & 255) will make it unsigned; you will still have to use another primitive, in this case Minecraft uses an integer. So that's why this.type is an integer. Still the constructor for Packet24MobSpawn has to be changed.
If you however leave it as it was and take off the byte cast you will be able to use any EntityId but the data won't be saved correctly since the packet is reading and writing it as a byte. Yes your Entity may work in the game but saving and restoring will make errors. Note I didn't test it out.
Edit:
I think the read and write packet methods only get called when you have multiple clients, meaning multiplayer.
Pretty sure there must also be an issue with MCP's decompilation process, as I'm writing a patch for a mod (currently on 1.3.1) which works fine when installed and played on the Minecraft jar, but the mobs are invisible in MCP.
Pretty sure there must also be an issue with MCP's decompilation process, as I'm writing a patch for a mod (currently on 1.3.1) which works fine when installed and played on the Minecraft jar, but the mobs are invisible in MCP.
I don't think it's MCP because all that does is decompile and fix all the class,methods, field names etc. Mobs work perfectly in MCP for me.
Rollback Post to RevisionRollBack
Same ****, different day - Modification Development Section
my entity throwable is invisible but i don't know why? when you make a throwable item do you only need to give it a ovveride texture like a item or do you need anything more? like a renderer or something?
The problem with throwable Entities is they don't use the Packet24MobSpawn packet. It uses the Packet23VehicleSpawn packet. See below for the main differences. That being said it's going to be more work lol. Every VehicleSpawn packet has their own if-else statement in the base file classes; EntityTrackerEntry, EntityTracker, and NetClientHandler. You could however add your Entity to that if-else statements but for more you make it will get confusing. Since you are editing these base classes your mod probably won't be compatible with other mods that do the same thing, but it will allow you to continue making your mod without having your Entities "invisible". I had a similar problem like yours so I needed a quick fix for now. This is how I did it.
Put that class in your mod, might need to format it or fix the imports too. I wasn't planning on releasing that so it might be confusing. After that edit your BaseMod class to something like this http://pastebin.com/EJghrHTk
Just make sure you set up the ModEntityHelper object. After that you need to edit some base classes...
Parameters(6 or 7)
entityClass(Class<? extends Entity>) - Your Entity class
entityId(int) - Entity Id
weightedProb(int) - Higher number means more likely to spawn.
min(int) - Minimum number of entities per spawn attempt.
max(int) - Maximum number of entities per spawn attempt.
creatureType(EnumCreatureType) - The type of list to add entity to. Monster, Creature, or Water.
biome(BiomeGenBase[]) - Array of biomes to add entity spawning to.
Registering a Mob Entity with Spawn Not recommended
Parameters(5 or 6)
entityClass(Class<? extends Entity>) - Your Entity class
weightedProb(int) - Higher number means more likely to spawn.
min(int) - Minimum number of entities per spawn attempt.
max(int) - Maximum number of entities per spawn attempt.
creatureType(EnumCreatureType) - The type of list to add entity to. Monster, Creature, or Water.
biome(BiomeGenBase[]) - Array of biomes to add entity spawning to.
Parameters(2)
entry(ModEntityHelper.EntityEntry) - Entity Entry, see below for more info
entityId(int) - Entity Id
I'm not going to post the rest of the methods because they are basically the name with the exception of EntityEntry.
ModEntityHelper.EntityEntry
EntityEntry.class is a static subclass of ModEntityHelper. The constructor has 4 arguments.
EntityEntry entry = new EntityEntry(EntityBlank.class, 64,20, true)
entityClass(Class<? extends Entity>) - Your Entity class
blocksDistanceThreshold(int) - distance to render
updateFrequency(int) - It is what it says,check for sync when ticks % updateFrequency==0, that's from MCP.
trackMotion(int) - Should track motion, most of the time this is true.
I'm still not completely sure on those fields but you can look in EntityTrackerEntry for more information.
Note that the Entity name is entityClass.class.getSimpleName(). Which returns the name of the class.
Main differences between Packet24MobSpawn and Packet23VehicleSpawn
Most obvious one is MobSpawn is for mobs, which makes sense. It has pitch, yaw, and velocity. VehicleSpawn is for just about everything else, that is spawned in the world. Examples are Items, Minecarts, Snowballs, Boats, Arrows and more. They need to be created separately which is why you have to edit base classes. Another difference is their Ids. MobSpawn goes from 0-255, if you changed some code that I said above, but VehicleSpawn goes from -128 to 128. Both of them use ints for Ids but VehicleSpawn doesn't case it to a byte. That being said you can give it any number but be warned when the packet writes or reads data. It will write it as a byte so don't use ModLoader for the Id. Look at both classes for more information.
This might be somewhat confusing but it works. For now this is what I'm doing.
BaseMod - your mod Class - Entity class int - Entity Id int - View distance of entity int - update frequency, in ticks boolean - Whether or not its motion should be tracked by the integrated server.
After it's added it to ModLoader, override the following two methods in your BaseMod class spawnEntity and getSpawnPacket
Here is an example
@Override
public Entity spawnEntity(int entityId, World worldClient, double x,
double y, double z) {
switch (entityId) {
case 101:
return new EntityBlank(worldClient, x, y, z);
default:
return null;
}
}
@Override
public Packet23VehicleSpawn getSpawnPacket(Entity entity, int type) {
if (entity instanceof EntityBlank)
return new Packet23VehicleSpawn(entity, type);
else
return null;
}
In the first method I made a switch statement which will create the Entity based on the Id of Entity. The second method I do an if statement depending on what Entity it is and make the Vehicle Packet.
If your Vehicle Packet will always be the same you could remove the if-else statement.
@Override
public Packet23VehicleSpawn getSpawnPacket(Entity entity, int type) {
return new Packet23VehicleSpawn(entity, type);
}
I went to that line of code and it's calling the method handleMobSpawn which in there it retrieves the Entity based on the EntityId. That error report above happens when that Entity that's being retrieved is null. So I double checked my code and made sure I added my Mob to the EntityList using ModLoader method,
The Entity is registered but I kept on getting the error report. But If you look at the first line of the error report,
you can see the Entity Id doesn't look right. In Modloader the method ModLoader.getUniqueEntityId() returns an EntityId which starts at 3000. So every time you call that method it will increment which gives an unique Id for each Entity. My Entity Id should be 3000 but why is Minecraft saying it's -72?
Apparently the problem is in the class Packet24MobSpawn. It's a packet class so it sends data to the Clients; correct me if I'm wrong. Looking at the constructor I noticed this line of code
this.type is an integer which is the type of mob and EntityList.getEntityID(par1EntityLiving) retrieves the Id from the Entity object(par1EntityLiving). Simple right? So if my Entity Id is 3000 then this.type should be 3000 too, but it's not. It's actually -72. Reason is because java is casting it to a byte. In Java, bytes range from -128 to 127 therefor 3000 isn't going to cast right. It's -72 because of Narrowing Primitive Conversion,
That being said, any value over 127 isn't going to work. If you look at EntityList.class and inside the static block you can see all the Entities' with their Ids. Every single one of them is below 127 except EntityEnderCrystal. EntityEnderCrystal uses Packet23VehicleSpawn which doesn't cast the Entity value, so no problem with that.
Update for Forge
http://www.minecraft...0#entry18822284
Above is a segment of Packet24MobSpawn.
What I don't get is why they(Mojang) are casting the type field. type isn't a byte. My guess is since this packet is being sent to each client they want the values to have less data, or is this a bug? For now I'm just removing the cast statement so custom mobs can work.http://www.minecraft.../#entry17289084
Why are my Entities invisible?
http://www.minecraft...7#entry17351137
Difference between Mob and Vehicle spawners and more
http://www.minecraft...0#entry17786787
I just wanted to point this out and may not fix everything but it's a start. If you have any information on this please tell us.
Thanks and guy btw. I tried my best at explaining it but most people will understand it. I just hope more people will see this. So far there are two ways around this. You can set your Entitiy Id to an Id that isn't in use or just take of the cast operation.
First solution
Use an Id that is between -128 to 127 which isn't in use. See below for Ids. Yes you can use this method minecraft probably reserved these Ids for future Entities.
Second solution
Remove the cast operation in Packet24MobSpawn class itself. Then just use any Id.
Read this too http://www.minecraft.../#entry17289084
Entity Ids
In use
Not in use
The entity Id 2, is that in or not in use?
Sorry it is in use, just made a mistake. Look at EntityList.class to see if it's in use too.
Ok, thanks
Nice! Thanks. For some reason, my entity is still working... I do only have one, but yeah. It's still fine, not sure why.
Might be a decompiler error.
They are sending the data as byte and convertering it to a int so 0-255 should be useable
I don't think it's a decompiler error because I looked at the byte code myself.
Good point, didn't see that.
Only problem is in order to use 0-255, the line where it is casting the entity id to a byte will also have to use that bitwise operation too.
Reason is because the handleMobSpawn method in the NetClientHandler class creates the Entity based of the id of the packet.
Thanks for the info anyway!
If you however leave it as it was and take off the byte cast you will be able to use any EntityId but the data won't be saved correctly since the packet is reading and writing it as a byte. Yes your Entity may work in the game but saving and restoring will make errors. Note I didn't test it out.
Edit:
I think the read and write packet methods only get called when you have multiple clients, meaning multiplayer.
I don't think it's MCP because all that does is decompile and fix all the class,methods, field names etc. Mobs work perfectly in MCP for me.
Not sure exactly what the issue is, then.
Yes
Update: http://www.minecraftforum.net/topic/1417041-mod-entity-problem/page__st__20#entry17445833
The problem with throwable Entities is they don't use the Packet24MobSpawn packet. It uses the Packet23VehicleSpawn packet. See below for the main differences. That being said it's going to be more work lol. Every VehicleSpawn packet has their own if-else statement in the base file classes; EntityTrackerEntry, EntityTracker, and NetClientHandler. You could however add your Entity to that if-else statements but for more you make it will get confusing. Since you are editing these base classes your mod probably won't be compatible with other mods that do the same thing, but it will allow you to continue making your mod without having your Entities "invisible". I had a similar problem like yours so I needed a quick fix for now. This is how I did it.
ModEntityHelper http://pastebin.com/6ez0MKz2
Put that class in your mod, might need to format it or fix the imports too. I wasn't planning on releasing that so it might be confusing. After that edit your BaseMod class to something like this http://pastebin.com/EJghrHTk
Just make sure you set up the ModEntityHelper object. After that you need to edit some base classes...
EntityTracker.addEntityToTracker
At the end of the long if-else statements, put
http://pastebin.com/8WpXLn3r
EntityTracker.getPacketForThisEntity
After the first if statement put
http://pastebin.com/NhkjUFNH
NetClientHandler.handleVehicleSpawn
I didn't know exactly where to put it so It's after the first long if-else statement.
http://pastebin.com/kqY053Nw
Once you do all of that it should be set up and you can know register new Entities with ModEntityHelper class. Using it isn't hard.
How to use ModEntityHelper
Registering a Mob Entity with Entity Id
Parameters(2)
entityClass(Class<? extends Entity>) - Your Entity class
entityId(int) - Entity Id
Registering a Mob Entity using ModLoader's Entity Id Not recommended.
Parameters(1)
entityClass(Class<? extends Entity>) - Your Entity class
Registering a Mob Entity with Entity Id and Spawn
Parameters(6 or 7)
entityClass(Class<? extends Entity>) - Your Entity class
entityId(int) - Entity Id
weightedProb(int) - Higher number means more likely to spawn.
min(int) - Minimum number of entities per spawn attempt.
max(int) - Maximum number of entities per spawn attempt.
creatureType(EnumCreatureType) - The type of list to add entity to. Monster, Creature, or Water.
biome(BiomeGenBase[]) - Array of biomes to add entity spawning to.
Registering a Mob Entity with Spawn Not recommended
Parameters(5 or 6)
entityClass(Class<? extends Entity>) - Your Entity class
weightedProb(int) - Higher number means more likely to spawn.
min(int) - Minimum number of entities per spawn attempt.
max(int) - Maximum number of entities per spawn attempt.
creatureType(EnumCreatureType) - The type of list to add entity to. Monster, Creature, or Water.
biome(BiomeGenBase[]) - Array of biomes to add entity spawning to.
Registering an Entity Entry with Entity Id
Parameters(2)
entry(ModEntityHelper.EntityEntry) - Entity Entry, see below for more info
entityId(int) - Entity Id
I'm not going to post the rest of the methods because they are basically the name with the exception of EntityEntry.
ModEntityHelper.EntityEntry
EntityEntry.class is a static subclass of ModEntityHelper. The constructor has 4 arguments.
entityClass(Class<? extends Entity>) - Your Entity class
blocksDistanceThreshold(int) - distance to render
updateFrequency(int) - It is what it says,check for sync when ticks % updateFrequency==0, that's from MCP.
trackMotion(int) - Should track motion, most of the time this is true.
I'm still not completely sure on those fields but you can look in EntityTrackerEntry for more information.
Note that the Entity name is entityClass.class.getSimpleName(). Which returns the name of the class.
Main differences between Packet24MobSpawn and Packet23VehicleSpawn
Most obvious one is MobSpawn is for mobs, which makes sense. It has pitch, yaw, and velocity. VehicleSpawn is for just about everything else, that is spawned in the world. Examples are Items, Minecarts, Snowballs, Boats, Arrows and more. They need to be created separately which is why you have to edit base classes. Another difference is their Ids. MobSpawn goes from 0-255, if you changed some code that I said above, but VehicleSpawn goes from -128 to 128. Both of them use ints for Ids but VehicleSpawn doesn't case it to a byte. That being said you can give it any number but be warned when the packet writes or reads data. It will write it as a byte so don't use ModLoader for the Id. Look at both classes for more information.
This might be somewhat confusing but it works. For now this is what I'm doing.
First just add an Entity Tracker
The parameters go in this order
BaseMod - your mod
Class - Entity class
int - Entity Id
int - View distance of entity
int - update frequency, in ticks
boolean - Whether or not its motion should be tracked by the integrated server.
After it's added it to ModLoader, override the following two methods in your BaseMod class
spawnEntity and getSpawnPacket
Here is an example
In the first method I made a switch statement which will create the Entity based on the Id of Entity. The second method I do an if statement depending on what Entity it is and make the Vehicle Packet.
If your Vehicle Packet will always be the same you could remove the if-else statement.
Still don't use that method, until it is fixed.