Jump to content

Recommended Posts

Posted

Hi, I've stared writing a mod and have had some good success so far (really impressed with Forge BTW!). However I think my ambitions lie somewhat outside the normal mods.

 

I want to add a special effect to any block (or ultimately tile entity). Basically I want one player to be able to mark a set of blocks and then have that set of blocks be highlighted (for all players). Perhaps something a little like the black outline on the block in the centre of the screen, but persistant and on more than one block, or maybe some glow effect... I'm thinking that I can just render transparent a (very slightly larger) block over the top of the base block. The actual rendering style is to be decided, but I'm guessing it wouldn't affect the implementation too much.

 

I've had a look through this forum as best I can and I've also dug through this tutorial:

 

http://www.minecraftforge.net/wiki/Multiple_Pass_Render_Blocks

 

but I've not had much success so far.

 

Ideally I want to avoid modifying core Minecraft code, and keep all my code nicely isolated, so adding a new render pass doesn't seem like a good idea (for a number of reasons!). There seem to be a couple of pre/post block render Forge hooks but they seem to be commented out at the moment. I also don't think that would be the right place because if a block is not rendered in the transparent pass then it wouldn't get the hooks called that would allow me to overlay a glow.

 

I've seen that there's a ISimpleBlockRenderingHandler, but I think if I implemented that then it would only get called for non-vanilla blocks, whereas I really want to be able to be able to do this for all blocks without having to customise all the existing blocks.

 

Hopefully that's a decent enough description, could any one give me any pointers of things to look into? I'm happy to consider entirely different methods of achieving the same results by the way! but I am keen to keep the code as simple and non-invasive as possible. I just need a foot in the door, some places to put breakpoints and some code to read :)

 

Thanks in advance!

Posted

FYI After a few more searches I found this, which might be an option to try:

 

you could technicly make an invisible entity that has information about the width/height/length of the protected area and x, y,z  and use this entity to draw a big box that represents the limit of the area.

Posted

FYI After a few more searches I found this, which might be an option to try:

 

you could technicly make an invisible entity that has information about the width/height/length of the protected area and x, y,z  and use this entity to draw a big box that represents the limit of the area.

 

hey thats ME :D!!!!

 

but yeah thats probably the best way to go unless you feel like doing ASM....... no come to think of it if you want the OTHER players to see it, its the only way to go

how to debug 101:http://www.minecraftforge.net/wiki/Debug_101

-hydroflame, author of the forge revolution-

Posted

hey thats ME :D!!!!

 

:D

 

but yeah thats probably the best way to go unless you feel like doing ASM....... no come to think of it if you want the OTHER players to see it, its the only way to go

 

ASM? I did actually think another way might be to do some code injection to (for example) modify the WorldRenderer... but I think that's probably bordering on yuk ;-)

Posted

So I've got this kinda working for using entities to do this, but I'm tending away from this idea now. The 'highlighting' of the blocks is something that is going to change relatively infrequently (e.g. about as often as block creation/destruction) rather than every frame. I think it would be more efficient to have it as part of the block render list rather than an entity that is updated every frame.

 

Or am I misundertanding how the block render lists are built?

 

NB I've got no idea yet on how I'll achieve it!

Posted

minecraft makes 1 glDisplayList per chunk, but i dont think theres any event that is called when a display list is updated, so you might have to make one

how to debug 101:http://www.minecraftforge.net/wiki/Debug_101

-hydroflame, author of the forge revolution-

Posted

I've got something working, but it's not the least invasive thing ever!

 

I extended the BlocksRederer to be a BlockEffectRenderer. It's still responsible for rendering the blocks themselves, but it also has the option to render a BlockEffect for each block it handles.

 

I had to do this because the block effect might be in renderpass 1, but if the block only renders in renderpass 0 then it all goes wrong :)

 

So I needed to modify WorldRenderer to instantiate (and call) my BlockEffectRenderer, which was only around 5 lines of code that needed changing, but I might try and tweak it a bit more to clean it up even more.

