Jump to content

[Solved?] [1.12] Make Illusioners spawn in mansions


IceMetalPunk

Recommended Posts

So, here's a tricky thing I'm finding: how do I make 1.12's Illusioner (EntityIllusionIllager class) spawn in woodland mansions? And I mean spawn naturally, not just generate with the structure like the other illagers do.

I can easily add EntityIllusionIllager to the roofed_forest's spawnable monsters list, but then they'd spawn in all roofed forests everywhere. I want them only to spawn in mansions.


Taking a look at the "location" advancement criterion's handling of feature detection, I see I can figure out if a location is in a given feature, say a mansion, with this code:

 

world.getChunkProvider().isInsideStructure(world, "Mansion", blockpos)

 

But since the Illusioner is a vanilla entity, how would I inject this into its spawning conditions?

 

Or would I need to create a new mob that extends the EntityIllusionIllager class, but overrides its getCanSpawnHere() method to consider the above condition? I hope I won't have to do that as I don't have much experience registering and using custom mobs, especially after 1.7.10... is there  a better/easier way to achieve this?

Edited by IceMetalPunk

Whatever Minecraft needs, it is most likely not yet another tool tier.

Link to comment
Share on other sites

12 hours ago, diesieben07 said:

You can use WorldEvent.PotentialSpawns to alter the list of potential spawns for a location. Look at ChunkGeneratorOverworld::getPossibleCreatures to see how e.g. witch spawns are handled.

Thank you for pointing me in the right direction! However, I can't seem to get it working... I have added this method to my registered event handler class (the extremely high weight and pack spawn values are for testing):

 

public void alterSpawns(WorldEvent.PotentialSpawns ev) {
		World world = ev.getWorld();
		BlockPos pos = ev.getPos();
		IChunkProvider prov = world.getChunkProvider();
		System.out.println("DEBUG: Getting potential spawns!");
		if (ev.getType() == EnumCreatureType.MONSTER && prov instanceof ChunkProviderServer) {
			ChunkProviderServer serverProv = (ChunkProviderServer) prov;
			System.out.println("DEBUG: Is Monster & Server Provider");
			if (serverProv.isInsideStructure(world, "Mansion", pos)) {
				System.out.println("DEBUG: Mansion at " + pos);
				ev.getList().clear();
				ev.getList().add(new SpawnListEntry(EntityIllusionIllager.class, 500, 5, 5));
			}
		}
		// Reference: ChunkGeneratorOverworld#getPossibleCreatures
	}

 

No illusioners spawn. According to the debug output, it *is* calling the method with a server-side chunk provider and an EnumCreatureType of MONSTER, but it is *not* ever finding a mansion at the current spot, even though I'm literally standing in a mansion where things are spawning.

I get no errors, it just never finds the mansion.

Am I missing something?

Whatever Minecraft needs, it is most likely not yet another tool tier.

Link to comment
Share on other sites

Use breakpoints and dive into the isInsideStructure method and see what's going on (you'll have to go a few levels deep).

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

Well, I guess that narrowed it down, but I'm still confused... So the problem is that MapGenStructure#getStructureAt(pos) is returning null, even if the position is inside a woodland mansion. The iteration while loop runs twice and then ultimately finishes without returning a value, leading to the default return value of null, which ends up signifying "no, there is no structure at this position."

But that doesn't make much sense to me, since when a structure is generated (and specifically mansions, I checked!), it's added to the structureMap.

So clearly I'm still missing something... but what?

Whatever Minecraft needs, it is most likely not yet another tool tier.

Link to comment
Share on other sites

14 minutes ago, diesieben07 said:

WoodlandMansion.Start overrides isSizeableStructure to return some isValid flag. See if that is the cause of the problem.

If you are still having trouble, please post a working git repo of your mod, so I can test this locally.

Hm. Seems like the only time that's false, as set in WoodlandMansion#create(), is if any of the 4 corners of the starting position of the mansion are below Y=60 (sea level, I guess?). But if that's the case, it also doesn't actually generate the mansion at all, whereas I'm testing it with a naturally generated mansion already (found with the /locate command)...

 

You can find the repo here: https://github.com/IceMetalPunk/TotemEssentials The event handler in question is events.TEEvents, with the FIXME-flagged alterSpawns() method being the relevant listener. I commented out the debugging output messages while continuing development on other features; you can of course uncomment them if you want to test.

