Jump to content

[1.7.10]Storing players UUIDs in block


webik150

Recommended Posts

Hey. I'm trying to make a block on which a player can right-click, but only once (every player can do it once). Is there any better way to do it that store the UUIDs in NBT?

 

The idea is there are 5 structures generated on random places, every one of them has a special block. A player comes, clicks on the block and gets a special item. Now, he cannot click on the block again. If he wants to get the special item again, he has to find some of the other four structures.

 

 

Currently I have a TileEntity:

 

public class TileEntityCollectionBookshelf extends TileEntity{
    ArrayList<String> playerUUIDs = new ArrayList<String>();

    public void giveCollectionBook(PlayerInteractEvent event){

        //SOMEHOW GET A LIST OF UUIDs FROM NBT

        for(int i = 0;i<playerUUIDs.size();i++){
        if(!(event.entityPlayer.getUniqueID().toString().equals(playerUUIDs.get(i)))){
        event.entityPlayer.inventory.addItemStackToInventory(new ItemStack(CollectiblesItems.collectionBook, 1));

          //SOMEHOW WRITE THE i TO NBT

         }
       }
    }

                   
         
    @Override
    public void readFromNBT(NBTTagCompound nbt){
        super.readFromNBT(nbt);
         //NOT REALLY SURE WHAT TO DO IN HERE
    }

    @Override
    public void writeToNBT(NBTTagCompound nbt){
        super.writeToNBT(nbt);
        for (int i = 0; i < playerUUIDs.size(); i++) {
            nbt.setString(playerUUIDs.get(i), "gotBook");
        }
    }
}

 

I'm using the PlayerInteractEvent in my EventHandler to detect right-clicks.

I can also post here my Block class and EventHandler if you want. Any suggestions?

 

 

Also sorry for any errors in my English.

Link to comment
Share on other sites

Well, nbt does seem the way to go. However, if I were you I'd store that on the player instead.

Afterall, it is the player who can't access it, not the block, e.g. it is information about the player.

Thus according to propper programming ethique it is data that should belong in the player.

 

Furthermore, let us consider a server with 100 players. If the 100th player click on the block it has to iterate through a list of 99 players, check if the player is in the list and if not hand the item. Now if that information was in the player, then it would have to iterate through only 5 blocks, namely the 5 possible blocks he can click on. And this can even be solved with a simple array of booleans. Also worth to note is that the amount of data that has to be saved is about the same while the data it needs to load at one time is significantly less, just 5 booleans for the player.

 

I think this is a decent start for a suggestion. Consider it.

Link to comment
Share on other sites

Why would you use NBT and PlayerInteractEvent? Why not casting world.getTileEntity to your TileEntity in the block's overridden onBlockActivated method and use your tile entity's public fields and methods that give you a list of players who already used the block?

Also, you can get the player's UUID from player.getGameProfile().getId().toString().

Link to comment
Share on other sites

Black's way is working perfectly. Thank you to you.

 

Also here's the code if anyone wants:

@SubscribeEvent
    public void OnRightClick(PlayerInteractEvent event){
        if (!event.world.isRemote) {
            if (event.action == PlayerInteractEvent.Action.RIGHT_CLICK_BLOCK) {
                if (event.world.getBlock(event.x, event.y, event.z) == CollectiblesBlocks.collectionBookshelf) {
                    if (!(event.entityPlayer.getEntityData().hasKey("GOTBOOKON.X."+event.x)&&event.entityPlayer.getEntityData().hasKey("GOTBOOKON.Y."+event.y)&&event.entityPlayer.getEntityData().hasKey("GOTBOOKON.Z."+event.z)))
                    event.entityPlayer.inventory.addItemStackToInventory(new ItemStack(CollectiblesItems.collectionBook, 1));
                    event.entityPlayer.getEntityData().setBoolean("GOTBOOKON.X."+event.x,true);
                    event.entityPlayer.getEntityData().setBoolean("GOTBOOKON.Y."+event.y,true);
                    event.entityPlayer.getEntityData().setBoolean("GOTBOOKON.Z."+event.z,true);
                }
            }
        }

    }

