Jump to content

Best Way to Give Blocks "Health"


1SDAN

Recommended Posts

I would like to add "health" to all blocks in the game, where breaking a block lowers it's "health", drops its drops but does not remove it from the world unless the "health" is now at or lower than zero.

 

I am able to add a event listener to replace the block when broken while still dropping its drops, but I am having trouble figuring out what would be the best method of adding a "health" value to all blocks in the game.

 

What do you suggest I do?

Link to comment
Share on other sites

All blocks in the game?

You won't be able to do this easily. Add it to your own blocks? Fairly easily. I did this with my own ores.

Apparently I'm a complete and utter jerk and come to this forum just like to make fun of people, be confrontational, and make your personal life miserable.  If you think this is the case, JUST REPORT ME.  Otherwise you're just going to get reported when you reply to my posts and point it out, because odds are, I was trying to be nice.

 

Exception: If you do not understand Java, I WILL NOT HELP YOU and your thread will get locked.

 

DO NOT PM ME WITH PROBLEMS. No help will be given.

Link to comment
Share on other sites

3 hours ago, 1SDAN said:

What do you suggest I do?

If you are dead set on this idea you will have to create a BlockPos to int Map kinda thing and save it to the world yourself.

VANILLA MINECRAFT CLASSES ARE THE BEST RESOURCES WHEN MODDING

I will be posting 1.15.2 modding tutorials on this channel. If you want to be notified of it do the normal YouTube stuff like subscribing, ect.

Forge and vanilla BlockState generator.

Link to comment
Share on other sites

1 hour ago, Animefan8888 said:

If you are dead set on this idea you will have to create a BlockPos to int Map kinda thing and save it to the world yourself.

Is there no way to store it as a variable within blocks?

3 hours ago, Draco18s said:

All blocks in the game?

You won't be able to do this easily. Add it to your own blocks? Fairly easily. I did this with my own ores.

I assume it's a limitation in Minecraft's implementation of blocks?

Edited by 1SDAN
Link to comment
Share on other sites

1 minute ago, diesieben07 said:

Block objects are singletons, they are more like block types. An actual placed block in the world is represented by a number in a big array, for efficiency. If additional data is required for a location, the block type must explicitly be configured to have a tile entity, this cannot be done for blocks that "are not yours" or after the fact and it comes with performance implications, which is why it is an opt-in thing.

 

You will need to use a capability attached to Chunk to store this additional data.

Thank you very much.

Link to comment
Share on other sites

4 hours ago, 1SDAN said:

Is there no way to store it as a variable within blocks?

No, you cannot. 

VANILLA MINECRAFT CLASSES ARE THE BEST RESOURCES WHEN MODDING

I will be posting 1.15.2 modding tutorials on this channel. If you want to be notified of it do the normal YouTube stuff like subscribing, ect.

Forge and vanilla BlockState generator.

Link to comment
Share on other sites

On 8/31/2018 at 5:18 PM, diesieben07 said:

Block objects are singletons, they are more like block types. An actual placed block in the world is represented by a number in a big array, for efficiency. If additional data is required for a location, the block type must explicitly be configured to have a tile entity, this cannot be done for blocks that "are not yours" or after the fact and it comes with performance implications, which is why it is an opt-in thing.

 

You will need to use a capability attached to Chunk to store this additional data.

Am I correct in that this means I will have to create a 3D array in order to store per-block values?

Link to comment
Share on other sites

8 minutes ago, 1SDAN said:

Am I correct in that this means I will have to create a 3D array in order to store per-block values?

No, you could create a Map<BlockPos, Float/Integer> which will map a x,y,z to a health value.

VANILLA MINECRAFT CLASSES ARE THE BEST RESOURCES WHEN MODDING

I will be posting 1.15.2 modding tutorials on this channel. If you want to be notified of it do the normal YouTube stuff like subscribing, ect.

Forge and vanilla BlockState generator.

Link to comment
Share on other sites

8 minutes ago, Animefan8888 said:

No, you could create a Map<BlockPos, Float/Integer> which will map a x,y,z to a health value.

If my understanding of Chunk Capabilities (based on the example mod) is correct, I need an IStorage, which requires the use of an NBT tag matching the type of the variable. However there's no NBTTagMap class. Did I do something wrong? Must I make my own?

Link to comment
Share on other sites

1 minute ago, 1SDAN said:

Did I do something wrong?

No

 

1 minute ago, 1SDAN said:

Must I make my own?

No, use the default NBT stuff, you can convert the BlockPos to a string and use that as the key for the health value, either by directly changing the xyz to some string and parsing it, or by converting it to a long via BlockPos#toLong and converting that to a string.

VANILLA MINECRAFT CLASSES ARE THE BEST RESOURCES WHEN MODDING

I will be posting 1.15.2 modding tutorials on this channel. If you want to be notified of it do the normal YouTube stuff like subscribing, ect.

Forge and vanilla BlockState generator.

Link to comment
Share on other sites

5 minutes ago, 1SDAN said:

NBT tag matching the type of the variable

Use an NBTTagCompound or an NBTTagList

VANILLA MINECRAFT CLASSES ARE THE BEST RESOURCES WHEN MODDING

