Jump to content

[1.7.2] Would this work? Some questions about modding


KGS

Recommended Posts

I'm planning on implementing some new features into my mod and for that I need more metadata per block. Only about a byte per block but I might end up using more than that for other things later.

 

I figured out a way to do it which some people would probably consider extremely hacky. I'm pretty certain it will work in singleplayer, but I don't know much about the multiplayer aspects of MC modding so I come here to ask the question... Would this work? :D

 

I have a hash table where the value is an int or byte, and the key is a tuple of 4 elements. Block coordinates x, y, z and dimension id. When I want to insert metadata at some location I create a tuple and put the relevant value at that location in the hash table. When I want to read it I can do the same. I save this hash table using the NBT.

 

Known issues:

*If a block using this metadata scheme is destroyed I must remember to erase the metadata (though this is not an important issue as only my own blocks will read from here)

*If a block is placed in some other dimension such as one created by another mod like Dimensional Doors, then when that dimension is "destroyed" I need to have the hash table erase all entries with data that is keyed to that world. Is there some way to detect when that happens and deal with it easily?

*How would this behave in practice in multiplayer? If there are any problems, how would I remedy them?

Link to comment
Share on other sites

I'm planning on implementing some new features into my mod and for that I need more metadata per block. Only about a byte per block but I might end up using more than that for other things later.

 

I have a hash table where the value is an int or byte, and the key is a tuple of 4 elements. Block coordinates x, y, z and dimension id. When I want to insert metadata at some location I create a tuple and put the relevant value at that location in the hash table. When I want to read it I can do the same. I save this hash table using the NBT.

 

I think you'll find the real issues are memory and speed.

How long does it take to generate a hash ?

How long does it take to retrieve a set of values (from the hash table) for a single block ?

How many blocks in world ?

How much memory total for the number of blocks ?

 

Even if you have a single one of your blocks visible, you need to have the data for all of them in memory.

Also where do you plan to store the data itself ?

 

Using a TileEntity is a much simpler method, especially if you need to add extra values for each block.

Link to comment
Share on other sites

Make another instance of the block.

Just using up one id space more in the world save isn't much.

 

As for your issues, since you would save into the world nbt (which is organized per dimension), you wouldn't have to worry about removing it if the dimension is removed. Automatically goes with it.

Link to comment
Share on other sites

Hi

 

I agree with GotoLink.  If you need a byte of storage per block, just define 16 new blocks which all inherit from the same base.  4 bits of metadata and 4 bits of block ID and you're there.  Far more robust than trying to code up something yourself.

 

Your idea sounds like it might work with a lot of effort; I think the "proper" way to do it would be to modify the chunk data storage to add an extra metadata array, and let vanilla handle the hard work of storing and reloading the chunk data.  There was a bloke asking about this on the forum a couple of weeks ago and he seemed to be pretty far advanced, perhaps he'd have some gems of wisdom.

 

Multiplayer becomes harder again because you have to synchronise the data stored on the server with the client.  It can be done but requires a fair bit of effort.

 

-TGG

 

 

Link to comment
Share on other sites

I've done something similar to this, in a currently developing mod (waiting on my texturer to get back to work). It implements 2 hash-maps or "Caches" one on the client and one on the server. Syncing them however has to split the data in parts, then send the parts as they're generated. I use a ChunkDataEvent.Load to load the data into my hash maps, the save event get them from the  "server" cache, and saves them into the chunk data. Then i use the ChunkEvent.unload to mark them for removal.

Link to comment
Share on other sites

Thanks for the replies people.

 

I'm planning on implementing some new features into my mod and for that I need more metadata per block. Only about a byte per block but I might end up using more than that for other things later.

 

I have a hash table where the value is an int or byte, and the key is a tuple of 4 elements. Block coordinates x, y, z and dimension id. When I want to insert metadata at some location I create a tuple and put the relevant value at that location in the hash table. When I want to read it I can do the same. I save this hash table using the NBT.

 

I think you'll find the real issues are memory and speed.

How long does it take to generate a hash ?

How long does it take to retrieve a set of values (from the hash table) for a single block ?

How many blocks in world ?

How much memory total for the number of blocks ?

 

Even if you have a single one of your blocks visible, you need to have the data for all of them in memory.

Also where do you plan to store the data itself ?

 

Using a TileEntity is a much simpler method, especially if you need to add extra values for each block.

 

Afaik hashing 4 ints should be trivial.

 

