Jump to content

[solved] Double Entity Spawning Problem ...


Torojima

Recommended Posts

I have a very strange behaviour when spawning a new Entity.

 

Situation:

I have registered a few new entities in the init method of my mod base class like this:

 

 

        // Chicobo
        int eggColChicobo = (170 << 16) + (70 <<  + 250;
        int eggDotsColChicobo = (250 << 16) + (250 <<  + 0;
        int globUniEntIdChicobo = EntityRegistry.findGlobalUniqueEntityId();
        String entNameChicobo = "Chicobo";
        LanguageRegistry.instance().addStringLocalization("entity.Chicobo.name", "en_US", "Chicobo");
        EntityRegistry.registerGlobalEntityID(EntityChicobo.class, entNameChicobo, globUniEntIdChicobo, eggColChicobo, eggDotsColChicobo);

 

 

also I am registering the entity in my client proxy.

 

package chococraft.client;

import cpw.mods.fml.client.registry.RenderingRegistry;
import net.minecraftforge.client.MinecraftForgeClient;
import chococraft.common.CommonProxyChocoCraft;
import chococraft.common.Constants;
import chococraft.common.ModelChicobo;
import chococraft.common.RenderChicobo;
import chococraft.common.entities.EntityChicobo;
import chococraft.common.entities.colours.*;

public class ClientProxyChocoCraft extends CommonProxyChocoCraft
{
    @Override
    public void registerRenderThings()
    {
    	MinecraftForgeClient.preloadTexture(Constants.CHOCOBO_ITEM_TEXTURES);
    }
    
    public static void registerRenderInformation()
    {
        RenderingRegistry.registerEntityRenderingHandler(EntityChicobo.class, new RenderChicobo(new ModelChicobo(), 0.5F));
    }
}

 

 

now I'm trying to spawn an entity in a world with this code (method written for debugging and put into a click listener of one of my items)

 

 

public void spawnRandomChocoboAtCoords(World world, double xPos, double yPos, double zPos)
{
	Random rand = new Random();
	int colourIdx = rand.nextInt((chocoboColor.values()).length);
	EntityChicobo ec = new EntityChicobo(world, chocoboColor.values()[colourIdx]);
	ec.timeUntilAdult = rand.nextInt(2000) + 27000;
	ec.setGrowingAge(ec.timeUntilAdult);
	ec.growUp = false;
               ec.setLocationAndAngles(xPos, yPos, zPos, 0.0F, 0.0F);
               world.spawnEntityInWorld(ec);
       DebugFileWriter.instance().writeLine("trying to spawn a " + ec.color.toString() + " chicobo at x:" + xPos + ", y:" + yPos + ", z:" + zPos);
}

 

 

the entity class has two constructors

 

    public EntityChicobo(World world)
    {
    	super(world);
    	this.color = chocoboColor.YELLOW;
        this.texture = this.getEntityTexture();
        this.setEntityHealth(this.getColorMaxHealth());
        name = "";
        this.setTamed(false);
        this.setFollowing(false);
        hidename = false;
        setSize(0.5F, 0.5F);
        growUp = false;
        canGrowUp = true;
        timeUntilAdult = rand.nextInt(2000) + 27000;
        setGrowingAge(timeUntilAdult);    	
    }
    
    public EntityChicobo(World world, chocoboColor color)
    {
        super(world);
    	this.color = color;
        if (color == chocoboColor.PURPLE)
        {
            isImmuneToFire = true;
        }
        this.texture = this.getEntityTexture();
        this.setEntityHealth(this.getColorMaxHealth());
        name = "";
        this.setTamed(false);
        this.setFollowing(false);
        hidename = false;
        setSize(0.5F, 0.5F);
        growUp = false;
        canGrowUp = true;
        timeUntilAdult = rand.nextInt(2000) + 27000;
        setGrowingAge(timeUntilAdult);
    }

 

 

Problem:

but instead of just one friendly mob in the world, there are spawning two. One behaving normally, but with the default colour, so I believe the extra entity it's created by the standard EntityChicobo(World world) constructor. The spawn entity with the "correct" colour on the other hand is only standing still without any behaviour and not clickable, thus it looks like the entity itself is not registered correctly?

 

Does anybody have any idea why I have two entities when I call the line  world.spawnEntityInWorld(ec); only once. Also the debug output right in the next line is printed only once ... right now I have no Idea what to do and how I could fix this bug (or even what I have done wrong in the first place ...)

 

I would appreciate every good idea and/or hint you guys could give me.

 

Edit: changed the debug spawning method, like it is atm, had copied a test I've put in before ...

 

Edit2: and there is another strange effect. I have a GUI for my mobs to control following behaviour and set names etc ... When I open the GUI for an entity I will get two GUI's one after each other for the same mob, but with two different data sets ...

 

 

running minecraft on Mac OS X - Sierra --- creating code since 1986 ... --- मेरा दिल भारतवासी है!

width=289 height=100http://www.arno-saxena.de/pictures/chococraft/banner_signature.png[/img]

Link to comment
Share on other sites

I have changed my spawning method like this:

 

 

public void spawnRandomChocoboAtCoords(World world, double xPos, double yPos, double zPos)
{

/////// new part
	if(world.isRemote)
	{
		return;
	}
////// end new part

	Random rand = new Random();
	int colourIdx = rand.nextInt((chocoboColor.values()).length);
        //EntityChocobo ec = (EntityChocobo) FactoryEntityChocobo.createChocobo(world, chocoboColor.values()[colourIdx], "testingChocobo", "", false, false, false);

        ////////////
	DebugFileWriter.instance().writeLine("creating a new chicobo in DebugEntitySpawner");
	EntityChicobo ec = new EntityChicobo(world, chocoboColor.values()[colourIdx]);
	DebugFileWriter.instance().writeLine("new chicobo created in DebugEntitySpawner");		
	//ec.setColor(chocoboColor.values()[colourIdx]);
	ec.timeUntilAdult = rand.nextInt(2000) + 27000;
	ec.setGrowingAge(ec.timeUntilAdult);
	ec.growUp = false;
	//////////////
        ec.setLocationAndAngles(xPos, yPos, zPos, 0.0F, 0.0F);
        //ec.setGrowingAge(6000);
        DebugFileWriter.instance().writeLine("now spawning the just created Chicobo");
        world.spawnEntityInWorld(ec);
	DebugFileWriter.instance().writeLine("trying to spawn a " + ec.color.toString() + " chicobo at x:" + xPos + ", y:" + yPos + ", z:" + zPos);
}

 

 

so the hole shebang should only be called if the client is calling the method, correct? But still there are two entities. I have forced an error in the EntityChicobo(World world) constructor (null pointer exception by trying to invoke a method on a not initialised field) to get a call stack and I got this:

 

 

 

2012-09-25 22:22:50 [iNFO] [sTDERR] java.lang.reflect.InvocationTargetException

2012-09-25 22:22:50 [iNFO] [sTDERR] at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)

2012-09-25 22:22:50 [iNFO] [sTDERR] at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)

