Optimizations

This commit is contained in:
filoghost 2021-12-24 16:49:05 +01:00
parent e25c2aca40
commit 90e26af19b
11 changed files with 123 additions and 42 deletions

View File

@ -0,0 +1,58 @@
/*
* Copyright (C) filoghost and contributors
*
* SPDX-License-Identifier: GPL-3.0-or-later
*/
package me.filoghost.holographicdisplays.plugin.hologram.tracking;
import me.filoghost.holographicdisplays.plugin.tick.TickClock;
import org.bukkit.Location;
import org.bukkit.entity.Player;
public class CachedPlayer {
private final Player player;
private final TickClock tickClock;
private Location location;
private long locationUpdateTick;
public CachedPlayer(Player player, TickClock tickClock) {
this.player = player;
this.tickClock = tickClock;
this.locationUpdateTick = -1;
}
public Player getBukkitPlayer() {
return player;
}
public Location getLocation() {
long currentTick = tickClock.getCurrentTick();
if (locationUpdateTick != currentTick) {
location = player.getLocation();
locationUpdateTick = currentTick;
}
return location;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null || getClass() != obj.getClass()) {
return false;
}
CachedPlayer other = (CachedPlayer) obj;
return player.equals(other.player);
}
@Override
public int hashCode() {
return player.hashCode();
}
}

View File

