Solved Custom Workbench Block?

Discussion in 'Spigot Plugin Development' started by Qruet, Feb 9, 2020.

  1. I have been working on a project that involves creating a custom GUI that can be opened up by right clicking a block (similarly to how you would open the Workbench GUI by simply right clicking a crafting table block). I thought I would simply utilize the smithing table block since it isn't currently being utilized. However, I have found that adding the added functionality of making into a functional block has been a bit difficult. Listening for an interact event doesn't work that well since if the player is holding a block item, they can place the block before the container opens up, which can be a bit annoying for the player. Cancelling this block placement can also be annoying for the player. The placement sound can still be heard, potentially making the player worry they accidentally placed their block, or even their inventory may not be properly updated after the cancellation, making them believe they just lost one of their blocks before it reappears. For aesthetic purposes, I intended to find a solution to this. I figured out that spawning a custom magma cube entity client sided will prevent the player from placing a block around the block of my choice (smithing table), while also triggering the interact event so that I can still open my custom container, however, this solution has created a new issue. Standing too close to this "hidden" entity will cause the player to be pushed away, which can be quite annoying (see media spoiler below). I've tried to work around it by detecting the player's distance from the block, if they're standing on top of the block, the faces of the block being looked at, and only spawning in the entity during certain times, however, there's not much I can do when a player stands directly in front of the smithing table block. I want to disable the custom entity from pushing the player, but I'm not sure if this is possible since I'm fairly certain that the velocity changes are handled via the client as well. Curious though if there's a way to override this displacement.

    tl;dr Spawning a custom entity around my custom "workbench" block so that player can't accidentally place block when right clicking it with a block. This solution though causes the player to get pushed by this entity when standing too close. How to avoid having player being pushed by entity?

    My latest attempt to resolve this solution is somehow hoping that spawning in the custom entity by the server instead of client will perhaps allow me to control the collisions between the entity and player, this, however, produces the same failed result.
    Code (Text):
    public class InterruptEntity extends EntityMagmaCube {

        public InterruptEntity(World world, Block block) {
            super(EntityTypes.MAGMA_CUBE, ((CraftWorld) world).getHandle());
            initAttr();

            getWorld().addEntity(this, CreatureSpawnEvent.SpawnReason.CUSTOM);

            Location location = block.getLocation().add(0.5, -0.25, 0.5);
            this.setPositionRotation(location.getX(), location.getY(), location.getZ(), 0f, 0f);
            Tasky.sync(t -> {
                setSize(3, false);
            }, 1L);
        }

        private void initAttr() {
            this.addEffect(new MobEffect(MobEffects.INVISIBILITY, Integer.MAX_VALUE, 1, false, false, false));
            this.setSize(0, false);
            this.noclip = true;
            this.setNoAI(true);
            this.setNoGravity(true);
            this.collides = false;
            this.getBukkitEntity().setGlowing(true);
        }

        @Override
        public boolean damageEntity(DamageSource damagesource, float f) {
            return false;
        }
    }

    For debug purposes, I added a glow effect around my invisible entity (magma cube) so that you can visually take notice of when it spawns in, size, and position.
    [​IMG]
     
  2. drives_a_ford

    Moderator

    Have you tried setting the collides field of the EntityLiving?
    (NMS because I assume that's how you created the client side entity)
     
  3. If you cancel the interact click event it shouldn't do place the block tho
     
  4. Don't invisible armor stands prevent block placement?
     
  5. Check my code snippet.
    Code (Text):
    this.collides = false;
    Yes, but actually no. The block is still placed client side, then almost instantaneously removed. However, for aesthetic purposes, I would like to avoid having the block placed at all. Instead of having a block flicker in and out due to the cancellation and the placement sound being played (plus the occasional visual glitch of the block item disappearing from the player's inventory), I would like the client to avoid placing any block by accident in the first place.
     
    #5 Qruet, Feb 9, 2020
    Last edited: Feb 9, 2020
  6. The size of the armor stand entity isn't ideal. Because I am dealing with a block, I want an entity that roughly matches the "bounding box" of a block, which the Magma Cube block does perfectly. Although I suppose if I were to spawn in quite a few to fill in the shape the best I could, and assuming armorstands don't push players, it might be a possible solution. Perhaps a 3x3 (or 2x2) array of ArmorStands to makeup the area of the block, but I'm not sure I really like that, I'll need to test it. Not sure if that's what you had in mind.
     
    #6 Qruet, Feb 9, 2020
    Last edited: Feb 9, 2020
  7. I agree armor stand could get messy/annoying.
    Since you are already doing packet stuff couldn't you use a crafting table then send a changeblock packet so they see a diff block?
     
    • Agree Agree x 1
  8. this, since you need the tile entity but you cant create a random tile entity. and then you can modify the default behavior of the interaction with this tile entity (thru playerinteract) if simply opening a crafting table isnt what youre going for.
     
  9. I get the idea, but what the client sees and registers is that there's a non-interactable block (smithing table) in front of the player, even if the server recognizes that a crafting bench is really there instead. The end result will most likely be equivalent to an event.setCancelled() action, where the block is placed, since the client sees no reason why it shouldn't place a block for a non-interactable block, then the server claims thats an illegal action and cancels it, but the block is still placed in that instance, the placement sound is played, and the block is momentarily removed from the player's inventory until the server cancels the action.
     
    #9 Qruet, Feb 9, 2020
    Last edited: Feb 9, 2020
  10. I finally got around to testing the idea out. Seems to work like a charm, minus the fact that the armorstands must be spawned and registered by the server and not sent directly to the player via packets. Apparently, it seems when right clicking an ArmorStand, the interaction is not sent to the server unless it's a living entity. This is fine, however, since armorstands do have the handy dandy #setInvisible(boolean) method.