Cryotron Posted April 14, 2020 Share Posted April 14, 2020 (edited) 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 April 16, 2020 by Cryotron 1 Quote Link to comment Share on other sites More sharing options...
Animefan8888 Posted April 14, 2020 Share Posted April 14, 2020 17 minutes ago, Cryotron said: the field variable is private static final Have you tried using Reflection? Quote 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 More sharing options...
Cryotron Posted April 14, 2020 Author Share Posted April 14, 2020 1 minute ago, Animefan8888 said: Have you tried using Reflection? I have not heard of it so probably not. I'll look it up and figure out what to do with it. Quote Link to comment Share on other sites More sharing options...
Cryotron Posted April 14, 2020 Author Share Posted April 14, 2020 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. Quote Link to comment Share on other sites More sharing options...
Cryotron Posted April 14, 2020 Author Share Posted April 14, 2020 (edited) 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 April 14, 2020 by Cryotron Quote Link to comment Share on other sites More sharing options...
Cryotron Posted April 14, 2020 Author Share Posted April 14, 2020 (edited) 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. Edited April 14, 2020 by Cryotron Quote Link to comment Share on other sites More sharing options...
Cryotron Posted April 15, 2020 Author Share Posted April 15, 2020 (edited) 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 April 15, 2020 by Cryotron Quote Link to comment Share on other sites More sharing options...
Cryotron Posted April 16, 2020 Author Share Posted April 16, 2020 (edited) 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 April 16, 2020 by Cryotron Quote Link to comment Share on other sites More sharing options...
Recommended Posts
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.