Chunky (Bukkit)

Chunky (Bukkit)

20.6k Downloads

[Folia] Intentional Player-Induced Server Crash

Closed this issue ยท 1 comments

commented

Players can crash your instance via an unknown method through Chunky's vehicle ejection block (users failed to display how it was actually reproduced), which generates the following crash/exception:
https://pastebin.com/36FGpAK3

Proposed solutions for BukkitPlayer (I would be happy to PR either solution depending on preference):
(Instead, schedule the vehicle rather than the player for teleportation).

    @Override
    public void teleport(final Location location) {
        final org.bukkit.World world = Bukkit.getWorld(location.getWorld().getName());
        final org.bukkit.Location loc = new org.bukkit.Location(world, location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch());
        final Entity vehicle = player.getVehicle();
        if (vehicle == null) {
            teleportAsync(player, loc);
        } else if (Paper.isPaper() && player.getWorld().equals(loc.getWorld())) {
            Paper.teleportAsyncWithPassengers(vehicle, loc);
        } else if (Folia.isFolia() && !Folia.isTickThread(player.getLocation())) {
            Folia.schedule(plugin, vehicle, () -> teleport(location), 1);
        } else {
            final List<Entity> passengers = vehicle.getPassengers();
            vehicle.eject();
            teleportAsync(player, loc).thenAcceptAsync(ignored -> {
                teleportAsync(vehicle, loc);
                for (final Entity passenger : passengers) {
                    teleportAsync(passenger, loc);
                    if (passenger instanceof final org.bukkit.entity.Player playerPassenger) {
                        playerPassenger.hideEntity(plugin, vehicle);
                        playerPassenger.showEntity(plugin, vehicle);
                    }
                    vehicle.addPassenger(passenger);
                }
            }, command -> {
                if (Folia.isFolia()) {
                    Folia.schedule(plugin, player, command, 1);
                } else {
                    plugin.getServer().getScheduler().scheduleSyncDelayedTask(plugin, command, 1);
                }
            });
        }
    }

or have an explicit check for "vehicle.eject," as such:

    @Override
    public void teleport(final Location location) {
        final org.bukkit.World world = Bukkit.getWorld(location.getWorld().getName());
        final org.bukkit.Location loc = new org.bukkit.Location(world, location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch());
        final Entity vehicle = player.getVehicle();
        if (vehicle == null) {
            teleportAsync(player, loc);
        } else if (Paper.isPaper() && player.getWorld().equals(loc.getWorld())) {
            Paper.teleportAsyncWithPassengers(vehicle, loc);
        } else if (Folia.isFolia() && !Folia.isTickThread(player.getLocation())) {
            Folia.schedule(plugin, player, () -> teleport(location), 1);
        } else {
            final List<Entity> passengers = vehicle.getPassengers();
            if (Folia.isFolia() && !Folia.isTickThread(vehicle.getLocation())) {
                Folia.schedule(plugin, vehicle, vehicle::eject, 1);
            } else {
                vehicle.eject();
            }
            teleportAsync(player, loc).thenAcceptAsync(ignored -> {
                teleportAsync(vehicle, loc);
                for (final Entity passenger : passengers) {
                    teleportAsync(passenger, loc);
                    if (passenger instanceof final org.bukkit.entity.Player playerPassenger) {
                        playerPassenger.hideEntity(plugin, vehicle);
                        playerPassenger.showEntity(plugin, vehicle);
                    }
                    vehicle.addPassenger(passenger);
                }
            }, command -> {
                if (Folia.isFolia()) {
                    Folia.schedule(plugin, player, command, 1);
                } else {
                    plugin.getServer().getScheduler().scheduleSyncDelayedTask(plugin, command, 1);
                }
            });
        }
    }
commented

If scheduling the vehicle instead works I would prefer that over potentially breaking the teleportation as the timing in this code is important. The vehicle should teleport with the player and remain mounted.