Jump to content

Recommended Posts

Posted

I've created a custom throwable class which is basically minecraft's default throwable class with a few values changed. I'm trying to do some math based on where the entity is in relation to the player that threw it. However, the client side copy of the entity has the thrower as null while the server doesn't. This causes null pointer errors when I try to access the thrower and it runs on the client. Any idea how to get the client and server synced correctly?

 

Taji34EntityThrowable.java:

package com.taji34.troncraft;

import java.util.List;

import net.minecraft.block.Block;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.IProjectile;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.init.Blocks;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.AxisAlignedBB;
import net.minecraft.util.MathHelper;
import net.minecraft.util.MovingObjectPosition;
import net.minecraft.util.Vec3;
import net.minecraft.world.World;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;

public abstract class Taji34EntityThrowable extends Entity implements IProjectile {
    private int field_145788_c = -1;
    private int field_145786_d = -1;
    private int field_145787_e = -1;
    private Block field_145785_f;
    protected boolean inGround;
    public int throwableShake;
    /** The entity that threw this throwable item. */
    private EntityLivingBase thrower;
    private String throwerName;
    private int ticksInGround;
    private int ticksInAir;
    private static final String __OBFID = "CL_00001723";

    public Taji34EntityThrowable(World par1World)
    {
        super(par1World);
        this.setSize(0.25F, 0.25F);
    }

    protected void entityInit() {}

    /**
     * Checks if the entity is in range to render by using the past in distance and comparing it to its average edge
     * length * 64 * renderDistanceWeight Args: distance
     */
    @SideOnly(Side.CLIENT)
    public boolean isInRangeToRenderDist(double par1)
    {
        double d1 = this.boundingBox.getAverageEdgeLength() * 4.0D;
        d1 *= 64.0D;
        return par1 < d1 * d1;
    }

    public Taji34EntityThrowable(World par1World, EntityLivingBase par2EntityLivingBase)
    {
        super(par1World);
        this.thrower = par2EntityLivingBase;
        this.setSize(0.25F, 0.25F);
        this.setLocationAndAngles(par2EntityLivingBase.posX, par2EntityLivingBase.posY + (double)par2EntityLivingBase.getEyeHeight(), par2EntityLivingBase.posZ, par2EntityLivingBase.rotationYaw, par2EntityLivingBase.rotationPitch);
        this.posX -= (double)(MathHelper.cos(this.rotationYaw / 180.0F * (float)Math.PI) * 0.16F);
        this.posY -= 0.10000000149011612D;
        this.posZ -= (double)(MathHelper.sin(this.rotationYaw / 180.0F * (float)Math.PI) * 0.16F);
        this.setPosition(this.posX, this.posY, this.posZ);
        this.yOffset = 0.0F;
        float f = 0.4F;
        this.motionX = (double)(-MathHelper.sin(this.rotationYaw / 180.0F * (float)Math.PI) * MathHelper.cos(this.rotationPitch / 180.0F * (float)Math.PI) * f);
        this.motionZ = (double)(MathHelper.cos(this.rotationYaw / 180.0F * (float)Math.PI) * MathHelper.cos(this.rotationPitch / 180.0F * (float)Math.PI) * f);
        this.motionY = (double)(-MathHelper.sin((this.rotationPitch + this.func_70183_g()) / 180.0F * (float)Math.PI) * f);
        this.setThrowableHeading(this.motionX, this.motionY, this.motionZ, this.func_70182_d(), 1.0F);
    }

    public Taji34EntityThrowable(World par1World, double par2, double par4, double par6)
    {
        super(par1World);
        this.ticksInGround = 0;
        this.setSize(0.25F, 0.25F);
        this.setPosition(par2, par4, par6);
        this.yOffset = 0.0F;
    }

    protected float func_70182_d()
    {
        return 1.5F;
    }

    protected float func_70183_g()
    {
        return 0.0F;
    }

