Posted August 31, 20187 yr 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?
August 31, 20187 yr 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.
August 31, 20187 yr 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.
August 31, 20187 yr Author 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 August 31, 20187 yr by 1SDAN
August 31, 20187 yr Author 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.
September 1, 20187 yr 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.
September 3, 20187 yr Author 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?
September 3, 20187 yr 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.
September 3, 20187 yr Author 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?
September 3, 20187 yr 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.
September 3, 20187 yr 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.
September 3, 20187 yr Author 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 September 3, 20187 yr by 1SDAN
September 3, 20187 yr 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 September 3, 20187 yr 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.
September 3, 20187 yr Author 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 September 3, 20187 yr by 1SDAN
September 3, 20187 yr 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.
September 4, 20187 yr Author I just noticed I typed String instead of Integer. (Short/String/Long instead of Short/Integer/Long)... *faceplam*
September 4, 20187 yr 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/
September 4, 20187 yr Author 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 September 4, 20187 yr by 1SDAN
September 4, 20187 yr Author 2 minutes ago, diesieben07 said: Never, ever use Integer[], it's terrible. Use int[]. int[] is just an Object, so you can use Short2ReferenceMap<int[]>. Understood. I would normally have used int[] but animefan advised using Float or Integer so I was misled to thinking it'd be better.
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.