Jump to content

[SOLVED][1.15.2] Updating the spawn list in the Nether Fortress...


Cryotron

Recommended Posts

Hello,

 

I'm trying to achieve a couple of different things in my mod that's going to be updated once 1.16 fully releases (and hopefully forge too) and I have a couple of stumbling blocks that I don't seem to understand about certain aspects about modding. I'm quite new at it and this is the very first mod that I've ever developed. It's been a month since I've developed a mod with a friend and for weeks and I kept stumbling about spawns... in general actually. For biomes, it seems pretty straightforward: using registryWorldSpawn() method to spawn the modded mobs into the world in that biome. 

 

I have 3 new mobs in this mod: the Skeletal Magi. The Skeletal Magi has three different versions much like the regular skeletons: Skeleton Mage, Stray Mage and Wither Mage. The difference between a Skeleton and a Skeleton Mage is that a Skeleton Mage shoots a magical projectile that causes aliments to the target entities they hit rather than shooting with an arrow (So a Skeleton Mage shoots a fireball much like Blaze but not as lethal as them). They also do not burn in sunlight as they are exposed to magic much like the Witches and they are pretty.. uhh... "Uncommonly common". The Skeletal Magi as classes of entities are complete (fully textured, successfully rendered, slight changes of AI here and there) but I have trouble with other interactions.

 

