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
  On 2/13/2014 at 11:48 PM, Sync Views said:

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



  • Recently Browsing

    • No registered users viewing this page.
  • Posts

    • just rewatched the tutorial and my code is exactly the same as kaupenjoe's.  the item is added into the game but like i said to start it doesnt have a texture or a proper name for whatever reason.
    • yes the name is en_us.json and it is in resources -> assests -> testmod -> lang folders.  i have checked my code and am pretty confident that the code itself is correct.  i even tried loading the project in eclipse and it has the same problems, I think i will just rewatch the whole tutorial and will give an update on the situation.
    • same error, I also tried removing Valkyrian skies as well because I noticed it coming up a lot in the debug log errors
    • Hey man,    i have only been modding Minecraft for a few days but maybe I can help you. First of all make sure to follow every step of Kaupenjoe's tutorial, I found it to been very helpful and complete. The game uses the raw translation key for the item (in your case "item.testmod.alexandrite") if it can't find the correct lang file. Make sure it's name is "en_us.json" and it is saved under "ressources" -> "assets" -> "testmod".
    • whenever I try to get this item to render into the game it appears with the not texture purple and black squares and calls itself by the lang translation file path instead of the name i gave it.   { "item.testmod.alexandrite": "Alexandrite" } this is the lang json file package net.Hurst.testmod.item; import net.Hurst.testmod.TestMod; import net.minecraft.world.item.Item; import net.minecraftforge.eventbus.api.IEventBus; import net.minecraftforge.registries.DeferredRegister; import net.minecraftforge.registries.ForgeRegistries; import net.minecraftforge.registries.RegistryObject; public class ModItems { public static final DeferredRegister<Item> ITEMS = DeferredRegister.create(ForgeRegistries.ITEMS, TestMod.MOD_ID); public static final RegistryObject<Item> ALEXANDRITE = ITEMS.register("alexandrite", () -> new Item(new Item.Properties())); public static void register(IEventBus eventBus){ ITEMS.register(eventBus); } } this is my ModItems.java file package net.Hurst.testmod; import com.mojang.logging.LogUtils; import net.Hurst.testmod.item.ModItems; import net.minecraft.world.item.CreativeModeTabs; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.event.BuildCreativeModeTabContentsEvent; import net.minecraftforge.event.server.ServerStartingEvent; import net.minecraftforge.eventbus.api.IEventBus; import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.fml.ModLoadingContext; import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.config.ModConfig; import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent; import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent; import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext; import org.slf4j.Logger; // The value here should match an entry in the META-INF/mods.toml file @Mod(TestMod.MOD_ID) public class TestMod { public static final String MOD_ID = "testmod"; private static final Logger LOGGER = LogUtils.getLogger(); public TestMod() { IEventBus modEventBus = FMLJavaModLoadingContext.get().getModEventBus(); modEventBus.addListener(this::commonSetup); ModItems.register(modEventBus); MinecraftForge.EVENT_BUS.register(this); modEventBus.addListener(this::addCreative); ModLoadingContext.get().registerConfig(ModConfig.Type.COMMON, Config.SPEC); } private void commonSetup(final FMLCommonSetupEvent event) { } // Add the example block item to the building blocks tab private void addCreative(BuildCreativeModeTabContentsEvent event) { if(event.getTabKey() == CreativeModeTabs.INGREDIENTS){ event.accept(ModItems.ALEXANDRITE); } } // You can use SubscribeEvent and let the Event Bus discover methods to call @SubscribeEvent public void onServerStarting(ServerStartingEvent event) { } // You can use EventBusSubscriber to automatically register all static methods in the class annotated with @SubscribeEvent @Mod.EventBusSubscriber(modid = MOD_ID, bus = Mod.EventBusSubscriber.Bus.MOD, value = Dist.CLIENT) public static class ClientModEvents { @SubscribeEvent public static void onClientSetup(FMLClientSetupEvent event) { } } } this is my TestMod.java file { "parent": "minecraft:item/generated", "textures": { "layer0": "testmod:item/generated" } } this is my model file for the item. I am using intellij 2025.1.2 with fdk 1.21 and java 21 I would appreciate the help.
  • Topics

  • Who's Online (See full list)

×
×
  • Create New...

Important Information

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