Compare commits

...

36 Commits

Author SHA1 Message Date
filoghost 6f343c5fc0 Fix viewers mutating after submitting async packet sending 2024-03-09 23:43:21 +01:00
filoghost 9dcf6035fe Remove duplicate thread initialization 2024-03-09 22:55:31 +01:00
filoghost 0754e0ac33 Experimental and potentially unstable: async packet sending 2024-02-19 23:11:34 +01:00
filoghost ed3bbad1fb Set version to 3.0.5-SNAPSHOT 2024-02-18 15:03:30 +01:00
filoghost 667668f0f0 Fix version (wrongfully set to 3.0.5) 2024-01-27 16:39:55 +01:00
filoghost c14141679f Set version to 3.0.4 2024-01-27 16:11:43 +01:00
filoghost 563df95561 Attempt to fix packet injector issues 2024-01-27 11:15:30 +01:00
Spongecade 3f067145b7 Update Minecraft wiki link to new domain 2024-01-26 22:48:48 +01:00
rayanbzd 9fd3bf2d0f Update to correct EntityTypeID 2024-01-26 22:27:32 +01:00
rayanbzd 0b289b017b 1.20.3 & 1.20.4 support 2024-01-26 22:27:32 +01:00
filoghost 07968520f0 Add support for Minecraft 1.20.2 2023-10-01 13:14:09 +02:00
filoghost 51fc2d0bd4 Set version to 3.0.4-SNAPSHOT 2023-10-01 13:12:53 +02:00
filoghost 5d22e2754d Set version to 3.0.3 2023-06-18 15:23:12 +02:00
Sascha Bartl a3c82bfddf Add support for Minecraft 1.20 2023-06-10 14:19:33 +02:00
filoghost 2fa71ad3e0 Only re-send spawn packets to respawned players on older versions 2023-05-01 22:14:02 +02:00
filoghost 917db5ad94 Update issue templates 2023-04-29 18:16:15 +02:00
filoghost 705abee6a3 Fix Maven build 2023-04-25 21:34:43 +02:00
filoghost 3727868dff Set version to 3.0.3-SNAPSHOT 2023-04-25 18:18:20 +02:00
filoghost fab8c9594d Set version to 3.0.2 2023-04-25 14:39:01 +02:00
filoghost ef890acacd Fix missing dependency 2023-03-25 15:59:38 +01:00
filoghost 2b5afc82af Add support for Minecraft 1.19.4 2023-03-25 15:55:52 +01:00
filoghost d057dd750c Drop support for less used minor Minecraft versions (1.16.0 to 1.16.3) 2023-03-19 16:49:08 +01:00
filoghost 27ebb9d2d8 Avoid extending internal NMS classes 2023-03-19 16:44:40 +01:00
filoghost 70779348af Set version to 3.0.2-SNAPSHOT 2023-02-05 15:12:30 +01:00
filoghost dd1f6f024d Set version to 3.0.1 2023-02-05 15:05:52 +01:00
filoghost 5d2c97f194 Add optional short format for PlaceholderAPI (e.g. %player% instead of {papi: player}) 2023-01-06 23:41:27 +01:00
filoghost 788cdc2c45 Add support for Minecraft 1.19.3 2022-12-13 23:37:57 +01:00
filoghost a5d9f58df3 Fix image rendering symbols 2022-12-04 15:06:40 +01:00
filoghost 850beaebb8 Refactoring 2022-12-04 12:39:01 +01:00
filoghost 2f83fdcfdb Update README.md versions 2022-11-18 22:09:22 +01:00
filoghost 39e51328cc Small simplification 2022-11-14 00:14:01 +01:00
filoghost 017b0a2346 Additional async checks 2022-11-14 00:12:58 +01:00
filoghost 80344c8503 Force initial refresh on line trackers 2022-11-13 23:54:30 +01:00
filoghost 39f0a02412 Make holograms view range configurable 2022-11-13 16:29:41 +01:00
filoghost 0e98b2f89a Move spaceBetweenLines to separate class 2022-11-13 16:29:41 +01:00
filoghost 0449fe65ca Set version to 3.0.1-SNAPSHOT 2022-10-30 10:19:13 +01:00
263 changed files with 4465 additions and 1097 deletions

View File

@ -1,16 +0,0 @@
name: 💡 Suggestion
description: "Suggest a new feature or an improvement."
labels:
- "Enhancement"
body:
- type: markdown
attributes:
value: |-
Please suggest changes that would benefit as many users as possible, not just specific situations. Thank you for contributing to the project.
- type: textarea
attributes:
label: "Description"
description: "Describe the new feature or improvement."
validations:
required: true

View File

