Jump to content

TileEntity Not Tracking Spawned Entity On World Reload.


Recommended Posts

Posted

Hey there modders, I come from a background of coding in quite a few different coding/scripting languages I am not entirely familiar with java but my understanding of general code and oop concepts  has helped me enough(that and dissecting the built in mojang code), unfortunately i have ran into a snag with a TileEntity behavior.

 

The idea is that the tile entity spawns a mob and it will need to track this mob, so far I have gotten the TileEntity to spawn the mob and remember a value to track it with all will work fine unless, I reload the world, then it'll stick unable to find the entity, I first tried saving the entity's UUID assuming this may be a unique persistent value for the mob, later finding that i can store custom data on the enslaved entity's NBT table i switched to this thinking it was more flexible, still it would not play ball.

 

I did splice some code from the mob base spawner logic but that was to save time when making it detect a player and spawn the mob, i will be adding more conditions once the basics are working(persisting tracking of the `enslaved` entity)

 

Here is my implementation so far(Sorry it is a mess, it is prototype code and i usually tidy up after it all works):

public class TileEntityRiftAlterEntity extends TileEntity {

/** The delay to spawn. */
    public int spawnDelay = 20;
    
    /** */
    private int FixedTime = 20;

/** The distance from which a player activates the spawner. */
    private int activatingRangeFromPlayer = 16;
    
    /** The entity that is 'enslaved' to this alter */
    private Entity Slave=null;
    
    /** Name to track enslaved entity by */
    private String SlaveName="";

    /** Slave object(PigZombie is temp) */
    private String SlaveID = "PigZombie";
    
    /** The range coefficient for spawning entities around. */
    private int spawnRange = 4;
    
/**
     * Returns true if there's a player close enough to this mob spawner to activate it.
     */
    public boolean canRun()
    {
        return this.getWorldObj().getClosestPlayer((double)this.xCoord + 0.5D, (double)this.yCoord + 0.5D, (double)this.zCoord + 0.5D, (double)this.activatingRangeFromPlayer) != null;
    }
    
    /**
     * Allows the entity to update its state. Overridden in most subclasses, e.g. the mob spawner uses this to count
     * ticks and creates a new spawn inside its implementation.
     */
    public void updateEntity()
    {
    	if (this.canRun() == true)
    	{
    		if (this.spawnDelay == -1)
            {
                this.spawnDelay=this.FixedTime;
            }

            if (this.spawnDelay > 0)
            {
                --this.spawnDelay;
                return;
            }
            
            if (this.getWorldObj().isRemote)
            {
                double d1 = (double)((float)this.xCoord + 0.5f);
                double d2 = (double)((float)this.yCoord + 0.6f);
                double d0 = (double)((float)this.zCoord + 0.5f);
                //this.getWorldObj().spawnParticle("smoke", d1, d2, d0, 0.0D, 0.0D, 0.0D);
                this.getWorldObj().spawnParticle("flame", d1, d2, d0, 0.0D, 0.0D, 0.0D);
            }
            else
            {
            	//TODO : Slave detection is not perfect(persistence is not yet handled)
            	if (this.Slave == null && this.SlaveName.equals(""))
            	{
            		this.Slave = EntityList.createEntityByName(this.SlaveID, this.getWorldObj());
            		
            		double d0 = (double)this.xCoord + (this.getWorldObj().rand.nextDouble() - this.getWorldObj().rand.nextDouble()) * (double)this.spawnRange;
                    double d3 = (double)(this.yCoord + this.getWorldObj().rand.nextInt(3) - 1);
                    double d4 = (double)this.zCoord + (this.getWorldObj().rand.nextDouble() - this.getWorldObj().rand.nextDouble()) * (double)this.spawnRange;
                    
                    EntityLiving entityliving = this.Slave instanceof EntityLiving ? (EntityLiving)this.Slave : null;
                    this.Slave.setLocationAndAngles(d0, d3, d4, this.getWorldObj().rand.nextFloat() * 360.0F, 0.0F);
                    
                    if (this.Slave.worldObj != null)
                    {
                    	this.Slave.worldObj.spawnEntityInWorld(this.Slave);
                    	
                    	this.SlaveName = "123";
                		this.Slave.getEntityData().setString("Enslaved", this.SlaveName);
                    }
            	}
            	
            	if (this.Slave == null && !this.SlaveName.equals(""))
            	{
            		EntityPlayerMP player=(EntityPlayerMP)this.worldObj.playerEntities.get(0);
            		
            		player.addChatMessage("Searching for slave");
            		for (int i=0; i < Minecraft.getMinecraft().theWorld.loadedEntityList.size(); i++)
            		{
            			Entity ent=(Entity)Minecraft.getMinecraft().theWorld.loadedEntityList.get(i);
            			//Compares the refrence not the string
            			//if (ent.getUniqueID().toString() == this.SlaveName)
            			
            			//String comparision.
            			String EnslavementTag=ent.getEntityData().getString("Enslaved");
            			
            			//if (EnslavementTag.equals(this.SlaveName))
            			if (EnslavementTag.length() > 0)
            			{
            				player.addChatMessage("Found slave");
            				this.Slave=ent;
            			}
            		}
            	}
            	
            	if (this.Slave != null)
            	{
            		if (!this.Slave.isEntityAlive())
            		{
            			this.Slave=null;
            			this.SlaveName="";
            		}
            	}
            }
    	}
    }
    
