package tc.oc.pgm.tutorial; import java.util.Objects; import java.util.concurrent.TimeUnit; import javax.annotation.Nullable; import javax.inject.Inject; import com.google.common.collect.ImmutableList; import net.md_5.bungee.api.ChatColor; import net.md_5.bungee.api.chat.BaseComponent; import net.md_5.bungee.api.chat.TranslatableComponent; import org.bukkit.Material; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; import org.bukkit.inventory.ItemFlag; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.PlayerInventory; import org.bukkit.inventory.meta.ItemMeta; import tc.oc.commons.bukkit.chat.ComponentRenderContext; import tc.oc.commons.bukkit.event.targeted.TargetedEventHandler; import tc.oc.commons.core.chat.Component; import tc.oc.commons.core.chat.Components; import tc.oc.time.Time; import tc.oc.pgm.events.ObserverInteractEvent; import tc.oc.pgm.map.MapInfo; import tc.oc.pgm.match.MatchPlayer; import tc.oc.pgm.match.MatchPlayerFacet; import tc.oc.pgm.match.MatchScope; import tc.oc.pgm.match.Parties; import tc.oc.pgm.match.Repeatable; import tc.oc.commons.bukkit.event.ObserverKitApplyEvent; public class TutorialPlayerFacet implements MatchPlayerFacet, Listener { private static final Material TUTORIAL_ITEM = Material.EMERALD; private static final int TUTORIAL_SLOT = 3; private final Player bukkit; private final PlayerInventory inventory; private final MatchPlayer player; private final Tutorial tutorial; private final MapInfo mapInfo; private final ComponentRenderContext renderer; private @Nullable TutorialStage currentStage; private @Nullable BaseComponent navigation; private long lastStageChangeMillis; @Inject TutorialPlayerFacet(Player bukkit, PlayerInventory inventory, MatchPlayer player, Tutorial tutorial, MapInfo mapInfo, ComponentRenderContext renderer) { this.bukkit = bukkit; this.inventory = inventory; this.player = player; this.tutorial = tutorial; this.mapInfo = mapInfo; this.renderer = renderer; } public void setCurrentStage(TutorialStage newStage) { if(player.isParticipating() || Objects.equals(currentStage, newStage)) return; // Debounce stage changes closer than 0.5 seconds final long nowMillis = TimeUnit.NANOSECONDS.toMillis(System.nanoTime()); if(nowMillis < lastStageChangeMillis + 500) return; currentStage = newStage; navigation = null; lastStageChangeMillis = nowMillis; if(newStage != null) { newStage.execute(player); } refreshNavigation(); } @TargetedEventHandler(priority = EventPriority.MONITOR) public void onApplyKit(ObserverKitApplyEvent event) { giveKit(player); } @TargetedEventHandler(priority = EventPriority.MONITOR) public void onPlayerInteract(ObserverInteractEvent event) { if(tutorial.hasStages() && event.getClickedItem() != null && event.getClickedItem().getType() == TUTORIAL_ITEM) { switch(event.getClickType()) { case LEFT: setCurrentStage(tutorial.getPreviousStage(currentStage)); break; case RIGHT: setCurrentStage(tutorial.getNextStage(currentStage)); break; } } } private void giveKit(MatchPlayer player) { if(tutorial.hasStages() && Parties.isObservingType(player.getParty())) { inventory.setItem(TUTORIAL_SLOT, createItem(bukkit)); } } private ItemStack createItem(CommandSender viewer) { final ItemStack item = new ItemStack(TUTORIAL_ITEM); final ItemMeta meta = item.getItemMeta(); meta.addItemFlags(ItemFlag.values()); meta.setDisplayName(renderer.renderLegacy(new Component(new TranslatableComponent("tutorial.displayName"), ChatColor.GOLD, ChatColor.BOLD), viewer)); meta.setLore(ImmutableList.of(renderer.renderLegacy(new Component(new TranslatableComponent("tutorial.tooltip", mapInfo.getColoredName()), ChatColor.WHITE), viewer))); item.setItemMeta(meta); return item; } @Repeatable(interval = @Time(seconds = 1), scope = MatchScope.LOADED) public void refreshNavigation() { if(!tutorial.hasStages()) return; final ItemStack holding = inventory.getItemInHand(); if(holding == null || holding.getType() != TUTORIAL_ITEM) return; if(currentStage != null) { if(navigation == null) { navigation = tutorial.renderNavigation(currentStage); } player.sendHotbarMessage(navigation); } else { if(navigation != null) { navigation = null; player.sendHotbarMessage(Components.blank()); } } } }