Jump to content

Adding Custom SpawnListEntry Object


jredfox

Recommended Posts

I don't understand where the biome spawn entries are tied into the chunk and passive spawning. My goal is to add biome spawn entity entries with nbt and jockie support. What classes and what forge events should I be using?


Edit:
I have almost solved this

Edited by jredfox
Link to comment
Share on other sites

The biome has four lists: spawnableCreatureList, spawnableMonsterList, spawnableCaveCreatureList and spawnableWaterCreatureList. 

 

I think you could add them during the post-init phase of loading where you could use the BiomeManager and find the entries you're interested in and then use the getSpawnableList() method and edit it (it is public so I think you can directly edit it).

Check out my tutorials here: http://jabelarminecraft.blogspot.com/

Link to comment
Share on other sites

9 hours ago, jabelar said:

The biome has four lists: spawnableCreatureList, spawnableMonsterList, spawnableCaveCreatureList and spawnableWaterCreatureList. 

 

I think you could add them during the post-init phase of loading where you could use the BiomeManager and find the entries you're interested in and then use the getSpawnableList() method and edit it (it is public so I think you can directly edit it).

Those don't support anything but, default, no nbt, no jockies

Edited by jredfox
Link to comment
Share on other sites

2 hours ago, diesieben07 said:

You can create a custom subclass of SpawnListEntry and return whatever entity you want in SpawnListEntry::newInstance.

And this has nothing to do with NBT.

I can just simply override it to add an entry thanks I will try it out. Didn't know I could add my own object extending it thought it had to only be that.

Question: Does that also work for passive spawning or is this another registry?

Link to comment
Share on other sites

5 hours ago, diesieben07 said:

You can create a custom subclass of SpawnListEntry and return whatever entity you want in SpawnListEntry::newInstance.

And this has nothing to do with NBT.

Nothing is spawning but, it is calling the spawnlist entry new instance I don't know what is going on. It prints that it's called but, somehow never gets spawned in no orange sheep
https://gist.github.com/jredfox/04150b6c839011c814dd01a502a382da

Biome Spawn List

[EntitySheep*(4-4):12, EntityPig*(4-4):10, EntityChicken*(4-4):10, EntityCow*(4-4):8, EntityHorse*(2-6):5, EntityDonkey*(1-3):1, EntitySheep (4-4) 12 {Color:1}]


NBT For Orange Sheep Test

[15:17:16] [Server thread/INFO] [STDOUT]: [com.EvilNotch.lib.util.minecraft.SpawnListEntryAdvanced:newInstance:57]: NBT Read



Edit: I narrowed it down to EntityWorldSpawner Doing Special Spawn Forge doesn't send in the spawn entry this is an issue, Also I just posted a form to get help on replacing a class it went down without explanation I said that format use to work I don't understand why it's not working now. Replace the class by naming it the same package and class name and just make sure your mod fires after xmod/vanilla well it's not working anymore at least in vanilla do you know what I am doing wrong? It works in the decompiled environment but, not the compiled environment 

Edited by jredfox
Link to comment
Share on other sites

7 hours ago, diesieben07 said:

Stop.

Using.

NBT.

This.

Has.

Nothing.

To.

Do.

With.

NBT.

 

You want an orange sheep? EntitySheep::setFleeceColor.

Why are you not re-using the superclass properly by calling super.newInstance? You do not need all this constructor fetching nonsense, it's already done for you (and much better at that, if you do not find the constructor you just say "OH NO THIS IS BAD OH WELL CARRY ON". This is not how programming works...

 

