package net.minecraft.server.players;

import org.apache.logging.log4j.LogManager;
import net.minecraft.network.protocol.game.ClientboundSetChunkCacheRadiusPacket;
import net.minecraft.world.level.storage.LevelResource;
import net.minecraft.network.protocol.game.ClientboundChatPacket;
import net.minecraft.world.inventory.AbstractContainerMenu;
import net.minecraft.network.protocol.game.ClientboundSetTimePacket;
import net.minecraft.network.protocol.game.ClientboundEntityEventPacket;
import java.util.Collection;
import net.minecraft.world.scores.Team;
import net.minecraft.core.BlockPos;
import net.minecraft.network.protocol.game.ClientboundSoundPacket;
import net.minecraft.sounds.SoundSource;
import net.minecraft.sounds.SoundEvents;
import net.minecraft.network.protocol.game.ClientboundSetExperiencePacket;
import net.minecraft.network.protocol.game.ClientboundSetDefaultSpawnPositionPacket;
import net.minecraft.network.protocol.game.ClientboundRespawnPacket;
import net.minecraft.network.protocol.game.ClientboundGameEventPacket;
import net.minecraft.world.level.block.RespawnAnchorBlock;
import net.minecraft.world.phys.Vec3;
import java.util.Optional;
import net.minecraft.server.level.ServerPlayerGameMode;
import net.minecraft.server.level.DemoMode;
import java.net.SocketAddress;
import net.minecraft.stats.Stats;
import javax.annotation.Nullable;
import net.minecraft.world.entity.player.Player;
import net.minecraft.network.protocol.game.ClientboundSetBorderPacket;
import net.minecraft.world.level.border.WorldBorder;
import net.minecraft.world.level.border.BorderChangeListener;
import net.minecraft.world.scores.Objective;
import java.util.Set;
import net.minecraft.network.protocol.game.ClientboundSetPlayerTeamPacket;
import net.minecraft.world.scores.PlayerTeam;
import com.google.common.collect.Sets;
import net.minecraft.server.ServerScoreboard;
import java.util.Iterator;
import net.minecraft.network.chat.MutableComponent;
import net.minecraft.world.level.storage.LevelData;
import net.minecraft.nbt.CompoundTag;
import com.mojang.authlib.GameProfile;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntityType;
import net.minecraft.network.protocol.game.ClientboundUpdateMobEffectPacket;
import net.minecraft.world.effect.MobEffectInstance;
import net.minecraft.network.protocol.game.ClientboundPlayerInfoPacket;
import net.minecraft.network.chat.Component;
import net.minecraft.Util;
import net.minecraft.network.chat.ChatType;
import net.minecraft.ChatFormatting;
import net.minecraft.network.chat.TranslatableComponent;
import net.minecraft.network.protocol.game.ClientboundUpdateTagsPacket;
import net.minecraft.network.protocol.game.ClientboundUpdateRecipesPacket;
import net.minecraft.network.protocol.game.ClientboundSetCarriedItemPacket;
import net.minecraft.network.protocol.game.ClientboundPlayerAbilitiesPacket;
import net.minecraft.network.protocol.game.ClientboundChangeDifficultyPacket;
import net.minecraft.network.FriendlyByteBuf;
import io.netty.buffer.Unpooled;
import net.minecraft.network.protocol.game.ClientboundCustomPayloadPacket;
import net.minecraft.network.protocol.Packet;
import net.minecraft.network.protocol.game.ClientboundLoginPacket;
import net.minecraft.world.level.biome.BiomeManager;
import net.minecraft.world.level.GameRules;
import net.minecraft.server.network.ServerGamePacketListenerImpl;
import net.minecraft.server.level.ServerLevel;
import java.util.function.Consumer;
import net.minecraft.world.level.dimension.DimensionType;
import com.mojang.serialization.DynamicOps;
import com.mojang.serialization.Dynamic;
import net.minecraft.nbt.NbtOps;
import net.minecraft.world.level.Level;
import net.minecraft.resources.ResourceKey;
import net.minecraft.network.Connection;
import com.google.common.collect.Maps;
import com.google.common.collect.Lists;
import net.minecraft.world.level.GameType;
import net.minecraft.core.RegistryAccess;
import net.minecraft.world.level.storage.PlayerDataStorage;
import net.minecraft.server.PlayerAdvancements;
import net.minecraft.stats.ServerStatsCounter;
import java.util.UUID;
import java.util.Map;
import net.minecraft.server.level.ServerPlayer;
import java.util.List;
import net.minecraft.server.MinecraftServer;
import java.text.SimpleDateFormat;
import org.apache.logging.log4j.Logger;
import java.io.File;