2012-09-25 22:22:50 [iNFO] [sTDERR] at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)

2012-09-25 22:22:50 [iNFO] [sTDERR] at java.lang.reflect.Constructor.newInstance(Constructor.java:513)

2012-09-25 22:22:50 [iNFO] [sTDERR] at jr.a(SourceFile:125)

2012-09-25 22:22:50 [iNFO] [sTDERR] at ro.a(ItemMonsterPlacer.java:84)

2012-09-25 22:22:50 [iNFO] [sTDERR] at ro.a(ItemMonsterPlacer.java:63)

2012-09-25 22:22:50 [iNFO] [sTDERR] at rj.a(SourceFile:88)

2012-09-25 22:22:50 [iNFO] [sTDERR] at gv.a(ItemInWorldManager.java:368)

2012-09-25 22:22:50 [iNFO] [sTDERR] at gz.a(NetServerHandler.java:507)

2012-09-25 22:22:50 [iNFO] [sTDERR] at eg.a(SourceFile:58)

2012-09-25 22:22:50 [iNFO] [sTDERR] at ba.b(MemoryConnection.java:78)

2012-09-25 22:22:50 [iNFO] [sTDERR] at gz.d(NetServerHandler.java:76)

2012-09-25 22:22:50 [iNFO] [sTDERR] at ha.b(NetworkListenThread.java:55)