I expect at most 30-40 blocks of special metadata. Maybe 100 in extreme situations.

 

I do not want to use a TileEntity because I might want to store more than just bits. Also the problem in general is interesting. I am aware of using multiple blocks to store metadata. It, however, is not as interesting as what I'm trying to get at here.

 

This also relates to another problem I'm working on for my mod.

 

I have a block that when it is placed in a chunk makes sure that no mobs can spawn in that chunk. It does so by adding a listener to events which checks if a spawned living event is triggered from inside a chunk with this particular block. Blocks are stored in a hash table which is a WorldSavedData using x, y, z, w tuples as keys and integers as values (the integer representing the number of these blocks in a particular chunk). What i want to know is how the server/client aspect might interfere with this.

 

This works fine in single player, but I don't actually know if it works in multiplayer as I have been unable to test it.

Link to comment
Share on other sites

Hi

 

I do not want to use a TileEntity because I might want to store more than just bits.

I don't understand what you mean.  You can store anything you like in a TileEntity.  You write the NBT serialisation code yourself and can put whatever you need into it.  TileEntities are specifically designed for exactly what it sounds like you're trying to do.

 

Also the problem in general is interesting. I am aware of using multiple blocks to store metadata. It, however, is not as interesting as what I'm trying to get at here.

Fair enough :-)

 

This also relates to another problem I'm working on for my mod.

 

I have a block that when it is placed in a chunk makes sure that no mobs can spawn in that chunk. It does so by adding a listener to events which checks if a spawned living event is triggered from inside a chunk with this particular block. Blocks are stored in a hash table which is a WorldSavedData using x, y, z, w tuples as keys and integers as values (the integer representing the number of these blocks in a particular chunk). What i want to know is how the server/client aspect might interfere with this.

 

This works fine in single player, but I don't actually know if it works in multiplayer as I have been unable to test it.

Actually this is probably pretty easy since you only need to prevent spawning on the server, which is also the place you record your block placements.  So the client doesn't need to know about your hash table at all.

 

Just a comment - you are using the inbuilt Java hash tables, yeah?  (HashMap, HashSet)

 

This works fine in single player, but I don't actually know if it works in multiplayer as I have been unable to test it.

Why haven't you been able to test it? (i.e. what's stopping you?)

 

-TGG

Link to comment
Share on other sites

I concur with what TGG said, there are better ways to go about inventing the wheel that is already on cars, trucks, wagons, and moon rovers. Why not use what's already in Minecraft rather than risk killing servers, clients, breaking savegames, and many other hazards?

Link to comment
Share on other sites

Hi

 

I do not want to use a TileEntity because I might want to store more than just bits.

I don't understand what you mean.  You can store anything you like in a TileEntity.  You write the NBT serialisation code yourself and can put whatever you need into it.  TileEntities are specifically designed for exactly what it sounds like you're trying to do.

 

Oh that's interesting. I haven't actually dealt with tile entities yet but now that I think about it's obvious they can store anything, seeing that they store inventory data for containers and such.

 

I will look into using tile entities.

 

Also the problem in general is interesting. I am aware of using multiple blocks to store metadata. It, however, is not as interesting as what I'm trying to get at here.

Fair enough :-)

 

:D

 

This also relates to another problem I'm working on for my mod.

 

I have a block that when it is placed in a chunk makes sure that no mobs can spawn in that chunk. It does so by adding a listener to events which checks if a spawned living event is triggered from inside a chunk with this particular block. Blocks are stored in a hash table which is a WorldSavedData using x, y, z, w tuples as keys and integers as values (the integer representing the number of these blocks in a particular chunk). What i want to know is how the server/client aspect might interfere with this.

 

This works fine in single player, but I don't actually know if it works in multiplayer as I have been unable to test it.

Actually this is probably pretty easy since you only need to prevent spawning on the server, which is also the place you record your block placements.  So the client doesn't need to know about your hash table at all.

 

Yes that's what I was thinking too. My worry was that I would have to do some kind of syncing manually between clients, but I guess minecraft automatically synchs clients with whatever is on the server. The reverse, though, to make sure the server is updated when some local changes are made on clients is when you need to be careful... (?)

 

Just a comment - you are using the inbuilt Java hash tables, yeah?  (HashMap, HashSet)

 

Yeah. I'm not going to write my own hash tables. THAT would be reinventing the wheel :P

 

This works fine in single player, but I don't actually know if it works in multiplayer as I have been unable to test it.