public abstract class PlayerList {
    public static final File USERBANLIST_FILE;
    public static final File IPBANLIST_FILE;
    public static final File OPLIST_FILE;
    public static final File WHITELIST_FILE;
    private static final Logger LOGGER;
    private static final SimpleDateFormat BAN_DATE_FORMAT;
    private final MinecraftServer server;
    private final List<ServerPlayer> players;
    private final Map<UUID, ServerPlayer> playersByUUID;
    private final UserBanList bans;
    private final IpBanList ipBans;
    private final ServerOpList ops;
    private final UserWhiteList whitelist;
    private final Map<UUID, ServerStatsCounter> stats;
    private final Map<UUID, PlayerAdvancements> advancements;
    private final PlayerDataStorage playerIo;
    private boolean doWhiteList;
    private final RegistryAccess.RegistryHolder registryHolder;
    protected final int maxPlayers;
    private int viewDistance;
    private GameType overrideGameMode;
    private boolean allowCheatsForAllPlayers;
    private int sendAllPlayerInfoIn;
    
    public PlayerList(final MinecraftServer minecraftServer, final RegistryAccess.RegistryHolder a, final PlayerDataStorage dai, final int integer) {
        this.players = Lists.newArrayList();
        this.playersByUUID = Maps.newHashMap();
        this.bans = new UserBanList(PlayerList.USERBANLIST_FILE);
        this.ipBans = new IpBanList(PlayerList.IPBANLIST_FILE);
        this.ops = new ServerOpList(PlayerList.OPLIST_FILE);
        this.whitelist = new UserWhiteList(PlayerList.WHITELIST_FILE);
        this.stats = Maps.newHashMap();
        this.advancements = Maps.newHashMap();
        this.server = minecraftServer;
        this.registryHolder = a;
        this.maxPlayers = integer;
        this.playerIo = dai;
    }
    
