Jump to content

[1.10.02] Entity constructor not working correctly


TrekkieCub314

Recommended Posts

I have a custom entity class that has a constructor that doesn't seem to be working.  The entity is designed to die when it hits certain kinds of blocks, and it's correctly done so.  The problem was, the block it was sent from can be the same kind as it can die on, so I wanted to store the source block's blockPos in the entity class so I can make sure it doesn't die on the source block.  I also have an orientation variable that changes the color of the entity depending on its value.  The problem is I tried to set these in a constructor, but said constructor doesn't seem to be setting these values.  I found a work-around for the position part, but the orientation part I can't seem to fix.  Can anyone see what might be going wrong?

 

[spoiler=entity class]

package com.trekkiecub.oddsandends.entity;

import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.projectile.EntityThrowable;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.RayTraceResult;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;

import com.trekkiecub.oddsandends.blocks.Block_Sceptre_Top;
import com.trekkiecub.oddsandends.util.OAE_Func;

public class Entity_PowerOrb extends EntityThrowable {
private int initX = -1;
private int initY = -1;
private int initZ = -1;
private int lifeTimer = 0;
private int orientation = 0;
private int timerMax = 300;
private int texFrames = 3;
public Entity_PowerOrb(World worldIn) {
	super(worldIn);
	this.setSize(0.25F, 0.25F);
}
public Entity_PowerOrb(World worldIn, double d, double e, double f, int orientation)
{
	super(worldIn, d, e, f);
	this.initX = MathHelper.floor_double(d);
	this.initY = MathHelper.floor_double(e);
	this.initZ = MathHelper.floor_double(f);
	this.setSize(0.25F, 0.25F);
	this.orientation = orientation;
}

public void setOrientation(int o)
{
	this.orientation = o;
}

public int getOrientation() {return orientation;}

public Entity_PowerOrb(World worldIn, EntityLivingBase throwerIn)
{
	super(worldIn, throwerIn);
}

@Override
protected void entityInit() {
	// TODO Auto-generated method stub

}

public void readEntityFromNBT(NBTTagCompound compound) {
	super.readEntityFromNBT(compound);
	this.orientation = compound.getInteger("orientation");
	this.lifeTimer = compound.getInteger("lifeTimer");
	this.initX = compound.getInteger("initX");
	this.initY = compound.getInteger("initY");
	this.initZ = compound.getInteger("initZ");

}

public void writeEntityToNBT(NBTTagCompound compound) {
	super.writeEntityToNBT(compound);
	compound.setInteger("orientation", this.orientation);
	compound.setInteger("lifeTimer", this.lifeTimer);
	compound.setInteger("posX", this.initX);
	compound.setInteger("posY", this.initY);
	compound.setInteger("posZ", this.initZ);
}

public void onUpdate()
{
	// Kill entity if too old
	lifeTimer++;
	if (lifeTimer > timerMax)
	{
		this.kill();
	}

	this.lastTickPosX = this.posX;
        this.lastTickPosY = this.posY;
        this.lastTickPosZ = this.posZ;
        
        // Ray Tracing
        
        Vec3d vec3d = new Vec3d(this.posX, this.posY, this.posZ);
        Vec3d vec3d1 = new Vec3d(this.posX + this.motionX, this.posY + this.motionY, this.posZ + this.motionZ);
        RayTraceResult raytraceresult = this.worldObj.rayTraceBlocks(vec3d, vec3d1);
        vec3d = new Vec3d(this.posX, this.posY, this.posZ);
        vec3d1 = new Vec3d(this.posX + this.motionX, this.posY + this.motionY, this.posZ + this.motionZ);

        if (raytraceresult != null)
        {
            vec3d1 = new Vec3d(raytraceresult.hitVec.xCoord, raytraceresult.hitVec.yCoord, raytraceresult.hitVec.zCoord);
        }
        
        if (raytraceresult != null)
        {
        	this.onImpact(raytraceresult);
        }
        
        // Update Initial Position
        if (this.initY < 0)
        {
        	this.initX = MathHelper.floor_double(this.posX);
        	this.initY = MathHelper.floor_double(this.posY);
        	this.initZ = MathHelper.floor_double(this.posZ);
        }
        
        BlockPos source = new BlockPos(this.initX, this.initY, this.initZ);
        if (!source.equals(this.getPosition()))
        {
        	if (this.worldObj.getBlockState(this.getPosition()).getBlock() instanceof Block_Sceptre_Top)
        	{
        		Vec3d currentCenter = OAE_Func.blockCenter(this.getPosition());
            	if (vec3d.distanceTo(currentCenter) < 0.25D)
            	{
            		this.kill();
            	}	
        	}
        }
        
        
	this.posX += this.motionX;
	this.posY += this.motionY;
	this.posZ += this.motionZ;
	this.setPosition(this.posX, this.posY, this.posZ);
}

@Override
public boolean func_189652_ae()
{
	return true;
}

@SideOnly(Side.CLIENT)
    public boolean isInRangeToRenderDist(double distance)
    {
        double d0 = this.getEntityBoundingBox().getAverageEdgeLength() * 4.0D;

        if (Double.isNaN(d0))
        {
            d0 = 4.0D;
        }

        d0 = d0 * 64.0D;
        return distance < d0 * d0;
    }
public int getTexByLifetime()
{
	if (lifeTimer%(2*texFrames) < texFrames)
	{
		return lifeTimer%texFrames;
	}
	else
	{
		return texFrames - 1 - (lifeTimer%texFrames);
	}
}

protected void onImpact(RayTraceResult result) {
	if (result.typeOfHit == RayTraceResult.Type.BLOCK && !(this.worldObj.getBlockState(result.getBlockPos()).getBlock() instanceof Block_Sceptre_Top))
	{
		this.orientation = 1 - this.orientation;
	}
	else if (result.typeOfHit == RayTraceResult.Type.ENTITY && result.entityHit instanceof Entity_PowerOrb)
	{
		this.kill();
	}
}


}

 

 

