Jump to content

[1.7.10] Random?! On An Entity Model


Rui

Recommended Posts

I got the Random object by casting down the passed in Entity to EntityLivingBase. To actually ensure that each entity had its own starting breath value, however, I had to make a Hashmap to keep track of each unique pig's starting breath (and created that value if it wasn't in the Hashmap yet). I then added it into my formula for breathing. Voila!

 

---- SOLUTION ABOVE ----

 

So I am currently working on making my models "breathe". It's working just like I want, except all entities that are rendered at the same time breathe at the same time (for example, when you join the world). So I tried this--

 

public class LAModelPig extends ModelBase

{

  [boxes and all that good stuff]

   

    Random rand;

    float startingBreath;

 

  public LAModelPig()

  {

rand = new Random();

startingBreath = rand.nextFloat();

      [...]

}

 

Nope, they still all breathe in perfect synchronization. I tried initializing both values in the global values, and just random in the globals; nothing worked.

 

I would like for this value to be connected to the entity so that each person sees the same thing. Entity has a rand Random object, buuut it's protected and as I'm working with the vanilla pig entity, I have no way of accessing that. I hear you can access protected fields through reflection? Would this cause a lot of overhead? I may potentially be calling .nextFloat() in the doRender function for other things. Is there maybe an easier way to do this?

Link to comment
Share on other sites

Man, now you've lost me. I did some searching and the most I could find was code to serialize one's inventory, but I wouldn't even know where to begin on making my own code to serialize a Random object. Not sure where I could look to find one either-- this is my first time really messing around with NBT tags.

Link to comment
Share on other sites

The consistency of the random isn't as important as the fact that I have a random object to pass around and that it is connected to a particularly entity, so that when I do the model it does random for each individual entity, and not just once for all of them.

 

Diesieben, you said there is only one renderer for all models, but I'm doing this in the model file, not the render file. Shouldn't each entity have its own model object then? That's why I was confused when putting it in the constructor didn't work.

Link to comment
Share on other sites

Looks like I'm going to have to use NBT tags after all. I can't use entity.getRand() in the Model because the only places that have an entity passed in are called continuously, and I can't cast EntityPig to LAEntityPig since it's not a subclass of EntityLivingBase.

 

Unless maybe if I can add a function to EntityPigs that lets me access the corresponding LAEntityPig? Is there a (relatively) easy way to do this?

Link to comment
Share on other sites

Okay, here's how my mod is set up.

 

I have a class called LAEntityPig, but maybe it should be called ModifyPig or something instead. It doesn't extend entity because I'm not actually making an LAEntityPig; that's the class where I modify the EntityPig upon its joining the world.

 

RenderLAPig and ModelLAPig don't call LAEntityPig, just the vanilla EntityPig. So I have no way of getting information directly from the instantiation of LAEntityPig.

Link to comment
Share on other sites

I have four methods from which I can call EntityPig:

 

render

setRotation

setRotationAngles

setLivingAnimations

 

To my understanding, all of these methods will loop until the pig is dead, unloaded or what-have-you. So I repeatedly assign the same random to the Model, so what. Well, I have to assign the value of startingBreath in that method as well. But I need to call startingBreath = rand.nextFloat() only once.

 

I mean, I guess I could just have it change to random numbers infinitely until the pig leaves the world, but I still need to have startingBreath added to the breathing formula only at the start.

Link to comment
Share on other sites

I need it in render, with my breathing block:

 

if(!entity.isDead) {

    GL11.glPushMatrix();

    float breath = MathHelper.cos(entity.ticksExisted * .1F + startingBreath) * 0.05F + 1F;

    GL11.glScalef(breath, breath, breath);

    GL11.glTranslatef(0.0F, 1.0F - breath, 0.0F);

    } 

    body.render(f5);

    if(!entity.isDead) {

    GL11.glPopMatrix();

    }

 

Although now I realize that it won't work that way since it will keep adding startingBreath. But yeah, I need it initialized for every entity and then added just once.

Link to comment
Share on other sites

If I'm understanding right, you want an RNG to seed your breathing animation function with so that you don't have every single animal breathing in synchronicity.

 

Instead of telling you how to do this, may I make a fundamental design suggestion? It sounds like you don't need a "random" value, just that you need a "relatively unique" value. Why not make some kind of hash function for the entity's unique ID? Use entity.getUniqueID() as your "seed" so to speak, and have some method work it into the range you need for your "starting breath" value.

Link to comment
Share on other sites

See, that's the thing though. I need to have some sort of way to have that part of the method called only once within the render function, or else it'd keep adding and make the animation all jerky.

 

I can actually call .getRNG() if I cast the entity passed into a LivingEntityBase, so I've taken care of that problem. Or... hopefully I did? I don't exactly remember the rules of downcasting.

Link to comment
Share on other sites

Figured it out! I'll update the first post with the solution.

 

MrCaracal, though I didn't use the ID for the actual breathing value, your reply gave me the idea of differentiating between entities in the Model class with their UUIDs, so I'll give you a thank you for that.

Link to comment
Share on other sites

I see your solution, but I don't know that I would recommend it.

 

You've employed a workaround to the fact that every time you call rand.nextFloat() you receive a different value. You don't need a new random value every time render() is called on your model, and you certainly don't need to be polling a HashMap every time render() is called to make sure the random number you got this time is the same one you got the first time. I doubt that this will scale very nicely with a large number of entities.

 

A random number generator simply isn't what you need for this application, I think... especially given you've gone to some length to ensure that the number you're getting is not random per render() call, but constant.

Link to comment
Share on other sites

I'll agree it's not a very elegant solution, but it's the only one I could come up with given the knowledge base I have right now. I'm not sure how else to get the render to differentiate between entities... Even the !entity.isDead conditional for the breathing doesn't work. The renderer seems very insistent on using the same values for every entity.

Link to comment
Share on other sites

Well, if the solution works as well as you need it to, I won't rain on your parade any further, but I will advise you to put it on your to-do list for things to take another look at in the future.

 

As for the other thing you just mentioned, isDead only returns true on the tick before the entity is to be destroyed. It's not exactly a "dead" flag in the way we'd think of a dead pig, i.e. one with zero hearts remaining. If you want your model to halt the breathing animation some time before that, I think you'll need to come up with a different trigger.

Link to comment
Share on other sites

Hey, I only just really got started in modding, so honestly I'm not really familiar with the Minecraft code environment at all. If you have any suggestions feel free to throw them at me!

 

And thank you for the tip on isDead!

Link to comment
Share on other sites

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.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.



×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.