I will be posting 1.15.2 modding tutorials on this channel. If you want to be notified of it do the normal YouTube stuff like subscribing, ect.

Forge and vanilla BlockState generator.

Link to comment
Share on other sites

40 minutes ago, Animefan8888 said:

Use an NBTTagCompound or an NBTTagList

I'm having trouble finding a method of iterating through an NBTTagCompound. It seems like I'm finding this a lot more difficult than it should be. I'm trying to use it in the following code:

public static class QubHealthStorage implements Capability.IStorage<IQubHealth>
    {
        @Nullable
        @Override
        public NBTBase writeNBT(Capability<IQubHealth> capability, IQubHealth instance, EnumFacing side) {
            return new NBTTagInt(instance.get());
        }
        @Override
        public void readNBT(Capability<IQubHealth> capability, IQubHealth instance, EnumFacing side, NBTBase nbt) {
            if (nbt instanceof NBTTagInt)
            {
                // The state is being loaded and not updated. We set the value silently to avoid unnecessary dirty chunks
                instance.set(((NBTTagInt) nbt).getInt(), false);
            }
        }
    }

 

That's the int implementation.

 

This is what I have in my current Map implementation

public static class QubHealthStorage implements Capability.IStorage<IQubHealth>
    {
        @Nullable
        @Override
        public NBTBase writeNBT(Capability<IQubHealth> capability, IQubHealth instance, EnumFacing side) {
            NBTTagCompound compound = new NBTTagCompound();
        	for (Entry<BlockPos, Integer> entry : instance.get().entrySet())
            {
            	compound.setInteger(entry.getKey().toString(), entry.getValue());
            }
            return compound;
        }
        @Override
        public void readNBT(Capability<IQubHealth> capability, IQubHealth instance, EnumFacing side, NBTBase nbt) {
            if (nbt instanceof NBTTagCompound)
            {
            	//iterate through compound and set values
            }
        }
    }
3 minutes ago, diesieben07 said:

I don't recommend using a Map<BlockPos,Float>, especially if you plan on giving this property to a lot of blocks.

Since you are storing positions per chunk (x and z 0 through 15, y 0 through 255), you can easily derive a single short for the position of a block in this chunk:

short uniqueKey = y << 8 | x << 4 | z

Then throw a Short2FloatMap on it and you should have something quite workable.

Seems like it'll end up being a lot less hassle, thanks.

Edited by 1SDAN
Link to comment
Share on other sites

2 minutes ago, 1SDAN said:

This is what I have in my current Map implementation

NBTTagCompound#getKeySet OR you could use an NBTTagList which may be easier.

Edited by Animefan8888

VANILLA MINECRAFT CLASSES ARE THE BEST RESOURCES WHEN MODDING

I will be posting 1.15.2 modding tutorials on this channel. If you want to be notified of it do the normal YouTube stuff like subscribing, ect.

Forge and vanilla BlockState generator.

Link to comment
Share on other sites

27 minutes ago, diesieben07 said:

I don't recommend using a Map<BlockPos,Float>, especially if you plan on giving this property to a lot of blocks.

Since you are storing positions per chunk (x and z 0 through 15, y 0 through 255), you can easily derive a single short for the position of a block in this chunk:

short uniqueKey = y << 8 | x << 4 | z

Then throw a Short2FloatMap on it and you should have something quite workable.

Your comment is a bit vague, are you saying I should use a Map<Short,Int> or a series of Longs/Strings/Shorts that when combined contain 16x256x16 X digit integers?

Edited by 1SDAN
Link to comment
Share on other sites

8 minutes ago, 1SDAN said:

Your comment is a bit vague, are you saying I should use a Map<Short,Int> or a series of Longs/Strings/Shorts that when combined contain 16x256x16 X digit integers?

He means a Map<Short, Float/Integer>

VANILLA MINECRAFT CLASSES ARE THE BEST RESOURCES WHEN MODDING

I will be posting 1.15.2 modding tutorials on this channel. If you want to be notified of it do the normal YouTube stuff like subscribing, ect.

Forge and vanilla BlockState generator.

Link to comment
Share on other sites

As diesieben07 is pointing out, performance is key for such an implementation. You need to understand the performance implications of the various collections and the iterations thereof.

 

One thing that might help performance -- I think you probably only need to store information on blocks that have been interacted with. So potentially your map could be a lot smaller than containing all blockpos positions in the chunk, with the assumption that any block not in the map is full health. 

Check out my tutorials here: http://jabelarminecraft.blogspot.com/

Link to comment
Share on other sites

3 hours ago, jabelar said:

As diesieben07 is pointing out, performance is key for such an implementation. You need to understand the performance implications of the various collections and the iterations thereof.

 

One thing that might help performance -- I think you probably only need to store information on blocks that have been interacted with. So potentially your map could be a lot smaller than containing all blockpos positions in the chunk, with the assumption that any block not in the map is full health. 

Funny enough, this is the exact implementation I went with.

4 hours ago, diesieben07 said:

No, I specifically mean to use the Fastutil one, which will not incur the boxing overhead.

Since starting this thread I've moved from Short, Integer maps to Short, Integer[] maps, does fastutil support something like this? I'm looking at the shorts package and can't find anything of the like.

Edited by 1SDAN
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.