The Ocelot code that deals with fish and coming towards you is not actually in the Ocelot code, it's in AITempt (I think). There's a line in the Ocelot code at the top: this.tasks.addTask(3, this.field_48149_b = new EntityAITempt(this, 0.18F, Item.fishRaw.shiftedIndex, true));
If you are using AI for everything else you can probably put this in there somewhere (changing the 3 near the beginning to be whatever # task it is now), and remember to change the Item.fishRaw to Item.apple or whatever you want to tempt the Eevees with.
Unless the 3 is the order it should be looked at? AI code is all so new.
The code I showed doesn't actually do anything about the temptation of fish or bones. That will only deal with when you click the entity, taming it, healing it, or making it sit/get up. Pre-1.2 I would have tried to use updateEntityActionState to deal with temptation, but the AI stuff should do the trick now.
I've gotten AI Tempt to work beautifully with apples, it's the sitting that's the problem. After you tame them if you're still holding an apple, they will continue to stand until you switch items. And then if they're sitting and you take out apples, they sit while periodically shifting to standing for a moment. It's like the code's fighting with itself, haha.
Still looking for a solution to this problem in the code.
Well, I can only guess at things at this point. Tempting and Sitting are two different AI classes, so I would hope you've not accidentally given them the same number in the tasks list. If you've more or less copied the Ocelot or even the Wolf's coding in the Interact method, they should do exactly as those do, and sit once tamed. You don't explicitly call any AI tasks in other locations other than at the top of the class, right? It sounds as if you're trying to use the AI Beg, judging by how they will respond when an apple appears in your hand.
Does the rest of their AI work correctly? That is, will they stand when clicked with anything then sit when clicked again, run after certain mobs, of scare away creepers (if you kept those bits from Ocelots, of course)?
you made that on techne.. yeh some of the values have issues, when exporting; export to java and call it Model(name) for some reason when techne exports to minecraft forat(including render file) it screws up.
The only parts I called from Ocelots were EntityAITempt and EntityAIAvoidEntity-- no chasing after chickens and stuff, hehe. And yes, the sitting commands work correctly, although not when I'm holding the treat. That's not really an issue for me, though.
Did some more searching today, came up with nothing. Somebody has got to have an answer.
Edit: Oh, derp. I do plan on releasing this to the public once I've got most everything working in proper order.
Well, cats won't sit/stand when I'm holding fish (although I'm in 1.2.2 for whatever reason) so I'm glad that doesn't seem to be a problem. If you have all the seemingly-random func_#### that the cats do, and they still will not sit when becoming tamed, then something elsewhere is probably interfering. Would it be too much to ask for you to send me the entity code, or at least post clips of it?
For instance, func_48097_s_ in the Ocelot code seems to deal with sneaking. If you had that and had modified things in there, maybe the Eevee is trying to sit and sprint/sneak at the same time.
*Fist pump* Yes!
At first I couldn't figure out what you were seeing; the Eevees would respond to apples, and if they sat only after moving slightly, it was no biggie. Then I started getting multiple Eevees following me, and I began to notice the problem you mentioned, where they'd 'jump' when I switched to the apple. Much puzzling through the Ocelot and Wolf code later, and a thought passes through my head: "what if the Task order makes a difference?"
this.tasks.addTask(#, field_48146_a);
this.tasks.addTask(#+1, field_48149_b = new EntityAITempt(this, 0.18F, Item.appleRed.shiftedIndex, true));
this.tasks.addTask(#+2, new EntityAIAvoidEntity(this, net.minecraft.src.EntityPlayer.class, 16F, 0.23F, 0.4F));
It doesn't matter where in the task list you put these three, but you must make sure that Sitting comes before Tempt, which comes before Avoid. Actually, scratch that. It probably matters, so at least put them up near 3, 4, 5 to be sure.
If sitting is after temp, then we get the glitching. If Avoid is before Tempt, they always run away before we can get close enough to Tempt.
I could pound my head on my desk, this solution seems so simple, yet it took us days to figure it out.
*Fist pump* Yes!
At first I couldn't figure out what you were seeing; the Eevees would respond to apples, and if they sat only after moving slightly, it was no biggie. Then I started getting multiple Eevees following me, and I began to notice the problem you mentioned, where they'd 'jump' when I switched to the apple. Much puzzling through the Ocelot and Wolf code later, and a thought passes through my head: "what if the Task order makes a difference?"
this.tasks.addTask(#, field_48146_a);
this.tasks.addTask(#+1, field_48149_b = new EntityAITempt(this, 0.18F, Item.appleRed.shiftedIndex, true));
this.tasks.addTask(#+2, new EntityAIAvoidEntity(this, net.minecraft.src.EntityPlayer.class, 16F, 0.23F, 0.4F));
It doesn't matter where in the task list you put these three, but you must make sure that Sitting comes before Tempt, which comes before Avoid. Actually, scratch that. It probably matters, so at least put them up near 3, 4, 5 to be sure.
If sitting is after temp, then we get the glitching. If Avoid is before Tempt, they always run away before we can get close enough to Tempt.
I could pound my head on my desk, this solution seems so simple, yet it took us days to figure it out.
By jord, I think I'm in love with you.
Thank you SO MUCH for figuring that out! >_< Now I can get onto adding some fun little animations... And it should be completed before soon!
I've added in a bit extra so that there's the chance of finding a shiny eevee! Problem: The shiny eevees don't stay shiny (and normal eevees sometimes turn shiny). I'm looking into the ocelot code to figure out how to keep the textures saved, but it's not as easy as it appears.
It shouldn't be that difficult, really. There's "getEntityTexture" which does what it says, so supply it with a silver skin and a brown skin. Of course, it is using a certain function to do this switching. In Eclipse, if you highlight a function or variable it will show the location of every place that function is used in the page; use this to find where all the other places this function is used. You will find you need to save the data to NBT, as "shiny" or "eeveetype".
Baby animals use this as well, to determine if they're Siamese or Tuxedo cats, so you might want to make sure it's included in the baby animal section.
Then you see that the function itself looks to object data byte 18, so make sure you include something like "this.dataWatcher.addObject(18, Byte.valueOf((byte)0));" in entityInit().
The problem is I can't figure out the getEntityTexture method, mostly because I have never seen the switch function before. Where in the world is it determining the cases?
Also, I took out the code from the first post because it just felt... kind of weird having it out there in the open.
The Switch function or operation or whatever it is called, is a sort of IF statement. We start by running the function in the Switch, this.func_48148_ad(). This function, if we scroll to the bottom of the Ocelot code, says return this.dataWatcher.getWatchableObjectByte(18), which really all it does it look at a certain number that the monster data itself is storing (or at least that is how I look at it).
So the Switch is in fact looking at what the value of ObjectByte(18) is. The next part of any Switch operation is the Case. Case 0 means "do this when the value that we're looking at is 0". Case 1 means, value = 1. And so on.
ObjectByte(18) is set near the bottom of the code as well, and is called whenever you tame an Ocelot or when a pair of cats have a child.
Lastly, in the Ocelot's code there is the last line "default" which means, what happens if ObjectByte(18) is none of the above?
For Eevees, you will probably only need two cases, 0 for brown Eevees, and 1 for Shiny. Default should probably be left as super.getEntityTexture() just for redundancy.
18 is just the 18th dataWatcher entry, which are probably various bits and pieces of information the entity stores. Since 16 and 17 are used by entityTameable, it's a good idea to use the higher numbers such as 18. 18 in particular because we know the Ocelot uses it for it's cat type, so we can use the same number for Eevee's rarity type since it amounts to the same thing.
public boolean isShiny() {
return isShiny;
}
/**
* (abstract) Protected helper method to write subclass entity data to NBT.
*/
public void writeEntityToNBT(NBTTagCompound par1NBTTagCompound)
{
super.writeEntityToNBT(par1NBTTagCompound);
par1NBTTagCompound.setBoolean("Shiny", isShiny());
par1NBTTagCompound.setBoolean("Locked", locked);
}
public void setShiny() {
isShiny = rand.nextInt(2) == 0;
}
/**
* (abstract) Protected helper method to read subclass entity data from NBT.
*/
public void readEntityFromNBT(NBTTagCompound par1NBTTagCompound)
{
super.readEntityFromNBT(par1NBTTagCompound);
isShiny = par1NBTTagCompound.getBoolean("Shiny");
locked = par1NBTTagCompound.getBoolean("Locked");
}
public String getTexture() {
if (isShiny) {
return "/mob/eeveeshiny.png";
} else {
return "/mob/eevee.png";
}
}
In onUpdate:
if (!locked) {
setShiny();
locked = true;
}
And then in the beginning of the code, the locked and isShiny booleans are initialized as false. There's no problem with the shiny code, it works beautifully, but for whatever reason the NBTTags don't seem to actually get used.
Edit: Oh, er, scratch that. The Shiny code works fine if the setShiny() piece is in the constructor rather than the onUpdate code, but the problem is still there.
Edit2: ... or it DID, but now it doesn't seem to be working at all. /headdesk, wtf
Edit3: Ok, I got the texture to change again, by putting if (!locked) above getTexture() in the constructor. However, saving it still poses a problem.
dataWatcherUpdate(1);
texture = "/mob/eevee.png";
setShiny(); <-- line 16
Methods and such:
public void writeEntityToNBT(NBTTagCompound par1NBTTagCompound)
{
super.writeEntityToNBT(par1NBTTagCompound);
par1NBTTagCompound.setInteger("Shiny", dataWatcher());
}
public void setShiny() {
if (rand.nextInt(2) == 0) { // determines if Eevee will be Shiny
dataWatcherUpdate(0);
} else { // else Eevee will be standard color
dataWatcherUpdate(1);
}
}
/**
* (abstract) Protected helper method to read subclass entity data from NBT.
*/
public void readEntityFromNBT(NBTTagCompound par1NBTTagCompound)
{
super.readEntityFromNBT(par1NBTTagCompound);
dataWatcherUpdate(par1NBTTagCompound.getInteger("Shiny"));
}
public String getTexture() {
switch (dataWatcher()) {
case 0:
return "/mob/eeveeshiny.png";
case 1:
return "/mob/eevee.png";
}
return super.getEntityTexture();
}
public int dataWatcher()
{
return dataWatcher.getWatchableObjectByte(18);
}
public void dataWatcherUpdate(int par1)
{
dataWatcher.updateObject(18, Byte.valueOf((byte)par1)); <-- line 255
}
And the error code, the bit that matters anyway:
Caused by: java.lang.NullPointerException
at net.minecraft.src.DataWatcher.updateObject(DataWatcher.java:78)
at net.minecraft.src.EntityEevee.dataWatcherUpdate(EntityEevee.java:255)
at net.minecraft.src.EntityEevee.<init>(EntityEevee.java:16)
I noticed at the top of my error code I also had:
java.lang.reflect.InvocationTargetException
at sun.reflect.GeneratedConstructorAccessor12.newInstance(Unknown Source)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:525)
I've gotten AI Tempt to work beautifully with apples, it's the sitting that's the problem. After you tame them if you're still holding an apple, they will continue to stand until you switch items. And then if they're sitting and you take out apples, they sit while periodically shifting to standing for a moment. It's like the code's fighting with itself, haha.
Still looking for a solution to this problem in the code.
Does the rest of their AI work correctly? That is, will they stand when clicked with anything then sit when clicked again, run after certain mobs, of scare away creepers (if you kept those bits from Ocelots, of course)?
Did some more searching today, came up with nothing. Somebody has got to have an answer.
Edit: Oh, derp. I do plan on releasing this to the public once I've got most everything working in proper order.
For instance, func_48097_s_ in the Ocelot code seems to deal with sneaking. If you had that and had modified things in there, maybe the Eevee is trying to sit and sprint/sneak at the same time.
At first I couldn't figure out what you were seeing; the Eevees would respond to apples, and if they sat only after moving slightly, it was no biggie. Then I started getting multiple Eevees following me, and I began to notice the problem you mentioned, where they'd 'jump' when I switched to the apple. Much puzzling through the Ocelot and Wolf code later, and a thought passes through my head: "what if the Task order makes a difference?"
It doesn't matter where in the task list you put these three, but you must make sure that Sitting comes before Tempt, which comes before Avoid. Actually, scratch that. It probably matters, so at least put them up near 3, 4, 5 to be sure.
If sitting is after temp, then we get the glitching. If Avoid is before Tempt, they always run away before we can get close enough to Tempt.
I could pound my head on my desk, this solution seems so simple, yet it took us days to figure it out.
By jord, I think I'm in love with you.
Thank you SO MUCH for figuring that out! >_< Now I can get onto adding some fun little animations... And it should be completed before soon!
Baby animals use this as well, to determine if they're Siamese or Tuxedo cats, so you might want to make sure it's included in the baby animal section.
Then you see that the function itself looks to object data byte 18, so make sure you include something like "this.dataWatcher.addObject(18, Byte.valueOf((byte)0));" in entityInit().
Hopefully that helps.
Also, I took out the code from the first post because it just felt... kind of weird having it out there in the open.
So the Switch is in fact looking at what the value of ObjectByte(18) is. The next part of any Switch operation is the Case. Case 0 means "do this when the value that we're looking at is 0". Case 1 means, value = 1. And so on.
ObjectByte(18) is set near the bottom of the code as well, and is called whenever you tame an Ocelot or when a pair of cats have a child.
Lastly, in the Ocelot's code there is the last line "default" which means, what happens if ObjectByte(18) is none of the above?
For Eevees, you will probably only need two cases, 0 for brown Eevees, and 1 for Shiny. Default should probably be left as super.getEntityTexture() just for redundancy.
In onUpdate:
And then in the beginning of the code, the locked and isShiny booleans are initialized as false. There's no problem with the shiny code, it works beautifully, but for whatever reason the NBTTags don't seem to actually get used.
Edit: Oh, er, scratch that. The Shiny code works fine if the setShiny() piece is in the constructor rather than the onUpdate code, but the problem is still there.
Edit2: ... or it DID, but now it doesn't seem to be working at all. /headdesk, wtf
Edit3: Ok, I got the texture to change again, by putting if (!locked) above getTexture() in the constructor. However, saving it still poses a problem.
Initializing code:
Methods and such:
And the error code, the bit that matters anyway:
Caused by: java.lang.NullPointerException
at net.minecraft.src.DataWatcher.updateObject(DataWatcher.java:78)
at net.minecraft.src.EntityEevee.dataWatcherUpdate(EntityEevee.java:255)
at net.minecraft.src.EntityEevee.<init>(EntityEevee.java:16)
I noticed at the top of my error code I also had:
java.lang.reflect.InvocationTargetException
at sun.reflect.GeneratedConstructorAccessor12.newInstance(Unknown Source)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:525)
Anyone know what's up?
I am ninja'd far too often.