    /**
     * Similar to setArrowHeading, it's point the throwable entity to a x, y, z direction.
     */
    public void setThrowableHeading(double par1, double par3, double par5, float par7, float par8)
    {
        float f2 = MathHelper.sqrt_double(par1 * par1 + par3 * par3 + par5 * par5);
        par1 /= (double)f2;
        par3 /= (double)f2;
        par5 /= (double)f2;
        par1 += this.rand.nextGaussian() * 0.007499999832361937D * (double)par8;
        par3 += this.rand.nextGaussian() * 0.007499999832361937D * (double)par8;
        par5 += this.rand.nextGaussian() * 0.007499999832361937D * (double)par8;
        par1 *= (double)par7;
        par3 *= (double)par7;
        par5 *= (double)par7;
        this.motionX = par1;
        this.motionY = par3;
        this.motionZ = par5;
        float f3 = MathHelper.sqrt_double(par1 * par1 + par5 * par5);
        this.prevRotationYaw = this.rotationYaw = (float)(Math.atan2(par1, par5) * 180.0D / Math.PI);
        this.prevRotationPitch = this.rotationPitch = (float)(Math.atan2(par3, (double)f3) * 180.0D / Math.PI);
        this.ticksInGround = 0;
    }

    /**
     * Sets the velocity to the args. Args: x, y, z
     */
    @SideOnly(Side.CLIENT)
    public void setVelocity(double par1, double par3, double par5)
    {
        this.motionX = par1;
        this.motionY = par3;
        this.motionZ = par5;

        if (this.prevRotationPitch == 0.0F && this.prevRotationYaw == 0.0F)
        {
            float f = MathHelper.sqrt_double(par1 * par1 + par5 * par5);
            this.prevRotationYaw = this.rotationYaw = (float)(Math.atan2(par1, par5) * 180.0D / Math.PI);
            this.prevRotationPitch = this.rotationPitch = (float)(Math.atan2(par3, (double)f) * 180.0D / Math.PI);
        }
    }

    /**
     * Called to update the entity's position/logic.
     */
    public void onUpdate()
    {
        this.lastTickPosX = this.posX;
        this.lastTickPosY = this.posY;
        this.lastTickPosZ = this.posZ;
        super.onUpdate();

        if (this.throwableShake > 0)
        {
            --this.throwableShake;
        }

        if (this.inGround)
        {
            if (this.worldObj.getBlock(this.field_145788_c, this.field_145786_d, this.field_145787_e) == this.field_145785_f)
            {
                ++this.ticksInGround;

                if (this.ticksInGround == 1200)
                {
                    this.setDead();
                }

                return;
            }

            this.inGround = false;
            this.motionX *= (double)(this.rand.nextFloat() * 0.2F);
            this.motionY *= (double)(this.rand.nextFloat() * 0.2F);
            this.motionZ *= (double)(this.rand.nextFloat() * 0.2F);
            this.ticksInGround = 0;
            this.ticksInAir = 0;
        }
        else
        {
            ++this.ticksInAir;
        }
        Vec3 vec3 = Vec3.createVectorHelper(this.posX, this.posY, this.posZ);
        Vec3 vec31 = Vec3.createVectorHelper(this.posX + this.motionX, this.posY + this.motionY, this.posZ + this.motionZ);
        MovingObjectPosition movingobjectposition = this.worldObj.rayTraceBlocks(vec3, vec31);
        vec3 = Vec3.createVectorHelper(this.posX, this.posY, this.posZ);
        vec31 = Vec3.createVectorHelper(this.posX + this.motionX, this.posY + this.motionY, this.posZ + this.motionZ);

        if (movingobjectposition != null)
        {
            vec31 = Vec3.createVectorHelper(movingobjectposition.hitVec.xCoord, movingobjectposition.hitVec.yCoord, movingobjectposition.hitVec.zCoord);
        }

        if (!this.worldObj.isRemote)
        {
            Entity entity = null;
            List list = this.worldObj.getEntitiesWithinAABBExcludingEntity(this, this.boundingBox.addCoord(this.motionX, this.motionY, this.motionZ).expand(1.0D, 1.0D, 1.0D));
            double d0 = 0.0D;
            EntityLivingBase entitylivingbase = this.getThrower();

            for (int j = 0; j < list.size(); ++j)
            {
                Entity entity1 = (Entity)list.get(j);

                if (entity1.canBeCollidedWith() && (entity1 != entitylivingbase || this.ticksInAir >= 5))
                {
                    float f = 0.3F;
                    AxisAlignedBB axisalignedbb = entity1.boundingBox.expand((double)f, (double)f, (double)f);
                    MovingObjectPosition movingobjectposition1 = axisalignedbb.calculateIntercept(vec3, vec31);

                    if (movingobjectposition1 != null)
                    {
                        double d1 = vec3.distanceTo(movingobjectposition1.hitVec);

                        if (d1 < d0 || d0 == 0.0D)
                        {
                            entity = entity1;
                            d0 = d1;
                        }
                    }
                }
            }

            if (entity != null)
            {
                movingobjectposition = new MovingObjectPosition(entity);
            }
        }

        if (movingobjectposition != null)
        {
            if (movingobjectposition.typeOfHit == MovingObjectPosition.MovingObjectType.BLOCK && this.worldObj.getBlock(movingobjectposition.blockX, movingobjectposition.blockY, movingobjectposition.blockZ) == Blocks.portal)
            {
                this.setInPortal();
            }
            else
            {
                this.onImpact(movingobjectposition);
            }
        }

        this.posX += this.motionX;
        this.posY += this.motionY;
        this.posZ += this.motionZ;
        float f1 = MathHelper.sqrt_double(this.motionX * this.motionX + this.motionZ * this.motionZ);
        this.rotationYaw = (float)(Math.atan2(this.motionX, this.motionZ) * 180.0D / Math.PI);

        for (this.rotationPitch = (float)(Math.atan2(this.motionY, (double)f1) * 180.0D / Math.PI); this.rotationPitch - this.prevRotationPitch < -180.0F; this.prevRotationPitch -= 360.0F)
        {
            ;
        }

        while (this.rotationPitch - this.prevRotationPitch >= 180.0F)
        {
            this.prevRotationPitch += 360.0F;
        }

        while (this.rotationYaw - this.prevRotationYaw < -180.0F)
        {
            this.prevRotationYaw -= 360.0F;
        }

        while (this.rotationYaw - this.prevRotationYaw >= 180.0F)
        {
            this.prevRotationYaw += 360.0F;
        }

        this.rotationPitch = this.prevRotationPitch + (this.rotationPitch - this.prevRotationPitch) * 0.2F;
        this.rotationYaw = this.prevRotationYaw + (this.rotationYaw - this.prevRotationYaw) * 0.2F;
        float f2 = 0.99F;
        float f3 = this.getGravityVelocity();

        if (this.isInWater())
        {
            for (int i = 0; i < 4; ++i)
            {
                float f4 = 0.25F;
                this.worldObj.spawnParticle("bubble", this.posX - this.motionX * (double)f4, this.posY - this.motionY * (double)f4, this.posZ - this.motionZ * (double)f4, this.motionX, this.motionY, this.motionZ);
            }

            f2 = 0.8F;
        }

        this.motionX *= (double)f2;
        this.motionY *= (double)f2;
        this.motionZ *= (double)f2;
        this.motionY -= (double)f3;
        this.setPosition(this.posX, this.posY, this.posZ);
        System.out.println(this.thrower);
    }