    public void placeNewPlayer(final Connection me, final ServerPlayer ze) {
        final GameProfile gameProfile4 = ze.getGameProfile();
        final GameProfileCache abl5 = this.server.getProfileCache();
        final GameProfile gameProfile5 = abl5.get(gameProfile4.getId());
        final String string7 = (gameProfile5 == null) ? gameProfile4.getName() : gameProfile5.getName();
        abl5.add(gameProfile4);
        final CompoundTag le8 = this.load(ze);
        final ResourceKey<Level> ug9 = (le8 != null) ? DimensionType.parseLegacy(new Dynamic((DynamicOps)NbtOps.INSTANCE, le8.get("Dimension"))).resultOrPartial((Consumer)PlayerList.LOGGER::error).orElse(Level.OVERWORLD) : Level.OVERWORLD;
        final ServerLevel zd10 = this.server.getLevel(ug9);
        ServerLevel zd11;
        if (zd10 == null) {
            PlayerList.LOGGER.warn("Unknown respawn dimension {}, defaulting to overworld", ug9);
            zd11 = this.server.overworld();
        }
        else {
            zd11 = zd10;
        }
        ze.setLevel(zd11);
        ze.gameMode.setLevel((ServerLevel)ze.level);
        String string8 = "local";
        if (me.getRemoteAddress() != null) {
            string8 = me.getRemoteAddress().toString();
        }
        PlayerList.LOGGER.info("{}[{}] logged in with entity id {} at ({}, {}, {})", ze.getName().getString(), string8, ze.getId(), ze.getX(), ze.getY(), ze.getZ());
        final LevelData dab13 = zd11.getLevelData();
        this.updatePlayerGameMode(ze, null, zd11);
        final ServerGamePacketListenerImpl zv14 = new ServerGamePacketListenerImpl(this.server, me, ze);
        final GameRules bpx15 = zd11.getGameRules();
        final boolean boolean16 = bpx15.getBoolean(GameRules.RULE_DO_IMMEDIATE_RESPAWN);
        final boolean boolean17 = bpx15.getBoolean(GameRules.RULE_REDUCEDDEBUGINFO);
        zv14.send(new ClientboundLoginPacket(ze.getId(), ze.gameMode.getGameModeForPlayer(), ze.gameMode.getPreviousGameModeForPlayer(), BiomeManager.obfuscateSeed(zd11.getSeed()), dab13.isHardcore(), this.server.levelKeys(), this.registryHolder, zd11.dimensionTypeKey(), zd11.dimension(), this.getMaxPlayers(), this.viewDistance, boolean17, !boolean16, zd11.isDebug(), zd11.isFlat()));
        zv14.send(new ClientboundCustomPayloadPacket(ClientboundCustomPayloadPacket.BRAND, new FriendlyByteBuf(Unpooled.buffer()).writeUtf(this.getServer().getServerModName())));
        zv14.send(new ClientboundChangeDifficultyPacket(dab13.getDifficulty(), dab13.isDifficultyLocked()));
        zv14.send(new ClientboundPlayerAbilitiesPacket(ze.abilities));
        zv14.send(new ClientboundSetCarriedItemPacket(ze.inventory.selected));
        zv14.send(new ClientboundUpdateRecipesPacket(this.server.getRecipeManager().getRecipes()));
        zv14.send(new ClientboundUpdateTagsPacket(this.server.getTags()));
        this.sendPlayerPermissionLevel(ze);
        ze.getStats().markAllDirty();
        ze.getRecipeBook().sendInitialRecipeBook(ze);
        this.updateEntireScoreboard(zd11.getScoreboard(), ze);
        this.server.invalidateStatus();
        MutableComponent mx18;
        if (ze.getGameProfile().getName().equalsIgnoreCase(string7)) {
            mx18 = new TranslatableComponent("multiplayer.player.joined", new Object[] { ze.getDisplayName() });
        }
        else {
            mx18 = new TranslatableComponent("multiplayer.player.joined.renamed", new Object[] { ze.getDisplayName(), string7 });
        }
        this.broadcastMessage(mx18.withStyle(ChatFormatting.YELLOW), ChatType.SYSTEM, Util.NIL_UUID);
        zv14.teleport(ze.getX(), ze.getY(), ze.getZ(), ze.yRot, ze.xRot);
        this.players.add(ze);
        this.playersByUUID.put(ze.getUUID(), ze);
        this.broadcastAll(new ClientboundPlayerInfoPacket(ClientboundPlayerInfoPacket.Action.ADD_PLAYER, new ServerPlayer[] { ze }));
        for (int integer19 = 0; integer19 < this.players.size(); ++integer19) {
            ze.connection.send(new ClientboundPlayerInfoPacket(ClientboundPlayerInfoPacket.Action.ADD_PLAYER, new ServerPlayer[] { this.players.get(integer19) }));
        }
        zd11.addNewPlayer(ze);
        this.server.getCustomBossEvents().onPlayerConnect(ze);
        this.sendLevelInfo(ze, zd11);
        if (!this.server.getResourcePack().isEmpty()) {
            ze.sendTexturePack(this.server.getResourcePack(), this.server.getResourcePackHash());
        }
        for (final MobEffectInstance aog20 : ze.getActiveEffects()) {
            zv14.send(new ClientboundUpdateMobEffectPacket(ze.getId(), aog20));
        }
        if (le8 != null && le8.contains("RootVehicle", 10)) {
            final CompoundTag le9 = le8.getCompound("RootVehicle");
            final Entity aom2 = EntityType.loadEntityRecursive(le9.getCompound("Entity"), (Level)zd11, aom -> {
                if (!zd11.addWithUUID(aom)) {
                    return null;
                }
                else {
                    return aom;
                }
            });
            if (aom2 != null) {
                UUID uUID21;
                if (le9.hasUUID("Attach")) {
                    uUID21 = le9.getUUID("Attach");
                }
                else {
                    uUID21 = null;
                }
                if (aom2.getUUID().equals(uUID21)) {
                    ze.startRiding(aom2, true);
                }
                else {
                    for (final Entity aom3 : aom2.getIndirectPassengers()) {
                        if (aom3.getUUID().equals(uUID21)) {
                            ze.startRiding(aom3, true);
                            break;
                        }
                    }
                }
                if (!ze.isPassenger()) {
                    PlayerList.LOGGER.warn("Couldn't reattach entity to player");
                    zd11.despawn(aom2);
                    for (final Entity aom3 : aom2.getIndirectPassengers()) {
                        zd11.despawn(aom3);
                    }
                }
            }
        }
        ze.initMenu();
    }
    
    protected void updateEntireScoreboard(final ServerScoreboard ux, final ServerPlayer ze) {
        final Set<Objective> set4 = Sets.newHashSet();
        for (final PlayerTeam dfk6 : ux.getPlayerTeams()) {
            ze.connection.send(new ClientboundSetPlayerTeamPacket(dfk6, 0));
        }
        for (int integer5 = 0; integer5 < 19; ++integer5) {
            final Objective dfj6 = ux.getDisplayObjective(integer5);
            if (dfj6 != null && !set4.contains(dfj6)) {
                final List<Packet<?>> list7 = ux.getStartTrackingPackets(dfj6);
                for (final Packet<?> ni9 : list7) {
                    ze.connection.send(ni9);
                }
                set4.add(dfj6);
            }
        }
    }
    
