mirror of
https://github.com/VolmitSoftware/Iris.git
synced 2025-07-01 15:36:45 +00:00
reconnect players on dimension type registry change
This commit is contained in:
parent
613575c0c5
commit
c98ed48ee2
@ -832,6 +832,7 @@ public class Iris extends VolmitPlugin implements Listener {
|
||||
if (!INMS.get().registerDimension(worldName, dim)) {
|
||||
throw new IllegalStateException("Unable to register dimension " + dim.getName());
|
||||
}
|
||||
INMS.get().reconnectAll();
|
||||
|
||||
return new BukkitChunkGenerator(w, false, ff, dim.getLoadKey());
|
||||
}
|
||||
|
@ -36,6 +36,7 @@ import org.bukkit.block.Biome;
|
||||
import org.bukkit.entity.Dolphin;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.EntityType;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.entity.CreatureSpawnEvent;
|
||||
import org.bukkit.generator.ChunkGenerator;
|
||||
import org.bukkit.generator.structure.Structure;
|
||||
@ -43,6 +44,8 @@ import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import java.io.File;
|
||||
import java.awt.Color;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
|
||||
public interface INMSBinding {
|
||||
boolean hasTile(Material material);
|
||||
@ -147,4 +150,11 @@ public interface INMSBinding {
|
||||
IPackRepository getPackRepository();
|
||||
|
||||
KList<String> getStructureKeys();
|
||||
|
||||
default void reconnectAll() {
|
||||
new ArrayList<>(Bukkit.getOnlinePlayers())
|
||||
.forEach(this::reconnect);
|
||||
}
|
||||
|
||||
void reconnect(Player player);
|
||||
}
|
||||
|
@ -45,6 +45,7 @@ import org.bukkit.block.Biome;
|
||||
import org.bukkit.entity.Dolphin;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.EntityType;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.entity.CreatureSpawnEvent;
|
||||
import org.bukkit.generator.ChunkGenerator;
|
||||
import org.bukkit.generator.structure.Structure;
|
||||
@ -145,6 +146,11 @@ public class NMSBinding1X implements INMSBinding {
|
||||
return new KList<>(list);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reconnect(Player player) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompoundTag serializeEntity(Entity location) {
|
||||
return null;
|
||||
|
@ -83,6 +83,7 @@ public class IrisWorldCreator {
|
||||
if (!INMS.get().registerDimension(name, dim)) {
|
||||
throw new IllegalStateException("Unable to register dimension " + dim.getName());
|
||||
}
|
||||
INMS.get().reconnectAll();
|
||||
|
||||
return new WorldCreator(name)
|
||||
.environment(findEnvironment())
|
||||
|
@ -23,11 +23,7 @@ import java.io.*;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Vector;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.logging.Logger;
|
||||
@ -40,17 +36,23 @@ import com.volmit.iris.engine.object.IrisBiomeReplacement;
|
||||
import com.volmit.iris.util.scheduling.J;
|
||||
import net.minecraft.nbt.*;
|
||||
import net.minecraft.nbt.Tag;
|
||||
import net.minecraft.network.Connection;
|
||||
import net.minecraft.network.protocol.game.ClientboundPlayerInfoPacket;
|
||||
import net.minecraft.resources.RegistryOps;
|
||||
import net.minecraft.server.PlayerAdvancements;
|
||||
import net.minecraft.server.commands.data.BlockDataAccessor;
|
||||
import com.volmit.iris.core.nms.container.IPackRepository;
|
||||
import com.volmit.iris.util.io.IO;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.server.network.ServerLoginPacketListenerImpl;
|
||||
import net.minecraft.server.players.PlayerList;
|
||||
import net.minecraft.stats.ServerStatsCounter;
|
||||
import net.minecraft.stats.Stats;
|
||||
import net.minecraft.tags.TagKey;
|
||||
import net.minecraft.world.level.LevelReader;
|
||||
import net.minecraft.world.level.block.EntityBlock;
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.mojang.datafixers.util.Pair;
|
||||
import com.mojang.serialization.Codec;
|
||||
import com.mojang.serialization.JsonOps;
|
||||
import com.mojang.serialization.Lifecycle;
|
||||
@ -82,11 +84,13 @@ import org.bukkit.craftbukkit.v1_19_R1.block.CraftBlock;
|
||||
import org.bukkit.craftbukkit.v1_19_R1.block.CraftBlockState;
|
||||
import org.bukkit.craftbukkit.v1_19_R1.block.CraftBlockStates;
|
||||
import org.bukkit.craftbukkit.v1_19_R1.block.data.CraftBlockData;
|
||||
import org.bukkit.craftbukkit.v1_19_R1.entity.CraftDolphin;
|
||||
import org.bukkit.craftbukkit.v1_19_R1.entity.CraftPlayer;
|
||||
import org.bukkit.craftbukkit.v1_19_R1.inventory.CraftItemStack;
|
||||
import org.bukkit.entity.Dolphin;
|
||||
import org.bukkit.craftbukkit.v1_19_R1.scoreboard.CraftScoreboardManager;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.entity.CreatureSpawnEvent;
|
||||
import org.bukkit.event.player.PlayerQuitEvent;
|
||||
import org.bukkit.generator.BiomeProvider;
|
||||
import org.bukkit.generator.ChunkGenerator;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
@ -105,7 +109,6 @@ import com.volmit.iris.util.json.JSONObject;
|
||||
import com.volmit.iris.util.mantle.Mantle;
|
||||
import com.volmit.iris.util.math.Vector3d;
|
||||
import com.volmit.iris.util.matter.MatterBiomeInject;
|
||||
import com.volmit.iris.util.nbt.io.NBTUtil;
|
||||
import com.volmit.iris.util.nbt.mca.NBTWorld;
|
||||
import com.volmit.iris.util.nbt.mca.palette.*;
|
||||
import com.volmit.iris.util.nbt.tag.CompoundTag;
|
||||
@ -118,13 +121,11 @@ import net.minecraft.core.RegistryAccess;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.world.entity.EntityType;
|
||||
import net.minecraft.world.level.biome.BiomeSource;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.chunk.ChunkAccess;
|
||||
import net.minecraft.world.level.chunk.LevelChunk;
|
||||
import sun.misc.Unsafe;
|
||||
|
||||
public class NMSBinding implements INMSBinding {
|
||||
private final KMap<Biome, Object> baseBiomeCache = new KMap<>();
|
||||
@ -891,6 +892,99 @@ public class NMSBinding implements INMSBinding {
|
||||
return keys;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reconnect(Player player) {
|
||||
var serverPlayer = ((CraftPlayer) player).getHandle();
|
||||
var listener = serverPlayer.connection;
|
||||
|
||||
try {
|
||||
var field = getField(listener.getClass(), Connection.class);
|
||||
field.setAccessible(true);
|
||||
var connection = (Connection) field.get(listener);
|
||||
var server = serverPlayer.getServer();
|
||||
var playerList = server.getPlayerList();
|
||||
J.s(() -> {
|
||||
try {
|
||||
remove(serverPlayer);
|
||||
} catch (Throwable e) {
|
||||
Iris.error("Failed to remove player " + player.getName());
|
||||
e.printStackTrace();
|
||||
return;
|
||||
}
|
||||
var result = playerList.canPlayerLogin(new ServerLoginPacketListenerImpl(server, connection), serverPlayer.getGameProfile(), serverPlayer.getProfilePublicKey());
|
||||
if (result != null) {
|
||||
playerList.placeNewPlayer(connection, result);
|
||||
}
|
||||
});
|
||||
} catch (Throwable e) {
|
||||
Iris.error("Failed to reconnect player " + player.getName());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private void remove(ServerPlayer player) throws NoSuchFieldException, IllegalAccessException {
|
||||
ServerLevel level = player.getLevel();
|
||||
player.awardStat(Stats.LEAVE_GAME);
|
||||
if (player.containerMenu != player.inventoryMenu) {
|
||||
player.closeContainer();
|
||||
}
|
||||
|
||||
PlayerQuitEvent playerQuitEvent = new PlayerQuitEvent(player.getBukkitEntity(), "§e" + player.getScoreboardName() + " left the game");
|
||||
Bukkit.getPluginManager().callEvent(playerQuitEvent);
|
||||
player.getBukkitEntity().disconnect(playerQuitEvent.getQuitMessage());
|
||||
player.doTick();
|
||||
|
||||
level.getServer().getPlayerList().playerIo.save(player);
|
||||
ServerStatsCounter stats = player.getStats();
|
||||
if (stats != null) stats.save();
|
||||
PlayerAdvancements advancements = player.getAdvancements();
|
||||
if (advancements != null) advancements.save();
|
||||
|
||||
if (player.isPassenger()) {
|
||||
var vehicle = player.getRootVehicle();
|
||||
if (vehicle.hasExactlyOnePlayerPassenger()) {
|
||||
Iris.debug("Removing player mount");
|
||||
player.stopRiding();
|
||||
vehicle.getPassengersAndSelf().forEach(passenger -> passenger.setRemoved(net.minecraft.world.entity.Entity.RemovalReason.UNLOADED_WITH_PLAYER));
|
||||
}
|
||||
}
|
||||
|
||||
player.unRide();
|
||||
level.removePlayerImmediately(player, net.minecraft.world.entity.Entity.RemovalReason.UNLOADED_WITH_PLAYER);
|
||||
player.getAdvancements().stopListening();
|
||||
|
||||
var playersField = getField(PlayerList.class, buildType(List.class, ServerPlayer.class.getName()));
|
||||
playersField.setAccessible(true);
|
||||
var playersByNameField = getField(PlayerList.class, buildType(Map.class, String.class.getName(), ServerPlayer.class.getName()));
|
||||
playersByNameField.setAccessible(true);
|
||||
var playersByUUIDField = getField(PlayerList.class, buildType(Map.class, UUID.class.getName(), ServerPlayer.class.getName()));
|
||||
playersByUUIDField.setAccessible(true);
|
||||
|
||||
var players = (List<ServerPlayer>)playersField.get(player.getServer().getPlayerList());
|
||||
var playersByName = (Map<String, ServerPlayer>)playersByNameField.get(player.getServer().getPlayerList());
|
||||
var playersByUUID = (Map<UUID, ServerPlayer>)playersByUUIDField.get(player.getServer().getPlayerList());
|
||||
|
||||
players.remove(player);
|
||||
playersByName.remove(player.getScoreboardName().toLowerCase(Locale.ROOT));
|
||||
level.getServer().getCustomBossEvents().onPlayerDisconnect(player);
|
||||
UUID uuid = player.getUUID();
|
||||
ServerPlayer currentPlayer = playersByUUID.get(uuid);
|
||||
if (currentPlayer == player) {
|
||||
playersByUUID.remove(uuid);
|
||||
}
|
||||
|
||||
ClientboundPlayerInfoPacket packet = new ClientboundPlayerInfoPacket(ClientboundPlayerInfoPacket.Action.REMOVE_PLAYER, player);
|
||||
for (ServerPlayer target : players) {
|
||||
if (target.getBukkitEntity().canSee(player.getBukkitEntity())) {
|
||||
target.connection.send(packet);
|
||||
} else {
|
||||
target.getBukkitEntity().onEntityRemove(player);
|
||||
}
|
||||
}
|
||||
|
||||
((CraftScoreboardManager) Bukkit.getScoreboardManager()).removePlayer(player.getBukkitEntity());
|
||||
}
|
||||
|
||||
private static Field getField(Class<?> clazz, Class<?> fieldType) throws NoSuchFieldException {
|
||||
try {
|
||||
for (Field f : clazz.getDeclaredFields()) {
|
||||
|
@ -23,12 +23,8 @@ import java.io.*;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.*;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Map;
|
||||
import java.util.Vector;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.logging.Logger;
|
||||
@ -43,8 +39,16 @@ import com.volmit.iris.util.io.IO;
|
||||
import com.volmit.iris.util.scheduling.J;
|
||||
import net.minecraft.nbt.*;
|
||||
import net.minecraft.nbt.Tag;
|
||||
import net.minecraft.network.Connection;
|
||||
import net.minecraft.network.protocol.game.ClientboundPlayerInfoRemovePacket;
|
||||
import net.minecraft.resources.RegistryOps;
|
||||
import net.minecraft.server.PlayerAdvancements;
|
||||
import net.minecraft.server.commands.data.BlockDataAccessor;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.server.network.ServerLoginPacketListenerImpl;
|
||||
import net.minecraft.server.players.PlayerList;
|
||||
import net.minecraft.stats.ServerStatsCounter;
|
||||
import net.minecraft.stats.Stats;
|
||||
import net.minecraft.tags.TagKey;
|
||||
import net.minecraft.world.level.LevelReader;
|
||||
import net.minecraft.world.level.biome.MobSpawnSettings;
|
||||
@ -85,10 +89,14 @@ import org.bukkit.craftbukkit.v1_19_R2.block.CraftBlockState;
|
||||
import org.bukkit.craftbukkit.v1_19_R2.block.CraftBlockStates;
|
||||
import org.bukkit.craftbukkit.v1_19_R2.block.data.CraftBlockData;
|
||||
import org.bukkit.craftbukkit.v1_19_R2.entity.CraftDolphin;
|
||||
import org.bukkit.craftbukkit.v1_19_R2.entity.CraftPlayer;
|
||||
import org.bukkit.craftbukkit.v1_19_R2.inventory.CraftItemStack;
|
||||
import org.bukkit.craftbukkit.v1_19_R2.scoreboard.CraftScoreboardManager;
|
||||
import org.bukkit.entity.Dolphin;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.entity.CreatureSpawnEvent;
|
||||
import org.bukkit.event.player.PlayerQuitEvent;
|
||||
import org.bukkit.generator.BiomeProvider;
|
||||
import org.bukkit.generator.ChunkGenerator;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
@ -829,6 +837,99 @@ public class NMSBinding implements INMSBinding {
|
||||
return keys;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reconnect(Player player) {
|
||||
var serverPlayer = ((CraftPlayer) player).getHandle();
|
||||
var listener = serverPlayer.connection;
|
||||
|
||||
try {
|
||||
var field = getField(listener.getClass(), Connection.class);
|
||||
field.setAccessible(true);
|
||||
var connection = (Connection) field.get(listener);
|
||||
var server = serverPlayer.getServer();
|
||||
var playerList = server.getPlayerList();
|
||||
J.s(() -> {
|
||||
try {
|
||||
remove(serverPlayer);
|
||||
} catch (Throwable e) {
|
||||
Iris.error("Failed to remove player " + player.getName());
|
||||
e.printStackTrace();
|
||||
return;
|
||||
}
|
||||
var result = playerList.canPlayerLogin(new ServerLoginPacketListenerImpl(server, connection), serverPlayer.getGameProfile());
|
||||
if (result != null) {
|
||||
playerList.placeNewPlayer(connection, result);
|
||||
}
|
||||
});
|
||||
} catch (Throwable e) {
|
||||
Iris.error("Failed to reconnect player " + player.getName());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private void remove(ServerPlayer player) throws NoSuchFieldException, IllegalAccessException {
|
||||
ServerLevel level = player.getLevel();
|
||||
player.awardStat(Stats.LEAVE_GAME);
|
||||
if (player.containerMenu != player.inventoryMenu) {
|
||||
player.closeContainer();
|
||||
}
|
||||
|
||||
PlayerQuitEvent playerQuitEvent = new PlayerQuitEvent(player.getBukkitEntity(), "§e" + player.getScoreboardName() + " left the game");
|
||||
Bukkit.getPluginManager().callEvent(playerQuitEvent);
|
||||
player.getBukkitEntity().disconnect(playerQuitEvent.getQuitMessage());
|
||||
player.doTick();
|
||||
|
||||
level.getServer().getPlayerList().playerIo.save(player);
|
||||
ServerStatsCounter stats = player.getStats();
|
||||
if (stats != null) stats.save();
|
||||
PlayerAdvancements advancements = player.getAdvancements();
|
||||
if (advancements != null) advancements.save();
|
||||
|
||||
if (player.isPassenger()) {
|
||||
var vehicle = player.getRootVehicle();
|
||||
if (vehicle.hasExactlyOnePlayerPassenger()) {
|
||||
Iris.debug("Removing player mount");
|
||||
player.stopRiding();
|
||||
vehicle.getPassengersAndSelf().forEach(passenger -> passenger.setRemoved(net.minecraft.world.entity.Entity.RemovalReason.UNLOADED_WITH_PLAYER));
|
||||
}
|
||||
}
|
||||
|
||||
player.unRide();
|
||||
level.removePlayerImmediately(player, net.minecraft.world.entity.Entity.RemovalReason.UNLOADED_WITH_PLAYER);
|
||||
player.getAdvancements().stopListening();
|
||||
|
||||
var playersField = getField(PlayerList.class, buildType(List.class, ServerPlayer.class.getName()));
|
||||
playersField.setAccessible(true);
|
||||
var playersByNameField = getField(PlayerList.class, buildType(Map.class, String.class.getName(), ServerPlayer.class.getName()));
|
||||
playersByNameField.setAccessible(true);
|
||||
var playersByUUIDField = getField(PlayerList.class, buildType(Map.class, UUID.class.getName(), ServerPlayer.class.getName()));
|
||||
playersByUUIDField.setAccessible(true);
|
||||
|
||||
var players = (List<ServerPlayer>)playersField.get(player.getServer().getPlayerList());
|
||||
var playersByName = (Map<String, ServerPlayer>)playersByNameField.get(player.getServer().getPlayerList());
|
||||
var playersByUUID = (Map<UUID, ServerPlayer>)playersByUUIDField.get(player.getServer().getPlayerList());
|
||||
|
||||
players.remove(player);
|
||||
playersByName.remove(player.getScoreboardName().toLowerCase(Locale.ROOT));
|
||||
level.getServer().getCustomBossEvents().onPlayerDisconnect(player);
|
||||
UUID uuid = player.getUUID();
|
||||
ServerPlayer currentPlayer = playersByUUID.get(uuid);
|
||||
if (currentPlayer == player) {
|
||||
playersByUUID.remove(uuid);
|
||||
}
|
||||
|
||||
ClientboundPlayerInfoRemovePacket packet = new ClientboundPlayerInfoRemovePacket(List.of(player.getUUID()));
|
||||
for (ServerPlayer target : players) {
|
||||
if (target.getBukkitEntity().canSee(player.getBukkitEntity())) {
|
||||
target.connection.send(packet);
|
||||
} else {
|
||||
target.getBukkitEntity().onEntityRemove(player);
|
||||
}
|
||||
}
|
||||
|
||||
((CraftScoreboardManager) Bukkit.getScoreboardManager()).removePlayer(player.getBukkitEntity());
|
||||
}
|
||||
|
||||
private static Field getField(Class<?> clazz, Class<?> fieldType) throws NoSuchFieldException {
|
||||
try {
|
||||
for (Field f : clazz.getDeclaredFields()) {
|
||||
|
@ -23,11 +23,7 @@ import java.io.*;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Vector;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.logging.Logger;
|
||||
@ -40,10 +36,18 @@ import com.volmit.iris.engine.object.IrisBiomeReplacement;
|
||||
import com.volmit.iris.util.scheduling.J;
|
||||
import net.minecraft.nbt.*;
|
||||
import net.minecraft.nbt.Tag;
|
||||
import net.minecraft.network.Connection;
|
||||
import net.minecraft.network.protocol.game.ClientboundPlayerInfoRemovePacket;
|
||||
import net.minecraft.resources.RegistryOps;
|
||||
import net.minecraft.server.PlayerAdvancements;
|
||||
import net.minecraft.server.commands.data.BlockDataAccessor;
|
||||
import com.volmit.iris.core.nms.container.IPackRepository;
|
||||
import com.volmit.iris.util.io.IO;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.server.network.ServerLoginPacketListenerImpl;
|
||||
import net.minecraft.server.players.PlayerList;
|
||||
import net.minecraft.stats.ServerStatsCounter;
|
||||
import net.minecraft.stats.Stats;
|
||||
import net.minecraft.tags.TagKey;
|
||||
import net.minecraft.world.level.LevelReader;
|
||||
import net.minecraft.world.level.biome.BiomeGenerationSettings;
|
||||
@ -85,10 +89,14 @@ import org.bukkit.craftbukkit.v1_19_R3.block.CraftBlockState;
|
||||
import org.bukkit.craftbukkit.v1_19_R3.block.CraftBlockStates;
|
||||
import org.bukkit.craftbukkit.v1_19_R3.block.data.CraftBlockData;
|
||||
import org.bukkit.craftbukkit.v1_19_R3.entity.CraftDolphin;
|
||||
import org.bukkit.craftbukkit.v1_19_R3.entity.CraftPlayer;
|
||||
import org.bukkit.craftbukkit.v1_19_R3.inventory.CraftItemStack;
|
||||
import org.bukkit.craftbukkit.v1_19_R3.scoreboard.CraftScoreboardManager;
|
||||
import org.bukkit.entity.Dolphin;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.entity.CreatureSpawnEvent;
|
||||
import org.bukkit.event.player.PlayerQuitEvent;
|
||||
import org.bukkit.generator.BiomeProvider;
|
||||
import org.bukkit.generator.ChunkGenerator;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
@ -847,6 +855,99 @@ public class NMSBinding implements INMSBinding {
|
||||
return keys;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reconnect(Player player) {
|
||||
var serverPlayer = ((CraftPlayer) player).getHandle();
|
||||
var listener = serverPlayer.connection;
|
||||
|
||||
try {
|
||||
var field = getField(listener.getClass(), Connection.class);
|
||||
field.setAccessible(true);
|
||||
var connection = (Connection) field.get(listener);
|
||||
var server = serverPlayer.getServer();
|
||||
var playerList = server.getPlayerList();
|
||||
J.s(() -> {
|
||||
try {
|
||||
remove(serverPlayer);
|
||||
} catch (Throwable e) {
|
||||
Iris.error("Failed to remove player " + player.getName());
|
||||
e.printStackTrace();
|
||||
return;
|
||||
}
|
||||
var result = playerList.canPlayerLogin(new ServerLoginPacketListenerImpl(server, connection), serverPlayer.getGameProfile());
|
||||
if (result != null) {
|
||||
playerList.placeNewPlayer(connection, result);
|
||||
}
|
||||
});
|
||||
} catch (Throwable e) {
|
||||
Iris.error("Failed to reconnect player " + player.getName());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private void remove(ServerPlayer player) throws NoSuchFieldException, IllegalAccessException {
|
||||
ServerLevel level = player.getLevel();
|
||||
player.awardStat(Stats.LEAVE_GAME);
|
||||
if (player.containerMenu != player.inventoryMenu) {
|
||||
player.closeContainer();
|
||||
}
|
||||
|
||||
PlayerQuitEvent playerQuitEvent = new PlayerQuitEvent(player.getBukkitEntity(), "§e" + player.getScoreboardName() + " left the game");
|
||||
Bukkit.getPluginManager().callEvent(playerQuitEvent);
|
||||
player.getBukkitEntity().disconnect(playerQuitEvent.getQuitMessage());
|
||||
player.doTick();
|
||||
|
||||
level.getServer().getPlayerList().playerIo.save(player);
|
||||
ServerStatsCounter stats = player.getStats();
|
||||
if (stats != null) stats.save();
|
||||
PlayerAdvancements advancements = player.getAdvancements();
|
||||
if (advancements != null) advancements.save();
|
||||
|
||||
if (player.isPassenger()) {
|
||||
var vehicle = player.getRootVehicle();
|
||||
if (vehicle.hasExactlyOnePlayerPassenger()) {
|
||||
Iris.debug("Removing player mount");
|
||||
player.stopRiding();
|
||||
vehicle.getPassengersAndSelf().forEach(passenger -> passenger.setRemoved(net.minecraft.world.entity.Entity.RemovalReason.UNLOADED_WITH_PLAYER));
|
||||
}
|
||||
}
|
||||
|
||||
player.unRide();
|
||||
level.removePlayerImmediately(player, net.minecraft.world.entity.Entity.RemovalReason.UNLOADED_WITH_PLAYER);
|
||||
player.getAdvancements().stopListening();
|
||||
|
||||
var playersField = getField(PlayerList.class, buildType(List.class, ServerPlayer.class.getName()));
|
||||
playersField.setAccessible(true);
|
||||
var playersByNameField = getField(PlayerList.class, buildType(Map.class, String.class.getName(), ServerPlayer.class.getName()));
|
||||
playersByNameField.setAccessible(true);
|
||||
var playersByUUIDField = getField(PlayerList.class, buildType(Map.class, UUID.class.getName(), ServerPlayer.class.getName()));
|
||||
playersByUUIDField.setAccessible(true);
|
||||
|
||||
var players = (List<ServerPlayer>)playersField.get(player.getServer().getPlayerList());
|
||||
var playersByName = (Map<String, ServerPlayer>)playersByNameField.get(player.getServer().getPlayerList());
|
||||
var playersByUUID = (Map<UUID, ServerPlayer>)playersByUUIDField.get(player.getServer().getPlayerList());
|
||||
|
||||
players.remove(player);
|
||||
playersByName.remove(player.getScoreboardName().toLowerCase(Locale.ROOT));
|
||||
level.getServer().getCustomBossEvents().onPlayerDisconnect(player);
|
||||
UUID uuid = player.getUUID();
|
||||
ServerPlayer currentPlayer = playersByUUID.get(uuid);
|
||||
if (currentPlayer == player) {
|
||||
playersByUUID.remove(uuid);
|
||||
}
|
||||
|
||||
ClientboundPlayerInfoRemovePacket packet = new ClientboundPlayerInfoRemovePacket(List.of(player.getUUID()));
|
||||
for (ServerPlayer target : players) {
|
||||
if (target.getBukkitEntity().canSee(player.getBukkitEntity())) {
|
||||
target.connection.send(packet);
|
||||
} else {
|
||||
target.getBukkitEntity().onEntityRemove(player);
|
||||
}
|
||||
}
|
||||
|
||||
((CraftScoreboardManager) Bukkit.getScoreboardManager()).removePlayer(player.getBukkitEntity());
|
||||
}
|
||||
|
||||
private static Field getField(Class<?> clazz, Class<?> fieldType) throws NoSuchFieldException {
|
||||
try {
|
||||
for (Field f : clazz.getDeclaredFields()) {
|
||||
|
@ -65,12 +65,20 @@ import net.minecraft.core.RegistryAccess;
|
||||
import net.minecraft.core.registries.Registries;
|
||||
import net.minecraft.nbt.*;
|
||||
import net.minecraft.nbt.Tag;
|
||||
import net.minecraft.network.Connection;
|
||||
import net.minecraft.network.protocol.game.ClientboundPlayerInfoRemovePacket;
|
||||
import net.minecraft.resources.RegistryOps;
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.PlayerAdvancements;
|
||||
import net.minecraft.server.commands.data.BlockDataAccessor;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.server.network.ServerLoginPacketListenerImpl;
|
||||
import net.minecraft.server.players.PlayerList;
|
||||
import net.minecraft.stats.ServerStatsCounter;
|
||||
import net.minecraft.stats.Stats;
|
||||
import net.minecraft.tags.TagKey;
|
||||
import net.minecraft.world.entity.EntityDimensions;
|
||||
import net.minecraft.world.level.LevelReader;
|
||||
@ -104,10 +112,14 @@ import org.bukkit.craftbukkit.v1_20_R1.block.CraftBlockState;
|
||||
import org.bukkit.craftbukkit.v1_20_R1.block.CraftBlockStates;
|
||||
import org.bukkit.craftbukkit.v1_20_R1.block.data.CraftBlockData;
|
||||
import org.bukkit.craftbukkit.v1_20_R1.entity.CraftDolphin;
|
||||
import org.bukkit.craftbukkit.v1_20_R1.entity.CraftPlayer;
|
||||
import org.bukkit.craftbukkit.v1_20_R1.inventory.CraftItemStack;
|
||||
import org.bukkit.craftbukkit.v1_20_R1.scoreboard.CraftScoreboardManager;
|
||||
import org.bukkit.entity.Dolphin;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.entity.CreatureSpawnEvent;
|
||||
import org.bukkit.event.player.PlayerQuitEvent;
|
||||
import org.bukkit.generator.BiomeProvider;
|
||||
import org.bukkit.generator.ChunkGenerator;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
@ -120,11 +132,7 @@ import java.io.*;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Vector;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.logging.Logger;
|
||||
@ -839,6 +847,99 @@ public class NMSBinding implements INMSBinding {
|
||||
return keys;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reconnect(Player player) {
|
||||
var serverPlayer = ((CraftPlayer) player).getHandle();
|
||||
var listener = serverPlayer.connection;
|
||||
|
||||
try {
|
||||
var field = getField(listener.getClass(), Connection.class);
|
||||
field.setAccessible(true);
|
||||
var connection = (Connection) field.get(listener);
|
||||
var server = serverPlayer.getServer();
|
||||
var playerList = server.getPlayerList();
|
||||
J.s(() -> {
|
||||
try {
|
||||
remove(serverPlayer);
|
||||
} catch (Throwable e) {
|
||||
Iris.error("Failed to remove player " + player.getName());
|
||||
e.printStackTrace();
|
||||
return;
|
||||
}
|
||||
var result = playerList.canPlayerLogin(new ServerLoginPacketListenerImpl(server, connection), serverPlayer.getGameProfile());
|
||||
if (result != null) {
|
||||
playerList.placeNewPlayer(connection, result);
|
||||
}
|
||||
});
|
||||
} catch (Throwable e) {
|
||||
Iris.error("Failed to reconnect player " + player.getName());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private void remove(ServerPlayer player) throws NoSuchFieldException, IllegalAccessException {
|
||||
ServerLevel level = player.serverLevel();
|
||||
player.awardStat(Stats.LEAVE_GAME);
|
||||
if (player.containerMenu != player.inventoryMenu) {
|
||||
player.closeContainer();
|
||||
}
|
||||
|
||||
PlayerQuitEvent playerQuitEvent = new PlayerQuitEvent(player.getBukkitEntity(), "§e" + player.getScoreboardName() + " left the game");
|
||||
Bukkit.getPluginManager().callEvent(playerQuitEvent);
|
||||
player.getBukkitEntity().disconnect(playerQuitEvent.getQuitMessage());
|
||||
player.doTick();
|
||||
|
||||
level.getServer().getPlayerList().playerIo.save(player);
|
||||
ServerStatsCounter stats = player.getStats();
|
||||
if (stats != null) stats.save();
|
||||
PlayerAdvancements advancements = player.getAdvancements();
|
||||
if (advancements != null) advancements.save();
|
||||
|
||||
if (player.isPassenger()) {
|
||||
var vehicle = player.getRootVehicle();
|
||||
if (vehicle.hasExactlyOnePlayerPassenger()) {
|
||||
Iris.debug("Removing player mount");
|
||||
player.stopRiding();
|
||||
vehicle.getPassengersAndSelf().forEach(passenger -> passenger.setRemoved(net.minecraft.world.entity.Entity.RemovalReason.UNLOADED_WITH_PLAYER));
|
||||
}
|
||||
}
|
||||
|
||||
player.unRide();
|
||||
level.removePlayerImmediately(player, net.minecraft.world.entity.Entity.RemovalReason.UNLOADED_WITH_PLAYER);
|
||||
player.getAdvancements().stopListening();
|
||||
|
||||
var playersField = getField(PlayerList.class, buildType(List.class, ServerPlayer.class.getName()));
|
||||
playersField.setAccessible(true);
|
||||
var playersByNameField = getField(PlayerList.class, buildType(Map.class, String.class.getName(), ServerPlayer.class.getName()));
|
||||
playersByNameField.setAccessible(true);
|
||||
var playersByUUIDField = getField(PlayerList.class, buildType(Map.class, UUID.class.getName(), ServerPlayer.class.getName()));
|
||||
playersByUUIDField.setAccessible(true);
|
||||
|
||||
var players = (List<ServerPlayer>)playersField.get(player.getServer().getPlayerList());
|
||||
var playersByName = (Map<String, ServerPlayer>)playersByNameField.get(player.getServer().getPlayerList());
|
||||
var playersByUUID = (Map<UUID, ServerPlayer>)playersByUUIDField.get(player.getServer().getPlayerList());
|
||||
|
||||
players.remove(player);
|
||||
playersByName.remove(player.getScoreboardName().toLowerCase(Locale.ROOT));
|
||||
level.getServer().getCustomBossEvents().onPlayerDisconnect(player);
|
||||
UUID uuid = player.getUUID();
|
||||
ServerPlayer currentPlayer = playersByUUID.get(uuid);
|
||||
if (currentPlayer == player) {
|
||||
playersByUUID.remove(uuid);
|
||||
}
|
||||
|
||||
ClientboundPlayerInfoRemovePacket packet = new ClientboundPlayerInfoRemovePacket(List.of(player.getUUID()));
|
||||
for (ServerPlayer target : players) {
|
||||
if (target.getBukkitEntity().canSee(player.getBukkitEntity())) {
|
||||
target.connection.send(packet);
|
||||
} else {
|
||||
target.getBukkitEntity().onEntityRemove(player);
|
||||
}
|
||||
}
|
||||
|
||||
((CraftScoreboardManager) Bukkit.getScoreboardManager()).removePlayer(player.getBukkitEntity());
|
||||
}
|
||||
|
||||
private static Field getField(Class<?> clazz, Class<?> fieldType) throws NoSuchFieldException {
|
||||
try {
|
||||
for (Field f : clazz.getDeclaredFields()) {
|
||||
|
@ -23,11 +23,7 @@ import java.io.*;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Vector;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.logging.Logger;
|
||||
@ -40,8 +36,17 @@ import com.volmit.iris.engine.object.IrisBiomeReplacement;
|
||||
import com.volmit.iris.util.scheduling.J;
|
||||
import net.minecraft.nbt.*;
|
||||
import net.minecraft.nbt.Tag;
|
||||
import net.minecraft.network.Connection;
|
||||
import net.minecraft.network.protocol.game.ClientboundPlayerInfoRemovePacket;
|
||||
import net.minecraft.resources.RegistryOps;
|
||||
import net.minecraft.server.PlayerAdvancements;
|
||||
import net.minecraft.server.commands.data.BlockDataAccessor;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.server.network.CommonListenerCookie;
|
||||
import net.minecraft.server.network.ServerLoginPacketListenerImpl;
|
||||
import net.minecraft.server.players.PlayerList;
|
||||
import net.minecraft.stats.ServerStatsCounter;
|
||||
import net.minecraft.stats.Stats;
|
||||
import net.minecraft.tags.TagKey;
|
||||
import com.volmit.iris.core.nms.container.IPackRepository;
|
||||
import com.volmit.iris.util.io.IO;
|
||||
@ -85,12 +90,16 @@ import org.bukkit.craftbukkit.v1_20_R2.block.CraftBlockState;
|
||||
import org.bukkit.craftbukkit.v1_20_R2.block.CraftBlockStates;
|
||||
import org.bukkit.craftbukkit.v1_20_R2.block.data.CraftBlockData;
|
||||
import org.bukkit.craftbukkit.v1_20_R2.entity.CraftDolphin;
|
||||
import org.bukkit.craftbukkit.v1_20_R2.entity.CraftPlayer;
|
||||
import org.bukkit.craftbukkit.v1_20_R2.inventory.CraftItemStack;
|
||||
import org.bukkit.craftbukkit.v1_20_R2.packs.CraftDataPackManager;
|
||||
import org.bukkit.craftbukkit.v1_20_R2.scoreboard.CraftScoreboardManager;
|
||||
import org.bukkit.craftbukkit.v1_20_R2.util.CraftNamespacedKey;
|
||||
import org.bukkit.entity.Dolphin;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.entity.CreatureSpawnEvent;
|
||||
import org.bukkit.event.player.PlayerQuitEvent;
|
||||
import org.bukkit.generator.BiomeProvider;
|
||||
import org.bukkit.generator.ChunkGenerator;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
@ -841,6 +850,101 @@ public class NMSBinding implements INMSBinding {
|
||||
return keys;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reconnect(Player player) {
|
||||
var serverPlayer = ((CraftPlayer) player).getHandle();
|
||||
var listener = serverPlayer.connection;
|
||||
var cookie = new CommonListenerCookie(serverPlayer.getGameProfile(), listener.latency(), serverPlayer.clientInformation());
|
||||
|
||||
try {
|
||||
var field = getField(listener.getClass(), Connection.class);
|
||||
field.setAccessible(true);
|
||||
var connection = (Connection) field.get(listener);
|
||||
var server = serverPlayer.getServer();
|
||||
var playerList = server.getPlayerList();
|
||||
J.s(() -> {
|
||||
try {
|
||||
remove(serverPlayer);
|
||||
} catch (Throwable e) {
|
||||
Iris.error("Failed to remove player " + player.getName());
|
||||
e.printStackTrace();
|
||||
return;
|
||||
}
|
||||
var result = playerList.canPlayerLogin(new ServerLoginPacketListenerImpl(server, connection), cookie.gameProfile());
|
||||
if (result != null) {
|
||||
result.updateOptions(cookie.clientInformation());
|
||||
playerList.placeNewPlayer(connection, result, cookie);
|
||||
}
|
||||
});
|
||||
} catch (Throwable e) {
|
||||
Iris.error("Failed to reconnect player " + player.getName());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private void remove(ServerPlayer player) throws NoSuchFieldException, IllegalAccessException {
|
||||
ServerLevel level = player.serverLevel();
|
||||
player.awardStat(Stats.LEAVE_GAME);
|
||||
if (player.containerMenu != player.inventoryMenu) {
|
||||
player.closeContainer();
|
||||
}
|
||||
|
||||
PlayerQuitEvent playerQuitEvent = new PlayerQuitEvent(player.getBukkitEntity(), "§e" + player.getScoreboardName() + " left the game");
|
||||
Bukkit.getPluginManager().callEvent(playerQuitEvent);
|
||||
player.getBukkitEntity().disconnect(playerQuitEvent.getQuitMessage());
|
||||
player.doTick();
|
||||
|
||||
level.getServer().getPlayerList().playerIo.save(player);
|
||||
ServerStatsCounter stats = player.getStats();
|
||||
if (stats != null) stats.save();
|
||||
PlayerAdvancements advancements = player.getAdvancements();
|
||||
if (advancements != null) advancements.save();
|
||||
|
||||
if (player.isPassenger()) {
|
||||
var vehicle = player.getRootVehicle();
|
||||
if (vehicle.hasExactlyOnePlayerPassenger()) {
|
||||
Iris.debug("Removing player mount");
|
||||
player.stopRiding();
|
||||
vehicle.getPassengersAndSelf().forEach(passenger -> passenger.setRemoved(net.minecraft.world.entity.Entity.RemovalReason.UNLOADED_WITH_PLAYER));
|
||||
}
|
||||
}
|
||||
|
||||
player.unRide();
|
||||
level.removePlayerImmediately(player, net.minecraft.world.entity.Entity.RemovalReason.UNLOADED_WITH_PLAYER);
|
||||
player.getAdvancements().stopListening();
|
||||
|
||||
var playersField = getField(PlayerList.class, buildType(List.class, ServerPlayer.class.getName()));
|
||||
playersField.setAccessible(true);
|
||||
var playersByNameField = getField(PlayerList.class, buildType(Map.class, String.class.getName(), ServerPlayer.class.getName()));
|
||||
playersByNameField.setAccessible(true);
|
||||
var playersByUUIDField = getField(PlayerList.class, buildType(Map.class, UUID.class.getName(), ServerPlayer.class.getName()));
|
||||
playersByUUIDField.setAccessible(true);
|
||||
|
||||
var players = (List<ServerPlayer>)playersField.get(player.getServer().getPlayerList());
|
||||
var playersByName = (Map<String, ServerPlayer>)playersByNameField.get(player.getServer().getPlayerList());
|
||||
var playersByUUID = (Map<UUID, ServerPlayer>)playersByUUIDField.get(player.getServer().getPlayerList());
|
||||
|
||||
players.remove(player);
|
||||
playersByName.remove(player.getScoreboardName().toLowerCase(Locale.ROOT));
|
||||
level.getServer().getCustomBossEvents().onPlayerDisconnect(player);
|
||||
UUID uuid = player.getUUID();
|
||||
ServerPlayer currentPlayer = playersByUUID.get(uuid);
|
||||
if (currentPlayer == player) {
|
||||
playersByUUID.remove(uuid);
|
||||
}
|
||||
|
||||
ClientboundPlayerInfoRemovePacket packet = new ClientboundPlayerInfoRemovePacket(List.of(player.getUUID()));
|
||||
for (ServerPlayer target : players) {
|
||||
if (target.getBukkitEntity().canSee(player.getBukkitEntity())) {
|
||||
target.connection.send(packet);
|
||||
} else {
|
||||
target.getBukkitEntity().onEntityRemove(player);
|
||||
}
|
||||
}
|
||||
|
||||
((CraftScoreboardManager) Bukkit.getScoreboardManager()).removePlayer(player.getBukkitEntity());
|
||||
}
|
||||
|
||||
private static Field getField(Class<?> clazz, Class<?> fieldType) throws NoSuchFieldException {
|
||||
try {
|
||||
for (Field f : clazz.getDeclaredFields()) {
|
||||
|
@ -33,7 +33,6 @@ import java.util.stream.Collectors;
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonNull;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.mojang.datafixers.util.Pair;
|
||||
import com.mojang.serialization.Codec;
|
||||
import com.mojang.serialization.JsonOps;
|
||||
@ -50,25 +49,25 @@ import com.volmit.iris.util.io.IO;
|
||||
import it.unimi.dsi.fastutil.objects.Reference2IntMap;
|
||||
import net.bytebuddy.ByteBuddy;
|
||||
import net.bytebuddy.asm.Advice;
|
||||
import net.bytebuddy.description.method.MethodDescription;
|
||||
import net.bytebuddy.description.type.TypeDescription;
|
||||
import net.bytebuddy.dynamic.loading.ClassReloadingStrategy;
|
||||
import net.bytebuddy.implementation.bytecode.StackManipulation;
|
||||
import net.bytebuddy.implementation.bytecode.assign.Assigner;
|
||||
import net.bytebuddy.implementation.bytecode.member.MethodInvocation;
|
||||
import net.bytebuddy.matcher.ElementMatchers;
|
||||
import net.minecraft.core.IdMapper;
|
||||
import net.minecraft.core.MappedRegistry;
|
||||
import net.minecraft.core.registries.BuiltInRegistries;
|
||||
import net.minecraft.network.Connection;
|
||||
import net.minecraft.network.protocol.game.ClientboundPlayerInfoRemovePacket;
|
||||
import net.minecraft.resources.RegistryOps;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.PlayerAdvancements;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.server.level.progress.ChunkProgressListener;
|
||||
import net.minecraft.server.network.CommonListenerCookie;
|
||||
import net.minecraft.server.network.ServerLoginPacketListenerImpl;
|
||||
import net.minecraft.server.players.PlayerList;
|
||||
import net.minecraft.stats.ServerStatsCounter;
|
||||
import net.minecraft.stats.Stats;
|
||||
import net.minecraft.util.GsonHelper;
|
||||
import net.minecraft.world.RandomSequences;
|
||||
import net.minecraft.world.entity.MobCategory;
|
||||
import net.minecraft.world.entity.MobSpawnType;
|
||||
import net.minecraft.world.entity.MobType;
|
||||
import net.minecraft.world.entity.ai.behavior.TryLaySpawnOnWaterNearLand;
|
||||
import net.minecraft.world.level.ChunkPos;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.LevelHeightAccessor;
|
||||
@ -80,7 +79,6 @@ import net.minecraft.world.level.dimension.DimensionType;
|
||||
import net.minecraft.world.level.dimension.LevelStem;
|
||||
import net.minecraft.world.level.storage.LevelStorageSource;
|
||||
import net.minecraft.world.level.storage.PrimaryLevelData;
|
||||
import com.mojang.datafixers.util.Pair;
|
||||
import com.volmit.iris.core.nms.container.BiomeColor;
|
||||
import com.volmit.iris.util.scheduling.J;
|
||||
import net.minecraft.nbt.*;
|
||||
@ -98,14 +96,14 @@ import org.bukkit.craftbukkit.v1_20_R3.CraftWorld;
|
||||
import org.bukkit.craftbukkit.v1_20_R3.block.CraftBlockState;
|
||||
import org.bukkit.craftbukkit.v1_20_R3.block.CraftBlockStates;
|
||||
import org.bukkit.craftbukkit.v1_20_R3.block.data.CraftBlockData;
|
||||
import org.bukkit.craftbukkit.v1_20_R3.entity.CraftDolphin;
|
||||
import org.bukkit.craftbukkit.v1_20_R3.entity.CraftPlayer;
|
||||
import org.bukkit.craftbukkit.v1_20_R3.inventory.CraftItemStack;
|
||||
import org.bukkit.craftbukkit.v1_20_R3.scoreboard.CraftScoreboardManager;
|
||||
import org.bukkit.craftbukkit.v1_20_R3.util.CraftNamespacedKey;
|
||||
import org.bukkit.entity.Dolphin;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.EntityCategory;
|
||||
import org.bukkit.entity.Mob;
|
||||
import org.bukkit.entity.*;
|
||||
import org.bukkit.event.entity.CreatureSpawnEvent;
|
||||
import org.bukkit.event.entity.EntityRemoveEvent;
|
||||
import org.bukkit.event.player.PlayerQuitEvent;
|
||||
import org.bukkit.generator.BiomeProvider;
|
||||
import org.bukkit.generator.ChunkGenerator;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
@ -124,7 +122,6 @@ import com.volmit.iris.util.json.JSONObject;
|
||||
import com.volmit.iris.util.mantle.Mantle;
|
||||
import com.volmit.iris.util.math.Vector3d;
|
||||
import com.volmit.iris.util.matter.MatterBiomeInject;
|
||||
import com.volmit.iris.util.nbt.io.NBTUtil;
|
||||
import com.volmit.iris.util.nbt.mca.NBTWorld;
|
||||
import com.volmit.iris.util.nbt.mca.palette.*;
|
||||
import com.volmit.iris.util.nbt.tag.CompoundTag;
|
||||
@ -139,14 +136,12 @@ import net.minecraft.resources.ResourceKey;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.world.entity.EntityType;
|
||||
import net.minecraft.world.level.biome.BiomeSource;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.chunk.ChunkAccess;
|
||||
import net.minecraft.world.level.chunk.ChunkStatus;
|
||||
import net.minecraft.world.level.chunk.LevelChunk;
|
||||
import sun.misc.Unsafe;
|
||||
|
||||
import static net.bytebuddy.matcher.ElementMatchers.takesArguments;
|
||||
|
||||
@ -893,6 +888,101 @@ public class NMSBinding implements INMSBinding {
|
||||
return keys;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reconnect(Player player) {
|
||||
var serverPlayer = ((CraftPlayer) player).getHandle();
|
||||
var listener = serverPlayer.connection;
|
||||
var cookie = new CommonListenerCookie(serverPlayer.getGameProfile(), listener.latency(), serverPlayer.clientInformation());
|
||||
|
||||
try {
|
||||
var field = getField(listener.getClass(), Connection.class);
|
||||
field.setAccessible(true);
|
||||
var connection = (Connection) field.get(listener);
|
||||
var server = serverPlayer.getServer();
|
||||
var playerList = server.getPlayerList();
|
||||
J.s(() -> {
|
||||
try {
|
||||
remove(serverPlayer);
|
||||
} catch (Throwable e) {
|
||||
Iris.error("Failed to remove player " + player.getName());
|
||||
e.printStackTrace();
|
||||
return;
|
||||
}
|
||||
var result = playerList.canPlayerLogin(new ServerLoginPacketListenerImpl(server, connection), cookie.gameProfile());
|
||||
if (result != null) {
|
||||
result.updateOptions(cookie.clientInformation());
|
||||
playerList.placeNewPlayer(connection, result, cookie);
|
||||
}
|
||||
});
|
||||
} catch (Throwable e) {
|
||||
Iris.error("Failed to reconnect player " + player.getName());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private void remove(ServerPlayer player) throws NoSuchFieldException, IllegalAccessException {
|
||||
ServerLevel level = player.serverLevel();
|
||||
player.awardStat(Stats.LEAVE_GAME);
|
||||
if (player.containerMenu != player.inventoryMenu) {
|
||||
player.closeContainer();
|
||||
}
|
||||
|
||||
PlayerQuitEvent playerQuitEvent = new PlayerQuitEvent(player.getBukkitEntity(), "§e" + player.getScoreboardName() + " left the game");
|
||||
Bukkit.getPluginManager().callEvent(playerQuitEvent);
|
||||
player.getBukkitEntity().disconnect(playerQuitEvent.getQuitMessage());
|
||||
player.doTick();
|
||||
|
||||
level.getServer().getPlayerList().playerIo.save(player);
|
||||
ServerStatsCounter stats = player.getStats();
|
||||
if (stats != null) stats.save();
|
||||
PlayerAdvancements advancements = player.getAdvancements();
|
||||
if (advancements != null) advancements.save();
|
||||
|
||||
if (player.isPassenger()) {
|
||||
var vehicle = player.getRootVehicle();
|
||||
if (vehicle.hasExactlyOnePlayerPassenger()) {
|
||||
Iris.debug("Removing player mount");
|
||||
player.stopRiding();
|
||||
vehicle.getPassengersAndSelf().forEach(passenger -> passenger.setRemoved(net.minecraft.world.entity.Entity.RemovalReason.UNLOADED_WITH_PLAYER));
|
||||
}
|
||||
}
|
||||
|
||||
player.unRide();
|
||||
level.removePlayerImmediately(player, net.minecraft.world.entity.Entity.RemovalReason.UNLOADED_WITH_PLAYER);
|
||||
player.getAdvancements().stopListening();
|
||||
|
||||
var playersField = getField(PlayerList.class, buildType(List.class, ServerPlayer.class.getName()));
|
||||
playersField.setAccessible(true);
|
||||
var playersByNameField = getField(PlayerList.class, buildType(Map.class, String.class.getName(), ServerPlayer.class.getName()));
|
||||
playersByNameField.setAccessible(true);
|
||||
var playersByUUIDField = getField(PlayerList.class, buildType(Map.class, UUID.class.getName(), ServerPlayer.class.getName()));
|
||||
playersByUUIDField.setAccessible(true);
|
||||
|
||||
var players = (List<ServerPlayer>)playersField.get(player.getServer().getPlayerList());
|
||||
var playersByName = (Map<String, ServerPlayer>)playersByNameField.get(player.getServer().getPlayerList());
|
||||
var playersByUUID = (Map<UUID, ServerPlayer>)playersByUUIDField.get(player.getServer().getPlayerList());
|
||||
|
||||
players.remove(player);
|
||||
playersByName.remove(player.getScoreboardName().toLowerCase(Locale.ROOT));
|
||||
level.getServer().getCustomBossEvents().onPlayerDisconnect(player);
|
||||
UUID uuid = player.getUUID();
|
||||
ServerPlayer currentPlayer = playersByUUID.get(uuid);
|
||||
if (currentPlayer == player) {
|
||||
playersByUUID.remove(uuid);
|
||||
}
|
||||
|
||||
ClientboundPlayerInfoRemovePacket packet = new ClientboundPlayerInfoRemovePacket(List.of(player.getUUID()));
|
||||
for (ServerPlayer target : players) {
|
||||
if (target.getBukkitEntity().canSee(player.getBukkitEntity())) {
|
||||
target.connection.send(packet);
|
||||
} else {
|
||||
target.getBukkitEntity().onEntityRemove(player);
|
||||
}
|
||||
}
|
||||
|
||||
((CraftScoreboardManager) Bukkit.getScoreboardManager()).removePlayer(player.getBukkitEntity());
|
||||
}
|
||||
|
||||
private static Field getField(Class<?> clazz, Class<?> fieldType) throws NoSuchFieldException {
|
||||
try {
|
||||
for (Field f : clazz.getDeclaredFields()) {
|
||||
|
@ -23,11 +23,7 @@ import java.io.*;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Vector;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.logging.Logger;
|
||||
@ -61,9 +57,18 @@ import com.volmit.iris.util.scheduling.J;
|
||||
import net.minecraft.core.*;
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.core.component.DataComponents;
|
||||
import net.minecraft.network.Connection;
|
||||
import net.minecraft.network.protocol.game.ClientboundPlayerInfoRemovePacket;
|
||||
import net.minecraft.resources.RegistryOps;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.PlayerAdvancements;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.server.level.progress.ChunkProgressListener;
|
||||
import net.minecraft.server.network.CommonListenerCookie;
|
||||
import net.minecraft.server.network.ServerLoginPacketListenerImpl;
|
||||
import net.minecraft.server.players.PlayerList;
|
||||
import net.minecraft.stats.ServerStatsCounter;
|
||||
import net.minecraft.stats.Stats;
|
||||
import net.minecraft.util.GsonHelper;
|
||||
import net.minecraft.world.RandomSequences;
|
||||
import net.minecraft.nbt.*;
|
||||
@ -103,12 +108,16 @@ import org.bukkit.craftbukkit.v1_20_R4.block.CraftBlockStates;
|
||||
import org.bukkit.craftbukkit.v1_20_R4.block.CraftBlockType;
|
||||
import org.bukkit.craftbukkit.v1_20_R4.block.data.CraftBlockData;
|
||||
import org.bukkit.craftbukkit.v1_20_R4.entity.CraftDolphin;
|
||||
import org.bukkit.craftbukkit.v1_20_R4.entity.CraftPlayer;
|
||||
import org.bukkit.craftbukkit.v1_20_R4.generator.CustomChunkGenerator;
|
||||
import org.bukkit.craftbukkit.v1_20_R4.inventory.CraftItemStack;
|
||||
import org.bukkit.craftbukkit.v1_20_R4.scoreboard.CraftScoreboardManager;
|
||||
import org.bukkit.craftbukkit.v1_20_R4.util.CraftNamespacedKey;
|
||||
import org.bukkit.entity.Dolphin;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.entity.CreatureSpawnEvent;
|
||||
import org.bukkit.event.player.PlayerQuitEvent;
|
||||
import org.bukkit.generator.BiomeProvider;
|
||||
import org.bukkit.generator.ChunkGenerator;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
@ -935,6 +944,101 @@ public class NMSBinding implements INMSBinding {
|
||||
return keys;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reconnect(Player player) {
|
||||
var serverPlayer = ((CraftPlayer) player).getHandle();
|
||||
var listener = serverPlayer.connection;
|
||||
var cookie = new CommonListenerCookie(serverPlayer.getGameProfile(), listener.latency(), serverPlayer.clientInformation(), false);
|
||||
|
||||
try {
|
||||
var field = getField(listener.getClass(), Connection.class);
|
||||
field.setAccessible(true);
|
||||
var connection = (Connection) field.get(listener);
|
||||
var server = serverPlayer.getServer();
|
||||
var playerList = server.getPlayerList();
|
||||
J.s(() -> {
|
||||
try {
|
||||
remove(serverPlayer);
|
||||
} catch (Throwable e) {
|
||||
Iris.error("Failed to remove player " + player.getName());
|
||||
e.printStackTrace();
|
||||
return;
|
||||
}
|
||||
var result = playerList.canPlayerLogin(new ServerLoginPacketListenerImpl(server, connection, false), cookie.gameProfile());
|
||||
if (result != null) {
|
||||
result.updateOptions(cookie.clientInformation());
|
||||
playerList.placeNewPlayer(connection, result, cookie);
|
||||
}
|
||||
});
|
||||
} catch (Throwable e) {
|
||||
Iris.error("Failed to reconnect player " + player.getName());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private void remove(ServerPlayer player) throws NoSuchFieldException, IllegalAccessException {
|
||||
ServerLevel level = player.serverLevel();
|
||||
player.awardStat(Stats.LEAVE_GAME);
|
||||
if (player.containerMenu != player.inventoryMenu) {
|
||||
player.closeContainer();
|
||||
}
|
||||
|
||||
PlayerQuitEvent playerQuitEvent = new PlayerQuitEvent(player.getBukkitEntity(), "§e" + player.getScoreboardName() + " left the game");
|
||||
Bukkit.getPluginManager().callEvent(playerQuitEvent);
|
||||
player.getBukkitEntity().disconnect(playerQuitEvent.getQuitMessage());
|
||||
player.doTick();
|
||||
|
||||
level.getServer().getPlayerList().playerIo.save(player);
|
||||
ServerStatsCounter stats = player.getStats();
|
||||
if (stats != null) stats.save();
|
||||
PlayerAdvancements advancements = player.getAdvancements();
|
||||
if (advancements != null) advancements.save();
|
||||
|
||||
if (player.isPassenger()) {
|
||||
var vehicle = player.getRootVehicle();
|
||||
if (vehicle.hasExactlyOnePlayerPassenger()) {
|
||||
Iris.debug("Removing player mount");
|
||||
player.stopRiding();
|
||||
vehicle.getPassengersAndSelf().forEach(passenger -> passenger.setRemoved(net.minecraft.world.entity.Entity.RemovalReason.UNLOADED_WITH_PLAYER));
|
||||
}
|
||||
}
|
||||
|
||||
player.unRide();
|
||||
level.removePlayerImmediately(player, net.minecraft.world.entity.Entity.RemovalReason.UNLOADED_WITH_PLAYER);
|
||||
player.getAdvancements().stopListening();
|
||||
|
||||
var playersField = getField(PlayerList.class, buildType(List.class, ServerPlayer.class.getName()));
|
||||
playersField.setAccessible(true);
|
||||
var playersByNameField = getField(PlayerList.class, buildType(Map.class, String.class.getName(), ServerPlayer.class.getName()));
|
||||
playersByNameField.setAccessible(true);
|
||||
var playersByUUIDField = getField(PlayerList.class, buildType(Map.class, UUID.class.getName(), ServerPlayer.class.getName()));
|
||||
playersByUUIDField.setAccessible(true);
|
||||
|
||||
var players = (List<ServerPlayer>)playersField.get(player.getServer().getPlayerList());
|
||||
var playersByName = (Map<String, ServerPlayer>)playersByNameField.get(player.getServer().getPlayerList());
|
||||
var playersByUUID = (Map<UUID, ServerPlayer>)playersByUUIDField.get(player.getServer().getPlayerList());
|
||||
|
||||
players.remove(player);
|
||||
playersByName.remove(player.getScoreboardName().toLowerCase(Locale.ROOT));
|
||||
level.getServer().getCustomBossEvents().onPlayerDisconnect(player);
|
||||
UUID uuid = player.getUUID();
|
||||
ServerPlayer currentPlayer = playersByUUID.get(uuid);
|
||||
if (currentPlayer == player) {
|
||||
playersByUUID.remove(uuid);
|
||||
}
|
||||
|
||||
ClientboundPlayerInfoRemovePacket packet = new ClientboundPlayerInfoRemovePacket(List.of(player.getUUID()));
|
||||
for (ServerPlayer target : players) {
|
||||
if (target.getBukkitEntity().canSee(player.getBukkitEntity())) {
|
||||
target.connection.send(packet);
|
||||
} else {
|
||||
target.getBukkitEntity().onEntityRemove(player);
|
||||
}
|
||||
}
|
||||
|
||||
((CraftScoreboardManager) Bukkit.getScoreboardManager()).removePlayer(player.getBukkitEntity());
|
||||
}
|
||||
|
||||
@Override
|
||||
public IPackRepository getPackRepository() {
|
||||
return packRepository;
|
||||
|
@ -56,10 +56,19 @@ import com.volmit.iris.util.scheduling.J;
|
||||
import net.minecraft.core.component.DataComponents;
|
||||
import net.minecraft.nbt.*;
|
||||
import net.minecraft.nbt.Tag;
|
||||
import net.minecraft.network.Connection;
|
||||
import net.minecraft.network.protocol.game.ClientboundPlayerInfoRemovePacket;
|
||||
import net.minecraft.resources.RegistryOps;
|
||||
import net.minecraft.server.PlayerAdvancements;
|
||||
import net.minecraft.server.commands.data.BlockDataAccessor;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.level.ChunkMap;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.server.network.CommonListenerCookie;
|
||||
import net.minecraft.server.network.ServerLoginPacketListenerImpl;
|
||||
import net.minecraft.server.players.PlayerList;
|
||||
import net.minecraft.stats.ServerStatsCounter;
|
||||
import net.minecraft.stats.Stats;
|
||||
import net.minecraft.tags.TagKey;
|
||||
import net.minecraft.server.level.progress.ChunkProgressListener;
|
||||
import net.minecraft.util.GsonHelper;
|
||||
@ -86,11 +95,15 @@ import org.bukkit.craftbukkit.v1_21_R1.block.CraftBlockState;
|
||||
import org.bukkit.craftbukkit.v1_21_R1.block.CraftBlockStates;
|
||||
import org.bukkit.craftbukkit.v1_21_R1.block.data.CraftBlockData;
|
||||
import org.bukkit.craftbukkit.v1_21_R1.entity.CraftDolphin;
|
||||
import org.bukkit.craftbukkit.v1_21_R1.entity.CraftPlayer;
|
||||
import org.bukkit.craftbukkit.v1_21_R1.inventory.CraftItemStack;
|
||||
import org.bukkit.craftbukkit.v1_21_R1.scoreboard.CraftScoreboardManager;
|
||||
import org.bukkit.craftbukkit.v1_21_R1.util.CraftNamespacedKey;
|
||||
import org.bukkit.entity.Dolphin;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.entity.CreatureSpawnEvent;
|
||||
import org.bukkit.event.player.PlayerQuitEvent;
|
||||
import org.bukkit.generator.BiomeProvider;
|
||||
import org.bukkit.generator.ChunkGenerator;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
@ -930,6 +943,101 @@ public class NMSBinding implements INMSBinding {
|
||||
return keys;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reconnect(Player player) {
|
||||
var serverPlayer = ((CraftPlayer) player).getHandle();
|
||||
var listener = serverPlayer.connection;
|
||||
var cookie = new CommonListenerCookie(serverPlayer.getGameProfile(), listener.latency(), serverPlayer.clientInformation(), false);
|
||||
|
||||
try {
|
||||
var field = getField(listener.getClass(), Connection.class);
|
||||
field.setAccessible(true);
|
||||
var connection = (Connection) field.get(listener);
|
||||
var server = serverPlayer.getServer();
|
||||
var playerList = server.getPlayerList();
|
||||
J.s(() -> {
|
||||
try {
|
||||
remove(serverPlayer);
|
||||
} catch (Throwable e) {
|
||||
Iris.error("Failed to remove player " + player.getName());
|
||||
e.printStackTrace();
|
||||
return;
|
||||
}
|
||||
var result = playerList.canPlayerLogin(new ServerLoginPacketListenerImpl(server, connection, false), cookie.gameProfile());
|
||||
if (result != null) {
|
||||
result.updateOptions(cookie.clientInformation());
|
||||
playerList.placeNewPlayer(connection, result, cookie);
|
||||
}
|
||||
});
|
||||
} catch (Throwable e) {
|
||||
Iris.error("Failed to reconnect player " + player.getName());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private void remove(ServerPlayer player) throws NoSuchFieldException, IllegalAccessException {
|
||||
ServerLevel level = player.serverLevel();
|
||||
player.awardStat(Stats.LEAVE_GAME);
|
||||
if (player.containerMenu != player.inventoryMenu) {
|
||||
player.closeContainer();
|
||||
}
|
||||
|
||||
PlayerQuitEvent playerQuitEvent = new PlayerQuitEvent(player.getBukkitEntity(), "§e" + player.getScoreboardName() + " left the game");
|
||||
Bukkit.getPluginManager().callEvent(playerQuitEvent);
|
||||
player.getBukkitEntity().disconnect(playerQuitEvent.getQuitMessage());
|
||||
player.doTick();
|
||||
|
||||
level.getServer().getPlayerList().playerIo.save(player);
|
||||
ServerStatsCounter stats = player.getStats();
|
||||
if (stats != null) stats.save();
|
||||
PlayerAdvancements advancements = player.getAdvancements();
|
||||
if (advancements != null) advancements.save();
|
||||
|
||||
if (player.isPassenger()) {
|
||||
var vehicle = player.getRootVehicle();
|
||||
if (vehicle.hasExactlyOnePlayerPassenger()) {
|
||||
Iris.debug("Removing player mount");
|
||||
player.stopRiding();
|
||||
vehicle.getPassengersAndSelf().forEach(passenger -> passenger.setRemoved(net.minecraft.world.entity.Entity.RemovalReason.UNLOADED_WITH_PLAYER));
|
||||
}
|
||||
}
|
||||
|
||||
player.unRide();
|
||||
level.removePlayerImmediately(player, net.minecraft.world.entity.Entity.RemovalReason.UNLOADED_WITH_PLAYER);
|
||||
player.getAdvancements().stopListening();
|
||||
|
||||
var playersField = getField(PlayerList.class, buildType(List.class, ServerPlayer.class.getName()));
|
||||
playersField.setAccessible(true);
|
||||
var playersByNameField = getField(PlayerList.class, buildType(Map.class, String.class.getName(), ServerPlayer.class.getName()));
|
||||
playersByNameField.setAccessible(true);
|
||||
var playersByUUIDField = getField(PlayerList.class, buildType(Map.class, UUID.class.getName(), ServerPlayer.class.getName()));
|
||||
playersByUUIDField.setAccessible(true);
|
||||
|
||||
var players = (List<ServerPlayer>)playersField.get(player.getServer().getPlayerList());
|
||||
var playersByName = (Map<String, ServerPlayer>)playersByNameField.get(player.getServer().getPlayerList());
|
||||
var playersByUUID = (Map<UUID, ServerPlayer>)playersByUUIDField.get(player.getServer().getPlayerList());
|
||||
|
||||
players.remove(player);
|
||||
playersByName.remove(player.getScoreboardName().toLowerCase(Locale.ROOT));
|
||||
level.getServer().getCustomBossEvents().onPlayerDisconnect(player);
|
||||
UUID uuid = player.getUUID();
|
||||
ServerPlayer currentPlayer = playersByUUID.get(uuid);
|
||||
if (currentPlayer == player) {
|
||||
playersByUUID.remove(uuid);
|
||||
}
|
||||
|
||||
ClientboundPlayerInfoRemovePacket packet = new ClientboundPlayerInfoRemovePacket(List.of(player.getUUID()));
|
||||
for (ServerPlayer target : players) {
|
||||
if (target.getBukkitEntity().canSee(player.getBukkitEntity())) {
|
||||
target.connection.send(packet);
|
||||
} else {
|
||||
target.getBukkitEntity().onEntityRemove(player);
|
||||
}
|
||||
}
|
||||
|
||||
((CraftScoreboardManager) Bukkit.getScoreboardManager()).removePlayer(player.getBukkitEntity());
|
||||
}
|
||||
|
||||
@Override
|
||||
public IPackRepository getPackRepository() {
|
||||
return packRepository;
|
||||
|
Loading…
x
Reference in New Issue
Block a user