mirror of
https://github.com/Xiao-MoMi/Custom-Nameplates.git
synced 2026-11-06 01:12:38 -05:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a5fd4f237e | ||
|
|
5046372177 | ||
|
|
df86e4bc33 | ||
|
|
b5e83ca984 | ||
|
|
04bb10cb3d | ||
|
|
e7371cc02a | ||
|
|
bee0b26a9f | ||
|
|
343c0e5cb0 | ||
|
|
81d3a888b8 | ||
|
|
58e16e5376 | ||
|
|
cc8c3d6bcd | ||
|
|
3000b26bfa | ||
|
|
a800481574 | ||
|
|
82350ac0c4 | ||
|
|
35edd85434 | ||
|
|
99bfc28be8 | ||
|
|
5ee27c126c | ||
|
|
5282d5e8a7 | ||
|
|
0f7a72bf1e | ||
|
|
b36d0c23e1 | ||
|
|
f8219659c4 | ||
|
|
eb730c8631 | ||
|
|
12b8b74031 | ||
|
|
365aae10f5 | ||
|
|
5e299bb0d4 | ||
|
|
79a0892b09 | ||
|
|
a8bc4d8de5 | ||
|
|
6276d27d57 | ||
|
|
096e6330d6 | ||
|
|
e41686aa31 | ||
|
|
590b26ac2a | ||
|
|
a7dc0db15d | ||
|
|
c9250fea13 | ||
|
|
fa914d52a2 | ||
|
|
efbf2d3b64 | ||
|
|
40672aefb4 | ||
|
|
8fb4b8317d | ||
|
|
e68a333527 | ||
|
|
53317c3e4b | ||
|
|
c2c1b703b7 | ||
|
|
abcece373f | ||
|
|
be8cf27f37 | ||
|
|
6fafb85cec | ||
|
|
d18bf83ecb | ||
|
|
2c8aad7a75 | ||
|
|
9e8e57c6df | ||
|
|
1c433d1891 | ||
|
|
6e77eb55d0 | ||
|
|
3afa1bfb58 | ||
|
|
39e9d40e3e | ||
|
|
2e90d02166 | ||
|
|
9d88ead4e3 | ||
|
|
810b8f0593 | ||
|
|
930cdf8c00 | ||
|
|
a26e6dc784 | ||
|
|
e450b1429d | ||
|
|
7811cea007 | ||
|
|
22a440ae23 | ||
|
|
c279c9a74d | ||
|
|
a6b11d1fe7 | ||
|
|
180b34f4c8 | ||
|
|
c69735ea2b | ||
|
|
f7628c2db9 | ||
|
|
4c0df8288b | ||
|
|
bd0abb3463 | ||
|
|
65b70a639b | ||
|
|
8ff48ad395 | ||
|
|
dc149dbb05 | ||
|
|
f70918befd | ||
|
|
53f9a9a85d |
No files matched your search
@@ -1,21 +1,80 @@
|
||||
# This project is currently under recoding
|
||||
# Custom-Nameplates
|
||||
|
||||
### Custom-Nameplates
|
||||
A unique way to customize nametags
|
||||

|
||||

|
||||

|
||||

|
||||

