<commit_before>package tc.oc.lobby.bukkit.listeners;

import java.util.Random;
import java.util.logging.Level;
import javax.annotation.Nullable;
import javax.inject.Inject;

import com.google.common.eventbus.Subscribe;
import net.md_5.bungee.api.ChatColor;
import net.md_5.bungee.api.chat.TranslatableComponent;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.boss.BarColor;
import org.bukkit.boss.BarStyle;
import org.bukkit.boss.BossBar;
import org.bukkit.entity.Player;
import org.bukkit.event.EventBus;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerCommandPreprocessEvent;
import org.bukkit.event.player.PlayerInitialSpawnEvent;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerMoveEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.event.player.PlayerRespawnEvent;
import org.bukkit.permissions.PermissionAttachmentInfo;
import org.bukkit.geometry.Cuboid;
import org.bukkit.plugin.Plugin;
import java.time.Duration;
import java.time.Instant;
import tc.oc.api.bukkit.users.OnlinePlayers;
import tc.oc.api.docs.User;
import tc.oc.api.docs.virtual.ServerDoc;
import tc.oc.api.minecraft.MinecraftService;
import tc.oc.api.util.Permissions;
import tc.oc.commons.bukkit.bossbar.BossBarFactory;
import tc.oc.commons.bukkit.chat.Audiences;
import tc.oc.commons.bukkit.chat.ComponentRenderContext;
import tc.oc.commons.bukkit.chat.HeaderComponent;
import tc.oc.commons.bukkit.event.ObserverKitApplyEvent;
import tc.oc.commons.bukkit.event.UserLoginEvent;
import tc.oc.commons.core.chat.Audience;
import tc.oc.commons.core.chat.Component;
import tc.oc.commons.core.chat.Components;
import tc.oc.commons.core.format.GeneralFormatter;
import tc.oc.commons.core.plugin.PluginFacet;
import tc.oc.commons.core.restart.RequestRestartEvent;
import tc.oc.commons.core.util.TimeUtils;
import tc.oc.lobby.bukkit.LobbyConfig;
import tc.oc.lobby.bukkit.Utils;
import tc.oc.commons.bukkit.chat.Links;

import static net.md_5.bungee.api.ChatColor.*;

public class PlayerListener implements PluginFacet, Listener {
    class SignUpdate implements ServerDoc.StatusUpdate {
        final int num_observing;

        SignUpdate(int num_observing) {
            this.num_observing = num_observing;
        }

        @Override
        public int num_observing() {
            return num_observing;
        }

        @Override
        public int max_players() {
            return lobby.getServer().getMaxPlayers();
        }
    }

    private final Plugin lobby;
    private final LobbyConfig config;
    private final MinecraftService minecraftService;
    private final OnlinePlayers onlinePlayers;
    private final Audiences audiences;
    private final BossBarFactory bossBarFactory;
    private final ComponentRenderContext renderer;
    private final EventBus eventBus;
    private final GeneralFormatter generalFormatter;

    private Cuboid boundaries = Cuboid.unbounded();
    private Location spawnLocation;
    private double spawnRadius;
    private @Nullable RequestRestartEvent.Deferral restartDeferral;

    @Inject PlayerListener(Plugin lobby, LobbyConfig config, MinecraftService minecraftService, OnlinePlayers onlinePlayers, Audiences audiences, BossBarFactory bossBarFactory, ComponentRenderContext renderer, EventBus eventBus, GeneralFormatter generalFormatter) {
        this.lobby = lobby;
        this.config = config;
        this.minecraftService = minecraftService;
        this.onlinePlayers = onlinePlayers;
        this.audiences = audiences;
        this.bossBarFactory = bossBarFactory;
        this.renderer = renderer;
        this.eventBus = eventBus;
        this.generalFormatter = generalFormatter;
    }

