Jump to content

Tile Entities for Metadata > 15?


Reika

Recommended Posts

I am developing a mod that contains many cases where there are many "variations" on a block, each largely the same but with slightly different properties. Because I use metadata to control direction, or there are often more than 16 variations on these blocks, default metadata is not an option. I could just use different IDs, but that would be poor form.

 

I have seen, when using TMI or NEI, that big mods like BuildCraft and RedPower seem to use damage values/metadata much larger than 15, often in the thousands. (For example, look to RedPower wires). I assume this is done with Tile Entities.

My question is how. No tutorial seems to exist on it, and one time I got a response to a similar question, the response was a rather rude "figure it out yourself".

 

I am somewhat familiar with Tile Entities, as I already use them to perform the functions of the blocks in question, but from what I understand, Tile Entities are created on block placement in the world, and as such how one can "craft" one and have them be functionally separate items in the inventory (again, like RedPower wires) is beyond me. Help?

 

Before anyone links me to Havvy's or Helfull's tutorials (which I have used), please note that they address a different problem - how to use the metadata to have different block types in the first place. What I need is something which functions like metadata without the 0-15 limit.

 

I have been suggested ItemBlocks before, but how will that help with this, having 1 Block ID contain > 16 block types?

Or will the ItemBlock also let me set a variable somewhere inside the block instance which can then be checked?

(That is, if I, say, declare "private int type" inside Block.java, can the ItemBlock then execute something like Block.type = 2 @ the placed coordinates?)

 

Also of note: I am using Minecraft 1.2.5, though in my experience the code is only different for a select few things at "mod initialization".

 

I apologize if this has been asked before - I tried searching, but at > 90s to load a page, it is extremely cumbersome.

 

EDIT: I forgot to mention: I looked at the BuildCraft source in attempt to learn how it accomplished the task; The result was akin to trying to learn basic calculus from a graduate-studies quantum mechanics textbook - that is, far beyond my understanding.

Link to comment
Share on other sites

I know this is kind of a side note for you but, uhm why are you modding for 1.2.5?

The new minecraft code post 1.3 and the new forge updates are massive improvements for modder's :)

The creators of the mods you are mentioning which are doing this are a part of the forge development team, creating hooks and logic to make the creation of fantastic mods like theirs possible and easier, while still being compitable with other mods!

Updating to the newest versions gives you quite an improvement :)

 

With that being said, If you want to learn how to do like it's done inn BC and RP you will need to study the code and see how it actually works, maybe you could download the repository as an eclipse project from git and look at it? It's easier when you can navigate trough the code inn an IDE :)

Yes there will be stuff with heavy math and things you don't understand but if you look at how the hard stuff is used, and read up on the specific math via internet(i.e. khan) you will probably be able to understand how it's done if not yet why.

 

But on the other hand depending on how many variations of the blocks you have and how different they are you could perhaps get away by using inheritance and extend from some base block which has mostly the same code as the 16+ variations you have?

If you guys dont get it.. then well ya.. try harder...

Link to comment
Share on other sites

I am using 1.2.5 since that is what I know, plus I have a few worlds locked in that version (dependent on old mods) and would like to use this mod there. I can always "retrofit" later.

 

I am afraid you did not understand my simile for what happened when I tried looking at the BuildCraft code. It is not math that is a problem, it is the fact that the code is exceedingly complex and nuanced, and not at all easy to follow. This is compounded by the fact that I am not at all a Java expert; I started learning modding in earnest a week ago.

 

As for using java's extend and inherit properties, that does not solve my problem. I need the Tile Entities to be able to distinguish these blocks from each other ingame, without taking up 16+ IDs to do so.

 

 

I acknowledge that I am being a bit vague about what exactly I am trying to make with the mod, but I do that because the last time I said it explicitly (with another mod idea), someone else took the idea and released it as their own.

Link to comment
Share on other sites

Okay I do understand your reasons for being vague.

And thank you for clarifying what you meant earlier.

 

If you are sticking to 1.2.5 I can understand why 16+ ID's is a problem, since there is such a small limit on how many block ID's one can have. I'm sadly not capable myself to provide an adequate solution to your problem, but perhaps someone else will be able to help you solve it when they have understood what you need :)

 

