0

I have developed my own Minecraft plugin in Spigot for version 1.19, which includes the command "mob". This command allows players to teleport a mob to their location while remaining invisible. However, I am encountering a problem where the mob is still able to push me, preventing me from remaining in one spot.

package de.snoopti.commands.extra;

import de.snoopti.Main;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerInteractEntityEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.plugin.Plugin;

public class Mob implements CommandExecutor, Listener {

    private final Plugin plugin;
    private LivingEntity mob;
    private Player player;

    public Mob(Main main) {
        this.plugin = main;
    }

    @Override
    public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
        if (!(sender instanceof Player)) {
            sender.sendMessage(Main.PREFIX + "Dieser Befehl kann nur von einem Spieler ausgeführt werden.");
            return true;
        }

        if (mob != null) {
            mob.remove();
            player.setInvisible(false);
            mob = null;
            player = null;
        }

        player = (Player) sender;

        if (args.length != 1) {
            player.sendMessage(Main.PREFIX + "Verwendung: /mob <Tier>");
            return true;
        }

        EntityType entityType = EntityType.fromName(args[0]);
        if (entityType == null || !entityType.isAlive()) {
            player.sendMessage(Main.PREFIX + "§cDies ist kein gültiges Tier.");
            player.playSound(player.getLocation(), Main.commandSOUNDerror, (float) Main.commandSOUNDvolume, 1f);
            return true;
        }

        mob = (LivingEntity) player.getWorld().spawnEntity(player.getLocation(), entityType);
        mob.setAI(false);
        mob.setCanPickupItems(false);
        mob.setInvulnerable(true);
        mob.setCollidable(false);

        player.sendMessage(Main.PREFIX + "Du hast dich in ein §5" + args[0] + " §7verwandelt.");
        player.playSound(player.getLocation(), Main.commandSOUND, (float) Main.commandSOUNDvolume, 1f);

        player.setInvisible(true);
        mob.setCollidable(false);
        player.setCollidable(false);

        Bukkit.getScheduler().scheduleSyncRepeatingTask(plugin, new Runnable() {
            @Override
            public void run() {
                if (!player.isOnline()) {
                    mob.remove();
                    player.setInvisible(false);
                    mob = null;
                    player = null;
                    return;
                }
                if (!mob.isValid() || mob.isDead()) {
                    player.setInvisible(false);
                    mob = null;
                    player = null;
                    return;
                }
                mob.teleport(player.getLocation());
            }
        }, 10L, 1L);

        return true;
    }

    @EventHandler
    public void onPlayerInteractEntity(PlayerInteractEntityEvent event) {
        if (mob != null && event.getRightClicked().equals(mob)) {
            event.setCancelled(true);
        }
    }

    @EventHandler
    public void onPlayerQuit(PlayerQuitEvent event) {
        if (player != null && event.getPlayer().equals(player)) {
            if (mob != null) {
                mob.remove();
                mob = null;
            }
            player = null;
        }
    }
}

Dharman
  • 30,962
  • 25
  • 85
  • 135
snoopti
  • 11
  • 2

2 Answers2

1

I've been working on similar stuff recently, but also haven't found a viable solution to this problem. I guess it's a Spigot/Paper issue, still planning to report it, but I have to do more testing first. So in my experience neither setCollidable(boolean), nor #getCollidableExemptions() seem to work properly.

I believe the only way to disable collisions is to add your entities to one Team and disabling team's collisions. You can create scoreboards with teams using commands or through Spigot API, see ScoreboardManager and Scoreboard. This approach will work 100%, but it will also disable collision between players of the same team.

UPD: it is confirmed on Spigot Jira that #setCollidable(boolean) is no longer in use SPIGOT-6399

0

I believe the reason the collision is still happening is that you are spawning the mob before you are setting their collidable status to false. I think doing mob.setCollidable(false); before you spawn it in might be an issue since you set mob to null, but you could try it. The other option would be to spawn the mob somewhere away from the player and then set then teleport it to the player after you set all the values.

EDIT: So it looks like .setCollidable is no longer working in Spigot, so this solution will not work. As VoidPainter said, you will need to use the Scoreboard API for collision rules.

atlaska826
  • 64
  • 7