    /**
     * Gets the amount of gravity to apply to the thrown entity with each tick.
     */
    protected float getGravityVelocity()
    {
        return 0.03F;
    }

    /**
     * Called when this EntityThrowable hits a block or entity.
     */
    protected abstract void onImpact(MovingObjectPosition var1);

    /**
     * (abstract) Protected helper method to write subclass entity data to NBT.
     */
    public void writeEntityToNBT(NBTTagCompound par1NBTTagCompound)
    {
        par1NBTTagCompound.setShort("xTile", (short)this.field_145788_c);
        par1NBTTagCompound.setShort("yTile", (short)this.field_145786_d);
        par1NBTTagCompound.setShort("zTile", (short)this.field_145787_e);
        par1NBTTagCompound.setByte("inTile", (byte)Block.getIdFromBlock(this.field_145785_f));
        par1NBTTagCompound.setByte("shake", (byte)this.throwableShake);
        par1NBTTagCompound.setByte("inGround", (byte)(this.inGround ? 1 : 0));

        if ((this.throwerName == null || this.throwerName.length() == 0) && this.thrower != null && this.thrower instanceof EntityPlayer)
        {
            this.throwerName = this.thrower.getCommandSenderName();
        }

        par1NBTTagCompound.setString("ownerName", this.throwerName == null ? "" : this.throwerName);
    }

    /**
     * (abstract) Protected helper method to read subclass entity data from NBT.
     */
    public void readEntityFromNBT(NBTTagCompound par1NBTTagCompound)
    {
        this.field_145788_c = par1NBTTagCompound.getShort("xTile");
        this.field_145786_d = par1NBTTagCompound.getShort("yTile");
        this.field_145787_e = par1NBTTagCompound.getShort("zTile");
        this.field_145785_f = Block.getBlockById(par1NBTTagCompound.getByte("inTile") & 255);
        this.throwableShake = par1NBTTagCompound.getByte("shake") & 255;
        this.inGround = par1NBTTagCompound.getByte("inGround") == 1;
        this.throwerName = par1NBTTagCompound.getString("ownerName");

        if (this.throwerName != null && this.throwerName.length() == 0)
        {
            this.throwerName = null;
        }
    }