    private Location spawnLocation(World world) {
        try {
            return spawnLocation = config.getSpawnLocation(world);
        } catch(Throwable e) {
            lobby.getLogger().log(Level.SEVERE, "Failed to get spawn location, using last good value", e);
            return spawnLocation;
        }
    }

    private double spawnRadius(World world) {
        try {
            return spawnRadius = config.getSpawnRadius(world);
        } catch(Throwable e) {
            lobby.getLogger().log(Level.SEVERE, "Failed to get spawn radius, using last good value", e);
            return spawnRadius;
        }
    }

    private Cuboid boundaries(World world) {
        try {
            return boundaries = config.getBoundaries(world);
        } catch(Throwable e) {
            lobby.getLogger().log(Level.SEVERE, "Failed to get boundaries, using last good value", e);
            return boundaries;
        }
    }

    private void resetPlayer(Player player) {
        Utils.resetPlayer(player);
        eventBus.callEvent(new ObserverKitApplyEvent(player));
    }

    @EventHandler(priority = EventPriority.HIGHEST)
    public void join(final PlayerJoinEvent event) {
        Player player = event.getPlayer();

        resetPlayer(player);

        event.getPlayer().addAttachment(lobby, Permissions.OBSERVER, true);

        if (player.hasPermission("lobby.overhead-news")) {
            final String datacenter = minecraftService.getLocalServer().datacenter();
            final Component news = new Component(ChatColor.GREEN)
                .extra(new TranslatableComponent(
                    "lobby.news",
                    new Component(ChatColor.GOLD, ChatColor.BOLD).extra(generalFormatter.publicHostname())
                ));

            final BossBar bar = bossBarFactory.createBossBar(player, renderer.render(news, player), BarColor.BLUE, BarStyle.SOLID);
            bar.setProgress(1);
            bar.setVisible(true);
        }

        if(!player.hasPermission("lobby.disabled-permissions-exempt")) {
            for(PermissionAttachmentInfo attachment : player.getEffectivePermissions()) {
                if(config.getDisabledPermissions().contains(attachment.getPermission())) {
                    attachment.getAttachment().setPermission(attachment.getPermission(), false);
                }
            }
        }

        int count = lobby.getServer().getOnlinePlayers().size();
        if(!lobby.getServer().getOnlinePlayers().contains(event.getPlayer())) count++;
        minecraftService.updateLocalServer(new SignUpdate(count));
    }

