"Edit" NMS classes?

Discussion in 'Plugin Development' started by nathanaelps, Oct 11, 2012.

Thread Status:
Not open for further replies.
  1. Offline

    nathanaelps

    cadika_orade got me interested in the idea of jacking with grass spread. As it is now, CB doesn't let you change the logic/speed of spread, at least not that I can find. Some of the logic of it is in net/minecraft/server/BlockGrass.java, however, and I'd love to mess it up.
    I understand that this would require me to update said plugin with every MC update, but that's a responsibility I'm willing to ignore. :D

    How do I mess with that?

    Actually, I really would like to get deeper than that. I'd love to find a way to tap into the "random spread" logic and make (say) mossy cobblestone spread to nearby cobblestone in the same way that grass spreads to dirt. Could somebody point me in the right direction? I'll do my homework, I promise!


    (edit to fix some horrid formatting)
     
  2. You can always build against craftbukkit.jar (which contains all net.minecraft.server classes) and directly access these classes. It's pretty complicated in some cases though.

    If you want to change behavior of grass, you could for instance create a class that extends BlockGrass and have it override the methods you want to change.
    To make the game actually use this new class, you can do something like that in onEnable:
    Code:
    Block.byId[Block.GRASS.id] = new YourGrassBlock(...);
    (where Block is net.minecraft.server.Block)
    (make sure you set it back when your plugin disables or leaks can happen)

    You might need to replace other occurrences as well, that's up to you to figure out ;)

    Increasing grass spread rates might be pretty hard, though, since grass simply does it on the "random block ticks". These are executed on 40 (?) random blocks in each chunk on each tick. Once it happens to hit grass, it spreads/fades. Not sure how you could increase that, but I'll happily let you try ;)

    Have fun, and welcome to the twisted world of native minecraft code :D
     
  3. Offline

    nathanaelps

    Got that. The whole "setting it back" thing is a little less... straightforward:

    I chose to tinker with mycelium, as it's a little less... pervasive.

    so,
    Code:
    net.minecraft.server.Block.byId[net.minecraft.server.Block.MYCEL.id] = new BlockMycelium(0);
    
    is in onEnable.
    The 0 is a wild guess: the constructor wanted an int, and obfuscation has made it difficult to tell why. I'll poke at it later, when I've figured out how to disable it in onDisable:
    Code:
    net.minecraft.server.Block.byId[net.minecraft.server.Block.MYCEL.id] = new net.minecraft.server.BlockMycel(0);
    Nope. That doesn't work... The BlockMycel(int) constructor (well, the ONLY BlockMycel constructor) is protected. I can't call it from my code.
    Which leaves me to wonder: Am I doing it wrong?
     
  4. Offline

    Njol

    Just do it like Minecraft does it:
    Code:
    public static final BlockMycel MYCEL = (BlockMycel) (new BlockMycel(110)).c(0.6F).a(g).a("mycel");
    If you can't access the constructor you either have to use reflection or save the block in onEnable so you'll be able to set it back in onDisable ;)
     
  5. onDisable:
    Code:
    Block.byId[Block.MYCEL.id] = Block.MYCEL;
    Remember that you only changed the entry in the array, not the constant itself! So it's still sitting there in its original form and you can easily reassign it.
     
  6. Offline

    nathanaelps

    Oh... really... That's obvious, now that you mention it. *koff* I'll turn in my "smart" card now.

    Thanks.

    It looks like it might just be done after all! I'll keep tinkering with it tomorrow! Thanks.
     
  7. Offline

    nathanaelps

    Tomorrow became Monday, and it's working! I made it work! Thanks, all you guys.
     
  8. Offline

    RawCode

    i play a lot with this feature, it also possible on forge and other serverbuilds. same method allows to replace entity objects and items\anything else. in rare cases you will be forced to replace class container too (like tree growth that contain static reference to vanilla class)
    vs164dev


    Code:
    package ru.rawcode.dev.blocks;
     
    import net.minecraft.server.v1_6_R3.Block;
    import net.minecraft.server.v1_6_R3.Material;
     
    public class CustomBlock extends Block {
       
        public CustomBlock(int i, Material material) {
            super(i, material);
        }
       
        public CustomBlock b(float f) {
            this.durability = f * 3.0F;
            return this;
        }
       
        public CustomBlock c(float f) {
            this.strength = f;
            if (this.durability < f * 5.0F) {
                this.durability = f * 5.0F;
            }
            return this;
        }
    }
    Code:
    package ru.rawcode.dev.blocks;
     
    import java.util.Random;
    import net.minecraft.server.v1_6_R3.Material;
    import net.minecraft.server.v1_6_R3.World;
     
    public class CustomCobble extends CustomBlock {
     
        public CustomCobble(int i, Material material) {
            super(i, Material.GRASS);
            this.b(true);
        }
     
        public void a(World world, int i, int j, int k, Random random) {
            if (!world.isStatic && random.nextFloat() >= 0.9)
            {
                    world.setAir(i, j, k);
            }
        }
    }
    any place, including runtime places allowed, but for runtime you MUST stop main thread before changing (via thread.park from unsafe) or ensure that change happen offtick by other means.

    Code:
            //Block.byId[Block.COBBLESTONE.id] = null;
            //Block.byId[Block.COBBLESTONE.id] = new CustomCobble(4, Material.STONE).c(2.0F).b(10.0F);
     
Thread Status:
Not open for further replies.

Share This Page