Why haven't you been able to test it? (i.e. what's stopping you?)

 

Well I guess I could run a server locally and test with myself only...

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



  • Recently Browsing

    • No registered users viewing this page.
  • Posts

    • They were already updated, and just to double check I even did a cleanup and fresh update from that same page. I'm quite sure drivers are not the problem here. 
    • i tried downloading the drivers but it says no AMD graphics hardware has been detected    
    • Update your AMD/ATI drivers - get the drivers from their website - do not update via system  
    • As the title says i keep on crashing on forge 1.20.1 even without any mods downloaded, i have the latest drivers (nvidia) and vanilla minecraft works perfectly fine for me logs: https://pastebin.com/5UR01yG9
    • Hello everyone, I'm making this post to seek help for my modded block, It's a special block called FrozenBlock supposed to take the place of an old block, then after a set amount of ticks, it's supposed to revert its Block State, Entity, data... to the old block like this :  The problem I have is that the system breaks when handling multi blocks (I tried some fix but none of them worked) :  The bug I have identified is that the function "setOldBlockFields" in the item's "setFrozenBlock" function gets called once for the 1st block of multiblock getting frozen (as it should), but gets called a second time BEFORE creating the first FrozenBlock with the data of the 1st block, hence giving the same data to the two FrozenBlock :   Old Block Fields set BlockState : Block{minecraft:black_bed}[facing=east,occupied=false,part=head] BlockEntity : net.minecraft.world.level.block.entity.BedBlockEntity@73681674 BlockEntityData : id:"minecraft:bed",x:3,y:-60,z:-6} Old Block Fields set BlockState : Block{minecraft:black_bed}[facing=east,occupied=false,part=foot] BlockEntity : net.minecraft.world.level.block.entity.BedBlockEntity@6d1aa3da BlockEntityData : {id:"minecraft:bed",x:2,y:-60,z:-6} Frozen Block Entity set BlockState : Block{minecraft:black_bed}[facing=east,occupied=false,part=foot] BlockPos{x=3, y=-60, z=-6} BlockEntity : net.minecraft.world.level.block.entity.BedBlockEntity@6d1aa3da BlockEntityData : {id:"minecraft:bed",x:2,y:-60,z:-6} Frozen Block Entity set BlockState : Block{minecraft:black_bed}[facing=east,occupied=false,part=foot] BlockPos{x=2, y=-60, z=-6} BlockEntity : net.minecraft.world.level.block.entity.BedBlockEntity@6d1aa3da BlockEntityData : {id:"minecraft:bed",x:2,y:-60,z:-6} here is the code inside my custom "freeze" item :    @Override     public @NotNull InteractionResult useOn(@NotNull UseOnContext pContext) {         if (!pContext.getLevel().isClientSide() && pContext.getHand() == InteractionHand.MAIN_HAND) {             BlockPos blockPos = pContext.getClickedPos();             BlockPos secondBlockPos = getMultiblockPos(blockPos, pContext.getLevel().getBlockState(blockPos));             if (secondBlockPos != null) {                 createFrozenBlock(pContext, secondBlockPos);             }             createFrozenBlock(pContext, blockPos);             return InteractionResult.SUCCESS;         }         return super.useOn(pContext);     }     public static void createFrozenBlock(UseOnContext pContext, BlockPos blockPos) {         BlockState oldState = pContext.getLevel().getBlockState(blockPos);         BlockEntity oldBlockEntity = oldState.hasBlockEntity() ? pContext.getLevel().getBlockEntity(blockPos) : null;         CompoundTag oldBlockEntityData = oldState.hasBlockEntity() ? oldBlockEntity.serializeNBT() : null;         if (oldBlockEntity != null) {             pContext.getLevel().removeBlockEntity(blockPos);         }         BlockState FrozenBlock = setFrozenBlock(oldState, oldBlockEntity, oldBlockEntityData);         pContext.getLevel().setBlockAndUpdate(blockPos, FrozenBlock);     }     public static BlockState setFrozenBlock(BlockState blockState, @Nullable BlockEntity blockEntity, @Nullable CompoundTag blockEntityData) {         BlockState FrozenBlock = BlockRegister.FROZEN_BLOCK.get().defaultBlockState();         ((FrozenBlock) FrozenBlock.getBlock()).setOldBlockFields(blockState, blockEntity, blockEntityData);         return FrozenBlock;     }  
  • Topics

×
×
  • Create New...

Important Information

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