    public void setLevel(final ServerLevel zd) {
        zd.getWorldBorder().addListener(new BorderChangeListener() {
            @Override
            public void onBorderSizeSet(final WorldBorder cgw, final double double2) {
                PlayerList.this.broadcastAll(new ClientboundSetBorderPacket(cgw, ClientboundSetBorderPacket.Type.SET_SIZE));
            }
            
            @Override
            public void onBorderSizeLerping(final WorldBorder cgw, final double double2, final double double3, final long long4) {
                PlayerList.this.broadcastAll(new ClientboundSetBorderPacket(cgw, ClientboundSetBorderPacket.Type.LERP_SIZE));
            }
            
            @Override
            public void onBorderCenterSet(final WorldBorder cgw, final double double2, final double double3) {
                PlayerList.this.broadcastAll(new ClientboundSetBorderPacket(cgw, ClientboundSetBorderPacket.Type.SET_CENTER));
            }
            
            @Override
            public void onBorderSetWarningTime(final WorldBorder cgw, final int integer) {
                PlayerList.this.broadcastAll(new ClientboundSetBorderPacket(cgw, ClientboundSetBorderPacket.Type.SET_WARNING_TIME));
            }
            
            @Override
            public void onBorderSetWarningBlocks(final WorldBorder cgw, final int integer) {
                PlayerList.this.broadcastAll(new ClientboundSetBorderPacket(cgw, ClientboundSetBorderPacket.Type.SET_WARNING_BLOCKS));
            }
            
            @Override
            public void onBorderSetDamagePerBlock(final WorldBorder cgw, final double double2) {
            }
            
            @Override
            public void onBorderSetDamageSafeZOne(final WorldBorder cgw, final double double2) {
            }
        });
    }
    
    @Nullable
    public CompoundTag load(final ServerPlayer ze) {
        final CompoundTag le3 = this.server.getWorldData().getLoadedPlayerTag();
        CompoundTag le4;
        if (ze.getName().getString().equals(this.server.getSingleplayerName()) && le3 != null) {
            le4 = le3;
            ze.load(le4);
            PlayerList.LOGGER.debug("loading single player");
        }
        else {
            le4 = this.playerIo.load(ze);
        }
        return le4;
    }
    
    protected void save(final ServerPlayer ze) {
        this.playerIo.save(ze);
        final ServerStatsCounter acq3 = this.stats.get(ze.getUUID());
        if (acq3 != null) {
            acq3.save();
        }
        final PlayerAdvancements uq4 = this.advancements.get(ze.getUUID());
        if (uq4 != null) {
            uq4.save();
        }
    }
    
    public void remove(final ServerPlayer ze) {
        final ServerLevel zd3 = ze.getLevel();
        ze.awardStat(Stats.LEAVE_GAME);
        this.save(ze);
        if (ze.isPassenger()) {
            final Entity aom4 = ze.getRootVehicle();
            if (aom4.hasOnePlayerPassenger()) {
                PlayerList.LOGGER.debug("Removing player mount");
                ze.stopRiding();
                zd3.despawn(aom4);
                aom4.removed = true;
                for (final Entity aom5 : aom4.getIndirectPassengers()) {
                    zd3.despawn(aom5);
                    aom5.removed = true;
                }
                zd3.getChunk(ze.xChunk, ze.zChunk).markUnsaved();
            }
        }
        ze.unRide();
        zd3.removePlayerImmediately(ze);
        ze.getAdvancements().stopListening();
        this.players.remove(ze);
        this.server.getCustomBossEvents().onPlayerDisconnect(ze);
        final UUID uUID4 = ze.getUUID();
        final ServerPlayer ze2 = this.playersByUUID.get(uUID4);
        if (ze2 == ze) {
            this.playersByUUID.remove(uUID4);
            this.stats.remove(uUID4);
            this.advancements.remove(uUID4);
        }
        this.broadcastAll(new ClientboundPlayerInfoPacket(ClientboundPlayerInfoPacket.Action.REMOVE_PLAYER, new ServerPlayer[] { ze }));
    }
    
