Solved Remove Death Screen in 1.13+

Discussion in 'Spigot Plugin Development' started by YourGameSpace, Jul 15, 2021.

Thread Status:
Not open for further replies.
  1. Hey, I'm unfortunately facing a bit of a problem at the moment.
    I am trying to remove the death screen, I have already read through several threads here in the forum and tested the various approaches there, but without success.

    The general function to "skip" the death of the player works without problems, the only problem is that you have to click on respawn manually.

    In 1.8, everything works until 1.12.2, but from 1.13 onwards, the problem starts.

    My code:

    Code (Java):
        @EventHandler
        public void onDeath(PlayerDeathEvent event) {
            Player player = event.getEntity();

            event.setDeathMessage(null);
            event.setKeepLevel(true);
            event.setKeepInventory(true);

            player.setHealth(20.0D);
            player.setVelocity(new Vector(0.0D, 0.0D, 0.0D));
            player.setFallDistance(0.0F);
            player.teleport(Objects.requireNonNull(player.getLocation().getWorld()).getSpawnLocation());
            player.getInventory().clear();
            player.getInventory().setArmorContents(null);
            //For 1.13+
            Bukkit.getScheduler().runTaskLaterAsynchronously(GunGame.getInstance(), () -> player.spigot().respawn(), 5);
        }
    I have also tried a sync timer, but without success.


    Another topic by the way: Apparently the instruction "event.#setKeepInventory(true);" is not observed. Does anyone know why?

    Best regards, TUBEOF :)
     
  2. Just call https://hub.spigotmc.org/javadocs/spigot/org/bukkit/entity/Player.Spigot.html#respawn()
     
  3. And if you call EntityDamageEvent before the player is dead?
     
  4. Well, I don't know if it will help, but maybe you can look into Mojang's Totem of Undying code? It seems like you want to achieve something like that with your plugin, so I suggest looking into how Mojang did it, as they also somehow had to "catch" the death of a player. Again, not sure if it will help, but all you can do is check it out
     
  5. @TimeoutHD is correct. Listen to EntityDamageEvent instead. Figure out if the damage given from the event will make their health less than 0, and do the appropriate things to respawn the player.
     
  6. SOLUTION

    The problem with `player#spigot#respawn()` is that it is only executed when the player is dead. Because the player was not dead, the whole thing was never executed.

    I simply used ProtocolLib and sent the player two packets, so that the respawn screen remains almost invisible for the player.

    Packet 1: Respawn
    Packet 2: Teleport

    Why an additional teleport package?
    If only the respawn is carried out, the chunks are no longer loaded correctly and the player has to reconnect.

    Code (Java):
        @EventHandler
        public void onDeath(PlayerDeathEvent event) {
            Player player = event.getEntity();

            event.setDeathMessage(null);
            event.setKeepLevel(true);
            event.setKeepInventory(true);

            player.setHealth(20.0D);
            player.setVelocity(new Vector(0.0D, 0.0D, 0.0D));
            player.setFallDistance(0.0F);
            player.teleport(Objects.requireNonNull(player.getLocation().getWorld()).getSpawnLocation());
            player.getInventory().clear();
            player.getInventory().setArmorContents(null);

            //For 1.13+
            if(data.isProtocollibInstalled()) {
                Bukkit.getScheduler().runTaskLater(GunGame.getInstance(), () -> {
                    try {
                        packetHandler.sendPlayerRespawnPacket(player);
                        packetHandler.sendPlayerTeleportPacket(player);
                    } catch (ReflectiveOperationException e) {
                        e.printStackTrace();
                    }
                }, 1);
            }
        }
    Packet Sender:
    Code (Java):
        public void sendPlayerRespawnPacket(Player player) throws ReflectiveOperationException {
            PacketContainer respawn = new PacketContainer(RESPAWN);
            EnumWrappers.Difficulty difficulty = EnumWrappers.getDifficultyConverter().getSpecific(player.getWorld().getDifficulty());
            //<= 1.13.1
            int dimensionId = player.getWorld().getEnvironment().getId();
            respawn.getIntegers().writeSafely(0, dimensionId);
            //> 1.13.1
            if (MinecraftVersion.getCurrentVersion().compareTo(MinecraftVersion.AQUATIC_UPDATE) > 0) {
                try {
                    respawn.getDimensions().writeSafely(0, dimensionId);
                } catch (NoSuchMethodError noSuchMethodError) {
                    throw new ReflectiveOperationException();
                }
            }
            respawn.getDifficulties().writeSafely(0, difficulty);
            respawn.getGameModes().writeSafely(0, EnumWrappers.NativeGameMode.fromBukkit(player.getGameMode()));
            respawn.getWorldTypeModifier().writeSafely(0, player.getWorld().getWorldType());
            protocolManager.sendServerPacket(player, respawn);
        }

        public void sendPlayerTeleportPacket(Player player) throws InvocationTargetException {
            PacketContainer teleport = new PacketContainer(POSITION);
            teleport.getModifier().writeDefaults();

            Location location = player.getLocation();
            teleport.getDoubles().write(0, location.getX());
            teleport.getDoubles().write(1, location.getY());
            teleport.getDoubles().write(2, location.getZ());
            teleport.getFloat().write(0, location.getYaw());
            teleport.getFloat().write(1, location.getPitch());

            //Sends invalid teleport id, to let Bukkit ignore the incoming client confirm packet
            teleport.getIntegers().writeSafely(0, -1337);
            protocolManager.sendServerPacket(player, teleport);
        }
     
Thread Status:
Not open for further replies.