2012-09-25 22:22:50 [iNFO] [sTDERR] at axy.b(IntegratedServerListenThread.java:111)

2012-09-25 22:22:50 [iNFO] [sTDERR] at net.minecraft.server.MinecraftServer.q(MinecraftServer.java:643)

2012-09-25 22:22:50 [iNFO] [sTDERR] at net.minecraft.server.MinecraftServer.p(MinecraftServer.java:560)

2012-09-25 22:22:50 [iNFO] [sTDERR] at axv.p(IntegratedServer.java:107)

2012-09-25 22:22:50 [iNFO] [sTDERR] at net.minecraft.server.MinecraftServer.run(MinecraftServer.java:466)

2012-09-25 22:22:50 [iNFO] [sTDERR] at ep.run(SourceFile:539)

2012-09-25 22:22:50 [iNFO] [sTDERR] Caused by: java.lang.NullPointerException

2012-09-25 22:22:50 [iNFO] [sTDERR] at chococraft.common.entities.EntityChicobo.<init>(EntityChicobo.java:43)

2012-09-25 22:22:50 [iNFO] [sTDERR] ... 20 more

 

 

 

so, it is indeed one entity on the server and one on the client ...

 

since I'm not calling the spawn if it's the remote side ... I must be doing something essentially wrong in registering the entity, since the call of the entity constructor is done from a point I have no direct access to ...

 

... so what could be me error??? or better, is there a detailed explanation somewhere on how to register an entity with forge?

 

Edit: btw, now that I have omited the spawn if on the server side I only can see one mob (the one just standing there is gone) but still the effect with the GUI opening twice and the debug output from the constructor printed twice is still happening ...

 

Edit2: and one more thing ... when using the minecraft own spawnEggs to spawn an entity, I still have the double GUI, double constructor debug output effect and there I can not influence the calls to the constructors ... Thus all the more I believe it's something I do wrong in registering ... should I maybe only use the entity from the server? how can I omit the constructor call from the client?

 

Edit3: now after some experimenting with FMLCommonHandler.instance().getEffectiveSide(), I came to the conclusion, the unwanted twin is created by the client side... funny enough... How so? As above mentioned I have two constructors, one with additional parameters needed to create one of my entities, which are set to default values when calling the simple just world parameter constructor without the additional parameters. Now the first call of a constructor is the one intended by me in my spawn method and calling the constructor with additional parameters, creating a entity as requested. The second call is done by the client side and calling the simple constructor.

 

So the question is what method is creating the shadow entity on the client side and why? Obviously, since the same is happening when an entity is spawned with the minecraft own spawnEggs, I can not prevent this by preventing calling the spawn method if called from the server side, since I have no access to the spawnEgg methods ...

 

I'm at a complete loss here and desperately in need of some help ...

 

Edit4 (and last for today, I'm going to sleep :) ): I've prevented the spawning first at the server side, then at the client side. But both results have been incomplete. If I prevent the server side spawn, the mob is not moving at all or reacting to player interaction. If I prevent the client side spawn, I can not see the mob (but hear it and see the debug outputs, so it is present ...). Thus I presume both are needed, but have to be synchronised somehow ... which I do not know how and where ...

running minecraft on Mac OS X - Sierra --- creating code since 1986 ... --- मेरा दिल भारतवासी है!

width=289 height=100http://www.arno-saxena.de/pictures/chococraft/banner_signature.png[/img]

Link to comment
Share on other sites

another day, another idea :)