[spoiler=tile entity onUpdate]

public void updateEntity()
{
	if (!this.worldObj.isRemote)
	{
		cooldown++;
		cooldown = cooldown%maxCooldown;
		if (cooldown == 0 && destinations.size() != 0)
		{
			BlockPos targetPos;
			for (int i = 0; i < destinations.size(); i++)
			{
				targetPos = destinations.get(i).getBlockPos();
				Entity_PowerOrb entity = new Entity_PowerOrb(this.worldObj, this.pos.getX()+.5, this.pos.getY()+.375, this.pos.getZ()+.5, this.worldObj.rand.nextInt(2));
				entity.setThrowableHeading(targetPos.getX() + .5 - entity.posX, targetPos.getY() + .375 - entity.posY, targetPos.getZ() + .5 - entity.posZ, 0.05F, 0);
				this.worldObj.spawnEntityInWorld(entity);
			}
		}
		markDirty();
	}
}

 

 

[spoiler=Renderer]

package com.trekkiecub.oddsandends.render;

import com.trekkiecub.oddsandends.entity.Entity_PowerOrb;

import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.renderer.OpenGlHelper;
import net.minecraft.client.renderer.RenderHelper;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.client.renderer.VertexBuffer;
import net.minecraft.client.renderer.entity.Render;
import net.minecraft.client.renderer.entity.RenderManager;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.entity.item.EntityXPOrb;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.math.MathHelper;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;

@SideOnly(Side.CLIENT)
public class RenderPowerOrb extends Render<Entity_PowerOrb>{
private static final ResourceLocation EXPERIENCE_ORB_TEXTURES = new ResourceLocation("textures/entity/experience_orb.png");
public RenderPowerOrb(RenderManager renderManager) {
	super(renderManager);
	this.shadowSize = 0.15F;
        this.shadowOpaque = 0.75F;
}

/**
     * Renders the desired {@code T} type Entity.
     */
@Override
    public void doRender(Entity_PowerOrb entity, double x, double y, double z, float entityYaw, float partialTicks)
    {
        if (!this.renderOutlines)
        {
            GlStateManager.pushMatrix();
            GlStateManager.translate((float)x, (float)y, (float)z);
            this.bindEntityTexture(entity);
            RenderHelper.enableStandardItemLighting();
            int i = entity.getTexByLifetime();
            float f = (float)(i % 4 * 16 + 0) / 64.0F;
            float f1 = (float)(i % 4 * 16 + 16) / 64.0F;
            float f2 = (float)(i / 4 * 16 + 0) / 64.0F;
            float f3 = (float)(i / 4 * 16 + 16) / 64.0F;
            float f4 = 1.0F;
            float f5 = 0.5F;
            float f6 = 0.25F;
            int j = entity.getBrightnessForRender(partialTicks);
            int k = j % 65536;
            int l = j / 65536;
            OpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, (float)k, (float)l);
            GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F);
            float f8 = 255.0F;
            float f9 = ((float)entity.getOrientation() * 100 + partialTicks) / 2.0F;
            
            l = (int)((MathHelper.sin(f9 + 0.0F) + 1.0F) * 0.5F * 255.0F);
            int i1 = 255;
            int j1 = (int)((MathHelper.sin(f9 + 4.1887903F) + 1.0F) * 0.1F * 255.0F);
            
