Jump to content

IceMetalPunk

Members
  • Posts

    402
  • Joined

  • Last visited

Everything posted by IceMetalPunk

  1. 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...
  2. 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...
  3. getRabbitType is, as its name suggests, a Rabbit-only method. If your EntityBandit class isn't extending the EntityRabbit class, you can't use that method. The process is quite simple for what you want, though: 1. Your RenderBandit class should have an array with all the possible textures. 2. In your EntityBandit's constructor, you choose a random number between 0 and N, where N is the highest index in your array from step 1. 3. You add a method in EntityBandit called, for instance, getTextureType, which simply returns that integer from step 2. 4. Now your RenderBandit class can call getTextureType to get the entity's texture index and apply it to the array of textures to get the actual texture used for rendering.
  4. 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...
  5. 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!
  6. 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....
  7. 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
  8. 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?
  9. 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.
  10. 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?
  11. 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?
  12. Keep in mind that the onItemUse() method will be called twice: once on the server, and once on the client. That's why you're getting two outputs, since both calls are sending a message. You can check which side is calling the method from the World#isRemote member. In your case, the world is a parameter called w, so you can check w.isRemote to see the side. If isRemote is false, it's the server, if it's true, it's the client. For instance, if your code only does things on the server, you can simply bypass it on the client by putting this snippet at the top of your method body: if (w.isRemote) { return EnumActionResult.PASS; }
  13. 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?
  14. Ah, that might just be the case! Looking into it, the "generateFalls" field of the biome decorator is true by default and not overridden by swamps, so it does in fact create surface water patches during decoration; that would explain why the issue occurs if I do this from a Biome, but not from the main world generation. I'll look into canceling the generation; I haven't used terrain generator events before, but I'm sure I can figure something out Thank you for pointing me in the right direction! EDIT Well, that didn't work I created a terrain gen event handler to deny the generation of lakes in my biome. Here's the code, and yes, it's registered on the terrain gen bus: package com.icemetalpunk.mita.events; import com.icemetalpunk.mita.biome.BiomeMitaSwamp; import net.minecraft.world.World; import net.minecraft.world.biome.Biome; import net.minecraftforge.event.terraingen.DecorateBiomeEvent; import net.minecraftforge.event.terraingen.DecorateBiomeEvent.Decorate; import net.minecraftforge.fml.common.eventhandler.Event.Result; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; public class TerrainEventHandler { @SubscribeEvent public void onDecoration(DecorateBiomeEvent.Decorate ev) { World world = ev.getWorld(); Decorate.EventType type = ev.getType(); Biome biome = world.getBiome(ev.getPos()); if (biome instanceof BiomeMitaSwamp && type == Decorate.EventType.LAKE_WATER) { ev.setResult(Result.DENY); } } } I know that it's definitely being run for my BiomeMitaSwamp because I originally tried to cancel it with ev.setCanceled(), and it crashed because it's not a cancelable event. But the description of the event says setting the result to DENY should prevent the decoration; yet it still has patches of water generating without blocks above them Any other ideas?
  15. Just make sure if you do that you first check that the Entity is, in fact, an instance of EntityZombie, otherwise the cast could fail and cause problems.
  16. The read methods take an NBT tag and read its contents into fields within the object reading it. It doesn't need to return anything. The write methods take the field values and write them into a supplied NBT tag container (often, but not always, a currently-empty NBT tag). It then returns that tag after the modifications have been made, so you can pass it around to other things to write to, or use it however you want. So read updates the object's state from the contents of an NBT tag, while write stores the object's state into an NBT tag.
  17. Yes, the HarvestDropsEvent might come in handy here.
  18. It depends. If you don't have a pack.mcmeta file using format 3, then Forge will try to adapt and use a legacy parser that allows mixed-case filenames. But that's poor practice, and you should be using the modern standards with the pack.mcmeta format and all lowercase names.
  19. Firstly, in 1.11 and above, all your asset filenames must be lower case; I see you have en_US.lang, which won't work. That's why the item name isn't being translated properly. As for why the model isn't loading, I can't watch the full video now, but if it's using outdated registration methods, you may want to update to the modern Registry Events and see if that solves your problem. If not, post the code in your .json model file for us to debug. (Also, a common issue is forgetting to include the namespaces in your model file's paths, so make sure you're doing that!)
  20. Some advice, which you can choose to take or ignore: giving you code doesn't help you learn how to apply programming knowledge in the future. On top of that, we can't debug your code if we don't know what your code is. So when we say things like "Try figuring it out yourself first, and if it doesn't work, then show us the code and we'll help" or "We can't help unless you give us your code", that's not sass, it's not superiority, it's us actually trying to help you learn from your mistakes. And in case it helps you understand our perspective, I currently teach a programming course for adults for a living, so I have a bit of experience in how people learn to code best. Giving you the code will help you get this one thing working, but the next time you encounter a similar (but different) problem, you'll get stuck again. Learning by guided trial-and-error is the best way to understand the logic behind the code and thus help you going forward. Again, this is just my perspective and advice, you don't have to take it. Good luck with everything.
  21. This is true. Thanks. So after making that optimization, the problem still persists: seemingly random patches of surface water in a swamp are not generating the blocks above them. New code: package com.icemetalpunk.mita.biome; import java.util.Random; import net.minecraft.block.material.Material; import net.minecraft.init.Blocks; import net.minecraft.world.World; import net.minecraft.world.biome.BiomeSwamp; import net.minecraft.world.chunk.ChunkPrimer; public class BiomeMitaSwamp extends BiomeSwamp { public BiomeMitaSwamp(BiomeProperties properties) { super(properties); this.setRegistryName("minecraft", "swampland"); } // FIXME: Leaves "random" patches of water in swamps uncovered; why? @Override public void genTerrainBlocks(World worldIn, Random rand, ChunkPrimer chunkPrimerIn, int j, int i, double noiseVal) { super.genTerrainBlocks(worldIn, rand, chunkPrimerIn, j, i, noiseVal); int x = j & 15; int z = i & 15; for (int y = 255; y >= 0; --y) { Material mat = chunkPrimerIn.getBlockState(x, y, z).getMaterial(); boolean isWater = (mat == Material.WATER); boolean isAir = (mat == Material.AIR); if (!isAir) { if (isWater) { chunkPrimerIn.setBlockState(x, y + 1, z, Blocks.MAGMA.getDefaultState()); } return; } } } }
  22. So, looking through the code, here are some thoughts. Note that there is probably a much better way of doing this that I'm just not aware of, but until someone mentions one, I'm offering this idea. There doesn't seem to be any event fired during outline rendering that you can hook into to change the color at the last moment. But the color is determined by the entity's team on the scoreboard (specifically, the team prefix has a section-symbol color code, and that's what's used to get the glowing color). So if you could switch the entity's team just before the outline is rendering, then switch it back immediately after, you could change the glowing color without any other code seeing the incorrect team. The relevant methods here are Entity#getTeam() and World#getScoreboard().addPlayerToTeam(String player, String newTeam). The idea is that you'd hook into the RenderLivingEvent.Pre<EntityLivingBase> event and change the entity's team there to the color you want, then change it back in the RenderLivingEvent.Post<EntityLivingBase> event.
  23. Generally speaking, the IInventory in question will be an instance of the Tile Entity class of the appropriate type when filling tile entity inventories. So you can just check if the passed IInventory is an instance of TileEntity, then cast it and store it somewhere.
  24. Right, but those are for two different behaviors. If it's not air, no matter what it is, the generation should return immediately, as I'm only wanting to generate blocks above water on the surface, not underground. And then from there, it should only generate if the block is water. So for instance, if it finds a grass block, that's not air, so I need to know that to stop looking further down, but it's also not water, which I need to know so it doesn't generate a block above the grass. I just don't understand why it's not generating blocks above *all* the surface water like I'd expect. The funny thing is I've been playing around with world generators using similar code (obviously with a bit added to iterate over an entire chunk), and it works perfectly fine; it's only when used in the Biome class that it doesn't fill every appropriate block. Are these methods not called for every block in the biome like I thought?
  25. For future reference, if you're using Eclipse as your IDE, you can right-click any field or method name and click "Open Call Hierarchy", and Eclipse will show you exactly what classes are referencing the field or calling the method, and where. It's a very useful research and debugging tool
×
×
  • Create New...

Important Information

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