    @Nullable
    public Component canPlayerLogin(final SocketAddress socketAddress, final GameProfile gameProfile) {
        if (this.bans.isBanned(gameProfile)) {
            final UserBanListEntry abv4 = this.bans.get(gameProfile);
            final MutableComponent mx5 = new TranslatableComponent("multiplayer.disconnect.banned.reason", new Object[] { abv4.getReason() });
            if (abv4.getExpires() != null) {
                mx5.append(new TranslatableComponent("multiplayer.disconnect.banned.expiration", new Object[] { PlayerList.BAN_DATE_FORMAT.format(abv4.getExpires()) }));
            }
            return mx5;
        }
        if (!this.isWhiteListed(gameProfile)) {
            return new TranslatableComponent("multiplayer.disconnect.not_whitelisted");
        }
        if (this.ipBans.isBanned(socketAddress)) {
            final IpBanListEntry abn4 = this.ipBans.get(socketAddress);
            final MutableComponent mx5 = new TranslatableComponent("multiplayer.disconnect.banned_ip.reason", new Object[] { abn4.getReason() });
            if (abn4.getExpires() != null) {
                mx5.append(new TranslatableComponent("multiplayer.disconnect.banned_ip.expiration", new Object[] { PlayerList.BAN_DATE_FORMAT.format(abn4.getExpires()) }));
            }
            return mx5;
        }
        if (this.players.size() >= this.maxPlayers && !this.canBypassPlayerLimit(gameProfile)) {
            return new TranslatableComponent("multiplayer.disconnect.server_full");
        }
        return null;
    }
    
    public ServerPlayer getPlayerForLogin(final GameProfile gameProfile) {
        final UUID uUID3 = Player.createPlayerUUID(gameProfile);
        final List<ServerPlayer> list4 = Lists.newArrayList();
        for (int integer5 = 0; integer5 < this.players.size(); ++integer5) {
            final ServerPlayer ze6 = this.players.get(integer5);
            if (ze6.getUUID().equals(uUID3)) {
                list4.add(ze6);
            }
        }
        final ServerPlayer ze7 = this.playersByUUID.get(gameProfile.getId());
        if (ze7 != null && !list4.contains(ze7)) {
            list4.add(ze7);
        }
        for (final ServerPlayer ze8 : list4) {
            ze8.connection.disconnect(new TranslatableComponent("multiplayer.disconnect.duplicate_login"));
        }
        final ServerLevel zd7 = this.server.overworld();
        ServerPlayerGameMode zf6;
        if (this.server.isDemo()) {
            zf6 = new DemoMode(zd7);
        }
        else {
            zf6 = new ServerPlayerGameMode(zd7);
        }
        return new ServerPlayer(this.server, zd7, gameProfile, zf6);
    }
    