Posted

Perhaps a bit of a different method:

 

There is a renderWorldLast event--called after other world rendering to allow you to render things in ...the world.

 

You would need to synch a list of the 'highlighted' blocks between server + clients (packets, basic synch stuff), but then could simply use the renderWorldLast event to directly render your highlights -- no need for entities and the overhead they bring, or trying to use block renderers.  Using the event, you could theoretically render...anything you wanted. It seems to work well with transparency and occlusion (I have it rendering large bounding boxes around block-selections as well, using semi-transparent lines).

 

(see https://github.com/shadowmage45/AncientWarfare/blob/master/AncientWarfare/src/shadowmage/ancient_warfare/client/render/AWRenderHelper.java#L201 for examples)

 

 

Posted

Perhaps a bit of a different method:

 

There is a renderWorldLast event--called after other world rendering to allow you to render things in ...the world.

 

Very interesting, let me dig into that a little...

Posted

There is a renderWorldLast event--called after other world rendering to allow you to render things in ...the world.

 

This is really useful stuff (and I'll definitely be using that hook) but for this particular use case the special effects on the blocks are relatively unchanging between frames rather than changing every frame; so for efficiencies sake I think it's better to bake this stuff into the render lists for the chunk rather than pay the per frame costs of rendering the effects.

 

Please correct me if I'm mistaken!

Posted

You may very well be correct about the per-frame costs.  The renderWorldLast method doesn't have an easy way to setup/call an optimized displayList, so it has to rebuild/recalculate per-frame.  I am by no means a rendering expert though, so others may have more accurate info/input on it.

 

Please keep us informed if you do find a better process to accomplish your goal, would be interested in hearing about it :)

Posted
I am by no means a rendering expert though, so others may have more accurate info/input on it.

*puts on glasses*

afaik there is no way to do that, for some reason mc uses displayList for 99% of the blocks then TileEntitySpecialRenderer for the other 1%, the thign that i hate is that there is no middle, you either need a TileEntity or you dont and cant use animation/render every frame .... :\ optifine has something for that but unfortunatelly that a mod in itself and now included in vanilla mc

how to debug 101:http://www.minecraftforge.net/wiki/Debug_101

-hydroflame, author of the forge revolution-

Posted

Please keep us informed if you do find a better process to accomplish your goal, would be interested in hearing about it :)

 

My best thinking at the moment is to do something like this in WorldRender:

 

                                    if (block != null)
                                    {
                                        if (l1 == 0 && block.hasTileEntity(chunkcache.getBlockMetadata(k2, i2, j2)))
                                        {
                                            TileEntity tileentity = chunkcache.getBlockTileEntity(k2, i2, j2);

                                            if (TileEntityRenderer.instance.hasSpecialRenderer(tileentity))
                                            {
                                                this.tileEntityRenderers.add(tileentity);
                                            }
                                        }

                                        int i3 = block.getRenderBlockPass();

                                        if (i3 > l1)
                                        {
                                            flag = true;
                                        }
                                        // !!! NEW: Slight change here !!!
                                        if (block.canRenderInPass(l1))
                                        {
                                            flag1 |= renderblocks.renderBlockByRenderType(block, k2, i2, j2);
                                        }
                                    }
                                     
                                    // !!! NEW !!!
                                    // Note that this can happen on air blocks (i.e. block == null)
                                    {
                                    	/*
                                         * to handle special effects for blocks
                                         */
                                        int i3 = ForgeHooksClient.getBlockEffectRenderPass(block, k2, i2, j2);

                                        if (i3 > l1)
                                        {
                                            flag = true;
                                        }
                                        if (i3 == l1)
                                        {
                                        	// This is the correct render pass for this block effect
                                        	flag1 |= ForgeHooksClient.renderBlockEffect(block, k2, i2, j2);
                                        }
                                    }
                                    // !!! END NEW !!!

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.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Announcements



×
×
  • Create New...

Important Information

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