    @SideOnly(Side.CLIENT)
    public float getShadowSize()
    {
        return 0.0F;
    }

    public EntityLivingBase getThrower()
    {
        if (this.thrower == null && this.throwerName != null && this.throwerName.length() > 0)
        {
            this.thrower = this.worldObj.getPlayerEntityByName(this.throwerName);
        }

        return this.thrower;
    }
}

 

Specifically I call

System.out.println(this.thrower);

 

and my console prints out

[15:00:44] [server thread/INFO] [sTDOUT]: [com.taji34.troncraft.Taji34EntityThrowable:onUpdate:279]: EntityPlayerMP['Player914'/0, l='Test', x=-190.50, y=4.00, z=-385.50]
[15:00:44] [Client thread/INFO] [sTDOUT]: [com.taji34.troncraft.Taji34EntityThrowable:onUpdate:279]: null
[15:00:44] [Client thread/INFO] [sTDOUT]: [com.taji34.troncraft.Taji34EntityThrowable:onUpdate:279]: null
[15:00:44] [server thread/INFO] [sTDOUT]: [com.taji34.troncraft.Taji34EntityThrowable:onUpdate:279]: EntityPlayerMP['Player914'/0, l='Test', x=-190.50, y=4.00, z=-385.50]
[15:00:44] [server thread/INFO] [sTDOUT]: [com.taji34.troncraft.Taji34EntityThrowable:onUpdate:279]: EntityPlayerMP['Player914'/0, l='Test', x=-190.50, y=4.00, z=-385.50]
[15:00:44] [Client thread/INFO] [sTDOUT]: [com.taji34.troncraft.Taji34EntityThrowable:onUpdate:279]: null
[15:00:44] [server thread/INFO] [sTDOUT]: [com.taji34.troncraft.Taji34EntityThrowable:onUpdate:279]: EntityPlayerMP['Player914'/0, l='Test', x=-190.50, y=4.00, z=-385.50]
[15:00:44] [Client thread/INFO] [sTDOUT]: [com.taji34.troncraft.Taji34EntityThrowable:onUpdate:279]: null
[15:00:44] [Client thread/INFO] [sTDOUT]: [com.taji34.troncraft.Taji34EntityThrowable:onUpdate:279]: null
[15:00:44] [server thread/INFO] [sTDOUT]: [com.taji34.troncraft.Taji34EntityThrowable:onUpdate:279]: EntityPlayerMP['Player914'/0, l='Test', x=-190.50, y=4.00, z=-385.50]
[15:00:44] [server thread/INFO] [sTDOUT]: [com.taji34.troncraft.Taji34EntityThrowable:onUpdate:279]: EntityPlayerMP['Player914'/0, l='Test', x=-190.50, y=4.00, z=-385.50]
[15:00:44] [Client thread/INFO] [sTDOUT]: [com.taji34.troncraft.Taji34EntityThrowable:onUpdate:279]: null
[15:00:44] [Client thread/INFO] [sTDOUT]: [com.taji34.troncraft.Taji34EntityThrowable:onUpdate:279]: null
[15:00:44] [server thread/INFO] [sTDOUT]: [com.taji34.troncraft.Taji34EntityThrowable:onUpdate:279]: EntityPlayerMP['Player914'/0, l='Test', x=-190.50, y=4.00, z=-385.50]
[15:00:44] [Client thread/INFO] [sTDOUT]: [com.taji34.troncraft.Taji34EntityThrowable:onUpdate:279]: null
[15:00:44] [server thread/INFO] [sTDOUT]: [com.taji34.troncraft.Taji34EntityThrowable:onUpdate:279]: EntityPlayerMP['Player914'/0, l='Test', x=-190.50, y=4.00, z=-385.50]
[15:00:44] [server thread/INFO] [sTDOUT]: [com.taji34.troncraft.Taji34EntityThrowable:onUpdate:279]: EntityPlayerMP['Player914'/0, l='Test', x=-190.50, y=4.00, z=-385.50]
[15:00:44] [Client thread/INFO] [sTDOUT]: [com.taji34.troncraft.Taji34EntityThrowable:onUpdate:279]: null
[15:00:44] [server thread/INFO] [sTDOUT]: [com.taji34.troncraft.Taji34EntityThrowable:onUpdate:279]: EntityPlayerMP['Player914'/0, l='Test', x=-190.50, y=4.00, z=-385.50]
[15:00:44] [Client thread/INFO] [sTDOUT]: [com.taji34.troncraft.Taji34EntityThrowable:onUpdate:279]: null
[15:00:44] [server thread/INFO] [sTDOUT]: [com.taji34.troncraft.Taji34EntityThrowable:onUpdate:279]: EntityPlayerMP['Player914'/0, l='Test', x=-190.50, y=4.00, z=-385.50]
[15:00:44] [Client thread/INFO] [sTDOUT]: [com.taji34.troncraft.Taji34EntityThrowable:onUpdate:279]: null

 