    public ServerPlayer respawn(final ServerPlayer ze, final boolean boolean2) {
        this.players.remove(ze);
        ze.getLevel().removePlayerImmediately(ze);
        final BlockPos fu4 = ze.getRespawnPosition();
        final boolean boolean3 = ze.isRespawnForced();
        final ServerLevel zd6 = this.server.getLevel(ze.getRespawnDimension());
        Optional<Vec3> optional7;
        if (zd6 != null && fu4 != null) {
            optional7 = Player.findRespawnPositionAndUseSpawnBlock(zd6, fu4, boolean3, boolean2);
        }
        else {
            optional7 = Optional.<Vec3>empty();
        }
        final ServerLevel zd7 = (zd6 != null && optional7.isPresent()) ? zd6 : this.server.overworld();
        ServerPlayerGameMode zf8;
        if (this.server.isDemo()) {
            zf8 = new DemoMode(zd7);
        }
        else {
            zf8 = new ServerPlayerGameMode(zd7);
        }
        final ServerPlayer ze2 = new ServerPlayer(this.server, zd7, ze.getGameProfile(), zf8);
        ze2.connection = ze.connection;
        ze2.restoreFrom(ze, boolean2);
        ze2.setId(ze.getId());
        ze2.setMainArm(ze.getMainArm());
        for (final String string12 : ze.getTags()) {
            ze2.addTag(string12);
        }
        this.updatePlayerGameMode(ze2, ze, zd7);
        boolean boolean4 = false;
        if (optional7.isPresent()) {
            final Vec3 dem12 = optional7.get();
            ze2.moveTo(dem12.x, dem12.y, dem12.z, 0.0f, 0.0f);
            ze2.setRespawnPosition(zd7.dimension(), fu4, boolean3, false);
            boolean4 = (!boolean2 && zd7.getBlockState(fu4).getBlock() instanceof RespawnAnchorBlock);
        }
        else if (fu4 != null) {
            ze2.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.NO_RESPAWN_BLOCK_AVAILABLE, 0.0f));
        }
        while (!zd7.noCollision(ze2) && ze2.getY() < 256.0) {
            ze2.setPos(ze2.getX(), ze2.getY() + 1.0, ze2.getZ());
        }
        final LevelData dab12 = ze2.level.getLevelData();
        ze2.connection.send(new ClientboundRespawnPacket(ze2.level.dimensionTypeKey(), ze2.level.dimension(), BiomeManager.obfuscateSeed(ze2.getLevel().getSeed()), ze2.gameMode.getGameModeForPlayer(), ze2.gameMode.getPreviousGameModeForPlayer(), ze2.getLevel().isDebug(), ze2.getLevel().isFlat(), boolean2));
        ze2.connection.teleport(ze2.getX(), ze2.getY(), ze2.getZ(), ze2.yRot, ze2.xRot);
        ze2.connection.send(new ClientboundSetDefaultSpawnPositionPacket(zd7.getSharedSpawnPos()));
        ze2.connection.send(new ClientboundChangeDifficultyPacket(dab12.getDifficulty(), dab12.isDifficultyLocked()));
        ze2.connection.send(new ClientboundSetExperiencePacket(ze2.experienceProgress, ze2.totalExperience, ze2.experienceLevel));
        this.sendLevelInfo(ze2, zd7);
        this.sendPlayerPermissionLevel(ze2);
        zd7.addRespawnedPlayer(ze2);
        this.players.add(ze2);
        this.playersByUUID.put(ze2.getUUID(), ze2);
        ze2.initMenu();
        ze2.setHealth(ze2.getHealth());
        if (boolean4) {
            ze2.connection.send(new ClientboundSoundPacket(SoundEvents.RESPAWN_ANCHOR_DEPLETE, SoundSource.BLOCKS, fu4.getX(), fu4.getY(), fu4.getZ(), 1.0f, 1.0f));
        }
        return ze2;
    }
    
    public void sendPlayerPermissionLevel(final ServerPlayer ze) {
        final GameProfile gameProfile3 = ze.getGameProfile();
        final int integer4 = this.server.getProfilePermissions(gameProfile3);
        this.sendPlayerPermissionLevel(ze, integer4);
    }
    
    public void tick() {
        if (++this.sendAllPlayerInfoIn > 600) {
            this.broadcastAll(new ClientboundPlayerInfoPacket(ClientboundPlayerInfoPacket.Action.UPDATE_LATENCY, this.players));
            this.sendAllPlayerInfoIn = 0;
        }
    }
    
    public void broadcastAll(final Packet<?> ni) {
        for (int integer3 = 0; integer3 < this.players.size(); ++integer3) {
            this.players.get(integer3).connection.send(ni);
        }
    }
    
    public void broadcastAll(final Packet<?> ni, final ResourceKey<Level> ug) {
        for (int integer4 = 0; integer4 < this.players.size(); ++integer4) {
            final ServerPlayer ze5 = this.players.get(integer4);
            if (ze5.level.dimension() == ug) {
                ze5.connection.send(ni);
            }
        }
    }
    
    public void broadcastToTeam(final Player bec, final Component mr) {
        final Team dfo4 = bec.getTeam();
        if (dfo4 == null) {
            return;
        }
        final Collection<String> collection5 = dfo4.getPlayers();
        for (final String string7 : collection5) {
            final ServerPlayer ze8 = this.getPlayerByName(string7);
            if (ze8 != null) {
                if (ze8 == bec) {
                    continue;
                }
                ze8.sendMessage(mr, bec.getUUID());
            }
        }
    }
    
    public void broadcastToAllExceptTeam(final Player bec, final Component mr) {
        final Team dfo4 = bec.getTeam();
        if (dfo4 == null) {
            this.broadcastMessage(mr, ChatType.SYSTEM, bec.getUUID());
            return;
        }
        for (int integer5 = 0; integer5 < this.players.size(); ++integer5) {
            final ServerPlayer ze6 = this.players.get(integer5);
            if (ze6.getTeam() != dfo4) {
                ze6.sendMessage(mr, bec.getUUID());
            }
        }
    }
    
    public String[] getPlayerNamesArray() {
        final String[] arr2 = new String[this.players.size()];
        for (int integer3 = 0; integer3 < this.players.size(); ++integer3) {
            arr2[integer3] = this.players.get(integer3).getGameProfile().getName();
        }
        return arr2;
    }
    
    public UserBanList getBans() {
        return this.bans;
    }
    
    public IpBanList getIpBans() {
        return this.ipBans;
    }
    
    public void op(final GameProfile gameProfile) {
        ((StoredUserList<K, ServerOpListEntry>)this.ops).add(new ServerOpListEntry(gameProfile, this.server.getOperatorUserPermissionLevel(), this.ops.canBypassPlayerLimit(gameProfile)));
        final ServerPlayer ze3 = this.getPlayer(gameProfile.getId());
        if (ze3 != null) {
            this.sendPlayerPermissionLevel(ze3);
        }
    }
    
    public void deop(final GameProfile gameProfile) {
        ((StoredUserList<GameProfile, V>)this.ops).remove(gameProfile);
        final ServerPlayer ze3 = this.getPlayer(gameProfile.getId());
        if (ze3 != null) {
            this.sendPlayerPermissionLevel(ze3);
        }
    }
    
    private void sendPlayerPermissionLevel(final ServerPlayer ze, final int integer) {
        if (ze.connection != null) {
            byte byte4;
            if (integer <= 0) {
                byte4 = 24;
            }
            else if (integer >= 4) {
                byte4 = 28;
            }
            else {
                byte4 = (byte)(24 + integer);
            }
            ze.connection.send(new ClientboundEntityEventPacket(ze, byte4));
        }
        this.server.getCommands().sendCommands(ze);
    }
    
    public boolean isWhiteListed(final GameProfile gameProfile) {
        return !this.doWhiteList || ((StoredUserList<GameProfile, V>)this.ops).contains(gameProfile) || ((StoredUserList<GameProfile, V>)this.whitelist).contains(gameProfile);
    }
    
    public boolean isOp(final GameProfile gameProfile) {
        return ((StoredUserList<GameProfile, V>)this.ops).contains(gameProfile) || (this.server.isSingleplayerOwner(gameProfile) && this.server.getWorldData().getAllowCommands()) || this.allowCheatsForAllPlayers;
    }
    
    @Nullable
    public ServerPlayer getPlayerByName(final String string) {
        for (final ServerPlayer ze4 : this.players) {
            if (ze4.getGameProfile().getName().equalsIgnoreCase(string)) {
                return ze4;
            }
        }
        return null;
    }
    
    public void broadcast(@Nullable final Player bec, final double double2, final double double3, final double double4, final double double5, final ResourceKey<Level> ug, final Packet<?> ni) {
        for (int integer13 = 0; integer13 < this.players.size(); ++integer13) {
            final ServerPlayer ze14 = this.players.get(integer13);
            if (ze14 != bec) {
                if (ze14.level.dimension() == ug) {
                    final double double6 = double2 - ze14.getX();
                    final double double7 = double3 - ze14.getY();
                    final double double8 = double4 - ze14.getZ();
                    if (double6 * double6 + double7 * double7 + double8 * double8 < double5 * double5) {
                        ze14.connection.send(ni);
                    }
                }
            }
        }
    }
    
    public void saveAll() {
        for (int integer2 = 0; integer2 < this.players.size(); ++integer2) {
            this.save(this.players.get(integer2));
        }
    }
    
    public UserWhiteList getWhiteList() {
        return this.whitelist;
    }
    
    public String[] getWhiteListNames() {
        return this.whitelist.getUserList();
    }
    
    public ServerOpList getOps() {
        return this.ops;
    }
    
    public String[] getOpNames() {
        return this.ops.getUserList();
    }
    
    public void reloadWhiteList() {
    }
    
    public void sendLevelInfo(final ServerPlayer ze, final ServerLevel zd) {
        final WorldBorder cgw4 = this.server.overworld().getWorldBorder();
        ze.connection.send(new ClientboundSetBorderPacket(cgw4, ClientboundSetBorderPacket.Type.INITIALIZE));
        ze.connection.send(new ClientboundSetTimePacket(zd.getGameTime(), zd.getDayTime(), zd.getGameRules().getBoolean(GameRules.RULE_DAYLIGHT)));
        ze.connection.send(new ClientboundSetDefaultSpawnPositionPacket(zd.getSharedSpawnPos()));
        if (zd.isRaining()) {
            ze.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.START_RAINING, 0.0f));
            ze.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.RAIN_LEVEL_CHANGE, zd.getRainLevel(1.0f)));
            ze.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.THUNDER_LEVEL_CHANGE, zd.getThunderLevel(1.0f)));
        }
    }
    
    public void sendAllPlayerInfo(final ServerPlayer ze) {
        ze.refreshContainer(ze.inventoryMenu);
        ze.resetSentInfo();
        ze.connection.send(new ClientboundSetCarriedItemPacket(ze.inventory.selected));
    }
    
    public int getPlayerCount() {
        return this.players.size();
    }
    
    public int getMaxPlayers() {
        return this.maxPlayers;
    }
    
    public boolean isUsingWhitelist() {
        return this.doWhiteList;
    }
    
    public void setUsingWhiteList(final boolean boolean1) {
        this.doWhiteList = boolean1;
    }
    
    public List<ServerPlayer> getPlayersWithAddress(final String string) {
        final List<ServerPlayer> list3 = Lists.newArrayList();
        for (final ServerPlayer ze5 : this.players) {
            if (ze5.getIpAddress().equals(string)) {
                list3.add(ze5);
            }
        }
        return list3;
    }
    
    public int getViewDistance() {
        return this.viewDistance;
    }
    
    public MinecraftServer getServer() {
        return this.server;
    }
    
    public CompoundTag getSingleplayerData() {
        return null;
    }
    
    public void setOverrideGameMode(final GameType bpy) {
        this.overrideGameMode = bpy;
    }
    
    private void updatePlayerGameMode(final ServerPlayer ze1, @Nullable final ServerPlayer ze2, final ServerLevel zd) {
        if (ze2 != null) {
            ze1.gameMode.setGameModeForPlayer(ze2.gameMode.getGameModeForPlayer(), ze2.gameMode.getPreviousGameModeForPlayer());
        }
        else if (this.overrideGameMode != null) {
            ze1.gameMode.setGameModeForPlayer(this.overrideGameMode, GameType.NOT_SET);
        }
        ze1.gameMode.updateGameMode(zd.getServer().getWorldData().getGameType());
    }
    
    public void setAllowCheatsForAllPlayers(final boolean boolean1) {
        this.allowCheatsForAllPlayers = boolean1;
    }
    
    public void removeAll() {
        for (int integer2 = 0; integer2 < this.players.size(); ++integer2) {
            this.players.get(integer2).connection.disconnect(new TranslatableComponent("multiplayer.disconnect.server_shutdown"));
        }
    }
    
    public void broadcastMessage(final Component mr, final ChatType mo, final UUID uUID) {
        this.server.sendMessage(mr, uUID);
        this.broadcastAll(new ClientboundChatPacket(mr, mo, uUID));
    }
    
    public ServerStatsCounter getPlayerStats(final Player bec) {
        final UUID uUID3 = bec.getUUID();
        ServerStatsCounter acq4 = (uUID3 == null) ? null : this.stats.get(uUID3);
        if (acq4 == null) {
            final File file5 = this.server.getWorldPath(LevelResource.PLAYER_STATS_DIR).toFile();
            final File file6 = new File(file5, uUID3 + ".json");
            if (!file6.exists()) {
                final File file7 = new File(file5, bec.getName().getString() + ".json");
                if (file7.exists() && file7.isFile()) {
                    file7.renameTo(file6);
                }
            }
            acq4 = new ServerStatsCounter(this.server, file6);
            this.stats.put(uUID3, acq4);
        }
        return acq4;
    }
    
    public PlayerAdvancements getPlayerAdvancements(final ServerPlayer ze) {
        final UUID uUID3 = ze.getUUID();
        PlayerAdvancements uq4 = this.advancements.get(uUID3);
        if (uq4 == null) {
            final File file5 = this.server.getWorldPath(LevelResource.PLAYER_ADVANCEMENTS_DIR).toFile();
            final File file6 = new File(file5, uUID3 + ".json");
            uq4 = new PlayerAdvancements(this.server.getFixerUpper(), this, this.server.getAdvancements(), file6, ze);
            this.advancements.put(uUID3, uq4);
        }
        uq4.setPlayer(ze);
        return uq4;
    }
    
    public void setViewDistance(final int integer) {
        this.viewDistance = integer;
        this.broadcastAll(new ClientboundSetChunkCacheRadiusPacket(integer));
        for (final ServerLevel zd4 : this.server.getAllLevels()) {
            if (zd4 != null) {
                zd4.getChunkSource().setViewDistance(integer);
            }
        }
    }
    
    public List<ServerPlayer> getPlayers() {
        return this.players;
    }
    
    @Nullable
    public ServerPlayer getPlayer(final UUID uUID) {
        return this.playersByUUID.get(uUID);
    }
    
    public boolean canBypassPlayerLimit(final GameProfile gameProfile) {
        return false;
    }
    
    public void reloadResources() {
        for (final PlayerAdvancements uq3 : this.advancements.values()) {
            uq3.reload(this.server.getAdvancements());
        }
        this.broadcastAll(new ClientboundUpdateTagsPacket(this.server.getTags()));
        final ClientboundUpdateRecipesPacket qv2 = new ClientboundUpdateRecipesPacket(this.server.getRecipeManager().getRecipes());
        for (final ServerPlayer ze4 : this.players) {
            ze4.connection.send(qv2);
            ze4.getRecipeBook().sendInitialRecipeBook(ze4);
        }
    }
    
    public boolean isAllowCheatsForAllPlayers() {
        return this.allowCheatsForAllPlayers;
    }
    
    static {
        USERBANLIST_FILE = new File("banned-players.json");
        IPBANLIST_FILE = new File("banned-ips.json");
        OPLIST_FILE = new File("ops.json");
        WHITELIST_FILE = new File("whitelist.json");
        LOGGER = LogManager.getLogger();
        BAN_DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd 'at' HH:mm:ss z");
    }
}
