Posted September 27, 201510 yr I am trying to spawn a custom mob I made using spawnEntityInWorld. To do so I am using the LivingSpawnEvent.CheckSpawn event to detect when a certain mob is spawned and then replace it with my own. My mob is spawned but doesn't do anything and then disappears after a few seconds. The mob works fine when spawned with an egg. Just to make sure that my mob is not the problem I have tried spawning vanilla mobs instead with the same result. Here is the code I am using. @SubscribeEvent public void onMobSpawnEvent( LivingSpawnEvent.CheckSpawn event ) { if( EntityList.getEntityString( event.entity ) == "Spider" ) { if( !event.world.isRemote ) { EntityBat bat = new EntityBat( event.world ); bat.posX = event.entity.posX; bat.posY = event.entity.posY; bat.posZ = event.entity.posZ; event.world.spawnEntityInWorld( bat ); event.setResult( Result.DENY ); } } } Using this a bat is spawned in place of a spider. But the bat does not move and despawns after a few seconds.
September 27, 201510 yr Try too only check the worldObj.isRemote for the spawning. Leave the other code outside of the iff check.
September 27, 201510 yr Try too only check the worldObj.isRemote for the spawning. Leave the other code outside of the iff check. No, that is completely wrong. If isRemote is true, that means it is a CLIENT world, and you DO NOT want to spawn an entity on the client - server only. Besides, the code that calls this event is only in WorldServer, so following your advice would result in nothing happening at all. @OP That is very strange - I haven't used that particular event before, nor do I see anything in its placement that would suggest it shouldn't work perfectly fine, but I've had success doing something similar using the EntityJoinWorldEvent. As an aside - rather than comparing strings, why not use an instanceof check, or Class#isAssignableFrom if you want to ensure ONLY that class (as in, not any sub-classes, such as if a mod extends EntitySpider): if (event.entity instanceof EntitySpider) { // it's either a spider or any sub-class thereof; e.g. a cave spider will also pass this check } if (event.entity.getClass().isAssignableFrom(EntitySpider.class)) { // only the regular vanilla spider will pass this check, cave spiders will not } http://i.imgur.com/NdrFdld.png[/img]
September 27, 201510 yr Author Thanks, I found the problem. Apparently if I don't use setLocationAndAngles to assign rotation angles as well as position, the server must think that the entity is invalid and deletes it. Also LivingSpawnEvent.CheckSpawn was not the right event to use as this is called constantly as the server searches for a valid spawn position. It worked but I ended up with a million bats on the screen. EntityJoinWorldEvent is fired only after a valid spawn point has been found and an entity is actually about to spawn there. After fixing my original problem and adding in suggestions above, here is my working code to spawn a custom mob in place of a vanilla mob: @SubscribeEvent public void onMobSpawnEvent( EntityJoinWorldEvent event ) { if( event.entity instanceof EntitySpider && Math.random() < 0.3 ) { event.setCanceled( true ); if( !event.world.isRemote ) { EntityBigSpider bigSpider = new EntityBigSpider( event.world ); bigSpider.setLocationAndAngles(event.entity.posX, event.entity.posY, event.entity.posZ, 0.0F, 0.0F); event.world.spawnEntityInWorld( bigSpider ); } } }
September 27, 201510 yr if (event.entity.getClass().isAssignableFrom(EntitySpider.class)) { // only the regular vanilla spider will pass this check, cave spiders will not } This is not true. isAssignableFrom does the same check as instanceof. If you want to only check for vanilla spider use .getClass() == EntitySpider.class. Diesieben, I'm shocked you don't know the difference, as they are definitely NOT the same. Put this in EntityInteractEvent and right click on some entities: System.out.println("Entity class: " + event.target.getClass()); System.out.println("Instanceof EntityLiving : " + (event.target instanceof EntityLiving ? "true" : "false")); System.out.println("Assignable from EntityLiving : " + event.target.getClass().isAssignableFrom(EntityLiving.class)); System.out.println("EntityLiving assignable from : " + event.target.getClass() + ": " + EntityLiving.class.isAssignableFrom(event.target.getClass())); Here is the output you will see: Entity class: class zeldaswordskills.entity.npc.EntityGoron Instanceof EntityLiving : true Assignable from EntityLiving : false // This one right here is the big difference EntityLiving assignable from : class zeldaswordskills.entity.npc.EntityGoron: true #isAssignableFrom can appear to act like instanceof depending on which class you compare to which. If a more specific class is the caller and a less specific class is the method argument, you will get false, as you cannot create the more specific class (such as EntityCaveSpider) from a less specific one (such as EntitySpider). In other words: // okay to assign an EntitySpider from an EntityCaveSpider EntitySpider spider = new EntityCaveSpider(world); // NOT okay to assign EntityCaveSpider from EntitySpider EntityCaveSpider spider = new EntitySpider(world); http://i.imgur.com/NdrFdld.png[/img]
September 27, 201510 yr Uhm, you are just using it wrong, my friend. The arguments are inverted: Sorry, but I disagree - there is nothing in the specification that requires it to be used with the calling class and argument in a specific order, especially given that #isAssignableFrom is usually used when there is not an object instance available or the object's type is not otherwise known until run-time. Here is part of the description of #isAssignableFrom: Specifically, this method tests whether the type represented by the specified Class parameter can be converted to the type represented by this Class object via [b]an identity conversion[/b] OR via a [url=http://docs.oracle.com/javase/specs/jls/se7/html/jls-5.html#jls-5.1.5][b]widening reference conversion[/b][/url] It is the widening reference conversion which gives it the subtle behavior depending on the order of arguments: A widening reference conversion exists from any reference type S to any reference type T, [b]provided S is a subtype (§4.10) of T[/b]. Therefore, if S is a subtype of T, and you then call T.class.isAssignableFrom(S.class) instead, you get false as expected; while instanceof would also give you false in such a case, it requires that you have an instance of T to test against S, which sometimes is impossible, and that's where #isAssignableFrom shines. Anyway, I don't mean to start an argument here, I was just surprised by your statements, and your suggestion of testing class identity is a more suitable solution anyway EDIT: Ah, I see what you mean now - you are correct that my usage of it may be confusing to people, as #isAssignableFrom does not usually imply that the classes are equal (though it does in this case because all of EntitySpider's parent classes are abstract), and therefore is inappropriate to use in this case. Okay, after all that, I agree with you. Damn it http://i.imgur.com/NdrFdld.png[/img]
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.