    @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
    public void onLogin(UserLoginEvent event) {
        final User user = event.getUser();
        final Player player = event.getPlayer();
        final Audience audience = audiences.get(player);

        audience.sendMessage(Components.blank());

        audience.sendMessage(
            new HeaderComponent(
                new Component(GREEN).translate("welcome", generalFormatter.brandName())
            )
        );

        audience.sendMessage(
            new Component(DARK_AQUA)
                .translate(
                    "welcome.instructions",
                    new Component(AQUA).translate("servers.lobby"),
                    new Component(GOLD).translate("welcome.sign"),
                    new Component(GREEN).translate("navigator.title")
                )
        );

        audience.sendMessage(new HeaderComponent(
            new Component(ChatColor.GREEN)
                .translate(
                    "welcome.visitWebsite",
                    Links.homeLink()<commit_msg>Readd trial rank handling code<commit_after>package tc.oc.lobby.bukkit.listeners;

import java.util.Random;
import java.util.logging.Level;
import javax.annotation.Nullable;
import javax.inject.Inject;

import com.google.common.eventbus.Subscribe;
import net.md_5.bungee.api.ChatColor;
import net.md_5.bungee.api.chat.TranslatableComponent;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.boss.BarColor;
import org.bukkit.boss.BarStyle;
import org.bukkit.boss.BossBar;
import org.bukkit.entity.Player;
import org.bukkit.event.EventBus;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerCommandPreprocessEvent;
import org.bukkit.event.player.PlayerInitialSpawnEvent;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerMoveEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.event.player.PlayerRespawnEvent;
import org.bukkit.permissions.PermissionAttachmentInfo;
import org.bukkit.geometry.Cuboid;
import org.bukkit.plugin.Plugin;
import java.time.Duration;
import java.time.Instant;
import tc.oc.api.bukkit.users.OnlinePlayers;
import tc.oc.api.docs.User;
import tc.oc.api.docs.virtual.ServerDoc;
import tc.oc.api.minecraft.MinecraftService;
import tc.oc.api.util.Permissions;
import tc.oc.commons.bukkit.bossbar.BossBarFactory;
import tc.oc.commons.bukkit.chat.Audiences;
import tc.oc.commons.bukkit.chat.ComponentRenderContext;
import tc.oc.commons.bukkit.chat.HeaderComponent;
import tc.oc.commons.bukkit.event.ObserverKitApplyEvent;
import tc.oc.commons.bukkit.event.UserLoginEvent;
import tc.oc.commons.core.chat.Audience;
import tc.oc.commons.core.chat.Component;
import tc.oc.commons.core.chat.Components;
import tc.oc.commons.core.format.GeneralFormatter;
import tc.oc.commons.core.plugin.PluginFacet;
import tc.oc.commons.core.restart.RequestRestartEvent;
import tc.oc.commons.core.util.TimeUtils;
import tc.oc.lobby.bukkit.LobbyConfig;
import tc.oc.lobby.bukkit.Utils;
import tc.oc.commons.bukkit.chat.Links;

import static net.md_5.bungee.api.ChatColor.*;

public class PlayerListener implements PluginFacet, Listener {
    class SignUpdate implements ServerDoc.StatusUpdate {
        final int num_observing;

        SignUpdate(int num_observing) {
            this.num_observing = num_observing;
        }

        @Override
        public int num_observing() {
            return num_observing;
        }

        @Override
        public int max_players() {
            return lobby.getServer().getMaxPlayers();
        }
    }

    private final Plugin lobby;
    private final LobbyConfig config;
    private final MinecraftService minecraftService;
    private final OnlinePlayers onlinePlayers;
    private final Audiences audiences;
    private final BossBarFactory bossBarFactory;
    private final ComponentRenderContext renderer;
    private final EventBus eventBus;
    private final GeneralFormatter generalFormatter;

    private Cuboid boundaries = Cuboid.unbounded();
    private Location spawnLocation;
    private double spawnRadius;
    private @Nullable RequestRestartEvent.Deferral restartDeferral;

    @Inject PlayerListener(Plugin lobby, LobbyConfig config, MinecraftService minecraftService, OnlinePlayers onlinePlayers, Audiences audiences, BossBarFactory bossBarFactory, ComponentRenderContext renderer, EventBus eventBus, GeneralFormatter generalFormatter) {
        this.lobby = lobby;
        this.config = config;
        this.minecraftService = minecraftService;
        this.onlinePlayers = onlinePlayers;
        this.audiences = audiences;
        this.bossBarFactory = bossBarFactory;
        this.renderer = renderer;
        this.eventBus = eventBus;
        this.generalFormatter = generalFormatter;
    }

    private Location spawnLocation(World world) {
        try {
            return spawnLocation = config.getSpawnLocation(world);
        } catch(Throwable e) {
            lobby.getLogger().log(Level.SEVERE, "Failed to get spawn location, using last good value", e);
            return spawnLocation;
        }
    }

    private double spawnRadius(World world) {
        try {
            return spawnRadius = config.getSpawnRadius(world);
        } catch(Throwable e) {
            lobby.getLogger().log(Level.SEVERE, "Failed to get spawn radius, using last good value", e);
            return spawnRadius;
        }
    }

    private Cuboid boundaries(World world) {
        try {
            return boundaries = config.getBoundaries(world);
        } catch(Throwable e) {
            lobby.getLogger().log(Level.SEVERE, "Failed to get boundaries, using last good value", e);
            return boundaries;
        }
    }

    private void resetPlayer(Player player) {
        Utils.resetPlayer(player);
        eventBus.callEvent(new ObserverKitApplyEvent(player));
    }

    @EventHandler(priority = EventPriority.HIGHEST)
    public void join(final PlayerJoinEvent event) {
        Player player = event.getPlayer();

        resetPlayer(player);

        event.getPlayer().addAttachment(lobby, Permissions.OBSERVER, true);

        if (player.hasPermission("lobby.overhead-news")) {
            final String datacenter = minecraftService.getLocalServer().datacenter();
            final Component news = new Component(ChatColor.GREEN)
                .extra(new TranslatableComponent(
                    "lobby.news",
                    new Component(ChatColor.GOLD, ChatColor.BOLD).extra(generalFormatter.publicHostname())
                ));

            final BossBar bar = bossBarFactory.createBossBar(player, renderer.render(news, player), BarColor.BLUE, BarStyle.SOLID);
            bar.setProgress(1);
            bar.setVisible(true);
        }

        if(!player.hasPermission("lobby.disabled-permissions-exempt")) {
            for(PermissionAttachmentInfo attachment : player.getEffectivePermissions()) {
                if(config.getDisabledPermissions().contains(attachment.getPermission())) {
                    attachment.getAttachment().setPermission(attachment.getPermission(), false);
                }
            }
        }

        int count = lobby.getServer().getOnlinePlayers().size();
        if(!lobby.getServer().getOnlinePlayers().contains(event.getPlayer())) count++;
        minecraftService.updateLocalServer(new SignUpdate(count));
    }

    @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
    public void onLogin(UserLoginEvent event) {
        final User user = event.getUser();
        final Player player = event.getPlayer();
        final Audience audience = audiences.get(player);

        audience.sendMessage(Components.blank());

        audience.sendMessage(
            new HeaderComponent(
                new Component(GREEN).translate("welcome", generalFormatter.brandName())
            )
        );

        audience.sendMessage(
            new Component(DARK_AQUA)
                .translate(
                    "welcome.instructions",
                    new Component(AQUA).translate("servers.lobby"),
                    new Component(GOLD).translate("welcome.sign"),
                    new Component(GREEN).translate("navigator.title")
                )
        );

        if(user.trial_expires_at() != null) {
            final Instant expires = TimeUtils.toInstant(user.trial_expires_at());
            final Instant now = Instant.now();

            if(expires.isAfter(now)) {
                long days = TimeUtils.daysRoundingUp(Duration.between(now, expires));
                final String key;
                if(days <= 1) {
                    key = "trial.remaining.singular";
                    days = 1;
                } else {
                    key = "trial.remaining.plural";
                }

                audience.sendMessage(
                        new Component(DARK_PURPLE)
                                .translate(
                                        key,
                                        new Component(LIGHT_PURPLE).translate("trial.freeTrial"),
                                        new Component(days, LIGHT_PURPLE)
                                )
                                .extra(" ")
                                .translate(
                                        "trial.details",
                                        new Component(LIGHT_PURPLE).translate("trial.joinFull"),
                                        new Component(LIGHT_PURPLE).translate("trial.chooseTeam")
                                )
                                .extra(" ")
                                .translate(
                                        "trial.upgrade",
                                        Links.shopLink()
                                )
                );
            }
        }

        audience.sendMessage(new HeaderComponent(
            new Component(ChatColor.GREEN)
                .translate(
                    "welcome.visitWebsite",
                    Links.homeLink()
{'fraction_non_alphanumeric': 0.09434987323433539, 'fraction_numerical': 0.0006036460219727152, 'mean_word_length': 2.539957264957265, 'pattern_counts': {'":': 0, '<': 4, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 12, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5452234', 'n_tokens_mistral': 4553, 'n_tokens_neox': 4413, 'n_words': 839}