I've just been reading in the SMP style guides. And there it is mentioned that "Any Inventory/Container is stored both client and serverside" ...  my mobs have an inventory.

 

 

I've given my mounts saddle-bags to store stuff and for that I've given the entity a field to store the inventory object...

 

 

could it be that's why the entity is persistently been created on both sides, even by the spawn eggs?

 

Edit: just after writing this and hitting the post button it came to my mind this can not be the cause of all the troubles ... I have two different entity types, one has an inventory, the other has not ... and the inventory is only added in an class branch where they have already separated ... so I'm back to space 0 in finding what's causing all this ...

running minecraft on Mac OS X - Sierra --- creating code since 1986 ... --- मेरा दिल भारतवासी है!

width=289 height=100http://www.arno-saxena.de/pictures/chococraft/banner_signature.png[/img]

Link to comment
Share on other sites

I have read somewhere in the mcforge wiki that world.isRemote in the last mc version will always return true and that now the correct way to do things would be

 

Side.CLIENT == FMLCommonHandler.instance().getEffectiveSide()

 

or

 

Side.SERVER == FMLCommonHandler.instance().getEffectiveSide()

 

...

 

but back to my problem (which hopefully shortly will be solved :D). Should I do everything for example in the onLivingUpdate(...) method of my mob Entity only in the case of Side.SERVER == FMLCommonHandler.instance().getEffectiveSide()? Then the server will notify the client about the outcome?

 

I also 'found' the IEntityAdditionalSpawnData interface, with this I'm able to initialise the entities created by the simple constructor with the data otherwise only initialised correctly by the second constructor.

running minecraft on Mac OS X - Sierra --- creating code since 1986 ... --- मेरा दिल भारतवासी है!

width=289 height=100http://www.arno-saxena.de/pictures/chococraft/banner_signature.png[/img]

Link to comment
Share on other sites

now when I do the spawning

world.spawnEntityInWorld(entity);

of a new entity on the server side

 

check for:

Side.SERVER == FMLCommonHandler.instance().getEffectiveSide()

 

I have an working entity I can interact with (use item on it, entity itself is running around etc...) also it will still be present when I leave the game and reload.

 

but, when I do the spawning on the client side

Side.CLIENT == FMLCommonHandler.instance().getEffectiveSide()

 

the entity is not moving at all, does not have a collision check, nor can I use any items on it. Also as soon as I leave the game and reload it, the entity is gone...

 

Since I've been advised (here and from numerous tutorials) to do a new entity spawning only on the client side, I must do something very wrong ... any ideas where to start searching?

running minecraft on Mac OS X - Sierra --- creating code since 1986 ... --- मेरा दिल भारतवासी है!

width=289 height=100http://www.arno-saxena.de/pictures/chococraft/banner_signature.png[/img]

Link to comment
Share on other sites

Since I've been advised (here and from numerous tutorials) to do a new entity spawning only on the client side, I must do something very wrong ... any ideas where to start searching?

 

Who told you that?  :o

 

Spawning of entities HAVE TO be done on the server side, and only there!

Don't ask for support per PM! They'll get ignored! | If a post helped you, click the "Thank You" button at the top right corner of said post! |

mah twitter

This thread makes me sad because people just post copy-paste-ready code when it's obvious that the OP has little to no programming experience. This is not how learning works.

Link to comment
Share on other sites

that would explain a hell of a lot :D and would also give me a bit of sanity back !!!

 

anyway, for example here:

 

http://www.minecraftforge.net/wiki/SMP_Coding_Guidelines

 

at the paragraph "Entities (that aren't EntityItem)"

 

Whenever your mod spawns an Entity, make sure the World is not a serverside World, or you will have a dummy dupe Entity.

 

either, that quote is a typo, or I do understand it very wrong ...

