A new modder here and pretty novice in java coding in general so sorry if I ask stupid questions!
Is there a way to add more than one FillerBlockType in the same method if I wanted to generate my ore for example in ocean floor?
The method works just fine, but only generates ores near stone. If I would like the ore to be generated near gravel and sand as well how to I do it? I got my own FillerBlockTypes made for them but it says I can't add operators to the arguments when calling the genOre method. Do I just call my genOre method multiple times for each FillerBlockType I want?
Another question I have is how to make an ore to generate only near water sources? If I set the FillerBlockType to WATER the ore would presumable generate where water normally does and I want it to generate like normal stone in underground in caves, but only near water (talking about a different ore here).
My method looks like this:
@SubscribeEvent
public static void generateOres(FMLLoadCompleteEvent event) {
You cannot make another filler block type. If you want ores to generate and replace different blocks, then you'll have to copy the ore feature code and then just replace the FillerBlockType with a way of testing if the ore can generate there. You'll also need to register the feature.
Another question I have is how to make an ore to generate only near water sources? If I set the FillerBlockType to WATER the ore would presumable generate where water normally does and I want it to generate like normal stone in underground in caves, but only near water (talking about a different ore here).
Do you mean like adjacent to water or within a few blocks?
You cannot make another filler block type. If you want ores to generate and replace different blocks, then you'll have to copy the ore feature code and then just replace the FillerBlockType with a way of testing if the ore can generate there. You'll also need to register the feature.
For placing ores adjacent to water, I would suggest in the line where the blocks are actually placed in testing if any of the fluids adjacent to the ore are water or flowing water.
I believe I'm trying to do exactly what you're trying to do, did you get anywhere with this?
As mentioned in the replies above, you need to copy the vanilla ore generation code and modify the place where it checks the block so it can instead check multiple block types; for example, my own custom ore generator (based on my own code which is completely different from any vanilla version but the principle is the same) has a "generateMetadataOreVein" method which places ores with data values based on the block being replaced (in this case, variants of stone and a "biome stone" block):
int meta = BlockMetadataOre.getMetadataForBlock(chunk.getBlockStateByIndex(ix));
if (meta >= 0) chunk.setBlockStateFastByIndex(ix, BlockStates.getBlockState(block, meta));
// Returns metadata corresponding to the block being replaced, returning -1 if there is no variant for
// the block
public static final int getMetadataForBlock(int blockState)
{
int block = BlockStates.getBlockId(blockState);
if (block == BlockStates.stone)
{
switch (BlockStates.getBlockMetadata(blockState))
{
case BlockStoneTMCW.STONE:
return STONE;
case BlockStoneTMCW.GRANITE:
return STONE;
case BlockStoneTMCW.POLISHED_GRANITE:
return -1;
case BlockStoneTMCW.DIORITE:
return STONE;
case BlockStoneTMCW.POLISHED_DIORITE:
return -1;
case BlockStoneTMCW.ANDESITE:
return STONE;
case BlockStoneTMCW.POLISHED_ANDESITE:
return -1;
case BlockStoneTMCW.RED_SANDSTONE:
return RED_SANDSTONE;
case BlockStoneTMCW.STONE_VEIN:
return STONE;
default:
return -1;
}
}
else if (block == BlockStates.biomeStone)
{
switch (BlockStates.getBlockMetadata(blockState))
{
case BlockStoneTMCW.SANDSTONE:
return SANDSTONE;
case BlockStoneTMCW.QUARTZ_SANDSTONE:
return QUARTZ_SANDSTONE;
case BlockStoneTMCW.HARDENED_CLAY:
return HARDENED_CLAY;
case BlockStoneTMCW.WHITE_STAINED_CLAY:
return HARDENED_CLAY;
case BlockStoneTMCW.ORANGE_STAINED_CLAY:
return HARDENED_CLAY;
case BlockStoneTMCW.YELLOW_STAINED_CLAY:
return HARDENED_CLAY;
case BlockStoneTMCW.LIGHT_GRAY_STAINED_CLAY:
return HARDENED_CLAY;
case BlockStoneTMCW.BROWN_STAINED_CLAY:
return HARDENED_CLAY;
case BlockStoneTMCW.RED_STAINED_CLAY:
return HARDENED_CLAY;
case BlockStoneTMCW.MAGENTA_STAINED_CLAY:
return HARDENED_CLAY;
case BlockStoneTMCW.PINK_STAINED_CLAY:
return HARDENED_CLAY;
case BlockStoneTMCW.PURPLE_STAINED_CLAY:
return HARDENED_CLAY;
case BlockStoneTMCW.SNOW:
return SNOW;
case BlockStoneTMCW.PACKED_ICE:
return PACKED_ICE;
case BlockStoneTMCW.OPAQUE_ICE:
return PACKED_ICE;
case BlockStoneTMCW.BLUE_ICE:
return BLUE_ICE;
default:
return -1;
}
}
else
{
return -1;
}
}
To have ores only generate near water/air/etc you essentially run through the code that places ores twice with the first pass checking each adjacent block and the second pass actually placing ores if the first pass found at least one exposed block in the entire vein (you could also do both at once but then only blocks right next to water/air/etc will be placed):
if (BlockMetadataOre.getMetadataForStone(chunk.getBlockStateByIndex(ix)) >= 0)
{
// Checks to the sides on layers 4 and above
if (by >= 4 && (isBlockExposed(chunkCache.getBlockId(bx - 1, by, bz)) || isBlockExposed(chunkCache.getBlockId(bx + 1, by, bz)) || isBlockExposed(chunkCache.getBlockId(bx, by, bz - 1)) || isBlockExposed(chunkCache.getBlockId(bx, by, bz + 1)))) isExposed = true;
// Checks below on layers 5 and above (layer 4 cannot be exposed below)
if (by >= 5 && isBlockExposed(chunk.getBlockIDByIndex(ix - 256))) isExposed = true;
// Checks above on layers 3 and above
if (isBlockExposed(chunk.getBlockIDByIndex(ix + 256))) isExposed = true;
if (isExposed) break exposureCheck;
}
// Ores are considered to be exposed if they touch a non-opaque cube block (air, water, lava, etc)
private static final boolean isBlockExposed(int block)
{
return !Block.opaqueCubeLookup[block];
}
In my case I do not place blocks directly with the code that generates the shape of a vein but instead initialize a mask which is then iterated over to place blocks in the world; otherwise, the RNG used by the code that creates the vein shape needs to be seeded the same for each pass (I mainly use a mask for efficiency since I can call getChunkFromBlockCoords once for each column instead of each block, and avoid a lot of redundant block lookups due to veins being made of overlapping "blobs" (even small veins like diamond have 4-6 times more innermost loop iterations than blocks placed). Note that checking for whether veins are exposed is more expensive either way due to up to 7 block lookups per block in the vein instead of one, which is why I only use it for additional veins which generate in caves to compensate for differences in air volume between the lower layers and overall, while not impacting ore density in solid ground/branch-mining).
Also, if you want to place veins on the seafloor you can check if the highest solid block is the seafloor before attempting to generate a vein; e.g. see how vanilla places sand/gravel/clay deposits underwater; then you can replace blocks as normal without having to check adjacent blocks since it will be guaranteed to be in contact with water (horizontal surfaces or the ceilings of underwater caves will require it, or you can be simpler and just check if the block at the center of a vein is a suitable replacement block and at least one of the adjacent blocks is water; this will cause a higher failure rate per attempt but it is cheaper to increase the number since you are only checking up to 7 blocks per vein. Note that the "center" of a vein is offset down from the y-coordinate passed to WorldGenMinable, which for smaller veins is the maximum altitude blocks will be placed; e.g. a diamond vein at y=15 will never place blocks above y=15 and as low as y=12).
A new modder here and pretty novice in java coding in general so sorry if I ask stupid questions!
Is there a way to add more than one FillerBlockType in the same method if I wanted to generate my ore for example in ocean floor?
The method works just fine, but only generates ores near stone. If I would like the ore to be generated near gravel and sand as well how to I do it? I got my own FillerBlockTypes made for them but it says I can't add operators to the arguments when calling the genOre method. Do I just call my genOre method multiple times for each FillerBlockType I want?
Another question I have is how to make an ore to generate only near water sources? If I set the FillerBlockType to WATER the ore would presumable generate where water normally does and I want it to generate like normal stone in underground in caves, but only near water (talking about a different ore here).
My method looks like this:
You cannot make another filler block type. If you want ores to generate and replace different blocks, then you'll have to copy the ore feature code and then just replace the FillerBlockType with a way of testing if the ore can generate there. You'll also need to register the feature.
Do you mean like adjacent to water or within a few blocks?
Uncrafting Table (1.15.2): https://www.minecraftforum.net/forums/mapping-and-modding-java-edition/minecraft-mods/wip-mods/3032965-uncrafting-table
Ruins of Humanity (mod, no longer being developed): https://www.minecraftforum.net/forums/mapping-and-modding-java-edition/minecraft-mods/wip-mods/2898701-1-12-2-wip-early-alpha-ruins-of-humanity
Ok thanks, i will try that!
Adjacent to water is what I meant.
For placing ores adjacent to water, I would suggest in the line where the blocks are actually placed in testing if any of the fluids adjacent to the ore are water or flowing water.
Uncrafting Table (1.15.2): https://www.minecraftforum.net/forums/mapping-and-modding-java-edition/minecraft-mods/wip-mods/3032965-uncrafting-table
Ruins of Humanity (mod, no longer being developed): https://www.minecraftforum.net/forums/mapping-and-modding-java-edition/minecraft-mods/wip-mods/2898701-1-12-2-wip-early-alpha-ruins-of-humanity
I believe I'm trying to do exactly what you're trying to do, did you get anywhere with this?
Hey, my modpack is pretty cool https://www.technicpack.net/modpack/the-avery-pack.1429648
As mentioned in the replies above, you need to copy the vanilla ore generation code and modify the place where it checks the block so it can instead check multiple block types; for example, my own custom ore generator (based on my own code which is completely different from any vanilla version but the principle is the same) has a "generateMetadataOreVein" method which places ores with data values based on the block being replaced (in this case, variants of stone and a "biome stone" block):
To have ores only generate near water/air/etc you essentially run through the code that places ores twice with the first pass checking each adjacent block and the second pass actually placing ores if the first pass found at least one exposed block in the entire vein (you could also do both at once but then only blocks right next to water/air/etc will be placed):
In my case I do not place blocks directly with the code that generates the shape of a vein but instead initialize a mask which is then iterated over to place blocks in the world; otherwise, the RNG used by the code that creates the vein shape needs to be seeded the same for each pass (I mainly use a mask for efficiency since I can call getChunkFromBlockCoords once for each column instead of each block, and avoid a lot of redundant block lookups due to veins being made of overlapping "blobs" (even small veins like diamond have 4-6 times more innermost loop iterations than blocks placed). Note that checking for whether veins are exposed is more expensive either way due to up to 7 block lookups per block in the vein instead of one, which is why I only use it for additional veins which generate in caves to compensate for differences in air volume between the lower layers and overall, while not impacting ore density in solid ground/branch-mining).
Also, if you want to place veins on the seafloor you can check if the highest solid block is the seafloor before attempting to generate a vein; e.g. see how vanilla places sand/gravel/clay deposits underwater; then you can replace blocks as normal without having to check adjacent blocks since it will be guaranteed to be in contact with water (horizontal surfaces or the ceilings of underwater caves will require it, or you can be simpler and just check if the block at the center of a vein is a suitable replacement block and at least one of the adjacent blocks is water; this will cause a higher failure rate per attempt but it is cheaper to increase the number since you are only checking up to 7 blocks per vein. Note that the "center" of a vein is offset down from the y-coordinate passed to WorldGenMinable, which for smaller veins is the maximum altitude blocks will be placed; e.g. a diamond vein at y=15 will never place blocks above y=15 and as low as y=12).
TheMasterCaver's First World - possibly the most caved-out world in Minecraft history - includes world download.
TheMasterCaver's World - my own version of Minecraft largely based on my views of how the game should have evolved since 1.6.4.
Why do I still play in 1.6.4?