I remember that RP's massive use of sub blocks made quite a lot of fuzz on the modding forums for minecraft, and there was quite a few threads asking the same questions. Perhaps you can find help in old threads here or on the mcboards. Either that or wait to see if someone comes along which knows how to solve the blockIds inn 1.2.5 :)

Either way, good luck to you and have fun coding :D

 

 

 

If you guys dont get it.. then well ya.. try harder...

Link to comment
Share on other sites

Either that or wait to see if someone comes along which knows how to solve the blockIds inn 1.2.5 :)

The problem is, though, by the time any such person comes along, this thread will be long since buried, and I abhor the idea of bumping it (which is probably against the rules anyways).

 

I have tried searching, but it is agonizingly slow (I have a poor internet connection), and what searching I did do found nothing relevant. Simply including "metadata" or "Tile Entity" in the terms nets thousands of generic results.

Link to comment
Share on other sites

first:you can make block ids with metadata 15 so blockid a 1-15, blockid b 1-15

 

second:you can look at the code inside of a tileentitychest or furnace to check this, the only methods you need in your case is the write and read to nbt... then you do onblockplaced check if it is whatever block and then set the damage in the tile entity to your block and display texture based on that.

 

third:items can store a damage value of much over 15 so many mods will use items that on place turn into blocks eg in vanilla they use seeds instead of cropsbase and on right click world.setblockid and remove an item

The Korecraft Mod

Link to comment
Share on other sites

first:you can make block ids with metadata 15 so blockid a 1-15, blockid b 1-15

That would still be rather sloppy programming.

 

second:you can look at the code inside of a tileentitychest or furnace to check this, the only methods you need in your case is the write and read to nbt... then you do onblockplaced check if it is whatever block and then set the damage in the tile entity to your block and display texture based on that.

Please elaborate. I have dug into those tile entities before, but not seen anything related to this.

Also worth noting is that these blocks are going to be far more different than simply different textures - think along the lines of RedPower logic gates or subblocks.

 

third:items can store a damage value of much over 15 so many mods will use items that on place turn into blocks eg in vanilla they use seeds instead of cropsbase and on right click world.setblockid and remove an item

Yes, but that does not solve the problem of other Tile Entities being able to distinguish these blocks from each other ingame.

Link to comment
Share on other sites

An ItemStack can have an NBTTagCompound attached to it, where you can store the information that needs to go into your tile entity when the block is placed.

 

Getting that to actually happen is a little bit tricky. It looks like one way would be to register your own subclass of ItemBlock to go with your block, and override the placeBlockAt method. That gives you access to the ItemStack being placed, the world and the coordinates in the world, so after calling super.placeBlockAt, you can retrieve the tile entity and set it up from the NBTagCompound of the stack.

 

You'll also need a custom item renderer for your ItemBlock subclass, so that you can render the block in the inventory correctly according to the NBTTagCompound. A normal block renderer won't work, because it doesn't get passed the ItemStack when rendering an inventory block.

 

You might like to look at the source of Greg's Blocks, where I do something like this (although I used a slightly different and more kludgy way of doing the placement):

 

http://www.cosc.canterbury.ac.nz/greg.ewing/minecraft/mods/GregsBlocks/

 

The relevant classes to study would be BlockShape, TileEntityShape, ItemBlockShape and ItemBlockShapeRenderer.

 

You're welcome to ask me, either here or by email, if you have any questions about it.

 

[email protected]

Link to comment
Share on other sites

Now that definitely sounds like an interesting, feasible, and effective idea; I will try that, and will post my results soon.

One side question: Will the fact that all of these separate block types share the same TileEntity class (differing only in internal control variables) be a stumbling block (no pun intended)?

Link to comment
Share on other sites

If you mean there's going to be hiccups down the road for all these tileents then it takes a LOT of them all working at once to get lag, (you can have a crapton of pistons working overtime and the only lag you get is from the sound engine not real lag) so your fine in that respect.

 

If you mean so many using the same class will have problems, that's not an issue either as each tile entity is a new instance (which is why this works in the first place) so unless you start using static variables you'll be fine.

 