            GlStateManager.translate(0.0F, 0.1F, 0.0F);
            GlStateManager.rotate(180.0F - this.renderManager.playerViewY, 0.0F, 1.0F, 0.0F);
            GlStateManager.rotate((float)(this.renderManager.options.thirdPersonView == 2 ? -1 : 1) * -this.renderManager.playerViewX, 1.0F, 0.0F, 0.0F);
            float f7 = 0.3F;
            GlStateManager.scale(0.3F, 0.3F, 0.3F);
            Tessellator tessellator = Tessellator.getInstance();
            VertexBuffer vertexbuffer = tessellator.getBuffer();
            vertexbuffer.begin(7, DefaultVertexFormats.POSITION_TEX_COLOR_NORMAL);
            double redMult = entity.getOrientation();
            double greenMult = 0.2 + 0.3*(1 - entity.getOrientation());
            double blueMult = 1 - entity.getOrientation();
            int red = (int) (255 * redMult);
            int green = (int) (255 * greenMult);
            int blue = (int) (255 * blueMult);
            vertexbuffer.pos(-0.5D, -0.25D, 0.0D).tex((double)f, (double)f3).color(red, green, blue, 128).normal(0.0F, 1.0F, 0.0F).endVertex();
            vertexbuffer.pos(0.5D, -0.25D, 0.0D).tex((double)f1, (double)f3).color(red, green, blue, 128).normal(0.0F, 1.0F, 0.0F).endVertex();
            vertexbuffer.pos(0.5D, 0.75D, 0.0D).tex((double)f1, (double)f2).color(red, green, blue, 128).normal(0.0F, 1.0F, 0.0F).endVertex();
            vertexbuffer.pos(-0.5D, 0.75D, 0.0D).tex((double)f, (double)f2).color(red, green, blue, 128).normal(0.0F, 1.0F, 0.0F).endVertex();
            tessellator.draw();
            GlStateManager.disableBlend();
            GlStateManager.disableRescaleNormal();
            GlStateManager.popMatrix();
            super.doRender(entity, x, y, z, entityYaw, partialTicks);
        }
    }

@Override
protected ResourceLocation getEntityTexture(Entity_PowerOrb entity) {
	// TODO Auto-generated method stub
	return EXPERIENCE_ORB_TEXTURES;
}

}

 

 

Link to comment
Share on other sites

I'm sure.  I've updated my post to include the onUpdate() portion of the tile entity that spawns said entity.

So where do you check the orientation?

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

At the moment, in the renderer.  The renderer is working perfectly, as it switches over if I change the orientation value manually in the entity class.

How are you changing it, I feel the problem is that orientation is not synced between client and server... Look into DataWatcher

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

The renderer code does not modify anything in the entity class, just pull information from it.  As I said, the renderer works fine if I change the orientation value in the entity class itself.  The problem is that the constructor is not setting the value for the orientation when supplied via constructor.  I'll include the renderer code in my original post if something is wrong there.

 

I was also looking at my renderer code and noticed I was overriding the doRender function, and I'm not sure if I'm supposed to do that as I call the super class's doRender function.  Whether I overrode the parent function didn't change the outcome.

Link to comment
Share on other sites

You should never set a value in the constructor.  There are something like three different constructors for entities, which are all used in different places.  Depending on which one you're using, that value might be being overwriten when the entity gets an update from the server that tells it what the server knows/sends to the client.

Apparently I'm a complete and utter jerk and come to this forum just like to make fun of people, be confrontational, and make your personal life miserable.  If you think this is the case, JUST REPORT ME.  Otherwise you're just going to get reported when you reply to my posts and point it out, because odds are, I was trying to be nice.

 

Exception: If you do not understand Java, I WILL NOT HELP YOU and your thread will get locked.

 

DO NOT PM ME WITH PROBLEMS. No help will be given.

Link to comment
Share on other sites

The constructor I'm using is a custom one for the entity itself.  You can find the constructor in the code I supplied.

 

I'm trying to set values that will change from instance to instance of this entity.  How am I supposed to set said values without using a constructor (btw, a setter isn't working either)?

Link to comment
Share on other sites

The client side doesnt care about your custom constructor.

It just gets told you have a entity on the server so it creates a new one using the World constructor. And then makes it read from NBT.

So As stated, there is no real reason to use custom constructors for entities, make sure your data is stored and sent to the client.

I do Forge for free, however the servers to run it arn't free, so anything is appreciated.
Consider supporting the team on Patreon

Link to comment
Share on other sites

The renderer code does not modify anything in the entity class, just pull information from it.  As I said, the renderer works fine if I change the orientation value in the entity class itself. 

 

Although your main problem is with the custom constructor, as mentioned above, I think you still don't get the full scope of what I was explaining. There is the entity class and then there are instances of the entity class. For every entity that spawns in the game, there are actually two instances -- one on client and one on server. The fields in these instances can only be synced up through network packets. The built-in fields like position are automatically kept in sync through built-in packets.

 

Furthermore, the syncing isn't necessarily in both ways. Like if you update the position only on the client, it won't take effect for long because the next time the server sync's it will return to the old value.

 

So, from within a client side class like the renderer, you cannot actually change things like position, at least without sending a custom packet and handling it on the server.

 

It may appear to work for something that is visual like orientation because the visual effect is processed on the client. For example, if you had a custom field in your entity that controlled whether the entity glowed, if you set that on the client the glowing would probably work. However, if you save the game, you'd lose that glow because the save information only happens on the server side.

 

Not sure if that was clear, but it is an important concept. Basically the thing to remember there are two entity instances running in parallel and the server side is the master and they won't be synced unless you use custom packets.

 

One last important thing, if you ever spawn an entity from the client side, it might appear to work but is really just a phantom that isn't fully recognized by the game. This is actually okay for something like a particle that is a temporary visual effect, but generally better to have server aware of all entities.

Check out my tutorials here: http://jabelarminecraft.blogspot.com/

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.

Announcements



×
×
  • Create New...

Important Information

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