Please clarify what you mean. WorldEntitySpawner (I assume that's what you mean) does not have a "special spawn" method. It also uses the SpawnListEntry's newInstance method. So... what?

You don't understand NBT is what mobs use for their values mob spawnage mod is all about setting those values orange sheep is just a test you can use nbt to summon a powered creeper nbt is a powerful tool everything should have been upgraded to use this long ago if it wasn't using the interface for entity. Yes the default spawn entry and interface has their benefits also but, if you specify nbt in my entry I expect it to readFromNBT() and not to use the interface at all

 

Specified Specific Entity per spawn list entry of type like husk and only husk, zombie villager only zombie villager, want it to work as the /suommon comamnd if nbt is specified use nbt else spawn in use interface

This has everything to do with nbt say I want a baby zombie to add spawns or a husk in the middle of an ice biome I would do EntityModRegistry.register(EnittyZombie.class,NBTUtil.getNBTFromString("{isBaby:true}",20,1,8,EnumCreatureType.MONSTER); or something like that. When People add an nbt entry it's expected that that mob will always be in that way. This can also be done with the /summon command if you can do it with the /summon command you should be able to do it via spawn list entry that's my upgrade if nbt isn't null make nbt not use interface use nbt. Also NBT is a universal system I could add modded mob entries without being dependent upon them and you can get the class from the resource location so...

 

WorldEntitySpawner  Is overriding my spawn list entry.newInstance(world); by always making it use the entity interface and forge is of no help with the events the spawn list entry

Edited by jredfox
Link to comment
Share on other sites

25 minutes ago, jredfox said:

You don't understand NBT is what mobs use for their values

No its not. NBT is for serializing to disk. It's like JSON but more compressed.

Stop using NBT.

Apparently I'm a complete and utter jerk and come to this forum just like to make fun of people, be confrontational, and make your personal life miserable.  If you think this is the case, JUST REPORT ME.  Otherwise you're just going to get reported when you reply to my posts and point it out, because odds are, I was trying to be nice.

 

Exception: If you do not understand Java, I WILL NOT HELP YOU and your thread will get locked.

 

DO NOT PM ME WITH PROBLEMS. No help will be given.

Link to comment
Share on other sites

24 minutes ago, Draco18s said:

No its not. NBT is for serializing to disk. It's like JSON but more compressed.

Stop using NBT.

Take a look at the Entity.class readFromNBT()

Take a look at the /summon command you see nbt as the argument nbt isn't just for serialization it's to update values as well

/summon zombie ~ ~ ~ {isBaby:1}

/summon spider ~ ~ ~ {Passengers:[{id:skeleton}]}

I want to add baby zombie husk entry to the plains biome and only that it doesn't change after it's initial spawn NBT Is necessary arg I want to add a jockie entry nbt is necessary arg. This is what is expected. This is an example don't say well you can just create an event scan for zombies no, I want a new entry that the user configures to any nbt from that new entry.

Saying nbt is for just serialization is like saying EntityLiving.onInitialSpawn() is just for serialization 

Edited by jredfox
Link to comment
Share on other sites

Ok fine

It's also used for the summon command

Which is a string

And strings is how you serialize things

Also, the summon command uses JSON format.

 

So no, you're still wrong.

  • Sad 1

Apparently I'm a complete and utter jerk and come to this forum just like to make fun of people, be confrontational, and make your personal life miserable.  If you think this is the case, JUST REPORT ME.  Otherwise you're just going to get reported when you reply to my posts and point it out, because odds are, I was trying to be nice.

 

Exception: If you do not understand Java, I WILL NOT HELP YOU and your thread will get locked.

 

DO NOT PM ME WITH PROBLEMS. No help will be given.

Link to comment
Share on other sites

15 minutes ago, diesieben07 said:

You never mentioned that this was user configurable. If so, that is the only reason to use NBT. None of the crap you mentioned above is a reason to use NBT for this.

 

Please clarify what exactly you are talking about. There is no "overriding" taking place. Please provide exact information.

After WorldEntitySpawner > new Entity > uses my newInstance() that then starting on line Line 159  it overrides me by always using the interface
 

if (!net.minecraftforge.event.ForgeEventFactory.doSpecialSpawn(entityliving, worldServerIn, f, i3, f1))
                                                    ientitylivingdata = entityliving.onInitialSpawn(worldServerIn.getDifficultyForLocation(new BlockPos(entityliving)), ientitylivingdata);


Also used by the overworld line 302 forces the use of the onInitialSpawn() after the newInstance. 

To me this seems like a program design issue the onInitalSpawn() should be used if and only if the spawn list entry decides to use it, and the forge event special spawn could be integrated into that
 

 if (net.minecraftforge.event.ForgeEventFactory.canEntitySpawn(entityliving, worldIn, j + 0.5f, (float) blockpos.getY(), k +0.5f, false) == net.minecraftforge.fml.common.eventhandler.Event.Result.DENY) continue;
                            entityliving.setLocationAndAngles((double)((float)j + 0.5F), (double)blockpos.getY(), (double)((float)k + 0.5F), randomIn.nextFloat() * 360.0F, 0.0F);
                           

 

My Class for the custom spawn list entry

https://gist.github.com/jredfox/73052b200bc50511466f26b4736a9c7f

So in conclusion even if I did set the EnumFleece color of the sheep  to orange via fleece it would have still gotten overridden 

Edited by jredfox
Link to comment
Share on other sites

7 minutes ago, diesieben07 said:

Why do you always find such ... convoluted ways to describe your problems? If you had said "onInitialSpawn is called after my newInstance and overwrites e.g. wool color", everyone would have known immediately.

Instead you mumbled something about "interfaces" and "overriding".

 

Here is a workaround:

In your newInstance method, store whatever data you want on the entity somehow (you could use a WeakHashMap<Entity, DATA>). Then in EntityJoinWorldEvent check if you have data for the entity and if so, apply it there (and remove from the map).

I guess I was still use to using the old terms I will be more generic in the future. I guess I had a brain fart

I was planing on using entity attachments since block pos wasn't an argument but, I see now that comparing the memory location from the hashmap is a way better idea thanks

Edited by jredfox
Link to comment
Share on other sites

3 hours ago, diesieben07 said:

It's not about genericity or age of terms. It's about using the correct terms. No interfaces or any overriding was involved in the problem you were describing. Yet you kept using those two terms almost exclusively.

Ok the EntityJoinWorldEvent fires 1 tick after the spawn event is my best guess because, the sheep flashed white and then went orange. Or maybe the client thought hey this entity that was dead last tick on server exists o wait now it's this new mob because, my method that supports jockies is kind of hard to code for a base that was already existent, I could code around this but, I was lazy

I fixed this by using LivingSpawnEvent.CheckSpawn instead works perfect now, I simply always deny the event if it's on my hashmap and spawn in my entity.

Edited by jredfox
Link to comment
Share on other sites

5 hours ago, diesieben07 said:

It's not about genericity or age of terms. It's about using the correct terms. No interfaces or any overriding was involved in the problem you were describing. Yet you kept using those two terms almost exclusively.

Ok It appears that with my current code the skeleton jockies spawn repetitive during the day how do I know whether or not A mob is suppose to naturally spawn there I thought it already checked it before the check spawn event was firing????

I seen that even vanilla mobs are still getting fired during that event even after it's supposedly checked can spawn here? What am I do


Look at mobspawnage > MainJava then you can browse the classes of com.evilnotch.lib.util.registry
https://github.com/jredfox/mobspawnage-beta

Edited by jredfox
Link to comment
Share on other sites

21 minutes ago, diesieben07 said:
  • I said to use WeakHashMap for a reason, then you don't need all this removing stuff (which is broken and hacky as all hell).
  • What the fuck is this? This is not "forge's bullshit" or anything like that. Stop blaming every issue you come across on Forge being intentionally harming towards what you are wanting to achieve. If you find problems, submit fixes, Forge is open source. Don't bitch around in passive-aggressive comments. It helps nobody but your own ego (maybe) and it makes you look like a total jackass.
  • The stunts you pull in your EntityUtil class are hilarious. We already had this in your thread about translation (in which you just ignored my final message). What the fuck are you doing? Just fucking set the NBT on the entity in EntityJoinWorldEvent. Don't do any of this "oh stop spawning this entity and spawn some other entity and also do some NBT magic in between". Seriously what the heck are you doing...

 

Sorry forge isn't as dynamic as my mods are. If it were they would have nbttagcompound object as an arg for dungeon mobs via their hooks as described by mine and choonsters frustrations in 2016, nbt also for spawnlist entries similar to the way I am doing it, if no nbt use onInitialSpawn(). Also they would have TileEntity boolean isMobSpawner() since TileEntity from vanilla are nearly impossible to extend since everything is private so nobody extends TileEntityMobSpawner

 

Currently there is no set design to get passengers I could put in a new system with xml but, I want users to use the /summon command format. So this means you can still have skeleton jockies with their bows without manually typing the gear. It's my system if people want any specific mob to force nbt reading they simply add another tag doesn't matter if it does anything. So use the onInitialSpawn() if specifies no actual tags besides passengers. Good for people use to using the /summon command , good for people who don't know how to add anything with equipment and mob specific data best of both worlds.

The EnityUtil translations are "halarious" so it doesn't crash with 400 mods I had literal 30 crash reports before the null checks try and catch out of every step of the way. After changes none if anything the string returns null and it says null mob spawner for silkspawners

I solved it I was noob after the init check forge does it also checks isnotcolliding and getCanSpawnHere()

Edited by jredfox
Link to comment
Share on other sites

On 3/22/2018 at 12:15 AM, jabelar said:

The biome has four lists: spawnableCreatureList, spawnableMonsterList, spawnableCaveCreatureList and spawnableWaterCreatureList. 

 

I think you could add them during the post-init phase of loading where you could use the BiomeManager and find the entries you're interested in and then use the getSpawnableList() method and edit it (it is public so I think you can directly edit it).

my code isn't quite working for this yet and the other people keep getting mad that I use nbt as an argument. I tested this with jeb sheeps for(nbt) and a skeleton jockey for the monster and that's what's bugging out

https://github.com/jredfox/mobspawnage-beta

If this is true during the spawn check it freaks out if it's false it doesn't

AnvilChunkLoader.readWorldEntityPos(nbt, entity.world, x, y, z, true);



I have my github here it appears to work then spams:

[21:52:24] [main/WARN]: Received passengers for unknown entity

 

 

Edited by jredfox
Link to comment
Share on other sites

12 hours ago, jredfox said:

my code isn't quite working for this yet and the other people keep getting mad that I use nbt as an argument.

The "problem" (reason you're making people irritated) is that you seem to know enough about modding and Java to attempt to do fairly complex stuff but you don't seem to have proper terminology or the the debugging skills that usually come along with that level of programming. 

 

But don't worry. I think you really just need to develop your debugging skills to help yourself. The most important thing for debugging is "tracing" the execution to see if the execution follows your expectation. There are common ways to do this -- (1) you can use the breakpoints and debugging mode in Eclipse (or whatever IDE you're using) to step through your code execution, (2) you can add console or logger print statements at all the critical points in your code. I use debugger for things that happen occasionally and use print statements for things that happen continuously (like you don't want to use breakpoints for rendering problems usually). In your case you're working with spawning so breakpoints are probably great.

 

One you start stepping through the code it almost always becomes immediately clear what is going wrong. Like maybe you'll find that something isn't being called, or an if statement isn't working as expected, or the NBT isn't being tagged properly, and so on.

 

In other words, when you're doing something advanced it is expected you have the advanced skills to crawl through the problem yourself.

 

Once you have very targeted observation on what is going wrong, if for some reason you still can't figure it out, come back and post a very clear explanation of what you're observing and then people will be able to provide help.

Edited by jabelar

Check out my tutorials here: http://jabelarminecraft.blogspot.com/

Link to comment
Share on other sites

1 hour ago, jabelar said:

The "problem" (reason you're making people irritated) is that you seem to know enough about modding and Java to attempt to do fairly complex stuff but you don't seem to have proper terminology or the the debugging skills that usually come along with that level of programming. 

 

But don't worry. I think you really just need to develop your debugging skills to help yourself. The most important thing for debugging is "tracing" the execution to see if the execution follows your expectation. There are common ways to do this -- (1) you can use the breakpoints and debugging mode in Eclipse (or whatever IDE you're using) to step through your code execution, (2) you can add console or logger print statements at all the critical points in your code. I use debugger for things that happen occasionally and use print statements for things that happen continuously (like you don't want to use breakpoints for rendering problems usually). In your case you're working with spawning so breakpoints are probably great.

 

One you start stepping through the code it almost always becomes immediately clear what is going wrong. Like maybe you'll find that something isn't being called, or an if statement isn't working as expected, or the NBT isn't being tagged properly, and so on.

 

In other words, when you're doing something advanced it is expected you have the advanced skills to crawl through the problem yourself.

 

Once you have very targeted observation on what is going wrong, if for some reason you still can't figure it out, come back and post a very clear explanation of what you're observing and then people will be able to provide help.

I always debug it before posting for help. Even after I post I still debug and usually fix a bug or two that's not related to it

My issue is this: the console keeps spamming received passengers for unknown entity. This is my code to spawn in the entity the rest of the event and custom spawn entry is found on github starting at mobspawnage main java. Since I last posted here I fixed adding and removing entities from the hashmap by memory location only as it's suppose to be only that instance for comparing, before I didn't know the entity overrode the .equals method
https://github.com/jredfox/mobspawnage-beta

Entity e = AnvilChunkLoader.readWorldEntityPos(nbt, entity.world, x, y, z, true);


I debuged by using vanilla's chunk loader for entities from pos same as the /summon command currently works but, if the boolean attempt spawn is true I get that error messege spaming in the console and if I move it spams faster, if it's false nothing happens but, no entities spawn

Edited by jredfox
Link to comment
Share on other sites

Okay but did you trace the execution for that error message. If you search the Java source you'd see that the "Received passengers for unknown entity" message is displayed in the NetHandlerPlayClient#handleSetPassengers() method whenever the getEntityByID()  for the packet returns null.

 

So you need to trace that. What is in that packet, what is the entity ID in the packet, and is it a valid ID according to the existing entities.

Check out my tutorials here: http://jabelarminecraft.blogspot.com/

Link to comment
Share on other sites

3 hours ago, jabelar said:

Okay but did you trace the execution for that error message. If you search the Java source you'd see that the "Received passengers for unknown entity" message is displayed in the NetHandlerPlayClient#handleSetPassengers() method whenever the getEntityByID()  for the packet returns null.

 

So you need to trace that. What is in that packet, what is the entity ID in the packet, and is it a valid ID according to the existing entities.

yeah I don't know what is going on

Link to comment
Share on other sites

2 hours ago, jredfox said:

yeah I don't know what is going on

Yeah so you need to trace it. Check if it is null. If it is null work backwards and look at the getEntityByID() method call and check what ID is being passed? If the ID is not valid then work backwards and find out what is inside the packet passed in. If that doesn't have the right thing work backwards and look at where the packet is constructed.

 

Just keep going backwards and it will become clear where the problem is starting.

Check out my tutorials here: http://jabelarminecraft.blogspot.com/

Link to comment
Share on other sites

2 hours ago, jabelar said:

Yeah so you need to trace it. Check if it is null. If it is null work backwards and look at the getEntityByID() method call and check what ID is being passed? If the ID is not valid then work backwards and find out what is inside the packet passed in. If that doesn't have the right thing work backwards and look at where the packet is constructed.

 

Just keep going backwards and it will become clear where the problem is starting.

the debugger doesn't trace to there after my event it just stops. I really don't know what the issue is here. Can't really trace this I noticed you posted on this specific error on multiple occasions what is happening in order for that error to occur is the client not expecting any passengers if so why does this not happen every time and with the /summon command and my custom /spawnMob command?


I did the java thing to replace the class with same package name and class name to replace the worldentityspawner since it does work in decompiled mode not compiled don't know why and it had the same resaults the only difference is A: the mob is toofar away or something or B: client isn't expecting any jockies from anything is this even a mod issue or is it forge's/vanilla's job to patch it? How can I get around this?

 

Could it be that the chunk isn't loaded yet it's spawning or something stated above or something else?

 

Edited by jredfox
Link to comment
Share on other sites

2 hours ago, jabelar said:

Yeah so you need to trace it. Check if it is null. If it is null work backwards and look at the getEntityByID() method call and check what ID is being passed? If the ID is not valid then work backwards and find out what is inside the packet passed in. If that doesn't have the right thing work backwards and look at where the packet is constructed.

 

Just keep going backwards and it will become clear where the problem is starting.

I have reproduced this in vanilla with the /summon command I spawned two jockies and a regular one went out of render distence then came back console spammed I think this might now be my issue should forge fix this for 1.12? Did this exists before the passenger system when using riding tags?
https://bugs.mojang.com/browse/MC-90683

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



  • Recently Browsing

    • No registered users viewing this page.
  • Posts

    • They were already updated, and just to double check I even did a cleanup and fresh update from that same page. I'm quite sure drivers are not the problem here. 
    • i tried downloading the drivers but it says no AMD graphics hardware has been detected    
    • Update your AMD/ATI drivers - get the drivers from their website - do not update via system  
    • As the title says i keep on crashing on forge 1.20.1 even without any mods downloaded, i have the latest drivers (nvidia) and vanilla minecraft works perfectly fine for me logs: https://pastebin.com/5UR01yG9
    • Hello everyone, I'm making this post to seek help for my modded block, It's a special block called FrozenBlock supposed to take the place of an old block, then after a set amount of ticks, it's supposed to revert its Block State, Entity, data... to the old block like this :  The problem I have is that the system breaks when handling multi blocks (I tried some fix but none of them worked) :  The bug I have identified is that the function "setOldBlockFields" in the item's "setFrozenBlock" function gets called once for the 1st block of multiblock getting frozen (as it should), but gets called a second time BEFORE creating the first FrozenBlock with the data of the 1st block, hence giving the same data to the two FrozenBlock :   Old Block Fields set BlockState : Block{minecraft:black_bed}[facing=east,occupied=false,part=head] BlockEntity : net.minecraft.world.level.block.entity.BedBlockEntity@73681674 BlockEntityData : id:"minecraft:bed",x:3,y:-60,z:-6} Old Block Fields set BlockState : Block{minecraft:black_bed}[facing=east,occupied=false,part=foot] BlockEntity : net.minecraft.world.level.block.entity.BedBlockEntity@6d1aa3da BlockEntityData : {id:"minecraft:bed",x:2,y:-60,z:-6} Frozen Block Entity set BlockState : Block{minecraft:black_bed}[facing=east,occupied=false,part=foot] BlockPos{x=3, y=-60, z=-6} BlockEntity : net.minecraft.world.level.block.entity.BedBlockEntity@6d1aa3da BlockEntityData : {id:"minecraft:bed",x:2,y:-60,z:-6} Frozen Block Entity set BlockState : Block{minecraft:black_bed}[facing=east,occupied=false,part=foot] BlockPos{x=2, y=-60, z=-6} BlockEntity : net.minecraft.world.level.block.entity.BedBlockEntity@6d1aa3da BlockEntityData : {id:"minecraft:bed",x:2,y:-60,z:-6} here is the code inside my custom "freeze" item :    @Override     public @NotNull InteractionResult useOn(@NotNull UseOnContext pContext) {         if (!pContext.getLevel().isClientSide() && pContext.getHand() == InteractionHand.MAIN_HAND) {             BlockPos blockPos = pContext.getClickedPos();             BlockPos secondBlockPos = getMultiblockPos(blockPos, pContext.getLevel().getBlockState(blockPos));             if (secondBlockPos != null) {                 createFrozenBlock(pContext, secondBlockPos);             }             createFrozenBlock(pContext, blockPos);             return InteractionResult.SUCCESS;         }         return super.useOn(pContext);     }     public static void createFrozenBlock(UseOnContext pContext, BlockPos blockPos) {         BlockState oldState = pContext.getLevel().getBlockState(blockPos);         BlockEntity oldBlockEntity = oldState.hasBlockEntity() ? pContext.getLevel().getBlockEntity(blockPos) : null;         CompoundTag oldBlockEntityData = oldState.hasBlockEntity() ? oldBlockEntity.serializeNBT() : null;         if (oldBlockEntity != null) {             pContext.getLevel().removeBlockEntity(blockPos);         }         BlockState FrozenBlock = setFrozenBlock(oldState, oldBlockEntity, oldBlockEntityData);         pContext.getLevel().setBlockAndUpdate(blockPos, FrozenBlock);     }     public static BlockState setFrozenBlock(BlockState blockState, @Nullable BlockEntity blockEntity, @Nullable CompoundTag blockEntityData) {         BlockState FrozenBlock = BlockRegister.FROZEN_BLOCK.get().defaultBlockState();         ((FrozenBlock) FrozenBlock.getBlock()).setOldBlockFields(blockState, blockEntity, blockEntityData);         return FrozenBlock;     }  
  • Topics

×
×
  • Create New...

Important Information

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