I wish to achieve the following goals and know more from posting here:

  • As the title suggests, one of the biggest stumbling block I have is spawning in a specific generated structure. While this is not really a problem for a customized generated structure, I have trouble with modifying the vanilla generated structure. I wish to update the Nether Fortress' list of mobs that spawn there. In FortressStructure class in the vanilla minecraft, there is a List of Biome.spawnListEntry that contains a list of mobs that spawn in that generated structure: Blazes, Zombie Pigmen (Or maybe Piglins in the future), Wither Skeletons, Skeletons and Magma Cubes. I wish to update this list by adding Skeleton Mages and Wither Mages as well. In this class: the field variable is private static final which means I can't even access it or even change the list variable (The objects are mutable but I don't see a reason why I would do so and this variable should be untouched anyway) and there is a List<Biome.SpawnListEntry> method called getSpawnList() that is public and is able to be overwritten only to do this in a deferred registry and my mod has trouble loading the said feature: only to update the spawn list! A shed of light that updates the SpawnList as well as usage of deferred registries of such feature would be much appreciated for this one because this has been bothering me for weeks. Do I need to use deferred registries to update the list of mobs? Have I yet to understand how they work? They seem to work for sounds, items and entities... :L
  • I also wish to update some things about other entities that is other than the Skeletal Magi: if a Skeleton gets hit by lightning, it becomes a Skeleton Mage. Clearly, this is not something that can be done through the mage classes themselves and this is just updating the normal skeleton entity from vanilla. While this is just one of the examples, I wish to know how to update certain attributes of normal minecraft entities from this mod.  I want to achieve something like: updating Vexes and Ghasts into undead attributes; if a fox gets hit by a lightning, it becomes a kumiho demon; etc. How do I achieve this? Do I just make a new class that extends the original class from the vanilla minecraft.

 

So that's pretty much I would like to know. There are more that I would like to know and would humbly like to ask for assistance such as enchantments, ambient boss musics, etc. In general, I would like to know how to replace or update entities spawned by vanilla minecraft such as the villagers and TangoTek's Tektopia mod. Any replies and enlightenment would be most interested.

 

TL;DR Look at the bolded words, but if you would like to know details, please read the whole post.

Edited by Cryotron
  • Like 1
Link to comment
Share on other sites

17 minutes ago, Cryotron said:

the field variable is private static final 

Have you tried using Reflection?

VANILLA MINECRAFT CLASSES ARE THE BEST RESOURCES WHEN MODDING

I will be posting 1.15.2 modding tutorials on this channel. If you want to be notified of it do the normal YouTube stuff like subscribing, ect.

Forge and vanilla BlockState generator.

Link to comment
Share on other sites

45 minutes ago, diesieben07 said:

You can use WorldEvent.PotentialSpawns to update the list of potential spawns for a location.

To change the spawns inside a fortress, replicate the logic you find in NetherChunkGenerator#getPossibleCreatures to check if the location being asked is in a fortress and if so modify the original list in the event to your liking.

Does that mean I have to find a chunk generating class to modify the spawnlist?

 

I'm also trying to figure out how reflections can apply to this. :P

Link to comment
Share on other sites

2 hours ago, diesieben07 said:

Not sure what you mean. You just need to subscribe to the event.

 

You don't need reflection.

Alright, so I am subscribing the event of spawning entities through a class and now what i'm stuck on is that what initializes the WorldEvent.PotentialSpawns?. I've replicated the logic found in NetherChunkGenerator#getPossibleCreatures.

 

I'm sorry for such a seemingly basic question.  It's one last step that I seem to stuck on.

 

EDIT: I got rid of Reflections.

 

 

Edited by Cryotron
Link to comment
Share on other sites

4 minutes ago, diesieben07 said:

Its fired by Forge when Minecraft determines what to spawn at a given location. Not really sure what your issue is.

Please show your code.

package com.cryotron.skyspaceproject.entities;

import com.cryotron.skyspaceproject.init.EntityInit;

import net.minecraft.block.Blocks;
import net.minecraft.entity.EntityClassification;
import net.minecraft.entity.EntitySpawnPlacementRegistry;
import net.minecraft.entity.monster.MonsterEntity;
import net.minecraft.entity.EntityType;
import net.minecraft.world.World;
import net.minecraft.world.biome.Biome;
import net.minecraft.world.biome.Biome.SpawnListEntry;
import net.minecraft.world.gen.Heightmap;
import net.minecraft.world.gen.feature.Feature;
import net.minecraft.world.biome.Biomes;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.event.world.WorldEvent;
import net.minecraftforge.registries.ForgeRegistries;

public class SSEntitySpawn {
	
	public static EntityType<?> skeleton_mage = EntityInit.SKELETON_MAGE.get();
	public static EntityType<?> stray_mage = EntityInit.STRAY_MAGE.get();
	public static EntityType<?> wither_mage = EntityInit.WITHER_MAGE.get();
	public static WorldEvent world_event = null; // <<<This line>>>
	
	public static void registerEntityWorldSpawns()
	{
		for (Biome biome : ForgeRegistries.BIOMES) {
            if (biome != Biomes.THE_END | biome != Biomes.NETHER) { 
            	if (biome != Biomes.SNOWY_TUNDRA | biome != Biomes.SNOWY_MOUNTAINS | biome != Biomes.ICE_SPIKES | biome != Biomes.FROZEN_RIVER | biome != Biomes.FROZEN_OCEAN | biome != Biomes.DEEP_FROZEN_OCEAN) { 
            		registerEntityWorldSpawn(skeleton_mage, 2, 1, 2, 
            				Biomes.BADLANDS,Biomes.BADLANDS_PLATEAU,
            				Biomes.BAMBOO_JUNGLE, Biomes.BAMBOO_JUNGLE_HILLS,
            				Biomes.BEACH,
            				Biomes.BIRCH_FOREST,Biomes.BIRCH_FOREST_HILLS,
            				Biomes.COLD_OCEAN,
            				Biomes.DARK_FOREST,	Biomes.DARK_FOREST_HILLS,
            				Biomes.DEEP_COLD_OCEAN, Biomes.DEEP_LUKEWARM_OCEAN, Biomes.DEEP_OCEAN, Biomes.DEEP_WARM_OCEAN,
            				Biomes.DESERT, Biomes.DESERT_HILLS, Biomes.DESERT_LAKES,
            				Biomes.ERODED_BADLANDS,
            				Biomes.FLOWER_FOREST,
            				Biomes.FOREST,
            				Biomes.GIANT_SPRUCE_TAIGA, Biomes.GIANT_SPRUCE_TAIGA_HILLS, Biomes.GIANT_TREE_TAIGA, Biomes.GIANT_TREE_TAIGA_HILLS,
            				Biomes.GRAVELLY_MOUNTAINS,
            				Biomes.JUNGLE, Biomes.JUNGLE_EDGE, Biomes.JUNGLE_HILLS,
            				Biomes.LUKEWARM_OCEAN,
            				Biomes.MODIFIED_BADLANDS_PLATEAU, Biomes.MODIFIED_GRAVELLY_MOUNTAINS, Biomes.MODIFIED_JUNGLE, Biomes.MODIFIED_JUNGLE_EDGE, Biomes.MODIFIED_WOODED_BADLANDS_PLATEAU,
            				Biomes.MOUNTAIN_EDGE, Biomes.MOUNTAINS,
            				Biomes.MUSHROOM_FIELD_SHORE, Biomes.MUSHROOM_FIELDS,
            				Biomes.OCEAN,
            				Biomes.PLAINS,
            				Biomes.SAVANNA, Biomes.SAVANNA_PLATEAU, Biomes.SHATTERED_SAVANNA, Biomes.SHATTERED_SAVANNA_PLATEAU,
            				Biomes.SNOWY_BEACH, Biomes.SNOWY_TAIGA, Biomes.SNOWY_TAIGA_HILLS, Biomes.SNOWY_TAIGA_MOUNTAINS, 
            				Biomes.STONE_SHORE, Biomes.SUNFLOWER_PLAINS,
            				Biomes.SWAMP, Biomes.SWAMP_HILLS,
            				Biomes.TAIGA, Biomes.TAIGA_HILLS, Biomes.TAIGA_MOUNTAINS,
            				Biomes.TALL_BIRCH_FOREST, Biomes.TALL_BIRCH_HILLS,
            				Biomes.WARM_OCEAN,
            				Biomes.WOODED_BADLANDS_PLATEAU, Biomes.WOODED_HILLS, Biomes.WOODED_MOUNTAINS
            		);
            	}
            	if (biome == Biomes.SNOWY_TUNDRA | biome == Biomes.SNOWY_MOUNTAINS | biome == Biomes.ICE_SPIKES | biome == Biomes.FROZEN_RIVER | biome == Biomes.FROZEN_OCEAN | biome == Biomes.DEEP_FROZEN_OCEAN) { 
            		registerEntityWorldSpawn(stray_mage, 2, 1, 2, Biomes.SNOWY_TUNDRA, Biomes.SNOWY_MOUNTAINS, Biomes.ICE_SPIKES, Biomes.FROZEN_RIVER, Biomes.FROZEN_OCEAN, Biomes.DEEP_FROZEN_OCEAN);
            	}
            }
            if (biome != Biomes.THE_END | biome == Biomes.NETHER) {
            	registerNetherSpawn(world_event);
            }
		}
	}

	public static void registerNetherSpawn(WorldEvent.PotentialSpawns event) {
		if(event.getType() == EntityClassification.MONSTER) {
	       if (Feature.NETHER_BRIDGE.isPositionInsideStructure(event.getWorld(), event.getPos())) {
	          registerEntityWorldSpawn(skeleton_mage,2,5,5);
	          registerEntityWorldSpawn(wither_mage,8,5,5);
	       }

	       if (Feature.NETHER_BRIDGE.isPositionInStructure(event.getWorld(), event.getPos()) && event.getWorld().getBlockState(event.getPos().down()).getBlock() == Blocks.NETHER_BRICKS) {
           	  registerEntityWorldSpawn(skeleton_mage,2,5,5);
           	  registerEntityWorldSpawn(wither_mage,8,5,5);
	       }
		}
	}	
	
	public static void registerEntityWorldSpawn(EntityType<?> entity, int weight, int minGroupIn, int maxGroupIn, Biome... biomes)
	{
		for(Biome biome : biomes)
		{
			if(biome != null)
			{
				biome.getSpawns(entity.getClassification()).add(new SpawnListEntry(entity, weight, minGroupIn, maxGroupIn));
			}
		}
	}

	static {
		EntitySpawnPlacementRegistry.register(EntityInit.SKELETON_MAGE.get(), EntitySpawnPlacementRegistry.PlacementType.ON_GROUND, Heightmap.Type.MOTION_BLOCKING_NO_LEAVES, MonsterEntity::canMonsterSpawnInLight);
		EntitySpawnPlacementRegistry.register(EntityInit.STRAY_MAGE.get(), EntitySpawnPlacementRegistry.PlacementType.ON_GROUND, Heightmap.Type.MOTION_BLOCKING_NO_LEAVES, MonsterEntity::canMonsterSpawnInLight);
		EntitySpawnPlacementRegistry.register(EntityInit.WITHER_MAGE.get(), EntitySpawnPlacementRegistry.PlacementType.ON_GROUND, Heightmap.Type.MOTION_BLOCKING_NO_LEAVES, MonsterEntity::canMonsterSpawnInLight);	
	}
}

All three entities are successfully spawned elsewhere aside of the Nether Fortress, so I'm pretty sure this class works with the Main class of the mod. Also pardon with the mess. xD

Edited by Cryotron
Link to comment
Share on other sites

7 hours ago, diesieben07 said:

This completely defeats the point of using RegistryObject. Do not do this.

 

You need to learn about events.

Ah, thank you for pointing that point for future reference.

 

Also I suppose I can learn more things about event handlers. I'll look into them as well.

Edited by Cryotron
Link to comment
Share on other sites

Finally nailed it.

 

It wasn't as intuitive but I finally did it.

 

Here is the code for those who want to add mobs in the Fortress.

 

package com.cryotron.skyspaceproject.entities;

import com.cryotron.skyspaceproject.init.EntityInit;

import net.minecraft.block.Blocks;
import net.minecraft.entity.EntityClassification;
import net.minecraft.world.biome.Biome;
import net.minecraft.world.gen.feature.Feature;
import net.minecraftforge.event.world.WorldEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;


public class SSNetherEntitySpawn {
	
	Biome.SpawnListEntry skeleMageSpawn = new Biome.SpawnListEntry(EntityInit.SKELETON_MAGE.get(), 2, 5, 5);
	Biome.SpawnListEntry witherMageSpawn = new Biome.SpawnListEntry(EntityInit.WITHER_MAGE.get(), 8, 5, 5);
	
	@SubscribeEvent
	public void registerNetherWorldSpawn(WorldEvent.PotentialSpawns event) {
		if(event.getType() == EntityClassification.MONSTER) {
	       if (Feature.NETHER_BRIDGE.isPositionInsideStructure(event.getWorld(), event.getPos())) {
	    	   event.getList().add(skeleMageSpawn);
	    	   event.getList().add(witherMageSpawn);
	       }

	       if (Feature.NETHER_BRIDGE.isPositionInStructure(event.getWorld(), event.getPos()) && event.getWorld().getBlockState(event.getPos().down()).getBlock() == Blocks.NETHER_BRICKS) {
	    	   event.getList().add(skeleMageSpawn);
	    	   event.getList().add(witherMageSpawn);
	       }
		}	
	}
}

 

I made this new class that is exclusively used to add the mages that spawns in the Nether Fortress. You need to initialize the entities you made and register the EVENT_BUS in your main class under the FMLCommonSetupEvent.

 

What a rush lol

Edited by Cryotron
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.