    public void readFromNBT(NBTTagCompound par1NBTTagCompound)
    {
    	super.readFromNBT(par1NBTTagCompound);
    	
    	this.SlaveName=par1NBTTagCompound.getString("SlaveName");
    }
    
    public void writeToNBT(NBTTagCompound par1NBTTagCompound)
    {
    	super.writeToNBT(par1NBTTagCompound);
    	
    	par1NBTTagCompound.setString("SlaveName", this.SlaveName);
    }
}

 

Again I am sorry this code looks like a warzone.

Posted

Not got a direct solution to this, but after both your tile entity and entity have been loaded, what is the contents of loadedEntityList? Can you locate the entity your looking for manually and see what is persisted that you can use?

Posted

Not got a direct solution to this, but after both your tile entity and entity have been loaded, what is the contents of loadedEntityList? Can you locate the entity your looking for manually and see what is persisted that you can use?

 

Thanks that put me on the right track, I decided to use a tag I know would persist(the custom name tag).

made the following tweaks in the code like this :

            	if (this.Slave == null && this.SlaveName.equals(""))
            	{
            		this.Slave = EntityList.createEntityByName(this.SlaveID, this.getWorldObj());
            		
            		double d0 = (double)this.xCoord + (this.getWorldObj().rand.nextDouble() - this.getWorldObj().rand.nextDouble()) * (double)this.spawnRange;
                    double d3 = (double)(this.yCoord + this.getWorldObj().rand.nextInt(3) - 1);
                    double d4 = (double)this.zCoord + (this.getWorldObj().rand.nextDouble() - this.getWorldObj().rand.nextDouble()) * (double)this.spawnRange;
                    
                    EntityLiving entityliving = this.Slave instanceof EntityLiving ? (EntityLiving)this.Slave : null;
                    this.Slave.setLocationAndAngles(d0, d3, d4, this.getWorldObj().rand.nextFloat() * 360.0F, 0.0F);
                    
                    if (this.Slave.worldObj != null)
                    {
                    	this.Slave.worldObj.spawnEntityInWorld(this.Slave);
                    	
                    	this.SlaveName = "123";
                		//this.Slave.getEntityData().setString("Enslaved", this.SlaveName);
                    	if (this.Slave instanceof EntityLiving)
                    	{
                    		EntityLiving LivingSlave=(EntityLiving)this.Slave;
                    		LivingSlave.setCustomNameTag(this.SlaveName);
                    	}
                    }
            	}
            	
            	if (this.Slave == null && !this.SlaveName.equals(""))
            	{
            		EntityPlayerMP player=(EntityPlayerMP)this.worldObj.playerEntities.get(0);
            		
            		player.addChatMessage("Searching for slave");
            		for (int i=0; i < Minecraft.getMinecraft().theWorld.loadedEntityList.size(); i++)
            		{
            			Entity ent=(Entity)Minecraft.getMinecraft().theWorld.loadedEntityList.get(i);
            			//Compares the refrence not the string
            			//if (ent.getUniqueID().toString() == this.SlaveName)
            			
            			/*
            			//String comparision.
            			String EnslavementTag=ent.getEntityData().getString("Enslaved");
            			
            			//if (EnslavementTag.equals(this.SlaveName))
            			if (EnslavementTag.length() > 0)
            			{
            				player.addChatMessage("Found slave");
            				this.Slave=ent;
            			}
            			*/
            			if (ent instanceof EntityLiving)
            			{
            				EntityLiving LivingEnt=(EntityLiving)ent;
            				if (LivingEnt.getCustomNameTag().equals(this.SlaveName))
            				{
            					player.addChatMessage("Found slave");
            					this.Slave=ent;
            				}
            			}
            		}
            	}

 

Now that works and tells me that with a custom mob I would have to add in a special NBT tag but I am now wondering if I want to use this with a vanilla mob, how do i store data on it in places other then the name tag as that shows up when the player looks over it and would look pretty ugly to the player if i store a tracking ID there or such(using the entity's spawned X,Y,Z as a unique reference and/or simular).

Posted

Id possibly have another look at the uniqueid thing again, and look closely in a debugger to see why it doesn't work as expected. I only just looked very quiickly in a 1.7.2 source, but the Entity class writeToNBT and readFromNBT do appear to be saving and loading the UUID entityUniqueID (which appears to be returned by getPersistentID AND getUniqueID, you will need to check the sources for whichever version of MC to see if this has changed).

 

 

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.