The client and server seem out of sync and I don't know how to fix them. Any suggestions?

Posted

Why do you need the thrower on the client?

 

Well, I'm making a an object that comes back to the player, so I need the throwers current position and I figured if I just changed the entities position on the server, then the client would go out of sync with the server, is that not the case?

Posted

Just send the entityID of the player to the client (you can e.g. use the DataWatcher for this).

 

I've having some trouble with DataWatcher. The tutorial on the wiki says to put adding the values into the datawatcher in the entityInit() method, however the value I need to set gets set in the constructor, but entityInit() is called before the constructor for some reason. Also, will the client and server version of the entity have the same datawatcher? Or do I still need to pass the value to the client's datawatcher?

Posted

It's actually not called before the constructor, it is called from the super-constructor (in Entity), so basically from the first line in your Constructor (because that calls the super-constructor). You can add things to the DataWatcher in the constructor just fine.

Oh, that makes sense, I have it in the constuctor now.

That's the entire point of the DataWatcher! It will watch the values for changes and make sends the changes to the client when it changes on the server.

That's what I figured but I'm still having issues.

 

private DataWatcher dw = this.getDataWatcher();

This is the global variable I have for the data watcher.

 

    	if(!this.worldObj.isRemote){
    		dw.addObject(2, this.thrower.getEntityId()); //Thrower ID
    	}

This is what I have in the constructor.

 

System.out.println(dw.getWatchableObjectInt(2) + " Read");

And this is the code the is causing a null pointer error in the onUpdate() function of the entity. Specifically this is what prints to the console when the entity is spawned:

 

 

