Restrict spectating to first and third person without freeroam

Discussion in 'Spigot Plugin Development' started by Galaxyzd, Dec 2, 2019 at 8:25 PM.

  1. I was looking to make a plugin that makes spectating only possible from other players' 1st and 3rd person perspectives and completely disable freeroaming so people cannot ghost and explore using spectator mode.

    Is there any straightforward way to do this or does a plugin exist that does already does this? I was looking at the javadocs but couldn't find much other than getSpectatorTarget and setSpectatorTarget.

    All the ways to achieve this that I can think of use some hacky way like constantly checking if someone has a spectator target. Not sure how great that'd be for performance as well as it feeling really hacky probably.
     
    #1 Galaxyzd, Dec 2, 2019 at 8:25 PM
    Last edited: Dec 2, 2019 at 8:33 PM
  2. You can try listening for and cancelling PlayerToggleSneakEvent which will fire when a player sneaks and tries to stop spectating an entity
     
    • Useful Useful x 1
  3. Although still a bit of a hacky solution this is a lot better than having to check over and over again on a timer or something like that. This combined with getSpectatorTarget and setSpectatorTarget could work out pretty well.
     
  4. Also don't forget to cancel the teleport event in case the player uses the spectator hotbar.
     
  5. Players should absolutely be able to pick a target for firstperson and thirdperson spectating from the hotbar so instead I made it find a nearby target upon choosing one and set that as their spectating target so that they cannot use this to go freeroaming either.

    Code (Java):
    @EventHandler
    public void onPlayerTeleport(PlayerTeleportEvent e) {
        if (e.getCause() == TeleportCause.SPECTATE) {
            Player player = e.getPlayer();
            try {
                Player target = (Player) player.getWorld().getNearbyEntities(e.getTo(), 1, 1, 1,
                        entity -> entity.getType() == EntityType.PLAYER && entity != player).toArray()[0];
                Utils.setSpectatorTarget(player, target); // This helper function checks if we aren't already spectating this target and sends a message
            } catch (Exception exception) {
                player.sendMessage("§cCould not find specified player.");
                e.setCancelled(true);
            }
        }
    }
     
    • Like Like x 1
  6. That's also a really clever possibly. I didn't think about it. However it's depends on the case if he wants to cancel it or allow it.