Jump to content

Any way to store unique data per block placement?


Lycanus Darkbinder

Recommended Posts

Given that Minecraft only uses one instance of a particular Block class, it makes it difficult to save unique data each time a block is placed in the world.

 

I'm trying to save some data about a block (two booleans and an array of neighboring block IDs and metadata) when onBlockAdded() is called. Naturally this information can't simply be stored in a local variable because each time onBlockAdded() is called it overwrites the previous data.

 

Is there any storage mechanism besides metadata that allows us to save unique data about an instance of a block?

 

Thanks.

 

 

PS:

 

I know I can write lookup functions to accomplish the same as the boolean values but I figured it would be a performance hit to drill down into World() for some info when I can just look it up once and save it until the block is destroyed.

 

The array is used by a lookup function called WhichBlockChanged() which is called from onNeighborBlockChange() since this function oddly gives the block its own coordinates instead of those of the block that changed.

Link to comment
Share on other sites

Given that Minecraft only uses one instance of a particular Block class, it makes it difficult to save unique data each time a block is placed in the world.

 

I'm trying to save some data about a block (two booleans and an array of neighboring block IDs and metadata) when onBlockAdded() is called. Naturally this information can't simply be stored in a local variable because each time onBlockAdded() is called it overwrites the previous data.

 

Is there any storage mechanism besides metadata that allows us to save unique data about an instance of a block?

 

Thanks.

 

 

PS:

 

I know I can write lookup functions to accomplish the same as the boolean values but I figured it would be a performance hit to drill down into World() for some info when I can just look it up once and save it until the block is destroyed.

 

The array is used by a lookup function called WhichBlockChanged() which is called from onNeighborBlockChange() since this function oddly gives the block its own coordinates instead of those of the block that changed.

Link to comment
Share on other sites

Sounds like you want to make a tile entity.  Try the wiki page on it.

 

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

 

Interesting. I just came back to reply that I had figured it out by creating my own ArrayList to track the info I needed. From the link you provided it's similar to a TileEntity.

 

In case anyone is interested, here's my code. It can be used as a blueprint where all you need to do is create your own "FencePostInfo" class (or whatever).

 

 

I created a class called FencePostInfo that contains two booleans and an array of 6 integers. I then store this in an ArrayList in my FencePost class and use accessor functions to add / remove instances of FencePostInfo.

 

    private static ArrayList<FencePostInfo> infList = new ArrayList<FencePostInfo>();
    private static ArrayList<String> infListIdx = new ArrayList<String>();

 

infListIdx is used as a lookup table for indices into infList by converting the xyz of the block into a string and using infListIdx.indexOf().

 

    private int addToInfList(int x, int y, int z)
    {
        // Adds an instance of FencePostInfo to the list
        //  and tracks the lookup key using the block's coordinates
        
        // Initialize private info for this block
        FencePostInfo i = new FencePostInfo (this.blockID, x, y, z);
        infList.add(i);
        infListIdx.add(coordsToString(x, y, z));

        return getInfListIdx(x, y, z); // return the index of our new entry
    }

    private void removeFromInfList(int x, int y, int z)
    {
        // Removes an instance of FencePostInfo from the list
        //  and delete it's index tracking entry

        int i = getInfListIdx(x, y, z);
        
        // If object doesn't exist, i = -1
        if (i > -1)
        {
            FencePostInfo ri = infList.get(i);
        
            if (ri != null)
            {
                infList.remove(i); // remove the instance
                infListIdx.remove(i); // remove the index tracker
                ri = null;
            }
        }
    }
    
    private FencePostInfo getInfo(int x, int y, int z)
    {
        // Allows access to a FencePostInfo instance

        int i = this.getInfListIdx(x, y, z);
        
        if (i == -1)
        {
            // instance didn't exist, make one so we don't crash
            addToInfList(x, y, z);
            i = this.getInfListIdx(x, y, z);
        }
        
        return infList.get(i);
    }

    private int getInfListIdx(int x, int y, int z)
    {
        // Returns the index of the FencePostInfo represented
        //  by the coordinate string so we can retrieve it from infList

        return infListIdx.indexOf(coordsToString(x, y, z));
    }

    private String coordsToString(int x, int y, int z)
    {
        // Converts a coordinate to a string
        //  in the format xN, yN, zN
        
        return "x" + x + "y" + y + "z" + z;
    }

 

 

I can then use it anywhere in my class like this:

 

boolean isBottom = getInfo(par1, par2, par3).isOnBottom()

 

It has quite a bit of flexibility. For example, I can add any fields and methods to FencePostInfo that I want such as a unique GUID for the block using Math.Random() and then use that info to make decisions when the block is destroyed, etc.

 