Link to comment
Share on other sites

Although the author already chose a solution. I have been thinking about this problem too as I might be implementing such a feature in my mod as well. Maybe writing it down will answer it for myself.

So here it goes:

Well, nbt does seem the way to go. However, if I were you I'd store that on the player instead.

Afterall, it is the player who can't access it, not the block, e.g. it is information about the player.

Thus according to propper programming ethique it is data that should belong in the player.

 

Furthermore, let us consider a server with 100 players. If the 100th player click on the block it has to iterate through a list of 99 players, check if the player is in the list and if not hand the item. Now if that information was in the player, then it would have to iterate through only 5 blocks, namely the 5 possible blocks he can click on. And this can even be solved with a simple array of booleans. Also worth to note is that the amount of data that has to be saved is about the same while the data it needs to load at one time is significantly less, just 5 booleans for the player.

 

I think this is a decent start for a suggestion. Consider it.

Initial reaction: This discussion can be made both ways, without contradicting the 'proper programming ethic'. 

 

But first, lets make clear what the different implementations I am thinking of using in my own mod.

1. Player-Attribute: A Block that has a meta-data value set on WorldGen and store it in the NBT-data of the Player and keep track of it by an OnInteractionEvent. The meta-data would be needed to identify which block the player has clicked.

2. TileEntity-Attribute: A TileEntity which keeps a list of playerIDs in its NBT-data structure.

 

* Player-Attribute (Block+OnInteractionEvent) over TileEntity-Attribute:

Reason: The player is the one who interacts with the block. The player either has clicked the TileEntity, or the player hasn't. So you keep track of this attribute on the player which of these blocks it has clicked. It is the player who can't access the TileEntity.

Pros: Checking on player is quicker, as the list is shorter. Five always present booleans are easier to write away in, and read from, NBT-data. Whenever something happens to the block, the data is not lost as it is stored in the player.

Cons: You cannot account for multiple worlds in which these blocks can be generated, unless that is intended. Every, every, time a player interacts with any block, your event is fired. Maybe not big for a single player world, but on the 100 player example all mining and interacting with blocks and tileEntities can start to contribute to the lag which is probably already present.

Personal Note: I would personally not use the booleans in the fashion described above, but use a MapCollection and .add(BlockReference, boolean) to prevent the need to change this every time I (you) decide to change the number of these structures. This way you can support multiple worlds easily.

 

* TileEntity-Attribute over Player-Attribute:

Reason: The TileEntity can be clicked by the player. The TileEntity keeps track who has or hasn't. It is the TileEntity which denies access to the Player. So, this is a TileEntity-attribute.

Pros: Each block has its own list. If the owner of a server decides to regenerate the world (without resetting the player data), players will be able to pick up the books from the new structures without the need to reset the values on every player. All code that regulate this is contained in one class which is the Object.

Cons: If something happens to that block, that list will be lost (can be exploited). When the TileEntity gathers a large number of elements the whole list has to be written and read whenever the TileEntity is loaded or unloaded.

Personal Note: There are collection implementations which guarantee an insertion and look-up time of O(1), http://bigocheatsheet.com/ . This means that each element added to the list will not increase the time needed to look-up or insert another element, but stays constant for each and everyone of them. A HashSet would probably be my choice.

 

Even though it sounds weird, I would go for the Tile-Entity attribute. It keeps the code in one Class which is (IMHO) more along the Object-Orientation Ethic. However, that is my opinion on the code ethic. There are many ways to see this.

 

"I guess as this is pretty much WIP, I can just 'borrow' the sounds from that game without problem. They are just 'placeholders' anyway." -Me, while extracting the Tear sounds of Bioshock Infinite.

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.



×
×
  • Create New...

Important Information

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