diff --git a/src/main/java/eu/decentsoftware/holograms/api/actions/ClickType.java b/src/main/java/eu/decentsoftware/holograms/api/actions/ClickType.java index b74dffcf..4914c32d 100644 --- a/src/main/java/eu/decentsoftware/holograms/api/actions/ClickType.java +++ b/src/main/java/eu/decentsoftware/holograms/api/actions/ClickType.java @@ -3,7 +3,7 @@ import org.bukkit.event.block.Action; public enum ClickType { - LEFT, RIGHT, SHIFT_LEFT, SHIFT_RIGHT; + LEFT, RIGHT, SHIFT_LEFT, SHIFT_RIGHT,HOVER,HOVER_LEAVE; public static ClickType fromAction(Action action, boolean sneak) { switch (action) { diff --git a/src/main/java/eu/decentsoftware/holograms/api/holograms/Hologram.java b/src/main/java/eu/decentsoftware/holograms/api/holograms/Hologram.java index 0a4dae7f..bfd6e944 100644 --- a/src/main/java/eu/decentsoftware/holograms/api/holograms/Hologram.java +++ b/src/main/java/eu/decentsoftware/holograms/api/holograms/Hologram.java @@ -29,13 +29,7 @@ import org.jetbrains.annotations.Nullable; import java.io.File; -import java.util.Collection; -import java.util.Collections; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.UUID; +import java.util.*; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; @@ -198,6 +192,7 @@ public static Hologram fromFile(final @NotNull String filePath) throws LocationP } } hologram.setFacing((float) config.getDouble("facing", 0.0f)); + hologram.setHoverCommands(config.getStringList("hover")); return hologram; } diff --git a/src/main/java/eu/decentsoftware/holograms/api/holograms/HologramManager.java b/src/main/java/eu/decentsoftware/holograms/api/holograms/HologramManager.java index 34301506..89ecccf0 100644 --- a/src/main/java/eu/decentsoftware/holograms/api/holograms/HologramManager.java +++ b/src/main/java/eu/decentsoftware/holograms/api/holograms/HologramManager.java @@ -8,6 +8,7 @@ import eu.decentsoftware.holograms.api.utils.file.FileUtils; import eu.decentsoftware.holograms.api.utils.scheduler.S; import eu.decentsoftware.holograms.api.utils.tick.Ticked; +import eu.decentsoftware.holograms.event.DecentHologramsRegisterEvent; import lombok.NonNull; import org.bukkit.Bukkit; import org.bukkit.Location; @@ -227,6 +228,9 @@ public boolean containsHologram(@NonNull String name) { */ public void registerHologram(@NonNull Hologram hologram) { hologramMap.put(hologram.getName(), hologram); + Bukkit.getScheduler().runTask(decentHolograms.getPlugin(), ()->{ + Bukkit.getServer().getPluginManager().callEvent(new DecentHologramsRegisterEvent()); + }); } /** diff --git a/src/main/java/eu/decentsoftware/holograms/api/holograms/objects/HologramObject.java b/src/main/java/eu/decentsoftware/holograms/api/holograms/objects/HologramObject.java index dac874c0..fde86f4e 100644 --- a/src/main/java/eu/decentsoftware/holograms/api/holograms/objects/HologramObject.java +++ b/src/main/java/eu/decentsoftware/holograms/api/holograms/objects/HologramObject.java @@ -27,6 +27,7 @@ public abstract class HologramObject extends FlagHolder { protected Location location; protected String permission = null; protected float facing = 0.0f; + protected List hoverCommands = new ArrayList<>(); /* * Constructors @@ -132,6 +133,10 @@ public void setFacing(float facing) { this.location.setYaw(facing); } + public void setHoverCommands(List hoverCommands) { + this.hoverCommands = hoverCommands; + } + public void setLocation(@NonNull Location location) { this.location = location; this.location.setYaw(facing); diff --git a/src/main/java/eu/decentsoftware/holograms/api/listeners/PlayerListener.java b/src/main/java/eu/decentsoftware/holograms/api/listeners/PlayerListener.java index 6cb40bb2..c80f8b99 100644 --- a/src/main/java/eu/decentsoftware/holograms/api/listeners/PlayerListener.java +++ b/src/main/java/eu/decentsoftware/holograms/api/listeners/PlayerListener.java @@ -2,15 +2,25 @@ import eu.decentsoftware.holograms.api.DecentHolograms; import eu.decentsoftware.holograms.api.Lang; +import eu.decentsoftware.holograms.api.actions.ClickType; +import eu.decentsoftware.holograms.api.holograms.Hologram; import eu.decentsoftware.holograms.api.utils.scheduler.S; +import eu.decentsoftware.holograms.event.DecentHologramsRegisterEvent; +import eu.decentsoftware.holograms.event.HologramClickEvent; +import lombok.Data; +import org.bukkit.Bukkit; +import org.bukkit.Chunk; +import org.bukkit.Location; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; -import org.bukkit.event.player.PlayerJoinEvent; -import org.bukkit.event.player.PlayerQuitEvent; -import org.bukkit.event.player.PlayerRespawnEvent; -import org.bukkit.event.player.PlayerTeleportEvent; +import org.bukkit.event.player.*; +import org.bukkit.util.Vector; + +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; +import java.util.stream.Collectors; @SuppressWarnings("unused") public class PlayerListener implements Listener { @@ -19,6 +29,7 @@ public class PlayerListener implements Listener { public PlayerListener(DecentHolograms decentHolograms) { this.decentHolograms = decentHolograms; + this.ref(); } @EventHandler(priority = EventPriority.MONITOR) @@ -53,6 +64,89 @@ public void onRespawn(PlayerRespawnEvent e) { S.async(() -> decentHolograms.getHologramManager().hideAll(player)); } + + // 视角对着的全息 + private Map viewHolograms = new ConcurrentHashMap<>(); + + + private Map tickLog = new ConcurrentHashMap<>(); + + public Map> chunkListMap = new ConcurrentHashMap<>(); + + private void ref(){ + chunkListMap.clear(); + decentHolograms.getHologramManager().getHolograms().stream().forEach(hologram -> { + Chunk chunk = hologram.getLocation().getChunk(); + chunkListMap.putIfAbsent(chunk,new ArrayList<>()); + chunkListMap.get(chunk).add(hologram); + }); + } + + + @EventHandler + public void onRegisterHd(DecentHologramsRegisterEvent registerEvent){ + this.ref(); + } + + @EventHandler + public void onPlayerMove(PlayerMoveEvent playerMoveEvent){ + Player player = playerMoveEvent.getPlayer(); + Long orDefault = tickLog.getOrDefault(player, 0L); + + if(chunkListMap.isEmpty()) ref(); + + if((System.currentTimeMillis()-orDefault) >= 200L){ + Optional.ofNullable(chunkListMap.get(player.getLocation().getChunk())).ifPresent(list->{ + List holograms = list.stream().collect(Collectors.toList()); + Vector playerDirection = player.getEyeLocation().getDirection(); + double threshold = 0.2; // 0.2弧度 + + tickLog.put(player,System.currentTimeMillis()); + + holograms.removeIf(hologram -> { + Location location = hologram.getLocation(); + Vector toHologram = location.toVector().subtract(player.getEyeLocation().toVector()); + double angle = playerDirection.angle(toHologram); + return angle>=threshold; + }); + + String currentViewHd = viewHolograms.get(player); + + + for (Hologram hologram : holograms) { + if(currentViewHd==null) viewHolograms.put(player,hologram.getName()); + + currentViewHd = viewHolograms.get(player); + + // 如果从一个全息移动到了另一个全息上 + if(!currentViewHd.equalsIgnoreCase(hologram.getName())){ + Hologram fromHologram = decentHolograms.getHologramManager().getHologram(currentViewHd); + List clickableEntityIds = fromHologram.getPage(player).getClickableEntityIds(); + if(clickableEntityIds.size()>0){ + fromHologram.onClick(player,clickableEntityIds.get(0),ClickType.HOVER_LEAVE); + viewHolograms.put(player,hologram.getName()); + } + } + + List clickableEntityIds = hologram.getPage(player).getClickableEntityIds(); + if(!clickableEntityIds.isEmpty()){ + hologram.onClick(player,clickableEntityIds.get(0), ClickType.HOVER); + } + return; + } + + if(currentViewHd!=null){ + Hologram fromHologram = decentHolograms.getHologramManager().getHologram(currentViewHd); + List clickableEntityIds = fromHologram.getPage(player).getClickableEntityIds(); + if(clickableEntityIds.size()>0){ + fromHologram.onClick(player,clickableEntityIds.get(0),ClickType.HOVER_LEAVE); + viewHolograms.remove(player); + } + } + }); + } + } + @EventHandler public void onTeleport(PlayerTeleportEvent e) { Player player = e.getPlayer(); diff --git a/src/main/java/eu/decentsoftware/holograms/event/DecentHologramsRegisterEvent.java b/src/main/java/eu/decentsoftware/holograms/event/DecentHologramsRegisterEvent.java new file mode 100644 index 00000000..0f059762 --- /dev/null +++ b/src/main/java/eu/decentsoftware/holograms/event/DecentHologramsRegisterEvent.java @@ -0,0 +1,32 @@ +package eu.decentsoftware.holograms.event; + +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; + +/** + * This event is called after the DecentHolograms plugin is reloaded. + * + * @author d0by + * @since 2.7.8 + */ +public class DecentHologramsRegisterEvent extends Event { + + private static final HandlerList HANDLERS = new HandlerList(); + + public DecentHologramsRegisterEvent() { + } + + @Override + public HandlerList getHandlers() { + return HANDLERS; + } + + public static HandlerList getHandlerList() { + return HANDLERS; + } + + public static boolean isRegistered() { + return HANDLERS.getRegisteredListeners().length > 0; + } + +}