running minecraft on Mac OS X - Sierra --- creating code since 1986 ... --- मेरा दिल भारतवासी है!

width=289 height=100http://www.arno-saxena.de/pictures/chococraft/banner_signature.png[/img]

Link to comment
Share on other sites

that would explain a hell of a lot :D and would also give me a bit of sanity back !!!

 

anyway, for example here:

 

http://www.minecraftforge.net/wiki/SMP_Coding_Guidelines

 

at the paragraph "Entities (that aren't EntityItem)"

 

Whenever your mod spawns an Entity, make sure the World is not a serverside World, or you will have a dummy dupe Entity.

 

either, that quote is a typo, or I do understand it very wrong ...

 

Yeah, this is unluckily explained. With serverside world is meant that it is a remote world, so worldObj.isRemote is true. This applies also for the new 1.3 update, but instead the client has now a server running in the background, so you have to spawn your entities into the serverside world.

Don't ask for support per PM! They'll get ignored! | If a post helped you, click the "Thank You" button at the top right corner of said post! |

mah twitter

This thread makes me sad because people just post copy-paste-ready code when it's obvious that the OP has little to no programming experience. This is not how learning works.

Link to comment
Share on other sites

ok, that's a relieve :D

 

I think I have my spawning now fixed.

Spawning on the server only, piping extra spawning data from writeSpawnData on the server to readSpawnData on the client. Entity looks good with all the correct data and behaviours after spawning and after reloading the world.

 

Now I have to find a way to:

 

a) force a reload of the texture, since some actions will cause a change in skins (saddle, packbags, taming ...). Right now the texture does not change even if the responsible flags have changed ... (my getTexture() checking for the respective flags and return the correct path)

 

b) get some data and flags from the server to the client at runtime... (most prominent health, if I hit my entity, the health will change on the server, but not on the client ... I thought fields from the mc native classes, like health from EntityLiving, would be changed automatically... )

 

for a) I haven't got a solution now, any suggestions?

 

for b) I do some experimenting with a PacketHandler etc ... any other suggestions?

 

Edit: after reading a bit, I belive a) isn't a problem at all on it own, but due to the texture responsible flags changed in the server entities, but not in the client ones ... thus the client doesn't change the texture, because it still has the unchanged responsible flags ... thus I'm only trying to solve b) how to get data from the server to the client ...

running minecraft on Mac OS X - Sierra --- creating code since 1986 ... --- मेरा दिल भारतवासी है!

width=289 height=100http://www.arno-saxena.de/pictures/chococraft/banner_signature.png[/img]

Link to comment
Share on other sites

I believe you also need to register your entity with

 

 

 

 

EntityRegistry.registerModEntity(EntityChicobo.class, entNameChicobo, globUniEntIdChicobo, eggColChicobo, eggDotsColChicobo);

 

 

 

 

Using only the one method you currently use instead of using both may be the cause of the original error you describe.

 

Link to comment
Share on other sites

yes, right now I'm doing both, below is a little method I'm using for registering my entities. Right now it looks like the entity registration works very well :) (got some other problems, but I hope to fix them too in the near future :D)

 

 

private void registerChocoboEntityClass(Class <? extends Entity> entityClass, String entityName, int eggColor, int eggDotsColor, String visibleName)
{
   int entityID = EntityRegistry.findGlobalUniqueEntityId();
   LanguageRegistry.instance().addStringLocalization("entity." + entityName  + ".name", "en_US", visibleName);
   EntityRegistry.registerGlobalEntityID(entityClass, entityName, entityID, eggColor, eggDotsColor);
   EntityRegistry.registerModEntity(entityClass, entityName, entityID, instance, 128, 1, true);
}

 

running minecraft on Mac OS X - Sierra --- creating code since 1986 ... --- मेरा दिल भारतवासी है!

width=289 height=100http://www.arno-saxena.de/pictures/chococraft/banner_signature.png[/img]

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.