Selecting objects programmatically?

  • Deutsch / Englisch
  • Selecting objects programmatically?

    Summary: I need a way for a player to "point" a specific object (currently, a chest) to a plug-in, telling it to work on that specific object.

    What I tried:

    1) A ray cast to get the object the player is looking at (the player would be required to look at the chest he want to work on); but ray cast result only identify players or NPCs;

    2) Find the chest nearest to the player (the player would be required to move near to the intended chest): but neither World.getAllChests() nor the world DB "Chests" table itself contain the chest position.

    Has anybody been able to solve this point?
    __________
    My plug-ins: Planks 'n Beams, GPS, UPS, Weather control, Plugin Central, RWGui (GUI back-end), Bank (Money back end)
  • Why not just trigger whatever you want to do in the chest access event?

    E.g.

    1. set a boolean attribute to the players named DoMyThing
    2. create a simple command (e.g. /a) that changes the value of that boolean
      • if the boolean is true accessing the chest triggers whatever you want to do and cancels the chest access event in the process.
      • if the boolean is false the player can access their chest as normal



    In general for all objects you could use the object interaction event too
    Admin on Artisan's Realm
    Rising World Projects:
    Blueprint Texture Editor
    MailingSystem
    ServerTools
    Portals

    Dieser Beitrag wurde bereits 6 mal editiert, zuletzt von Minotorious ()

  • @Minotorious, thanks for the reply. Perhaps, it would be possible in my case, but probably in a very counter-intuitive way. This is my scenario:

    - In the Area Protection plug-in, an area may restrict access to chests, all the chests of that area.

    - I would like to be able to tell the plug-in: "This specific chest (or furnace or whatever) is no longer restricted, but can be accessed (for taking, for giving or for both) by anyone."

    According to your description, it would be implemented more or less like this:

    • The player issues a command meaning "I want to edit the access rights for a chest"; the command just sets an attribute (say, "chestRights") for the player and does nothing else
    • Each time a player opens a chest, the attribute "chestRights" is looked for; if present, the chest opening is cancelled and the procedure to set the rights for that chest (whatever it actually is) is started instead.


    Would this make sense?
    __________
    My plug-ins: Planks 'n Beams, GPS, UPS, Weather control, Plugin Central, RWGui (GUI back-end), Bank (Money back end)
  • hmm I see no this wouldn't work very well, as in it would work but it is a super awkward solution for a much simpler problem.

    Why not just have a separate table in your Area Protection database called CommunityChests or something like that. Then in that table you add the IDs of the chests you want to be accessible by everyone, e.g. via command /ap commchest add 156 or GUI text field to add chest 156 to the community chests.

    Then you can have a for loop over the community chest ID numbers every time someone opens a chest to compare the ID of the chest that was just opened to the ones in the list, if the one is in the list then you allow the event else you check further e.g. if the chest is in an area the player has chest access rights in.
    Admin on Artisan's Realm
    Rising World Projects:
    Blueprint Texture Editor
    MailingSystem
    ServerTools
    Portals
  • Yes, of course ultimately access data would end up in a DB table, with the object ID and access rights.

    My problem, as stated initially, is: how can the I (or the generic user) know the chest ID in order to tell it to the plug-in? Or, in other words, how can the user tells the plug-in "this specific chest", so that the plug-in can work its ID out?
    __________
    My plug-ins: Planks 'n Beams, GPS, UPS, Weather control, Plugin Central, RWGui (GUI back-end), Bank (Money back end)
  • Hmm sorry got a bit sidetracked as I was concentrating on something else at the time of writting my previous reply :D

    What I have done for a similar case (Specialty Chests plugin on my github) is the following:

    Java-Quellcode

    1. @EventMethod
    2. public void onPlayerCommand(PlayerCommandEvent event){
    3. Player player = event.getPlayer();
    4. if (player.isAdmin()){
    5. String command = event.getCommand();
    6. if (command.equals("/sc")){
    7. if(player.hasAttribute("MinoShowChestIDs")){
    8. boolean ShowChestIDs = (boolean) player.getAttribute("MinoShowChestIDs");
    9. if (ShowChestIDs){
    10. player.setAttribute("MinoShowChestIDs", false);
    11. player.sendTextMessage("[#00AEE1]Chest IDs not showing anymore");
    12. }
    13. else{
    14. player.setAttribute("MinoShowChestIDs", true);
    15. player.sendTextMessage("[#00AEE1]Chest IDs now showing when opening chests");
    16. }
    17. }
    18. }
    19. }
    20. }
    21. @EventMethod
    22. public void onChestAccess(PlayerChestAccessEvent event){
    23. Player player = event.getPlayer();
    24. if (player.isAdmin()){
    25. if(player.hasAttribute("MinoShowChestIDs")){
    26. boolean ShowChestIDs = (boolean) player.getAttribute("MinoShowChestIDs");
    27. if (ShowChestIDs){
    28. player.sendTextMessage("[#00AEE1]This chest's unique ID is: " + Integer.toString(event.getChestID()));
    29. }
    30. }
    31. }
    32. }
    Alles anzeigen

    This way I get the chest ID as a chat message when I access a chest only if I have typed my command first. Then I can use that ID in further commands for example.
    Admin on Artisan's Realm
    Rising World Projects:
    Blueprint Texture Editor
    MailingSystem
    ServerTools
    Portals

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von Minotorious ()

  • sorry if I but in but why not use the f key to identify the chest or furnace or crafting table like yahgiggle does in the object protection plugin. it is on a timer to make the command so it doesn't just sit there and wate. You have to reactivate it with the f key after 30 sec or so. On my server we find it works very well. since we use the f key for activating things, opening doors, and chests, it should be fairly intuitive. :) Also, just a suggestion, please take into concideration the chests that were placed before object protection was placed.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von sharkbitefischer ()

  • Minotorious schrieb:

    What I have done for a similar case (Specialty Chests plugin on my github) is the following:

    Java-Quellcode

    1. <code removed>
    This way I get the chest ID as a chat message when I access a chest only if I have typed my command first. Then I can use that ID in further commands for example.
    Thanks for the code sample. In practice, with all the differences in the details, what I described in post no. 3 above is generically equivalent to your implementation: issue a command and the next chest interaction will be in some way special.

    sharkbitefischer schrieb:

    sorry if I but in but why not use the f key to identify the chest or furnace or crafting table like yahgiggle does in the object protection plugin. it is on a timer to make the command so it doesn't just sit there and wate. You have to reactivate it with the f key after 30 sec or so. On my server we find it works very well. since we use the f key for activating things, opening doors, and chests, it should be fairly intuitive. :)
    Would mind to elaborate a bit? How the F is used to identify an object?

    sharkbitefischer schrieb:

    Also, just a suggestion, please take into concideration the chests that were placed before object protection was placed.
    That's the whole point of all this; limiting to objects placed after the plug-in is installed simplifies some points, but it would be too limiting. But working on all objects requires identify them without any "previous knowledge" of them.
    __________
    My plug-ins: Planks 'n Beams, GPS, UPS, Weather control, Plugin Central, RWGui (GUI back-end), Bank (Money back end)
  • I don't know the specifics but yahgiggle seems to have it worked out. I think he is drawing the object id from the opening of the chest and the ID is based on the chests coordinates. Other then that you would have to ask yahgiggle about this. object protection works pretty good. If you want to see how it works come over to rosalia and I would be happy to show you around. But object protection does protect the chests everywhere on the server. It also does not work on chests placed before the plugin was installed because of no whay to tell who owns them, but that could be solved by being in the claim area. The object would be assigned to the owner of the claim.
  • You're probably referring to the ObjectInteractionEvent which is called when a player presses F while looking at an object (ignore the note about "setListenForObjectInteractions()", that's deprecated and no longer required, I will update the javadoc soon). It works for all objects (even for objects the player cannot interact with by default, like tables) and allows you to get all relevant information about the object.

    Alternatively the player.raycast() attempt is already a very good approach. Unfortunately it's not possible to get the actual object position yet (instead just the collision point can be retrieved, which is useless in this case). However, the raycast() Method will be enhanced with the next update (or more preceisely, the "RayCastResult" object) so it will be possible to get the actual object coordinates ^^
  • red51 schrieb:


    Alternatively the player.raycast() attempt is already a very good approach. Unfortunately it's not possible to get the actual object position yet (instead just the collision point can be retrieved, which is useless in this case). However, the raycast() Method will be enhanced with the next update (or more preceisely, the "RayCastResult" object) so it will be possible to get the actual object coordinates ^^
    In my case, the problem with RayCastResult is that it does not report the hit object itself in .getCollisionObject(); it only reports something if the hit object is a player or an NPC.
    __________
    My plug-ins: Planks 'n Beams, GPS, UPS, Weather control, Plugin Central, RWGui (GUI back-end), Bank (Money back end)
  • Miwarre schrieb:

    In my case, the problem with RayCastResult is that it does not report the hit object itself in .getCollisionObject(); it only reports something if the hit object is a player or an NPC.
    Unfortunately there is no "Object" object (lol) in the API, so getCollisionObject() only works for entities (like players or npcs). It's difficult to create a class representing an "Object" in the API... the game uses something similar though, but it becomes tricky to keep track of this object (and all changes of its state). The server only uses the actual "Object" instances temporarily in certain situations (when any changes happen), most of the time the server only holds the compressed chunk data.
    Maybe there will be an actual "Object" representation in the API (and also other objects like "Plants" or "ConstructionElements") in the future, but currently it's not planned :|

    But with the next update, it will be possible to retrieve the actual object position and also the type id (as well as the "info id", which - in case the object is a chest - represents the chest id). So if you want to get the actual chest, it could look like this (after the next update):

    Java-Quellcode

    1. //Just an example ;)
    2. player.raycast(CollisionType.OBJECTS, (RayCastResult r) -> {
    3. if(r != null){
    4. //Get the object world position if needed (but check for null)
    5. Vector3f pos = r.getElementPosition();
    6. if(pos != null){
    7. //Now get the object definition from the type id
    8. short type = r.getElementTypeID();
    9. Definitions.ObjectDefinition objectDef =
    10. Definitions.getObjectDefinition(type);
    11. //Def shouldn't be null at this stage, but who knows...
    12. if(objectDef != null){
    13. //Now you can check if it's a chest, for example
    14. if(objectDef.isChest()){
    15. //Get the chest id (info)
    16. int chestID = r.getCollisionInfo();
    17. Chest chest = getWorld().getChest(chestID);
    18. }
    19. }
    20. }
    21. }
    22. });
    Alles anzeigen
  • I'm struggling to get a chest ID via a raycast, I'm using this code:

    Quellcode

    1. player.raycast(CollisionType.OBJECTS, (RayCastResult r) -> {
    2. if(r != null){
    3. //Get the object world position if needed (but check for null)
    4. Vector3f pos = r.getElementPosition();
    5. if(pos != null){
    6. //Now get the object definition from the type id
    7. short type = r.getElementTypeID();
    8. Definitions.ObjectDefinition objectDef = Definitions.getObjectDefinition(type);
    9. //Def shouldn't be null at this stage, but who knows...
    10. if(objectDef != null){
    11. //Now you can check if it's a chest, for example
    12. if(objectDef.isChest()){
    13. int chestID = r.getCollisionInfo();
    14. System.out.println("chestID:"+ chestID);//always returns -1
    15. Storage chest = plugin.getWorld().getStorage(chestID);
    16. // int chestID = r.getCollisionInfo();
    17. // Chest chest = plugin.getWorld().getChest(chestID);
    18. System.out.println("cid:"+ chest.getID());
    19. }
    20. }
    21. }
    22. }
    23. });
    Alles anzeigen

    But as my code comment states, I always get a -1 return on the r.getCollisionInfor();
    Medieval Realms - connect to server via server.medievalrealms.co.uk
    Medieval Realms Website