What WILL be a problem is that tile entities stop rendering past a certain distance. Your going to have to override that distance or your blocks will just dissapear relatively close to view. (I don't know exactly how to do it with tileents but I do know it has to do with how it's registered - Forge has a method to register Mod Entities, that might be what you want)

Link to comment
Share on other sites

My concern was borne from the fact he says "retrieve the tile entity", which calls to my mind the this.worldObj.getBlockTileEntity() function. This would, in the case of using the same class for each one, always return the same result, resulting in no ability to differentiate them. But combining his idea with the previous poster's idea about NBT tags and it may well work.

 

As for issues with lag, if a computer can Minecraft decently well (> 30 fps), then this mod should not have a drastic impact. Mine, though stronger than most, takes no performance hit at all (so far). These Tile Entities are not likely to exist in too large of quantities (as they will be expensive and for a specific purpose, not "decorative"/"world composition" like sand/dirt/stone/wood/bricks/etc).

 

As for the rendering distance, thank you for the heads-up. While this is not a severe issue - if I do not find a solution I can still release the mod and put the issue on the "to do" list without impacting the mod's usability - it is good to be aware of.

Link to comment
Share on other sites

Reika, for whatever it's worth. I admire your commitment and drive for your project. Hope it works out good and I can't wait to see what kind of stuff you will end up creating on your coding journey :)

width=23 height=23http://i257.photobucket.com/albums/hh240/RadicalOne/AnnunakiSmileys/Vector_Smiley.png[/img]

I do hope it succeeds as well. My fear is that it will, like 99% of mods, maybe get a few downloads then get forgotten forever. So I am trying to delay that as long as I can (ideally to infinity) by making this mod as big, advanced, and "still-to-get-better" as possible within my abilities and my ideas. Not a usual approach for someone's first mod, that is for certain...

Link to comment
Share on other sites

Perhaps, yes.

 

Back on topic, I tried the ItemBlock approach and it works. Basically, the itemblock places the block at the coordinates, then sets an internal tile entity variable, which is used by the code. Here is the code for my "dummy/test" block to do it:

(No, my source is not normally this messy. I just did not care to keep this tidy, as it is a test.)

 

ItemBlock:

public boolean onItemUse(ItemStack par1ItemStack, EntityPlayer par2EntityPlayer, World par3World,
	int par4, int par5, int par6, int par7)
{
if (par3World.getBlockId(par4, par5, par6) != Block.snow.blockID &&
par3World.getBlockId(par4, par5, par6) != Block.waterMoving.blockID &&
par3World.getBlockId(par4, par5, par6) != Block.lavaStill.blockID &&
par3World.getBlockId(par4, par5, par6) != Block.lavaMoving.blockID
&& par3World.getBlockId(par4, par5, par6) != Block.waterStill.blockID)
    {
        if (par7 == 0)
            --par5;
        if (par7 == 1)
            ++par5;
        if (par7 == 2)
            --par6;
        if (par7 == 3)
            ++par6;
        if (par7 == 4)
            --par4;
        if (par7 == 5)
            ++par4;
        if (!par3World.isAirBlock(par4, par5, par6) && 
par3World.getBlockMaterial(par4, par5, par6) != Material.water &&
par3World.getBlockMaterial(par4, par5, par6) != Material.lava)
            return false;
    }
    if (!par2EntityPlayer.canPlayerEdit(par4, par5, par6))
    {
        return false;
    }
    else
    {
    	if (!par2EntityPlayer.capabilities.isCreativeMode)
           --par1ItemStack.stackSize;
           par3World.setBlockWithNotify(par4, par5, par6, mod_LearningMultiblocks.testblock.blockID);
		TileEntityTest te = (TileEntityTest)par3World.getBlockTileEntity(par4, par5, par6);
	if (te != null) {
		par3World.playSoundEffect(par4+0.5, par5+0.5, par6+0.5, "step.stone", 1F, 1F);
		te.type = par5-60;
	}
	return true;
    }
}

Tile Entity:

package net.minecraft.src;


public class TileEntityTest extends TileEntity {

public int type;

public void updateEntity() {
	//ModLoader.getMinecraftInstance().ingameGUI.addChatMessage(String.format("%d", this.type));
}