@ -7,7 +7,6 @@ package me.filoghost.holographicdisplays.plugin.hologram.tracking;
import me.filoghost.holographicdisplays.common.PositionCoordinates;
import org.bukkit.Location;
import org.bukkit.entity.Player;
public class CollisionHelper {
@ -25,7 +24,7 @@ public class CollisionHelper {
private static final double REQUIRED_DISTANCE_Z = REQUIRED_DISTANCE_X;
private static final double REQUIRED_DISTANCE_Y = PLAYER_HEIGHT_RADIUS + PLAYER_GROW_HEIGHT + ITEM_HEIGHT_RADIUS;
public static boolean isInPickupRange(Player player, PositionCoordinates itemPosition) {
public static boolean isInPickupRange(Location playerLocation, PositionCoordinates itemPosition) {
/*
* Normally, the server determines if a player is picking up a dropped item
* by checking if the bounding boxes of the player and the item intersect.
@ -58,7 +57,6 @@ public class CollisionHelper {
* In the example above, the distance between the centers is lower than the sum of the two radii,
* so the boxes collide in that direction.
*/
Location playerLocation = player.getLocation();
// The Y position is on lowest point of the bounding box, not in the center
double playerCenterY = playerLocation.getY() + PLAYER_HEIGHT_RADIUS;

View File

@ -94,7 +94,7 @@ class DisplayText {
public @NotNull String computeIndividualText(Viewer viewer) {
Preconditions.notNull(unreplacedText, "unreplacedText");
return unreplacedText.replacePlaceholders(viewer.getPlayer(), placeholderTracker);
return unreplacedText.replacePlaceholders(viewer.getBukkitPlayer(), placeholderTracker);
}
}

View File

@ -9,7 +9,6 @@ import me.filoghost.holographicdisplays.nms.common.NMSManager;
import me.filoghost.holographicdisplays.nms.common.entity.ItemNMSPacketEntity;
import me.filoghost.holographicdisplays.plugin.hologram.base.BaseItemHologramLine;
import me.filoghost.holographicdisplays.plugin.listener.LineClickListener;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.MustBeInvokedByOverriders;
@ -40,13 +39,13 @@ public class ItemLineTracker extends ClickableLineTracker<Viewer> {
@MustBeInvokedByOverriders
@Override
protected void update(Collection<? extends Player> onlinePlayers) {
protected void update(Collection<CachedPlayer> onlinePlayers) {
super.update(onlinePlayers);
if (spawnItemEntity && hasViewers() && line.hasPickupCallback()) {
for (Viewer viewer : getViewers()) {
if (CollisionHelper.isInPickupRange(viewer.getPlayer(), position)) {
line.onPickup(viewer.getPlayer());
if (CollisionHelper.isInPickupRange(viewer.getLocation(), position)) {
line.onPickup(viewer.getBukkitPlayer());
}
}
}
@ -58,8 +57,8 @@ public class ItemLineTracker extends ClickableLineTracker<Viewer> {
}
@Override
protected Viewer createViewer(Player player) {
return new Viewer(player);
protected Viewer createViewer(CachedPlayer cachedPlayer) {
return new Viewer(cachedPlayer);
}
@MustBeInvokedByOverriders

View File

@ -44,7 +44,7 @@ public abstract class LineTracker<T extends Viewer> {
}
@MustBeInvokedByOverriders
protected void update(Collection<? extends Player> onlinePlayers) {
protected void update(Collection<CachedPlayer> onlinePlayers) {
boolean sendChangesPackets = false;
// First, detect the changes if the flag is on and set it off
@ -76,7 +76,7 @@ public abstract class LineTracker<T extends Viewer> {
protected abstract boolean updatePlaceholders();
private void modifyViewersAndSendPackets(Collection<? extends Player> onlinePlayers) {
private void modifyViewersAndSendPackets(Collection<CachedPlayer> onlinePlayers) {
if (!getLine().isInLoadedChunk()) {
resetViewersAndSendDestroyPackets();
return;
@ -86,19 +86,20 @@ public abstract class LineTracker<T extends Viewer> {
MutableViewers<T> addedPlayers = null;
MutableViewers<T> removedPlayers = null;
for (Player player : onlinePlayers) {
if (shouldTrackPlayer(player)) {
if (!viewers.containsKey(player)) {
T viewer = createViewer(player);
viewers.put(player, viewer);
for (CachedPlayer cachedPlayer : onlinePlayers) {
Player bukkitPlayer = cachedPlayer.getBukkitPlayer();
if (shouldTrackPlayer(cachedPlayer)) {
if (!viewers.containsKey(bukkitPlayer)) {
T viewer = createViewer(cachedPlayer);
viewers.put(bukkitPlayer, viewer);
if (addedPlayers == null) {
addedPlayers = new MutableViewers<>();
}
addedPlayers.add(viewer);
}
} else {
if (viewers.containsKey(player)) {
T viewer = viewers.remove(player);
if (viewers.containsKey(bukkitPlayer)) {
T viewer = viewers.remove(bukkitPlayer);
if (removedPlayers == null) {
removedPlayers = new MutableViewers<>();
}
@ -115,9 +116,9 @@ public abstract class LineTracker<T extends Viewer> {
}
}
protected abstract T createViewer(Player player);
protected abstract T createViewer(CachedPlayer cachedPlayer);
protected abstract boolean shouldTrackPlayer(Player player);
protected abstract boolean shouldTrackPlayer(CachedPlayer cachedPlayer);
protected final boolean hasViewers() {
return !viewers.isEmpty();

View File

@ -10,7 +10,6 @@ import me.filoghost.holographicdisplays.plugin.hologram.base.BaseItemHologramLin
import me.filoghost.holographicdisplays.plugin.hologram.base.BaseTextHologramLine;
import me.filoghost.holographicdisplays.plugin.listener.LineClickListener;
import me.filoghost.holographicdisplays.plugin.placeholder.tracking.ActivePlaceholderTracker;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import java.util.Collection;
@ -43,9 +42,7 @@ public class LineTrackerManager {
return tracker;
}
public void update() {
Collection<? extends Player> onlinePlayers = Bukkit.getOnlinePlayers();
public void update(Collection<CachedPlayer> onlinePlayers) {
Iterator<LineTracker<?>> iterator = lineTrackers.iterator();
while (iterator.hasNext()) {
LineTracker<?> lineTracker = iterator.next();

View File

@ -7,7 +7,6 @@ package me.filoghost.holographicdisplays.plugin.hologram.tracking;
import me.filoghost.holographicdisplays.common.PositionCoordinates;
import org.bukkit.Location;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.MustBeInvokedByOverriders;
import java.util.Objects;
@ -36,8 +35,8 @@ abstract class PositionBasedLineTracker<T extends Viewer> extends LineTracker<T>
}
@Override
protected final boolean shouldTrackPlayer(Player player) {
Location playerLocation = player.getLocation();
protected final boolean shouldTrackPlayer(CachedPlayer cachedPlayer) {
Location playerLocation = cachedPlayer.getLocation();
if (playerLocation.getWorld() != getLine().getWorldIfLoaded()) {
return false;
}
@ -47,7 +46,7 @@ abstract class PositionBasedLineTracker<T extends Viewer> extends LineTracker<T>
return diffX <= (double) ENTITY_VIEW_RANGE
&& diffZ <= (double) ENTITY_VIEW_RANGE
&& getLine().isVisibleTo(player);
&& getLine().isVisibleTo(cachedPlayer.getBukkitPlayer());
}
@MustBeInvokedByOverriders

View File

@ -11,7 +11,6 @@ import me.filoghost.holographicdisplays.nms.common.entity.TextNMSPacketEntity;
import me.filoghost.holographicdisplays.plugin.hologram.base.BaseTextHologramLine;
import me.filoghost.holographicdisplays.plugin.listener.LineClickListener;
import me.filoghost.holographicdisplays.plugin.placeholder.tracking.ActivePlaceholderTracker;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.MustBeInvokedByOverriders;
import java.util.Objects;
@ -50,8 +49,8 @@ public class TextLineTracker extends ClickableLineTracker<TextLineViewer> {
}
@Override
protected TextLineViewer createViewer(Player player) {
return new TextLineViewer(player, displayText);
protected TextLineViewer createViewer(CachedPlayer cachedPlayer) {
return new TextLineViewer(cachedPlayer, displayText);
}
@MustBeInvokedByOverriders

View File

@ -6,7 +6,6 @@
package me.filoghost.holographicdisplays.plugin.hologram.tracking;
import me.filoghost.holographicdisplays.nms.common.IndividualTextPacketGroup;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.Nullable;
import java.util.Objects;
@ -18,7 +17,7 @@ class TextLineViewer extends Viewer {
private String individualText;
private String lastSentText;
TextLineViewer(Player player, DisplayText displayText) {
TextLineViewer(CachedPlayer player, DisplayText displayText) {
super(player);
this.displayText = displayText;
}
@ -26,7 +25,7 @@ class TextLineViewer extends Viewer {
public void sendTextPackets(IndividualTextPacketGroup packets) {
String text = getOrComputeText();
this.lastSentText = text;
packets.sendTo(getPlayer(), text);
sendIndividualPackets(packets, text);
}
public void sendTextPacketsIfNecessary(IndividualTextPacketGroup packets) {
@ -35,7 +34,7 @@ class TextLineViewer extends Viewer {
return; // Avoid sending unnecessary packets
}
this.lastSentText = text;
packets.sendTo(getPlayer(), text);
sendIndividualPackets(packets, text);
}
private @Nullable String getOrComputeText() {

View File

@ -5,23 +5,33 @@
*/
package me.filoghost.holographicdisplays.plugin.hologram.tracking;
import me.filoghost.holographicdisplays.nms.common.IndividualTextPacketGroup;
import me.filoghost.holographicdisplays.nms.common.PacketGroup;
import org.bukkit.Location;
import org.bukkit.entity.Player;
class Viewer {
private final Player player;
private final CachedPlayer player;
Viewer(Player player) {
Viewer(CachedPlayer player) {
this.player = player;
}
public final Player getPlayer() {
return player;
public final Player getBukkitPlayer() {
return player.getBukkitPlayer();
}
public Location getLocation() {
return player.getLocation();
}
public void sendPackets(PacketGroup packetGroup) {
packetGroup.sendTo(player);
packetGroup.sendTo(player.getBukkitPlayer());
}
public void sendIndividualPackets(IndividualTextPacketGroup packetGroup, String text) {
packetGroup.sendTo(player.getBukkitPlayer(), text);
}
}

View File

@ -6,9 +6,16 @@
package me.filoghost.holographicdisplays.plugin.tick;
import me.filoghost.fcommons.logging.Log;
import me.filoghost.holographicdisplays.plugin.hologram.tracking.CachedPlayer;
import me.filoghost.holographicdisplays.plugin.hologram.tracking.LineTrackerManager;
import me.filoghost.holographicdisplays.plugin.listener.LineClickListener;
import me.filoghost.holographicdisplays.plugin.placeholder.tracking.ActivePlaceholderTracker;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import java.util.ArrayList;
import java.util.Collection;
import java.util.WeakHashMap;
public class TickingTask implements Runnable {
@ -16,6 +23,7 @@ public class TickingTask implements Runnable {
private final ActivePlaceholderTracker placeholderTracker;
private final LineTrackerManager lineTrackerManager;
private final LineClickListener lineClickListener;
private final WeakHashMap<Player, CachedPlayer> cachedPlayersMap;
private long lastErrorLogTick;
@ -28,6 +36,7 @@ public class TickingTask implements Runnable {
this.placeholderTracker = placeholderTracker;
this.lineTrackerManager = lineTrackerManager;
this.lineClickListener = lineClickListener;
this.cachedPlayersMap = new WeakHashMap<>();
}
@Override
@ -38,7 +47,7 @@ public class TickingTask implements Runnable {
placeholderTracker.clearOutdatedEntries();
try {
lineTrackerManager.update();
lineTrackerManager.update(getOnlineCachedPlayers());
} catch (Throwable t) {
// Catch all types of Throwable because we're using NMS code
if (tickClock.getCurrentTick() - lastErrorLogTick >= 20) {
@ -54,4 +63,16 @@ public class TickingTask implements Runnable {
lineClickListener.processQueuedClickEvents();
}
private Collection<CachedPlayer> getOnlineCachedPlayers() {
Collection<? extends Player> bukkitPlayers = Bukkit.getOnlinePlayers();
Collection<CachedPlayer> cachedPlayers = new ArrayList<>(bukkitPlayers.size());
for (Player bukkitPlayer : bukkitPlayers) {
CachedPlayer cachedPlayer = cachedPlayersMap.computeIfAbsent(bukkitPlayer, key -> new CachedPlayer(key, tickClock));
cachedPlayers.add(cachedPlayer);
}
return cachedPlayers;
}
}