@ -1,42 +0,0 @@
name: 📝 Help request
description: "Ask a question."
labels:
- "Help"
body:
- type: markdown
attributes:
value: |-
Please make sure you are using a recent version of the plugin.
- type: checkboxes
attributes:
label: "Confirmation"
description: "Please confirm to have done the following checks before opening a new issue."
options:
- label: "I have read the [documentation](https://filoghost.me/docs/holographic-displays)."
required: true
- label: "I have read the [FAQ](https://filoghost.me/docs/holographic-displays/faq)."
required: true
- type: textarea
attributes:
label: "Description"
description: "Describe your goal and what you have tried so far."
placeholder: "What are you trying to achieve? What have you tried so far?"
validations:
required: true
- type: input
attributes:
label: "Holographic Displays version"
description: "Output of the command `/version HolographicDisplays`."
placeholder: "HolographicDisplays version 2.4.8-SNAPSHOT-b174"
validations:
required: true
- type: textarea
attributes:
label: Additional information
description: |-
Relevant attachments such as **screenshots**, **server logs**, **configurations files** or any other additional information that might be useful.
Text files can also be uploaded to [Pastebin](https://pastebin.com) and shared through the generated link.

View File

@ -1,16 +0,0 @@
name: 📚 Documentation improvement
description: "Suggest a change or report an error to improve the official documentation."
labels:
- "Documentation"
body:
- type: markdown
attributes:
value: |-
Suggest a change or report an error to improve the official documentation. Thank you for contributing to the project.
- type: textarea
attributes:
label: "Description"
description: "Describe what should be improved and, if possible, _how_."
validations:
required: true

View File

@ -17,9 +17,9 @@ Development Builds: https://ci.codemc.io/job/filoghost/job/HolographicDisplays
```xml
<dependency>
<groupId>com.gmail.filoghost.holographicdisplays</groupId>
<groupId>me.filoghost.holographicdisplays</groupId>
<artifactId>holographicdisplays-api</artifactId>
<version>2.4.9</version>
<version>3.0.0</version>
<scope>provided</scope>
</dependency>
```
@ -32,7 +32,7 @@ maven {
```
```groovy
compileOnly 'com.gmail.filoghost.holographicdisplays:holographicdisplays-api:2.4.9'
compileOnly 'me.filoghost.holographicdisplays:holographicdisplays-api:3.0.0'
```
## License

View File

@ -6,7 +6,7 @@
<parent>
<groupId>me.filoghost.holographicdisplays</groupId>
<artifactId>holographicdisplays-parent</artifactId>
<version>3.0.0</version>
<version>3.0.5-SNAPSHOT</version>
</parent>
<artifactId>holographicdisplays-api</artifactId>

View File

@ -125,7 +125,6 @@
<!-- Miscellaneous -->
<module name="ArrayTypeStyle"/>
<module name="AvoidEscapedUnicodeCharacters"/>
<module name="CommentsIndentation"/>
<module name="Indentation">
<property name="basicOffset" value="4"/>

View File

@ -6,7 +6,7 @@
<parent>
<groupId>me.filoghost.holographicdisplays</groupId>
<artifactId>holographicdisplays-parent</artifactId>
<version>3.0.0</version>
<version>3.0.5-SNAPSHOT</version>
</parent>
<artifactId>holographicdisplays-common</artifactId>

View File

@ -6,7 +6,7 @@
<parent>
<groupId>me.filoghost.holographicdisplays</groupId>
<artifactId>holographicdisplays-parent</artifactId>
<version>3.0.0</version>
<version>3.0.5-SNAPSHOT</version>
</parent>
<artifactId>holographicdisplays-core</artifactId>
@ -74,16 +74,6 @@
<artifactId>holographicdisplays-nms-v1_15_r1</artifactId>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>holographicdisplays-nms-v1_16_r1</artifactId>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>holographicdisplays-nms-v1_16_r2</artifactId>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>holographicdisplays-nms-v1_16_r3</artifactId>
@ -109,6 +99,31 @@
<artifactId>holographicdisplays-nms-v1_19_r1</artifactId>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>holographicdisplays-nms-v1_19_r2</artifactId>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>holographicdisplays-nms-v1_19_r3</artifactId>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>holographicdisplays-nms-v1_20_r1</artifactId>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>holographicdisplays-nms-v1_20_r2</artifactId>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>holographicdisplays-nms-v1_20_r3</artifactId>
</dependency>
<dependency>
<groupId>org.spigotmc</groupId>
<artifactId>spigot-api</artifactId>

View File

@ -0,0 +1,13 @@
/*
* Copyright (C) filoghost and contributors
*
* SPDX-License-Identifier: GPL-3.0-or-later
*/
package me.filoghost.holographicdisplays.core;
public class CoreGlobalConfig {
public static double spaceBetweenLines;
public static int maxViewRange;
}

View File

@ -0,0 +1,16 @@
/*
* Copyright (C) filoghost and contributors
*
* SPDX-License-Identifier: GPL-3.0-or-later
*/
package me.filoghost.holographicdisplays.core;
import me.filoghost.fcommons.Preconditions;
public class CorePreconditions {
public static void checkMainThread() {
Preconditions.checkMainThread("async operation is not supported");
}
}

View File

@ -16,7 +16,6 @@ import me.filoghost.holographicdisplays.core.api.current.DefaultHolographicDispl
import me.filoghost.holographicdisplays.core.api.v2.V2HologramManager;
import me.filoghost.holographicdisplays.core.api.v2.V2HologramsAPIProvider;
import me.filoghost.holographicdisplays.core.base.BaseHologram;
import me.filoghost.holographicdisplays.core.base.BaseHologramLines;
import me.filoghost.holographicdisplays.core.listener.ChunkListener;
import me.filoghost.holographicdisplays.core.listener.LineClickListener;
import me.filoghost.holographicdisplays.core.listener.PlayerListener;
@ -25,6 +24,7 @@ import me.filoghost.holographicdisplays.core.placeholder.tracking.ActivePlacehol
import me.filoghost.holographicdisplays.core.tick.TickClock;
import me.filoghost.holographicdisplays.core.tick.TickingTask;
import me.filoghost.holographicdisplays.core.tracking.LineTrackerManager;
import me.filoghost.holographicdisplays.core.tracking.PacketSenderExecutor;
import me.filoghost.holographicdisplays.nms.common.NMSManager;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
@ -41,13 +41,15 @@ public class HolographicDisplaysCore {
try {
nmsManager = NMSVersion.getCurrent().createNMSManager(errorCollector);
} catch (UnknownVersionException e) {
throw new PluginEnableException("Holographic Displays only supports Spigot from 1.8 to 1.18.2.");
throw new PluginEnableException("Holographic Displays only supports Spigot from 1.8 to 1.20.");
} catch (OutdatedVersionException e) {
throw new PluginEnableException("Holographic Displays only supports " + e.getMinimumSupportedVersion() + " and above.");
} catch (Throwable t) {
throw new PluginEnableException(t, "Couldn't initialize the NMS manager.");
}
PacketSenderExecutor.start();
PlaceholderRegistry placeholderRegistry = new PlaceholderRegistry();
TickClock tickClock = new TickClock();
ActivePlaceholderTracker placeholderTracker = new ActivePlaceholderTracker(placeholderRegistry, tickClock);
@ -81,7 +83,7 @@ public class HolographicDisplaysCore {
}
public void setSpaceBetweenHologramLines(double spaceBetweenLines) {
BaseHologramLines.spaceBetweenLines = spaceBetweenLines;
CoreGlobalConfig.spaceBetweenLines = spaceBetweenLines;
for (BaseHologram hologram : apiHologramManager.getHolograms()) {
hologram.getLines().updatePositions();
}
@ -90,6 +92,10 @@ public class HolographicDisplaysCore {
}
}
public void setMaxViewRange(int maxViewRange) {
CoreGlobalConfig.maxViewRange = maxViewRange;
}
public void disable() {
if (lineTrackerManager != null) {
lineTrackerManager.resetViewersAndSendDestroyPackets();
@ -100,6 +106,8 @@ public class HolographicDisplaysCore {
nmsManager.uninjectPacketListener(player);
}
}
PacketSenderExecutor.stopGracefully();
}
}

View File

@ -32,13 +32,18 @@ public enum NMSVersion {
/* 1.13.1 - 1.13.2 */ v1_13_R2(errorCollector -> new me.filoghost.holographicdisplays.nms.v1_13_R2.VersionNMSManager(errorCollector)),
/* 1.14 - 1.14.4 */ v1_14_R1(errorCollector -> new me.filoghost.holographicdisplays.nms.v1_14_R1.VersionNMSManager(errorCollector)),
/* 1.15 - 1.15.2 */ v1_15_R1(errorCollector -> new me.filoghost.holographicdisplays.nms.v1_15_R1.VersionNMSManager(errorCollector)),
/* 1.16 - 1.16.1 */ v1_16_R1(errorCollector -> new me.filoghost.holographicdisplays.nms.v1_16_R1.VersionNMSManager(errorCollector)),
/* 1.16.2 - 1.16.3 */ v1_16_R2(errorCollector -> new me.filoghost.holographicdisplays.nms.v1_16_R2.VersionNMSManager(errorCollector)),
/* 1.16 - 1.16.1 */ v1_16_R1(NMSManagerFactory.outdatedVersion("1.16.4")),
/* 1.16.2 - 1.16.3 */ v1_16_R2(NMSManagerFactory.outdatedVersion("1.16.4")),
/* 1.16.4 - 1.16.5 */ v1_16_R3(errorCollector -> new me.filoghost.holographicdisplays.nms.v1_16_R3.VersionNMSManager(errorCollector)),
/* 1.17 */ v1_17_R1(errorCollector -> new me.filoghost.holographicdisplays.nms.v1_17_R1.VersionNMSManager(errorCollector)),
/* 1.18 - 1.18.1 */ v1_18_R1(errorCollector -> new me.filoghost.holographicdisplays.nms.v1_18_R1.VersionNMSManager(errorCollector)),
/* 1.18.2 */ v1_18_R2(errorCollector -> new me.filoghost.holographicdisplays.nms.v1_18_R2.VersionNMSManager(errorCollector)),
/* 1.19 - ? */ v1_19_R1(errorCollector -> new me.filoghost.holographicdisplays.nms.v1_19_R1.VersionNMSManager(errorCollector)),
/* 1.19 - 1.19.2 */ v1_19_R1(errorCollector -> new me.filoghost.holographicdisplays.nms.v1_19_R1.VersionNMSManager(errorCollector)),
/* 1.19.3 */ v1_19_R2(errorCollector -> new me.filoghost.holographicdisplays.nms.v1_19_R2.VersionNMSManager(errorCollector)),
/* 1.19.4 */ v1_19_R3(errorCollector -> new me.filoghost.holographicdisplays.nms.v1_19_R3.VersionNMSManager(errorCollector)),
/* 1.20 - 1.20.1 */ v1_20_R1(errorCollector -> new me.filoghost.holographicdisplays.nms.v1_20_R1.VersionNMSManager(errorCollector)),
/* 1.20.2 */ v1_20_R2(errorCollector -> new me.filoghost.holographicdisplays.nms.v1_20_R2.VersionNMSManager(errorCollector)),
/* 1.20.3 - 1.20.4 */ v1_20_R3(errorCollector -> new me.filoghost.holographicdisplays.nms.v1_20_R3.VersionNMSManager(errorCollector)),
/* Other versions */ UNKNOWN(NMSManagerFactory.unknownVersion());
private static final NMSVersion CURRENT_VERSION = detectCurrentVersion();

View File

@ -9,6 +9,7 @@ import me.filoghost.fcommons.Preconditions;
import me.filoghost.holographicdisplays.api.Position;
import me.filoghost.holographicdisplays.api.hologram.Hologram;
import me.filoghost.holographicdisplays.api.hologram.PlaceholderSetting;
import me.filoghost.holographicdisplays.core.CorePreconditions;
import me.filoghost.holographicdisplays.core.base.BaseHologram;
import me.filoghost.holographicdisplays.core.base.ImmutablePosition;
import me.filoghost.holographicdisplays.core.tracking.LineTrackerManager;
@ -30,7 +31,7 @@ class APIHologram extends BaseHologram implements Hologram {
LineTrackerManager lineTrackerManager) {
super(position, lineTrackerManager);
Preconditions.notNull(plugin, "plugin");
this.lines = new APIHologramLines(this);
this.lines = new APIHologramLines(this, lineTrackerManager);
this.plugin = plugin;
this.hologramManager = hologramManager;
this.placeholderSetting = PlaceholderSetting.DEFAULT;
@ -53,6 +54,7 @@ class APIHologram extends BaseHologram implements Hologram {
@Override
public void setPlaceholderSetting(@NotNull PlaceholderSetting placeholderSetting) {
CorePreconditions.checkMainThread();
Preconditions.notNull(placeholderSetting, "placeholderSetting");
checkNotDeleted();

View File

@ -11,6 +11,7 @@ import me.filoghost.holographicdisplays.api.hologram.line.HologramLine;
import me.filoghost.holographicdisplays.api.hologram.line.ItemHologramLine;
import me.filoghost.holographicdisplays.api.hologram.line.TextHologramLine;
import me.filoghost.holographicdisplays.core.base.BaseHologramLines;
import me.filoghost.holographicdisplays.core.tracking.LineTrackerManager;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@ -19,8 +20,8 @@ class APIHologramLines extends BaseHologramLines<APIHologramLine> implements Hol
private final APIHologram hologram;
APIHologramLines(APIHologram hologram) {
super(hologram);
APIHologramLines(APIHologram hologram, LineTrackerManager lineTrackerManager) {
super(hologram, lineTrackerManager);
this.hologram = hologram;
}

View File

@ -8,6 +8,7 @@ package me.filoghost.holographicdisplays.core.api.current;
import me.filoghost.holographicdisplays.api.hologram.line.HologramLineClickListener;
import me.filoghost.holographicdisplays.api.hologram.line.HologramLinePickupListener;
import me.filoghost.holographicdisplays.api.hologram.line.ItemHologramLine;
import me.filoghost.holographicdisplays.core.CorePreconditions;
import me.filoghost.holographicdisplays.core.base.BaseItemHologramLine;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
@ -24,35 +25,39 @@ class APIItemHologramLine extends BaseItemHologramLine implements ItemHologramLi
@Override
public @Nullable HologramLinePickupListener getPickupListener() {
CorePreconditions.checkMainThread();
return pickupListener;
}
@Override
public void setPickupListener(@Nullable HologramLinePickupListener pickupListener) {
CorePreconditions.checkMainThread();
checkNotDeleted();
this.pickupListener = pickupListener;
}
@Override
public @Nullable HologramLineClickListener getClickListener() {
return clickListener;
}
@Override
public boolean hasPickupCallback() {
return pickupListener != null;
}
@Override
protected void invokePickupCallback(Player player) {
protected void invokeExternalPickupCallback(Player player) {
if (pickupListener != null) {
pickupListener.onPickup(new SimpleHologramLinePickupEvent(player));
}
}
@Override
public @Nullable HologramLineClickListener getClickListener() {
CorePreconditions.checkMainThread();
return clickListener;
}
@Override
public void setClickListener(@Nullable HologramLineClickListener clickListener) {
CorePreconditions.checkMainThread();
checkNotDeleted();
this.clickListener = clickListener;
@ -65,7 +70,7 @@ class APIItemHologramLine extends BaseItemHologramLine implements ItemHologramLi
}
@Override
protected void invokeClickCallback(Player player) {
protected void invokeExternalClickCallback(Player player) {
if (clickListener != null) {
clickListener.onClick(new SimpleHologramLineClickEvent(player));
}

View File

@ -8,6 +8,7 @@ package me.filoghost.holographicdisplays.core.api.current;
import me.filoghost.holographicdisplays.api.hologram.PlaceholderSetting;
import me.filoghost.holographicdisplays.api.hologram.line.HologramLineClickListener;
import me.filoghost.holographicdisplays.api.hologram.line.TextHologramLine;
import me.filoghost.holographicdisplays.core.CorePreconditions;
import me.filoghost.holographicdisplays.core.base.BaseTextHologramLine;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.Nullable;
@ -30,6 +31,7 @@ class APITextHologramLine extends BaseTextHologramLine implements TextHologramLi
@Override
public void setClickListener(@Nullable HologramLineClickListener clickListener) {
CorePreconditions.checkMainThread();
checkNotDeleted();
this.clickListener = clickListener;
@ -47,7 +49,7 @@ class APITextHologramLine extends BaseTextHologramLine implements TextHologramLi
}
@Override
protected void invokeClickCallback(Player player) {
protected void invokeExternalClickCallback(Player player) {
if (clickListener != null) {
clickListener.onClick(new SimpleHologramLineClickEvent(player));
}

View File

@ -17,26 +17,20 @@ import org.bukkit.block.Block;
import org.bukkit.entity.Entity;
import org.bukkit.plugin.Plugin;
import java.util.Map;
import java.util.WeakHashMap;
import java.util.function.Function;
public class DefaultHolographicDisplaysAPIProvider extends HolographicDisplaysAPIProvider {
private final Map<Plugin, HolographicDisplaysAPI> apiCache;
private final Function<Plugin, HolographicDisplaysAPI> apiFactory;
private final APIHologramManager apiHologramManager;
private final PlaceholderRegistry placeholderRegistry;
public DefaultHolographicDisplaysAPIProvider(APIHologramManager apiHologramManager, PlaceholderRegistry placeholderRegistry) {
this.apiCache = new WeakHashMap<>();
this.apiFactory = plugin -> new DefaultHolographicDisplaysAPI(plugin, apiHologramManager, placeholderRegistry);
this.apiHologramManager = apiHologramManager;
this.placeholderRegistry = placeholderRegistry;
}
@Override
public HolographicDisplaysAPI getHolographicDisplaysAPI(Plugin plugin) {
Preconditions.notNull(plugin, "plugin");
// Optimization: avoid creating a new instance every time a plugin requests it, in case it never stores a reference
return apiCache.computeIfAbsent(plugin, apiFactory);
return new DefaultHolographicDisplaysAPI(plugin, apiHologramManager, placeholderRegistry);
}
@Override

View File

@ -37,7 +37,7 @@ class V2Hologram extends BaseHologram implements Hologram {
super(position, lineTrackerManager);
this.plugin = plugin;
this.hologramManager = hologramManager;
this.lines = new BaseHologramLines<>(this);
this.lines = new BaseHologramLines<>(this, lineTrackerManager);
this.visibilityManager = new V2VisibilityManager(getVisibilitySettings());
this.creationTimestamp = System.currentTimeMillis();
}

View File

@ -46,7 +46,7 @@ class V2ItemLine extends BaseItemHologramLine implements ItemLine, V2HologramLin
}
@Override
protected void invokeClickCallback(Player player) {
protected void invokeExternalClickCallback(Player player) {
if (touchHandler != null) {
touchHandler.onTouch(player);
}
@ -68,7 +68,7 @@ class V2ItemLine extends BaseItemHologramLine implements ItemLine, V2HologramLin
}
@Override
protected void invokePickupCallback(Player player) {
protected void invokeExternalPickupCallback(Player player) {
if (pickupHandler != null) {
pickupHandler.onPickup(player);
}

View File

@ -48,7 +48,7 @@ class V2TextLine extends BaseTextHologramLine implements TextLine, V2HologramLin
}
@Override
protected void invokeClickCallback(Player player) {
protected void invokeExternalClickCallback(Player player) {
if (touchHandler != null) {
touchHandler.onTouch(player);
}

View File

@ -6,8 +6,6 @@
package me.filoghost.holographicdisplays.core.base;
import me.filoghost.fcommons.logging.Log;
import me.filoghost.holographicdisplays.common.PositionCoordinates;
import org.bukkit.Location;
import org.bukkit.entity.Player;
public abstract class BaseClickableHologramLine extends BaseHologramLine {
@ -17,30 +15,16 @@ public abstract class BaseClickableHologramLine extends BaseHologramLine {
}
public void onClick(Player player) {
if (hasClickCallback() && canInteract(player) && isInClickRange(player)) {
try {
invokeClickCallback(player);
} catch (Throwable t) {
Log.warning("The plugin " + getCreatorPlugin().getName() + " generated an exception"
+ " when the player " + player.getName() + " clicked a hologram.", t);
}
try {
invokeExternalClickCallback(player);
} catch (Throwable t) {
Log.warning("The plugin " + getCreatorPlugin().getName() + " generated an exception"
+ " when the player " + player.getName() + " clicked a hologram.", t);
}
}
public abstract boolean hasClickCallback();
protected abstract void invokeClickCallback(Player player);
private boolean isInClickRange(Player player) {
Location playerLocation = player.getLocation();
PositionCoordinates positionCoordinates = this.getCoordinates();
double xDiff = playerLocation.getX() - positionCoordinates.getX();
double yDiff = playerLocation.getY() + 1.3 - positionCoordinates.getY(); // Use shoulder height
double zDiff = playerLocation.getZ() - positionCoordinates.getZ();
double distanceSquared = (xDiff * xDiff) + (yDiff * yDiff) + (zDiff * zDiff);
return distanceSquared < 5 * 5;
}
protected abstract void invokeExternalClickCallback(Player player);
}

View File

@ -6,6 +6,7 @@
package me.filoghost.holographicdisplays.core.base;
import me.filoghost.fcommons.Preconditions;
import me.filoghost.holographicdisplays.core.CorePreconditions;
import me.filoghost.holographicdisplays.core.api.current.DefaultVisibilitySettings;
import me.filoghost.holographicdisplays.core.tracking.LineTrackerManager;
import org.bukkit.Chunk;
@ -70,6 +71,7 @@ public abstract class BaseHologram extends BaseHologramComponent {
}
public void setPosition(@NotNull ImmutablePosition position) {
CorePreconditions.checkMainThread();
Preconditions.notNull(position, "position");
checkNotDeleted();

View File

@ -8,9 +8,6 @@ package me.filoghost.holographicdisplays.core.base;
import me.filoghost.fcommons.Preconditions;
import me.filoghost.holographicdisplays.common.PositionCoordinates;
import me.filoghost.holographicdisplays.core.api.current.DefaultVisibilitySettings;
import me.filoghost.holographicdisplays.core.tracking.LineTracker;
import me.filoghost.holographicdisplays.core.tracking.LineTrackerManager;
import org.bukkit.GameMode;
import org.bukkit.World;
import org.bukkit.entity.Player;
import org.bukkit.plugin.Plugin;
@ -20,24 +17,30 @@ import org.jetbrains.annotations.Nullable;
public abstract class BaseHologramLine extends BaseHologramComponent implements EditableHologramLine {
private final BaseHologram hologram;
private final LineTracker<?> tracker;
private PositionCoordinates coordinates;
/**
* Flag to indicate that the line has changed in some way and update packets might be necessary.
*/
private boolean changed;
protected BaseHologramLine(BaseHologram hologram) {
Preconditions.notNull(hologram, "hologram");
this.hologram = hologram;
this.tracker = createTracker(hologram.getTrackerManager());
setChanged(); // Force the initial refresh
}
protected abstract LineTracker<?> createTracker(LineTrackerManager trackerManager);
public boolean hasChanged() {
return changed;
}
public final void setChanged() {
tracker.setLineChanged();
changed = true;
}
protected final boolean isViewer(Player player) {
return tracker.isViewer(player);
public void clearChanged() {
changed = false;
}
@Override
@ -77,12 +80,4 @@ public abstract class BaseHologramLine extends BaseHologramComponent implements
return hologram.getVisibilitySettings();
}
protected boolean canInteract(Player player) {
return !isDeleted()
&& player.isOnline()
&& player.getGameMode() != GameMode.SPECTATOR
&& isViewer(player)
&& isVisibleTo(player);
}
}

View File

@ -6,6 +6,9 @@
package me.filoghost.holographicdisplays.core.base;
import me.filoghost.holographicdisplays.api.Position;
import me.filoghost.holographicdisplays.core.CoreGlobalConfig;
import me.filoghost.holographicdisplays.core.CorePreconditions;
import me.filoghost.holographicdisplays.core.tracking.LineTrackerManager;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
@ -15,46 +18,54 @@ import java.util.List;
public class BaseHologramLines<T extends EditableHologramLine> implements Iterable<T> {
public static double spaceBetweenLines;
private final BaseHologram hologram;
private final LineTrackerManager lineTrackerManager;
private final List<T> lines;
private final List<T> unmodifiableLinesView;
public BaseHologramLines(BaseHologram hologram) {
public BaseHologramLines(BaseHologram hologram, LineTrackerManager lineTrackerManager) {
this.hologram = hologram;
this.lineTrackerManager = lineTrackerManager;
this.lines = new ArrayList<>();
this.unmodifiableLinesView = Collections.unmodifiableList(lines);
}
@Override
public Iterator<T> iterator() {
CorePreconditions.checkMainThread();
return unmodifiableLinesView.iterator();
}
public int size() {
CorePreconditions.checkMainThread();
return lines.size();
}
public @NotNull T get(int index) {
CorePreconditions.checkMainThread();
return lines.get(index);
}
public void add(T line) {
CorePreconditions.checkMainThread();
checkNotDeleted();
lines.add(line);
lineTrackerManager.startTracking(line);
updatePositions();
}
public void insert(int beforeIndex, T line) {
CorePreconditions.checkMainThread();
checkNotDeleted();
lines.add(beforeIndex, line);
lineTrackerManager.startTracking(line);
updatePositions();
}
public void remove(int index) {
CorePreconditions.checkMainThread();
checkNotDeleted();
lines.remove(index).setDeleted();
@ -62,6 +73,7 @@ public class BaseHologramLines<T extends EditableHologramLine> implements Iterab
}
public boolean remove(T line) {
CorePreconditions.checkMainThread();
checkNotDeleted();
boolean removed = lines.remove(line);
@ -73,6 +85,7 @@ public class BaseHologramLines<T extends EditableHologramLine> implements Iterab
}
public void clear() {
CorePreconditions.checkMainThread();
checkNotDeleted();
Iterator<T> iterator = lines.iterator();
@ -98,7 +111,7 @@ public class BaseHologramLines<T extends EditableHologramLine> implements Iterab
currentLineY -= line.getHeight();
if (i > 0) {
currentLineY -= spaceBetweenLines;
currentLineY -= CoreGlobalConfig.spaceBetweenLines;
}
line.setCoordinates(hologramPosition.getX(), currentLineY, hologramPosition.getZ());
@ -106,6 +119,8 @@ public class BaseHologramLines<T extends EditableHologramLine> implements Iterab
}
public double getHeight() {
CorePreconditions.checkMainThread();
if (lines.isEmpty()) {
return 0;
}
@ -116,7 +131,7 @@ public class BaseHologramLines<T extends EditableHologramLine> implements Iterab
height += line.getHeight();
}
height += spaceBetweenLines * (lines.size() - 1);
height += CoreGlobalConfig.spaceBetweenLines * (lines.size() - 1);
return height;
}

View File

@ -5,7 +5,7 @@
*/
package me.filoghost.holographicdisplays.core.base;
import me.filoghost.fcommons.Preconditions;
import me.filoghost.holographicdisplays.core.CorePreconditions;
import org.bukkit.Chunk;
import org.bukkit.World;
@ -21,7 +21,7 @@ public abstract class BaseHologramManager<H extends BaseHologram> {
private final List<H> unmodifiableHologramsView = Collections.unmodifiableList(holograms);
protected void addHologram(H hologram) {
Preconditions.checkMainThread("async hologram create");
CorePreconditions.checkMainThread();
holograms.add(hologram);
}
@ -31,14 +31,14 @@ public abstract class BaseHologramManager<H extends BaseHologram> {
}
public void deleteHologram(H hologram) {
Preconditions.checkMainThread("async hologram delete");
CorePreconditions.checkMainThread();
hologram.setDeleted();
holograms.remove(hologram);
}
public void deleteHologramsIf(Predicate<H> condition) {
Preconditions.checkMainThread("async hologram delete");
CorePreconditions.checkMainThread();
Iterator<H> iterator = holograms.iterator();
while (iterator.hasNext()) {
@ -51,7 +51,7 @@ public abstract class BaseHologramManager<H extends BaseHologram> {
}
public void deleteHolograms() {
Preconditions.checkMainThread("async hologram delete");
CorePreconditions.checkMainThread();
Iterator<H> iterator = holograms.iterator();
while (iterator.hasNext()) {

View File

@ -7,9 +7,8 @@ package me.filoghost.holographicdisplays.core.base;
import me.filoghost.fcommons.Preconditions;
import me.filoghost.fcommons.logging.Log;
import me.filoghost.holographicdisplays.core.CorePreconditions;
import me.filoghost.holographicdisplays.nms.common.entity.ItemNMSPacketEntity;
import me.filoghost.holographicdisplays.core.tracking.ItemLineTracker;
import me.filoghost.holographicdisplays.core.tracking.LineTrackerManager;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.Nullable;
@ -23,31 +22,25 @@ public abstract class BaseItemHologramLine extends BaseClickableHologramLine {
setItemStack(itemStack);
}
@Override
public ItemLineTracker createTracker(LineTrackerManager trackerManager) {
return trackerManager.startTracking(this);
}
public void onPickup(Player player) {
if (hasPickupCallback() && canInteract(player)) {
try {
invokePickupCallback(player);
} catch (Throwable t) {
Log.warning("The plugin " + getCreatorPlugin().getName() + " generated an exception"
+ " when the player " + player.getName() + " picked up an item from a hologram.", t);
}
try {
invokeExternalPickupCallback(player);
} catch (Throwable t) {
Log.warning("The plugin " + getCreatorPlugin().getName() + " generated an exception"
+ " when the player " + player.getName() + " picked up an item from a hologram.", t);
}
}
public abstract boolean hasPickupCallback();
protected abstract void invokePickupCallback(Player player);
protected abstract void invokeExternalPickupCallback(Player player);
public @Nullable ItemStack getItemStack() {
return clone(itemStack);
}
public void setItemStack(@Nullable ItemStack itemStack) {
CorePreconditions.checkMainThread();
checkNotDeleted();
if (itemStack != null) {

View File

@ -5,9 +5,8 @@
*/
package me.filoghost.holographicdisplays.core.base;
import me.filoghost.holographicdisplays.core.CorePreconditions;
import me.filoghost.holographicdisplays.nms.common.entity.TextNMSPacketEntity;
import me.filoghost.holographicdisplays.core.tracking.LineTrackerManager;
import me.filoghost.holographicdisplays.core.tracking.TextLineTracker;
import org.jetbrains.annotations.Nullable;
public abstract class BaseTextHologramLine extends BaseClickableHologramLine {
@ -21,16 +20,12 @@ public abstract class BaseTextHologramLine extends BaseClickableHologramLine {
public abstract boolean isAllowPlaceholders();
@Override
protected TextLineTracker createTracker(LineTrackerManager trackerManager) {
return trackerManager.startTracking(this);
}
public @Nullable String getText() {
return text;
}
public void setText(@Nullable String text) {
CorePreconditions.checkMainThread();
checkNotDeleted();
this.text = text;

View File

@ -5,9 +5,9 @@
*/
package me.filoghost.holographicdisplays.core.listener;
import me.filoghost.holographicdisplays.core.tracking.ClickableLineTracker;
import me.filoghost.holographicdisplays.nms.common.EntityID;
import me.filoghost.holographicdisplays.nms.common.PacketListener;
import me.filoghost.holographicdisplays.core.base.BaseClickableHologramLine;
import org.bukkit.entity.Player;
import java.util.Collections;
@ -17,22 +17,22 @@ import java.util.concurrent.ConcurrentMap;
public class LineClickListener implements PacketListener {
private final ConcurrentMap<Integer, BaseClickableHologramLine> linesByEntityID;
private final ConcurrentMap<Integer, ClickableLineTracker<?>> lineTrackerByEntityID;
// It is necessary to queue async click events to process them from the main thread.
// Use a set to avoid duplicate click events to the same line.
private final Set<QueuedClickEvent> queuedClickEvents;
public LineClickListener() {
linesByEntityID = new ConcurrentHashMap<>();
lineTrackerByEntityID = new ConcurrentHashMap<>();
queuedClickEvents = Collections.newSetFromMap(new ConcurrentHashMap<>());
}
@Override
public boolean onAsyncEntityInteract(Player player, int entityID) {
BaseClickableHologramLine line = linesByEntityID.get(entityID);
if (line != null) {
queuedClickEvents.add(new QueuedClickEvent(player, line));
ClickableLineTracker<?> lineTracker = lineTrackerByEntityID.get(entityID);
if (lineTracker != null) {
queuedClickEvents.add(new QueuedClickEvent(player, lineTracker));
return true;
} else {
return false;
@ -41,19 +41,19 @@ public class LineClickListener implements PacketListener {
// This method is called from the main thread
public void processQueuedClickEvents() {
for (QueuedClickEvent queuedClickEvent : queuedClickEvents) {
queuedClickEvent.line.onClick(queuedClickEvent.player);
for (QueuedClickEvent event : queuedClickEvents) {
event.lineTracker.onClientClick(event.player);
}
queuedClickEvents.clear();
}
public void registerLine(EntityID clickableEntityID, BaseClickableHologramLine line) {
linesByEntityID.put(clickableEntityID.getNumericID(), line);
public void addLineTracker(EntityID clickableEntityID, ClickableLineTracker<?> lineTracker) {
lineTrackerByEntityID.put(clickableEntityID.getNumericID(), lineTracker);
}
public void unregisterLine(EntityID clickableEntityID) {
public void removeLineTracker(EntityID clickableEntityID) {
if (clickableEntityID.hasInitializedNumericID()) {
linesByEntityID.remove(clickableEntityID.getNumericID());
lineTrackerByEntityID.remove(clickableEntityID.getNumericID());
}
}
@ -61,11 +61,11 @@ public class LineClickListener implements PacketListener {
private static class QueuedClickEvent {
private final Player player;
private final BaseClickableHologramLine line;
private final ClickableLineTracker<?> lineTracker;
QueuedClickEvent(Player player, BaseClickableHologramLine line) {
QueuedClickEvent(Player player, ClickableLineTracker<?> lineTracker) {
this.player = player;
this.line = line;
this.lineTracker = lineTracker;
}
@Override
@ -78,13 +78,13 @@ public class LineClickListener implements PacketListener {
}
QueuedClickEvent other = (QueuedClickEvent) obj;
return this.player.equals(other.player) && this.line.equals(other.line);
return this.player.equals(other.player) && this.lineTracker.equals(other.lineTracker);
}
@Override
public int hashCode() {
int result = player.hashCode();
result = 31 * result + line.hashCode();
result = 31 * result + lineTracker.hashCode();
return result;
}

View File

@ -123,6 +123,22 @@ class Parser {
}
}
public static String addEscapes(String string) {
StringBuilder output = new StringBuilder(string.length() + 16); // String gets longer with escapes
for (int i = 0; i < string.length(); i++) {
char currentChar = string.charAt(i);
if (isSpecialCharacter(currentChar)) {
output.append(ESCAPE_CHAR);
}
output.append(currentChar);
}
return output.toString();
}
private static boolean isSpecialCharacter(char currentChar) {
return currentChar == ESCAPE_CHAR
|| currentChar == PLACEHOLDER_START_CHAR

View File

@ -27,6 +27,10 @@ public final class StringWithPlaceholders {
return Parser.parse(string, true);
}
public static String addEscapes(@NotNull String string) {
return Parser.addEscapes(string);
}
StringWithPlaceholders(@NotNull String string, @Nullable List<Part> parts) {
this.string = string;
this.parts = parts;
@ -71,7 +75,7 @@ public final class StringWithPlaceholders {
return replace(player, replaceFunction, StringReplaceFunction.NO_REPLACEMENTS);
}
public @NotNull String replaceStrings(StringReplaceFunction replaceFunction) {
public @NotNull String replaceOutsidePlaceholders(StringReplaceFunction replaceFunction) {
return replace(null, PlaceholderReplaceFunction.NO_REPLACEMENTS, replaceFunction);
}

View File

@ -6,6 +6,8 @@
package me.filoghost.holographicdisplays.core.tick;
import me.filoghost.fcommons.logging.Log;
import me.filoghost.holographicdisplays.core.CoreGlobalConfig;
import me.filoghost.holographicdisplays.core.NMSVersion;
import me.filoghost.holographicdisplays.core.listener.LineClickListener;
import me.filoghost.holographicdisplays.core.placeholder.tracking.ActivePlaceholderTracker;
import me.filoghost.holographicdisplays.core.tracking.LineTrackerManager;
@ -56,7 +58,24 @@ public class TickingTask implements Runnable {
}
public void onPlayerRespawn(Player player) {
lineTrackerManager.removeViewer(player);
switch (NMSVersion.getCurrent()) {
case v1_8_R1:
case v1_8_R2:
case v1_8_R3:
case v1_9_R1:
case v1_9_R2:
case v1_10_R1:
case v1_11_R1:
case v1_12_R1:
case v1_13_R1:
case v1_13_R2:
case v1_14_R1:
// For older versions, force spawn packets to be resent after the player respawns
lineTrackerManager.removeViewer(player);
break;
default:
break;
}
}
@Override
@ -75,6 +94,9 @@ public class TickingTask implements Runnable {
// Holograms need to disappear before chunks (code taken from Bukkit)
int maxViewRange = (Bukkit.getViewDistance() - 1) * 16;
if (maxViewRange > CoreGlobalConfig.maxViewRange) {
maxViewRange = CoreGlobalConfig.maxViewRange;
}
try {
lineTrackerManager.update(onlinePlayers, movedPlayers, maxViewRange);

View File

@ -10,6 +10,8 @@ import me.filoghost.holographicdisplays.core.base.BaseClickableHologramLine;
import me.filoghost.holographicdisplays.core.listener.LineClickListener;
import me.filoghost.holographicdisplays.nms.common.NMSManager;
import me.filoghost.holographicdisplays.nms.common.entity.ClickableNMSPacketEntity;
import org.bukkit.Location;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.MustBeInvokedByOverriders;
public abstract class ClickableLineTracker<T extends Viewer> extends LineTracker<T> {
@ -27,14 +29,32 @@ public abstract class ClickableLineTracker<T extends Viewer> extends LineTracker
this.lineClickListener = lineClickListener;
}
public void onClientClick(Player player) {
if (getLine().hasClickCallback() && canInteract(player) && isInClickRange(player)) {
getLine().onClick(player);
}
}
private boolean isInClickRange(Player player) {
Location playerLocation = player.getLocation();
PositionCoordinates positionCoordinates = getLine().getCoordinates();
double xDiff = playerLocation.getX() - positionCoordinates.getX();
double yDiff = playerLocation.getY() + 1.3 - positionCoordinates.getY(); // Use shoulder height
double zDiff = playerLocation.getZ() - positionCoordinates.getZ();
double distanceSquared = (xDiff * xDiff) + (yDiff * yDiff) + (zDiff * zDiff);
return distanceSquared < 5 * 5;
}
@Override
protected abstract BaseClickableHologramLine getLine();
public abstract BaseClickableHologramLine getLine();
@MustBeInvokedByOverriders
@Override
public void onRemoval() {
super.onRemoval();
lineClickListener.unregisterLine(clickableEntity.getID());
lineClickListener.removeLineTracker(clickableEntity.getID());
}
@MustBeInvokedByOverriders
@ -47,9 +67,9 @@ public abstract class ClickableLineTracker<T extends Viewer> extends LineTracker
this.spawnClickableEntity = spawnClickableEntity;
this.spawnClickableEntityChanged = true;
if (spawnClickableEntity) {
lineClickListener.registerLine(clickableEntity.getID(), getLine());
lineClickListener.addLineTracker(clickableEntity.getID(), this);
} else {
lineClickListener.unregisterLine(clickableEntity.getID());
lineClickListener.removeLineTracker(clickableEntity.getID());
}
}
}
@ -65,7 +85,11 @@ public abstract class ClickableLineTracker<T extends Viewer> extends LineTracker
@Override
protected void sendSpawnPackets(Viewers<T> viewers) {
if (spawnClickableEntity) {
viewers.sendPackets(clickableEntity.newSpawnPackets(getClickableEntityPosition()));
// Copy for async use
PositionCoordinates clickableEntityPosition = getClickableEntityPosition();
PacketSenderExecutor.execute(() -> {
viewers.sendPackets(clickableEntity.newSpawnPackets(clickableEntityPosition));
});
}
}
@ -73,7 +97,9 @@ public abstract class ClickableLineTracker<T extends Viewer> extends LineTracker
@Override
protected void sendDestroyPackets(Viewers<T> viewers) {
if (spawnClickableEntity) {
viewers.sendPackets(clickableEntity.newDestroyPackets());
PacketSenderExecutor.execute(() -> {
viewers.sendPackets(clickableEntity.newDestroyPackets());
});
}
}
@ -84,9 +110,15 @@ public abstract class ClickableLineTracker<T extends Viewer> extends LineTracker
if (spawnClickableEntityChanged) {
if (spawnClickableEntity) {
viewers.sendPackets(clickableEntity.newSpawnPackets(getClickableEntityPosition()));
// Copy for async use
PositionCoordinates clickableEntityPosition = getClickableEntityPosition();
PacketSenderExecutor.execute(() -> {
viewers.sendPackets(clickableEntity.newSpawnPackets(clickableEntityPosition));
});
} else {
viewers.sendPackets(clickableEntity.newDestroyPackets());
PacketSenderExecutor.execute(() -> {
viewers.sendPackets(clickableEntity.newDestroyPackets());
});
}
}
}
@ -95,7 +127,11 @@ public abstract class ClickableLineTracker<T extends Viewer> extends LineTracker
@Override
protected void sendPositionChangePackets(Viewers<T> viewers) {
if (spawnClickableEntity) {
viewers.sendPackets(clickableEntity.newTeleportPackets(getClickableEntityPosition()));
// Copy for async use
PositionCoordinates clickableEntityPosition = getClickableEntityPosition();
PacketSenderExecutor.execute(() -> {
viewers.sendPackets(clickableEntity.newTeleportPackets(clickableEntityPosition));
});
}
}

View File

@ -5,15 +5,16 @@
*/
package me.filoghost.holographicdisplays.core.tracking;
import java.util.ArrayList;
import java.util.Collection;
import java.util.function.Consumer;
public class DelegateViewers<T extends Viewer> implements Viewers<T> {
public class ImmutableViewers<T extends Viewer> implements Viewers<T> {
private final Collection<T> viewers;
public DelegateViewers(Collection<T> viewers) {
this.viewers = viewers;
public ImmutableViewers(Collection<T> viewers) {
this.viewers = new ArrayList<>(viewers);
}
@Override

View File

@ -5,11 +5,14 @@
*/
package me.filoghost.holographicdisplays.core.tracking;
import me.filoghost.holographicdisplays.common.PositionCoordinates;
import me.filoghost.holographicdisplays.core.base.BaseItemHologramLine;
import me.filoghost.holographicdisplays.core.listener.LineClickListener;
import me.filoghost.holographicdisplays.core.tick.CachedPlayer;
import me.filoghost.holographicdisplays.nms.common.NMSManager;
import me.filoghost.holographicdisplays.nms.common.entity.ItemNMSPacketEntity;
import org.bukkit.Location;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.MustBeInvokedByOverriders;
@ -48,13 +51,20 @@ public class ItemLineTracker extends ClickableLineTracker<Viewer> {
if (spawnItemEntity && hasViewers() && line.hasPickupCallback()) {
for (Viewer viewer : getViewers()) {
if (viewer.getLocation() != null && CollisionHelper.isInPickupRange(viewer.getLocation(), positionCoordinates)) {
line.onPickup(viewer.getBukkitPlayer());
}
invokePickupIfNecessary(viewer);
}
}
}
private void invokePickupIfNecessary(Viewer viewer) {
Location location = viewer.getLocation();
Player player = viewer.getBukkitPlayer();
if (location != null && CollisionHelper.isInPickupRange(location, positionCoordinates) && canInteract(player)) {
line.onPickup(player);
}
}
@Override
protected boolean updatePlaceholders() {
return false;
@ -97,7 +107,12 @@ public class ItemLineTracker extends ClickableLineTracker<Viewer> {
super.sendSpawnPackets(viewers);
if (spawnItemEntity) {
viewers.sendPackets(itemEntity.newSpawnPackets(positionCoordinates, itemStack));
// Copy for async use
PositionCoordinates positionCoordinates = this.positionCoordinates;
ItemStack itemStack = this.itemStack;
PacketSenderExecutor.execute(() -> {
viewers.sendPackets(itemEntity.newSpawnPackets(positionCoordinates, itemStack));
});
}
}
@ -107,7 +122,9 @@ public class ItemLineTracker extends ClickableLineTracker<Viewer> {
super.sendDestroyPackets(viewers);
if (spawnItemEntity) {
viewers.sendPackets(itemEntity.newDestroyPackets());
PacketSenderExecutor.execute(() -> {
viewers.sendPackets(itemEntity.newDestroyPackets());
});
}
}
@ -118,13 +135,24 @@ public class ItemLineTracker extends ClickableLineTracker<Viewer> {
if (spawnItemEntityChanged) {
if (spawnItemEntity) {
viewers.sendPackets(itemEntity.newSpawnPackets(positionCoordinates, itemStack));
// Copy for async use
PositionCoordinates positionCoordinates = this.positionCoordinates;
ItemStack itemStack = this.itemStack;
PacketSenderExecutor.execute(() -> {
viewers.sendPackets(itemEntity.newSpawnPackets(positionCoordinates, itemStack));
});
} else {
viewers.sendPackets(itemEntity.newDestroyPackets());
PacketSenderExecutor.execute(() -> {
viewers.sendPackets(itemEntity.newDestroyPackets());
});
}
} else if (itemStackChanged) {
// Only send item changes if full spawn/destroy packets were not sent
viewers.sendPackets(itemEntity.newChangePackets(itemStack));
// Copy for async use
ItemStack itemStack = this.itemStack;
PacketSenderExecutor.execute(() -> {
viewers.sendPackets(itemEntity.newChangePackets(itemStack));
});
}
}
@ -134,7 +162,11 @@ public class ItemLineTracker extends ClickableLineTracker<Viewer> {
super.sendPositionChangePackets(viewers);
if (spawnItemEntity) {
viewers.sendPackets(itemEntity.newTeleportPackets(positionCoordinates));
// Copy for async use
PositionCoordinates positionCoordinates = this.positionCoordinates;
PacketSenderExecutor.execute(() -> {
viewers.sendPackets(itemEntity.newTeleportPackets(positionCoordinates));
});
}
}

View File

@ -8,35 +8,30 @@ package me.filoghost.holographicdisplays.core.tracking;
import me.filoghost.holographicdisplays.common.PositionCoordinates;
import me.filoghost.holographicdisplays.core.base.BaseHologramLine;
import me.filoghost.holographicdisplays.core.tick.CachedPlayer;
import org.bukkit.GameMode;
import org.bukkit.Location;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.MustBeInvokedByOverriders;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
public abstract class LineTracker<T extends Viewer> {
private final Map<Player, T> viewers;
private final Viewers<T> iterableViewers;
private final ConcurrentMap<Player, T> viewers;
private String positionWorldName;
protected PositionCoordinates positionCoordinates;
private boolean positionChanged;
/**
* Flag to indicate that the line has changed in some way and there could be the need to send update packets.
*/
private boolean lineChanged;
private boolean inLoadedChunk;
private int lastVisibilitySettingsVersion;
protected LineTracker() {
this.viewers = new HashMap<>();
this.iterableViewers = new DelegateViewers<>(viewers.values());
this.viewers = new ConcurrentHashMap<>();
}
protected abstract BaseHologramLine getLine();
@ -50,17 +45,13 @@ public abstract class LineTracker<T extends Viewer> {
resetViewersAndSendDestroyPackets();
}
public final void setLineChanged() {
lineChanged = true;
}
@MustBeInvokedByOverriders
protected void update(List<CachedPlayer> onlinePlayers, List<CachedPlayer> movedPlayers, int maxViewRange) {
boolean sendChangesPackets = false;
// First, detect the changes if the flag is on and set it off
if (lineChanged) {
lineChanged = false;
if (getLine().hasChanged()) {
getLine().clearChanged();
detectChanges();
sendChangesPackets = true;
}
@ -74,7 +65,7 @@ public abstract class LineTracker<T extends Viewer> {
// Then, send the changes (if any) to already tracked players
if (sendChangesPackets && hasViewers()) {
sendChangesPackets(iterableViewers);
sendChangesPackets(new ImmutableViewers<>(viewers.values()));
}
// Finally, add/remove viewers sending them the full spawn/destroy packets
@ -189,7 +180,7 @@ public abstract class LineTracker<T extends Viewer> {
return viewers.values();
}
public final boolean isViewer(Player player) {
protected final boolean isViewer(Player player) {
return viewers.containsKey(player);
}
@ -197,6 +188,14 @@ public abstract class LineTracker<T extends Viewer> {
viewers.remove(player);
}
protected boolean canInteract(Player player) {
return !getLine().isDeleted()
&& player.isOnline()
&& player.getGameMode() != GameMode.SPECTATOR
&& isViewer(player)
&& getLine().isVisibleTo(player);
}
@MustBeInvokedByOverriders
protected void detectChanges() {
PositionCoordinates positionCoordinates = getLine().getCoordinates();
@ -222,7 +221,7 @@ public abstract class LineTracker<T extends Viewer> {
return;
}
sendDestroyPackets(iterableViewers);
sendDestroyPackets(new ImmutableViewers<>(viewers.values()));
viewers.clear();
}

View File

@ -7,6 +7,7 @@ package me.filoghost.holographicdisplays.core.tracking;
import me.filoghost.holographicdisplays.core.base.BaseItemHologramLine;
import me.filoghost.holographicdisplays.core.base.BaseTextHologramLine;
import me.filoghost.holographicdisplays.core.base.EditableHologramLine;
import me.filoghost.holographicdisplays.core.listener.LineClickListener;
import me.filoghost.holographicdisplays.core.placeholder.tracking.ActivePlaceholderTracker;
import me.filoghost.holographicdisplays.core.tick.CachedPlayer;
@ -35,16 +36,14 @@ public class LineTrackerManager {
this.lineTrackers = new LinkedList<>();
}
public TextLineTracker startTracking(BaseTextHologramLine line) {
TextLineTracker tracker = new TextLineTracker(line, nmsManager, lineClickListener, placeholderTracker);
lineTrackers.add(tracker);
return tracker;
}
public ItemLineTracker startTracking(BaseItemHologramLine line) {
ItemLineTracker tracker = new ItemLineTracker(line, nmsManager, lineClickListener);
lineTrackers.add(tracker);
return tracker;
public <T extends EditableHologramLine> void startTracking(T line) {
if (line instanceof BaseTextHologramLine) {
lineTrackers.add(new TextLineTracker((BaseTextHologramLine) line, nmsManager, lineClickListener, placeholderTracker));
} else if (line instanceof BaseItemHologramLine) {
lineTrackers.add(new ItemLineTracker((BaseItemHologramLine) line, nmsManager, lineClickListener));
} else {
throw new UnsupportedOperationException("unsupported line class: " + line.getClass().getName());
}
}
public void update(List<CachedPlayer> onlinePlayers, List<CachedPlayer> movedPlayers, int maxViewRange) {

View File

@ -15,7 +15,7 @@ public class MutableViewers<T extends Viewer> implements Viewers<T> {
private T viewer;
private List<T> additionalViewers;
public void add(T viewer) {
public synchronized void add(T viewer) {
if (this.viewer == null) {
this.viewer = viewer;
} else {
@ -27,7 +27,7 @@ public class MutableViewers<T extends Viewer> implements Viewers<T> {
}
@Override
public void forEach(Consumer<? super T> action) {
public synchronized void forEach(Consumer<? super T> action) {
if (viewer != null) {
action.accept(viewer);
if (additionalViewers != null) {

View File

@ -0,0 +1,53 @@
/*
* 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.
* Important note: this executor can only have one thread, as packets must be sent in a precise order.
*/
public class PacketSenderExecutor {
private static volatile BlockingQueue<Runnable> tasks;
private static final Runnable STOP_MARKER_TASK = () -> {};
public static void execute(Runnable task) {
tasks.add(task);
}
public static void start() {
tasks = new LinkedBlockingQueue<>();
Thread 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 async packets");
thread.start();
}
public static void stopGracefully() {
if (tasks != null) {
tasks.add(STOP_MARKER_TASK);
}
}
}

View File

@ -5,6 +5,7 @@
*/
package me.filoghost.holographicdisplays.core.tracking;
import me.filoghost.holographicdisplays.common.PositionCoordinates;
import me.filoghost.holographicdisplays.core.base.BaseTextHologramLine;
import me.filoghost.holographicdisplays.core.listener.LineClickListener;
import me.filoghost.holographicdisplays.core.placeholder.tracking.ActivePlaceholderTracker;
@ -84,15 +85,22 @@ public class TextLineTracker extends ClickableLineTracker<TextLineViewer> {
protected void sendSpawnPackets(Viewers<TextLineViewer> viewers) {
super.sendSpawnPackets(viewers);
IndividualTextPacketGroup spawnPackets = textEntity.newSpawnPackets(positionCoordinates);
viewers.forEach(viewer -> viewer.sendTextPackets(spawnPackets));
// Copy for async use
PositionCoordinates positionCoordinates = this.positionCoordinates;
viewers.forEach(TextLineViewer::updateNextTextToSend);
PacketSenderExecutor.execute(() -> {
IndividualTextPacketGroup spawnPackets = textEntity.newSpawnPackets(positionCoordinates);
viewers.forEach(viewer -> viewer.sendTextPackets(spawnPackets));
});
}
@MustBeInvokedByOverriders
@Override
protected void sendDestroyPackets(Viewers<TextLineViewer> viewers) {
super.sendDestroyPackets(viewers);
viewers.sendPackets(textEntity.newDestroyPackets());
PacketSenderExecutor.execute(() -> {
viewers.sendPackets(textEntity.newDestroyPackets());
});
}
@Override
@ -100,8 +108,11 @@ public class TextLineTracker extends ClickableLineTracker<TextLineViewer> {
super.sendChangesPackets(viewers);
if (displayTextChanged) {
IndividualTextPacketGroup changePackets = textEntity.newChangePackets();
viewers.forEach(viewer -> viewer.sendTextPacketsIfNecessary(changePackets));
viewers.forEach(TextLineViewer::updateNextTextToSend);
PacketSenderExecutor.execute(() -> {
IndividualTextPacketGroup changePackets = textEntity.newChangePackets();
viewers.forEach(viewer -> viewer.sendTextPacketsIfNecessary(changePackets));
});
}
}
@ -109,7 +120,11 @@ public class TextLineTracker extends ClickableLineTracker<TextLineViewer> {
@Override
protected void sendPositionChangePackets(Viewers<TextLineViewer> viewers) {
super.sendPositionChangePackets(viewers);
viewers.sendPackets(textEntity.newTeleportPackets(positionCoordinates));
// Copy for async use
PositionCoordinates positionCoordinates = this.positionCoordinates;
PacketSenderExecutor.execute(() -> {
viewers.sendPackets(textEntity.newTeleportPackets(positionCoordinates));
});
}
@Override

View File

@ -5,9 +5,8 @@
*/
package me.filoghost.holographicdisplays.core.tracking;
import me.filoghost.holographicdisplays.nms.common.IndividualTextPacketGroup;
import me.filoghost.holographicdisplays.core.tick.CachedPlayer;
import org.jetbrains.annotations.Nullable;
import me.filoghost.holographicdisplays.nms.common.IndividualTextPacketGroup;
import java.util.Objects;
@ -15,8 +14,10 @@ class TextLineViewer extends Viewer {
private final DisplayText displayText;
// Access to these variables must be synchronized, they are accessed from multiple threads
private String individualText;
private String lastSentText;
private String nextTextToSend;
TextLineViewer(CachedPlayer player, DisplayText displayText) {
super(player);
@ -24,39 +25,47 @@ class TextLineViewer extends Viewer {
}
public void sendTextPackets(IndividualTextPacketGroup packets) {
String text = getOrComputeText();
this.lastSentText = text;
String text;
synchronized (this) {
text = nextTextToSend;
this.lastSentText = text;
}
sendIndividualPackets(packets, text);
}
public void sendTextPacketsIfNecessary(IndividualTextPacketGroup packets) {
String text = getOrComputeText();
if (Objects.equals(lastSentText, text)) {
return; // Avoid sending unnecessary packets
String text;
synchronized (this) {
text = nextTextToSend;
if (Objects.equals(lastSentText, text)) {
return; // Avoid sending unnecessary packets
}
this.lastSentText = text;
}
this.lastSentText = text;
sendIndividualPackets(packets, text);
}
private @Nullable String getOrComputeText() {
public synchronized void updateNextTextToSend() {
if (displayText.containsIndividualPlaceholders()) {
if (individualText == null) {
individualText = displayText.computeIndividualText(this);
}
return individualText;
nextTextToSend = individualText;
} else {
individualText = null;
return displayText.getGlobalText();
nextTextToSend = displayText.getGlobalText();
}
}
public boolean updateIndividualText() {
String individualText = displayText.computeIndividualText(this);
if (!Objects.equals(this.individualText, individualText)) {
this.individualText = individualText;
return true;
} else {
return false;
synchronized (this) {
if (!Objects.equals(this.individualText, individualText)) {
this.individualText = individualText;
return true;
} else {
return false;
}
}
}

View File

@ -37,6 +37,8 @@ class StringWithPlaceholdersTest {
Arguments.of(" {p} ", " # "),
Arguments.of("{p} {p} {p}", "# # #"),
Arguments.of("{{p}}", "{#}"), // Only the innermost placeholder should be replaced
Arguments.of("{{p}", "{#"),
Arguments.of("{p}}", "#}"),
Arguments.of("{p abc", "{p abc"), // Placeholder without closing tag
Arguments.of("abc p}", "abc p}") // Placeholder without opening tag
);
@ -46,7 +48,7 @@ class StringWithPlaceholdersTest {
@MethodSource("replaceLiteralPartsTestArguments")
void replaceLiteralParts(String input, String expectedOutput) {
StringWithPlaceholders s = StringWithPlaceholders.of(input);
assertThat(s.replaceStrings(literalPart -> "_")).isEqualTo(expectedOutput);
assertThat(s.replaceOutsidePlaceholders(literalPart -> "_")).isEqualTo(expectedOutput);
}
static Stream<Arguments> replaceLiteralPartsTestArguments() {
@ -112,7 +114,7 @@ class StringWithPlaceholdersTest {
@ParameterizedTest(name = "[{index}] {0} -> {0}")
@MethodSource("escapesTestArguments")
void preservingEscapes(String input) {
String output = StringWithPlaceholders.withEscapes(input).replaceStrings(StringReplaceFunction.NO_REPLACEMENTS);
String output = StringWithPlaceholders.withEscapes(input).replaceOutsidePlaceholders(StringReplaceFunction.NO_REPLACEMENTS);
assertThat(output).isEqualTo(input);
}
@ -133,4 +135,10 @@ class StringWithPlaceholdersTest {
);
}
@Test
void addEscapes() {
String escaped = StringWithPlaceholders.addEscapes("} { \\");
assertThat(escaped).isEqualTo("\\} \\{ \\\\");
}
}

View File

@ -6,7 +6,7 @@
<parent>
<groupId>me.filoghost.holographicdisplays</groupId>
<artifactId>holographicdisplays-example</artifactId>
<version>3.0.0</version>
<version>3.0.5-SNAPSHOT</version>
</parent>
<artifactId>holographicdisplays-example-deathholograms</artifactId>

View File

@ -6,7 +6,7 @@
<parent>
<groupId>me.filoghost.holographicdisplays</groupId>
<artifactId>holographicdisplays-parent</artifactId>
<version>3.0.0</version>
<version>3.0.5-SNAPSHOT</version>
</parent>
<artifactId>holographicdisplays-example</artifactId>

View File

@ -6,7 +6,7 @@
<parent>
<groupId>me.filoghost.holographicdisplays</groupId>
<artifactId>holographicdisplays-example</artifactId>
<version>3.0.0</version>
<version>3.0.5-SNAPSHOT</version>
</parent>
<artifactId>holographicdisplays-example-powerups</artifactId>

View File

@ -6,7 +6,7 @@
<parent>
<groupId>me.filoghost.holographicdisplays</groupId>
<artifactId>holographicdisplays-parent</artifactId>
<version>3.0.0</version>
<version>3.0.5-SNAPSHOT</version>
</parent>
<artifactId>holographicdisplays-legacy-api</artifactId>

View File

@ -6,7 +6,7 @@
<parent>
<groupId>me.filoghost.holographicdisplays</groupId>
<artifactId>holographicdisplays-legacy-api</artifactId>
<version>3.0.0</version>
<version>3.0.5-SNAPSHOT</version>
</parent>
<artifactId>holographicdisplays-legacy-api-v1</artifactId>

View File

@ -6,7 +6,7 @@
<parent>
<groupId>me.filoghost.holographicdisplays</groupId>
<artifactId>holographicdisplays-legacy-api</artifactId>
<version>3.0.0</version>
<version>3.0.5-SNAPSHOT</version>
</parent>
<artifactId>holographicdisplays-legacy-api-v2</artifactId>

View File

@ -6,7 +6,7 @@
<parent>
<groupId>me.filoghost.holographicdisplays</groupId>
<artifactId>holographicdisplays-nms</artifactId>
<version>3.0.0</version>
<version>3.0.5-SNAPSHOT</version>
</parent>
<artifactId>holographicdisplays-nms-common</artifactId>

View File

@ -1,42 +1,45 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>me.filoghost.holographicdisplays</groupId>
<artifactId>holographicdisplays-parent</artifactId>
<version>3.0.0</version>
</parent>
<artifactId>holographicdisplays-nms</artifactId>
<name>HolographicDisplays NMS</name>
<packaging>pom</packaging>
<modules>
<module>common</module>
<module>v1_8_r3</module>
<module>v1_9_r2</module>
<module>v1_10_r1</module>
<module>v1_11_r1</module>
<module>v1_12_r1</module>
<module>v1_13_r2</module>
<module>v1_14_r1</module>
<module>v1_15_r1</module>
<module>v1_16_r1</module>
<module>v1_16_r2</module>
<module>v1_16_r3</module>
<module>v1_17_r1</module>
<module>v1_18_r1</module>
<module>v1_18_r2</module>
<module>v1_19_r1</module>
</modules>
<dependencies>
<dependency>
<groupId>me.filoghost.fcommons</groupId>
<artifactId>fcommons</artifactId>
</dependency>
</dependencies>
</project>
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>me.filoghost.holographicdisplays</groupId>
<artifactId>holographicdisplays-parent</artifactId>
<version>3.0.5-SNAPSHOT</version>
</parent>
<artifactId>holographicdisplays-nms</artifactId>
<name>HolographicDisplays NMS</name>
<packaging>pom</packaging>
<modules>
<module>common</module>
<module>v1_8_r3</module>
<module>v1_9_r2</module>
<module>v1_10_r1</module>
<module>v1_11_r1</module>
<module>v1_12_r1</module>
<module>v1_13_r2</module>
<module>v1_14_r1</module>
<module>v1_15_r1</module>
<module>v1_16_r3</module>
<module>v1_17_r1</module>
<module>v1_18_r1</module>
<module>v1_18_r2</module>
<module>v1_19_r1</module>
<module>v1_19_r2</module>
<module>v1_19_r3</module>
<module>v1_20_r1</module>
<module>v1_20_r2</module>
<module>v1_20_r3</module>
</modules>
<dependencies>
<dependency>
<groupId>me.filoghost.fcommons</groupId>
<artifactId>fcommons</artifactId>
</dependency>
</dependencies>
</project>

View File

@ -6,7 +6,7 @@
<parent>
<groupId>me.filoghost.holographicdisplays</groupId>
<artifactId>holographicdisplays-nms</artifactId>
<version>3.0.0</version>
<version>3.0.5-SNAPSHOT</version>
</parent>
<artifactId>holographicdisplays-nms-v1_10_r1</artifactId>

View File

@ -62,7 +62,7 @@ class EntityLivingSpawnNMSPacket extends VersionNMSPacket {
// Entries are deserialized and saved into a field which is not used during the re-serialization, set as empty
packetByteBuffer.writeDataWatcherEntriesEnd();
Packet<?> rawPacket = writeData(new PacketPlayOutSpawnEntityLiving(), packetByteBuffer);
Packet<?> rawPacket = packetByteBuffer.writeDataTo(new PacketPlayOutSpawnEntityLiving());
return new Builder(rawPacket, PacketByteBuffer.get());
}

View File

@ -14,7 +14,7 @@ class EntityMetadataNMSPacket extends VersionNMSPacket {
private final Packet<?> rawPacket;
private EntityMetadataNMSPacket(PacketByteBuffer packetByteBuffer) {
this.rawPacket = writeData(new PacketPlayOutEntityMetadata(), packetByteBuffer);
this.rawPacket = packetByteBuffer.writeDataTo(new PacketPlayOutEntityMetadata());
}
@Override

View File

@ -19,7 +19,7 @@ class EntityMountNMSPacket extends VersionNMSPacket {
packetByteBuffer.writeVarInt(vehicleEntityID.getNumericID());
packetByteBuffer.writeVarIntArray(passengerEntityID.getNumericID());
this.rawPacket = writeData(new PacketPlayOutMount(), packetByteBuffer);
this.rawPacket = packetByteBuffer.writeDataTo(new PacketPlayOutMount());
}
@Override

View File

@ -42,7 +42,7 @@ class EntitySpawnNMSPacket extends VersionNMSPacket {
packetByteBuffer.writeShort(0);
packetByteBuffer.writeShort(0);
this.rawPacket = writeData(new PacketPlayOutSpawnEntity(), packetByteBuffer);
this.rawPacket = packetByteBuffer.writeDataTo(new PacketPlayOutSpawnEntity());
}
@Override

View File

@ -31,7 +31,7 @@ class EntityTeleportNMSPacket extends VersionNMSPacket {
// On ground
packetByteBuffer.writeBoolean(false);
this.rawPacket = writeData(new PacketPlayOutEntityTeleport(), packetByteBuffer);
this.rawPacket = packetByteBuffer.writeDataTo(new PacketPlayOutEntityTeleport());
}
@Override

View File

@ -6,25 +6,58 @@
package me.filoghost.holographicdisplays.nms.v1_10_R1;
import io.netty.buffer.Unpooled;
import net.minecraft.server.v1_10_R1.Packet;
import net.minecraft.server.v1_10_R1.PacketDataSerializer;
import java.io.IOException;
import java.util.UUID;
class PacketByteBuffer extends PacketDataSerializer {
class PacketByteBuffer {
private static final PacketByteBuffer INSTANCE = new PacketByteBuffer();
private static final ThreadLocal<PacketByteBuffer> LOCAL_INSTANCE = ThreadLocal.withInitial(PacketByteBuffer::new);
private final PacketDataSerializer serializer;
static PacketByteBuffer get() {
INSTANCE.clear();
return INSTANCE;
PacketByteBuffer instance = LOCAL_INSTANCE.get();
instance.clear();
return instance;
}
private PacketByteBuffer() {
super(Unpooled.buffer());
this.serializer = new PacketDataSerializer(Unpooled.buffer());
}
int readableBytes() {
return serializer.readableBytes();
}
void readBytes(byte[] bytes) {
serializer.readBytes(bytes);
}
void writeBoolean(boolean flag) {
serializer.writeBoolean(flag);
}
void writeByte(int i) {
serializer.writeByte(i);
}
void writeShort(int i) {
serializer.writeShort(i);
}
void writeInt(int i) {
serializer.writeInt(i);
}
void writeDouble(double d) {
serializer.writeDouble(d);
}
void writeVarInt(int i) {
super.d(i);
serializer.d(i);
}
void writeVarIntArray(int i1) {
@ -33,17 +66,31 @@ class PacketByteBuffer extends PacketDataSerializer {
}
void writeUUID(UUID uuid) {
super.a(uuid);
serializer.a(uuid);
}
<T> void writeDataWatcherEntry(DataWatcherKey<T> key, T value) {
writeByte(key.getIndex());
serializer.writeByte(key.getIndex());
writeVarInt(key.getSerializerTypeID());
key.getSerializer().a(this, value);
key.getSerializer().a(serializer, value);
}
void writeDataWatcherEntriesEnd() {
writeByte(0xFF);
serializer.writeByte(0xFF);
}
void clear() {
serializer.clear();
}
<T extends Packet<?>> T writeDataTo(T packet) {
try {
packet.a(serializer);
return packet;
} catch (IOException e) {
// Never thrown by the implementations
throw new RuntimeException(e);
}
}
}

View File

@ -8,6 +8,7 @@ package me.filoghost.holographicdisplays.nms.v1_10_R1;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.EventLoop;
import me.filoghost.fcommons.logging.ErrorCollector;
import me.filoghost.fcommons.logging.Log;
import me.filoghost.fcommons.reflection.ReflectField;
@ -115,8 +116,12 @@ public class VersionNMSManager implements NMSManager {
PlayerConnection playerConnection = ((CraftPlayer) player).getHandle().playerConnection;
NetworkManager networkManager = playerConnection.a();
Channel channel = networkManager.channel;
if (channel == null) {
return;
}
EventLoop eventLoop = channel.eventLoop();
channel.eventLoop().execute(() -> {
Runnable safeModifierTask = () -> {
if (!player.isOnline()) {
return;
}
@ -125,7 +130,13 @@ public class VersionNMSManager implements NMSManager {
} catch (Exception e) {
Log.warning(NMSErrors.EXCEPTION_MODIFYING_CHANNEL_PIPELINE, e);
}
});
};
if (eventLoop.inEventLoop()) {
safeModifierTask.run();
} else {
eventLoop.execute(safeModifierTask);
}
}
}

View File

@ -10,8 +10,6 @@ import net.minecraft.server.v1_10_R1.Packet;
import org.bukkit.craftbukkit.v1_10_R1.entity.CraftPlayer;
import org.bukkit.entity.Player;
import java.io.IOException;
abstract class VersionNMSPacket implements PacketGroup {
@Override
@ -21,14 +19,4 @@ abstract class VersionNMSPacket implements PacketGroup {
abstract Packet<?> getRawPacket();
protected static <T extends Packet<?>> T writeData(T packet, PacketByteBuffer packetByteBuffer) {
try {
packet.a(packetByteBuffer);
return packet;
} catch (IOException e) {
// Never thrown by the implementations
throw new RuntimeException(e);
}
}
}

View File

@ -6,7 +6,7 @@
<parent>
<groupId>me.filoghost.holographicdisplays</groupId>
<artifactId>holographicdisplays-nms</artifactId>
<version>3.0.0</version>
<version>3.0.5-SNAPSHOT</version>
</parent>
<artifactId>holographicdisplays-nms-v1_11_r1</artifactId>

View File

@ -62,7 +62,7 @@ class EntityLivingSpawnNMSPacket extends VersionNMSPacket {
// Entries are deserialized and saved into a field which is not used during the re-serialization, set as empty
packetByteBuffer.writeDataWatcherEntriesEnd();
Packet<?> rawPacket = writeData(new PacketPlayOutSpawnEntityLiving(), packetByteBuffer);
Packet<?> rawPacket = packetByteBuffer.writeDataTo(new PacketPlayOutSpawnEntityLiving());
return new Builder(rawPacket, PacketByteBuffer.get());
}

View File

@ -14,7 +14,7 @@ class EntityMetadataNMSPacket extends VersionNMSPacket {
private final Packet<?> rawPacket;
private EntityMetadataNMSPacket(PacketByteBuffer packetByteBuffer) {
this.rawPacket = writeData(new PacketPlayOutEntityMetadata(), packetByteBuffer);
this.rawPacket = packetByteBuffer.writeDataTo(new PacketPlayOutEntityMetadata());
}
@Override

View File

@ -19,7 +19,7 @@ class EntityMountNMSPacket extends VersionNMSPacket {
packetByteBuffer.writeVarInt(vehicleEntityID.getNumericID());
packetByteBuffer.writeVarIntArray(passengerEntityID.getNumericID());
this.rawPacket = writeData(new PacketPlayOutMount(), packetByteBuffer);
this.rawPacket = packetByteBuffer.writeDataTo(new PacketPlayOutMount());
}
@Override

View File

@ -42,7 +42,7 @@ class EntitySpawnNMSPacket extends VersionNMSPacket {
packetByteBuffer.writeShort(0);
packetByteBuffer.writeShort(0);
this.rawPacket = writeData(new PacketPlayOutSpawnEntity(), packetByteBuffer);
this.rawPacket = packetByteBuffer.writeDataTo(new PacketPlayOutSpawnEntity());
}
@Override

View File

@ -31,7 +31,7 @@ class EntityTeleportNMSPacket extends VersionNMSPacket {
// On ground
packetByteBuffer.writeBoolean(false);
this.rawPacket = writeData(new PacketPlayOutEntityTeleport(), packetByteBuffer);
this.rawPacket = packetByteBuffer.writeDataTo(new PacketPlayOutEntityTeleport());
}
@Override

View File

@ -6,25 +6,58 @@
package me.filoghost.holographicdisplays.nms.v1_11_R1;
import io.netty.buffer.Unpooled;
import net.minecraft.server.v1_11_R1.Packet;
import net.minecraft.server.v1_11_R1.PacketDataSerializer;
import java.io.IOException;
import java.util.UUID;
class PacketByteBuffer extends PacketDataSerializer {
class PacketByteBuffer {
private static final PacketByteBuffer INSTANCE = new PacketByteBuffer();
private static final ThreadLocal<PacketByteBuffer> LOCAL_INSTANCE = ThreadLocal.withInitial(PacketByteBuffer::new);
private final PacketDataSerializer serializer;
static PacketByteBuffer get() {
INSTANCE.clear();
return INSTANCE;
PacketByteBuffer instance = LOCAL_INSTANCE.get();
instance.clear();
return instance;
}
private PacketByteBuffer() {
super(Unpooled.buffer());
this.serializer = new PacketDataSerializer(Unpooled.buffer());
}
int readableBytes() {
return serializer.readableBytes();
}
void readBytes(byte[] bytes) {
serializer.readBytes(bytes);
}
void writeBoolean(boolean flag) {
serializer.writeBoolean(flag);
}
void writeByte(int i) {
serializer.writeByte(i);
}
void writeShort(int i) {
serializer.writeShort(i);
}
void writeInt(int i) {
serializer.writeInt(i);
}
void writeDouble(double d) {
serializer.writeDouble(d);
}
void writeVarInt(int i) {
super.d(i);
serializer.d(i);
}
void writeVarIntArray(int i1) {
@ -33,17 +66,31 @@ class PacketByteBuffer extends PacketDataSerializer {
}
void writeUUID(UUID uuid) {
super.a(uuid);
serializer.a(uuid);
}
<T> void writeDataWatcherEntry(DataWatcherKey<T> key, T value) {
writeByte(key.getIndex());
serializer.writeByte(key.getIndex());
writeVarInt(key.getSerializerTypeID());
key.getSerializer().a(this, value);
key.getSerializer().a(serializer, value);
}
void writeDataWatcherEntriesEnd() {
writeByte(0xFF);
serializer.writeByte(0xFF);
}
void clear() {
serializer.clear();
}
<T extends Packet<?>> T writeDataTo(T packet) {
try {
packet.a(serializer);
return packet;
} catch (IOException e) {
// Never thrown by the implementations
throw new RuntimeException(e);
}
}
}

View File

@ -8,6 +8,7 @@ package me.filoghost.holographicdisplays.nms.v1_11_R1;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.EventLoop;
import me.filoghost.fcommons.logging.ErrorCollector;
import me.filoghost.fcommons.logging.Log;
import me.filoghost.fcommons.reflection.ReflectField;
@ -115,8 +116,12 @@ public class VersionNMSManager implements NMSManager {
PlayerConnection playerConnection = ((CraftPlayer) player).getHandle().playerConnection;
NetworkManager networkManager = playerConnection.a();
Channel channel = networkManager.channel;
if (channel == null) {
return;
}
EventLoop eventLoop = channel.eventLoop();
channel.eventLoop().execute(() -> {
Runnable safeModifierTask = () -> {
if (!player.isOnline()) {
return;
}
@ -125,7 +130,13 @@ public class VersionNMSManager implements NMSManager {
} catch (Exception e) {
Log.warning(NMSErrors.EXCEPTION_MODIFYING_CHANNEL_PIPELINE, e);
}
});
};
if (eventLoop.inEventLoop()) {
safeModifierTask.run();
} else {
eventLoop.execute(safeModifierTask);
}
}
}

View File

@ -10,8 +10,6 @@ import net.minecraft.server.v1_11_R1.Packet;
import org.bukkit.craftbukkit.v1_11_R1.entity.CraftPlayer;
import org.bukkit.entity.Player;
import java.io.IOException;
abstract class VersionNMSPacket implements PacketGroup {
@Override
@ -21,14 +19,4 @@ abstract class VersionNMSPacket implements PacketGroup {
abstract Packet<?> getRawPacket();
protected static <T extends Packet<?>> T writeData(T packet, PacketByteBuffer packetByteBuffer) {
try {
packet.a(packetByteBuffer);
return packet;
} catch (IOException e) {
// Never thrown by the implementations
throw new RuntimeException(e);
}
}
}

View File

@ -6,7 +6,7 @@
<parent>
<groupId>me.filoghost.holographicdisplays</groupId>
<artifactId>holographicdisplays-nms</artifactId>
<version>3.0.0</version>
<version>3.0.5-SNAPSHOT</version>
</parent>
<artifactId>holographicdisplays-nms-v1_12_r1</artifactId>

View File

@ -62,7 +62,7 @@ class EntityLivingSpawnNMSPacket extends VersionNMSPacket {
// Entries are deserialized and saved into a field which is not used during the re-serialization, set as empty
packetByteBuffer.writeDataWatcherEntriesEnd();
Packet<?> rawPacket = writeData(new PacketPlayOutSpawnEntityLiving(), packetByteBuffer);
Packet<?> rawPacket = packetByteBuffer.writeDataTo(new PacketPlayOutSpawnEntityLiving());
return new Builder(rawPacket, PacketByteBuffer.get());
}

View File

@ -14,7 +14,7 @@ class EntityMetadataNMSPacket extends VersionNMSPacket {
private final Packet<?> rawPacket;
private EntityMetadataNMSPacket(PacketByteBuffer packetByteBuffer) {
this.rawPacket = writeData(new PacketPlayOutEntityMetadata(), packetByteBuffer);
this.rawPacket = packetByteBuffer.writeDataTo(new PacketPlayOutEntityMetadata());
}
@Override

View File

@ -19,7 +19,7 @@ class EntityMountNMSPacket extends VersionNMSPacket {
packetByteBuffer.writeVarInt(vehicleEntityID.getNumericID());
packetByteBuffer.writeVarIntArray(passengerEntityID.getNumericID());
this.rawPacket = writeData(new PacketPlayOutMount(), packetByteBuffer);
this.rawPacket = packetByteBuffer.writeDataTo(new PacketPlayOutMount());
}
@Override

View File

@ -42,7 +42,7 @@ class EntitySpawnNMSPacket extends VersionNMSPacket {
packetByteBuffer.writeShort(0);
packetByteBuffer.writeShort(0);
this.rawPacket = writeData(new PacketPlayOutSpawnEntity(), packetByteBuffer);
this.rawPacket = packetByteBuffer.writeDataTo(new PacketPlayOutSpawnEntity());
}
@Override

View File

@ -31,7 +31,7 @@ class EntityTeleportNMSPacket extends VersionNMSPacket {
// On ground
packetByteBuffer.writeBoolean(false);
this.rawPacket = writeData(new PacketPlayOutEntityTeleport(), packetByteBuffer);
this.rawPacket = packetByteBuffer.writeDataTo(new PacketPlayOutEntityTeleport());
}
@Override

View File

@ -6,25 +6,58 @@
package me.filoghost.holographicdisplays.nms.v1_12_R1;
import io.netty.buffer.Unpooled;
import net.minecraft.server.v1_12_R1.Packet;
import net.minecraft.server.v1_12_R1.PacketDataSerializer;
import java.io.IOException;
import java.util.UUID;
class PacketByteBuffer extends PacketDataSerializer {
class PacketByteBuffer {
private static final PacketByteBuffer INSTANCE = new PacketByteBuffer();
private static final ThreadLocal<PacketByteBuffer> LOCAL_INSTANCE = ThreadLocal.withInitial(PacketByteBuffer::new);
private final PacketDataSerializer serializer;
static PacketByteBuffer get() {
INSTANCE.clear();
return INSTANCE;
PacketByteBuffer instance = LOCAL_INSTANCE.get();
instance.clear();
return instance;
}
private PacketByteBuffer() {
super(Unpooled.buffer());
this.serializer = new PacketDataSerializer(Unpooled.buffer());
}
int readableBytes() {
return serializer.readableBytes();
}
void readBytes(byte[] bytes) {
serializer.readBytes(bytes);
}
void writeBoolean(boolean flag) {
serializer.writeBoolean(flag);
}
void writeByte(int i) {
serializer.writeByte(i);
}
void writeShort(int i) {
serializer.writeShort(i);
}
void writeInt(int i) {
serializer.writeInt(i);
}
void writeDouble(double d) {
serializer.writeDouble(d);
}
void writeVarInt(int i) {
super.d(i);
serializer.d(i);
}
void writeVarIntArray(int i1) {
@ -33,17 +66,31 @@ class PacketByteBuffer extends PacketDataSerializer {
}
void writeUUID(UUID uuid) {
super.a(uuid);
serializer.a(uuid);
}
<T> void writeDataWatcherEntry(DataWatcherKey<T> key, T value) {
writeByte(key.getIndex());
serializer.writeByte(key.getIndex());
writeVarInt(key.getSerializerTypeID());
key.getSerializer().a(this, value);
key.getSerializer().a(serializer, value);
}
void writeDataWatcherEntriesEnd() {
writeByte(0xFF);
serializer.writeByte(0xFF);
}
void clear() {
serializer.clear();
}
<T extends Packet<?>> T writeDataTo(T packet) {
try {
packet.a(serializer);
return packet;
} catch (IOException e) {
// Never thrown by the implementations
throw new RuntimeException(e);
}
}
}

View File

@ -8,6 +8,7 @@ package me.filoghost.holographicdisplays.nms.v1_12_R1;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.EventLoop;
import me.filoghost.fcommons.logging.ErrorCollector;
import me.filoghost.fcommons.logging.Log;
import me.filoghost.fcommons.reflection.ReflectField;
@ -115,8 +116,12 @@ public class VersionNMSManager implements NMSManager {
PlayerConnection playerConnection = ((CraftPlayer) player).getHandle().playerConnection;
NetworkManager networkManager = playerConnection.a();
Channel channel = networkManager.channel;
if (channel == null) {
return;
}
EventLoop eventLoop = channel.eventLoop();
channel.eventLoop().execute(() -> {
Runnable safeModifierTask = () -> {
if (!player.isOnline()) {
return;
}
@ -125,7 +130,13 @@ public class VersionNMSManager implements NMSManager {
} catch (Exception e) {
Log.warning(NMSErrors.EXCEPTION_MODIFYING_CHANNEL_PIPELINE, e);
}
});
};
if (eventLoop.inEventLoop()) {
safeModifierTask.run();
} else {
eventLoop.execute(safeModifierTask);
}
}
}

View File

@ -10,8 +10,6 @@ import net.minecraft.server.v1_12_R1.Packet;
import org.bukkit.craftbukkit.v1_12_R1.entity.CraftPlayer;
import org.bukkit.entity.Player;
import java.io.IOException;
abstract class VersionNMSPacket implements PacketGroup {
@Override
@ -21,14 +19,4 @@ abstract class VersionNMSPacket implements PacketGroup {
abstract Packet<?> getRawPacket();
protected static <T extends Packet<?>> T writeData(T packet, PacketByteBuffer packetByteBuffer) {
try {
packet.a(packetByteBuffer);
return packet;
} catch (IOException e) {
// Never thrown by the implementations
throw new RuntimeException(e);
}
}
}

View File

@ -6,7 +6,7 @@
<parent>
<groupId>me.filoghost.holographicdisplays</groupId>
<artifactId>holographicdisplays-nms</artifactId>
<version>3.0.0</version>
<version>3.0.5-SNAPSHOT</version>
</parent>
<artifactId>holographicdisplays-nms-v1_13_r2</artifactId>

View File

@ -62,7 +62,7 @@ class EntityLivingSpawnNMSPacket extends VersionNMSPacket {
// Entries are deserialized and saved into a field which is not used during the re-serialization, set as empty
packetByteBuffer.writeDataWatcherEntriesEnd();
Packet<?> rawPacket = writeData(new PacketPlayOutSpawnEntityLiving(), packetByteBuffer);
Packet<?> rawPacket = packetByteBuffer.writeDataTo(new PacketPlayOutSpawnEntityLiving());
return new Builder(rawPacket, PacketByteBuffer.get());
}

View File

@ -14,7 +14,7 @@ class EntityMetadataNMSPacket extends VersionNMSPacket {
private final Packet<?> rawPacket;
private EntityMetadataNMSPacket(PacketByteBuffer packetByteBuffer) {
this.rawPacket = writeData(new PacketPlayOutEntityMetadata(), packetByteBuffer);
this.rawPacket = packetByteBuffer.writeDataTo(new PacketPlayOutEntityMetadata());
}
@Override

View File

@ -19,7 +19,7 @@ class EntityMountNMSPacket extends VersionNMSPacket {
packetByteBuffer.writeVarInt(vehicleEntityID.getNumericID());
packetByteBuffer.writeVarIntArray(passengerEntityID.getNumericID());
this.rawPacket = writeData(new PacketPlayOutMount(), packetByteBuffer);
this.rawPacket = packetByteBuffer.writeDataTo(new PacketPlayOutMount());
}
@Override

View File

@ -42,7 +42,7 @@ class EntitySpawnNMSPacket extends VersionNMSPacket {
packetByteBuffer.writeShort(0);
packetByteBuffer.writeShort(0);
this.rawPacket = writeData(new PacketPlayOutSpawnEntity(), packetByteBuffer);
this.rawPacket = packetByteBuffer.writeDataTo(new PacketPlayOutSpawnEntity());
}
@Override

View File

@ -31,7 +31,7 @@ class EntityTeleportNMSPacket extends VersionNMSPacket {
// On ground
packetByteBuffer.writeBoolean(false);
this.rawPacket = writeData(new PacketPlayOutEntityTeleport(), packetByteBuffer);
this.rawPacket = packetByteBuffer.writeDataTo(new PacketPlayOutEntityTeleport());
}
@Override

View File

@ -6,25 +6,58 @@
package me.filoghost.holographicdisplays.nms.v1_13_R2;
import io.netty.buffer.Unpooled;
import net.minecraft.server.v1_13_R2.Packet;
import net.minecraft.server.v1_13_R2.PacketDataSerializer;
import java.io.IOException;
import java.util.UUID;
class PacketByteBuffer extends PacketDataSerializer {
class PacketByteBuffer {
private static final PacketByteBuffer INSTANCE = new PacketByteBuffer();
private static final ThreadLocal<PacketByteBuffer> LOCAL_INSTANCE = ThreadLocal.withInitial(PacketByteBuffer::new);
private final PacketDataSerializer serializer;
static PacketByteBuffer get() {
INSTANCE.clear();
return INSTANCE;
PacketByteBuffer instance = LOCAL_INSTANCE.get();
instance.clear();
return instance;
}
private PacketByteBuffer() {
super(Unpooled.buffer());
this.serializer = new PacketDataSerializer(Unpooled.buffer());
}
int readableBytes() {
return serializer.readableBytes();
}
void readBytes(byte[] bytes) {
serializer.readBytes(bytes);
}
void writeBoolean(boolean flag) {
serializer.writeBoolean(flag);
}
void writeByte(int i) {
serializer.writeByte(i);
}
void writeShort(int i) {
serializer.writeShort(i);
}
void writeInt(int i) {
serializer.writeInt(i);
}
void writeDouble(double d) {
serializer.writeDouble(d);
}
void writeVarInt(int i) {
super.d(i);
serializer.d(i);
}
void writeVarIntArray(int i1) {
@ -33,17 +66,31 @@ class PacketByteBuffer extends PacketDataSerializer {
}
void writeUUID(UUID uuid) {
super.a(uuid);
serializer.a(uuid);
}
<T> void writeDataWatcherEntry(DataWatcherKey<T> key, T value) {
writeByte(key.getIndex());
serializer.writeByte(key.getIndex());
writeVarInt(key.getSerializerTypeID());
key.getSerializer().a(this, value);
key.getSerializer().a(serializer, value);
}
void writeDataWatcherEntriesEnd() {
writeByte(0xFF);
serializer.writeByte(0xFF);
}
void clear() {
serializer.clear();
}
<T extends Packet<?>> T writeDataTo(T packet) {
try {
packet.a(serializer);
return packet;
} catch (IOException e) {
// Never thrown by the implementations
throw new RuntimeException(e);
}
}
}

View File

@ -8,6 +8,7 @@ package me.filoghost.holographicdisplays.nms.v1_13_R2;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.EventLoop;
import me.filoghost.fcommons.logging.ErrorCollector;
import me.filoghost.fcommons.logging.Log;
import me.filoghost.fcommons.reflection.ReflectField;
@ -115,8 +116,12 @@ public class VersionNMSManager implements NMSManager {
PlayerConnection playerConnection = ((CraftPlayer) player).getHandle().playerConnection;
NetworkManager networkManager = playerConnection.a();
Channel channel = networkManager.channel;
if (channel == null) {
return;
}
EventLoop eventLoop = channel.eventLoop();
channel.eventLoop().execute(() -> {
Runnable safeModifierTask = () -> {
if (!player.isOnline()) {
return;
}
@ -125,7 +130,13 @@ public class VersionNMSManager implements NMSManager {
} catch (Exception e) {
Log.warning(NMSErrors.EXCEPTION_MODIFYING_CHANNEL_PIPELINE, e);
}
});
};
if (eventLoop.inEventLoop()) {
safeModifierTask.run();
} else {
eventLoop.execute(safeModifierTask);
}
}
}

View File

@ -10,8 +10,6 @@ import net.minecraft.server.v1_13_R2.Packet;
import org.bukkit.craftbukkit.v1_13_R2.entity.CraftPlayer;
import org.bukkit.entity.Player;
import java.io.IOException;
abstract class VersionNMSPacket implements PacketGroup {
@Override
@ -21,14 +19,4 @@ abstract class VersionNMSPacket implements PacketGroup {
abstract Packet<?> getRawPacket();
protected static <T extends Packet<?>> T writeData(T packet, PacketByteBuffer packetByteBuffer) {
try {
packet.a(packetByteBuffer);
return packet;
} catch (IOException e) {
// Never thrown by the implementations
throw new RuntimeException(e);
}
}
}

View File

@ -6,7 +6,7 @@
<parent>
<groupId>me.filoghost.holographicdisplays</groupId>
<artifactId>holographicdisplays-nms</artifactId>
<version>3.0.0</version>
<version>3.0.5-SNAPSHOT</version>
</parent>
<artifactId>holographicdisplays-nms-v1_14_r1</artifactId>

View File

@ -62,7 +62,7 @@ class EntityLivingSpawnNMSPacket extends VersionNMSPacket {
// Entries are deserialized and saved into a field which is not used during the re-serialization, set as empty
packetByteBuffer.writeDataWatcherEntriesEnd();
Packet<?> rawPacket = writeData(new PacketPlayOutSpawnEntityLiving(), packetByteBuffer);
Packet<?> rawPacket = packetByteBuffer.writeDataTo(new PacketPlayOutSpawnEntityLiving());
return new Builder(rawPacket, PacketByteBuffer.get());
}

View File

@ -14,7 +14,7 @@ class EntityMetadataNMSPacket extends VersionNMSPacket {
private final Packet<?> rawPacket;
private EntityMetadataNMSPacket(PacketByteBuffer packetByteBuffer) {
this.rawPacket = writeData(new PacketPlayOutEntityMetadata(), packetByteBuffer);
this.rawPacket = packetByteBuffer.writeDataTo(new PacketPlayOutEntityMetadata());
}
@Override

View File

@ -19,7 +19,7 @@ class EntityMountNMSPacket extends VersionNMSPacket {
packetByteBuffer.writeVarInt(vehicleEntityID.getNumericID());
packetByteBuffer.writeVarIntArray(passengerEntityID.getNumericID());
this.rawPacket = writeData(new PacketPlayOutMount(), packetByteBuffer);
this.rawPacket = packetByteBuffer.writeDataTo(new PacketPlayOutMount());
}
@Override

View File

@ -42,7 +42,7 @@ class EntitySpawnNMSPacket extends VersionNMSPacket {
packetByteBuffer.writeShort(0);
packetByteBuffer.writeShort(0);
this.rawPacket = writeData(new PacketPlayOutSpawnEntity(), packetByteBuffer);
this.rawPacket = packetByteBuffer.writeDataTo(new PacketPlayOutSpawnEntity());
}
@Override

View File

@ -31,7 +31,7 @@ class EntityTeleportNMSPacket extends VersionNMSPacket {
// On ground
packetByteBuffer.writeBoolean(false);
this.rawPacket = writeData(new PacketPlayOutEntityTeleport(), packetByteBuffer);
this.rawPacket = packetByteBuffer.writeDataTo(new PacketPlayOutEntityTeleport());
}
@Override

View File

@ -6,25 +6,58 @@
package me.filoghost.holographicdisplays.nms.v1_14_R1;
import io.netty.buffer.Unpooled;
import net.minecraft.server.v1_14_R1.Packet;
import net.minecraft.server.v1_14_R1.PacketDataSerializer;
import java.io.IOException;
import java.util.UUID;
class PacketByteBuffer extends PacketDataSerializer {
class PacketByteBuffer {
private static final PacketByteBuffer INSTANCE = new PacketByteBuffer();
private static final ThreadLocal<PacketByteBuffer> LOCAL_INSTANCE = ThreadLocal.withInitial(PacketByteBuffer::new);
private final PacketDataSerializer serializer;
static PacketByteBuffer get() {
INSTANCE.clear();
return INSTANCE;
PacketByteBuffer instance = LOCAL_INSTANCE.get();
instance.clear();
return instance;
}
private PacketByteBuffer() {
super(Unpooled.buffer());
this.serializer = new PacketDataSerializer(Unpooled.buffer());
}
int readableBytes() {
return serializer.readableBytes();
}
void readBytes(byte[] bytes) {
serializer.readBytes(bytes);
}
void writeBoolean(boolean flag) {
serializer.writeBoolean(flag);
}
void writeByte(int i) {
serializer.writeByte(i);
}
void writeShort(int i) {
serializer.writeShort(i);
}
void writeInt(int i) {
serializer.writeInt(i);
}
void writeDouble(double d) {
serializer.writeDouble(d);
}
void writeVarInt(int i) {
super.d(i);
serializer.d(i);
}
void writeVarIntArray(int i1) {
@ -33,17 +66,31 @@ class PacketByteBuffer extends PacketDataSerializer {
}
void writeUUID(UUID uuid) {
super.a(uuid);
serializer.a(uuid);
}
<T> void writeDataWatcherEntry(DataWatcherKey<T> key, T value) {
writeByte(key.getIndex());
serializer.writeByte(key.getIndex());
writeVarInt(key.getSerializerTypeID());
key.getSerializer().a(this, value);
key.getSerializer().a(serializer, value);
}
void writeDataWatcherEntriesEnd() {
writeByte(0xFF);
serializer.writeByte(0xFF);
}
void clear() {
serializer.clear();
}
<T extends Packet<?>> T writeDataTo(T packet) {
try {
packet.a(serializer);
return packet;
} catch (IOException e) {
// Never thrown by the implementations
throw new RuntimeException(e);
}
}
}

View File

@ -8,6 +8,7 @@ package me.filoghost.holographicdisplays.nms.v1_14_R1;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.EventLoop;
import me.filoghost.fcommons.logging.ErrorCollector;
import me.filoghost.fcommons.logging.Log;
import me.filoghost.fcommons.reflection.ReflectField;
@ -100,8 +101,12 @@ public class VersionNMSManager implements NMSManager {
PlayerConnection playerConnection = ((CraftPlayer) player).getHandle().playerConnection;
NetworkManager networkManager = playerConnection.a();
Channel channel = networkManager.channel;
if (channel == null) {
return;
}
EventLoop eventLoop = channel.eventLoop();
channel.eventLoop().execute(() -> {
Runnable safeModifierTask = () -> {
if (!player.isOnline()) {
return;
}
@ -110,7 +115,13 @@ public class VersionNMSManager implements NMSManager {
} catch (Exception e) {
Log.warning(NMSErrors.EXCEPTION_MODIFYING_CHANNEL_PIPELINE, e);
}
});
};
if (eventLoop.inEventLoop()) {
safeModifierTask.run();
} else {
eventLoop.execute(safeModifierTask);
}
}
}

View File

@ -10,8 +10,6 @@ import net.minecraft.server.v1_14_R1.Packet;
import org.bukkit.craftbukkit.v1_14_R1.entity.CraftPlayer;
import org.bukkit.entity.Player;
import java.io.IOException;
abstract class VersionNMSPacket implements PacketGroup {
@Override
@ -21,14 +19,4 @@ abstract class VersionNMSPacket implements PacketGroup {
abstract Packet<?> getRawPacket();
protected static <T extends Packet<?>> T writeData(T packet, PacketByteBuffer packetByteBuffer) {
try {
packet.a(packetByteBuffer);
return packet;
} catch (IOException e) {
// Never thrown by the implementations
throw new RuntimeException(e);
}
}
}

View File

@ -6,7 +6,7 @@
<parent>
<groupId>me.filoghost.holographicdisplays</groupId>
<artifactId>holographicdisplays-nms</artifactId>
<version>3.0.0</version>
<version>3.0.5-SNAPSHOT</version>
</parent>
<artifactId>holographicdisplays-nms-v1_15_r1</artifactId>

View File

@ -38,7 +38,7 @@ class EntityLivingSpawnNMSPacket extends VersionNMSPacket {
packetByteBuffer.writeShort(0);
packetByteBuffer.writeShort(0);
this.rawPacket = writeData(new PacketPlayOutSpawnEntityLiving(), packetByteBuffer);
this.rawPacket = packetByteBuffer.writeDataTo(new PacketPlayOutSpawnEntityLiving());
}
@Override

View File

@ -14,7 +14,7 @@ class EntityMetadataNMSPacket extends VersionNMSPacket {
private final Packet<?> rawPacket;
private EntityMetadataNMSPacket(PacketByteBuffer packetByteBuffer) {
this.rawPacket = writeData(new PacketPlayOutEntityMetadata(), packetByteBuffer);
this.rawPacket = packetByteBuffer.writeDataTo(new PacketPlayOutEntityMetadata());
}
@Override

View File

@ -19,7 +19,7 @@ class EntityMountNMSPacket extends VersionNMSPacket {
packetByteBuffer.writeVarInt(vehicleEntityID.getNumericID());
packetByteBuffer.writeVarIntArray(passengerEntityID.getNumericID());
this.rawPacket = writeData(new PacketPlayOutMount(), packetByteBuffer);
this.rawPacket = packetByteBuffer.writeDataTo(new PacketPlayOutMount());
}
@Override

View File

@ -42,7 +42,7 @@ class EntitySpawnNMSPacket extends VersionNMSPacket {
packetByteBuffer.writeShort(0);
packetByteBuffer.writeShort(0);
this.rawPacket = writeData(new PacketPlayOutSpawnEntity(), packetByteBuffer);
this.rawPacket = packetByteBuffer.writeDataTo(new PacketPlayOutSpawnEntity());
}
@Override

Some files were not shown because too many files have changed in this diff Show More