|
||||
[](https://jitpack.io/#Xiao-MoMi/Custom-Nameplates)
|
||||
<a href="https://mo-mi.gitbook.io/xiaomomi-plugins/plugin-wiki/customnameplates" alt="GitBook">
|
||||
<img src="https://img.shields.io/badge/docs-gitbook-brightgreen" alt="Gitbook"/>
|
||||
</a>
|
||||
|
||||
### How to support the developer
|
||||
CustomNameplates is a Paper plugin that provides unlimited customization for nametags, bossbars, actionbars and chat bubbles.
|
||||
|
||||
https://afdian.net/@xiaomomi
|
||||
## How to build
|
||||
|
||||
https://polymart.org/resource/customnameplates.2543
|
||||
### Windows
|
||||
|
||||
### How to compile
|
||||
Open the project with your IDE and execute gradle build. Finally you will get the jar at /project/build/libs/CustomNameplates-xxx-all.jar.
|
||||
|
||||
### I don't know how to build with IDE
|
||||
#### Command Line
|
||||
Install JDK 17 and set the JDK installation path to JAVA_HOME as an environment variable.\
|
||||
Start powershell and change directory to the project folder.\
|
||||
Execute ".\gradlew build" and get the jar at /project/build/libs/CustomNameplates-xxx-all.jar.
|
||||
Execute ".\gradlew build" and get the jar at /target/CustomNameplates-universe-version.jar.
|
||||
|
||||
### API
|
||||
Plugin is scheduled to be recoded on December. At that time API would be available. For the moment you can use the jar as local library.
|
||||
#### IDE
|
||||
Import the project and execute gradle build action.
|
||||
|
||||
##### About Proxy
|
||||
If you are using a proxy, configurate the proxy in gradle.properties. Otherwise comment the lines in gradle.properties.
|
||||
|
||||
## Support the developer
|
||||
|
||||
Polymart: https://polymart.org/resource/customnameplates.2543 \
|
||||
Afdian: https://afdian.net/@xiaomomi
|
||||
|
||||
## Use CustomNameplates API
|
||||
|
||||
### Maven
|
||||
|
||||
```
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>jitpack</id>
|
||||
<url>https://jitpack.io/</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
```
|
||||
```
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.github.Xiao-MoMi</groupId>
|
||||
<artifactId>Custom-Nameplates</artifactId>
|
||||
<version>{LATEST}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
```
|
||||
### Gradle (Groovy)
|
||||
|
||||
```
|
||||
repositories {
|
||||
maven { url 'https://jitpack.io' }
|
||||
}
|
||||
```
|
||||
```
|
||||
dependencies {
|
||||
compileOnly 'com.github.Xiao-MoMi:Custom-Nameplates:{LATEST}'
|
||||
}
|
||||
```
|
||||
### Gradle (Kotlin)
|
||||
|
||||
```
|
||||
repositories {
|
||||
maven("https://jitpack.io/")
|
||||
}
|
||||
```
|
||||
```
|
||||
dependencies {
|
||||
compileOnly("com.github.Xiao-MoMi:Custom-Nameplates:{LATEST}")
|
||||
}
|
||||
```
|
||||
@@ -1,5 +1,12 @@
|
||||
dependencies {
|
||||
implementation(project(":common"))
|
||||
compileOnly("dev.folia:folia-api:1.20.1-R0.1-SNAPSHOT")
|
||||
compileOnly("me.clip:placeholderapi:2.11.5")
|
||||
implementation(project(":common"))
|
||||
implementation("net.kyori:adventure-api:4.16.0")
|
||||
}
|
||||
|
||||
tasks {
|
||||
shadowJar {
|
||||
relocate ("net.kyori", "net.momirealms.customnameplates.libraries")
|
||||
}
|
||||
}
|
||||
@@ -41,6 +41,13 @@ public interface DataStorageInterface {
|
||||
*/
|
||||
StorageType getStorageType();
|
||||
|
||||
/**
|
||||
* Get a player's data by uuid
|
||||
* This player can be an offline one
|
||||
*
|
||||
* @param uuid uuid
|
||||
* @return player data
|
||||
*/
|
||||
CompletableFuture<Optional<PlayerData>> getPlayerData(UUID uuid);
|
||||
|
||||
CompletableFuture<Boolean> updatePlayerData(UUID uuid, PlayerData playerData);
|
||||
|
||||
@@ -82,6 +82,10 @@ public class OnlineUser {
|
||||
return CustomNameplatesPlugin.get().getNameplateManager().getNameplate(temp);
|
||||
}
|
||||
|
||||
/**
|
||||
* This value might be inconsistent with the key get by "getBubbleKey()"
|
||||
* Because if a player doesn't have a bubble, his bubble would be the default one
|
||||
*/
|
||||
@Nullable
|
||||
public Bubble getBubble() {
|
||||
String temp = nameplate;
|
||||
|
||||
@@ -26,5 +26,6 @@ public enum StorageType {
|
||||
MySQL,
|
||||
MariaDB,
|
||||
MongoDB,
|
||||
Redis
|
||||
Redis,
|
||||
None
|
||||
}
|
||||
@@ -23,6 +23,9 @@ import org.bukkit.event.HandlerList;
|
||||
import org.bukkit.event.player.PlayerEvent;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* An event triggered when player sends a message
|
||||
*/
|
||||
public class BubblesSpawnEvent extends PlayerEvent implements Cancellable {
|
||||
|
||||
private boolean cancelled;
|
||||
@@ -57,18 +60,34 @@ public class BubblesSpawnEvent extends PlayerEvent implements Cancellable {
|
||||
return getHandlerList();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the bubble's key
|
||||
*/
|
||||
public String getBubble() {
|
||||
return bubble;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the bubble
|
||||
*
|
||||
* @param bubble bubble's key
|
||||
*/
|
||||
public void setBubble(String bubble) {
|
||||
this.bubble = bubble;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the bubble text content
|
||||
*/
|
||||
public String getText() {
|
||||
return text;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the bubble text content
|
||||
*
|
||||
* @param text text
|
||||
*/
|
||||
public void setText(String text) {
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
+3
@@ -22,6 +22,9 @@ import org.bukkit.event.Event;
|
||||
import org.bukkit.event.HandlerList;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* Plugin reload event
|
||||
*/
|
||||
public class CustomNameplatesReloadEvent extends Event {
|
||||
|
||||
private static final HandlerList handlerList = new HandlerList();
|
||||
|
||||
+13
@@ -24,6 +24,9 @@ import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Player data loaded event
|
||||
*/
|
||||
public class NameplateDataLoadEvent extends Event {
|
||||
|
||||
private static final HandlerList handlerList = new HandlerList();
|
||||
@@ -36,10 +39,20 @@ public class NameplateDataLoadEvent extends Event {
|
||||
this.onlineUser = onlineUser;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the UUID
|
||||
*
|
||||
* @return uuid
|
||||
*/
|
||||
public UUID getUUID() {
|
||||
return uuid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the online user
|
||||
*
|
||||
* @return online user
|
||||
*/
|
||||
public OnlineUser getOnlineUser() {
|
||||
return onlineUser;
|
||||
}
|
||||
|
||||
@@ -149,6 +149,12 @@ public interface AdventureManager {
|
||||
@SuppressWarnings("BooleanMethodIsAlwaysInverted")
|
||||
boolean isColorCode(char c);
|
||||
|
||||
/**
|
||||
* Convert a color into decimal
|
||||
*
|
||||
* @param color color
|
||||
* @return decimal
|
||||
*/
|
||||
int colorToDecimal(ChatColor color);
|
||||
|
||||
/**
|
||||
@@ -175,5 +181,11 @@ public interface AdventureManager {
|
||||
*/
|
||||
String getMiniMessageFormat(Component component);
|
||||
|
||||
/**
|
||||
* Get IChatComponent from Json
|
||||
*
|
||||
* @param json json
|
||||
* @return component
|
||||
*/
|
||||
Object getIChatComponent(String json);
|
||||
}
|
||||
@@ -34,6 +34,11 @@ public interface BackGroundManager {
|
||||
@Nullable
|
||||
BackGround getBackGround(@NotNull String key);
|
||||
|
||||
/**
|
||||
* Get all the backgrounds
|
||||
*
|
||||
* @return backgrounds
|
||||
*/
|
||||
Collection<BackGround> getBackGrounds();
|
||||
|
||||
/**
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
package net.momirealms.customnameplates.api.manager;
|
||||
|
||||
import net.momirealms.customnameplates.api.mechanic.bubble.Bubble;
|
||||
import net.momirealms.customnameplates.api.mechanic.bubble.provider.AbstractChatProvider;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -26,29 +27,127 @@ import java.util.List;
|
||||
|
||||
public interface BubbleManager {
|
||||
|
||||
/**
|
||||
* Set a custom chat provider
|
||||
*
|
||||
* @param provider provider
|
||||
* @return success or not
|
||||
*/
|
||||
boolean setCustomChatProvider(AbstractChatProvider provider);
|
||||
|
||||
/**
|
||||
* Remove a custom chat provider
|
||||
*
|
||||
* @return success or not
|
||||
*/
|
||||
boolean removeCustomChatProvider();
|
||||
|
||||
/**
|
||||
* Register a bubble into map
|
||||
*
|
||||
* @param key key
|
||||
* @param bubble bubble
|
||||
* @return success or not
|
||||
*/
|
||||
boolean registerBubble(String key, Bubble bubble);
|
||||
|
||||
/**
|
||||
* Unregister a bubble from map
|
||||
*
|
||||
* @param key key
|
||||
* @return success or not
|
||||
*/
|
||||
boolean unregisterBubble(String key);
|
||||
|
||||
/**
|
||||
* Get a bubble from map
|
||||
*
|
||||
* @param bubble key
|
||||
* @return bubble
|
||||
*/
|
||||
@Nullable Bubble getBubble(String bubble);
|
||||
|
||||
/**
|
||||
* If a player has a certain bubble
|
||||
*
|
||||
* @param player player
|
||||
* @param bubble key
|
||||
* @return
|
||||
*/
|
||||
boolean hasBubble(Player player, String bubble);
|
||||
|
||||
/**
|
||||
* Get a list of the bubbles that a player has
|
||||
*
|
||||
* @param player player
|
||||
* @return bubbles' keys
|
||||
*/
|
||||
List<String> getAvailableBubbles(Player player);
|
||||
|
||||
/**
|
||||
* Get a list of the bubbles' display names that a player has
|
||||
*
|
||||
* @param player player
|
||||
* @return bubbles' display names
|
||||
*/
|
||||
List<String> getAvailableBubblesDisplayNames(Player player);
|
||||
|
||||
/**
|
||||
* Get blacklist chat channels
|
||||
*
|
||||
* @return channels
|
||||
*/
|
||||
String[] getBlacklistChannels();
|
||||
|
||||
/**
|
||||
* Get all the bubbles
|
||||
*
|
||||
* @return bubbles
|
||||
*/
|
||||
Collection<Bubble> getBubbles();
|
||||
|
||||
/**
|
||||
* Whether a bubble exists
|
||||
*/
|
||||
boolean containsBubble(String key);
|
||||
|
||||
/**
|
||||
* Equip a bubble for a player
|
||||
*
|
||||
* @param player player
|
||||
* @param bubble bubble
|
||||
* @return success or not
|
||||
*/
|
||||
boolean equipBubble(Player player, String bubble);
|
||||
|
||||
/**
|
||||
* Unequip a bubble for a player
|
||||
*
|
||||
* @param player player
|
||||
*/
|
||||
void unEquipBubble(Player player);
|
||||
|
||||
/**
|
||||
* Get the default bubble key
|
||||
*
|
||||
* @return bubble key
|
||||
*/
|
||||
String getDefaultBubble();
|
||||
|
||||
void onChat(Player player, String text, String channel);
|
||||
|
||||
/**
|
||||
* Get all the bubbles' keys
|
||||
*
|
||||
* @return keys
|
||||
*/
|
||||
Collection<String> getBubbleKeys();
|
||||
|
||||
/**
|
||||
* Trigger chat
|
||||
*
|
||||
* @param player player
|
||||
* @param text text
|
||||
*/
|
||||
void onChat(Player player, String text);
|
||||
}
|
||||
@@ -34,6 +34,11 @@ public interface ImageManager {
|
||||
@Nullable
|
||||
ConfiguredChar getImage(@NotNull String key);
|
||||
|
||||
/**
|
||||
* Get all the images
|
||||
*
|
||||
* @return images
|
||||
*/
|
||||
Collection<ConfiguredChar> getImages();
|
||||
|
||||
/**
|
||||
|
||||
+158
-23
@@ -39,6 +39,10 @@ public interface NameplateManager {
|
||||
@NotNull
|
||||
String getDefaultNameplate();
|
||||
|
||||
void handlePlayerJoin(Player player);
|
||||
|
||||
void handlePlayerQuit(Player player);
|
||||
|
||||
/**
|
||||
* Put an entity's ID to map
|
||||
* This map is used for quickly getting the entity instance
|
||||
@@ -48,7 +52,7 @@ public interface NameplateManager {
|
||||
* @param entityID entityID
|
||||
* @param entity entity
|
||||
*/
|
||||
boolean putEntityIDToMap(int entityID, Entity entity);
|
||||
boolean putEntityIDToMap(int entityID, @NotNull Entity entity);
|
||||
|
||||
/**
|
||||
* Remove the entity from map
|
||||
@@ -66,7 +70,7 @@ public interface NameplateManager {
|
||||
* @param uuid player uuid
|
||||
* @param nameplate cached nameplate
|
||||
*/
|
||||
boolean putCachedNameplateToMap(UUID uuid, CachedNameplate nameplate);
|
||||
boolean putCachedNameplateToMap(@NotNull UUID uuid, @NotNull CachedNameplate nameplate);
|
||||
|
||||
/**
|
||||
* Remove CachedNameplate from map
|
||||
@@ -75,7 +79,7 @@ public interface NameplateManager {
|
||||
* @return removed CachedNameplate
|
||||
*/
|
||||
@Nullable
|
||||
CachedNameplate removeCachedNameplateFromMap(UUID uuid);
|
||||
CachedNameplate removeCachedNameplateFromMap(@NotNull UUID uuid);
|
||||
|
||||
/**
|
||||
* Get player by entityID from the cache
|
||||
@@ -102,7 +106,7 @@ public interface NameplateManager {
|
||||
* @param player player
|
||||
* @return if the nameplate is updated
|
||||
*/
|
||||
boolean updateCachedNameplate(Player player);
|
||||
boolean updateCachedNameplate(@NotNull Player player);
|
||||
|
||||
/**
|
||||
* Update a player's cached nameplate
|
||||
@@ -111,7 +115,7 @@ public interface NameplateManager {
|
||||
* @param player player
|
||||
* @return if the nameplate is updated
|
||||
*/
|
||||
boolean updateCachedNameplate(Player player, Nameplate nameplate);
|
||||
boolean updateCachedNameplate(@NotNull Player player, @Nullable Nameplate nameplate);
|
||||
|
||||
/**
|
||||
* This should not be null when player's data is loaded (async process)
|
||||
@@ -120,61 +124,192 @@ public interface NameplateManager {
|
||||
* @return cached nameplate
|
||||
*/
|
||||
@Nullable
|
||||
CachedNameplate getCacheNameplate(Player player);
|
||||
CachedNameplate getCacheNameplate(@NotNull Player player);
|
||||
|
||||
/**
|
||||
* Create a name tag for a player, the tag type is decided by the mode in nameplate.yml
|
||||
* If mode is DISABLE, this method would return null
|
||||
* The tag would be put into map automatically and you can get it by getNameplatePlayer(uuid)
|
||||
*
|
||||
* @param player player
|
||||
*/
|
||||
void createNameTag(Player player);
|
||||
@Nullable
|
||||
NameplatePlayer createNameTag(@NotNull Player player);
|
||||
|
||||
void putNameplatePlayerToMap(NameplatePlayer player);
|
||||
/**
|
||||
* Put a nameplater player to map
|
||||
*
|
||||
* @param player player
|
||||
*/
|
||||
void putNameplatePlayerToMap(@NotNull NameplatePlayer player);
|
||||
|
||||
NameplatePlayer getNameplatePlayer(UUID uuid);
|
||||
/**
|
||||
* Get a nameplate player from map
|
||||
*
|
||||
* @param uuid uuid
|
||||
* @return nameplate player
|
||||
*/
|
||||
@Nullable
|
||||
NameplatePlayer getNameplatePlayer(@NotNull UUID uuid);
|
||||
|
||||
NameplatePlayer removeNameplatePlayerFromMap(UUID uuid);
|
||||
/**
|
||||
* Remove nameplate player from map
|
||||
*
|
||||
* @param uuid uuid
|
||||
* @return removed nameplate player
|
||||
*/
|
||||
@Nullable
|
||||
NameplatePlayer removeNameplatePlayerFromMap(@NotNull UUID uuid);
|
||||
|
||||
String getNameplatePrefix(Player player);
|
||||
/**
|
||||
* Get the nameplate's prefix with text tags
|
||||
*
|
||||
* @param player player
|
||||
* @return prefix with text tags
|
||||
*/
|
||||
@NotNull
|
||||
String getNameplatePrefix(@NotNull Player player);
|
||||
|
||||
String getNameplateSuffix(Player player);
|
||||
/**
|
||||
* Get the nameplate's suffix with text tags
|
||||
*
|
||||
* @param player player
|
||||
* @return suffix with text tags
|
||||
*/
|
||||
@NotNull
|
||||
String getNameplateSuffix(@NotNull Player player);
|
||||
|
||||
String getFullNameTag(Player player);
|
||||
/**
|
||||
* Get the full nameplate tag
|
||||
*
|
||||
* @param player player
|
||||
* @return nameplate tag
|
||||
*/
|
||||
@NotNull
|
||||
String getFullNameTag(@NotNull Player player);
|
||||
|
||||
boolean registerNameplate(String key, Nameplate nameplate);
|
||||
/**
|
||||
* Register a custom nameplate into map
|
||||
*
|
||||
* @param key key
|
||||
* @param nameplate nameplate
|
||||
* @return success or not
|
||||
*/
|
||||
boolean registerNameplate(@NotNull String key, @NotNull Nameplate nameplate);
|
||||
|
||||
boolean equipNameplate(Player player, String nameplateKey, boolean temp);
|
||||
/**
|
||||
* Unregister a nameplate from map
|
||||
*
|
||||
* @param key key
|
||||
* @return success or not
|
||||
*/
|
||||
boolean unregisterNameplate(@NotNull String key);
|
||||
|
||||
/**
|
||||
* Equip a nameplate for a player
|
||||
*
|
||||
* @param player player
|
||||
* @param nameplateKey key
|
||||
* @param temp whether save to storage
|
||||
* @return success or not
|
||||
*/
|
||||
boolean equipNameplate(@NotNull Player player, @NotNull String nameplateKey, boolean temp);
|
||||
|
||||
/**
|
||||
* Remove a nameplate for a player
|
||||
*
|
||||
* @param player player
|
||||
* @param temp whether save to storage
|
||||
*/
|
||||
void unEquipNameplate(Player player, boolean temp);
|
||||
|
||||
boolean unregisterNameplate(String key);
|
||||
|
||||
/**
|
||||
* Is team managed on proxy side
|
||||
*/
|
||||
boolean isProxyMode();
|
||||
|
||||
/**
|
||||
* Get preview duration
|
||||
*/
|
||||
int getPreviewDuration();
|
||||
|
||||
/**
|
||||
* Get the tag mode
|
||||
*/
|
||||
@NotNull
|
||||
TagMode getTagMode();
|
||||
|
||||
Nameplate getNameplate(String key);
|
||||
/**
|
||||
* Get a nameplate by key
|
||||
*
|
||||
* @param key key
|
||||
* @return nameplate
|
||||
*/
|
||||
@Nullable
|
||||
Nameplate getNameplate(@NotNull String key);
|
||||
|
||||
/**
|
||||
* Get all the nameplates
|
||||
*
|
||||
* @return nameplates
|
||||
*/
|
||||
@NotNull
|
||||
Collection<Nameplate> getNameplates();
|
||||
|
||||
/**
|
||||
* Get all the nameplates' keys
|
||||
*
|
||||
* @return keys
|
||||
*/
|
||||
@NotNull
|
||||
Collection<String> getNameplateKeys();
|
||||
|
||||
boolean containsNameplate(String key);
|
||||
/**
|
||||
* Whether a nameplate key exists
|
||||
*/
|
||||
boolean containsNameplate(@NotNull String key);
|
||||
|
||||
List<String> getAvailableNameplates(Player player);
|
||||
/**
|
||||
* Get all the nameplates that the player has
|
||||
*
|
||||
* @param player player
|
||||
* @return nameplates' keys
|
||||
*/
|
||||
@NotNull
|
||||
List<String> getAvailableNameplates(@NotNull Player player);
|
||||
|
||||
/**
|
||||
* If player has permission for a certain nameplate
|
||||
*/
|
||||
boolean hasNameplate(Player player, String nameplate);
|
||||
boolean hasNameplate(@NotNull Player player, @NotNull String nameplate);
|
||||
|
||||
List<String> getAvailableNameplateDisplayNames(Player player);
|
||||
/**
|
||||
* Get all the nameplates' display names that the player has
|
||||
*
|
||||
* @param player player
|
||||
* @return nameplates' display names
|
||||
*/
|
||||
@NotNull
|
||||
List<String> getAvailableNameplateDisplayNames(@NotNull Player player);
|
||||
|
||||
TeamColor getTeamColor(Player player);
|
||||
/**
|
||||
* Get the nameplate's team color
|
||||
*
|
||||
* @param player player
|
||||
* @return team color
|
||||
*/
|
||||
@NotNull
|
||||
TeamColor getTeamColor(@NotNull Player player);
|
||||
|
||||
/**
|
||||
* Get team tag manager
|
||||
*/
|
||||
@NotNull
|
||||
TeamTagManager getTeamTagManager();
|
||||
|
||||
/**
|
||||
* Get unlimited tag manager
|
||||
*/
|
||||
@NotNull
|
||||
UnlimitedTagManager getUnlimitedTagManager();
|
||||
}
|
||||
@@ -44,6 +44,11 @@ public interface PlaceholderManager {
|
||||
@Nullable
|
||||
StaticText getStaticText(String key);
|
||||
|
||||
/**
|
||||
* Get all the static texts
|
||||
*
|
||||
* @return static texts
|
||||
*/
|
||||
Collection<StaticText> getStaticTexts();
|
||||
|
||||
/**
|
||||
@@ -55,6 +60,11 @@ public interface PlaceholderManager {
|
||||
@Nullable
|
||||
SwitchText getSwitchText(String key);
|
||||
|
||||
/**
|
||||
* Get all the switch texts
|
||||
*
|
||||
* @return switch texts
|
||||
*/
|
||||
Collection<SwitchText> getSwitchTexts();
|
||||
|
||||
/**
|
||||
@@ -66,6 +76,11 @@ public interface PlaceholderManager {
|
||||
@Nullable
|
||||
DescentText getDescentText(String key);
|
||||
|
||||
/**
|
||||
* Get all the descent texts
|
||||
*
|
||||
* @return descent texts
|
||||
*/
|
||||
Collection<DescentText> getDescentTexts();
|
||||
|
||||
/**
|
||||
@@ -77,6 +92,11 @@ public interface PlaceholderManager {
|
||||
@Nullable
|
||||
ConditionalText getConditionalText(String key);
|
||||
|
||||
/**
|
||||
* Get all the conditional texts
|
||||
*
|
||||
* @return conditional texts
|
||||
*/
|
||||
Collection<ConditionalText> getConditionalTexts();
|
||||
|
||||
/**
|
||||
@@ -88,6 +108,11 @@ public interface PlaceholderManager {
|
||||
@Nullable
|
||||
NameplateText getNameplateText(String key);
|
||||
|
||||
/**
|
||||
* Get all the nameplate texts
|
||||
*
|
||||
* @return nameplate texts
|
||||
*/
|
||||
Collection<NameplateText> getNameplateTexts();
|
||||
|
||||
/**
|
||||
@@ -99,9 +124,25 @@ public interface PlaceholderManager {
|
||||
@Nullable
|
||||
BackGroundText getBackGroundText(String key);
|
||||
|
||||
/**
|
||||
* Get all the background texts
|
||||
*
|
||||
* @return background texts
|
||||
*/
|
||||
Collection<BackGroundText> getBackGroundTexts();
|
||||
|
||||
/**
|
||||
* Get a vanilla hud
|
||||
*
|
||||
* @param key key
|
||||
* @return vanilla hud
|
||||
*/
|
||||
VanillaHud getVanillaHud(String key);
|
||||
|
||||
/**
|
||||
* Get all the vanilla huds
|
||||
*
|
||||
* @return vanilla huds
|
||||
*/
|
||||
Collection<VanillaHud> getVanillaHuds();
|
||||
}
|
||||
@@ -26,5 +26,10 @@ public interface ResourcePackManager {
|
||||
*/
|
||||
void generateResourcePack();
|
||||
|
||||
/**
|
||||
* Delete a directory
|
||||
*
|
||||
* @param file file
|
||||
*/
|
||||
void deleteDirectory(File file);
|
||||
}
|
||||
@@ -46,7 +46,8 @@ public interface TeamManager {
|
||||
* Get the team player in
|
||||
*
|
||||
* @param player player
|
||||
* @param viewer viewer
|
||||
* @return team name
|
||||
*/
|
||||
String getTeamName(Player player);
|
||||
String getTeamName(Player player, Player viewer);
|
||||
}
|
||||
@@ -19,6 +19,7 @@ package net.momirealms.customnameplates.api.manager;
|
||||
|
||||
import net.momirealms.customnameplates.api.mechanic.tag.team.TeamTagPlayer;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.UUID;
|
||||
@@ -32,7 +33,7 @@ public interface TeamTagManager {
|
||||
*
|
||||
* @return team tag
|
||||
*/
|
||||
@Nullable
|
||||
@NotNull
|
||||
TeamTagPlayer createTagForPlayer(Player player, String prefix, String suffix);
|
||||
|
||||
/**
|
||||
|
||||
+20
-2
@@ -24,6 +24,14 @@ import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public interface UnlimitedTagManager {
|
||||
|
||||
/**
|
||||
* Create a named entity (ArmorStand) for an entity
|
||||
* To apply the changes, you should add it to the EntityTagEntity
|
||||
*
|
||||
* @param entity entity
|
||||
* @param setting setting
|
||||
* @return named entity
|
||||
*/
|
||||
@NotNull StaticTextEntity createNamedEntity(EntityTagEntity entity, StaticTextTagSetting setting);
|
||||
|
||||
/**
|
||||
@@ -37,9 +45,19 @@ public interface UnlimitedTagManager {
|
||||
@NotNull
|
||||
DynamicTextEntity createNamedEntity(EntityTagPlayer player, DynamicTextTagSetting setting);
|
||||
|
||||
/**
|
||||
* Create or get a tag instance
|
||||
*
|
||||
* @param entity entity
|
||||
* @return entity tag instance
|
||||
*/
|
||||
EntityTagEntity createOrGetTagForEntity(Entity entity);
|
||||
|
||||
/**
|
||||
* Create or get a tag instance
|
||||
*
|
||||
* @param player player
|
||||
* @return entity tag instance
|
||||
*/
|
||||
EntityTagPlayer createOrGetTagForPlayer(Player player);
|
||||
|
||||
EntityTagPlayer createOrGetTagForPlayer(Player player, boolean manageTeam);
|
||||
}
|
||||
@@ -17,18 +17,52 @@
|
||||
|
||||
package net.momirealms.customnameplates.api.manager;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.concurrent.CompletionStage;
|
||||
|
||||
public interface VersionManager {
|
||||
|
||||
/**
|
||||
* Is folia scheduler implemented
|
||||
*/
|
||||
boolean isFolia();
|
||||
|
||||
String getServerVersion();
|
||||
|
||||
/**
|
||||
* Check update
|
||||
*
|
||||
* @return return true if plugin needs update
|
||||
*/
|
||||
CompletionStage<Boolean> checkUpdate();
|
||||
|
||||
boolean isVersionNewerThan1_20_5();
|
||||
|
||||
/**
|
||||
* Get plugin version
|
||||
*
|
||||
* @return version
|
||||
*/
|
||||
@NotNull
|
||||
String getPluginVersion();
|
||||
|
||||
/**
|
||||
* Is the plugin the latest version
|
||||
*
|
||||
* @return latest or not
|
||||
*/
|
||||
boolean isLatest();
|
||||
|
||||
/**
|
||||
* Get pack format
|
||||
*
|
||||
* @return pack format
|
||||
*/
|
||||
int getPackFormat();
|
||||
|
||||
boolean isVersionNewerThan1_19();
|
||||
|
||||
boolean isMojmap();
|
||||
|
||||
boolean isVersionNewerThan1_19_R2();
|
||||
|
||||
boolean isVersionNewerThan1_19_R3();
|
||||
@@ -36,11 +70,4 @@ public interface VersionManager {
|
||||
boolean isVersionNewerThan1_20();
|
||||
|
||||
boolean isVersionNewerThan1_20_R2();
|
||||
|
||||
String getPluginVersion();
|
||||
|
||||
boolean isLatest();
|
||||
|
||||
int getPackFormat();
|
||||
|
||||
}
|
||||
@@ -19,15 +19,43 @@ package net.momirealms.customnameplates.api.manager;
|
||||
|
||||
import net.momirealms.customnameplates.api.mechanic.font.FontData;
|
||||
import net.momirealms.customnameplates.common.Key;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public interface WidthManager {
|
||||
|
||||
boolean registerFontData(Key key, FontData fontData);
|
||||
/**
|
||||
* Register a font data into the plugin
|
||||
* If there already exists one, it would fail
|
||||
*
|
||||
* @param key key
|
||||
* @param fontData data
|
||||
* @return success or not
|
||||
*/
|
||||
boolean registerFontData(@NotNull Key key, @NotNull FontData fontData);
|
||||
|
||||
boolean unregisterFontData(Key key);
|
||||
/**
|
||||
* Unregister a font data from map
|
||||
*
|
||||
* @param key key
|
||||
* @return success or not
|
||||
*/
|
||||
boolean unregisterFontData(@NotNull Key key);
|
||||
|
||||
@Nullable FontData getFontData(Key key);
|
||||
/**
|
||||
* Get font data by key
|
||||
*
|
||||
* @param key key
|
||||
* @return font data
|
||||
*/
|
||||
@Nullable
|
||||
FontData getFontData(@NotNull Key key);
|
||||
|
||||
int getTextWidth(String textWithTags);
|
||||
/**
|
||||
* Get text's width (MiniMessage format text)
|
||||
*
|
||||
* @param textWithTags text
|
||||
* @return width
|
||||
*/
|
||||
int getTextWidth(@NotNull String textWithTags);
|
||||
}
|
||||
+5
-3
@@ -15,9 +15,11 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package net.momirealms.customnameplates.paper.mechanic.team;
|
||||
|
||||
public interface Team {
|
||||
package net.momirealms.customnameplates.api.mechanic.bubble;
|
||||
|
||||
public enum ChannelMode {
|
||||
|
||||
ALL,
|
||||
JOINED,
|
||||
CAN_JOIN
|
||||
}
|
||||
+16
-5
@@ -15,16 +15,27 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package net.momirealms.customnameplates.paper.mechanic.bubble.listener;
|
||||
package net.momirealms.customnameplates.api.mechanic.bubble.provider;
|
||||
|
||||
import net.momirealms.customnameplates.paper.mechanic.bubble.BubbleManagerImpl;
|
||||
import net.momirealms.customnameplates.api.manager.BubbleManager;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.Listener;
|
||||
|
||||
public abstract class AbstractChatListener implements Listener {
|
||||
public abstract class AbstractChatProvider implements Listener {
|
||||
|
||||
protected BubbleManagerImpl chatBubblesManager;
|
||||
protected BubbleManager chatBubblesManager;
|
||||
|
||||
public AbstractChatListener(BubbleManagerImpl chatBubblesManager) {
|
||||
public AbstractChatProvider(BubbleManager chatBubblesManager) {
|
||||
this.chatBubblesManager = chatBubblesManager;
|
||||
}
|
||||
|
||||
public abstract void register();
|
||||
|
||||
public abstract void unregister();
|
||||
|
||||
public abstract boolean hasJoinedChannel(Player player, String channelID);
|
||||
|
||||
public abstract boolean canJoinChannel(Player player, String channelID);
|
||||
|
||||
public abstract boolean isIgnoring(Player sender, Player receiver);
|
||||
}
|
||||
+15
@@ -25,17 +25,32 @@ public class CharacterArranger {
|
||||
currentChar = (char) (currentChar + '\u0001');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get and increase the char arranged automatically by the plugin
|
||||
*
|
||||
* @return char
|
||||
*/
|
||||
public static char getAndIncrease() {
|
||||
char temp = currentChar;
|
||||
increase();
|
||||
return temp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Increase and get the char arranged automatically by the plugin
|
||||
*
|
||||
* @return char
|
||||
*/
|
||||
public static char increaseAndGet() {
|
||||
increase();
|
||||
return currentChar;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the initial char
|
||||
*
|
||||
* @param c char
|
||||
*/
|
||||
public static void reset(char c) {
|
||||
currentChar = c;
|
||||
}
|
||||
|
||||
@@ -29,18 +29,40 @@ public class FontData {
|
||||
this.defaultWidth = defaultWidth;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a char's width
|
||||
*
|
||||
* @param codePoint code point
|
||||
* @param width width
|
||||
*/
|
||||
public void registerCharWidth(int codePoint, int width) {
|
||||
widthData.put(codePoint, width);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a character's width
|
||||
*
|
||||
* @param codePoint code point
|
||||
* @return width
|
||||
*/
|
||||
public int getWidth(int codePoint) {
|
||||
return widthData.getOrDefault(codePoint, defaultWidth);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the data map
|
||||
*
|
||||
* @return map
|
||||
*/
|
||||
public HashMap<Integer, Integer> getWidthData() {
|
||||
return widthData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Override the data with another one
|
||||
*
|
||||
* @param fontData font data
|
||||
*/
|
||||
public void overrideWith(FontData fontData) {
|
||||
if (fontData == null) return;
|
||||
widthData.putAll(fontData.getWidthData());
|
||||
|
||||
@@ -66,6 +66,12 @@ public enum OffsetFont {
|
||||
return this.height;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get offset characters
|
||||
*
|
||||
* @param offset offset
|
||||
* @return chars
|
||||
*/
|
||||
public static String getOffsetChars(int offset) {
|
||||
if (offset >= 0) {
|
||||
return getShortestPosChars(offset);
|
||||
@@ -74,6 +80,12 @@ public enum OffsetFont {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* get negative characters
|
||||
*
|
||||
* @param n n > 0
|
||||
* @return chars
|
||||
*/
|
||||
public static String getShortestNegChars(int n) {
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
while (n >= 128) {
|
||||
@@ -126,6 +138,12 @@ public enum OffsetFont {
|
||||
return stringBuilder.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* get positive characters
|
||||
*
|
||||
* @param n n > 0
|
||||
* @return chars
|
||||
*/
|
||||
public static String getShortestPosChars(int n) {
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
while (n >= 128) {
|
||||
|
||||
+15
-5
@@ -44,9 +44,11 @@ public class ViewerText {
|
||||
for (String placeholder : placeholders) {
|
||||
processedText = processedText.replace(placeholder, "%s");
|
||||
if (placeholder.startsWith("%viewer_")) {
|
||||
this.placeholders[i] = new ClaimedText(null, "%" + placeholder.substring("%viewer_".length()));
|
||||
this.placeholders[i] = new ClaimedText(null, "%" + placeholder.substring("%viewer_".length()), false);
|
||||
} else if (placeholder.startsWith("%rel_")) {
|
||||
this.placeholders[i] = new ClaimedText(owner, placeholder, true);
|
||||
} else {
|
||||
this.placeholders[i] = new ClaimedText(owner, placeholder);
|
||||
this.placeholders[i] = new ClaimedText(owner, placeholder, false);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
@@ -109,23 +111,31 @@ public class ViewerText {
|
||||
private final String placeholder;
|
||||
private final Player owner;
|
||||
private String latestValue;
|
||||
private final boolean relational;
|
||||
|
||||
public ClaimedText(Player owner, String placeholder) {
|
||||
public ClaimedText(Player owner, String placeholder, boolean relational) {
|
||||
this.placeholder = placeholder;
|
||||
this.owner = owner;
|
||||
this.latestValue = null;
|
||||
this.relational = relational;
|
||||
this.update();
|
||||
}
|
||||
|
||||
public void update() {
|
||||
if (owner == null) return;
|
||||
if (owner == null || relational) return;
|
||||
this.latestValue = PlaceholderAPI.setPlaceholders(owner, placeholder);
|
||||
}
|
||||
|
||||
public String getValue(Player viewer) {
|
||||
return Objects.requireNonNullElseGet(
|
||||
latestValue,
|
||||
() -> PlaceholderAPI.setPlaceholders(owner == null ? viewer : owner, placeholder)
|
||||
() -> {
|
||||
if (relational) {
|
||||
return PlaceholderAPI.setRelationalPlaceholders(viewer, owner, placeholder);
|
||||
} else {
|
||||
return PlaceholderAPI.setPlaceholders(owner == null ? viewer : owner, placeholder);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
+3
-3
@@ -18,7 +18,7 @@
|
||||
package net.momirealms.customnameplates.api.mechanic.placeholder;
|
||||
|
||||
import me.clip.placeholderapi.PlaceholderAPI;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
@@ -41,9 +41,9 @@ public class SwitchText {
|
||||
this.toParse = toParse;
|
||||
}
|
||||
|
||||
public String getValue(Player player) {
|
||||
public String getValue(OfflinePlayer player) {
|
||||
String parsed = PlaceholderAPI.setPlaceholders(player, toParse);
|
||||
return valueMap.getOrDefault(parsed, defaultValue);
|
||||
return PlaceholderAPI.setPlaceholders(player, valueMap.getOrDefault(parsed, defaultValue));
|
||||
}
|
||||
|
||||
public static class Builder {
|
||||
|
||||
-2
@@ -18,12 +18,10 @@
|
||||
package net.momirealms.customnameplates.api.mechanic.placeholder;
|
||||
|
||||
import me.clip.placeholderapi.PlaceholderAPI;
|
||||
import net.momirealms.customnameplates.api.CustomNameplatesPlugin;
|
||||
import net.momirealms.customnameplates.api.mechanic.font.OffsetFont;
|
||||
import net.momirealms.customnameplates.api.util.FontUtils;
|
||||
import net.momirealms.customnameplates.api.util.LogUtils;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public class VanillaHud {
|
||||
|
||||
|
||||
+24
@@ -21,13 +21,37 @@ import net.momirealms.customnameplates.api.mechanic.misc.ViewerText;
|
||||
import net.momirealms.customnameplates.api.mechanic.tag.NameplatePlayer;
|
||||
|
||||
public interface TeamTagPlayer extends NameplatePlayer {
|
||||
|
||||
/**
|
||||
* Set a player's prefix
|
||||
*
|
||||
* @param prefix prefix
|
||||
*/
|
||||
void setPrefix(String prefix);
|
||||
|
||||
/**
|
||||
* Set a player's suffix
|
||||
*
|
||||
* @param suffix suffix
|
||||
*/
|
||||
void setSuffix(String suffix);
|
||||
|
||||
/**
|
||||
* Get a player's prefix
|
||||
*
|
||||
* @return prefix
|
||||
*/
|
||||
ViewerText getPrefix();
|
||||
|
||||
/**
|
||||
* Get a player's suffix
|
||||
*
|
||||
* @return suffix
|
||||
*/
|
||||
ViewerText getSuffix();
|
||||
|
||||
/**
|
||||
* Destroy the tag
|
||||
*/
|
||||
void destroy();
|
||||
}
|
||||
+2
@@ -49,6 +49,8 @@ public interface DynamicTextEntity {
|
||||
|
||||
void setSneak(boolean sneaking, boolean respawn);
|
||||
|
||||
void updateVisibility();
|
||||
|
||||
void removePlayerFromViewers(Player player);
|
||||
|
||||
void addPlayerToViewers(Player player);
|
||||
|
||||
+2
-2
@@ -20,7 +20,7 @@ package net.momirealms.customnameplates.api.mechanic.tag.unlimited;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.Vector;
|
||||
import java.util.Collection;
|
||||
|
||||
public interface EntityTagEntity {
|
||||
|
||||
@@ -30,7 +30,7 @@ public interface EntityTagEntity {
|
||||
|
||||
void removeTag(StaticTextEntity tag);
|
||||
|
||||
Vector<StaticTextEntity> getStaticTags();
|
||||
Collection<StaticTextEntity> getStaticTags();
|
||||
|
||||
void forceAddNearbyPlayer(Player player);
|
||||
|
||||
|
||||
+3
-5
@@ -19,7 +19,7 @@ package net.momirealms.customnameplates.api.mechanic.tag.unlimited;
|
||||
|
||||
import net.momirealms.customnameplates.api.mechanic.tag.NameplatePlayer;
|
||||
|
||||
import java.util.Vector;
|
||||
import java.util.Collection;
|
||||
|
||||
public interface EntityTagPlayer extends NameplatePlayer {
|
||||
|
||||
@@ -35,14 +35,12 @@ public interface EntityTagPlayer extends NameplatePlayer {
|
||||
|
||||
void removeTag(StaticTextEntity tag);
|
||||
|
||||
Vector<DynamicTextEntity> getDynamicTags();
|
||||
Collection<DynamicTextEntity> getDynamicTags();
|
||||
|
||||
Vector<StaticTextEntity> getStaticTags();
|
||||
Collection<StaticTextEntity> getStaticTags();
|
||||
|
||||
void setHatOffset(double hatOffset);
|
||||
|
||||
void setManageTeams(boolean manageTeams);
|
||||
|
||||
double getHatOffset();
|
||||
|
||||
void destroy();
|
||||
|
||||
+3
-1
@@ -24,7 +24,7 @@ import java.util.UUID;
|
||||
|
||||
public interface StaticTextEntity {
|
||||
|
||||
String getPlugin();
|
||||
String getID();
|
||||
|
||||
boolean isShownTo(Player viewer);
|
||||
|
||||
@@ -73,4 +73,6 @@ public interface StaticTextEntity {
|
||||
UUID getUUID();
|
||||
|
||||
void handlePose(Pose previous, Pose pose);
|
||||
|
||||
void setSneak(boolean sneaking, boolean onGround);
|
||||
}
|
||||
+8
-8
@@ -24,14 +24,14 @@ public class StaticTextTagSetting {
|
||||
private NearbyRule comeRule;
|
||||
private NearbyRule leaveRule;
|
||||
private String defaultText;
|
||||
private String plugin;
|
||||
private String id;
|
||||
|
||||
public StaticTextTagSetting(double verticalOffset, NearbyRule comeRule, NearbyRule leaveRule, String defaultText, String plugin) {
|
||||
public StaticTextTagSetting(double verticalOffset, NearbyRule comeRule, NearbyRule leaveRule, String defaultText, String id) {
|
||||
this.verticalOffset = verticalOffset;
|
||||
this.comeRule = comeRule;
|
||||
this.leaveRule = leaveRule;
|
||||
this.defaultText = defaultText;
|
||||
this.plugin = plugin;
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
private StaticTextTagSetting() {
|
||||
@@ -39,7 +39,7 @@ public class StaticTextTagSetting {
|
||||
comeRule = (player, entity) -> true;
|
||||
leaveRule = (player, entity) -> true;
|
||||
defaultText = "";
|
||||
plugin = "";
|
||||
id = "";
|
||||
}
|
||||
|
||||
public static Builder builder() {
|
||||
@@ -78,8 +78,8 @@ public class StaticTextTagSetting {
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder plugin(String type) {
|
||||
this.setting.plugin = type;
|
||||
public Builder id(String id) {
|
||||
this.setting.id = id;
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -100,8 +100,8 @@ public class StaticTextTagSetting {
|
||||
return defaultText;
|
||||
}
|
||||
|
||||
public String getPlugin() {
|
||||
return plugin;
|
||||
public String getID() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public NearbyRule getLeaveRule() {
|
||||
|
||||
@@ -21,7 +21,11 @@ import org.bukkit.OfflinePlayer;
|
||||
|
||||
public class Condition {
|
||||
|
||||
private final OfflinePlayer player;
|
||||
private OfflinePlayer player;
|
||||
|
||||
public Condition() {
|
||||
this.player = null;
|
||||
}
|
||||
|
||||
public Condition(OfflinePlayer player) {
|
||||
this.player = player;
|
||||
@@ -30,4 +34,26 @@ public class Condition {
|
||||
public OfflinePlayer getOfflinePlayer() {
|
||||
return player;
|
||||
}
|
||||
|
||||
public static Builder builder() {
|
||||
return new Builder();
|
||||
}
|
||||
|
||||
public static class Builder {
|
||||
|
||||
private final Condition condition;
|
||||
|
||||
public Builder() {
|
||||
this.condition = new Condition();
|
||||
}
|
||||
|
||||
public Builder player(OfflinePlayer player) {
|
||||
condition.player = player;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Condition build() {
|
||||
return condition;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -22,6 +22,13 @@ import org.bukkit.entity.Entity;
|
||||
|
||||
public class LocationUtils {
|
||||
|
||||
/**
|
||||
* Get distance by two entities
|
||||
*
|
||||
* @param e1 entity
|
||||
* @param e2 entity
|
||||
* @return distance
|
||||
*/
|
||||
public static double getDistance(Entity e1, Entity e2) {
|
||||
Location loc1 = e1.getLocation();
|
||||
Location loc2 = e2.getLocation();
|
||||
|
||||
+6
-4
@@ -2,17 +2,17 @@ plugins {
|
||||
id("java")
|
||||
id("application")
|
||||
id("maven-publish")
|
||||
id("com.github.johnrengelman.shadow") version "8.1.1"
|
||||
id("io.github.goooler.shadow") version "8.1.7"
|
||||
}
|
||||
|
||||
allprojects {
|
||||
|
||||
version = "2.3.0.0"
|
||||
version = "2.4.7"
|
||||
|
||||
apply<JavaPlugin>()
|
||||
apply(plugin = "java")
|
||||
apply(plugin = "application")
|
||||
apply(plugin = "com.github.johnrengelman.shadow")
|
||||
apply(plugin = "io.github.goooler.shadow")
|
||||
apply(plugin = "org.gradle.maven-publish")
|
||||
|
||||
application {
|
||||
@@ -20,8 +20,8 @@ allprojects {
|
||||
}
|
||||
|
||||
repositories {
|
||||
maven("https://maven.aliyun.com/repository/public/")
|
||||
mavenCentral()
|
||||
maven("https://maven.aliyun.com/repository/public/")
|
||||
maven("https://papermc.io/repo/repository/maven-public/")
|
||||
maven("https://oss.sonatype.org/content/groups/public/")
|
||||
maven("https://repo.dmulloy2.net/repository/public/")
|
||||
@@ -43,6 +43,8 @@ allprojects {
|
||||
maven("https://repo.kryptonmc.org/releases")
|
||||
maven("https://repo.oraxen.com/releases/")
|
||||
maven("https://nexus.codecrafter47.de/content/repositories/public/")
|
||||
maven("https://repo.opencollab.dev/main/")
|
||||
maven("https://repo.md-5.net/content/groups/public/")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -10,10 +10,10 @@ dependencies {
|
||||
compileOnly("net.md-5:bungeecord-event:1.20-R0.2-SNAPSHOT")
|
||||
compileOnly("net.md-5:bungeecord-proxy:1.20-R0.2-SNAPSHOT")
|
||||
|
||||
implementation("net.kyori:adventure-api:4.15.0")
|
||||
implementation("net.kyori:adventure-api:4.16.0")
|
||||
implementation("net.kyori:adventure-platform-bungeecord:4.3.2")
|
||||
implementation("net.kyori:adventure-text-minimessage:4.15.0")
|
||||
implementation("net.kyori:adventure-text-serializer-legacy:4.15.0")
|
||||
implementation("net.kyori:adventure-text-minimessage:4.16.0")
|
||||
implementation("net.kyori:adventure-text-serializer-legacy:4.16.0")
|
||||
}
|
||||
|
||||
tasks {
|
||||
|
||||
-1
@@ -30,7 +30,6 @@ public class CustomNameplatesBungeeCord extends Plugin implements Listener {
|
||||
instance = this;
|
||||
this.getProxy().registerChannel(CHANNEL);
|
||||
this.getProxy().getPluginManager().registerListener(this, this);
|
||||
this.getLogger().warning("It's not necessary to install the plugin on BungeeCord now!");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
name: CustomNameplates
|
||||
main: net.momirealms.customnameplates.bungeecord.CustomNameplatesBungeeCord
|
||||
version: '${version}'
|
||||
author: XiaoMoMi
|
||||
softDepends: [TAB, BungeeTabListPlus]
|
||||
author: XiaoMoMi
|
||||
@@ -1,8 +0,0 @@
|
||||
#systemProp.socks.proxyHost=127.0.0.1
|
||||
#systemProp.socks.proxyPort=7890
|
||||
#
|
||||
#systemProp.http.proxyHost=127.0.0.1
|
||||
#systemProp.http.proxyPort=7890
|
||||
#
|
||||
#systemProp.https.proxyHost=127.0.0.1
|
||||
#systemProp.https.proxyPort=7890
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-bin.zip
|
||||
networkTimeout=10000
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
|
||||
+27
-18
@@ -3,16 +3,19 @@ dependencies {
|
||||
compileOnly("dev.folia:folia-api:1.20.1-R0.1-SNAPSHOT")
|
||||
|
||||
// command
|
||||
compileOnly("dev.jorel:commandapi-bukkit-core:9.3.0")
|
||||
compileOnly("dev.jorel:commandapi-bukkit-core:9.5.3")
|
||||
|
||||
// packet
|
||||
compileOnly("com.comphenix.protocol:ProtocolLib:5.2.0-SNAPSHOT")
|
||||
|
||||
// papi
|
||||
compileOnly("me.clip:placeholderapi:2.11.5")
|
||||
compileOnly("me.clip:placeholderapi:2.11.6")
|
||||
|
||||
// config
|
||||
compileOnly("dev.dejvokep:boosted-yaml:1.3.1")
|
||||
compileOnly("dev.dejvokep:boosted-yaml:1.3.6")
|
||||
|
||||
// bStats
|
||||
compileOnly("org.bstats:bstats-bukkit:3.0.2")
|
||||
|
||||
// team
|
||||
compileOnly("me.neznamy:tab-api:4.0.2")
|
||||
@@ -22,44 +25,50 @@ dependencies {
|
||||
compileOnly("com.google.code.gson:gson:2.10.1")
|
||||
|
||||
// database
|
||||
compileOnly("org.xerial:sqlite-jdbc:3.43.0.0")
|
||||
compileOnly("org.xerial:sqlite-jdbc:3.45.3.0")
|
||||
compileOnly("com.h2database:h2:2.2.224")
|
||||
compileOnly("org.mongodb:mongodb-driver-sync:4.11.1")
|
||||
compileOnly("org.mongodb:mongodb-driver-sync:5.0.1")
|
||||
compileOnly("com.zaxxer:HikariCP:5.0.1")
|
||||
compileOnly("redis.clients:jedis:5.1.0")
|
||||
compileOnly("redis.clients:jedis:5.1.3")
|
||||
|
||||
// others
|
||||
compileOnly("com.github.LoneDev6:api-itemsadder:3.5.0c-r5")
|
||||
compileOnly("io.th0rgal:oraxen:1.165.0")
|
||||
compileOnly("com.github.FrancoBM12:API-MagicCosmetics:2.2.5")
|
||||
compileOnly("commons-io:commons-io:2.15.1")
|
||||
|
||||
compileOnly("org.geysermc.geyser:api:2.2.0-SNAPSHOT")
|
||||
compileOnly("LibsDisguises:LibsDisguises:10.0.42")
|
||||
|
||||
// chat channels
|
||||
compileOnly(files("libs/VentureChat-3.7.1.jar"))
|
||||
compileOnly(files("libs/TrChat-2.0.11.jar"))
|
||||
compileOnly(files("libs/carbonchat-paper-3.0.0-beta.26.jar"))
|
||||
compileOnly(files("libs/AdvancedChat-1.3.7.jar"))
|
||||
compileOnly("net.william278:huskchat:2.7.1")
|
||||
|
||||
// api module
|
||||
implementation(project(":api"))
|
||||
implementation(project(":common"))
|
||||
implementation("com.github.Xiao-MoMi:Sparrow-Heart:0.35")
|
||||
|
||||
// adventure
|
||||
implementation("net.kyori:adventure-api:4.15.0")
|
||||
implementation("net.kyori:adventure-platform-bukkit:4.3.2")
|
||||
implementation("net.kyori:adventure-text-minimessage:4.15.0")
|
||||
implementation("net.kyori:adventure-text-serializer-legacy:4.15.0")
|
||||
|
||||
// bStats
|
||||
implementation("org.bstats:bstats-bukkit:3.0.2")
|
||||
|
||||
// local lib
|
||||
implementation(files("libs/BiomeAPI.jar"))
|
||||
implementation("net.kyori:adventure-api:4.17.0")
|
||||
implementation("net.kyori:adventure-platform-bukkit:4.3.3")
|
||||
}
|
||||
|
||||
tasks {
|
||||
shadowJar {
|
||||
relocate ("net.kyori", "net.momirealms.customnameplates.libraries")
|
||||
relocate ("org.bstats", "net.momirealms.customnameplates.libraries.bstats")
|
||||
relocate ("net.momirealms.biomeapi", "net.momirealms.customnameplates.libraries.biomeapi")
|
||||
relocate ("net.momirealms.sparrow.heart", "net.momirealms.customnameplates.libraries.sparrow")
|
||||
relocate ("org.apache.commons.pool2", "net.momirealms.customnameplates.libraries.commonspool2")
|
||||
relocate ("com.mysql", "net.momirealms.customnameplates.libraries.mysql")
|
||||
relocate ("org.mariadb", "net.momirealms.customnameplates.libraries.mariadb")
|
||||
relocate ("com.zaxxer.hikari", "net.momirealms.customnameplates.libraries.hikari")
|
||||
relocate ("redis.clients.jedis", "net.momirealms.customnameplates.libraries.jedis")
|
||||
relocate ("com.mongodb", "net.momirealms.customnameplates.libraries.mongodb")
|
||||
relocate ("org.bson", "net.momirealms.customnameplates.libraries.bson")
|
||||
relocate ("dev.jorel.commandapi", "net.momirealms.customnameplates.libraries.commandapi")
|
||||
relocate ("dev.dejvokep.boostedyaml", "net.momirealms.customnameplates.libraries.boostedyaml")
|
||||
}
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
+40
-26
@@ -22,7 +22,10 @@ import net.momirealms.customnameplates.api.event.CustomNameplatesReloadEvent;
|
||||
import net.momirealms.customnameplates.api.util.LogUtils;
|
||||
import net.momirealms.customnameplates.paper.adventure.AdventureManagerImpl;
|
||||
import net.momirealms.customnameplates.paper.command.CommandManager;
|
||||
import net.momirealms.customnameplates.paper.helper.LibraryLoader;
|
||||
import net.momirealms.customnameplates.paper.libraries.classpath.ReflectionClassPathAppender;
|
||||
import net.momirealms.customnameplates.paper.libraries.dependencies.Dependency;
|
||||
import net.momirealms.customnameplates.paper.libraries.dependencies.DependencyManager;
|
||||
import net.momirealms.customnameplates.paper.libraries.dependencies.DependencyManagerImpl;
|
||||
import net.momirealms.customnameplates.paper.mechanic.actionbar.ActionBarManagerImpl;
|
||||
import net.momirealms.customnameplates.paper.mechanic.background.BackGroundManagerImpl;
|
||||
import net.momirealms.customnameplates.paper.mechanic.bossbar.BossBarManagerImpl;
|
||||
@@ -43,22 +46,47 @@ import net.momirealms.customnameplates.paper.setting.CNLocale;
|
||||
import net.momirealms.customnameplates.paper.storage.StorageManagerImpl;
|
||||
import net.momirealms.customnameplates.paper.util.Migration;
|
||||
import net.momirealms.customnameplates.paper.util.ReflectionUtils;
|
||||
import org.bstats.bukkit.Metrics;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import org.bukkit.event.HandlerList;
|
||||
import org.bukkit.event.Listener;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.TimeZone;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class CustomNameplatesPluginImpl extends CustomNameplatesPlugin implements Listener {
|
||||
|
||||
private CoolDownManager coolDownManager;
|
||||
private PacketManager packetManager;
|
||||
private DependencyManager dependencyManager;
|
||||
|
||||
@Override
|
||||
public void onLoad() {
|
||||
this.loadLibraries();
|
||||
this.versionManager = new VersionManagerImpl(this);
|
||||
this.dependencyManager = new DependencyManagerImpl(this, new ReflectionClassPathAppender(this.getClassLoader()));
|
||||
this.dependencyManager.loadDependencies(new ArrayList<>(
|
||||
List.of(
|
||||
Dependency.GSON,
|
||||
Dependency.SLF4J_API,
|
||||
Dependency.SLF4J_SIMPLE,
|
||||
versionManager.isMojmap() ? Dependency.COMMAND_API_MOJMAP : Dependency.COMMAND_API,
|
||||
Dependency.BOOSTED_YAML,
|
||||
Dependency.MYSQL_DRIVER,
|
||||
Dependency.MARIADB_DRIVER,
|
||||
Dependency.MONGODB_DRIVER_SYNC,
|
||||
Dependency.MONGODB_DRIVER_CORE,
|
||||
Dependency.MONGODB_DRIVER_BSON,
|
||||
Dependency.JEDIS,
|
||||
Dependency.COMMONS_POOL_2,
|
||||
Dependency.H2_DRIVER,
|
||||
Dependency.SQLITE_DRIVER,
|
||||
Dependency.BSTATS_BASE,
|
||||
Dependency.HIKARI,
|
||||
Dependency.BSTATS_BUKKIT
|
||||
)
|
||||
));
|
||||
ReflectionUtils.load();
|
||||
}
|
||||
|
||||
@@ -70,7 +98,6 @@ public class CustomNameplatesPluginImpl extends CustomNameplatesPlugin implement
|
||||
return;
|
||||
}
|
||||
this.adventureManager = new AdventureManagerImpl(this);
|
||||
this.versionManager = new VersionManagerImpl(this);
|
||||
this.scheduler = new SchedulerImpl(this);
|
||||
this.storageManager = new StorageManagerImpl(this);
|
||||
this.requirementManager = new RequirementManagerImpl(this);
|
||||
@@ -93,6 +120,10 @@ public class CustomNameplatesPluginImpl extends CustomNameplatesPlugin implement
|
||||
else this.getAdventure().sendConsoleMessage("[CustomNameplates] Update is available: <u>https://polymart.org/resource/2543<!u>");
|
||||
});
|
||||
this.getServer().getPluginManager().registerEvents((VersionManagerImpl) versionManager, this);
|
||||
if (CNConfig.generatePackOnStart)
|
||||
this.resourcePackManager.generateResourcePack();
|
||||
if (CNConfig.metrics)
|
||||
new Metrics(this, 16649);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -100,7 +131,7 @@ public class CustomNameplatesPluginImpl extends CustomNameplatesPlugin implement
|
||||
if (scheduler != null) ((SchedulerImpl) this.scheduler).shutdown();
|
||||
if (actionBarManager != null) ((ActionBarManagerImpl) actionBarManager).unload();
|
||||
if (nameplateManager != null) ((NameplateManagerImpl) this.nameplateManager).disable();
|
||||
if (teamManager != null) ((TeamManagerImpl) this.teamManager).unload();
|
||||
if (teamManager != null) ((TeamManagerImpl) this.teamManager).disable();
|
||||
if (bossBarManager != null) ((BossBarManagerImpl) this.bossBarManager).unload();
|
||||
if (imageManager != null) ((ImageManagerImpl) this.imageManager).unload();
|
||||
if (backGroundManager != null) ((BackGroundManagerImpl) this.backGroundManager).unload();
|
||||
@@ -150,27 +181,6 @@ public class CustomNameplatesPluginImpl extends CustomNameplatesPlugin implement
|
||||
}
|
||||
}
|
||||
|
||||
private void loadLibraries() {
|
||||
String mavenRepo = TimeZone.getDefault().getID().startsWith("Asia") ?
|
||||
"https://maven.aliyun.com/repository/public/" : "https://repo.maven.apache.org/maven2/";
|
||||
LibraryLoader.loadDependencies(
|
||||
"org.apache.commons:commons-pool2:2.12.0", mavenRepo,
|
||||
"redis.clients:jedis:5.1.0", mavenRepo,
|
||||
"dev.dejvokep:boosted-yaml:1.3.1", mavenRepo,
|
||||
"com.zaxxer:HikariCP:5.0.1", mavenRepo,
|
||||
"org.mariadb.jdbc:mariadb-java-client:3.3.0", mavenRepo,
|
||||
"com.mysql:mysql-connector-j:8.2.0", mavenRepo,
|
||||
"commons-io:commons-io:2.15.1", mavenRepo,
|
||||
"com.google.code.gson:gson:2.10.1", mavenRepo,
|
||||
"com.h2database:h2:2.2.224", mavenRepo,
|
||||
"org.mongodb:mongodb-driver-sync:4.11.1", mavenRepo,
|
||||
"org.mongodb:mongodb-driver-core:4.11.1", mavenRepo,
|
||||
"org.mongodb:bson:4.11.1", mavenRepo,
|
||||
"org.xerial:sqlite-jdbc:3.43.2.2", mavenRepo,
|
||||
"dev.jorel:commandapi-bukkit-shade:9.3.0", mavenRepo
|
||||
);
|
||||
}
|
||||
|
||||
public CoolDownManager getCoolDownManager() {
|
||||
return coolDownManager;
|
||||
}
|
||||
@@ -178,4 +188,8 @@ public class CustomNameplatesPluginImpl extends CustomNameplatesPlugin implement
|
||||
public PacketManager getPacketManager() {
|
||||
return packetManager;
|
||||
}
|
||||
|
||||
public DependencyManager getDependencyManager() {
|
||||
return dependencyManager;
|
||||
}
|
||||
}
|
||||
+19
-16
@@ -19,7 +19,6 @@ package net.momirealms.customnameplates.paper.adventure;
|
||||
|
||||
import com.comphenix.protocol.PacketType;
|
||||
import com.comphenix.protocol.events.PacketContainer;
|
||||
import com.comphenix.protocol.wrappers.WrappedChatComponent;
|
||||
import com.google.common.cache.CacheBuilder;
|
||||
import com.google.common.cache.CacheLoader;
|
||||
import com.google.common.cache.LoadingCache;
|
||||
@@ -75,8 +74,8 @@ public class AdventureManagerImpl implements AdventureManager {
|
||||
this.cacheSystem = new CacheSystem(CNConfig.cacheSize);
|
||||
}
|
||||
|
||||
public WrappedChatComponent getWrappedChatComponentFromMiniMessage(String text) {
|
||||
return cacheSystem.getWrappedChatComponentFromCache(text);
|
||||
public String getJsonComponentFromMiniMessage(String text) {
|
||||
return cacheSystem.getJsonComponentFromCache(text);
|
||||
}
|
||||
|
||||
public Object getIChatComponentFromMiniMessage(String text) {
|
||||
@@ -195,12 +194,12 @@ public class AdventureManagerImpl implements AdventureManager {
|
||||
case 'd' -> stringBuilder.append("<light_purple>");
|
||||
case 'e' -> stringBuilder.append("<yellow>");
|
||||
case 'f' -> stringBuilder.append("<white>");
|
||||
case 'r' -> stringBuilder.append("<r><!i>");
|
||||
case 'r' -> stringBuilder.append("<reset>");
|
||||
case 'l' -> stringBuilder.append("<b>");
|
||||
case 'm' -> stringBuilder.append("<s>");
|
||||
case 'm' -> stringBuilder.append("<st>");
|
||||
case 'o' -> stringBuilder.append("<i>");
|
||||
case 'n' -> stringBuilder.append("<u>");
|
||||
case 'k' -> stringBuilder.append("<o>");
|
||||
case 'k' -> stringBuilder.append("<obf>");
|
||||
case 'x' -> {
|
||||
if (i + 13 >= chars.length
|
||||
|| !isColorCode(chars[i+2])
|
||||
@@ -286,11 +285,15 @@ public class AdventureManagerImpl implements AdventureManager {
|
||||
}
|
||||
}
|
||||
|
||||
public Audience audience(Player player) {
|
||||
return adventure.player(player);
|
||||
}
|
||||
|
||||
public class CacheSystem {
|
||||
|
||||
private final LoadingCache<String, Object> miniMessageToIChatComponentCache;
|
||||
private final LoadingCache<String, Component> miniMessageToComponentCache;
|
||||
private final LoadingCache<String, WrappedChatComponent> miniMessageToWrappedChatComponentCache;
|
||||
private final LoadingCache<String, String> miniMessageToJsonChatComponentCache;
|
||||
|
||||
public CacheSystem(int size) {
|
||||
miniMessageToIChatComponentCache = CacheBuilder.newBuilder()
|
||||
@@ -315,15 +318,15 @@ public class AdventureManagerImpl implements AdventureManager {
|
||||
return fetchComponent(text);
|
||||
}
|
||||
});
|
||||
miniMessageToWrappedChatComponentCache = CacheBuilder.newBuilder()
|
||||
miniMessageToJsonChatComponentCache = CacheBuilder.newBuilder()
|
||||
.maximumSize(size)
|
||||
.expireAfterWrite(10, TimeUnit.MINUTES)
|
||||
.build(
|
||||
new CacheLoader<>() {
|
||||
@NotNull
|
||||
@Override
|
||||
public WrappedChatComponent load(@NotNull String text) {
|
||||
return fetchWrappedChatComponent(text);
|
||||
public String load(@NotNull String text) {
|
||||
return fetchJsonChatComponent(text);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -349,11 +352,11 @@ public class AdventureManagerImpl implements AdventureManager {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private WrappedChatComponent fetchWrappedChatComponent(String text) {
|
||||
private String fetchJsonChatComponent(String text) {
|
||||
if (CNConfig.legacyColorSupport) {
|
||||
return WrappedChatComponent.fromJson(GsonComponentSerializer.gson().serialize(MiniMessage.miniMessage().deserialize(legacyToMiniMessage(text))));
|
||||
return GsonComponentSerializer.gson().serialize(MiniMessage.miniMessage().deserialize(legacyToMiniMessage(text)));
|
||||
} else {
|
||||
return WrappedChatComponent.fromJson(GsonComponentSerializer.gson().serialize(MiniMessage.miniMessage().deserialize(text)));
|
||||
return GsonComponentSerializer.gson().serialize(MiniMessage.miniMessage().deserialize(text));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -375,12 +378,12 @@ public class AdventureManagerImpl implements AdventureManager {
|
||||
}
|
||||
}
|
||||
|
||||
public WrappedChatComponent getWrappedChatComponentFromCache(String text) {
|
||||
public String getJsonComponentFromCache(String text) {
|
||||
try {
|
||||
return miniMessageToWrappedChatComponentCache.get(text);
|
||||
return miniMessageToJsonChatComponentCache.get(text);
|
||||
} catch (ExecutionException e) {
|
||||
e.printStackTrace();
|
||||
return WrappedChatComponent.fromText("");
|
||||
return "{\"text\":\"\"}";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+27
-12
@@ -107,7 +107,7 @@ public class CommandManager {
|
||||
|
||||
public static CommandAPICommand getListCommand() {
|
||||
return new CommandAPICommand("list")
|
||||
.withPermission("bubbles.list")
|
||||
.withPermission("bubbles.command.list")
|
||||
.executesPlayer((player, args) -> {
|
||||
if (!CNConfig.bubbleModule) return;
|
||||
List<String> bubbles = CustomNameplatesPlugin.get().getBubbleManager().getAvailableBubblesDisplayNames(player);
|
||||
@@ -116,7 +116,7 @@ public class CommandManager {
|
||||
for (String availableBubble : bubbles) {
|
||||
stringJoiner.add(availableBubble);
|
||||
}
|
||||
AdventureManagerImpl.getInstance().sendMessageWithPrefix(player, CNLocale.MSG_AVAILABLE_BUBBLE.replace("{Bubble}", stringJoiner.toString()));
|
||||
AdventureManagerImpl.getInstance().sendMessageWithPrefix(player, CNLocale.MSG_AVAILABLE_BUBBLE.replace("{Bubble}", stringJoiner.toString()).replace("{Bubbles}", stringJoiner.toString()));
|
||||
} else {
|
||||
AdventureManagerImpl.getInstance().sendMessageWithPrefix(player, CNLocale.MSG_HAVE_NO_BUBBLE);
|
||||
}
|
||||
@@ -125,15 +125,22 @@ public class CommandManager {
|
||||
|
||||
public static CommandAPICommand getEquipCommand() {
|
||||
return new CommandAPICommand("equip")
|
||||
.withPermission("bubbles.equip")
|
||||
.withPermission("bubbles.command.equip")
|
||||
.withArguments(new StringArgument("bubble").replaceSuggestions(ArgumentSuggestions.strings(commandSenderSuggestionInfo -> CustomNameplatesPlugin.get().getBubbleManager().getAvailableBubbles((Player) commandSenderSuggestionInfo.sender()).toArray(new String[0]))))
|
||||
.executesPlayer((player, args) -> {
|
||||
if (!CNConfig.bubbleModule) return;
|
||||
String bubble = (String) args.get("bubble");
|
||||
if (!CustomNameplatesPlugin.get().getBubbleManager().equipBubble(player, bubble)) {
|
||||
if (!CustomNameplatesPlugin.get().getBubbleManager().containsBubble(bubble)) {
|
||||
AdventureManagerImpl.getInstance().sendMessageWithPrefix(player, CNLocale.MSG_BUBBLE_NOT_EXIST);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!CustomNameplatesPlugin.get().getBubbleManager().hasBubble(player, bubble)) {
|
||||
AdventureManagerImpl.getInstance().sendMessageWithPrefix(player, CNLocale.MSG_BUBBLE_NOT_AVAILABLE);
|
||||
return;
|
||||
}
|
||||
|
||||
CustomNameplatesPlugin.get().getBubbleManager().equipBubble(player, bubble);
|
||||
Bubble bubbleInstance = CustomNameplatesPlugin.get().getBubbleManager().getBubble(bubble);
|
||||
AdventureManagerImpl.getInstance().sendMessageWithPrefix(player, CNLocale.MSG_EQUIP_BUBBLE.replace("{Bubble}", bubbleInstance.getDisplayName()));
|
||||
});
|
||||
@@ -141,7 +148,7 @@ public class CommandManager {
|
||||
|
||||
public static CommandAPICommand getUnEquipCommand() {
|
||||
return new CommandAPICommand("unequip")
|
||||
.withPermission("bubbles.unequip")
|
||||
.withPermission("bubbles.command.unequip")
|
||||
.executesPlayer((player, args) -> {
|
||||
if (!CNConfig.bubbleModule) return;
|
||||
CustomNameplatesPlugin.get().getBubbleManager().unEquipBubble(player);
|
||||
@@ -218,7 +225,7 @@ public class CommandManager {
|
||||
|
||||
public static CommandAPICommand getPreviewCommand() {
|
||||
return new CommandAPICommand("preview")
|
||||
.withPermission("nameplates.preview")
|
||||
.withPermission("nameplates.command.preview")
|
||||
.executesPlayer((player, args) -> {
|
||||
if (!CNConfig.nameplateModule) return;
|
||||
NameplatePlayer nameplatePlayer = CustomNameplatesPlugin.get().getNameplateManager().getNameplatePlayer(player.getUniqueId());
|
||||
@@ -290,15 +297,23 @@ public class CommandManager {
|
||||
|
||||
public static CommandAPICommand getEquipCommand() {
|
||||
return new CommandAPICommand("equip")
|
||||
.withPermission("nameplates.equip")
|
||||
.withPermission("nameplates.command.equip")
|
||||
.withArguments(new StringArgument("nameplate").replaceSuggestions(ArgumentSuggestions.strings(commandSenderSuggestionInfo -> CustomNameplatesPlugin.get().getNameplateManager().getAvailableNameplates((Player) commandSenderSuggestionInfo.sender()).toArray(new String[0]))))
|
||||
.executesPlayer((player, args) -> {
|
||||
if (!CNConfig.nameplateModule) return;
|
||||
String nameplate = (String) args.get("nameplate");
|
||||
if (!CustomNameplatesPlugin.get().getNameplateManager().equipNameplate(player, nameplate, false)) {
|
||||
|
||||
if (!CustomNameplatesPlugin.get().getNameplateManager().containsNameplate(nameplate)) {
|
||||
AdventureManagerImpl.getInstance().sendMessageWithPrefix(player, CNLocale.MSG_NAMEPLATE_NOT_EXISTS);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!CustomNameplatesPlugin.get().getNameplateManager().hasNameplate(player, nameplate)) {
|
||||
AdventureManagerImpl.getInstance().sendMessageWithPrefix(player, CNLocale.MSG_NAMEPLATE_NOT_AVAILABLE);
|
||||
return;
|
||||
}
|
||||
|
||||
CustomNameplatesPlugin.get().getNameplateManager().equipNameplate(player, nameplate, false);
|
||||
Nameplate nameplateInstance = CustomNameplatesPlugin.get().getNameplateManager().getNameplate(nameplate);
|
||||
AdventureManagerImpl.getInstance().sendMessageWithPrefix(player, CNLocale.MSG_EQUIP_NAMEPLATE.replace("{Nameplate}", nameplateInstance.getDisplayName()));
|
||||
});
|
||||
@@ -306,7 +321,7 @@ public class CommandManager {
|
||||
|
||||
public static CommandAPICommand getUnEquipCommand() {
|
||||
return new CommandAPICommand("unequip")
|
||||
.withPermission("nameplates.unequip")
|
||||
.withPermission("nameplates.command.unequip")
|
||||
.executesPlayer((player, args) -> {
|
||||
if (!CNConfig.nameplateModule) return;
|
||||
CustomNameplatesPlugin.get().getNameplateManager().unEquipNameplate(player, false);
|
||||
@@ -316,7 +331,7 @@ public class CommandManager {
|
||||
|
||||
public static CommandAPICommand getListCommand() {
|
||||
return new CommandAPICommand("list")
|
||||
.withPermission("nameplates.list")
|
||||
.withPermission("nameplates.command.list")
|
||||
.executesPlayer((player, args) -> {
|
||||
if (!CNConfig.nameplateModule) return;
|
||||
List<String> nameplates = CustomNameplatesPlugin.get().getNameplateManager().getAvailableNameplateDisplayNames(player);
|
||||
@@ -325,7 +340,7 @@ public class CommandManager {
|
||||
for (String availableNameplate : nameplates) {
|
||||
stringJoiner.add(availableNameplate);
|
||||
}
|
||||
AdventureManagerImpl.getInstance().sendMessageWithPrefix(player, CNLocale.MSG_AVAILABLE_NAMEPLATE.replace("{Nameplates}", stringJoiner.toString()));
|
||||
AdventureManagerImpl.getInstance().sendMessageWithPrefix(player, CNLocale.MSG_AVAILABLE_NAMEPLATE.replace("{Nameplates}", stringJoiner.toString()).replace("{Nameplate}", stringJoiner.toString()));
|
||||
} else {
|
||||
AdventureManagerImpl.getInstance().sendMessageWithPrefix(player, CNLocale.MSG_HAVE_NO_NAMEPLATE);
|
||||
}
|
||||
@@ -383,7 +398,7 @@ public class CommandManager {
|
||||
|
||||
public static CommandAPICommand getAboutCommand() {
|
||||
return new CommandAPICommand("about")
|
||||
.withPermission("customnameplates.about")
|
||||
.withPermission("customnameplates.admin")
|
||||
.executes((sender, args) -> {
|
||||
AdventureManagerImpl.getInstance().sendMessage(sender, "<#3CB371>⚓ CustomNameplates <gray>- <#98FB98>" + CustomNameplatesPlugin.getInstance().getVersionManager().getPluginVersion());
|
||||
AdventureManagerImpl.getInstance().sendMessage(sender, "<#7FFFAA>A plugin that provides adjustable images for texts");
|
||||
|
||||
@@ -1,182 +0,0 @@
|
||||
/*
|
||||
* This file is part of helper, licensed under the MIT License.
|
||||
*
|
||||
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
||||
* Copyright (c) contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package net.momirealms.customnameplates.paper.helper;
|
||||
|
||||
import com.google.common.base.Supplier;
|
||||
import com.google.common.base.Suppliers;
|
||||
import net.momirealms.customnameplates.api.CustomNameplatesPlugin;
|
||||
import net.momirealms.customnameplates.api.util.LogUtils;
|
||||
import net.momirealms.customnameplates.paper.CustomNameplatesPluginImpl;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.InputStream;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import java.nio.file.Files;
|
||||
import java.util.Objects;
|
||||
import java.util.StringJoiner;
|
||||
|
||||
/**
|
||||
* Resolves {@link MavenLibrary} annotations for a class, and loads the dependency
|
||||
* into the classloader.
|
||||
*/
|
||||
public final class LibraryLoader {
|
||||
|
||||
@SuppressWarnings("Guava")
|
||||
private static final Supplier<URLClassLoaderAccess> URL_INJECTOR = Suppliers.memoize(() -> URLClassLoaderAccess.create((URLClassLoader) CustomNameplatesPluginImpl.getInstance().getClass().getClassLoader()));
|
||||
|
||||
/**
|
||||
* Resolves all {@link MavenLibrary} annotations on the given object.
|
||||
*
|
||||
* @param object the object to load libraries for.
|
||||
*/
|
||||
public static void loadAll(Object object) {
|
||||
loadAll(object.getClass());
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves all {@link MavenLibrary} annotations on the given class.
|
||||
*
|
||||
* @param clazz the class to load libraries for.
|
||||
*/
|
||||
public static void loadAll(Class<?> clazz) {
|
||||
MavenLibrary[] libs = clazz.getDeclaredAnnotationsByType(MavenLibrary.class);
|
||||
for (MavenLibrary lib : libs) {
|
||||
load(lib.groupId(), lib.artifactId(), lib.version(), lib.repo().url());
|
||||
}
|
||||
}
|
||||
|
||||
public static void load(String groupId, String artifactId, String version, String repoUrl) {
|
||||
load(new Dependency(groupId, artifactId, version, repoUrl));
|
||||
}
|
||||
|
||||
public static void loadDependencies(String... libs) {
|
||||
if (libs == null || libs.length % 2 != 0)
|
||||
return;
|
||||
for (int i = 0; i < libs.length; i+=2) {
|
||||
String[] split = libs[i].split(":");
|
||||
load(new Dependency(
|
||||
split[0],
|
||||
split[1],
|
||||
split[2],
|
||||
libs[i+1]
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
public static void load(Dependency d) {
|
||||
// LogUtils.info(String.format("Loading dependency %s:%s:%s", d.groupId, d.artifactId, d.version));
|
||||
String name = d.artifactId() + "-" + d.version();
|
||||
File saveLocation = new File(getLibFolder(d), name + ".jar");
|
||||
if (!saveLocation.exists()) {
|
||||
try {
|
||||
LogUtils.info("Dependency '" + name + "' is not already in the libraries folder. Attempting to download...");
|
||||
URL url = d.getUrl();
|
||||
try (InputStream is = url.openStream()) {
|
||||
Files.copy(is, saveLocation.toPath());
|
||||
LogUtils.info("Dependency '" + name + "' successfully downloaded.");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
if (!saveLocation.exists())
|
||||
throw new RuntimeException("Unable to download dependency: " + d);
|
||||
try {
|
||||
URL_INJECTOR.get().addURL(saveLocation.toURI().toURL());
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Unable to load dependency: " + saveLocation, e);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("all")
|
||||
private static File getLibFolder(Dependency dependency) {
|
||||
File pluginDataFolder = CustomNameplatesPlugin.getInstance().getDataFolder();
|
||||
File serverDir = pluginDataFolder.getParentFile().getParentFile();
|
||||
|
||||
File helperDir = new File(serverDir, "libraries");
|
||||
String[] split = dependency.groupId().split("\\.");
|
||||
File jarDir;
|
||||
StringJoiner stringJoiner = new StringJoiner(File.separator);
|
||||
for (String str : split) {
|
||||
stringJoiner.add(str);
|
||||
}
|
||||
jarDir = new File(helperDir, stringJoiner + File.separator + dependency.artifactId + File.separator + dependency.version);
|
||||
jarDir.mkdirs();
|
||||
return jarDir;
|
||||
}
|
||||
|
||||
public record Dependency(String groupId, String artifactId, String version, String repoUrl) {
|
||||
public Dependency(String groupId, String artifactId, String version, String repoUrl) {
|
||||
this.groupId = Objects.requireNonNull(groupId, "groupId");
|
||||
this.artifactId = Objects.requireNonNull(artifactId, "artifactId");
|
||||
this.version = Objects.requireNonNull(version, "version");
|
||||
this.repoUrl = Objects.requireNonNull(repoUrl, "repoUrl");
|
||||
}
|
||||
|
||||
public URL getUrl() throws MalformedURLException {
|
||||
String repo = this.repoUrl;
|
||||
if (!repo.endsWith("/")) {
|
||||
repo += "/";
|
||||
}
|
||||
repo += "%s/%s/%s/%s-%s.jar";
|
||||
|
||||
String url = String.format(repo, this.groupId.replace(".", "/"), this.artifactId, this.version, this.artifactId, this.version);
|
||||
return new URL(url);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (o == this) return true;
|
||||
if (!(o instanceof Dependency other)) return false;
|
||||
return this.groupId().equals(other.groupId()) &&
|
||||
this.artifactId().equals(other.artifactId()) &&
|
||||
this.version().equals(other.version()) &&
|
||||
this.repoUrl().equals(other.repoUrl());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int PRIME = 59;
|
||||
int result = 1;
|
||||
result = result * PRIME + this.groupId().hashCode();
|
||||
result = result * PRIME + this.artifactId().hashCode();
|
||||
result = result * PRIME + this.version().hashCode();
|
||||
result = result * PRIME + this.repoUrl().hashCode();
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "LibraryLoader.Dependency(" +
|
||||
"groupId=" + this.groupId() + ", " +
|
||||
"artifactId=" + this.artifactId() + ", " +
|
||||
"version=" + this.version() + ", " +
|
||||
"repoUrl=" + this.repoUrl() + ")";
|
||||
}
|
||||
}
|
||||
}
|
||||
+10
-12
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* This file is part of helper, licensed under the MIT License.
|
||||
* This file is part of LuckPerms, licensed under the MIT License.
|
||||
*
|
||||
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
||||
* Copyright (c) contributors
|
||||
@@ -23,21 +23,19 @@
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package net.momirealms.customnameplates.paper.helper;
|
||||
package net.momirealms.customnameplates.paper.libraries.classpath;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
import java.nio.file.Path;
|
||||
|
||||
/**
|
||||
* Annotation to indicate the required libraries for a class.
|
||||
* Interface which allows access to add URLs to the plugin classpath at runtime.
|
||||
*/
|
||||
@Documented
|
||||
@Target(ElementType.TYPE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface MavenLibraries {
|
||||
public interface ClassPathAppender extends AutoCloseable {
|
||||
|
||||
@NotNull
|
||||
MavenLibrary[] value() default {};
|
||||
void addJarToClasspath(Path file);
|
||||
|
||||
@Override
|
||||
default void close() {
|
||||
|
||||
}
|
||||
}
|
||||
+62
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* This file is part of LuckPerms, licensed under the MIT License.
|
||||
*
|
||||
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
||||
* Copyright (c) contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package net.momirealms.customnameplates.paper.libraries.classpath;
|
||||
|
||||
import net.momirealms.customnameplates.paper.libraries.loader.JarInJarClassLoader;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.MalformedURLException;
|
||||
import java.nio.file.Path;
|
||||
|
||||
public class JarInJarClassPathAppender implements ClassPathAppender {
|
||||
private final JarInJarClassLoader classLoader;
|
||||
|
||||
public JarInJarClassPathAppender(ClassLoader classLoader) {
|
||||
if (!(classLoader instanceof JarInJarClassLoader)) {
|
||||
throw new IllegalArgumentException("Loader is not a JarInJarClassLoader: " + classLoader.getClass().getName());
|
||||
}
|
||||
this.classLoader = (JarInJarClassLoader) classLoader;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addJarToClasspath(Path file) {
|
||||
try {
|
||||
this.classLoader.addJarToClasspath(file.toUri().toURL());
|
||||
} catch (MalformedURLException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
this.classLoader.deleteJarResource();
|
||||
try {
|
||||
this.classLoader.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* This file is part of LuckPerms, licensed under the MIT License.
|
||||
*
|
||||
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
||||
* Copyright (c) contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package net.momirealms.customnameplates.paper.libraries.classpath;
|
||||
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URLClassLoader;
|
||||
import java.nio.file.Path;
|
||||
|
||||
public class ReflectionClassPathAppender implements ClassPathAppender {
|
||||
private final URLClassLoaderAccess classLoaderAccess;
|
||||
|
||||
public ReflectionClassPathAppender(ClassLoader classLoader) throws IllegalStateException {
|
||||
if (classLoader instanceof URLClassLoader) {
|
||||
this.classLoaderAccess = URLClassLoaderAccess.create((URLClassLoader) classLoader);
|
||||
} else {
|
||||
throw new IllegalStateException("ClassLoader is not instance of URLClassLoader");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addJarToClasspath(Path file) {
|
||||
try {
|
||||
this.classLoaderAccess.addURL(file.toUri().toURL());
|
||||
} catch (MalformedURLException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+62
-11
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* This file is part of helper, licensed under the MIT License.
|
||||
* This file is part of LuckPerms, licensed under the MIT License.
|
||||
*
|
||||
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
||||
* Copyright (c) contributors
|
||||
@@ -23,11 +23,12 @@
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package net.momirealms.customnameplates.paper.helper;
|
||||
package net.momirealms.customnameplates.paper.libraries.classpath;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import java.util.Collection;
|
||||
@@ -43,8 +44,10 @@ public abstract class URLClassLoaderAccess {
|
||||
* @param classLoader the class loader
|
||||
* @return the access object
|
||||
*/
|
||||
static URLClassLoaderAccess create(URLClassLoader classLoader) {
|
||||
if (Unsafe.isSupported()) {
|
||||
public static URLClassLoaderAccess create(URLClassLoader classLoader) {
|
||||
if (Reflection.isSupported()) {
|
||||
return new Reflection(classLoader);
|
||||
} else if (Unsafe.isSupported()) {
|
||||
return new Unsafe(classLoader);
|
||||
} else {
|
||||
return Noop.INSTANCE;
|
||||
@@ -63,7 +66,48 @@ public abstract class URLClassLoaderAccess {
|
||||
*
|
||||
* @param url the URL to add
|
||||
*/
|
||||
public abstract void addURL(@NotNull URL url);
|
||||
public abstract void addURL(@NonNull URL url);
|
||||
|
||||
private static void throwError(Throwable cause) throws UnsupportedOperationException {
|
||||
throw new UnsupportedOperationException("CustomNameplates is unable to inject into the plugin URLClassLoader.\n" +
|
||||
"You may be able to fix this problem by adding the following command-line argument " +
|
||||
"directly after the 'java' command in your start script: \n'--add-opens java.base/java.lang=ALL-UNNAMED'", cause);
|
||||
}
|
||||
|
||||
/**
|
||||
* Accesses using reflection, not supported on Java 9+.
|
||||
*/
|
||||
private static class Reflection extends URLClassLoaderAccess {
|
||||
private static final Method ADD_URL_METHOD;
|
||||
|
||||
static {
|
||||
Method addUrlMethod;
|
||||
try {
|
||||
addUrlMethod = URLClassLoader.class.getDeclaredMethod("addURL", URL.class);
|
||||
addUrlMethod.setAccessible(true);
|
||||
} catch (Exception e) {
|
||||
addUrlMethod = null;
|
||||
}
|
||||
ADD_URL_METHOD = addUrlMethod;
|
||||
}
|
||||
|
||||
private static boolean isSupported() {
|
||||
return ADD_URL_METHOD != null;
|
||||
}
|
||||
|
||||
Reflection(URLClassLoader classLoader) {
|
||||
super(classLoader);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addURL(@NonNull URL url) {
|
||||
try {
|
||||
ADD_URL_METHOD.invoke(super.classLoader, url);
|
||||
} catch (ReflectiveOperationException e) {
|
||||
URLClassLoaderAccess.throwError(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Accesses using sun.misc.Unsafe, supported on Java 9+.
|
||||
@@ -106,6 +150,7 @@ public abstract class URLClassLoaderAccess {
|
||||
unopenedURLs = null;
|
||||
pathURLs = null;
|
||||
}
|
||||
|
||||
this.unopenedURLs = unopenedURLs;
|
||||
this.pathURLs = pathURLs;
|
||||
}
|
||||
@@ -117,9 +162,15 @@ public abstract class URLClassLoaderAccess {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addURL(@NotNull URL url) {
|
||||
this.unopenedURLs.add(url);
|
||||
this.pathURLs.add(url);
|
||||
public void addURL(@NonNull URL url) {
|
||||
if (this.unopenedURLs == null || this.pathURLs == null) {
|
||||
URLClassLoaderAccess.throwError(new NullPointerException("unopenedURLs or pathURLs"));
|
||||
}
|
||||
|
||||
synchronized (this.unopenedURLs) {
|
||||
this.unopenedURLs.add(url);
|
||||
this.pathURLs.add(url);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -131,8 +182,8 @@ public abstract class URLClassLoaderAccess {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addURL(@NotNull URL url) {
|
||||
throw new UnsupportedOperationException();
|
||||
public void addURL(@NonNull URL url) {
|
||||
URLClassLoaderAccess.throwError(null);
|
||||
}
|
||||
}
|
||||
|
||||
+272
@@ -0,0 +1,272 @@
|
||||
/*
|
||||
* This file is part of LuckPerms, licensed under the MIT License.
|
||||
*
|
||||
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
||||
* Copyright (c) contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package net.momirealms.customnameplates.paper.libraries.dependencies;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import net.momirealms.customnameplates.paper.libraries.dependencies.relocation.Relocation;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
* The dependencies used by CustomNameplates.
|
||||
*/
|
||||
public enum Dependency {
|
||||
|
||||
ASM(
|
||||
"org.ow2.asm",
|
||||
"asm",
|
||||
"9.7",
|
||||
null,
|
||||
"asm"
|
||||
),
|
||||
ASM_COMMONS(
|
||||
"org.ow2.asm",
|
||||
"asm-commons",
|
||||
"9.7",
|
||||
null,
|
||||
"asm-commons"
|
||||
),
|
||||
JAR_RELOCATOR(
|
||||
"me.lucko",
|
||||
"jar-relocator",
|
||||
"1.7",
|
||||
null,
|
||||
"jar-relocator"
|
||||
),
|
||||
COMMAND_API(
|
||||
"dev{}jorel",
|
||||
"commandapi-bukkit-shade",
|
||||
"9.5.3",
|
||||
null,
|
||||
"commandapi-bukkit",
|
||||
Relocation.of("commandapi", "dev{}jorel{}commandapi")
|
||||
),
|
||||
COMMAND_API_MOJMAP(
|
||||
"dev{}jorel",
|
||||
"commandapi-bukkit-shade-mojang-mapped",
|
||||
"9.5.3",
|
||||
null,
|
||||
"commandapi-bukkit-mojang-mapped",
|
||||
Relocation.of("commandapi", "dev{}jorel{}commandapi")
|
||||
),
|
||||
MARIADB_DRIVER(
|
||||
"org{}mariadb{}jdbc",
|
||||
"mariadb-java-client",
|
||||
"3.3.3",
|
||||
null,
|
||||
"mariadb-java-client",
|
||||
Relocation.of("mariadb", "org{}mariadb")
|
||||
),
|
||||
BOOSTED_YAML(
|
||||
"dev{}dejvokep",
|
||||
"boosted-yaml",
|
||||
"1.3.6",
|
||||
null,
|
||||
"boosted-yaml",
|
||||
Relocation.of("boostedyaml", "dev{}dejvokep{}boostedyaml")
|
||||
),
|
||||
MYSQL_DRIVER(
|
||||
"com{}mysql",
|
||||
"mysql-connector-j",
|
||||
"9.0.0",
|
||||
null,
|
||||
"mysql-connector-j",
|
||||
Relocation.of("mysql", "com{}mysql")
|
||||
),
|
||||
H2_DRIVER(
|
||||
"com.h2database",
|
||||
"h2",
|
||||
"2.2.224",
|
||||
null,
|
||||
"h2database"
|
||||
),
|
||||
SQLITE_DRIVER(
|
||||
"org.xerial",
|
||||
"sqlite-jdbc",
|
||||
"3.46.0.1",
|
||||
null,
|
||||
"sqlite-jdbc"
|
||||
),
|
||||
HIKARI(
|
||||
"com{}zaxxer",
|
||||
"HikariCP",
|
||||
"5.1.0",
|
||||
null,
|
||||
"HikariCP",
|
||||
Relocation.of("hikari", "com{}zaxxer{}hikari")
|
||||
),
|
||||
SLF4J_SIMPLE(
|
||||
"org.slf4j",
|
||||
"slf4j-simple",
|
||||
"2.0.12",
|
||||
null,
|
||||
"slf4j-simple"
|
||||
),
|
||||
SLF4J_API(
|
||||
"org.slf4j",
|
||||
"slf4j-api",
|
||||
"2.0.12",
|
||||
null,
|
||||
"slf4j-api"
|
||||
),
|
||||
MONGODB_DRIVER_CORE(
|
||||
"org{}mongodb",
|
||||
"mongodb-driver-core",
|
||||
"5.1.0",
|
||||
null,
|
||||
"mongodb-driver-core",
|
||||
Relocation.of("mongodb", "com{}mongodb"),
|
||||
Relocation.of("bson", "org{}bson")
|
||||
),
|
||||
MONGODB_DRIVER_SYNC(
|
||||
"org{}mongodb",
|
||||
"mongodb-driver-sync",
|
||||
"5.1.0",
|
||||
null,
|
||||
"mongodb-driver-sync",
|
||||
Relocation.of("mongodb", "com{}mongodb"),
|
||||
Relocation.of("bson", "org{}bson")
|
||||
),
|
||||
MONGODB_DRIVER_BSON(
|
||||
"org{}mongodb",
|
||||
"bson",
|
||||
"5.1.0",
|
||||
null,
|
||||
"mongodb-bson",
|
||||
Relocation.of("mongodb", "com{}mongodb"),
|
||||
Relocation.of("bson", "org{}bson")
|
||||
),
|
||||
JEDIS(
|
||||
"redis{}clients",
|
||||
"jedis",
|
||||
"5.1.2",
|
||||
null,
|
||||
"jedis",
|
||||
Relocation.of("jedis", "redis{}clients{}jedis"),
|
||||
Relocation.of("commonspool2", "org{}apache{}commons{}pool2")
|
||||
),
|
||||
BSTATS_BASE(
|
||||
"org{}bstats",
|
||||
"bstats-base",
|
||||
"3.0.2",
|
||||
null,
|
||||
"bstats-base",
|
||||
Relocation.of("bstats", "org{}bstats")
|
||||
),
|
||||
BSTATS_BUKKIT(
|
||||
"org{}bstats",
|
||||
"bstats-bukkit",
|
||||
"3.0.2",
|
||||
null,
|
||||
"bstats-bukkit",
|
||||
Relocation.of("bstats", "org{}bstats")
|
||||
),
|
||||
COMMONS_POOL_2(
|
||||
"org{}apache{}commons",
|
||||
"commons-pool2",
|
||||
"2.12.0",
|
||||
null,
|
||||
"commons-pool2",
|
||||
Relocation.of("commonspool2", "org{}apache{}commons{}pool2")
|
||||
),
|
||||
GSON(
|
||||
"com.google.code.gson",
|
||||
"gson",
|
||||
"2.10.1",
|
||||
null,
|
||||
"gson"
|
||||
);
|
||||
|
||||
private final String mavenRepoPath;
|
||||
private final String version;
|
||||
private final List<Relocation> relocations;
|
||||
private final String repo;
|
||||
private final String artifact;
|
||||
|
||||
private static final String MAVEN_FORMAT = "%s/%s/%s/%s-%s.jar";
|
||||
|
||||
Dependency(String groupId, String artifactId, String version, String repo, String artifact) {
|
||||
this(groupId, artifactId, version, repo, artifact, new Relocation[0]);
|
||||
}
|
||||
|
||||
Dependency(String groupId, String artifactId, String version, String repo, String artifact, Relocation... relocations) {
|
||||
this.mavenRepoPath = String.format(MAVEN_FORMAT,
|
||||
rewriteEscaping(groupId).replace(".", "/"),
|
||||
rewriteEscaping(artifactId),
|
||||
version,
|
||||
rewriteEscaping(artifactId),
|
||||
version
|
||||
);
|
||||
this.version = version;
|
||||
this.relocations = ImmutableList.copyOf(relocations);
|
||||
this.repo = repo;
|
||||
this.artifact = artifact;
|
||||
}
|
||||
|
||||
private static String rewriteEscaping(String s) {
|
||||
return s.replace("{}", ".");
|
||||
}
|
||||
|
||||
public String getFileName(String classifier) {
|
||||
String name = artifact.toLowerCase(Locale.ROOT).replace('_', '-');
|
||||
String extra = classifier == null || classifier.isEmpty()
|
||||
? ""
|
||||
: "-" + classifier;
|
||||
|
||||
return name + "-" + this.version + extra + ".jar";
|
||||
}
|
||||
|
||||
String getMavenRepoPath() {
|
||||
return this.mavenRepoPath;
|
||||
}
|
||||
|
||||
public List<Relocation> getRelocations() {
|
||||
return this.relocations;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link MessageDigest} suitable for computing the checksums
|
||||
* of dependencies.
|
||||
*
|
||||
* @return the digest
|
||||
*/
|
||||
public static MessageDigest createDigest() {
|
||||
try {
|
||||
return MessageDigest.getInstance("SHA-256");
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getRepo() {
|
||||
return repo;
|
||||
}
|
||||
}
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* This file is part of LuckPerms, licensed under the MIT License.
|
||||
*
|
||||
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
||||
* Copyright (c) contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package net.momirealms.customnameplates.paper.libraries.dependencies;
|
||||
|
||||
/**
|
||||
* Exception thrown if a dependency cannot be downloaded.
|
||||
*/
|
||||
public class DependencyDownloadException extends Exception {
|
||||
|
||||
public DependencyDownloadException() {
|
||||
|
||||
}
|
||||
|
||||
public DependencyDownloadException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public DependencyDownloadException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
public DependencyDownloadException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
}
|
||||
+15
-35
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* This file is part of helper, licensed under the MIT License.
|
||||
* This file is part of LuckPerms, licensed under the MIT License.
|
||||
*
|
||||
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
||||
* Copyright (c) contributors
|
||||
@@ -23,51 +23,31 @@
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package net.momirealms.customnameplates.paper.helper;
|
||||
package net.momirealms.customnameplates.paper.libraries.dependencies;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
import java.util.Collection;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Annotation to indicate a required library for a class.
|
||||
* Loads and manages runtime dependencies for the plugin.
|
||||
*/
|
||||
@Documented
|
||||
@Repeatable(MavenLibraries.class)
|
||||
@Target(ElementType.TYPE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface MavenLibrary {
|
||||
public interface DependencyManager extends AutoCloseable {
|
||||
|
||||
/**
|
||||
* The group id of the library
|
||||
* Loads dependencies.
|
||||
*
|
||||
* @return the group id of the library
|
||||
* @param dependencies the dependencies to load
|
||||
*/
|
||||
@NotNull
|
||||
String groupId();
|
||||
void loadDependencies(Collection<Dependency> dependencies);
|
||||
|
||||
/**
|
||||
* The artifact id of the library
|
||||
* Obtains an isolated classloader containing the given dependencies.
|
||||
*
|
||||
* @return the artifact id of the library
|
||||
* @param dependencies the dependencies
|
||||
* @return the classloader
|
||||
*/
|
||||
@NotNull
|
||||
String artifactId();
|
||||
|
||||
/**
|
||||
* The version of the library
|
||||
*
|
||||
* @return the version of the library
|
||||
*/
|
||||
@NotNull
|
||||
String version();
|
||||
|
||||
/**
|
||||
* The repo where the library can be obtained from
|
||||
*
|
||||
* @return the repo where the library can be obtained from
|
||||
*/
|
||||
@NotNull
|
||||
Repository repo() default @Repository(url = "https://repo1.maven.org/maven2");
|
||||
ClassLoader obtainClassLoaderWith(Set<Dependency> dependencies);
|
||||
|
||||
@Override
|
||||
void close();
|
||||
}
|
||||
+233
@@ -0,0 +1,233 @@
|
||||
/*
|
||||
* This file is part of LuckPerms, licensed under the MIT License.
|
||||
*
|
||||
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
||||
* Copyright (c) contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package net.momirealms.customnameplates.paper.libraries.dependencies;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import net.momirealms.customnameplates.api.util.LogUtils;
|
||||
import net.momirealms.customnameplates.paper.CustomNameplatesPluginImpl;
|
||||
import net.momirealms.customnameplates.paper.libraries.classpath.ClassPathAppender;
|
||||
import net.momirealms.customnameplates.paper.libraries.dependencies.classloader.IsolatedClassLoader;
|
||||
import net.momirealms.customnameplates.paper.libraries.dependencies.relocation.Relocation;
|
||||
import net.momirealms.customnameplates.paper.libraries.dependencies.relocation.RelocationHandler;
|
||||
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
|
||||
/**
|
||||
* Loads and manages runtime dependencies for the plugin.
|
||||
*/
|
||||
public class DependencyManagerImpl implements DependencyManager {
|
||||
|
||||
/** A registry containing plugin specific behaviour for dependencies. */
|
||||
private final DependencyRegistry registry;
|
||||
/** The path where library jars are cached. */
|
||||
private final Path cacheDirectory;
|
||||
/** The classpath appender to preload dependencies into */
|
||||
private final ClassPathAppender classPathAppender;
|
||||
/** A map of dependencies which have already been loaded. */
|
||||
private final EnumMap<Dependency, Path> loaded = new EnumMap<>(Dependency.class);
|
||||
/** A map of isolated classloaders which have been created. */
|
||||
private final Map<ImmutableSet<Dependency>, IsolatedClassLoader> loaders = new HashMap<>();
|
||||
/** Cached relocation handler instance. */
|
||||
private @MonotonicNonNull RelocationHandler relocationHandler = null;
|
||||
|
||||
public DependencyManagerImpl(CustomNameplatesPluginImpl plugin, ClassPathAppender classPathAppender) {
|
||||
this.registry = new DependencyRegistry();
|
||||
this.cacheDirectory = setupCacheDirectory(plugin);
|
||||
this.classPathAppender = classPathAppender;
|
||||
this.relocationHandler = new RelocationHandler(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClassLoader obtainClassLoaderWith(Set<Dependency> dependencies) {
|
||||
ImmutableSet<Dependency> set = ImmutableSet.copyOf(dependencies);
|
||||
|
||||
for (Dependency dependency : dependencies) {
|
||||
if (!this.loaded.containsKey(dependency)) {
|
||||
throw new IllegalStateException("Dependency " + dependency + " is not loaded.");
|
||||
}
|
||||
}
|
||||
|
||||
synchronized (this.loaders) {
|
||||
IsolatedClassLoader classLoader = this.loaders.get(set);
|
||||
if (classLoader != null) {
|
||||
return classLoader;
|
||||
}
|
||||
|
||||
URL[] urls = set.stream()
|
||||
.map(this.loaded::get)
|
||||
.map(file -> {
|
||||
try {
|
||||
return file.toUri().toURL();
|
||||
} catch (MalformedURLException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
})
|
||||
.toArray(URL[]::new);
|
||||
|
||||
classLoader = new IsolatedClassLoader(urls);
|
||||
this.loaders.put(set, classLoader);
|
||||
return classLoader;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadDependencies(Collection<Dependency> dependencies) {
|
||||
CountDownLatch latch = new CountDownLatch(dependencies.size());
|
||||
|
||||
for (Dependency dependency : dependencies) {
|
||||
if (this.loaded.containsKey(dependency)) {
|
||||
latch.countDown();
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
loadDependency(dependency);
|
||||
} catch (Throwable e) {
|
||||
new RuntimeException("Unable to load dependency " + dependency.name(), e).printStackTrace();
|
||||
} finally {
|
||||
latch.countDown();
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
latch.await();
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
}
|
||||
|
||||
private void loadDependency(Dependency dependency) throws Exception {
|
||||
if (this.loaded.containsKey(dependency)) {
|
||||
return;
|
||||
}
|
||||
|
||||
Path file = remapDependency(dependency, downloadDependency(dependency));
|
||||
|
||||
this.loaded.put(dependency, file);
|
||||
|
||||
if (this.classPathAppender != null && this.registry.shouldAutoLoad(dependency)) {
|
||||
this.classPathAppender.addJarToClasspath(file);
|
||||
}
|
||||
}
|
||||
|
||||
private Path downloadDependency(Dependency dependency) throws DependencyDownloadException {
|
||||
Path file = this.cacheDirectory.resolve(dependency.getFileName(null));
|
||||
|
||||
// if the file already exists, don't attempt to re-download it.
|
||||
if (Files.exists(file)) {
|
||||
return file;
|
||||
}
|
||||
|
||||
DependencyDownloadException lastError = null;
|
||||
|
||||
String fileName = dependency.getFileName(null);
|
||||
String forceRepo = dependency.getRepo();
|
||||
if (forceRepo == null) {
|
||||
// attempt to download the dependency from each repo in order.
|
||||
for (DependencyRepository repo : DependencyRepository.values()) {
|
||||
if (repo.getId().equals("maven") && TimeZone.getDefault().getID().startsWith("Asia")) {
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
LogUtils.info("Downloading dependency(" + fileName + ") from " + repo.getUrl() + dependency.getMavenRepoPath());
|
||||
repo.download(dependency, file);
|
||||
LogUtils.info("Successfully downloaded " + fileName);
|
||||
return file;
|
||||
} catch (DependencyDownloadException e) {
|
||||
lastError = e;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
DependencyRepository repository = DependencyRepository.getByID(forceRepo);
|
||||
if (repository != null) {
|
||||
try {
|
||||
LogUtils.info("Downloading dependency(" + fileName + ") from " + repository.getUrl() + dependency.getMavenRepoPath());
|
||||
repository.download(dependency, file);
|
||||
LogUtils.info("Successfully downloaded " + fileName);
|
||||
return file;
|
||||
} catch (DependencyDownloadException e) {
|
||||
lastError = e;
|
||||
}
|
||||
}
|
||||
}
|
||||
throw Objects.requireNonNull(lastError);
|
||||
}
|
||||
|
||||
private Path remapDependency(Dependency dependency, Path normalFile) throws Exception {
|
||||
List<Relocation> rules = new ArrayList<>(dependency.getRelocations());
|
||||
if (rules.isEmpty()) {
|
||||
return normalFile;
|
||||
}
|
||||
|
||||
Path remappedFile = this.cacheDirectory.resolve(dependency.getFileName(DependencyRegistry.isGsonRelocated() ? "remapped-legacy" : "remapped"));
|
||||
|
||||
// if the remapped source exists already, just use that.
|
||||
if (Files.exists(remappedFile)) {
|
||||
return remappedFile;
|
||||
}
|
||||
|
||||
LogUtils.info("Remapping " + dependency.getFileName(null));
|
||||
relocationHandler.remap(normalFile, remappedFile, rules);
|
||||
LogUtils.info("Successfully remapped " + dependency.getFileName(null));
|
||||
return remappedFile;
|
||||
}
|
||||
|
||||
private static Path setupCacheDirectory(CustomNameplatesPluginImpl plugin) {
|
||||
File folder = new File(plugin.getDataFolder(), "libs");
|
||||
folder.mkdirs();
|
||||
return folder.toPath();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
IOException firstEx = null;
|
||||
|
||||
for (IsolatedClassLoader loader : this.loaders.values()) {
|
||||
try {
|
||||
loader.close();
|
||||
} catch (IOException ex) {
|
||||
if (firstEx == null) {
|
||||
firstEx = ex;
|
||||
} else {
|
||||
firstEx.addSuppressed(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (firstEx != null) {
|
||||
firstEx.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+62
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* This file is part of LuckPerms, licensed under the MIT License.
|
||||
*
|
||||
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
||||
* Copyright (c) contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package net.momirealms.customnameplates.paper.libraries.dependencies;
|
||||
|
||||
import com.google.gson.JsonElement;
|
||||
|
||||
/**
|
||||
* Applies CustomNameplates specific behaviour for {@link Dependency}s.
|
||||
*/
|
||||
public class DependencyRegistry {
|
||||
|
||||
public boolean shouldAutoLoad(Dependency dependency) {
|
||||
return switch (dependency) {
|
||||
// all used within 'isolated' classloaders, and are therefore not
|
||||
// relocated.
|
||||
case ASM, ASM_COMMONS, JAR_RELOCATOR, H2_DRIVER, SQLITE_DRIVER -> false;
|
||||
default -> true;
|
||||
};
|
||||
}
|
||||
|
||||
@SuppressWarnings("ConstantConditions")
|
||||
public static boolean isGsonRelocated() {
|
||||
return JsonElement.class.getName().startsWith("net.momirealms");
|
||||
}
|
||||
|
||||
private static boolean classExists(String className) {
|
||||
try {
|
||||
Class.forName(className);
|
||||
return true;
|
||||
} catch (ClassNotFoundException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean slf4jPresent() {
|
||||
return classExists("org.slf4j.Logger") && classExists("org.slf4j.LoggerFactory");
|
||||
}
|
||||
|
||||
}
|
||||
+149
@@ -0,0 +1,149 @@
|
||||
/*
|
||||
* This file is part of LuckPerms, licensed under the MIT License.
|
||||
*
|
||||
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
||||
* Copyright (c) contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package net.momirealms.customnameplates.paper.libraries.dependencies;
|
||||
|
||||
import com.google.common.io.ByteStreams;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* Represents a repository which contains {@link Dependency}s.
|
||||
*/
|
||||
public enum DependencyRepository {
|
||||
|
||||
MAVEN_CENTRAL("maven", "https://repo1.maven.org/maven2/") {
|
||||
@Override
|
||||
protected URLConnection openConnection(Dependency dependency) throws IOException {
|
||||
URLConnection connection = super.openConnection(dependency);
|
||||
connection.setConnectTimeout((int) TimeUnit.SECONDS.toMillis(5));
|
||||
connection.setReadTimeout((int) TimeUnit.SECONDS.toMillis(5));
|
||||
return connection;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Maven Central
|
||||
*/
|
||||
MAVEN_CENTRAL_MIRROR("aliyun", "https://maven.aliyun.com/repository/public/"),
|
||||
/**
|
||||
* Code MC
|
||||
*/
|
||||
CODE_MC("codemc", "https://repo.codemc.io/repository/maven-public/"),
|
||||
/**
|
||||
* Jitpack
|
||||
*/
|
||||
JITPACK("jitpack", "https://jitpack.io/");
|
||||
|
||||
private final String url;
|
||||
private final String id;
|
||||
|
||||
DependencyRepository(String id, String url) {
|
||||
this.url = url;
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getUrl() {
|
||||
return url;
|
||||
}
|
||||
|
||||
public static DependencyRepository getByID(String id) {
|
||||
for (DependencyRepository repository : values()) {
|
||||
if (id.equals(repository.id)) {
|
||||
return repository;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens a connection to the given {@code dependency}.
|
||||
*
|
||||
* @param dependency the dependency to download
|
||||
* @return the connection
|
||||
* @throws IOException if unable to open a connection
|
||||
*/
|
||||
protected URLConnection openConnection(Dependency dependency) throws IOException {
|
||||
URL dependencyUrl = new URL(this.url + dependency.getMavenRepoPath());
|
||||
return dependencyUrl.openConnection();
|
||||
}
|
||||
|
||||
/**
|
||||
* Downloads the raw bytes of the {@code dependency}.
|
||||
*
|
||||
* @param dependency the dependency to download
|
||||
* @return the downloaded bytes
|
||||
* @throws DependencyDownloadException if unable to download
|
||||
*/
|
||||
public byte[] downloadRaw(Dependency dependency) throws DependencyDownloadException {
|
||||
try {
|
||||
URLConnection connection = openConnection(dependency);
|
||||
try (InputStream in = connection.getInputStream()) {
|
||||
byte[] bytes = ByteStreams.toByteArray(in);
|
||||
if (bytes.length == 0) {
|
||||
throw new DependencyDownloadException("Empty stream");
|
||||
}
|
||||
return bytes;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new DependencyDownloadException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param dependency the dependency to download
|
||||
* @return the downloaded bytes
|
||||
* @throws DependencyDownloadException if unable to download
|
||||
*/
|
||||
public byte[] download(Dependency dependency) throws DependencyDownloadException {
|
||||
return downloadRaw(dependency);
|
||||
}
|
||||
|
||||
/**
|
||||
* Downloads the the {@code dependency} to the {@code file}, ensuring the
|
||||
* downloaded bytes match the checksum.
|
||||
*
|
||||
* @param dependency the dependency to download
|
||||
* @param file the file to write to
|
||||
* @throws DependencyDownloadException if unable to download
|
||||
*/
|
||||
public void download(Dependency dependency, Path file) throws DependencyDownloadException {
|
||||
try {
|
||||
Files.write(file, download(dependency));
|
||||
} catch (IOException e) {
|
||||
throw new DependencyDownloadException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
}
|
||||
+54
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* This file is part of LuckPerms, licensed under the MIT License.
|
||||
*
|
||||
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
||||
* Copyright (c) contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package net.momirealms.customnameplates.paper.libraries.dependencies.classloader;
|
||||
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
|
||||
/**
|
||||
* A classloader "isolated" from the rest of the Minecraft server.
|
||||
*
|
||||
* <p>Used to load specific CustomNameplates dependencies without causing conflicts
|
||||
* with other plugins, or libraries provided by the server implementation.</p>
|
||||
*/
|
||||
public class IsolatedClassLoader extends URLClassLoader {
|
||||
static {
|
||||
ClassLoader.registerAsParallelCapable();
|
||||
}
|
||||
|
||||
public IsolatedClassLoader(URL[] urls) {
|
||||
/*
|
||||
* ClassLoader#getSystemClassLoader returns the AppClassLoader
|
||||
*
|
||||
* Calling #getParent on this returns the ExtClassLoader (Java 8) or
|
||||
* the PlatformClassLoader (Java 9). Since we want this classloader to
|
||||
* be isolated from the Minecraft server (the app), we set the parent
|
||||
* to be the platform class loader.
|
||||
*/
|
||||
super(urls, ClassLoader.getSystemClassLoader().getParent());
|
||||
}
|
||||
|
||||
}
|
||||
+66
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* This file is part of LuckPerms, licensed under the MIT License.
|
||||
*
|
||||
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
||||
* Copyright (c) contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package net.momirealms.customnameplates.paper.libraries.dependencies.relocation;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public final class Relocation {
|
||||
private static final String RELOCATION_PREFIX = "net.momirealms.customnameplates.libraries.";
|
||||
|
||||
public static Relocation of(String id, String pattern) {
|
||||
return new Relocation(pattern.replace("{}", "."), RELOCATION_PREFIX + id);
|
||||
}
|
||||
|
||||
private final String pattern;
|
||||
private final String relocatedPattern;
|
||||
|
||||
private Relocation(String pattern, String relocatedPattern) {
|
||||
this.pattern = pattern;
|
||||
this.relocatedPattern = relocatedPattern;
|
||||
}
|
||||
|
||||
public String getPattern() {
|
||||
return this.pattern;
|
||||
}
|
||||
|
||||
public String getRelocatedPattern() {
|
||||
return this.relocatedPattern;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
Relocation that = (Relocation) o;
|
||||
return Objects.equals(this.pattern, that.pattern) &&
|
||||
Objects.equals(this.relocatedPattern, that.relocatedPattern);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(this.pattern, this.relocatedPattern);
|
||||
}
|
||||
}
|
||||
+91
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* This file is part of LuckPerms, licensed under the MIT License.
|
||||
*
|
||||
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
||||
* Copyright (c) contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package net.momirealms.customnameplates.paper.libraries.dependencies.relocation;
|
||||
|
||||
import net.momirealms.customnameplates.paper.libraries.dependencies.Dependency;
|
||||
import net.momirealms.customnameplates.paper.libraries.dependencies.DependencyManager;
|
||||
import net.momirealms.customnameplates.paper.libraries.dependencies.classloader.IsolatedClassLoader;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Method;
|
||||
import java.nio.file.Path;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Handles class runtime relocation of packages in downloaded dependencies
|
||||
*/
|
||||
public class RelocationHandler {
|
||||
public static final Set<Dependency> DEPENDENCIES = EnumSet.of(Dependency.ASM, Dependency.ASM_COMMONS, Dependency.JAR_RELOCATOR);
|
||||
private static final String JAR_RELOCATOR_CLASS = "me.lucko.jarrelocator.JarRelocator";
|
||||
private static final String JAR_RELOCATOR_RUN_METHOD = "run";
|
||||
|
||||
private final Constructor<?> jarRelocatorConstructor;
|
||||
private final Method jarRelocatorRunMethod;
|
||||
|
||||
public RelocationHandler(DependencyManager dependencyManager) {
|
||||
ClassLoader classLoader = null;
|
||||
try {
|
||||
// download the required dependencies for remapping
|
||||
dependencyManager.loadDependencies(DEPENDENCIES);
|
||||
// get a classloader containing the required dependencies as sources
|
||||
classLoader = dependencyManager.obtainClassLoaderWith(DEPENDENCIES);
|
||||
|
||||
// load the relocator class
|
||||
Class<?> jarRelocatorClass = classLoader.loadClass(JAR_RELOCATOR_CLASS);
|
||||
|
||||
// prepare the the reflected constructor & method instances
|
||||
this.jarRelocatorConstructor = jarRelocatorClass.getDeclaredConstructor(File.class, File.class, Map.class);
|
||||
this.jarRelocatorConstructor.setAccessible(true);
|
||||
|
||||
this.jarRelocatorRunMethod = jarRelocatorClass.getDeclaredMethod(JAR_RELOCATOR_RUN_METHOD);
|
||||
this.jarRelocatorRunMethod.setAccessible(true);
|
||||
} catch (Exception e) {
|
||||
try {
|
||||
if (classLoader instanceof IsolatedClassLoader) {
|
||||
((IsolatedClassLoader) classLoader).close();
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
e.addSuppressed(ex);
|
||||
}
|
||||
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void remap(Path input, Path output, List<Relocation> relocations) throws Exception {
|
||||
Map<String, String> mappings = new HashMap<>();
|
||||
for (Relocation relocation : relocations) {
|
||||
mappings.put(relocation.getPattern(), relocation.getRelocatedPattern());
|
||||
}
|
||||
|
||||
// create and invoke a new relocator
|
||||
Object relocator = this.jarRelocatorConstructor.newInstance(input.toFile(), output.toFile(), mappings);
|
||||
this.jarRelocatorRunMethod.invoke(relocator);
|
||||
}
|
||||
|
||||
}
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* This file is part of LuckPerms, licensed under the MIT License.
|
||||
*
|
||||
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
||||
* Copyright (c) contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package net.momirealms.customnameplates.paper.libraries.dependencies.relocation;
|
||||
|
||||
public final class RelocationHelper {
|
||||
|
||||
// screw maven shade
|
||||
public static final String OKIO_STRING = String.valueOf(new char[]{'o', 'k', 'i', 'o'});
|
||||
public static final String OKHTTP3_STRING = String.valueOf(new char[]{'o', 'k', 'h', 't', 't', 'p', '3'});
|
||||
|
||||
private RelocationHelper() {
|
||||
|
||||
}
|
||||
}
|
||||
+155
@@ -0,0 +1,155 @@
|
||||
/*
|
||||
* This file is part of LuckPerms, licensed under the MIT License.
|
||||
*
|
||||
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
||||
* Copyright (c) contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package net.momirealms.customnameplates.paper.libraries.loader;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.nio.file.StandardCopyOption;
|
||||
|
||||
/**
|
||||
* Classloader that can load a jar from within another jar file.
|
||||
*
|
||||
* <p>The "loader" jar contains the loading code & public API classes,
|
||||
* and is class-loaded by the platform.</p>
|
||||
*
|
||||
* <p>The inner "plugin" jar contains the plugin itself, and is class-loaded
|
||||
* by the loading code & this classloader.</p>
|
||||
*/
|
||||
public class JarInJarClassLoader extends URLClassLoader {
|
||||
static {
|
||||
ClassLoader.registerAsParallelCapable();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new jar-in-jar class loader.
|
||||
*
|
||||
* @param loaderClassLoader the loader plugin's classloader (setup and created by the platform)
|
||||
* @param jarResourcePath the path to the jar-in-jar resource within the loader jar
|
||||
* @throws LoadingException if something unexpectedly bad happens
|
||||
*/
|
||||
public JarInJarClassLoader(ClassLoader loaderClassLoader, String jarResourcePath) throws LoadingException {
|
||||
super(new URL[]{extractJar(loaderClassLoader, jarResourcePath)}, loaderClassLoader);
|
||||
}
|
||||
|
||||
public void addJarToClasspath(URL url) {
|
||||
addURL(url);
|
||||
}
|
||||
|
||||
public void deleteJarResource() {
|
||||
URL[] urls = getURLs();
|
||||
if (urls.length == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
Path path = Paths.get(urls[0].toURI());
|
||||
Files.deleteIfExists(path);
|
||||
} catch (Exception e) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new plugin instance.
|
||||
*
|
||||
* @param bootstrapClass the name of the bootstrap plugin class
|
||||
* @param loaderPluginType the type of the loader plugin, the only parameter of the bootstrap
|
||||
* plugin constructor
|
||||
* @param loaderPlugin the loader plugin instance
|
||||
* @param <T> the type of the loader plugin
|
||||
* @return the instantiated bootstrap plugin
|
||||
*/
|
||||
public <T> LoaderBootstrap instantiatePlugin(String bootstrapClass, Class<T> loaderPluginType, T loaderPlugin) throws LoadingException {
|
||||
Class<? extends LoaderBootstrap> plugin;
|
||||
try {
|
||||
plugin = loadClass(bootstrapClass).asSubclass(LoaderBootstrap.class);
|
||||
} catch (ReflectiveOperationException e) {
|
||||
throw new LoadingException("Unable to load bootstrap class", e);
|
||||
}
|
||||
|
||||
Constructor<? extends LoaderBootstrap> constructor;
|
||||
try {
|
||||
constructor = plugin.getConstructor(loaderPluginType);
|
||||
} catch (ReflectiveOperationException e) {
|
||||
throw new LoadingException("Unable to get bootstrap constructor", e);
|
||||
}
|
||||
|
||||
try {
|
||||
return constructor.newInstance(loaderPlugin);
|
||||
} catch (ReflectiveOperationException e) {
|
||||
throw new LoadingException("Unable to create bootstrap plugin instance", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the "jar-in-jar" from the loader plugin into a temporary file,
|
||||
* then returns a URL that can be used by the {@link JarInJarClassLoader}.
|
||||
*
|
||||
* @param loaderClassLoader the classloader for the "host" loader plugin
|
||||
* @param jarResourcePath the inner jar resource path
|
||||
* @return a URL to the extracted file
|
||||
*/
|
||||
private static URL extractJar(ClassLoader loaderClassLoader, String jarResourcePath) throws LoadingException {
|
||||
// get the jar-in-jar resource
|
||||
URL jarInJar = loaderClassLoader.getResource(jarResourcePath);
|
||||
if (jarInJar == null) {
|
||||
throw new LoadingException("Could not locate jar-in-jar");
|
||||
}
|
||||
|
||||
// create a temporary file
|
||||
// on posix systems by default this is only read/writable by the process owner
|
||||
Path path;
|
||||
try {
|
||||
path = Files.createTempFile("customnameplates-jarinjar", ".jar.tmp");
|
||||
} catch (IOException e) {
|
||||
throw new LoadingException("Unable to create a temporary file", e);
|
||||
}
|
||||
|
||||
// mark that the file should be deleted on exit
|
||||
path.toFile().deleteOnExit();
|
||||
|
||||
// copy the jar-in-jar to the temporary file path
|
||||
try (InputStream in = jarInJar.openStream()) {
|
||||
Files.copy(in, path, StandardCopyOption.REPLACE_EXISTING);
|
||||
} catch (IOException e) {
|
||||
throw new LoadingException("Unable to copy jar-in-jar to temporary path", e);
|
||||
}
|
||||
|
||||
try {
|
||||
return path.toUri().toURL();
|
||||
} catch (MalformedURLException e) {
|
||||
throw new LoadingException("Unable to get URL from path", e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+9
-15
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* This file is part of helper, licensed under the MIT License.
|
||||
* This file is part of LuckPerms, licensed under the MIT License.
|
||||
*
|
||||
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
||||
* Copyright (c) contributors
|
||||
@@ -23,23 +23,17 @@
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package net.momirealms.customnameplates.paper.helper;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
package net.momirealms.customnameplates.paper.libraries.loader;
|
||||
|
||||
/**
|
||||
* Represents a maven repository.
|
||||
* Minimal bootstrap plugin, called by the loader plugin.
|
||||
*/
|
||||
@Documented
|
||||
@Target(ElementType.LOCAL_VARIABLE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface Repository {
|
||||
public interface LoaderBootstrap {
|
||||
|
||||
/**
|
||||
* Gets the base url of the repository.
|
||||
*
|
||||
* @return the base url of the repository
|
||||
*/
|
||||
String url();
|
||||
void onLoad();
|
||||
|
||||
default void onEnable() {}
|
||||
|
||||
default void onDisable() {}
|
||||
|
||||
}
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* This file is part of LuckPerms, licensed under the MIT License.
|
||||
*
|
||||
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
||||
* Copyright (c) contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package net.momirealms.customnameplates.paper.libraries.loader;
|
||||
|
||||
/**
|
||||
* Runtime exception used if there is a problem during loading
|
||||
*/
|
||||
public class LoadingException extends RuntimeException {
|
||||
|
||||
public LoadingException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public LoadingException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
}
|
||||
+30
-11
@@ -24,17 +24,18 @@ import com.comphenix.protocol.wrappers.EnumWrappers;
|
||||
import com.comphenix.protocol.wrappers.WrappedChatComponent;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.TranslatableComponent;
|
||||
import net.kyori.adventure.text.minimessage.MiniMessage;
|
||||
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
|
||||
import net.momirealms.customnameplates.api.CustomNameplatesPlugin;
|
||||
import net.momirealms.customnameplates.api.manager.ActionBarManager;
|
||||
import net.momirealms.customnameplates.api.util.LogUtils;
|
||||
import net.momirealms.customnameplates.paper.adventure.AdventureManagerImpl;
|
||||
import net.momirealms.customnameplates.paper.mechanic.actionbar.listener.ActionBarListener;
|
||||
import net.momirealms.customnameplates.paper.mechanic.actionbar.listener.ChatMessageListener;
|
||||
import net.momirealms.customnameplates.paper.mechanic.actionbar.listener.SystemChatListener;
|
||||
import net.momirealms.customnameplates.paper.mechanic.misc.DisplayController;
|
||||
import net.momirealms.customnameplates.paper.setting.CNConfig;
|
||||
import net.momirealms.customnameplates.paper.util.ConfigUtils;
|
||||
import net.momirealms.customnameplates.paper.util.ReflectionUtils;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
@@ -60,11 +61,15 @@ public class ActionBarManagerImpl implements ActionBarManager, Listener {
|
||||
private ActionBarConfig config;
|
||||
private ChatMessageListener chatMessageListener;
|
||||
private SystemChatListener systemChatListener;
|
||||
private final MiniMessage miniMessage;
|
||||
|
||||
public ActionBarManagerImpl(CustomNameplatesPlugin plugin) {
|
||||
this.receiverMap = new ConcurrentHashMap<>();
|
||||
this.plugin = plugin;
|
||||
this.actionBarListener = new ActionBarListener(this);
|
||||
this.miniMessage = MiniMessage.builder()
|
||||
.strict(true)
|
||||
.build();
|
||||
if (plugin.getVersionManager().isVersionNewerThan1_19()) {
|
||||
this.systemChatListener = new SystemChatListener(this);
|
||||
} else {
|
||||
@@ -176,13 +181,23 @@ public class ActionBarManagerImpl implements ActionBarManager, Listener {
|
||||
if (receiver != null) {
|
||||
event.setCancelled(true);
|
||||
String json = packet.getStrings().readSafely(0);
|
||||
if (json != null && !json.equals("")) {
|
||||
if (json != null && !json.isEmpty()) {
|
||||
Component component = GsonComponentSerializer.gson().deserialize(json);
|
||||
if (component instanceof TranslatableComponent) {
|
||||
// We can't get TranslatableComponent's width :(
|
||||
return;
|
||||
}
|
||||
receiver.setOtherPluginText(AdventureManagerImpl.getInstance().getMiniMessageFormat(component), System.currentTimeMillis());
|
||||
receiver.setOtherPluginText(miniMessage.serialize(component), System.currentTimeMillis());
|
||||
} else {
|
||||
WrappedChatComponent wrappedChatComponent = packet.getChatComponents().readSafely(0);
|
||||
if (wrappedChatComponent != null) {
|
||||
json = wrappedChatComponent.getJson();
|
||||
Component component = GsonComponentSerializer.gson().deserialize(json);
|
||||
if (component instanceof TranslatableComponent) {
|
||||
return;
|
||||
}
|
||||
receiver.setOtherPluginText(miniMessage.serialize(component), System.currentTimeMillis());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -204,7 +219,7 @@ public class ActionBarManagerImpl implements ActionBarManager, Listener {
|
||||
// We can't get TranslatableComponent's width :(
|
||||
return;
|
||||
}
|
||||
receiver.setOtherPluginText(AdventureManagerImpl.getInstance().getMiniMessageFormat(component), System.currentTimeMillis());
|
||||
receiver.setOtherPluginText(miniMessage.serialize(component), System.currentTimeMillis());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -212,10 +227,10 @@ public class ActionBarManagerImpl implements ActionBarManager, Listener {
|
||||
|
||||
public void onReceiveActionBarPacket(PacketEvent event) {
|
||||
PacketContainer packet = event.getPacket();
|
||||
WrappedChatComponent wrappedChatComponent = packet.getChatComponents().read(0);
|
||||
if (wrappedChatComponent != null) {
|
||||
ActionBarReceiver receiver = getReceiver(event.getPlayer().getUniqueId());
|
||||
if (receiver != null) {
|
||||
ActionBarReceiver receiver = getReceiver(event.getPlayer().getUniqueId());
|
||||
if (receiver != null) {
|
||||
WrappedChatComponent wrappedChatComponent = packet.getChatComponents().read(0);
|
||||
if (wrappedChatComponent != null) {
|
||||
String strJson = wrappedChatComponent.getJson();
|
||||
// for better performance
|
||||
if (strJson.contains("\"name\":\"np\",\"objective\":\"ab\"")) {
|
||||
@@ -223,10 +238,14 @@ public class ActionBarManagerImpl implements ActionBarManager, Listener {
|
||||
}
|
||||
event.setCancelled(true);
|
||||
receiver.setOtherPluginText(
|
||||
AdventureManagerImpl.getInstance().getMiniMessageFormat(
|
||||
GsonComponentSerializer.gson().deserialize(strJson)
|
||||
), System.currentTimeMillis()
|
||||
miniMessage.serialize(GsonComponentSerializer.gson().deserialize(strJson)), System.currentTimeMillis()
|
||||
);
|
||||
} else if (ReflectionUtils.isPaper()) {
|
||||
Object adventureComponent = packet.getModifier().readSafely(1);
|
||||
if (adventureComponent != null) {
|
||||
String other = ReflectionUtils.getMiniMessageTextFromNonShadedComponent(adventureComponent);
|
||||
receiver.setOtherPluginText(other, System.currentTimeMillis());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -62,7 +62,7 @@ public class ActionBarReceiver {
|
||||
}
|
||||
case UPDATE -> {
|
||||
if (controller.isShown()) {
|
||||
controller.initialize();
|
||||
controller.initialize(condition);
|
||||
AdventureManagerImpl.getInstance().sendActionbar(player, controller.getLatestContent());
|
||||
} else {
|
||||
AdventureManagerImpl.getInstance().sendActionbar(player, "");
|
||||
|
||||
+6
-43
@@ -17,15 +17,12 @@
|
||||
|
||||
package net.momirealms.customnameplates.paper.mechanic.bossbar;
|
||||
|
||||
import com.comphenix.protocol.PacketType;
|
||||
import com.comphenix.protocol.events.InternalStructure;
|
||||
import com.comphenix.protocol.events.PacketContainer;
|
||||
import net.momirealms.customnameplates.paper.adventure.AdventureManagerImpl;
|
||||
import net.momirealms.customnameplates.paper.mechanic.misc.PacketManager;
|
||||
import net.momirealms.customnameplates.paper.util.ReflectionUtils;
|
||||
import net.momirealms.sparrow.heart.SparrowHeart;
|
||||
import net.momirealms.sparrow.heart.feature.bossbar.BossBarColor;
|
||||
import net.momirealms.sparrow.heart.feature.bossbar.BossBarOverlay;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.UUID;
|
||||
|
||||
public class BossBar {
|
||||
@@ -46,17 +43,17 @@ public class BossBar {
|
||||
}
|
||||
|
||||
public void show() {
|
||||
PacketManager.getInstance().send(owner, getCreatePacket());
|
||||
SparrowHeart.getInstance().createBossBar(owner, uuid, AdventureManagerImpl.getInstance().getJsonComponentFromMiniMessage(latestMiniMessage), BossBarColor.valueOf(barColor.name()), BossBarOverlay.valueOf(overlay.name()), 0f, false, false, false);
|
||||
this.visible = true;
|
||||
}
|
||||
|
||||
public void hide() {
|
||||
PacketManager.getInstance().send(owner, getRemovePacket());
|
||||
SparrowHeart.getInstance().removeBossBar(owner, uuid);
|
||||
this.visible = false;
|
||||
}
|
||||
|
||||
public void update() {
|
||||
PacketManager.getInstance().send(owner, getUpdatePacket());
|
||||
SparrowHeart.getInstance().updateBossBarName(owner, uuid, AdventureManagerImpl.getInstance().getJsonComponentFromMiniMessage(latestMiniMessage));
|
||||
}
|
||||
|
||||
public boolean isVisible() {
|
||||
@@ -66,38 +63,4 @@ public class BossBar {
|
||||
public void setMiniMessageText(String text) {
|
||||
latestMiniMessage = text;
|
||||
}
|
||||
|
||||
private PacketContainer getCreatePacket() {
|
||||
PacketContainer packet = new PacketContainer(PacketType.Play.Server.BOSS);
|
||||
packet.getModifier().write(0, uuid);
|
||||
InternalStructure internalStructure = packet.getStructures().read(1);
|
||||
internalStructure.getChatComponents().write(0, AdventureManagerImpl.getInstance().getWrappedChatComponentFromMiniMessage(latestMiniMessage));
|
||||
internalStructure.getFloat().write(0,1F);
|
||||
internalStructure.getEnumModifier(BarColor.class, 2).write(0, barColor);
|
||||
internalStructure.getEnumModifier(Overlay.class, 3).write(0, overlay);
|
||||
internalStructure.getModifier().write(4, false);
|
||||
internalStructure.getModifier().write(5, false);
|
||||
internalStructure.getModifier().write(6, false);
|
||||
return packet;
|
||||
}
|
||||
|
||||
private PacketContainer getUpdatePacket() {
|
||||
PacketContainer packet = new PacketContainer(PacketType.Play.Server.BOSS);
|
||||
packet.getModifier().write(0, uuid);
|
||||
try {
|
||||
Object chatComponent = AdventureManagerImpl.getInstance().getIChatComponentFromMiniMessage(latestMiniMessage);
|
||||
Object updatePacket = ReflectionUtils.getUpdateConstructor().newInstance(chatComponent);
|
||||
packet.getModifier().write(1, updatePacket);
|
||||
} catch (InvocationTargetException | IllegalAccessException | InstantiationException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
return packet;
|
||||
}
|
||||
|
||||
private PacketContainer getRemovePacket() {
|
||||
PacketContainer packet = new PacketContainer(PacketType.Play.Server.BOSS);
|
||||
packet.getModifier().write(0, uuid);
|
||||
packet.getModifier().write(1, ReflectionUtils.getRemoveBossBarPacket());
|
||||
return packet;
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -98,7 +98,7 @@ public class BossBarReceiver {
|
||||
if (this.bossBars[j].left().isShown())
|
||||
this.bossBars[j].right().hide();
|
||||
|
||||
controller.initialize();
|
||||
controller.initialize(condition);
|
||||
pair.right().setMiniMessageText(pair.left().getLatestContent());
|
||||
pair.right().show();
|
||||
|
||||
|
||||
+121
-33
@@ -19,16 +19,22 @@ package net.momirealms.customnameplates.paper.mechanic.bubble;
|
||||
|
||||
import me.clip.placeholderapi.PlaceholderAPI;
|
||||
import net.kyori.adventure.text.minimessage.MiniMessage;
|
||||
import net.momirealms.customnameplates.api.CustomNameplatesPlugin;
|
||||
import net.momirealms.customnameplates.api.data.OnlineUser;
|
||||
import net.momirealms.customnameplates.api.event.BubblesSpawnEvent;
|
||||
import net.momirealms.customnameplates.api.event.NameplateDataLoadEvent;
|
||||
import net.momirealms.customnameplates.api.manager.BubbleManager;
|
||||
import net.momirealms.customnameplates.api.manager.RequirementManager;
|
||||
import net.momirealms.customnameplates.api.mechanic.bubble.Bubble;
|
||||
import net.momirealms.customnameplates.api.mechanic.bubble.ChannelMode;
|
||||
import net.momirealms.customnameplates.api.mechanic.bubble.provider.AbstractChatProvider;
|
||||
import net.momirealms.customnameplates.api.mechanic.character.CharacterArranger;
|
||||
import net.momirealms.customnameplates.api.mechanic.character.ConfiguredChar;
|
||||
import net.momirealms.customnameplates.api.mechanic.tag.unlimited.EntityTagPlayer;
|
||||
import net.momirealms.customnameplates.api.mechanic.tag.unlimited.EntityTagEntity;
|
||||
import net.momirealms.customnameplates.api.mechanic.tag.unlimited.StaticTextEntity;
|
||||
import net.momirealms.customnameplates.api.mechanic.tag.unlimited.StaticTextTagSetting;
|
||||
import net.momirealms.customnameplates.api.requirement.Condition;
|
||||
import net.momirealms.customnameplates.api.requirement.Requirement;
|
||||
import net.momirealms.customnameplates.api.util.FontUtils;
|
||||
import net.momirealms.customnameplates.api.util.LogUtils;
|
||||
import net.momirealms.customnameplates.paper.CustomNameplatesPluginImpl;
|
||||
@@ -36,29 +42,28 @@ import net.momirealms.customnameplates.paper.adventure.AdventureManagerImpl;
|
||||
import net.momirealms.customnameplates.paper.mechanic.bubble.image.ImageParser;
|
||||
import net.momirealms.customnameplates.paper.mechanic.bubble.image.ItemsAdderImageImpl;
|
||||
import net.momirealms.customnameplates.paper.mechanic.bubble.image.OraxenImageImpl;
|
||||
import net.momirealms.customnameplates.paper.mechanic.bubble.listener.AbstractChatListener;
|
||||
import net.momirealms.customnameplates.paper.mechanic.bubble.listener.AsyncChatListener;
|
||||
import net.momirealms.customnameplates.paper.mechanic.bubble.listener.TrChatListener;
|
||||
import net.momirealms.customnameplates.paper.mechanic.bubble.listener.VentureChatListener;
|
||||
import net.momirealms.customnameplates.paper.mechanic.bubble.provider.*;
|
||||
import net.momirealms.customnameplates.paper.setting.CNConfig;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.GameMode;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.HandlerList;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.plugin.PluginManager;
|
||||
import org.bukkit.potion.PotionEffectType;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class BubbleManagerImpl implements BubbleManager {
|
||||
public class BubbleManagerImpl implements BubbleManager, Listener {
|
||||
|
||||
private AbstractChatListener chatListener;
|
||||
private AbstractChatProvider chatProvider;
|
||||
private AbstractChatProvider customProvider;
|
||||
private ImageParser imageParser;
|
||||
private final HashMap<String, Bubble> bubbleMap;
|
||||
private final CustomNameplatesPluginImpl plugin;
|
||||
@@ -75,6 +80,8 @@ public class BubbleManagerImpl implements BubbleManager {
|
||||
private int lengthPerLine;
|
||||
private int subStringIndex;
|
||||
private String[] blacklistChannels;
|
||||
private ChannelMode channelMode;
|
||||
private Requirement[] requirements;
|
||||
|
||||
public BubbleManagerImpl(CustomNameplatesPluginImpl plugin) {
|
||||
this.plugin = plugin;
|
||||
@@ -90,18 +97,21 @@ public class BubbleManagerImpl implements BubbleManager {
|
||||
if (!CNConfig.bubbleModule) return;
|
||||
this.loadConfig();
|
||||
this.loadBubbles();
|
||||
this.registerListener();
|
||||
this.registerChatProvider();
|
||||
this.registerImageParser();
|
||||
Bukkit.getPluginManager().registerEvents(this, plugin);
|
||||
}
|
||||
|
||||
public void unload() {
|
||||
this.imageParser = null;
|
||||
this.bubbleMap.clear();
|
||||
if (chatListener != null) HandlerList.unregisterAll(chatListener);
|
||||
if (chatProvider != null) chatProvider.unregister();
|
||||
HandlerList.unregisterAll(this);
|
||||
}
|
||||
|
||||
private void loadConfig() {
|
||||
YamlConfiguration config = plugin.getConfig("configs" + File.separator + "bubble.yml");
|
||||
updateConfigFile(config);
|
||||
defaultBubble = config.getString("default-bubbles", "chat");
|
||||
prefix = config.getString("text-prefix", "");
|
||||
suffix = config.getString("text-suffix", "");
|
||||
@@ -115,6 +125,23 @@ public class BubbleManagerImpl implements BubbleManager {
|
||||
lengthPerLine = config.getInt("characters-per-line", 30);
|
||||
startFormat = config.getString("default-format.start", "<gradient:#F5F5F5:#E1FFFF:#F5F5F5><u>");
|
||||
endFormat = config.getString("default-format.end", "<!u></gradient>");
|
||||
channelMode = ChannelMode.valueOf(config.getString("channel-mode","all").toUpperCase(Locale.ENGLISH));
|
||||
requirements = plugin.getRequirementManager().getRequirements(config.getConfigurationSection("requirements"));
|
||||
}
|
||||
|
||||
private void updateConfigFile(YamlConfiguration config) {
|
||||
try {
|
||||
if (!config.contains("requirements")) {
|
||||
ConfigurationSection section = config.createSection("requirements");
|
||||
section.set("!gamemode", "spectator");
|
||||
section.set("permission", "bubbles.use");
|
||||
section.set("self-disguised", false);
|
||||
section.set("potion-effect", "INVISIBILITY<0");
|
||||
config.save(new File(plugin.getDataFolder(), "configs" + File.separator + "bubble.yml"));
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private void registerImageParser() {
|
||||
@@ -126,16 +153,49 @@ public class BubbleManagerImpl implements BubbleManager {
|
||||
}
|
||||
}
|
||||
|
||||
private void registerListener() {
|
||||
PluginManager pluginManager = Bukkit.getPluginManager();
|
||||
if (CNConfig.trChatChannel) {
|
||||
this.chatListener = new TrChatListener(this);
|
||||
private void registerChatProvider() {
|
||||
if (this.customProvider != null) {
|
||||
this.chatProvider = customProvider;
|
||||
} else if (CNConfig.trChatChannel) {
|
||||
this.chatProvider = new TrChatProvider(this);
|
||||
} else if (CNConfig.ventureChatChannel) {
|
||||
this.chatListener = new VentureChatListener(this);
|
||||
this.chatProvider = new VentureChatProvider(this);
|
||||
} else if (CNConfig.huskChatChannel) {
|
||||
this.chatProvider = new HuskChatProvider(this);
|
||||
} else if (CNConfig.carbonChatChannel) {
|
||||
this.chatProvider = new CarbonChatProvider(this);
|
||||
} else if (CNConfig.advancedChatChannel) {
|
||||
this.chatProvider = new AdvancedChatProvider(this);
|
||||
} else {
|
||||
this.chatListener = new AsyncChatListener(this);
|
||||
try {
|
||||
Class.forName("io.papermc.paper.event.player.AsyncChatEvent");
|
||||
this.chatProvider = new PaperAsyncChatProvider(this);
|
||||
} catch (ClassNotFoundException e) {
|
||||
this.chatProvider = new AsyncChatProvider(this);
|
||||
}
|
||||
}
|
||||
pluginManager.registerEvents(chatListener, plugin);
|
||||
this.chatProvider.register();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setCustomChatProvider(AbstractChatProvider provider) {
|
||||
if (this.customProvider != null)
|
||||
return false;
|
||||
this.customProvider = provider;
|
||||
if (chatProvider != null) chatProvider.unregister();
|
||||
this.registerChatProvider();
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeCustomChatProvider() {
|
||||
if (this.customProvider != null) {
|
||||
this.customProvider.unregister();
|
||||
this.customProvider = null;
|
||||
this.registerChatProvider();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void loadBubbles() {
|
||||
@@ -208,11 +268,22 @@ public class BubbleManagerImpl implements BubbleManager {
|
||||
return this.bubbleMap.remove(key) != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChat(Player player, String text) {
|
||||
if ( player.getGameMode() == GameMode.SPECTATOR
|
||||
|| player.hasPotionEffect(PotionEffectType.INVISIBILITY)
|
||||
|| !player.hasPermission("bubbles.use")
|
||||
) return;
|
||||
onChat(player, text, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChat(Player player, String text, String channel) {
|
||||
if (!RequirementManager.isRequirementMet(new Condition(player), requirements)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (Bukkit.isPrimaryThread()) {
|
||||
String finalText = text;
|
||||
CustomNameplatesPlugin.get().getScheduler().runTaskAsync(() -> onChat(player, finalText));
|
||||
return;
|
||||
}
|
||||
|
||||
var optionalUser = plugin.getStorageManager().getOnlineUser(player.getUniqueId());
|
||||
if (optionalUser.isEmpty()) {
|
||||
@@ -258,14 +329,14 @@ public class BubbleManagerImpl implements BubbleManager {
|
||||
int finalIndex = i;
|
||||
String finalBubble = bubble;
|
||||
plugin.getScheduler().runTaskAsyncLater(
|
||||
() -> sendBubble(player, split[finalIndex], bubbleConfig, finalBubble),
|
||||
() -> sendBubble(player, split[finalIndex], bubbleConfig, finalBubble, channel),
|
||||
(long) i * 250 + 100,
|
||||
TimeUnit.MILLISECONDS
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private void sendBubble(Player player, String text, Bubble bubbleConfig, String key) {
|
||||
private void sendBubble(Player player, String text, Bubble bubbleConfig, String key, @Nullable String channel) {
|
||||
if (key.equals("none")) {
|
||||
text = startFormat + PlaceholderAPI.setPlaceholders(player, prefix) + text + PlaceholderAPI.setPlaceholders(player, suffix) + endFormat;
|
||||
} else {
|
||||
@@ -273,26 +344,43 @@ public class BubbleManagerImpl implements BubbleManager {
|
||||
int width = FontUtils.getTextWidth(text);
|
||||
text = bubbleConfig.getPrefixWithFont(width) + text + bubbleConfig.getSuffixWithFont(width);
|
||||
}
|
||||
EntityTagPlayer tagPlayer = plugin.getNameplateManager().getUnlimitedTagManager().createOrGetTagForPlayer(player);
|
||||
if (tagPlayer == null)
|
||||
|
||||
EntityTagEntity tagEntity = plugin.getNameplateManager().getUnlimitedTagManager().createOrGetTagForEntity(player);
|
||||
if (tagEntity == null)
|
||||
return;
|
||||
|
||||
StaticTextEntity entity = tagPlayer.addTag(StaticTextTagSetting.builder()
|
||||
.leaveRule((p, e) -> true)
|
||||
.comeRule((p, e) -> true)
|
||||
StaticTextEntity entity = tagEntity.addTag(StaticTextTagSetting.builder()
|
||||
.leaveRule((receiver, owner) -> true)
|
||||
.comeRule((receiver, owner) -> {
|
||||
if ((owner instanceof Player sender) && chatProvider.isIgnoring(sender, receiver)) {
|
||||
return false;
|
||||
}
|
||||
switch (channelMode) {
|
||||
case ALL -> {
|
||||
return true;
|
||||
}
|
||||
case JOINED -> {
|
||||
return channel == null || chatProvider.hasJoinedChannel(receiver, channel);
|
||||
}
|
||||
case CAN_JOIN -> {
|
||||
return channel == null || chatProvider.canJoinChannel(receiver, channel);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
})
|
||||
.verticalOffset(yOffset)
|
||||
.defaultText(text)
|
||||
.plugin("bubble")
|
||||
.id("bubble")
|
||||
.build());
|
||||
|
||||
for (StaticTextEntity bubble : tagPlayer.getStaticTags()) {
|
||||
if (bubble.getPlugin().equals("bubble")) {
|
||||
for (StaticTextEntity bubble : tagEntity.getStaticTags()) {
|
||||
if (bubble.getID().equals("bubble")) {
|
||||
bubble.setOffset(bubble.getOffset() + lineSpace);
|
||||
}
|
||||
}
|
||||
|
||||
plugin.getScheduler().runTaskAsyncLater(() -> {
|
||||
tagPlayer.removeTag(entity);
|
||||
tagEntity.removeTag(entity);
|
||||
}, stayTime, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
|
||||
-35
@@ -1,35 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) <2022> <XiaoMoMi>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package net.momirealms.customnameplates.paper.mechanic.bubble.listener;
|
||||
|
||||
import net.momirealms.customnameplates.paper.mechanic.bubble.BubbleManagerImpl;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.player.AsyncPlayerChatEvent;
|
||||
|
||||
public class AsyncChatListener extends AbstractChatListener {
|
||||
|
||||
public AsyncChatListener(BubbleManagerImpl chatBubblesManager) {
|
||||
super(chatBubblesManager);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onChat(AsyncPlayerChatEvent event) {
|
||||
if (event.isCancelled()) return;
|
||||
chatBubblesManager.onChat(event.getPlayer(), event.getMessage());
|
||||
}
|
||||
}
|
||||
-43
@@ -1,43 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) <2022> <XiaoMoMi>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package net.momirealms.customnameplates.paper.mechanic.bubble.listener;
|
||||
|
||||
import me.arasple.mc.trchat.api.event.TrChatEvent;
|
||||
import me.arasple.mc.trchat.module.display.channel.Channel;
|
||||
import net.momirealms.customnameplates.api.CustomNameplatesPlugin;
|
||||
import net.momirealms.customnameplates.paper.mechanic.bubble.BubbleManagerImpl;
|
||||
import org.bukkit.event.EventHandler;
|
||||
|
||||
public class TrChatListener extends AbstractChatListener {
|
||||
|
||||
public TrChatListener(BubbleManagerImpl chatBubblesManager) {
|
||||
super(chatBubblesManager);
|
||||
}
|
||||
|
||||
@EventHandler (ignoreCancelled = true)
|
||||
public void onTrChat(TrChatEvent event) {
|
||||
if (!event.getForward()) return;
|
||||
Channel channelName = event.getChannel();
|
||||
for (String channel : chatBubblesManager.getBlacklistChannels()) {
|
||||
if (channelName.equals(channel)) return;
|
||||
}
|
||||
CustomNameplatesPlugin.get().getScheduler().runTaskAsync(() -> {
|
||||
chatBubblesManager.onChat(event.getSession().getPlayer(), event.getMessage());
|
||||
});
|
||||
}
|
||||
}
|
||||
-46
@@ -1,46 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) <2022> <XiaoMoMi>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package net.momirealms.customnameplates.paper.mechanic.bubble.listener;
|
||||
|
||||
import mineverse.Aust1n46.chat.api.MineverseChatPlayer;
|
||||
import mineverse.Aust1n46.chat.api.events.VentureChatEvent;
|
||||
import net.momirealms.customnameplates.api.CustomNameplatesPlugin;
|
||||
import net.momirealms.customnameplates.paper.mechanic.bubble.BubbleManagerImpl;
|
||||
import org.bukkit.event.EventHandler;
|
||||
|
||||
public class VentureChatListener extends AbstractChatListener {
|
||||
|
||||
public VentureChatListener(BubbleManagerImpl chatBubblesManager) {
|
||||
super(chatBubblesManager);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onVentureChat(VentureChatEvent event) {
|
||||
String channelName = event.getChannel().getName();
|
||||
for (String channel : chatBubblesManager.getBlacklistChannels()) {
|
||||
if (channelName.equals(channel)) return;
|
||||
}
|
||||
final MineverseChatPlayer chatPlayer = event.getMineverseChatPlayer();
|
||||
if (chatPlayer == null) {
|
||||
return;
|
||||
}
|
||||
CustomNameplatesPlugin.get().getScheduler().runTaskAsync(() -> {
|
||||
chatBubblesManager.onChat(chatPlayer.getPlayer(), event.getChat());
|
||||
});
|
||||
}
|
||||
}
|
||||
+88
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* Copyright (C) <2022> <XiaoMoMi>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package net.momirealms.customnameplates.paper.mechanic.bubble.provider;
|
||||
|
||||
import net.advancedplugins.chat.api.AdvancedChannelChatEvent;
|
||||
import net.advancedplugins.chat.api.AdvancedChatAPI;
|
||||
import net.advancedplugins.chat.channel.ChatChannel;
|
||||
import net.momirealms.customnameplates.api.CustomNameplatesPlugin;
|
||||
import net.momirealms.customnameplates.api.manager.BubbleManager;
|
||||
import net.momirealms.customnameplates.api.mechanic.bubble.provider.AbstractChatProvider;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.HandlerList;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class AdvancedChatProvider extends AbstractChatProvider {
|
||||
|
||||
public AdvancedChatProvider(BubbleManager chatBubblesManager) {
|
||||
super(chatBubblesManager);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void register() {
|
||||
Bukkit.getPluginManager().registerEvents(this, CustomNameplatesPlugin.get());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unregister() {
|
||||
HandlerList.unregisterAll(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasJoinedChannel(Player player, String channelID) {
|
||||
ChatChannel chatChannel = AdvancedChatAPI.getApi().getPlayerChatChannel(player.getUniqueId());
|
||||
if (chatChannel == null) {
|
||||
return false;
|
||||
}
|
||||
return chatChannel.getSectionName().equals(channelID);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canJoinChannel(Player player, String channelID) {
|
||||
List<ChatChannel> channelList = AdvancedChatAPI.getApi().getAllowedChatChannels(player);
|
||||
for (ChatChannel chatChannel : channelList) {
|
||||
if (chatChannel.getSectionName().equals(channelID)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isIgnoring(Player sender, Player receiver) {
|
||||
return AdvancedChatAPI.getApi().getIgnoredPlayers(receiver).contains(sender.getName());
|
||||
}
|
||||
|
||||
@EventHandler (ignoreCancelled = true)
|
||||
public void onAdvancedChat(AdvancedChannelChatEvent event) {
|
||||
String channel = event.getChannel().getSectionName();
|
||||
for (String black : chatBubblesManager.getBlacklistChannels()) {
|
||||
if (channel.equals(black)) return;
|
||||
}
|
||||
if (event.getSender() instanceof Player player) {
|
||||
if (!player.isOnline())
|
||||
return;
|
||||
CustomNameplatesPlugin.get().getScheduler().runTaskAsync(() -> {
|
||||
chatBubblesManager.onChat(player, event.getMessage(), channel);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
+65
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright (C) <2022> <XiaoMoMi>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package net.momirealms.customnameplates.paper.mechanic.bubble.provider;
|
||||
|
||||
import net.momirealms.customnameplates.api.CustomNameplatesPlugin;
|
||||
import net.momirealms.customnameplates.api.manager.BubbleManager;
|
||||
import net.momirealms.customnameplates.api.mechanic.bubble.provider.AbstractChatProvider;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.HandlerList;
|
||||
import org.bukkit.event.player.AsyncPlayerChatEvent;
|
||||
|
||||
public class AsyncChatProvider extends AbstractChatProvider {
|
||||
|
||||
public AsyncChatProvider(BubbleManager chatBubblesManager) {
|
||||
super(chatBubblesManager);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void register() {
|
||||
Bukkit.getPluginManager().registerEvents(this, CustomNameplatesPlugin.get());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unregister() {
|
||||
HandlerList.unregisterAll(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasJoinedChannel(Player player, String channelID) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canJoinChannel(Player player, String channelID) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isIgnoring(Player sender, Player receiver) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// This event is not async sometimes
|
||||
@EventHandler (ignoreCancelled = true)
|
||||
public void onChat(AsyncPlayerChatEvent event) {
|
||||
CustomNameplatesPlugin.get().getScheduler().runTaskAsync(() -> chatBubblesManager.onChat(event.getPlayer(), event.getMessage()));
|
||||
}
|
||||
}
|
||||
+169
@@ -0,0 +1,169 @@
|
||||
/*
|
||||
* Copyright (C) <2022> <XiaoMoMi>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package net.momirealms.customnameplates.paper.mechanic.bubble.provider;
|
||||
|
||||
import net.draycia.carbon.api.CarbonChat;
|
||||
import net.draycia.carbon.api.channels.ChannelRegistry;
|
||||
import net.draycia.carbon.api.channels.ChatChannel;
|
||||
import net.draycia.carbon.api.event.CarbonEventSubscription;
|
||||
import net.draycia.carbon.api.event.events.CarbonChatEvent;
|
||||
import net.draycia.carbon.api.users.CarbonPlayer;
|
||||
import net.momirealms.customnameplates.api.CustomNameplatesPlugin;
|
||||
import net.momirealms.customnameplates.api.manager.BubbleManager;
|
||||
import net.momirealms.customnameplates.api.mechanic.bubble.provider.AbstractChatProvider;
|
||||
import net.momirealms.customnameplates.api.util.LogUtils;
|
||||
import net.momirealms.customnameplates.paper.util.ReflectionUtils;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.UUID;
|
||||
|
||||
public class CarbonChatProvider extends AbstractChatProvider {
|
||||
|
||||
private final CarbonChat api;
|
||||
private CarbonEventSubscription<CarbonChatEvent> subscription;
|
||||
private Method originalMessageMethod;
|
||||
private Method channelKeyMethod;
|
||||
private Method getChannelByKeyMethod;
|
||||
|
||||
public CarbonChatProvider(BubbleManager chatBubblesManager) {
|
||||
super(chatBubblesManager);
|
||||
this.api = net.draycia.carbon.api.CarbonChatProvider.carbonChat();
|
||||
try {
|
||||
this.originalMessageMethod = CarbonChatEvent.class.getMethod("originalMessage");
|
||||
this.channelKeyMethod = ChatChannel.class.getMethod("key");
|
||||
this.getChannelByKeyMethod = ChannelRegistry.class.getMethod("channel", ReflectionUtils.getKeyClass());
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void register() {
|
||||
subscription = api.eventHandler().subscribe(CarbonChatEvent.class, event -> {
|
||||
if (event.cancelled())
|
||||
return;
|
||||
ChatChannel chatChannel = event.chatChannel();
|
||||
Object key = getChannelKey(chatChannel);
|
||||
if (key == null) return;
|
||||
String channel = ReflectionUtils.getKeyAsString(key);
|
||||
for (String black : chatBubblesManager.getBlacklistChannels()) {
|
||||
if (channel.equals(black)) return;
|
||||
}
|
||||
Player player = Bukkit.getPlayer(event.sender().uuid());
|
||||
if (player == null || !player.isOnline())
|
||||
return;
|
||||
Object component = getComponentFromEvent(event);
|
||||
String message = ReflectionUtils.getMiniMessageTextFromNonShadedComponent(component);
|
||||
CustomNameplatesPlugin.get().getScheduler().runTaskAsync(() -> chatBubblesManager.onChat(player, message, channel));
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unregister() {
|
||||
if (subscription != null) {
|
||||
subscription.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasJoinedChannel(Player player, String channelID) {
|
||||
CarbonPlayer cPlayer = null;
|
||||
for (CarbonPlayer carbonPlayer : api.server().players()) {
|
||||
if (carbonPlayer.uuid().equals(player.getUniqueId())) {
|
||||
cPlayer = carbonPlayer;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (cPlayer == null) {
|
||||
return false;
|
||||
}
|
||||
ChatChannel selectedChannel = cPlayer.selectedChannel();
|
||||
ChatChannel currentChannel = selectedChannel != null ? selectedChannel : api.channelRegistry().defaultChannel();
|
||||
Object key = getChannelKey(currentChannel);
|
||||
String str = ReflectionUtils.getKeyAsString(key);
|
||||
return str.equals(channelID);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canJoinChannel(Player player, String channelID) {
|
||||
ChannelRegistry registry = api.channelRegistry();
|
||||
Object key = ReflectionUtils.getKerFromString(channelID);
|
||||
if (key == null) {
|
||||
return false;
|
||||
}
|
||||
ChatChannel channel = null;
|
||||
try {
|
||||
channel = (ChatChannel) getChannelByKeyMethod.invoke(registry, key);
|
||||
} catch (IllegalAccessException | InvocationTargetException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
if (channel == null) {
|
||||
LogUtils.warn("Channel " + channelID + " doesn't exist.");
|
||||
return false;
|
||||
}
|
||||
String perm = channel.permission();
|
||||
if (perm == null) {
|
||||
return true;
|
||||
}
|
||||
return player.hasPermission(perm);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isIgnoring(Player sender, Player receiver) {
|
||||
CarbonPlayer sPlayer = carbonPlayer(sender.getUniqueId());
|
||||
CarbonPlayer rPlayer = carbonPlayer(receiver.getUniqueId());
|
||||
if (sPlayer == null || rPlayer == null) {
|
||||
return false;
|
||||
}
|
||||
return rPlayer.ignoring(sPlayer.uuid());
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private CarbonPlayer carbonPlayer(UUID uuid) {
|
||||
CarbonPlayer carbonPlayer = null;
|
||||
for (CarbonPlayer cPlayer : api.server().players()) {
|
||||
if (cPlayer.uuid().equals(uuid)) {
|
||||
carbonPlayer = cPlayer;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return carbonPlayer;
|
||||
}
|
||||
|
||||
private Object getChannelKey(ChatChannel channel) {
|
||||
try {
|
||||
return this.channelKeyMethod.invoke(channel);
|
||||
} catch (InvocationTargetException | IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private Object getComponentFromEvent(CarbonChatEvent event) {
|
||||
try {
|
||||
return this.originalMessageMethod.invoke(event);
|
||||
} catch (InvocationTargetException | IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return ReflectionUtils.getEmptyComponent();
|
||||
}
|
||||
}
|
||||
+90
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Copyright (C) <2022> <XiaoMoMi>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package net.momirealms.customnameplates.paper.mechanic.bubble.provider;
|
||||
|
||||
import net.momirealms.customnameplates.api.CustomNameplatesPlugin;
|
||||
import net.momirealms.customnameplates.api.manager.BubbleManager;
|
||||
import net.momirealms.customnameplates.api.mechanic.bubble.provider.AbstractChatProvider;
|
||||
import net.momirealms.customnameplates.api.util.LogUtils;
|
||||
import net.william278.huskchat.bukkit.BukkitHuskChat;
|
||||
import net.william278.huskchat.bukkit.event.ChatMessageEvent;
|
||||
import net.william278.huskchat.channel.Channel;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.HandlerList;
|
||||
|
||||
public class HuskChatProvider extends AbstractChatProvider {
|
||||
|
||||
public HuskChatProvider(BubbleManager chatBubblesManager) {
|
||||
super(chatBubblesManager);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void register() {
|
||||
Bukkit.getPluginManager().registerEvents(this, CustomNameplatesPlugin.get());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unregister() {
|
||||
HandlerList.unregisterAll(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasJoinedChannel(Player player, String channelID) {
|
||||
String channel = BukkitHuskChat.getInstance().getPlayerCache().getPlayerChannel(player.getUniqueId());
|
||||
if (channel == null) {
|
||||
LogUtils.warn("Channel " + channelID + " doesn't exist.");
|
||||
return false;
|
||||
}
|
||||
return channel.equals(channelID);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canJoinChannel(Player player, String channelID) {
|
||||
Channel channel = BukkitHuskChat.getInstance().getSettings().getChannels().get(channelID);
|
||||
if (channel == null) {
|
||||
LogUtils.warn("Channel " + channelID + " doesn't exist.");
|
||||
return false;
|
||||
}
|
||||
String receivePerm = channel.getReceivePermission();
|
||||
if (receivePerm == null) {
|
||||
return true;
|
||||
}
|
||||
return player.hasPermission(receivePerm);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isIgnoring(Player sender, Player receiver) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@EventHandler (ignoreCancelled = true)
|
||||
public void onHuskChat(ChatMessageEvent event) {
|
||||
String channel = event.getChannelId();
|
||||
for (String black : chatBubblesManager.getBlacklistChannels()) {
|
||||
if (channel.equals(black)) return;
|
||||
}
|
||||
Player player = Bukkit.getPlayer(event.getSender().getUuid());
|
||||
if (player == null || !player.isOnline())
|
||||
return;
|
||||
CustomNameplatesPlugin.get().getScheduler().runTaskAsync(() -> {
|
||||
chatBubblesManager.onChat(player, event.getMessage(), channel);
|
||||
});
|
||||
}
|
||||
}
|
||||
+86
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* Copyright (C) <2022> <XiaoMoMi>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package net.momirealms.customnameplates.paper.mechanic.bubble.provider;
|
||||
|
||||
import io.papermc.paper.event.player.AsyncChatEvent;
|
||||
import net.momirealms.customnameplates.api.CustomNameplatesPlugin;
|
||||
import net.momirealms.customnameplates.api.manager.BubbleManager;
|
||||
import net.momirealms.customnameplates.api.mechanic.bubble.provider.AbstractChatProvider;
|
||||
import net.momirealms.customnameplates.paper.util.ReflectionUtils;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.HandlerList;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
public class PaperAsyncChatProvider extends AbstractChatProvider {
|
||||
|
||||
private Method messageMethod;
|
||||
|
||||
public PaperAsyncChatProvider(BubbleManager chatBubblesManager) {
|
||||
super(chatBubblesManager);
|
||||
try {
|
||||
this.messageMethod = AsyncChatEvent.class.getMethod("message");
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void register() {
|
||||
Bukkit.getPluginManager().registerEvents(this, CustomNameplatesPlugin.get());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unregister() {
|
||||
HandlerList.unregisterAll(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasJoinedChannel(Player player, String channelID) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canJoinChannel(Player player, String channelID) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isIgnoring(Player sender, Player receiver) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@EventHandler (ignoreCancelled = true)
|
||||
public void onChat(AsyncChatEvent event) {
|
||||
Object component = getComponentFromEvent(event);
|
||||
String message = ReflectionUtils.getMiniMessageTextFromNonShadedComponent(component);
|
||||
CustomNameplatesPlugin.get().getScheduler().runTaskAsync(() -> chatBubblesManager.onChat(event.getPlayer(), message));
|
||||
}
|
||||
|
||||
private Object getComponentFromEvent(AsyncChatEvent event) {
|
||||
try {
|
||||
return this.messageMethod.invoke(event);
|
||||
} catch (InvocationTargetException | IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return ReflectionUtils.getEmptyComponent();
|
||||
}
|
||||
}
|
||||
+92
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Copyright (C) <2022> <XiaoMoMi>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package net.momirealms.customnameplates.paper.mechanic.bubble.provider;
|
||||
|
||||
import me.arasple.mc.trchat.TrChat;
|
||||
import me.arasple.mc.trchat.api.event.TrChatEvent;
|
||||
import me.arasple.mc.trchat.module.display.channel.Channel;
|
||||
import me.arasple.mc.trchat.module.internal.filter.FilteredObject;
|
||||
import me.arasple.mc.trchat.taboolib.platform.BukkitAdapter;
|
||||
import net.momirealms.customnameplates.api.CustomNameplatesPlugin;
|
||||
import net.momirealms.customnameplates.api.manager.BubbleManager;
|
||||
import net.momirealms.customnameplates.api.mechanic.bubble.provider.AbstractChatProvider;
|
||||
import net.momirealms.customnameplates.api.util.LogUtils;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.HandlerList;
|
||||
|
||||
public class TrChatProvider extends AbstractChatProvider {
|
||||
|
||||
private final BukkitAdapter adapter;
|
||||
|
||||
public TrChatProvider(BubbleManager chatBubblesManager) {
|
||||
super(chatBubblesManager);
|
||||
this.adapter = new BukkitAdapter();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void register() {
|
||||
Bukkit.getPluginManager().registerEvents(this, CustomNameplatesPlugin.get());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unregister() {
|
||||
HandlerList.unregisterAll(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasJoinedChannel(Player player, String channelID) {
|
||||
if (TrChat.INSTANCE.api().getChannelManager().getChannel(channelID) instanceof Channel channel) {
|
||||
return channel.getListeners().contains(player.getName());
|
||||
} else {
|
||||
LogUtils.warn("Channel " + channelID + " doesn't exist.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canJoinChannel(Player player, String channelID) {
|
||||
if (TrChat.INSTANCE.api().getChannelManager().getChannel(channelID) instanceof Channel channel) {
|
||||
String perm = channel.getSettings().getJoinPermission();
|
||||
return player.hasPermission(perm);
|
||||
} else {
|
||||
LogUtils.warn("Channel " + channelID + " doesn't exist.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isIgnoring(Player sender, Player receiver) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@EventHandler (ignoreCancelled = true)
|
||||
public void onTrChat(TrChatEvent event) {
|
||||
if (!event.getForward()) return;
|
||||
Channel channel = event.getChannel();
|
||||
String channelName = channel.getId();
|
||||
for (String black : chatBubblesManager.getBlacklistChannels()) {
|
||||
if (channelName.equals(black)) return;
|
||||
}
|
||||
FilteredObject object = TrChat.INSTANCE.api().getFilterManager().filter(event.getMessage(), adapter.adaptPlayer(event.getPlayer()), true);
|
||||
CustomNameplatesPlugin.get().getScheduler().runTaskAsync(() -> {
|
||||
chatBubblesManager.onChat(event.getSession().getPlayer(), object.getFiltered(), channelName);
|
||||
});
|
||||
}
|
||||
}
|
||||
+87
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* Copyright (C) <2022> <XiaoMoMi>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package net.momirealms.customnameplates.paper.mechanic.bubble.provider;
|
||||
|
||||
import mineverse.Aust1n46.chat.api.MineverseChatAPI;
|
||||
import mineverse.Aust1n46.chat.api.MineverseChatPlayer;
|
||||
import mineverse.Aust1n46.chat.api.events.VentureChatEvent;
|
||||
import mineverse.Aust1n46.chat.channel.ChatChannel;
|
||||
import net.momirealms.customnameplates.api.CustomNameplatesPlugin;
|
||||
import net.momirealms.customnameplates.api.manager.BubbleManager;
|
||||
import net.momirealms.customnameplates.api.mechanic.bubble.provider.AbstractChatProvider;
|
||||
import net.momirealms.customnameplates.api.util.LogUtils;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.HandlerList;
|
||||
|
||||
public class VentureChatProvider extends AbstractChatProvider {
|
||||
|
||||
public VentureChatProvider(BubbleManager chatBubblesManager) {
|
||||
super(chatBubblesManager);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void register() {
|
||||
Bukkit.getPluginManager().registerEvents(this, CustomNameplatesPlugin.get());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unregister() {
|
||||
HandlerList.unregisterAll(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasJoinedChannel(Player player, String channelID) {
|
||||
MineverseChatPlayer mcp = MineverseChatAPI.getOnlineMineverseChatPlayer(player);
|
||||
return mcp.getCurrentChannel().getName().equals(channelID);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canJoinChannel(Player player, String channelID) {
|
||||
ChatChannel channel = ChatChannel.getChannel(channelID);
|
||||
if (channel == null) {
|
||||
LogUtils.warn("Channel " + channelID + " doesn't exist.");
|
||||
return false;
|
||||
}
|
||||
if (channel.hasPermission()) {
|
||||
return player.hasPermission(channel.getPermission());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isIgnoring(Player sender, Player receiver) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@EventHandler (ignoreCancelled = true)
|
||||
public void onVentureChat(VentureChatEvent event) {
|
||||
String channelName = event.getChannel().getName();
|
||||
for (String channel : chatBubblesManager.getBlacklistChannels()) {
|
||||
if (channelName.equals(channel)) return;
|
||||
}
|
||||
final MineverseChatPlayer chatPlayer = event.getMineverseChatPlayer();
|
||||
if (chatPlayer == null) {
|
||||
return;
|
||||
}
|
||||
CustomNameplatesPlugin.get().getScheduler().runTaskAsync(() -> {
|
||||
chatBubblesManager.onChat(chatPlayer.getPlayer(), event.getChat(), channelName);
|
||||
});
|
||||
}
|
||||
}
|
||||
+74
-20
@@ -72,10 +72,12 @@ public class WidthManagerImpl implements WidthManager {
|
||||
private FontData NONLATIN_EUROPEAN_DATA;
|
||||
private FontData UNIFONT_DATA;
|
||||
private FontData UNICODE_DATA;
|
||||
private final HashSet<Integer> bitMapChars;
|
||||
|
||||
public WidthManagerImpl(CustomNameplatesPlugin plugin) {
|
||||
this.plugin = plugin;
|
||||
this.fontDataMap = new HashMap<>();
|
||||
this.bitMapChars = new HashSet<>();
|
||||
this.saveFontImages();
|
||||
this.cacheImageWidthIfNotCached();
|
||||
this.loadCachedFontData();
|
||||
@@ -96,6 +98,7 @@ public class WidthManagerImpl implements WidthManager {
|
||||
if (this.cacheSystem != null)
|
||||
this.cacheSystem.destroy();
|
||||
fontDataMap.clear();
|
||||
bitMapChars.clear();
|
||||
}
|
||||
|
||||
private void loadInternalConfigs() {
|
||||
@@ -158,6 +161,10 @@ public class WidthManagerImpl implements WidthManager {
|
||||
Key.of(CNConfig.namespace, "ascent_" + ascent), descentFont
|
||||
);
|
||||
}
|
||||
|
||||
this.bitMapChars.addAll(ASCII_DATA.getWidthData().keySet());
|
||||
this.bitMapChars.addAll(NONLATIN_EUROPEAN_DATA.getWidthData().keySet());
|
||||
this.bitMapChars.addAll(ACCENTED_DATA.getWidthData().keySet());
|
||||
}
|
||||
|
||||
private void loadUserConfigs() {
|
||||
@@ -176,6 +183,7 @@ public class WidthManagerImpl implements WidthManager {
|
||||
case "unifont" -> fontData.overrideWith(UNIFONT_DATA);
|
||||
}
|
||||
}
|
||||
boolean defaultFont = entry.getKey().equals("minecraft:default");
|
||||
ConfigurationSection customSection = innerSection.getConfigurationSection("values");
|
||||
if (customSection != null)
|
||||
for (Map.Entry<String, Object> innerEntry : customSection.getValues(false).entrySet()) {
|
||||
@@ -187,8 +195,12 @@ public class WidthManagerImpl implements WidthManager {
|
||||
continue;
|
||||
}
|
||||
fontData.registerCharWidth(stripped.charAt(0), (Integer) innerEntry.getValue());
|
||||
if (defaultFont)
|
||||
bitMapChars.add((int) stripped.charAt(0));
|
||||
} else if (key.length() == 1) {
|
||||
fontData.registerCharWidth(key.charAt(0), (Integer) innerEntry.getValue());
|
||||
if (defaultFont)
|
||||
bitMapChars.add((int) key.charAt(0));
|
||||
} else {
|
||||
LogUtils.warn("Illegal image format: " + key);
|
||||
}
|
||||
@@ -442,7 +454,9 @@ public class WidthManagerImpl implements WidthManager {
|
||||
}
|
||||
}
|
||||
}
|
||||
int charWidth = (int) (((double) (x_final - i * single) / single * 8) + 1);
|
||||
int pixels = x_final - i * single + 1;
|
||||
double times = (double) width / 128;
|
||||
int charWidth = (int) (pixels / times);
|
||||
yml.set(ConfigUtils.native2ascii(c), charWidth);
|
||||
i++;
|
||||
}
|
||||
@@ -501,7 +515,9 @@ public class WidthManagerImpl implements WidthManager {
|
||||
}
|
||||
}
|
||||
}
|
||||
int charWidth = (int) (((double) (x_final - i * single) / single * 8) + 1);
|
||||
int pixels = x_final - i * single + 1;
|
||||
double times = (double) width / 128;
|
||||
int charWidth = (int) (pixels / times);
|
||||
yml.set(ConfigUtils.native2ascii(c), charWidth);
|
||||
i++;
|
||||
}
|
||||
@@ -548,7 +564,10 @@ public class WidthManagerImpl implements WidthManager {
|
||||
}
|
||||
}
|
||||
}
|
||||
int charWidth = (int) (((double) (x_final - i * single) / single * 8) + 1);
|
||||
|
||||
int pixels = x_final - i * single + 1;
|
||||
double times = (double) width / 128;
|
||||
int charWidth = (int) (pixels / times);
|
||||
yml.set(ConfigUtils.native2ascii(c), charWidth);
|
||||
i++;
|
||||
}
|
||||
@@ -652,11 +671,12 @@ public class WidthManagerImpl implements WidthManager {
|
||||
char[] chars = ConfigUtils.convertUnicodeStringToChars(line);
|
||||
for (char c : chars) {
|
||||
int width = bufferedImage.getWidth();
|
||||
double times = (double) width / 144;
|
||||
int single = width / 16;
|
||||
int x_final = i * single;
|
||||
outer:
|
||||
for (int x = i * single; x < (i+1) * single; x++) {
|
||||
for (int y = j * single; y < (j+1) * single; y++) {
|
||||
for (int y = (int) (j * 12 * times); y < (j+1) * 12 * times; y++) {
|
||||
int rgb = bufferedImage.getRGB(x, y);
|
||||
int alpha = (rgb >> 24) & 0xff;
|
||||
if (alpha != 0) {
|
||||
@@ -665,7 +685,9 @@ public class WidthManagerImpl implements WidthManager {
|
||||
}
|
||||
}
|
||||
}
|
||||
int charWidth = (int) (((double) (x_final - i * single) / single * 8) + 1);
|
||||
|
||||
int pixels = x_final - i * single + 1;
|
||||
int charWidth = (int) (pixels / times);
|
||||
yml.set(ConfigUtils.native2ascii(c), charWidth);
|
||||
i++;
|
||||
}
|
||||
@@ -786,7 +808,9 @@ public class WidthManagerImpl implements WidthManager {
|
||||
}
|
||||
}
|
||||
}
|
||||
int charWidth = (int) (((double) (x_final - i * single) / single * 8) + 1);
|
||||
int pixels = x_final - i * single + 1;
|
||||
double times = (double) width / 128;
|
||||
int charWidth = (int) (pixels / times);
|
||||
yml.set(unicode, charWidth);
|
||||
i++;
|
||||
}
|
||||
@@ -846,8 +870,12 @@ public class WidthManagerImpl implements WidthManager {
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isNotReplacedUnifont(int codePoint) {
|
||||
return !bitMapChars.contains(codePoint);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean registerFontData(Key key, FontData fontData) {
|
||||
public boolean registerFontData(@NotNull Key key, @NotNull FontData fontData) {
|
||||
if (fontDataMap.containsKey(key)) {
|
||||
return false;
|
||||
}
|
||||
@@ -856,18 +884,18 @@ public class WidthManagerImpl implements WidthManager {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean unregisterFontData(Key key) {
|
||||
public boolean unregisterFontData(@NotNull Key key) {
|
||||
return fontDataMap.remove(key) != null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public FontData getFontData(Key key) {
|
||||
public FontData getFontData(@NotNull Key key) {
|
||||
return fontDataMap.get(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getTextWidth(String textWithTags) {
|
||||
public int getTextWidth(@NotNull String textWithTags) {
|
||||
return cacheSystem.getWidthFromCache(textWithTags);
|
||||
}
|
||||
|
||||
@@ -894,25 +922,47 @@ public class WidthManagerImpl implements WidthManager {
|
||||
text = AdventureManagerImpl.getInstance().legacyToMiniMessage(text);
|
||||
ElementNode node = (ElementNode) MiniMessage.miniMessage().deserializeToTree(text);
|
||||
ArrayList<Tuple<String, Key, Boolean>> list = new ArrayList<>();
|
||||
nodeToStringInfo(node, list, Key.of("minecraft", "default"), false);
|
||||
|
||||
Key defaultFont = Key.of("minecraft", "default");
|
||||
nodeToStringInfo(node, list, defaultFont, false);
|
||||
int totalLength = 0;
|
||||
for (Tuple<String, Key, Boolean> element : list) {
|
||||
for (int i = 0, size = list.size(); i < size; i++) {
|
||||
Tuple<String, Key, Boolean> element = list.get(i);
|
||||
FontData data = getFontData(element.getMid());
|
||||
if (data == null) {
|
||||
LogUtils.warn("Unknown font: " + element.getMid() + " Please register it in font-width-data.yml");
|
||||
continue;
|
||||
}
|
||||
char[] chars = element.getLeft().toCharArray();
|
||||
for (int i = 0; i < chars.length; i++) {
|
||||
if (Character.isHighSurrogate(chars[i])) {
|
||||
totalLength += data.getWidth(Character.toCodePoint(chars[i], chars[++i]));
|
||||
} else {
|
||||
totalLength += data.getWidth(chars[i]);
|
||||
if (!element.getMid().equals(defaultFont)) {
|
||||
for (int j = 0; j < chars.length; j++) {
|
||||
int width;
|
||||
if (Character.isHighSurrogate(chars[j])) {
|
||||
width = data.getWidth(Character.toCodePoint(chars[j], chars[++j]));
|
||||
} else {
|
||||
width = data.getWidth(chars[j]);
|
||||
}
|
||||
totalLength += (width + (element.getRight() ? 2 : 1)) * 2;
|
||||
}
|
||||
} else {
|
||||
for (int j = 0; j < chars.length; j++) {
|
||||
if (Character.isHighSurrogate(chars[j])) {
|
||||
int codePoint = Character.toCodePoint(chars[j], chars[++j]);
|
||||
if (isNotReplacedUnifont(codePoint)) {
|
||||
totalLength += (data.getWidth(codePoint) * 2 + (element.getRight() ? 3 : 2));
|
||||
} else {
|
||||
totalLength += (element.getRight() ? 2 : 1) * 2;
|
||||
}
|
||||
} else {
|
||||
if (isNotReplacedUnifont(chars[j])) {
|
||||
totalLength += (data.getWidth(chars[j]) * 2 + (element.getRight() ? 3 : 2));
|
||||
} else {
|
||||
totalLength += (data.getWidth(chars[j]) + (element.getRight() ? 2 : 1)) * 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
totalLength += element.getRight() ? element.getLeft().length() * 2 : element.getLeft().length();
|
||||
}
|
||||
totalLength /= 2;
|
||||
return totalLength;
|
||||
}
|
||||
|
||||
@@ -924,7 +974,11 @@ public class WidthManagerImpl implements WidthManager {
|
||||
} else if (node instanceof TagNode tagNode) {
|
||||
if (tagNode.tag() instanceof Inserting inserting) {
|
||||
Component component = inserting.value();
|
||||
isBold = component.hasDecoration(TextDecoration.BOLD);
|
||||
if (component.decoration(TextDecoration.BOLD) == TextDecoration.State.TRUE) {
|
||||
isBold = true;
|
||||
} else if (component.decoration(TextDecoration.BOLD) == TextDecoration.State.FALSE) {
|
||||
isBold = false;
|
||||
}
|
||||
var key = component.font();
|
||||
if (key != null) {
|
||||
font = net.momirealms.customnameplates.common.Key.of(key.namespace(), key.value());
|
||||
|
||||
+23
-8
@@ -21,6 +21,7 @@ import me.clip.placeholderapi.PlaceholderAPI;
|
||||
import net.momirealms.customnameplates.api.manager.RequirementManager;
|
||||
import net.momirealms.customnameplates.api.requirement.Condition;
|
||||
import net.momirealms.customnameplates.api.requirement.Requirement;
|
||||
import net.momirealms.customnameplates.api.util.LogUtils;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public class DisplayController {
|
||||
@@ -35,6 +36,7 @@ public class DisplayController {
|
||||
private int timeLeft;
|
||||
private int index;
|
||||
private final TimeLimitText[] texts;
|
||||
private boolean metAnyCondition;
|
||||
|
||||
public DisplayController(
|
||||
Player player,
|
||||
@@ -44,10 +46,10 @@ public class DisplayController {
|
||||
) {
|
||||
this.owner = player;
|
||||
this.checkFrequency = checkFrequency;
|
||||
this.checkTimer = 0;
|
||||
this.refreshTimer = 0;
|
||||
this.requirements = requirements;
|
||||
this.texts = texts;
|
||||
this.checkTimer = checkFrequency - 1;
|
||||
}
|
||||
|
||||
public NextStage stateCheck(Condition condition) {
|
||||
@@ -78,21 +80,33 @@ public class DisplayController {
|
||||
}
|
||||
|
||||
public boolean updateText(Condition condition) {
|
||||
timeLeft--;
|
||||
if (timeLeft <= 0) {
|
||||
if (timeLeft > 0)
|
||||
timeLeft--;
|
||||
|
||||
// Definitely goto "if" on init
|
||||
if (timeLeft == 0) {
|
||||
int triedTimes = 0;
|
||||
do {
|
||||
index++;
|
||||
if (index >= texts.length) {
|
||||
index = 0;
|
||||
}
|
||||
if (triedTimes == texts.length) {
|
||||
timeLeft = Math.max(checkFrequency, 1);
|
||||
metAnyCondition = false;
|
||||
LogUtils.warn("No text is available for player " + owner.getName() + ". Please check your conditions.");
|
||||
return updateText("");
|
||||
}
|
||||
triedTimes++;
|
||||
} while (!RequirementManager.isRequirementMet(condition, texts[index].getRequirements()));
|
||||
|
||||
metAnyCondition = true;
|
||||
timeLeft = texts[index].getDuration();
|
||||
refreshTimer = 0;
|
||||
return updateText(texts[index].getText());
|
||||
}
|
||||
|
||||
if (texts[index].getRefreshFrequency() <= 0) {
|
||||
if (!metAnyCondition || texts[index].getRefreshFrequency() <= 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -114,12 +128,13 @@ public class DisplayController {
|
||||
return true;
|
||||
}
|
||||
|
||||
public void initialize() {
|
||||
index = 0;
|
||||
public void initialize(Condition condition) {
|
||||
index = texts.length - 1;
|
||||
checkTimer = 0;
|
||||
refreshTimer = 0;
|
||||
timeLeft = texts[0].getDuration();
|
||||
latestValue = PlaceholderAPI.setPlaceholders(owner, texts[0].getText());
|
||||
timeLeft = 1;
|
||||
// The text would definitely be refreshed
|
||||
updateText(condition);
|
||||
}
|
||||
|
||||
public String getLatestContent() {
|
||||
|
||||
-9
@@ -1,9 +0,0 @@
|
||||
package net.momirealms.customnameplates.paper.mechanic.misc;
|
||||
|
||||
import org.bukkit.event.Listener;
|
||||
|
||||
public class MessageManager implements Listener {
|
||||
|
||||
|
||||
|
||||
}
|
||||
+1
-2
@@ -22,7 +22,6 @@ import com.comphenix.protocol.ProtocolLibrary;
|
||||
import com.comphenix.protocol.ProtocolManager;
|
||||
import com.comphenix.protocol.events.PacketContainer;
|
||||
import net.momirealms.customnameplates.api.CustomNameplatesPlugin;
|
||||
import net.momirealms.customnameplates.api.util.LogUtils;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -47,7 +46,7 @@ public class PacketManager {
|
||||
|
||||
public void send(Player player, PacketContainer packet) {
|
||||
if (!player.isOnline()) {
|
||||
LogUtils.warn(player.getName() + " not online");
|
||||
return;
|
||||
}
|
||||
this.plugin.debug("Packet sent: " + packet.getType() + " to " + player.getName());
|
||||
this.protocolManager.sendServerPacket(player, packet);
|
||||
|
||||
+55
-49
@@ -22,10 +22,12 @@ import net.momirealms.customnameplates.api.manager.VersionManager;
|
||||
import net.momirealms.customnameplates.api.util.LogUtils;
|
||||
import net.momirealms.customnameplates.paper.CustomNameplatesPluginImpl;
|
||||
import net.momirealms.customnameplates.paper.adventure.AdventureManagerImpl;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.PlayerJoinEvent;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.InputStream;
|
||||
@@ -39,14 +41,11 @@ import java.util.concurrent.CompletableFuture;
|
||||
*/
|
||||
public class VersionManagerImpl implements VersionManager, Listener {
|
||||
|
||||
private final boolean isNewerThan1_19;
|
||||
private final boolean isNewerThan1_19_R2;
|
||||
private final boolean isNewerThan1_19_R3;
|
||||
private final boolean isNewerThan1_20;
|
||||
private final boolean isNewerThan1_20_R2;
|
||||
private final String serverVersion;
|
||||
|
||||
private final float mcVersion;
|
||||
private final CustomNameplatesPluginImpl plugin;
|
||||
private boolean isFolia;
|
||||
private boolean isMojmap;
|
||||
private final String pluginVersion;
|
||||
private boolean isLatest = true;
|
||||
|
||||
@@ -54,49 +53,55 @@ public class VersionManagerImpl implements VersionManager, Listener {
|
||||
public VersionManagerImpl(CustomNameplatesPluginImpl plugin) {
|
||||
this.plugin = plugin;
|
||||
// Get the server version
|
||||
serverVersion = plugin.getServer().getClass().getPackage().getName().split("\\.")[3];
|
||||
String[] split = serverVersion.split("_");
|
||||
int main_ver = Integer.parseInt(split[1]);
|
||||
// Determine if the server version is newer than 1_19_R2 and 1_20_R1
|
||||
if (main_ver >= 20) {
|
||||
isNewerThan1_20_R2 = Integer.parseInt(split[2].substring(1)) >= 2;
|
||||
isNewerThan1_19_R2 = isNewerThan1_19_R3 = true;
|
||||
isNewerThan1_20 = true;
|
||||
isNewerThan1_19 = true;
|
||||
} else if (main_ver == 19) {
|
||||
isNewerThan1_19_R2 = Integer.parseInt(split[2].substring(1)) >= 2;
|
||||
isNewerThan1_19_R3 = Integer.parseInt(split[2].substring(1)) >= 3;
|
||||
isNewerThan1_20 = isNewerThan1_20_R2 = false;
|
||||
isNewerThan1_19 = true;
|
||||
} else {
|
||||
isNewerThan1_19 = isNewerThan1_19_R2= isNewerThan1_19_R3 = false;
|
||||
isNewerThan1_20 = isNewerThan1_20_R2 = false;
|
||||
}
|
||||
// Check if the server is Folia
|
||||
try {
|
||||
Class.forName("io.papermc.paper.threadedregions.scheduler.AsyncScheduler");
|
||||
this.isFolia = true;
|
||||
} catch (ClassNotFoundException ignored) {
|
||||
}
|
||||
|
||||
String[] split = Bukkit.getServer().getBukkitVersion().split("-")[0].split("\\.");
|
||||
this.mcVersion = Float.parseFloat(split[1] + "." + (split.length >= 3 ? split[2] : "0"));
|
||||
|
||||
// Get the plugin version
|
||||
this.pluginVersion = plugin.getDescription().getVersion();
|
||||
|
||||
// Check if the server is Folia
|
||||
try {
|
||||
Class.forName("io.papermc.paper.threadedregions.RegionizedServer");
|
||||
this.isFolia = true;
|
||||
} catch (ClassNotFoundException ignored) {
|
||||
this.isFolia = false;
|
||||
}
|
||||
|
||||
// Check if the server is Mojmap
|
||||
try {
|
||||
Class.forName("net.minecraft.network.protocol.game.ClientboundBossEventPacket");
|
||||
this.isMojmap = true;
|
||||
} catch (ClassNotFoundException ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isMojmap() {
|
||||
return isMojmap;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isVersionNewerThan1_19_R2() {
|
||||
return isNewerThan1_19_R2;
|
||||
return mcVersion >= 19.3;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isVersionNewerThan1_20() {
|
||||
return isNewerThan1_20;
|
||||
return mcVersion >= 20;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isVersionNewerThan1_20_R2() {
|
||||
return isNewerThan1_20_R2;
|
||||
return mcVersion >= 20.2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isVersionNewerThan1_20_5() {
|
||||
return mcVersion >= 20.5;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getPluginVersion() {
|
||||
return pluginVersion;
|
||||
@@ -109,36 +114,42 @@ public class VersionManagerImpl implements VersionManager, Listener {
|
||||
|
||||
@Override
|
||||
public boolean isVersionNewerThan1_19() {
|
||||
return isNewerThan1_19;
|
||||
return mcVersion >= 19;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isVersionNewerThan1_19_R3() {
|
||||
return isNewerThan1_19_R3;
|
||||
return mcVersion >= 19.4;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPackFormat() {
|
||||
switch (serverVersion) {
|
||||
case "v1_20_R3" -> {
|
||||
switch (Bukkit.getServer().getBukkitVersion().split("-")[0]) {
|
||||
case "1.21" -> {
|
||||
return 34;
|
||||
}
|
||||
case "1.20.5", "1.20.6" -> {
|
||||
return 32;
|
||||
}
|
||||
case "1.20.3", "1.20.4" -> {
|
||||
return 22;
|
||||
}
|
||||
case "v1_20_R2" -> {
|
||||
case "1.20.2" -> {
|
||||
return 18;
|
||||
}
|
||||
case "v1_20_R1" -> {
|
||||
case "1.20", "1.20.1" -> {
|
||||
return 15;
|
||||
}
|
||||
case "v1_19_R3" -> {
|
||||
case "1.19.4" -> {
|
||||
return 13;
|
||||
}
|
||||
case "v1_19_R2" -> {
|
||||
case "1.19.3" -> {
|
||||
return 12;
|
||||
}
|
||||
case "v1_19_R1" -> {
|
||||
case "1.19", "1.19.1", "1.19.2" -> {
|
||||
return 9;
|
||||
}
|
||||
case "v1_18_R1", "v1_18_R2" -> {
|
||||
case "1.18", "1.18.1", "1.18.2" -> {
|
||||
return 8;
|
||||
}
|
||||
default -> {
|
||||
@@ -152,11 +163,6 @@ public class VersionManagerImpl implements VersionManager, Listener {
|
||||
return isFolia;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getServerVersion() {
|
||||
return serverVersion;
|
||||
}
|
||||
|
||||
// Method to asynchronously check for plugin updates
|
||||
public CompletableFuture<Boolean> checkUpdate() {
|
||||
CompletableFuture<Boolean> updateFuture = new CompletableFuture<>();
|
||||
@@ -236,7 +242,7 @@ public class VersionManagerImpl implements VersionManager, Listener {
|
||||
final Player player = event.getPlayer();
|
||||
if (player.isOp()) {
|
||||
if (!PlaceholderAPI.isRegistered("player")) {
|
||||
AdventureManagerImpl.getInstance().sendMessageWithPrefix(player, "You haven't installed Player Expansion yet. Click <b><gold><click:run_command:/papi ecloud download Player>HERE</click></gold><b> to download.");
|
||||
AdventureManagerImpl.getInstance().sendMessageWithPrefix(player, "You haven't installed Player Expansion yet. Click <b><gold><u><click:run_command:/papi ecloud download Player>HERE</click></u></gold></b> to download. Otherwise you might encounter console spam on first installation.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+107
-44
@@ -51,9 +51,11 @@ import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.HandlerList;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.entity.EntityPoseChangeEvent;
|
||||
import org.bukkit.event.entity.EntityPotionEffectEvent;
|
||||
import org.bukkit.event.player.PlayerJoinEvent;
|
||||
import org.bukkit.event.player.PlayerQuitEvent;
|
||||
import org.bukkit.event.player.PlayerToggleSneakEvent;
|
||||
import org.bukkit.potion.PotionEffectType;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -81,6 +83,8 @@ public class NameplateManagerImpl implements NameplateManager, Listener {
|
||||
private final EntityMoveListener entityMoveListener;
|
||||
private final EntityLookListener entityLookListener;
|
||||
private final EntityTeleportListener entityTeleportListener;
|
||||
private final EntityAddEffectListener entityAddEffectListener;
|
||||
private final EntityRemoveEffectListener entityRemoveEffectListener;
|
||||
|
||||
/**
|
||||
* Configs
|
||||
@@ -113,6 +117,8 @@ public class NameplateManagerImpl implements NameplateManager, Listener {
|
||||
this.entitySpawnListener = new EntitySpawnListener(this);
|
||||
this.entityLookListener = new EntityLookListener(this);
|
||||
this.entityMoveListener = new EntityMoveListener(this);
|
||||
this.entityAddEffectListener = new EntityAddEffectListener(this);
|
||||
this.entityRemoveEffectListener = new EntityRemoveEffectListener(this);
|
||||
}
|
||||
|
||||
public void reload() {
|
||||
@@ -135,6 +141,8 @@ public class NameplateManagerImpl implements NameplateManager, Listener {
|
||||
ProtocolLibrary.getProtocolManager().removePacketListener(entityLookListener);
|
||||
ProtocolLibrary.getProtocolManager().removePacketListener(entityMoveListener);
|
||||
ProtocolLibrary.getProtocolManager().removePacketListener(entityTeleportListener);
|
||||
ProtocolLibrary.getProtocolManager().removePacketListener(entityAddEffectListener);
|
||||
ProtocolLibrary.getProtocolManager().removePacketListener(entityRemoveEffectListener);
|
||||
}
|
||||
|
||||
public void disable() {
|
||||
@@ -145,6 +153,14 @@ public class NameplateManagerImpl implements NameplateManager, Listener {
|
||||
|
||||
public void load() {
|
||||
this.unlimitedTagManager.load();
|
||||
Bukkit.getPluginManager().registerEvents(this, plugin);
|
||||
ProtocolLibrary.getProtocolManager().addPacketListener(entityDestroyListener);
|
||||
ProtocolLibrary.getProtocolManager().addPacketListener(entitySpawnListener);
|
||||
ProtocolLibrary.getProtocolManager().addPacketListener(entityLookListener);
|
||||
ProtocolLibrary.getProtocolManager().addPacketListener(entityMoveListener);
|
||||
ProtocolLibrary.getProtocolManager().addPacketListener(entityTeleportListener);
|
||||
ProtocolLibrary.getProtocolManager().addPacketListener(entityAddEffectListener);
|
||||
ProtocolLibrary.getProtocolManager().addPacketListener(entityRemoveEffectListener);
|
||||
|
||||
if (!CNConfig.nameplateModule) return;
|
||||
this.loadConfig();
|
||||
@@ -160,13 +176,6 @@ public class NameplateManagerImpl implements NameplateManager, Listener {
|
||||
for (Player online : Bukkit.getOnlinePlayers()) {
|
||||
createNameTag(online);
|
||||
}
|
||||
|
||||
Bukkit.getPluginManager().registerEvents(this, plugin);
|
||||
ProtocolLibrary.getProtocolManager().addPacketListener(entityDestroyListener);
|
||||
ProtocolLibrary.getProtocolManager().addPacketListener(entitySpawnListener);
|
||||
ProtocolLibrary.getProtocolManager().addPacketListener(entityLookListener);
|
||||
ProtocolLibrary.getProtocolManager().addPacketListener(entityMoveListener);
|
||||
ProtocolLibrary.getProtocolManager().addPacketListener(entityTeleportListener);
|
||||
}
|
||||
|
||||
private void loadConfig() {
|
||||
@@ -259,6 +268,8 @@ public class NameplateManagerImpl implements NameplateManager, Listener {
|
||||
|
||||
@EventHandler (ignoreCancelled = true, priority = EventPriority.LOW)
|
||||
public void onDataLoaded(NameplateDataLoadEvent event) {
|
||||
if (!CNConfig.nameplateModule) return;
|
||||
|
||||
OnlineUser data = event.getOnlineUser();
|
||||
String nameplate = data.getNameplateKey();
|
||||
if (nameplate.equals("none")) {
|
||||
@@ -286,26 +297,44 @@ public class NameplateManagerImpl implements NameplateManager, Listener {
|
||||
@EventHandler
|
||||
public void onPlayerJoin(PlayerJoinEvent event) {
|
||||
var player = event.getPlayer();
|
||||
handlePlayerJoin(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handlePlayerJoin(Player player) {
|
||||
this.putEntityIDToMap(player.getEntityId(), player);
|
||||
if (!CNConfig.isOtherTeamPluginHooked() && !isProxyMode())
|
||||
plugin.getTeamManager().createTeam(player);
|
||||
plugin.getScheduler().runTaskAsyncLater(() -> {
|
||||
if (player.isOnline())
|
||||
this.createNameTag(player);
|
||||
}, 200, TimeUnit.MILLISECONDS);
|
||||
|
||||
// nameplate module part
|
||||
if (CNConfig.nameplateModule) {
|
||||
if (!CNConfig.isOtherTeamPluginHooked() && !isProxyMode()) {
|
||||
plugin.getTeamManager().createTeam(player);
|
||||
}
|
||||
plugin.getScheduler().runTaskAsyncLater(() -> {
|
||||
if (player.isOnline())
|
||||
this.createNameTag(player);
|
||||
}, 50, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onPlayerQuit(PlayerQuitEvent event) {
|
||||
var player = event.getPlayer();
|
||||
this.removeCachedNameplateFromMap(player.getUniqueId());
|
||||
this.removeEntityIDFromMap(player.getEntityId());
|
||||
handlePlayerQuit(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handlePlayerQuit(Player player) {
|
||||
this.removeEntityIDFromMap(player.getEntityId());
|
||||
this.teamTagManager.handlePlayerQuit(player);
|
||||
this.unlimitedTagManager.handlePlayerQuit(player);
|
||||
this.removeNameplatePlayerFromMap(player.getUniqueId());
|
||||
|
||||
if (!CNConfig.isOtherTeamPluginHooked() && !isProxyMode()) {
|
||||
plugin.getTeamManager().removeTeam(player);
|
||||
// nameplate module part
|
||||
if (CNConfig.nameplateModule) {
|
||||
this.removeCachedNameplateFromMap(player.getUniqueId());
|
||||
if (!CNConfig.isOtherTeamPluginHooked() && !isProxyMode()) {
|
||||
plugin.getTeamManager().removeTeam(player);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -322,8 +351,19 @@ public class NameplateManagerImpl implements NameplateManager, Listener {
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Potion effect packet seems to be only sent to the player who has effect,
|
||||
// it might be something related to metadata. Using BukkitAPI is not the best choice
|
||||
// since it might conflict with some potion plugins that based on packets
|
||||
@EventHandler (ignoreCancelled = true)
|
||||
public void onPotionEffectChange(EntityPotionEffectEvent event) {
|
||||
if (event.getModifiedType() == PotionEffectType.INVISIBILITY) {
|
||||
unlimitedTagManager.handlePotionEffect(event.getEntity(),
|
||||
event.getAction() == EntityPotionEffectEvent.Action.REMOVED || event.getAction() == EntityPotionEffectEvent.Action.CLEARED);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean putEntityIDToMap(int entityID, Entity entity) {
|
||||
public boolean putEntityIDToMap(int entityID, @NotNull Entity entity) {
|
||||
if (this.entityID2EntityMap.containsKey(entityID))
|
||||
return false;
|
||||
this.entityID2EntityMap.put(entityID, entity);
|
||||
@@ -336,7 +376,7 @@ public class NameplateManagerImpl implements NameplateManager, Listener {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean putCachedNameplateToMap(UUID uuid, CachedNameplate nameplate) {
|
||||
public boolean putCachedNameplateToMap(@NotNull UUID uuid, @NotNull CachedNameplate nameplate) {
|
||||
if (this.cachedNameplateMap.containsKey(uuid)) {
|
||||
return false;
|
||||
}
|
||||
@@ -345,7 +385,7 @@ public class NameplateManagerImpl implements NameplateManager, Listener {
|
||||
}
|
||||
|
||||
@Override
|
||||
public CachedNameplate removeCachedNameplateFromMap(UUID uuid) {
|
||||
public CachedNameplate removeCachedNameplateFromMap(@NotNull UUID uuid) {
|
||||
return this.cachedNameplateMap.remove(uuid);
|
||||
}
|
||||
|
||||
@@ -364,7 +404,7 @@ public class NameplateManagerImpl implements NameplateManager, Listener {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean updateCachedNameplate(Player player) {
|
||||
public boolean updateCachedNameplate(@NotNull Player player) {
|
||||
Optional<OnlineUser> onlineUser = plugin.getStorageManager().getOnlineUser(player.getUniqueId());
|
||||
if (onlineUser.isEmpty()) return false;
|
||||
Nameplate nameplate = onlineUser.get().getNameplate();
|
||||
@@ -372,45 +412,49 @@ public class NameplateManagerImpl implements NameplateManager, Listener {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean updateCachedNameplate(Player player, Nameplate nameplate) {
|
||||
public boolean updateCachedNameplate(@NotNull Player player, Nameplate nameplate) {
|
||||
CachedNameplate cachedNameplate = cachedNameplateMap.get(player.getUniqueId());
|
||||
if (cachedNameplate == null) return false;
|
||||
return updateCachedNameplate(cachedNameplate, player, nameplate);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CachedNameplate getCacheNameplate(Player player) {
|
||||
public CachedNameplate getCacheNameplate(@NotNull Player player) {
|
||||
return cachedNameplateMap.get(player.getUniqueId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void createNameTag(Player player) {
|
||||
public NameplatePlayer createNameTag(@NotNull Player player) {
|
||||
if (tagMode == TagMode.TEAM) {
|
||||
putNameplatePlayerToMap(this.teamTagManager.createTagForPlayer(player, teamPrefix, teamSuffix));
|
||||
EntityTagPlayer tagPlayer = this.unlimitedTagManager.createOrGetTagForPlayer(player, false);
|
||||
NameplatePlayer nameplatePlayer = this.teamTagManager.createTagForPlayer(player, teamPrefix, teamSuffix);
|
||||
putNameplatePlayerToMap(nameplatePlayer);
|
||||
this.unlimitedTagManager.createOrGetTagForPlayer(player);
|
||||
return nameplatePlayer;
|
||||
} else if (tagMode == TagMode.UNLIMITED) {
|
||||
EntityTagPlayer tagPlayer = this.unlimitedTagManager.createOrGetTagForPlayer(player, true);
|
||||
EntityTagPlayer tagPlayer = this.unlimitedTagManager.createOrGetTagForPlayer(player);
|
||||
for (DynamicTextTagSetting setting : tagSettings) {
|
||||
tagPlayer.addTag(setting);
|
||||
}
|
||||
putNameplatePlayerToMap(tagPlayer);
|
||||
return tagPlayer;
|
||||
} else {
|
||||
EntityTagPlayer tagPlayer = this.unlimitedTagManager.createOrGetTagForPlayer(player, false);
|
||||
this.unlimitedTagManager.createOrGetTagForPlayer(player);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void putNameplatePlayerToMap(NameplatePlayer player) {
|
||||
public void putNameplatePlayerToMap(@NotNull NameplatePlayer player) {
|
||||
this.nameplatePlayerMap.put(player.getPlayer().getUniqueId(), player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public NameplatePlayer getNameplatePlayer(UUID uuid) {
|
||||
public NameplatePlayer getNameplatePlayer(@NotNull UUID uuid) {
|
||||
return this.nameplatePlayerMap.get(uuid);
|
||||
}
|
||||
|
||||
@Override
|
||||
public NameplatePlayer removeNameplatePlayerFromMap(UUID uuid) {
|
||||
public NameplatePlayer removeNameplatePlayerFromMap(@NotNull UUID uuid) {
|
||||
return this.nameplatePlayerMap.remove(uuid);
|
||||
}
|
||||
|
||||
@@ -443,22 +487,25 @@ public class NameplateManagerImpl implements NameplateManager, Listener {
|
||||
return true;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getNameplatePrefix(Player player) {
|
||||
public String getNameplatePrefix(@NotNull Player player) {
|
||||
CachedNameplate cachedNameplate = cachedNameplateMap.get(player.getUniqueId());
|
||||
if (cachedNameplate == null) return "";
|
||||
return cachedNameplate.getTagPrefix();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getNameplateSuffix(Player player) {
|
||||
public String getNameplateSuffix(@NotNull Player player) {
|
||||
CachedNameplate cachedNameplate = cachedNameplateMap.get(player.getUniqueId());
|
||||
if (cachedNameplate == null) return "";
|
||||
return cachedNameplate.getTagSuffix();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getFullNameTag(Player player) {
|
||||
public String getFullNameTag(@NotNull Player player) {
|
||||
CachedNameplate cachedNameplate = cachedNameplateMap.get(player.getUniqueId());
|
||||
if (cachedNameplate == null) {
|
||||
return player.getName();
|
||||
@@ -471,8 +518,9 @@ public class NameplateManagerImpl implements NameplateManager, Listener {
|
||||
+ cachedNameplate.getNameSuffix();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public List<String> getAvailableNameplates(Player player) {
|
||||
public List<String> getAvailableNameplates(@NotNull Player player) {
|
||||
List<String> nameplates = new ArrayList<>();
|
||||
for (String nameplate : nameplateMap.keySet()) {
|
||||
if (hasNameplate(player, nameplate)) {
|
||||
@@ -482,8 +530,9 @@ public class NameplateManagerImpl implements NameplateManager, Listener {
|
||||
return nameplates;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public List<String> getAvailableNameplateDisplayNames(Player player) {
|
||||
public List<String> getAvailableNameplateDisplayNames(@NotNull Player player) {
|
||||
List<String> nameplates = new ArrayList<>();
|
||||
for (Map.Entry<String, Nameplate> entry : nameplateMap.entrySet()) {
|
||||
if (hasNameplate(player, entry.getKey())) {
|
||||
@@ -494,7 +543,7 @@ public class NameplateManagerImpl implements NameplateManager, Listener {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equipNameplate(Player player, String nameplateKey, boolean temp) {
|
||||
public boolean equipNameplate(@NotNull Player player, @NotNull String nameplateKey, boolean temp) {
|
||||
Nameplate nameplate = getNameplate(nameplateKey);
|
||||
if (nameplate == null && nameplateKey.equals("none")) {
|
||||
return false;
|
||||
@@ -545,14 +594,14 @@ public class NameplateManagerImpl implements NameplateManager, Listener {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean registerNameplate(String key, Nameplate nameplate) {
|
||||
public boolean registerNameplate(@NotNull String key, @NotNull Nameplate nameplate) {
|
||||
if (this.nameplateMap.containsKey(key)) return false;
|
||||
this.nameplateMap.put(key, nameplate);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean unregisterNameplate(String key) {
|
||||
public boolean unregisterNameplate(@NotNull String key) {
|
||||
return this.nameplateMap.remove(key) != null;
|
||||
}
|
||||
|
||||
@@ -566,39 +615,43 @@ public class NameplateManagerImpl implements NameplateManager, Listener {
|
||||
return previewDuration;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public TagMode getTagMode() {
|
||||
return tagMode;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public Nameplate getNameplate(String key) {
|
||||
@Override
|
||||
public Nameplate getNameplate(@NotNull String key) {
|
||||
return nameplateMap.get(key);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Collection<Nameplate> getNameplates() {
|
||||
return nameplateMap.values();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Collection<String> getNameplateKeys() {
|
||||
return nameplateMap.keySet();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsNameplate(String key) {
|
||||
public boolean containsNameplate(@NotNull String key) {
|
||||
return nameplateMap.containsKey(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNameplate(Player player, String nameplate) {
|
||||
public boolean hasNameplate(@NotNull Player player, @NotNull String nameplate) {
|
||||
return player.hasPermission("nameplates.equip." + nameplate);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public TeamColor getTeamColor(Player player) {
|
||||
public TeamColor getTeamColor(@NotNull Player player) {
|
||||
CachedNameplate nameplate = getCacheNameplate(player);
|
||||
return nameplate == null ? TeamColor.WHITE : nameplate.getTeamColor();
|
||||
}
|
||||
@@ -609,11 +662,13 @@ public class NameplateManagerImpl implements NameplateManager, Listener {
|
||||
return defaultNameplate;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public TeamTagManager getTeamTagManager() {
|
||||
return teamTagManager;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public UnlimitedTagManager getUnlimitedTagManager() {
|
||||
return unlimitedTagManager;
|
||||
@@ -636,4 +691,12 @@ public class NameplateManagerImpl implements NameplateManager, Listener {
|
||||
public void onEntityTeleport(Player receiver, int entityID, double x, double y, double z, boolean onGround) {
|
||||
unlimitedTagManager.handleEntityTeleportPacket(receiver, entityID, x, y, z, onGround);
|
||||
}
|
||||
|
||||
// public void onEntityRemoveEffect(Player player, int entityID) {
|
||||
// unlimitedTagManager.handlePotionEffect(player, entityID,true);
|
||||
// }
|
||||
//
|
||||
// public void onEntityAddEffect(Player player, int entityID) {
|
||||
// unlimitedTagManager.handlePotionEffect(player, entityID,false);
|
||||
// }
|
||||
}
|
||||
+51
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright (C) <2022> <XiaoMoMi>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package net.momirealms.customnameplates.paper.mechanic.nameplate.tag.listener;
|
||||
|
||||
import me.libraryaddict.disguise.events.DisguiseEvent;
|
||||
import me.libraryaddict.disguise.events.UndisguiseEvent;
|
||||
import net.momirealms.customnameplates.api.CustomNameplatesPlugin;
|
||||
import net.momirealms.customnameplates.paper.mechanic.nameplate.tag.unlimited.UnlimitedPlayer;
|
||||
import net.momirealms.customnameplates.paper.mechanic.nameplate.tag.unlimited.UnlimitedTagManagerImpl;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class DisguiseListener implements Listener {
|
||||
|
||||
private final UnlimitedTagManagerImpl unlimitedTagManager;
|
||||
|
||||
public DisguiseListener(UnlimitedTagManagerImpl unlimitedTagManager) {
|
||||
this.unlimitedTagManager = unlimitedTagManager;
|
||||
}
|
||||
|
||||
@EventHandler (ignoreCancelled = true)
|
||||
public void onDisguise(DisguiseEvent event) {
|
||||
if (this.unlimitedTagManager.getUnlimitedObject(event.getEntity().getUniqueId()) instanceof UnlimitedPlayer player) {
|
||||
CustomNameplatesPlugin.get().getScheduler().runTaskAsyncLater(player::updateVisibility, 50, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler (ignoreCancelled = true)
|
||||
public void onUnDisguise(UndisguiseEvent event) {
|
||||
if (this.unlimitedTagManager.getUnlimitedObject(event.getEntity().getUniqueId()) instanceof UnlimitedPlayer player) {
|
||||
CustomNameplatesPlugin.get().getScheduler().runTaskAsyncLater(player::updateVisibility, 50, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
}
|
||||
}
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright (C) <2022> <XiaoMoMi>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package net.momirealms.customnameplates.paper.mechanic.nameplate.tag.listener;
|
||||
|
||||
import com.comphenix.protocol.PacketType;
|
||||
import com.comphenix.protocol.events.ListenerPriority;
|
||||
import com.comphenix.protocol.events.PacketAdapter;
|
||||
import com.comphenix.protocol.events.PacketEvent;
|
||||
import net.momirealms.customnameplates.api.CustomNameplatesPlugin;
|
||||
import net.momirealms.customnameplates.paper.mechanic.nameplate.NameplateManagerImpl;
|
||||
|
||||
public class EntityAddEffectListener extends PacketAdapter {
|
||||
|
||||
private final NameplateManagerImpl manager;
|
||||
|
||||
public EntityAddEffectListener(NameplateManagerImpl manager) {
|
||||
super(CustomNameplatesPlugin.getInstance(), ListenerPriority.NORMAL, PacketType.Play.Server.ENTITY_EFFECT);
|
||||
this.manager = manager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPacketSending(PacketEvent event) {
|
||||
// PacketContainer packet = event.getPacket();
|
||||
// System.out.println("添加包");
|
||||
// if (packet.getEffectTypes().read(0) == PotionEffectType.INVISIBILITY) {
|
||||
// System.out.println("是隐身");
|
||||
// manager.onEntityAddEffect(event.getPlayer(), packet.getIntegers().read(0));
|
||||
// }
|
||||
}
|
||||
}
|
||||
+3
-1
@@ -30,11 +30,13 @@ public class EntityDestroyListener extends PacketAdapter {
|
||||
private final NameplateManagerImpl manager;
|
||||
|
||||
public EntityDestroyListener(NameplateManagerImpl manager) {
|
||||
super(CustomNameplatesPlugin.getInstance(), ListenerPriority.HIGH, PacketType.Play.Server.ENTITY_DESTROY);
|
||||
super(CustomNameplatesPlugin.getInstance(), ListenerPriority.NORMAL, PacketType.Play.Server.ENTITY_DESTROY);
|
||||
this.manager = manager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPacketSending(PacketEvent event) {
|
||||
if (event.isCancelled()) return;
|
||||
PacketContainer packet = event.getPacket();
|
||||
manager.onEntityDestroy(event.getPlayer(), packet.getIntLists().read(0));
|
||||
}
|
||||
|
||||
+3
-1
@@ -30,11 +30,13 @@ public class EntityLookListener extends PacketAdapter {
|
||||
private final NameplateManagerImpl manager;
|
||||
|
||||
public EntityLookListener(NameplateManagerImpl manager) {
|
||||
super(CustomNameplatesPlugin.getInstance(), ListenerPriority.HIGHEST, PacketType.Play.Server.REL_ENTITY_MOVE_LOOK);
|
||||
super(CustomNameplatesPlugin.getInstance(), ListenerPriority.NORMAL, PacketType.Play.Server.REL_ENTITY_MOVE_LOOK);
|
||||
this.manager = manager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPacketSending(PacketEvent event) {
|
||||
if (event.isCancelled()) return;
|
||||
PacketContainer packet = event.getPacket();
|
||||
manager.onEntityMove(event.getPlayer(),
|
||||
packet.getIntegers().read(0),
|
||||
|
||||
+3
-1
@@ -30,11 +30,13 @@ public class EntityMoveListener extends PacketAdapter {
|
||||
private final NameplateManagerImpl manager;
|
||||
|
||||
public EntityMoveListener(NameplateManagerImpl manager) {
|
||||
super(CustomNameplatesPlugin.getInstance(), ListenerPriority.HIGHEST, PacketType.Play.Server.REL_ENTITY_MOVE);
|
||||
super(CustomNameplatesPlugin.getInstance(), ListenerPriority.NORMAL, PacketType.Play.Server.REL_ENTITY_MOVE);
|
||||
this.manager = manager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPacketSending(PacketEvent event) {
|
||||
if (event.isCancelled()) return;
|
||||
PacketContainer packet = event.getPacket();
|
||||
manager.onEntityMove(event.getPlayer(),
|
||||
packet.getIntegers().read(0),
|
||||
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright (C) <2022> <XiaoMoMi>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package net.momirealms.customnameplates.paper.mechanic.nameplate.tag.listener;
|
||||
|
||||
import com.comphenix.protocol.PacketType;
|
||||
import com.comphenix.protocol.events.ListenerPriority;
|
||||
import com.comphenix.protocol.events.PacketAdapter;
|
||||
import com.comphenix.protocol.events.PacketEvent;
|
||||
import net.momirealms.customnameplates.api.CustomNameplatesPlugin;
|
||||
import net.momirealms.customnameplates.paper.mechanic.nameplate.NameplateManagerImpl;
|
||||
|
||||
public class EntityRemoveEffectListener extends PacketAdapter {
|
||||
|
||||
private final NameplateManagerImpl manager;
|
||||
|
||||
public EntityRemoveEffectListener(NameplateManagerImpl manager) {
|
||||
super(CustomNameplatesPlugin.getInstance(), ListenerPriority.HIGHEST, PacketType.Play.Server.REMOVE_ENTITY_EFFECT);
|
||||
this.manager = manager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPacketSending(PacketEvent event) {
|
||||
// if (event.isCancelled()) return;
|
||||
// PacketContainer packet = event.getPacket();
|
||||
// if (packet.getEffectTypes().read(0) == PotionEffectType.INVISIBILITY) {
|
||||
// manager.onEntityRemoveEffect(event.getPlayer(), packet.getIntegers().read(0));
|
||||
// }
|
||||
}
|
||||
}
|
||||
+4
-2
@@ -29,11 +29,13 @@ public class EntitySpawnListener extends PacketAdapter {
|
||||
private final NameplateManagerImpl manager;
|
||||
|
||||
public EntitySpawnListener(NameplateManagerImpl manager) {
|
||||
super(CustomNameplatesPlugin.getInstance(), ListenerPriority.HIGH, CustomNameplatesPlugin.getInstance().getVersionManager().isVersionNewerThan1_20_R2() ? PacketType.Play.Server.SPAWN_ENTITY : PacketType.Play.Server.NAMED_ENTITY_SPAWN);
|
||||
super(CustomNameplatesPlugin.getInstance(), ListenerPriority.NORMAL, CustomNameplatesPlugin.getInstance().getVersionManager().isVersionNewerThan1_20_R2() ? PacketType.Play.Server.SPAWN_ENTITY : PacketType.Play.Server.NAMED_ENTITY_SPAWN);
|
||||
this.manager = manager;
|
||||
}
|
||||
|
||||
public synchronized void onPacketSending(PacketEvent event) {
|
||||
@Override
|
||||
public void onPacketSending(PacketEvent event) {
|
||||
if (event.isCancelled()) return;
|
||||
manager.onEntitySpawn(event.getPlayer(), event.getPacket().getIntegers().read(0));
|
||||
}
|
||||
}
|
||||
+3
-1
@@ -30,11 +30,13 @@ public class EntityTeleportListener extends PacketAdapter {
|
||||
private final NameplateManagerImpl manager;
|
||||
|
||||
public EntityTeleportListener(NameplateManagerImpl manager) {
|
||||
super(CustomNameplatesPlugin.getInstance(), ListenerPriority.HIGHEST, PacketType.Play.Server.ENTITY_TELEPORT);
|
||||
super(CustomNameplatesPlugin.getInstance(), ListenerPriority.NORMAL, PacketType.Play.Server.ENTITY_TELEPORT);
|
||||
this.manager = manager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPacketSending(PacketEvent event) {
|
||||
if (event.isCancelled()) return;
|
||||
PacketContainer packet = event.getPacket();
|
||||
manager.onEntityTeleport(
|
||||
event.getPlayer(),
|
||||
|
||||
+18
-8
@@ -22,12 +22,15 @@ import com.francobm.magicosmetics.api.CosmeticType;
|
||||
import com.francobm.magicosmetics.cache.PlayerData;
|
||||
import com.francobm.magicosmetics.cache.cosmetics.Hat;
|
||||
import com.francobm.magicosmetics.events.*;
|
||||
import net.momirealms.customnameplates.api.CustomNameplatesPlugin;
|
||||
import net.momirealms.customnameplates.paper.mechanic.nameplate.tag.unlimited.UnlimitedPlayer;
|
||||
import net.momirealms.customnameplates.paper.mechanic.nameplate.tag.unlimited.UnlimitedTagManagerImpl;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class MagicCosmeticsListener implements Listener {
|
||||
|
||||
private final UnlimitedTagManagerImpl unlimitedTagManager;
|
||||
@@ -36,18 +39,19 @@ public class MagicCosmeticsListener implements Listener {
|
||||
this.unlimitedTagManager = unlimitedTagManager;
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
@EventHandler (ignoreCancelled = true)
|
||||
public void onChangeCos(CosmeticChangeEquipEvent event) {
|
||||
final Cosmetic cosmetic = event.getNewCosmetic();
|
||||
final Player player = event.getPlayer();
|
||||
if (cosmetic instanceof Hat hat) {
|
||||
if (unlimitedTagManager.getUnlimitedObject(player.getUniqueId()) instanceof UnlimitedPlayer unlimitedPlayer) {
|
||||
unlimitedPlayer.setHatOffset(hat.isHideCosmetic() ? 0 : hat.getOffSetY());
|
||||
unlimitedPlayer.teleport();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
@EventHandler (ignoreCancelled = true)
|
||||
public void onEnterBlackListWorld(PlayerChangeBlacklistEvent event) {
|
||||
var player = event.getPlayer();
|
||||
if (unlimitedTagManager.getUnlimitedObject(player.getUniqueId()) instanceof UnlimitedPlayer unlimitedPlayer) {
|
||||
@@ -59,40 +63,46 @@ public class MagicCosmeticsListener implements Listener {
|
||||
final Cosmetic cosmetic = playerData.getHat();
|
||||
if (cosmetic instanceof Hat hat) {
|
||||
unlimitedPlayer.setHatOffset(hat.isHideCosmetic() ? 0 : hat.getOffSetY());
|
||||
unlimitedPlayer.teleport();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
@EventHandler (ignoreCancelled = true)
|
||||
public void onEquip(CosmeticEquipEvent event) {
|
||||
final Cosmetic cosmetic = event.getCosmetic();
|
||||
final Player player = event.getPlayer();
|
||||
if (cosmetic instanceof Hat hat) {
|
||||
if (unlimitedTagManager.getUnlimitedObject(player.getUniqueId()) instanceof UnlimitedPlayer unlimitedPlayer) {
|
||||
unlimitedPlayer.setHatOffset(hat.isHideCosmetic() ? 0 : hat.getOffSetY());
|
||||
unlimitedPlayer.teleport();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
@EventHandler (ignoreCancelled = true)
|
||||
public void onUnEquip(CosmeticUnEquipEvent event) {
|
||||
final Player player = event.getPlayer();
|
||||
if (event.getCosmeticType() == CosmeticType.HAT) {
|
||||
if (unlimitedTagManager.getUnlimitedObject(player.getUniqueId()) instanceof UnlimitedPlayer unlimitedPlayer) {
|
||||
unlimitedPlayer.setHatOffset(0);
|
||||
unlimitedPlayer.teleport();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
@EventHandler (ignoreCancelled = true)
|
||||
public void onDataLoaded(PlayerDataLoadEvent event) {
|
||||
for (Cosmetic cosmetic : event.getEquippedCosmetics()) {
|
||||
if (cosmetic instanceof Hat hat) {
|
||||
if (unlimitedTagManager.getUnlimitedObject(event.getPlayerData().getUniqueId()) instanceof UnlimitedPlayer unlimitedPlayer) {
|
||||
unlimitedPlayer.setHatOffset(hat.isHideCosmetic() ? 0 : hat.getOffSetY());
|
||||
}
|
||||
CustomNameplatesPlugin.get().getScheduler().runTaskAsyncLater(() -> {
|
||||
if (unlimitedTagManager.getUnlimitedObject(event.getPlayerData().getUniqueId()) instanceof UnlimitedPlayer unlimitedPlayer) {
|
||||
unlimitedPlayer.setHatOffset(hat.isHideCosmetic() ? 0 : hat.getOffSetY());
|
||||
unlimitedPlayer.teleport();
|
||||
}
|
||||
}, 100, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+3
-3
@@ -26,9 +26,7 @@ import com.comphenix.protocol.wrappers.EnumWrappers;
|
||||
import com.comphenix.protocol.wrappers.PlayerInfoData;
|
||||
import com.comphenix.protocol.wrappers.WrappedChatComponent;
|
||||
import com.comphenix.protocol.wrappers.WrappedGameProfile;
|
||||
import com.destroystokyo.paper.profile.PlayerProfile;
|
||||
import net.momirealms.customnameplates.api.CustomNameplatesPlugin;
|
||||
import net.momirealms.customnameplates.paper.mechanic.nameplate.NameplateManagerImpl;
|
||||
import net.momirealms.customnameplates.paper.mechanic.nameplate.tag.team.TeamTagManagerImpl;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -40,11 +38,13 @@ public class PlayerInfoListener extends PacketAdapter {
|
||||
private final TeamTagManagerImpl manager;
|
||||
|
||||
public PlayerInfoListener(TeamTagManagerImpl manager) {
|
||||
super(CustomNameplatesPlugin.getInstance(), ListenerPriority.HIGHEST, PacketType.Play.Server.PLAYER_INFO);
|
||||
super(CustomNameplatesPlugin.getInstance(), ListenerPriority.NORMAL, PacketType.Play.Server.PLAYER_INFO);
|
||||
this.manager = manager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPacketSending(PacketEvent event) {
|
||||
if (event.isCancelled()) return;
|
||||
PacketContainer packet = event.getPacket();
|
||||
Set<EnumWrappers.PlayerInfoAction> actions = packet.getPlayerInfoActions().read(0);
|
||||
if (!actions.contains(EnumWrappers.PlayerInfoAction.UPDATE_DISPLAY_NAME))
|
||||
|
||||
+4
-2
@@ -28,6 +28,7 @@ import net.momirealms.customnameplates.paper.mechanic.nameplate.tag.listener.Pla
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
@@ -40,7 +41,7 @@ public class TeamTagManagerImpl implements TeamTagManager {
|
||||
private final NameplateManager manager;
|
||||
private final ConcurrentHashMap<UUID, TeamPlayer> teamPlayerMap;
|
||||
private CancellableTask refreshTask;
|
||||
private PlayerInfoListener tabListener;
|
||||
private final PlayerInfoListener tabListener;
|
||||
|
||||
public TeamTagManagerImpl(NameplateManager manager) {
|
||||
this.manager = manager;
|
||||
@@ -84,11 +85,12 @@ public class TeamTagManagerImpl implements TeamTagManager {
|
||||
ProtocolLibrary.getProtocolManager().removePacketListener(tabListener);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
@SuppressWarnings("DuplicatedCode")
|
||||
public TeamPlayer createTagForPlayer(Player player, String prefix, String suffix) {
|
||||
if (this.teamPlayerMap.containsKey(player.getUniqueId())) {
|
||||
return null;
|
||||
return this.teamPlayerMap.get(player.getUniqueId());
|
||||
}
|
||||
|
||||
var teamPlayer = new TeamPlayer(this, player, prefix, suffix);
|
||||
|
||||
+52
-39
@@ -26,6 +26,8 @@ import net.momirealms.customnameplates.api.mechanic.tag.unlimited.DynamicTextEnt
|
||||
import net.momirealms.customnameplates.api.requirement.Condition;
|
||||
import net.momirealms.customnameplates.api.requirement.Requirement;
|
||||
import net.momirealms.customnameplates.paper.mechanic.misc.PacketManager;
|
||||
import net.momirealms.customnameplates.paper.setting.CNConfig;
|
||||
import net.momirealms.customnameplates.paper.util.DisguiseUtils;
|
||||
import net.momirealms.customnameplates.paper.util.FakeEntityUtils;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.EntityType;
|
||||
@@ -47,6 +49,7 @@ public class DynamicTextEntityImpl implements DynamicTextEntity {
|
||||
private final Requirement[] ownerRequirements;
|
||||
private final Requirement[] viewerRequirements;
|
||||
private final Vector<Player> viewers;
|
||||
private Player[] viewerArray;
|
||||
private final int refreshFrequency;
|
||||
private final int checkFrequency;
|
||||
private int checkTimer;
|
||||
@@ -71,10 +74,11 @@ public class DynamicTextEntityImpl implements DynamicTextEntity {
|
||||
this.viewerRequirements = viewerRequirements;
|
||||
this.checkFrequency = checkFrequency;
|
||||
this.refreshFrequency = refreshFrequency;
|
||||
this.viewers = new Vector<>();
|
||||
this.ownerCanShow = RequirementManager.isRequirementMet(new Condition(owner.getPlayer()), ownerRequirements);
|
||||
this.destroyPacket = new PacketContainer(PacketType.Play.Server.ENTITY_DESTROY);
|
||||
this.destroyPacket.getIntLists().write(0, List.of(entityId));
|
||||
this.viewers = new Vector<>();
|
||||
this.viewersToArray();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -116,21 +120,7 @@ public class DynamicTextEntityImpl implements DynamicTextEntity {
|
||||
checkTimer++;
|
||||
if (checkTimer >= checkFrequency) {
|
||||
checkTimer = 0;
|
||||
if (!RequirementManager.isRequirementMet(new Condition(owner.getPlayer()), ownerRequirements)) {
|
||||
ownerCanShow = false;
|
||||
for (Player all : owner.getNearbyPlayers()) {
|
||||
removePlayerFromViewers(all);
|
||||
}
|
||||
} else {
|
||||
ownerCanShow = true;
|
||||
for (Player all : owner.getNearbyPlayers()) {
|
||||
if (canSee(all)) {
|
||||
addPlayerToViewers(all);
|
||||
} else {
|
||||
removePlayerFromViewers(all);
|
||||
}
|
||||
}
|
||||
}
|
||||
updateVisibility();
|
||||
}
|
||||
|
||||
refreshTimer++;
|
||||
@@ -141,12 +131,32 @@ public class DynamicTextEntityImpl implements DynamicTextEntity {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateVisibility() {
|
||||
if (!RequirementManager.isRequirementMet(new Condition(owner.getPlayer()), ownerRequirements)) {
|
||||
ownerCanShow = false;
|
||||
for (Player all : owner.getNearbyPlayers()) {
|
||||
removePlayerFromViewers(all);
|
||||
}
|
||||
} else {
|
||||
ownerCanShow = true;
|
||||
for (Player all : owner.getNearbyPlayers()) {
|
||||
if (canSee(all)) {
|
||||
addPlayerToViewers(all);
|
||||
} else {
|
||||
removePlayerFromViewers(all);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removePlayerFromViewers(Player player) {
|
||||
if (!viewers.contains(player)) {
|
||||
return;
|
||||
}
|
||||
this.viewers.remove(player);
|
||||
viewersToArray();
|
||||
destroy(player);
|
||||
}
|
||||
|
||||
@@ -156,6 +166,7 @@ public class DynamicTextEntityImpl implements DynamicTextEntity {
|
||||
return;
|
||||
}
|
||||
this.viewers.add(player);
|
||||
viewersToArray();
|
||||
spawn(player, owner.getPlayer().getPose());
|
||||
}
|
||||
|
||||
@@ -168,7 +179,7 @@ public class DynamicTextEntityImpl implements DynamicTextEntity {
|
||||
public void setOffset(double offset) {
|
||||
if (yOffset == offset) return;
|
||||
yOffset = offset;
|
||||
for (Player all : viewers) {
|
||||
for (Player all : viewerArray) {
|
||||
PacketManager.getInstance().send(all, getTeleportPacket(0));
|
||||
}
|
||||
}
|
||||
@@ -187,18 +198,19 @@ public class DynamicTextEntityImpl implements DynamicTextEntity {
|
||||
|
||||
@Override
|
||||
public void spawn(Pose pose) {
|
||||
for (Player all : viewers) {
|
||||
for (Player all : viewerArray) {
|
||||
spawn(all, pose);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() {
|
||||
for (Player all : viewers) {
|
||||
for (Player all : viewerArray) {
|
||||
PacketManager.getInstance().send(all, destroyPacket);
|
||||
}
|
||||
viewerText.clear();
|
||||
viewers.clear();
|
||||
viewersToArray();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -210,15 +222,15 @@ public class DynamicTextEntityImpl implements DynamicTextEntity {
|
||||
@Override
|
||||
public void teleport(double x, double y, double z, boolean onGround) {
|
||||
PacketContainer packet = getTeleportPacket(x, y, z, onGround);
|
||||
for (Player all : viewers) {
|
||||
for (Player all : viewerArray) {
|
||||
PacketManager.getInstance().send(all, packet);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void teleport() {
|
||||
PacketContainer packet = getTeleportPacket(getCorrection(owner.getPlayer().getPose()));
|
||||
for (Player viewer : viewers) {
|
||||
PacketContainer packet = getTeleportPacket(getPlayerHeight());
|
||||
for (Player viewer : viewerArray) {
|
||||
PacketManager.getInstance().send(viewer, packet);
|
||||
}
|
||||
}
|
||||
@@ -233,7 +245,7 @@ public class DynamicTextEntityImpl implements DynamicTextEntity {
|
||||
@Override
|
||||
public void setSneak(boolean isSneaking, boolean onGround) {
|
||||
if (!onGround) {
|
||||
for (Player viewer : viewers) {
|
||||
for (Player viewer : viewerArray) {
|
||||
PacketManager.getInstance().send(viewer, FakeEntityUtils.getMetaPacket(entityId, viewerText.getLatestValue(viewer), isSneaking));
|
||||
}
|
||||
}
|
||||
@@ -247,7 +259,7 @@ public class DynamicTextEntityImpl implements DynamicTextEntity {
|
||||
@Override
|
||||
public void move(short x, short y, short z, boolean onGround) {
|
||||
PacketContainer packet = getMovePacket(x, y, z, onGround);
|
||||
for (Player viewer : viewers) {
|
||||
for (Player viewer : viewerArray) {
|
||||
PacketManager.getInstance().send(viewer, packet);
|
||||
}
|
||||
}
|
||||
@@ -268,14 +280,14 @@ public class DynamicTextEntityImpl implements DynamicTextEntity {
|
||||
|
||||
@Override
|
||||
public void respawn(Pose pose) {
|
||||
for (Player viewer : viewers) {
|
||||
for (Player viewer : viewerArray) {
|
||||
respawn(viewer, pose);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateText() {
|
||||
for (Player viewer : viewers) {
|
||||
for (Player viewer : viewerArray) {
|
||||
updateText(viewer);
|
||||
}
|
||||
}
|
||||
@@ -296,7 +308,7 @@ public class DynamicTextEntityImpl implements DynamicTextEntity {
|
||||
public void handlePose(Pose previous, Pose pose) {
|
||||
// Add delay to prevent the tag from appearing earlier
|
||||
CustomNameplatesPlugin.get().getScheduler().runTaskAsyncLater(() -> {
|
||||
for (Player viewer : viewers) {
|
||||
for (Player viewer : viewerArray) {
|
||||
respawn(viewer, pose);
|
||||
}
|
||||
}, 20, TimeUnit.MILLISECONDS);
|
||||
@@ -316,7 +328,7 @@ public class DynamicTextEntityImpl implements DynamicTextEntity {
|
||||
PacketContainer packet = new PacketContainer(PacketType.Play.Server.ENTITY_TELEPORT);
|
||||
packet.getIntegers().write(0, entityId);
|
||||
packet.getDoubles().write(0, x);
|
||||
packet.getDoubles().write(1, y + owner.getHatOffset() + getCorrection(owner.getPlayer().getPose()) + yOffset);
|
||||
packet.getDoubles().write(1, y + owner.getHatOffset() + getPlayerHeight() + yOffset);
|
||||
packet.getDoubles().write(2, z);
|
||||
packet.getBooleans().write(0, onGround);
|
||||
return packet;
|
||||
@@ -332,14 +344,14 @@ public class DynamicTextEntityImpl implements DynamicTextEntity {
|
||||
return packet;
|
||||
}
|
||||
|
||||
private Location getEntityLocation(double correction) {
|
||||
private Location getEntityLocation(double playerHeight) {
|
||||
var player = owner.getPlayer();
|
||||
double x = player.getLocation().getX();
|
||||
double y = player.getLocation().getY();
|
||||
double z = player.getLocation().getZ();
|
||||
y += yOffset;
|
||||
y += owner.getHatOffset();
|
||||
y += correction;
|
||||
y += playerHeight;
|
||||
return new Location(null, x, y, z);
|
||||
}
|
||||
|
||||
@@ -348,7 +360,7 @@ public class DynamicTextEntityImpl implements DynamicTextEntity {
|
||||
entityPacket.getModifier().write(0, entityId);
|
||||
entityPacket.getModifier().write(1, uuid);
|
||||
entityPacket.getEntityTypeModifier().write(0, EntityType.ARMOR_STAND);
|
||||
Location location = getEntityLocation(getCorrection(pose));
|
||||
Location location = getEntityLocation(getPlayerHeight());
|
||||
entityPacket.getDoubles().write(0, location.getX());
|
||||
entityPacket.getDoubles().write(1, location.getY());
|
||||
entityPacket.getDoubles().write(2, location.getZ());
|
||||
@@ -356,13 +368,14 @@ public class DynamicTextEntityImpl implements DynamicTextEntity {
|
||||
return new PacketContainer[] {entityPacket, metaPacket};
|
||||
}
|
||||
|
||||
private double getCorrection(Pose pose) {
|
||||
return switch (pose) {
|
||||
case STANDING -> 1.8;
|
||||
case SNEAKING -> 1.5;
|
||||
case SLEEPING -> 0.2;
|
||||
case SWIMMING, FALL_FLYING, SPIN_ATTACK -> 0.55;
|
||||
default -> 0;
|
||||
};
|
||||
private double getPlayerHeight() {
|
||||
if (CNConfig.hasLibsDisguise && DisguiseUtils.isDisguised(owner.getPlayer()) && DisguiseUtils.getDisguisedType(owner.getPlayer()) != EntityType.PLAYER) {
|
||||
return DisguiseUtils.getDisguisedHeight(owner.getPlayer());
|
||||
}
|
||||
return owner.getPlayer().getHeight();
|
||||
}
|
||||
|
||||
private void viewersToArray() {
|
||||
viewerArray = viewers.toArray(new Player[0]);
|
||||
}
|
||||
}
|
||||
+45
-15
@@ -23,6 +23,8 @@ import net.momirealms.customnameplates.api.CustomNameplatesPlugin;
|
||||
import net.momirealms.customnameplates.api.mechanic.tag.unlimited.NearbyRule;
|
||||
import net.momirealms.customnameplates.api.mechanic.tag.unlimited.StaticTextEntity;
|
||||
import net.momirealms.customnameplates.paper.mechanic.misc.PacketManager;
|
||||
import net.momirealms.customnameplates.paper.setting.CNConfig;
|
||||
import net.momirealms.customnameplates.paper.util.DisguiseUtils;
|
||||
import net.momirealms.customnameplates.paper.util.FakeEntityUtils;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.EntityType;
|
||||
@@ -42,11 +44,12 @@ public class StaticTextEntityImpl implements StaticTextEntity {
|
||||
private double yOffset;
|
||||
private final int entityId;
|
||||
private final Vector<Player> viewers;
|
||||
private Player[] viewerArray;
|
||||
private final ConcurrentHashMap<UUID, String> textCache;
|
||||
private final NearbyRule comeRule;
|
||||
private final NearbyRule leaveRule;
|
||||
private String defaultText;
|
||||
private final String plugin;
|
||||
private final String id;
|
||||
private final PacketContainer destroyPacket;
|
||||
|
||||
public StaticTextEntityImpl (
|
||||
@@ -55,7 +58,7 @@ public class StaticTextEntityImpl implements StaticTextEntity {
|
||||
NearbyRule comeRule,
|
||||
NearbyRule leaveRule,
|
||||
String defaultText,
|
||||
String plugin
|
||||
String id
|
||||
) {
|
||||
this.entityId = FakeEntityUtils.getAndIncrease();
|
||||
this.owner = owner;
|
||||
@@ -65,14 +68,15 @@ public class StaticTextEntityImpl implements StaticTextEntity {
|
||||
this.comeRule = comeRule;
|
||||
this.leaveRule = leaveRule;
|
||||
this.defaultText = defaultText;
|
||||
this.plugin = plugin;
|
||||
this.id = id;
|
||||
this.destroyPacket = new PacketContainer(PacketType.Play.Server.ENTITY_DESTROY);
|
||||
this.destroyPacket.getIntLists().write(0, List.of(entityId));
|
||||
this.viewersToArray();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPlugin() {
|
||||
return plugin;
|
||||
public String getID() {
|
||||
return id;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -109,6 +113,7 @@ public class StaticTextEntityImpl implements StaticTextEntity {
|
||||
return;
|
||||
}
|
||||
this.viewers.remove(player);
|
||||
viewersToArray();
|
||||
destroy(player);
|
||||
}
|
||||
|
||||
@@ -118,6 +123,7 @@ public class StaticTextEntityImpl implements StaticTextEntity {
|
||||
return;
|
||||
}
|
||||
this.viewers.add(player);
|
||||
viewersToArray();
|
||||
spawn(player, owner.getEntity().getPose());
|
||||
}
|
||||
|
||||
@@ -130,7 +136,7 @@ public class StaticTextEntityImpl implements StaticTextEntity {
|
||||
public void setOffset(double offset) {
|
||||
if (yOffset == offset) return;
|
||||
yOffset = offset;
|
||||
for (Player all : viewers) {
|
||||
for (Player all : viewerArray) {
|
||||
PacketManager.getInstance().send(all, getTeleportPacket());
|
||||
}
|
||||
}
|
||||
@@ -139,7 +145,7 @@ public class StaticTextEntityImpl implements StaticTextEntity {
|
||||
public void setText(String text) {
|
||||
if (text.equals(defaultText)) return;
|
||||
this.defaultText = text;
|
||||
for (Player viewer : viewers) {
|
||||
for (Player viewer : viewerArray) {
|
||||
PacketManager.getInstance().send(viewer, FakeEntityUtils.getMetaPacket(entityId, getText(viewer), owner.getEntity().isSneaking()));
|
||||
}
|
||||
}
|
||||
@@ -174,11 +180,12 @@ public class StaticTextEntityImpl implements StaticTextEntity {
|
||||
|
||||
@Override
|
||||
public void destroy() {
|
||||
for (Player all : viewers) {
|
||||
for (Player all : viewerArray) {
|
||||
PacketManager.getInstance().send(all, destroyPacket);
|
||||
}
|
||||
viewers.clear();
|
||||
textCache.clear();
|
||||
viewersToArray();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -190,7 +197,7 @@ public class StaticTextEntityImpl implements StaticTextEntity {
|
||||
@Override
|
||||
public void teleport(double x, double y, double z, boolean onGround) {
|
||||
PacketContainer packet = getTeleportPacket(x, y, z, onGround);
|
||||
for (Player all : viewers) {
|
||||
for (Player all : viewerArray) {
|
||||
PacketManager.getInstance().send(all, packet);
|
||||
}
|
||||
}
|
||||
@@ -205,7 +212,7 @@ public class StaticTextEntityImpl implements StaticTextEntity {
|
||||
@Override
|
||||
public void teleport() {
|
||||
PacketContainer packet = getTeleportPacket();
|
||||
for (Player viewer : viewers) {
|
||||
for (Player viewer : viewerArray) {
|
||||
PacketManager.getInstance().send(viewer, packet);
|
||||
}
|
||||
}
|
||||
@@ -218,7 +225,7 @@ public class StaticTextEntityImpl implements StaticTextEntity {
|
||||
@Override
|
||||
public void move(short x, short y, short z, boolean onGround) {
|
||||
PacketContainer packet = getMovePacket(x, y, z, onGround);
|
||||
for (Player viewer : viewers) {
|
||||
for (Player viewer : viewerArray) {
|
||||
PacketManager.getInstance().send(viewer, packet);
|
||||
}
|
||||
}
|
||||
@@ -239,7 +246,7 @@ public class StaticTextEntityImpl implements StaticTextEntity {
|
||||
|
||||
@Override
|
||||
public void respawn(Pose pose) {
|
||||
for (Player viewer : viewers) {
|
||||
for (Player viewer : viewerArray) {
|
||||
respawn(viewer, pose);
|
||||
}
|
||||
}
|
||||
@@ -253,12 +260,21 @@ public class StaticTextEntityImpl implements StaticTextEntity {
|
||||
public void handlePose(Pose previous, Pose pose) {
|
||||
// Add delay to prevent the tag from appearing earlier
|
||||
CustomNameplatesPlugin.get().getScheduler().runTaskAsyncLater(() -> {
|
||||
for (Player viewer : viewers) {
|
||||
for (Player viewer : viewerArray) {
|
||||
respawn(viewer, pose);
|
||||
}
|
||||
}, 20, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSneak(boolean isSneaking, boolean onGround) {
|
||||
if (!onGround) {
|
||||
for (Player viewer : viewerArray) {
|
||||
PacketManager.getInstance().send(viewer, FakeEntityUtils.getMetaPacket(entityId, getText(viewer), isSneaking));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public PacketContainer getMovePacket(short x, short y, short z, boolean onGround) {
|
||||
PacketContainer packet = new PacketContainer(PacketType.Play.Server.REL_ENTITY_MOVE);
|
||||
packet.getIntegers().write(0, entityId);
|
||||
@@ -273,7 +289,7 @@ public class StaticTextEntityImpl implements StaticTextEntity {
|
||||
PacketContainer packet = new PacketContainer(PacketType.Play.Server.ENTITY_TELEPORT);
|
||||
packet.getIntegers().write(0, entityId);
|
||||
packet.getDoubles().write(0, x);
|
||||
packet.getDoubles().write(1, y + yOffset);
|
||||
packet.getDoubles().write(1, y + ((owner instanceof UnlimitedPlayer player) ? player.getHatOffset() : 0) + getCorrection() + yOffset);
|
||||
packet.getDoubles().write(2, z);
|
||||
packet.getBooleans().write(0, onGround);
|
||||
return packet;
|
||||
@@ -295,6 +311,8 @@ public class StaticTextEntityImpl implements StaticTextEntity {
|
||||
double y = entity.getLocation().getY();
|
||||
double z = entity.getLocation().getZ();
|
||||
y += yOffset;
|
||||
if (owner instanceof UnlimitedPlayer player) y += player.getHatOffset();
|
||||
y += getCorrection();
|
||||
return new Location(null, x, y, z);
|
||||
}
|
||||
|
||||
@@ -305,9 +323,21 @@ public class StaticTextEntityImpl implements StaticTextEntity {
|
||||
entityPacket.getEntityTypeModifier().write(0, EntityType.ARMOR_STAND);
|
||||
Location location = getEntityLocation();
|
||||
entityPacket.getDoubles().write(0, location.getX());
|
||||
entityPacket.getDoubles().write(1, location.getY() + (pose == Pose.SNEAKING ? -0.3 : 0));
|
||||
entityPacket.getDoubles().write(1, location.getY());
|
||||
entityPacket.getDoubles().write(2, location.getZ());
|
||||
PacketContainer metaPacket = FakeEntityUtils.getMetaPacket(entityId, text, pose == Pose.SNEAKING);
|
||||
return new PacketContainer[] {entityPacket, metaPacket};
|
||||
}
|
||||
|
||||
private double getCorrection() {
|
||||
double height = owner.getEntity().getHeight();
|
||||
if (CNConfig.hasLibsDisguise && DisguiseUtils.isDisguised(owner.getEntity()) && DisguiseUtils.getDisguisedType(owner.getEntity()) != EntityType.PLAYER) {
|
||||
height = DisguiseUtils.getDisguisedHeight(owner.getEntity());
|
||||
}
|
||||
return height - 1.8;
|
||||
}
|
||||
|
||||
private void viewersToArray() {
|
||||
viewerArray = viewers.toArray(new Player[0]);
|
||||
}
|
||||
}
|
||||
Loaded 100 of 160 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user