mirror of
https://github.com/filoghost/HolographicDisplays.git
synced 2024-12-24 17:57:36 +01:00
Experimental and potentially unstable: async packet sending
This commit is contained in:
parent
ed3bbad1fb
commit
0754e0ac33
@ -24,6 +24,7 @@ import me.filoghost.holographicdisplays.core.placeholder.tracking.ActivePlacehol
|
|||||||
import me.filoghost.holographicdisplays.core.tick.TickClock;
|
import me.filoghost.holographicdisplays.core.tick.TickClock;
|
||||||
import me.filoghost.holographicdisplays.core.tick.TickingTask;
|
import me.filoghost.holographicdisplays.core.tick.TickingTask;
|
||||||
import me.filoghost.holographicdisplays.core.tracking.LineTrackerManager;
|
import me.filoghost.holographicdisplays.core.tracking.LineTrackerManager;
|
||||||
|
import me.filoghost.holographicdisplays.core.tracking.PacketSenderExecutor;
|
||||||
import me.filoghost.holographicdisplays.nms.common.NMSManager;
|
import me.filoghost.holographicdisplays.nms.common.NMSManager;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
@ -47,6 +48,8 @@ public class HolographicDisplaysCore {
|
|||||||
throw new PluginEnableException(t, "Couldn't initialize the NMS manager.");
|
throw new PluginEnableException(t, "Couldn't initialize the NMS manager.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PacketSenderExecutor.start();
|
||||||
|
|
||||||
PlaceholderRegistry placeholderRegistry = new PlaceholderRegistry();
|
PlaceholderRegistry placeholderRegistry = new PlaceholderRegistry();
|
||||||
TickClock tickClock = new TickClock();
|
TickClock tickClock = new TickClock();
|
||||||
ActivePlaceholderTracker placeholderTracker = new ActivePlaceholderTracker(placeholderRegistry, tickClock);
|
ActivePlaceholderTracker placeholderTracker = new ActivePlaceholderTracker(placeholderRegistry, tickClock);
|
||||||
@ -103,6 +106,8 @@ public class HolographicDisplaysCore {
|
|||||||
nmsManager.uninjectPacketListener(player);
|
nmsManager.uninjectPacketListener(player);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PacketSenderExecutor.stopGracefully();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -85,7 +85,11 @@ public abstract class ClickableLineTracker<T extends Viewer> extends LineTracker
|
|||||||
@Override
|
@Override
|
||||||
protected void sendSpawnPackets(Viewers<T> viewers) {
|
protected void sendSpawnPackets(Viewers<T> viewers) {
|
||||||
if (spawnClickableEntity) {
|
if (spawnClickableEntity) {
|
||||||
viewers.sendPackets(clickableEntity.newSpawnPackets(getClickableEntityPosition()));
|
// Copy for async use
|
||||||
|
PositionCoordinates clickableEntityPosition = getClickableEntityPosition();
|
||||||
|
PacketSenderExecutor.execute(() -> {
|
||||||
|
viewers.sendPackets(clickableEntity.newSpawnPackets(clickableEntityPosition));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -93,7 +97,9 @@ public abstract class ClickableLineTracker<T extends Viewer> extends LineTracker
|
|||||||
@Override
|
@Override
|
||||||
protected void sendDestroyPackets(Viewers<T> viewers) {
|
protected void sendDestroyPackets(Viewers<T> viewers) {
|
||||||
if (spawnClickableEntity) {
|
if (spawnClickableEntity) {
|
||||||
|
PacketSenderExecutor.execute(() -> {
|
||||||
viewers.sendPackets(clickableEntity.newDestroyPackets());
|
viewers.sendPackets(clickableEntity.newDestroyPackets());
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -104,9 +110,15 @@ public abstract class ClickableLineTracker<T extends Viewer> extends LineTracker
|
|||||||
|
|
||||||
if (spawnClickableEntityChanged) {
|
if (spawnClickableEntityChanged) {
|
||||||
if (spawnClickableEntity) {
|
if (spawnClickableEntity) {
|
||||||
viewers.sendPackets(clickableEntity.newSpawnPackets(getClickableEntityPosition()));
|
// Copy for async use
|
||||||
|
PositionCoordinates clickableEntityPosition = getClickableEntityPosition();
|
||||||
|
PacketSenderExecutor.execute(() -> {
|
||||||
|
viewers.sendPackets(clickableEntity.newSpawnPackets(clickableEntityPosition));
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
|
PacketSenderExecutor.execute(() -> {
|
||||||
viewers.sendPackets(clickableEntity.newDestroyPackets());
|
viewers.sendPackets(clickableEntity.newDestroyPackets());
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -115,7 +127,11 @@ public abstract class ClickableLineTracker<T extends Viewer> extends LineTracker
|
|||||||
@Override
|
@Override
|
||||||
protected void sendPositionChangePackets(Viewers<T> viewers) {
|
protected void sendPositionChangePackets(Viewers<T> viewers) {
|
||||||
if (spawnClickableEntity) {
|
if (spawnClickableEntity) {
|
||||||
viewers.sendPackets(clickableEntity.newTeleportPackets(getClickableEntityPosition()));
|
// Copy for async use
|
||||||
|
PositionCoordinates clickableEntityPosition = getClickableEntityPosition();
|
||||||
|
PacketSenderExecutor.execute(() -> {
|
||||||
|
viewers.sendPackets(clickableEntity.newTeleportPackets(clickableEntityPosition));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
*/
|
*/
|
||||||
package me.filoghost.holographicdisplays.core.tracking;
|
package me.filoghost.holographicdisplays.core.tracking;
|
||||||
|
|
||||||
|
import me.filoghost.holographicdisplays.common.PositionCoordinates;
|
||||||
import me.filoghost.holographicdisplays.core.base.BaseItemHologramLine;
|
import me.filoghost.holographicdisplays.core.base.BaseItemHologramLine;
|
||||||
import me.filoghost.holographicdisplays.core.listener.LineClickListener;
|
import me.filoghost.holographicdisplays.core.listener.LineClickListener;
|
||||||
import me.filoghost.holographicdisplays.core.tick.CachedPlayer;
|
import me.filoghost.holographicdisplays.core.tick.CachedPlayer;
|
||||||
@ -106,7 +107,12 @@ public class ItemLineTracker extends ClickableLineTracker<Viewer> {
|
|||||||
super.sendSpawnPackets(viewers);
|
super.sendSpawnPackets(viewers);
|
||||||
|
|
||||||
if (spawnItemEntity) {
|
if (spawnItemEntity) {
|
||||||
|
// Copy for async use
|
||||||
|
PositionCoordinates positionCoordinates = this.positionCoordinates;
|
||||||
|
ItemStack itemStack = this.itemStack;
|
||||||
|
PacketSenderExecutor.execute(() -> {
|
||||||
viewers.sendPackets(itemEntity.newSpawnPackets(positionCoordinates, itemStack));
|
viewers.sendPackets(itemEntity.newSpawnPackets(positionCoordinates, itemStack));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -116,7 +122,9 @@ public class ItemLineTracker extends ClickableLineTracker<Viewer> {
|
|||||||
super.sendDestroyPackets(viewers);
|
super.sendDestroyPackets(viewers);
|
||||||
|
|
||||||
if (spawnItemEntity) {
|
if (spawnItemEntity) {
|
||||||
|
PacketSenderExecutor.execute(() -> {
|
||||||
viewers.sendPackets(itemEntity.newDestroyPackets());
|
viewers.sendPackets(itemEntity.newDestroyPackets());
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -127,13 +135,24 @@ public class ItemLineTracker extends ClickableLineTracker<Viewer> {
|
|||||||
|
|
||||||
if (spawnItemEntityChanged) {
|
if (spawnItemEntityChanged) {
|
||||||
if (spawnItemEntity) {
|
if (spawnItemEntity) {
|
||||||
|
// Copy for async use
|
||||||
|
PositionCoordinates positionCoordinates = this.positionCoordinates;
|
||||||
|
ItemStack itemStack = this.itemStack;
|
||||||
|
PacketSenderExecutor.execute(() -> {
|
||||||
viewers.sendPackets(itemEntity.newSpawnPackets(positionCoordinates, itemStack));
|
viewers.sendPackets(itemEntity.newSpawnPackets(positionCoordinates, itemStack));
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
|
PacketSenderExecutor.execute(() -> {
|
||||||
viewers.sendPackets(itemEntity.newDestroyPackets());
|
viewers.sendPackets(itemEntity.newDestroyPackets());
|
||||||
|
});
|
||||||
}
|
}
|
||||||
} else if (itemStackChanged) {
|
} else if (itemStackChanged) {
|
||||||
// Only send item changes if full spawn/destroy packets were not sent
|
// Only send item changes if full spawn/destroy packets were not sent
|
||||||
|
// Copy for async use
|
||||||
|
ItemStack itemStack = this.itemStack;
|
||||||
|
PacketSenderExecutor.execute(() -> {
|
||||||
viewers.sendPackets(itemEntity.newChangePackets(itemStack));
|
viewers.sendPackets(itemEntity.newChangePackets(itemStack));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -143,7 +162,11 @@ public class ItemLineTracker extends ClickableLineTracker<Viewer> {
|
|||||||
super.sendPositionChangePackets(viewers);
|
super.sendPositionChangePackets(viewers);
|
||||||
|
|
||||||
if (spawnItemEntity) {
|
if (spawnItemEntity) {
|
||||||
|
// Copy for async use
|
||||||
|
PositionCoordinates positionCoordinates = this.positionCoordinates;
|
||||||
|
PacketSenderExecutor.execute(() -> {
|
||||||
viewers.sendPackets(itemEntity.newTeleportPackets(positionCoordinates));
|
viewers.sendPackets(itemEntity.newTeleportPackets(positionCoordinates));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,14 +14,14 @@ import org.bukkit.entity.Player;
|
|||||||
import org.jetbrains.annotations.MustBeInvokedByOverriders;
|
import org.jetbrains.annotations.MustBeInvokedByOverriders;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.concurrent.ConcurrentMap;
|
||||||
|
|
||||||
public abstract class LineTracker<T extends Viewer> {
|
public abstract class LineTracker<T extends Viewer> {
|
||||||
|
|
||||||
private final Map<Player, T> viewers;
|
private final ConcurrentMap<Player, T> viewers;
|
||||||
private final Viewers<T> iterableViewers;
|
private final Viewers<T> iterableViewers;
|
||||||
|
|
||||||
private String positionWorldName;
|
private String positionWorldName;
|
||||||
@ -32,7 +32,7 @@ public abstract class LineTracker<T extends Viewer> {
|
|||||||
private int lastVisibilitySettingsVersion;
|
private int lastVisibilitySettingsVersion;
|
||||||
|
|
||||||
protected LineTracker() {
|
protected LineTracker() {
|
||||||
this.viewers = new HashMap<>();
|
this.viewers = new ConcurrentHashMap<>();
|
||||||
this.iterableViewers = new DelegateViewers<>(viewers.values());
|
this.iterableViewers = new DelegateViewers<>(viewers.values());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,7 +15,7 @@ public class MutableViewers<T extends Viewer> implements Viewers<T> {
|
|||||||
private T viewer;
|
private T viewer;
|
||||||
private List<T> additionalViewers;
|
private List<T> additionalViewers;
|
||||||
|
|
||||||
public void add(T viewer) {
|
public synchronized void add(T viewer) {
|
||||||
if (this.viewer == null) {
|
if (this.viewer == null) {
|
||||||
this.viewer = viewer;
|
this.viewer = viewer;
|
||||||
} else {
|
} else {
|
||||||
@ -27,7 +27,7 @@ public class MutableViewers<T extends Viewer> implements Viewers<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void forEach(Consumer<? super T> action) {
|
public synchronized void forEach(Consumer<? super T> action) {
|
||||||
if (viewer != null) {
|
if (viewer != null) {
|
||||||
action.accept(viewer);
|
action.accept(viewer);
|
||||||
if (additionalViewers != null) {
|
if (additionalViewers != null) {
|
||||||
|
@ -0,0 +1,69 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) filoghost and contributors
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
*/
|
||||||
|
package me.filoghost.holographicdisplays.core.tracking;
|
||||||
|
|
||||||
|
import me.filoghost.fcommons.logging.Log;
|
||||||
|
|
||||||
|
import java.util.concurrent.BlockingQueue;
|
||||||
|
import java.util.concurrent.LinkedBlockingQueue;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is a quick but ugly helper class for creating and sending packets async.
|
||||||
|
* Static classes like this should be avoided.
|
||||||
|
*/
|
||||||
|
public class PacketSenderExecutor {
|
||||||
|
|
||||||
|
private static volatile BlockingQueue<Runnable> tasks;
|
||||||
|
private static volatile Thread thread;
|
||||||
|
|
||||||
|
private static final Runnable STOP_MARKER_TASK = () -> {};
|
||||||
|
|
||||||
|
static {
|
||||||
|
tasks = new LinkedBlockingQueue<>();
|
||||||
|
thread = new Thread(() -> {
|
||||||
|
while (true) {
|
||||||
|
try {
|
||||||
|
Runnable task = tasks.take();
|
||||||
|
task.run();
|
||||||
|
} catch (Throwable t) {
|
||||||
|
Log.severe("Error in packet sender task", t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
thread.setName("Holographic Displays async packets");
|
||||||
|
thread.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void execute(Runnable task) {
|
||||||
|
tasks.add(task);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void start() {
|
||||||
|
tasks = new LinkedBlockingQueue<>();
|
||||||
|
thread = new Thread(() -> {
|
||||||
|
while (true) {
|
||||||
|
try {
|
||||||
|
Runnable task = tasks.take();
|
||||||
|
if (task == STOP_MARKER_TASK) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
task.run();
|
||||||
|
} catch (Throwable t) {
|
||||||
|
Log.severe("Error in packet sender task", t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
thread.setName("Holographic Displays packet sender");
|
||||||
|
thread.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void stopGracefully() {
|
||||||
|
if (tasks != null) {
|
||||||
|
tasks.add(STOP_MARKER_TASK);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -5,6 +5,7 @@
|
|||||||
*/
|
*/
|
||||||
package me.filoghost.holographicdisplays.core.tracking;
|
package me.filoghost.holographicdisplays.core.tracking;
|
||||||
|
|
||||||
|
import me.filoghost.holographicdisplays.common.PositionCoordinates;
|
||||||
import me.filoghost.holographicdisplays.core.base.BaseTextHologramLine;
|
import me.filoghost.holographicdisplays.core.base.BaseTextHologramLine;
|
||||||
import me.filoghost.holographicdisplays.core.listener.LineClickListener;
|
import me.filoghost.holographicdisplays.core.listener.LineClickListener;
|
||||||
import me.filoghost.holographicdisplays.core.placeholder.tracking.ActivePlaceholderTracker;
|
import me.filoghost.holographicdisplays.core.placeholder.tracking.ActivePlaceholderTracker;
|
||||||
@ -84,15 +85,22 @@ public class TextLineTracker extends ClickableLineTracker<TextLineViewer> {
|
|||||||
protected void sendSpawnPackets(Viewers<TextLineViewer> viewers) {
|
protected void sendSpawnPackets(Viewers<TextLineViewer> viewers) {
|
||||||
super.sendSpawnPackets(viewers);
|
super.sendSpawnPackets(viewers);
|
||||||
|
|
||||||
|
// Copy for async use
|
||||||
|
PositionCoordinates positionCoordinates = this.positionCoordinates;
|
||||||
|
viewers.forEach(TextLineViewer::updateNextTextToSend);
|
||||||
|
PacketSenderExecutor.execute(() -> {
|
||||||
IndividualTextPacketGroup spawnPackets = textEntity.newSpawnPackets(positionCoordinates);
|
IndividualTextPacketGroup spawnPackets = textEntity.newSpawnPackets(positionCoordinates);
|
||||||
viewers.forEach(viewer -> viewer.sendTextPackets(spawnPackets));
|
viewers.forEach(viewer -> viewer.sendTextPackets(spawnPackets));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@MustBeInvokedByOverriders
|
@MustBeInvokedByOverriders
|
||||||
@Override
|
@Override
|
||||||
protected void sendDestroyPackets(Viewers<TextLineViewer> viewers) {
|
protected void sendDestroyPackets(Viewers<TextLineViewer> viewers) {
|
||||||
super.sendDestroyPackets(viewers);
|
super.sendDestroyPackets(viewers);
|
||||||
|
PacketSenderExecutor.execute(() -> {
|
||||||
viewers.sendPackets(textEntity.newDestroyPackets());
|
viewers.sendPackets(textEntity.newDestroyPackets());
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -100,8 +108,11 @@ public class TextLineTracker extends ClickableLineTracker<TextLineViewer> {
|
|||||||
super.sendChangesPackets(viewers);
|
super.sendChangesPackets(viewers);
|
||||||
|
|
||||||
if (displayTextChanged) {
|
if (displayTextChanged) {
|
||||||
|
viewers.forEach(TextLineViewer::updateNextTextToSend);
|
||||||
|
PacketSenderExecutor.execute(() -> {
|
||||||
IndividualTextPacketGroup changePackets = textEntity.newChangePackets();
|
IndividualTextPacketGroup changePackets = textEntity.newChangePackets();
|
||||||
viewers.forEach(viewer -> viewer.sendTextPacketsIfNecessary(changePackets));
|
viewers.forEach(viewer -> viewer.sendTextPacketsIfNecessary(changePackets));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -109,7 +120,11 @@ public class TextLineTracker extends ClickableLineTracker<TextLineViewer> {
|
|||||||
@Override
|
@Override
|
||||||
protected void sendPositionChangePackets(Viewers<TextLineViewer> viewers) {
|
protected void sendPositionChangePackets(Viewers<TextLineViewer> viewers) {
|
||||||
super.sendPositionChangePackets(viewers);
|
super.sendPositionChangePackets(viewers);
|
||||||
|
// Copy for async use
|
||||||
|
PositionCoordinates positionCoordinates = this.positionCoordinates;
|
||||||
|
PacketSenderExecutor.execute(() -> {
|
||||||
viewers.sendPackets(textEntity.newTeleportPackets(positionCoordinates));
|
viewers.sendPackets(textEntity.newTeleportPackets(positionCoordinates));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -5,9 +5,8 @@
|
|||||||
*/
|
*/
|
||||||
package me.filoghost.holographicdisplays.core.tracking;
|
package me.filoghost.holographicdisplays.core.tracking;
|
||||||
|
|
||||||
import me.filoghost.holographicdisplays.nms.common.IndividualTextPacketGroup;
|
|
||||||
import me.filoghost.holographicdisplays.core.tick.CachedPlayer;
|
import me.filoghost.holographicdisplays.core.tick.CachedPlayer;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import me.filoghost.holographicdisplays.nms.common.IndividualTextPacketGroup;
|
||||||
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
@ -15,8 +14,10 @@ class TextLineViewer extends Viewer {
|
|||||||
|
|
||||||
private final DisplayText displayText;
|
private final DisplayText displayText;
|
||||||
|
|
||||||
|
// Access to these variables must be synchronized, they are accessed from multiple threads
|
||||||
private String individualText;
|
private String individualText;
|
||||||
private String lastSentText;
|
private String lastSentText;
|
||||||
|
private String nextTextToSend;
|
||||||
|
|
||||||
TextLineViewer(CachedPlayer player, DisplayText displayText) {
|
TextLineViewer(CachedPlayer player, DisplayText displayText) {
|
||||||
super(player);
|
super(player);
|
||||||
@ -24,34 +25,41 @@ class TextLineViewer extends Viewer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void sendTextPackets(IndividualTextPacketGroup packets) {
|
public void sendTextPackets(IndividualTextPacketGroup packets) {
|
||||||
String text = getOrComputeText();
|
String text;
|
||||||
|
synchronized (this) {
|
||||||
|
text = nextTextToSend;
|
||||||
this.lastSentText = text;
|
this.lastSentText = text;
|
||||||
|
}
|
||||||
sendIndividualPackets(packets, text);
|
sendIndividualPackets(packets, text);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void sendTextPacketsIfNecessary(IndividualTextPacketGroup packets) {
|
public void sendTextPacketsIfNecessary(IndividualTextPacketGroup packets) {
|
||||||
String text = getOrComputeText();
|
String text;
|
||||||
|
synchronized (this) {
|
||||||
|
text = nextTextToSend;
|
||||||
if (Objects.equals(lastSentText, text)) {
|
if (Objects.equals(lastSentText, text)) {
|
||||||
return; // Avoid sending unnecessary packets
|
return; // Avoid sending unnecessary packets
|
||||||
}
|
}
|
||||||
this.lastSentText = text;
|
this.lastSentText = text;
|
||||||
|
}
|
||||||
sendIndividualPackets(packets, text);
|
sendIndividualPackets(packets, text);
|
||||||
}
|
}
|
||||||
|
|
||||||
private @Nullable String getOrComputeText() {
|
public synchronized void updateNextTextToSend() {
|
||||||
if (displayText.containsIndividualPlaceholders()) {
|
if (displayText.containsIndividualPlaceholders()) {
|
||||||
if (individualText == null) {
|
if (individualText == null) {
|
||||||
individualText = displayText.computeIndividualText(this);
|
individualText = displayText.computeIndividualText(this);
|
||||||
}
|
}
|
||||||
return individualText;
|
nextTextToSend = individualText;
|
||||||
} else {
|
} else {
|
||||||
individualText = null;
|
individualText = null;
|
||||||
return displayText.getGlobalText();
|
nextTextToSend = displayText.getGlobalText();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean updateIndividualText() {
|
public boolean updateIndividualText() {
|
||||||
String individualText = displayText.computeIndividualText(this);
|
String individualText = displayText.computeIndividualText(this);
|
||||||
|
synchronized (this) {
|
||||||
if (!Objects.equals(this.individualText, individualText)) {
|
if (!Objects.equals(this.individualText, individualText)) {
|
||||||
this.individualText = individualText;
|
this.individualText = individualText;
|
||||||
return true;
|
return true;
|
||||||
@ -59,5 +67,6 @@ class TextLineViewer extends Viewer {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -14,13 +14,14 @@ import java.util.UUID;
|
|||||||
|
|
||||||
class PacketByteBuffer {
|
class PacketByteBuffer {
|
||||||
|
|
||||||
private static final PacketByteBuffer INSTANCE = new PacketByteBuffer();
|
private static final ThreadLocal<PacketByteBuffer> LOCAL_INSTANCE = ThreadLocal.withInitial(PacketByteBuffer::new);
|
||||||
|
|
||||||
private final PacketDataSerializer serializer;
|
private final PacketDataSerializer serializer;
|
||||||
|
|
||||||
static PacketByteBuffer get() {
|
static PacketByteBuffer get() {
|
||||||
INSTANCE.clear();
|
PacketByteBuffer instance = LOCAL_INSTANCE.get();
|
||||||
return INSTANCE;
|
instance.clear();
|
||||||
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
private PacketByteBuffer() {
|
private PacketByteBuffer() {
|
||||||
|
@ -14,13 +14,14 @@ import java.util.UUID;
|
|||||||
|
|
||||||
class PacketByteBuffer {
|
class PacketByteBuffer {
|
||||||
|
|
||||||
private static final PacketByteBuffer INSTANCE = new PacketByteBuffer();
|
private static final ThreadLocal<PacketByteBuffer> LOCAL_INSTANCE = ThreadLocal.withInitial(PacketByteBuffer::new);
|
||||||
|
|
||||||
private final PacketDataSerializer serializer;
|
private final PacketDataSerializer serializer;
|
||||||
|
|
||||||
static PacketByteBuffer get() {
|
static PacketByteBuffer get() {
|
||||||
INSTANCE.clear();
|
PacketByteBuffer instance = LOCAL_INSTANCE.get();
|
||||||
return INSTANCE;
|
instance.clear();
|
||||||
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
private PacketByteBuffer() {
|
private PacketByteBuffer() {
|
||||||
|
@ -14,13 +14,14 @@ import java.util.UUID;
|
|||||||
|
|
||||||
class PacketByteBuffer {
|
class PacketByteBuffer {
|
||||||
|
|
||||||
private static final PacketByteBuffer INSTANCE = new PacketByteBuffer();
|
private static final ThreadLocal<PacketByteBuffer> LOCAL_INSTANCE = ThreadLocal.withInitial(PacketByteBuffer::new);
|
||||||
|
|
||||||
private final PacketDataSerializer serializer;
|
private final PacketDataSerializer serializer;
|
||||||
|
|
||||||
static PacketByteBuffer get() {
|
static PacketByteBuffer get() {
|
||||||
INSTANCE.clear();
|
PacketByteBuffer instance = LOCAL_INSTANCE.get();
|
||||||
return INSTANCE;
|
instance.clear();
|
||||||
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
private PacketByteBuffer() {
|
private PacketByteBuffer() {
|
||||||
|
@ -14,13 +14,14 @@ import java.util.UUID;
|
|||||||
|
|
||||||
class PacketByteBuffer {
|
class PacketByteBuffer {
|
||||||
|
|
||||||
private static final PacketByteBuffer INSTANCE = new PacketByteBuffer();
|
private static final ThreadLocal<PacketByteBuffer> LOCAL_INSTANCE = ThreadLocal.withInitial(PacketByteBuffer::new);
|
||||||
|
|
||||||
private final PacketDataSerializer serializer;
|
private final PacketDataSerializer serializer;
|
||||||
|
|
||||||
static PacketByteBuffer get() {
|
static PacketByteBuffer get() {
|
||||||
INSTANCE.clear();
|
PacketByteBuffer instance = LOCAL_INSTANCE.get();
|
||||||
return INSTANCE;
|
instance.clear();
|
||||||
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
private PacketByteBuffer() {
|
private PacketByteBuffer() {
|
||||||
|
@ -14,13 +14,14 @@ import java.util.UUID;
|
|||||||
|
|
||||||
class PacketByteBuffer {
|
class PacketByteBuffer {
|
||||||
|
|
||||||
private static final PacketByteBuffer INSTANCE = new PacketByteBuffer();
|
private static final ThreadLocal<PacketByteBuffer> LOCAL_INSTANCE = ThreadLocal.withInitial(PacketByteBuffer::new);
|
||||||
|
|
||||||
private final PacketDataSerializer serializer;
|
private final PacketDataSerializer serializer;
|
||||||
|
|
||||||
static PacketByteBuffer get() {
|
static PacketByteBuffer get() {
|
||||||
INSTANCE.clear();
|
PacketByteBuffer instance = LOCAL_INSTANCE.get();
|
||||||
return INSTANCE;
|
instance.clear();
|
||||||
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
private PacketByteBuffer() {
|
private PacketByteBuffer() {
|
||||||
|
@ -14,13 +14,14 @@ import java.util.UUID;
|
|||||||
|
|
||||||
class PacketByteBuffer {
|
class PacketByteBuffer {
|
||||||
|
|
||||||
private static final PacketByteBuffer INSTANCE = new PacketByteBuffer();
|
private static final ThreadLocal<PacketByteBuffer> LOCAL_INSTANCE = ThreadLocal.withInitial(PacketByteBuffer::new);
|
||||||
|
|
||||||
private final PacketDataSerializer serializer;
|
private final PacketDataSerializer serializer;
|
||||||
|
|
||||||
static PacketByteBuffer get() {
|
static PacketByteBuffer get() {
|
||||||
INSTANCE.clear();
|
PacketByteBuffer instance = LOCAL_INSTANCE.get();
|
||||||
return INSTANCE;
|
instance.clear();
|
||||||
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
private PacketByteBuffer() {
|
private PacketByteBuffer() {
|
||||||
|
@ -14,13 +14,14 @@ import java.util.UUID;
|
|||||||
|
|
||||||
class PacketByteBuffer {
|
class PacketByteBuffer {
|
||||||
|
|
||||||
private static final PacketByteBuffer INSTANCE = new PacketByteBuffer();
|
private static final ThreadLocal<PacketByteBuffer> LOCAL_INSTANCE = ThreadLocal.withInitial(PacketByteBuffer::new);
|
||||||
|
|
||||||
private final PacketDataSerializer serializer;
|
private final PacketDataSerializer serializer;
|
||||||
|
|
||||||
static PacketByteBuffer get() {
|
static PacketByteBuffer get() {
|
||||||
INSTANCE.clear();
|
PacketByteBuffer instance = LOCAL_INSTANCE.get();
|
||||||
return INSTANCE;
|
instance.clear();
|
||||||
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
void writeBoolean(boolean flag) {
|
void writeBoolean(boolean flag) {
|
||||||
|
@ -12,13 +12,14 @@ import java.util.UUID;
|
|||||||
|
|
||||||
class PacketByteBuffer {
|
class PacketByteBuffer {
|
||||||
|
|
||||||
private static final PacketByteBuffer INSTANCE = new PacketByteBuffer();
|
private static final ThreadLocal<PacketByteBuffer> LOCAL_INSTANCE = ThreadLocal.withInitial(PacketByteBuffer::new);
|
||||||
|
|
||||||
private final PacketDataSerializer serializer;
|
private final PacketDataSerializer serializer;
|
||||||
|
|
||||||
static PacketByteBuffer get() {
|
static PacketByteBuffer get() {
|
||||||
INSTANCE.clear();
|
PacketByteBuffer instance = LOCAL_INSTANCE.get();
|
||||||
return INSTANCE;
|
instance.clear();
|
||||||
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
private PacketByteBuffer() {
|
private PacketByteBuffer() {
|
||||||
|
@ -12,13 +12,14 @@ import java.util.UUID;
|
|||||||
|
|
||||||
class PacketByteBuffer {
|
class PacketByteBuffer {
|
||||||
|
|
||||||
private static final PacketByteBuffer INSTANCE = new PacketByteBuffer();
|
private static final ThreadLocal<PacketByteBuffer> LOCAL_INSTANCE = ThreadLocal.withInitial(PacketByteBuffer::new);
|
||||||
|
|
||||||
private final PacketDataSerializer serializer;
|
private final PacketDataSerializer serializer;
|
||||||
|
|
||||||
static PacketByteBuffer get() {
|
static PacketByteBuffer get() {
|
||||||
INSTANCE.clear();
|
PacketByteBuffer instance = LOCAL_INSTANCE.get();
|
||||||
return INSTANCE;
|
instance.clear();
|
||||||
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
private PacketByteBuffer() {
|
private PacketByteBuffer() {
|
||||||
|
@ -12,13 +12,14 @@ import java.util.UUID;
|
|||||||
|
|
||||||
class PacketByteBuffer {
|
class PacketByteBuffer {
|
||||||
|
|
||||||
private static final PacketByteBuffer INSTANCE = new PacketByteBuffer();
|
private static final ThreadLocal<PacketByteBuffer> LOCAL_INSTANCE = ThreadLocal.withInitial(PacketByteBuffer::new);
|
||||||
|
|
||||||
private final PacketDataSerializer serializer;
|
private final PacketDataSerializer serializer;
|
||||||
|
|
||||||
static PacketByteBuffer get() {
|
static PacketByteBuffer get() {
|
||||||
INSTANCE.clear();
|
PacketByteBuffer instance = LOCAL_INSTANCE.get();
|
||||||
return INSTANCE;
|
instance.clear();
|
||||||
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
private PacketByteBuffer() {
|
private PacketByteBuffer() {
|
||||||
|
@ -12,13 +12,14 @@ import java.util.UUID;
|
|||||||
|
|
||||||
class PacketByteBuffer {
|
class PacketByteBuffer {
|
||||||
|
|
||||||
private static final PacketByteBuffer INSTANCE = new PacketByteBuffer();
|
private static final ThreadLocal<PacketByteBuffer> LOCAL_INSTANCE = ThreadLocal.withInitial(PacketByteBuffer::new);
|
||||||
|
|
||||||
private final PacketDataSerializer serializer;
|
private final PacketDataSerializer serializer;
|
||||||
|
|
||||||
static PacketByteBuffer get() {
|
static PacketByteBuffer get() {
|
||||||
INSTANCE.clear();
|
PacketByteBuffer instance = LOCAL_INSTANCE.get();
|
||||||
return INSTANCE;
|
instance.clear();
|
||||||
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
private PacketByteBuffer() {
|
private PacketByteBuffer() {
|
||||||
|
@ -12,13 +12,14 @@ import java.util.UUID;
|
|||||||
|
|
||||||
class PacketByteBuffer {
|
class PacketByteBuffer {
|
||||||
|
|
||||||
private static final PacketByteBuffer INSTANCE = new PacketByteBuffer();
|
private static final ThreadLocal<PacketByteBuffer> LOCAL_INSTANCE = ThreadLocal.withInitial(PacketByteBuffer::new);
|
||||||
|
|
||||||
private final PacketDataSerializer serializer;
|
private final PacketDataSerializer serializer;
|
||||||
|
|
||||||
static PacketByteBuffer get() {
|
static PacketByteBuffer get() {
|
||||||
INSTANCE.clear();
|
PacketByteBuffer instance = LOCAL_INSTANCE.get();
|
||||||
return INSTANCE;
|
instance.clear();
|
||||||
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
private PacketByteBuffer() {
|
private PacketByteBuffer() {
|
||||||
|
@ -12,13 +12,14 @@ import java.util.UUID;
|
|||||||
|
|
||||||
class PacketByteBuffer {
|
class PacketByteBuffer {
|
||||||
|
|
||||||
private static final PacketByteBuffer INSTANCE = new PacketByteBuffer();
|
private static final ThreadLocal<PacketByteBuffer> LOCAL_INSTANCE = ThreadLocal.withInitial(PacketByteBuffer::new);
|
||||||
|
|
||||||
private final PacketDataSerializer serializer;
|
private final PacketDataSerializer serializer;
|
||||||
|
|
||||||
static PacketByteBuffer get() {
|
static PacketByteBuffer get() {
|
||||||
INSTANCE.clear();
|
PacketByteBuffer instance = LOCAL_INSTANCE.get();
|
||||||
return INSTANCE;
|
instance.clear();
|
||||||
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
private PacketByteBuffer() {
|
private PacketByteBuffer() {
|
||||||
|
@ -12,13 +12,14 @@ import java.util.UUID;
|
|||||||
|
|
||||||
class PacketByteBuffer {
|
class PacketByteBuffer {
|
||||||
|
|
||||||
private static final PacketByteBuffer INSTANCE = new PacketByteBuffer();
|
private static final ThreadLocal<PacketByteBuffer> LOCAL_INSTANCE = ThreadLocal.withInitial(PacketByteBuffer::new);
|
||||||
|
|
||||||
private final PacketDataSerializer serializer;
|
private final PacketDataSerializer serializer;
|
||||||
|
|
||||||
static PacketByteBuffer get() {
|
static PacketByteBuffer get() {
|
||||||
INSTANCE.clear();
|
PacketByteBuffer instance = LOCAL_INSTANCE.get();
|
||||||
return INSTANCE;
|
instance.clear();
|
||||||
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
private PacketByteBuffer() {
|
private PacketByteBuffer() {
|
||||||
|
@ -12,13 +12,14 @@ import java.util.UUID;
|
|||||||
|
|
||||||
class PacketByteBuffer {
|
class PacketByteBuffer {
|
||||||
|
|
||||||
private static final PacketByteBuffer INSTANCE = new PacketByteBuffer();
|
private static final ThreadLocal<PacketByteBuffer> LOCAL_INSTANCE = ThreadLocal.withInitial(PacketByteBuffer::new);
|
||||||
|
|
||||||
private final PacketDataSerializer serializer;
|
private final PacketDataSerializer serializer;
|
||||||
|
|
||||||
static PacketByteBuffer get() {
|
static PacketByteBuffer get() {
|
||||||
INSTANCE.clear();
|
PacketByteBuffer instance = LOCAL_INSTANCE.get();
|
||||||
return INSTANCE;
|
instance.clear();
|
||||||
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
private PacketByteBuffer() {
|
private PacketByteBuffer() {
|
||||||
|
@ -12,13 +12,14 @@ import java.util.UUID;
|
|||||||
|
|
||||||
class PacketByteBuffer {
|
class PacketByteBuffer {
|
||||||
|
|
||||||
private static final PacketByteBuffer INSTANCE = new PacketByteBuffer();
|
private static final ThreadLocal<PacketByteBuffer> LOCAL_INSTANCE = ThreadLocal.withInitial(PacketByteBuffer::new);
|
||||||
|
|
||||||
private final PacketDataSerializer serializer;
|
private final PacketDataSerializer serializer;
|
||||||
|
|
||||||
static PacketByteBuffer get() {
|
static PacketByteBuffer get() {
|
||||||
INSTANCE.clear();
|
PacketByteBuffer instance = LOCAL_INSTANCE.get();
|
||||||
return INSTANCE;
|
instance.clear();
|
||||||
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
private PacketByteBuffer() {
|
private PacketByteBuffer() {
|
||||||
|
@ -14,13 +14,14 @@ import java.io.IOException;
|
|||||||
|
|
||||||
class PacketByteBuffer {
|
class PacketByteBuffer {
|
||||||
|
|
||||||
private static final PacketByteBuffer INSTANCE = new PacketByteBuffer();
|
private static final ThreadLocal<PacketByteBuffer> LOCAL_INSTANCE = ThreadLocal.withInitial(PacketByteBuffer::new);
|
||||||
|
|
||||||
private final PacketDataSerializer serializer;
|
private final PacketDataSerializer serializer;
|
||||||
|
|
||||||
static PacketByteBuffer get() {
|
static PacketByteBuffer get() {
|
||||||
INSTANCE.clear();
|
PacketByteBuffer instance = LOCAL_INSTANCE.get();
|
||||||
return INSTANCE;
|
instance.clear();
|
||||||
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
private PacketByteBuffer() {
|
private PacketByteBuffer() {
|
||||||
|
@ -14,13 +14,14 @@ import java.util.UUID;
|
|||||||
|
|
||||||
class PacketByteBuffer {
|
class PacketByteBuffer {
|
||||||
|
|
||||||
private static final PacketByteBuffer INSTANCE = new PacketByteBuffer();
|
private static final ThreadLocal<PacketByteBuffer> LOCAL_INSTANCE = ThreadLocal.withInitial(PacketByteBuffer::new);
|
||||||
|
|
||||||
private final PacketDataSerializer serializer;
|
private final PacketDataSerializer serializer;
|
||||||
|
|
||||||
static PacketByteBuffer get() {
|
static PacketByteBuffer get() {
|
||||||
INSTANCE.clear();
|
PacketByteBuffer instance = LOCAL_INSTANCE.get();
|
||||||
return INSTANCE;
|
instance.clear();
|
||||||
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
private PacketByteBuffer() {
|
private PacketByteBuffer() {
|
||||||
|
Loading…
Reference in New Issue
Block a user