    /**
     * Writes a tile entity to NBT.
     */
    public void writeToNBT(NBTTagCompound par1NBTTagCompound)
    {
        super.writeToNBT(par1NBTTagCompound);
        par1NBTTagCompound.setInteger("type", this.type);
    }

    /**
     * Reads a tile entity from NBT.
     */
    public void readFromNBT(NBTTagCompound par1NBTTagCompound)
    {
        super.readFromNBT(par1NBTTagCompound);
        this.type = par1NBTTagCompound.getInteger("type");
    }

}

Link to comment
Share on other sites

What WILL be a problem is that tile entities stop rendering past a certain distance.

 

Only if you use a TileEntitySpecialRenderer to do the rendering. You don't have to do that -- you can use an ordinary block renderer that uses information from the tile entity to decide what to draw.

Link to comment
Share on other sites

What WILL be a problem is that tile entities stop rendering past a certain distance.

Only if you use a TileEntitySpecialRenderer to do the rendering. You don't have to do that -- you can use an ordinary block renderer that uses information from the tile entity to decide what to draw.

Given that I plan to use custom models - an issue for another time; function is going to be completed first - then I may well need to worry about that.

Link to comment
Share on other sites

It would be possible to render a model for a block via block rendering hooks, if only for one flaw, which is if you try and override the texture there then blocks rendered afterwards take on your texture in that chunk. it's quite weird.

 

One way around this would be to save what texture is binded to openGL and then re-load it after you finish rendering the model, but that doesn't work perfectly all the time.

 

And I never thought to just to use the tile entity as data, and not use a special renderer. Thanks for the tip!

Link to comment
Share on other sites

Well, I have solved my original problem, but another related one has come up.

Is there any way to fetch the Tile Entity in a block file without having been passed the block's x,y,z?

 

For example, if I want a block that actually has 24 different states, each of which have a different texture on one side of the block, how can I get the Tile Entity into getBlockTextureFromSideAndMetadata(int s, int dmg)? Simply using TileEntity**** tile = (TileEntity****)world.getBlockTileEntity does not work, as there is no way for this function to determine the coordinates of its "parent" block, or the world it is in. There is a "getBlockTileEntity" function in Block.java I can access, but it "will fall back to BlockContainer.getBlockEntity if this block is a BlockContainer", in the words of the documentation, and thus will return a new TileEntity, not the existing one.

 

Now, I could of course just declare three integer variables x,y,z and one world variable and set them in onBlockAdded, but can I do it without creating additional variables (and thus more resources)?

 

EDIT: No, even that does not work; it returns null every single time.

Link to comment
Share on other sites

Use public int getBlockTexture(IBlockAccess blockAccess, int x, int y, int z, int side) in the Block file.

blockAccess is basically a World. It will give you the TileEntity.

That appears to mean I have to fetch the metadata in the TileEntity and pass it back to the block, which is rather awkward, but that should work, yes.

Link to comment
Share on other sites

On a related note, is it feasible to combine two totally separate blocks, each with their own Tile Entities, containers, etc, into one ID, keeping the distinct tile entity classes?

Sure. There is a metadata-sensitive version of createNewTileEntity in the Block class, added by forge.

And what if the metadata is used to control something totally different, like block direction, and the different "types" of Tile Entity would be determined from a variable in the "parent" tile Entity? Still possible?

 

That is, could I have one class applicable for all the variations of the block, and depending on the state of a variable within it, another tile entity of another type?

Link to comment
Share on other sites

You coild do something like this:

 

TileEntityParent extends TileEntity{

// some methods and variables you want for all your TE's ie:

}

 

And then have your TE's extend TileEntityParent instead of Te.

Like EE3 has done. But thats not the question or reason for talking about parentTE's.

 

Hmm I guess you could have a TE which returns different TE's when called upon depending the value of a variable?

 

 

 

If you guys dont get it.. then well ya.. try harder...

Link to comment
Share on other sites

And what if the metadata is used to control something totally different, like block direction, and the different "types" of Tile Entity would be determined from a variable in the "parent" tile Entity?

 

Your TileEntity can have a field referring to another object, and you can put different subclasses there depending on metadata or other information in the TileEntity.

 

The sub-object doesn't have to extend TileEntity, btw, it can be anything you want.

Link to comment
Share on other sites

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.