[09:30:49] [server thread/INFO] [sTDOUT]: [com.taji34.troncraft.Taji34EntityThrowable:onUpdate:284]: 11 Read
[09:30:49] [server thread/INFO] [sTDOUT]: [com.taji34.troncraft.Taji34EntityThrowable:onUpdate:284]: 11 Read
[09:30:49] [server thread/INFO] [sTDOUT]: [com.taji34.troncraft.Taji34EntityThrowable:onUpdate:284]: 11 Read
[09:30:49] [server thread/INFO] [sTDOUT]: [com.taji34.troncraft.Taji34EntityThrowable:onUpdate:284]: 11 Read
[09:30:49] [server thread/INFO] [sTDOUT]: [com.taji34.troncraft.Taji34EntityThrowable:onUpdate:284]: 11 Read
[09:30:49] [server thread/INFO] [sTDOUT]: [com.taji34.troncraft.Taji34EntityThrowable:onUpdate:284]: 11 Read
[09:30:49] [server thread/INFO] [sTDOUT]: [com.taji34.troncraft.Taji34EntityThrowable:onUpdate:284]: 11 Read
[09:30:49] [server thread/INFO] [sTDOUT]: [com.taji34.troncraft.Taji34EntityThrowable:onUpdate:284]: 11 Read
[09:30:50] [server thread/INFO] [sTDOUT]: [com.taji34.troncraft.Taji34EntityThrowable:onUpdate:284]: 11 Read
[09:30:50] [server thread/INFO] [sTDOUT]: [com.taji34.troncraft.Taji34EntityThrowable:onUpdate:284]: 11 Read
[09:30:50] [server thread/INFO] [sTDOUT]: [com.taji34.troncraft.Taji34EntityThrowable:onUpdate:284]: 11 Read
[09:30:50] [server thread/INFO] [sTDOUT]: [com.taji34.troncraft.Taji34EntityThrowable:onUpdate:284]: 11 Read
[09:30:50] [server thread/INFO] [sTDOUT]: [com.taji34.troncraft.Taji34EntityThrowable:onUpdate:284]: 11 Read
[09:30:50] [server thread/INFO] [sTDOUT]: [com.taji34.troncraft.Taji34EntityThrowable:onUpdate:284]: 11 Read
[09:30:50] [server thread/INFO] [sTDOUT]: [com.taji34.troncraft.Taji34EntityThrowable:onUpdate:284]: 11 Read
[09:30:50] [server thread/INFO]: Stopping server
[09:30:50] [server thread/INFO]: Saving players
[09:30:50] [server thread/INFO]: Saving worlds
[09:30:50] [server thread/INFO]: Saving chunks for level 'Copy of Copy of test'/Overworld
[09:30:51] [server thread/INFO]: Saving chunks for level 'Copy of Copy of test'/Nether
[09:30:51] [server thread/INFO]: Saving chunks for level 'Copy of Copy of test'/The End
[09:30:53] [server thread/INFO] [FML]: Unloading dimension 0
[09:30:53] [server thread/INFO] [FML]: Unloading dimension -1
[09:30:53] [server thread/INFO] [FML]: Unloading dimension 1
[09:30:53] [server thread/INFO] [FML]: Applying holder lookups
[09:30:53] [server thread/INFO] [FML]: Holder lookups applied
[09:30:54] [Client thread/FATAL]: Reported exception thrown!
net.minecraft.util.ReportedException: Ticking entity
at net.minecraft.world.World.updateEntities(World.java:2121) ~[World.class:?]
at net.minecraft.client.Minecraft.runTick(Minecraft.java:2086) ~[Minecraft.class:?]
at net.minecraft.client.Minecraft.runGameLoop(Minecraft.java:1028) ~[Minecraft.class:?]
at net.minecraft.client.Minecraft.run(Minecraft.java:951) [Minecraft.class:?]
at net.minecraft.client.main.Main.main(Main.java:164) [Main.class:?]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.7.0_51]
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) ~[?:1.7.0_51]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[?:1.7.0_51]
at java.lang.reflect.Method.invoke(Unknown Source) ~[?:1.7.0_51]
at net.minecraft.launchwrapper.Launch.launch(Launch.java:135) [launchwrapper-1.11.jar:?]
at net.minecraft.launchwrapper.Launch.main(Launch.java:28) [launchwrapper-1.11.jar:?]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.7.0_51]
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) ~[?:1.7.0_51]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[?:1.7.0_51]
at java.lang.reflect.Method.invoke(Unknown Source) ~[?:1.7.0_51]
at GradleStart.bounce(GradleStart.java:107) [start/:?]
at GradleStart.startClient(GradleStart.java:100) [start/:?]
at GradleStart.main(GradleStart.java:55) [start/:?]
Caused by: java.lang.NullPointerException
at net.minecraft.entity.DataWatcher.getWatchableObjectInt(DataWatcher.java:98) ~[DataWatcher.class:?]
at com.taji34.troncraft.Taji34EntityThrowable.onUpdate(Taji34EntityThrowable.java:284) ~[Taji34EntityThrowable.class:?]
at net.minecraft.world.World.updateEntityWithOptionalForce(World.java:2296) ~[World.class:?]
at net.minecraft.world.World.updateEntity(World.java:2256) ~[World.class:?]
at net.minecraft.world.World.updateEntities(World.java:2106) ~[World.class:?]
... 17 more

 

Posted

First of all: why are you making a new field for the DataWatcher?

Then: you need to call addObject on both sides, otherwise the client will not know what to do with the data it gets from the server.

 

I was following the tutorial on the wiki. Should I just be calling it directly when I want to add something or no? Also, I took the If statement out of the constructor to check if it was on the server and it's still crashing with the same error.

 

EDIT: I realized the constructor was only being called on the server, so the client never gets the info added. How would I go about doing this?

Posted

If the constructor is never called on the client you have a problem. That would mean your entity is not even spawned on the client. Have you registered your Entity properly?

 

After some investigation, I found that the client is calling a different constructor (The object has three) so I think it's registered properly.

 

For the DataWatcher: call addObject with a dummy value (0) on both sides. Then call setObject with the right value, on the server only.

 

After setting the dummy value in all constructors and then updating it using updateObject() in the constructor the server uses, everything works! Thanks!

 

 

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.