Whatever Minecraft needs, it is most likely not yet another tool tier.

Link to comment
Share on other sites

The root of the repository should be the root directory of your mod, i.e. where build.gradle and the src directory are.

 

See my mod and its .gitignore file for an example of the repository structure to use and the files to include.

Please don't PM me to ask for help. Asking your question in a public thread preserves it for people who are having the same problem in the future.

Link to comment
Share on other sites

10 minutes ago, diesieben07 said:

Your repository is broken, it does not even contain a build.gradle.

Ah, no, I just didn't include the project settings in the repo, only the code in the src subdirectory. What's the best way to "move the repo up" one level without breaking git's links?

Edited by IceMetalPunk

Whatever Minecraft needs, it is most likely not yet another tool tier.

Link to comment
Share on other sites

Okay, so I guess manually moving the .git folder up didn't create a ton of reference errors like I'd expected. That's good to know! The repo has been updated to include the build files now.

 

I also cleaned up the repo a small bit by creating a feature branch for the Illusioner spawning code; so you'll want to look at the illusioner-spawn branch for the relevant code here :)

Edited by IceMetalPunk

Whatever Minecraft needs, it is most likely not yet another tool tier.

Link to comment
Share on other sites

11 minutes ago, diesieben07 said:

The issue is that your SpawnListEntry is not constant. Minecraft assumes SpawnListEntry objects to be re-used, don't create a new one every time.

I changed it to a constant value (final, too, just to be sure), but still no Illusioners spawn. Plenty of zombies, skeletons, and spiders spawning in the mansion, but not one Illusioner. I've pushed the changes to the feature branch, but that doesn't seem to have fixed anything....

Whatever Minecraft needs, it is most likely not yet another tool tier.

Link to comment
Share on other sites

Huh. Well, that's weird. They weren't spawning for me, so I ended up deleting the world and creating a new one, as a sort of "reset before the test". And this time, they did spawn! I'm not sure what weirdness was happening in my other world, but it seems like it works now, so... yay!

Thank you for all your help! :)

Whatever Minecraft needs, it is most likely not yet another tool tier.

Link to comment
Share on other sites

Wait, no... I now know why the reset helped. It seems the Illusioners are spawning with the generation of the world, but not afterwards. If I /kill everything, then go up to world height and drop back down (to trigger a fresh round of spawning), no Illusioners spawn anymore...

Whatever Minecraft needs, it is most likely not yet another tool tier.

Link to comment
Share on other sites

16 minutes ago, diesieben07 said:

It seems that once you reload the world (or something) isValid in the WoodlandMansion.Start class is set to false. Why, I do not know.

I didn't reload the world this time, though... The Illusioners spawned fine, then I killed everything, flew to Y=260 or so, and dropped back down. I didn't even leave the chunk (though I suppose I did leave the sub-chunk?).

Does isValid get set to false after the initial generation of the mansion or something? But that's even more confusing, because the LocationPredicate of the PositionTrigger (used for the "location" advancement) uses isInsideStructure to detect features, and that advancement trigger works just fine with mansions...

Whatever Minecraft needs, it is most likely not yet another tool tier.

Link to comment
Share on other sites

Well... I think I found the problem... though I haven't yet figured out how to work around it...

 

It seems like when a chunk is loaded that already has a structure in it, the Start instance of it is created via Class.newInstance(), using the default zero-parameter constructor. In the mansion's case, that particular constructor has an empty body, meaning it never calls the create() method in which isValid is actually set. And in Java, an uninitialized boolean is always false by default.

 

So now I have to figure out how to detect if a position is inside a mansion, regardless of whether it's marked as "valid" or not...

Whatever Minecraft needs, it is most likely not yet another tool tier.

Link to comment
Share on other sites

12 hours ago, diesieben07 said:

You can probably just replicate the vanilla code, but ignore the isValid flag.

Well... that's what I've done, then. And it works! Except it required a lot of reflection, since many of the generators are in private or protected fields, and the initialization method is also protected... It feels quite hacky. But it works!

Can you take a look at the code I've added and tell me if you can think of a less... reflection-heavy way of accomplishing this? https://github.com/IceMetalPunk/TotemEssentials/blob/c1bfa555a3c1c5e470ce4860add62dfaea5942fe/src/main/java/com/icemetalpunk/totemessentials/events/TEEvents.java#L157

Whatever Minecraft needs, it is most likely not yet another tool tier.

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.