Jump to content

Vryday_Vrything

Members
  • Posts

    11
  • Joined

  • Last visited

Recent Profile Visitors

The recent visitors block is disabled and is not being shown to other users.

Vryday_Vrything's Achievements

Tree Puncher

Tree Puncher (2/8)

0

Reputation

  1. I must admit that I gave up on Minecraft and went back to my own voxel engine but I'll see what I can find in my old code.............. Okay, first, I should mention that static references to the old blocks are the only things that are not changed by substitution. This should mean that other mods, "custom biomes", do not need to be updated in any way (at least I believe this is the case if they are coded properly). You could search for all static references to the block you're replacing and manually write the code to update it but I chose to write some reflection code to automate it for me. I hope this helps, it appears to have worked for me... Map<Block, Block> blockReplacementMap = new HashMap<Block, Block>(); //Key is old block, value is new block void updateBiomeBlocks() { for (Iterator<Biome> it = Biome.REGISTRY.iterator(); it.hasNext();) { //iterate through all registered biomes Biome biome = it.next(); for (Entry<Block, Block> entry : this.blockReplacementMap.entrySet()) { //iterate through the substitution map Block oldBlock = entry.getKey(); //the original block Block newBlock = entry.getValue(); //your replacement block //Below are the only places I found static references to blocks if (biome.theBiomeDecorator.gravelAsSandGen instanceof WorldGenSand) { if (oldBlock == ReflectionHelper.getPrivateValue(WorldGenSand.class, (WorldGenSand)biome.theBiomeDecorator.gravelAsSandGen, 0)) ReflectionHelper.setPrivateValue(WorldGenSand.class, (WorldGenSand)biome.theBiomeDecorator.gravelAsSandGen, newBlock, 0); } if (biome.theBiomeDecorator.sandGen instanceof WorldGenSand) { if (oldBlock == ReflectionHelper.getPrivateValue(WorldGenSand.class, (WorldGenSand)biome.theBiomeDecorator.sandGen, 0)) ReflectionHelper.setPrivateValue(WorldGenSand.class, (WorldGenSand)biome.theBiomeDecorator.sandGen, newBlock, 0); } } } }
  2. Unfortunately, while using GetCollisionBoxesEvent I still noticed collisions with many blocks when I clear the entire collision list (as a test). <EDIT> It appears this is because Block#isNormalCube still evaluates to true... EntityPlayerSp#pushOutOfBlocks calls EntityPlayerSp#isHeadspaceFree calls EntityPlayerSp#isOpenBlockSpace calls Block#isNormalCube </EDIT> Also, there doesn't appear to be an event for raytracing, which is unfortunate but, perhaps, not absolutely critical... As I feared, it appears this solution will not work either... but thanks again anyway diesieben07. I'll explore some of the earlier forge releases in hopes that one of these solutions will work. Or perhaps I will just use my own world gen and duplicate all the blocks. Though that would be a shame as I believe it would be more difficult to use my mod with other mods... EDIT I've experimented with the substitution limit more and hacked past the limitation for now... I hope to find a more legitimate solution in the future...
  3. Awesome, thank you. I'll try to do it without substitution again. If I may ask one more question... do you know a good way in forge to catch specific blocks in an event? I was going to implement an interface on the substituted blocks. Without substitution the only idea I have is to keep a large list of blocks I want to catch at specific points and iterate over it every time. Seems excessive...
  4. I've never used github so I hope this is okay... apologies if not... addSubstitutionAlias-example As for why. I made an algorithm that contours the blocks a bit. Long story short, I want to change the collision boxes returned by the vanilla blocks to match the contoured terrain better. It's also much cleaner to change out the blocks for the rendering aspect, though not strictly necessary I don't think.
  5. After tinkering for a couple days I have everything working with the addSubstitutionAlias method. So I started substituting blocks and ran into the odd limitation of only being able to substitute 19 blocks. I wrote some test/example code to show the problem (below). Sure enough, if I substitute 19 of the blocks it works great. Add a 20th substitution and I get java.lang.NullPointerException: Initializing game (also below). I also tried the code in the latest 1.11.2 build and got the same thing. Any advice? I'm pretty new here, is there somewhere I should report this as an error? Thanks. package com.example.examplemod; import net.minecraft.block.Block; import net.minecraft.block.BlockOre; import net.minecraft.block.material.Material; import net.minecraft.init.Blocks; import net.minecraft.item.Item; import net.minecraft.item.ItemBlock; import net.minecraft.util.ResourceLocation; import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.common.Mod.EventHandler; import net.minecraftforge.fml.common.event.FMLPreInitializationEvent; import net.minecraftforge.fml.common.registry.ExistingSubstitutionException; import net.minecraftforge.fml.common.registry.GameRegistry; @Mod(modid = ExampleMod.MODID, version = ExampleMod.VERSION) public class ExampleMod { public static final String MODID = "examplemod"; public static final String VERSION = "1.0"; @EventHandler public void preInit(FMLPreInitializationEvent event) { substitute(Blocks.COBBLESTONE, new ModBlock("stonebrick")); substitute(Blocks.LAPIS_BLOCK, new ModBlock("blockLapis")); substitute(Blocks.GOLD_BLOCK, new ModBlock("blockGold")); substitute(Blocks.IRON_BLOCK, new ModBlock("blockIron")); substitute(Blocks.BRICK_BLOCK, new ModBlock("brick")); substitute(Blocks.MOSSY_COBBLESTONE, new ModBlock("stoneMoss")); substitute(Blocks.DIAMOND_BLOCK, new ModBlock("blockDiamond")); substitute(Blocks.END_STONE, new ModBlock("whiteStone")); substitute(Blocks.EMERALD_BLOCK, new ModBlock("blockEmerald")); substitute(Blocks.COAL_BLOCK, new ModBlock("blockCoal")); substitute(Blocks.PURPUR_BLOCK, new ModBlock("purpurBlock")); substitute(Blocks.END_BRICKS, new ModBlock("endBricks")); substitute(Blocks.NETHER_WART_BLOCK, new ModBlock("netherWartBlock")); substitute(Blocks.GOLD_ORE, new ModBlockOre("oreGold")); substitute(Blocks.IRON_ORE, new ModBlockOre("oreIron")); substitute(Blocks.COAL_ORE, new ModBlockOre("oreCoal")); substitute(Blocks.LAPIS_ORE, new ModBlockOre("oreLapis")); substitute(Blocks.DIAMOND_ORE, new ModBlockOre("oreDiamond")); substitute(Blocks.EMERALD_ORE, new ModBlockOre("oreEmerald")); substitute(Blocks.QUARTZ_ORE, new ModBlockOre("netherquartz")); } public static void substitute(Block toReplace, Block newBlock) { substitute(toReplace, newBlock, new ItemBlock(newBlock)); } public static void substitute(Block toReplace, Block newBlock, Item newItem) { try { ResourceLocation oldName = Block.REGISTRY.getNameForObject(toReplace); String nameToSubstitute = oldName.toString(); String nameToRegister = ExampleMod.MODID + ":" + oldName.getResourcePath(); newBlock.setRegistryName(nameToRegister); GameRegistry.addSubstitutionAlias(nameToSubstitute.toString(), GameRegistry.Type.BLOCK, newBlock); newItem.setRegistryName(nameToRegister); GameRegistry.addSubstitutionAlias(nameToSubstitute.toString(), GameRegistry.Type.ITEM, newItem); } catch (ExistingSubstitutionException e) { e.printStackTrace(); throw new RuntimeException(e); } } public static class ModBlock extends Block { public ModBlock(String name) { super(Material.ROCK); this.setUnlocalizedName(name); } } public static class ModBlockOre extends BlockOre { public ModBlockOre(String name) { this.setUnlocalizedName(name); } } } The error
  6. There doesn't seem to be much interest in this thread but I've come up with a few solutions that seem to fix any problems with substitution (pending more testing). So, if anyone needs help with it just let me know. I'll try to help.
  7. After thinking about this for a little bit and doing a quick test, it seems vanilla biomes are created before the FMLPreInitializationEvent and not updated with substitution. Therefore the old block instance is used. For example, to fix this for sand I can simply do the following for each biome with Blocks.SAND in it: BiomeDesert biomeDesert = (BiomeDesert)Biome.REGISTRY.getObjectById(2); biomeDesert.topBlock = newBlock.getDefaultState(); biomeDesert.fillerBlock = newBlock.getDefaultState(); The index for the biome, in this case "desert", is listed in the net.minecraft.world.biome.Biome class.
  8. Just a small update. I substituted sand instead of grass as a test. Now there is no sand to be found anywhere in the world. Just floating bodies of water and deserts missing the sand layer. More notably I found blocks along the ocean where sand should be that seem to exist server side only, as I collide with nothing. Those places are unlit. Placing a block there brings it client side, it then becomes a block with a missing texture (black, purple) labelled as "null variant:sand" in the debug info (F3). The light is also updated. The block ID is 12 before and after substitution... Other things seem to work. Placing a block of sand over nothing allows it to fall and return to the new block type. I can craft sandstone from it. If placed with nothing underneath it falls becomes sand again. I can craft sandstone from it.
  9. I was in a hurry when I posted, sorry. Please see the edit in my original post... hope it helps more.
  10. In case you want something more specific, this should work. First you'll have to choose the block state you want to use. For example: IBlockState state = Blocks.STONE.getDefaultState(); Then use: Minecraft.getMinecraft().getBlockRendererDispatcher().getBlockModelShapes().getTexture(state); EDIT If you want to specify the side/facing etc. use: Minecraft.getMinecraft().getBlockRendererDispatcher().getBlockModelShapes().getModelForState(state); Then you can use something like this to get the texture: private TextureAtlasSprite getTexture(IBakedModel ibakedmodel, IBlockState state, EnumFacing facing) { List<BakedQuad> quadList = ibakedmodel.getQuads(state, facing, 0L); TextureAtlasSprite sprite = quadList.isEmpty() ? ibakedmodel.getParticleTexture() : quadList.get(0).getSprite(); return sprite == null ? this.missingTexture : sprite; } My method above is for my own usage and won't work for some blocks like lava, water and certain tile entity blocks but .getTexture(state) should. Better yet, take a look at BlockModelShapes.getTexture(state) method. You could copy that and modify it to your liking. You can change the quadList.get(index) to another index to get another quad attached to that facing.
  11. When I use addSubstitutionAlias world generation often places an air block instead of my replacement block (see attached screenshot). Any advice on how to fix this? Some more information: The block appears twice in my BUILDING_BLOCKS tab The example code below works great, except the above mentioned problems (thanks for any and all help): package com.example.examplemod; import net.minecraft.block.Block; import net.minecraft.block.BlockGrass; import net.minecraft.block.SoundType; import net.minecraft.block.state.IBlockState; import net.minecraft.entity.EntityLivingBase; import net.minecraft.init.Blocks; import net.minecraft.item.Item; import net.minecraft.item.ItemColored; import net.minecraft.item.ItemStack; import net.minecraft.util.ResourceLocation; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.common.Mod.EventHandler; import net.minecraftforge.fml.common.event.FMLPreInitializationEvent; import net.minecraftforge.fml.common.registry.ExistingSubstitutionException; import net.minecraftforge.fml.common.registry.GameRegistry; @Mod(modid = ExampleMod.MODID, version = ExampleMod.VERSION) public class ExampleMod { public static final String MODID = "examplemod"; public static final String VERSION = "1.0"; @EventHandler public void preInit(FMLPreInitializationEvent event) { try { Block newBlock = new ModBlockGrass(); Item newItem = new ItemColored(newBlock, false); ResourceLocation oldName = Block.REGISTRY.getNameForObject(Blocks.GRASS); String nameToSubstitute = oldName.toString(); //"minecraft:grass" String nameToRegister = ExampleMod.MODID + ":" + oldName.getResourcePath(); //"examplemod:grass" newBlock.setRegistryName(nameToRegister); GameRegistry.addSubstitutionAlias(nameToSubstitute.toString(), GameRegistry.Type.BLOCK, newBlock); newItem.setRegistryName(nameToRegister); GameRegistry.addSubstitutionAlias(nameToSubstitute.toString(), GameRegistry.Type.ITEM, newItem); } catch (ExistingSubstitutionException e) { e.printStackTrace(); throw new RuntimeException(e); } } public static class ModBlockGrass extends BlockGrass { public ModBlockGrass() { this.setHardness(0.6F); this.setSoundType(SoundType.PLANT); this.setUnlocalizedName("grass"); } @Override public void onBlockPlacedBy(World worldIn, BlockPos pos, IBlockState state, EntityLivingBase placer, ItemStack stack) { System.out.println("ModBlockGrass.onBlockPlacedBy"); super.onBlockPlacedBy(worldIn, pos, state, placer, stack); } } }
×
×
  • Create New...

Important Information

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