Note: The current implementation does not save ArrayList...it only works if you only "quit to title" and don't close Minecraft. Need to implement saving this to disk (it's more lightweight than a TileEntity).

Link to comment
Share on other sites

Sounds like you want to make a tile entity.  Try the wiki page on it.

 

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

 

Interesting. I just came back to reply that I had figured it out by creating my own ArrayList to track the info I needed. From the link you provided it's similar to a TileEntity.

 

In case anyone is interested, here's my code. It can be used as a blueprint where all you need to do is create your own "FencePostInfo" class (or whatever).

 

 

I created a class called FencePostInfo that contains two booleans and an array of 6 integers. I then store this in an ArrayList in my FencePost class and use accessor functions to add / remove instances of FencePostInfo.

 

    private static ArrayList<FencePostInfo> infList = new ArrayList<FencePostInfo>();
    private static ArrayList<String> infListIdx = new ArrayList<String>();

 

infListIdx is used as a lookup table for indices into infList by converting the xyz of the block into a string and using infListIdx.indexOf().

 

    private int addToInfList(int x, int y, int z)
    {
        // Adds an instance of FencePostInfo to the list
        //  and tracks the lookup key using the block's coordinates
        
        // Initialize private info for this block
        FencePostInfo i = new FencePostInfo (this.blockID, x, y, z);
        infList.add(i);
        infListIdx.add(coordsToString(x, y, z));

        return getInfListIdx(x, y, z); // return the index of our new entry
    }

    private void removeFromInfList(int x, int y, int z)
    {
        // Removes an instance of FencePostInfo from the list
        //  and delete it's index tracking entry

        int i = getInfListIdx(x, y, z);
        
        // If object doesn't exist, i = -1
        if (i > -1)
        {
            FencePostInfo ri = infList.get(i);
        
            if (ri != null)
            {
                infList.remove(i); // remove the instance
                infListIdx.remove(i); // remove the index tracker
                ri = null;
            }
        }
    }
    
    private FencePostInfo getInfo(int x, int y, int z)
    {
        // Allows access to a FencePostInfo instance

        int i = this.getInfListIdx(x, y, z);
        
        if (i == -1)
        {
            // instance didn't exist, make one so we don't crash
            addToInfList(x, y, z);
            i = this.getInfListIdx(x, y, z);
        }
        
        return infList.get(i);
    }

    private int getInfListIdx(int x, int y, int z)
    {
        // Returns the index of the FencePostInfo represented
        //  by the coordinate string so we can retrieve it from infList

        return infListIdx.indexOf(coordsToString(x, y, z));
    }

    private String coordsToString(int x, int y, int z)
    {
        // Converts a coordinate to a string
        //  in the format xN, yN, zN
        
        return "x" + x + "y" + y + "z" + z;
    }

 

 

I can then use it anywhere in my class like this:

 

boolean isBottom = getInfo(par1, par2, par3).isOnBottom()

 

It has quite a bit of flexibility. For example, I can add any fields and methods to FencePostInfo that I want such as a unique GUID for the block using Math.Random() and then use that info to make decisions when the block is destroyed, etc.

 

Note: The current implementation does not save ArrayList...it only works if you only "quit to title" and don't close Minecraft. Need to implement saving this to disk (it's more lightweight than a TileEntity).

Link to comment
Share on other sites

Note: The current implementation does not save ArrayList...it only works if you only "quit to title" and don't close Minecraft. Need to implement saving this to disk.

 

This is all handled by the Tile Entity.  I know it's a pain to implement, but it means it gets saved with the world file. 

Link to comment
Share on other sites

Note: The current implementation does not save ArrayList...it only works if you only "quit to title" and don't close Minecraft. Need to implement saving this to disk.

 

This is all handled by the Tile Entity.  I know it's a pain to implement, but it means it gets saved with the world file. 

Link to comment
Share on other sites

Your supposed 'saving of resources' is flawed. if someone where to build a massive fence based structure and then those chunks where unloaded, rinse lather repeat, you would leave the print of all of those blocks in the system(the more you put, the slower saving and loading gets...), unless you used system resources to load and offload the values as needed, basically you either suffer one way or another... so tile entity is your best bet.

I think its my java of the variables.

Link to comment
Share on other sites

Your supposed 'saving of resources' is flawed. if someone where to build a massive fence based structure and then those chunks where unloaded, rinse lather repeat, you would leave the print of all of those blocks in the system(the more you put, the slower saving and loading gets...), unless you used system resources to load and offload the values as needed, basically you either suffer one way or another... so tile entity is your best bet.

I think its my java of the variables.

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.